]> git.saurik.com Git - apple/system_cmds.git/blob - reboot.tproj/reboot.c
system_cmds-230.tar.gz
[apple/system_cmds.git] / reboot.tproj / reboot.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1980, 1986, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57 #include <sys/reboot.h>
58 #include <signal.h>
59 #include <pwd.h>
60 #include <errno.h>
61 #include <syslog.h>
62 #include <unistd.h>
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <string.h>
66
67 void err __P((const char *fmt, ...));
68 void usage __P((void));
69
70 int dohalt;
71
72 int
73 main(argc, argv)
74 int argc;
75 char *argv[];
76 {
77 register int i;
78 struct passwd *pw;
79 int ch, howto, lflag, nflag, qflag, sverrno;
80 char *p, *user;
81
82 if (!strcmp((p = rindex(*argv, '/')) ? p + 1 : *argv, "halt")) {
83 dohalt = 1;
84 howto = RB_HALT;
85 } else
86 howto = 0;
87 lflag = nflag = qflag = 0;
88 while ((ch = getopt(argc, argv, "lnq")) != EOF)
89 switch(ch) {
90 case 'l': /* Undocumented; used by shutdown. */
91 lflag = 1;
92 break;
93 case 'n':
94 nflag = 1;
95 howto |= RB_NOSYNC;
96 break;
97 case 'q':
98 qflag = 1;
99 break;
100 case '?':
101 default:
102 usage();
103 }
104 argc -= optind;
105 argv += optind;
106
107 if (geteuid())
108 err("%s", strerror(EPERM));
109
110 if (qflag) {
111 reboot(howto);
112 err("%s", strerror(errno));
113 }
114
115 /* Log the reboot. */
116 if (!lflag) {
117 if ((user = getlogin()) == NULL)
118 user = (pw = getpwuid(getuid())) ?
119 pw->pw_name : "???";
120 if (dohalt) {
121 openlog("halt", 0, LOG_AUTH | LOG_CONS);
122 syslog(LOG_CRIT, "halted by %s", user);
123 } else {
124 openlog("reboot", 0, LOG_AUTH | LOG_CONS);
125 syslog(LOG_CRIT, "rebooted by %s", user);
126 }
127 }
128 logwtmp("~", "shutdown", "");
129
130 /*
131 * Do a sync early on, so disks start transfers while we're off
132 * killing processes. Don't worry about writes done before the
133 * processes die, the reboot system call syncs the disks.
134 */
135 if (!nflag)
136 sync();
137
138 /* Just stop init -- if we fail, we'll restart it. */
139 if (kill(1, SIGTSTP) == -1)
140 err("SIGTSTP init: %s", strerror(errno));
141
142 /* Ignore the SIGHUP we get when our parent shell dies. */
143 (void)signal(SIGHUP, SIG_IGN);
144
145 #if 0
146 /* Send a SIGTERM first, a chance to save the buffers. */
147 if (kill(-1, SIGTERM) == -1)
148 err("SIGTERM processes: %s", strerror(errno));
149
150 /*
151 * After the processes receive the signal, start the rest of the
152 * buffers on their way. Wait 5 seconds between the SIGTERM and
153 * the SIGKILL to give everybody a chance.
154 */
155 sleep(2);
156 if (!nflag)
157 sync();
158 sleep(3);
159
160 for (i = 1;; ++i) {
161 if (kill(-1, SIGKILL) == -1) {
162 if (errno == ESRCH)
163 break;
164 goto restart;
165 }
166 if (i > 5) {
167 (void)fprintf(stderr,
168 "WARNING: some process(es) wouldn't die\n");
169 break;
170 }
171 (void)sleep(2 * i);
172 }
173 #endif
174 reboot(howto);
175 /* FALLTHROUGH */
176
177 restart:
178 sverrno = errno;
179 err("%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
180 strerror(sverrno));
181 /* NOTREACHED */
182 }
183
184 void
185 usage()
186 {
187 (void)fprintf(stderr, "usage: %s [-nq]\n", dohalt ? "halt" : "reboot");
188 exit(1);
189 }
190
191 #if __STDC__
192 #include <stdarg.h>
193 #else
194 #include <varargs.h>
195 #endif
196
197 void
198 #if __STDC__
199 err(const char *fmt, ...)
200 #else
201 err(fmt, va_alist)
202 char *fmt;
203 va_dcl
204 #endif
205 {
206 va_list ap;
207 #if __STDC__
208 va_start(ap, fmt);
209 #else
210 va_start(ap);
211 #endif
212 (void)fprintf(stderr, "%s: ", dohalt ? "halt" : "reboot");
213 (void)vfprintf(stderr, fmt, ap);
214 va_end(ap);
215 (void)fprintf(stderr, "\n");
216 exit(1);
217 /* NOTREACHED */
218 }