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

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

unix.superglobalmegacorp.com

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