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

unix.superglobalmegacorp.com

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