kernel/arm: send SIGSEGV to processes
[minix3.git] / sbin / reboot / reboot.c
blob2da61705f7b4278f8b1a21e51085cc477e5cb641
1 /* $NetBSD: reboot.c,v 1.40 2012/11/04 22:28:16 christos Exp $ */
3 /*
4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
34 #ifndef lint
35 __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1993\
36 The Regents of the University of California. All rights reserved.");
37 #endif /* not lint */
39 #ifndef lint
40 #if 0
41 static char sccsid[] = "@(#)reboot.c 8.1 (Berkeley) 6/5/93";
42 #else
43 __RCSID("$NetBSD: reboot.c,v 1.40 2012/11/04 22:28:16 christos Exp $");
44 #endif
45 #endif /* not lint */
47 #include <sys/reboot.h>
49 #include <err.h>
50 #include <errno.h>
51 #include <pwd.h>
52 #include <signal.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <syslog.h>
57 #include <unistd.h>
58 #include <util.h>
59 #ifdef SUPPORT_UTMPX
60 #include <utmpx.h>
61 #endif
63 __dead static void usage(void);
65 static int dohalt;
66 static int dopoweroff;
68 int
69 main(int argc, char *argv[])
71 const char *progname;
72 #if !defined(__minix)
73 int i;
74 #endif /* !defined(__minix) */
75 struct passwd *pw;
76 int ch, howto, lflag, nflag, qflag, sverrno, len;
77 const char *user;
78 char *bootstr, **av;
80 progname = getprogname();
81 if (progname[0] == '-')
82 progname++;
83 if (strcmp(progname, "halt") == 0) {
84 dohalt = 1;
85 howto = RB_HALT;
86 } else if (strcmp(progname, "poweroff") == 0) {
87 dopoweroff = 1;
88 howto = RB_HALT | RB_POWERDOWN;
89 } else
90 howto = 0;
91 lflag = nflag = qflag = 0;
92 while ((ch = getopt(argc, argv, "dlnpqvxz")) != -1)
93 switch(ch) {
94 case 'd':
95 howto |= RB_DUMP;
96 break;
97 case 'l':
98 lflag = 1;
99 break;
100 case 'n':
101 nflag = 1;
102 howto |= RB_NOSYNC;
103 break;
104 case 'p':
105 if (dohalt == 0)
106 usage();
107 howto |= RB_POWERDOWN;
108 break;
109 case 'q':
110 qflag = 1;
111 break;
112 case 'v':
113 howto |= AB_VERBOSE;
114 break;
115 case 'x':
116 howto |= AB_DEBUG;
117 break;
118 case 'z':
119 howto |= AB_SILENT;
120 break;
121 case '?':
122 default:
123 usage();
125 argc -= optind;
126 argv += optind;
128 if (argc) {
129 for (av = argv, len = 0; *av; av++)
130 len += strlen(*av) + 1;
131 bootstr = malloc(len + 1);
132 *bootstr = '\0'; /* for first strcat */
133 for (av = argv; *av; av++) {
134 strcat(bootstr, *av);
135 strcat(bootstr, " ");
137 bootstr[len - 1] = '\0'; /* to kill last space */
138 howto |= RB_STRING;
139 } else
140 bootstr = NULL;
142 if (geteuid())
143 errx(1, "%s", strerror(EPERM));
145 if (qflag) {
146 reboot(howto, bootstr);
147 err(1, "reboot");
150 /* Log the reboot. */
151 if (!lflag) {
152 if ((user = getlogin()) == NULL)
153 user = (pw = getpwuid(getuid())) ?
154 pw->pw_name : "???";
155 if (dohalt) {
156 openlog("halt", LOG_CONS, LOG_AUTH);
157 syslog(LOG_CRIT, "halted by %s", user);
158 } else if (dopoweroff) {
159 openlog("poweroff", LOG_CONS, LOG_AUTH);
160 syslog(LOG_CRIT, "powered off by %s", user);
161 } else {
162 openlog("reboot", LOG_CONS, LOG_AUTH);
163 if (bootstr)
164 syslog(LOG_CRIT, "rebooted by %s: %s", user,
165 bootstr);
166 else
167 syslog(LOG_CRIT, "rebooted by %s", user);
170 #ifdef SUPPORT_UTMP
171 logwtmp("~", "shutdown", "");
172 #endif
173 #ifdef SUPPORT_UTMPX
174 logwtmpx("~", "shutdown", "", INIT_PROCESS, 0);
175 #endif
178 * Do a sync early on, so disks start transfers while we're off
179 * killing processes. Don't worry about writes done before the
180 * processes die, the reboot system call syncs the disks.
182 if (!nflag)
183 sync();
186 * Ignore signals that we can get as a result of killing
187 * parents, group leaders, etc.
189 (void)signal(SIGHUP, SIG_IGN);
190 (void)signal(SIGINT, SIG_IGN);
191 (void)signal(SIGQUIT, SIG_IGN);
192 (void)signal(SIGTERM, SIG_IGN);
193 (void)signal(SIGTSTP, SIG_IGN);
196 * If we're running in a pipeline, we don't want to die
197 * after killing whatever we're writing to.
199 (void)signal(SIGPIPE, SIG_IGN);
201 /* Just stop init -- if we fail, we'll restart it. */
202 if (kill(1, SIGTSTP) == -1)
203 err(1, "SIGTSTP init");
205 /* Send a SIGTERM first, a chance to save the buffers. */
206 if (kill(-1, SIGTERM) == -1) {
208 * If ESRCH, everything's OK: we're the only non-system
209 * process! That can happen e.g. via 'exec reboot' in
210 * single-user mode.
212 if (errno != ESRCH) {
213 warn("SIGTERM all processes");
214 goto restart;
219 * After the processes receive the signal, start the rest of the
220 * buffers on their way. Wait 5 seconds between the SIGTERM and
221 * the SIGKILL to pretend to give everybody a chance.
223 sleep(2);
224 if (!nflag)
225 sync();
226 sleep(3);
228 #if !defined(__minix)
229 for (i = 1;; ++i) {
230 if (kill(-1, SIGKILL) == -1) {
231 if (errno == ESRCH)
232 break;
233 warn("SIGKILL all processes");
234 goto restart;
236 if (i > 5) {
237 warnx("WARNING: some process(es) wouldn't die");
238 break;
240 (void)sleep(2 * i);
242 #endif /* !defined(__minix) */
244 reboot(howto, bootstr);
245 warn("reboot()");
246 /* FALLTHROUGH */
248 restart:
249 sverrno = errno;
250 errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
251 strerror(sverrno));
252 /* NOTREACHED */
255 static void
256 usage(void)
258 const char *pflag = dohalt ? "p" : "";
260 (void)fprintf(stderr, "usage: %s [-dln%sqvxz] [-- <boot string>]\n",
261 getprogname(), pflag);
262 exit(1);