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
main(argc,argv)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
usage()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__
err(const char * fmt,...)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