[BACK]Return to init.c CVS log [TXT][DIR] Up to [local] / src / sbin / init

Annotation of src/sbin/init/init.c, Revision 1.54

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