122712Sdist /* 234921Sbostic * Copyright (c) 1983 Eric P. Allman 333731Sbostic * Copyright (c) 1988 Regents of the University of California. 433731Sbostic * All rights reserved. 533731Sbostic * 633731Sbostic * Redistribution and use in source and binary forms are permitted 734921Sbostic * provided that the above copyright notice and this paragraph are 834921Sbostic * duplicated in all such forms and that any documentation, 934921Sbostic * advertising materials, and other materials related to such 1034921Sbostic * distribution and use acknowledge that the software was developed 1134921Sbostic * by the University of California, Berkeley. The name of the 1234921Sbostic * University may not be used to endorse or promote products derived 1334921Sbostic * from this software without specific prior written permission. 1434921Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1534921Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1634921Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1733731Sbostic */ 1822712Sdist 1933731Sbostic # include "sendmail.h" 2022712Sdist 2133731Sbostic #ifndef lint 2233731Sbostic #ifdef SMTP 23*36579Sbostic static char sccsid[] = "@(#)srvrsmtp.c 5.27 (Berkeley) 01/18/89 (with SMTP)"; 2433731Sbostic #else 25*36579Sbostic static char sccsid[] = "@(#)srvrsmtp.c 5.27 (Berkeley) 01/18/89 (without SMTP)"; 2633731Sbostic #endif 2733731Sbostic #endif /* not lint */ 2833731Sbostic 299339Seric # include <errno.h> 3011728Seric # include <signal.h> 314549Seric 3233731Sbostic # ifdef SMTP 334556Seric 344549Seric /* 354549Seric ** SMTP -- run the SMTP protocol. 364549Seric ** 374549Seric ** Parameters: 384549Seric ** none. 394549Seric ** 404549Seric ** Returns: 414549Seric ** never. 424549Seric ** 434549Seric ** Side Effects: 444549Seric ** Reads commands from the input channel and processes 454549Seric ** them. 464549Seric */ 474549Seric 484549Seric struct cmd 494549Seric { 504549Seric char *cmdname; /* command name */ 514549Seric int cmdcode; /* internal code, see below */ 524549Seric }; 534549Seric 544549Seric /* values for cmdcode */ 554549Seric # define CMDERROR 0 /* bad command */ 564549Seric # define CMDMAIL 1 /* mail -- designate sender */ 574976Seric # define CMDRCPT 2 /* rcpt -- designate recipient */ 584549Seric # define CMDDATA 3 /* data -- send message text */ 599339Seric # define CMDRSET 4 /* rset -- reset state */ 609339Seric # define CMDVRFY 5 /* vrfy -- verify address */ 619339Seric # define CMDHELP 6 /* help -- give usage info */ 629339Seric # define CMDNOOP 7 /* noop -- do nothing */ 639339Seric # define CMDQUIT 8 /* quit -- close connection and die */ 649339Seric # define CMDHELO 9 /* helo -- be polite */ 6536230Skarels # define CMDONEX 10 /* onex -- sending one transaction only */ 6636230Skarels # define CMDVERB 11 /* verb -- go into verbose mode */ 6736230Skarels /* debugging-only commands, only enabled if SMTPDEBUG is defined */ 6836230Skarels # define CMDDBGQSHOW 12 /* showq -- show send queue */ 6936230Skarels # define CMDDBGDEBUG 13 /* debug -- set debug mode */ 704549Seric 714549Seric static struct cmd CmdTab[] = 724549Seric { 734549Seric "mail", CMDMAIL, 744976Seric "rcpt", CMDRCPT, 754549Seric "data", CMDDATA, 764549Seric "rset", CMDRSET, 774549Seric "vrfy", CMDVRFY, 787762Seric "expn", CMDVRFY, 794549Seric "help", CMDHELP, 804549Seric "noop", CMDNOOP, 814549Seric "quit", CMDQUIT, 824976Seric "helo", CMDHELO, 838544Seric "verb", CMDVERB, 849314Seric "onex", CMDONEX, 8536230Skarels /* 8636230Skarels * remaining commands are here only 8736230Skarels * to trap and log attempts to use them 8836230Skarels */ 899339Seric "showq", CMDDBGQSHOW, 908544Seric "debug", CMDDBGDEBUG, 914549Seric NULL, CMDERROR, 924549Seric }; 934549Seric 949339Seric bool InChild = FALSE; /* true if running in a subprocess */ 959378Seric bool OneXact = FALSE; /* one xaction only this run */ 9611146Seric 979339Seric #define EX_QUIT 22 /* special code for QUIT command */ 988544Seric 994549Seric smtp() 1004549Seric { 1014549Seric register char *p; 1028544Seric register struct cmd *c; 1034549Seric char *cmd; 1044549Seric extern char *skipword(); 1054549Seric bool hasmail; /* mail command received */ 1065003Seric auto ADDRESS *vrfyqueue; 10712612Seric ADDRESS *a; 10830448Seric char *sendinghost; 1098544Seric char inp[MAXLINE]; 11024981Seric char cmdbuf[100]; 1117124Seric extern char Version[]; 11211151Seric extern char *macvalue(); 11312612Seric extern ADDRESS *recipient(); 11424943Seric extern ENVELOPE BlankEnvelope; 11524943Seric extern ENVELOPE *newenvelope(); 1164549Seric 1175003Seric hasmail = FALSE; 1187363Seric if (OutChannel != stdout) 1197363Seric { 1207363Seric /* arrange for debugging output to go to remote host */ 1217363Seric (void) close(1); 1227363Seric (void) dup(fileno(OutChannel)); 1237363Seric } 12411931Seric settime(); 12524971Seric if (RealHostName != NULL) 12625050Seric { 12725050Seric CurHostName = RealHostName; 12825050Seric setproctitle("srvrsmtp %s", CurHostName); 12925050Seric } 13025050Seric else 13125050Seric { 13225050Seric /* this must be us!! */ 13325050Seric CurHostName = MyHostName; 13425050Seric } 13516153Seric expand("\001e", inp, &inp[sizeof inp], CurEnv); 13610708Seric message("220", inp); 13724943Seric SmtpPhase = "startup"; 13830448Seric sendinghost = NULL; 1394549Seric for (;;) 1404549Seric { 14112612Seric /* arrange for backout */ 14212612Seric if (setjmp(TopFrame) > 0 && InChild) 14312612Seric finis(); 14412612Seric QuickAbort = FALSE; 14512612Seric HoldErrs = FALSE; 14612612Seric 1477356Seric /* setup for the read */ 1486907Seric CurEnv->e_to = NULL; 1494577Seric Errors = 0; 1507275Seric (void) fflush(stdout); 1517356Seric 1527356Seric /* read the input line */ 1537685Seric p = sfgets(inp, sizeof inp, InChannel); 1547356Seric 1557685Seric /* handle errors */ 1567356Seric if (p == NULL) 1577356Seric { 1584549Seric /* end of file, just die */ 15936230Skarels message("421", "%s Lost input channel from %s", 16025050Seric MyHostName, CurHostName); 1614549Seric finis(); 1624549Seric } 1634549Seric 1644549Seric /* clean up end of line */ 1654558Seric fixcrlf(inp, TRUE); 1664549Seric 1674713Seric /* echo command to transcript */ 1689545Seric if (CurEnv->e_xfp != NULL) 1699545Seric fprintf(CurEnv->e_xfp, "<<< %s\n", inp); 1704713Seric 1714549Seric /* break off command */ 1724549Seric for (p = inp; isspace(*p); p++) 1734549Seric continue; 1744549Seric cmd = p; 17524981Seric for (cmd = cmdbuf; *p != '\0' && !isspace(*p); ) 17624981Seric *cmd++ = *p++; 17724981Seric *cmd = '\0'; 1784549Seric 17925691Seric /* throw away leading whitespace */ 18025691Seric while (isspace(*p)) 18125691Seric p++; 18225691Seric 1834549Seric /* decode command */ 1844549Seric for (c = CmdTab; c->cmdname != NULL; c++) 1854549Seric { 18633725Sbostic if (!strcasecmp(c->cmdname, cmdbuf)) 1874549Seric break; 1884549Seric } 1894549Seric 1904549Seric /* process command */ 1914549Seric switch (c->cmdcode) 1924549Seric { 1934976Seric case CMDHELO: /* hello -- introduce yourself */ 19424943Seric SmtpPhase = "HELO"; 19525050Seric setproctitle("%s: %s", CurHostName, inp); 19633725Sbostic if (!strcasecmp(p, MyHostName)) 19714877Seric { 19836230Skarels /* 19936230Skarels * didn't know about alias, 20036230Skarels * or connected to an echo server 20136230Skarels */ 20236230Skarels message("553", "Local configuration error, hostname not recognized as local"); 20314877Seric break; 20414877Seric } 20533725Sbostic if (RealHostName != NULL && strcasecmp(p, RealHostName)) 20611146Seric { 20724981Seric char hostbuf[MAXNAME]; 20811146Seric 20924981Seric (void) sprintf(hostbuf, "%s (%s)", p, RealHostName); 21030448Seric sendinghost = newstr(hostbuf); 21111146Seric } 21211146Seric else 21330448Seric sendinghost = newstr(p); 2144997Seric message("250", "%s Hello %s, pleased to meet you", 21536230Skarels MyHostName, sendinghost); 2164976Seric break; 2174976Seric 2184549Seric case CMDMAIL: /* mail -- designate sender */ 21924943Seric SmtpPhase = "MAIL"; 22024943Seric 22111151Seric /* force a sending host even if no HELO given */ 22211151Seric if (RealHostName != NULL && macvalue('s', CurEnv) == NULL) 22330448Seric sendinghost = RealHostName; 22411151Seric 2259314Seric /* check for validity of this command */ 2264558Seric if (hasmail) 2274558Seric { 2284558Seric message("503", "Sender already specified"); 2294558Seric break; 2304558Seric } 2319339Seric if (InChild) 2329339Seric { 23336230Skarels errno = 0; 2349339Seric syserr("Nested MAIL command"); 2359339Seric exit(0); 2369339Seric } 2379339Seric 2389339Seric /* fork a subprocess to process this command */ 2399339Seric if (runinchild("SMTP-MAIL") > 0) 2409339Seric break; 24130448Seric define('s', sendinghost, CurEnv); 242*36579Sbostic define('r', "SMTP", CurEnv); 2439339Seric initsys(); 24425016Seric setproctitle("%s %s: %s", CurEnv->e_id, 24525050Seric CurHostName, inp); 2469339Seric 2479339Seric /* child -- go do the processing */ 2484549Seric p = skipword(p, "from"); 2494549Seric if (p == NULL) 2504549Seric break; 2514549Seric setsender(p); 2524577Seric if (Errors == 0) 2534549Seric { 2544549Seric message("250", "Sender ok"); 2554549Seric hasmail = TRUE; 2564549Seric } 2579339Seric else if (InChild) 2589339Seric finis(); 2594549Seric break; 2604549Seric 2614976Seric case CMDRCPT: /* rcpt -- designate recipient */ 26224943Seric SmtpPhase = "RCPT"; 26325016Seric setproctitle("%s %s: %s", CurEnv->e_id, 26425050Seric CurHostName, inp); 26512612Seric if (setjmp(TopFrame) > 0) 26614785Seric { 26714785Seric CurEnv->e_flags &= ~EF_FATALERRS; 26812612Seric break; 26914785Seric } 27012612Seric QuickAbort = TRUE; 2714549Seric p = skipword(p, "to"); 2724549Seric if (p == NULL) 2734549Seric break; 27416140Seric a = parseaddr(p, (ADDRESS *) NULL, 1, '\0'); 27512612Seric if (a == NULL) 27612612Seric break; 27716886Seric a->q_flags |= QPRIMARY; 27812612Seric a = recipient(a, &CurEnv->e_sendqueue); 27912612Seric if (Errors != 0) 28012612Seric break; 28112612Seric 28212612Seric /* no errors during parsing, but might be a duplicate */ 28312612Seric CurEnv->e_to = p; 28412612Seric if (!bitset(QBADADDR, a->q_flags)) 28512612Seric message("250", "Recipient ok"); 28612612Seric else 2874549Seric { 28812612Seric /* punt -- should keep message in ADDRESS.... */ 28912612Seric message("550", "Addressee unknown"); 2904549Seric } 29112612Seric CurEnv->e_to = NULL; 2924549Seric break; 2934549Seric 2944549Seric case CMDDATA: /* data -- text of mail */ 29524943Seric SmtpPhase = "DATA"; 2964976Seric if (!hasmail) 2974549Seric { 2984976Seric message("503", "Need MAIL command"); 2994976Seric break; 3004549Seric } 30124943Seric else if (CurEnv->e_nrcpts <= 0) 3024549Seric { 3034976Seric message("503", "Need RCPT (recipient)"); 3044976Seric break; 3054549Seric } 3064976Seric 3074976Seric /* collect the text of the message */ 30824943Seric SmtpPhase = "collect"; 30925016Seric setproctitle("%s %s: %s", CurEnv->e_id, 31025050Seric CurHostName, inp); 3114976Seric collect(TRUE); 3124976Seric if (Errors != 0) 3134976Seric break; 3144976Seric 3158238Seric /* 3168238Seric ** Arrange to send to everyone. 3178238Seric ** If sending to multiple people, mail back 3188238Seric ** errors rather than reporting directly. 3198238Seric ** In any case, don't mail back errors for 3208238Seric ** anything that has happened up to 3218238Seric ** now (the other end will do this). 32210197Seric ** Truncate our transcript -- the mail has gotten 32310197Seric ** to us successfully, and if we have 32410197Seric ** to mail this back, it will be easier 32510197Seric ** on the reader. 3268238Seric ** Then send to everyone. 3278238Seric ** Finally give a reply code. If an error has 3288238Seric ** already been given, don't mail a 3298238Seric ** message back. 3309339Seric ** We goose error returns by clearing error bit. 3318238Seric */ 3328238Seric 33324943Seric SmtpPhase = "delivery"; 33424943Seric if (CurEnv->e_nrcpts != 1) 3359378Seric { 3369378Seric HoldErrs = TRUE; 33716886Seric ErrorMode = EM_MAIL; 3389378Seric } 3399339Seric CurEnv->e_flags &= ~EF_FATALERRS; 34010197Seric CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp); 3414976Seric 3424976Seric /* send to all recipients */ 34314877Seric sendall(CurEnv, SM_DEFAULT); 3446907Seric CurEnv->e_to = NULL; 3454976Seric 34623516Seric /* save statistics */ 34723516Seric markstats(CurEnv, (ADDRESS *) NULL); 34823516Seric 3498238Seric /* issue success if appropriate and reset */ 3508238Seric if (Errors == 0 || HoldErrs) 3519283Seric message("250", "Ok"); 3528238Seric else 3539339Seric CurEnv->e_flags &= ~EF_FATALERRS; 3549339Seric 3559339Seric /* if in a child, pop back to our parent */ 3569339Seric if (InChild) 3579339Seric finis(); 35824943Seric 35924943Seric /* clean up a bit */ 36024943Seric hasmail = 0; 36124943Seric dropenvelope(CurEnv); 36224943Seric CurEnv = newenvelope(CurEnv); 36324943Seric CurEnv->e_flags = BlankEnvelope.e_flags; 3644549Seric break; 3654549Seric 3664549Seric case CMDRSET: /* rset -- reset state */ 3674549Seric message("250", "Reset state"); 3689339Seric if (InChild) 3699339Seric finis(); 3709339Seric break; 3714549Seric 3724549Seric case CMDVRFY: /* vrfy -- verify address */ 3739339Seric if (runinchild("SMTP-VRFY") > 0) 3749339Seric break; 37525050Seric setproctitle("%s: %s", CurHostName, inp); 3765003Seric vrfyqueue = NULL; 3777762Seric QuickAbort = TRUE; 3789619Seric sendtolist(p, (ADDRESS *) NULL, &vrfyqueue); 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"; 3995003Seric if (vrfyqueue->q_fullname == NULL) 4005003Seric message(code, "<%s>", vrfyqueue->q_paddr); 4015003Seric else 4025003Seric message(code, "%s <%s>", 4035003Seric vrfyqueue->q_fullname, vrfyqueue->q_paddr); 4045003Seric } 4055003Seric else if (a == NULL) 4065003Seric message("554", "Self destructive alias loop"); 4075003Seric vrfyqueue = a; 4085003Seric } 4099339Seric if (InChild) 4109339Seric finis(); 4114549Seric break; 4124549Seric 4134549Seric case CMDHELP: /* help -- give user info */ 4144577Seric if (*p == '\0') 4154577Seric p = "SMTP"; 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="); 4436907Seric printaddr(CurEnv->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 5554577Seric len = strlen(topic); 5564577Seric makelower(topic); 5574577Seric noinfo = TRUE; 5584577Seric 5594577Seric while (fgets(buf, sizeof buf, hf) != NULL) 5604577Seric { 5614577Seric if (strncmp(buf, topic, len) == 0) 5624577Seric { 5634577Seric register char *p; 5644577Seric 5654577Seric p = index(buf, '\t'); 5664577Seric if (p == NULL) 5674577Seric p = buf; 5684577Seric else 5694577Seric p++; 5704577Seric fixcrlf(p, TRUE); 5714577Seric message("214-", p); 5724577Seric noinfo = FALSE; 5734577Seric } 5744577Seric } 5754577Seric 5764577Seric if (noinfo) 5774577Seric message("504", "HELP topic unknown"); 5784577Seric else 5794577Seric message("214", "End of HELP info"); 5804628Seric (void) fclose(hf); 5814577Seric } 5828544Seric /* 5839339Seric ** RUNINCHILD -- return twice -- once in the child, then in the parent again 5849339Seric ** 5859339Seric ** Parameters: 5869339Seric ** label -- a string used in error messages 5879339Seric ** 5889339Seric ** Returns: 5899339Seric ** zero in the child 5909339Seric ** one in the parent 5919339Seric ** 5929339Seric ** Side Effects: 5939339Seric ** none. 5949339Seric */ 5958544Seric 5969339Seric runinchild(label) 5979339Seric char *label; 5989339Seric { 5999339Seric int childpid; 6009339Seric 60116158Seric if (!OneXact) 6029339Seric { 60316158Seric childpid = dofork(); 60416158Seric if (childpid < 0) 60516158Seric { 60616158Seric syserr("%s: cannot fork", label); 60716158Seric return (1); 60816158Seric } 60916158Seric if (childpid > 0) 61016158Seric { 61116158Seric auto int st; 6129339Seric 61316158Seric /* parent -- wait for child to complete */ 61416158Seric st = waitfor(childpid); 61516158Seric if (st == -1) 61616158Seric syserr("%s: lost child", label); 6179339Seric 61816158Seric /* if we exited on a QUIT command, complete the process */ 61916158Seric if (st == (EX_QUIT << 8)) 62016158Seric finis(); 6219339Seric 62216158Seric return (1); 62316158Seric } 62416158Seric else 62516158Seric { 62616158Seric /* child */ 62716158Seric InChild = TRUE; 62825050Seric QuickAbort = FALSE; 62925614Seric clearenvelope(CurEnv, FALSE); 63016158Seric } 6319339Seric } 63215256Seric 63316158Seric /* open alias database */ 63416158Seric initaliases(AliasFile, FALSE); 63516158Seric 63616158Seric return (0); 6379339Seric } 6389339Seric 6395181Seric # endif SMTP 640