122712Sdist /* 2*34921Sbostic * 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 7*34921Sbostic * provided that the above copyright notice and this paragraph are 8*34921Sbostic * duplicated in all such forms and that any documentation, 9*34921Sbostic * advertising materials, and other materials related to such 10*34921Sbostic * distribution and use acknowledge that the software was developed 11*34921Sbostic * by the University of California, Berkeley. The name of the 12*34921Sbostic * University may not be used to endorse or promote products derived 13*34921Sbostic * from this software without specific prior written permission. 14*34921Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15*34921Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16*34921Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1733731Sbostic */ 1822712Sdist 1933731Sbostic # include "sendmail.h" 2022712Sdist 2133731Sbostic #ifndef lint 2233731Sbostic #ifdef SMTP 23*34921Sbostic static char sccsid[] = "@(#)srvrsmtp.c 5.22 (Berkeley) 06/30/88 (with SMTP)"; 2433731Sbostic #else 25*34921Sbostic static char sccsid[] = "@(#)srvrsmtp.c 5.22 (Berkeley) 06/30/88 (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 */ 659339Seric # define CMDDBGQSHOW 10 /* showq -- show send queue (DEBUG) */ 669339Seric # define CMDDBGDEBUG 11 /* debug -- set debug mode */ 679339Seric # define CMDVERB 12 /* verb -- go into verbose mode */ 689339Seric # define CMDDBGKILL 13 /* kill -- kill sendmail */ 699339Seric # define CMDDBGWIZ 14 /* wiz -- become a wizard */ 709339Seric # define CMDONEX 15 /* onex -- sending one transaction only */ 714549Seric 724549Seric static struct cmd CmdTab[] = 734549Seric { 744549Seric "mail", CMDMAIL, 754976Seric "rcpt", CMDRCPT, 764549Seric "data", CMDDATA, 774549Seric "rset", CMDRSET, 784549Seric "vrfy", CMDVRFY, 797762Seric "expn", CMDVRFY, 804549Seric "help", CMDHELP, 814549Seric "noop", CMDNOOP, 824549Seric "quit", CMDQUIT, 834976Seric "helo", CMDHELO, 848544Seric "verb", CMDVERB, 859314Seric "onex", CMDONEX, 865003Seric # ifdef DEBUG 879339Seric "showq", CMDDBGQSHOW, 888544Seric "debug", CMDDBGDEBUG, 8924945Seric # endif DEBUG 9024945Seric # ifdef WIZ 918544Seric "kill", CMDDBGKILL, 9224945Seric # endif WIZ 938544Seric "wiz", CMDDBGWIZ, 944549Seric NULL, CMDERROR, 954549Seric }; 964549Seric 9724955Seric # ifdef WIZ 988544Seric bool IsWiz = FALSE; /* set if we are a wizard */ 9924955Seric # endif WIZ 10015596Seric char *WizWord; /* the wizard word to compare against */ 1019339Seric bool InChild = FALSE; /* true if running in a subprocess */ 1029378Seric bool OneXact = FALSE; /* one xaction only this run */ 10311146Seric 1049339Seric #define EX_QUIT 22 /* special code for QUIT command */ 1058544Seric 1064549Seric smtp() 1074549Seric { 1084549Seric register char *p; 1098544Seric register struct cmd *c; 1104549Seric char *cmd; 1114549Seric extern char *skipword(); 1124549Seric bool hasmail; /* mail command received */ 1135003Seric auto ADDRESS *vrfyqueue; 11412612Seric ADDRESS *a; 11530448Seric char *sendinghost; 1168544Seric char inp[MAXLINE]; 11724981Seric char cmdbuf[100]; 1187124Seric extern char Version[]; 1197356Seric extern tick(); 1208544Seric extern bool iswiz(); 1219349Seric extern char *arpadate(); 12211151Seric extern char *macvalue(); 12312612Seric extern ADDRESS *recipient(); 12424943Seric extern ENVELOPE BlankEnvelope; 12524943Seric extern ENVELOPE *newenvelope(); 1264549Seric 1275003Seric hasmail = FALSE; 1287363Seric if (OutChannel != stdout) 1297363Seric { 1307363Seric /* arrange for debugging output to go to remote host */ 1317363Seric (void) close(1); 1327363Seric (void) dup(fileno(OutChannel)); 1337363Seric } 13411931Seric settime(); 13524971Seric if (RealHostName != NULL) 13625050Seric { 13725050Seric CurHostName = RealHostName; 13825050Seric setproctitle("srvrsmtp %s", CurHostName); 13925050Seric } 14025050Seric else 14125050Seric { 14225050Seric /* this must be us!! */ 14325050Seric CurHostName = MyHostName; 14425050Seric } 14516153Seric expand("\001e", inp, &inp[sizeof inp], CurEnv); 14610708Seric message("220", inp); 14724943Seric SmtpPhase = "startup"; 14830448Seric sendinghost = NULL; 1494549Seric for (;;) 1504549Seric { 15112612Seric /* arrange for backout */ 15212612Seric if (setjmp(TopFrame) > 0 && InChild) 15312612Seric finis(); 15412612Seric QuickAbort = FALSE; 15512612Seric HoldErrs = FALSE; 15612612Seric 1577356Seric /* setup for the read */ 1586907Seric CurEnv->e_to = NULL; 1594577Seric Errors = 0; 1607275Seric (void) fflush(stdout); 1617356Seric 1627356Seric /* read the input line */ 1637685Seric p = sfgets(inp, sizeof inp, InChannel); 1647356Seric 1657685Seric /* handle errors */ 1667356Seric if (p == NULL) 1677356Seric { 1684549Seric /* end of file, just die */ 16925050Seric message("421", "%s Lost input channel to %s", 17025050Seric MyHostName, CurHostName); 1714549Seric finis(); 1724549Seric } 1734549Seric 1744549Seric /* clean up end of line */ 1754558Seric fixcrlf(inp, TRUE); 1764549Seric 1774713Seric /* echo command to transcript */ 1789545Seric if (CurEnv->e_xfp != NULL) 1799545Seric fprintf(CurEnv->e_xfp, "<<< %s\n", inp); 1804713Seric 1814549Seric /* break off command */ 1824549Seric for (p = inp; isspace(*p); p++) 1834549Seric continue; 1844549Seric cmd = p; 18524981Seric for (cmd = cmdbuf; *p != '\0' && !isspace(*p); ) 18624981Seric *cmd++ = *p++; 18724981Seric *cmd = '\0'; 1884549Seric 18925691Seric /* throw away leading whitespace */ 19025691Seric while (isspace(*p)) 19125691Seric p++; 19225691Seric 1934549Seric /* decode command */ 1944549Seric for (c = CmdTab; c->cmdname != NULL; c++) 1954549Seric { 19633725Sbostic if (!strcasecmp(c->cmdname, cmdbuf)) 1974549Seric break; 1984549Seric } 1994549Seric 2004549Seric /* process command */ 2014549Seric switch (c->cmdcode) 2024549Seric { 2034976Seric case CMDHELO: /* hello -- introduce yourself */ 20424943Seric SmtpPhase = "HELO"; 20525050Seric setproctitle("%s: %s", CurHostName, inp); 20633725Sbostic if (!strcasecmp(p, MyHostName)) 20714877Seric { 20814877Seric /* connected to an echo server */ 20914877Seric message("553", "%s I refuse to talk to myself", 21025050Seric MyHostName); 21114877Seric break; 21214877Seric } 21333725Sbostic if (RealHostName != NULL && strcasecmp(p, RealHostName)) 21411146Seric { 21524981Seric char hostbuf[MAXNAME]; 21611146Seric 21724981Seric (void) sprintf(hostbuf, "%s (%s)", p, RealHostName); 21830448Seric sendinghost = newstr(hostbuf); 21911146Seric } 22011146Seric else 22130448Seric sendinghost = newstr(p); 2224997Seric message("250", "%s Hello %s, pleased to meet you", 22325050Seric MyHostName, p); 2244976Seric break; 2254976Seric 2264549Seric case CMDMAIL: /* mail -- designate sender */ 22724943Seric SmtpPhase = "MAIL"; 22824943Seric 22911151Seric /* force a sending host even if no HELO given */ 23011151Seric if (RealHostName != NULL && macvalue('s', CurEnv) == NULL) 23130448Seric sendinghost = RealHostName; 23211151Seric 2339314Seric /* check for validity of this command */ 2344558Seric if (hasmail) 2354558Seric { 2364558Seric message("503", "Sender already specified"); 2374558Seric break; 2384558Seric } 2399339Seric if (InChild) 2409339Seric { 2419339Seric syserr("Nested MAIL command"); 2429339Seric exit(0); 2439339Seric } 2449339Seric 2459339Seric /* fork a subprocess to process this command */ 2469339Seric if (runinchild("SMTP-MAIL") > 0) 2479339Seric break; 24830448Seric define('s', sendinghost, CurEnv); 2499339Seric initsys(); 25025016Seric setproctitle("%s %s: %s", CurEnv->e_id, 25125050Seric CurHostName, inp); 2529339Seric 2539339Seric /* child -- go do the processing */ 2544549Seric p = skipword(p, "from"); 2554549Seric if (p == NULL) 2564549Seric break; 2574549Seric setsender(p); 2584577Seric if (Errors == 0) 2594549Seric { 2604549Seric message("250", "Sender ok"); 2614549Seric hasmail = TRUE; 2624549Seric } 2639339Seric else if (InChild) 2649339Seric finis(); 2654549Seric break; 2664549Seric 2674976Seric case CMDRCPT: /* rcpt -- designate recipient */ 26824943Seric SmtpPhase = "RCPT"; 26925016Seric setproctitle("%s %s: %s", CurEnv->e_id, 27025050Seric CurHostName, inp); 27112612Seric if (setjmp(TopFrame) > 0) 27214785Seric { 27314785Seric CurEnv->e_flags &= ~EF_FATALERRS; 27412612Seric break; 27514785Seric } 27612612Seric QuickAbort = TRUE; 2774549Seric p = skipword(p, "to"); 2784549Seric if (p == NULL) 2794549Seric break; 28016140Seric a = parseaddr(p, (ADDRESS *) NULL, 1, '\0'); 28112612Seric if (a == NULL) 28212612Seric break; 28316886Seric a->q_flags |= QPRIMARY; 28412612Seric a = recipient(a, &CurEnv->e_sendqueue); 28512612Seric if (Errors != 0) 28612612Seric break; 28712612Seric 28812612Seric /* no errors during parsing, but might be a duplicate */ 28912612Seric CurEnv->e_to = p; 29012612Seric if (!bitset(QBADADDR, a->q_flags)) 29112612Seric message("250", "Recipient ok"); 29212612Seric else 2934549Seric { 29412612Seric /* punt -- should keep message in ADDRESS.... */ 29512612Seric message("550", "Addressee unknown"); 2964549Seric } 29712612Seric CurEnv->e_to = NULL; 2984549Seric break; 2994549Seric 3004549Seric case CMDDATA: /* data -- text of mail */ 30124943Seric SmtpPhase = "DATA"; 3024976Seric if (!hasmail) 3034549Seric { 3044976Seric message("503", "Need MAIL command"); 3054976Seric break; 3064549Seric } 30724943Seric else if (CurEnv->e_nrcpts <= 0) 3084549Seric { 3094976Seric message("503", "Need RCPT (recipient)"); 3104976Seric break; 3114549Seric } 3124976Seric 3134976Seric /* collect the text of the message */ 31424943Seric SmtpPhase = "collect"; 31525016Seric setproctitle("%s %s: %s", CurEnv->e_id, 31625050Seric CurHostName, inp); 3174976Seric collect(TRUE); 3184976Seric if (Errors != 0) 3194976Seric break; 3204976Seric 3218238Seric /* 3228238Seric ** Arrange to send to everyone. 3238238Seric ** If sending to multiple people, mail back 3248238Seric ** errors rather than reporting directly. 3258238Seric ** In any case, don't mail back errors for 3268238Seric ** anything that has happened up to 3278238Seric ** now (the other end will do this). 32810197Seric ** Truncate our transcript -- the mail has gotten 32910197Seric ** to us successfully, and if we have 33010197Seric ** to mail this back, it will be easier 33110197Seric ** on the reader. 3328238Seric ** Then send to everyone. 3338238Seric ** Finally give a reply code. If an error has 3348238Seric ** already been given, don't mail a 3358238Seric ** message back. 3369339Seric ** We goose error returns by clearing error bit. 3378238Seric */ 3388238Seric 33924943Seric SmtpPhase = "delivery"; 34024943Seric if (CurEnv->e_nrcpts != 1) 3419378Seric { 3429378Seric HoldErrs = TRUE; 34316886Seric ErrorMode = EM_MAIL; 3449378Seric } 3459339Seric CurEnv->e_flags &= ~EF_FATALERRS; 34610197Seric CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp); 3474976Seric 3484976Seric /* send to all recipients */ 34914877Seric sendall(CurEnv, SM_DEFAULT); 3506907Seric CurEnv->e_to = NULL; 3514976Seric 35223516Seric /* save statistics */ 35323516Seric markstats(CurEnv, (ADDRESS *) NULL); 35423516Seric 3558238Seric /* issue success if appropriate and reset */ 3568238Seric if (Errors == 0 || HoldErrs) 3579283Seric message("250", "Ok"); 3588238Seric else 3599339Seric CurEnv->e_flags &= ~EF_FATALERRS; 3609339Seric 3619339Seric /* if in a child, pop back to our parent */ 3629339Seric if (InChild) 3639339Seric finis(); 36424943Seric 36524943Seric /* clean up a bit */ 36624943Seric hasmail = 0; 36724943Seric dropenvelope(CurEnv); 36824943Seric CurEnv = newenvelope(CurEnv); 36924943Seric CurEnv->e_flags = BlankEnvelope.e_flags; 3704549Seric break; 3714549Seric 3724549Seric case CMDRSET: /* rset -- reset state */ 3734549Seric message("250", "Reset state"); 3749339Seric if (InChild) 3759339Seric finis(); 3769339Seric break; 3774549Seric 3784549Seric case CMDVRFY: /* vrfy -- verify address */ 3799339Seric if (runinchild("SMTP-VRFY") > 0) 3809339Seric break; 38125050Seric setproctitle("%s: %s", CurHostName, inp); 3825003Seric vrfyqueue = NULL; 3837762Seric QuickAbort = TRUE; 3849619Seric sendtolist(p, (ADDRESS *) NULL, &vrfyqueue); 3857762Seric if (Errors != 0) 3869339Seric { 3879339Seric if (InChild) 3889339Seric finis(); 3897762Seric break; 3909339Seric } 3915003Seric while (vrfyqueue != NULL) 3925003Seric { 3935003Seric register ADDRESS *a = vrfyqueue->q_next; 3945003Seric char *code; 3955003Seric 3967685Seric while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags)) 3975003Seric a = a->q_next; 3985003Seric 3997685Seric if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags)) 4005003Seric { 4015003Seric if (a != NULL) 4025003Seric code = "250-"; 4035003Seric else 4045003Seric code = "250"; 4055003Seric if (vrfyqueue->q_fullname == NULL) 4065003Seric message(code, "<%s>", vrfyqueue->q_paddr); 4075003Seric else 4085003Seric message(code, "%s <%s>", 4095003Seric vrfyqueue->q_fullname, vrfyqueue->q_paddr); 4105003Seric } 4115003Seric else if (a == NULL) 4125003Seric message("554", "Self destructive alias loop"); 4135003Seric vrfyqueue = a; 4145003Seric } 4159339Seric if (InChild) 4169339Seric finis(); 4174549Seric break; 4184549Seric 4194549Seric case CMDHELP: /* help -- give user info */ 4204577Seric if (*p == '\0') 4214577Seric p = "SMTP"; 4224577Seric help(p); 4234549Seric break; 4244549Seric 4254549Seric case CMDNOOP: /* noop -- do nothing */ 4264549Seric message("200", "OK"); 4274549Seric break; 4284549Seric 4294549Seric case CMDQUIT: /* quit -- leave mail */ 43025050Seric message("221", "%s closing connection", MyHostName); 4319339Seric if (InChild) 4329339Seric ExitStat = EX_QUIT; 4334549Seric finis(); 4344549Seric 4358544Seric case CMDVERB: /* set verbose mode */ 4368544Seric Verbose = TRUE; 43725025Seric SendMode = SM_DELIVER; 4388544Seric message("200", "Verbose mode"); 4398544Seric break; 4408544Seric 4419314Seric case CMDONEX: /* doing one transaction only */ 4429378Seric OneXact = TRUE; 4439314Seric message("200", "Only one transaction"); 4449314Seric break; 4459314Seric 4465003Seric # ifdef DEBUG 4479339Seric case CMDDBGQSHOW: /* show queues */ 4486907Seric printf("Send Queue="); 4496907Seric printaddr(CurEnv->e_sendqueue, TRUE); 4505003Seric break; 4517275Seric 4527275Seric case CMDDBGDEBUG: /* set debug mode */ 4537676Seric tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); 4547676Seric tTflag(p); 4557676Seric message("200", "Debug set"); 4567275Seric break; 45724945Seric # endif DEBUG 4587275Seric 45924945Seric # ifdef WIZ 4607282Seric case CMDDBGKILL: /* kill the parent */ 4618544Seric if (!iswiz()) 4628544Seric break; 4637282Seric if (kill(MotherPid, SIGTERM) >= 0) 4647282Seric message("200", "Mother is dead"); 4657282Seric else 4667282Seric message("500", "Can't kill Mom"); 4677282Seric break; 4688544Seric 4698544Seric case CMDDBGWIZ: /* become a wizard */ 4708544Seric if (WizWord != NULL) 4718544Seric { 4728544Seric char seed[3]; 4738544Seric extern char *crypt(); 4748544Seric 47523106Seric (void) strncpy(seed, WizWord, 2); 47615596Seric if (strcmp(WizWord, crypt(p, seed)) == 0) 4778544Seric { 47815596Seric IsWiz = TRUE; 47915596Seric message("200", "Please pass, oh mighty wizard"); 4808544Seric break; 4818544Seric } 4828544Seric } 48315596Seric message("500", "You are no wizard!"); 4848544Seric break; 4855003Seric 48624945Seric # else WIZ 48724945Seric case CMDDBGWIZ: /* try to become a wizard */ 48824945Seric message("500", "You wascal wabbit! Wandering wizards won't win!"); 48924945Seric break; 49024945Seric # endif WIZ 49124945Seric 4924549Seric case CMDERROR: /* unknown command */ 4934549Seric message("500", "Command unrecognized"); 4944549Seric break; 4954549Seric 4964549Seric default: 4974549Seric syserr("smtp: unknown code %d", c->cmdcode); 4984549Seric break; 4994549Seric } 5004549Seric } 5014549Seric } 5024549Seric /* 5034549Seric ** SKIPWORD -- skip a fixed word. 5044549Seric ** 5054549Seric ** Parameters: 5064549Seric ** p -- place to start looking. 5074549Seric ** w -- word to skip. 5084549Seric ** 5094549Seric ** Returns: 5104549Seric ** p following w. 5114549Seric ** NULL on error. 5124549Seric ** 5134549Seric ** Side Effects: 5144549Seric ** clobbers the p data area. 5154549Seric */ 5164549Seric 5174549Seric static char * 5184549Seric skipword(p, w) 5194549Seric register char *p; 5204549Seric char *w; 5214549Seric { 5224549Seric register char *q; 5234549Seric 5244549Seric /* find beginning of word */ 5254549Seric while (isspace(*p)) 5264549Seric p++; 5274549Seric q = p; 5284549Seric 5294549Seric /* find end of word */ 5304549Seric while (*p != '\0' && *p != ':' && !isspace(*p)) 5314549Seric p++; 5324549Seric while (isspace(*p)) 5334549Seric *p++ = '\0'; 5344549Seric if (*p != ':') 5354549Seric { 5364549Seric syntax: 5374549Seric message("501", "Syntax error"); 5384549Seric Errors++; 5394549Seric return (NULL); 5404549Seric } 5414549Seric *p++ = '\0'; 5424549Seric while (isspace(*p)) 5434549Seric p++; 5444549Seric 5454549Seric /* see if the input word matches desired word */ 54633725Sbostic if (strcasecmp(q, w)) 5474549Seric goto syntax; 5484549Seric 5494549Seric return (p); 5504549Seric } 5514577Seric /* 5524577Seric ** HELP -- implement the HELP command. 5534577Seric ** 5544577Seric ** Parameters: 5554577Seric ** topic -- the topic we want help for. 5564577Seric ** 5574577Seric ** Returns: 5584577Seric ** none. 5594577Seric ** 5604577Seric ** Side Effects: 5614577Seric ** outputs the help file to message output. 5624577Seric */ 5634577Seric 5644577Seric help(topic) 5654577Seric char *topic; 5664577Seric { 5674577Seric register FILE *hf; 5684577Seric int len; 5694577Seric char buf[MAXLINE]; 5704577Seric bool noinfo; 5714577Seric 5728269Seric if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL) 5734577Seric { 5744577Seric /* no help */ 57511931Seric errno = 0; 5764577Seric message("502", "HELP not implemented"); 5774577Seric return; 5784577Seric } 5794577Seric 5804577Seric len = strlen(topic); 5814577Seric makelower(topic); 5824577Seric noinfo = TRUE; 5834577Seric 5844577Seric while (fgets(buf, sizeof buf, hf) != NULL) 5854577Seric { 5864577Seric if (strncmp(buf, topic, len) == 0) 5874577Seric { 5884577Seric register char *p; 5894577Seric 5904577Seric p = index(buf, '\t'); 5914577Seric if (p == NULL) 5924577Seric p = buf; 5934577Seric else 5944577Seric p++; 5954577Seric fixcrlf(p, TRUE); 5964577Seric message("214-", p); 5974577Seric noinfo = FALSE; 5984577Seric } 5994577Seric } 6004577Seric 6014577Seric if (noinfo) 6024577Seric message("504", "HELP topic unknown"); 6034577Seric else 6044577Seric message("214", "End of HELP info"); 6054628Seric (void) fclose(hf); 6064577Seric } 6078544Seric /* 6088544Seric ** ISWIZ -- tell us if we are a wizard 6098544Seric ** 6108544Seric ** If not, print a nasty message. 6118544Seric ** 6128544Seric ** Parameters: 6138544Seric ** none. 6148544Seric ** 6158544Seric ** Returns: 6168544Seric ** TRUE if we are a wizard. 6178544Seric ** FALSE if we are not a wizard. 6188544Seric ** 6198544Seric ** Side Effects: 6208544Seric ** Prints a 500 exit stat if we are not a wizard. 6218544Seric */ 6225181Seric 62324945Seric #ifdef WIZ 62419038Seric 6258544Seric bool 6268544Seric iswiz() 6278544Seric { 6288544Seric if (!IsWiz) 6298544Seric message("500", "Mere mortals musn't mutter that mantra"); 6308544Seric return (IsWiz); 6318544Seric } 63219038Seric 63324945Seric #endif WIZ 6349339Seric /* 6359339Seric ** RUNINCHILD -- return twice -- once in the child, then in the parent again 6369339Seric ** 6379339Seric ** Parameters: 6389339Seric ** label -- a string used in error messages 6399339Seric ** 6409339Seric ** Returns: 6419339Seric ** zero in the child 6429339Seric ** one in the parent 6439339Seric ** 6449339Seric ** Side Effects: 6459339Seric ** none. 6469339Seric */ 6478544Seric 6489339Seric runinchild(label) 6499339Seric char *label; 6509339Seric { 6519339Seric int childpid; 6529339Seric 65316158Seric if (!OneXact) 6549339Seric { 65516158Seric childpid = dofork(); 65616158Seric if (childpid < 0) 65716158Seric { 65816158Seric syserr("%s: cannot fork", label); 65916158Seric return (1); 66016158Seric } 66116158Seric if (childpid > 0) 66216158Seric { 66316158Seric auto int st; 6649339Seric 66516158Seric /* parent -- wait for child to complete */ 66616158Seric st = waitfor(childpid); 66716158Seric if (st == -1) 66816158Seric syserr("%s: lost child", label); 6699339Seric 67016158Seric /* if we exited on a QUIT command, complete the process */ 67116158Seric if (st == (EX_QUIT << 8)) 67216158Seric finis(); 6739339Seric 67416158Seric return (1); 67516158Seric } 67616158Seric else 67716158Seric { 67816158Seric /* child */ 67916158Seric InChild = TRUE; 68025050Seric QuickAbort = FALSE; 68125614Seric clearenvelope(CurEnv, FALSE); 68216158Seric } 6839339Seric } 68415256Seric 68516158Seric /* open alias database */ 68616158Seric initaliases(AliasFile, FALSE); 68716158Seric 68816158Seric return (0); 6899339Seric } 6909339Seric 6915181Seric # endif SMTP 692