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

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

unix.superglobalmegacorp.com

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