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