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