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