Annotation of 43BSDTahoe/usr.lib/sendmail/src/srvrsmtp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Eric P. Allman
                      3:  * Copyright (c) 1988 Regents of the University of California.
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms are permitted
                      7:  * provided that the above copyright notice and this paragraph are
                      8:  * duplicated in all such forms and that any documentation,
                      9:  * advertising materials, and other materials related to such
                     10:  * distribution and use acknowledge that the software was developed
                     11:  * by the University of California, Berkeley.  The name of the
                     12:  * University may not be used to endorse or promote products derived
                     13:  * from this software without specific prior written permission.
                     14:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     15:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     16:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     17:  */
                     18: 
                     19: # include "sendmail.h"
                     20: 
                     21: #ifndef lint
                     22: #ifdef SMTP
                     23: static char sccsid[] = "@(#)srvrsmtp.c 5.22 (Berkeley) 6/30/88 (with SMTP)";
                     24: #else
                     25: static char sccsid[] = "@(#)srvrsmtp.c 5.22 (Berkeley) 6/30/88 (without SMTP)";
                     26: #endif
                     27: #endif /* not lint */
                     28: 
                     29: # include <errno.h>
                     30: # include <signal.h>
                     31: 
                     32: # ifdef SMTP
                     33: 
                     34: /*
                     35: **  SMTP -- run the SMTP protocol.
                     36: **
                     37: **     Parameters:
                     38: **             none.
                     39: **
                     40: **     Returns:
                     41: **             never.
                     42: **
                     43: **     Side Effects:
                     44: **             Reads commands from the input channel and processes
                     45: **                     them.
                     46: */
                     47: 
                     48: struct cmd
                     49: {
                     50:        char    *cmdname;       /* command name */
                     51:        int     cmdcode;        /* internal code, see below */
                     52: };
                     53: 
                     54: /* values for cmdcode */
                     55: # define CMDERROR      0       /* bad command */
                     56: # define CMDMAIL       1       /* mail -- designate sender */
                     57: # define CMDRCPT       2       /* rcpt -- designate recipient */
                     58: # define CMDDATA       3       /* data -- send message text */
                     59: # define CMDRSET       4       /* rset -- reset state */
                     60: # define CMDVRFY       5       /* vrfy -- verify address */
                     61: # define CMDHELP       6       /* help -- give usage info */
                     62: # define CMDNOOP       7       /* noop -- do nothing */
                     63: # define CMDQUIT       8       /* quit -- close connection and die */
                     64: # define CMDHELO       9       /* helo -- be polite */
                     65: # define CMDDBGQSHOW   10      /* showq -- show send queue (DEBUG) */
                     66: # define CMDDBGDEBUG   11      /* debug -- set debug mode */
                     67: # define CMDVERB       12      /* verb -- go into verbose mode */
                     68: # define CMDDBGKILL    13      /* kill -- kill sendmail */
                     69: # define CMDDBGWIZ     14      /* wiz -- become a wizard */
                     70: # define CMDONEX       15      /* onex -- sending one transaction only */
                     71: 
                     72: static struct cmd      CmdTab[] =
                     73: {
                     74:        "mail",         CMDMAIL,
                     75:        "rcpt",         CMDRCPT,
                     76:        "data",         CMDDATA,
                     77:        "rset",         CMDRSET,
                     78:        "vrfy",         CMDVRFY,
                     79:        "expn",         CMDVRFY,
                     80:        "help",         CMDHELP,
                     81:        "noop",         CMDNOOP,
                     82:        "quit",         CMDQUIT,
                     83:        "helo",         CMDHELO,
                     84:        "verb",         CMDVERB,
                     85:        "onex",         CMDONEX,
                     86: # ifdef DEBUG
                     87:        "showq",        CMDDBGQSHOW,
                     88:        "debug",        CMDDBGDEBUG,
                     89: # endif DEBUG
                     90: # ifdef WIZ
                     91:        "kill",         CMDDBGKILL,
                     92: # endif WIZ
                     93:        "wiz",          CMDDBGWIZ,
                     94:        NULL,           CMDERROR,
                     95: };
                     96: 
                     97: # ifdef WIZ
                     98: bool   IsWiz = FALSE;                  /* set if we are a wizard */
                     99: # endif WIZ
                    100: char   *WizWord;                       /* the wizard word to compare against */
                    101: bool   InChild = FALSE;                /* true if running in a subprocess */
                    102: bool   OneXact = FALSE;                /* one xaction only this run */
                    103: 
                    104: #define EX_QUIT                22              /* special code for QUIT command */
                    105: 
                    106: smtp()
                    107: {
                    108:        register char *p;
                    109:        register struct cmd *c;
                    110:        char *cmd;
                    111:        extern char *skipword();
                    112:        bool hasmail;                   /* mail command received */
                    113:        auto ADDRESS *vrfyqueue;
                    114:        ADDRESS *a;
                    115:        char *sendinghost;
                    116:        char inp[MAXLINE];
                    117:        char cmdbuf[100];
                    118:        extern char Version[];
                    119:        extern tick();
                    120:        extern bool iswiz();
                    121:        extern char *arpadate();
                    122:        extern char *macvalue();
                    123:        extern ADDRESS *recipient();
                    124:        extern ENVELOPE BlankEnvelope;
                    125:        extern ENVELOPE *newenvelope();
                    126: 
                    127:        hasmail = FALSE;
                    128:        if (OutChannel != stdout)
                    129:        {
                    130:                /* arrange for debugging output to go to remote host */
                    131:                (void) close(1);
                    132:                (void) dup(fileno(OutChannel));
                    133:        }
                    134:        settime();
                    135:        if (RealHostName != NULL)
                    136:        {
                    137:                CurHostName = RealHostName;
                    138:                setproctitle("srvrsmtp %s", CurHostName);
                    139:        }
                    140:        else
                    141:        {
                    142:                /* this must be us!! */
                    143:                CurHostName = MyHostName;
                    144:        }
                    145:        expand("\001e", inp, &inp[sizeof inp], CurEnv);
                    146:        message("220", inp);
                    147:        SmtpPhase = "startup";
                    148:        sendinghost = NULL;
                    149:        for (;;)
                    150:        {
                    151:                /* arrange for backout */
                    152:                if (setjmp(TopFrame) > 0 && InChild)
                    153:                        finis();
                    154:                QuickAbort = FALSE;
                    155:                HoldErrs = FALSE;
                    156: 
                    157:                /* setup for the read */
                    158:                CurEnv->e_to = NULL;
                    159:                Errors = 0;
                    160:                (void) fflush(stdout);
                    161: 
                    162:                /* read the input line */
                    163:                p = sfgets(inp, sizeof inp, InChannel);
                    164: 
                    165:                /* handle errors */
                    166:                if (p == NULL)
                    167:                {
                    168:                        /* end of file, just die */
                    169:                        message("421", "%s Lost input channel to %s",
                    170:                                MyHostName, CurHostName);
                    171:                        finis();
                    172:                }
                    173: 
                    174:                /* clean up end of line */
                    175:                fixcrlf(inp, TRUE);
                    176: 
                    177:                /* echo command to transcript */
                    178:                if (CurEnv->e_xfp != NULL)
                    179:                        fprintf(CurEnv->e_xfp, "<<< %s\n", inp);
                    180: 
                    181:                /* break off command */
                    182:                for (p = inp; isspace(*p); p++)
                    183:                        continue;
                    184:                cmd = p;
                    185:                for (cmd = cmdbuf; *p != '\0' && !isspace(*p); )
                    186:                        *cmd++ = *p++;
                    187:                *cmd = '\0';
                    188: 
                    189:                /* throw away leading whitespace */
                    190:                while (isspace(*p))
                    191:                        p++;
                    192: 
                    193:                /* decode command */
                    194:                for (c = CmdTab; c->cmdname != NULL; c++)
                    195:                {
                    196:                        if (!strcasecmp(c->cmdname, cmdbuf))
                    197:                                break;
                    198:                }
                    199: 
                    200:                /* process command */
                    201:                switch (c->cmdcode)
                    202:                {
                    203:                  case CMDHELO:         /* hello -- introduce yourself */
                    204:                        SmtpPhase = "HELO";
                    205:                        setproctitle("%s: %s", CurHostName, inp);
                    206:                        if (!strcasecmp(p, MyHostName))
                    207:                        {
                    208:                                /* connected to an echo server */
                    209:                                message("553", "%s I refuse to talk to myself",
                    210:                                        MyHostName);
                    211:                                break;
                    212:                        }
                    213:                        if (RealHostName != NULL && strcasecmp(p, RealHostName))
                    214:                        {
                    215:                                char hostbuf[MAXNAME];
                    216: 
                    217:                                (void) sprintf(hostbuf, "%s (%s)", p, RealHostName);
                    218:                                sendinghost = newstr(hostbuf);
                    219:                        }
                    220:                        else
                    221:                                sendinghost = newstr(p);
                    222:                        message("250", "%s Hello %s, pleased to meet you",
                    223:                                MyHostName, p);
                    224:                        break;
                    225: 
                    226:                  case CMDMAIL:         /* mail -- designate sender */
                    227:                        SmtpPhase = "MAIL";
                    228: 
                    229:                        /* force a sending host even if no HELO given */
                    230:                        if (RealHostName != NULL && macvalue('s', CurEnv) == NULL)
                    231:                                sendinghost = RealHostName;
                    232: 
                    233:                        /* check for validity of this command */
                    234:                        if (hasmail)
                    235:                        {
                    236:                                message("503", "Sender already specified");
                    237:                                break;
                    238:                        }
                    239:                        if (InChild)
                    240:                        {
                    241:                                syserr("Nested MAIL command");
                    242:                                exit(0);
                    243:                        }
                    244: 
                    245:                        /* fork a subprocess to process this command */
                    246:                        if (runinchild("SMTP-MAIL") > 0)
                    247:                                break;
                    248:                        define('s', sendinghost, CurEnv);
                    249:                        initsys();
                    250:                        setproctitle("%s %s: %s", CurEnv->e_id,
                    251:                                CurHostName, inp);
                    252: 
                    253:                        /* child -- go do the processing */
                    254:                        p = skipword(p, "from");
                    255:                        if (p == NULL)
                    256:                                break;
                    257:                        setsender(p);
                    258:                        if (Errors == 0)
                    259:                        {
                    260:                                message("250", "Sender ok");
                    261:                                hasmail = TRUE;
                    262:                        }
                    263:                        else if (InChild)
                    264:                                finis();
                    265:                        break;
                    266: 
                    267:                  case CMDRCPT:         /* rcpt -- designate recipient */
                    268:                        SmtpPhase = "RCPT";
                    269:                        setproctitle("%s %s: %s", CurEnv->e_id,
                    270:                                CurHostName, inp);
                    271:                        if (setjmp(TopFrame) > 0)
                    272:                        {
                    273:                                CurEnv->e_flags &= ~EF_FATALERRS;
                    274:                                break;
                    275:                        }
                    276:                        QuickAbort = TRUE;
                    277:                        p = skipword(p, "to");
                    278:                        if (p == NULL)
                    279:                                break;
                    280:                        a = parseaddr(p, (ADDRESS *) NULL, 1, '\0');
                    281:                        if (a == NULL)
                    282:                                break;
                    283:                        a->q_flags |= QPRIMARY;
                    284:                        a = recipient(a, &CurEnv->e_sendqueue);
                    285:                        if (Errors != 0)
                    286:                                break;
                    287: 
                    288:                        /* no errors during parsing, but might be a duplicate */
                    289:                        CurEnv->e_to = p;
                    290:                        if (!bitset(QBADADDR, a->q_flags))
                    291:                                message("250", "Recipient ok");
                    292:                        else
                    293:                        {
                    294:                                /* punt -- should keep message in ADDRESS.... */
                    295:                                message("550", "Addressee unknown");
                    296:                        }
                    297:                        CurEnv->e_to = NULL;
                    298:                        break;
                    299: 
                    300:                  case CMDDATA:         /* data -- text of mail */
                    301:                        SmtpPhase = "DATA";
                    302:                        if (!hasmail)
                    303:                        {
                    304:                                message("503", "Need MAIL command");
                    305:                                break;
                    306:                        }
                    307:                        else if (CurEnv->e_nrcpts <= 0)
                    308:                        {
                    309:                                message("503", "Need RCPT (recipient)");
                    310:                                break;
                    311:                        }
                    312: 
                    313:                        /* collect the text of the message */
                    314:                        SmtpPhase = "collect";
                    315:                        setproctitle("%s %s: %s", CurEnv->e_id,
                    316:                                CurHostName, inp);
                    317:                        collect(TRUE);
                    318:                        if (Errors != 0)
                    319:                                break;
                    320: 
                    321:                        /*
                    322:                        **  Arrange to send to everyone.
                    323:                        **      If sending to multiple people, mail back
                    324:                        **              errors rather than reporting directly.
                    325:                        **      In any case, don't mail back errors for
                    326:                        **              anything that has happened up to
                    327:                        **              now (the other end will do this).
                    328:                        **      Truncate our transcript -- the mail has gotten
                    329:                        **              to us successfully, and if we have
                    330:                        **              to mail this back, it will be easier
                    331:                        **              on the reader.
                    332:                        **      Then send to everyone.
                    333:                        **      Finally give a reply code.  If an error has
                    334:                        **              already been given, don't mail a
                    335:                        **              message back.
                    336:                        **      We goose error returns by clearing error bit.
                    337:                        */
                    338: 
                    339:                        SmtpPhase = "delivery";
                    340:                        if (CurEnv->e_nrcpts != 1)
                    341:                        {
                    342:                                HoldErrs = TRUE;
                    343:                                ErrorMode = EM_MAIL;
                    344:                        }
                    345:                        CurEnv->e_flags &= ~EF_FATALERRS;
                    346:                        CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp);
                    347: 
                    348:                        /* send to all recipients */
                    349:                        sendall(CurEnv, SM_DEFAULT);
                    350:                        CurEnv->e_to = NULL;
                    351: 
                    352:                        /* save statistics */
                    353:                        markstats(CurEnv, (ADDRESS *) NULL);
                    354: 
                    355:                        /* issue success if appropriate and reset */
                    356:                        if (Errors == 0 || HoldErrs)
                    357:                                message("250", "Ok");
                    358:                        else
                    359:                                CurEnv->e_flags &= ~EF_FATALERRS;
                    360: 
                    361:                        /* if in a child, pop back to our parent */
                    362:                        if (InChild)
                    363:                                finis();
                    364: 
                    365:                        /* clean up a bit */
                    366:                        hasmail = 0;
                    367:                        dropenvelope(CurEnv);
                    368:                        CurEnv = newenvelope(CurEnv);
                    369:                        CurEnv->e_flags = BlankEnvelope.e_flags;
                    370:                        break;
                    371: 
                    372:                  case CMDRSET:         /* rset -- reset state */
                    373:                        message("250", "Reset state");
                    374:                        if (InChild)
                    375:                                finis();
                    376:                        break;
                    377: 
                    378:                  case CMDVRFY:         /* vrfy -- verify address */
                    379:                        if (runinchild("SMTP-VRFY") > 0)
                    380:                                break;
                    381:                        setproctitle("%s: %s", CurHostName, inp);
                    382:                        vrfyqueue = NULL;
                    383:                        QuickAbort = TRUE;
                    384:                        sendtolist(p, (ADDRESS *) NULL, &vrfyqueue);
                    385:                        if (Errors != 0)
                    386:                        {
                    387:                                if (InChild)
                    388:                                        finis();
                    389:                                break;
                    390:                        }
                    391:                        while (vrfyqueue != NULL)
                    392:                        {
                    393:                                register ADDRESS *a = vrfyqueue->q_next;
                    394:                                char *code;
                    395: 
                    396:                                while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags))
                    397:                                        a = a->q_next;
                    398: 
                    399:                                if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))
                    400:                                {
                    401:                                        if (a != NULL)
                    402:                                                code = "250-";
                    403:                                        else
                    404:                                                code = "250";
                    405:                                        if (vrfyqueue->q_fullname == NULL)
                    406:                                                message(code, "<%s>", vrfyqueue->q_paddr);
                    407:                                        else
                    408:                                                message(code, "%s <%s>",
                    409:                                                    vrfyqueue->q_fullname, vrfyqueue->q_paddr);
                    410:                                }
                    411:                                else if (a == NULL)
                    412:                                        message("554", "Self destructive alias loop");
                    413:                                vrfyqueue = a;
                    414:                        }
                    415:                        if (InChild)
                    416:                                finis();
                    417:                        break;
                    418: 
                    419:                  case CMDHELP:         /* help -- give user info */
                    420:                        if (*p == '\0')
                    421:                                p = "SMTP";
                    422:                        help(p);
                    423:                        break;
                    424: 
                    425:                  case CMDNOOP:         /* noop -- do nothing */
                    426:                        message("200", "OK");
                    427:                        break;
                    428: 
                    429:                  case CMDQUIT:         /* quit -- leave mail */
                    430:                        message("221", "%s closing connection", MyHostName);
                    431:                        if (InChild)
                    432:                                ExitStat = EX_QUIT;
                    433:                        finis();
                    434: 
                    435:                  case CMDVERB:         /* set verbose mode */
                    436:                        Verbose = TRUE;
                    437:                        SendMode = SM_DELIVER;
                    438:                        message("200", "Verbose mode");
                    439:                        break;
                    440: 
                    441:                  case CMDONEX:         /* doing one transaction only */
                    442:                        OneXact = TRUE;
                    443:                        message("200", "Only one transaction");
                    444:                        break;
                    445: 
                    446: # ifdef DEBUG
                    447:                  case CMDDBGQSHOW:     /* show queues */
                    448:                        printf("Send Queue=");
                    449:                        printaddr(CurEnv->e_sendqueue, TRUE);
                    450:                        break;
                    451: 
                    452:                  case CMDDBGDEBUG:     /* set debug mode */
                    453:                        tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
                    454:                        tTflag(p);
                    455:                        message("200", "Debug set");
                    456:                        break;
                    457: # endif DEBUG
                    458: 
                    459: # ifdef WIZ
                    460:                  case CMDDBGKILL:      /* kill the parent */
                    461:                        if (!iswiz())
                    462:                                break;
                    463:                        if (kill(MotherPid, SIGTERM) >= 0)
                    464:                                message("200", "Mother is dead");
                    465:                        else
                    466:                                message("500", "Can't kill Mom");
                    467:                        break;
                    468: 
                    469:                  case CMDDBGWIZ:       /* become a wizard */
                    470:                        if (WizWord != NULL)
                    471:                        {
                    472:                                char seed[3];
                    473:                                extern char *crypt();
                    474: 
                    475:                                (void) strncpy(seed, WizWord, 2);
                    476:                                if (strcmp(WizWord, crypt(p, seed)) == 0)
                    477:                                {
                    478:                                        IsWiz = TRUE;
                    479:                                        message("200", "Please pass, oh mighty wizard");
                    480:                                        break;
                    481:                                }
                    482:                        }
                    483:                        message("500", "You are no wizard!");
                    484:                        break;
                    485: 
                    486: # else WIZ
                    487:                  case CMDDBGWIZ:       /* try to become a wizard */
                    488:                        message("500", "You wascal wabbit!  Wandering wizards won't win!");
                    489:                        break;
                    490: # endif WIZ
                    491: 
                    492:                  case CMDERROR:        /* unknown command */
                    493:                        message("500", "Command unrecognized");
                    494:                        break;
                    495: 
                    496:                  default:
                    497:                        syserr("smtp: unknown code %d", c->cmdcode);
                    498:                        break;
                    499:                }
                    500:        }
                    501: }
                    502: /*
                    503: **  SKIPWORD -- skip a fixed word.
                    504: **
                    505: **     Parameters:
                    506: **             p -- place to start looking.
                    507: **             w -- word to skip.
                    508: **
                    509: **     Returns:
                    510: **             p following w.
                    511: **             NULL on error.
                    512: **
                    513: **     Side Effects:
                    514: **             clobbers the p data area.
                    515: */
                    516: 
                    517: static char *
                    518: skipword(p, w)
                    519:        register char *p;
                    520:        char *w;
                    521: {
                    522:        register char *q;
                    523: 
                    524:        /* find beginning of word */
                    525:        while (isspace(*p))
                    526:                p++;
                    527:        q = p;
                    528: 
                    529:        /* find end of word */
                    530:        while (*p != '\0' && *p != ':' && !isspace(*p))
                    531:                p++;
                    532:        while (isspace(*p))
                    533:                *p++ = '\0';
                    534:        if (*p != ':')
                    535:        {
                    536:          syntax:
                    537:                message("501", "Syntax error");
                    538:                Errors++;
                    539:                return (NULL);
                    540:        }
                    541:        *p++ = '\0';
                    542:        while (isspace(*p))
                    543:                p++;
                    544: 
                    545:        /* see if the input word matches desired word */
                    546:        if (strcasecmp(q, w))
                    547:                goto syntax;
                    548: 
                    549:        return (p);
                    550: }
                    551: /*
                    552: **  HELP -- implement the HELP command.
                    553: **
                    554: **     Parameters:
                    555: **             topic -- the topic we want help for.
                    556: **
                    557: **     Returns:
                    558: **             none.
                    559: **
                    560: **     Side Effects:
                    561: **             outputs the help file to message output.
                    562: */
                    563: 
                    564: help(topic)
                    565:        char *topic;
                    566: {
                    567:        register FILE *hf;
                    568:        int len;
                    569:        char buf[MAXLINE];
                    570:        bool noinfo;
                    571: 
                    572:        if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL)
                    573:        {
                    574:                /* no help */
                    575:                errno = 0;
                    576:                message("502", "HELP not implemented");
                    577:                return;
                    578:        }
                    579: 
                    580:        len = strlen(topic);
                    581:        makelower(topic);
                    582:        noinfo = TRUE;
                    583: 
                    584:        while (fgets(buf, sizeof buf, hf) != NULL)
                    585:        {
                    586:                if (strncmp(buf, topic, len) == 0)
                    587:                {
                    588:                        register char *p;
                    589: 
                    590:                        p = index(buf, '\t');
                    591:                        if (p == NULL)
                    592:                                p = buf;
                    593:                        else
                    594:                                p++;
                    595:                        fixcrlf(p, TRUE);
                    596:                        message("214-", p);
                    597:                        noinfo = FALSE;
                    598:                }
                    599:        }
                    600: 
                    601:        if (noinfo)
                    602:                message("504", "HELP topic unknown");
                    603:        else
                    604:                message("214", "End of HELP info");
                    605:        (void) fclose(hf);
                    606: }
                    607: /*
                    608: **  ISWIZ -- tell us if we are a wizard
                    609: **
                    610: **     If not, print a nasty message.
                    611: **
                    612: **     Parameters:
                    613: **             none.
                    614: **
                    615: **     Returns:
                    616: **             TRUE if we are a wizard.
                    617: **             FALSE if we are not a wizard.
                    618: **
                    619: **     Side Effects:
                    620: **             Prints a 500 exit stat if we are not a wizard.
                    621: */
                    622: 
                    623: #ifdef WIZ
                    624: 
                    625: bool
                    626: iswiz()
                    627: {
                    628:        if (!IsWiz)
                    629:                message("500", "Mere mortals musn't mutter that mantra");
                    630:        return (IsWiz);
                    631: }
                    632: 
                    633: #endif WIZ
                    634: /*
                    635: **  RUNINCHILD -- return twice -- once in the child, then in the parent again
                    636: **
                    637: **     Parameters:
                    638: **             label -- a string used in error messages
                    639: **
                    640: **     Returns:
                    641: **             zero in the child
                    642: **             one in the parent
                    643: **
                    644: **     Side Effects:
                    645: **             none.
                    646: */
                    647: 
                    648: runinchild(label)
                    649:        char *label;
                    650: {
                    651:        int childpid;
                    652: 
                    653:        if (!OneXact)
                    654:        {
                    655:                childpid = dofork();
                    656:                if (childpid < 0)
                    657:                {
                    658:                        syserr("%s: cannot fork", label);
                    659:                        return (1);
                    660:                }
                    661:                if (childpid > 0)
                    662:                {
                    663:                        auto int st;
                    664: 
                    665:                        /* parent -- wait for child to complete */
                    666:                        st = waitfor(childpid);
                    667:                        if (st == -1)
                    668:                                syserr("%s: lost child", label);
                    669: 
                    670:                        /* if we exited on a QUIT command, complete the process */
                    671:                        if (st == (EX_QUIT << 8))
                    672:                                finis();
                    673: 
                    674:                        return (1);
                    675:                }
                    676:                else
                    677:                {
                    678:                        /* child */
                    679:                        InChild = TRUE;
                    680:                        QuickAbort = FALSE;
                    681:                        clearenvelope(CurEnv, FALSE);
                    682:                }
                    683:        }
                    684: 
                    685:        /* open alias database */
                    686:        initaliases(AliasFile, FALSE);
                    687: 
                    688:        return (0);
                    689: }
                    690: 
                    691: # endif SMTP

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.