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

1.1       root        1: /*
                      2:  * Copyright (c) 1983,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: char copyright[] =
                      9: "@(#) Copyright (c) 1983,1986 Regents of the University of California.\n\
                     10:  All rights reserved.\n";
                     11: #endif not lint
                     12: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)shutdown.c 5.7 (Berkeley) 12/26/87";
                     15: #endif not lint
                     16: 
                     17: #include <stdio.h>
                     18: #include <ctype.h>
                     19: #include <signal.h>
                     20: #include <setjmp.h>
                     21: #include <utmp.h>
                     22: #include <pwd.h>
                     23: #include <sys/time.h>
                     24: #include <sys/resource.h>
                     25: #include <sys/param.h>
                     26: #include <sys/syslog.h>
                     27: 
                     28: /*
                     29:  *     /etc/shutdown when [messages]
                     30:  *
                     31:  *     allow super users to tell users and remind users
                     32:  *     of iminent shutdown of unix
                     33:  *     and shut it down automatically
                     34:  *     and even reboot or halt the machine if they desire
                     35:  */
                     36: 
                     37: #define        REBOOT  "/etc/reboot"
                     38: #define        HALT    "/etc/halt"
                     39: #define MAXINTS 20
                     40: #define        HOURS   *3600
                     41: #define MINUTES        *60
                     42: #define SECONDS
                     43: #define NLOG           600             /* no of bytes possible for message */
                     44: #define        NOLOGTIME       5 MINUTES
                     45: #define IGNOREUSER     "sleeper"
                     46: 
                     47: char   hostname[MAXHOSTNAMELEN];
                     48: 
                     49: int    timeout();
                     50: time_t getsdt();
                     51: void   finish();
                     52: 
                     53: extern char *ctime();
                     54: extern struct tm *localtime();
                     55: extern long time();
                     56: 
                     57: extern char *strcpy();
                     58: extern char *strncat();
                     59: extern off_t lseek();
                     60: 
                     61: struct utmp utmp;
                     62: int    sint;
                     63: int    stogo;
                     64: char   tpath[] =       "/dev/";
                     65: int    nlflag = 1;             /* nolog yet to be done */
                     66: int    killflg = 1;
                     67: int    doreboot = 0;
                     68: int    halt = 0;
                     69: int     fast = 0;
                     70: char    *nosync = NULL;
                     71: char    nosyncflag[] = "-n";
                     72: char   term[sizeof tpath + sizeof utmp.ut_line];
                     73: char   tbuf[BUFSIZ];
                     74: char   nolog1[] = "\n\nNO LOGINS: System going down at %5.5s\n\n";
                     75: char   nolog2[NLOG+1];
                     76: #ifdef DEBUG
                     77: char   nologin[] = "nologin";
                     78: char    fastboot[] = "fastboot";
                     79: #else
                     80: char   nologin[] = "/etc/nologin";
                     81: char   fastboot[] = "/fastboot";
                     82: #endif
                     83: time_t nowtime;
                     84: jmp_buf        alarmbuf;
                     85: 
                     86: struct interval {
                     87:        int stogo;
                     88:        int sint;
                     89: } interval[] = {
                     90:        4 HOURS,        1 HOURS,
                     91:        2 HOURS,        30 MINUTES,
                     92:        1 HOURS,        15 MINUTES,
                     93:        30 MINUTES,     10 MINUTES,
                     94:        15 MINUTES,     5 MINUTES,
                     95:        10 MINUTES,     5 MINUTES,
                     96:        5 MINUTES,      3 MINUTES,
                     97:        2 MINUTES,      1 MINUTES,
                     98:        1 MINUTES,      30 SECONDS,
                     99:        0 SECONDS,      0 SECONDS
                    100: };
                    101: 
                    102: char *shutter, *getlogin();
                    103: 
                    104: main(argc,argv)
                    105:        int argc;
                    106:        char **argv;
                    107: {
                    108:        register i, ufd;
                    109:        register char *f;
                    110:        char *ts;
                    111:        time_t sdt;
                    112:        int h, m;
                    113:        int first;
                    114:        FILE *termf;
                    115:        struct passwd *pw, *getpwuid();
                    116:        extern char *strcat();
                    117:        extern uid_t geteuid();
                    118: 
                    119:        shutter = getlogin();
                    120:        if (shutter == 0 && (pw = getpwuid(getuid())))
                    121:                shutter = pw->pw_name;
                    122:        if (shutter == 0)
                    123:                shutter = "???";
                    124:        (void) gethostname(hostname, sizeof (hostname));
                    125:        openlog("shutdown", 0, LOG_AUTH);
                    126:        argc--, argv++;
                    127:        while (argc > 0 && (f = argv[0], *f++ == '-')) {
                    128:                while (i = *f++) switch (i) {
                    129:                case 'k':
                    130:                        killflg = 0;
                    131:                        continue;
                    132:                case 'n':
                    133:                        nosync = nosyncflag;
                    134:                        continue;
                    135:                case 'f':
                    136:                        fast = 1;
                    137:                        continue;
                    138:                case 'r':
                    139:                        doreboot = 1;
                    140:                        continue;
                    141:                case 'h':
                    142:                        halt = 1;
                    143:                        continue;
                    144:                default:
                    145:                        fprintf(stderr, "shutdown: '%c' - unknown flag\n", i);
                    146:                        exit(1);
                    147:                }
                    148:                argc--, argv++;
                    149:        }
                    150:        if (argc < 1) {
                    151:                /* argv[0] is not available after the argument handling. */
                    152:                printf("Usage: shutdown [ -krhfn ] shutdowntime [ message ]\n");
                    153:                finish();
                    154:        }
                    155:        if (fast && (nosync == nosyncflag)) {
                    156:                printf ("shutdown: Incompatible switches 'fast' & 'nosync'\n");
                    157:                finish();
                    158:        }
                    159:        if (geteuid()) {
                    160:                fprintf(stderr, "NOT super-user\n");
                    161:                finish();
                    162:        }
                    163:        nowtime = time((long *)0);
                    164:        sdt = getsdt(argv[0]);
                    165:        argc--, argv++;
                    166:        nolog2[0] = '\0';
                    167:        while (argc-- > 0) {
                    168:                (void) strcat(nolog2, " ");
                    169:                (void) strcat(nolog2, *argv++);
                    170:        }
                    171:        m = ((stogo = sdt - nowtime) + 30)/60;
                    172:        h = m/60; 
                    173:        m %= 60;
                    174:        ts = ctime(&sdt);
                    175:        printf("Shutdown at %5.5s (in ", ts+11);
                    176:        if (h > 0)
                    177:                printf("%d hour%s ", h, h != 1 ? "s" : "");
                    178:        printf("%d minute%s) ", m, m != 1 ? "s" : "");
                    179: #ifndef DEBUG
                    180:        (void) signal(SIGHUP, SIG_IGN);
                    181:        (void) signal(SIGQUIT, SIG_IGN);
                    182:        (void) signal(SIGINT, SIG_IGN);
                    183: #endif
                    184:        (void) signal(SIGTTOU, SIG_IGN);
                    185:        (void) signal(SIGTERM, finish);
                    186:        (void) signal(SIGALRM, timeout);
                    187:        (void) setpriority(PRIO_PROCESS, 0, PRIO_MIN);
                    188:        (void) fflush(stdout);
                    189: #ifndef DEBUG
                    190:        if (i = fork()) {
                    191:                printf("[pid %d]\n", i);
                    192:                exit(0);
                    193:        }
                    194: #else
                    195:        (void) putc('\n', stdout);
                    196: #endif
                    197:        sint = 1 HOURS;
                    198:        f = "";
                    199:        ufd = open("/etc/utmp",0);
                    200:        if (ufd < 0) {
                    201:                perror("shutdown: /etc/utmp");
                    202:                exit(1);
                    203:        }
                    204:        first = 1;
                    205:        for (;;) {
                    206:                for (i = 0; stogo <= interval[i].stogo && interval[i].sint; i++)
                    207:                        sint = interval[i].sint;
                    208:                if (stogo > 0 && (stogo-sint) < interval[i].stogo)
                    209:                        sint = stogo - interval[i].stogo;
                    210:                if (stogo <= NOLOGTIME && nlflag) {
                    211:                        nlflag = 0;
                    212:                        nolog(sdt);
                    213:                }
                    214:                if (sint >= stogo || sint == 0)
                    215:                        f = "FINAL ";
                    216:                nowtime = time((long *)0);
                    217:                (void) lseek(ufd, 0L, 0);
                    218:                while (read(ufd,(char *)&utmp,sizeof utmp)==sizeof utmp)
                    219:                if (utmp.ut_name[0] &&
                    220:                    strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name))) {
                    221:                        if (setjmp(alarmbuf))
                    222:                                continue;
                    223:                        (void) strcpy(term, tpath);
                    224:                        (void) strncat(term, utmp.ut_line, sizeof utmp.ut_line);
                    225:                        (void) alarm(3);
                    226: #ifdef DEBUG
                    227:                        if ((termf = stdout) != NULL)
                    228: #else
                    229:                        if ((termf = fopen(term, "w")) != NULL)
                    230: #endif
                    231:                        {
                    232:                                (void) alarm(0);
                    233:                                setbuf(termf, tbuf);
                    234:                                fprintf(termf, "\n\r\n");
                    235:                                warn(termf, sdt, nowtime, f);
                    236:                                if (first || sdt - nowtime > 1 MINUTES) {
                    237:                                        if (*nolog2)
                    238:                                                fprintf(termf, "\t...%s", nolog2);
                    239:                                }
                    240:                                (void) fputc('\r', termf);
                    241:                                (void) fputc('\n', termf);
                    242:                                (void) alarm(5);
                    243: #ifdef DEBUG
                    244:                                (void) fflush(termf);
                    245: #else
                    246:                                (void) fclose(termf);
                    247: #endif
                    248:                                (void) alarm(0);
                    249:                        }
                    250:                }
                    251:                if (stogo <= 0) {
                    252:                        printf("\n\007\007System shutdown time has arrived\007\007\n");
                    253:                        syslog(LOG_CRIT, "%s by %s: %s",
                    254:                            doreboot ? "reboot" : halt ? "halt" : "shutdown",
                    255:                            shutter, nolog2);
                    256:                        sleep(2);
                    257:                        (void) unlink(nologin);
                    258:                        if (!killflg) {
                    259:                                printf("but you'll have to do it yourself\n");
                    260:                                finish();
                    261:                        }
                    262:                        if (fast)
                    263:                                doitfast();
                    264: #ifndef DEBUG
                    265:                        if (doreboot)
                    266:                                execle(REBOOT, "reboot", "-l", nosync, 0, 0);
                    267:                        if (halt)
                    268:                                execle(HALT, "halt", "-l", nosync, 0, 0);
                    269:                        (void) kill(1, SIGTERM);        /* to single user */
                    270: #else
                    271:                        if (doreboot)
                    272:                                printf("REBOOT");
                    273:                        if (halt)
                    274:                                printf(" HALT");
                    275:                        if (fast)
                    276:                                printf(" -l %s (without fsck's)\n", nosync);
                    277:                        else
                    278:                                printf(" -l %s\n", nosync);
                    279:                        else
                    280:                                printf("kill -HUP 1\n");
                    281: 
                    282: #endif
                    283:                        finish();
                    284:                }
                    285:                stogo = sdt - time((long *) 0);
                    286:                if (stogo > 0 && sint > 0)
                    287:                        sleep((unsigned)(sint<stogo ? sint : stogo));
                    288:                stogo -= sint;
                    289:                first = 0;
                    290:        }
                    291: }
                    292: 
                    293: time_t
                    294: getsdt(s)
                    295:        register char *s;
                    296: {
                    297:        time_t t, t1, tim;
                    298:        register char c;
                    299:        struct tm *lt;
                    300: 
                    301:        if (strcmp(s, "now") == 0)
                    302:                return(nowtime);
                    303:        if (*s == '+') {
                    304:                ++s; 
                    305:                t = 0;
                    306:                for (;;) {
                    307:                        c = *s++;
                    308:                        if (!isdigit(c))
                    309:                                break;
                    310:                        t = t * 10 + c - '0';
                    311:                }
                    312:                if (t <= 0)
                    313:                        t = 5;
                    314:                t *= 60;
                    315:                tim = time((long *) 0) + t;
                    316:                return(tim);
                    317:        }
                    318:        t = 0;
                    319:        while (strlen(s) > 2 && isdigit(*s))
                    320:                t = t * 10 + *s++ - '0';
                    321:        if (*s == ':')
                    322:                s++;
                    323:        if (t > 23)
                    324:                goto badform;
                    325:        tim = t*60;
                    326:        t = 0;
                    327:        while (isdigit(*s))
                    328:                t = t * 10 + *s++ - '0';
                    329:        if (t > 59)
                    330:                goto badform;
                    331:        tim += t; 
                    332:        tim *= 60;
                    333:        t1 = time((long *) 0);
                    334:        lt = localtime(&t1);
                    335:        t = lt->tm_sec + lt->tm_min*60 + lt->tm_hour*3600;
                    336:        if (tim < t || tim >= (24*3600)) {
                    337:                /* before now or after midnight */
                    338:                printf("That must be tomorrow\nCan't you wait till then?\n");
                    339:                finish();
                    340:        }
                    341:        return (t1 + tim - t);
                    342: badform:
                    343:        printf("Bad time format\n");
                    344:        finish();
                    345:        /*NOTREACHED*/
                    346: }
                    347: 
                    348: warn(term, sdt, now, type)
                    349:        FILE *term;
                    350:        time_t sdt, now;
                    351:        char *type;
                    352: {
                    353:        char *ts;
                    354:        register delay = sdt - now;
                    355: 
                    356:        if (delay > 8)
                    357:                while (delay % 5)
                    358:                        delay++;
                    359: 
                    360:        fprintf(term,
                    361:            "\007\007\t*** %sSystem shutdown message from %s@%s ***\r\n\n",
                    362:                    type, shutter, hostname);
                    363: 
                    364:        ts = ctime(&sdt);
                    365:        if (delay > 10 MINUTES)
                    366:                fprintf(term, "System going down at %5.5s\r\n", ts+11);
                    367:        else if (delay > 95 SECONDS) {
                    368:                fprintf(term, "System going down in %d minute%s\r\n",
                    369:                    (delay+30)/60, (delay+30)/60 != 1 ? "s" : "");
                    370:        } else if (delay > 0) {
                    371:                fprintf(term, "System going down in %d second%s\r\n",
                    372:                    delay, delay != 1 ? "s" : "");
                    373:        } else
                    374:                fprintf(term, "System going down IMMEDIATELY\r\n");
                    375: }
                    376: 
                    377: doitfast()
                    378: {
                    379:        FILE *fastd;
                    380: 
                    381:        if ((fastd = fopen(fastboot, "w")) != NULL) {
                    382:                putc('\n', fastd);
                    383:                (void) fclose(fastd);
                    384:        }
                    385: }
                    386: 
                    387: nolog(sdt)
                    388:        time_t sdt;
                    389: {
                    390:        FILE *nologf;
                    391: 
                    392:        (void) unlink(nologin);                 /* in case linked to std file */
                    393:        if ((nologf = fopen(nologin, "w")) != NULL) {
                    394:                fprintf(nologf, nolog1, (ctime(&sdt)) + 11);
                    395:                if (*nolog2)
                    396:                        fprintf(nologf, "\t%s\n", nolog2 + 1);
                    397:                (void) fclose(nologf);
                    398:        }
                    399: }
                    400: 
                    401: void
                    402: finish()
                    403: {
                    404:        (void) signal(SIGTERM, SIG_IGN);
                    405:        (void) unlink(nologin);
                    406:        exit(0);
                    407: }
                    408: 
                    409: timeout()
                    410: {
                    411:        longjmp(alarmbuf, 1);
                    412: }

unix.superglobalmegacorp.com

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