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

Defined functions

doitfast defined in line 368; used 1 times
finish defined in line 392; used 8 times
getsdt defined in line 284; used 2 times
main defined in line 97; never used
nolog defined in line 378; used 1 times
timeout defined in line 399; used 2 times
warn defined in line 339; used 1 times

Defined variables

alarmbuf defined in line 77; used 2 times
copyright defined in line 8; never used
doreboot defined in line 60; used 4 times
fast defined in line 62; used 4 times
fastboot defined in line 74; used 1 times
halt defined in line 61; used 4 times
hostname defined in line 49; used 3 times
interval defined in line 82; used 5 times
killflg defined in line 59; used 2 times
nlflag defined in line 58; used 2 times
nolog1 defined in line 67; used 1 times
nolog2 defined in line 68; used 8 times
nologin defined in line 73; used 4 times
nosync defined in line 63; used 6 times
nosyncflag defined in line 64; used 2 times
nowtime defined in line 76; used 6 times
sccsid defined in line 12; never used
shutter defined in line 95; used 7 times
sint defined in line 55; used 13 times
stogo defined in line 56; used 17 times
tbuf defined in line 66; used 1 times
term defined in line 65; used 10 times
tpath defined in line 57; used 2 times
utmp defined in line 54; used 9 times

Defined struct's

interval defined in line 79; never used

Defined macros

HALT defined in line 40; used 1 times
HOURS defined in line 42; used 5 times
IGNOREUSER defined in line 47; used 1 times
MAXINTS defined in line 41; never used
MINUTES defined in line 43; used 16 times
NLOG defined in line 45; used 1 times
  • in line 68
NOLOGTIME defined in line 46; used 1 times
REBOOT defined in line 39; used 1 times
SECONDS defined in line 44; used 4 times
Last modified: 1997-10-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5547
Valid CSS Valid XHTML 1.0 Strict