|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.