Annotation of src/sbin/init/init.c, Revision 1.54
1.54 ! deraadt 1: /* $OpenBSD: init.c,v 1.53 2015/07/14 19:14:05 millert Exp $ */
1.2 deraadt 2: /* $NetBSD: init.c,v 1.22 1996/05/15 23:29:33 jtc Exp $ */
1.1 deraadt 3:
4: /*-
5: * Copyright (c) 1991, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley by
9: * Donn Seeley at Berkeley Software Design, Inc.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
1.32 millert 19: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
1.52 deraadt 36: #include <sys/types.h>
1.1 deraadt 37: #include <sys/sysctl.h>
38: #include <sys/wait.h>
1.16 deraadt 39: #include <sys/reboot.h>
1.47 halex 40: #include <machine/cpu.h>
1.1 deraadt 41:
42: #include <db.h>
1.43 dcoppa 43: #include <err.h>
1.1 deraadt 44: #include <errno.h>
45: #include <fcntl.h>
46: #include <signal.h>
1.25 millert 47: #include <stdarg.h>
1.1 deraadt 48: #include <stdio.h>
49: #include <stdlib.h>
50: #include <string.h>
51: #include <syslog.h>
52: #include <time.h>
53: #include <ttyent.h>
54: #include <unistd.h>
1.2 deraadt 55: #include <util.h>
1.1 deraadt 56:
57: #ifdef SECURE
58: #include <pwd.h>
59: #endif
60:
1.20 millert 61: #ifdef LOGIN_CAP
62: #include <login_cap.h>
63: #endif
64:
1.1 deraadt 65: #include "pathnames.h"
66:
67: /*
68: * Sleep times; used to prevent thrashing.
69: */
70: #define GETTY_SPACING 5 /* N secs minimum getty spacing */
71: #define GETTY_SLEEP 30 /* sleep N secs after spacing problem */
72: #define WINDOW_WAIT 3 /* wait N secs after starting window */
73: #define STALL_TIMEOUT 30 /* wait N secs after warning */
74: #define DEATH_WATCH 10 /* wait N secs for procs to die */
75:
1.20 millert 76: /*
77: * User-based resource limits.
78: */
79: #define RESOURCE_RC "daemon"
80: #define RESOURCE_WINDOW "default"
81: #define RESOURCE_GETTY "default"
82:
1.19 millert 83: #ifndef DEFAULT_STATE
84: #define DEFAULT_STATE runcom
85: #endif
86:
1.24 millert 87: void handle(sig_t, ...);
88: void delset(sigset_t *, ...);
1.1 deraadt 89:
1.24 millert 90: void stall(char *, ...);
91: void warning(char *, ...);
92: void emergency(char *, ...);
93: void disaster(int);
94: void badsys(int);
1.1 deraadt 95:
1.53 millert 96: typedef enum {
97: invalid_state,
98: single_user,
99: runcom,
100: read_ttys,
101: multi_user,
102: clean_ttys,
103: catatonia,
104: death,
105: do_reboot,
106: hard_death,
107: nice_death
108: } state_t;
109: typedef state_t (*state_func_t)(void);
110:
111: state_t f_single_user(void);
112: state_t f_runcom(void);
113: state_t f_read_ttys(void);
114: state_t f_multi_user(void);
115: state_t f_clean_ttys(void);
116: state_t f_catatonia(void);
117: state_t f_death(void);
118: state_t f_do_reboot(void);
119: state_t f_hard_death(void);
120: state_t f_nice_death(void);
121:
122: state_func_t state_funcs[] = {
123: NULL,
124: f_single_user,
125: f_runcom,
126: f_read_ttys,
127: f_multi_user,
128: f_clean_ttys,
129: f_catatonia,
130: f_death,
131: f_do_reboot,
132: f_hard_death,
133: f_nice_death
134: };
1.1 deraadt 135:
136: enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT;
137:
1.24 millert 138: void transition(state_t);
1.53 millert 139: volatile sig_atomic_t requested_transition = DEFAULT_STATE;
1.1 deraadt 140:
1.24 millert 141: void setctty(char *);
1.1 deraadt 142:
143: typedef struct init_session {
144: int se_index; /* index of entry in ttys file */
145: pid_t se_process; /* controlling process */
146: time_t se_started; /* used to avoid thrashing */
147: int se_flags; /* status of session */
148: #define SE_SHUTDOWN 0x1 /* session won't be restarted */
149: #define SE_PRESENT 0x2 /* session is in /etc/ttys */
1.6 deraadt 150: #define SE_DEVEXISTS 0x4 /* open does not result in ENODEV */
1.1 deraadt 151: char *se_device; /* filename of port */
152: char *se_getty; /* what to run on that port */
153: char **se_getty_argv; /* pre-parsed argument array */
154: char *se_window; /* window system (started only once) */
155: char **se_window_argv; /* pre-parsed argument array */
156: struct init_session *se_prev;
157: struct init_session *se_next;
158: } session_t;
159:
1.24 millert 160: void free_session(session_t *);
161: session_t *new_session(session_t *, int, struct ttyent *);
1.1 deraadt 162: session_t *sessions;
163:
1.24 millert 164: char **construct_argv(char *);
165: void start_window_system(session_t *);
166: void collect_child(pid_t);
167: pid_t start_getty(session_t *);
168: void transition_handler(int);
169: void alrm_handler(int);
170: void setsecuritylevel(int);
171: int getsecuritylevel(void);
172: int setupargv(session_t *, struct ttyent *);
1.1 deraadt 173: int clang;
174:
1.20 millert 175: #ifdef LOGIN_CAP
1.24 millert 176: void setprocresources(char *);
1.20 millert 177: #else
178: #define setprocresources(p)
179: #endif
180:
1.24 millert 181: void clear_session_logs(session_t *);
1.1 deraadt 182:
1.24 millert 183: int start_session_db(void);
184: void add_session(session_t *);
185: void del_session(session_t *);
186: session_t *find_session(pid_t);
1.1 deraadt 187: DB *session_db;
188:
189: /*
190: * The mother of all processes.
191: */
192: int
1.28 deraadt 193: main(int argc, char *argv[])
1.1 deraadt 194: {
195: int c;
196: struct sigaction sa;
197: sigset_t mask;
198:
199: /* Dispose of random users. */
200: if (getuid() != 0) {
201: (void)fprintf(stderr, "init: %s\n", strerror(EPERM));
202: exit (1);
203: }
204:
205: /* System V users like to reexec init. */
206: if (getpid() != 1) {
207: (void)fprintf(stderr, "init: already running\n");
208: exit (1);
209: }
210:
211: /*
212: * Note that this does NOT open a file...
213: * Does 'init' deserve its own facility number?
214: */
215: openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH);
216:
217: /*
218: * Create an initial session.
219: */
220: if (setsid() < 0)
221: warning("initial setsid() failed: %m");
222:
223: /*
224: * Establish an initial user so that programs running
225: * single user do not freak out and die (like passwd).
226: */
227: if (setlogin("root") < 0)
228: warning("setlogin() failed: %m");
229:
230: /*
231: * This code assumes that we always get arguments through flags,
232: * never through bits set in some random machine register.
233: */
234: while ((c = getopt(argc, argv, "sf")) != -1)
235: switch (c) {
236: case 's':
237: requested_transition = single_user;
238: break;
239: case 'f':
240: runcom_mode = FASTBOOT;
241: break;
242: default:
243: warning("unrecognized flag '-%c'", c);
244: break;
245: }
246:
247: if (optind != argc)
248: warning("ignoring excess arguments");
249:
250: /*
251: * We catch or block signals rather than ignore them,
252: * so that they get reset on exec.
253: */
254: handle(badsys, SIGSYS, 0);
255: handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV,
1.33 deraadt 256: SIGBUS, SIGXCPU, SIGXFSZ, 0);
1.45 dlg 257: handle(transition_handler, SIGHUP, SIGINT, SIGTERM, SIGTSTP,
1.44 dlg 258: SIGUSR1, SIGUSR2, 0);
1.1 deraadt 259: handle(alrm_handler, SIGALRM, 0);
260: sigfillset(&mask);
261: delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS,
1.45 dlg 262: SIGXCPU, SIGXFSZ, SIGHUP, SIGINT, SIGTERM, SIGUSR1, SIGUSR2,
1.39 deraadt 263: SIGTSTP, SIGALRM, 0);
1.10 kstailey 264: sigprocmask(SIG_SETMASK, &mask, NULL);
1.15 deraadt 265: memset(&sa, 0, sizeof sa);
1.1 deraadt 266: sigemptyset(&sa.sa_mask);
267: sa.sa_flags = 0;
268: sa.sa_handler = SIG_IGN;
1.10 kstailey 269: (void) sigaction(SIGTTIN, &sa, NULL);
270: (void) sigaction(SIGTTOU, &sa, NULL);
1.1 deraadt 271:
272: /*
273: * Paranoia.
274: */
1.30 millert 275: close(STDIN_FILENO);
276: close(STDOUT_FILENO);
277: close(STDERR_FILENO);
1.1 deraadt 278:
279: /*
280: * Start the state machine.
281: */
282: transition(requested_transition);
283:
284: /*
285: * Should never reach here.
286: */
1.30 millert 287: exit(1);
1.1 deraadt 288: }
289:
290: /*
291: * Associate a function with a signal handler.
292: */
293: void
294: handle(sig_t handler, ...)
295: {
296: int sig;
297: struct sigaction sa;
1.12 deraadt 298: sigset_t mask_everything;
1.1 deraadt 299: va_list ap;
300:
301: va_start(ap, handler);
302:
1.15 deraadt 303: memset(&sa, 0, sizeof sa);
1.1 deraadt 304: sa.sa_handler = handler;
305: sigfillset(&mask_everything);
306:
1.11 deraadt 307: while ((sig = va_arg(ap, int))) {
1.1 deraadt 308: sa.sa_mask = mask_everything;
309: /* XXX SA_RESTART? */
310: sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0;
1.10 kstailey 311: sigaction(sig, &sa, NULL);
1.1 deraadt 312: }
313: va_end(ap);
314: }
315:
316: /*
317: * Delete a set of signals from a mask.
318: */
319: void
320: delset(sigset_t *maskp, ...)
321: {
322: int sig;
323: va_list ap;
324:
325: va_start(ap, maskp);
1.11 deraadt 326: while ((sig = va_arg(ap, int)))
1.1 deraadt 327: sigdelset(maskp, sig);
328: va_end(ap);
329: }
330:
331: /*
332: * Log a message and sleep for a while (to give someone an opportunity
333: * to read it and to save log or hardcopy output if the problem is chronic).
334: * NB: should send a message to the session logger to avoid blocking.
335: */
336: void
337: stall(char *message, ...)
338: {
339: va_list ap;
340:
341: va_start(ap, message);
342: vsyslog(LOG_ALERT, message, ap);
343: va_end(ap);
1.9 deraadt 344: closelog();
1.1 deraadt 345: sleep(STALL_TIMEOUT);
346: }
347:
348: /*
349: * Like stall(), but doesn't sleep.
350: * If cpp had variadic macros, the two functions could be #defines for another.
351: * NB: should send a message to the session logger to avoid blocking.
352: */
353: void
354: warning(char *message, ...)
355: {
356: va_list ap;
357:
358: va_start(ap, message);
359: vsyslog(LOG_ALERT, message, ap);
360: va_end(ap);
1.9 deraadt 361: closelog();
1.1 deraadt 362: }
363:
364: /*
365: * Log an emergency message.
366: * NB: should send a message to the session logger to avoid blocking.
367: */
368: void
369: emergency(char *message, ...)
370: {
1.28 deraadt 371: struct syslog_data sdata = SYSLOG_DATA_INIT;
1.1 deraadt 372: va_list ap;
373:
374: va_start(ap, message);
1.28 deraadt 375: vsyslog_r(LOG_EMERG, &sdata, message, ap);
1.1 deraadt 376: va_end(ap);
377: }
378:
379: /*
380: * Catch a SIGSYS signal.
381: *
382: * These may arise if a system does not support sysctl.
383: * We tolerate up to 25 of these, then throw in the towel.
384: */
385: void
1.28 deraadt 386: badsys(int sig)
1.1 deraadt 387: {
388: static int badcount = 0;
389:
390: if (badcount++ < 25)
391: return;
392: disaster(sig);
393: }
394:
395: /*
396: * Catch an unexpected signal.
397: */
398: void
1.28 deraadt 399: disaster(int sig)
1.1 deraadt 400: {
401: emergency("fatal signal: %s", strsignal(sig));
402:
403: sleep(STALL_TIMEOUT);
404: _exit(sig); /* reboot */
405: }
406:
407: /*
408: * Get the security level of the kernel.
409: */
410: int
1.28 deraadt 411: getsecuritylevel(void)
1.1 deraadt 412: {
413: #ifdef KERN_SECURELVL
414: int name[2], curlevel;
415: size_t len;
416:
417: name[0] = CTL_KERN;
418: name[1] = KERN_SECURELVL;
419: len = sizeof curlevel;
420: if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) {
421: emergency("cannot get kernel security level: %s",
422: strerror(errno));
423: return (-1);
424: }
425: return (curlevel);
426: #else
427: return (-1);
428: #endif
429: }
430:
431: /*
432: * Set the security level of the kernel.
433: */
434: void
1.28 deraadt 435: setsecuritylevel(int newlevel)
1.1 deraadt 436: {
437: #ifdef KERN_SECURELVL
438: int name[2], curlevel;
439:
440: curlevel = getsecuritylevel();
441: if (newlevel == curlevel)
442: return;
443: name[0] = CTL_KERN;
444: name[1] = KERN_SECURELVL;
445: if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) {
446: emergency(
447: "cannot change kernel security level from %d to %d: %s",
448: curlevel, newlevel, strerror(errno));
449: return;
450: }
451: #ifdef SECURE
452: warning("kernel security level changed from %d to %d",
453: curlevel, newlevel);
454: #endif
455: #endif
456: }
457:
458: /*
459: * Change states in the finite state machine.
460: * The initial state is passed as an argument.
461: */
462: void
1.28 deraadt 463: transition(state_t s)
1.1 deraadt 464: {
465: for (;;)
1.53 millert 466: s = (*state_funcs[s])();
1.1 deraadt 467: }
468:
469: /*
470: * Close out the accounting files for a login session.
471: * NB: should send a message to the session logger to avoid blocking.
472: */
473: void
1.28 deraadt 474: clear_session_logs(session_t *sp)
1.1 deraadt 475: {
476: char *line = sp->se_device + sizeof(_PATH_DEV) - 1;
477:
478: if (logout(line))
479: logwtmp(line, "", "");
480: }
481:
482: /*
483: * Start a session and allocate a controlling terminal.
484: * Only called by children of init after forking.
485: */
486: void
1.28 deraadt 487: setctty(char *name)
1.1 deraadt 488: {
489: int fd;
490:
491: (void) revoke(name);
1.28 deraadt 492: sleep(2); /* leave DTR low */
1.1 deraadt 493: if ((fd = open(name, O_RDWR)) == -1) {
494: stall("can't open %s: %m", name);
495: _exit(1);
496: }
497: if (login_tty(fd) == -1) {
498: stall("can't get %s for controlling terminal: %m", name);
499: _exit(1);
500: }
501: }
502:
503: /*
504: * Bring the system up single user.
505: */
1.53 millert 506: state_t
507: f_single_user(void)
1.1 deraadt 508: {
509: pid_t pid, wpid;
510: int status;
511: sigset_t mask;
1.52 deraadt 512: char shell[PATH_MAX]; /* Allocate space here */
513: char name[PATH_MAX]; /* Name (argv[0]) of shell */
1.1 deraadt 514: char *argv[2];
515: #ifdef SECURE
516: struct ttyent *typ;
517: struct passwd *pp;
518: static const char banner[] =
519: "Enter root password, or ^D to go multi-user\n";
520: char *clear, *password;
521: #endif
522:
1.4 weingart 523: /* Init shell and name */
1.26 deraadt 524: strlcpy(shell, _PATH_BSHELL, sizeof shell);
525: strlcpy(name, "-sh", sizeof name);
1.4 weingart 526:
1.1 deraadt 527: /*
528: * If the kernel is in secure mode, downgrade it to insecure mode.
529: */
530: if (getsecuritylevel() > 0)
531: setsecuritylevel(0);
532:
533: if ((pid = fork()) == 0) {
534: /*
535: * Start the single user session.
536: */
537: setctty(_PATH_CONSOLE);
538:
539: #ifdef SECURE
540: /*
541: * Check the root password.
542: * We don't care if the console is 'on' by default;
543: * it's the only tty that can be 'off' and 'secure'.
544: */
545: typ = getttynam("console");
546: pp = getpwnam("root");
1.5 deraadt 547: if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp &&
548: *pp->pw_passwd) {
1.29 millert 549: write(STDERR_FILENO, banner, sizeof banner - 1);
1.1 deraadt 550: for (;;) {
551: clear = getpass("Password:");
552: if (clear == 0 || *clear == '\0')
553: _exit(0);
554: password = crypt(clear, pp->pw_passwd);
555: memset(clear, 0, _PASSWORD_LEN);
556: if (strcmp(password, pp->pw_passwd) == 0)
557: break;
558: warning("single-user login failed\n");
559: }
560: }
561: endttyent();
562: endpwent();
563: #endif /* SECURE */
564:
565: #ifdef DEBUGSHELL
566: {
567: char altshell[128], *cp = altshell;
568: int num;
569:
570: #define SHREQUEST \
571: "Enter pathname of shell or RETURN for sh: "
1.26 deraadt 572:
1.1 deraadt 573: (void)write(STDERR_FILENO,
574: SHREQUEST, sizeof(SHREQUEST) - 1);
575: while ((num = read(STDIN_FILENO, cp, 1)) != -1 &&
576: num != 0 && *cp != '\n' && cp < &altshell[127])
1.21 deraadt 577: cp++;
1.1 deraadt 578: *cp = '\0';
1.4 weingart 579:
580: /* Copy in alternate shell */
581: if (altshell[0] != '\0'){
582: char *p;
583:
584: /* Binary to exec */
1.26 deraadt 585: strlcpy(shell, altshell, sizeof shell);
1.4 weingart 586:
587: /* argv[0] */
588: p = strrchr(altshell, '/');
589: if(p == NULL) p = altshell;
590: else p++;
591:
592: name[0] = '-';
1.26 deraadt 593: strlcpy(&name[1], p, sizeof name -1);
1.4 weingart 594: }
1.1 deraadt 595: }
596: #endif /* DEBUGSHELL */
597:
598: /*
599: * Unblock signals.
600: * We catch all the interesting ones,
601: * and those are reset to SIG_DFL on exec.
602: */
603: sigemptyset(&mask);
1.10 kstailey 604: sigprocmask(SIG_SETMASK, &mask, NULL);
1.1 deraadt 605:
606: /*
607: * Fire off a shell.
608: * If the default one doesn't work, try the Bourne shell.
609: */
1.4 weingart 610: argv[0] = name;
611: argv[1] = NULL;
1.1 deraadt 612: setenv("PATH", _PATH_STDPATH, 1);
613: execv(shell, argv);
614: emergency("can't exec %s for single user: %m", shell);
1.4 weingart 615:
616: argv[0] = "-sh";
617: argv[1] = NULL;
1.1 deraadt 618: execv(_PATH_BSHELL, argv);
619: emergency("can't exec %s for single user: %m", _PATH_BSHELL);
620: sleep(STALL_TIMEOUT);
621: _exit(1);
622: }
623:
624: if (pid == -1) {
625: /*
626: * We are seriously hosed. Do our best.
627: */
628: emergency("can't fork single-user shell, trying again");
1.10 kstailey 629: while (waitpid(-1, NULL, WNOHANG) > 0)
1.1 deraadt 630: continue;
1.53 millert 631: return single_user;
1.1 deraadt 632: }
633:
634: requested_transition = 0;
635: do {
636: if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
637: collect_child(wpid);
638: if (wpid == -1) {
639: if (errno == EINTR)
640: continue;
641: warning("wait for single-user shell failed: %m; restarting");
1.53 millert 642: return single_user;
1.1 deraadt 643: }
644: if (wpid == pid && WIFSTOPPED(status)) {
645: warning("init: shell stopped, restarting\n");
646: kill(pid, SIGCONT);
647: wpid = -1;
648: }
649: } while (wpid != pid && !requested_transition);
650:
651: if (requested_transition)
1.53 millert 652: return requested_transition;
1.1 deraadt 653:
654: if (!WIFEXITED(status)) {
1.27 todd 655: if (WTERMSIG(status) == SIGKILL) {
656: /*
657: * reboot(8) killed shell?
1.1 deraadt 658: */
659: warning("single user shell terminated.");
660: sleep(STALL_TIMEOUT);
661: _exit(0);
1.33 deraadt 662: } else {
1.1 deraadt 663: warning("single user shell terminated, restarting");
1.53 millert 664: return single_user;
1.1 deraadt 665: }
666: }
667:
668: runcom_mode = FASTBOOT;
1.53 millert 669: return runcom;
1.1 deraadt 670: }
671:
672: /*
673: * Run the system startup script.
674: */
1.53 millert 675: state_t
676: f_runcom(void)
1.1 deraadt 677: {
678: pid_t pid, wpid;
679: int status;
680: char *argv[4];
681: struct sigaction sa;
682:
683: if ((pid = fork()) == 0) {
1.15 deraadt 684: memset(&sa, 0, sizeof sa);
1.1 deraadt 685: sigemptyset(&sa.sa_mask);
686: sa.sa_flags = 0;
687: sa.sa_handler = SIG_IGN;
1.10 kstailey 688: (void) sigaction(SIGTSTP, &sa, NULL);
689: (void) sigaction(SIGHUP, &sa, NULL);
1.1 deraadt 690:
691: setctty(_PATH_CONSOLE);
692:
693: argv[0] = "sh";
694: argv[1] = _PATH_RUNCOM;
695: argv[2] = runcom_mode == AUTOBOOT ? "autoboot" : 0;
696: argv[3] = 0;
697:
1.10 kstailey 698: sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);
1.1 deraadt 699:
1.20 millert 700: setprocresources(RESOURCE_RC);
701:
1.1 deraadt 702: execv(_PATH_BSHELL, argv);
703: stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNCOM);
704: _exit(1); /* force single user mode */
705: }
706:
707: if (pid == -1) {
708: emergency("can't fork for %s on %s: %m",
709: _PATH_BSHELL, _PATH_RUNCOM);
1.10 kstailey 710: while (waitpid(-1, NULL, WNOHANG) > 0)
1.1 deraadt 711: continue;
712: sleep(STALL_TIMEOUT);
1.53 millert 713: return single_user;
1.1 deraadt 714: }
715:
716: /*
717: * Copied from single_user(). This is a bit paranoid.
718: */
719: do {
720: if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
721: collect_child(wpid);
722: if (wpid == -1) {
723: if (errno == EINTR)
724: continue;
725: warning("wait for %s on %s failed: %m; going to single user mode",
1.33 deraadt 726: _PATH_BSHELL, _PATH_RUNCOM);
1.53 millert 727: return single_user;
1.1 deraadt 728: }
729: if (wpid == pid && WIFSTOPPED(status)) {
730: warning("init: %s on %s stopped, restarting\n",
1.33 deraadt 731: _PATH_BSHELL, _PATH_RUNCOM);
1.1 deraadt 732: kill(pid, SIGCONT);
733: wpid = -1;
734: }
735: } while (wpid != pid);
736:
737: if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
738: requested_transition == catatonia) {
739: /* /etc/rc executed /sbin/reboot; wait for the end quietly */
740: sigset_t s;
741:
742: sigfillset(&s);
743: for (;;)
744: sigsuspend(&s);
745: }
746:
747: if (!WIFEXITED(status)) {
748: warning("%s on %s terminated abnormally, going to single user mode",
1.33 deraadt 749: _PATH_BSHELL, _PATH_RUNCOM);
1.53 millert 750: return single_user;
1.1 deraadt 751: }
752:
753: if (WEXITSTATUS(status))
1.53 millert 754: return single_user;
1.1 deraadt 755:
756: runcom_mode = AUTOBOOT; /* the default */
757: /* NB: should send a message to the session logger to avoid blocking. */
758: logwtmp("~", "reboot", "");
1.53 millert 759: return read_ttys;
1.1 deraadt 760: }
761:
762: /*
763: * Open the session database.
764: *
765: * NB: We could pass in the size here; is it necessary?
766: */
767: int
1.28 deraadt 768: start_session_db(void)
1.1 deraadt 769: {
770: if (session_db && (*session_db->close)(session_db))
771: emergency("session database close: %s", strerror(errno));
772: if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == 0) {
773: emergency("session database open: %s", strerror(errno));
774: return (1);
775: }
776: return (0);
777: }
778:
779: /*
780: * Add a new login session.
781: */
782: void
1.28 deraadt 783: add_session(session_t *sp)
1.1 deraadt 784: {
785: DBT key;
786: DBT data;
787:
788: key.data = &sp->se_process;
789: key.size = sizeof sp->se_process;
790: data.data = &sp;
791: data.size = sizeof sp;
792:
793: if ((*session_db->put)(session_db, &key, &data, 0))
794: emergency("insert %d: %s", sp->se_process, strerror(errno));
795: }
796:
797: /*
798: * Delete an old login session.
799: */
800: void
1.28 deraadt 801: del_session(session_t *sp)
1.1 deraadt 802: {
803: DBT key;
804:
805: key.data = &sp->se_process;
806: key.size = sizeof sp->se_process;
807:
808: if ((*session_db->del)(session_db, &key, 0))
809: emergency("delete %d: %s", sp->se_process, strerror(errno));
810: }
811:
812: /*
813: * Look up a login session by pid.
814: */
815: session_t *
816: find_session(pid_t pid)
817: {
818: DBT key;
819: DBT data;
820: session_t *ret;
821:
822: key.data = &pid;
823: key.size = sizeof pid;
824: if ((*session_db->get)(session_db, &key, &data, 0) != 0)
1.29 millert 825: return (0);
1.1 deraadt 826: memcpy(&ret, data.data, sizeof(ret));
1.29 millert 827: return (ret);
1.1 deraadt 828: }
829:
830: /*
831: * Construct an argument vector from a command line.
832: */
833: char **
1.28 deraadt 834: construct_argv(char *command)
1.1 deraadt 835: {
1.23 mpech 836: int argc = 0;
1.54 ! deraadt 837: char **argv = calloc((strlen(command) + 1) / 2 + 1, sizeof (char *));
1.1 deraadt 838: static const char separators[] = " \t";
839:
1.38 otto 840: if (argv == NULL)
1.29 millert 841: return (0);
1.38 otto 842:
843: if ((argv[argc++] = strtok(command, separators)) == 0) {
844: free(argv);
845: return (0);
846: }
1.11 deraadt 847: while ((argv[argc++] = strtok(NULL, separators)))
1.1 deraadt 848: continue;
1.29 millert 849: return (argv);
1.1 deraadt 850: }
851:
852: /*
853: * Deallocate a session descriptor.
854: */
855: void
1.28 deraadt 856: free_session(session_t *sp)
1.1 deraadt 857: {
858: free(sp->se_device);
859: if (sp->se_getty) {
860: free(sp->se_getty);
861: free(sp->se_getty_argv);
862: }
863: if (sp->se_window) {
864: free(sp->se_window);
865: free(sp->se_window_argv);
866: }
867: free(sp);
868: }
869:
870: /*
871: * Allocate a new session descriptor.
872: */
873: session_t *
1.28 deraadt 874: new_session(session_t *sprev, int session_index, struct ttyent *typ)
1.1 deraadt 875: {
1.23 mpech 876: session_t *sp;
1.1 deraadt 877:
878: if ((typ->ty_status & TTY_ON) == 0 ||
879: typ->ty_name == 0 ||
880: typ->ty_getty == 0)
1.29 millert 881: return (0);
1.1 deraadt 882:
1.50 tedu 883: sp = calloc(1, sizeof (session_t));
884: if (sp == NULL)
885: err(1, "calloc");
1.1 deraadt 886:
887: sp->se_flags = SE_PRESENT;
888: sp->se_index = session_index;
889:
1.37 deraadt 890: if (asprintf(&sp->se_device, "%s%s", _PATH_DEV, typ->ty_name) == -1)
891: err(1, "asprintf");
1.1 deraadt 892:
893: if (setupargv(sp, typ) == 0) {
894: free_session(sp);
895: return (0);
896: }
897:
898: sp->se_next = 0;
899: if (sprev == 0) {
900: sessions = sp;
901: sp->se_prev = 0;
902: } else {
903: sprev->se_next = sp;
904: sp->se_prev = sprev;
905: }
906:
1.29 millert 907: return (sp);
1.1 deraadt 908: }
909:
910: /*
911: * Calculate getty and if useful window argv vectors.
912: */
913: int
1.28 deraadt 914: setupargv(session_t *sp, struct ttyent *typ)
1.1 deraadt 915: {
916: if (sp->se_getty) {
917: free(sp->se_getty);
918: free(sp->se_getty_argv);
919: }
1.37 deraadt 920: if (asprintf(&sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name) == -1)
921: err(1, "asprintf");
1.1 deraadt 922: sp->se_getty_argv = construct_argv(sp->se_getty);
923: if (sp->se_getty_argv == 0) {
924: warning("can't parse getty for port %s", sp->se_device);
925: free(sp->se_getty);
926: sp->se_getty = 0;
927: return (0);
928: }
929: if (typ->ty_window) {
930: if (sp->se_window)
931: free(sp->se_window);
932: sp->se_window = strdup(typ->ty_window);
1.34 deraadt 933: if (sp->se_window == NULL) {
934: warning("can't allocate window");
935: return (0);
936: }
1.1 deraadt 937: sp->se_window_argv = construct_argv(sp->se_window);
1.34 deraadt 938: if (sp->se_window_argv == NULL) {
1.1 deraadt 939: warning("can't parse window for port %s",
1.33 deraadt 940: sp->se_device);
1.1 deraadt 941: free(sp->se_window);
1.34 deraadt 942: sp->se_window = NULL;
1.1 deraadt 943: return (0);
944: }
945: }
946: return (1);
947: }
948:
949: /*
950: * Walk the list of ttys and create sessions for each active line.
951: */
1.53 millert 952: state_t
953: f_read_ttys(void)
1.1 deraadt 954: {
955: int session_index = 0;
1.23 mpech 956: session_t *sp, *snext;
957: struct ttyent *typ;
1.1 deraadt 958:
959: /*
960: * Destroy any previous session state.
961: * There shouldn't be any, but just in case...
962: */
963: for (sp = sessions; sp; sp = snext) {
964: if (sp->se_process)
965: clear_session_logs(sp);
966: snext = sp->se_next;
967: free_session(sp);
968: }
969: sessions = 0;
970: if (start_session_db())
1.53 millert 971: return single_user;
1.1 deraadt 972:
973: /*
974: * Allocate a session entry for each active port.
975: * Note that sp starts at 0.
976: */
1.11 deraadt 977: while ((typ = getttyent()))
978: if ((snext = new_session(sp, ++session_index, typ)))
1.1 deraadt 979: sp = snext;
980:
981: endttyent();
982:
1.53 millert 983: return multi_user;
1.1 deraadt 984: }
985:
986: /*
987: * Start a window system running.
988: */
989: void
1.28 deraadt 990: start_window_system(session_t *sp)
1.1 deraadt 991: {
992: pid_t pid;
993: sigset_t mask;
994:
995: if ((pid = fork()) == -1) {
996: emergency("can't fork for window system on port %s: %m",
1.33 deraadt 997: sp->se_device);
1.1 deraadt 998: /* hope that getty fails and we can try again */
999: return;
1000: }
1001:
1002: if (pid)
1003: return;
1004:
1005: sigemptyset(&mask);
1.10 kstailey 1006: sigprocmask(SIG_SETMASK, &mask, NULL);
1.1 deraadt 1007:
1008: if (setsid() < 0)
1009: emergency("setsid failed (window) %m");
1010:
1.20 millert 1011: setprocresources(RESOURCE_WINDOW);
1012:
1.1 deraadt 1013: execv(sp->se_window_argv[0], sp->se_window_argv);
1014: stall("can't exec window system '%s' for port %s: %m",
1.33 deraadt 1015: sp->se_window_argv[0], sp->se_device);
1.1 deraadt 1016: _exit(1);
1017: }
1018:
1019: /*
1020: * Start a login session running.
1.6 deraadt 1021: * For first open, man-handle tty directly to determine if it
1022: * really exists. It is not efficient to spawn gettys on devices
1.27 todd 1023: * that do not exist.
1.1 deraadt 1024: */
1025: pid_t
1.28 deraadt 1026: start_getty(session_t *sp)
1.1 deraadt 1027: {
1028: pid_t pid;
1029: sigset_t mask;
1.10 kstailey 1030: time_t current_time = time(NULL);
1.6 deraadt 1031: int p[2], new = 1;
1032:
1033: if (sp->se_flags & SE_DEVEXISTS)
1034: new = 0;
1035:
1036: if (new) {
1037: if (pipe(p) == -1)
1.29 millert 1038: return (-1);
1.6 deraadt 1039: }
1.1 deraadt 1040:
1041: /*
1042: * fork(), not vfork() -- we can't afford to block.
1043: */
1044: if ((pid = fork()) == -1) {
1045: emergency("can't fork for getty on port %s: %m", sp->se_device);
1.29 millert 1046: return (-1);
1.1 deraadt 1047: }
1048:
1.6 deraadt 1049: if (pid) {
1050: if (new) {
1051: char c;
1052:
1053: close(p[1]);
1054: if (read(p[0], &c, 1) != 1) {
1055: close(p[0]);
1.29 millert 1056: return (-1);
1.6 deraadt 1057: }
1058: close(p[0]);
1059: if (c == '1')
1060: sp->se_flags |= SE_DEVEXISTS;
1061: else
1062: sp->se_flags |= SE_SHUTDOWN;
1063: }
1.29 millert 1064: return (pid);
1.6 deraadt 1065: }
1066: if (new) {
1067: int fd;
1068:
1069: close(p[0]);
1070: fd = open(sp->se_device, O_RDONLY | O_NONBLOCK, 0666);
1071: if (fd == -1 && (errno == ENXIO || errno == ENOENT ||
1072: errno == EISDIR)) {
1073: (void)write(p[1], "0", 1);
1074: close(p[1]);
1075: _exit(1);
1076: }
1077: (void)write(p[1], "1", 1);
1078: close(p[1]);
1079: close(fd);
1080: sleep(1);
1081: }
1.1 deraadt 1082:
1083: if (current_time > sp->se_started &&
1084: current_time - sp->se_started < GETTY_SPACING) {
1085: warning("getty repeating too quickly on port %s, sleeping",
1.33 deraadt 1086: sp->se_device);
1.46 deraadt 1087: sleep(GETTY_SLEEP);
1.1 deraadt 1088: }
1089:
1090: if (sp->se_window) {
1091: start_window_system(sp);
1092: sleep(WINDOW_WAIT);
1093: }
1094:
1095: sigemptyset(&mask);
1.10 kstailey 1096: sigprocmask(SIG_SETMASK, &mask, NULL);
1.1 deraadt 1097:
1.20 millert 1098: setprocresources(RESOURCE_GETTY);
1099:
1.1 deraadt 1100: execv(sp->se_getty_argv[0], sp->se_getty_argv);
1101: stall("can't exec getty '%s' for port %s: %m",
1.33 deraadt 1102: sp->se_getty_argv[0], sp->se_device);
1.1 deraadt 1103: _exit(1);
1104: }
1105:
1106: /*
1107: * Collect exit status for a child.
1108: * If an exiting login, start a new login running.
1109: */
1110: void
1111: collect_child(pid_t pid)
1112: {
1.23 mpech 1113: session_t *sp, *sprev, *snext;
1.1 deraadt 1114:
1.30 millert 1115: if (sessions == NULL)
1.1 deraadt 1116: return;
1117:
1.30 millert 1118: if ((sp = find_session(pid)) == NULL)
1.1 deraadt 1119: return;
1120:
1121: clear_session_logs(sp);
1.13 millert 1122: login_fbtab(sp->se_device + sizeof(_PATH_DEV) - 1, 0, 0);
1.1 deraadt 1123: del_session(sp);
1124: sp->se_process = 0;
1125:
1126: if (sp->se_flags & SE_SHUTDOWN) {
1.11 deraadt 1127: if ((sprev = sp->se_prev))
1.1 deraadt 1128: sprev->se_next = sp->se_next;
1129: else
1130: sessions = sp->se_next;
1.11 deraadt 1131: if ((snext = sp->se_next))
1.1 deraadt 1132: snext->se_prev = sp->se_prev;
1133: free_session(sp);
1134: return;
1135: }
1136:
1137: if ((pid = start_getty(sp)) == -1) {
1138: /* serious trouble */
1139: requested_transition = clean_ttys;
1140: return;
1141: }
1142:
1143: sp->se_process = pid;
1.10 kstailey 1144: sp->se_started = time(NULL);
1.1 deraadt 1145: add_session(sp);
1146: }
1147:
1148: /*
1149: * Catch a signal and request a state transition.
1150: */
1151: void
1.28 deraadt 1152: transition_handler(int sig)
1.1 deraadt 1153: {
1154:
1155: switch (sig) {
1156: case SIGHUP:
1157: requested_transition = clean_ttys;
1158: break;
1.45 dlg 1159: case SIGINT:
1.44 dlg 1160: requested_transition = do_reboot;
1161: break;
1.1 deraadt 1162: case SIGTERM:
1163: requested_transition = death;
1164: break;
1.16 deraadt 1165: case SIGUSR1:
1166: requested_transition = nice_death;
1167: break;
1.39 deraadt 1168: case SIGUSR2:
1169: requested_transition = hard_death;
1170: break;
1.1 deraadt 1171: case SIGTSTP:
1172: requested_transition = catatonia;
1173: break;
1174: default:
1175: requested_transition = 0;
1176: break;
1177: }
1178: }
1179:
1180: /*
1181: * Take the system multiuser.
1182: */
1.53 millert 1183: state_t
1184: f_multi_user(void)
1.1 deraadt 1185: {
1186: pid_t pid;
1.23 mpech 1187: session_t *sp;
1.1 deraadt 1188:
1189: /*
1190: * If the administrator has not set the security level to -1
1191: * to indicate that the kernel should not run multiuser in secure
1.27 todd 1192: * mode, and the run script has not set a higher level of security
1.1 deraadt 1193: * than level 1, then put the kernel into secure mode.
1194: */
1.49 millert 1195: if (requested_transition != catatonia) {
1196: if (getsecuritylevel() == 0)
1197: setsecuritylevel(1);
1198: }
1199:
1200: requested_transition = 0;
1.1 deraadt 1201:
1202: for (sp = sessions; sp; sp = sp->se_next) {
1203: if (sp->se_process)
1204: continue;
1205: if ((pid = start_getty(sp)) == -1) {
1206: /* serious trouble */
1207: requested_transition = clean_ttys;
1208: break;
1209: }
1210: sp->se_process = pid;
1.10 kstailey 1211: sp->se_started = time(NULL);
1.1 deraadt 1212: add_session(sp);
1213: }
1214:
1215: while (!requested_transition)
1.10 kstailey 1216: if ((pid = waitpid(-1, NULL, 0)) != -1)
1.1 deraadt 1217: collect_child(pid);
1218:
1.53 millert 1219: return requested_transition;
1.1 deraadt 1220: }
1221:
1222: /*
1223: * This is an n-squared algorithm. We hope it isn't run often...
1224: */
1.53 millert 1225: state_t
1226: f_clean_ttys(void)
1.1 deraadt 1227: {
1.23 mpech 1228: session_t *sp, *sprev;
1229: struct ttyent *typ;
1230: int session_index = 0;
1231: int devlen;
1.1 deraadt 1232:
1233: for (sp = sessions; sp; sp = sp->se_next)
1234: sp->se_flags &= ~SE_PRESENT;
1235:
1236: devlen = sizeof(_PATH_DEV) - 1;
1.11 deraadt 1237: while ((typ = getttyent())) {
1.1 deraadt 1238: ++session_index;
1239:
1240: for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next)
1241: if (strcmp(typ->ty_name, sp->se_device + devlen) == 0)
1242: break;
1243:
1244: if (sp) {
1245: sp->se_flags |= SE_PRESENT;
1246: if (sp->se_index != session_index) {
1247: warning("port %s changed utmp index from %d to %d",
1.33 deraadt 1248: sp->se_device, sp->se_index,
1249: session_index);
1.1 deraadt 1250: sp->se_index = session_index;
1251: }
1252: if ((typ->ty_status & TTY_ON) == 0 ||
1253: typ->ty_getty == 0) {
1254: sp->se_flags |= SE_SHUTDOWN;
1255: kill(sp->se_process, SIGHUP);
1256: continue;
1257: }
1258: sp->se_flags &= ~SE_SHUTDOWN;
1259: if (setupargv(sp, typ) == 0) {
1260: warning("can't parse getty for port %s",
1.33 deraadt 1261: sp->se_device);
1.1 deraadt 1262: sp->se_flags |= SE_SHUTDOWN;
1263: kill(sp->se_process, SIGHUP);
1264: }
1265: continue;
1266: }
1267:
1268: new_session(sprev, session_index, typ);
1269: }
1270:
1271: endttyent();
1272:
1273: for (sp = sessions; sp; sp = sp->se_next)
1274: if ((sp->se_flags & SE_PRESENT) == 0) {
1275: sp->se_flags |= SE_SHUTDOWN;
1276: kill(sp->se_process, SIGHUP);
1277: }
1278:
1.53 millert 1279: return multi_user;
1.1 deraadt 1280: }
1281:
1282: /*
1283: * Block further logins.
1284: */
1.53 millert 1285: state_t
1286: f_catatonia(void)
1.1 deraadt 1287: {
1.23 mpech 1288: session_t *sp;
1.1 deraadt 1289:
1290: for (sp = sessions; sp; sp = sp->se_next)
1291: sp->se_flags |= SE_SHUTDOWN;
1292:
1.53 millert 1293: return multi_user;
1.1 deraadt 1294: }
1295:
1296: /*
1297: * Note SIGALRM.
1298: */
1299: void
1.28 deraadt 1300: alrm_handler(int sig)
1.1 deraadt 1301: {
1302: clang = 1;
1.16 deraadt 1303: }
1304:
1.39 deraadt 1305: int death_howto = RB_HALT;
1.44 dlg 1306:
1307: /*
1308: * Reboot the system.
1309: */
1.53 millert 1310: state_t
1311: f_do_reboot(void)
1.44 dlg 1312: {
1313: death_howto = RB_AUTOBOOT;
1.53 millert 1314: return nice_death;
1.44 dlg 1315: }
1.39 deraadt 1316:
1317: /*
1318: * Bring the system down nicely, then we must powerdown because something
1319: * is very wrong.
1320: */
1.53 millert 1321: state_t
1322: f_hard_death(void)
1.39 deraadt 1323: {
1324: death_howto |= RB_POWERDOWN;
1.53 millert 1325: return nice_death;
1.39 deraadt 1326: }
1327:
1.16 deraadt 1328: /*
1329: * Bring the system down to single user nicely, after run the shutdown script.
1330: */
1.53 millert 1331: state_t
1332: f_nice_death(void)
1.16 deraadt 1333: {
1.23 mpech 1334: session_t *sp;
1335: int i;
1.16 deraadt 1336: pid_t pid;
1337: static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL };
1338: int status;
1.42 phessler 1339:
1.47 halex 1340: #ifdef CPU_LIDSUSPEND
1.42 phessler 1341: int lidsuspend_mib[] = {CTL_MACHDEP, CPU_LIDSUSPEND};
1342: int dontsuspend = 0;
1343:
1344: if ((death_howto & RB_POWERDOWN) &&
1345: (sysctl(lidsuspend_mib, 2, NULL, NULL, &dontsuspend,
1.48 millert 1346: sizeof(dontsuspend)) == -1) && (errno != EOPNOTSUPP))
1.42 phessler 1347: warning("cannot disable lid suspend");
1348: #endif
1.16 deraadt 1349:
1350: for (sp = sessions; sp; sp = sp->se_next) {
1351: sp->se_flags &= ~SE_PRESENT;
1352: sp->se_flags |= SE_SHUTDOWN;
1353: kill(sp->se_process, SIGHUP);
1354: }
1355:
1.36 markus 1356: /* terminate the accounting process */
1357: acct(NULL);
1358:
1.16 deraadt 1359: /* NB: should send a message to the session logger to avoid blocking. */
1360: logwtmp("~", "shutdown", "");
1361:
1.17 deraadt 1362: if (access(_PATH_RUNCOM, R_OK) != -1) {
1.16 deraadt 1363: struct sigaction sa;
1364:
1365: switch ((pid = fork())) {
1366: case -1:
1367: break;
1368: case 0:
1369:
1370: memset(&sa, 0, sizeof sa);
1371: sigemptyset(&sa.sa_mask);
1372: sa.sa_flags = 0;
1373: sa.sa_handler = SIG_IGN;
1374: (void) sigaction(SIGTSTP, &sa, NULL);
1375: (void) sigaction(SIGHUP, &sa, NULL);
1376:
1377: setctty(_PATH_CONSOLE);
1378:
1379: sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);
1380:
1.17 deraadt 1381: execl(_PATH_BSHELL, "sh", _PATH_RUNCOM, "shutdown",
1.22 deraadt 1382: (char *)NULL);
1.17 deraadt 1383: stall("can't exec %s for %s %s: %m", _PATH_BSHELL,
1384: _PATH_RUNCOM, "shutdown");
1.16 deraadt 1385: _exit(1);
1386: default:
1387: waitpid(pid, &status, 0);
1388: if (WIFEXITED(status) && WEXITSTATUS(status) == 2)
1.39 deraadt 1389: death_howto |= RB_POWERDOWN;
1.16 deraadt 1390: }
1391: }
1392:
1393: for (i = 0; i < 3; ++i) {
1394: if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH)
1395: goto die;
1396:
1397: clang = 0;
1398: alarm(DEATH_WATCH);
1.33 deraadt 1399: do {
1.16 deraadt 1400: if ((pid = waitpid(-1, NULL, 0)) != -1)
1401: collect_child(pid);
1.33 deraadt 1402: } while (clang == 0 && errno != ECHILD);
1.16 deraadt 1403:
1404: if (errno == ECHILD)
1405: goto die;
1406: }
1407:
1408: warning("some processes would not die; ps axl advised");
1409:
1410: die:
1.39 deraadt 1411: reboot(death_howto);
1.16 deraadt 1412:
1413: /* ... and if that fails.. oh well */
1.53 millert 1414: return single_user;
1.1 deraadt 1415: }
1416:
1417: /*
1418: * Bring the system down to single user.
1419: */
1.53 millert 1420: state_t
1421: f_death(void)
1.1 deraadt 1422: {
1.23 mpech 1423: session_t *sp;
1424: int i;
1.1 deraadt 1425: pid_t pid;
1426: static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL };
1.36 markus 1427:
1428: /* terminate the accounting process */
1429: acct(NULL);
1.1 deraadt 1430:
1431: for (sp = sessions; sp; sp = sp->se_next)
1432: sp->se_flags |= SE_SHUTDOWN;
1433:
1434: /* NB: should send a message to the session logger to avoid blocking. */
1435: logwtmp("~", "shutdown", "");
1436:
1437: for (i = 0; i < 3; ++i) {
1438: if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH)
1.53 millert 1439: return single_user;
1.1 deraadt 1440:
1441: clang = 0;
1442: alarm(DEATH_WATCH);
1.33 deraadt 1443: do {
1.10 kstailey 1444: if ((pid = waitpid(-1, NULL, 0)) != -1)
1.1 deraadt 1445: collect_child(pid);
1.33 deraadt 1446: } while (clang == 0 && errno != ECHILD);
1.1 deraadt 1447:
1448: if (errno == ECHILD)
1.53 millert 1449: return single_user;
1.1 deraadt 1450: }
1451:
1452: warning("some processes would not die; ps axl advised");
1453:
1.53 millert 1454: return single_user;
1.1 deraadt 1455: }
1.20 millert 1456:
1457: #ifdef LOGIN_CAP
1458: void
1.28 deraadt 1459: setprocresources(char *class)
1.20 millert 1460: {
1461: login_cap_t *lc;
1462:
1463: if ((lc = login_getclass(class)) != NULL) {
1464: setusercontext(lc, NULL, 0,
1465: LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK);
1466: login_close(lc);
1467: }
1468: }
1469: #endif