halt.c (f040a7a67fcbe6fabda79a643f3fd1a520472325) halt.c (3f2f09c1efd66f6d2995998ea72c5df8c70c9a97)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28/* All Rights Reserved */
29
30/*
31 * University Copyright- Copyright (c) 1982, 1986, 1988

--- 7 unchanged lines hidden (view full) ---

39
40#pragma ident "%Z%%M% %I% %E% SMI"
41
42/*
43 * Common code for halt(1M), poweroff(1M), and reboot(1M). We use
44 * argv[0] to determine which behavior to exhibit.
45 */
46
23 * Use is subject to license terms.
24 */
25
26/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27/* All Rights Reserved */
28
29/*
30 * University Copyright- Copyright (c) 1982, 1986, 1988

--- 7 unchanged lines hidden (view full) ---

38
39#pragma ident "%Z%%M% %I% %E% SMI"
40
41/*
42 * Common code for halt(1M), poweroff(1M), and reboot(1M). We use
43 * argv[0] to determine which behavior to exhibit.
44 */
45
47#include <sys/stat.h>
46#include <procfs.h>
48#include <sys/types.h>
49#include <sys/uadmin.h>
50#include <alloca.h>
51#include <assert.h>
52#include <errno.h>
53#include <fcntl.h>
54#include <libgen.h>
55#include <libscf.h>

--- 17 unchanged lines hidden (view full) ---

73extern int audit_halt_setup(int, char **);
74extern int audit_halt_success(void);
75extern int audit_halt_fail(void);
76
77extern int audit_reboot_setup(void);
78extern int audit_reboot_success(void);
79extern int audit_reboot_fail(void);
80
47#include <sys/types.h>
48#include <sys/uadmin.h>
49#include <alloca.h>
50#include <assert.h>
51#include <errno.h>
52#include <fcntl.h>
53#include <libgen.h>
54#include <libscf.h>

--- 17 unchanged lines hidden (view full) ---

72extern int audit_halt_setup(int, char **);
73extern int audit_halt_success(void);
74extern int audit_halt_fail(void);
75
76extern int audit_reboot_setup(void);
77extern int audit_reboot_success(void);
78extern int audit_reboot_fail(void);
79
80static char *cmdname; /* basename(argv[0]), the name of the command */
81
81typedef struct ctidlist_struct {
82 ctid_t ctid;
83 struct ctidlist_struct *next;
84} ctidlist_t;
85
86static ctidlist_t *ctidlist = NULL;
87static ctid_t startdct = -1;
88
89#define FMRI_STARTD_CONTRACT \
90 "svc:/system/svc/restarter:default/:properties/restarter/contract"
91
92#define ZONEADM_PROG "/usr/sbin/zoneadm"
93
82typedef struct ctidlist_struct {
83 ctid_t ctid;
84 struct ctidlist_struct *next;
85} ctidlist_t;
86
87static ctidlist_t *ctidlist = NULL;
88static ctid_t startdct = -1;
89
90#define FMRI_STARTD_CONTRACT \
91 "svc:/system/svc/restarter:default/:properties/restarter/contract"
92
93#define ZONEADM_PROG "/usr/sbin/zoneadm"
94
95static pid_t
96get_initpid()
97{
98 static int init_pid = -1;
99
100 if (init_pid == -1) {
101 if (zone_getattr(getzoneid(), ZONE_ATTR_INITPID, &init_pid,
102 sizeof (init_pid)) != sizeof (init_pid)) {
103 assert(errno == ESRCH);
104 init_pid = -1;
105 }
106 }
107 return (init_pid);
108}
109
110/*
111 * Quiesce or resume init using /proc. When stopping init, we can't send
112 * SIGTSTP (since init ignores it) or SIGSTOP (since the kernel won't permit
113 * it).
114 */
115static int
116direct_init(long command)
117{
118 char ctlfile[MAXPATHLEN];
119 pid_t pid;
120 int ctlfd;
121
122 assert(command == PCDSTOP || command == PCRUN);
123 if ((pid = get_initpid()) == -1) {
124 return (-1);
125 }
126
127 (void) snprintf(ctlfile, sizeof (ctlfile), "/proc/%d/ctl", pid);
128 if ((ctlfd = open(ctlfile, O_WRONLY)) == -1)
129 return (-1);
130
131 if (command == PCDSTOP) {
132 if (write(ctlfd, &command, sizeof (long)) == -1) {
133 (void) close(ctlfd);
134 return (-1);
135 }
136 } else { /* command == PCRUN */
137 long cmds[2];
138 cmds[0] = command;
139 cmds[1] = 0;
140 if (write(ctlfd, cmds, sizeof (cmds)) == -1) {
141 (void) close(ctlfd);
142 return (-1);
143 }
144 }
145 (void) close(ctlfd);
146 return (0);
147}
148
94static void
95stop_startd()
96{
149static void
150stop_startd()
151{
97 ctid_t ctid;
98
99 scf_handle_t *h;
100 scf_property_t *prop = NULL;
101 scf_value_t *val = NULL;
102 uint64_t uint64;
152 scf_handle_t *h;
153 scf_property_t *prop = NULL;
154 scf_value_t *val = NULL;
155 uint64_t uint64;
103 int ret;
104
156
105 h = scf_handle_create(SCF_VERSION);
106 if (h == NULL)
157 if ((h = scf_handle_create(SCF_VERSION)) == NULL)
107 return;
108
158 return;
159
109 ret = scf_handle_bind(h);
110 if (ret) {
111 scf_handle_destroy(h);
112 return;
113 }
114
115 prop = scf_property_create(h);
116 val = scf_value_create(h);
117
118 if (!(prop && val))
160 if ((scf_handle_bind(h) != 0) ||
161 ((prop = scf_property_create(h)) == NULL) ||
162 ((val = scf_value_create(h)) == NULL))
119 goto out;
120
163 goto out;
164
121 ret = scf_handle_decode_fmri(h, FMRI_STARTD_CONTRACT,
122 NULL, NULL, NULL, NULL, prop, SCF_DECODE_FMRI_EXACT);
123 if (ret)
165 if (scf_handle_decode_fmri(h, FMRI_STARTD_CONTRACT,
166 NULL, NULL, NULL, NULL, prop, SCF_DECODE_FMRI_EXACT) != 0)
124 goto out;
125
167 goto out;
168
126 ret = scf_property_is_type(prop, SCF_TYPE_COUNT);
127 if (ret)
169 if (scf_property_is_type(prop, SCF_TYPE_COUNT) != 0 ||
170 scf_property_get_value(prop, val) != 0 ||
171 scf_value_get_count(val, &uint64) != 0)
128 goto out;
129
172 goto out;
173
130 ret = scf_property_get_value(prop, val);
131 if (ret)
132 goto out;
174 startdct = (ctid_t)uint64;
175 (void) sigsend(P_CTID, startdct, SIGSTOP);
133
176
134 ret = scf_value_get_count(val, &uint64);
135 if (ret)
136 goto out;
137
138 ctid = (ctid_t)uint64;
139 startdct = ctid;
140 (void) sigsend(P_CTID, ctid, SIGSTOP);
141
142out:
177out:
143 if (prop)
144 scf_property_destroy(prop);
145 if (val)
146 scf_value_destroy(val);
147
148 (void) scf_handle_unbind(h);
178 scf_property_destroy(prop);
179 scf_value_destroy(val);
149 scf_handle_destroy(h);
150}
151
152static void
153continue_startd()
154{
155 if (startdct != -1)
156 (void) sigsend(P_CTID, startdct, SIGCONT);

--- 36 unchanged lines hidden (view full) ---

193 scf_value_t *val = NULL;
194 scf_iter_t *siter = NULL;
195 scf_iter_t *iiter = NULL;
196 char *fmri;
197 ssize_t length;
198
199 uint64_t uint64;
200 ssize_t bytes;
180 scf_handle_destroy(h);
181}
182
183static void
184continue_startd()
185{
186 if (startdct != -1)
187 (void) sigsend(P_CTID, startdct, SIGCONT);

--- 36 unchanged lines hidden (view full) ---

224 scf_value_t *val = NULL;
225 scf_iter_t *siter = NULL;
226 scf_iter_t *iiter = NULL;
227 char *fmri;
228 ssize_t length;
229
230 uint64_t uint64;
231 ssize_t bytes;
201 int ret;
202
203 length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
204 if (length <= 0)
205 return;
206
207 length++;
208 fmri = alloca(length * sizeof (char));
209
232
233 length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
234 if (length <= 0)
235 return;
236
237 length++;
238 fmri = alloca(length * sizeof (char));
239
210 h = scf_handle_create(SCF_VERSION);
211 if (!h)
240 if ((h = scf_handle_create(SCF_VERSION)) == NULL)
212 return;
213
241 return;
242
214 ret = scf_handle_bind(h);
215 if (ret) {
243 if (scf_handle_bind(h) != 0) {
216 scf_handle_destroy(h);
217 return;
218 }
219
244 scf_handle_destroy(h);
245 return;
246 }
247
220 sc = scf_scope_create(h);
221 svc = scf_service_create(h);
222 inst = scf_instance_create(h);
223 snap = scf_snapshot_create(h);
224 pg = scf_pg_create(h);
225 prop = scf_property_create(h);
226 val = scf_value_create(h);
227 siter = scf_iter_create(h);
228 iiter = scf_iter_create(h);
229
230 if (!(sc && svc && inst && snap &&
231 pg && prop && val && siter && iiter))
248 if ((sc = scf_scope_create(h)) == NULL ||
249 (svc = scf_service_create(h)) == NULL ||
250 (inst = scf_instance_create(h)) == NULL ||
251 (snap = scf_snapshot_create(h)) == NULL ||
252 (pg = scf_pg_create(h)) == NULL ||
253 (prop = scf_property_create(h)) == NULL ||
254 (val = scf_value_create(h)) == NULL ||
255 (siter = scf_iter_create(h)) == NULL ||
256 (iiter = scf_iter_create(h)) == NULL)
232 goto out;
233
257 goto out;
258
234 ret = scf_handle_get_scope(h, SCF_SCOPE_LOCAL, sc);
235 if (ret)
259 if (scf_handle_get_scope(h, SCF_SCOPE_LOCAL, sc) != 0)
236 goto out;
237
260 goto out;
261
238 ret = scf_iter_scope_services(siter, sc);
239 if (ret)
262 if (scf_iter_scope_services(siter, sc) != 0)
240 goto out;
241
242 while (scf_iter_next_service(siter, svc) == 1) {
243
263 goto out;
264
265 while (scf_iter_next_service(siter, svc) == 1) {
266
244 ret = scf_iter_service_instances(iiter, svc);
245 if (ret)
267 if (scf_iter_service_instances(iiter, svc) != 0)
246 continue;
247
248 while (scf_iter_next_instance(iiter, inst) == 1) {
249
268 continue;
269
270 while (scf_iter_next_instance(iiter, inst) == 1) {
271
250 ret = scf_instance_get_snapshot(inst, "running", snap);
251 if (ret)
252 isnap = NULL;
253 else
254 isnap = snap;
272 if ((scf_instance_get_snapshot(inst, "running",
273 snap)) != 0)
274 isnap = NULL;
275 else
276 isnap = snap;
255
277
256 ret = scf_instance_get_pg_composed(inst, isnap,
257 SCF_PG_GENERAL, pg);
258 if (ret)
278 if (scf_instance_get_pg_composed(inst, isnap,
279 SCF_PG_GENERAL, pg) != 0)
259 continue;
260
280 continue;
281
261 ret = scf_pg_get_property(pg, "restarter", prop);
262 if (ret)
282 if (scf_pg_get_property(pg, SCF_PROPERTY_RESTARTER,
283 prop) != 0 ||
284 scf_property_get_value(prop, val) != 0)
263 continue;
264
285 continue;
286
265 ret = scf_property_is_type(prop, SCF_TYPE_ASTRING);
266 if (ret)
267 continue;
268
269 ret = scf_property_get_value(prop, val);
270 if (ret)
271 continue;
272
273 bytes = scf_value_get_astring(val, fmri, length);
274 if (bytes <= 0 || bytes >= length)
275 continue;
276
277 if (strlcat(fmri, FMRI_CONTRACT_PROP, length) >=
278 length)
279 continue;
280
287 bytes = scf_value_get_astring(val, fmri, length);
288 if (bytes <= 0 || bytes >= length)
289 continue;
290
291 if (strlcat(fmri, FMRI_CONTRACT_PROP, length) >=
292 length)
293 continue;
294
281 ret = scf_handle_decode_fmri(h, fmri, NULL, NULL,
282 NULL, NULL, prop, SCF_DECODE_FMRI_EXACT);
283 if (ret)
295 if (scf_handle_decode_fmri(h, fmri, NULL, NULL,
296 NULL, NULL, prop, SCF_DECODE_FMRI_EXACT) != 0)
284 continue;
285
297 continue;
298
286 ret = scf_property_is_type(prop, SCF_TYPE_COUNT);
287 if (ret)
299 if (scf_property_is_type(prop, SCF_TYPE_COUNT) != 0 ||
300 scf_property_get_value(prop, val) != 0 ||
301 scf_value_get_count(val, &uint64) != 0)
288 continue;
289
302 continue;
303
290 ret = scf_property_get_value(prop, val);
291 if (ret)
292 continue;
293
294 ret = scf_value_get_count(val, &uint64);
295 if (ret)
296 continue;
297
298 ctid = (ctid_t)uint64;
299 if (save_ctid(ctid) == 0) {
300 (void) sigsend(P_CTID, ctid, SIGSTOP);
301 }
302 }
303 }
304out:
304 ctid = (ctid_t)uint64;
305 if (save_ctid(ctid) == 0) {
306 (void) sigsend(P_CTID, ctid, SIGSTOP);
307 }
308 }
309 }
310out:
305 if (sc)
306 scf_scope_destroy(sc);
307 if (svc)
308 scf_service_destroy(svc);
309 if (inst)
310 scf_instance_destroy(inst);
311 if (snap)
312 scf_snapshot_destroy(snap);
313 if (pg)
314 scf_pg_destroy(pg);
315 if (prop)
316 scf_property_destroy(prop);
317 if (val)
318 scf_value_destroy(val);
319 if (siter)
320 scf_iter_destroy(siter);
321 if (iiter)
322 scf_iter_destroy(iiter);
311 scf_scope_destroy(sc);
312 scf_service_destroy(svc);
313 scf_instance_destroy(inst);
314 scf_snapshot_destroy(snap);
315 scf_pg_destroy(pg);
316 scf_property_destroy(prop);
317 scf_value_destroy(val);
318 scf_iter_destroy(siter);
319 scf_iter_destroy(iiter);
323
324 (void) scf_handle_unbind(h);
325 scf_handle_destroy(h);
326}
327
328static void
329continue_delegates()
330{

--- 38 unchanged lines hidden (view full) ---

369
370/*
371 * Halt every zone on the system. We are committed to doing a shutdown
372 * even if something goes wrong here. If something goes wrong, we just
373 * continue with the shutdown. Return non-zero if we need to wait for zones to
374 * halt later on.
375 */
376static int
320
321 (void) scf_handle_unbind(h);
322 scf_handle_destroy(h);
323}
324
325static void
326continue_delegates()
327{

--- 38 unchanged lines hidden (view full) ---

366
367/*
368 * Halt every zone on the system. We are committed to doing a shutdown
369 * even if something goes wrong here. If something goes wrong, we just
370 * continue with the shutdown. Return non-zero if we need to wait for zones to
371 * halt later on.
372 */
373static int
377halt_zones(const char *name)
374halt_zones()
378{
379 pid_t pid;
380 zoneid_t *zones;
375{
376 pid_t pid;
377 zoneid_t *zones;
381 size_t nz, old_nz;
378 size_t nz = 0, old_nz;
382 int i;
383 char zname[ZONENAME_MAX];
384
385 /*
386 * Get a list of zones. If the number of zones changes in between the
387 * two zone_list calls, try again.
388 */
389
390 for (;;) {
391 (void) zone_list(NULL, &nz);
392 if (nz == 1)
393 return (0);
394 old_nz = nz;
395 zones = calloc(sizeof (zoneid_t), nz);
396 if (zones == NULL) {
397 (void) fprintf(stderr,
398 gettext("%s: Could not halt zones"
379 int i;
380 char zname[ZONENAME_MAX];
381
382 /*
383 * Get a list of zones. If the number of zones changes in between the
384 * two zone_list calls, try again.
385 */
386
387 for (;;) {
388 (void) zone_list(NULL, &nz);
389 if (nz == 1)
390 return (0);
391 old_nz = nz;
392 zones = calloc(sizeof (zoneid_t), nz);
393 if (zones == NULL) {
394 (void) fprintf(stderr,
395 gettext("%s: Could not halt zones"
399 " (out of memory).\n"), name);
396 " (out of memory).\n"), cmdname);
400 return (0);
401 }
402
403 (void) zone_list(zones, &nz);
404 if (old_nz == nz)
405 break;
406 free(zones);
407 }
408
409 if (nz == 2) {
397 return (0);
398 }
399
400 (void) zone_list(zones, &nz);
401 if (old_nz == nz)
402 break;
403 free(zones);
404 }
405
406 if (nz == 2) {
410 (void) fprintf(stderr,
411 gettext("%s: Halting 1 zone.\n"),
412 name);
407 (void) fprintf(stderr, gettext("%s: Halting 1 zone.\n"),
408 cmdname);
413 } else {
409 } else {
414 (void) fprintf(stderr,
415 gettext("%s: Halting %i zones.\n"),
416 name, nz - 1);
410 (void) fprintf(stderr, gettext("%s: Halting %i zones.\n"),
411 cmdname, nz - 1);
417 }
418
419 for (i = 0; i < nz; i++) {
420 if (zones[i] == GLOBAL_ZONEID)
421 continue;
422 if (getzonenamebyid(zones[i], zname, sizeof (zname)) < 0) {
423 /*
424 * getzonenamebyid should only fail if we raced with
425 * another process trying to shut down the zone.
426 * We assume this happened and ignore the error.
427 */
428 if (errno != EINVAL) {
429 (void) fprintf(stderr,
430 gettext("%s: Unexpected error while "
431 "looking up zone %ul: %s.\n"),
412 }
413
414 for (i = 0; i < nz; i++) {
415 if (zones[i] == GLOBAL_ZONEID)
416 continue;
417 if (getzonenamebyid(zones[i], zname, sizeof (zname)) < 0) {
418 /*
419 * getzonenamebyid should only fail if we raced with
420 * another process trying to shut down the zone.
421 * We assume this happened and ignore the error.
422 */
423 if (errno != EINVAL) {
424 (void) fprintf(stderr,
425 gettext("%s: Unexpected error while "
426 "looking up zone %ul: %s.\n"),
432 name, zones[i], strerror(errno));
427 cmdname, zones[i], strerror(errno));
433 }
434
435 continue;
436 }
437 pid = fork();
438 if (pid < 0) {
439 (void) fprintf(stderr,
440 gettext("%s: Zone \"%s\" could not be"
441 " halted (could not fork(): %s).\n"),
428 }
429
430 continue;
431 }
432 pid = fork();
433 if (pid < 0) {
434 (void) fprintf(stderr,
435 gettext("%s: Zone \"%s\" could not be"
436 " halted (could not fork(): %s).\n"),
442 name, zname, strerror(errno));
437 cmdname, zname, strerror(errno));
443 continue;
444 }
445 if (pid == 0) {
446 (void) execl(ZONEADM_PROG, ZONEADM_PROG,
447 "-z", zname, "halt", NULL);
448 (void) fprintf(stderr,
449 gettext("%s: Zone \"%s\" could not be halted"
450 " (cannot exec(" ZONEADM_PROG "): %s).\n"),
438 continue;
439 }
440 if (pid == 0) {
441 (void) execl(ZONEADM_PROG, ZONEADM_PROG,
442 "-z", zname, "halt", NULL);
443 (void) fprintf(stderr,
444 gettext("%s: Zone \"%s\" could not be halted"
445 " (cannot exec(" ZONEADM_PROG "): %s).\n"),
451 name, zname, strerror(errno));
446 cmdname, zname, strerror(errno));
452 exit(0);
453 }
454 }
455
456 return (1);
457}
458
459/*
460 * This function tries to wait for all non-global zones to go away.
461 * It will timeout if no progress is made for 5 seconds, or a total of
462 * 30 seconds elapses.
463 */
464
465static void
447 exit(0);
448 }
449 }
450
451 return (1);
452}
453
454/*
455 * This function tries to wait for all non-global zones to go away.
456 * It will timeout if no progress is made for 5 seconds, or a total of
457 * 30 seconds elapses.
458 */
459
460static void
466check_zones_haltedness(const char *name)
461check_zones_haltedness()
467{
468 int t = 0, t_prog = 0;
469 size_t nz = 0, last_nz;
470
471 do {
472 last_nz = nz;
473 (void) zone_list(NULL, &nz);
474 if (nz == 1)

--- 7 unchanged lines hidden (view full) ---

482 t++;
483 t_prog++;
484
485 if (t == 10) {
486 if (nz == 2) {
487 (void) fprintf(stderr,
488 gettext("%s: Still waiting for 1 zone to "
489 "halt. Will wait up to 20 seconds.\n"),
462{
463 int t = 0, t_prog = 0;
464 size_t nz = 0, last_nz;
465
466 do {
467 last_nz = nz;
468 (void) zone_list(NULL, &nz);
469 if (nz == 1)

--- 7 unchanged lines hidden (view full) ---

477 t++;
478 t_prog++;
479
480 if (t == 10) {
481 if (nz == 2) {
482 (void) fprintf(stderr,
483 gettext("%s: Still waiting for 1 zone to "
484 "halt. Will wait up to 20 seconds.\n"),
490 name);
485 cmdname);
491 } else {
492 (void) fprintf(stderr,
493 gettext("%s: Still waiting for %i zones "
494 "to halt. Will wait up to 20 seconds.\n"),
486 } else {
487 (void) fprintf(stderr,
488 gettext("%s: Still waiting for %i zones "
489 "to halt. Will wait up to 20 seconds.\n"),
495 name, nz - 1);
490 cmdname, nz - 1);
496 }
497 }
498
499 } while ((t < 30) && (t_prog < 5));
500}
501
502int
503main(int argc, char *argv[])
504{
491 }
492 }
493
494 } while ((t < 30) && (t_prog < 5));
495}
496
497int
498main(int argc, char *argv[])
499{
505 char *cmdname = basename(argv[0]);
506 char *ttyn = ttyname(STDERR_FILENO);
507
508 int qflag = 0, needlog = 1, nosync = 0;
509 uintptr_t mdep = NULL;
510 int cmd, fcn, c, aval, r;
511 const char *usage;
512 zoneid_t zoneid = getzoneid();
500 char *ttyn = ttyname(STDERR_FILENO);
501
502 int qflag = 0, needlog = 1, nosync = 0;
503 uintptr_t mdep = NULL;
504 int cmd, fcn, c, aval, r;
505 const char *usage;
506 zoneid_t zoneid = getzoneid();
513 pid_t init_pid = 1;
514 int need_check_zones;
507 int need_check_zones = 0;
515
508
516 char bootargs_buf[257]; /* uadmin()'s buffer is 257 bytes. */
509 char bootargs_buf[BOOTARGS_MAX];
517
518 const char * const resetting = "/etc/svc/volatile/resetting";
519
510
511 const char * const resetting = "/etc/svc/volatile/resetting";
512
520
521 (void) setlocale(LC_ALL, "");
522 (void) textdomain(TEXT_DOMAIN);
523
513 (void) setlocale(LC_ALL, "");
514 (void) textdomain(TEXT_DOMAIN);
515
516 cmdname = basename(argv[0]);
517
524 if (strcmp(cmdname, "halt") == 0) {
525 (void) audit_halt_setup(argc, argv);
526 usage = gettext("usage: %s [ -dlnqy ]\n");
527 cmd = A_SHUTDOWN;
528 fcn = AD_HALT;
529 } else if (strcmp(cmdname, "poweroff") == 0) {
530 (void) audit_halt_setup(argc, argv);
531 usage = gettext("usage: %s [ -dlnqy ]\n");

--- 113 unchanged lines hidden (view full) ---

645 (void) fprintf(stderr,
646 gettext("%s: can't turn off auditd\n"), cmdname);
647 if (needlog)
648 (void) sleep(5); /* Give syslogd time to record this */
649 }
650
651 (void) signal(SIGHUP, SIG_IGN); /* for remote connections */
652
518 if (strcmp(cmdname, "halt") == 0) {
519 (void) audit_halt_setup(argc, argv);
520 usage = gettext("usage: %s [ -dlnqy ]\n");
521 cmd = A_SHUTDOWN;
522 fcn = AD_HALT;
523 } else if (strcmp(cmdname, "poweroff") == 0) {
524 (void) audit_halt_setup(argc, argv);
525 usage = gettext("usage: %s [ -dlnqy ]\n");

--- 113 unchanged lines hidden (view full) ---

639 (void) fprintf(stderr,
640 gettext("%s: can't turn off auditd\n"), cmdname);
641 if (needlog)
642 (void) sleep(5); /* Give syslogd time to record this */
643 }
644
645 (void) signal(SIGHUP, SIG_IGN); /* for remote connections */
646
653 if (zone_getattr(getzoneid(), ZONE_ATTR_INITPID, &init_pid,
654 sizeof (init_pid)) != sizeof (init_pid)) {
655 assert(errno == ESRCH);
656 init_pid = -1;
657 }
658
659 /*
660 * We start to fork a bunch of zoneadms to halt any active zones.
661 * This will proceed with halt in parallel until we call
662 * check_zone_haltedness later on.
663 */
664 if (zoneid == GLOBAL_ZONEID && cmd != A_DUMP) {
647 /*
648 * We start to fork a bunch of zoneadms to halt any active zones.
649 * This will proceed with halt in parallel until we call
650 * check_zone_haltedness later on.
651 */
652 if (zoneid == GLOBAL_ZONEID && cmd != A_DUMP) {
665 need_check_zones = halt_zones(cmdname);
653 need_check_zones = halt_zones();
666 }
667
668
669 /* sync boot archive in the global zone */
654 }
655
656
657 /* sync boot archive in the global zone */
670 if (getzoneid() == GLOBAL_ZONEID && !nosync) {
658 if (zoneid == GLOBAL_ZONEID && !nosync) {
671 (void) system("/sbin/bootadm -a update_all");
672 }
673
674 /*
675 * If we're not forcing a crash dump, mark the system as quiescing for
676 * smf(5)'s benefit, and idle the init process.
677 */
678 if (cmd != A_DUMP) {
659 (void) system("/sbin/bootadm -a update_all");
660 }
661
662 /*
663 * If we're not forcing a crash dump, mark the system as quiescing for
664 * smf(5)'s benefit, and idle the init process.
665 */
666 if (cmd != A_DUMP) {
679 if (init_pid != -1 && kill(init_pid, SIGTSTP) == -1) {
667 if (direct_init(PCDSTOP) == -1) {
680 /*
681 * TRANSLATION_NOTE
682 * Don't translate the word "init"
683 */
684 (void) fprintf(stderr,
685 gettext("%s: can't idle init\n"), cmdname);
668 /*
669 * TRANSLATION_NOTE
670 * Don't translate the word "init"
671 */
672 (void) fprintf(stderr,
673 gettext("%s: can't idle init\n"), cmdname);
686
687 goto fail;
688 }
689
690 if (creat(resetting, 0755) == -1)
691 (void) fprintf(stderr,
692 gettext("%s: could not create %s.\n"),
693 cmdname, resetting);
694
695 /*
696 * Stop all restarters so they do not try to restart services
697 * that are terminated.
698 */
699 stop_restarters();
700
701 /*
702 * Wait a little while for zones to shutdown.
703 */
704 if (need_check_zones) {
674 goto fail;
675 }
676
677 if (creat(resetting, 0755) == -1)
678 (void) fprintf(stderr,
679 gettext("%s: could not create %s.\n"),
680 cmdname, resetting);
681
682 /*
683 * Stop all restarters so they do not try to restart services
684 * that are terminated.
685 */
686 stop_restarters();
687
688 /*
689 * Wait a little while for zones to shutdown.
690 */
691 if (need_check_zones) {
705 check_zones_haltedness(cmdname);
692 check_zones_haltedness();
706
707 (void) fprintf(stderr,
708 gettext("%s: Completing system halt.\n"),
709 cmdname);
710 }
711 }
712
713 /*

--- 28 unchanged lines hidden (view full) ---

742
743 (void) updwtmpx(WTMPX_FILE, &wtmpx);
744 sync();
745 }
746
747 if (cmd == A_DUMP && nosync != 0)
748 (void) uadmin(A_DUMP, AD_NOSYNC, NULL);
749
693
694 (void) fprintf(stderr,
695 gettext("%s: Completing system halt.\n"),
696 cmdname);
697 }
698 }
699
700 /*

--- 28 unchanged lines hidden (view full) ---

729
730 (void) updwtmpx(WTMPX_FILE, &wtmpx);
731 sync();
732 }
733
734 if (cmd == A_DUMP && nosync != 0)
735 (void) uadmin(A_DUMP, AD_NOSYNC, NULL);
736
750 (void) uadmin(cmd, fcn, mdep);
751 perror(cmdname);
752 do
737 if (uadmin(cmd, fcn, mdep) == -1)
738 (void) fprintf(stderr, "%s: uadmin failed: %s\n",
739 cmdname, strerror(errno));
740 else
741 (void) fprintf(stderr, "%s: uadmin unexpectedly returned 0\n",
742 cmdname);
743
744 do {
753 r = remove(resetting);
745 r = remove(resetting);
754 while (r != 0 && errno == EINTR);
746 } while (r != 0 && errno == EINTR);
747
755 if (r != 0 && errno != ENOENT)
756 (void) fprintf(stderr, gettext("%s: could not remove %s.\n"),
757 cmdname, resetting);
758
748 if (r != 0 && errno != ENOENT)
749 (void) fprintf(stderr, gettext("%s: could not remove %s.\n"),
750 cmdname, resetting);
751
752 if (direct_init(PCRUN) == -1) {
753 /*
754 * TRANSLATION_NOTE
755 * Don't translate the word "init"
756 */
757 (void) fprintf(stderr,
758 gettext("%s: can't resume init\n"), cmdname);
759 }
760
759 continue_restarters();
760
761 continue_restarters();
762
761 if (init_pid != -1)
763 if (get_initpid() != -1)
762 /* tell init to restate current level */
764 /* tell init to restate current level */
763 (void) kill(init_pid, SIGHUP);
765 (void) kill(get_initpid(), SIGHUP);
764
765fail:
766 if (fcn == AD_BOOT)
767 (void) audit_reboot_fail();
768 else
769 (void) audit_halt_fail();
770
771 return (1);
772}
766
767fail:
768 if (fcn == AD_BOOT)
769 (void) audit_reboot_fail();
770 else
771 (void) audit_halt_fail();
772
773 return (1);
774}