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