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