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