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*51951Seric static char sccsid[] = "@(#)srvrsmtp.c	5.32 (Berkeley) 12/15/91 (with SMTP)";
1433731Sbostic #else
15*51951Seric static char sccsid[] = "@(#)srvrsmtp.c	5.32 (Berkeley) 12/15/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;
136*51951Seric 		LogUsrErrs = FALSE;
13712612Seric 
1387356Seric 		/* setup for the read */
1396907Seric 		CurEnv->e_to = NULL;
1404577Seric 		Errors = 0;
1417275Seric 		(void) fflush(stdout);
1427356Seric 
1437356Seric 		/* read the input line */
1447685Seric 		p = sfgets(inp, sizeof inp, InChannel);
1457356Seric 
1467685Seric 		/* handle errors */
1477356Seric 		if (p == NULL)
1487356Seric 		{
1494549Seric 			/* end of file, just die */
15036230Skarels 			message("421", "%s Lost input channel from %s",
15125050Seric 				MyHostName, CurHostName);
1524549Seric 			finis();
1534549Seric 		}
1544549Seric 
1554549Seric 		/* clean up end of line */
1564558Seric 		fixcrlf(inp, TRUE);
1574549Seric 
1584713Seric 		/* echo command to transcript */
1599545Seric 		if (CurEnv->e_xfp != NULL)
1609545Seric 			fprintf(CurEnv->e_xfp, "<<< %s\n", inp);
1614713Seric 
1624549Seric 		/* break off command */
1634549Seric 		for (p = inp; isspace(*p); p++)
1644549Seric 			continue;
1654549Seric 		cmd = p;
16624981Seric 		for (cmd = cmdbuf; *p != '\0' && !isspace(*p); )
16724981Seric 			*cmd++ = *p++;
16824981Seric 		*cmd = '\0';
1694549Seric 
17025691Seric 		/* throw away leading whitespace */
17125691Seric 		while (isspace(*p))
17225691Seric 			p++;
17325691Seric 
1744549Seric 		/* decode command */
1754549Seric 		for (c = CmdTab; c->cmdname != NULL; c++)
1764549Seric 		{
17733725Sbostic 			if (!strcasecmp(c->cmdname, cmdbuf))
1784549Seric 				break;
1794549Seric 		}
1804549Seric 
1814549Seric 		/* process command */
1824549Seric 		switch (c->cmdcode)
1834549Seric 		{
1844976Seric 		  case CMDHELO:		/* hello -- introduce yourself */
18524943Seric 			SmtpPhase = "HELO";
18625050Seric 			setproctitle("%s: %s", CurHostName, inp);
18733725Sbostic 			if (!strcasecmp(p, MyHostName))
18814877Seric 			{
18936230Skarels 				/*
19036230Skarels 				 * didn't know about alias,
19136230Skarels 				 * or connected to an echo server
19236230Skarels 				 */
19347570Seric 				message("553", "%s config error: mail loops back to myself",
19447570Seric 					MyHostName);
19514877Seric 				break;
19614877Seric 			}
19733725Sbostic 			if (RealHostName != NULL && strcasecmp(p, RealHostName))
19811146Seric 			{
19924981Seric 				char hostbuf[MAXNAME];
20011146Seric 
20124981Seric 				(void) sprintf(hostbuf, "%s (%s)", p, RealHostName);
20230448Seric 				sendinghost = newstr(hostbuf);
20311146Seric 			}
20411146Seric 			else
20530448Seric 				sendinghost = newstr(p);
2064997Seric 			message("250", "%s Hello %s, pleased to meet you",
20736230Skarels 				MyHostName, sendinghost);
2084976Seric 			break;
2094976Seric 
2104549Seric 		  case CMDMAIL:		/* mail -- designate sender */
21124943Seric 			SmtpPhase = "MAIL";
21224943Seric 
21311151Seric 			/* force a sending host even if no HELO given */
21411151Seric 			if (RealHostName != NULL && macvalue('s', CurEnv) == NULL)
21530448Seric 				sendinghost = RealHostName;
21611151Seric 
2179314Seric 			/* check for validity of this command */
2184558Seric 			if (hasmail)
2194558Seric 			{
2204558Seric 				message("503", "Sender already specified");
2214558Seric 				break;
2224558Seric 			}
2239339Seric 			if (InChild)
2249339Seric 			{
22536230Skarels 				errno = 0;
2269339Seric 				syserr("Nested MAIL command");
2279339Seric 				exit(0);
2289339Seric 			}
2299339Seric 
2309339Seric 			/* fork a subprocess to process this command */
2319339Seric 			if (runinchild("SMTP-MAIL") > 0)
2329339Seric 				break;
23330448Seric 			define('s', sendinghost, CurEnv);
23436579Sbostic 			define('r', "SMTP", CurEnv);
2359339Seric 			initsys();
23625016Seric 			setproctitle("%s %s: %s", CurEnv->e_id,
23725050Seric 				CurHostName, inp);
2389339Seric 
2399339Seric 			/* child -- go do the processing */
2404549Seric 			p = skipword(p, "from");
2414549Seric 			if (p == NULL)
2424549Seric 				break;
2434549Seric 			setsender(p);
2444577Seric 			if (Errors == 0)
2454549Seric 			{
2464549Seric 				message("250", "Sender ok");
2474549Seric 				hasmail = TRUE;
2484549Seric 			}
2499339Seric 			else if (InChild)
2509339Seric 				finis();
2514549Seric 			break;
2524549Seric 
2534976Seric 		  case CMDRCPT:		/* rcpt -- designate recipient */
25424943Seric 			SmtpPhase = "RCPT";
25525016Seric 			setproctitle("%s %s: %s", CurEnv->e_id,
25625050Seric 				CurHostName, inp);
25712612Seric 			if (setjmp(TopFrame) > 0)
25814785Seric 			{
25914785Seric 				CurEnv->e_flags &= ~EF_FATALERRS;
26012612Seric 				break;
26114785Seric 			}
26212612Seric 			QuickAbort = TRUE;
263*51951Seric 			LogUsrErrs = TRUE;
2644549Seric 			p = skipword(p, "to");
2654549Seric 			if (p == NULL)
2664549Seric 				break;
26716140Seric 			a = parseaddr(p, (ADDRESS *) NULL, 1, '\0');
26812612Seric 			if (a == NULL)
26912612Seric 				break;
27016886Seric 			a->q_flags |= QPRIMARY;
27112612Seric 			a = recipient(a, &CurEnv->e_sendqueue);
27212612Seric 			if (Errors != 0)
27312612Seric 				break;
27412612Seric 
27512612Seric 			/* no errors during parsing, but might be a duplicate */
27612612Seric 			CurEnv->e_to = p;
27712612Seric 			if (!bitset(QBADADDR, a->q_flags))
27812612Seric 				message("250", "Recipient ok");
27912612Seric 			else
2804549Seric 			{
28112612Seric 				/* punt -- should keep message in ADDRESS.... */
28212612Seric 				message("550", "Addressee unknown");
2834549Seric 			}
28412612Seric 			CurEnv->e_to = NULL;
2854549Seric 			break;
2864549Seric 
2874549Seric 		  case CMDDATA:		/* data -- text of mail */
28824943Seric 			SmtpPhase = "DATA";
2894976Seric 			if (!hasmail)
2904549Seric 			{
2914976Seric 				message("503", "Need MAIL command");
2924976Seric 				break;
2934549Seric 			}
29424943Seric 			else if (CurEnv->e_nrcpts <= 0)
2954549Seric 			{
2964976Seric 				message("503", "Need RCPT (recipient)");
2974976Seric 				break;
2984549Seric 			}
2994976Seric 
3004976Seric 			/* collect the text of the message */
30124943Seric 			SmtpPhase = "collect";
30225016Seric 			setproctitle("%s %s: %s", CurEnv->e_id,
30325050Seric 				CurHostName, inp);
3044976Seric 			collect(TRUE);
3054976Seric 			if (Errors != 0)
3064976Seric 				break;
3074976Seric 
3088238Seric 			/*
3098238Seric 			**  Arrange to send to everyone.
3108238Seric 			**	If sending to multiple people, mail back
3118238Seric 			**		errors rather than reporting directly.
3128238Seric 			**	In any case, don't mail back errors for
3138238Seric 			**		anything that has happened up to
3148238Seric 			**		now (the other end will do this).
31510197Seric 			**	Truncate our transcript -- the mail has gotten
31610197Seric 			**		to us successfully, and if we have
31710197Seric 			**		to mail this back, it will be easier
31810197Seric 			**		on the reader.
3198238Seric 			**	Then send to everyone.
3208238Seric 			**	Finally give a reply code.  If an error has
3218238Seric 			**		already been given, don't mail a
3228238Seric 			**		message back.
3239339Seric 			**	We goose error returns by clearing error bit.
3248238Seric 			*/
3258238Seric 
32624943Seric 			SmtpPhase = "delivery";
32724943Seric 			if (CurEnv->e_nrcpts != 1)
3289378Seric 			{
3299378Seric 				HoldErrs = TRUE;
33016886Seric 				ErrorMode = EM_MAIL;
3319378Seric 			}
3329339Seric 			CurEnv->e_flags &= ~EF_FATALERRS;
33310197Seric 			CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp);
3344976Seric 
3354976Seric 			/* send to all recipients */
33614877Seric 			sendall(CurEnv, SM_DEFAULT);
3376907Seric 			CurEnv->e_to = NULL;
3384976Seric 
33923516Seric 			/* save statistics */
34023516Seric 			markstats(CurEnv, (ADDRESS *) NULL);
34123516Seric 
3428238Seric 			/* issue success if appropriate and reset */
3438238Seric 			if (Errors == 0 || HoldErrs)
3449283Seric 				message("250", "Ok");
3458238Seric 			else
3469339Seric 				CurEnv->e_flags &= ~EF_FATALERRS;
3479339Seric 
3489339Seric 			/* if in a child, pop back to our parent */
3499339Seric 			if (InChild)
3509339Seric 				finis();
35124943Seric 
35224943Seric 			/* clean up a bit */
35324943Seric 			hasmail = 0;
35424943Seric 			dropenvelope(CurEnv);
35524943Seric 			CurEnv = newenvelope(CurEnv);
35624943Seric 			CurEnv->e_flags = BlankEnvelope.e_flags;
3574549Seric 			break;
3584549Seric 
3594549Seric 		  case CMDRSET:		/* rset -- reset state */
3604549Seric 			message("250", "Reset state");
3619339Seric 			if (InChild)
3629339Seric 				finis();
3639339Seric 			break;
3644549Seric 
3654549Seric 		  case CMDVRFY:		/* vrfy -- verify address */
3669339Seric 			if (runinchild("SMTP-VRFY") > 0)
3679339Seric 				break;
36825050Seric 			setproctitle("%s: %s", CurHostName, inp);
3695003Seric 			vrfyqueue = NULL;
3707762Seric 			QuickAbort = TRUE;
3719619Seric 			sendtolist(p, (ADDRESS *) NULL, &vrfyqueue);
3727762Seric 			if (Errors != 0)
3739339Seric 			{
3749339Seric 				if (InChild)
3759339Seric 					finis();
3767762Seric 				break;
3779339Seric 			}
3785003Seric 			while (vrfyqueue != NULL)
3795003Seric 			{
3805003Seric 				register ADDRESS *a = vrfyqueue->q_next;
3815003Seric 				char *code;
3825003Seric 
3837685Seric 				while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags))
3845003Seric 					a = a->q_next;
3855003Seric 
3867685Seric 				if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))
3875003Seric 				{
3885003Seric 					if (a != NULL)
3895003Seric 						code = "250-";
3905003Seric 					else
3915003Seric 						code = "250";
3925003Seric 					if (vrfyqueue->q_fullname == NULL)
3935003Seric 						message(code, "<%s>", vrfyqueue->q_paddr);
3945003Seric 					else
3955003Seric 						message(code, "%s <%s>",
3965003Seric 						    vrfyqueue->q_fullname, vrfyqueue->q_paddr);
3975003Seric 				}
3985003Seric 				else if (a == NULL)
3995003Seric 					message("554", "Self destructive alias loop");
4005003Seric 				vrfyqueue = a;
4015003Seric 			}
4029339Seric 			if (InChild)
4039339Seric 				finis();
4044549Seric 			break;
4054549Seric 
4064549Seric 		  case CMDHELP:		/* help -- give user info */
4074577Seric 			help(p);
4084549Seric 			break;
4094549Seric 
4104549Seric 		  case CMDNOOP:		/* noop -- do nothing */
4114549Seric 			message("200", "OK");
4124549Seric 			break;
4134549Seric 
4144549Seric 		  case CMDQUIT:		/* quit -- leave mail */
41525050Seric 			message("221", "%s closing connection", MyHostName);
4169339Seric 			if (InChild)
4179339Seric 				ExitStat = EX_QUIT;
4184549Seric 			finis();
4194549Seric 
4208544Seric 		  case CMDVERB:		/* set verbose mode */
4218544Seric 			Verbose = TRUE;
42225025Seric 			SendMode = SM_DELIVER;
4238544Seric 			message("200", "Verbose mode");
4248544Seric 			break;
4258544Seric 
4269314Seric 		  case CMDONEX:		/* doing one transaction only */
4279378Seric 			OneXact = TRUE;
4289314Seric 			message("200", "Only one transaction");
4299314Seric 			break;
4309314Seric 
43136230Skarels # ifdef SMTPDEBUG
4329339Seric 		  case CMDDBGQSHOW:	/* show queues */
4336907Seric 			printf("Send Queue=");
4346907Seric 			printaddr(CurEnv->e_sendqueue, TRUE);
4355003Seric 			break;
4367275Seric 
4377275Seric 		  case CMDDBGDEBUG:	/* set debug mode */
4387676Seric 			tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
4397676Seric 			tTflag(p);
4407676Seric 			message("200", "Debug set");
4417275Seric 			break;
4427275Seric 
44336230Skarels # else /* not SMTPDEBUG */
44424945Seric 
44536230Skarels 		  case CMDDBGQSHOW:	/* show queues */
44636230Skarels 		  case CMDDBGDEBUG:	/* set debug mode */
44736233Skarels # ifdef LOG
44836233Skarels 			if (RealHostName != NULL && LogLevel > 0)
44936230Skarels 				syslog(LOG_NOTICE,
45036230Skarels 				    "\"%s\" command from %s (%s)\n",
45136230Skarels 				    c->cmdname, RealHostName,
45236230Skarels 				    inet_ntoa(RealHostAddr.sin_addr));
45336233Skarels # endif
45436230Skarels 			/* FALL THROUGH */
45536230Skarels # endif /* SMTPDEBUG */
45636230Skarels 
4574549Seric 		  case CMDERROR:	/* unknown command */
4584549Seric 			message("500", "Command unrecognized");
4594549Seric 			break;
4604549Seric 
4614549Seric 		  default:
46236230Skarels 			errno = 0;
4634549Seric 			syserr("smtp: unknown code %d", c->cmdcode);
4644549Seric 			break;
4654549Seric 		}
4664549Seric 	}
4674549Seric }
4684549Seric /*
4694549Seric **  SKIPWORD -- skip a fixed word.
4704549Seric **
4714549Seric **	Parameters:
4724549Seric **		p -- place to start looking.
4734549Seric **		w -- word to skip.
4744549Seric **
4754549Seric **	Returns:
4764549Seric **		p following w.
4774549Seric **		NULL on error.
4784549Seric **
4794549Seric **	Side Effects:
4804549Seric **		clobbers the p data area.
4814549Seric */
4824549Seric 
4834549Seric static char *
4844549Seric skipword(p, w)
4854549Seric 	register char *p;
4864549Seric 	char *w;
4874549Seric {
4884549Seric 	register char *q;
4894549Seric 
4904549Seric 	/* find beginning of word */
4914549Seric 	while (isspace(*p))
4924549Seric 		p++;
4934549Seric 	q = p;
4944549Seric 
4954549Seric 	/* find end of word */
4964549Seric 	while (*p != '\0' && *p != ':' && !isspace(*p))
4974549Seric 		p++;
4984549Seric 	while (isspace(*p))
4994549Seric 		*p++ = '\0';
5004549Seric 	if (*p != ':')
5014549Seric 	{
5024549Seric 	  syntax:
5034549Seric 		message("501", "Syntax error");
5044549Seric 		Errors++;
5054549Seric 		return (NULL);
5064549Seric 	}
5074549Seric 	*p++ = '\0';
5084549Seric 	while (isspace(*p))
5094549Seric 		p++;
5104549Seric 
5114549Seric 	/* see if the input word matches desired word */
51233725Sbostic 	if (strcasecmp(q, w))
5134549Seric 		goto syntax;
5144549Seric 
5154549Seric 	return (p);
5164549Seric }
5174577Seric /*
5184577Seric **  HELP -- implement the HELP command.
5194577Seric **
5204577Seric **	Parameters:
5214577Seric **		topic -- the topic we want help for.
5224577Seric **
5234577Seric **	Returns:
5244577Seric **		none.
5254577Seric **
5264577Seric **	Side Effects:
5274577Seric **		outputs the help file to message output.
5284577Seric */
5294577Seric 
5304577Seric help(topic)
5314577Seric 	char *topic;
5324577Seric {
5334577Seric 	register FILE *hf;
5344577Seric 	int len;
5354577Seric 	char buf[MAXLINE];
5364577Seric 	bool noinfo;
5374577Seric 
5388269Seric 	if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL)
5394577Seric 	{
5404577Seric 		/* no help */
54111931Seric 		errno = 0;
5424577Seric 		message("502", "HELP not implemented");
5434577Seric 		return;
5444577Seric 	}
5454577Seric 
54649669Seric 	if (topic == NULL || *topic == '\0')
54749669Seric 		topic = "smtp";
54849669Seric 	else
54949669Seric 		makelower(topic);
55049669Seric 
5514577Seric 	len = strlen(topic);
5524577Seric 	noinfo = TRUE;
5534577Seric 
5544577Seric 	while (fgets(buf, sizeof buf, hf) != NULL)
5554577Seric 	{
5564577Seric 		if (strncmp(buf, topic, len) == 0)
5574577Seric 		{
5584577Seric 			register char *p;
5594577Seric 
5604577Seric 			p = index(buf, '\t');
5614577Seric 			if (p == NULL)
5624577Seric 				p = buf;
5634577Seric 			else
5644577Seric 				p++;
5654577Seric 			fixcrlf(p, TRUE);
5664577Seric 			message("214-", p);
5674577Seric 			noinfo = FALSE;
5684577Seric 		}
5694577Seric 	}
5704577Seric 
5714577Seric 	if (noinfo)
5724577Seric 		message("504", "HELP topic unknown");
5734577Seric 	else
5744577Seric 		message("214", "End of HELP info");
5754628Seric 	(void) fclose(hf);
5764577Seric }
5778544Seric /*
5789339Seric **  RUNINCHILD -- return twice -- once in the child, then in the parent again
5799339Seric **
5809339Seric **	Parameters:
5819339Seric **		label -- a string used in error messages
5829339Seric **
5839339Seric **	Returns:
5849339Seric **		zero in the child
5859339Seric **		one in the parent
5869339Seric **
5879339Seric **	Side Effects:
5889339Seric **		none.
5899339Seric */
5908544Seric 
5919339Seric runinchild(label)
5929339Seric 	char *label;
5939339Seric {
5949339Seric 	int childpid;
5959339Seric 
59616158Seric 	if (!OneXact)
5979339Seric 	{
59816158Seric 		childpid = dofork();
59916158Seric 		if (childpid < 0)
60016158Seric 		{
60116158Seric 			syserr("%s: cannot fork", label);
60216158Seric 			return (1);
60316158Seric 		}
60416158Seric 		if (childpid > 0)
60516158Seric 		{
60616158Seric 			auto int st;
6079339Seric 
60816158Seric 			/* parent -- wait for child to complete */
60916158Seric 			st = waitfor(childpid);
61016158Seric 			if (st == -1)
61116158Seric 				syserr("%s: lost child", label);
6129339Seric 
61316158Seric 			/* if we exited on a QUIT command, complete the process */
61416158Seric 			if (st == (EX_QUIT << 8))
61516158Seric 				finis();
6169339Seric 
61716158Seric 			return (1);
61816158Seric 		}
61916158Seric 		else
62016158Seric 		{
62116158Seric 			/* child */
62216158Seric 			InChild = TRUE;
62325050Seric 			QuickAbort = FALSE;
62425614Seric 			clearenvelope(CurEnv, FALSE);
62516158Seric 		}
6269339Seric 	}
62715256Seric 
62816158Seric 	/* open alias database */
62916158Seric 	initaliases(AliasFile, FALSE);
63016158Seric 
63116158Seric 	return (0);
6329339Seric }
6339339Seric 
6345181Seric # endif SMTP
635