122712Sdist /*
234921Sbostic  * Copyright (c) 1983 Eric P. Allman
333731Sbostic  * Copyright (c) 1988 Regents of the University of California.
433731Sbostic  * All rights reserved.
533731Sbostic  *
642829Sbostic  * %sccs.include.redist.c%
733731Sbostic  */
822712Sdist 
933731Sbostic # include "sendmail.h"
1022712Sdist 
1133731Sbostic #ifndef lint
1233731Sbostic #ifdef SMTP
13*49669Seric static char sccsid[] = "@(#)srvrsmtp.c	5.31 (Berkeley) 05/10/91 (with SMTP)";
1433731Sbostic #else
15*49669Seric static char sccsid[] = "@(#)srvrsmtp.c	5.31 (Berkeley) 05/10/91 (without SMTP)";
1633731Sbostic #endif
1733731Sbostic #endif /* not lint */
1833731Sbostic 
199339Seric # include <errno.h>
2011728Seric # include <signal.h>
214549Seric 
2233731Sbostic # ifdef SMTP
234556Seric 
244549Seric /*
254549Seric **  SMTP -- run the SMTP protocol.
264549Seric **
274549Seric **	Parameters:
284549Seric **		none.
294549Seric **
304549Seric **	Returns:
314549Seric **		never.
324549Seric **
334549Seric **	Side Effects:
344549Seric **		Reads commands from the input channel and processes
354549Seric **			them.
364549Seric */
374549Seric 
384549Seric struct cmd
394549Seric {
404549Seric 	char	*cmdname;	/* command name */
414549Seric 	int	cmdcode;	/* internal code, see below */
424549Seric };
434549Seric 
444549Seric /* values for cmdcode */
454549Seric # define CMDERROR	0	/* bad command */
464549Seric # define CMDMAIL	1	/* mail -- designate sender */
474976Seric # define CMDRCPT	2	/* rcpt -- designate recipient */
484549Seric # define CMDDATA	3	/* data -- send message text */
499339Seric # define CMDRSET	4	/* rset -- reset state */
509339Seric # define CMDVRFY	5	/* vrfy -- verify address */
519339Seric # define CMDHELP	6	/* help -- give usage info */
529339Seric # define CMDNOOP	7	/* noop -- do nothing */
539339Seric # define CMDQUIT	8	/* quit -- close connection and die */
549339Seric # define CMDHELO	9	/* helo -- be polite */
5536230Skarels # define CMDONEX	10	/* onex -- sending one transaction only */
5636230Skarels # define CMDVERB	11	/* verb -- go into verbose mode */
5736230Skarels /* debugging-only commands, only enabled if SMTPDEBUG is defined */
5836230Skarels # define CMDDBGQSHOW	12	/* showq -- show send queue */
5936230Skarels # define CMDDBGDEBUG	13	/* debug -- set debug mode */
604549Seric 
614549Seric static struct cmd	CmdTab[] =
624549Seric {
634549Seric 	"mail",		CMDMAIL,
644976Seric 	"rcpt",		CMDRCPT,
654549Seric 	"data",		CMDDATA,
664549Seric 	"rset",		CMDRSET,
674549Seric 	"vrfy",		CMDVRFY,
687762Seric 	"expn",		CMDVRFY,
694549Seric 	"help",		CMDHELP,
704549Seric 	"noop",		CMDNOOP,
714549Seric 	"quit",		CMDQUIT,
724976Seric 	"helo",		CMDHELO,
738544Seric 	"verb",		CMDVERB,
749314Seric 	"onex",		CMDONEX,
7536230Skarels 	/*
7636230Skarels 	 * remaining commands are here only
7736230Skarels 	 * to trap and log attempts to use them
7836230Skarels 	 */
799339Seric 	"showq",	CMDDBGQSHOW,
808544Seric 	"debug",	CMDDBGDEBUG,
814549Seric 	NULL,		CMDERROR,
824549Seric };
834549Seric 
849339Seric bool	InChild = FALSE;		/* true if running in a subprocess */
859378Seric bool	OneXact = FALSE;		/* one xaction only this run */
8611146Seric 
879339Seric #define EX_QUIT		22		/* special code for QUIT command */
888544Seric 
894549Seric smtp()
904549Seric {
914549Seric 	register char *p;
928544Seric 	register struct cmd *c;
934549Seric 	char *cmd;
9446928Sbostic 	static char *skipword();
954549Seric 	bool hasmail;			/* mail command received */
965003Seric 	auto ADDRESS *vrfyqueue;
9712612Seric 	ADDRESS *a;
9830448Seric 	char *sendinghost;
998544Seric 	char inp[MAXLINE];
10024981Seric 	char cmdbuf[100];
1017124Seric 	extern char Version[];
10211151Seric 	extern char *macvalue();
10312612Seric 	extern ADDRESS *recipient();
10424943Seric 	extern ENVELOPE BlankEnvelope;
10524943Seric 	extern ENVELOPE *newenvelope();
1064549Seric 
1075003Seric 	hasmail = FALSE;
1087363Seric 	if (OutChannel != stdout)
1097363Seric 	{
1107363Seric 		/* arrange for debugging output to go to remote host */
1117363Seric 		(void) close(1);
1127363Seric 		(void) dup(fileno(OutChannel));
1137363Seric 	}
11411931Seric 	settime();
11524971Seric 	if (RealHostName != NULL)
11625050Seric 	{
11725050Seric 		CurHostName = RealHostName;
11825050Seric 		setproctitle("srvrsmtp %s", CurHostName);
11925050Seric 	}
12025050Seric 	else
12125050Seric 	{
12225050Seric 		/* this must be us!! */
12325050Seric 		CurHostName = MyHostName;
12425050Seric 	}
12516153Seric 	expand("\001e", inp, &inp[sizeof inp], CurEnv);
12610708Seric 	message("220", inp);
12724943Seric 	SmtpPhase = "startup";
12830448Seric 	sendinghost = NULL;
1294549Seric 	for (;;)
1304549Seric 	{
13112612Seric 		/* arrange for backout */
13212612Seric 		if (setjmp(TopFrame) > 0 && InChild)
13312612Seric 			finis();
13412612Seric 		QuickAbort = FALSE;
13512612Seric 		HoldErrs = FALSE;
13612612Seric 
1377356Seric 		/* setup for the read */
1386907Seric 		CurEnv->e_to = NULL;
1394577Seric 		Errors = 0;
1407275Seric 		(void) fflush(stdout);
1417356Seric 
1427356Seric 		/* read the input line */
1437685Seric 		p = sfgets(inp, sizeof inp, InChannel);
1447356Seric 
1457685Seric 		/* handle errors */
1467356Seric 		if (p == NULL)
1477356Seric 		{
1484549Seric 			/* end of file, just die */
14936230Skarels 			message("421", "%s Lost input channel from %s",
15025050Seric 				MyHostName, CurHostName);
1514549Seric 			finis();
1524549Seric 		}
1534549Seric 
1544549Seric 		/* clean up end of line */
1554558Seric 		fixcrlf(inp, TRUE);
1564549Seric 
1574713Seric 		/* echo command to transcript */
1589545Seric 		if (CurEnv->e_xfp != NULL)
1599545Seric 			fprintf(CurEnv->e_xfp, "<<< %s\n", inp);
1604713Seric 
1614549Seric 		/* break off command */
1624549Seric 		for (p = inp; isspace(*p); p++)
1634549Seric 			continue;
1644549Seric 		cmd = p;
16524981Seric 		for (cmd = cmdbuf; *p != '\0' && !isspace(*p); )
16624981Seric 			*cmd++ = *p++;
16724981Seric 		*cmd = '\0';
1684549Seric 
16925691Seric 		/* throw away leading whitespace */
17025691Seric 		while (isspace(*p))
17125691Seric 			p++;
17225691Seric 
1734549Seric 		/* decode command */
1744549Seric 		for (c = CmdTab; c->cmdname != NULL; c++)
1754549Seric 		{
17633725Sbostic 			if (!strcasecmp(c->cmdname, cmdbuf))
1774549Seric 				break;
1784549Seric 		}
1794549Seric 
1804549Seric 		/* process command */
1814549Seric 		switch (c->cmdcode)
1824549Seric 		{
1834976Seric 		  case CMDHELO:		/* hello -- introduce yourself */
18424943Seric 			SmtpPhase = "HELO";
18525050Seric 			setproctitle("%s: %s", CurHostName, inp);
18633725Sbostic 			if (!strcasecmp(p, MyHostName))
18714877Seric 			{
18836230Skarels 				/*
18936230Skarels 				 * didn't know about alias,
19036230Skarels 				 * or connected to an echo server
19136230Skarels 				 */
19247570Seric 				message("553", "%s config error: mail loops back to myself",
19347570Seric 					MyHostName);
19414877Seric 				break;
19514877Seric 			}
19633725Sbostic 			if (RealHostName != NULL && strcasecmp(p, RealHostName))
19711146Seric 			{
19824981Seric 				char hostbuf[MAXNAME];
19911146Seric 
20024981Seric 				(void) sprintf(hostbuf, "%s (%s)", p, RealHostName);
20130448Seric 				sendinghost = newstr(hostbuf);
20211146Seric 			}
20311146Seric 			else
20430448Seric 				sendinghost = newstr(p);
2054997Seric 			message("250", "%s Hello %s, pleased to meet you",
20636230Skarels 				MyHostName, sendinghost);
2074976Seric 			break;
2084976Seric 
2094549Seric 		  case CMDMAIL:		/* mail -- designate sender */
21024943Seric 			SmtpPhase = "MAIL";
21124943Seric 
21211151Seric 			/* force a sending host even if no HELO given */
21311151Seric 			if (RealHostName != NULL && macvalue('s', CurEnv) == NULL)
21430448Seric 				sendinghost = RealHostName;
21511151Seric 
2169314Seric 			/* check for validity of this command */
2174558Seric 			if (hasmail)
2184558Seric 			{
2194558Seric 				message("503", "Sender already specified");
2204558Seric 				break;
2214558Seric 			}
2229339Seric 			if (InChild)
2239339Seric 			{
22436230Skarels 				errno = 0;
2259339Seric 				syserr("Nested MAIL command");
2269339Seric 				exit(0);
2279339Seric 			}
2289339Seric 
2299339Seric 			/* fork a subprocess to process this command */
2309339Seric 			if (runinchild("SMTP-MAIL") > 0)
2319339Seric 				break;
23230448Seric 			define('s', sendinghost, CurEnv);
23336579Sbostic 			define('r', "SMTP", CurEnv);
2349339Seric 			initsys();
23525016Seric 			setproctitle("%s %s: %s", CurEnv->e_id,
23625050Seric 				CurHostName, inp);
2379339Seric 
2389339Seric 			/* child -- go do the processing */
2394549Seric 			p = skipword(p, "from");
2404549Seric 			if (p == NULL)
2414549Seric 				break;
2424549Seric 			setsender(p);
2434577Seric 			if (Errors == 0)
2444549Seric 			{
2454549Seric 				message("250", "Sender ok");
2464549Seric 				hasmail = TRUE;
2474549Seric 			}
2489339Seric 			else if (InChild)
2499339Seric 				finis();
2504549Seric 			break;
2514549Seric 
2524976Seric 		  case CMDRCPT:		/* rcpt -- designate recipient */
25324943Seric 			SmtpPhase = "RCPT";
25425016Seric 			setproctitle("%s %s: %s", CurEnv->e_id,
25525050Seric 				CurHostName, inp);
25612612Seric 			if (setjmp(TopFrame) > 0)
25714785Seric 			{
25814785Seric 				CurEnv->e_flags &= ~EF_FATALERRS;
25912612Seric 				break;
26014785Seric 			}
26112612Seric 			QuickAbort = TRUE;
2624549Seric 			p = skipword(p, "to");
2634549Seric 			if (p == NULL)
2644549Seric 				break;
26516140Seric 			a = parseaddr(p, (ADDRESS *) NULL, 1, '\0');
26612612Seric 			if (a == NULL)
26712612Seric 				break;
26816886Seric 			a->q_flags |= QPRIMARY;
26912612Seric 			a = recipient(a, &CurEnv->e_sendqueue);
27012612Seric 			if (Errors != 0)
27112612Seric 				break;
27212612Seric 
27312612Seric 			/* no errors during parsing, but might be a duplicate */
27412612Seric 			CurEnv->e_to = p;
27512612Seric 			if (!bitset(QBADADDR, a->q_flags))
27612612Seric 				message("250", "Recipient ok");
27712612Seric 			else
2784549Seric 			{
27912612Seric 				/* punt -- should keep message in ADDRESS.... */
28012612Seric 				message("550", "Addressee unknown");
2814549Seric 			}
28212612Seric 			CurEnv->e_to = NULL;
2834549Seric 			break;
2844549Seric 
2854549Seric 		  case CMDDATA:		/* data -- text of mail */
28624943Seric 			SmtpPhase = "DATA";
2874976Seric 			if (!hasmail)
2884549Seric 			{
2894976Seric 				message("503", "Need MAIL command");
2904976Seric 				break;
2914549Seric 			}
29224943Seric 			else if (CurEnv->e_nrcpts <= 0)
2934549Seric 			{
2944976Seric 				message("503", "Need RCPT (recipient)");
2954976Seric 				break;
2964549Seric 			}
2974976Seric 
2984976Seric 			/* collect the text of the message */
29924943Seric 			SmtpPhase = "collect";
30025016Seric 			setproctitle("%s %s: %s", CurEnv->e_id,
30125050Seric 				CurHostName, inp);
3024976Seric 			collect(TRUE);
3034976Seric 			if (Errors != 0)
3044976Seric 				break;
3054976Seric 
3068238Seric 			/*
3078238Seric 			**  Arrange to send to everyone.
3088238Seric 			**	If sending to multiple people, mail back
3098238Seric 			**		errors rather than reporting directly.
3108238Seric 			**	In any case, don't mail back errors for
3118238Seric 			**		anything that has happened up to
3128238Seric 			**		now (the other end will do this).
31310197Seric 			**	Truncate our transcript -- the mail has gotten
31410197Seric 			**		to us successfully, and if we have
31510197Seric 			**		to mail this back, it will be easier
31610197Seric 			**		on the reader.
3178238Seric 			**	Then send to everyone.
3188238Seric 			**	Finally give a reply code.  If an error has
3198238Seric 			**		already been given, don't mail a
3208238Seric 			**		message back.
3219339Seric 			**	We goose error returns by clearing error bit.
3228238Seric 			*/
3238238Seric 
32424943Seric 			SmtpPhase = "delivery";
32524943Seric 			if (CurEnv->e_nrcpts != 1)
3269378Seric 			{
3279378Seric 				HoldErrs = TRUE;
32816886Seric 				ErrorMode = EM_MAIL;
3299378Seric 			}
3309339Seric 			CurEnv->e_flags &= ~EF_FATALERRS;
33110197Seric 			CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp);
3324976Seric 
3334976Seric 			/* send to all recipients */
33414877Seric 			sendall(CurEnv, SM_DEFAULT);
3356907Seric 			CurEnv->e_to = NULL;
3364976Seric 
33723516Seric 			/* save statistics */
33823516Seric 			markstats(CurEnv, (ADDRESS *) NULL);
33923516Seric 
3408238Seric 			/* issue success if appropriate and reset */
3418238Seric 			if (Errors == 0 || HoldErrs)
3429283Seric 				message("250", "Ok");
3438238Seric 			else
3449339Seric 				CurEnv->e_flags &= ~EF_FATALERRS;
3459339Seric 
3469339Seric 			/* if in a child, pop back to our parent */
3479339Seric 			if (InChild)
3489339Seric 				finis();
34924943Seric 
35024943Seric 			/* clean up a bit */
35124943Seric 			hasmail = 0;
35224943Seric 			dropenvelope(CurEnv);
35324943Seric 			CurEnv = newenvelope(CurEnv);
35424943Seric 			CurEnv->e_flags = BlankEnvelope.e_flags;
3554549Seric 			break;
3564549Seric 
3574549Seric 		  case CMDRSET:		/* rset -- reset state */
3584549Seric 			message("250", "Reset state");
3599339Seric 			if (InChild)
3609339Seric 				finis();
3619339Seric 			break;
3624549Seric 
3634549Seric 		  case CMDVRFY:		/* vrfy -- verify address */
3649339Seric 			if (runinchild("SMTP-VRFY") > 0)
3659339Seric 				break;
36625050Seric 			setproctitle("%s: %s", CurHostName, inp);
3675003Seric 			vrfyqueue = NULL;
3687762Seric 			QuickAbort = TRUE;
3699619Seric 			sendtolist(p, (ADDRESS *) NULL, &vrfyqueue);
3707762Seric 			if (Errors != 0)
3719339Seric 			{
3729339Seric 				if (InChild)
3739339Seric 					finis();
3747762Seric 				break;
3759339Seric 			}
3765003Seric 			while (vrfyqueue != NULL)
3775003Seric 			{
3785003Seric 				register ADDRESS *a = vrfyqueue->q_next;
3795003Seric 				char *code;
3805003Seric 
3817685Seric 				while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags))
3825003Seric 					a = a->q_next;
3835003Seric 
3847685Seric 				if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))
3855003Seric 				{
3865003Seric 					if (a != NULL)
3875003Seric 						code = "250-";
3885003Seric 					else
3895003Seric 						code = "250";
3905003Seric 					if (vrfyqueue->q_fullname == NULL)
3915003Seric 						message(code, "<%s>", vrfyqueue->q_paddr);
3925003Seric 					else
3935003Seric 						message(code, "%s <%s>",
3945003Seric 						    vrfyqueue->q_fullname, vrfyqueue->q_paddr);
3955003Seric 				}
3965003Seric 				else if (a == NULL)
3975003Seric 					message("554", "Self destructive alias loop");
3985003Seric 				vrfyqueue = a;
3995003Seric 			}
4009339Seric 			if (InChild)
4019339Seric 				finis();
4024549Seric 			break;
4034549Seric 
4044549Seric 		  case CMDHELP:		/* help -- give user info */
4054577Seric 			help(p);
4064549Seric 			break;
4074549Seric 
4084549Seric 		  case CMDNOOP:		/* noop -- do nothing */
4094549Seric 			message("200", "OK");
4104549Seric 			break;
4114549Seric 
4124549Seric 		  case CMDQUIT:		/* quit -- leave mail */
41325050Seric 			message("221", "%s closing connection", MyHostName);
4149339Seric 			if (InChild)
4159339Seric 				ExitStat = EX_QUIT;
4164549Seric 			finis();
4174549Seric 
4188544Seric 		  case CMDVERB:		/* set verbose mode */
4198544Seric 			Verbose = TRUE;
42025025Seric 			SendMode = SM_DELIVER;
4218544Seric 			message("200", "Verbose mode");
4228544Seric 			break;
4238544Seric 
4249314Seric 		  case CMDONEX:		/* doing one transaction only */
4259378Seric 			OneXact = TRUE;
4269314Seric 			message("200", "Only one transaction");
4279314Seric 			break;
4289314Seric 
42936230Skarels # ifdef SMTPDEBUG
4309339Seric 		  case CMDDBGQSHOW:	/* show queues */
4316907Seric 			printf("Send Queue=");
4326907Seric 			printaddr(CurEnv->e_sendqueue, TRUE);
4335003Seric 			break;
4347275Seric 
4357275Seric 		  case CMDDBGDEBUG:	/* set debug mode */
4367676Seric 			tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
4377676Seric 			tTflag(p);
4387676Seric 			message("200", "Debug set");
4397275Seric 			break;
4407275Seric 
44136230Skarels # else /* not SMTPDEBUG */
44224945Seric 
44336230Skarels 		  case CMDDBGQSHOW:	/* show queues */
44436230Skarels 		  case CMDDBGDEBUG:	/* set debug mode */
44536233Skarels # ifdef LOG
44636233Skarels 			if (RealHostName != NULL && LogLevel > 0)
44736230Skarels 				syslog(LOG_NOTICE,
44836230Skarels 				    "\"%s\" command from %s (%s)\n",
44936230Skarels 				    c->cmdname, RealHostName,
45036230Skarels 				    inet_ntoa(RealHostAddr.sin_addr));
45136233Skarels # endif
45236230Skarels 			/* FALL THROUGH */
45336230Skarels # endif /* SMTPDEBUG */
45436230Skarels 
4554549Seric 		  case CMDERROR:	/* unknown command */
4564549Seric 			message("500", "Command unrecognized");
4574549Seric 			break;
4584549Seric 
4594549Seric 		  default:
46036230Skarels 			errno = 0;
4614549Seric 			syserr("smtp: unknown code %d", c->cmdcode);
4624549Seric 			break;
4634549Seric 		}
4644549Seric 	}
4654549Seric }
4664549Seric /*
4674549Seric **  SKIPWORD -- skip a fixed word.
4684549Seric **
4694549Seric **	Parameters:
4704549Seric **		p -- place to start looking.
4714549Seric **		w -- word to skip.
4724549Seric **
4734549Seric **	Returns:
4744549Seric **		p following w.
4754549Seric **		NULL on error.
4764549Seric **
4774549Seric **	Side Effects:
4784549Seric **		clobbers the p data area.
4794549Seric */
4804549Seric 
4814549Seric static char *
4824549Seric skipword(p, w)
4834549Seric 	register char *p;
4844549Seric 	char *w;
4854549Seric {
4864549Seric 	register char *q;
4874549Seric 
4884549Seric 	/* find beginning of word */
4894549Seric 	while (isspace(*p))
4904549Seric 		p++;
4914549Seric 	q = p;
4924549Seric 
4934549Seric 	/* find end of word */
4944549Seric 	while (*p != '\0' && *p != ':' && !isspace(*p))
4954549Seric 		p++;
4964549Seric 	while (isspace(*p))
4974549Seric 		*p++ = '\0';
4984549Seric 	if (*p != ':')
4994549Seric 	{
5004549Seric 	  syntax:
5014549Seric 		message("501", "Syntax error");
5024549Seric 		Errors++;
5034549Seric 		return (NULL);
5044549Seric 	}
5054549Seric 	*p++ = '\0';
5064549Seric 	while (isspace(*p))
5074549Seric 		p++;
5084549Seric 
5094549Seric 	/* see if the input word matches desired word */
51033725Sbostic 	if (strcasecmp(q, w))
5114549Seric 		goto syntax;
5124549Seric 
5134549Seric 	return (p);
5144549Seric }
5154577Seric /*
5164577Seric **  HELP -- implement the HELP command.
5174577Seric **
5184577Seric **	Parameters:
5194577Seric **		topic -- the topic we want help for.
5204577Seric **
5214577Seric **	Returns:
5224577Seric **		none.
5234577Seric **
5244577Seric **	Side Effects:
5254577Seric **		outputs the help file to message output.
5264577Seric */
5274577Seric 
5284577Seric help(topic)
5294577Seric 	char *topic;
5304577Seric {
5314577Seric 	register FILE *hf;
5324577Seric 	int len;
5334577Seric 	char buf[MAXLINE];
5344577Seric 	bool noinfo;
5354577Seric 
5368269Seric 	if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL)
5374577Seric 	{
5384577Seric 		/* no help */
53911931Seric 		errno = 0;
5404577Seric 		message("502", "HELP not implemented");
5414577Seric 		return;
5424577Seric 	}
5434577Seric 
544*49669Seric 	if (topic == NULL || *topic == '\0')
545*49669Seric 		topic = "smtp";
546*49669Seric 	else
547*49669Seric 		makelower(topic);
548*49669Seric 
5494577Seric 	len = strlen(topic);
5504577Seric 	noinfo = TRUE;
5514577Seric 
5524577Seric 	while (fgets(buf, sizeof buf, hf) != NULL)
5534577Seric 	{
5544577Seric 		if (strncmp(buf, topic, len) == 0)
5554577Seric 		{
5564577Seric 			register char *p;
5574577Seric 
5584577Seric 			p = index(buf, '\t');
5594577Seric 			if (p == NULL)
5604577Seric 				p = buf;
5614577Seric 			else
5624577Seric 				p++;
5634577Seric 			fixcrlf(p, TRUE);
5644577Seric 			message("214-", p);
5654577Seric 			noinfo = FALSE;
5664577Seric 		}
5674577Seric 	}
5684577Seric 
5694577Seric 	if (noinfo)
5704577Seric 		message("504", "HELP topic unknown");
5714577Seric 	else
5724577Seric 		message("214", "End of HELP info");
5734628Seric 	(void) fclose(hf);
5744577Seric }
5758544Seric /*
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;
62125050Seric 			QuickAbort = FALSE;
62225614Seric 			clearenvelope(CurEnv, FALSE);
62316158Seric 		}
6249339Seric 	}
62515256Seric 
62616158Seric 	/* open alias database */
62716158Seric 	initaliases(AliasFile, FALSE);
62816158Seric 
62916158Seric 	return (0);
6309339Seric }
6319339Seric 
6325181Seric # endif SMTP
633