122712Sdist /*
222712Sdist **  Sendmail
322712Sdist **  Copyright (c) 1983  Eric P. Allman
422712Sdist **  Berkeley, California
522712Sdist **
622712Sdist **  Copyright (c) 1983 Regents of the University of California.
722712Sdist **  All rights reserved.  The Berkeley software License Agreement
822712Sdist **  specifies the terms and conditions for redistribution.
922712Sdist */
1022712Sdist 
1122712Sdist 
129339Seric # include <errno.h>
134549Seric # include "sendmail.h"
1411728Seric # include <signal.h>
154549Seric 
165181Seric # ifndef SMTP
17*23122Seric # ifndef lint
18*23122Seric static char	SccsId[] = "@(#)srvrsmtp.c	5.4 (Berkeley) 06/08/85	(no SMTP)";
19*23122Seric # endif not lint
205181Seric # else SMTP
214556Seric 
22*23122Seric # ifndef lint
23*23122Seric static char	SccsId[] = "@(#)srvrsmtp.c	5.4 (Berkeley) 06/08/85";
24*23122Seric # endif not lint
255181Seric 
264549Seric /*
274549Seric **  SMTP -- run the SMTP protocol.
284549Seric **
294549Seric **	Parameters:
304549Seric **		none.
314549Seric **
324549Seric **	Returns:
334549Seric **		never.
344549Seric **
354549Seric **	Side Effects:
364549Seric **		Reads commands from the input channel and processes
374549Seric **			them.
384549Seric */
394549Seric 
404549Seric struct cmd
414549Seric {
424549Seric 	char	*cmdname;	/* command name */
434549Seric 	int	cmdcode;	/* internal code, see below */
444549Seric };
454549Seric 
464549Seric /* values for cmdcode */
474549Seric # define CMDERROR	0	/* bad command */
484549Seric # define CMDMAIL	1	/* mail -- designate sender */
494976Seric # define CMDRCPT	2	/* rcpt -- designate recipient */
504549Seric # define CMDDATA	3	/* data -- send message text */
519339Seric # define CMDRSET	4	/* rset -- reset state */
529339Seric # define CMDVRFY	5	/* vrfy -- verify address */
539339Seric # define CMDHELP	6	/* help -- give usage info */
549339Seric # define CMDNOOP	7	/* noop -- do nothing */
559339Seric # define CMDQUIT	8	/* quit -- close connection and die */
569339Seric # define CMDHELO	9	/* helo -- be polite */
579339Seric # define CMDDBGQSHOW	10	/* showq -- show send queue (DEBUG) */
589339Seric # define CMDDBGDEBUG	11	/* debug -- set debug mode */
599339Seric # define CMDVERB	12	/* verb -- go into verbose mode */
609339Seric # define CMDDBGKILL	13	/* kill -- kill sendmail */
619339Seric # define CMDDBGWIZ	14	/* wiz -- become a wizard */
629339Seric # define CMDONEX	15	/* onex -- sending one transaction only */
634549Seric 
644549Seric static struct cmd	CmdTab[] =
654549Seric {
664549Seric 	"mail",		CMDMAIL,
674976Seric 	"rcpt",		CMDRCPT,
684549Seric 	"data",		CMDDATA,
694549Seric 	"rset",		CMDRSET,
704549Seric 	"vrfy",		CMDVRFY,
717762Seric 	"expn",		CMDVRFY,
724549Seric 	"help",		CMDHELP,
734549Seric 	"noop",		CMDNOOP,
744549Seric 	"quit",		CMDQUIT,
754976Seric 	"helo",		CMDHELO,
768544Seric 	"verb",		CMDVERB,
779314Seric 	"onex",		CMDONEX,
785003Seric # ifdef DEBUG
799339Seric 	"showq",	CMDDBGQSHOW,
808544Seric 	"debug",	CMDDBGDEBUG,
818544Seric 	"kill",		CMDDBGKILL,
828544Seric 	"wiz",		CMDDBGWIZ,
835003Seric # endif DEBUG
844549Seric 	NULL,		CMDERROR,
854549Seric };
864549Seric 
878544Seric bool	IsWiz = FALSE;			/* set if we are a wizard */
8815596Seric char	*WizWord;			/* the wizard word to compare against */
899339Seric bool	InChild = FALSE;		/* true if running in a subprocess */
909378Seric bool	OneXact = FALSE;		/* one xaction only this run */
9111146Seric char	*RealHostName = NULL;		/* verified hostname, set in daemon.c */
9211146Seric 
939339Seric #define EX_QUIT		22		/* special code for QUIT command */
948544Seric 
954549Seric smtp()
964549Seric {
974549Seric 	register char *p;
988544Seric 	register struct cmd *c;
994549Seric 	char *cmd;
1004549Seric 	extern char *skipword();
1014549Seric 	extern bool sameword();
1024549Seric 	bool hasmail;			/* mail command received */
1034713Seric 	int rcps;			/* number of recipients */
1045003Seric 	auto ADDRESS *vrfyqueue;
10512612Seric 	ADDRESS *a;
1068544Seric 	char inp[MAXLINE];
1077124Seric 	extern char Version[];
1087356Seric 	extern tick();
1098544Seric 	extern bool iswiz();
1109349Seric 	extern char *arpadate();
11111151Seric 	extern char *macvalue();
11212612Seric 	extern ADDRESS *recipient();
1134549Seric 
1145003Seric 	hasmail = FALSE;
1154713Seric 	rcps = 0;
1167363Seric 	if (OutChannel != stdout)
1177363Seric 	{
1187363Seric 		/* arrange for debugging output to go to remote host */
1197363Seric 		(void) close(1);
1207363Seric 		(void) dup(fileno(OutChannel));
1217363Seric 	}
12211931Seric 	settime();
12316153Seric 	expand("\001e", inp, &inp[sizeof inp], CurEnv);
12410708Seric 	message("220", inp);
1254549Seric 	for (;;)
1264549Seric 	{
12712612Seric 		/* arrange for backout */
12812612Seric 		if (setjmp(TopFrame) > 0 && InChild)
12912612Seric 			finis();
13012612Seric 		QuickAbort = FALSE;
13112612Seric 		HoldErrs = FALSE;
13212612Seric 
1337356Seric 		/* setup for the read */
1346907Seric 		CurEnv->e_to = NULL;
1354577Seric 		Errors = 0;
1367275Seric 		(void) fflush(stdout);
1377356Seric 
1387356Seric 		/* read the input line */
1397685Seric 		p = sfgets(inp, sizeof inp, InChannel);
1407356Seric 
1417685Seric 		/* handle errors */
1427356Seric 		if (p == NULL)
1437356Seric 		{
1444549Seric 			/* end of file, just die */
1454558Seric 			message("421", "%s Lost input channel", HostName);
1464549Seric 			finis();
1474549Seric 		}
1484549Seric 
1494549Seric 		/* clean up end of line */
1504558Seric 		fixcrlf(inp, TRUE);
1514549Seric 
1524713Seric 		/* echo command to transcript */
1539545Seric 		if (CurEnv->e_xfp != NULL)
1549545Seric 			fprintf(CurEnv->e_xfp, "<<< %s\n", inp);
1554713Seric 
1564549Seric 		/* break off command */
1574549Seric 		for (p = inp; isspace(*p); p++)
1584549Seric 			continue;
1594549Seric 		cmd = p;
1604549Seric 		while (*++p != '\0' && !isspace(*p))
1614549Seric 			continue;
1624549Seric 		if (*p != '\0')
1634549Seric 			*p++ = '\0';
1644549Seric 
1654549Seric 		/* decode command */
1664549Seric 		for (c = CmdTab; c->cmdname != NULL; c++)
1674549Seric 		{
1684549Seric 			if (sameword(c->cmdname, cmd))
1694549Seric 				break;
1704549Seric 		}
1714549Seric 
1724549Seric 		/* process command */
1734549Seric 		switch (c->cmdcode)
1744549Seric 		{
1754976Seric 		  case CMDHELO:		/* hello -- introduce yourself */
17614877Seric 			if (sameword(p, HostName))
17714877Seric 			{
17814877Seric 				/* connected to an echo server */
17914877Seric 				message("553", "%s I refuse to talk to myself",
18014877Seric 					HostName);
18114877Seric 				break;
18214877Seric 			}
18311146Seric 			if (RealHostName != NULL && !sameword(p, RealHostName))
18411146Seric 			{
18511146Seric 				char buf[MAXNAME];
18611146Seric 
18711146Seric 				(void) sprintf(buf, "%s (%s)", p, RealHostName);
18811146Seric 				define('s', newstr(buf), CurEnv);
18911146Seric 			}
19011146Seric 			else
19111146Seric 				define('s', newstr(p), CurEnv);
1924997Seric 			message("250", "%s Hello %s, pleased to meet you",
1934997Seric 				HostName, p);
1944976Seric 			break;
1954976Seric 
1964549Seric 		  case CMDMAIL:		/* mail -- designate sender */
19711151Seric 			/* force a sending host even if no HELO given */
19811151Seric 			if (RealHostName != NULL && macvalue('s', CurEnv) == NULL)
19911151Seric 				define('s', RealHostName, CurEnv);
20011151Seric 
2019314Seric 			/* check for validity of this command */
2024558Seric 			if (hasmail)
2034558Seric 			{
2044558Seric 				message("503", "Sender already specified");
2054558Seric 				break;
2064558Seric 			}
2079339Seric 			if (InChild)
2089339Seric 			{
2099339Seric 				syserr("Nested MAIL command");
2109339Seric 				exit(0);
2119339Seric 			}
2129339Seric 
2139339Seric 			/* fork a subprocess to process this command */
2149339Seric 			if (runinchild("SMTP-MAIL") > 0)
2159339Seric 				break;
2169339Seric 			initsys();
2179339Seric 
2189339Seric 			/* child -- go do the processing */
2194549Seric 			p = skipword(p, "from");
2204549Seric 			if (p == NULL)
2214549Seric 				break;
2224549Seric 			setsender(p);
2234577Seric 			if (Errors == 0)
2244549Seric 			{
2254549Seric 				message("250", "Sender ok");
2264549Seric 				hasmail = TRUE;
2274549Seric 			}
2289339Seric 			else if (InChild)
2299339Seric 				finis();
2304549Seric 			break;
2314549Seric 
2324976Seric 		  case CMDRCPT:		/* rcpt -- designate recipient */
23312612Seric 			if (setjmp(TopFrame) > 0)
23414785Seric 			{
23514785Seric 				CurEnv->e_flags &= ~EF_FATALERRS;
23612612Seric 				break;
23714785Seric 			}
23812612Seric 			QuickAbort = TRUE;
2394549Seric 			p = skipword(p, "to");
2404549Seric 			if (p == NULL)
2414549Seric 				break;
24216140Seric 			a = parseaddr(p, (ADDRESS *) NULL, 1, '\0');
24312612Seric 			if (a == NULL)
24412612Seric 				break;
24516886Seric 			a->q_flags |= QPRIMARY;
24612612Seric 			a = recipient(a, &CurEnv->e_sendqueue);
24712612Seric 			if (Errors != 0)
24812612Seric 				break;
24912612Seric 
25012612Seric 			/* no errors during parsing, but might be a duplicate */
25112612Seric 			CurEnv->e_to = p;
25212612Seric 			if (!bitset(QBADADDR, a->q_flags))
25312612Seric 				message("250", "Recipient ok");
25412612Seric 			else
2554549Seric 			{
25612612Seric 				/* punt -- should keep message in ADDRESS.... */
25712612Seric 				message("550", "Addressee unknown");
2584549Seric 			}
25912612Seric 			CurEnv->e_to = NULL;
26012612Seric 			rcps++;
2614549Seric 			break;
2624549Seric 
2634549Seric 		  case CMDDATA:		/* data -- text of mail */
2644976Seric 			if (!hasmail)
2654549Seric 			{
2664976Seric 				message("503", "Need MAIL command");
2674976Seric 				break;
2684549Seric 			}
2694713Seric 			else if (rcps <= 0)
2704549Seric 			{
2714976Seric 				message("503", "Need RCPT (recipient)");
2724976Seric 				break;
2734549Seric 			}
2744976Seric 
2754976Seric 			/* collect the text of the message */
2764976Seric 			collect(TRUE);
2774976Seric 			if (Errors != 0)
2784976Seric 				break;
2794976Seric 
2808238Seric 			/*
2818238Seric 			**  Arrange to send to everyone.
2828238Seric 			**	If sending to multiple people, mail back
2838238Seric 			**		errors rather than reporting directly.
2848238Seric 			**	In any case, don't mail back errors for
2858238Seric 			**		anything that has happened up to
2868238Seric 			**		now (the other end will do this).
28710197Seric 			**	Truncate our transcript -- the mail has gotten
28810197Seric 			**		to us successfully, and if we have
28910197Seric 			**		to mail this back, it will be easier
29010197Seric 			**		on the reader.
2918238Seric 			**	Then send to everyone.
2928238Seric 			**	Finally give a reply code.  If an error has
2938238Seric 			**		already been given, don't mail a
2948238Seric 			**		message back.
2959339Seric 			**	We goose error returns by clearing error bit.
2968238Seric 			*/
2978238Seric 
2984976Seric 			if (rcps != 1)
2999378Seric 			{
3009378Seric 				HoldErrs = TRUE;
30116886Seric 				ErrorMode = EM_MAIL;
3029378Seric 			}
3039339Seric 			CurEnv->e_flags &= ~EF_FATALERRS;
30410197Seric 			CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp);
3054976Seric 
3064976Seric 			/* send to all recipients */
30714877Seric 			sendall(CurEnv, SM_DEFAULT);
3086907Seric 			CurEnv->e_to = NULL;
3094976Seric 
3108238Seric 			/* issue success if appropriate and reset */
3118238Seric 			if (Errors == 0 || HoldErrs)
3129283Seric 				message("250", "Ok");
3138238Seric 			else
3149339Seric 				CurEnv->e_flags &= ~EF_FATALERRS;
3159339Seric 
3169339Seric 			/* if in a child, pop back to our parent */
3179339Seric 			if (InChild)
3189339Seric 				finis();
3194549Seric 			break;
3204549Seric 
3214549Seric 		  case CMDRSET:		/* rset -- reset state */
3224549Seric 			message("250", "Reset state");
3239339Seric 			if (InChild)
3249339Seric 				finis();
3259339Seric 			break;
3264549Seric 
3274549Seric 		  case CMDVRFY:		/* vrfy -- verify address */
3289339Seric 			if (runinchild("SMTP-VRFY") > 0)
3299339Seric 				break;
3305003Seric 			vrfyqueue = NULL;
3317762Seric 			QuickAbort = TRUE;
3329619Seric 			sendtolist(p, (ADDRESS *) NULL, &vrfyqueue);
3337762Seric 			if (Errors != 0)
3349339Seric 			{
3359339Seric 				if (InChild)
3369339Seric 					finis();
3377762Seric 				break;
3389339Seric 			}
3395003Seric 			while (vrfyqueue != NULL)
3405003Seric 			{
3415003Seric 				register ADDRESS *a = vrfyqueue->q_next;
3425003Seric 				char *code;
3435003Seric 
3447685Seric 				while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags))
3455003Seric 					a = a->q_next;
3465003Seric 
3477685Seric 				if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))
3485003Seric 				{
3495003Seric 					if (a != NULL)
3505003Seric 						code = "250-";
3515003Seric 					else
3525003Seric 						code = "250";
3535003Seric 					if (vrfyqueue->q_fullname == NULL)
3545003Seric 						message(code, "<%s>", vrfyqueue->q_paddr);
3555003Seric 					else
3565003Seric 						message(code, "%s <%s>",
3575003Seric 						    vrfyqueue->q_fullname, vrfyqueue->q_paddr);
3585003Seric 				}
3595003Seric 				else if (a == NULL)
3605003Seric 					message("554", "Self destructive alias loop");
3615003Seric 				vrfyqueue = a;
3625003Seric 			}
3639339Seric 			if (InChild)
3649339Seric 				finis();
3654549Seric 			break;
3664549Seric 
3674549Seric 		  case CMDHELP:		/* help -- give user info */
3684577Seric 			if (*p == '\0')
3694577Seric 				p = "SMTP";
3704577Seric 			help(p);
3714549Seric 			break;
3724549Seric 
3734549Seric 		  case CMDNOOP:		/* noop -- do nothing */
3744549Seric 			message("200", "OK");
3754549Seric 			break;
3764549Seric 
3774549Seric 		  case CMDQUIT:		/* quit -- leave mail */
3784549Seric 			message("221", "%s closing connection", HostName);
3799339Seric 			if (InChild)
3809339Seric 				ExitStat = EX_QUIT;
3814549Seric 			finis();
3824549Seric 
3838544Seric 		  case CMDVERB:		/* set verbose mode */
3848544Seric 			Verbose = TRUE;
3858544Seric 			message("200", "Verbose mode");
3868544Seric 			break;
3878544Seric 
3889314Seric 		  case CMDONEX:		/* doing one transaction only */
3899378Seric 			OneXact = TRUE;
3909314Seric 			message("200", "Only one transaction");
3919314Seric 			break;
3929314Seric 
3935003Seric # ifdef DEBUG
3949339Seric 		  case CMDDBGQSHOW:	/* show queues */
3956907Seric 			printf("Send Queue=");
3966907Seric 			printaddr(CurEnv->e_sendqueue, TRUE);
3975003Seric 			break;
3987275Seric 
3997275Seric 		  case CMDDBGDEBUG:	/* set debug mode */
4007676Seric 			tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
4017676Seric 			tTflag(p);
4027676Seric 			message("200", "Debug set");
4037275Seric 			break;
4047275Seric 
4057282Seric 		  case CMDDBGKILL:	/* kill the parent */
4068544Seric 			if (!iswiz())
4078544Seric 				break;
4087282Seric 			if (kill(MotherPid, SIGTERM) >= 0)
4097282Seric 				message("200", "Mother is dead");
4107282Seric 			else
4117282Seric 				message("500", "Can't kill Mom");
4127282Seric 			break;
4138544Seric 
4148544Seric 		  case CMDDBGWIZ:	/* become a wizard */
4158544Seric 			if (WizWord != NULL)
4168544Seric 			{
4178544Seric 				char seed[3];
4188544Seric 				extern char *crypt();
4198544Seric 
42023106Seric 				(void) strncpy(seed, WizWord, 2);
42115596Seric 				if (strcmp(WizWord, crypt(p, seed)) == 0)
4228544Seric 				{
42315596Seric 					IsWiz = TRUE;
42415596Seric 					message("200", "Please pass, oh mighty wizard");
4258544Seric 					break;
4268544Seric 				}
4278544Seric 			}
42815596Seric 			message("500", "You are no wizard!");
4298544Seric 			break;
4305003Seric # endif DEBUG
4315003Seric 
4324549Seric 		  case CMDERROR:	/* unknown command */
4334549Seric 			message("500", "Command unrecognized");
4344549Seric 			break;
4354549Seric 
4364549Seric 		  default:
4374549Seric 			syserr("smtp: unknown code %d", c->cmdcode);
4384549Seric 			break;
4394549Seric 		}
4404549Seric 	}
4414549Seric }
4424549Seric /*
4434549Seric **  SKIPWORD -- skip a fixed word.
4444549Seric **
4454549Seric **	Parameters:
4464549Seric **		p -- place to start looking.
4474549Seric **		w -- word to skip.
4484549Seric **
4494549Seric **	Returns:
4504549Seric **		p following w.
4514549Seric **		NULL on error.
4524549Seric **
4534549Seric **	Side Effects:
4544549Seric **		clobbers the p data area.
4554549Seric */
4564549Seric 
4574549Seric static char *
4584549Seric skipword(p, w)
4594549Seric 	register char *p;
4604549Seric 	char *w;
4614549Seric {
4624549Seric 	register char *q;
4634549Seric 	extern bool sameword();
4644549Seric 
4654549Seric 	/* find beginning of word */
4664549Seric 	while (isspace(*p))
4674549Seric 		p++;
4684549Seric 	q = p;
4694549Seric 
4704549Seric 	/* find end of word */
4714549Seric 	while (*p != '\0' && *p != ':' && !isspace(*p))
4724549Seric 		p++;
4734549Seric 	while (isspace(*p))
4744549Seric 		*p++ = '\0';
4754549Seric 	if (*p != ':')
4764549Seric 	{
4774549Seric 	  syntax:
4784549Seric 		message("501", "Syntax error");
4794549Seric 		Errors++;
4804549Seric 		return (NULL);
4814549Seric 	}
4824549Seric 	*p++ = '\0';
4834549Seric 	while (isspace(*p))
4844549Seric 		p++;
4854549Seric 
4864549Seric 	/* see if the input word matches desired word */
4874549Seric 	if (!sameword(q, w))
4884549Seric 		goto syntax;
4894549Seric 
4904549Seric 	return (p);
4914549Seric }
4924577Seric /*
4934577Seric **  HELP -- implement the HELP command.
4944577Seric **
4954577Seric **	Parameters:
4964577Seric **		topic -- the topic we want help for.
4974577Seric **
4984577Seric **	Returns:
4994577Seric **		none.
5004577Seric **
5014577Seric **	Side Effects:
5024577Seric **		outputs the help file to message output.
5034577Seric */
5044577Seric 
5054577Seric help(topic)
5064577Seric 	char *topic;
5074577Seric {
5084577Seric 	register FILE *hf;
5094577Seric 	int len;
5104577Seric 	char buf[MAXLINE];
5114577Seric 	bool noinfo;
5124577Seric 
5138269Seric 	if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL)
5144577Seric 	{
5154577Seric 		/* no help */
51611931Seric 		errno = 0;
5174577Seric 		message("502", "HELP not implemented");
5184577Seric 		return;
5194577Seric 	}
5204577Seric 
5214577Seric 	len = strlen(topic);
5224577Seric 	makelower(topic);
5234577Seric 	noinfo = TRUE;
5244577Seric 
5254577Seric 	while (fgets(buf, sizeof buf, hf) != NULL)
5264577Seric 	{
5274577Seric 		if (strncmp(buf, topic, len) == 0)
5284577Seric 		{
5294577Seric 			register char *p;
5304577Seric 
5314577Seric 			p = index(buf, '\t');
5324577Seric 			if (p == NULL)
5334577Seric 				p = buf;
5344577Seric 			else
5354577Seric 				p++;
5364577Seric 			fixcrlf(p, TRUE);
5374577Seric 			message("214-", p);
5384577Seric 			noinfo = FALSE;
5394577Seric 		}
5404577Seric 	}
5414577Seric 
5424577Seric 	if (noinfo)
5434577Seric 		message("504", "HELP topic unknown");
5444577Seric 	else
5454577Seric 		message("214", "End of HELP info");
5464628Seric 	(void) fclose(hf);
5474577Seric }
5488544Seric /*
5498544Seric **  ISWIZ -- tell us if we are a wizard
5508544Seric **
5518544Seric **	If not, print a nasty message.
5528544Seric **
5538544Seric **	Parameters:
5548544Seric **		none.
5558544Seric **
5568544Seric **	Returns:
5578544Seric **		TRUE if we are a wizard.
5588544Seric **		FALSE if we are not a wizard.
5598544Seric **
5608544Seric **	Side Effects:
5618544Seric **		Prints a 500 exit stat if we are not a wizard.
5628544Seric */
5635181Seric 
56419038Seric #ifdef DEBUG
56519038Seric 
5668544Seric bool
5678544Seric iswiz()
5688544Seric {
5698544Seric 	if (!IsWiz)
5708544Seric 		message("500", "Mere mortals musn't mutter that mantra");
5718544Seric 	return (IsWiz);
5728544Seric }
57319038Seric 
57419038Seric #endif DEBUG
5759339Seric /*
5769339Seric **  RUNINCHILD -- return twice -- once in the child, then in the parent again
5779339Seric **
5789339Seric **	Parameters:
5799339Seric **		label -- a string used in error messages
5809339Seric **
5819339Seric **	Returns:
5829339Seric **		zero in the child
5839339Seric **		one in the parent
5849339Seric **
5859339Seric **	Side Effects:
5869339Seric **		none.
5879339Seric */
5888544Seric 
5899339Seric runinchild(label)
5909339Seric 	char *label;
5919339Seric {
5929339Seric 	int childpid;
5939339Seric 
59416158Seric 	if (!OneXact)
5959339Seric 	{
59616158Seric 		childpid = dofork();
59716158Seric 		if (childpid < 0)
59816158Seric 		{
59916158Seric 			syserr("%s: cannot fork", label);
60016158Seric 			return (1);
60116158Seric 		}
60216158Seric 		if (childpid > 0)
60316158Seric 		{
60416158Seric 			auto int st;
6059339Seric 
60616158Seric 			/* parent -- wait for child to complete */
60716158Seric 			st = waitfor(childpid);
60816158Seric 			if (st == -1)
60916158Seric 				syserr("%s: lost child", label);
6109339Seric 
61116158Seric 			/* if we exited on a QUIT command, complete the process */
61216158Seric 			if (st == (EX_QUIT << 8))
61316158Seric 				finis();
6149339Seric 
61516158Seric 			return (1);
61616158Seric 		}
61716158Seric 		else
61816158Seric 		{
61916158Seric 			/* child */
62016158Seric 			InChild = TRUE;
62116158Seric 		}
6229339Seric 	}
62315256Seric 
62416158Seric 	/* child (or ONEX command specified) */
62516158Seric 	clearenvelope(CurEnv);
62615256Seric 
62716158Seric 	/* open alias database */
62816158Seric 	initaliases(AliasFile, FALSE);
62916158Seric 
63016158Seric 	return (0);
6319339Seric }
6329339Seric 
6335181Seric # endif SMTP
634