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