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