122712Sdist /* 222712Sdist ** Sendmail 322712Sdist ** Copyright (c) 1983 Eric P. Allman 422712Sdist ** Berkeley, California 522712Sdist ** 622712Sdist ** Copyright (c) 1983 Regents of the University of California. 722712Sdist ** All rights reserved. The Berkeley software License Agreement 822712Sdist ** specifies the terms and conditions for redistribution. 922712Sdist */ 1022712Sdist 1122712Sdist 129339Seric # include <errno.h> 134549Seric # include "sendmail.h" 1411728Seric # include <signal.h> 154549Seric 165181Seric # ifndef SMTP 1723122Seric # ifndef lint 18*24945Seric static char SccsId[] = "@(#)srvrsmtp.c 5.8 (Berkeley) 09/19/85 (no SMTP)"; 1923122Seric # endif not lint 205181Seric # else SMTP 214556Seric 2223122Seric # ifndef lint 23*24945Seric static char SccsId[] = "@(#)srvrsmtp.c 5.8 (Berkeley) 09/19/85"; 2423122Seric # endif not lint 255181Seric 264549Seric /* 274549Seric ** SMTP -- run the SMTP protocol. 284549Seric ** 294549Seric ** Parameters: 304549Seric ** none. 314549Seric ** 324549Seric ** Returns: 334549Seric ** never. 344549Seric ** 354549Seric ** Side Effects: 364549Seric ** Reads commands from the input channel and processes 374549Seric ** them. 384549Seric */ 394549Seric 404549Seric struct cmd 414549Seric { 424549Seric char *cmdname; /* command name */ 434549Seric int cmdcode; /* internal code, see below */ 444549Seric }; 454549Seric 464549Seric /* values for cmdcode */ 474549Seric # define CMDERROR 0 /* bad command */ 484549Seric # define CMDMAIL 1 /* mail -- designate sender */ 494976Seric # define CMDRCPT 2 /* rcpt -- designate recipient */ 504549Seric # define CMDDATA 3 /* data -- send message text */ 519339Seric # define CMDRSET 4 /* rset -- reset state */ 529339Seric # define CMDVRFY 5 /* vrfy -- verify address */ 539339Seric # define CMDHELP 6 /* help -- give usage info */ 549339Seric # define CMDNOOP 7 /* noop -- do nothing */ 559339Seric # define CMDQUIT 8 /* quit -- close connection and die */ 569339Seric # define CMDHELO 9 /* helo -- be polite */ 579339Seric # define CMDDBGQSHOW 10 /* showq -- show send queue (DEBUG) */ 589339Seric # define CMDDBGDEBUG 11 /* debug -- set debug mode */ 599339Seric # define CMDVERB 12 /* verb -- go into verbose mode */ 609339Seric # define CMDDBGKILL 13 /* kill -- kill sendmail */ 619339Seric # define CMDDBGWIZ 14 /* wiz -- become a wizard */ 629339Seric # define CMDONEX 15 /* onex -- sending one transaction only */ 634549Seric 644549Seric static struct cmd CmdTab[] = 654549Seric { 664549Seric "mail", CMDMAIL, 674976Seric "rcpt", CMDRCPT, 684549Seric "data", CMDDATA, 694549Seric "rset", CMDRSET, 704549Seric "vrfy", CMDVRFY, 717762Seric "expn", CMDVRFY, 724549Seric "help", CMDHELP, 734549Seric "noop", CMDNOOP, 744549Seric "quit", CMDQUIT, 754976Seric "helo", CMDHELO, 768544Seric "verb", CMDVERB, 779314Seric "onex", CMDONEX, 785003Seric # ifdef DEBUG 799339Seric "showq", CMDDBGQSHOW, 808544Seric "debug", CMDDBGDEBUG, 81*24945Seric # endif DEBUG 82*24945Seric # ifdef WIZ 838544Seric "kill", CMDDBGKILL, 84*24945Seric # endif WIZ 858544Seric "wiz", CMDDBGWIZ, 864549Seric NULL, CMDERROR, 874549Seric }; 884549Seric 898544Seric bool IsWiz = FALSE; /* set if we are a wizard */ 9015596Seric char *WizWord; /* the wizard word to compare against */ 919339Seric bool InChild = FALSE; /* true if running in a subprocess */ 929378Seric bool OneXact = FALSE; /* one xaction only this run */ 9311146Seric 949339Seric #define EX_QUIT 22 /* special code for QUIT command */ 958544Seric 964549Seric smtp() 974549Seric { 984549Seric register char *p; 998544Seric register struct cmd *c; 1004549Seric char *cmd; 1014549Seric extern char *skipword(); 1024549Seric extern bool sameword(); 1034549Seric bool hasmail; /* mail command received */ 1044713Seric int rcps; /* number of recipients */ 1055003Seric auto ADDRESS *vrfyqueue; 10612612Seric ADDRESS *a; 1078544Seric char inp[MAXLINE]; 1087124Seric extern char Version[]; 1097356Seric extern tick(); 1108544Seric extern bool iswiz(); 1119349Seric extern char *arpadate(); 11211151Seric extern char *macvalue(); 11312612Seric extern ADDRESS *recipient(); 11424943Seric extern ENVELOPE BlankEnvelope; 11524943Seric extern ENVELOPE *newenvelope(); 1164549Seric 1175003Seric hasmail = FALSE; 1184713Seric rcps = 0; 1197363Seric if (OutChannel != stdout) 1207363Seric { 1217363Seric /* arrange for debugging output to go to remote host */ 1227363Seric (void) close(1); 1237363Seric (void) dup(fileno(OutChannel)); 1247363Seric } 12511931Seric settime(); 12616153Seric expand("\001e", inp, &inp[sizeof inp], CurEnv); 12710708Seric message("220", inp); 12824943Seric SmtpPhase = "startup"; 1294549Seric for (;;) 1304549Seric { 13112612Seric /* arrange for backout */ 13212612Seric if (setjmp(TopFrame) > 0 && InChild) 13312612Seric finis(); 13412612Seric QuickAbort = FALSE; 13512612Seric HoldErrs = FALSE; 13612612Seric 1377356Seric /* setup for the read */ 1386907Seric CurEnv->e_to = NULL; 1394577Seric Errors = 0; 1407275Seric (void) fflush(stdout); 1417356Seric 1427356Seric /* read the input line */ 1437685Seric p = sfgets(inp, sizeof inp, InChannel); 1447356Seric 1457685Seric /* handle errors */ 1467356Seric if (p == NULL) 1477356Seric { 1484549Seric /* end of file, just die */ 1494558Seric message("421", "%s Lost input channel", HostName); 1504549Seric finis(); 1514549Seric } 1524549Seric 1534549Seric /* clean up end of line */ 1544558Seric fixcrlf(inp, TRUE); 1554549Seric 1564713Seric /* echo command to transcript */ 1579545Seric if (CurEnv->e_xfp != NULL) 1589545Seric fprintf(CurEnv->e_xfp, "<<< %s\n", inp); 1594713Seric 1604549Seric /* break off command */ 1614549Seric for (p = inp; isspace(*p); p++) 1624549Seric continue; 1634549Seric cmd = p; 1644549Seric while (*++p != '\0' && !isspace(*p)) 1654549Seric continue; 1664549Seric if (*p != '\0') 1674549Seric *p++ = '\0'; 1684549Seric 1694549Seric /* decode command */ 1704549Seric for (c = CmdTab; c->cmdname != NULL; c++) 1714549Seric { 1724549Seric if (sameword(c->cmdname, cmd)) 1734549Seric break; 1744549Seric } 1754549Seric 1764549Seric /* process command */ 1774549Seric switch (c->cmdcode) 1784549Seric { 1794976Seric case CMDHELO: /* hello -- introduce yourself */ 18024943Seric SmtpPhase = "HELO"; 18114877Seric if (sameword(p, HostName)) 18214877Seric { 18314877Seric /* connected to an echo server */ 18414877Seric message("553", "%s I refuse to talk to myself", 18514877Seric HostName); 18614877Seric break; 18714877Seric } 18811146Seric if (RealHostName != NULL && !sameword(p, RealHostName)) 18911146Seric { 19011146Seric char buf[MAXNAME]; 19111146Seric 19211146Seric (void) sprintf(buf, "%s (%s)", p, RealHostName); 19311146Seric define('s', newstr(buf), CurEnv); 19411146Seric } 19511146Seric else 19611146Seric define('s', newstr(p), CurEnv); 1974997Seric message("250", "%s Hello %s, pleased to meet you", 1984997Seric HostName, p); 1994976Seric break; 2004976Seric 2014549Seric case CMDMAIL: /* mail -- designate sender */ 20224943Seric SmtpPhase = "MAIL"; 20324943Seric 20411151Seric /* force a sending host even if no HELO given */ 20511151Seric if (RealHostName != NULL && macvalue('s', CurEnv) == NULL) 20611151Seric define('s', RealHostName, CurEnv); 20711151Seric 2089314Seric /* check for validity of this command */ 2094558Seric if (hasmail) 2104558Seric { 2114558Seric message("503", "Sender already specified"); 2124558Seric break; 2134558Seric } 2149339Seric if (InChild) 2159339Seric { 2169339Seric syserr("Nested MAIL command"); 2179339Seric exit(0); 2189339Seric } 2199339Seric 2209339Seric /* fork a subprocess to process this command */ 2219339Seric if (runinchild("SMTP-MAIL") > 0) 2229339Seric break; 2239339Seric initsys(); 2249339Seric 2259339Seric /* child -- go do the processing */ 2264549Seric p = skipword(p, "from"); 2274549Seric if (p == NULL) 2284549Seric break; 2294549Seric setsender(p); 2304577Seric if (Errors == 0) 2314549Seric { 2324549Seric message("250", "Sender ok"); 2334549Seric hasmail = TRUE; 2344549Seric } 2359339Seric else if (InChild) 2369339Seric finis(); 2374549Seric break; 2384549Seric 2394976Seric case CMDRCPT: /* rcpt -- designate recipient */ 24024943Seric SmtpPhase = "RCPT"; 24112612Seric if (setjmp(TopFrame) > 0) 24214785Seric { 24314785Seric CurEnv->e_flags &= ~EF_FATALERRS; 24412612Seric break; 24514785Seric } 24612612Seric QuickAbort = TRUE; 2474549Seric p = skipword(p, "to"); 2484549Seric if (p == NULL) 2494549Seric break; 25016140Seric a = parseaddr(p, (ADDRESS *) NULL, 1, '\0'); 25112612Seric if (a == NULL) 25212612Seric break; 25316886Seric a->q_flags |= QPRIMARY; 25412612Seric a = recipient(a, &CurEnv->e_sendqueue); 25512612Seric if (Errors != 0) 25612612Seric break; 25712612Seric 25812612Seric /* no errors during parsing, but might be a duplicate */ 25912612Seric CurEnv->e_to = p; 26012612Seric if (!bitset(QBADADDR, a->q_flags)) 26112612Seric message("250", "Recipient ok"); 26212612Seric else 2634549Seric { 26412612Seric /* punt -- should keep message in ADDRESS.... */ 26512612Seric message("550", "Addressee unknown"); 2664549Seric } 26712612Seric CurEnv->e_to = NULL; 26812612Seric rcps++; 2694549Seric break; 2704549Seric 2714549Seric case CMDDATA: /* data -- text of mail */ 27224943Seric SmtpPhase = "DATA"; 2734976Seric if (!hasmail) 2744549Seric { 2754976Seric message("503", "Need MAIL command"); 2764976Seric break; 2774549Seric } 27824943Seric else if (CurEnv->e_nrcpts <= 0) 2794549Seric { 2804976Seric message("503", "Need RCPT (recipient)"); 2814976Seric break; 2824549Seric } 2834976Seric 2844976Seric /* collect the text of the message */ 28524943Seric SmtpPhase = "collect"; 2864976Seric collect(TRUE); 2874976Seric if (Errors != 0) 2884976Seric break; 2894976Seric 2908238Seric /* 2918238Seric ** Arrange to send to everyone. 2928238Seric ** If sending to multiple people, mail back 2938238Seric ** errors rather than reporting directly. 2948238Seric ** In any case, don't mail back errors for 2958238Seric ** anything that has happened up to 2968238Seric ** now (the other end will do this). 29710197Seric ** Truncate our transcript -- the mail has gotten 29810197Seric ** to us successfully, and if we have 29910197Seric ** to mail this back, it will be easier 30010197Seric ** on the reader. 3018238Seric ** Then send to everyone. 3028238Seric ** Finally give a reply code. If an error has 3038238Seric ** already been given, don't mail a 3048238Seric ** message back. 3059339Seric ** We goose error returns by clearing error bit. 3068238Seric */ 3078238Seric 30824943Seric SmtpPhase = "delivery"; 30924943Seric if (CurEnv->e_nrcpts != 1) 3109378Seric { 3119378Seric HoldErrs = TRUE; 31216886Seric ErrorMode = EM_MAIL; 3139378Seric } 3149339Seric CurEnv->e_flags &= ~EF_FATALERRS; 31510197Seric CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp); 3164976Seric 3174976Seric /* send to all recipients */ 31814877Seric sendall(CurEnv, SM_DEFAULT); 3196907Seric CurEnv->e_to = NULL; 3204976Seric 32123516Seric /* save statistics */ 32223516Seric markstats(CurEnv, (ADDRESS *) NULL); 32323516Seric 3248238Seric /* issue success if appropriate and reset */ 3258238Seric if (Errors == 0 || HoldErrs) 3269283Seric message("250", "Ok"); 3278238Seric else 3289339Seric CurEnv->e_flags &= ~EF_FATALERRS; 3299339Seric 3309339Seric /* if in a child, pop back to our parent */ 3319339Seric if (InChild) 3329339Seric finis(); 33324943Seric 33424943Seric /* clean up a bit */ 33524943Seric hasmail = 0; 33624943Seric rcps = 0; 33724943Seric dropenvelope(CurEnv); 33824943Seric CurEnv = newenvelope(CurEnv); 33924943Seric CurEnv->e_flags = BlankEnvelope.e_flags; 3404549Seric break; 3414549Seric 3424549Seric case CMDRSET: /* rset -- reset state */ 3434549Seric message("250", "Reset state"); 3449339Seric if (InChild) 3459339Seric finis(); 3469339Seric break; 3474549Seric 3484549Seric case CMDVRFY: /* vrfy -- verify address */ 3499339Seric if (runinchild("SMTP-VRFY") > 0) 3509339Seric break; 3515003Seric vrfyqueue = NULL; 3527762Seric QuickAbort = TRUE; 3539619Seric sendtolist(p, (ADDRESS *) NULL, &vrfyqueue); 3547762Seric if (Errors != 0) 3559339Seric { 3569339Seric if (InChild) 3579339Seric finis(); 3587762Seric break; 3599339Seric } 3605003Seric while (vrfyqueue != NULL) 3615003Seric { 3625003Seric register ADDRESS *a = vrfyqueue->q_next; 3635003Seric char *code; 3645003Seric 3657685Seric while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags)) 3665003Seric a = a->q_next; 3675003Seric 3687685Seric if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags)) 3695003Seric { 3705003Seric if (a != NULL) 3715003Seric code = "250-"; 3725003Seric else 3735003Seric code = "250"; 3745003Seric if (vrfyqueue->q_fullname == NULL) 3755003Seric message(code, "<%s>", vrfyqueue->q_paddr); 3765003Seric else 3775003Seric message(code, "%s <%s>", 3785003Seric vrfyqueue->q_fullname, vrfyqueue->q_paddr); 3795003Seric } 3805003Seric else if (a == NULL) 3815003Seric message("554", "Self destructive alias loop"); 3825003Seric vrfyqueue = a; 3835003Seric } 3849339Seric if (InChild) 3859339Seric finis(); 3864549Seric break; 3874549Seric 3884549Seric case CMDHELP: /* help -- give user info */ 3894577Seric if (*p == '\0') 3904577Seric p = "SMTP"; 3914577Seric help(p); 3924549Seric break; 3934549Seric 3944549Seric case CMDNOOP: /* noop -- do nothing */ 3954549Seric message("200", "OK"); 3964549Seric break; 3974549Seric 3984549Seric case CMDQUIT: /* quit -- leave mail */ 3994549Seric message("221", "%s closing connection", HostName); 4009339Seric if (InChild) 4019339Seric ExitStat = EX_QUIT; 4024549Seric finis(); 4034549Seric 4048544Seric case CMDVERB: /* set verbose mode */ 4058544Seric Verbose = TRUE; 4068544Seric message("200", "Verbose mode"); 4078544Seric break; 4088544Seric 4099314Seric case CMDONEX: /* doing one transaction only */ 4109378Seric OneXact = TRUE; 4119314Seric message("200", "Only one transaction"); 4129314Seric break; 4139314Seric 4145003Seric # ifdef DEBUG 4159339Seric case CMDDBGQSHOW: /* show queues */ 4166907Seric printf("Send Queue="); 4176907Seric printaddr(CurEnv->e_sendqueue, TRUE); 4185003Seric break; 4197275Seric 4207275Seric case CMDDBGDEBUG: /* set debug mode */ 4217676Seric tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); 4227676Seric tTflag(p); 4237676Seric message("200", "Debug set"); 4247275Seric break; 425*24945Seric # endif DEBUG 4267275Seric 427*24945Seric # ifdef WIZ 4287282Seric case CMDDBGKILL: /* kill the parent */ 4298544Seric if (!iswiz()) 4308544Seric break; 4317282Seric if (kill(MotherPid, SIGTERM) >= 0) 4327282Seric message("200", "Mother is dead"); 4337282Seric else 4347282Seric message("500", "Can't kill Mom"); 4357282Seric break; 4368544Seric 4378544Seric case CMDDBGWIZ: /* become a wizard */ 4388544Seric if (WizWord != NULL) 4398544Seric { 4408544Seric char seed[3]; 4418544Seric extern char *crypt(); 4428544Seric 44323106Seric (void) strncpy(seed, WizWord, 2); 44415596Seric if (strcmp(WizWord, crypt(p, seed)) == 0) 4458544Seric { 44615596Seric IsWiz = TRUE; 44715596Seric message("200", "Please pass, oh mighty wizard"); 4488544Seric break; 4498544Seric } 4508544Seric } 45115596Seric message("500", "You are no wizard!"); 4528544Seric break; 4535003Seric 454*24945Seric # else WIZ 455*24945Seric case CMDDBGWIZ: /* try to become a wizard */ 456*24945Seric message("500", "You wascal wabbit! Wandering wizards won't win!"); 457*24945Seric break; 458*24945Seric # endif WIZ 459*24945Seric 4604549Seric case CMDERROR: /* unknown command */ 4614549Seric message("500", "Command unrecognized"); 4624549Seric break; 4634549Seric 4644549Seric default: 4654549Seric syserr("smtp: unknown code %d", c->cmdcode); 4664549Seric break; 4674549Seric } 4684549Seric } 4694549Seric } 4704549Seric /* 4714549Seric ** SKIPWORD -- skip a fixed word. 4724549Seric ** 4734549Seric ** Parameters: 4744549Seric ** p -- place to start looking. 4754549Seric ** w -- word to skip. 4764549Seric ** 4774549Seric ** Returns: 4784549Seric ** p following w. 4794549Seric ** NULL on error. 4804549Seric ** 4814549Seric ** Side Effects: 4824549Seric ** clobbers the p data area. 4834549Seric */ 4844549Seric 4854549Seric static char * 4864549Seric skipword(p, w) 4874549Seric register char *p; 4884549Seric char *w; 4894549Seric { 4904549Seric register char *q; 4914549Seric extern bool sameword(); 4924549Seric 4934549Seric /* find beginning of word */ 4944549Seric while (isspace(*p)) 4954549Seric p++; 4964549Seric q = p; 4974549Seric 4984549Seric /* find end of word */ 4994549Seric while (*p != '\0' && *p != ':' && !isspace(*p)) 5004549Seric p++; 5014549Seric while (isspace(*p)) 5024549Seric *p++ = '\0'; 5034549Seric if (*p != ':') 5044549Seric { 5054549Seric syntax: 5064549Seric message("501", "Syntax error"); 5074549Seric Errors++; 5084549Seric return (NULL); 5094549Seric } 5104549Seric *p++ = '\0'; 5114549Seric while (isspace(*p)) 5124549Seric p++; 5134549Seric 5144549Seric /* see if the input word matches desired word */ 5154549Seric if (!sameword(q, w)) 5164549Seric goto syntax; 5174549Seric 5184549Seric return (p); 5194549Seric } 5204577Seric /* 5214577Seric ** HELP -- implement the HELP command. 5224577Seric ** 5234577Seric ** Parameters: 5244577Seric ** topic -- the topic we want help for. 5254577Seric ** 5264577Seric ** Returns: 5274577Seric ** none. 5284577Seric ** 5294577Seric ** Side Effects: 5304577Seric ** outputs the help file to message output. 5314577Seric */ 5324577Seric 5334577Seric help(topic) 5344577Seric char *topic; 5354577Seric { 5364577Seric register FILE *hf; 5374577Seric int len; 5384577Seric char buf[MAXLINE]; 5394577Seric bool noinfo; 5404577Seric 5418269Seric if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL) 5424577Seric { 5434577Seric /* no help */ 54411931Seric errno = 0; 5454577Seric message("502", "HELP not implemented"); 5464577Seric return; 5474577Seric } 5484577Seric 5494577Seric len = strlen(topic); 5504577Seric makelower(topic); 5514577Seric noinfo = TRUE; 5524577Seric 5534577Seric while (fgets(buf, sizeof buf, hf) != NULL) 5544577Seric { 5554577Seric if (strncmp(buf, topic, len) == 0) 5564577Seric { 5574577Seric register char *p; 5584577Seric 5594577Seric p = index(buf, '\t'); 5604577Seric if (p == NULL) 5614577Seric p = buf; 5624577Seric else 5634577Seric p++; 5644577Seric fixcrlf(p, TRUE); 5654577Seric message("214-", p); 5664577Seric noinfo = FALSE; 5674577Seric } 5684577Seric } 5694577Seric 5704577Seric if (noinfo) 5714577Seric message("504", "HELP topic unknown"); 5724577Seric else 5734577Seric message("214", "End of HELP info"); 5744628Seric (void) fclose(hf); 5754577Seric } 5768544Seric /* 5778544Seric ** ISWIZ -- tell us if we are a wizard 5788544Seric ** 5798544Seric ** If not, print a nasty message. 5808544Seric ** 5818544Seric ** Parameters: 5828544Seric ** none. 5838544Seric ** 5848544Seric ** Returns: 5858544Seric ** TRUE if we are a wizard. 5868544Seric ** FALSE if we are not a wizard. 5878544Seric ** 5888544Seric ** Side Effects: 5898544Seric ** Prints a 500 exit stat if we are not a wizard. 5908544Seric */ 5915181Seric 592*24945Seric #ifdef WIZ 59319038Seric 5948544Seric bool 5958544Seric iswiz() 5968544Seric { 5978544Seric if (!IsWiz) 5988544Seric message("500", "Mere mortals musn't mutter that mantra"); 5998544Seric return (IsWiz); 6008544Seric } 60119038Seric 602*24945Seric #endif WIZ 6039339Seric /* 6049339Seric ** RUNINCHILD -- return twice -- once in the child, then in the parent again 6059339Seric ** 6069339Seric ** Parameters: 6079339Seric ** label -- a string used in error messages 6089339Seric ** 6099339Seric ** Returns: 6109339Seric ** zero in the child 6119339Seric ** one in the parent 6129339Seric ** 6139339Seric ** Side Effects: 6149339Seric ** none. 6159339Seric */ 6168544Seric 6179339Seric runinchild(label) 6189339Seric char *label; 6199339Seric { 6209339Seric int childpid; 6219339Seric 62216158Seric if (!OneXact) 6239339Seric { 62416158Seric childpid = dofork(); 62516158Seric if (childpid < 0) 62616158Seric { 62716158Seric syserr("%s: cannot fork", label); 62816158Seric return (1); 62916158Seric } 63016158Seric if (childpid > 0) 63116158Seric { 63216158Seric auto int st; 6339339Seric 63416158Seric /* parent -- wait for child to complete */ 63516158Seric st = waitfor(childpid); 63616158Seric if (st == -1) 63716158Seric syserr("%s: lost child", label); 6389339Seric 63916158Seric /* if we exited on a QUIT command, complete the process */ 64016158Seric if (st == (EX_QUIT << 8)) 64116158Seric finis(); 6429339Seric 64316158Seric return (1); 64416158Seric } 64516158Seric else 64616158Seric { 64716158Seric /* child */ 64816158Seric InChild = TRUE; 649*24945Seric clearenvelope(CurEnv); 65016158Seric } 6519339Seric } 65215256Seric 65316158Seric /* open alias database */ 65416158Seric initaliases(AliasFile, FALSE); 65516158Seric 65616158Seric return (0); 6579339Seric } 6589339Seric 6595181Seric # endif SMTP 660