# 2.11BSD#431 - /usr/src/usr.sbin/sendmail.MX/src/main.c

##### Functions

    disconnect        X
    finis             X
    freeze            X
    initmacros        X
    intsig            X
    main              X
    thaw              X

##### Variables

    Argv              X
    BlankEnvelope     X
    FullName          X
    LastArgv          X
    MainEnvelope      X
    MetaMacros        X
    NextMailer        X
    NullAddress       X
    copyright         X
    edata             X
    end               X

##### Macros

    _DEFINE           X

##### struct's

    metamac           X

##### unions's

    frz               X

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

#### Defined functions

disconnect defined in line 985; used 2 times

- in line 624
- in /usr/src/usr.sbin/sendmail.MX/src/deliver.c line 1422

finis defined in line 733; used 23 times

- in line 101, 491, 559, 596, 672, 718
- in /usr/src/usr.sbin/sendmail.MX/src/collect.c line 60, 191
- in /usr/src/usr.sbin/sendmail.MX/src/daemon.c line 124
- in /usr/src/usr.sbin/sendmail.MX/src/deliver.c line 1503
- in /usr/src/usr.sbin/sendmail.MX/src/envelope.c line 549
- in /usr/src/usr.sbin/sendmail.MX/src/queue.c line 285, 650
- in /usr/src/usr.sbin/sendmail.MX/src/savemail.c line 94
- in /usr/src/usr.sbin/sendmail.MX/src/srvrsmtp.c line 152, 170, 263, 362, 374, 387, 415, 432, 671

freeze defined in line 866; used 1 times

- in line 436

initmacros defined in line 818; used 1 times

- in line 244

intsig defined in line 772; used 4 times

- in line 115, 225-228(3)

main defined in line 90; never used
thaw defined in line 918; used 1 times

- in line 198

#### Defined variables

Argv defined in line 84; used 1 times

- in line 211

BlankEnvelope defined in line 71; used 6 times

- in line 156-160(5), 539

FullName defined in line 70; used 2 times

- in line 233, 362

LastArgv defined in line 85; used 2 times

- in line 213-215(2)

MainEnvelope defined in line 72; used 3 times

- in line 161, 538-539(2)

MetaMacros defined in line 800; used 1 times

- in line 824

NextMailer defined in line 69; never used
NullAddress defined in line 73; used 2 times

- in line 159-161(2)

copyright defined in line 18; never used
edata defined in line 34; used 10 times

- in line 871, 889, 895-896(3), 923, 939, 956-957(3)

end defined in line 34; used 4 times

- in line 871, 890, 923, 940

sccsid defined in line 22; never used

#### Defined struct's

metamac defined in line 794; used 4 times

- in line 800(2), 820(2)

#### Defined union's

frz defined in line 853; used 4 times

- in line 870(2), 922(2)

#### Defined macros

_DEFINE defined in line 25; never used

Last modified: 1997-10-03 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2865 |