[Raw Msg Headers][Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Ideas for developement..



In dist.zmailer, article <92Dec19.030321eet.91182-3@nic.funet.fi>,
  Matti Aarnio <mea@nic.funet.fi> writes:
> I have been toying with a few developement ideas for the Zmailer, any takers ?
> 
[ Ideas deleted ]

What about MIME and the proposed 8-bit SMTP extension? I've patched
my smtpserver to accept the proposd EHLO and EMAL commands, just for
kicks (some people actually use these features already), but the Right
Thing would be to fall back to 7-bit encoding if the receiver doesn't
say that it can accept 8-bit data (or, worse, if it says it can't.)

This one looks like some work, but not so much work as the two or three
lines mentioning X.400 which has been commented out for the last few
years allude to. ;-)

I also extended the list of messages to the router process because
I need to do some rather ugly accounting stuff (not shown here ;-).

This patch corrects some other problems; mainly "const" strings and
variable renames to shup up gcc -W and, more important, exit codes
to get BatchSMTP problems to the attention of UUCP; this is important
if somebody has an old Smail3 which thinks that the argument to HELO
should be inside angle brackets.  :-(

--- /tmp/zmailer/smtpserver/smtpserver.c	Mon Jun  8 17:47:09 1992
+++ smtpserver.c	Fri Dec 18 12:06:59 1992
@@ -7,8 +7,8 @@
  * ZMailer SMTP server.
  */
 
-char *VerbID = "ZMailer SMTP server %s";
-char *Copyright = "Copyright 1990 Rayan S. Zachariassen";
+const char *VerbID = "ZMailer SMTP server %s";
+const char *Copyright = "Copyright 1990 Rayan S. Zachariassen";
 
 /*
  * The smtpserver connects to the router to ask it various questions, like,
@@ -20,10 +20,13 @@
 #define	ROUTER_SERVER	"server"	/* name of portal function */
 
 #define	RKEY_INIT	"init"		/* initialize state of server */
-#define	RKEY_FROM	"from"		/* mail from address verification */
-#define	RKEY_TO		"to"		/* recipient to address verification */
-#define	RKEY_VERIFY	"verify"	/* verify this address */
-#define	RKEY_EXPAND	"expand"	/* expand this address */
+#define	RKEY_HELLO	"hello"		/* h initialize state of server */
+#define	RKEY_FROM	"from"		/* f mail from address verification */
+#define	RKEY_SIZE	"size"		/* s tell size of message */
+#define	RKEY_TO		"to"		/* t recipient to address verification */
+#define	RKEY_DATA	"data"		/* d size confirmation */
+#define	RKEY_VERIFY	"verify"	/* v verify this address */
+#define	RKEY_EXPAND	"expand"	/* e expand this address */
 
 
 #include <stdio.h>
@@ -71,9 +74,10 @@
 #define	CHECK42INETD	/* heuristics to detect the 4.2 inetd */
 
 
-typedef enum {	Null, Hello, Mail, MailOrHello, Recipient,
-		RecipientOrData, Data, Send, SendOrMail,
-		SendAndMail, Reset, Verify, Expand, Help,
+typedef enum {	Null, Hello, EHello, Mail, EMail, MailOrHello, Size,
+		Recipient, RecipientOrSize, RecipientOrData, Data, Send, 
+		ESend, ESendOrMail, ESendAndMail, 
+		SendOrMail, SendAndMail, Reset, Verify, Expand, Help,
 		NoOp, Quit, Turn, Tick, Verbose
 } Command;
 
@@ -80,34 +84,37 @@
 Command state;
 
 struct command {
-	char	*verb;
+	const char	*verb;
+	const char	*verb2;
 	Command	cmd;	
-} command_list[] = {	{	"helo",		Hello		},
-			{	"mail",		Mail		},
-			{	"rcpt",		Recipient	},
-			{	"data",		Data		},
-			{	"send",		Send		},
-			{	"soml",		SendOrMail	},
-			{	"saml",		SendAndMail	},
-			{	"rset",		Reset		},
-			{	"vrfy",		Verify		},
-			{	"expn",		Expand		},
-			{	"help",		Help		},
-			{	"noop",		NoOp		},
-			{	"quit",		Quit		},
-			{	"turn",		Turn		},
+} command_list[] = {	{	"HELO","",	Hello		},
+			{	"MAIL","FROM",	Mail		},
+			{	"RCPT","TO",	Recipient	},
+			{	"DATA","",	Data		},
+			{	"SEND",NULL,	Send		},
+			{	"SOML",NULL,	SendOrMail	},
+			{	"SAML",NULL,	SendAndMail	},
+			{	"RSET","",	Reset		},
+			{	"VRFY","",	Verify		},
+			{	"EXPN","",	Expand		},
+			{	"HELP","",	Help		},
+			{	"NOOP","",	NoOp		},
+			{	"QUIT","",	Quit		},
+			{	"TURN",NULL,	Turn		},
 			/* sendmail extensions */
-			{	"onex",		NoOp		},
-			{	"verb",		Verbose		},
+			{	"ONEX",NULL,	NoOp		},
+			{	"VERB",NULL,	Verbose		},
 			/* bsmtp extensions */
-			{	"tick",		Tick		},
+			{	"TICK",NULL,	Tick		},
 			/* 8-bit smtp extensions */
-			{	"emal",		Mail		},
-			{	"esnd",		Send		},
-			{	"esom",		Send		},
-			{	"esam",		Send		},
-			{	"evfy",		Verify		},
-			{	0,		Null		}
+			{	"EHLO","",	EHello		},
+			{	"EMAL","FROM",	EMail		},
+			{	"ESND",NULL,	ESend		},
+			{	"ESOM",NULL,	ESendOrMail	},
+			{	"ESAM",NULL,	ESendAndMail	},
+			{	"EVFY","",	Verify		},
+			{	"SIZE","",	Size		},
+			{	NULL,NULL,	Null		}
 };
 
 struct smtpconf {
@@ -120,7 +127,7 @@
 struct smtpconf *cfhead = NULL;
 
 char	*progname, *cmdline, *eocmdline, *logfile;
-char	*postoffice = NULL;
+const char	*postoffice = NULL;
 char	*routerprog = NULL;
 char	helobuf[MAXHOSTNAMELEN+1];
 char	myhostname[MAXHOSTNAMELEN+1];
@@ -128,6 +135,7 @@
 char	ihostaddr[3*4+1*3+2+1 /* == 18 for '[255.255.255.255]' */ +10/*slack*/];
 int	rport;
 int	skeptical = 1;
+int	err = 0;
 int	pid, routerpid;
 FILE	*logfp = NULL;
 
@@ -140,13 +148,14 @@
  * e:	check EXPN command argument
  */
 
-char	*style = "ve";
+const char	*style = "veft";
 
 #define STYLE(i,c)	(strchr(((i)==NULL ? style : (i)->flags), (c)) != NULL)
 
-#define	WITH_SMTP	"SMTP"
-#define	WITH_BSMTP	"BSMTP"
-char	*with_protocol;
+#define	WITH_SMTP	"smtp"
+#define	WITH_BSMTP	"bsmtp"
+#define	WITH_ESMTP	"esmtp"
+const char	*with_protocol;
 
 extern int optind;
 extern char *optarg;
@@ -161,13 +170,15 @@
 	int argc;
 	char *argv[];
 {
-	int daemon, inetd, errflg, c, raddrlen, s, msgfd, pid, version, i;
-	char *mailshare, path[1024];
+	int daemon, inetd, errflg, c, raddrlen, s, msgfd, thispid, version, i;
+	const char *mailshare;
+	char path[1024];
 #ifdef	USE_INET
 	struct sockaddr_in sad, raddr;
 #endif	/* USE_INET */
 	u_short port = 0;
-	extern char *emalloc(), *strerror();
+	extern void *emalloc();
+	extern char *strerror();
 	extern int getmyhostname(), isit42inetd();
 	extern int getpeername();
 	extern SIGNAL_TYPE reaper(), timedout();
@@ -178,6 +189,7 @@
 	daemon = 1;
 	inetd = errflg = version = 0;
 	logfile = NULL;
+	with_protocol = WITH_SMTP;
 	progname = argv[0];
 	cmdline = &argv[0][0];
 	eocmdline = cmdline;
@@ -188,8 +200,11 @@
 				       progname, strerror(errno));
 		exit(1);
 	}
-	while ((c = getopt(argc, argv, "igl:np:P:R:s:V")) != EOF) {
+	while ((c = getopt(argc, argv, "bigl:np:P:R:s:V")) != EOF) {
 		switch (c) {
+		case 'b': /* Batch SMTP */
+			with_protocol = WITH_BSMTP;
+			break;
 		case 'i':	/* interactive */
 			daemon = 0;
 			break;
@@ -205,7 +220,7 @@
 			break;
 		case 's':	/* checking style */
 			style = emalloc(strlen(optarg)+1);
-			strcpy(style, optarg);
+			strcpy((char *)style, optarg);
 			break;
 #ifdef	USE_INET
 		case 'p':
@@ -218,7 +233,7 @@
 			break;
 		case 'P':
 			postoffice = emalloc(strlen(optarg)+1);
-			strcpy(postoffice, optarg);
+			strcpy((char *)postoffice, optarg);
 			break;
 		case 'V':
 			prversion("smtpserver");
@@ -353,7 +368,7 @@
 					exit(1);
 				}
 			}
-			if ((pid = fork()) < 0) {	/* can't fork! */
+			if ((thispid = fork()) < 0) {	/* can't fork! */
 				(void) close(msgfd);
 				(void) fprintf(stderr,
 					       "%s: fork(): %s\n",
@@ -360,7 +375,7 @@
 					       progname, strerror(errno));
 				(void) sleep(5);
 				continue;
-			} else if (pid == 0) {		/* child */
+			} else if (thispid == 0) {		/* child */
 				(void) close(s);
 				(void) signal(SIGTERM, SIG_IGN);
 				if (msgfd != 0)
@@ -389,7 +404,7 @@
 #endif	/* USE_INET */
 	if (routerpid > 0)
 		killr(routerpid);
-	exit(0);
+	exit(err);
 	/* NOTREACHED */
 	return 0;
 }
@@ -461,7 +476,7 @@
 	
 	if (routerpid > 0)
 		killr(routerpid);
-	exit(0);
+	exit(err);
 }
 
 SIGNAL_TYPE
@@ -491,6 +506,7 @@
 	syslog(LOG_ERR,
 		"aborted (%ldc) from %s/%d: %s", tell, rhostname, rport, msg);
 #endif	/* LOG_INFO */
+	err++;
 	if (logfp != NULL) {
 		(void) fprintf(logfp, "%d#\taborted: %s\n", pid, msg);
 		(void) fflush(logfp);
@@ -534,7 +550,6 @@
 	(void) runastrusteduser();
 
 	mfp = NULL;
-	with_protocol = WITH_SMTP;
 	report("(connected)");
 	now = time((time_t *)0);
 	cp = (char *)rfc822date(&now);
@@ -595,6 +610,7 @@
 			       "unknown SMTP command '%s' from %s/%d",
 			       buf, rhostname, rport);
 #endif	/* LOG_WARNING */
+			err = 1;
 			continue;
 		}
 		switch (carp->cmd) {
@@ -602,19 +618,28 @@
 			type(550, "panic!");
 			break;
 		case Hello:
+		case EHello:
 			if (state != Hello && state != MailOrHello) {
+				const char *cpx;
+
 				switch (state) {
 				case Mail:
-					cp = "Waiting for MAIL command";
+					cpx = "Waiting for MAIL command";
+					break;
+				case RecipientOrSize:
+					cpx = "Waiting for RCPT or SIZE command";
+					break;
+				case RecipientOrData:
+					cpx = "Waiting for RCPT or DATA command";
 					break;
 				case Recipient:
-					cp = "Waiting for RCPT or DATA command";
+					cpx = "Waiting for RCPT command";
 					break;
 				default:
-					cp = NULL;
+					cpx = NULL;
 					break;
 				}
-				type(503, cp);
+				type(503, cpx);
 				break;
 			}
 			if (sscanf(cp, "%s", helobuf) != 1) {
@@ -637,36 +662,67 @@
 					type(501, "%s", (cfinfo->flags)+1);
 				else
 					type(501, "Sorry, access denied.");
+
 				break;
 			}
-			/* check helobuf corresponds to the reverse address */
-			if (ihostaddr[0] != '\0'
-			    && rhostname[0] != '\0' && rhostname[0] != '['
-			    && cistrcmp(helobuf, rhostname) != 0) {
-				type(-250, "That hostname is inconsistent with your address to name mapping.");
-				type(250, "%s expected \"%s %s\"",
-					myhostname, buf, rhostname);
-			} else
+			if (STYLE(cfinfo,'h')) {
+				if ((s = router(RKEY_HELLO, 1, helobuf)) == NULL)
+				{
+					/* the error was printed in router() */
+
+					break;
+				}
+				if(carp->cmd == Hello)
+					type(atoi(s),s+4);
+				free(s);
+			} 
+			else if(carp->cmd == Hello)
 				type(250, "%s Hello %s", myhostname, helobuf);
+			if(carp->cmd == EHello) {
+				printf("255-%s\r\n", myhostname);
+				for (carp = &command_list[0]; carp->verb != NULL; ++carp) {
+
+					if(carp->verb2 == NULL)
+						continue;
+					if(*carp->verb2 == '\0')
+						printf("255-%s\r\n",carp->verb);
+					else
+						printf("255-%s %s\r\n",carp->verb, carp->verb2);
+				}
+				type(255,"LIMIT 64 65535");
+			}
 			state = MailOrHello;
 			break;
+		case EMail:
+		case ESend:
+		case ESendOrMail:
+		case ESendAndMail:
 		case Mail:
 		case Send:
 		case SendOrMail:
 		case SendAndMail:
 			if (state != Mail && state != MailOrHello) {
+				const char *cpx;
+
 				switch (state) {
 				case Hello:
-					cp = "Waiting for HELO command";
+					cpx = "Waiting for HELO command";
+					break;
+				case RecipientOrSize:
+					cpx = "Waiting for RCPT or SIZE command";
 					break;
 				case Recipient:
-					cp = "Waiting for RCPT or DATA command";
+					cpx = "Waiting for RCPT command";
+					break;
+				case RecipientOrData:
+
+					cpx = "Waiting for RCPT or DATA command";
 					break;
 				default:
-					cp = NULL;
+					cpx = NULL;
 					break;
 				}
-				type(503, cp);
+				type(503, cpx);
 				break;
 			}
 			if (cistrncmp(cp, "From:", 5) != 0) {
@@ -711,6 +767,9 @@
 					free(s);
 					break;
 				}
+			} else if(STYLE(cfinfo,'f')) {
+				if((s = router(RKEY_FROM,1,"")) == NULL)
+					break;
 			}
 
 			if (mfp == NULL
@@ -742,23 +801,78 @@
 				type(250, (char *)NULL);
 			if (s)
 				free(s);
+			state = RecipientOrSize;
+			break;
+		case Size:
+			if (state != RecipientOrSize) {
+				const char *cpx;
+
+				switch (state) {
+				case Hello:
+					cpx = "Waiting for HELO command";
+					break;
+				case Mail:
+				case MailOrHello:
+					cpx = "Waiting for MAIL command";
+					break;
+				case Recipient:
+					cpx = "Waiting for RCPT command";
+					break;
+				case RecipientOrData:
+					cpx = "Waiting for RCPT or DATA command";
+					break;
+				default:
+					cpx = NULL;
+					break;
+				}
+				type(503, cpx);
+				break;
+			}
+			{
+			    int siz;
+			    if (sscanf(cp, "%d", &siz) != 1) {
+				type(501, "What is the size in KBytes?");
+				break;
+			    }
+			}
+			if (STYLE(cfinfo, 's')) {
+				if ((s = router(RKEY_SIZE, 1, cp)) == NULL)
+					/* the error was printed in router() */
+					break;
+				type(atoi(s),s+4);
+				if (atoi(s) / 100 != 2) {
+					/* verification failed */
+					if (mfp != NULL) {
+						(void) mail_abort(mfp);
+						mfp = NULL;
+					}
+					state = Mail;
+				} else
+					state = Recipient;
+				free(s);
+			} else {
+				type(250,"Ok");
 			state = Recipient;
+			}
 			break;
 		case Recipient:
-			if (state != Recipient && state != RecipientOrData) {
+			if (state != Recipient && state != RecipientOrData &&
+					state != RecipientOrSize) {
+				const char *cpx;
+
 				switch (state) {
 				case Hello:
-					cp = "Waiting for HELO command";
+					cpx = "Waiting for HELO command";
 					break;
 				case Mail:
 				case MailOrHello:
-					cp = "Waiting for MAIL command";
+					cpx = "Waiting for MAIL command";
 					break;
 				default:
-					cp = NULL;
+					cpx = NULL;
 					break;
 				}
-				type(503, cp);
+				type(503, cpx);
 				break;
 			}
 			if (cistrncmp(cp, "To:", 3) != 0) {
@@ -806,7 +920,6 @@
 				if (atoi(s) / 100 != 2) {
 					/* verification failed */
 					type(atoi(s), s+4, "Failed", "Failed");
-					free(s);
 					break;
 				}
 			}
@@ -815,32 +928,41 @@
 			if (ferror(mfp)) {
 				type(452, (char *)NULL);
 				clearerr(mfp);
-			} else if (s)
+				if(s)
+					free(s);
+			} else if (s) {
 				type(atoi(s), s+4, "Ok", "Ok");
-			else
-				type(250, (char *)NULL);
-			if (s)
+				if(atoi(s)/100 == 2)
+					state = RecipientOrData;
 				free(s);
+			} else {
+				type(250, (char *)NULL);
 			state = RecipientOrData;
+			}
 			break;
 		case Data:
 			if (state != RecipientOrData) {
+				const char *cpx;
+
 				switch (state) {
 				case Hello:
-					cp = "Waiting for HELO command";
+					cpx = "Waiting for HELO command";
 					break;
 				case Mail:
 				case MailOrHello:
-					cp = "Waiting for MAIL command";
+					cpx = "Waiting for MAIL command";
 					break;
+				case RecipientOrSize:
+					cpx = "Waiting for RCPT or SIZE command";
+					break;
 				case Recipient:
-					cp = "Waiting for RCPT command";
+					cpx = "Waiting for RCPT command";
 					break;
 				default:
-					cp = NULL;
+					cpx = NULL;
 					break;
 				}
-				type(503, cp);
+				type(503, cpx);
 				break;
 			}
 			type(354, (char *)NULL);
@@ -857,17 +979,35 @@
 				/* [mea@utu.fi] says this can happen */
 				(void) mail_abort(mfp);
 				reporterr(tell, "premature EOF on DATA input");
-				return;
 			} else if (ferror(mfp)) {
 				type(452, (char *)NULL);
 				clearerr(mfp);
 				(void) mail_abort(mfp);
 				reporterr(tell, "message file error");
-			} else if (mail_close(mfp) == EOF) {
+			} else {
+				s = NULL;
+				if (STYLE(cfinfo, 'd')) {
+					char numbuf[20];
+					sprintf(numbuf,"%d",tell);
+					if ((s = router(RKEY_DATA, 1, numbuf)) == NULL)
+						/* the error was printed in router() */
+						break;
+					if (atoi(s) / 100 != 2) {
+						/* verification failed */
+						type(atoi(s), s+4, "Failed", "Failed");
+						break;
+					}
+				} 
+				if(s == NULL || atoi(s)/100 == 2) {
+				    if(mail_close(mfp) == EOF) {
 				type(452, (char *)NULL);
 				reporterr(tell, "message file close failed");
 			} else {
-				type(250, "Roger");
+					if(s != NULL)
+						type(atoi(s),s+4);
+					else
+						type(250,"Roger");
+				    }
 #ifdef	LOG_INFO
 				syslog(LOG_INFO,
 				       "accepted id %d (%ldc) from %s/%d",
@@ -879,6 +1019,13 @@
 						       pid, inum, tell);
 					(void) fflush(logfp);
 				}
+				} else {
+				    if (mfp != NULL) {
+					    (void) mail_abort(mfp);
+				    }
+				}
+				if(s != NULL)
+					free(s);
 			}
 			(void) fclose(mfp);	/* just in case */
 			mfp = NULL;
@@ -899,7 +1046,7 @@
 		case Verify:
 			if (STYLE(cfinfo, 'v')) {
 				if ((s = router(RKEY_VERIFY, 0, cp)) != NULL) {
-					printf("%s\r\n", s);
+					type(atoi(s),s+4);
 					free(s);
 				}
 			} else
@@ -908,7 +1055,7 @@
 		case Expand:
 			if (STYLE(cfinfo, 'e')) {
 				if ((s = router(RKEY_EXPAND, 0, cp)) != NULL) {
-					printf("%s\r\n", s);
+					type(atoi(s),s+4);
 					free(s);
 				}
 			} else
@@ -957,7 +1104,6 @@
 	char *query;
 {
 	int	col;
-	char	*cp;
 	struct command *carp;
 	extern int cistrcmp();
 	extern void type();
@@ -972,6 +1118,12 @@
 		TYPE_("\tIt is polite to introduce yourself before talking.");
 		TYPE ("\tI will in fact ignore you until you do!");
 		break;
+	case EHello:
+		TYPE_("ehlo your.domain.name");
+		TYPE_("\tThis is the 8-bit alternate to HELO.");
+		TYPE_("\tThe reply consists of my host name, a list of");
+		TYPE_("\tsupported commands, and a LIMITS statement.");
+		break;
 	case Mail:
 		TYPE_("mail from:<sender>");
 		TYPE_("\tSpecify the originator address for the next message.");
@@ -990,12 +1142,16 @@
 			TYPE ("\tAny address will be accepted here, but may be rejected later.");
 		}
 		break;
+	case Size:
+		TYPE_("size NUMBER");
+		TYPE_("\tSpecify the size of the next message, in approximate KBytes.");
+		break;
 	case Data:
 		TYPE_("data");
 		TYPE_("\tStart collecting the message itself.  The text data");
 		TYPE ("\tis terminated by a <CRLF>.<CRLF> combination.");
 		break;
-	case Reset:
+	case Reset: { const char *cpx;
 		TYPE_("rset");
 		TYPE_("\tReset the state of the SMTP server to be ready for");
 		TYPE_("\tthe next message, and abort any current transaction.");
@@ -1002,25 +1158,28 @@
 		TYPE_("");
 		switch (state) {
 		case Hello:
-			cp = "Waiting for \"helo\" command";
+			cpx = "Waiting for \"helo\" command";
 			break;
 		case Mail:
-			cp = "Waiting for \"mail\" command";
+			cpx = "Waiting for \"mail\" command";
 			break;
 		case MailOrHello:
-			cp = "Waiting for \"mail\" or \"helo\" command";
+			cpx = "Waiting for \"mail\" or \"helo\" command";
 			break;
+		case RecipientOrSize:
+			cpx = "Waiting for \"rcpt\" or \"size\" command";
+			break;
 		case Recipient:
-			cp = "Waiting for \"rcpt\" command";
+			cpx = "Waiting for \"rcpt\" command";
 			break;
 		case RecipientOrData:
-			cp = "Waiting for \"rcpt\" or \"data\" command";
+			cpx = "Waiting for \"rcpt\" or \"data\" command";
 		default:
-			cp = "Unknown";
+			cpx = "*Unknown*";
 			break;
 		}
-		(void) printf("241 The current state is: %s.\r\n", cp);
-		break;
+		type(241,"The current state is: %s.\r\n", cpx);
+		} break;
 	case Send:
 	case SendOrMail:
 	case SendAndMail:
@@ -1138,7 +1297,7 @@
 tmalloc(n)
 	int n;
 {
-	extern char *emalloc();
+	extern void *emalloc();
 
 	return emalloc((u_int)n);
 }
@@ -1196,7 +1355,8 @@
 	register char *cp;
 	char *s;
 	static char *obuf = NULL;
-	extern char *emalloc(), *erealloc();
+	extern void *emalloc(), *erealloc();
+	int cc;
 	
 	if (buf != NULL)
 		free(buf);
@@ -1207,7 +1367,8 @@
 
 	bufsize = 10;
 	cp = buf = emalloc(bufsize);
-	while ((*cp = getc(fp)) != EOF) {
+	while ((cc = getc(fp)) != EOF) {
+		*cp = cc;
 		if (*cp == '\n') {
 			*flagp = 0;
 			break;
@@ -1225,7 +1386,7 @@
 			buf = s;
 		}
 	}
-	if (*cp == EOF) {
+	if (cc == EOF) {
 		(void) printf("got EOF!\n");
 		free(buf);
 		return NULL;
@@ -1242,16 +1403,16 @@
 	return cp;
 }
 
-char *newenviron[] = { "SMTPSERVER=y", (char *)0 };
+const char *newenviron[] = { "SMTPSERVER=y", (char *)0 };
 
 int
 callr()
 {
-	int sawend, pid, to[2], from[2];
+	int sawend, thispid, to[2], from[2];
 	char *buf, *cp;
-	extern char *emalloc();
+	extern void *emalloc();
 	extern void runasrootuser(), killr();
-	extern char **environ;
+	extern const char **environ;
 
 	if (pipe(to) < 0 || pipe(from) < 0)
 		return -1;
@@ -1270,7 +1431,7 @@
 		(void) sprintf(routerprog, "%s/router", buf);
 	}
 
-	if ((pid = fork()) == 0) {	/* child */
+	if ((thispid = fork()) == 0) {	/* child */
 		(void) dup2(to[0], 0);
 		(void) dup2(from[1], 1);
 		(void) dup2(from[1], 2);
@@ -1282,7 +1443,7 @@
 #define	BADEXEC	"8@$#&(\n\n"
 		(void) write(1, BADEXEC, strlen(BADEXEC));
 		_exit(1);
-	} else if (pid < 0)
+	} else if (thispid < 0)
 		return -1;
 	(void) close(to[0]); close(from[1]);
 	tofp = fdopen(to[1], "w");
@@ -1312,25 +1473,25 @@
 	while ((buf = mgets(buf, &sawend, fromfp)) != NULL) {
 		if (strncmp(buf, BADEXEC, strlen(BADEXEC)-2) == 0) {
 			free(buf);
-			killr(pid);
+			killr(thispid);
 			return -1;
 		}
 		/*printf("241%c%s\n", sawend == 1 ? ' ' : '-', buf);*/
 	}
 
-	return pid;
+	return thispid;
 }
 
 void
-killr(pid)
-	int pid;
+killr(thispid)
+	int thispid;
 {
 	extern int kill();
 	
-	if (pid > 0) {
+	if (thispid > 0) {
 		(void) fclose(tofp);
 		(void) fclose(fromfp);
-		(void) kill(pid, SIGKILL);
+		(void) kill(thispid, SIGKILL);
 	}
 }
 
@@ -1396,7 +1557,7 @@
 	char *fmt, *s1, *s2, *s3;
 {
 	char format[BUFSIZ];
-	char *text = NULL;
+	const char *text = NULL;
 	char c;
 
 	if (code < 0) {
@@ -1542,7 +1703,7 @@
 	register FILE *out;
 {
 	register FILE *input;
-	register int c, state, *idxnum, *sts, endstate;
+	register int c, statei, *idxnum, *sts, endstate;
 
 	idxnum = indexnum+1;
 	idxnum['\r'] = 1;
@@ -1549,7 +1710,7 @@
 	idxnum['\n'] = 2;
 	idxnum['.'] = 3;
 	/* idxnum[EOF] = 4; */
-	state = 10;
+	statei = 10;
 	endstate = X_;
 	input = stdin;
 	sts = states;
@@ -1559,15 +1720,15 @@
 		if (c == EOF)		/* a little slower... */
 			return;
 #endif
-		if ((state = sts[state+idxnum[c]]) & ~0xff) {
-			if (state & O_) {
-				if (state == endstate)
-					return;
-				state = (char)state;
+		if ((statei = sts[statei+idxnum[c]]) & ~0xff) {
+			if (statei & O_) {
+				if (statei == endstate)
+					return ;
+				statei = (char)statei;
 				continue;
 			}
-			(void) putc((state>>8), out);
-			state = (char)state;
+			(void) putc((statei>>8), out);
+			statei = (char)statei;
 		}
 		(void) putc(c, out);
 	}
@@ -1583,15 +1744,15 @@
 	FILE *fp;
 	struct smtpconf scf, *head, *tail;
 	char c, *cp, buf[1024];
-	extern char *emalloc();
+        extern void *emalloc();
 
 	if ((fp = fopen(name, "r")) == NULL)
 		return NULL;
-	head = NULL;
+        head = tail = NULL;
 	while (fgets(buf, sizeof buf, fp) != NULL) {
 		if (buf[0] == '#' || (isascii(buf[0]) && isspace(buf[0])))
 			continue;
-		scf.flags = "";
+                scf.flags = (char *)"";
 		scf.next = NULL;
 		cp = buf;
 		SKIPWHILE(!isspace,cp);
@@ -1611,10 +1772,10 @@
 			if (isascii(*cp) && isalpha(*cp) && isupper(*cp))
 				*cp = tolower(*cp);
 		if (head == NULL) {
-			head = tail = (struct smtpconf *)emalloc(sizeof scf);
+                        head = tail = emalloc(sizeof scf);
 			*head = scf;
 		} else {
-			tail->next = (struct smtpconf *)emalloc(sizeof scf);
+                        tail->next = emalloc(sizeof scf);
 			*(tail->next) = scf;
 			tail = tail->next;
 		}
@@ -1629,6 +1790,7 @@
 {
 	struct smtpconf *scfp;
 	register char *cp, *s;
+	extern void *emalloc();
 
 	cp = emalloc(strlen(h)+1);
 	for (s = cp; *h != '\0'; ++h) {
--- proto/cf/server.cf	Sun Jan 20 01:09:17 1991
+++ /l/mail/zmail/conf/cf/server.cf	Fri Dec  4 12:41:22 1992
@@ -8,15 +8,23 @@
 	local text
 
 	case $(channel $quad) in
-	local)	text=$(login2uid $(user $quad))	# ignore return value
+	local)	sift "$(user $quad)" in
+	    [|].* text="Program delivery for" ; break ;;
+	    [/].* text="File delivery for" ; break ;;
+	    .*	text=$(login2uid "$(user $quad)");
+		if [ $text != $NOBODY ] ; then
 		if text="$(fullname $(user $quad))"; then
-			text="local delivery for $text"
+			text="250 local delivery for $text"
 		else
-			text="local delivery for"
+			text="550 unknown user"
 		fi
-		;;
+		else
+			text="550 Unknown user"
+		fi
+		break ;;
+	    tfis ;;
 	usenet)	text="local delivery to newsgroup" ;;
-	*)	text="$(channel $quad) delivery"
+	*)	text="250 $(channel $quad) delivery"
 		case "$(host $quad)" in
 		-|'')	text="$text for" ;;
 		*)	text="$text to $(host $quad) for" ;;
@@ -32,8 +40,10 @@
 #| function to interface with the rest of the configuration code.  The key
 #| specifies the semantics of the additional arguments provided by the
 #| smtpserver.  The key values are: init, to, from, verify, and expand.
+#| Additional values are hello, size and data. Hello may not print multiline
+#| values because smtpserver needs to do some special EHLO processing.
 
-	local a A
+	local a A elist b
 
 	A=$(newattribute default_attributes type sender)
 
@@ -44,30 +54,102 @@
 #| level should be appropriate.
 
 	case $key in
+        to|from|verify|expand)
+		db flush delivered
+#                a="$1"
+#                sift "$a" in
+#                <(.+)>  a="\1" ;;
+#                tfis
+#                if rfc822syntax "$a"; then ; else
+#                        echo "554 illegal address syntax: <$a>"
+#                        return
+#                fi
+#                ;;
+        esac
+ 
+        case $key in
 	init)	# If you want to log incoming connections, it can be done here
-		#echo server $@ >> /tmp/server
-		# redefine the log function
+#		echo server1 "$1" >> /tmp/server
+#		echo server2 "$2" >> /tmp/server
+		# redefine the log function, turn off logging output
 		log () {
 		}
+		exec 3>/dev/null
+		remhost="$(recase -l "$1")"
 		;;
-	to|from)
-		a="$(router "$1" default_attributes)"
+	hello)	a="$(router @"$1":postmaster default_attributes)"
+		for i in $(elements $a)
+		do
+			for j in $(elements $i)
+			do
+				case $(channel $j) in
+				error)	echo "250 $hostname '$1', I don't know that name! You're '$remhost'." ;;
+				*)	if [ "$(recase -l $1)" -eq "$remhost" ] ; then
+					    echo "250 $hostname Hi $1, nice to see you."
+					else
+					    echo "250 $hostname Hi $1 (alias $remhost), please behave yourself this time."
+					fi
+				;;
+				esac
+				return
+			done
+		done
+		echo "250 $hostname Hi $1 alias $remohst, please behave yourself."
+		;;
+	from)
+		a="$(router "$1" $A)"
 		for i in $(elements $a)
 		do
 			for j in $(elements $i)
 			do
 				case $(channel $j) in
-				error)	echo "554 unresolvable address: <$1>"
+				error)	echo "554 error - $(host $j) - <$1>"
 					return ;;
 				esac
-
-#| If any of the addresses in the expansion gave errors, we reject the
-#| original address.  The lack of distinction between different kinds of errors
-#| may be inadequate in some situations.
-
+			done
+		done
+		echo "250 Hmmm..."
+		srcaddr=$a
+		dstaddr=()
+		;;
+	to)
+		a="$(router "$1" $(newattribute default-attributes with PRESCAN headersize 1000 bodysize 1000))"
+		b=0
+		elist=""
+		for i in $(elements $a)
+		do
+			for j in $(elements $i)
+			do
+				case $(channel $j) in
+				error)	elist="$(host $j) $elist"
+					;;
+				*)	b=1
+					;;
+				esac
 			done
 		done
-		echo "250 Ok (verified)"
+		if [ $b = 1 ] ; then
+			echo "250 I'll try."
+                	case $#dstaddr in
+                	0)      dstaddr=$a
+                        	;;
+                	*)      
+                        	a=$(setf $(cdr $(last $dstaddr)) $a)
+                        	;;
+                	esac
+		else
+			echo "554 error - $elist - <$1>"
+		fi
+		;;
+	size)
+		echo "250 Room for $1 kBytes"
+		;;
+	data)
+		# for i in $(elements $dstaddr)
+		# do
+		#     grind "250-" $i
+		# done
+		echo "250 Let's see if this works..."
 		;;
 	verify)
 		a="$(router "$1" $A)"
@@ -81,6 +163,7 @@
 				quadprint $j
 			done
 		done
+		db flush expansions
 		;;
 	expand)
 		a="$(router "$1" default_attributes)"
@@ -94,6 +177,7 @@
 				quadprint $j
 			done
 		done
+		db flush expansions
 		;;
 	esac
 }

-- 
If a logical expression is hard to understand, try transforming it.
-- 
Matthias Urlichs  --  urlichs@smurf.sub.org -- urlichs@smurf.ira.uka.de   /(o\
Humboldtstrasse 7 -- 7500 Karlsruhe 1 -- Germany  --  +49-721-9612521     \o)/