Annotation of 43BSDTahoe/etc/init.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980,1986 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)init.c     5.10 (Berkeley) 1/10/88";
                      9: #endif not lint
                     10: 
                     11: #include <signal.h>
                     12: #include <sys/types.h>
                     13: #include <utmp.h>
                     14: #include <setjmp.h>
                     15: #include <sys/reboot.h>
                     16: #include <errno.h>
                     17: #include <sys/file.h>
                     18: #include <ttyent.h>
                     19: #include <sys/syslog.h>
                     20: #include <sys/stat.h>
                     21: 
                     22: #define        LINSIZ  sizeof(wtmp.ut_line)
                     23: #define        CMDSIZ  200     /* max string length for getty or window command*/
                     24: #define        ALL     p = itab; p ; p = p->next
                     25: #define        EVER    ;;
                     26: #define SCPYN(a, b)    strncpy(a, b, sizeof(a))
                     27: #define SCMPN(a, b)    strncmp(a, b, sizeof(a))
                     28: 
                     29: char   shell[] = "/bin/sh";
                     30: char   minus[] = "-";
                     31: char   runc[]  = "/etc/rc";
                     32: char   utmpf[] = "/etc/utmp";
                     33: char   wtmpf[] = "/usr/adm/wtmp";
                     34: char   ctty[]  = "/dev/console";
                     35: 
                     36: struct utmp wtmp;
                     37: struct tab
                     38: {
                     39:        char    line[LINSIZ];
                     40:        char    comn[CMDSIZ];
                     41:        char    xflag;
                     42:        int     pid;
                     43:        int     wpid;           /* window system pid for SIGHUP */
                     44:        char    wcmd[CMDSIZ];   /* command to start window system process */
                     45:        time_t  gettytime;
                     46:        int     gettycnt;
                     47:        time_t  windtime;
                     48:        int     windcnt;
                     49:        struct  tab *next;
                     50: } *itab;
                     51: 
                     52: int    fi;
                     53: int    mergflag;
                     54: char   tty[20];
                     55: jmp_buf        sjbuf, shutpass;
                     56: time_t time0;
                     57: 
                     58: int    reset();
                     59: int    idle();
                     60: char   *strcpy(), *strcat();
                     61: long   lseek();
                     62: 
                     63: struct sigvec rvec = { reset, sigmask(SIGHUP), 0 };
                     64: 
                     65: 
                     66: #if defined(vax) || defined(tahoe)
                     67: main()
                     68: {
                     69: #if defined(tahoe)
                     70:        register int r12;               /* make sure r11 gets bootflags */
                     71: #endif
                     72:        register int r11;               /* passed thru from boot */
                     73: #else
                     74: main(argc, argv)
                     75:        char **argv;
                     76: {
                     77: #endif
                     78:        int howto, oldhowto;
                     79: 
                     80:        time0 = time(0);
                     81: #if defined(vax) || defined(tahoe)
                     82:        howto = r11;
                     83: #else
                     84:        if (argc > 1 && argv[1][0] == '-') {
                     85:                char *cp;
                     86: 
                     87:                howto = 0;
                     88:                cp = &argv[1][1];
                     89:                while (*cp) switch (*cp++) {
                     90:                case 'a':
                     91:                        howto |= RB_ASKNAME;
                     92:                        break;
                     93:                case 's':
                     94:                        howto |= RB_SINGLE;
                     95:                        break;
                     96:                }
                     97:        } else {
                     98:                howto = RB_SINGLE;
                     99:        }
                    100: #endif
                    101:        openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH);
                    102:        sigvec(SIGTERM, &rvec, (struct sigvec *)0);
                    103:        signal(SIGTSTP, idle);
                    104:        signal(SIGSTOP, SIG_IGN);
                    105:        signal(SIGTTIN, SIG_IGN);
                    106:        signal(SIGTTOU, SIG_IGN);
                    107:        (void) setjmp(sjbuf);
                    108:        for (EVER) {
                    109:                oldhowto = howto;
                    110:                howto = RB_SINGLE;
                    111:                if (setjmp(shutpass) == 0)
                    112:                        shutdown();
                    113:                if (oldhowto & RB_SINGLE)
                    114:                        single();
                    115:                if (runcom(oldhowto) == 0) 
                    116:                        continue;
                    117:                merge();
                    118:                multiple();
                    119:        }
                    120: }
                    121: 
                    122: int    shutreset();
                    123: 
                    124: shutdown()
                    125: {
                    126:        register i;
                    127:        register struct tab *p, *p1;
                    128: 
                    129:        close(creat(utmpf, 0644));
                    130:        signal(SIGHUP, SIG_IGN);
                    131:        for (p = itab; p ; ) {
                    132:                term(p);
                    133:                p1 = p->next;
                    134:                free(p);
                    135:                p = p1;
                    136:        }
                    137:        itab = (struct tab *)0;
                    138:        signal(SIGALRM, shutreset);
                    139:        (void) kill(-1, SIGTERM);       /* one chance to catch it */
                    140:        sleep(5);
                    141:        alarm(30);
                    142:        for (i = 0; i < 5; i++)
                    143:                kill(-1, SIGKILL);
                    144:        while (wait((int *)0) != -1)
                    145:                ;
                    146:        alarm(0);
                    147:        shutend();
                    148: }
                    149: 
                    150: char shutfailm[] = "WARNING: Something is hung (won't die); ps axl advised\n";
                    151: 
                    152: shutreset()
                    153: {
                    154:        int status;
                    155: 
                    156:        if (fork() == 0) {
                    157:                int ct = open(ctty, 1);
                    158:                write(ct, shutfailm, sizeof (shutfailm));
                    159:                sleep(5);
                    160:                exit(1);
                    161:        }
                    162:        sleep(5);
                    163:        shutend();
                    164:        longjmp(shutpass, 1);
                    165: }
                    166: 
                    167: shutend()
                    168: {
                    169:        register i, f;
                    170: 
                    171:        acct(0);
                    172:        signal(SIGALRM, SIG_DFL);
                    173:        for (i = 0; i < 10; i++)
                    174:                close(i);
                    175:        f = open(wtmpf, O_WRONLY|O_APPEND);
                    176:        if (f >= 0) {
                    177:                SCPYN(wtmp.ut_line, "~");
                    178:                SCPYN(wtmp.ut_name, "shutdown");
                    179:                SCPYN(wtmp.ut_host, "");
                    180:                time(&wtmp.ut_time);
                    181:                write(f, (char *)&wtmp, sizeof(wtmp));
                    182:                close(f);
                    183:        }
                    184:        return (1);
                    185: }
                    186: 
                    187: single()
                    188: {
                    189:        register pid;
                    190:        register xpid;
                    191:        extern  errno;
                    192: 
                    193:        do {
                    194:                pid = fork();
                    195:                if (pid == 0) {
                    196:                        signal(SIGTERM, SIG_DFL);
                    197:                        signal(SIGHUP, SIG_DFL);
                    198:                        signal(SIGALRM, SIG_DFL);
                    199:                        signal(SIGTSTP, SIG_IGN);
                    200:                        (void) open(ctty, O_RDWR);
                    201:                        dup2(0, 1);
                    202:                        dup2(0, 2);
                    203:                        execl(shell, minus, (char *)0);
                    204:                        perror(shell);
                    205:                        exit(0);
                    206:                }
                    207:                while ((xpid = wait((int *)0)) != pid)
                    208:                        if (xpid == -1 && errno == ECHILD)
                    209:                                break;
                    210:        } while (xpid == -1);
                    211: }
                    212: 
                    213: runcom(oldhowto)
                    214:        int oldhowto;
                    215: {
                    216:        register pid, f;
                    217:        int status;
                    218: 
                    219:        pid = fork();
                    220:        if (pid == 0) {
                    221:                (void) open("/", O_RDONLY);
                    222:                dup2(0, 1);
                    223:                dup2(0, 2);
                    224:                if (oldhowto & RB_SINGLE)
                    225:                        execl(shell, shell, runc, (char *)0);
                    226:                else
                    227:                        execl(shell, shell, runc, "autoboot", (char *)0);
                    228:                exit(1);
                    229:        }
                    230:        while (wait(&status) != pid)
                    231:                ;
                    232:        if (status)
                    233:                return (0);
                    234:        f = open(wtmpf, O_WRONLY|O_APPEND);
                    235:        if (f >= 0) {
                    236:                SCPYN(wtmp.ut_line, "~");
                    237:                SCPYN(wtmp.ut_name, "reboot");
                    238:                SCPYN(wtmp.ut_host, "");
                    239:                if (time0) {
                    240:                        wtmp.ut_time = time0;
                    241:                        time0 = 0;
                    242:                } else
                    243:                        time(&wtmp.ut_time);
                    244:                write(f, (char *)&wtmp, sizeof(wtmp));
                    245:                close(f);
                    246:        }
                    247:        return (1);
                    248: }
                    249: 
                    250: int merge();
                    251: struct sigvec  mvec = { merge, sigmask(SIGTERM), 0 };
                    252: /*
                    253:  * Multi-user.  Listen for users leaving, SIGHUP's
                    254:  * which indicate ttys has changed, and SIGTERM's which
                    255:  * are used to shutdown the system.
                    256:  */
                    257: multiple()
                    258: {
                    259:        register struct tab *p;
                    260:        register pid;
                    261:        int omask;
                    262: 
                    263:        sigvec(SIGHUP, &mvec, (struct sigvec *)0);
                    264:        for (EVER) {
                    265:                pid = wait((int *)0);
                    266:                if (pid == -1)
                    267:                        return;
                    268:                omask = sigblock(sigmask(SIGHUP));
                    269:                for (ALL) {
                    270:                        /* must restart window system BEFORE emulator */
                    271:                        if (p->wpid == pid || p->wpid == -1)
                    272:                                wstart(p);
                    273:                        if (p->pid == pid || p->pid == -1) {
                    274:                                /* disown the window system */
                    275:                                if (p->wpid)
                    276:                                        kill(p->wpid, SIGHUP);
                    277:                                rmut(p);
                    278:                                dfork(p);
                    279:                        }
                    280:                }
                    281:                sigsetmask(omask);
                    282:        }
                    283: }
                    284: 
                    285: /*
                    286:  * Merge current contents of ttys file
                    287:  * into in-core table of configured tty lines.
                    288:  * Entered as signal handler for SIGHUP.
                    289:  */
                    290: #define        FOUND   1
                    291: #define        CHANGE  2
                    292: #define WCHANGE 4
                    293: 
                    294: merge()
                    295: {
                    296:        register struct tab *p;
                    297:        register struct ttyent *t;
                    298:        register struct tab *p1;
                    299: 
                    300:        for (ALL)
                    301:                p->xflag = 0;
                    302:        setttyent();
                    303:        while (t = getttyent()) {
                    304:                if ((t->ty_status & TTY_ON) == 0)
                    305:                        continue;
                    306:                for (ALL) {
                    307:                        if (SCMPN(p->line, t->ty_name))
                    308:                                continue;
                    309:                        p->xflag |= FOUND;
                    310:                        if (SCMPN(p->comn, t->ty_getty)) {
                    311:                                p->xflag |= CHANGE;
                    312:                                SCPYN(p->comn, t->ty_getty);
                    313:                        }
                    314:                        if (SCMPN(p->wcmd, t->ty_window ? t->ty_window : "")) {
                    315:                                p->xflag |= WCHANGE|CHANGE;
                    316:                                SCPYN(p->wcmd, t->ty_window);
                    317:                        }
                    318:                        goto contin1;
                    319:                }
                    320: 
                    321:                /*
                    322:                 * Make space for a new one
                    323:                 */
                    324:                p1 = (struct tab *)calloc(1, sizeof(*p1));
                    325:                if (!p1) {
                    326:                        syslog(LOG_ERR, "no space for '%s' !?!", t->ty_name);
                    327:                        goto contin1;
                    328:                }
                    329:                /*
                    330:                 * Put new terminal at the end of the linked list.
                    331:                 */
                    332:                if (itab) {
                    333:                        for (p = itab; p->next ; p = p->next)
                    334:                                ;
                    335:                        p->next = p1;
                    336:                } else
                    337:                        itab = p1;
                    338: 
                    339:                p = p1;
                    340:                SCPYN(p->line, t->ty_name);
                    341:                p->xflag |= FOUND|CHANGE;
                    342:                SCPYN(p->comn, t->ty_getty);
                    343:                if (t->ty_window && strcmp(t->ty_window, "") != 0) {
                    344:                        p->xflag |= WCHANGE;
                    345:                        SCPYN(p->wcmd, t->ty_window);
                    346:                }
                    347:        contin1:
                    348:                ;
                    349:        }
                    350:        endttyent();
                    351:        p1 = (struct tab *)0;
                    352:        for (ALL) {
                    353:                if ((p->xflag&FOUND) == 0) {
                    354:                        term(p);
                    355:                        wterm(p);
                    356:                        if (p1)
                    357:                                p1->next = p->next;
                    358:                        else
                    359:                                itab = p->next;
                    360:                        free(p);
                    361:                        p = p1 ? p1 : itab;
                    362:                } else {
                    363:                        /* window system should be started first */
                    364:                        if (p->xflag&WCHANGE) {
                    365:                                wterm(p);
                    366:                                wstart(p);
                    367:                        }
                    368:                        if (p->xflag&CHANGE) {
                    369:                                term(p);
                    370:                                dfork(p);
                    371:                        }
                    372:                }
                    373:                p1 = p;
                    374:        }
                    375: }
                    376: 
                    377: term(p)
                    378:        register struct tab *p;
                    379: {
                    380: 
                    381:        if (p->pid != 0) {
                    382:                rmut(p);
                    383:                kill(p->pid, SIGKILL);
                    384:        }
                    385:        p->pid = 0;
                    386:        /* send SIGHUP to get rid of connections */
                    387:        if (p->wpid > 0)
                    388:                kill(p->wpid, SIGHUP);
                    389: }
                    390: 
                    391: dfork(p)
                    392:        struct tab *p;
                    393: {
                    394:        register pid;
                    395:        time_t t;
                    396:        int dowait = 0;
                    397: 
                    398:        time(&t);
                    399:        p->gettycnt++;
                    400:        if ((t - p->gettytime) >= 60) {
                    401:                p->gettytime = t;
                    402:                p->gettycnt = 1;
                    403:        } else if (p->gettycnt >= 5) {
                    404:                dowait = 1;
                    405:                p->gettytime = t;
                    406:                p->gettycnt = 1;
                    407:        }
                    408:        pid = fork();
                    409:        if (pid == 0) {
                    410:                signal(SIGTERM, SIG_DFL);
                    411:                signal(SIGHUP, SIG_IGN);
                    412:                sigsetmask(0);  /* since can be called from masked code */
                    413:                if (dowait) {
                    414:                        syslog(LOG_ERR, "'%s %s' failing, sleeping", p->comn, p->line);
                    415:                        closelog();
                    416:                        sleep(30);
                    417:                }
                    418:                execit(p->comn, p->line);
                    419:                exit(0);
                    420:        }
                    421:        p->pid = pid;
                    422: }
                    423: 
                    424: /*
                    425:  * Remove utmp entry.
                    426:  */
                    427: rmut(p)
                    428:        register struct tab *p;
                    429: {
                    430:        register f;
                    431:        int found = 0;
                    432:        static unsigned utmpsize;
                    433:        static struct utmp *utmp;
                    434:        register struct utmp *u;
                    435:        int nutmp;
                    436:        struct stat statbf;
                    437: 
                    438:        f = open(utmpf, O_RDWR);
                    439:        if (f >= 0) {
                    440:                fstat(f, &statbf);
                    441:                if (utmpsize < statbf.st_size) {
                    442:                        utmpsize = statbf.st_size + 10 * sizeof(struct utmp);
                    443:                        if (utmp)
                    444:                                utmp = (struct utmp *)realloc(utmp, utmpsize);
                    445:                        else
                    446:                                utmp = (struct utmp *)malloc(utmpsize);
                    447:                        if (!utmp)
                    448:                                syslog(LOG_ERR, "utmp malloc failed");
                    449:                }
                    450:                if (statbf.st_size && utmp) {
                    451:                        nutmp = read(f, utmp, statbf.st_size);
                    452:                        nutmp /= sizeof(struct utmp);
                    453:                        for (u = utmp ; u < &utmp[nutmp] ; u++) {
                    454:                                if (u->ut_name[0] == 0 ||
                    455:                                    SCMPN(u->ut_line, p->line))
                    456:                                        continue;
                    457:                                lseek(f, ((long)u)-((long)utmp), L_SET);
                    458:                                SCPYN(u->ut_name, "");
                    459:                                SCPYN(u->ut_host, "");
                    460:                                time(&u->ut_time);
                    461:                                write(f, (char *)u, sizeof(*u));
                    462:                                found++;
                    463:                        }
                    464:                }
                    465:                close(f);
                    466:        }
                    467:        if (found) {
                    468:                f = open(wtmpf, O_WRONLY|O_APPEND);
                    469:                if (f >= 0) {
                    470:                        SCPYN(wtmp.ut_line, p->line);
                    471:                        SCPYN(wtmp.ut_name, "");
                    472:                        SCPYN(wtmp.ut_host, "");
                    473:                        time(&wtmp.ut_time);
                    474:                        write(f, (char *)&wtmp, sizeof(wtmp));
                    475:                        close(f);
                    476:                }
                    477:                /*
                    478:                 * After a proper login force reset
                    479:                 * of error detection code in dfork.
                    480:                 */
                    481:                p->gettytime = 0;
                    482:                p->windtime = 0;
                    483:        }
                    484: }
                    485: 
                    486: reset()
                    487: {
                    488: 
                    489:        longjmp(sjbuf, 1);
                    490: }
                    491: 
                    492: jmp_buf        idlebuf;
                    493: 
                    494: idlehup()
                    495: {
                    496: 
                    497:        longjmp(idlebuf, 1);
                    498: }
                    499: 
                    500: idle()
                    501: {
                    502:        register struct tab *p;
                    503:        register pid;
                    504: 
                    505:        signal(SIGHUP, idlehup);
                    506:        for (EVER) {
                    507:                if (setjmp(idlebuf))
                    508:                        return;
                    509:                pid = wait((int *) 0);
                    510:                if (pid == -1) {
                    511:                        sigpause(0);
                    512:                        continue;
                    513:                }
                    514:                for (ALL) {
                    515:                        /* if window system dies, mark it for restart */
                    516:                        if (p->wpid == pid)
                    517:                                p->wpid = -1;
                    518:                        if (p->pid == pid) {
                    519:                                rmut(p);
                    520:                                p->pid = -1;
                    521:                        }
                    522:                }
                    523:        }
                    524: }
                    525: 
                    526: wterm(p)
                    527:        register struct tab *p;
                    528: {
                    529:        if (p->wpid != 0) {
                    530:                kill(p->wpid, SIGKILL);
                    531:        }
                    532:        p->wpid = 0;
                    533: }
                    534: 
                    535: wstart(p)
                    536:        register struct tab *p;
                    537: {
                    538:        register pid;
                    539:        time_t t;
                    540:        int dowait = 0;
                    541: 
                    542:        time(&t);
                    543:        p->windcnt++;
                    544:        if ((t - p->windtime) >= 60) {
                    545:                p->windtime = t;
                    546:                p->windcnt = 1;
                    547:        } else if (p->windcnt >= 5) {
                    548:                dowait = 1;
                    549:                p->windtime = t;
                    550:                p->windcnt = 1;
                    551:        }
                    552: 
                    553:        pid = fork();
                    554: 
                    555:        if (pid == 0) {
                    556:                signal(SIGTERM, SIG_DFL);
                    557:                signal(SIGHUP,  SIG_IGN);
                    558:                sigsetmask(0);  /* since can be called from masked code */
                    559:                if (dowait) {
                    560:                        syslog(LOG_ERR, "'%s %s' failing, sleeping", p->wcmd, p->line);
                    561:                        closelog();
                    562:                        sleep(30);
                    563:                }
                    564:                execit(p->wcmd, p->line);
                    565:                exit(0);
                    566:        }
                    567:        p->wpid = pid;
                    568: }
                    569: 
                    570: #define NARGS  20      /* must be at least 4 */
                    571: #define ARGLEN 512     /* total size for all the argument strings */
                    572: 
                    573: execit(s, arg)
                    574:        char *s;
                    575:        char *arg;      /* last argument on line */
                    576: {
                    577:        char *argv[NARGS], args[ARGLEN], *envp[1];
                    578:        register char *sp = s;
                    579:        register char *ap = args;
                    580:        register char c;
                    581:        register int i;
                    582: 
                    583:        /*
                    584:         * First we have to set up the argument vector.
                    585:         * "prog arg1 arg2" maps to exec("prog", "-", "arg1", "arg2"). 
                    586:         */
                    587:        for (i = 1; i < NARGS - 2; i++) {
                    588:                argv[i] = ap;
                    589:                for (EVER) {
                    590:                        if ((c = *sp++) == '\0' || ap >= &args[ARGLEN-1]) {
                    591:                                *ap = '\0';
                    592:                                goto done;
                    593:                        }
                    594:                        if (c == ' ') {
                    595:                                *ap++ = '\0';
                    596:                                while (*sp == ' ')
                    597:                                        sp++;
                    598:                                if (*sp == '\0')
                    599:                                        goto done;
                    600:                                break;
                    601:                        }
                    602:                        *ap++ = c;
                    603:                }
                    604:        }
                    605: done:
                    606:        argv[0] = argv[1];
                    607:        argv[1] = "-";
                    608:        argv[i+1] = arg;
                    609:        argv[i+2] = 0;
                    610:        envp[0] = 0;
                    611:        execve(argv[0], &argv[1], envp);
                    612:        /* report failure of exec */
                    613:        syslog(LOG_ERR, "%s: %m", argv[0]);
                    614:        closelog();
                    615:        sleep(10);      /* prevent failures from eating machine */
                    616: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.