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: }

Defined functions

doitfast defined in line 376; used 1 times
finish defined in line 400; used 8 times
getsdt defined in line 292; used 2 times
main defined in line 103; never used
nolog defined in line 386; used 1 times
timeout defined in line 407; used 2 times
warn defined in line 347; used 1 times

Defined variables

alarmbuf defined in line 83; used 2 times
copyright defined in line 8; never used
doreboot defined in line 66; used 4 times
fast defined in line 68; used 4 times
fastboot defined in line 80; used 1 times
halt defined in line 67; used 4 times
hostname defined in line 47; used 3 times
interval defined in line 88; used 5 times
killflg defined in line 65; used 2 times
nlflag defined in line 64; used 2 times
nolog1 defined in line 73; used 1 times
nolog2 defined in line 74; used 8 times
nologin defined in line 79; used 4 times
nosync defined in line 69; used 6 times
nosyncflag defined in line 70; used 2 times
sccsid defined in line 14; never used
shutter defined in line 101; used 7 times
sint defined in line 61; used 13 times
stogo defined in line 62; used 17 times
tbuf defined in line 72; used 1 times
term defined in line 71; used 10 times
tpath defined in line 63; used 2 times
utmp defined in line 60; used 9 times

Defined struct's

interval defined in line 85; never used

Defined macros

HALT defined in line 38; used 1 times
HOURS defined in line 40; used 5 times
IGNOREUSER defined in line 45; used 1 times
MAXINTS defined in line 39; never used
MINUTES defined in line 41; used 16 times
NLOG defined in line 43; used 1 times
  • in line 74
NOLOGTIME defined in line 44; used 1 times
REBOOT defined in line 37; used 1 times
SECONDS defined in line 42; used 4 times
Last modified: 1986-05-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1684
Valid CSS Valid XHTML 1.0 Strict