xref: /original-bsd/sbin/reboot/reboot.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1980, 1986, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1980, 1986, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)reboot.c	8.1 (Berkeley) 06/05/93";
16 #endif /* not lint */
17 
18 #include <sys/reboot.h>
19 #include <signal.h>
20 #include <pwd.h>
21 #include <errno.h>
22 #include <syslog.h>
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 void err __P((const char *fmt, ...));
29 void usage __P((void));
30 
31 int dohalt;
32 
33 int
34 main(argc, argv)
35 	int argc;
36 	char *argv[];
37 {
38 	register int i;
39 	struct passwd *pw;
40 	int ch, howto, lflag, nflag, qflag, sverrno;
41 	char *p, *user;
42 
43 	if (!strcmp((p = rindex(*argv, '/')) ? p + 1 : *argv, "halt")) {
44 		dohalt = 1;
45 		howto = RB_HALT;
46 	} else
47 		howto = 0;
48 	lflag = nflag = qflag = 0;
49 	while ((ch = getopt(argc, argv, "lnq")) != EOF)
50 		switch(ch) {
51 		case 'l':		/* Undocumented; used by shutdown. */
52 			lflag = 1;
53 			break;
54 		case 'n':
55 			nflag = 1;
56 			howto |= RB_NOSYNC;
57 			break;
58 		case 'q':
59 			qflag = 1;
60 			break;
61 		case '?':
62 		default:
63 			usage();
64 		}
65 	argc -= optind;
66 	argv += optind;
67 
68 	if (geteuid())
69 		err("%s", strerror(EPERM));
70 
71 	if (qflag) {
72 		reboot(howto);
73 		err("%s", strerror(errno));
74 	}
75 
76 	/* Log the reboot. */
77 	if (!lflag)  {
78 		if ((user = getlogin()) == NULL)
79 			user = (pw = getpwuid(getuid())) ?
80 			    pw->pw_name : "???";
81 		if (dohalt) {
82 			openlog("halt", 0, LOG_AUTH | LOG_CONS);
83 			syslog(LOG_CRIT, "halted by %s", user);
84 		} else {
85 			openlog("reboot", 0, LOG_AUTH | LOG_CONS);
86 			syslog(LOG_CRIT, "rebooted by %s", user);
87 		}
88 	}
89 	logwtmp("~", "shutdown", "");
90 
91 	/*
92 	 * Do a sync early on, so disks start transfers while we're off
93 	 * killing processes.  Don't worry about writes done before the
94 	 * processes die, the reboot system call syncs the disks.
95 	 */
96 	if (!nflag)
97 		sync();
98 
99 	/* Just stop init -- if we fail, we'll restart it. */
100 	if (kill(1, SIGTSTP) == -1)
101 		err("SIGTSTP init: %s", strerror(errno));
102 
103 	/* Ignore the SIGHUP we get when our parent shell dies. */
104 	(void)signal(SIGHUP, SIG_IGN);
105 
106 	/* Send a SIGTERM first, a chance to save the buffers. */
107 	if (kill(-1, SIGTERM) == -1)
108 		err("SIGTERM processes: %s", strerror(errno));
109 
110 	/*
111 	 * After the processes receive the signal, start the rest of the
112 	 * buffers on their way.  Wait 5 seconds between the SIGTERM and
113 	 * the SIGKILL to give everybody a chance.
114 	 */
115 	sleep(2);
116 	if (!nflag)
117 		sync();
118 	sleep(3);
119 
120 	for (i = 1;; ++i) {
121 		if (kill(-1, SIGKILL) == -1) {
122 			if (errno == ESRCH)
123 				break;
124 			goto restart;
125 		}
126 		if (i > 5) {
127 			(void)fprintf(stderr,
128 			    "WARNING: some process(es) wouldn't die\n");
129 			break;
130 		}
131 		(void)sleep(2 * i);
132 	}
133 
134 	reboot(howto);
135 	/* FALLTHROUGH */
136 
137 restart:
138 	sverrno = errno;
139 	err("%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
140 	    strerror(sverrno));
141 	/* NOTREACHED */
142 }
143 
144 void
145 usage()
146 {
147 	(void)fprintf(stderr, "usage: %s [-nq]\n", dohalt ? "halt" : "reboot");
148 	exit(1);
149 }
150 
151 #if __STDC__
152 #include <stdarg.h>
153 #else
154 #include <varargs.h>
155 #endif
156 
157 void
158 #if __STDC__
159 err(const char *fmt, ...)
160 #else
161 err(fmt, va_alist)
162 	char *fmt;
163         va_dcl
164 #endif
165 {
166 	va_list ap;
167 #if __STDC__
168 	va_start(ap, fmt);
169 #else
170 	va_start(ap);
171 #endif
172 	(void)fprintf(stderr, "%s: ", dohalt ? "halt" : "reboot");
173 	(void)vfprintf(stderr, fmt, ap);
174 	va_end(ap);
175 	(void)fprintf(stderr, "\n");
176 	exit(1);
177 	/* NOTREACHED */
178 }
179