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*58069Seric static char sccsid[] = "@(#)srvrsmtp.c 6.10 (Berkeley) 02/19/93 (with SMTP)"; 1433731Sbostic #else 15*58069Seric static char sccsid[] = "@(#)srvrsmtp.c 6.10 (Berkeley) 02/19/93 (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 8955012Seric smtp(e) 9055012Seric register ENVELOPE *e; 914549Seric { 924549Seric register char *p; 938544Seric register struct cmd *c; 944549Seric char *cmd; 9546928Sbostic static char *skipword(); 964549Seric bool hasmail; /* mail command received */ 975003Seric auto ADDRESS *vrfyqueue; 9812612Seric ADDRESS *a; 9930448Seric char *sendinghost; 1008544Seric char inp[MAXLINE]; 10157232Seric char cmdbuf[MAXLINE]; 1027124Seric extern char Version[]; 10311151Seric extern char *macvalue(); 10412612Seric extern ADDRESS *recipient(); 10524943Seric extern ENVELOPE BlankEnvelope; 10624943Seric extern ENVELOPE *newenvelope(); 1074549Seric 1085003Seric hasmail = FALSE; 1097363Seric if (OutChannel != stdout) 1107363Seric { 1117363Seric /* arrange for debugging output to go to remote host */ 1127363Seric (void) close(1); 1137363Seric (void) dup(fileno(OutChannel)); 1147363Seric } 11555012Seric settime(e); 11657642Seric if (RealHostName == NULL) 11757642Seric RealHostName = MyHostName; 11857642Seric CurHostName = RealHostName; 11957642Seric setproctitle("srvrsmtp %s", CurHostName); 12058050Seric expand("\201e", inp, &inp[sizeof inp], e); 12155360Seric message("220", "%s", inp); 12224943Seric SmtpPhase = "startup"; 12330448Seric sendinghost = NULL; 1244549Seric for (;;) 1254549Seric { 12612612Seric /* arrange for backout */ 12712612Seric if (setjmp(TopFrame) > 0 && InChild) 12812612Seric finis(); 12912612Seric QuickAbort = FALSE; 13012612Seric HoldErrs = FALSE; 13151951Seric LogUsrErrs = FALSE; 13212612Seric 1337356Seric /* setup for the read */ 13455012Seric e->e_to = NULL; 1354577Seric Errors = 0; 1367275Seric (void) fflush(stdout); 1377356Seric 1387356Seric /* read the input line */ 13957389Seric p = sfgets(inp, sizeof inp, InChannel, ReadTimeout); 1407356Seric 1417685Seric /* handle errors */ 1427356Seric if (p == NULL) 1437356Seric { 1444549Seric /* end of file, just die */ 14536230Skarels message("421", "%s Lost input channel from %s", 14625050Seric MyHostName, CurHostName); 14755464Seric #ifdef LOG 14858020Seric if (LogLevel > 1) 14955464Seric syslog(LOG_NOTICE, "lost input channel from %s", 15055464Seric CurHostName); 15155464Seric #endif 152*58069Seric if (InChild) 153*58069Seric ExitStat = EX_QUIT; 1544549Seric finis(); 1554549Seric } 1564549Seric 1574549Seric /* clean up end of line */ 1584558Seric fixcrlf(inp, TRUE); 1594549Seric 1604713Seric /* echo command to transcript */ 16155012Seric if (e->e_xfp != NULL) 16255012Seric fprintf(e->e_xfp, "<<< %s\n", inp); 1634713Seric 1644549Seric /* break off command */ 16558050Seric for (p = inp; isascii(*p) && isspace(*p); p++) 1664549Seric continue; 16757232Seric cmd = cmdbuf; 16858050Seric while (*p != '\0' && 16958050Seric !(isascii(*p) && isspace(*p)) && 17058050Seric cmd < &cmdbuf[sizeof cmdbuf - 2]) 17124981Seric *cmd++ = *p++; 17224981Seric *cmd = '\0'; 1734549Seric 17425691Seric /* throw away leading whitespace */ 17558050Seric while (isascii(*p) && isspace(*p)) 17625691Seric p++; 17725691Seric 1784549Seric /* decode command */ 1794549Seric for (c = CmdTab; c->cmdname != NULL; c++) 1804549Seric { 18133725Sbostic if (!strcasecmp(c->cmdname, cmdbuf)) 1824549Seric break; 1834549Seric } 1844549Seric 18551954Seric /* reset errors */ 18651954Seric errno = 0; 18751954Seric 1884549Seric /* process command */ 1894549Seric switch (c->cmdcode) 1904549Seric { 1914976Seric case CMDHELO: /* hello -- introduce yourself */ 19224943Seric SmtpPhase = "HELO"; 19325050Seric setproctitle("%s: %s", CurHostName, inp); 19433725Sbostic if (!strcasecmp(p, MyHostName)) 19514877Seric { 19636230Skarels /* 19736230Skarels * didn't know about alias, 19836230Skarels * or connected to an echo server 19936230Skarels */ 20047570Seric message("553", "%s config error: mail loops back to myself", 20147570Seric MyHostName); 20214877Seric break; 20314877Seric } 20433725Sbostic if (RealHostName != NULL && strcasecmp(p, RealHostName)) 20511146Seric { 20624981Seric char hostbuf[MAXNAME]; 20711146Seric 20824981Seric (void) sprintf(hostbuf, "%s (%s)", p, RealHostName); 20930448Seric sendinghost = newstr(hostbuf); 21011146Seric } 21111146Seric else 21230448Seric sendinghost = newstr(p); 2134997Seric message("250", "%s Hello %s, pleased to meet you", 21436230Skarels MyHostName, sendinghost); 2154976Seric break; 2164976Seric 2174549Seric case CMDMAIL: /* mail -- designate sender */ 21824943Seric SmtpPhase = "MAIL"; 21924943Seric 22011151Seric /* force a sending host even if no HELO given */ 22158064Seric if (sendinghost == NULL && macvalue('s', e) == NULL) 22230448Seric sendinghost = RealHostName; 22311151Seric 2249314Seric /* check for validity of this command */ 2254558Seric if (hasmail) 2264558Seric { 2274558Seric message("503", "Sender already specified"); 2284558Seric break; 2294558Seric } 2309339Seric if (InChild) 2319339Seric { 23236230Skarels errno = 0; 23358008Seric syserr("Nested MAIL command: MAIL %s", p); 234*58069Seric finis(); 2359339Seric } 2369339Seric 2379339Seric /* fork a subprocess to process this command */ 23855012Seric if (runinchild("SMTP-MAIL", e) > 0) 2399339Seric break; 24058064Seric if (sendinghost != NULL) 24158064Seric define('s', sendinghost, e); 24255012Seric define('r', "SMTP", e); 24355012Seric initsys(e); 24457389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 2459339Seric 2469339Seric /* child -- go do the processing */ 2474549Seric p = skipword(p, "from"); 2484549Seric if (p == NULL) 2494549Seric break; 25057977Seric if (setjmp(TopFrame) > 0) 25157977Seric break; 25257977Seric QuickAbort = TRUE; 25355012Seric setsender(p, e); 2544577Seric if (Errors == 0) 2554549Seric { 2564549Seric message("250", "Sender ok"); 2574549Seric hasmail = TRUE; 2584549Seric } 2599339Seric else if (InChild) 2609339Seric finis(); 2614549Seric break; 2624549Seric 2634976Seric case CMDRCPT: /* rcpt -- designate recipient */ 26424943Seric SmtpPhase = "RCPT"; 26557389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 26612612Seric if (setjmp(TopFrame) > 0) 26714785Seric { 26855012Seric e->e_flags &= ~EF_FATALERRS; 26912612Seric break; 27014785Seric } 27112612Seric QuickAbort = TRUE; 27251951Seric LogUsrErrs = TRUE; 2734549Seric p = skipword(p, "to"); 2744549Seric if (p == NULL) 2754549Seric break; 27655012Seric a = parseaddr(p, (ADDRESS *) NULL, 1, '\0', e); 27712612Seric if (a == NULL) 27812612Seric break; 27916886Seric a->q_flags |= QPRIMARY; 28055012Seric a = recipient(a, &e->e_sendqueue, e); 28112612Seric if (Errors != 0) 28212612Seric break; 28312612Seric 28412612Seric /* no errors during parsing, but might be a duplicate */ 28555012Seric e->e_to = p; 28612612Seric if (!bitset(QBADADDR, a->q_flags)) 28712612Seric message("250", "Recipient ok"); 28812612Seric else 2894549Seric { 29012612Seric /* punt -- should keep message in ADDRESS.... */ 29112612Seric message("550", "Addressee unknown"); 2924549Seric } 29355012Seric e->e_to = NULL; 2944549Seric break; 2954549Seric 2964549Seric case CMDDATA: /* data -- text of mail */ 29724943Seric SmtpPhase = "DATA"; 2984976Seric if (!hasmail) 2994549Seric { 3004976Seric message("503", "Need MAIL command"); 3014976Seric break; 3024549Seric } 30355012Seric else if (e->e_nrcpts <= 0) 3044549Seric { 3054976Seric message("503", "Need RCPT (recipient)"); 3064976Seric break; 3074549Seric } 3084976Seric 3094976Seric /* collect the text of the message */ 31024943Seric SmtpPhase = "collect"; 31157389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 31255012Seric collect(TRUE, e); 3134976Seric if (Errors != 0) 3144976Seric break; 3154976Seric 3168238Seric /* 3178238Seric ** Arrange to send to everyone. 3188238Seric ** If sending to multiple people, mail back 3198238Seric ** errors rather than reporting directly. 3208238Seric ** In any case, don't mail back errors for 3218238Seric ** anything that has happened up to 3228238Seric ** now (the other end will do this). 32310197Seric ** Truncate our transcript -- the mail has gotten 32410197Seric ** to us successfully, and if we have 32510197Seric ** to mail this back, it will be easier 32610197Seric ** on the reader. 3278238Seric ** Then send to everyone. 3288238Seric ** Finally give a reply code. If an error has 3298238Seric ** already been given, don't mail a 3308238Seric ** message back. 3319339Seric ** We goose error returns by clearing error bit. 3328238Seric */ 3338238Seric 33424943Seric SmtpPhase = "delivery"; 33555012Seric if (e->e_nrcpts != 1) 3369378Seric { 3379378Seric HoldErrs = TRUE; 33816886Seric ErrorMode = EM_MAIL; 3399378Seric } 34055012Seric e->e_flags &= ~EF_FATALERRS; 34155012Seric e->e_xfp = freopen(queuename(e, 'x'), "w", e->e_xfp); 3424976Seric 3434976Seric /* send to all recipients */ 34455012Seric sendall(e, SM_DEFAULT); 34555012Seric e->e_to = NULL; 3464976Seric 34723516Seric /* save statistics */ 34855012Seric markstats(e, (ADDRESS *) NULL); 34923516Seric 3508238Seric /* issue success if appropriate and reset */ 3518238Seric if (Errors == 0 || HoldErrs) 3529283Seric message("250", "Ok"); 3538238Seric else 35455012Seric e->e_flags &= ~EF_FATALERRS; 3559339Seric 3569339Seric /* if in a child, pop back to our parent */ 3579339Seric if (InChild) 3589339Seric finis(); 35924943Seric 36024943Seric /* clean up a bit */ 36158008Seric hasmail = FALSE; 36255012Seric dropenvelope(e); 36355012Seric CurEnv = e = newenvelope(e); 36455012Seric e->e_flags = BlankEnvelope.e_flags; 3654549Seric break; 3664549Seric 3674549Seric case CMDRSET: /* rset -- reset state */ 3684549Seric message("250", "Reset state"); 3699339Seric if (InChild) 3709339Seric finis(); 3719339Seric break; 3724549Seric 3734549Seric case CMDVRFY: /* vrfy -- verify address */ 37455012Seric if (runinchild("SMTP-VRFY", e) > 0) 3759339Seric break; 37625050Seric setproctitle("%s: %s", CurHostName, inp); 37755173Seric #ifdef LOG 37858020Seric if (LogLevel > 5) 37955173Seric syslog(LOG_INFO, "%s: %s", CurHostName, inp); 38055173Seric #endif 3815003Seric vrfyqueue = NULL; 3827762Seric QuickAbort = TRUE; 38355012Seric sendtolist(p, (ADDRESS *) NULL, &vrfyqueue, e); 3847762Seric if (Errors != 0) 3859339Seric { 3869339Seric if (InChild) 3879339Seric finis(); 3887762Seric break; 3899339Seric } 3905003Seric while (vrfyqueue != NULL) 3915003Seric { 3925003Seric register ADDRESS *a = vrfyqueue->q_next; 3935003Seric char *code; 3945003Seric 3957685Seric while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags)) 3965003Seric a = a->q_next; 3975003Seric 3987685Seric if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags)) 3995003Seric { 4005003Seric if (a != NULL) 4015003Seric code = "250-"; 4025003Seric else 4035003Seric code = "250"; 40458010Seric if (strchr(vrfyqueue->q_paddr, '<') != NULL) 40558010Seric message(code, "%s", vrfyqueue->q_paddr); 40658010Seric else if (vrfyqueue->q_fullname == NULL) 4075003Seric message(code, "<%s>", vrfyqueue->q_paddr); 4085003Seric else 4095003Seric message(code, "%s <%s>", 4105003Seric vrfyqueue->q_fullname, vrfyqueue->q_paddr); 4115003Seric } 4125003Seric else if (a == NULL) 4135003Seric message("554", "Self destructive alias loop"); 4145003Seric vrfyqueue = a; 4155003Seric } 4169339Seric if (InChild) 4179339Seric finis(); 4184549Seric break; 4194549Seric 4204549Seric case CMDHELP: /* help -- give user info */ 4214577Seric help(p); 4224549Seric break; 4234549Seric 4244549Seric case CMDNOOP: /* noop -- do nothing */ 4254549Seric message("200", "OK"); 4264549Seric break; 4274549Seric 4284549Seric case CMDQUIT: /* quit -- leave mail */ 42925050Seric message("221", "%s closing connection", MyHostName); 4309339Seric if (InChild) 4319339Seric ExitStat = EX_QUIT; 4324549Seric finis(); 4334549Seric 4348544Seric case CMDVERB: /* set verbose mode */ 4358544Seric Verbose = TRUE; 43625025Seric SendMode = SM_DELIVER; 4378544Seric message("200", "Verbose mode"); 4388544Seric break; 4398544Seric 4409314Seric case CMDONEX: /* doing one transaction only */ 4419378Seric OneXact = TRUE; 4429314Seric message("200", "Only one transaction"); 4439314Seric break; 4449314Seric 44536230Skarels # ifdef SMTPDEBUG 4469339Seric case CMDDBGQSHOW: /* show queues */ 4476907Seric printf("Send Queue="); 44855012Seric printaddr(e->e_sendqueue, TRUE); 4495003Seric break; 4507275Seric 4517275Seric case CMDDBGDEBUG: /* set debug mode */ 4527676Seric tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); 4537676Seric tTflag(p); 4547676Seric message("200", "Debug set"); 4557275Seric break; 4567275Seric 45736230Skarels # else /* not SMTPDEBUG */ 45824945Seric 45936230Skarels case CMDDBGQSHOW: /* show queues */ 46036230Skarels case CMDDBGDEBUG: /* set debug mode */ 46136233Skarels # ifdef LOG 46236233Skarels if (RealHostName != NULL && LogLevel > 0) 46336230Skarels syslog(LOG_NOTICE, 46458020Seric "\"%s\" command from %s (%s)", 46536230Skarels c->cmdname, RealHostName, 46636230Skarels inet_ntoa(RealHostAddr.sin_addr)); 46736233Skarels # endif 46836230Skarels /* FALL THROUGH */ 46936230Skarels # endif /* SMTPDEBUG */ 47036230Skarels 4714549Seric case CMDERROR: /* unknown command */ 4724549Seric message("500", "Command unrecognized"); 4734549Seric break; 4744549Seric 4754549Seric default: 47636230Skarels errno = 0; 4774549Seric syserr("smtp: unknown code %d", c->cmdcode); 4784549Seric break; 4794549Seric } 4804549Seric } 4814549Seric } 4824549Seric /* 4834549Seric ** SKIPWORD -- skip a fixed word. 4844549Seric ** 4854549Seric ** Parameters: 4864549Seric ** p -- place to start looking. 4874549Seric ** w -- word to skip. 4884549Seric ** 4894549Seric ** Returns: 4904549Seric ** p following w. 4914549Seric ** NULL on error. 4924549Seric ** 4934549Seric ** Side Effects: 4944549Seric ** clobbers the p data area. 4954549Seric */ 4964549Seric 4974549Seric static char * 4984549Seric skipword(p, w) 4994549Seric register char *p; 5004549Seric char *w; 5014549Seric { 5024549Seric register char *q; 5034549Seric 5044549Seric /* find beginning of word */ 50558050Seric while (isascii(*p) && isspace(*p)) 5064549Seric p++; 5074549Seric q = p; 5084549Seric 5094549Seric /* find end of word */ 51058050Seric while (*p != '\0' && *p != ':' && !(isascii(*p) && isspace(*p))) 5114549Seric p++; 51258050Seric while (isascii(*p) && isspace(*p)) 5134549Seric *p++ = '\0'; 5144549Seric if (*p != ':') 5154549Seric { 5164549Seric syntax: 5174549Seric message("501", "Syntax error"); 5184549Seric Errors++; 5194549Seric return (NULL); 5204549Seric } 5214549Seric *p++ = '\0'; 52258050Seric while (isascii(*p) && isspace(*p)) 5234549Seric p++; 5244549Seric 5254549Seric /* see if the input word matches desired word */ 52633725Sbostic if (strcasecmp(q, w)) 5274549Seric goto syntax; 5284549Seric 5294549Seric return (p); 5304549Seric } 5314577Seric /* 5324577Seric ** HELP -- implement the HELP command. 5334577Seric ** 5344577Seric ** Parameters: 5354577Seric ** topic -- the topic we want help for. 5364577Seric ** 5374577Seric ** Returns: 5384577Seric ** none. 5394577Seric ** 5404577Seric ** Side Effects: 5414577Seric ** outputs the help file to message output. 5424577Seric */ 5434577Seric 5444577Seric help(topic) 5454577Seric char *topic; 5464577Seric { 5474577Seric register FILE *hf; 5484577Seric int len; 5494577Seric char buf[MAXLINE]; 5504577Seric bool noinfo; 5514577Seric 5528269Seric if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL) 5534577Seric { 5544577Seric /* no help */ 55511931Seric errno = 0; 5564577Seric message("502", "HELP not implemented"); 5574577Seric return; 5584577Seric } 5594577Seric 56049669Seric if (topic == NULL || *topic == '\0') 56149669Seric topic = "smtp"; 56249669Seric else 56349669Seric makelower(topic); 56449669Seric 5654577Seric len = strlen(topic); 5664577Seric noinfo = TRUE; 5674577Seric 5684577Seric while (fgets(buf, sizeof buf, hf) != NULL) 5694577Seric { 5704577Seric if (strncmp(buf, topic, len) == 0) 5714577Seric { 5724577Seric register char *p; 5734577Seric 57456795Seric p = strchr(buf, '\t'); 5754577Seric if (p == NULL) 5764577Seric p = buf; 5774577Seric else 5784577Seric p++; 5794577Seric fixcrlf(p, TRUE); 5804577Seric message("214-", p); 5814577Seric noinfo = FALSE; 5824577Seric } 5834577Seric } 5844577Seric 5854577Seric if (noinfo) 5864577Seric message("504", "HELP topic unknown"); 5874577Seric else 5884577Seric message("214", "End of HELP info"); 5894628Seric (void) fclose(hf); 5904577Seric } 5918544Seric /* 5929339Seric ** RUNINCHILD -- return twice -- once in the child, then in the parent again 5939339Seric ** 5949339Seric ** Parameters: 5959339Seric ** label -- a string used in error messages 5969339Seric ** 5979339Seric ** Returns: 5989339Seric ** zero in the child 5999339Seric ** one in the parent 6009339Seric ** 6019339Seric ** Side Effects: 6029339Seric ** none. 6039339Seric */ 6048544Seric 60555012Seric runinchild(label, e) 6069339Seric char *label; 60755012Seric register ENVELOPE *e; 6089339Seric { 6099339Seric int childpid; 6109339Seric 61116158Seric if (!OneXact) 6129339Seric { 61316158Seric childpid = dofork(); 61416158Seric if (childpid < 0) 61516158Seric { 61616158Seric syserr("%s: cannot fork", label); 61716158Seric return (1); 61816158Seric } 61916158Seric if (childpid > 0) 62016158Seric { 62116158Seric auto int st; 6229339Seric 62316158Seric /* parent -- wait for child to complete */ 62416158Seric st = waitfor(childpid); 62516158Seric if (st == -1) 62616158Seric syserr("%s: lost child", label); 6279339Seric 62816158Seric /* if we exited on a QUIT command, complete the process */ 62916158Seric if (st == (EX_QUIT << 8)) 63016158Seric finis(); 6319339Seric 63216158Seric return (1); 63316158Seric } 63416158Seric else 63516158Seric { 63616158Seric /* child */ 63716158Seric InChild = TRUE; 63825050Seric QuickAbort = FALSE; 63955012Seric clearenvelope(e, FALSE); 64016158Seric } 6419339Seric } 64215256Seric 64316158Seric /* open alias database */ 64455012Seric initaliases(AliasFile, FALSE, e); 64516158Seric 64616158Seric return (0); 6479339Seric } 6489339Seric 64956795Seric # endif /* SMTP */ 650