This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / sbin / init.chmr / init.c
CommitLineData
9a6eb889
NW
1/*
2 * Copyright (c) 1993 Christoph M. Robitschko
800ffe89
NW
3 * All rights reserved.
4 *
800ffe89
NW
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
9a6eb889
NW
15 * This product includes software developed by Christoph M. Robitschko
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software withough specific prior written permission
800ffe89 18 *
9a6eb889
NW
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
800ffe89
NW
29 */
30
31/*
32 * init.c
33 * Main program for init.
34 * Also contains definitions for global variables etc.
35 */
36
37#include <unistd.h>
38#include <stdlib.h>
39#include <sys/types.h>
40#include <sys/signal.h>
41#include <sys/wait.h>
42#include <sys/errno.h>
43#include <setjmp.h>
44#include <syslog.h>
45#include <ttyent.h>
46#include <string.h>
47
48#include "init.h"
49#include "prototypes.h"
9a6eb889 50#include "libutil.h"
800ffe89
NW
51
52
53/* global variables, preset to their defaults */
800ffe89
NW
54int timeout_m2s_TERM = INIT_M2S_TERMTO;
55int timeout_m2s_KILL = INIT_M2S_KILLTO;
56int retrytime = RETRYTIME;
57int startup_single = 0;
58int checkonly = 0;
800ffe89 59int force_single = -1;
9a6eb889
NW
60#ifdef DEBUG
61int force_debug = -1;
62int debug = DEBUG_LEVEL;
63#endif
800ffe89
NW
64#ifdef CONFIGURE
65char *config_file = INIT_CONFIG;
66#endif
67
68static ttytab_t *ttytab = (ttytab_t *)0;
69static callout_t *callout_tab = (callout_t *)0;
70static callout_t *callout_free = (callout_t *)0;
71static int callout_nfree = 0;
72sigset_t block_set;
73jmp_buf boing_singleuser,
74 boing_single2multi,
75 boing_multiuser,
76 boing_multi2single,
77 boing_waitforboot,
78 *boing_m2stimeout;
79
80static enum { SINGLEUSER, MULTIUSER, SINGLE2MULTI, MULTI2SINGLE }
81 State;
82
83struct ttyent RCent_auto = {
84 "console",
85 "/bin/sh sh /etc/rc autoboot",
86 "dumb",
87 TTY_ON | TTY_SECURE,
88 0,
89 0
90 };
91struct ttyent RCent_fast = {
92 "console",
93 "/bin/sh sh /etc/rc",
94 "dumb",
95 TTY_ON | TTY_SECURE,
96 0,
97 0
98 };
99struct ttyent Single_ent = {
100 "console",
101 "/bin/sh -",
102 "pc3",
103 TTY_ON | TTY_SECURE,
104 0,
105 0
106 };
107static struct ttyent *RCent = &RCent_auto;
108static struct ttyent *Singlesh = &Single_ent;
109
110
111
112
113/**********************************************************
114 * Main *
115 **********************************************************/
116void
117main(argc, argv)
118int argc;
119char **argv;
120{
121
122
123 /* make it a session leader */
124 (void) setsid();
125
126 /* initialize syslog */
127 openlog("init", LOG_CONS | LOG_PID, LOG_DAEMON);
128
129
130 /* parse command line */
131 while(argc > 1) {
132 if(!strcmp(argv[1], "-s")) /* Singleuser */
133 force_single = startup_single = 1;
134
135 else if(!strcmp(argv[1], "-f")) /* Fastboot */
136 RCent = &RCent_fast;
137
9a6eb889 138#ifdef DEBUG
800ffe89
NW
139 else if (!strcmp(argv[1], "-d")) /* Debug level */
140 if (argc > 2) {
141 if ((force_debug = str2u(argv[2])) >= 0) {
142 debug = force_debug;
143 argc --; argv++;
144 } else
145 syslog(LOG_ERR, "option -d needs positive integer argument");
146 } else
147 syslog(LOG_ERR, "option -d needs an argument");
9a6eb889 148#endif
800ffe89
NW
149#ifdef CONFIGURE
150 else if (!strcmp(argv[1], "-C")) /* Configuration file */
151 if (argc > 2) {
152 config_file = argv[2];
153 argc--; argv++;
154 } else
155 syslog(LOG_ERR, "option -C needs an argument");
156
157 else if (!strcmp(argv[1], "-S")) /* Syntaxcheck only */
158 checkonly = 1;
159#endif
160 else if (!strcmp(argv[1], "-")) /* ignore this */
161 ;
9ea48534
NW
162 else if (!strcmp(argv[1], "--")) /* ... and this */
163 ;
800ffe89
NW
164 else
165 syslog(LOG_ERR, "unknown option \"%s\"", argv[1]);
166 argc--; argv++;
167 }
168
169
170#ifndef TESTRUN
171 /* did some idiot try to run init ? */
172 if((getpid() != 1) && !checkonly) {
173 const char errmsg[] = "init: system daemon, not runnable by user\r\n";
174 write(2, errmsg, strlen(errmsg));
175 exit(0xff);
176 }
177#endif /* ! TESTRUN */
178
179
180#ifdef CONFIGURE
181 /* read the default configuration (limits etc) */
182 getconf();
183 /* read configuration file */
184 configure(config_file);
185 /* set global configuration parameters */
186 checkconf();
187 if (checkonly)
188 exit(0);
800ffe89
NW
189
190 /* values configured by command-line arguments take precedence */
191 /* over values in the config file */
9a6eb889 192# ifdef DEBUG
800ffe89
NW
193 if (force_debug >= 0)
194 debug = force_debug;
9a6eb889 195# endif
800ffe89
NW
196 if (force_single >= 0)
197 startup_single = force_single;
9a6eb889 198#endif
800ffe89
NW
199
200 /*
201 * initialize callout table
202 */
203 allocate_callout();
204
205 /*
206 * initialize the longjmp buffers;
207 * after a longjmp(), the appropriate function is called and
208 * does not return.
209 */
210 if (setjmp(boing_singleuser))
211 singleuser();
212 if (setjmp(boing_single2multi))
213 single2multi();
214 if (setjmp(boing_multiuser))
215 multiuser();
216 if (setjmp(boing_multi2single))
217 multi2single();
218 if (setjmp(boing_waitforboot))
219 waitforboot();
220
221 /* install signal handlers for catched signals */
222 signal(SIGTSTP, sig_tstp);
223 signal(SIGTERM, sig_term);
224 signal(SIGHUP, sig_hup);
225 signal(SIGALRM, sig_alrm);
226#ifdef DEBUG
227 signal(SIGUSR1, sig_usr1);
228 signal(SIGUSR2, sig_usr2);
229#endif
230#ifdef CONFIGURE
231 signal(SIGTTIN, sig_ttin);
232#endif
233#if defined (UNTRUSTED) && !defined (TESTRUN)
234 signal(SIGINT, sig_int);
235#endif
236
237 /* define Set of signals to be blocked for critical parts */
238 (void) sigemptyset (&block_set);
239 (void) sigaddset (&block_set, SIGTSTP);
240 (void) sigaddset (&block_set, SIGTERM);
241 (void) sigaddset (&block_set, SIGHUP);
242 (void) sigaddset (&block_set, SIGUSR1);
243 (void) sigaddset (&block_set, SIGUSR2);
244 (void) sigaddset (&block_set, SIGALRM);
245
246 /* Action ! */
247 if (startup_single)
248 longjmp(boing_singleuser, 1);
249 else
250 longjmp(boing_single2multi, 1);
251
252 /* NOTREACHED */
253}
254
255
256
257/**********************************************************
258 * Signal Handlers *
259 **********************************************************/
260
261/* TSTP -- wait for children, but don't spawn new ones */
262void
263sig_tstp(sig)
264int sig;
265{
266 Debug(3, "TSTP Signal received");
267 longjmp(boing_waitforboot, 2);
268}
269
270
271/* TERM -- Go to singleuser mode */
272void
273sig_term(sig)
274int sig;
275{
276 Debug(3, "Terminate Signal received");
277 longjmp(boing_multi2single, 2);
278}
279
280
281/* HUP -- Reread /etc/ttys file */
282void
283sig_hup(sig)
284int sig;
285{
286 Debug(3, "Hangup Signal received");
287 if (State == MULTIUSER)
288 longjmp(boing_multiuser, 2);
289}
290
291
292/* ALRM -- Timeout Signal */
293void
294sig_alrm(sig)
295int sig;
296{
297 Debug(3, "Alarm Signal received");
298 if (callout_tab)
299 do_callout();
300}
301
302
303#ifdef DEBUG
304/* USR1 -- Increment debugging level */
305void
306sig_usr1(sig)
307int sig;
308{
309 debug++;
310 if (debug == 1)
311 Debug(0, "I will chat like a gossip");
312 else
313 Debug(0, "I will chat like %d gossips", debug);
314}
315
316/* USR2 -- switch off debugging */
317void
318sig_usr2(sig)
319int sig;
320{
321 Debug(0, "OK, I will shut up now.");
322 debug = 0;
323}
324#endif
325
326#if defined (UNTRUSTED) && !defined (TESTRUN)
327/* INT -- execute original init (Signal can be generated from the kernel
328 debugger with 'call pfind(1)' and then 'call psignal(XXXXX, 2)'
329 where XXXXX is the return value of the pfind call).
330 This isn't very pretty, but it saved me from booting from floppy
331 disk many times. */
332void
333sig_int(sig)
334int sig;
335{
336 Debug(0, "Interrupt signal received; trying to execute /sbin/init.ori");
337 Debug(0, "(Are you not satisfied with me ?)");
338 kill (-1, SIGKILL);
339 execl("/sbin/init.ori", "init", "-s", 0);
340 Debug(0, "Could not execute /sbin/init.ori (%m)");
341 longjmp(boing_multi2single, 1);
342}
343#endif /* UNTRUSTED */
344
345
346#ifdef CONFIGURE
347/* TTIN -- reread configuration file; only valid when in singleuser mode */
348void
349sig_ttin(sig)
350int sig;
351{
352 if (State == SINGLEUSER) {
353 blocksig();
354 Debug(0, "TTIN signal received, re-reading configuration file");
355 setconf();
356 configure(config_file);
357 checkconf();
358 unblocksig();
359 } else
360 syslog(LOG_NOTICE, "TTIN signal received, but not in singleuser mode");
361}
362#endif
363
364
365
366/**********************************************************
367 * SingleUserMode *
368 **********************************************************/
369
370void
371singleuser(void)
372{
373int status;
374
375
376 State = SINGLEUSER;
377 clear_callout();
378 Debug(1, "Entered State singleuser");
379
380 if (ttytab) {
381 syslog(LOG_ERR, "internal error: multiple users in singleusermode");
382 longjmp(boing_multi2single, 1);
383 }
384
385
386 RCent = &RCent_fast;
387 blocksig();
388 ttytab = ent_to_tab(Singlesh, (ttytab_t *)0, ttytab, INIT_NODEV | INIT_OPEN | INIT_ARG0);
389 unblocksig();
390 if (do_getty(ttytab, 0) < 0) {
391 syslog(LOG_EMERG, "Unable to start singleuser shell");
392 sync(); sleep(1);
393 _exit(1); /* What else should we do about this ? */
394 }
395
396#ifndef TESTRUN
397 while(wait(&status) != ttytab->pid);
398#else
399 scanf("%d\n", &status); /* XXX */
400#endif
401 Debug(1, "Singleusershell exited with status %d", status);
402
403
404 blocksig();
405 ttytab = free_tty(ttytab, ttytab);
406 unblocksig();
407
408 longjmp(boing_single2multi, 1);
409 /* NOTREACHED */
410}
411
412
413
414/**********************************************************
415 * Single 2 Multi *
416 **********************************************************/
417
418void
419single2multi(void)
420{
421int status;
422
423
424 State = SINGLE2MULTI;
425 clear_callout();
426 Debug(1, "Entered State single2multi");
427
428 if (ttytab) {
429 syslog(LOG_ERR, "internal error: users in single2multi");
430 longjmp(boing_multi2single, 1);
431 }
432
433
434 blocksig();
435 ttytab = ent_to_tab(RCent, (ttytab_t *)0, ttytab, INIT_NODEV | INIT_OPEN | INIT_ARG0);
436 unblocksig();
437 if (do_getty(ttytab, 0) < 0) {
438 syslog(LOG_ERR, "Unable to execute /etc/rc");
439 ttytab = free_tty(ttytab, ttytab);
440 longjmp(boing_singleuser, 2);
441 }
442
443#ifndef TESTRUN
444 while(wait(&status) != ttytab->pid);
445#else
446 scanf("%d\n", &status);
447#endif
448 Debug(1, "/etc/rc exited with status %d", status);
449
450
451 blocksig();
452 ttytab = free_tty(ttytab, ttytab);
453 unblocksig();
454
455 if (status)
456 longjmp(boing_singleuser, 1);
9a6eb889
NW
457 else {
458 logwtmp("~", "reboot", "");
800ffe89 459 longjmp(boing_multiuser, 1);
9a6eb889 460 }
800ffe89
NW
461 /* NOTREACHED */
462}
463
464
465
466/**********************************************************
467 * WaitForBoot *
468 **********************************************************/
469
470void
471waitforboot(void)
472{
473int status;
474pid_t pid;
475ttytab_t *tt;
476
477
478
479 /* Note that the State variable is not set here */
480 clear_callout();
481 Debug(1, "Entered State waitforboot");
482
483 while (1) {
484 pid = wait(&status);
485 if (pid < 0)
486 pause();
487 else {
488 Debug(4, "Process %d exited with status %d", pid, status);
489 for (tt=ttytab; tt; tt = tt->next)
490 if (tt->pid == pid) {
491 blocksig();
492 ttytab = free_tty(ttytab, tt);
493 unblocksig();
494 break;
495 }
496 }
497 }
498 /* NOTREACHED */
499}
500
501
502
503/**********************************************************
504 * MultiUser *
505 **********************************************************/
506
507void
508multiuser(void)
509{
510ttytab_t *tt;
511struct ttyent *tent;
512int pid;
513int status;
514
515
516
517 State = MULTIUSER;
518 clear_callout();
519 Debug(1, "Entered State multiuser");
520
521 /* First, (re)build ttytab based on what is in /etc/ttys */
522 blocksig();
523 setttyent();
524
525 for (tt = ttytab; tt; tt = tt->next)
526 tt->intflags &= ~(INIT_SEEN | INIT_CHANGED | INIT_NEW);
527
528 while ((tent = getttyent()))
529 if (tent->ty_status & TTY_ON) {
530 for (tt = ttytab; tt; tt = tt->next)
531 if (!strcmp(tent->ty_name, tt->name))
532 break;
533 ttytab = ent_to_tab(tent, tt, ttytab, 0);
534 }
535
536 unblocksig();
537
538 /* Kill the processes whose entries are deleted or changed */
539 /* Also start the getty process on the lines that were just added */
540 for (tt = ttytab; tt; tt = tt->next)
541 if (!(tt->intflags & INIT_SEEN)) {
542 Debug(5, "killing %s (PID %d): Not seen", tt->name, tt->pid);
543 kill (tt->pid, SIGKILL);
544 tt->intflags |= INIT_DONTSPAWN;
545 }
546 else if (tt->intflags & INIT_NEW)
547 (void)do_getty(tt, 0);
548 else if (tt->intflags & INIT_CHANGED) {
549 Debug(5, "killing %s (PID %d): Changed", tt->name, tt->pid);
550 kill (tt->pid, SIGKILL);
551 }
552 else if (tt->intflags & INIT_FAILSLEEP) {
553 Debug(5, "continuing %s (PID %d)", tt->name, tt->pid);
554#define UNSLEEP(a)
555 UNSLEEP(tt->pid);
556 tt->intflags &= ~INIT_FAILED | INIT_FAILSLEEP;
557 do_getty(tt, 0);
558 }
559
560
561 /* Now handle terminating children and respawn gettys for lines */
562 while (1) {
563 pid = wait(&status);
564 if (pid < 0) {
565 switch (errno) {
566 case EINTR: break;
567 case ECHILD:
568 syslog(LOG_ERR, "wait() found no child processes -- going singleuser.");
569 longjmp(boing_multi2single, 2);
570 default:
571 syslog(LOG_ERR, "wait() failed: %m");
572 sleep(5);
573 }
574 } else {
575 Debug(4, "Process %d terminated with status %d", pid, status);
576 for (tt = ttytab; tt; tt = tt->next)
577 if (pid == tt->pid)
578 if (tt->intflags & INIT_DONTSPAWN) {
579 blocksig();
580 ttytab = free_tty(ttytab, tt);
581 unblocksig();
582 }
583 else
584 (void)do_getty(tt, 0);
585 }
586 }
587 /* NOTREACHED */
588}
589
590
591
592/**********************************************************
593 * Multi2Single *
594 **********************************************************/
595
596void
597multi2single(void)
598{
599static jmp_buf boing_timeout;
600pid_t pid;
601int status;
602volatile int round;
603
604
605 State = MULTI2SINGLE;
606 clear_callout();
607 Debug(1, "Entering State multi2single");
608
609 /* forget about the gettys */
610 blocksig();
611 while (ttytab)
612 ttytab = free_tty(ttytab, ttytab);
613 unblocksig();
614
615 /*
616 * round = 1: TERMinate children, then wait for them (default 10 seconds)
617 * round = 2: KILL children, then wait for them (default 30 seconds)
618 * round = 3: timeout expired; go to singleuser mode
619 */
620 round = 0;
621 setjmp(boing_timeout);
622 boing_m2stimeout = &boing_timeout;
623 round ++;
624 if (round < 3) {
625 if (round == 1){
626 Debug(3, "TERMinating processes");
627 kill (-1, SIGTERM);
628 kill (-1, SIGCONT);
629 callout (timeout_m2s_TERM, CO_MUL2SIN, (void *)0);
630 }
631 else {
632 Debug(3, "KILLing processes");
633 kill (-1, SIGKILL);
634 kill (-1, SIGCONT);
635 callout (timeout_m2s_KILL, CO_MUL2SIN, (void *)0);
636 }
637 while ((pid = wait(&status)) >= 0)
638 Debug(4, "Process %d exited with status %d", pid, status);
639 Debug(2, "Wait returned error: %m");
640 }
641 else
642 syslog(LOG_NOTICE, "There are still some (hung) processes.");
643
644 /* We don't need no steenkin timeout any more... */
645 boing_m2stimeout = (jmp_buf *)0;
646
647 /* Jump ! (Rein ins Vergnuegen) */
648 longjmp(boing_singleuser, 2);
649 /* NOTREACHED */
650}
651
652
653
654/**********************************************************
655 * Callout *
656 * Schedule a retry operation for a later time *
657 **********************************************************/
658void
659callout(when, type, arg)
660unsigned int when;
661retr_t type;
662void *arg;
663{
664callout_t *ntp,
665 *ctp,
666 *octp;
667
668
669 Debug(3, "Scheduling callout in %d seconds.", when);
670 blocksig();
671
672 /* find a free callout entry */
673 if (callout_nfree <= CALLOUT_MINFREE)
674 allocate_callout();
675 ntp = callout_free;
676 if (!ntp) {
677 syslog(LOG_WARNING, "Callout table is full !");
678 return;
679 }
680 callout_free = ntp->next;
681 callout_nfree --;
682
683 /* look at which point we put it in the callout list */
684 when += (unsigned int)time(NULL);
685 for (octp = NULL, ctp = callout_tab; ctp; octp = ctp, ctp = ctp->next)
686 if (when < ctp->sleept)
687 break;
688 else
689 when -= ctp->sleept;
690
691
692 if (octp)
693 octp->next = ntp;
694 else
695 callout_tab = ntp;
696 ntp->next = ctp;
697 ntp->sleept = when;
698 if (ctp) ctp->sleept -= when;
699 ntp->what = type;
700 ntp->arg = arg;
701
702 /* schedule alarm */
703 when = callout_tab->sleept - (unsigned int)time(NULL);
704 if (when <= 0) {
705 Debug(4, "Next callout: NOW !");
706 alarm(0);
707 kill (getpid(), SIGALRM);
708 } else
709 Debug(4, "Next callout in %d seconds.", when);
710 alarm(when);
711
712 unblocksig();
713}
714
715
716/**********************************************************
717 * Allocate_Callout *
718 * allocate (further) elements to the callout table *
719 *********************************************************/
720void
721allocate_callout(void)
722{
723callout_t *ntp;
724int i;
725
726
727 ntp = malloc(sizeof(callout_t) * CALLOUT_CHUNK);
728 if (ntp) {
729 for (i=1; i< CALLOUT_CHUNK; i++)
730 ntp[i].next = &ntp[i-1];
731 ntp->next = callout_free;
732 callout_free = &ntp[i-1];
733 callout_nfree += CALLOUT_CHUNK;
734 }
735}
736
737
738/**********************************************************
739 * Clear_Callout *
740 * Removes all callout entries *
741 *********************************************************/
742void
743clear_callout(void)
744{
745callout_t *ctp,
746 *nctp;
747
748
749 if (callout_tab)
750 Debug(4, "All callouts for today cancelled.");
751 blocksig();
752 alarm(0);
753 for (ctp = callout_tab; ctp; ctp = nctp) {
754 nctp = ctp->next;
755 ctp->next = callout_free;
756 callout_free = ctp;
757 callout_nfree ++;
758 }
9ea48534 759 callout_tab = (callout_t *)0;
800ffe89
NW
760 unblocksig();
761}
762
763
764
765/**********************************************************
766 * Do_Callout *
767 * calls the callback routines when the time has expired *
768 *********************************************************/
769void
770do_callout(void)
771{
772callout_t *ctp;
773unsigned int now;
774
775
776 now = (unsigned int) time(NULL);
777 for (ctp = callout_tab; ctp;) {
778 if (ctp->sleept > now)
779 break;
780 ctp = ctp->next;
781 if (ctp)
782 ctp->sleept += callout_tab->sleept;
783 callout_tab->next = callout_free;
784 callout_free = callout_tab;
785 callout_tab = ctp;
786 callout_nfree ++;
787
788 switch (callout_free->what) {
789 case CO_ENT2TAB:
790 Debug(3, "Callout -> Multiuser");
791 longjmp(boing_multiuser, 2);
792 case CO_FORK:
793 case CO_GETTY:
794 Debug(3, "Callout -> do_getty()");
795 (void)do_getty((ttytab_t *)callout_free->arg, 0);
796 break;
797 case CO_MUL2SIN:
798 Debug(3, "Callout -> M2S timeout");
799 if (boing_m2stimeout)
800 longjmp(*boing_m2stimeout, 2);
801 }
802 }
803
804 /* schedule next alarm */
805 if (callout_tab) {
806 Debug(4, "Next callout in %d seconds.", callout_tab->sleept - now);
807 alarm(callout_tab->sleept - now);
808 }
809}
810
811
812/**********************************************************
813 * SignalsForChile *
814 * Set up signals for the child processes *
815 *********************************************************/
816void
817signalsforchile(void)
818{
819 signal(SIGTSTP, SIG_DFL);
820 signal(SIGTERM, SIG_DFL);
821 signal(SIGHUP , SIG_DFL);
822 signal(SIGUSR1, SIG_DFL);
823 signal(SIGUSR2, SIG_DFL);
824 signal(SIGALRM, SIG_DFL);
825 signal(SIGINT, SIG_DFL);
826 signal(SIGTTIN, SIG_DFL);
827 unblocksig();
828}