|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.