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