Annotation of 43BSD/usr.lib/sendmail/src/main.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: #ifndef lint
                     12: char copyright[] =
                     13: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
                     14:  All rights reserved.\n";
                     15: #endif not lint
                     16: 
                     17: #ifndef lint
                     18: static char    SccsId[] = "@(#)main.c  5.11 (Berkeley) 1/30/86";
                     19: #endif not lint
                     20: 
                     21: # define  _DEFINE
                     22: # include <signal.h>
                     23: # include <sgtty.h>
                     24: # include "sendmail.h"
                     25: 
                     26: # ifdef lint
                     27: char   edata, end;
                     28: # endif lint
                     29: 
                     30: /*
                     31: **  SENDMAIL -- Post mail to a set of destinations.
                     32: **
                     33: **     This is the basic mail router.  All user mail programs should
                     34: **     call this routine to actually deliver mail.  Sendmail in
                     35: **     turn calls a bunch of mail servers that do the real work of
                     36: **     delivering the mail.
                     37: **
                     38: **     Sendmail is driven by tables read in from /usr/lib/sendmail.cf
                     39: **     (read by readcf.c).  Some more static configuration info,
                     40: **     including some code that you may want to tailor for your
                     41: **     installation, is in conf.c.  You may also want to touch
                     42: **     daemon.c (if you have some other IPC mechanism), acct.c
                     43: **     (to change your accounting), names.c (to adjust the name
                     44: **     server mechanism).
                     45: **
                     46: **     Usage:
                     47: **             /usr/lib/sendmail [flags] addr ...
                     48: **
                     49: **             See the associated documentation for details.
                     50: **
                     51: **     Author:
                     52: **             Eric Allman, UCB/INGRES (until 10/81)
                     53: **                          Britton-Lee, Inc., purveyors of fine
                     54: **                             database computers (from 11/81)
                     55: **             The support of the INGRES Project and Britton-Lee is
                     56: **                     gratefully acknowledged.  Britton-Lee in
                     57: **                     particular had absolutely nothing to gain from
                     58: **                     my involvement in this project.
                     59: */
                     60: 
                     61: 
                     62: 
                     63: 
                     64: 
                     65: int            NextMailer;     /* "free" index into Mailer struct */
                     66: char           *FullName;      /* sender's full name */
                     67: ENVELOPE       BlankEnvelope;  /* a "blank" envelope */
                     68: ENVELOPE       MainEnvelope;   /* the envelope around the basic letter */
                     69: ADDRESS                NullAddress =   /* a null address */
                     70:                { "", "", "" };
                     71: 
                     72: /*
                     73: **  Pointers for setproctitle.
                     74: **     This allows "ps" listings to give more useful information.
                     75: **     These must be kept out of BSS for frozen configuration files
                     76: **             to work.
                     77: */
                     78: 
                     79: # ifdef SETPROCTITLE
                     80: char           **Argv = NULL;          /* pointer to argument vector */
                     81: char           *LastArgv = NULL;       /* end of argv */
                     82: # endif SETPROCTITLE
                     83: 
                     84: #ifdef DAEMON
                     85: #ifndef SMTP
                     86: ERROR %%%%   Cannot have daemon mode without SMTP   %%%% ERROR
                     87: #endif SMTP
                     88: #endif DAEMON
                     89: 
                     90: 
                     91: 
                     92: 
                     93: 
                     94: 
                     95: main(argc, argv, envp)
                     96:        int argc;
                     97:        char **argv;
                     98:        char **envp;
                     99: {
                    100:        register char *p;
                    101:        char **av;
                    102:        extern int finis();
                    103:        extern char Version[];
                    104:        char *from;
                    105:        typedef int (*fnptr)();
                    106:        STAB *st;
                    107:        register int i;
                    108:        bool readconfig = TRUE;
                    109:        bool queuemode = FALSE;         /* process queue requests */
                    110:        bool nothaw;
                    111:        static bool reenter = FALSE;
                    112:        char jbuf[30];                  /* holds MyHostName */
                    113:        extern bool safefile();
                    114:        extern time_t convtime();
                    115:        extern putheader(), putbody();
                    116:        extern ENVELOPE *newenvelope();
                    117:        extern intsig();
                    118:        extern char **myhostname();
                    119:        extern char *arpadate();
                    120:        extern char **environ;
                    121: 
                    122:        /*
                    123:        **  Check to see if we reentered.
                    124:        **      This would normally happen if e_putheader or e_putbody
                    125:        **      were NULL when invoked.
                    126:        */
                    127: 
                    128:        if (reenter)
                    129:        {
                    130:                syserr("main: reentered!");
                    131:                abort();
                    132:        }
                    133:        reenter = TRUE;
                    134: 
                    135:        /*
                    136:        **  Be sure we have enough file descriptors.
                    137:        */
                    138: 
                    139:        for (i = 3; i < 50; i++)
                    140:                (void) close(i);
                    141:        errno = 0;
                    142: 
                    143:        /*
                    144:        **  Set default values for variables.
                    145:        **      These cannot be in initialized data space.
                    146:        */
                    147: 
                    148:        setdefaults();
                    149: 
                    150:        /* set up the blank envelope */
                    151:        BlankEnvelope.e_puthdr = putheader;
                    152:        BlankEnvelope.e_putbody = putbody;
                    153:        BlankEnvelope.e_xfp = NULL;
                    154:        STRUCTCOPY(NullAddress, BlankEnvelope.e_from);
                    155:        CurEnv = &BlankEnvelope;
                    156:        STRUCTCOPY(NullAddress, MainEnvelope.e_from);
                    157: 
                    158:        /*
                    159:        **  Do a quick prescan of the argument list.
                    160:        **      We do this to find out if we can potentially thaw the
                    161:        **      configuration file.  If not, we do the thaw now so that
                    162:        **      the argument processing applies to this run rather than
                    163:        **      to the run that froze the configuration.
                    164:        */
                    165: 
                    166:        argv[argc] = NULL;
                    167:        av = argv;
                    168:        nothaw = FALSE;
                    169:        while ((p = *++av) != NULL)
                    170:        {
                    171:                if (strncmp(p, "-C", 2) == 0)
                    172:                {
                    173:                        ConfFile = &p[2];
                    174:                        if (ConfFile[0] == '\0')
                    175:                                ConfFile = "sendmail.cf";
                    176:                        (void) setgid(getrgid());
                    177:                        (void) setuid(getruid());
                    178:                        nothaw = TRUE;
                    179:                }
                    180:                else if (strncmp(p, "-bz", 3) == 0)
                    181:                        nothaw = TRUE;
                    182: # ifdef DEBUG
                    183:                else if (strncmp(p, "-d", 2) == 0)
                    184:                {
                    185:                        tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
                    186:                        tTflag(&p[2]);
                    187:                        setbuf(stdout, (char *) NULL);
                    188:                        printf("Version %s\n", Version);
                    189:                }
                    190: # endif DEBUG
                    191:        }
                    192:        if (!nothaw)
                    193:                readconfig = !thaw(FreezeFile);
                    194: 
                    195:        /* reset the environment after the thaw */
                    196:        for (i = 0; i < MAXUSERENVIRON && envp[i] != NULL; i++)
                    197:                UserEnviron[i] = newstr(envp[i]);
                    198:        UserEnviron[i] = NULL;
                    199:        environ = UserEnviron;
                    200: 
                    201: # ifdef SETPROCTITLE
                    202:        /*
                    203:        **  Save start and extent of argv for setproctitle.
                    204:        */
                    205: 
                    206:        Argv = argv;
                    207:        if (i > 0)
                    208:                LastArgv = envp[i - 1] + strlen(envp[i - 1]);
                    209:        else
                    210:                LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
                    211: # endif SETPROCTITLE
                    212: 
                    213:        /*
                    214:        **  Now do basic initialization
                    215:        */
                    216: 
                    217:        InChannel = stdin;
                    218:        OutChannel = stdout;
                    219:        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                    220:                (void) signal(SIGINT, intsig);
                    221:        if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
                    222:                (void) signal(SIGHUP, intsig);
                    223:        (void) signal(SIGTERM, intsig);
                    224:        (void) signal(SIGPIPE, SIG_IGN);
                    225:        OldUmask = umask(0);
                    226:        OpMode = MD_DELIVER;
                    227:        MotherPid = getpid();
                    228: # ifndef V6
                    229:        FullName = getenv("NAME");
                    230: # endif V6
                    231: 
                    232: # ifdef LOG
                    233:        openlog("sendmail", LOG_PID, LOG_MAIL);
                    234: # endif LOG
                    235:        errno = 0;
                    236:        from = NULL;
                    237: 
                    238:        if (readconfig)
                    239:        {
                    240:                /* initialize some macros, etc. */
                    241:                initmacros();
                    242: 
                    243:                /* hostname */
                    244:                av = myhostname(jbuf, sizeof jbuf);
                    245:                if (jbuf[0] != '\0')
                    246:                {
                    247: #ifdef DEBUG
                    248:                        if (tTd(0, 4))
                    249:                                printf("canonical name: %s\n", jbuf);
                    250: #endif DEBUG
                    251:                        p = newstr(jbuf);
                    252:                        define('w', p, CurEnv);
                    253:                        setclass('w', p);
                    254:                }
                    255:                while (av != NULL && *av != NULL)
                    256:                {
                    257: #ifdef DEBUG
                    258:                        if (tTd(0, 4))
                    259:                                printf("\ta.k.a.: %s\n", *av);
                    260: #endif DEBUG
                    261:                        setclass('w', *av++);
                    262:                }
                    263: 
                    264:                /* version */
                    265:                define('v', Version, CurEnv);
                    266:        }
                    267: 
                    268:        /* current time */
                    269:        define('b', arpadate((char *) NULL), CurEnv);
                    270: 
                    271:        /*
                    272:        ** Crack argv.
                    273:        */
                    274: 
                    275:        av = argv;
                    276:        p = rindex(*av, '/');
                    277:        if (p++ == NULL)
                    278:                p = *av;
                    279:        if (strcmp(p, "newaliases") == 0)
                    280:                OpMode = MD_INITALIAS;
                    281:        else if (strcmp(p, "mailq") == 0)
                    282:                OpMode = MD_PRINT;
                    283:        else if (strcmp(p, "smtpd") == 0)
                    284:                OpMode = MD_DAEMON;
                    285:        while ((p = *++av) != NULL && p[0] == '-')
                    286:        {
                    287:                switch (p[1])
                    288:                {
                    289:                  case 'b':     /* operations mode */
                    290:                        switch (p[2])
                    291:                        {
                    292:                          case MD_DAEMON:
                    293: # ifndef DAEMON
                    294:                                syserr("Daemon mode not implemented");
                    295:                                break;
                    296: # endif DAEMON
                    297:                          case MD_SMTP:
                    298: # ifndef SMTP
                    299:                                syserr("I don't speak SMTP");
                    300:                                break;
                    301: # endif SMTP
                    302:                          case MD_ARPAFTP:
                    303:                          case MD_DELIVER:
                    304:                          case MD_VERIFY:
                    305:                          case MD_TEST:
                    306:                          case MD_INITALIAS:
                    307:                          case MD_PRINT:
                    308:                          case MD_FREEZE:
                    309:                                OpMode = p[2];
                    310:                                break;
                    311: 
                    312:                          default:
                    313:                                syserr("Invalid operation mode %c", p[2]);
                    314:                                break;
                    315:                        }
                    316:                        break;
                    317: 
                    318:                  case 'C':     /* select configuration file (already done) */
                    319:                        break;
                    320: 
                    321: # ifdef DEBUG
                    322:                  case 'd':     /* debugging -- redo in case frozen */
                    323:                        tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
                    324:                        tTflag(&p[2]);
                    325:                        setbuf(stdout, (char *) NULL);
                    326:                        break;
                    327: # endif DEBUG
                    328: 
                    329:                  case 'f':     /* from address */
                    330:                  case 'r':     /* obsolete -f flag */
                    331:                        p += 2;
                    332:                        if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
                    333:                        {
                    334:                                p = *++av;
                    335:                                if (p == NULL || *p == '-')
                    336:                                {
                    337:                                        syserr("No \"from\" person");
                    338:                                        av--;
                    339:                                        break;
                    340:                                }
                    341:                        }
                    342:                        if (from != NULL)
                    343:                        {
                    344:                                syserr("More than one \"from\" person");
                    345:                                break;
                    346:                        }
                    347:                        from = newstr(p);
                    348:                        break;
                    349: 
                    350:                  case 'F':     /* set full name */
                    351:                        p += 2;
                    352:                        if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
                    353:                        {
                    354:                                syserr("Bad -F flag");
                    355:                                av--;
                    356:                                break;
                    357:                        }
                    358:                        FullName = newstr(p);
                    359:                        break;
                    360: 
                    361:                  case 'h':     /* hop count */
                    362:                        p += 2;
                    363:                        if (*p == '\0' && ((p = *++av) == NULL || !isdigit(*p)))
                    364:                        {
                    365:                                syserr("Bad hop count (%s)", p);
                    366:                                av--;
                    367:                                break;
                    368:                        }
                    369:                        CurEnv->e_hopcount = atoi(p);
                    370:                        break;
                    371:                
                    372:                  case 'n':     /* don't alias */
                    373:                        NoAlias = TRUE;
                    374:                        break;
                    375: 
                    376:                  case 'o':     /* set option */
                    377:                        setoption(p[2], &p[3], FALSE, TRUE);
                    378:                        break;
                    379: 
                    380:                  case 'q':     /* run queue files at intervals */
                    381: # ifdef QUEUE
                    382:                        queuemode = TRUE;
                    383:                        QueueIntvl = convtime(&p[2]);
                    384: # else QUEUE
                    385:                        syserr("I don't know about queues");
                    386: # endif QUEUE
                    387:                        break;
                    388: 
                    389:                  case 't':     /* read recipients from message */
                    390:                        GrabTo = TRUE;
                    391:                        break;
                    392: 
                    393:                        /* compatibility flags */
                    394:                  case 'c':     /* connect to non-local mailers */
                    395:                  case 'e':     /* error message disposition */
                    396:                  case 'i':     /* don't let dot stop me */
                    397:                  case 'm':     /* send to me too */
                    398:                  case 'T':     /* set timeout interval */
                    399:                  case 'v':     /* give blow-by-blow description */
                    400:                        setoption(p[1], &p[2], FALSE, TRUE);
                    401:                        break;
                    402: 
                    403:                  case 's':     /* save From lines in headers */
                    404:                        setoption('f', &p[2], FALSE, TRUE);
                    405:                        break;
                    406: 
                    407: # ifdef DBM
                    408:                  case 'I':     /* initialize alias DBM file */
                    409:                        OpMode = MD_INITALIAS;
                    410:                        break;
                    411: # endif DBM
                    412:                }
                    413:        }
                    414: 
                    415:        /*
                    416:        **  Do basic initialization.
                    417:        **      Read system control file.
                    418:        **      Extract special fields for local use.
                    419:        */
                    420: 
                    421:        if (OpMode == MD_FREEZE || readconfig)
                    422:                readcf(ConfFile);
                    423: 
                    424:        switch (OpMode)
                    425:        {
                    426:          case MD_FREEZE:
                    427:                /* this is critical to avoid forgeries of the frozen config */
                    428:                (void) setgid(getgid());
                    429:                (void) setuid(getuid());
                    430: 
                    431:                /* freeze the configuration */
                    432:                freeze(FreezeFile);
                    433:                exit(EX_OK);
                    434: 
                    435:          case MD_INITALIAS:
                    436:                Verbose = TRUE;
                    437:                break;
                    438:        }
                    439: 
                    440:        /* do heuristic mode adjustment */
                    441:        if (Verbose)
                    442:        {
                    443:                /* turn off noconnect option */
                    444:                setoption('c', "F", TRUE, FALSE);
                    445: 
                    446:                /* turn on interactive delivery */
                    447:                setoption('d', "", TRUE, FALSE);
                    448:        }
                    449: 
                    450:        /* our name for SMTP codes */
                    451:        expand("\001j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv);
                    452:        MyHostName = jbuf;
                    453: 
                    454:        /* the indices of local and program mailers */
                    455:        st = stab("local", ST_MAILER, ST_FIND);
                    456:        if (st == NULL)
                    457:                syserr("No local mailer defined");
                    458:        else
                    459:                LocalMailer = st->s_mailer;
                    460:        st = stab("prog", ST_MAILER, ST_FIND);
                    461:        if (st == NULL)
                    462:                syserr("No prog mailer defined");
                    463:        else
                    464:                ProgMailer = st->s_mailer;
                    465: 
                    466:        /* operate in queue directory */
                    467:        if (chdir(QueueDir) < 0)
                    468:        {
                    469:                syserr("cannot chdir(%s)", QueueDir);
                    470:                exit(EX_SOFTWARE);
                    471:        }
                    472: 
                    473:        /*
                    474:        **  Do operation-mode-dependent initialization.
                    475:        */
                    476: 
                    477:        switch (OpMode)
                    478:        {
                    479:          case MD_PRINT:
                    480:                /* print the queue */
                    481: #ifdef QUEUE
                    482:                dropenvelope(CurEnv);
                    483:                printqueue();
                    484:                exit(EX_OK);
                    485: #else QUEUE
                    486:                usrerr("No queue to print");
                    487:                finis();
                    488: #endif QUEUE
                    489: 
                    490:          case MD_INITALIAS:
                    491:                /* initialize alias database */
                    492:                initaliases(AliasFile, TRUE);
                    493:                exit(EX_OK);
                    494: 
                    495:          case MD_DAEMON:
                    496:                /* don't open alias database -- done in srvrsmtp */
                    497:                break;
                    498: 
                    499:          default:
                    500:                /* open the alias database */
                    501:                initaliases(AliasFile, FALSE);
                    502:                break;
                    503:        }
                    504: 
                    505: # ifdef DEBUG
                    506:        if (tTd(0, 15))
                    507:        {
                    508:                /* print configuration table (or at least part of it) */
                    509:                printrules();
                    510:                for (i = 0; i < MAXMAILERS; i++)
                    511:                {
                    512:                        register struct mailer *m = Mailer[i];
                    513:                        int j;
                    514: 
                    515:                        if (m == NULL)
                    516:                                continue;
                    517:                        printf("mailer %d (%s): P=%s S=%d R=%d M=%ld F=", i, m->m_name,
                    518:                                m->m_mailer, m->m_s_rwset, m->m_r_rwset,
                    519:                                m->m_maxsize);
                    520:                        for (j = '\0'; j <= '\177'; j++)
                    521:                                if (bitnset(j, m->m_flags))
                    522:                                        (void) putchar(j);
                    523:                        printf(" E=");
                    524:                        xputs(m->m_eol);
                    525:                        printf("\n");
                    526:                }
                    527:        }
                    528: # endif DEBUG
                    529: 
                    530:        /*
                    531:        **  Switch to the main envelope.
                    532:        */
                    533: 
                    534:        CurEnv = newenvelope(&MainEnvelope);
                    535:        MainEnvelope.e_flags = BlankEnvelope.e_flags;
                    536: 
                    537:        /*
                    538:        **  If test mode, read addresses from stdin and process.
                    539:        */
                    540: 
                    541:        if (OpMode == MD_TEST)
                    542:        {
                    543:                char buf[MAXLINE];
                    544: 
                    545:                printf("ADDRESS TEST MODE\nEnter <ruleset> <address>\n");
                    546:                for (;;)
                    547:                {
                    548:                        register char **pvp;
                    549:                        char *q;
                    550:                        extern char *DelimChar;
                    551: 
                    552:                        printf("> ");
                    553:                        (void) fflush(stdout);
                    554:                        if (fgets(buf, sizeof buf, stdin) == NULL)
                    555:                                finis();
                    556:                        for (p = buf; isspace(*p); *p++)
                    557:                                continue;
                    558:                        q = p;
                    559:                        while (*p != '\0' && !isspace(*p))
                    560:                                p++;
                    561:                        if (*p == '\0')
                    562:                                continue;
                    563:                        *p = '\0';
                    564:                        do
                    565:                        {
                    566:                                extern char **prescan();
                    567:                                char pvpbuf[PSBUFSIZE];
                    568: 
                    569:                                pvp = prescan(++p, ',', pvpbuf);
                    570:                                if (pvp == NULL)
                    571:                                        continue;
                    572:                                rewrite(pvp, 3);
                    573:                                p = q;
                    574:                                while (*p != '\0')
                    575:                                {
                    576:                                        rewrite(pvp, atoi(p));
                    577:                                        while (*p != '\0' && *p++ != ',')
                    578:                                                continue;
                    579:                                }
                    580:                        } while (*(p = DelimChar) != '\0');
                    581:                }
                    582:        }
                    583: 
                    584: # ifdef QUEUE
                    585:        /*
                    586:        **  If collecting stuff from the queue, go start doing that.
                    587:        */
                    588: 
                    589:        if (queuemode && OpMode != MD_DAEMON && QueueIntvl == 0)
                    590:        {
                    591:                runqueue(FALSE);
                    592:                finis();
                    593:        }
                    594: # endif QUEUE
                    595: 
                    596:        /*
                    597:        **  If a daemon, wait for a request.
                    598:        **      getrequests will always return in a child.
                    599:        **      If we should also be processing the queue, start
                    600:        **              doing it in background.
                    601:        **      We check for any errors that might have happened
                    602:        **              during startup.
                    603:        */
                    604: 
                    605:        if (OpMode == MD_DAEMON || QueueIntvl != 0)
                    606:        {
                    607:                if (!tTd(0, 1))
                    608:                {
                    609:                        /* put us in background */
                    610:                        i = fork();
                    611:                        if (i < 0)
                    612:                                syserr("daemon: cannot fork");
                    613:                        if (i != 0)
                    614:                                exit(0);
                    615: 
                    616:                        /* get our pid right */
                    617:                        MotherPid = getpid();
                    618: 
                    619:                        /* disconnect from our controlling tty */
                    620:                        disconnect(TRUE);
                    621:                }
                    622: 
                    623: # ifdef QUEUE
                    624:                if (queuemode)
                    625:                {
                    626:                        runqueue(TRUE);
                    627:                        if (OpMode != MD_DAEMON)
                    628:                                for (;;)
                    629:                                        pause();
                    630:                }
                    631: # endif QUEUE
                    632:                dropenvelope(CurEnv);
                    633: 
                    634: #ifdef DAEMON
                    635:                getrequests();
                    636: 
                    637:                /* at this point we are in a child: reset state */
                    638:                OpMode = MD_SMTP;
                    639:                (void) newenvelope(CurEnv);
                    640:                openxscript(CurEnv);
                    641: #endif DAEMON
                    642:        }
                    643:        
                    644: # ifdef SMTP
                    645:        /*
                    646:        **  If running SMTP protocol, start collecting and executing
                    647:        **  commands.  This will never return.
                    648:        */
                    649: 
                    650:        if (OpMode == MD_SMTP)
                    651:                smtp();
                    652: # endif SMTP
                    653: 
                    654:        /*
                    655:        **  Do basic system initialization and set the sender
                    656:        */
                    657: 
                    658:        initsys();
                    659:        setsender(from);
                    660: 
                    661:        if (OpMode != MD_ARPAFTP && *av == NULL && !GrabTo)
                    662:        {
                    663:                usrerr("Recipient names must be specified");
                    664: 
                    665:                /* collect body for UUCP return */
                    666:                if (OpMode != MD_VERIFY)
                    667:                        collect(FALSE);
                    668:                finis();
                    669:        }
                    670:        if (OpMode == MD_VERIFY)
                    671:                SendMode = SM_VERIFY;
                    672: 
                    673:        /*
                    674:        **  Scan argv and deliver the message to everyone.
                    675:        */
                    676: 
                    677:        sendtoargv(av);
                    678: 
                    679:        /* if we have had errors sofar, arrange a meaningful exit stat */
                    680:        if (Errors > 0 && ExitStat == EX_OK)
                    681:                ExitStat = EX_USAGE;
                    682: 
                    683:        /*
                    684:        **  Read the input mail.
                    685:        */
                    686: 
                    687:        CurEnv->e_to = NULL;
                    688:        if (OpMode != MD_VERIFY || GrabTo)
                    689:                collect(FALSE);
                    690:        errno = 0;
                    691: 
                    692:        /* collect statistics */
                    693:        if (OpMode != MD_VERIFY)
                    694:                markstats(CurEnv, (ADDRESS *) NULL);
                    695: 
                    696: # ifdef DEBUG
                    697:        if (tTd(1, 1))
                    698:                printf("From person = \"%s\"\n", CurEnv->e_from.q_paddr);
                    699: # endif DEBUG
                    700: 
                    701:        /*
                    702:        **  Actually send everything.
                    703:        **      If verifying, just ack.
                    704:        */
                    705: 
                    706:        CurEnv->e_from.q_flags |= QDONTSEND;
                    707:        CurEnv->e_to = NULL;
                    708:        sendall(CurEnv, SM_DEFAULT);
                    709: 
                    710:        /*
                    711:        ** All done.
                    712:        */
                    713: 
                    714:        finis();
                    715: }
                    716: /*
                    717: **  FINIS -- Clean up and exit.
                    718: **
                    719: **     Parameters:
                    720: **             none
                    721: **
                    722: **     Returns:
                    723: **             never
                    724: **
                    725: **     Side Effects:
                    726: **             exits sendmail
                    727: */
                    728: 
                    729: finis()
                    730: {
                    731: # ifdef DEBUG
                    732:        if (tTd(2, 1))
                    733:                printf("\n====finis: stat %d e_flags %o\n", ExitStat, CurEnv->e_flags);
                    734: # endif DEBUG
                    735: 
                    736:        /* clean up temp files */
                    737:        CurEnv->e_to = NULL;
                    738:        dropenvelope(CurEnv);
                    739: 
                    740:        /* post statistics */
                    741:        poststats(StatFile);
                    742: 
                    743:        /* and exit */
                    744: # ifdef LOG
                    745:        if (LogLevel > 11)
                    746:                syslog(LOG_DEBUG, "finis, pid=%d", getpid());
                    747: # endif LOG
                    748:        if (ExitStat == EX_TEMPFAIL)
                    749:                ExitStat = EX_OK;
                    750:        exit(ExitStat);
                    751: }
                    752: /*
                    753: **  INTSIG -- clean up on interrupt
                    754: **
                    755: **     This just arranges to exit.  It pessimises in that it
                    756: **     may resend a message.
                    757: **
                    758: **     Parameters:
                    759: **             none.
                    760: **
                    761: **     Returns:
                    762: **             none.
                    763: **
                    764: **     Side Effects:
                    765: **             Unlocks the current job.
                    766: */
                    767: 
                    768: intsig()
                    769: {
                    770:        FileName = NULL;
                    771:        unlockqueue(CurEnv);
                    772:        exit(EX_OK);
                    773: }
                    774: /*
                    775: **  INITMACROS -- initialize the macro system
                    776: **
                    777: **     This just involves defining some macros that are actually
                    778: **     used internally as metasymbols to be themselves.
                    779: **
                    780: **     Parameters:
                    781: **             none.
                    782: **
                    783: **     Returns:
                    784: **             none.
                    785: **
                    786: **     Side Effects:
                    787: **             initializes several macros to be themselves.
                    788: */
                    789: 
                    790: struct metamac
                    791: {
                    792:        char    metaname;
                    793:        char    metaval;
                    794: };
                    795: 
                    796: struct metamac MetaMacros[] =
                    797: {
                    798:        /* LHS pattern matching characters */
                    799:        '*', MATCHZANY, '+', MATCHANY,  '-', MATCHONE,  '=', MATCHCLASS,
                    800:        '~', MATCHNCLASS,
                    801: 
                    802:        /* these are RHS metasymbols */
                    803:        '#', CANONNET,  '@', CANONHOST, ':', CANONUSER, '>', CALLSUBR,
                    804: 
                    805:        /* the conditional operations */
                    806:        '?', CONDIF,    '|', CONDELSE,  '.', CONDFI,
                    807: 
                    808:        /* and finally the hostname lookup characters */
                    809:        '[', HOSTBEGIN, ']', HOSTEND,
                    810: 
                    811:        '\0'
                    812: };
                    813: 
                    814: initmacros()
                    815: {
                    816:        register struct metamac *m;
                    817:        char buf[5];
                    818:        register int c;
                    819: 
                    820:        for (m = MetaMacros; m->metaname != '\0'; m++)
                    821:        {
                    822:                buf[0] = m->metaval;
                    823:                buf[1] = '\0';
                    824:                define(m->metaname, newstr(buf), CurEnv);
                    825:        }
                    826:        buf[0] = MATCHREPL;
                    827:        buf[2] = '\0';
                    828:        for (c = '0'; c <= '9'; c++)
                    829:        {
                    830:                buf[1] = c;
                    831:                define(c, newstr(buf), CurEnv);
                    832:        }
                    833: }
                    834: /*
                    835: **  FREEZE -- freeze BSS & allocated memory
                    836: **
                    837: **     This will be used to efficiently load the configuration file.
                    838: **
                    839: **     Parameters:
                    840: **             freezefile -- the name of the file to freeze to.
                    841: **
                    842: **     Returns:
                    843: **             none.
                    844: **
                    845: **     Side Effects:
                    846: **             Writes BSS and malloc'ed memory to freezefile
                    847: */
                    848: 
                    849: union frz
                    850: {
                    851:        char            frzpad[BUFSIZ]; /* insure we are on a BUFSIZ boundary */
                    852:        struct
                    853:        {
                    854:                time_t  frzstamp;       /* timestamp on this freeze */
                    855:                char    *frzbrk;        /* the current break */
                    856:                char    *frzedata;      /* address of edata */
                    857:                char    *frzend;        /* address of end */
                    858:                char    frzver[252];    /* sendmail version */
                    859:        } frzinfo;
                    860: };
                    861: 
                    862: freeze(freezefile)
                    863:        char *freezefile;
                    864: {
                    865:        int f;
                    866:        union frz fhdr;
                    867:        extern char edata, end;
                    868:        extern char *sbrk();
                    869:        extern char Version[];
                    870: 
                    871:        if (freezefile == NULL)
                    872:                return;
                    873: 
                    874:        /* try to open the freeze file */
                    875:        f = creat(freezefile, FileMode);
                    876:        if (f < 0)
                    877:        {
                    878:                syserr("Cannot freeze");
                    879:                errno = 0;
                    880:                return;
                    881:        }
                    882: 
                    883:        /* build the freeze header */
                    884:        fhdr.frzinfo.frzstamp = curtime();
                    885:        fhdr.frzinfo.frzbrk = sbrk(0);
                    886:        fhdr.frzinfo.frzedata = &edata;
                    887:        fhdr.frzinfo.frzend = &end;
                    888:        (void) strcpy(fhdr.frzinfo.frzver, Version);
                    889: 
                    890:        /* write out the freeze header */
                    891:        if (write(f, (char *) &fhdr, sizeof fhdr) != sizeof fhdr ||
                    892:            write(f, (char *) &edata, (int) (fhdr.frzinfo.frzbrk - &edata)) !=
                    893:                                        (int) (fhdr.frzinfo.frzbrk - &edata))
                    894:        {
                    895:                syserr("Cannot freeze");
                    896:        }
                    897: 
                    898:        /* fine, clean up */
                    899:        (void) close(f);
                    900: }
                    901: /*
                    902: **  THAW -- read in the frozen configuration file.
                    903: **
                    904: **     Parameters:
                    905: **             freezefile -- the name of the file to thaw from.
                    906: **
                    907: **     Returns:
                    908: **             TRUE if it successfully read the freeze file.
                    909: **             FALSE otherwise.
                    910: **
                    911: **     Side Effects:
                    912: **             reads freezefile in to BSS area.
                    913: */
                    914: 
                    915: thaw(freezefile)
                    916:        char *freezefile;
                    917: {
                    918:        int f;
                    919:        union frz fhdr;
                    920:        extern char edata;
                    921:        extern char Version[];
                    922:        extern caddr_t brk();
                    923: 
                    924:        if (freezefile == NULL)
                    925:                return (FALSE);
                    926: 
                    927:        /* open the freeze file */
                    928:        f = open(freezefile, 0);
                    929:        if (f < 0)
                    930:        {
                    931:                errno = 0;
                    932:                return (FALSE);
                    933:        }
                    934: 
                    935:        /* read in the header */
                    936:        if (read(f, (char *) &fhdr, sizeof fhdr) < sizeof fhdr ||
                    937:            fhdr.frzinfo.frzedata != &edata ||
                    938:            fhdr.frzinfo.frzend != &end ||
                    939:            strcmp(fhdr.frzinfo.frzver, Version) != 0)
                    940:        {
                    941:                (void) close(f);
                    942:                return (FALSE);
                    943:        }
                    944: 
                    945:        /* arrange to have enough space */
                    946:        if (brk(fhdr.frzinfo.frzbrk) == (caddr_t) -1)
                    947:        {
                    948:                syserr("Cannot break to %x", fhdr.frzinfo.frzbrk);
                    949:                (void) close(f);
                    950:                return (FALSE);
                    951:        }
                    952: 
                    953:        /* now read in the freeze file */
                    954:        if (read(f, (char *) &edata, (int) (fhdr.frzinfo.frzbrk - &edata)) !=
                    955:                                        (int) (fhdr.frzinfo.frzbrk - &edata))
                    956:        {
                    957:                /* oops!  we have trashed memory..... */
                    958:                (void) write(2, "Cannot read freeze file\n", 24);
                    959:                _exit(EX_SOFTWARE);
                    960:        }
                    961: 
                    962:        (void) close(f);
                    963:        return (TRUE);
                    964: }
                    965: /*
                    966: **  DISCONNECT -- remove our connection with any foreground process
                    967: **
                    968: **     Parameters:
                    969: **             fulldrop -- if set, we should also drop the controlling
                    970: **                     TTY if possible -- this should only be done when
                    971: **                     setting up the daemon since otherwise UUCP can
                    972: **                     leave us trying to open a dialin, and we will
                    973: **                     wait for the carrier.
                    974: **
                    975: **     Returns:
                    976: **             none
                    977: **
                    978: **     Side Effects:
                    979: **             Trys to insure that we are immune to vagaries of
                    980: **             the controlling tty.
                    981: */
                    982: 
                    983: disconnect(fulldrop)
                    984:        bool fulldrop;
                    985: {
                    986:        int fd;
                    987: 
                    988: #ifdef DEBUG
                    989:        if (tTd(52, 1))
                    990:                printf("disconnect: In %d Out %d\n", fileno(InChannel),
                    991:                                                fileno(OutChannel));
                    992:        if (tTd(52, 5))
                    993:        {
                    994:                printf("don't\n");
                    995:                return;
                    996:        }
                    997: #endif DEBUG
                    998: 
                    999:        /* be sure we don't get nasty signals */
                   1000:        (void) signal(SIGHUP, SIG_IGN);
                   1001:        (void) signal(SIGINT, SIG_IGN);
                   1002:        (void) signal(SIGQUIT, SIG_IGN);
                   1003: 
                   1004:        /* we can't communicate with our caller, so.... */
                   1005:        HoldErrs = TRUE;
                   1006:        ErrorMode = EM_MAIL;
                   1007:        Verbose = FALSE;
                   1008: 
                   1009:        /* all input from /dev/null */
                   1010:        if (InChannel != stdin)
                   1011:        {
                   1012:                (void) fclose(InChannel);
                   1013:                InChannel = stdin;
                   1014:        }
                   1015:        (void) freopen("/dev/null", "r", stdin);
                   1016: 
                   1017:        /* output to the transcript */
                   1018:        if (OutChannel != stdout)
                   1019:        {
                   1020:                (void) fclose(OutChannel);
                   1021:                OutChannel = stdout;
                   1022:        }
                   1023:        if (CurEnv->e_xfp == NULL)
                   1024:                CurEnv->e_xfp = fopen("/dev/null", "w");
                   1025:        (void) fflush(stdout);
                   1026:        (void) close(1);
                   1027:        (void) close(2);
                   1028:        while ((fd = dup(fileno(CurEnv->e_xfp))) < 2 && fd > 0)
                   1029:                continue;
                   1030: 
                   1031: #ifdef TIOCNOTTY
                   1032:        /* drop our controlling TTY completely if possible */
                   1033:        if (fulldrop)
                   1034:        {
                   1035:                fd = open("/dev/tty", 2);
                   1036:                if (fd >= 0)
                   1037:                {
                   1038:                        (void) ioctl(fd, (int) TIOCNOTTY, (char *) 0);
                   1039:                        (void) close(fd);
                   1040:                }
                   1041:                (void) setpgrp(0, 0);
                   1042:                errno = 0;
                   1043:        }
                   1044: #endif TIOCNOTTY
                   1045: 
                   1046: # ifdef LOG
                   1047:        if (LogLevel > 11)
                   1048:                syslog(LOG_DEBUG, "in background, pid=%d", getpid());
                   1049: # endif LOG
                   1050: 
                   1051:        errno = 0;
                   1052: }

unix.superglobalmegacorp.com

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