Annotation of 42BSD/etc/init.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char *sccsid = "@(#)init.c      4.12 (Berkeley) 6/12/83";
                      3: #endif
                      4: 
                      5: #include <signal.h>
                      6: #include <sys/types.h>
                      7: #include <utmp.h>
                      8: #include <setjmp.h>
                      9: #include <sys/reboot.h>
                     10: #include <errno.h>
                     11: #include <sys/file.h>
                     12: 
                     13: #define        LINSIZ  sizeof(wtmp.ut_line)
                     14: #define        TABSIZ  100
                     15: #define        ALL     p = &itab[0]; p < &itab[TABSIZ]; p++
                     16: #define        EVER    ;;
                     17: #define SCPYN(a, b)    strncpy(a, b, sizeof(a))
                     18: #define SCMPN(a, b)    strncmp(a, b, sizeof(a))
                     19: #define        mask(s) (1 << ((s)-1))
                     20: 
                     21: char   shell[] = "/bin/sh";
                     22: char   getty[]  = "/etc/getty";
                     23: char   minus[] = "-";
                     24: char   runc[]  = "/etc/rc";
                     25: char   ifile[] = "/etc/ttys";
                     26: char   utmp[]  = "/etc/utmp";
                     27: char   wtmpf[] = "/usr/adm/wtmp";
                     28: char   ctty[]  = "/dev/console";
                     29: char   dev[]   = "/dev/";
                     30: 
                     31: struct utmp wtmp;
                     32: struct
                     33: {
                     34:        char    line[LINSIZ];
                     35:        char    comn;
                     36:        char    flag;
                     37: } line;
                     38: struct tab
                     39: {
                     40:        char    line[LINSIZ];
                     41:        char    comn;
                     42:        char    xflag;
                     43:        int     pid;
                     44:        time_t  gettytime;
                     45:        int     gettycnt;
                     46: } itab[TABSIZ];
                     47: 
                     48: int    fi;
                     49: int    mergflag;
                     50: char   tty[20];
                     51: jmp_buf        sjbuf, shutpass;
                     52: time_t time0;
                     53: 
                     54: int    reset();
                     55: int    idle();
                     56: char   *strcpy(), *strcat();
                     57: long   lseek();
                     58: 
                     59: struct sigvec rvec = { reset, mask(SIGHUP), 0 };
                     60: 
                     61: #ifdef vax
                     62: main()
                     63: {
                     64:        register int r11;               /* passed thru from boot */
                     65: #else
                     66: main(argc, argv)
                     67:        char **argv;
                     68: {
                     69: #endif
                     70:        int howto, oldhowto;
                     71: 
                     72:        time0 = time(0);
                     73: #ifdef vax
                     74:        howto = r11;
                     75: #else
                     76:        if (argc > 1 && argv[1][0] == '-') {
                     77:                char *cp;
                     78: 
                     79:                howto = 0;
                     80:                cp = &argv[1][1];
                     81:                while (*cp) switch (*cp++) {
                     82:                case 'a':
                     83:                        howto |= RB_ASKNAME;
                     84:                        break;
                     85:                case 's':
                     86:                        howto |= RB_SINGLE;
                     87:                        break;
                     88:                }
                     89:        } else {
                     90:                howto = RB_SINGLE;
                     91:        }
                     92: #endif
                     93:        sigvec(SIGTERM, &rvec, (struct sigvec *)0);
                     94:        signal(SIGTSTP, idle);
                     95:        signal(SIGSTOP, SIG_IGN);
                     96:        signal(SIGTTIN, SIG_IGN);
                     97:        signal(SIGTTOU, SIG_IGN);
                     98:        (void) setjmp(sjbuf);
                     99:        for (EVER) {
                    100:                oldhowto = howto;
                    101:                howto = RB_SINGLE;
                    102:                if (setjmp(shutpass) == 0)
                    103:                        shutdown();
                    104:                if (oldhowto & RB_SINGLE)
                    105:                        single();
                    106:                if (runcom(oldhowto) == 0) 
                    107:                        continue;
                    108:                merge();
                    109:                multiple();
                    110:        }
                    111: }
                    112: 
                    113: int    shutreset();
                    114: 
                    115: shutdown()
                    116: {
                    117:        register i;
                    118:        register struct tab *p;
                    119: 
                    120:        close(creat(utmp, 0644));
                    121:        signal(SIGHUP, SIG_IGN);
                    122:        for (ALL) {
                    123:                term(p);
                    124:                p->line[0] = 0;
                    125:        }
                    126:        signal(SIGALRM, shutreset);
                    127:        alarm(30);
                    128:        for (i = 0; i < 5; i++)
                    129:                kill(-1, SIGKILL);
                    130:        while (wait((int *)0) != -1)
                    131:                ;
                    132:        alarm(0);
                    133:        shutend();
                    134: }
                    135: 
                    136: char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";
                    137: 
                    138: shutreset()
                    139: {
                    140:        int status;
                    141: 
                    142:        if (fork() == 0) {
                    143:                int ct = open(ctty, 1);
                    144:                write(ct, shutfailm, sizeof (shutfailm));
                    145:                sleep(5);
                    146:                exit(1);
                    147:        }
                    148:        sleep(5);
                    149:        shutend();
                    150:        longjmp(shutpass, 1);
                    151: }
                    152: 
                    153: shutend()
                    154: {
                    155:        register i, f;
                    156: 
                    157:        acct(0);
                    158:        signal(SIGALRM, SIG_DFL);
                    159:        for (i = 0; i < 10; i++)
                    160:                close(i);
                    161:        f = open(wtmpf, O_WRONLY|O_APPEND);
                    162:        if (f >= 0) {
                    163:                SCPYN(wtmp.ut_line, "~");
                    164:                SCPYN(wtmp.ut_name, "shutdown");
                    165:                SCPYN(wtmp.ut_host, "");
                    166:                time(&wtmp.ut_time);
                    167:                write(f, (char *)&wtmp, sizeof(wtmp));
                    168:                close(f);
                    169:        }
                    170:        return (1);
                    171: }
                    172: 
                    173: single()
                    174: {
                    175:        register pid;
                    176:        register xpid;
                    177:        extern  errno;
                    178: 
                    179:        do {
                    180:                pid = fork();
                    181:                if (pid == 0) {
                    182:                        signal(SIGTERM, SIG_DFL);
                    183:                        signal(SIGHUP, SIG_DFL);
                    184:                        signal(SIGALRM, SIG_DFL);
                    185:                        (void) open(ctty, O_RDWR);
                    186:                        dup2(0, 1);
                    187:                        dup2(0, 2);
                    188:                        execl(shell, minus, (char *)0);
                    189:                        exit(0);
                    190:                }
                    191:                while ((xpid = wait((int *)0)) != pid)
                    192:                        if (xpid == -1 && errno == ECHILD)
                    193:                                break;
                    194:        } while (xpid == -1);
                    195: }
                    196: 
                    197: runcom(oldhowto)
                    198:        int oldhowto;
                    199: {
                    200:        register pid, f;
                    201:        int status;
                    202: 
                    203:        pid = fork();
                    204:        if (pid == 0) {
                    205:                (void) open("/", O_RDONLY);
                    206:                dup2(0, 1);
                    207:                dup2(0, 2);
                    208:                if (oldhowto & RB_SINGLE)
                    209:                        execl(shell, shell, runc, (char *)0);
                    210:                else
                    211:                        execl(shell, shell, runc, "autoboot", (char *)0);
                    212:                exit(1);
                    213:        }
                    214:        while (wait(&status) != pid)
                    215:                ;
                    216:        if (status)
                    217:                return (0);
                    218:        f = open(wtmpf, O_WRONLY|O_APPEND);
                    219:        if (f >= 0) {
                    220:                SCPYN(wtmp.ut_line, "~");
                    221:                SCPYN(wtmp.ut_name, "reboot");
                    222:                SCPYN(wtmp.ut_host, "");
                    223:                if (time0) {
                    224:                        wtmp.ut_time = time0;
                    225:                        time0 = 0;
                    226:                } else
                    227:                        time(&wtmp.ut_time);
                    228:                write(f, (char *)&wtmp, sizeof(wtmp));
                    229:                close(f);
                    230:        }
                    231:        return (1);
                    232: }
                    233: 
                    234: struct sigvec  mvec = { merge, mask(SIGTERM), 0 };
                    235: /*
                    236:  * Multi-user.  Listen for users leaving, SIGHUP's
                    237:  * which indicate ttys has changed, and SIGTERM's which
                    238:  * are used to shutdown the system.
                    239:  */
                    240: multiple()
                    241: {
                    242:        register struct tab *p;
                    243:        register pid;
                    244: 
                    245:        sigvec(SIGHUP, &mvec, (struct sigvec *)0);
                    246:        for (EVER) {
                    247:                pid = wait((int *)0);
                    248:                if (pid == -1)
                    249:                        return;
                    250:                for (ALL)
                    251:                        if (p->pid == pid || p->pid == -1) {
                    252:                                rmut(p);
                    253:                                dfork(p);
                    254:                        }
                    255:        }
                    256: }
                    257: 
                    258: /*
                    259:  * Merge current contents of ttys file
                    260:  * into in-core table of configured tty lines.
                    261:  * Entered as signal handler for SIGHUP.
                    262:  */
                    263: #define        FOUND   1
                    264: #define        CHANGE  2
                    265: 
                    266: merge()
                    267: {
                    268:        register struct tab *p;
                    269: 
                    270:        fi = open(ifile, 0);
                    271:        if (fi < 0)
                    272:                return;
                    273:        for (ALL)
                    274:                p->xflag = 0;
                    275:        while (rline()) {
                    276:                for (ALL) {
                    277:                        if (SCMPN(p->line, line.line))
                    278:                                continue;
                    279:                        p->xflag |= FOUND;
                    280:                        if (line.comn != p->comn) {
                    281:                                p->xflag |= CHANGE;
                    282:                                p->comn = line.comn;
                    283:                        }
                    284:                        goto contin1;
                    285:                }
                    286:                for (ALL) {
                    287:                        if (p->line[0] != 0)
                    288:                                continue;
                    289:                        SCPYN(p->line, line.line);
                    290:                        p->xflag |= FOUND|CHANGE;
                    291:                        p->comn = line.comn;
                    292:                        goto contin1;
                    293:                }
                    294:        contin1:
                    295:                ;
                    296:        }
                    297:        close(fi);
                    298:        for (ALL) {
                    299:                if ((p->xflag&FOUND) == 0) {
                    300:                        term(p);
                    301:                        p->line[0] = 0;
                    302:                }
                    303:                if (p->xflag&CHANGE) {
                    304:                        term(p);
                    305:                        dfork(p);
                    306:                }
                    307:        }
                    308: }
                    309: 
                    310: term(p)
                    311:        register struct tab *p;
                    312: {
                    313: 
                    314:        if (p->pid != 0) {
                    315:                rmut(p);
                    316:                kill(p->pid, SIGKILL);
                    317:        }
                    318:        p->pid = 0;
                    319: }
                    320: 
                    321: rline()
                    322: {
                    323:        register c, i;
                    324: 
                    325: loop:
                    326:        c = get();
                    327:        if (c < 0)
                    328:                return(0);
                    329:        if (c == 0)
                    330:                goto loop;
                    331:        line.flag = c;
                    332:        c = get();
                    333:        if (c <= 0)
                    334:                goto loop;
                    335:        line.comn = c;
                    336:        SCPYN(line.line, "");
                    337:        for (i = 0; i < LINSIZ; i++) {
                    338:                c = get();
                    339:                if (c <= 0)
                    340:                        break;
                    341:                line.line[i] = c;
                    342:        }
                    343:        while (c > 0)
                    344:                c = get();
                    345:        if (line.line[0] == 0)
                    346:                goto loop;
                    347:        if (line.flag == '0')
                    348:                goto loop;
                    349:        strcpy(tty, dev);
                    350:        strncat(tty, line.line, LINSIZ);
                    351:        if (access(tty, 06) < 0)
                    352:                goto loop;
                    353:        return (1);
                    354: }
                    355: 
                    356: get()
                    357: {
                    358:        char b;
                    359: 
                    360:        if (read(fi, &b, 1) != 1)
                    361:                return (-1);
                    362:        if (b == '\n')
                    363:                return (0);
                    364:        return (b);
                    365: }
                    366: 
                    367: #include <sys/ioctl.h>
                    368: 
                    369: dfork(p)
                    370:        struct tab *p;
                    371: {
                    372:        register pid;
                    373:        time_t t;
                    374:        int dowait = 0;
                    375:        extern char *sys_errlist[];
                    376: 
                    377:        time(&t);
                    378:        p->gettycnt++;
                    379:        if ((t - p->gettytime) >= 60) {
                    380:                p->gettytime = t;
                    381:                p->gettycnt = 1;
                    382:        } else {
                    383:                if (p->gettycnt >= 5) {
                    384:                        dowait = 1;
                    385:                        p->gettytime = t;
                    386:                        p->gettycnt = 1;
                    387:                }
                    388:        }
                    389:        pid = fork();
                    390:        if (pid == 0) {
                    391:                int oerrno, f;
                    392:                extern int errno;
                    393: 
                    394:                signal(SIGTERM, SIG_DFL);
                    395:                signal(SIGHUP, SIG_IGN);
                    396:                strcpy(tty, dev);
                    397:                strncat(tty, p->line, LINSIZ);
                    398:                if (dowait) {
                    399:                        f = open("/dev/console", O_WRONLY);
                    400:                        write(f, "init: ", 6);
                    401:                        write(f, tty, strlen(tty));
                    402:                        write(f, ": getty failing, sleeping\n\r", 27);
                    403:                        close(f);
                    404:                        sleep(30);
                    405:                        if ((f = open("/dev/tty", O_RDWR)) >= 0) {
                    406:                                ioctl(f, TIOCNOTTY, 0);
                    407:                                close(f);
                    408:                        }
                    409:                }
                    410:                chown(tty, 0, 0);
                    411:                chmod(tty, 0622);
                    412:                if (open(tty, O_RDWR) < 0) {
                    413:                        int repcnt = 0;
                    414:                        do {
                    415:                                oerrno = errno;
                    416:                                if (repcnt % 10 == 0) {
                    417:                                        f = open("/dev/console", O_WRONLY);
                    418:                                        write(f, "init: ", 6);
                    419:                                        write(f, tty, strlen(tty));
                    420:                                        write(f, ": ", 2);
                    421:                                        write(f, sys_errlist[oerrno],
                    422:                                                strlen(sys_errlist[oerrno]));
                    423:                                        write(f, "\n", 1);
                    424:                                        close(f);
                    425:                                        if ((f = open("/dev/tty", 2)) >= 0) {
                    426:                                                ioctl(f, TIOCNOTTY, 0);
                    427:                                                close(f);
                    428:                                        }
                    429:                                }
                    430:                                repcnt++;
                    431:                                sleep(60);
                    432:                        } while (open(tty, O_RDWR) < 0);
                    433:                        exit(0);        /* have wrong control tty, start over */
                    434:                }
                    435:                vhangup();
                    436:                signal(SIGHUP, SIG_DFL);
                    437:                (void) open(tty, O_RDWR);
                    438:                close(0);
                    439:                dup(1);
                    440:                dup(0);
                    441:                tty[0] = p->comn;
                    442:                tty[1] = 0;
                    443:                execl(getty, minus, tty, (char *)0);
                    444:                exit(0);
                    445:        }
                    446:        p->pid = pid;
                    447: }
                    448: 
                    449: /*
                    450:  * Remove utmp entry.
                    451:  */
                    452: rmut(p)
                    453:        register struct tab *p;
                    454: {
                    455:        register f;
                    456:        int found = 0;
                    457: 
                    458:        f = open(utmp, O_RDWR);
                    459:        if (f >= 0) {
                    460:                while (read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
                    461:                        if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0)
                    462:                                continue;
                    463:                        lseek(f, -(long)sizeof(wtmp), 1);
                    464:                        SCPYN(wtmp.ut_name, "");
                    465:                        SCPYN(wtmp.ut_host, "");
                    466:                        time(&wtmp.ut_time);
                    467:                        write(f, (char *)&wtmp, sizeof(wtmp));
                    468:                        found++;
                    469:                }
                    470:                close(f);
                    471:        }
                    472:        if (found) {
                    473:                f = open(wtmpf, O_WRONLY|O_APPEND);
                    474:                if (f >= 0) {
                    475:                        SCPYN(wtmp.ut_line, p->line);
                    476:                        SCPYN(wtmp.ut_name, "");
                    477:                        SCPYN(wtmp.ut_host, "");
                    478:                        time(&wtmp.ut_time);
                    479:                        write(f, (char *)&wtmp, sizeof(wtmp));
                    480:                        close(f);
                    481:                }
                    482:        }
                    483: }
                    484: 
                    485: reset()
                    486: {
                    487: 
                    488:        longjmp(sjbuf, 1);
                    489: }
                    490: 
                    491: jmp_buf        idlebuf;
                    492: 
                    493: idlehup()
                    494: {
                    495: 
                    496:        longjmp(idlebuf, 1);
                    497: }
                    498: 
                    499: idle()
                    500: {
                    501:        register struct tab *p;
                    502:        register pid;
                    503: 
                    504:        signal(SIGHUP, idlehup);
                    505:        for (;;) {
                    506:                if (setjmp(idlebuf))
                    507:                        return;
                    508:                pid = wait((int *) 0);
                    509:                if (pid == -1) {
                    510:                        sigpause(0);
                    511:                        continue;
                    512:                }
                    513:                for (ALL)
                    514:                        if (p->pid == pid) {
                    515:                                rmut(p);
                    516:                                p->pid = -1;
                    517:                        }
                    518:        }
                    519: }

unix.superglobalmegacorp.com

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