Annotation of 43BSDTahoe/etc/init.c, revision 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.