Annotation of 43BSDReno/sbin/shutdown/shutdown.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988, 1990 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted provided
        !             6:  * that: (1) source distributions retain this entire copyright notice and
        !             7:  * comment, and (2) distributions including binaries display the following
        !             8:  * acknowledgement:  ``This product includes software developed by the
        !             9:  * University of California, Berkeley and its contributors'' in the
        !            10:  * documentation or other materials provided with the distribution and in
        !            11:  * all advertising materials mentioning features or use of this software.
        !            12:  * Neither the name of the University nor the names of its contributors may
        !            13:  * be used to endorse or promote products derived from this software without
        !            14:  * specific prior written permission.
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            18:  */
        !            19: 
        !            20: #ifndef lint
        !            21: char copyright[] =
        !            22: "@(#) Copyright (c) 1988 Regents of the University of California.\n\
        !            23:  All rights reserved.\n";
        !            24: #endif /* not lint */
        !            25: 
        !            26: #ifndef lint
        !            27: static char sccsid[] = "@(#)shutdown.c 5.15 (Berkeley) 6/22/90";
        !            28: #endif /* not lint */
        !            29: 
        !            30: #include <sys/param.h>
        !            31: #include <sys/time.h>
        !            32: #include <sys/file.h>
        !            33: #include <sys/resource.h>
        !            34: #include <sys/syslog.h>
        !            35: #include <sys/signal.h>
        !            36: #include <setjmp.h>
        !            37: #include <tzfile.h>
        !            38: #include <pwd.h>
        !            39: #include <stdio.h>
        !            40: #include <ctype.h>
        !            41: #include "pathnames.h"
        !            42: 
        !            43: #ifdef DEBUG
        !            44: #undef _PATH_NOLOGIN
        !            45: #define        _PATH_NOLOGIN   "./nologin"
        !            46: #undef _PATH_FASTBOOT
        !            47: #define        _PATH_FASTBOOT  "./fastboot"
        !            48: #endif
        !            49: 
        !            50: #define        H               *60*60
        !            51: #define        M               *60
        !            52: #define        S               *1
        !            53: #define        NOLOG_TIME      5*60
        !            54: struct interval {
        !            55:        int timeleft, timetowait;
        !            56: } tlist[] = {
        !            57:        10 H,  5 H,      5 H,  3 H,      2 H,  1 H,     1 H, 30 M,
        !            58:        30 M, 10 M,     20 M, 10 M,     10 M,  5 M,     5 M,  3 M,
        !            59:         2 M,  1 M,      1 M, 30 S,     30 S, 30 S,
        !            60:         0, 0,
        !            61: }, *tp = tlist;
        !            62: #undef H
        !            63: #undef M
        !            64: #undef S
        !            65: 
        !            66: static time_t offset, shuttime;
        !            67: static int dofast, dohalt, doreboot, killflg, mbuflen;
        !            68: static char *nosync, *whom, mbuf[BUFSIZ];
        !            69: 
        !            70: main(argc, argv)
        !            71:        int argc;
        !            72:        char **argv;
        !            73: {
        !            74:        extern int optind;
        !            75:        register char *p, *endp;
        !            76:        int arglen, ch, len, readstdin;
        !            77:        struct passwd *pw, *getpwuid();
        !            78:        char *strcat(), *getlogin();
        !            79:        uid_t geteuid();
        !            80: 
        !            81: #ifndef DEBUG
        !            82:        if (geteuid()) {
        !            83:                (void)fprintf(stderr, "shutdown: NOT super-user\n");
        !            84:                exit(1);
        !            85:        }
        !            86: #endif
        !            87:        nosync = NULL;
        !            88:        readstdin = 0;
        !            89:        while ((ch = getopt(argc, argv, "-fhknr")) != EOF)
        !            90:                switch (ch) {
        !            91:                case '-':
        !            92:                        readstdin = 1;
        !            93:                        break;
        !            94:                case 'f':
        !            95:                        dofast = 1;
        !            96:                        break;
        !            97:                case 'h':
        !            98:                        dohalt = 1;
        !            99:                        break;
        !           100:                case 'k':
        !           101:                        killflg = 1;
        !           102:                        break;
        !           103:                case 'n':
        !           104:                        nosync = "-n";
        !           105:                        break;
        !           106:                case 'r':
        !           107:                        doreboot = 1;
        !           108:                        break;
        !           109:                case '?':
        !           110:                default:
        !           111:                        usage();
        !           112:                }
        !           113:        argc -= optind;
        !           114:        argv += optind;
        !           115: 
        !           116:        if (argc < 1)
        !           117:                usage();
        !           118: 
        !           119:        if (dofast && nosync) {
        !           120:                (void)fprintf(stderr,
        !           121:                    "shutdown: incompatible switches -f and -n.\n");
        !           122:                usage();
        !           123:        }
        !           124:        if (doreboot && dohalt) {
        !           125:                (void)fprintf(stderr,
        !           126:                    "shutdown: incompatible switches -h and -r.\n");
        !           127:                usage();
        !           128:        }
        !           129:        getoffset(*argv++);
        !           130: 
        !           131:        if (*argv) {
        !           132:                for (p = mbuf, len = sizeof(mbuf); *argv; ++argv) {
        !           133:                        arglen = strlen(*argv);
        !           134:                        if ((len -= arglen) <= 2)
        !           135:                                break;
        !           136:                        if (p != mbuf)
        !           137:                                *p++ = ' ';
        !           138:                        bcopy(*argv, p, arglen);
        !           139:                        p += arglen;
        !           140:                }
        !           141:                *p = '\n';
        !           142:                *++p = '\0';
        !           143:        }
        !           144: 
        !           145:        if (readstdin) {
        !           146:                p = mbuf;
        !           147:                endp = mbuf + sizeof(mbuf) - 2;
        !           148:                for (;;) {
        !           149:                        if (!fgets(p, endp - p + 1, stdin))
        !           150:                                break;
        !           151:                        for (; *p &&  p < endp; ++p);
        !           152:                        if (p == endp) {
        !           153:                                *p = '\n';
        !           154:                                *++p = '\0';
        !           155:                                break;
        !           156:                        }
        !           157:                }
        !           158:        }
        !           159:        mbuflen = strlen(mbuf);
        !           160: 
        !           161:        if (offset)
        !           162:                (void)printf("Shutdown at %.24s.\n", ctime(&shuttime));
        !           163:        else
        !           164:                (void)printf("Shutdown NOW!\n");
        !           165: 
        !           166:        if (!(whom = getlogin()))
        !           167:                whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
        !           168: 
        !           169: #ifdef DEBUG
        !           170:        (void)putc('\n', stdout);
        !           171: #else
        !           172:        (void)setpriority(PRIO_PROCESS, 0, PRIO_MIN);
        !           173:        {
        !           174:                int forkpid;
        !           175: 
        !           176:                forkpid = fork();
        !           177:                if (forkpid == -1) {
        !           178:                        perror("shutdown: fork");
        !           179:                        exit(1);
        !           180:                }
        !           181:                if (forkpid) {
        !           182:                        (void)printf("shutdown: [pid %d]\n", forkpid);
        !           183:                        exit(0);
        !           184:                }
        !           185:        }
        !           186: #endif
        !           187:        openlog("shutdown", LOG_CONS, LOG_AUTH);
        !           188:        loop();
        !           189:        /*NOTREACHED*/
        !           190: }
        !           191: 
        !           192: loop()
        !           193: {
        !           194:        u_int sltime;
        !           195:        int logged;
        !           196: 
        !           197:        if (offset <= NOLOG_TIME) {
        !           198:                logged = 1;
        !           199:                nolog();
        !           200:        }
        !           201:        else
        !           202:                logged = 0;
        !           203:        tp = tlist;
        !           204:        if (tp->timeleft < offset)
        !           205:                (void)sleep((u_int)(offset - tp->timeleft));
        !           206:        else {
        !           207:                while (offset < tp->timeleft)
        !           208:                        ++tp;
        !           209:                /*
        !           210:                 * warn now, if going to sleep more than a fifth of
        !           211:                 * the next wait time.
        !           212:                 */
        !           213:                if (sltime = offset - tp->timeleft) {
        !           214:                        if (sltime > tp->timetowait / 5)
        !           215:                                warn();
        !           216:                        (void)sleep(sltime);
        !           217:                }
        !           218:        }
        !           219:        for (;; ++tp) {
        !           220:                warn();
        !           221:                if (!logged && tp->timeleft <= NOLOG_TIME) {
        !           222:                        logged = 1;
        !           223:                        nolog();
        !           224:                }
        !           225:                (void)sleep((u_int)tp->timetowait);
        !           226:                if (!tp->timeleft)
        !           227:                        break;
        !           228:        }
        !           229:        die_you_gravy_sucking_pig_dog();
        !           230: }
        !           231: 
        !           232: static jmp_buf alarmbuf;
        !           233: 
        !           234: warn()
        !           235: {
        !           236:        static int first;
        !           237:        static char hostname[MAXHOSTNAMELEN + 1];
        !           238:        char wcmd[MAXPATHLEN + 4];
        !           239:        FILE *pf;
        !           240:        char *ctime();
        !           241:        void timeout();
        !           242: 
        !           243:        if (!first++)
        !           244:                (void)gethostname(hostname, sizeof(hostname));
        !           245: 
        !           246:        /* undoc -n option to wall suppresses normal wall banner */
        !           247:        (void)sprintf(wcmd, "%s -n", _PATH_WALL);
        !           248:        if (!(pf = popen(wcmd, "w"))) {
        !           249:                syslog(LOG_ERR, "shutdown: can't find %s: %m", _PATH_WALL);
        !           250:                return;
        !           251:        }
        !           252: 
        !           253:        (void)fprintf(pf,
        !           254:            "\007*** %sSystem shutdown message from %s@%s ***\007\n",
        !           255:            tp->timeleft ? "": "FINAL ", whom, hostname);
        !           256: 
        !           257:        if (tp->timeleft > 10*60)
        !           258:                (void)fprintf(pf, "System going down at %5.5s\n\n",
        !           259:                    ctime(&shuttime) + 11);
        !           260:        else if (tp->timeleft > 59)
        !           261:                (void)fprintf(pf, "System going down in %d minute%s\n\n",
        !           262:                    tp->timeleft / 60, (tp->timeleft > 60) ? "s" : "");
        !           263:        else if (tp->timeleft)
        !           264:                (void)fprintf(pf, "System going down in 30 seconds\n\n");
        !           265:        else
        !           266:                (void)fprintf(pf, "System going down IMMEDIATELY\n\n");
        !           267: 
        !           268:        if (mbuflen)
        !           269:                (void)fwrite(mbuf, sizeof(*mbuf), mbuflen, pf);
        !           270: 
        !           271:        /*
        !           272:         * play some games, just in case wall doesn't come back
        !           273:         * probably unecessary, given that wall is careful.
        !           274:         */
        !           275:        if (!setjmp(alarmbuf)) {
        !           276:                (void)signal(SIGALRM, timeout);
        !           277:                (void)alarm((u_int)30);
        !           278:                (void)pclose(pf);
        !           279:                (void)alarm((u_int)0);
        !           280:                (void)signal(SIGALRM, SIG_DFL);
        !           281:        }
        !           282: }
        !           283: 
        !           284: void
        !           285: timeout()
        !           286: {
        !           287:        longjmp(alarmbuf, 1);
        !           288: }
        !           289: 
        !           290: die_you_gravy_sucking_pig_dog()
        !           291: {
        !           292:        void finish();
        !           293: 
        !           294:        syslog(LOG_NOTICE, "%s by %s: %s",
        !           295:            doreboot ? "reboot" : dohalt ? "halt" : "shutdown", whom, mbuf);
        !           296:        (void)sleep(2);
        !           297: 
        !           298:        (void)printf("\r\nSystem shutdown time has arrived\007\007\r\n");
        !           299:        if (killflg) {
        !           300:                (void)printf("\rbut you'll have to do it yourself\r\n");
        !           301:                finish();
        !           302:        }
        !           303:        if (dofast)
        !           304:                doitfast();
        !           305: #ifdef DEBUG
        !           306:        if (doreboot)
        !           307:                (void)printf("reboot");
        !           308:        else if (dohalt)
        !           309:                (void)printf("halt");
        !           310:        if (nosync)
        !           311:                (void)printf(" no sync");
        !           312:        if (dofast)
        !           313:                (void)printf(" no fsck");
        !           314:        (void)printf("\nkill -HUP 1\n");
        !           315: #else
        !           316:        if (doreboot) {
        !           317:                execle(_PATH_REBOOT, "reboot", "-l", nosync, 0);
        !           318:                syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_REBOOT);
        !           319:                perror("shutdown");
        !           320:        }
        !           321:        else if (dohalt) {
        !           322:                execle(_PATH_HALT, "halt", "-l", nosync, 0);
        !           323:                syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_HALT);
        !           324:                perror("shutdown");
        !           325:        }
        !           326:        (void)kill(1, SIGTERM);         /* to single user */
        !           327: #endif
        !           328:        finish();
        !           329: }
        !           330: 
        !           331: #define        ATOI2(p)        (p[0] - '0') * 10 + (p[1] - '0'); p += 2;
        !           332: 
        !           333: getoffset(timearg)
        !           334:        register char *timearg;
        !           335: {
        !           336:        register struct tm *lt;
        !           337:        register char *p;
        !           338:        time_t now, time();
        !           339: 
        !           340:        if (!strcasecmp(timearg, "now")) {              /* now */
        !           341:                offset = 0;
        !           342:                return;
        !           343:        }
        !           344: 
        !           345:        (void)time(&now);
        !           346:        if (*timearg == '+') {                          /* +minutes */
        !           347:                if (!isdigit(*++timearg))
        !           348:                        badtime();
        !           349:                offset = atoi(timearg) * 60;
        !           350:                shuttime = now + offset;
        !           351:                return;
        !           352:        }
        !           353: 
        !           354:        /* handle hh:mm by getting rid of the colon */
        !           355:        for (p = timearg; *p; ++p)
        !           356:                if (!isascii(*p) || !isdigit(*p))
        !           357:                        if (*p == ':' && strlen(p) == 3) {
        !           358:                                p[0] = p[1];
        !           359:                                p[1] = p[2];
        !           360:                                p[2] = '\0';
        !           361:                        }
        !           362:                        else
        !           363:                                badtime();
        !           364: 
        !           365:        unsetenv("TZ");                                 /* OUR timezone */
        !           366:        lt = localtime(&now);                           /* current time val */
        !           367: 
        !           368:        switch(strlen(timearg)) {
        !           369:        case 10:
        !           370:                lt->tm_year = ATOI2(timearg);
        !           371:                /* FALLTHROUGH */
        !           372:        case 8:
        !           373:                lt->tm_mon = ATOI2(timearg);
        !           374:                if (--lt->tm_mon < 0 || lt->tm_mon > 11)
        !           375:                        badtime();
        !           376:                /* FALLTHROUGH */
        !           377:        case 6:
        !           378:                lt->tm_mday = ATOI2(timearg);
        !           379:                if (lt->tm_mday < 1 || lt->tm_mday > 31)
        !           380:                        badtime();
        !           381:                /* FALLTHROUGH */
        !           382:        case 4:
        !           383:                lt->tm_hour = ATOI2(timearg);
        !           384:                if (lt->tm_hour < 0 || lt->tm_hour > 23)
        !           385:                        badtime();
        !           386:                lt->tm_min = ATOI2(timearg);
        !           387:                if (lt->tm_min < 0 || lt->tm_min > 59)
        !           388:                        badtime();
        !           389:                lt->tm_sec = 0;
        !           390:                if ((shuttime = mktime(lt)) == -1)
        !           391:                        badtime();
        !           392:                if ((offset = shuttime - now) < 0) {
        !           393:                        (void)fprintf(stderr,
        !           394:                            "shutdown: that time is already past.\n");
        !           395:                        exit(1);
        !           396:                }
        !           397:                break;
        !           398:        default:
        !           399:                badtime();
        !           400:        }
        !           401: }
        !           402: 
        !           403: #define        FSMSG   "fastboot file for fsck\n"
        !           404: doitfast()
        !           405: {
        !           406:        int fastfd;
        !           407: 
        !           408:        if ((fastfd = open(_PATH_FASTBOOT, O_WRONLY|O_CREAT|O_TRUNC,
        !           409:            0664)) >= 0) {
        !           410:                (void)write(fastfd, FSMSG, sizeof(FSMSG) - 1);
        !           411:                (void)close(fastfd);
        !           412:        }
        !           413: }
        !           414: 
        !           415: #define        NOMSG   "\n\nNO LOGINS: System going down at "
        !           416: nolog()
        !           417: {
        !           418:        int logfd;
        !           419:        char *ct, *ctime();
        !           420:        void finish();
        !           421: 
        !           422:        (void)unlink(_PATH_NOLOGIN);    /* in case linked to another file */
        !           423:        (void)signal(SIGINT, finish);
        !           424:        (void)signal(SIGHUP, finish);
        !           425:        (void)signal(SIGQUIT, finish);
        !           426:        (void)signal(SIGTERM, finish);
        !           427:        if ((logfd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT|O_TRUNC,
        !           428:            0664)) >= 0) {
        !           429:                (void)write(logfd, NOMSG, sizeof(NOMSG) - 1);
        !           430:                ct = ctime(&shuttime);
        !           431:                (void)write(logfd, ct + 11, 5);
        !           432:                (void)write(logfd, "\n\n", 2);
        !           433:                (void)write(logfd, mbuf, strlen(mbuf));
        !           434:                (void)close(logfd);
        !           435:        }
        !           436: }
        !           437: 
        !           438: void
        !           439: finish()
        !           440: {
        !           441:        (void)unlink(_PATH_NOLOGIN);
        !           442:        exit(0);
        !           443: }
        !           444: 
        !           445: badtime()
        !           446: {
        !           447:        (void)fprintf(stderr, "shutdown: bad time format.\n");
        !           448:        exit(1);
        !           449: }
        !           450: 
        !           451: usage()
        !           452: {
        !           453:        fprintf(stderr, "usage: shutdown [-fhknr] shutdowntime [ message ]\n");
        !           454:        exit(1);
        !           455: }

unix.superglobalmegacorp.com

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