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