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