|
|
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.