1: static  char *sccsid = "@(#)shutdown.c	4.7 (Berkeley) 81/05/11";
   2: 
   3: #include <stdio.h>
   4: #include <ctype.h>
   5: #include <signal.h>
   6: #include <utmp.h>
   7: #include <time.h>
   8: #include <sys/types.h>
   9: #include <pwd.h>
  10: /*
  11:  *	/etc/shutdown when [messages]
  12:  *
  13:  *	allow super users to tell users and remind users
  14:  *	of imminent shutdown of unix
  15:  *	and shut it down automatically
  16:  *	and even reboot or halt the machine if they desire
  17:  *
  18:  *		Ian Johnstone, Sydney, 1977
  19:  *		Robert Elz, Melbourne, 1978
  20:  *		Peter Lamb, Melbourne, 1980
  21:  *		William Joy, Berkeley, 1981
  22:  *		Michael Toy, Berkeley, 1981
  23:  *		Dave Presotto, Berkeley, 1981
  24:  *
  25:  */
  26: #ifdef DEBUG
  27: #define LOGFILE "shutdown.log"
  28: #else
  29: #define LOGFILE "/usr/adm/shutdownlog"
  30: #endif
  31: #define REBOOT  "/etc/reboot"
  32: #define HALT_OPT    "-h"    /* option to reboot to halt */
  33: #define MAXINTS 20
  34: #define HOURS   *3600
  35: #define MINUTES *60
  36: #define SECONDS
  37: #define NLOG        20      /* no of lines possible for message */
  38: #define NOLOGTIME   5 MINUTES
  39: #define IGNOREUSER  "sleeper"
  40: 
  41: int finish ();
  42: int do_nothing();
  43: time_t  getsdt();
  44: 
  45: extern  char *ctime();
  46: extern  time_t time();
  47: extern  struct tm *localtime();
  48: 
  49: struct  utmp utmp;
  50: int sint;
  51: int stogo;
  52: char    tpath[] =   "/dev/";
  53: int nlflag = 1;     /* nolog yet to be done */
  54: int killflg = 1;
  55: int reboot = 0;
  56: int halt = 0;
  57: char    term[sizeof tpath + sizeof utmp.ut_line];
  58: char    tbuf[BUFSIZ];
  59: char    nolog1[] = "\n\nNO LOGINS: System going down at %5.5s\n\n";
  60: char    *nolog2[NLOG+1];
  61: #ifdef  DEBUG
  62: char    nologin[] = "nologin";
  63: #else
  64: char    nologin[] = "/etc/nologin";
  65: #endif
  66: int slots;
  67: struct interval {
  68:     int stogo;
  69:     int sint;
  70: } interval[] = {
  71:     4 HOURS,    1 HOURS,
  72:     2 HOURS,    30 MINUTES,
  73:     1 HOURS,    15 MINUTES,
  74:     30 MINUTES, 10 MINUTES,
  75:     15 MINUTES, 5 MINUTES,
  76:     10 MINUTES, 5 MINUTES,
  77:     5 MINUTES,  3 MINUTES,
  78:     2 MINUTES,  30 SECONDS,
  79:     0 SECONDS,  0 SECONDS
  80: };
  81: char *shutter;
  82: struct  passwd  *pwent, *getpwuid();
  83: main(argc,argv)
  84:     int argc;
  85:     char **argv;
  86: {
  87:     register i, ufd;
  88:     register char **mess, *f;
  89:     char *ts;
  90:     time_t sdt;
  91:     int h, m;
  92:     time_t nowtime;
  93:     FILE *termf;
  94: 
  95:     pwent = getpwuid(getuid());
  96:     if (pwent != (struct passwd *) NULL)
  97:         shutter = pwent->pw_name;
  98: 
  99:     argc--, argv++;
 100:     while (argc > 0 && (f = argv[0], *f++ == '-')) {
 101:         while (i = *f++) switch (i) {
 102:         case 'k':
 103:             killflg = 0;
 104:             continue;
 105:         case 'r':
 106:             reboot = 1;
 107:             continue;
 108:         case 'h':
 109:             halt = 1;
 110:             continue;
 111:         default:
 112:             fprintf(stderr, "shutdown: '%c' - unknown flag\n", i);
 113:             exit(1);
 114:         }
 115:         argc--, argv++;
 116:     }
 117:     if (argc < 1) {
 118:         printf("Usage: shutdown [ -krd ] shutdowntime [ message ]\n");
 119:         finish();
 120:     }
 121:     if (geteuid()) {
 122:         fprintf(stderr, "NOT super-user\n");
 123:         finish();
 124:     }
 125:     sdt = getsdt(argv[0]);
 126:     argc--, argv++;
 127:     i = 0;
 128:     while (argc-- > 0)
 129:         if (i < NLOG)
 130:             nolog2[i++] = *argv++;
 131:     nolog2[i] = NULL;
 132:     nowtime = time((time_t *)0);
 133:     m = ((stogo = sdt - nowtime) + 30)/60;
 134:     h = m/60;
 135:     m %= 60;
 136:     ts = ctime(&sdt);
 137:     printf("Shutdown at %5.5s (in ", ts+11);
 138:     if (h > 0)
 139:         printf("%d hour%s ", h, h != 1 ? "s" : "");
 140:     printf("%d minute%s) ", m, m != 1 ? "s" : "");
 141: #ifndef DEBUG
 142:     signal(SIGHUP, SIG_IGN);
 143:     signal(SIGQUIT, SIG_IGN);
 144:     signal(SIGINT, SIG_IGN);
 145: #endif
 146:     signal(SIGTERM, finish);
 147:     signal(SIGALRM, do_nothing);
 148:     nice(-20);
 149: #ifndef DEBUG
 150:     if (i = fork()) {
 151:         printf("[pid %d]\n", i);
 152:         exit(0);
 153:     }
 154: #endif
 155:     sint = 1 HOURS;
 156:     f = "";
 157:     for (;;) {
 158:         for (i = 0; stogo <= interval[i].stogo && interval[i].sint; i++)
 159:             sint = interval[i].sint;
 160:         if (stogo <= NOLOGTIME && nlflag) {
 161:             nlflag = 0;
 162:             nolog(sdt);
 163:         }
 164:         if (sint >= stogo || sint == 0)
 165:             f = "FINAL ";
 166:         ufd = open("/etc/utmp",0);
 167:         nowtime = time((time_t *) 0);
 168:         while (read(ufd,&utmp,sizeof utmp)==sizeof utmp)
 169:         if (utmp.ut_name[0] && strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name)) ){
 170:             strcpy(term, tpath);
 171:             strncat(term, utmp.ut_line, sizeof utmp.ut_line);
 172:             alarm(3);
 173: #ifdef DEBUG
 174:             if ((termf = stdout) != NULL)
 175: #else
 176:             if ((termf = fopen(term, "w")) != NULL)
 177: #endif
 178:             {
 179:                 alarm(0);
 180:                 setbuf(termf, tbuf);
 181:                 fprintf(termf, "\n\n");
 182:                 warn(termf, sdt, nowtime);
 183:                 if (sdt - nowtime > 1 MINUTES)
 184:                     for (mess = nolog2; *mess; mess++)
 185:                         fprintf(termf, "%s ", *mess);
 186:                 fputc('\n', termf);
 187:                 alarm(5);
 188: #ifdef DEBUG
 189:                 fflush(termf);
 190: #else
 191:                 fclose(termf);
 192: #endif
 193:                 alarm(0);
 194:             }
 195:         }
 196:         if (stogo < 0) {
 197:     printf("\n\007\007System shutdown time has arrived\007\007\n");
 198:             log_entry(sdt);
 199:             unlink(nologin);
 200:             if (!killflg) {
 201:                 printf("but you'll have to do it yourself\n");
 202:                 finish();
 203:             }
 204: #ifndef DEBUG
 205:             if (reboot)
 206:                 execle(REBOOT, "reboot", 0, 0);
 207:             if (halt)
 208:                 execle(REBOOT, "reboot", HALT_OPT, 0, 0);
 209:             kill(1, SIGTERM);   /* sync */
 210:             kill(1, SIGTERM);   /* sync */
 211:             sleep(20);
 212: #else
 213:             printf("EXTERMINATE EXTERMINATE\n");
 214: #endif
 215:             finish();
 216:         }
 217:         stogo = sdt - time((time_t *) 0);
 218:         if (stogo > 0)
 219:             sleep(sint<stogo ? sint : stogo);
 220:         stogo -= sint;
 221:     }
 222: }
 223: 
 224: time_t
 225: getsdt(s)
 226: register char *s;
 227: {
 228:     time_t t, t1, tim;
 229:     register char c;
 230:     struct tm *lt;
 231: 
 232:     if (*s == '+') {
 233:         ++s;
 234:         t = 0;
 235:         for (;;) {
 236:             c = *s++;
 237:             if (!isdigit(c))
 238:                 break;
 239:             t = t * 10 + c - '0';
 240:         }
 241:         if (t <= 0)
 242:             t = 5;
 243:         t *= 60;
 244:         tim = time((time_t *) 0) + t;
 245:         return(tim);
 246:     }
 247:     t = 0;
 248:     while (strlen(s) > 2 && isdigit(*s))
 249:         t = t * 10 + *s++ - '0';
 250:     if (*s == ':')
 251:         s++;
 252:     if (t > 23)
 253:         goto badform;
 254:     tim = t*60;
 255:     t = 0;
 256:     while (isdigit(*s))
 257:         t = t * 10 + *s++ - '0';
 258:     if (t > 59)
 259:         goto badform;
 260:     tim += t;
 261:     tim *= 60;
 262:     t1 = time((time_t *) 0);
 263:     lt = localtime(&t1);
 264:     t = lt->tm_sec + lt->tm_min*60L + lt->tm_hour*3600L;
 265:     if (tim < t || tim >= (24*3600L)) {
 266:         /* before now or after midnight */
 267:         printf("That must be tomorrow\nCan't you wait till then?\n");
 268:         finish();
 269:     }
 270:     return (t1 + tim -t);
 271: badform:
 272:     printf("Bad time format\n");
 273:     finish();
 274: }
 275: 
 276: warn(term, sdt, nowtime)
 277:     FILE *term;
 278:     time_t sdt, nowtime;
 279: {
 280:     char *ts;
 281: 
 282:     if (shutter)
 283:         fprintf(term,
 284:             "\007\007*** System shutdown message from %s ***\n",
 285:             shutter);
 286:     else
 287:         fprintf(term,
 288:             "\007\007*** System shutdown message ***\n");
 289:     ts = ctime(&sdt);
 290:     if (sdt - nowtime > 10 MINUTES)
 291:         fprintf(term, "System going down at %5.5s\n", ts+11);
 292:     else if ( sdt - nowtime > 60 SECONDS ) {
 293:         fprintf(term, "System going down in %d minute%s\n",
 294:         (int)((sdt-nowtime+30)/60),
 295:         (sdt-nowtime+30)/60 != 1 ? "s" : "");
 296:     } else if ( sdt - nowtime > 0 ) {
 297:         fprintf(term, "System going down in %d second%s\n",
 298:         (int)(sdt-nowtime), sdt-nowtime != 1 ? "s" : "");
 299:     } else
 300:         fprintf(term, "System going down IMMEDIATELY\n");
 301: }
 302: 
 303: nolog(sdt)
 304:     time_t sdt;
 305: {
 306:     FILE *nologf;
 307:     register char **mess;
 308: 
 309:     if ((nologf = fopen(nologin, "w")) != NULL) {
 310:         fprintf(nologf, nolog1, (ctime(&sdt)) + 11);
 311:         for (mess = nolog2; *mess; mess++)
 312:             fprintf(nologf, "\t%s\n", *mess);
 313:         fclose(nologf);
 314:     }
 315: }
 316: 
 317: finish()
 318: {
 319:     signal(SIGTERM, SIG_IGN);
 320:     unlink(nologin);
 321:     exit(0);
 322: }
 323: 
 324: do_nothing()
 325: {
 326:     signal(SIGALRM, do_nothing);
 327: }
 328: 
 329: /*
 330:  * make an entry in the shutdown log
 331:  */
 332: 
 333: char *days[] = {
 334:     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 335: };
 336: 
 337: char *months[] = {
 338:     "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
 339:     "Oct", "Nov", "Dec"
 340: };
 341: 
 342: log_entry(now)
 343: time_t now;
 344: {
 345:     register FILE *fp;
 346:     register char **mess;
 347:     struct tm *tm, *localtime();
 348: 
 349:     tm = localtime(&now);
 350:     fp = fopen(LOGFILE, "a");
 351:     if (fp==0)
 352:         return;
 353:     fseek(fp, 0L, 2);
 354:     fprintf(fp, "%02d:%02d  %s %s %2d, %4d.  Shutdown:", tm->tm_hour,
 355:         tm->tm_min, days[tm->tm_wday], months[tm->tm_mon],
 356:         tm->tm_mday, tm->tm_year + 1900);
 357:     for (mess = nolog2; *mess; mess++)
 358:         fprintf(fp, " %s", *mess);
 359:     if (shutter)
 360:         fprintf(fp, " (by %s)", shutter);
 361:     fputc('\n', fp);
 362:     fclose(fp);
 363: }

Defined functions

do_nothing defined in line 324; used 3 times
finish defined in line 317; used 8 times
getsdt defined in line 224; used 2 times
log_entry defined in line 342; used 1 times
main defined in line 83; never used
nolog defined in line 303; used 1 times
warn defined in line 276; used 1 times

Defined variables

days defined in line 333; used 1 times
halt defined in line 56; used 2 times
interval defined in line 70; used 3 times
killflg defined in line 54; used 2 times
months defined in line 337; used 1 times
nlflag defined in line 53; used 2 times
nolog1 defined in line 59; used 1 times
nolog2 defined in line 60; used 5 times
nologin defined in line 64; used 3 times
pwent defined in line 82; used 3 times
reboot defined in line 55; used 2 times
sccsid defined in line 1; never used
shutter defined in line 81; used 5 times
sint defined in line 50; used 10 times
slots defined in line 66; never used
stogo defined in line 51; used 12 times
tbuf defined in line 58; used 1 times
term defined in line 57; used 11 times
tpath defined in line 52; used 2 times
utmp defined in line 49; used 9 times

Defined struct's

interval defined in line 67; never used

Defined macros

HALT_OPT defined in line 32; used 1 times
HOURS defined in line 34; used 5 times
IGNOREUSER defined in line 39; used 1 times
LOGFILE defined in line 29; used 1 times
MAXINTS defined in line 33; never used
MINUTES defined in line 35; used 14 times
NLOG defined in line 37; used 2 times
NOLOGTIME defined in line 38; used 1 times
REBOOT defined in line 31; used 2 times
SECONDS defined in line 36; used 4 times
Last modified: 1983-06-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1433
Valid CSS Valid XHTML 1.0 Strict