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*58050Seric static char sccsid[] = "@(#)srvrsmtp.c 6.8 (Berkeley) 02/18/93 (with SMTP)"; 1433731Sbostic #else 15*58050Seric static char sccsid[] = "@(#)srvrsmtp.c 6.8 (Berkeley) 02/18/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); 120*58050Seric 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 1524549Seric finis(); 1534549Seric } 1544549Seric 1554549Seric /* clean up end of line */ 1564558Seric fixcrlf(inp, TRUE); 1574549Seric 1584713Seric /* echo command to transcript */ 15955012Seric if (e->e_xfp != NULL) 16055012Seric fprintf(e->e_xfp, "<<< %s\n", inp); 1614713Seric 1624549Seric /* break off command */ 163*58050Seric for (p = inp; isascii(*p) && isspace(*p); p++) 1644549Seric continue; 16557232Seric cmd = cmdbuf; 166*58050Seric while (*p != '\0' && 167*58050Seric !(isascii(*p) && isspace(*p)) && 168*58050Seric cmd < &cmdbuf[sizeof cmdbuf - 2]) 16924981Seric *cmd++ = *p++; 17024981Seric *cmd = '\0'; 1714549Seric 17225691Seric /* throw away leading whitespace */ 173*58050Seric while (isascii(*p) && isspace(*p)) 17425691Seric p++; 17525691Seric 1764549Seric /* decode command */ 1774549Seric for (c = CmdTab; c->cmdname != NULL; c++) 1784549Seric { 17933725Sbostic if (!strcasecmp(c->cmdname, cmdbuf)) 1804549Seric break; 1814549Seric } 1824549Seric 18351954Seric /* reset errors */ 18451954Seric errno = 0; 18551954Seric 1864549Seric /* process command */ 1874549Seric switch (c->cmdcode) 1884549Seric { 1894976Seric case CMDHELO: /* hello -- introduce yourself */ 19024943Seric SmtpPhase = "HELO"; 19125050Seric setproctitle("%s: %s", CurHostName, inp); 19233725Sbostic if (!strcasecmp(p, MyHostName)) 19314877Seric { 19436230Skarels /* 19536230Skarels * didn't know about alias, 19636230Skarels * or connected to an echo server 19736230Skarels */ 19847570Seric message("553", "%s config error: mail loops back to myself", 19947570Seric MyHostName); 20014877Seric break; 20114877Seric } 20233725Sbostic if (RealHostName != NULL && strcasecmp(p, RealHostName)) 20311146Seric { 20424981Seric char hostbuf[MAXNAME]; 20511146Seric 20624981Seric (void) sprintf(hostbuf, "%s (%s)", p, RealHostName); 20730448Seric sendinghost = newstr(hostbuf); 20811146Seric } 20911146Seric else 21030448Seric sendinghost = newstr(p); 2114997Seric message("250", "%s Hello %s, pleased to meet you", 21236230Skarels MyHostName, sendinghost); 2134976Seric break; 2144976Seric 2154549Seric case CMDMAIL: /* mail -- designate sender */ 21624943Seric SmtpPhase = "MAIL"; 21724943Seric 21811151Seric /* force a sending host even if no HELO given */ 21955012Seric if (RealHostName != NULL && macvalue('s', e) == NULL) 22030448Seric sendinghost = RealHostName; 22111151Seric 2229314Seric /* check for validity of this command */ 2234558Seric if (hasmail) 2244558Seric { 2254558Seric message("503", "Sender already specified"); 2264558Seric break; 2274558Seric } 2289339Seric if (InChild) 2299339Seric { 23036230Skarels errno = 0; 23158008Seric syserr("Nested MAIL command: MAIL %s", p); 2329339Seric exit(0); 2339339Seric } 2349339Seric 2359339Seric /* fork a subprocess to process this command */ 23655012Seric if (runinchild("SMTP-MAIL", e) > 0) 2379339Seric break; 23855012Seric define('s', sendinghost, e); 23955012Seric define('r', "SMTP", e); 24055012Seric initsys(e); 24157389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 2429339Seric 2439339Seric /* child -- go do the processing */ 2444549Seric p = skipword(p, "from"); 2454549Seric if (p == NULL) 2464549Seric break; 24757977Seric if (setjmp(TopFrame) > 0) 24857977Seric break; 24957977Seric QuickAbort = TRUE; 25055012Seric setsender(p, e); 2514577Seric if (Errors == 0) 2524549Seric { 2534549Seric message("250", "Sender ok"); 2544549Seric hasmail = TRUE; 2554549Seric } 2569339Seric else if (InChild) 2579339Seric finis(); 2584549Seric break; 2594549Seric 2604976Seric case CMDRCPT: /* rcpt -- designate recipient */ 26124943Seric SmtpPhase = "RCPT"; 26257389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 26312612Seric if (setjmp(TopFrame) > 0) 26414785Seric { 26555012Seric e->e_flags &= ~EF_FATALERRS; 26612612Seric break; 26714785Seric } 26812612Seric QuickAbort = TRUE; 26951951Seric LogUsrErrs = TRUE; 2704549Seric p = skipword(p, "to"); 2714549Seric if (p == NULL) 2724549Seric break; 27355012Seric a = parseaddr(p, (ADDRESS *) NULL, 1, '\0', e); 27412612Seric if (a == NULL) 27512612Seric break; 27616886Seric a->q_flags |= QPRIMARY; 27755012Seric a = recipient(a, &e->e_sendqueue, e); 27812612Seric if (Errors != 0) 27912612Seric break; 28012612Seric 28112612Seric /* no errors during parsing, but might be a duplicate */ 28255012Seric e->e_to = p; 28312612Seric if (!bitset(QBADADDR, a->q_flags)) 28412612Seric message("250", "Recipient ok"); 28512612Seric else 2864549Seric { 28712612Seric /* punt -- should keep message in ADDRESS.... */ 28812612Seric message("550", "Addressee unknown"); 2894549Seric } 29055012Seric e->e_to = NULL; 2914549Seric break; 2924549Seric 2934549Seric case CMDDATA: /* data -- text of mail */ 29424943Seric SmtpPhase = "DATA"; 2954976Seric if (!hasmail) 2964549Seric { 2974976Seric message("503", "Need MAIL command"); 2984976Seric break; 2994549Seric } 30055012Seric else if (e->e_nrcpts <= 0) 3014549Seric { 3024976Seric message("503", "Need RCPT (recipient)"); 3034976Seric break; 3044549Seric } 3054976Seric 3064976Seric /* collect the text of the message */ 30724943Seric SmtpPhase = "collect"; 30857389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 30955012Seric collect(TRUE, e); 3104976Seric if (Errors != 0) 3114976Seric break; 3124976Seric 3138238Seric /* 3148238Seric ** Arrange to send to everyone. 3158238Seric ** If sending to multiple people, mail back 3168238Seric ** errors rather than reporting directly. 3178238Seric ** In any case, don't mail back errors for 3188238Seric ** anything that has happened up to 3198238Seric ** now (the other end will do this). 32010197Seric ** Truncate our transcript -- the mail has gotten 32110197Seric ** to us successfully, and if we have 32210197Seric ** to mail this back, it will be easier 32310197Seric ** on the reader. 3248238Seric ** Then send to everyone. 3258238Seric ** Finally give a reply code. If an error has 3268238Seric ** already been given, don't mail a 3278238Seric ** message back. 3289339Seric ** We goose error returns by clearing error bit. 3298238Seric */ 3308238Seric 33124943Seric SmtpPhase = "delivery"; 33255012Seric if (e->e_nrcpts != 1) 3339378Seric { 3349378Seric HoldErrs = TRUE; 33516886Seric ErrorMode = EM_MAIL; 3369378Seric } 33755012Seric e->e_flags &= ~EF_FATALERRS; 33855012Seric e->e_xfp = freopen(queuename(e, 'x'), "w", e->e_xfp); 3394976Seric 3404976Seric /* send to all recipients */ 34155012Seric sendall(e, SM_DEFAULT); 34255012Seric e->e_to = NULL; 3434976Seric 34423516Seric /* save statistics */ 34555012Seric markstats(e, (ADDRESS *) NULL); 34623516Seric 3478238Seric /* issue success if appropriate and reset */ 3488238Seric if (Errors == 0 || HoldErrs) 3499283Seric message("250", "Ok"); 3508238Seric else 35155012Seric e->e_flags &= ~EF_FATALERRS; 3529339Seric 3539339Seric /* if in a child, pop back to our parent */ 3549339Seric if (InChild) 3559339Seric finis(); 35624943Seric 35724943Seric /* clean up a bit */ 35858008Seric hasmail = FALSE; 35955012Seric dropenvelope(e); 36055012Seric CurEnv = e = newenvelope(e); 36155012Seric e->e_flags = BlankEnvelope.e_flags; 3624549Seric break; 3634549Seric 3644549Seric case CMDRSET: /* rset -- reset state */ 3654549Seric message("250", "Reset state"); 3669339Seric if (InChild) 3679339Seric finis(); 3689339Seric break; 3694549Seric 3704549Seric case CMDVRFY: /* vrfy -- verify address */ 37155012Seric if (runinchild("SMTP-VRFY", e) > 0) 3729339Seric break; 37325050Seric setproctitle("%s: %s", CurHostName, inp); 37455173Seric #ifdef LOG 37558020Seric if (LogLevel > 5) 37655173Seric syslog(LOG_INFO, "%s: %s", CurHostName, inp); 37755173Seric #endif 3785003Seric vrfyqueue = NULL; 3797762Seric QuickAbort = TRUE; 38055012Seric sendtolist(p, (ADDRESS *) NULL, &vrfyqueue, e); 3817762Seric if (Errors != 0) 3829339Seric { 3839339Seric if (InChild) 3849339Seric finis(); 3857762Seric break; 3869339Seric } 3875003Seric while (vrfyqueue != NULL) 3885003Seric { 3895003Seric register ADDRESS *a = vrfyqueue->q_next; 3905003Seric char *code; 3915003Seric 3927685Seric while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags)) 3935003Seric a = a->q_next; 3945003Seric 3957685Seric if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags)) 3965003Seric { 3975003Seric if (a != NULL) 3985003Seric code = "250-"; 3995003Seric else 4005003Seric code = "250"; 40158010Seric if (strchr(vrfyqueue->q_paddr, '<') != NULL) 40258010Seric message(code, "%s", vrfyqueue->q_paddr); 40358010Seric else if (vrfyqueue->q_fullname == NULL) 4045003Seric message(code, "<%s>", vrfyqueue->q_paddr); 4055003Seric else 4065003Seric message(code, "%s <%s>", 4075003Seric vrfyqueue->q_fullname, vrfyqueue->q_paddr); 4085003Seric } 4095003Seric else if (a == NULL) 4105003Seric message("554", "Self destructive alias loop"); 4115003Seric vrfyqueue = a; 4125003Seric } 4139339Seric if (InChild) 4149339Seric finis(); 4154549Seric break; 4164549Seric 4174549Seric case CMDHELP: /* help -- give user info */ 4184577Seric help(p); 4194549Seric break; 4204549Seric 4214549Seric case CMDNOOP: /* noop -- do nothing */ 4224549Seric message("200", "OK"); 4234549Seric break; 4244549Seric 4254549Seric case CMDQUIT: /* quit -- leave mail */ 42625050Seric message("221", "%s closing connection", MyHostName); 4279339Seric if (InChild) 4289339Seric ExitStat = EX_QUIT; 4294549Seric finis(); 4304549Seric 4318544Seric case CMDVERB: /* set verbose mode */ 4328544Seric Verbose = TRUE; 43325025Seric SendMode = SM_DELIVER; 4348544Seric message("200", "Verbose mode"); 4358544Seric break; 4368544Seric 4379314Seric case CMDONEX: /* doing one transaction only */ 4389378Seric OneXact = TRUE; 4399314Seric message("200", "Only one transaction"); 4409314Seric break; 4419314Seric 44236230Skarels # ifdef SMTPDEBUG 4439339Seric case CMDDBGQSHOW: /* show queues */ 4446907Seric printf("Send Queue="); 44555012Seric printaddr(e->e_sendqueue, TRUE); 4465003Seric break; 4477275Seric 4487275Seric case CMDDBGDEBUG: /* set debug mode */ 4497676Seric tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); 4507676Seric tTflag(p); 4517676Seric message("200", "Debug set"); 4527275Seric break; 4537275Seric 45436230Skarels # else /* not SMTPDEBUG */ 45524945Seric 45636230Skarels case CMDDBGQSHOW: /* show queues */ 45736230Skarels case CMDDBGDEBUG: /* set debug mode */ 45836233Skarels # ifdef LOG 45936233Skarels if (RealHostName != NULL && LogLevel > 0) 46036230Skarels syslog(LOG_NOTICE, 46158020Seric "\"%s\" command from %s (%s)", 46236230Skarels c->cmdname, RealHostName, 46336230Skarels inet_ntoa(RealHostAddr.sin_addr)); 46436233Skarels # endif 46536230Skarels /* FALL THROUGH */ 46636230Skarels # endif /* SMTPDEBUG */ 46736230Skarels 4684549Seric case CMDERROR: /* unknown command */ 4694549Seric message("500", "Command unrecognized"); 4704549Seric break; 4714549Seric 4724549Seric default: 47336230Skarels errno = 0; 4744549Seric syserr("smtp: unknown code %d", c->cmdcode); 4754549Seric break; 4764549Seric } 4774549Seric } 4784549Seric } 4794549Seric /* 4804549Seric ** SKIPWORD -- skip a fixed word. 4814549Seric ** 4824549Seric ** Parameters: 4834549Seric ** p -- place to start looking. 4844549Seric ** w -- word to skip. 4854549Seric ** 4864549Seric ** Returns: 4874549Seric ** p following w. 4884549Seric ** NULL on error. 4894549Seric ** 4904549Seric ** Side Effects: 4914549Seric ** clobbers the p data area. 4924549Seric */ 4934549Seric 4944549Seric static char * 4954549Seric skipword(p, w) 4964549Seric register char *p; 4974549Seric char *w; 4984549Seric { 4994549Seric register char *q; 5004549Seric 5014549Seric /* find beginning of word */ 502*58050Seric while (isascii(*p) && isspace(*p)) 5034549Seric p++; 5044549Seric q = p; 5054549Seric 5064549Seric /* find end of word */ 507*58050Seric while (*p != '\0' && *p != ':' && !(isascii(*p) && isspace(*p))) 5084549Seric p++; 509*58050Seric while (isascii(*p) && isspace(*p)) 5104549Seric *p++ = '\0'; 5114549Seric if (*p != ':') 5124549Seric { 5134549Seric syntax: 5144549Seric message("501", "Syntax error"); 5154549Seric Errors++; 5164549Seric return (NULL); 5174549Seric } 5184549Seric *p++ = '\0'; 519*58050Seric while (isascii(*p) && isspace(*p)) 5204549Seric p++; 5214549Seric 5224549Seric /* see if the input word matches desired word */ 52333725Sbostic if (strcasecmp(q, w)) 5244549Seric goto syntax; 5254549Seric 5264549Seric return (p); 5274549Seric } 5284577Seric /* 5294577Seric ** HELP -- implement the HELP command. 5304577Seric ** 5314577Seric ** Parameters: 5324577Seric ** topic -- the topic we want help for. 5334577Seric ** 5344577Seric ** Returns: 5354577Seric ** none. 5364577Seric ** 5374577Seric ** Side Effects: 5384577Seric ** outputs the help file to message output. 5394577Seric */ 5404577Seric 5414577Seric help(topic) 5424577Seric char *topic; 5434577Seric { 5444577Seric register FILE *hf; 5454577Seric int len; 5464577Seric char buf[MAXLINE]; 5474577Seric bool noinfo; 5484577Seric 5498269Seric if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL) 5504577Seric { 5514577Seric /* no help */ 55211931Seric errno = 0; 5534577Seric message("502", "HELP not implemented"); 5544577Seric return; 5554577Seric } 5564577Seric 55749669Seric if (topic == NULL || *topic == '\0') 55849669Seric topic = "smtp"; 55949669Seric else 56049669Seric makelower(topic); 56149669Seric 5624577Seric len = strlen(topic); 5634577Seric noinfo = TRUE; 5644577Seric 5654577Seric while (fgets(buf, sizeof buf, hf) != NULL) 5664577Seric { 5674577Seric if (strncmp(buf, topic, len) == 0) 5684577Seric { 5694577Seric register char *p; 5704577Seric 57156795Seric p = strchr(buf, '\t'); 5724577Seric if (p == NULL) 5734577Seric p = buf; 5744577Seric else 5754577Seric p++; 5764577Seric fixcrlf(p, TRUE); 5774577Seric message("214-", p); 5784577Seric noinfo = FALSE; 5794577Seric } 5804577Seric } 5814577Seric 5824577Seric if (noinfo) 5834577Seric message("504", "HELP topic unknown"); 5844577Seric else 5854577Seric message("214", "End of HELP info"); 5864628Seric (void) fclose(hf); 5874577Seric } 5888544Seric /* 5899339Seric ** RUNINCHILD -- return twice -- once in the child, then in the parent again 5909339Seric ** 5919339Seric ** Parameters: 5929339Seric ** label -- a string used in error messages 5939339Seric ** 5949339Seric ** Returns: 5959339Seric ** zero in the child 5969339Seric ** one in the parent 5979339Seric ** 5989339Seric ** Side Effects: 5999339Seric ** none. 6009339Seric */ 6018544Seric 60255012Seric runinchild(label, e) 6039339Seric char *label; 60455012Seric register ENVELOPE *e; 6059339Seric { 6069339Seric int childpid; 6079339Seric 60816158Seric if (!OneXact) 6099339Seric { 61016158Seric childpid = dofork(); 61116158Seric if (childpid < 0) 61216158Seric { 61316158Seric syserr("%s: cannot fork", label); 61416158Seric return (1); 61516158Seric } 61616158Seric if (childpid > 0) 61716158Seric { 61816158Seric auto int st; 6199339Seric 62016158Seric /* parent -- wait for child to complete */ 62116158Seric st = waitfor(childpid); 62216158Seric if (st == -1) 62316158Seric syserr("%s: lost child", label); 6249339Seric 62516158Seric /* if we exited on a QUIT command, complete the process */ 62616158Seric if (st == (EX_QUIT << 8)) 62716158Seric finis(); 6289339Seric 62916158Seric return (1); 63016158Seric } 63116158Seric else 63216158Seric { 63316158Seric /* child */ 63416158Seric InChild = TRUE; 63525050Seric QuickAbort = FALSE; 63655012Seric clearenvelope(e, FALSE); 63716158Seric } 6389339Seric } 63915256Seric 64016158Seric /* open alias database */ 64155012Seric initaliases(AliasFile, FALSE, e); 64216158Seric 64316158Seric return (0); 6449339Seric } 6459339Seric 64656795Seric # endif /* SMTP */ 647