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*58010Seric static char sccsid[] = "@(#)srvrsmtp.c 6.6 (Berkeley) 02/15/93 (with SMTP)"; 1433731Sbostic #else 15*58010Seric static char sccsid[] = "@(#)srvrsmtp.c 6.6 (Berkeley) 02/15/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); 12055012Seric expand("\001e", 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 14855464Seric if (LogLevel >= 4) 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 */ 1634549Seric for (p = inp; isspace(*p); p++) 1644549Seric continue; 16557232Seric cmd = cmdbuf; 16657232Seric while (*p != '\0' && !isspace(*p) && cmd < &cmdbuf[sizeof cmdbuf - 2]) 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 18151954Seric /* reset errors */ 18251954Seric errno = 0; 18351954Seric 1844549Seric /* process command */ 1854549Seric switch (c->cmdcode) 1864549Seric { 1874976Seric case CMDHELO: /* hello -- introduce yourself */ 18824943Seric SmtpPhase = "HELO"; 18925050Seric setproctitle("%s: %s", CurHostName, inp); 19033725Sbostic if (!strcasecmp(p, MyHostName)) 19114877Seric { 19236230Skarels /* 19336230Skarels * didn't know about alias, 19436230Skarels * or connected to an echo server 19536230Skarels */ 19647570Seric message("553", "%s config error: mail loops back to myself", 19747570Seric MyHostName); 19814877Seric break; 19914877Seric } 20033725Sbostic if (RealHostName != NULL && strcasecmp(p, RealHostName)) 20111146Seric { 20224981Seric char hostbuf[MAXNAME]; 20311146Seric 20424981Seric (void) sprintf(hostbuf, "%s (%s)", p, RealHostName); 20530448Seric sendinghost = newstr(hostbuf); 20611146Seric } 20711146Seric else 20830448Seric sendinghost = newstr(p); 2094997Seric message("250", "%s Hello %s, pleased to meet you", 21036230Skarels MyHostName, sendinghost); 2114976Seric break; 2124976Seric 2134549Seric case CMDMAIL: /* mail -- designate sender */ 21424943Seric SmtpPhase = "MAIL"; 21524943Seric 21611151Seric /* force a sending host even if no HELO given */ 21755012Seric if (RealHostName != NULL && macvalue('s', e) == NULL) 21830448Seric sendinghost = RealHostName; 21911151Seric 2209314Seric /* check for validity of this command */ 2214558Seric if (hasmail) 2224558Seric { 2234558Seric message("503", "Sender already specified"); 2244558Seric break; 2254558Seric } 2269339Seric if (InChild) 2279339Seric { 22836230Skarels errno = 0; 22958008Seric syserr("Nested MAIL command: MAIL %s", p); 2309339Seric exit(0); 2319339Seric } 2329339Seric 2339339Seric /* fork a subprocess to process this command */ 23455012Seric if (runinchild("SMTP-MAIL", e) > 0) 2359339Seric break; 23655012Seric define('s', sendinghost, e); 23755012Seric define('r', "SMTP", e); 23855012Seric initsys(e); 23957389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 2409339Seric 2419339Seric /* child -- go do the processing */ 2424549Seric p = skipword(p, "from"); 2434549Seric if (p == NULL) 2444549Seric break; 24557977Seric if (setjmp(TopFrame) > 0) 24657977Seric break; 24757977Seric QuickAbort = TRUE; 24855012Seric setsender(p, e); 2494577Seric if (Errors == 0) 2504549Seric { 2514549Seric message("250", "Sender ok"); 2524549Seric hasmail = TRUE; 2534549Seric } 2549339Seric else if (InChild) 2559339Seric finis(); 2564549Seric break; 2574549Seric 2584976Seric case CMDRCPT: /* rcpt -- designate recipient */ 25924943Seric SmtpPhase = "RCPT"; 26057389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 26112612Seric if (setjmp(TopFrame) > 0) 26214785Seric { 26355012Seric e->e_flags &= ~EF_FATALERRS; 26412612Seric break; 26514785Seric } 26612612Seric QuickAbort = TRUE; 26751951Seric LogUsrErrs = TRUE; 2684549Seric p = skipword(p, "to"); 2694549Seric if (p == NULL) 2704549Seric break; 27155012Seric a = parseaddr(p, (ADDRESS *) NULL, 1, '\0', e); 27212612Seric if (a == NULL) 27312612Seric break; 27416886Seric a->q_flags |= QPRIMARY; 27555012Seric a = recipient(a, &e->e_sendqueue, e); 27612612Seric if (Errors != 0) 27712612Seric break; 27812612Seric 27912612Seric /* no errors during parsing, but might be a duplicate */ 28055012Seric e->e_to = p; 28112612Seric if (!bitset(QBADADDR, a->q_flags)) 28212612Seric message("250", "Recipient ok"); 28312612Seric else 2844549Seric { 28512612Seric /* punt -- should keep message in ADDRESS.... */ 28612612Seric message("550", "Addressee unknown"); 2874549Seric } 28855012Seric e->e_to = NULL; 2894549Seric break; 2904549Seric 2914549Seric case CMDDATA: /* data -- text of mail */ 29224943Seric SmtpPhase = "DATA"; 2934976Seric if (!hasmail) 2944549Seric { 2954976Seric message("503", "Need MAIL command"); 2964976Seric break; 2974549Seric } 29855012Seric else if (e->e_nrcpts <= 0) 2994549Seric { 3004976Seric message("503", "Need RCPT (recipient)"); 3014976Seric break; 3024549Seric } 3034976Seric 3044976Seric /* collect the text of the message */ 30524943Seric SmtpPhase = "collect"; 30657389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 30755012Seric collect(TRUE, e); 3084976Seric if (Errors != 0) 3094976Seric break; 3104976Seric 3118238Seric /* 3128238Seric ** Arrange to send to everyone. 3138238Seric ** If sending to multiple people, mail back 3148238Seric ** errors rather than reporting directly. 3158238Seric ** In any case, don't mail back errors for 3168238Seric ** anything that has happened up to 3178238Seric ** now (the other end will do this). 31810197Seric ** Truncate our transcript -- the mail has gotten 31910197Seric ** to us successfully, and if we have 32010197Seric ** to mail this back, it will be easier 32110197Seric ** on the reader. 3228238Seric ** Then send to everyone. 3238238Seric ** Finally give a reply code. If an error has 3248238Seric ** already been given, don't mail a 3258238Seric ** message back. 3269339Seric ** We goose error returns by clearing error bit. 3278238Seric */ 3288238Seric 32924943Seric SmtpPhase = "delivery"; 33055012Seric if (e->e_nrcpts != 1) 3319378Seric { 3329378Seric HoldErrs = TRUE; 33316886Seric ErrorMode = EM_MAIL; 3349378Seric } 33555012Seric e->e_flags &= ~EF_FATALERRS; 33655012Seric e->e_xfp = freopen(queuename(e, 'x'), "w", e->e_xfp); 3374976Seric 3384976Seric /* send to all recipients */ 33955012Seric sendall(e, SM_DEFAULT); 34055012Seric e->e_to = NULL; 3414976Seric 34223516Seric /* save statistics */ 34355012Seric markstats(e, (ADDRESS *) NULL); 34423516Seric 3458238Seric /* issue success if appropriate and reset */ 3468238Seric if (Errors == 0 || HoldErrs) 3479283Seric message("250", "Ok"); 3488238Seric else 34955012Seric e->e_flags &= ~EF_FATALERRS; 3509339Seric 3519339Seric /* if in a child, pop back to our parent */ 3529339Seric if (InChild) 3539339Seric finis(); 35424943Seric 35524943Seric /* clean up a bit */ 35658008Seric hasmail = FALSE; 35755012Seric dropenvelope(e); 35855012Seric CurEnv = e = newenvelope(e); 35955012Seric e->e_flags = BlankEnvelope.e_flags; 3604549Seric break; 3614549Seric 3624549Seric case CMDRSET: /* rset -- reset state */ 3634549Seric message("250", "Reset state"); 3649339Seric if (InChild) 3659339Seric finis(); 3669339Seric break; 3674549Seric 3684549Seric case CMDVRFY: /* vrfy -- verify address */ 36955012Seric if (runinchild("SMTP-VRFY", e) > 0) 3709339Seric break; 37125050Seric setproctitle("%s: %s", CurHostName, inp); 37255173Seric #ifdef LOG 37355173Seric if (LogLevel >= 9) 37455173Seric syslog(LOG_INFO, "%s: %s", CurHostName, inp); 37555173Seric #endif 3765003Seric vrfyqueue = NULL; 3777762Seric QuickAbort = TRUE; 37855012Seric sendtolist(p, (ADDRESS *) NULL, &vrfyqueue, e); 3797762Seric if (Errors != 0) 3809339Seric { 3819339Seric if (InChild) 3829339Seric finis(); 3837762Seric break; 3849339Seric } 3855003Seric while (vrfyqueue != NULL) 3865003Seric { 3875003Seric register ADDRESS *a = vrfyqueue->q_next; 3885003Seric char *code; 3895003Seric 3907685Seric while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags)) 3915003Seric a = a->q_next; 3925003Seric 3937685Seric if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags)) 3945003Seric { 3955003Seric if (a != NULL) 3965003Seric code = "250-"; 3975003Seric else 3985003Seric code = "250"; 399*58010Seric if (strchr(vrfyqueue->q_paddr, '<') != NULL) 400*58010Seric message(code, "%s", vrfyqueue->q_paddr); 401*58010Seric else if (vrfyqueue->q_fullname == NULL) 4025003Seric message(code, "<%s>", vrfyqueue->q_paddr); 4035003Seric else 4045003Seric message(code, "%s <%s>", 4055003Seric vrfyqueue->q_fullname, vrfyqueue->q_paddr); 4065003Seric } 4075003Seric else if (a == NULL) 4085003Seric message("554", "Self destructive alias loop"); 4095003Seric vrfyqueue = a; 4105003Seric } 4119339Seric if (InChild) 4129339Seric finis(); 4134549Seric break; 4144549Seric 4154549Seric case CMDHELP: /* help -- give user info */ 4164577Seric help(p); 4174549Seric break; 4184549Seric 4194549Seric case CMDNOOP: /* noop -- do nothing */ 4204549Seric message("200", "OK"); 4214549Seric break; 4224549Seric 4234549Seric case CMDQUIT: /* quit -- leave mail */ 42425050Seric message("221", "%s closing connection", MyHostName); 4259339Seric if (InChild) 4269339Seric ExitStat = EX_QUIT; 4274549Seric finis(); 4284549Seric 4298544Seric case CMDVERB: /* set verbose mode */ 4308544Seric Verbose = TRUE; 43125025Seric SendMode = SM_DELIVER; 4328544Seric message("200", "Verbose mode"); 4338544Seric break; 4348544Seric 4359314Seric case CMDONEX: /* doing one transaction only */ 4369378Seric OneXact = TRUE; 4379314Seric message("200", "Only one transaction"); 4389314Seric break; 4399314Seric 44036230Skarels # ifdef SMTPDEBUG 4419339Seric case CMDDBGQSHOW: /* show queues */ 4426907Seric printf("Send Queue="); 44355012Seric printaddr(e->e_sendqueue, TRUE); 4445003Seric break; 4457275Seric 4467275Seric case CMDDBGDEBUG: /* set debug mode */ 4477676Seric tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); 4487676Seric tTflag(p); 4497676Seric message("200", "Debug set"); 4507275Seric break; 4517275Seric 45236230Skarels # else /* not SMTPDEBUG */ 45324945Seric 45436230Skarels case CMDDBGQSHOW: /* show queues */ 45536230Skarels case CMDDBGDEBUG: /* set debug mode */ 45636233Skarels # ifdef LOG 45736233Skarels if (RealHostName != NULL && LogLevel > 0) 45836230Skarels syslog(LOG_NOTICE, 45936230Skarels "\"%s\" command from %s (%s)\n", 46036230Skarels c->cmdname, RealHostName, 46136230Skarels inet_ntoa(RealHostAddr.sin_addr)); 46236233Skarels # endif 46336230Skarels /* FALL THROUGH */ 46436230Skarels # endif /* SMTPDEBUG */ 46536230Skarels 4664549Seric case CMDERROR: /* unknown command */ 4674549Seric message("500", "Command unrecognized"); 4684549Seric break; 4694549Seric 4704549Seric default: 47136230Skarels errno = 0; 4724549Seric syserr("smtp: unknown code %d", c->cmdcode); 4734549Seric break; 4744549Seric } 4754549Seric } 4764549Seric } 4774549Seric /* 4784549Seric ** SKIPWORD -- skip a fixed word. 4794549Seric ** 4804549Seric ** Parameters: 4814549Seric ** p -- place to start looking. 4824549Seric ** w -- word to skip. 4834549Seric ** 4844549Seric ** Returns: 4854549Seric ** p following w. 4864549Seric ** NULL on error. 4874549Seric ** 4884549Seric ** Side Effects: 4894549Seric ** clobbers the p data area. 4904549Seric */ 4914549Seric 4924549Seric static char * 4934549Seric skipword(p, w) 4944549Seric register char *p; 4954549Seric char *w; 4964549Seric { 4974549Seric register char *q; 4984549Seric 4994549Seric /* find beginning of word */ 5004549Seric while (isspace(*p)) 5014549Seric p++; 5024549Seric q = p; 5034549Seric 5044549Seric /* find end of word */ 5054549Seric while (*p != '\0' && *p != ':' && !isspace(*p)) 5064549Seric p++; 5074549Seric while (isspace(*p)) 5084549Seric *p++ = '\0'; 5094549Seric if (*p != ':') 5104549Seric { 5114549Seric syntax: 5124549Seric message("501", "Syntax error"); 5134549Seric Errors++; 5144549Seric return (NULL); 5154549Seric } 5164549Seric *p++ = '\0'; 5174549Seric while (isspace(*p)) 5184549Seric p++; 5194549Seric 5204549Seric /* see if the input word matches desired word */ 52133725Sbostic if (strcasecmp(q, w)) 5224549Seric goto syntax; 5234549Seric 5244549Seric return (p); 5254549Seric } 5264577Seric /* 5274577Seric ** HELP -- implement the HELP command. 5284577Seric ** 5294577Seric ** Parameters: 5304577Seric ** topic -- the topic we want help for. 5314577Seric ** 5324577Seric ** Returns: 5334577Seric ** none. 5344577Seric ** 5354577Seric ** Side Effects: 5364577Seric ** outputs the help file to message output. 5374577Seric */ 5384577Seric 5394577Seric help(topic) 5404577Seric char *topic; 5414577Seric { 5424577Seric register FILE *hf; 5434577Seric int len; 5444577Seric char buf[MAXLINE]; 5454577Seric bool noinfo; 5464577Seric 5478269Seric if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL) 5484577Seric { 5494577Seric /* no help */ 55011931Seric errno = 0; 5514577Seric message("502", "HELP not implemented"); 5524577Seric return; 5534577Seric } 5544577Seric 55549669Seric if (topic == NULL || *topic == '\0') 55649669Seric topic = "smtp"; 55749669Seric else 55849669Seric makelower(topic); 55949669Seric 5604577Seric len = strlen(topic); 5614577Seric noinfo = TRUE; 5624577Seric 5634577Seric while (fgets(buf, sizeof buf, hf) != NULL) 5644577Seric { 5654577Seric if (strncmp(buf, topic, len) == 0) 5664577Seric { 5674577Seric register char *p; 5684577Seric 56956795Seric p = strchr(buf, '\t'); 5704577Seric if (p == NULL) 5714577Seric p = buf; 5724577Seric else 5734577Seric p++; 5744577Seric fixcrlf(p, TRUE); 5754577Seric message("214-", p); 5764577Seric noinfo = FALSE; 5774577Seric } 5784577Seric } 5794577Seric 5804577Seric if (noinfo) 5814577Seric message("504", "HELP topic unknown"); 5824577Seric else 5834577Seric message("214", "End of HELP info"); 5844628Seric (void) fclose(hf); 5854577Seric } 5868544Seric /* 5879339Seric ** RUNINCHILD -- return twice -- once in the child, then in the parent again 5889339Seric ** 5899339Seric ** Parameters: 5909339Seric ** label -- a string used in error messages 5919339Seric ** 5929339Seric ** Returns: 5939339Seric ** zero in the child 5949339Seric ** one in the parent 5959339Seric ** 5969339Seric ** Side Effects: 5979339Seric ** none. 5989339Seric */ 5998544Seric 60055012Seric runinchild(label, e) 6019339Seric char *label; 60255012Seric register ENVELOPE *e; 6039339Seric { 6049339Seric int childpid; 6059339Seric 60616158Seric if (!OneXact) 6079339Seric { 60816158Seric childpid = dofork(); 60916158Seric if (childpid < 0) 61016158Seric { 61116158Seric syserr("%s: cannot fork", label); 61216158Seric return (1); 61316158Seric } 61416158Seric if (childpid > 0) 61516158Seric { 61616158Seric auto int st; 6179339Seric 61816158Seric /* parent -- wait for child to complete */ 61916158Seric st = waitfor(childpid); 62016158Seric if (st == -1) 62116158Seric syserr("%s: lost child", label); 6229339Seric 62316158Seric /* if we exited on a QUIT command, complete the process */ 62416158Seric if (st == (EX_QUIT << 8)) 62516158Seric finis(); 6269339Seric 62716158Seric return (1); 62816158Seric } 62916158Seric else 63016158Seric { 63116158Seric /* child */ 63216158Seric InChild = TRUE; 63325050Seric QuickAbort = FALSE; 63455012Seric clearenvelope(e, FALSE); 63516158Seric } 6369339Seric } 63715256Seric 63816158Seric /* open alias database */ 63955012Seric initaliases(AliasFile, FALSE, e); 64016158Seric 64116158Seric return (0); 6429339Seric } 6439339Seric 64456795Seric # endif /* SMTP */ 645