1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Donn Seeley at UUNET Technologies, Inc. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 char copyright[] = 13 "@(#) Copyright (c) 1991 The Regents of the University of California.\n\ 14 All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)init.c 6.5 (Berkeley) 07/25/91"; 19 #endif /* not lint */ 20 21 #include <sys/types.h> 22 #include <sys/wait.h> 23 #include <db.h> 24 #include <errno.h> 25 #include <fcntl.h> 26 #include <signal.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <syslog.h> 30 #include <time.h> 31 #include <ttyent.h> 32 #include <unistd.h> 33 34 #ifdef __STDC__ 35 #include <stdarg.h> 36 #else 37 #include <varargs.h> 38 #endif 39 40 #ifdef SECURE 41 #include <pwd.h> 42 #endif 43 44 #include "pathnames.h" 45 46 /* 47 * Until the mythical util.h arrives... 48 */ 49 extern int login_tty __P((int)); 50 extern int logout __P((const char *)); 51 extern void logwtmp __P((const char *, const char *, const char *)); 52 53 /* 54 * Sleep times; used to prevent thrashing. 55 */ 56 #define GETTY_SPACING 10 /* fork getty on a port every N secs */ 57 #define WINDOW_WAIT 3 /* wait N secs after starting window */ 58 #define STALL_TIMEOUT 30 /* wait N secs after warning */ 59 #define DEATH_WATCH 10 /* wait N secs for procs to die */ 60 61 void handle __P((sig_t, ...)); 62 void delset __P((sigset_t *, ...)); 63 64 void stall __P((char *, ...)); 65 void warning __P((char *, ...)); 66 void emergency __P((char *, ...)); 67 void disaster __P((int)); 68 69 /* 70 * We really need a recursive typedef... 71 * The following at least guarantees that the return type of (*state_t)() 72 * is sufficiently wide to hold a function pointer. 73 */ 74 typedef long (*state_func_t) __P((void)); 75 typedef state_func_t (*state_t) __P((void)); 76 77 state_func_t single_user __P((void)); 78 state_func_t runcom __P((void)); 79 state_func_t read_ttys __P((void)); 80 state_func_t multi_user __P((void)); 81 state_func_t clean_ttys __P((void)); 82 state_func_t catatonia __P((void)); 83 state_func_t death __P((void)); 84 85 enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT; 86 87 void transition __P((state_t)); 88 state_t requested_transition = runcom; 89 90 void setctty __P((char *)); 91 92 typedef struct session { 93 int se_index; /* index of entry in ttys file */ 94 pid_t se_process; /* controlling process */ 95 time_t se_started; /* used to avoid thrashing */ 96 int se_flags; /* status of session */ 97 #define SE_SHUTDOWN 0x1 /* session won't be restarted */ 98 char *se_device; /* filename of port */ 99 char *se_getty; /* what to run on that port */ 100 char **se_getty_argv; /* pre-parsed argument array */ 101 char *se_window; /* window system (started only once) */ 102 char **se_window_argv; /* pre-parsed argument array */ 103 struct session *se_prev; 104 struct session *se_next; 105 } session_t; 106 107 void free_session __P((session_t *)); 108 session_t *new_session __P((session_t *, int, struct ttyent *)); 109 session_t *sessions; 110 111 char **construct_argv __P((char *)); 112 void start_window_system __P((session_t *)); 113 void collect_child __P((int)); 114 pid_t start_getty __P((session_t *)); 115 void transition_handler __P((int)); 116 void alrm_handler __P((int)); 117 int clang; 118 119 int start_logger __P((void)); 120 void clear_session_logs __P((session_t *)); 121 int logger_enable; 122 123 int start_session_db __P((void)); 124 void add_session __P((session_t *)); 125 void del_session __P((session_t *)); 126 session_t *find_session __P((pid_t)); 127 DB *session_db; 128 129 /* 130 * The mother of all processes. 131 */ 132 int 133 main(argc, argv) 134 int argc; 135 char **argv; 136 { 137 int c; 138 struct sigaction sa; 139 sigset_t mask; 140 141 /* 142 * Silently dispose of random users running this program. 143 */ 144 if (getuid() != 0) 145 return 1; 146 147 /* 148 * Note that this does NOT open a file... 149 * Does 'init' deserve its own facility number? 150 */ 151 openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH); 152 153 /* 154 * Create an initial session. 155 */ 156 if (setsid() < 0) 157 syslog(LOG_ERR, "setsid failed (initial) %m"); 158 159 /* 160 * This code assumes that we always get arguments through flags, 161 * never through bits set in some random machine register. 162 */ 163 while ((c = getopt(argc, argv, "sf")) != -1) 164 switch (c) { 165 case 's': 166 requested_transition = single_user; 167 break; 168 case 'f': 169 runcom_mode = FASTBOOT; 170 break; 171 default: 172 warning("unrecognized flag '-%c'", c); 173 break; 174 } 175 176 if (optind != argc) 177 warning("ignoring excess arguments"); 178 179 /* 180 * We catch or block signals rather than ignore them, 181 * so that they get reset on exec. 182 */ 183 handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV, 184 SIGBUS, SIGSYS, SIGXCPU, SIGXFSZ, 0); 185 handle(transition_handler, SIGHUP, SIGTERM, SIGTSTP, 0); 186 handle(alrm_handler, SIGALRM, 0); 187 sigfillset(&mask); 188 delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS, 189 SIGXCPU, SIGXFSZ, SIGHUP, SIGTERM, SIGTSTP, SIGALRM, 0); 190 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 191 sigemptyset(&sa.sa_mask); 192 sa.sa_flags = 0; 193 sa.sa_handler = SIG_IGN; 194 (void) sigaction(SIGTTIN, &sa, (struct sigaction *)0); 195 (void) sigaction(SIGTTOU, &sa, (struct sigaction *)0); 196 197 /* 198 * Paranoia. 199 */ 200 close(0); 201 close(1); 202 close(2); 203 204 /* 205 * Start the state machine. 206 */ 207 transition(requested_transition); 208 209 /* 210 * Should never reach here. 211 */ 212 return 1; 213 } 214 215 /* 216 * Associate a function with a signal handler. 217 */ 218 void 219 #ifdef __STDC__ 220 handle(sig_t handler, ...) 221 #else 222 handle(va_alist) 223 va_dcl 224 #endif 225 { 226 int sig; 227 struct sigaction sa; 228 int mask_everything; 229 va_list ap; 230 #ifndef __STDC__ 231 sig_t handler; 232 233 va_start(ap); 234 handler = va_arg(ap, sig_t); 235 #else 236 va_start(ap, handler); 237 #endif 238 239 sa.sa_handler = handler; 240 sigfillset(&mask_everything); 241 242 while (sig = va_arg(ap, int)) { 243 sa.sa_mask = mask_everything; 244 /* XXX SA_RESTART? */ 245 sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0; 246 sigaction(sig, &sa, (struct sigaction *) 0); 247 } 248 } 249 250 /* 251 * Delete a set of signals from a mask. 252 */ 253 void 254 #ifdef __STDC__ 255 delset(sigset_t *maskp, ...) 256 #else 257 delset(va_alist) 258 va_dcl 259 #endif 260 { 261 int sig; 262 va_list ap; 263 #ifndef __STDC__ 264 sigset_t *maskp; 265 266 va_start(ap); 267 maskp = va_arg(ap, sigset_t *); 268 #else 269 va_start(ap, maskp); 270 #endif 271 272 while (sig = va_arg(ap, int)) 273 sigdelset(maskp, sig); 274 } 275 276 /* 277 * Log a message and sleep for a while (to give someone an opportunity 278 * to read it and to save log or hardcopy output if the problem is chronic). 279 * NB: should send a message to the session logger to avoid blocking. 280 */ 281 void 282 #ifdef __STDC__ 283 stall(char *message, ...) 284 #else 285 stall(va_alist) 286 va_dcl 287 #endif 288 { 289 pid_t pid; 290 va_list ap; 291 #ifndef __STDC__ 292 char *message; 293 294 va_start(ap); 295 message = va_arg(ap, char *); 296 #else 297 va_start(ap, message); 298 #endif 299 300 vsyslog(LOG_ALERT, message, ap); 301 va_end(ap); 302 sleep(STALL_TIMEOUT); 303 } 304 305 /* 306 * Like stall(), but doesn't sleep. 307 * If cpp had variadic macros, the two functions could be #defines for another. 308 * NB: should send a message to the session logger to avoid blocking. 309 */ 310 void 311 #ifdef __STDC__ 312 warning(char *message, ...) 313 #else 314 warning(va_alist) 315 va_dcl 316 #endif 317 { 318 va_list ap; 319 #ifndef __STDC__ 320 char *message; 321 322 va_start(ap); 323 message = va_arg(ap, char *); 324 #else 325 va_start(ap, message); 326 #endif 327 328 vsyslog(LOG_ALERT, message, ap); 329 va_end(ap); 330 } 331 332 /* 333 * Log an emergency message. 334 * NB: should send a message to the session logger to avoid blocking. 335 */ 336 void 337 #ifdef __STDC__ 338 emergency(char *message, ...) 339 #else 340 emergency(va_alist) 341 va_dcl 342 #endif 343 { 344 va_list ap; 345 #ifndef __STDC__ 346 char *message; 347 348 va_start(ap); 349 message = va_arg(ap, char *); 350 #else 351 va_start(ap, message); 352 #endif 353 354 vsyslog(LOG_EMERG, message, ap); 355 va_end(ap); 356 } 357 358 /* 359 * Catch an unexpected signal. 360 */ 361 void 362 disaster(sig) 363 int sig; 364 { 365 emergency("fatal signal: %s", 366 sig < (unsigned) NSIG ? sys_siglist[sig] : "unknown signal"); 367 368 sleep(STALL_TIMEOUT); 369 _exit(sig); /* reboot */ 370 } 371 372 /* 373 * Change states in the finite state machine. 374 * The initial state is passed as an argument. 375 */ 376 void 377 transition(s) 378 state_t s; 379 { 380 for (;;) 381 s = (state_t) (*s)(); 382 } 383 384 /* 385 * We send requests for session logging to another process for two reasons. 386 * First, we don't want to block if the log files go away (e.g. because 387 * one or more are on hard-mounted NFS systems whose server crashes). 388 * Second, despite all the crud already contained in init, it still isn't 389 * right that init should care about session logging record formats and files. 390 * We could use explicit 'Unix' IPC for this, but let's try to be POSIX... 391 */ 392 int 393 start_logger() 394 { 395 static char *argv[] = { _PATH_SLOGGER, 0 }; 396 int fd, pfd[2]; 397 pid_t pid; 398 sigset_t mask; 399 400 if (pipe(pfd) == -1) { 401 warning("session logging disabled: can't make pipe to %s: %m", 402 argv[0]); 403 return -1; 404 } 405 if ((pid = fork()) == -1) { 406 emergency("session logging disabled: can't fork for %s: %m", 407 argv[0]); 408 return -1; 409 } 410 411 if (pid == 0) { 412 close(pfd[1]); 413 if (pfd[0] != 0) { 414 dup2(pfd[0], 0); 415 close(pfd[0]); 416 } 417 if ((fd = open(_PATH_DEVNULL, O_WRONLY)) != -1) { 418 if (fd != 1) 419 dup2(fd, 1); 420 if (fd != 2) 421 dup2(fd, 2); 422 if (fd != 1 && fd != 2) 423 close(fd); 424 } else { 425 /* paranoid */ 426 close(1); 427 close(2); 428 } 429 sigemptyset(&mask); 430 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 431 execv(argv[0], argv); 432 stall("can't exec %s: %m", argv[0]); 433 _exit(1); 434 } 435 436 close(pfd[0]); 437 fcntl(pfd[1], F_SETFD, FD_CLOEXEC); 438 fcntl(pfd[1], F_SETFL, O_NONBLOCK); 439 440 return pfd[1]; 441 } 442 443 /* 444 * Close out the accounting files for a login session. 445 * NB: should send a message to the session logger to avoid blocking. 446 */ 447 void 448 clear_session_logs(sp) 449 session_t *sp; 450 { 451 if (logout(sp->se_device)) 452 logwtmp(sp->se_device, "", ""); 453 } 454 455 /* 456 * Start a session and allocate a controlling terminal. 457 * Only called by children of init after forking. 458 */ 459 void 460 setctty(name) 461 char *name; 462 { 463 int fd; 464 465 (void) revoke(name); 466 if ((fd = open(name, O_RDWR)) == -1) { 467 stall("can't open %s: %m", name); 468 _exit(1); 469 } 470 if (login_tty(fd) == -1) { 471 stall("can't get %s for controlling terminal: %m", name); 472 _exit(1); 473 } 474 } 475 476 /* 477 * Bring the system up single user. 478 */ 479 state_func_t 480 single_user() 481 { 482 pid_t pid, wpid; 483 int status; 484 sigset_t mask; 485 char *shell = _PATH_BSHELL; 486 char *argv[2]; 487 #ifdef SECURE 488 struct ttyent *typ; 489 struct passwd *pp; 490 static const char banner[] = 491 "Enter root password, or ^D to go multi-user\n"; 492 char *password; 493 #endif 494 495 if ((pid = fork()) == 0) { 496 /* 497 * Start the single user session. 498 */ 499 setctty(_PATH_CONSOLE); 500 501 #ifdef SECURE 502 /* 503 * Check the root password. 504 * We don't care if the console is 'on' by default; 505 * it's the only tty that can be 'off' and 'secure'. 506 */ 507 typ = getttynam("console"); 508 pp = getpwnam("root"); 509 if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp) { 510 write(2, banner, sizeof banner - 1); 511 for (;;) { 512 password = getpass("Password:"); 513 if (password == 0 || *password == '\0') 514 _exit(0); 515 if (strcmp(password, pp->pw_passwd) == 0) 516 break; 517 } 518 } 519 #if 0 520 /* 521 * Make the single-user shell be root's standard shell? 522 */ 523 if (pp && pp->pw_shell) 524 shell = pp->pw_shell; 525 #endif 526 endttyent(); 527 endpwent(); 528 #endif 529 530 /* 531 * Unblock signals. 532 * We catch all the interesting ones, 533 * and those are reset to SIG_DFL on exec. 534 */ 535 sigemptyset(&mask); 536 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 537 538 /* 539 * Fire off a shell. 540 * If the default one doesn't work, try the Bourne shell. 541 */ 542 argv[0] = "-sh"; 543 argv[1] = 0; 544 execv(shell, argv); 545 emergency("can't exec %s for single user: %m", shell); 546 execv(_PATH_BSHELL, argv); 547 emergency("can't exec %s for single user: %m", _PATH_BSHELL); 548 sleep(STALL_TIMEOUT); 549 _exit(1); 550 } 551 552 if (pid == -1) { 553 /* 554 * We are seriously hosed. Do our best. 555 */ 556 emergency("can't fork single-user shell, trying again"); 557 while (waitpid(-1, (int *) 0, WNOHANG) > 0) 558 ; 559 return (state_func_t) single_user; 560 } 561 562 requested_transition = 0; 563 do { 564 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 565 collect_child(wpid); 566 if (wpid == -1) { 567 if (errno == EINTR) 568 continue; 569 warning("wait for single-user shell failed: %m; restarting"); 570 return (state_func_t) single_user; 571 } 572 if (wpid == pid && WIFSTOPPED(status)) { 573 warning("init: shell stopped, restarting\n"); 574 kill(pid, SIGCONT); 575 wpid = -1; 576 } 577 } while (wpid != pid && !requested_transition); 578 579 if (requested_transition) 580 return (state_func_t) requested_transition; 581 582 if (!WIFEXITED(status)) { 583 if (WTERMSIG(status) == SIGKILL) { 584 /* 585 * reboot(8) killed shell? 586 */ 587 warning("single user shell terminated."); 588 sleep(STALL_TIMEOUT); 589 _exit(0); 590 } else { 591 warning("single user shell terminated, restarting"); 592 return (state_func_t) single_user; 593 } 594 } 595 596 runcom_mode = FASTBOOT; 597 return (state_func_t) runcom; 598 } 599 600 /* 601 * Run the system startup script. 602 */ 603 state_func_t 604 runcom() 605 { 606 pid_t pid, wpid; 607 int status; 608 char *argv[4]; 609 struct sigaction sa; 610 611 if ((pid = fork()) == 0) { 612 sigemptyset(&sa.sa_mask); 613 sa.sa_flags = 0; 614 sa.sa_handler = SIG_IGN; 615 (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0); 616 (void) sigaction(SIGHUP, &sa, (struct sigaction *)0); 617 618 setctty(_PATH_CONSOLE); 619 620 argv[0] = "sh"; 621 argv[1] = _PATH_RUNCOM; 622 argv[2] = runcom_mode == AUTOBOOT ? "autoboot" : 0; 623 argv[3] = 0; 624 625 sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0); 626 627 execv(_PATH_BSHELL, argv); 628 stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNCOM); 629 _exit(1); /* force single user mode */ 630 } 631 632 if (pid == -1) { 633 emergency("can't fork for %s on %s: %m", 634 _PATH_BSHELL, _PATH_RUNCOM); 635 while (waitpid(-1, (int *) 0, WNOHANG) > 0) 636 ; 637 sleep(STALL_TIMEOUT); 638 return (state_func_t) single_user; 639 } 640 641 /* 642 * Copied from single_user(). This is a bit paranoid. 643 */ 644 do { 645 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 646 collect_child(wpid); 647 if (wpid == -1) { 648 if (errno == EINTR) 649 continue; 650 warning("wait for %s on %s failed: %m; going to single user mode", 651 _PATH_BSHELL, _PATH_RUNCOM); 652 return (state_func_t) single_user; 653 } 654 if (wpid == pid && WIFSTOPPED(status)) { 655 warning("init: %s on %s stopped, restarting\n", 656 _PATH_BSHELL, _PATH_RUNCOM); 657 kill(pid, SIGCONT); 658 wpid = -1; 659 } 660 } while (wpid != pid); 661 662 if (!WIFEXITED(status)) { 663 warning("%s on %s terminated abnormally, going to single user mode", 664 _PATH_BSHELL, _PATH_RUNCOM); 665 return (state_func_t) single_user; 666 } 667 668 if (WEXITSTATUS(status)) 669 return (state_func_t) single_user; 670 671 runcom_mode = AUTOBOOT; /* the default */ 672 /* NB: should send a message to the session logger to avoid blocking. */ 673 logwtmp("~", "reboot", ""); 674 return (state_func_t) read_ttys; 675 } 676 677 /* 678 * Open the session database. 679 * 680 * NB: We could pass in the size here; is it necessary? 681 */ 682 int 683 start_session_db() 684 { 685 if (session_db && (*session_db->close)(session_db)) 686 emergency("session database close: %s", strerror(errno)); 687 if ((session_db = hash_open(NULL, O_RDWR, 0, NULL)) == 0) { 688 emergency("session database open: %s", strerror(errno)); 689 return (1); 690 } 691 return (0); 692 693 } 694 695 /* 696 * Add a new login session. 697 */ 698 void 699 add_session(sp) 700 session_t *sp; 701 { 702 DBT key; 703 DBT data; 704 705 key.data = &sp->se_process; 706 key.size = sizeof sp->se_process; 707 data.data = &sp; 708 data.size = sizeof sp; 709 710 if ((*session_db->put)(session_db, &key, &data, R_PUT)) 711 emergency("insert %d: %s", sp->se_process, strerror(errno)); 712 } 713 714 /* 715 * Delete an old login session. 716 */ 717 void 718 del_session(sp) 719 session_t *sp; 720 { 721 DBT key; 722 723 key.data = &sp->se_process; 724 key.size = sizeof sp->se_process; 725 726 if ((*session_db->del)(session_db, &key, 0)) 727 emergency("delete %d: %s", sp->se_process, strerror(errno)); 728 } 729 730 /* 731 * Look up a login session by pid. 732 */ 733 session_t * 734 #ifdef __STDC__ 735 find_session(pid_t pid) 736 #else 737 find_session(pid) 738 pid_t pid; 739 #endif 740 { 741 DBT key; 742 DBT data; 743 744 key.data = &pid; 745 key.size = sizeof pid; 746 if ((*session_db->get)(session_db, &key, &data, 0) != 0) 747 return 0; 748 return *(session_t **)data.data; 749 } 750 751 /* 752 * Construct an argument vector from a command line. 753 */ 754 char ** 755 construct_argv(command) 756 char *command; 757 { 758 register int argc = 0; 759 register char **argv = (char **) malloc(((strlen(command) + 1) / 2 + 1) 760 * sizeof (char *)); 761 static const char separators[] = " \t"; 762 763 if ((argv[argc++] = strtok(command, separators)) == 0) 764 return 0; 765 while (argv[argc++] = strtok((char *) 0, separators)) 766 ; 767 return argv; 768 } 769 770 /* 771 * Deallocate a session descriptor. 772 */ 773 void 774 free_session(sp) 775 register session_t *sp; 776 { 777 free(sp->se_device); 778 free(sp->se_getty); 779 free(sp->se_getty_argv); 780 if (sp->se_window) { 781 free(sp->se_window); 782 free(sp->se_window_argv); 783 } 784 free(sp); 785 } 786 787 /* 788 * Allocate a new session descriptor. 789 */ 790 session_t * 791 new_session(sprev, session_index, typ) 792 session_t *sprev; 793 int session_index; 794 register struct ttyent *typ; 795 { 796 register session_t *sp; 797 798 if ((typ->ty_status & TTY_ON) == 0 || 799 typ->ty_name == 0 || 800 typ->ty_getty == 0) 801 return 0; 802 803 sp = (session_t *) malloc(sizeof (session_t)); 804 805 sp->se_index = session_index; 806 sp->se_process = 0; 807 sp->se_started = 0; 808 sp->se_flags = 0; 809 sp->se_window = 0; 810 811 sp->se_device = malloc(6 + strlen(typ->ty_name)); 812 memcpy(sp->se_device, _PATH_DEV, 5); 813 strcpy(sp->se_device + 5, typ->ty_name); 814 815 sp->se_getty = strdup(typ->ty_getty); 816 sp->se_getty_argv = construct_argv(sp->se_getty); 817 if (sp->se_getty_argv == 0) { 818 warning("can't parse getty for port %s", 819 sp->se_device); 820 free_session(sp); 821 return 0; 822 } 823 if (typ->ty_window) { 824 sp->se_window = strdup(typ->ty_window); 825 sp->se_window_argv = construct_argv(sp->se_window); 826 if (sp->se_window_argv == 0) { 827 warning("can't parse window for port %s", 828 sp->se_device); 829 free_session(sp); 830 return 0; 831 } 832 } 833 834 sp->se_next = 0; 835 if (sprev == 0) { 836 sessions = sp; 837 sp->se_prev = 0; 838 } else { 839 sprev->se_next = sp; 840 sp->se_prev = sprev; 841 } 842 843 return sp; 844 } 845 846 /* 847 * Walk the list of ttys and create sessions for each active line. 848 */ 849 state_func_t 850 read_ttys() 851 { 852 int session_index = 0; 853 register session_t *sp, *snext; 854 register struct ttyent *typ; 855 856 /* 857 * Destroy any previous session state. 858 * There shouldn't be any, but just in case... 859 */ 860 for (sp = sessions; sp; sp = snext) { 861 if (sp->se_process) 862 clear_session_logs(sp); 863 snext = sp->se_next; 864 free_session(sp); 865 } 866 sessions = 0; 867 if (start_session_db()) 868 return (state_func_t) single_user; 869 870 /* 871 * Allocate a session entry for each active port. 872 * Note that sp starts at 0. 873 */ 874 while (typ = getttyent()) 875 if (snext = new_session(sp, ++session_index, typ)) 876 sp = snext; 877 878 endttyent(); 879 880 logger_enable = 1; 881 return (state_func_t) multi_user; 882 } 883 884 /* 885 * Start a window system running. 886 */ 887 void 888 start_window_system(sp) 889 session_t *sp; 890 { 891 pid_t pid; 892 sigset_t mask; 893 894 if ((pid = fork()) == -1) { 895 emergency("can't fork for window system on port %s: %m", 896 sp->se_device); 897 /* hope that getty fails and we can try again */ 898 return; 899 } 900 901 if (pid) 902 return; 903 904 sigemptyset(&mask); 905 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 906 907 if (setsid() < 0) 908 emergency("setsid failed (window) %m"); 909 910 execv(sp->se_window_argv[0], sp->se_window_argv); 911 stall("can't exec window system '%s' for port %s: %m", 912 sp->se_window_argv[0], sp->se_device); 913 _exit(1); 914 } 915 916 /* 917 * Start a login session running. 918 */ 919 pid_t 920 start_getty(sp) 921 session_t *sp; 922 { 923 pid_t pid; 924 sigset_t mask; 925 time_t current_time = time((time_t *) 0); 926 927 /* 928 * fork(), not vfork() -- we can't afford to block. 929 */ 930 if ((pid = fork()) == -1) { 931 emergency("can't fork for getty on port %s: %m", sp->se_device); 932 return -1; 933 } 934 935 if (pid) 936 return pid; 937 938 if (current_time > sp->se_started && 939 current_time - sp->se_started < GETTY_SPACING) { 940 warning("getty repeating too quickly on port %s, sleeping", 941 sp->se_device); 942 sleep((unsigned) GETTY_SPACING - 943 (current_time - sp->se_started)); 944 } 945 946 if (sp->se_window) { 947 start_window_system(sp); 948 sleep(WINDOW_WAIT); 949 } 950 951 setctty(sp->se_device); 952 953 sigemptyset(&mask); 954 sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); 955 956 execv(sp->se_getty_argv[0], sp->se_getty_argv); 957 stall("can't exec getty '%s' for port %s: %m", 958 sp->se_getty_argv[0], sp->se_device); 959 _exit(1); 960 } 961 962 /* 963 * Collect exit status for a child. 964 * If an exiting login, start a new login running. 965 */ 966 void 967 collect_child(pid) 968 pid_t pid; 969 { 970 register session_t *sp, *sprev, *snext; 971 972 if (! sessions) 973 return; 974 975 if (! (sp = find_session(pid))) 976 return; 977 978 clear_session_logs(sp); 979 del_session(sp); 980 sp->se_process = 0; 981 982 if (sp->se_flags & SE_SHUTDOWN) { 983 if (sprev = sp->se_prev) 984 sprev->se_next = sp->se_next; 985 else 986 sessions = sp->se_next; 987 if (snext = sp->se_next) 988 snext->se_prev = sp->se_prev; 989 free_session(sp); 990 return; 991 } 992 993 if ((pid = start_getty(sp)) == -1) { 994 /* serious trouble */ 995 requested_transition = clean_ttys; 996 return; 997 } 998 999 sp->se_process = pid; 1000 sp->se_started = time((time_t *) 0); 1001 add_session(sp); 1002 } 1003 1004 /* 1005 * Catch a signal and request a state transition. 1006 */ 1007 void 1008 transition_handler(sig) 1009 int sig; 1010 { 1011 1012 switch (sig) { 1013 case SIGHUP: 1014 requested_transition = clean_ttys; 1015 break; 1016 case SIGTERM: 1017 requested_transition = death; 1018 break; 1019 case SIGTSTP: 1020 requested_transition = catatonia; 1021 break; 1022 default: 1023 requested_transition = 0; 1024 break; 1025 } 1026 } 1027 1028 /* 1029 * Take the system multiuser. 1030 */ 1031 state_func_t 1032 multi_user() 1033 { 1034 pid_t pid; 1035 register session_t *sp; 1036 1037 requested_transition = 0; 1038 logger_enable = 1; 1039 1040 for (sp = sessions; sp; sp = sp->se_next) { 1041 if (sp->se_process) 1042 continue; 1043 if ((pid = start_getty(sp)) == -1) { 1044 /* serious trouble */ 1045 requested_transition = clean_ttys; 1046 break; 1047 } 1048 sp->se_process = pid; 1049 sp->se_started = time((time_t *) 0); 1050 add_session(sp); 1051 } 1052 1053 while (!requested_transition) 1054 if ((pid = waitpid(-1, (int *) 0, 0)) != -1) 1055 collect_child(pid); 1056 1057 return (state_func_t) requested_transition; 1058 } 1059 1060 /* 1061 * This is an n-squared algorithm. We hope it isn't run often... 1062 */ 1063 state_func_t 1064 clean_ttys() 1065 { 1066 register session_t *sp, *sprev; 1067 register struct ttyent *typ; 1068 register int session_index = 0; 1069 1070 if (! sessions) 1071 return (state_func_t) multi_user; 1072 1073 while (typ = getttyent()) { 1074 ++session_index; 1075 1076 for (sp = sessions; sp; sprev = sp, sp = sp->se_next) 1077 if (strcmp(typ->ty_name, sp->se_device) == 0) 1078 break; 1079 1080 if (sp) { 1081 if (sp->se_index != session_index) { 1082 warning("port %s changed utmp index from %d to %d", 1083 sp->se_device, sp->se_index, 1084 session_index); 1085 sp->se_index = session_index; 1086 } 1087 if (typ->ty_status & TTY_ON) 1088 sp->se_flags &= ~SE_SHUTDOWN; 1089 else { 1090 sp->se_flags |= SE_SHUTDOWN; 1091 kill(sp->se_process, SIGHUP); 1092 } 1093 continue; 1094 } 1095 1096 new_session(sprev, session_index, typ); 1097 } 1098 1099 endttyent(); 1100 1101 return (state_func_t) multi_user; 1102 } 1103 1104 /* 1105 * Block further logins. 1106 */ 1107 state_func_t 1108 catatonia() 1109 { 1110 register session_t *sp; 1111 1112 for (sp = sessions; sp; sp = sp->se_next) 1113 sp->se_flags |= SE_SHUTDOWN; 1114 1115 return (state_func_t) multi_user; 1116 } 1117 1118 /* 1119 * Note SIGALRM. 1120 */ 1121 void 1122 alrm_handler(sig) 1123 int sig; 1124 { 1125 clang = 1; 1126 } 1127 1128 /* 1129 * Bring the system down to single user. 1130 */ 1131 state_func_t 1132 death() 1133 { 1134 register session_t *sp; 1135 register int i; 1136 pid_t pid; 1137 static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL }; 1138 1139 for (sp = sessions; sp; sp = sp->se_next) 1140 sp->se_flags |= SE_SHUTDOWN; 1141 1142 /* NB: should send a message to the session logger to avoid blocking. */ 1143 logwtmp("~", "shutdown", ""); 1144 logger_enable = 0; 1145 1146 for (i = 0; i < 3; ++i) { 1147 if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH) 1148 return (state_func_t) single_user; 1149 1150 clang = 0; 1151 alarm(DEATH_WATCH); 1152 do 1153 if ((pid = waitpid(-1, (int *)0, 0)) != -1) 1154 collect_child(pid); 1155 while (clang == 0 && errno != ECHILD); 1156 1157 if (errno == ECHILD) 1158 return (state_func_t) single_user; 1159 } 1160 1161 warning("some processes wouldn't die"); 1162 1163 return (state_func_t) single_user; 1164 } 1165