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*24969Seric static char SccsId[] = "@(#)srvrsmtp.c 5.10 (Berkeley) 09/19/85 (no SMTP)"; 1923122Seric # endif not lint 205181Seric # else SMTP 214556Seric 2223122Seric # ifndef lint 23*24969Seric static char SccsId[] = "@(#)srvrsmtp.c 5.10 (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, 8124945Seric # endif DEBUG 8224945Seric # ifdef WIZ 838544Seric "kill", CMDDBGKILL, 8424945Seric # endif WIZ 858544Seric "wiz", CMDDBGWIZ, 864549Seric NULL, CMDERROR, 874549Seric }; 884549Seric 8924955Seric # ifdef WIZ 908544Seric bool IsWiz = FALSE; /* set if we are a wizard */ 9124955Seric # endif WIZ 9215596Seric char *WizWord; /* the wizard word to compare against */ 939339Seric bool InChild = FALSE; /* true if running in a subprocess */ 949378Seric bool OneXact = FALSE; /* one xaction only this run */ 9511146Seric 969339Seric #define EX_QUIT 22 /* special code for QUIT command */ 978544Seric 984549Seric smtp() 994549Seric { 1004549Seric register char *p; 1018544Seric register struct cmd *c; 1024549Seric char *cmd; 1034549Seric extern char *skipword(); 1044549Seric extern bool sameword(); 1054549Seric bool hasmail; /* mail command received */ 1065003Seric auto ADDRESS *vrfyqueue; 10712612Seric ADDRESS *a; 108*24969Seric char state[100]; 1098544Seric char inp[MAXLINE]; 1107124Seric extern char Version[]; 1117356Seric extern tick(); 1128544Seric extern bool iswiz(); 1139349Seric extern char *arpadate(); 11411151Seric extern char *macvalue(); 11512612Seric extern ADDRESS *recipient(); 11624943Seric extern ENVELOPE BlankEnvelope; 11724943Seric extern ENVELOPE *newenvelope(); 1184549Seric 1195003Seric hasmail = FALSE; 1207363Seric if (OutChannel != stdout) 1217363Seric { 1227363Seric /* arrange for debugging output to go to remote host */ 1237363Seric (void) close(1); 1247363Seric (void) dup(fileno(OutChannel)); 1257363Seric } 12611931Seric settime(); 12716153Seric expand("\001e", inp, &inp[sizeof inp], CurEnv); 12810708Seric message("220", inp); 12924943Seric SmtpPhase = "startup"; 1304549Seric for (;;) 1314549Seric { 13212612Seric /* arrange for backout */ 13312612Seric if (setjmp(TopFrame) > 0 && InChild) 13412612Seric finis(); 13512612Seric QuickAbort = FALSE; 13612612Seric HoldErrs = FALSE; 13712612Seric 1387356Seric /* setup for the read */ 1396907Seric CurEnv->e_to = NULL; 1404577Seric Errors = 0; 1417275Seric (void) fflush(stdout); 1427356Seric 1437356Seric /* read the input line */ 1447685Seric p = sfgets(inp, sizeof inp, InChannel); 1457356Seric 1467685Seric /* handle errors */ 1477356Seric if (p == NULL) 1487356Seric { 1494549Seric /* end of file, just die */ 1504558Seric message("421", "%s Lost input channel", HostName); 1514549Seric finis(); 1524549Seric } 1534549Seric 1544549Seric /* clean up end of line */ 1554558Seric fixcrlf(inp, TRUE); 1564549Seric 1574713Seric /* echo command to transcript */ 1589545Seric if (CurEnv->e_xfp != NULL) 1599545Seric fprintf(CurEnv->e_xfp, "<<< %s\n", inp); 1604713Seric 1614549Seric /* break off command */ 1624549Seric for (p = inp; isspace(*p); p++) 1634549Seric continue; 1644549Seric cmd = p; 1654549Seric while (*++p != '\0' && !isspace(*p)) 1664549Seric continue; 1674549Seric if (*p != '\0') 1684549Seric *p++ = '\0'; 1694549Seric 1704549Seric /* decode command */ 1714549Seric for (c = CmdTab; c->cmdname != NULL; c++) 1724549Seric { 1734549Seric if (sameword(c->cmdname, cmd)) 1744549Seric break; 1754549Seric } 1764549Seric 1774549Seric /* process command */ 1784549Seric switch (c->cmdcode) 1794549Seric { 1804976Seric case CMDHELO: /* hello -- introduce yourself */ 18124943Seric SmtpPhase = "HELO"; 18214877Seric if (sameword(p, HostName)) 18314877Seric { 18414877Seric /* connected to an echo server */ 18514877Seric message("553", "%s I refuse to talk to myself", 18614877Seric HostName); 18714877Seric break; 18814877Seric } 18911146Seric if (RealHostName != NULL && !sameword(p, RealHostName)) 19011146Seric { 19111146Seric char buf[MAXNAME]; 19211146Seric 19311146Seric (void) sprintf(buf, "%s (%s)", p, RealHostName); 19411146Seric define('s', newstr(buf), CurEnv); 19511146Seric } 19611146Seric else 19711146Seric define('s', newstr(p), CurEnv); 1984997Seric message("250", "%s Hello %s, pleased to meet you", 1994997Seric HostName, p); 2004976Seric break; 2014976Seric 2024549Seric case CMDMAIL: /* mail -- designate sender */ 20324943Seric SmtpPhase = "MAIL"; 20424943Seric 20511151Seric /* force a sending host even if no HELO given */ 20611151Seric if (RealHostName != NULL && macvalue('s', CurEnv) == NULL) 20711151Seric define('s', RealHostName, CurEnv); 20811151Seric 2099314Seric /* check for validity of this command */ 2104558Seric if (hasmail) 2114558Seric { 2124558Seric message("503", "Sender already specified"); 2134558Seric break; 2144558Seric } 2159339Seric if (InChild) 2169339Seric { 2179339Seric syserr("Nested MAIL command"); 2189339Seric exit(0); 2199339Seric } 2209339Seric 2219339Seric /* fork a subprocess to process this command */ 2229339Seric if (runinchild("SMTP-MAIL") > 0) 2239339Seric break; 2249339Seric initsys(); 225*24969Seric (void) sprintf(state, "srvrsmtp %s", CurEnv->e_id); 226*24969Seric setproctitle(state); 2279339Seric 2289339Seric /* child -- go do the processing */ 2294549Seric p = skipword(p, "from"); 2304549Seric if (p == NULL) 2314549Seric break; 2324549Seric setsender(p); 2334577Seric if (Errors == 0) 2344549Seric { 2354549Seric message("250", "Sender ok"); 2364549Seric hasmail = TRUE; 2374549Seric } 2389339Seric else if (InChild) 2399339Seric finis(); 2404549Seric break; 2414549Seric 2424976Seric case CMDRCPT: /* rcpt -- designate recipient */ 24324943Seric SmtpPhase = "RCPT"; 24412612Seric if (setjmp(TopFrame) > 0) 24514785Seric { 24614785Seric CurEnv->e_flags &= ~EF_FATALERRS; 24712612Seric break; 24814785Seric } 24912612Seric QuickAbort = TRUE; 2504549Seric p = skipword(p, "to"); 2514549Seric if (p == NULL) 2524549Seric break; 25316140Seric a = parseaddr(p, (ADDRESS *) NULL, 1, '\0'); 25412612Seric if (a == NULL) 25512612Seric break; 25616886Seric a->q_flags |= QPRIMARY; 25712612Seric a = recipient(a, &CurEnv->e_sendqueue); 25812612Seric if (Errors != 0) 25912612Seric break; 26012612Seric 26112612Seric /* no errors during parsing, but might be a duplicate */ 26212612Seric CurEnv->e_to = p; 26312612Seric if (!bitset(QBADADDR, a->q_flags)) 26412612Seric message("250", "Recipient ok"); 26512612Seric else 2664549Seric { 26712612Seric /* punt -- should keep message in ADDRESS.... */ 26812612Seric message("550", "Addressee unknown"); 2694549Seric } 27012612Seric CurEnv->e_to = NULL; 2714549Seric break; 2724549Seric 2734549Seric case CMDDATA: /* data -- text of mail */ 27424943Seric SmtpPhase = "DATA"; 2754976Seric if (!hasmail) 2764549Seric { 2774976Seric message("503", "Need MAIL command"); 2784976Seric break; 2794549Seric } 28024943Seric else if (CurEnv->e_nrcpts <= 0) 2814549Seric { 2824976Seric message("503", "Need RCPT (recipient)"); 2834976Seric break; 2844549Seric } 2854976Seric 2864976Seric /* collect the text of the message */ 28724943Seric SmtpPhase = "collect"; 2884976Seric collect(TRUE); 2894976Seric if (Errors != 0) 2904976Seric break; 2914976Seric 2928238Seric /* 2938238Seric ** Arrange to send to everyone. 2948238Seric ** If sending to multiple people, mail back 2958238Seric ** errors rather than reporting directly. 2968238Seric ** In any case, don't mail back errors for 2978238Seric ** anything that has happened up to 2988238Seric ** now (the other end will do this). 29910197Seric ** Truncate our transcript -- the mail has gotten 30010197Seric ** to us successfully, and if we have 30110197Seric ** to mail this back, it will be easier 30210197Seric ** on the reader. 3038238Seric ** Then send to everyone. 3048238Seric ** Finally give a reply code. If an error has 3058238Seric ** already been given, don't mail a 3068238Seric ** message back. 3079339Seric ** We goose error returns by clearing error bit. 3088238Seric */ 3098238Seric 31024943Seric SmtpPhase = "delivery"; 31124943Seric if (CurEnv->e_nrcpts != 1) 3129378Seric { 3139378Seric HoldErrs = TRUE; 31416886Seric ErrorMode = EM_MAIL; 3159378Seric } 3169339Seric CurEnv->e_flags &= ~EF_FATALERRS; 31710197Seric CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp); 3184976Seric 3194976Seric /* send to all recipients */ 32014877Seric sendall(CurEnv, SM_DEFAULT); 3216907Seric CurEnv->e_to = NULL; 3224976Seric 32323516Seric /* save statistics */ 32423516Seric markstats(CurEnv, (ADDRESS *) NULL); 32523516Seric 3268238Seric /* issue success if appropriate and reset */ 3278238Seric if (Errors == 0 || HoldErrs) 3289283Seric message("250", "Ok"); 3298238Seric else 3309339Seric CurEnv->e_flags &= ~EF_FATALERRS; 3319339Seric 3329339Seric /* if in a child, pop back to our parent */ 3339339Seric if (InChild) 3349339Seric finis(); 33524943Seric 33624943Seric /* clean up a bit */ 33724943Seric hasmail = 0; 33824943Seric dropenvelope(CurEnv); 33924943Seric CurEnv = newenvelope(CurEnv); 34024943Seric CurEnv->e_flags = BlankEnvelope.e_flags; 3414549Seric break; 3424549Seric 3434549Seric case CMDRSET: /* rset -- reset state */ 3444549Seric message("250", "Reset state"); 3459339Seric if (InChild) 3469339Seric finis(); 3479339Seric break; 3484549Seric 3494549Seric case CMDVRFY: /* vrfy -- verify address */ 3509339Seric if (runinchild("SMTP-VRFY") > 0) 3519339Seric break; 352*24969Seric setproctitle("SMTP-VRFY"); 3535003Seric vrfyqueue = NULL; 3547762Seric QuickAbort = TRUE; 3559619Seric sendtolist(p, (ADDRESS *) NULL, &vrfyqueue); 3567762Seric if (Errors != 0) 3579339Seric { 3589339Seric if (InChild) 3599339Seric finis(); 3607762Seric break; 3619339Seric } 3625003Seric while (vrfyqueue != NULL) 3635003Seric { 3645003Seric register ADDRESS *a = vrfyqueue->q_next; 3655003Seric char *code; 3665003Seric 3677685Seric while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags)) 3685003Seric a = a->q_next; 3695003Seric 3707685Seric if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags)) 3715003Seric { 3725003Seric if (a != NULL) 3735003Seric code = "250-"; 3745003Seric else 3755003Seric code = "250"; 3765003Seric if (vrfyqueue->q_fullname == NULL) 3775003Seric message(code, "<%s>", vrfyqueue->q_paddr); 3785003Seric else 3795003Seric message(code, "%s <%s>", 3805003Seric vrfyqueue->q_fullname, vrfyqueue->q_paddr); 3815003Seric } 3825003Seric else if (a == NULL) 3835003Seric message("554", "Self destructive alias loop"); 3845003Seric vrfyqueue = a; 3855003Seric } 3869339Seric if (InChild) 3879339Seric finis(); 3884549Seric break; 3894549Seric 3904549Seric case CMDHELP: /* help -- give user info */ 3914577Seric if (*p == '\0') 3924577Seric p = "SMTP"; 3934577Seric help(p); 3944549Seric break; 3954549Seric 3964549Seric case CMDNOOP: /* noop -- do nothing */ 3974549Seric message("200", "OK"); 3984549Seric break; 3994549Seric 4004549Seric case CMDQUIT: /* quit -- leave mail */ 4014549Seric message("221", "%s closing connection", HostName); 4029339Seric if (InChild) 4039339Seric ExitStat = EX_QUIT; 4044549Seric finis(); 4054549Seric 4068544Seric case CMDVERB: /* set verbose mode */ 4078544Seric Verbose = TRUE; 4088544Seric message("200", "Verbose mode"); 4098544Seric break; 4108544Seric 4119314Seric case CMDONEX: /* doing one transaction only */ 4129378Seric OneXact = TRUE; 4139314Seric message("200", "Only one transaction"); 4149314Seric break; 4159314Seric 4165003Seric # ifdef DEBUG 4179339Seric case CMDDBGQSHOW: /* show queues */ 4186907Seric printf("Send Queue="); 4196907Seric printaddr(CurEnv->e_sendqueue, TRUE); 4205003Seric break; 4217275Seric 4227275Seric case CMDDBGDEBUG: /* set debug mode */ 4237676Seric tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); 4247676Seric tTflag(p); 4257676Seric message("200", "Debug set"); 4267275Seric break; 42724945Seric # endif DEBUG 4287275Seric 42924945Seric # ifdef WIZ 4307282Seric case CMDDBGKILL: /* kill the parent */ 4318544Seric if (!iswiz()) 4328544Seric break; 4337282Seric if (kill(MotherPid, SIGTERM) >= 0) 4347282Seric message("200", "Mother is dead"); 4357282Seric else 4367282Seric message("500", "Can't kill Mom"); 4377282Seric break; 4388544Seric 4398544Seric case CMDDBGWIZ: /* become a wizard */ 4408544Seric if (WizWord != NULL) 4418544Seric { 4428544Seric char seed[3]; 4438544Seric extern char *crypt(); 4448544Seric 44523106Seric (void) strncpy(seed, WizWord, 2); 44615596Seric if (strcmp(WizWord, crypt(p, seed)) == 0) 4478544Seric { 44815596Seric IsWiz = TRUE; 44915596Seric message("200", "Please pass, oh mighty wizard"); 4508544Seric break; 4518544Seric } 4528544Seric } 45315596Seric message("500", "You are no wizard!"); 4548544Seric break; 4555003Seric 45624945Seric # else WIZ 45724945Seric case CMDDBGWIZ: /* try to become a wizard */ 45824945Seric message("500", "You wascal wabbit! Wandering wizards won't win!"); 45924945Seric break; 46024945Seric # endif WIZ 46124945Seric 4624549Seric case CMDERROR: /* unknown command */ 4634549Seric message("500", "Command unrecognized"); 4644549Seric break; 4654549Seric 4664549Seric default: 4674549Seric syserr("smtp: unknown code %d", c->cmdcode); 4684549Seric break; 4694549Seric } 4704549Seric } 4714549Seric } 4724549Seric /* 4734549Seric ** SKIPWORD -- skip a fixed word. 4744549Seric ** 4754549Seric ** Parameters: 4764549Seric ** p -- place to start looking. 4774549Seric ** w -- word to skip. 4784549Seric ** 4794549Seric ** Returns: 4804549Seric ** p following w. 4814549Seric ** NULL on error. 4824549Seric ** 4834549Seric ** Side Effects: 4844549Seric ** clobbers the p data area. 4854549Seric */ 4864549Seric 4874549Seric static char * 4884549Seric skipword(p, w) 4894549Seric register char *p; 4904549Seric char *w; 4914549Seric { 4924549Seric register char *q; 4934549Seric extern bool sameword(); 4944549Seric 4954549Seric /* find beginning of word */ 4964549Seric while (isspace(*p)) 4974549Seric p++; 4984549Seric q = p; 4994549Seric 5004549Seric /* find end of word */ 5014549Seric while (*p != '\0' && *p != ':' && !isspace(*p)) 5024549Seric p++; 5034549Seric while (isspace(*p)) 5044549Seric *p++ = '\0'; 5054549Seric if (*p != ':') 5064549Seric { 5074549Seric syntax: 5084549Seric message("501", "Syntax error"); 5094549Seric Errors++; 5104549Seric return (NULL); 5114549Seric } 5124549Seric *p++ = '\0'; 5134549Seric while (isspace(*p)) 5144549Seric p++; 5154549Seric 5164549Seric /* see if the input word matches desired word */ 5174549Seric if (!sameword(q, w)) 5184549Seric goto syntax; 5194549Seric 5204549Seric return (p); 5214549Seric } 5224577Seric /* 5234577Seric ** HELP -- implement the HELP command. 5244577Seric ** 5254577Seric ** Parameters: 5264577Seric ** topic -- the topic we want help for. 5274577Seric ** 5284577Seric ** Returns: 5294577Seric ** none. 5304577Seric ** 5314577Seric ** Side Effects: 5324577Seric ** outputs the help file to message output. 5334577Seric */ 5344577Seric 5354577Seric help(topic) 5364577Seric char *topic; 5374577Seric { 5384577Seric register FILE *hf; 5394577Seric int len; 5404577Seric char buf[MAXLINE]; 5414577Seric bool noinfo; 5424577Seric 5438269Seric if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL) 5444577Seric { 5454577Seric /* no help */ 54611931Seric errno = 0; 5474577Seric message("502", "HELP not implemented"); 5484577Seric return; 5494577Seric } 5504577Seric 5514577Seric len = strlen(topic); 5524577Seric makelower(topic); 5534577Seric noinfo = TRUE; 5544577Seric 5554577Seric while (fgets(buf, sizeof buf, hf) != NULL) 5564577Seric { 5574577Seric if (strncmp(buf, topic, len) == 0) 5584577Seric { 5594577Seric register char *p; 5604577Seric 5614577Seric p = index(buf, '\t'); 5624577Seric if (p == NULL) 5634577Seric p = buf; 5644577Seric else 5654577Seric p++; 5664577Seric fixcrlf(p, TRUE); 5674577Seric message("214-", p); 5684577Seric noinfo = FALSE; 5694577Seric } 5704577Seric } 5714577Seric 5724577Seric if (noinfo) 5734577Seric message("504", "HELP topic unknown"); 5744577Seric else 5754577Seric message("214", "End of HELP info"); 5764628Seric (void) fclose(hf); 5774577Seric } 5788544Seric /* 5798544Seric ** ISWIZ -- tell us if we are a wizard 5808544Seric ** 5818544Seric ** If not, print a nasty message. 5828544Seric ** 5838544Seric ** Parameters: 5848544Seric ** none. 5858544Seric ** 5868544Seric ** Returns: 5878544Seric ** TRUE if we are a wizard. 5888544Seric ** FALSE if we are not a wizard. 5898544Seric ** 5908544Seric ** Side Effects: 5918544Seric ** Prints a 500 exit stat if we are not a wizard. 5928544Seric */ 5935181Seric 59424945Seric #ifdef WIZ 59519038Seric 5968544Seric bool 5978544Seric iswiz() 5988544Seric { 5998544Seric if (!IsWiz) 6008544Seric message("500", "Mere mortals musn't mutter that mantra"); 6018544Seric return (IsWiz); 6028544Seric } 60319038Seric 60424945Seric #endif WIZ 6059339Seric /* 6069339Seric ** RUNINCHILD -- return twice -- once in the child, then in the parent again 6079339Seric ** 6089339Seric ** Parameters: 6099339Seric ** label -- a string used in error messages 6109339Seric ** 6119339Seric ** Returns: 6129339Seric ** zero in the child 6139339Seric ** one in the parent 6149339Seric ** 6159339Seric ** Side Effects: 6169339Seric ** none. 6179339Seric */ 6188544Seric 6199339Seric runinchild(label) 6209339Seric char *label; 6219339Seric { 6229339Seric int childpid; 6239339Seric 62416158Seric if (!OneXact) 6259339Seric { 62616158Seric childpid = dofork(); 62716158Seric if (childpid < 0) 62816158Seric { 62916158Seric syserr("%s: cannot fork", label); 63016158Seric return (1); 63116158Seric } 63216158Seric if (childpid > 0) 63316158Seric { 63416158Seric auto int st; 6359339Seric 63616158Seric /* parent -- wait for child to complete */ 63716158Seric st = waitfor(childpid); 63816158Seric if (st == -1) 63916158Seric syserr("%s: lost child", label); 6409339Seric 64116158Seric /* if we exited on a QUIT command, complete the process */ 64216158Seric if (st == (EX_QUIT << 8)) 64316158Seric finis(); 6449339Seric 64516158Seric return (1); 64616158Seric } 64716158Seric else 64816158Seric { 64916158Seric /* child */ 65016158Seric InChild = TRUE; 65124945Seric clearenvelope(CurEnv); 65216158Seric } 6539339Seric } 65415256Seric 65516158Seric /* open alias database */ 65616158Seric initaliases(AliasFile, FALSE); 65716158Seric 65816158Seric return (0); 6599339Seric } 6609339Seric 6615181Seric # endif SMTP 662