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

Defined functions

disconnect defined in line 864; used 1 times
freeze defined in line 748; used 1 times
initmacros defined in line 702; used 1 times
intsig defined in line 659; used 4 times
main defined in line 51; never used
thaw defined in line 799; used 1 times

Defined variables

BlankEnvelope defined in line 46; used 5 times
FullName defined in line 45; used 2 times
MainEnvelope defined in line 47; used 2 times
MetaMacros defined in line 687; used 1 times
NextMailer defined in line 44; never used

Defined struct's

metamac defined in line 681; used 4 times

Defined union's

frz defined in line 737; used 4 times

Defined macros

_DEFINE defined in line 1; never used
Last modified: 1983-12-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1927
Valid CSS Valid XHTML 1.0 Strict