|
|
1.1 ! root 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.3 9/5/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: /* this is critical to avoid forgeries of the frozen config */ ! 338: setuid(getuid()); ! 339: setgid(getgid()); ! 340: ! 341: /* freeze the configuration */ ! 342: freeze(FreezeFile); ! 343: exit(EX_OK); ! 344: ! 345: case MD_INITALIAS: ! 346: Verbose = TRUE; ! 347: break; ! 348: } ! 349: ! 350: /* do heuristic mode adjustment */ ! 351: if (Verbose) ! 352: { ! 353: /* turn off noconnect option */ ! 354: setoption('c', "F", TRUE, FALSE); ! 355: ! 356: /* turn on interactive delivery */ ! 357: setoption('d', "", TRUE, FALSE); ! 358: } ! 359: ! 360: /* our name for SMTP codes */ ! 361: expand("$j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv); ! 362: HostName = jbuf; ! 363: ! 364: /* the indices of local and program mailers */ ! 365: st = stab("local", ST_MAILER, ST_FIND); ! 366: if (st == NULL) ! 367: syserr("No local mailer defined"); ! 368: else ! 369: LocalMailer = st->s_mailer; ! 370: st = stab("prog", ST_MAILER, ST_FIND); ! 371: if (st == NULL) ! 372: syserr("No prog mailer defined"); ! 373: else ! 374: ProgMailer = st->s_mailer; ! 375: ! 376: /* operate in queue directory */ ! 377: if (chdir(QueueDir) < 0) ! 378: { ! 379: syserr("cannot chdir(%s)", QueueDir); ! 380: exit(EX_SOFTWARE); ! 381: } ! 382: ! 383: /* ! 384: ** If printing the queue, go off and do that. ! 385: */ ! 386: ! 387: if (OpMode == MD_PRINT) ! 388: { ! 389: #ifdef QUEUE ! 390: dropenvelope(CurEnv); ! 391: printqueue(); ! 392: exit(EX_OK); ! 393: #else QUEUE ! 394: usrerr("No queue to print"); ! 395: finis(); ! 396: #endif QUEUE ! 397: } ! 398: ! 399: /* ! 400: ** Initialize aliases. ! 401: */ ! 402: ! 403: initaliases(AliasFile, OpMode == MD_INITALIAS); ! 404: if (OpMode == MD_INITALIAS) ! 405: exit(EX_OK); ! 406: ! 407: # ifdef DEBUG ! 408: if (tTd(0, 15)) ! 409: { ! 410: /* print configuration table (or at least part of it) */ ! 411: printrules(); ! 412: for (i = 0; i < MAXMAILERS; i++) ! 413: { ! 414: register struct mailer *m = Mailer[i]; ! 415: int j; ! 416: ! 417: if (m == NULL) ! 418: continue; ! 419: printf("mailer %d (%s): P=%s S=%d R=%d M=%ld F=", i, m->m_name, ! 420: m->m_mailer, m->m_s_rwset, m->m_r_rwset, ! 421: m->m_maxsize); ! 422: for (j = '\0'; j <= '\177'; j++) ! 423: if (bitnset(j, m->m_flags)) ! 424: putchar(j); ! 425: printf(" E="); ! 426: xputs(m->m_eol); ! 427: printf("\n"); ! 428: } ! 429: } ! 430: # endif DEBUG ! 431: ! 432: /* ! 433: ** Switch to the main envelope. ! 434: */ ! 435: ! 436: CurEnv = newenvelope(&MainEnvelope); ! 437: MainEnvelope.e_flags = BlankEnvelope.e_flags; ! 438: ! 439: /* ! 440: ** If test mode, read addresses from stdin and process. ! 441: */ ! 442: ! 443: if (OpMode == MD_TEST) ! 444: { ! 445: char buf[MAXLINE]; ! 446: ! 447: printf("ADDRESS TEST MODE\nEnter <ruleset> <address>\n"); ! 448: for (;;) ! 449: { ! 450: register char **pvp; ! 451: char *q; ! 452: extern char **prescan(); ! 453: extern char *DelimChar; ! 454: ! 455: printf("> "); ! 456: fflush(stdout); ! 457: if (fgets(buf, sizeof buf, stdin) == NULL) ! 458: finis(); ! 459: for (p = buf; isspace(*p); *p++) ! 460: continue; ! 461: q = p; ! 462: while (*p != '\0' && !isspace(*p)) ! 463: p++; ! 464: if (*p == '\0') ! 465: continue; ! 466: *p = '\0'; ! 467: do ! 468: { ! 469: pvp = prescan(++p, ','); ! 470: if (pvp == NULL) ! 471: continue; ! 472: rewrite(pvp, 3); ! 473: p = q; ! 474: while (*p != '\0') ! 475: { ! 476: rewrite(pvp, atoi(p)); ! 477: while (*p != '\0' && *p++ != ',') ! 478: continue; ! 479: } ! 480: } while (*(p = DelimChar) != '\0'); ! 481: } ! 482: } ! 483: ! 484: # ifdef QUEUE ! 485: /* ! 486: ** If collecting stuff from the queue, go start doing that. ! 487: */ ! 488: ! 489: if (queuemode && OpMode != MD_DAEMON && QueueIntvl == 0) ! 490: { ! 491: runqueue(FALSE); ! 492: finis(); ! 493: } ! 494: # endif QUEUE ! 495: ! 496: /* ! 497: ** If a daemon, wait for a request. ! 498: ** getrequests will always return in a child. ! 499: ** If we should also be processing the queue, start ! 500: ** doing it in background. ! 501: ** We check for any errors that might have happened ! 502: ** during startup. ! 503: */ ! 504: ! 505: if (OpMode == MD_DAEMON || QueueIntvl != 0) ! 506: { ! 507: if (!tTd(0, 1)) ! 508: { ! 509: /* put us in background */ ! 510: i = fork(); ! 511: if (i < 0) ! 512: syserr("daemon: cannot fork"); ! 513: if (i != 0) ! 514: exit(0); ! 515: ! 516: /* get our pid right */ ! 517: MotherPid = getpid(); ! 518: ! 519: /* disconnect from our controlling tty */ ! 520: disconnect(TRUE); ! 521: } ! 522: ! 523: # ifdef QUEUE ! 524: if (queuemode) ! 525: { ! 526: runqueue(TRUE); ! 527: if (OpMode != MD_DAEMON) ! 528: for (;;) ! 529: pause(); ! 530: } ! 531: # endif QUEUE ! 532: dropenvelope(CurEnv); ! 533: ! 534: #ifdef DAEMON ! 535: getrequests(); ! 536: ! 537: /* at this point we are in a child: reset state */ ! 538: OpMode = MD_SMTP; ! 539: (void) newenvelope(CurEnv); ! 540: openxscript(CurEnv); ! 541: #endif DAEMON ! 542: } ! 543: ! 544: # ifdef SMTP ! 545: /* ! 546: ** If running SMTP protocol, start collecting and executing ! 547: ** commands. This will never return. ! 548: */ ! 549: ! 550: if (OpMode == MD_SMTP) ! 551: smtp(); ! 552: # endif SMTP ! 553: ! 554: /* ! 555: ** Do basic system initialization and set the sender ! 556: */ ! 557: ! 558: initsys(); ! 559: setsender(from); ! 560: ! 561: if (OpMode != MD_ARPAFTP && *av == NULL && !GrabTo) ! 562: { ! 563: usrerr("Usage: /etc/sendmail [flags] addr..."); ! 564: finis(); ! 565: } ! 566: if (OpMode == MD_VERIFY) ! 567: SendMode = SM_VERIFY; ! 568: ! 569: /* ! 570: ** Scan argv and deliver the message to everyone. ! 571: */ ! 572: ! 573: sendtoargv(av); ! 574: ! 575: /* if we have had errors sofar, arrange a meaningful exit stat */ ! 576: if (Errors > 0 && ExitStat == EX_OK) ! 577: ExitStat = EX_USAGE; ! 578: ! 579: /* ! 580: ** Read the input mail. ! 581: */ ! 582: ! 583: CurEnv->e_to = NULL; ! 584: if (OpMode != MD_VERIFY || GrabTo) ! 585: collect(FALSE); ! 586: errno = 0; ! 587: ! 588: /* collect statistics */ ! 589: if (OpMode != MD_VERIFY) ! 590: markstats(CurEnv, (ADDRESS *) NULL); ! 591: ! 592: # ifdef DEBUG ! 593: if (tTd(1, 1)) ! 594: printf("From person = \"%s\"\n", CurEnv->e_from.q_paddr); ! 595: # endif DEBUG ! 596: ! 597: /* ! 598: ** Actually send everything. ! 599: ** If verifying, just ack. ! 600: */ ! 601: ! 602: CurEnv->e_from.q_flags |= QDONTSEND; ! 603: CurEnv->e_to = NULL; ! 604: sendall(CurEnv, SM_DEFAULT); ! 605: ! 606: /* ! 607: ** All done. ! 608: */ ! 609: ! 610: finis(); ! 611: } ! 612: /* ! 613: ** FINIS -- Clean up and exit. ! 614: ** ! 615: ** Parameters: ! 616: ** none ! 617: ** ! 618: ** Returns: ! 619: ** never ! 620: ** ! 621: ** Side Effects: ! 622: ** exits sendmail ! 623: */ ! 624: ! 625: finis() ! 626: { ! 627: # ifdef DEBUG ! 628: if (tTd(2, 1)) ! 629: printf("\n====finis: stat %d e_flags %o\n", ExitStat, CurEnv->e_flags); ! 630: # endif DEBUG ! 631: ! 632: /* clean up temp files */ ! 633: CurEnv->e_to = NULL; ! 634: dropenvelope(CurEnv); ! 635: ! 636: /* post statistics */ ! 637: poststats(StatFile); ! 638: ! 639: /* and exit */ ! 640: # ifdef LOG ! 641: if (LogLevel > 11) ! 642: syslog(LOG_DEBUG, "finis, pid=%d", getpid()); ! 643: # endif LOG ! 644: if (ExitStat == EX_TEMPFAIL) ! 645: ExitStat = EX_OK; ! 646: exit(ExitStat); ! 647: } ! 648: /* ! 649: ** INTSIG -- clean up on interrupt ! 650: ** ! 651: ** This just arranges to exit. It pessimises in that it ! 652: ** may resend a message. ! 653: ** ! 654: ** Parameters: ! 655: ** none. ! 656: ** ! 657: ** Returns: ! 658: ** none. ! 659: ** ! 660: ** Side Effects: ! 661: ** Unlocks the current job. ! 662: */ ! 663: ! 664: intsig() ! 665: { ! 666: FileName = NULL; ! 667: unlockqueue(CurEnv); ! 668: exit(EX_OK); ! 669: } ! 670: /* ! 671: ** INITMACROS -- initialize the macro system ! 672: ** ! 673: ** This just involves defining some macros that are actually ! 674: ** used internally as metasymbols to be themselves. ! 675: ** ! 676: ** Parameters: ! 677: ** none. ! 678: ** ! 679: ** Returns: ! 680: ** none. ! 681: ** ! 682: ** Side Effects: ! 683: ** initializes several macros to be themselves. ! 684: */ ! 685: ! 686: struct metamac ! 687: { ! 688: char metaname; ! 689: char metaval; ! 690: }; ! 691: ! 692: struct metamac MetaMacros[] = ! 693: { ! 694: /* these are important on the LHS */ ! 695: '*', MATCHZANY, '+', MATCHANY, '-', MATCHONE, '=', MATCHCLASS, ! 696: '~', MATCHNCLASS, ! 697: ! 698: /* these are RHS metasymbols */ ! 699: '#', CANONNET, '@', CANONHOST, ':', CANONUSER, '>', CALLSUBR, ! 700: ! 701: /* and finally the conditional operations */ ! 702: '?', CONDIF, '|', CONDELSE, '.', CONDFI, ! 703: ! 704: '\0' ! 705: }; ! 706: ! 707: initmacros() ! 708: { ! 709: register struct metamac *m; ! 710: char buf[5]; ! 711: register int c; ! 712: ! 713: for (m = MetaMacros; m->metaname != '\0'; m++) ! 714: { ! 715: buf[0] = m->metaval; ! 716: buf[1] = '\0'; ! 717: define(m->metaname, newstr(buf), CurEnv); ! 718: } ! 719: buf[0] = MATCHREPL; ! 720: buf[2] = '\0'; ! 721: for (c = '0'; c <= '9'; c++) ! 722: { ! 723: buf[1] = c; ! 724: define(c, newstr(buf), CurEnv); ! 725: } ! 726: } ! 727: /* ! 728: ** FREEZE -- freeze BSS & allocated memory ! 729: ** ! 730: ** This will be used to efficiently load the configuration file. ! 731: ** ! 732: ** Parameters: ! 733: ** freezefile -- the name of the file to freeze to. ! 734: ** ! 735: ** Returns: ! 736: ** none. ! 737: ** ! 738: ** Side Effects: ! 739: ** Writes BSS and malloc'ed memory to freezefile ! 740: */ ! 741: ! 742: union frz ! 743: { ! 744: char frzpad[BUFSIZ]; /* insure we are on a BUFSIZ boundary */ ! 745: struct ! 746: { ! 747: time_t frzstamp; /* timestamp on this freeze */ ! 748: char *frzbrk; /* the current break */ ! 749: char frzver[252]; /* sendmail version */ ! 750: } frzinfo; ! 751: }; ! 752: ! 753: freeze(freezefile) ! 754: char *freezefile; ! 755: { ! 756: int f; ! 757: union frz fhdr; ! 758: extern char edata; ! 759: extern char *sbrk(); ! 760: extern char Version[]; ! 761: ! 762: if (freezefile == NULL) ! 763: return; ! 764: ! 765: /* try to open the freeze file */ ! 766: f = creat(freezefile, FileMode); ! 767: if (f < 0) ! 768: { ! 769: syserr("Cannot freeze"); ! 770: errno = 0; ! 771: return; ! 772: } ! 773: ! 774: /* build the freeze header */ ! 775: fhdr.frzinfo.frzstamp = curtime(); ! 776: fhdr.frzinfo.frzbrk = sbrk(0); ! 777: strcpy(fhdr.frzinfo.frzver, Version); ! 778: ! 779: /* write out the freeze header */ ! 780: if (write(f, (char *) &fhdr, sizeof fhdr) != sizeof fhdr || ! 781: write(f, (char *) &edata, fhdr.frzinfo.frzbrk - &edata) != ! 782: (fhdr.frzinfo.frzbrk - &edata)) ! 783: { ! 784: syserr("Cannot freeze"); ! 785: } ! 786: ! 787: /* fine, clean up */ ! 788: (void) close(f); ! 789: } ! 790: /* ! 791: ** THAW -- read in the frozen configuration file. ! 792: ** ! 793: ** Parameters: ! 794: ** freezefile -- the name of the file to thaw from. ! 795: ** ! 796: ** Returns: ! 797: ** TRUE if it successfully read the freeze file. ! 798: ** FALSE otherwise. ! 799: ** ! 800: ** Side Effects: ! 801: ** reads freezefile in to BSS area. ! 802: */ ! 803: ! 804: thaw(freezefile) ! 805: char *freezefile; ! 806: { ! 807: int f; ! 808: union frz fhdr; ! 809: extern char edata; ! 810: extern char Version[]; ! 811: ! 812: if (freezefile == NULL) ! 813: return (FALSE); ! 814: ! 815: /* open the freeze file */ ! 816: f = open(freezefile, 0); ! 817: if (f < 0) ! 818: { ! 819: errno = 0; ! 820: return (FALSE); ! 821: } ! 822: ! 823: /* read in the header */ ! 824: if (read(f, (char *) &fhdr, sizeof fhdr) < sizeof fhdr || ! 825: strcmp(fhdr.frzinfo.frzver, Version) != 0) ! 826: { ! 827: (void) close(f); ! 828: return (FALSE); ! 829: } ! 830: ! 831: /* arrange to have enough space */ ! 832: if (brk(fhdr.frzinfo.frzbrk) < 0) ! 833: { ! 834: syserr("Cannot break to %x", fhdr.frzinfo.frzbrk); ! 835: (void) close(f); ! 836: return (FALSE); ! 837: } ! 838: ! 839: /* now read in the freeze file */ ! 840: if (read(f, (char *) &edata, fhdr.frzinfo.frzbrk - &edata) != ! 841: (fhdr.frzinfo.frzbrk - &edata)) ! 842: { ! 843: /* oops! we have trashed memory..... */ ! 844: write(2, "Cannot read freeze file\n", 24); ! 845: _exit(EX_SOFTWARE); ! 846: } ! 847: ! 848: (void) close(f); ! 849: return (TRUE); ! 850: } ! 851: /* ! 852: ** DISCONNECT -- remove our connection with any foreground process ! 853: ** ! 854: ** Parameters: ! 855: ** fulldrop -- if set, we should also drop the controlling ! 856: ** TTY if possible -- this should only be done when ! 857: ** setting up the daemon since otherwise UUCP can ! 858: ** leave us trying to open a dialin, and we will ! 859: ** wait for the carrier. ! 860: ** ! 861: ** Returns: ! 862: ** none ! 863: ** ! 864: ** Side Effects: ! 865: ** Trys to insure that we are immune to vagaries of ! 866: ** the controlling tty. ! 867: */ ! 868: ! 869: disconnect(fulldrop) ! 870: bool fulldrop; ! 871: { ! 872: int fd; ! 873: ! 874: #ifdef DEBUG ! 875: if (tTd(52, 1)) ! 876: printf("disconnect: In %d Out %d\n", fileno(InChannel), ! 877: fileno(OutChannel)); ! 878: if (tTd(52, 5)) ! 879: { ! 880: printf("don't\n"); ! 881: return; ! 882: } ! 883: #endif DEBUG ! 884: ! 885: /* be sure we don't get nasty signals */ ! 886: signal(SIGHUP, SIG_IGN); ! 887: signal(SIGINT, SIG_IGN); ! 888: signal(SIGQUIT, SIG_IGN); ! 889: ! 890: /* we can't communicate with our caller, so.... */ ! 891: HoldErrs = TRUE; ! 892: ErrorMode = EM_MAIL; ! 893: Verbose = FALSE; ! 894: ! 895: /* all input from /dev/null */ ! 896: if (InChannel != stdin) ! 897: { ! 898: (void) fclose(InChannel); ! 899: InChannel = stdin; ! 900: } ! 901: (void) freopen("/dev/null", "r", stdin); ! 902: ! 903: /* output to the transcript */ ! 904: if (OutChannel != stdout) ! 905: { ! 906: (void) fclose(OutChannel); ! 907: OutChannel = stdout; ! 908: } ! 909: if (CurEnv->e_xfp == NULL) ! 910: CurEnv->e_xfp = fopen("/dev/null", "w"); ! 911: (void) fflush(stdout); ! 912: (void) close(1); ! 913: (void) close(2); ! 914: while ((fd = dup(fileno(CurEnv->e_xfp))) < 2 && fd > 0) ! 915: continue; ! 916: ! 917: #ifdef TIOCNOTTY ! 918: /* drop our controlling TTY completely if possible */ ! 919: if (fulldrop) ! 920: { ! 921: fd = open("/dev/tty", 2); ! 922: if (fd >= 0) ! 923: { ! 924: (void) ioctl(fd, TIOCNOTTY, 0); ! 925: (void) close(fd); ! 926: } ! 927: errno = 0; ! 928: } ! 929: #endif TIOCNOTTY ! 930: ! 931: # ifdef LOG ! 932: if (LogLevel > 11) ! 933: syslog(LOG_DEBUG, "in background, pid=%d", getpid()); ! 934: # endif LOG ! 935: ! 936: errno = 0; ! 937: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.