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