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

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

1.1       cgd         1: /*
                      2:  * Copyright (c) 1986, 1987, 1992 Daniel D. Lanciani.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by
                     16:  *     Daniel D. Lanciani.
                     17:  * 4. The name of the author may not
                     18:  *    be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY Daniel D. Lanciani ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL Daniel D. Lanciani BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  */
1.3       cgd        33:
1.6     ! cgd        34: /* $Header: /b/source/CVS/src/sbin/init/init.c,v 1.5 1993/04/06 19:33:33 cgd Exp $ */
1.1       cgd        35:
                     36:
                     37: #include <sys/types.h>
                     38: #include <sys/errno.h>
                     39: #include <sys/signal.h>
                     40: #include <sys/wait.h>
                     41: #include <setjmp.h>
                     42: #include <ttyent.h>
                     43: #include <unistd.h>
                     44:
1.5       cgd        45: #ifdef SECURE_CONSOLE
                     46: #include <pwd.h>
                     47: #endif
                     48:
1.1       cgd        49: #define NTTY 32                        /* max ttys */
                     50: #define NARG 16                        /* max args to login/getty */
                     51:
                     52: /* internal flags */
                     53: #define TTY_SEEN 0x8000
                     54: #define TTY_DIFF 0x4000
                     55: #define TTY_LOGIN 0x2000
                     56:
                     57: /* non-standard tty_logout: rerun login/getty with -o switch to clean line */
                     58: #ifndef        TTY_LOGOUT
                     59: #define TTY_LOGOUT 0x1000
                     60: #endif
                     61:
                     62: /* non-standard tty_open: open device for login/getty */
                     63: #ifndef        TTY_OPEN
                     64: #define TTY_OPEN 0x0800
                     65: #endif
                     66:
                     67: #define isspace(c) ((c) == ' ' || (c) == '\t')
                     68:
                     69: struct ttytab {
                     70:        char *tt_name;
                     71:        char *tt_getty;
                     72:        char *tt_type;
                     73:        int tt_status;
                     74:        int tt_pid;
                     75: } ttytab[NTTY], *ttytabend = ttytab;
                     76: int drain, sflag;
                     77: char arg[128], nam[64], term[64], *env[] = { term, 0 };
                     78: jmp_buf single, reread;
                     79: char *Reboot = "autoboot";
                     80:
                     81: char *newstring(), *malloc();
                     82: extern int errno;
                     83:
                     84: /* signal state of child process */
                     85: #define        SIGNALSFORCHILD  \
                     86:        signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_DFL); \
                     87:        signal(SIGTERM, SIG_DFL); signal(SIGALRM, SIG_DFL); \
                     88:        signal(SIGTSTP, SIG_DFL); signal(SIGCHLD, SIG_DFL); \
1.2       cgd        89:        signal(SIGTTIN, SIG_DFL); signal(SIGTTOU, SIG_DFL); \
                     90:        sigsetmask( 0);                         /* 04 Sep 92*/
1.1       cgd        91:
                     92: /* SIGHUP: reread /etc/ttys */
                     93: void
                     94: shup(sig)
                     95: {
                     96:        longjmp(reread, 1);
                     97: }
                     98:
                     99: /* SIGALRM: abort wait and go single user */
                    100: void
                    101: salrm(sig)
                    102: {
                    103:        signal(SIGALRM, SIG_DFL);
                    104:        warn("process hung");
                    105:        longjmp(single, 1);
                    106: }
                    107:
                    108: /* SIGTERM: go single user */
                    109: void
                    110: sterm(sig)
                    111: {
                    112:        register struct ttytab *tt;
                    113:
                    114:        if (!Reboot) {
                    115:                for(tt = ttytab; tt < ttytabend; tt++) {
                    116:                        free(tt->tt_name);
                    117:                        free(tt->tt_getty);
                    118:                        free(tt->tt_type);
                    119:                }
                    120:                ttytabend = ttytab;
1.2       cgd       121:                /* give processes time to exit cleanly */       /* 15 Aug 92*/
                    122:                kill(-1, SIGTERM);
                    123:                sleep(10);
                    124:                /* Now murder them */
1.1       cgd       125:                kill(-1, SIGKILL);
                    126:                kill(-1, SIGCONT);
                    127:                signal(SIGALRM, salrm);
                    128:                alarm(30);
                    129:                while(wait((int *)0) > 0);
                    130:                alarm(0);
                    131:                signal(SIGALRM, SIG_DFL);
                    132:                longjmp(single, 1);
                    133:        }
                    134: }
                    135:
                    136: /* SIGTSTP: drain system */
                    137: void
                    138: ststp(sig)
                    139: {
                    140:        drain = 1;
                    141: }
                    142:
                    143: /* init [-s] [-f] */
                    144:
                    145: main(argc, argv)
                    146: char **argv;
                    147: {
                    148:        register int pid;
                    149:        register struct ttytab *tt;
                    150:        struct ttyent *ty;
                    151:        int status;
                    152:        long mask = sigblock(sigmask(SIGHUP) | sigmask(SIGTERM));
                    153:
                    154:        /* did some idiot try to run us? */
                    155:        if(getpid() != 1) {
                    156:                writes(2,"init: sorry, system daemon, runnable only by system\n");
                    157:                exit(0xff);
                    158:        }
                    159:
                    160:        /* allocate a session for init */
                    161:        (void) setsid();
                    162:
                    163:        /* protect against signals, listen for outside requests */
                    164:        signal(SIGHUP, shup);
                    165:        signal(SIGTSTP, ststp);
                    166:
                    167:        signal (SIGTTIN, SIG_IGN);
                    168:        signal (SIGTTOU, SIG_IGN);
                    169:        signal (SIGCHLD, SIG_IGN);
                    170:        signal (SIGINT, SIG_IGN);
                    171:
                    172:        /* handle arguments, if any */
                    173:        if(argc > 1)
                    174:                if(!strcmp(argv[1], "-s"))
                    175:                        sflag++;
                    176:                else if(!strcmp(argv[1], "-f"))
                    177:                        Reboot = 0;
                    178: top:
                    179:        /* Single user mode? */
                    180:        if(sflag) {
                    181:                sflag = 0;
                    182:                status = 1;
                    183:        } else {
                    184:                /* otherwise, execute /etc/rc */
                    185:                if (access("/etc/rc", F_OK)  == 0) {
                    186:
                    187:                        signal(SIGTERM, SIG_IGN);       /* XXX */
                    188:                        if((pid = fork()) < 0)
                    189:                                fatal("fork");
                    190:                        else if(!pid) {
                    191:                                /* signals, to default state */
                    192:                                SIGNALSFORCHILD;
                    193:
                    194:                                /* clean off console */
                    195:                                revoke("/dev/console");
                    196:
                    197:                                /* create a shell */
                    198:                                login_tty(open("/dev/console", 2));
                    199:                                execl("/bin/sh", "sh", "/etc/rc", Reboot, (char *)0);
                    200:                                _exit(127);
                    201:                        }
1.2       cgd       202:                        Reboot = 0;                     /* 31 Jul 92*/
1.1       cgd       203:                        while(wait(&status) != pid);
                    204:
                    205:                        /* if we are about to be rebooted, then wait for it */
                    206:                        if (WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL)
                    207:                                pause();
                    208:                } else  { status = 1;  sflag = 1; goto top; }
                    209:        }
                    210:        signal(SIGTERM, sterm);
                    211:        Reboot = 0;
                    212:
                    213:        /* do single user shell on console */
                    214:        if (setjmp(single) || status) {
1.5       cgd       215: #ifdef SECURE_CONSOLE
                    216:                struct ttyent *ttyp;
                    217:                struct passwd *passp;
                    218:                char *pass;
                    219:                static const char banner[] =
                    220:                        "Enter root password, or Control-D to go multi-user\n";
                    221: #endif
                    222:
1.1       cgd       223:                if((pid = fork()) < 0)
                    224:                        fatal("fork");
                    225:                else if(!pid) {
                    226:                        /* signals, to default state */
                    227:                        SIGNALSFORCHILD;
                    228:
                    229:                        /* clean off console */
                    230:                        revoke("/dev/console");
                    231:
                    232:                        /* do open and configuration of console */
                    233:                        login_tty(open("/dev/console", 2));
1.5       cgd       234: #ifdef SECURE_CONSOLE
                    235:                        /* if the console isn't secure, check the root PW */
                    236:                        ttyp = getttynam("console");
                    237:                        if (!ttyp) {
                    238:                                /* don't have an entry for "console", probably
                    239:                                 * have one for /dev/vga
                    240:                                 */
                    241:                                ttyp = getttynam("vga");
                    242:                        }
                    243:                        passp = getpwnam("root");
                    244:                        if (ttyp && ((ttyp->ty_status & TTY_SECURE) == 0) &&
                    245:                            passp) {
                    246:                                write(2, banner, sizeof(banner) - 1);
                    247:                                do {
                    248:                                        pass = getpass("Password:");
                    249:                                        if ((pass == 0) || (*pass == '\0'))
                    250:                                                _exit(0); /* got control-d */
                    251:                                        pass = crypt(pass, passp->pw_passwd);
                    252:                                } while (strcmp(pass, passp->pw_passwd) != 0);
                    253:                        }
                    254: #endif
1.1       cgd       255:                        execl("/bin/sh", "-", (char *)0);
                    256:                        _exit(127);
                    257:                }
1.2       cgd       258:                while(wait(&status) != pid);
                    259:                while(drain)                            /* 31 Jul 92*/
                    260:                        pause();
1.1       cgd       261:                goto top;
                    262:        }
                    263:
                    264:        /* multiuser mode, traipse through table */
                    265:        setttyent();
                    266:        for(tt = ttytab; (ty = getttyent()) && tt < &ttytab[NTTY]; tt++) {
                    267:                tt->tt_name = newstring(ty->ty_name);
                    268:                tt->tt_getty = newstring(ty->ty_getty);
                    269:                tt->tt_type = newstring(ty->ty_type);
                    270:                tt->tt_status = ty->ty_status;
                    271:        }
                    272:        ttytabend = tt;
                    273:        endttyent();
                    274:        for(tt = ttytab; tt < ttytabend; getty(tt++));
                    275:
                    276:        /* if we receive a request to reread the table, come here */
                    277:        if(setjmp(reread)) {
                    278:
                    279:                /* first pass. find and clean the entries that have changed */
                    280:                setttyent();
                    281:                while(ty = getttyent()) {
                    282:                        for(tt = ttytab; tt < ttytabend; tt++)
                    283:                        if(!strcmp(tt->tt_name, ty->ty_name)) {
                    284:                                /* if a process present, mark */
                    285:                                if((tt->tt_status & ~TTY_LOGIN) !=ty->ty_status)
                    286:                                        tt->tt_status = ty->ty_status |TTY_DIFF;
                    287:                                if(strcmp(tt->tt_getty, ty->ty_getty)) {
                    288:                                        free(tt->tt_getty);
                    289:                                        tt->tt_getty = newstring(ty->ty_getty);
                    290:                                        tt->tt_status |= TTY_DIFF;
                    291:                                }
                    292:                                if(strcmp(tt->tt_type, ty->ty_type)) {
                    293:                                        free(tt->tt_type);
                    294:                                        tt->tt_type = newstring(ty->ty_type);
                    295:                                        tt->tt_status |= TTY_DIFF;
                    296:                                }
                    297:                                if(((tt->tt_status |= TTY_SEEN) & TTY_DIFF)
                    298:                                        && tt->tt_pid > 1)
                    299:                                        kill(tt->tt_pid, 9);
                    300:                                break;
                    301:                        }
                    302:                        if(tt == ttytabend && tt < &ttytab[NTTY]) {
                    303:                                tt->tt_name = newstring(ty->ty_name);
                    304:                                tt->tt_getty = newstring(ty->ty_getty);
                    305:                                tt->tt_type = newstring(ty->ty_type);
                    306:                                tt->tt_status = ty->ty_status |
                    307:                                        TTY_SEEN | TTY_DIFF;
                    308:                                ttytabend++;
                    309:                        }
                    310:                }
                    311:                endttyent();
                    312:                /* second pass. offer gettys on previously cleaned entries,
                    313:                   and garbage collect "dead" entries */
                    314:                for(tt = ttytab; tt < ttytabend; tt++)
                    315:                        if(tt->tt_status & TTY_SEEN) {
                    316:                                tt->tt_status &= ~TTY_SEEN;
                    317:                                if(tt->tt_status & TTY_DIFF) {
                    318:                                        tt->tt_status &= ~TTY_DIFF;
                    319:                                        getty(tt);
                    320:                                }
                    321:                        }
                    322:                        else {
                    323:                                if(tt->tt_pid > 1)
                    324:                                        kill(tt->tt_pid, 9);
                    325:                                free(tt->tt_name);
                    326:                                free(tt->tt_getty);
                    327:                                free(tt->tt_type);
                    328:                                pid = tt - ttytab;
                    329:                                for(tt++; tt < ttytabend; tt++)
                    330:                                        tt[-1] = *tt;
                    331:                                ttytabend--;
                    332:                                tt = &ttytab[pid];
                    333:                        }
                    334:        }
                    335:        drain = 0;
                    336:
                    337:        /* listen for terminating gettys and sessions, and process them */
                    338:        while(1) {
                    339:                sigsetmask(mask);
                    340:                pid = wait(&status);
                    341:                sigblock(sigmask(SIGHUP) | sigmask(SIGTERM));
                    342:                if(pid < 0) {
                    343:                        sleep(5);
                    344:                        continue;
                    345:                }
                    346:                for(tt = ttytab; tt < ttytabend; tt++)
                    347:                        if(pid == tt->tt_pid) {
1.2       cgd       348: /* 24 Jul 92*/                 if (logout(tt->tt_name)) logwtmp(tt->tt_name,"","");
1.1       cgd       349:                                if(drain && !(tt->tt_status & TTY_LOGIN)) {
                    350:                                        free(tt->tt_name);
                    351:                                        free(tt->tt_getty);
                    352:                                        free(tt->tt_type);
                    353:                                        for(tt++; tt < ttytabend; tt++)
                    354:                                                tt[-1] = *tt;
                    355:                                        ttytabend--;
                    356:                                }
                    357:                                else
                    358:                                        getty(tt);
                    359:                                break;
                    360:                        }
                    361:        }
                    362: }
                    363:
                    364: /* process a getty for a "line". N.B. by having getty do open, init
                    365:    is not limited by filedescriptors for number of possible users */
                    366: getty(tt)
                    367: struct ttytab *tt;
                    368: {
                    369:        char *sargv[NARG];
                    370:        register char *p = arg, **sp = sargv;
                    371:
                    372:        if(!(tt->tt_status & TTY_ON)) {
                    373:                tt->tt_pid = -1;
                    374:                return;
                    375:        }
                    376:        if((tt->tt_pid = fork()) < 0)
                    377:                fatal("getty fork");
                    378:        else if(tt->tt_pid) {
                    379:                if(tt->tt_status & TTY_LOGOUT)
                    380:                        tt->tt_status ^= TTY_LOGIN;
                    381:                return;
                    382:        }
                    383:        signal(SIGHUP, SIG_DFL);
                    384:        signal(SIGTERM, SIG_DFL);
                    385:        signal(SIGTSTP, SIG_DFL);
                    386:        sigsetmask(0);
                    387:        strcpy(p, tt->tt_getty);
                    388:        while(sp < &sargv[NARG - 2]) {
                    389:                while(isspace(*p))
                    390:                        p++;
                    391:                if(!*p)
                    392:                        break;
                    393:                *sp++ = p;
                    394:                while(!isspace(*p) && *p)
                    395:                        p++;
                    396:                if(!*p)
                    397:                        break;
                    398:                *p++ = 0;
                    399:        }
                    400:        strcpy(nam, tt->tt_name);
                    401:        *sp++ = nam;
                    402:        *sp = 0;
                    403:        p = *sargv;
                    404:        strcpy(term, "TERM=");
                    405:        strcat(term, tt->tt_type);
                    406:        execve(p, sargv, env);
                    407: bad:
                    408:        sleep(30);
                    409:        fatal(tt->tt_name);
                    410: }
                    411:
                    412: char *
                    413: newstring(s)
                    414: register char *s;
                    415: {
                    416:        register char *n;
                    417:
                    418:        if(!(n = malloc(strlen(s) + 1)))
                    419:                fatal("out of memory");
                    420:        strcpy(n, s);
                    421:        return(n);
                    422: }
                    423:
                    424: warn(s)
                    425: char *s;
                    426: {
                    427:        register int pid;
                    428:        int fd;
                    429:
                    430:        fd = open("/dev/console", 2);
                    431:        writes(fd, "init WARNING: ");
                    432:        writes(fd, s);
                    433:        write(fd, "\n", 1);
                    434:        close(fd);
                    435: }
                    436:
                    437: fatal(s)
                    438: char *s;
                    439: {
                    440:        login_tty(open("/dev/console", 2));
                    441:        writes(2, "init FATAL error: ");
                    442:        perror(s);
1.2       cgd       443:        _exit(1);                               /* 04 Sep 92*/
1.1       cgd       444:        /* panic: init died */
                    445: }
                    446:
                    447: writes(n, s)
                    448: char *s;
                    449: {
                    450:        write(n, s, strlen(s));
                    451: }

CVSweb <webmaster@jp.NetBSD.org>