xref: /titanic_53/usr/src/cmd/halt/halt.c (revision 26f665e8f24bd83c7bbb0c9281930ce0525d3a3b)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
327c478bd9Sstevel@tonic-gate  * The Regents of the University of California
337c478bd9Sstevel@tonic-gate  * All Rights Reserved
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
367c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
377c478bd9Sstevel@tonic-gate  * contributors.
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /*
437c478bd9Sstevel@tonic-gate  * Common code for halt(1M), poweroff(1M), and reboot(1M).  We use
447c478bd9Sstevel@tonic-gate  * argv[0] to determine which behavior to exhibit.
457c478bd9Sstevel@tonic-gate  */
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #include <sys/stat.h>
487c478bd9Sstevel@tonic-gate #include <sys/types.h>
497c478bd9Sstevel@tonic-gate #include <sys/uadmin.h>
507c478bd9Sstevel@tonic-gate #include <alloca.h>
517c478bd9Sstevel@tonic-gate #include <assert.h>
527c478bd9Sstevel@tonic-gate #include <errno.h>
537c478bd9Sstevel@tonic-gate #include <fcntl.h>
547c478bd9Sstevel@tonic-gate #include <libgen.h>
557c478bd9Sstevel@tonic-gate #include <libscf.h>
567c478bd9Sstevel@tonic-gate #include <locale.h>
577c478bd9Sstevel@tonic-gate #include <libintl.h>
587c478bd9Sstevel@tonic-gate #include <syslog.h>
597c478bd9Sstevel@tonic-gate #include <signal.h>
607c478bd9Sstevel@tonic-gate #include <strings.h>
617c478bd9Sstevel@tonic-gate #include <unistd.h>
627c478bd9Sstevel@tonic-gate #include <stdlib.h>
637c478bd9Sstevel@tonic-gate #include <stdio.h>
647c478bd9Sstevel@tonic-gate #include <strings.h>
657c478bd9Sstevel@tonic-gate #include <time.h>
667c478bd9Sstevel@tonic-gate #include <utmpx.h>
677c478bd9Sstevel@tonic-gate #include <pwd.h>
687c478bd9Sstevel@tonic-gate #include <zone.h>
697c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
707c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
717c478bd9Sstevel@tonic-gate #endif
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate extern int audit_halt_setup(int, char **);
747c478bd9Sstevel@tonic-gate extern int audit_halt_success(void);
757c478bd9Sstevel@tonic-gate extern int audit_halt_fail(void);
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate extern int audit_reboot_setup(void);
787c478bd9Sstevel@tonic-gate extern int audit_reboot_success(void);
797c478bd9Sstevel@tonic-gate extern int audit_reboot_fail(void);
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate typedef struct ctidlist_struct {
827c478bd9Sstevel@tonic-gate 	ctid_t ctid;
837c478bd9Sstevel@tonic-gate 	struct ctidlist_struct *next;
847c478bd9Sstevel@tonic-gate } ctidlist_t;
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate static ctidlist_t *ctidlist = NULL;
877c478bd9Sstevel@tonic-gate static ctid_t startdct = -1;
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate #define	FMRI_STARTD_CONTRACT \
907c478bd9Sstevel@tonic-gate 	"svc:/system/svc/restarter:default/:properties/restarter/contract"
917c478bd9Sstevel@tonic-gate 
92*26f665e8Sdstaff #define	ZONEADM_PROG "/usr/sbin/zoneadm"
93*26f665e8Sdstaff 
947c478bd9Sstevel@tonic-gate static void
957c478bd9Sstevel@tonic-gate stop_startd()
967c478bd9Sstevel@tonic-gate {
977c478bd9Sstevel@tonic-gate 	ctid_t ctid;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	scf_handle_t *h;
1007c478bd9Sstevel@tonic-gate 	scf_property_t *prop = NULL;
1017c478bd9Sstevel@tonic-gate 	scf_value_t *val = NULL;
1027c478bd9Sstevel@tonic-gate 	uint64_t uint64;
1037c478bd9Sstevel@tonic-gate 	int ret;
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	h = scf_handle_create(SCF_VERSION);
1067c478bd9Sstevel@tonic-gate 	if (h == NULL)
1077c478bd9Sstevel@tonic-gate 		return;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	ret = scf_handle_bind(h);
1107c478bd9Sstevel@tonic-gate 	if (ret) {
1117c478bd9Sstevel@tonic-gate 		scf_handle_destroy(h);
1127c478bd9Sstevel@tonic-gate 		return;
1137c478bd9Sstevel@tonic-gate 	}
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	prop = scf_property_create(h);
1167c478bd9Sstevel@tonic-gate 	val = scf_value_create(h);
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	if (!(prop && val))
1197c478bd9Sstevel@tonic-gate 		goto out;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	ret = scf_handle_decode_fmri(h, FMRI_STARTD_CONTRACT,
1227c478bd9Sstevel@tonic-gate 	    NULL, NULL, NULL, NULL, prop, SCF_DECODE_FMRI_EXACT);
1237c478bd9Sstevel@tonic-gate 	if (ret)
1247c478bd9Sstevel@tonic-gate 		goto out;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	ret = scf_property_is_type(prop, SCF_TYPE_COUNT);
1277c478bd9Sstevel@tonic-gate 	if (ret)
1287c478bd9Sstevel@tonic-gate 		goto out;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	ret = scf_property_get_value(prop, val);
1317c478bd9Sstevel@tonic-gate 	if (ret)
1327c478bd9Sstevel@tonic-gate 		goto out;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	ret = scf_value_get_count(val, &uint64);
1357c478bd9Sstevel@tonic-gate 	if (ret)
1367c478bd9Sstevel@tonic-gate 		goto out;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	ctid = (ctid_t)uint64;
1397c478bd9Sstevel@tonic-gate 	startdct = ctid;
1407c478bd9Sstevel@tonic-gate 	(void) sigsend(P_CTID, ctid, SIGSTOP);
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate out:
1437c478bd9Sstevel@tonic-gate 	if (prop)
1447c478bd9Sstevel@tonic-gate 		scf_property_destroy(prop);
1457c478bd9Sstevel@tonic-gate 	if (val)
1467c478bd9Sstevel@tonic-gate 		scf_value_destroy(val);
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	(void) scf_handle_unbind(h);
1497c478bd9Sstevel@tonic-gate 	scf_handle_destroy(h);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate static void
1537c478bd9Sstevel@tonic-gate continue_startd()
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	if (startdct != -1)
1567c478bd9Sstevel@tonic-gate 		(void) sigsend(P_CTID, startdct, SIGCONT);
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate #define	FMRI_RESTARTER_PROP "/:properties/general/restarter"
1607c478bd9Sstevel@tonic-gate #define	FMRI_CONTRACT_PROP "/:properties/restarter/contract"
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate static int
1637c478bd9Sstevel@tonic-gate save_ctid(ctid_t ctid)
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate 	ctidlist_t *next;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	for (next = ctidlist; next != NULL; next = next->next)
1687c478bd9Sstevel@tonic-gate 		if (next->ctid == ctid)
1697c478bd9Sstevel@tonic-gate 			return (-1);
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	next = (ctidlist_t *)malloc(sizeof (ctidlist_t));
1727c478bd9Sstevel@tonic-gate 	if (next == NULL)
1737c478bd9Sstevel@tonic-gate 		return (-1);
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	next->ctid = ctid;
1767c478bd9Sstevel@tonic-gate 	next->next = ctidlist;
1777c478bd9Sstevel@tonic-gate 	ctidlist = next;
1787c478bd9Sstevel@tonic-gate 	return (0);
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate static void
1827c478bd9Sstevel@tonic-gate stop_delegates()
1837c478bd9Sstevel@tonic-gate {
1847c478bd9Sstevel@tonic-gate 	ctid_t ctid;
1857c478bd9Sstevel@tonic-gate 	scf_handle_t *h;
1867c478bd9Sstevel@tonic-gate 	scf_scope_t *sc = NULL;
1877c478bd9Sstevel@tonic-gate 	scf_service_t *svc = NULL;
1887c478bd9Sstevel@tonic-gate 	scf_instance_t *inst = NULL;
1897c478bd9Sstevel@tonic-gate 	scf_snapshot_t *snap = NULL;
1907c478bd9Sstevel@tonic-gate 	scf_snapshot_t *isnap = NULL;
1917c478bd9Sstevel@tonic-gate 	scf_propertygroup_t *pg = NULL;
1927c478bd9Sstevel@tonic-gate 	scf_property_t *prop = NULL;
1937c478bd9Sstevel@tonic-gate 	scf_value_t *val = NULL;
1947c478bd9Sstevel@tonic-gate 	scf_iter_t *siter = NULL;
1957c478bd9Sstevel@tonic-gate 	scf_iter_t *iiter = NULL;
1967c478bd9Sstevel@tonic-gate 	char *fmri;
1977c478bd9Sstevel@tonic-gate 	ssize_t length;
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	uint64_t uint64;
2007c478bd9Sstevel@tonic-gate 	ssize_t bytes;
2017c478bd9Sstevel@tonic-gate 	int ret;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
2047c478bd9Sstevel@tonic-gate 	if (length <= 0)
2057c478bd9Sstevel@tonic-gate 		return;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	length++;
2087c478bd9Sstevel@tonic-gate 	fmri = alloca(length * sizeof (char));
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	h = scf_handle_create(SCF_VERSION);
2117c478bd9Sstevel@tonic-gate 	if (!h)
2127c478bd9Sstevel@tonic-gate 		return;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	ret = scf_handle_bind(h);
2157c478bd9Sstevel@tonic-gate 	if (ret) {
2167c478bd9Sstevel@tonic-gate 		scf_handle_destroy(h);
2177c478bd9Sstevel@tonic-gate 		return;
2187c478bd9Sstevel@tonic-gate 	}
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	sc = scf_scope_create(h);
2217c478bd9Sstevel@tonic-gate 	svc = scf_service_create(h);
2227c478bd9Sstevel@tonic-gate 	inst = scf_instance_create(h);
2237c478bd9Sstevel@tonic-gate 	snap = scf_snapshot_create(h);
2247c478bd9Sstevel@tonic-gate 	pg = scf_pg_create(h);
2257c478bd9Sstevel@tonic-gate 	prop = scf_property_create(h);
2267c478bd9Sstevel@tonic-gate 	val = scf_value_create(h);
2277c478bd9Sstevel@tonic-gate 	siter = scf_iter_create(h);
2287c478bd9Sstevel@tonic-gate 	iiter = scf_iter_create(h);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	if (!(sc && svc && inst && snap &&
2317c478bd9Sstevel@tonic-gate 	    pg && prop && val && siter && iiter))
2327c478bd9Sstevel@tonic-gate 		goto out;
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	ret = scf_handle_get_scope(h, SCF_SCOPE_LOCAL, sc);
2357c478bd9Sstevel@tonic-gate 	if (ret)
2367c478bd9Sstevel@tonic-gate 		goto out;
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	ret = scf_iter_scope_services(siter, sc);
2397c478bd9Sstevel@tonic-gate 	if (ret)
2407c478bd9Sstevel@tonic-gate 		goto out;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	while (scf_iter_next_service(siter, svc) == 1) {
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 		ret = scf_iter_service_instances(iiter, svc);
2457c478bd9Sstevel@tonic-gate 		if (ret)
2467c478bd9Sstevel@tonic-gate 			continue;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 		while (scf_iter_next_instance(iiter, inst) == 1) {
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 			ret = scf_instance_get_snapshot(inst, "running", snap);
2517c478bd9Sstevel@tonic-gate 				if (ret)
2527c478bd9Sstevel@tonic-gate 					isnap = NULL;
2537c478bd9Sstevel@tonic-gate 				else
2547c478bd9Sstevel@tonic-gate 					isnap = snap;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 			ret = scf_instance_get_pg_composed(inst, isnap,
2577c478bd9Sstevel@tonic-gate 			    SCF_PG_GENERAL, pg);
2587c478bd9Sstevel@tonic-gate 			if (ret)
2597c478bd9Sstevel@tonic-gate 				continue;
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 			ret = scf_pg_get_property(pg, "restarter", prop);
2627c478bd9Sstevel@tonic-gate 			if (ret)
2637c478bd9Sstevel@tonic-gate 				continue;
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 			ret = scf_property_is_type(prop, SCF_TYPE_ASTRING);
2667c478bd9Sstevel@tonic-gate 			if (ret)
2677c478bd9Sstevel@tonic-gate 				continue;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 			ret = scf_property_get_value(prop, val);
2707c478bd9Sstevel@tonic-gate 			if (ret)
2717c478bd9Sstevel@tonic-gate 				continue;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 			bytes = scf_value_get_astring(val, fmri, length);
2747c478bd9Sstevel@tonic-gate 			if (bytes <= 0 || bytes >= length)
2757c478bd9Sstevel@tonic-gate 				continue;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 			if (strlcat(fmri, FMRI_CONTRACT_PROP, length) >=
2787c478bd9Sstevel@tonic-gate 			    length)
2797c478bd9Sstevel@tonic-gate 				continue;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 			ret = scf_handle_decode_fmri(h, fmri, NULL, NULL,
2827c478bd9Sstevel@tonic-gate 			    NULL, NULL, prop, SCF_DECODE_FMRI_EXACT);
2837c478bd9Sstevel@tonic-gate 			if (ret)
2847c478bd9Sstevel@tonic-gate 				continue;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 			ret = scf_property_is_type(prop, SCF_TYPE_COUNT);
2877c478bd9Sstevel@tonic-gate 			if (ret)
2887c478bd9Sstevel@tonic-gate 				continue;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 			ret = scf_property_get_value(prop, val);
2917c478bd9Sstevel@tonic-gate 			if (ret)
2927c478bd9Sstevel@tonic-gate 				continue;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 			ret = scf_value_get_count(val, &uint64);
2957c478bd9Sstevel@tonic-gate 			if (ret)
2967c478bd9Sstevel@tonic-gate 				continue;
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 			ctid = (ctid_t)uint64;
2997c478bd9Sstevel@tonic-gate 			if (save_ctid(ctid) == 0) {
3007c478bd9Sstevel@tonic-gate 				(void) sigsend(P_CTID, ctid, SIGSTOP);
3017c478bd9Sstevel@tonic-gate 			}
3027c478bd9Sstevel@tonic-gate 		}
3037c478bd9Sstevel@tonic-gate 	}
3047c478bd9Sstevel@tonic-gate out:
3057c478bd9Sstevel@tonic-gate 	if (sc)
3067c478bd9Sstevel@tonic-gate 		scf_scope_destroy(sc);
3077c478bd9Sstevel@tonic-gate 	if (svc)
3087c478bd9Sstevel@tonic-gate 		scf_service_destroy(svc);
3097c478bd9Sstevel@tonic-gate 	if (inst)
3107c478bd9Sstevel@tonic-gate 		scf_instance_destroy(inst);
3117c478bd9Sstevel@tonic-gate 	if (snap)
3127c478bd9Sstevel@tonic-gate 		scf_snapshot_destroy(snap);
3137c478bd9Sstevel@tonic-gate 	if (pg)
3147c478bd9Sstevel@tonic-gate 		scf_pg_destroy(pg);
3157c478bd9Sstevel@tonic-gate 	if (prop)
3167c478bd9Sstevel@tonic-gate 		scf_property_destroy(prop);
3177c478bd9Sstevel@tonic-gate 	if (val)
3187c478bd9Sstevel@tonic-gate 		scf_value_destroy(val);
3197c478bd9Sstevel@tonic-gate 	if (siter)
3207c478bd9Sstevel@tonic-gate 		scf_iter_destroy(siter);
3217c478bd9Sstevel@tonic-gate 	if (iiter)
3227c478bd9Sstevel@tonic-gate 		scf_iter_destroy(iiter);
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	(void) scf_handle_unbind(h);
3257c478bd9Sstevel@tonic-gate 	scf_handle_destroy(h);
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate static void
3297c478bd9Sstevel@tonic-gate continue_delegates()
3307c478bd9Sstevel@tonic-gate {
3317c478bd9Sstevel@tonic-gate 	ctidlist_t *next;
3327c478bd9Sstevel@tonic-gate 	for (next = ctidlist; next != NULL; next = next->next)
3337c478bd9Sstevel@tonic-gate 		(void) sigsend(P_CTID, next->ctid, SIGCONT);
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate static void
3377c478bd9Sstevel@tonic-gate stop_restarters()
3387c478bd9Sstevel@tonic-gate {
3397c478bd9Sstevel@tonic-gate 	stop_startd();
3407c478bd9Sstevel@tonic-gate 	stop_delegates();
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate static void
3447c478bd9Sstevel@tonic-gate continue_restarters()
3457c478bd9Sstevel@tonic-gate {
3467c478bd9Sstevel@tonic-gate 	continue_startd();
3477c478bd9Sstevel@tonic-gate 	continue_delegates();
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate /*
3517c478bd9Sstevel@tonic-gate  * Copy an array of strings into buf, separated by spaces.  Returns 0 on
3527c478bd9Sstevel@tonic-gate  * success.
3537c478bd9Sstevel@tonic-gate  */
3547c478bd9Sstevel@tonic-gate static int
3557c478bd9Sstevel@tonic-gate gather_args(char **args, char *buf, size_t buf_sz)
3567c478bd9Sstevel@tonic-gate {
3577c478bd9Sstevel@tonic-gate 	if (strlcpy(buf, *args, buf_sz) >= buf_sz)
3587c478bd9Sstevel@tonic-gate 		return (-1);
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	for (++args; *args != NULL; ++args) {
3617c478bd9Sstevel@tonic-gate 		if (strlcat(buf, " ", buf_sz) >= buf_sz)
3627c478bd9Sstevel@tonic-gate 			return (-1);
3637c478bd9Sstevel@tonic-gate 		if (strlcat(buf, *args, buf_sz) >= buf_sz)
3647c478bd9Sstevel@tonic-gate 			return (-1);
3657c478bd9Sstevel@tonic-gate 	}
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	return (0);
3687c478bd9Sstevel@tonic-gate }
3697c478bd9Sstevel@tonic-gate 
370*26f665e8Sdstaff /*
371*26f665e8Sdstaff  * Halt every zone on the system.  We are committed to doing a shutdown
372*26f665e8Sdstaff  * even if something goes wrong here. If something goes wrong, we just
373*26f665e8Sdstaff  * continue with the shutdown.  Return non-zero if we need to wait for zones to
374*26f665e8Sdstaff  * halt later on.
375*26f665e8Sdstaff  */
376*26f665e8Sdstaff static int
377*26f665e8Sdstaff halt_zones(const char *name)
378*26f665e8Sdstaff {
379*26f665e8Sdstaff 	pid_t pid;
380*26f665e8Sdstaff 	zoneid_t *zones;
381*26f665e8Sdstaff 	size_t nz, old_nz;
382*26f665e8Sdstaff 	int i;
383*26f665e8Sdstaff 	char zname[ZONENAME_MAX];
384*26f665e8Sdstaff 
385*26f665e8Sdstaff 	/*
386*26f665e8Sdstaff 	 * Get a list of zones. If the number of zones changes in between the
387*26f665e8Sdstaff 	 * two zone_list calls, try again.
388*26f665e8Sdstaff 	 */
389*26f665e8Sdstaff 
390*26f665e8Sdstaff 	for (;;) {
391*26f665e8Sdstaff 		(void) zone_list(NULL, &nz);
392*26f665e8Sdstaff 		if (nz == 1)
393*26f665e8Sdstaff 			return (0);
394*26f665e8Sdstaff 		old_nz = nz;
395*26f665e8Sdstaff 		zones = calloc(sizeof (zoneid_t), nz);
396*26f665e8Sdstaff 		if (zones == NULL) {
397*26f665e8Sdstaff 			(void) fprintf(stderr,
398*26f665e8Sdstaff 			    gettext("%s: Could not halt zones"
399*26f665e8Sdstaff 			    " (out of memory).\n"), name);
400*26f665e8Sdstaff 			return (0);
401*26f665e8Sdstaff 		}
402*26f665e8Sdstaff 
403*26f665e8Sdstaff 		(void) zone_list(zones, &nz);
404*26f665e8Sdstaff 		if (old_nz == nz)
405*26f665e8Sdstaff 			break;
406*26f665e8Sdstaff 		free(zones);
407*26f665e8Sdstaff 	}
408*26f665e8Sdstaff 
409*26f665e8Sdstaff 	if (nz == 2) {
410*26f665e8Sdstaff 		(void) fprintf(stderr,
411*26f665e8Sdstaff 		    gettext("%s: Halting 1 zone.\n"),
412*26f665e8Sdstaff 		    name);
413*26f665e8Sdstaff 	} else {
414*26f665e8Sdstaff 		(void) fprintf(stderr,
415*26f665e8Sdstaff 		    gettext("%s: Halting %i zones.\n"),
416*26f665e8Sdstaff 		    name, nz - 1);
417*26f665e8Sdstaff 	}
418*26f665e8Sdstaff 
419*26f665e8Sdstaff 	for (i = 0; i < nz; i++) {
420*26f665e8Sdstaff 		if (zones[i] == GLOBAL_ZONEID)
421*26f665e8Sdstaff 			continue;
422*26f665e8Sdstaff 		if (getzonenamebyid(zones[i], zname, sizeof (zname)) < 0) {
423*26f665e8Sdstaff 			/*
424*26f665e8Sdstaff 			 * getzonenamebyid should only fail if we raced with
425*26f665e8Sdstaff 			 * another process trying to shut down the zone.
426*26f665e8Sdstaff 			 * We assume this happened and ignore the error.
427*26f665e8Sdstaff 			 */
428*26f665e8Sdstaff 			if (errno != EINVAL) {
429*26f665e8Sdstaff 				(void) fprintf(stderr,
430*26f665e8Sdstaff 				    gettext("%s: Unexpected error while "
431*26f665e8Sdstaff 				    "looking up zone %ul: %s.\n"),
432*26f665e8Sdstaff 				    name, zones[i], strerror(errno));
433*26f665e8Sdstaff 			}
434*26f665e8Sdstaff 
435*26f665e8Sdstaff 			continue;
436*26f665e8Sdstaff 		}
437*26f665e8Sdstaff 		pid = fork();
438*26f665e8Sdstaff 		if (pid < 0) {
439*26f665e8Sdstaff 			(void) fprintf(stderr,
440*26f665e8Sdstaff 			    gettext("%s: Zone \"%s\" could not be"
441*26f665e8Sdstaff 			    " halted (could not fork(): %s).\n"),
442*26f665e8Sdstaff 			    name, zname, strerror(errno));
443*26f665e8Sdstaff 			continue;
444*26f665e8Sdstaff 		}
445*26f665e8Sdstaff 		if (pid == 0) {
446*26f665e8Sdstaff 			(void) execl(ZONEADM_PROG, ZONEADM_PROG,
447*26f665e8Sdstaff 			    "-z", zname, "halt", NULL);
448*26f665e8Sdstaff 			(void) fprintf(stderr,
449*26f665e8Sdstaff 			    gettext("%s: Zone \"%s\" could not be halted"
450*26f665e8Sdstaff 			    " (cannot exec(" ZONEADM_PROG "): %s).\n"),
451*26f665e8Sdstaff 			    name, zname, strerror(errno));
452*26f665e8Sdstaff 			exit(0);
453*26f665e8Sdstaff 		}
454*26f665e8Sdstaff 	}
455*26f665e8Sdstaff 
456*26f665e8Sdstaff 	return (1);
457*26f665e8Sdstaff }
458*26f665e8Sdstaff 
459*26f665e8Sdstaff /*
460*26f665e8Sdstaff  * This function tries to wait for all non-global zones to go away.
461*26f665e8Sdstaff  * It will timeout if no progress is made for 5 seconds, or a total of
462*26f665e8Sdstaff  * 30 seconds elapses.
463*26f665e8Sdstaff  */
464*26f665e8Sdstaff 
465*26f665e8Sdstaff static void
466*26f665e8Sdstaff check_zones_haltedness(const char *name)
467*26f665e8Sdstaff {
468*26f665e8Sdstaff 	int t = 0, t_prog = 0;
469*26f665e8Sdstaff 	size_t nz = 0, last_nz;
470*26f665e8Sdstaff 
471*26f665e8Sdstaff 	do {
472*26f665e8Sdstaff 		last_nz = nz;
473*26f665e8Sdstaff 		(void) zone_list(NULL, &nz);
474*26f665e8Sdstaff 		if (nz == 1)
475*26f665e8Sdstaff 			return;
476*26f665e8Sdstaff 
477*26f665e8Sdstaff 		(void) sleep(1);
478*26f665e8Sdstaff 
479*26f665e8Sdstaff 		if (last_nz > nz)
480*26f665e8Sdstaff 			t_prog = 0;
481*26f665e8Sdstaff 
482*26f665e8Sdstaff 		t++;
483*26f665e8Sdstaff 		t_prog++;
484*26f665e8Sdstaff 
485*26f665e8Sdstaff 		if (t == 10) {
486*26f665e8Sdstaff 			if (nz == 2) {
487*26f665e8Sdstaff 				(void) fprintf(stderr,
488*26f665e8Sdstaff 				    gettext("%s: Still waiting for 1 zone to "
489*26f665e8Sdstaff 				    "halt. Will wait up to 20 seconds.\n"),
490*26f665e8Sdstaff 				    name);
491*26f665e8Sdstaff 			} else {
492*26f665e8Sdstaff 				(void) fprintf(stderr,
493*26f665e8Sdstaff 				    gettext("%s: Still waiting for %i zones "
494*26f665e8Sdstaff 				    "to halt. Will wait up to 20 seconds.\n"),
495*26f665e8Sdstaff 				    name, nz - 1);
496*26f665e8Sdstaff 			}
497*26f665e8Sdstaff 		}
498*26f665e8Sdstaff 
499*26f665e8Sdstaff 	} while ((t < 30) && (t_prog < 5));
500*26f665e8Sdstaff }
501*26f665e8Sdstaff 
5027c478bd9Sstevel@tonic-gate int
5037c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
5047c478bd9Sstevel@tonic-gate {
5057c478bd9Sstevel@tonic-gate 	char *cmdname = basename(argv[0]);
5067c478bd9Sstevel@tonic-gate 	char *ttyn = ttyname(STDERR_FILENO);
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 	int qflag = 0, needlog = 1, nosync = 0;
5097c478bd9Sstevel@tonic-gate 	uintptr_t mdep = NULL;
5107c478bd9Sstevel@tonic-gate 	int cmd, fcn, c, aval, r;
5117c478bd9Sstevel@tonic-gate 	const char *usage;
5127c478bd9Sstevel@tonic-gate 	zoneid_t zoneid = getzoneid();
5137c478bd9Sstevel@tonic-gate 	pid_t init_pid = 1;
514*26f665e8Sdstaff 	int need_check_zones;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	char bootargs_buf[257];		/* uadmin()'s buffer is 257 bytes. */
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	const char * const resetting = "/etc/svc/volatile/resetting";
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
5227c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 	if (strcmp(cmdname, "halt") == 0) {
5257c478bd9Sstevel@tonic-gate 		(void) audit_halt_setup(argc, argv);
5267c478bd9Sstevel@tonic-gate 		usage = gettext("usage: %s [ -dlnqy ]\n");
5277c478bd9Sstevel@tonic-gate 		cmd = A_SHUTDOWN;
5287c478bd9Sstevel@tonic-gate 		fcn = AD_HALT;
5297c478bd9Sstevel@tonic-gate 	} else if (strcmp(cmdname, "poweroff") == 0) {
5307c478bd9Sstevel@tonic-gate 		(void) audit_halt_setup(argc, argv);
5317c478bd9Sstevel@tonic-gate 		usage = gettext("usage: %s [ -dlnqy ]\n");
5327c478bd9Sstevel@tonic-gate 		cmd = A_SHUTDOWN;
5337c478bd9Sstevel@tonic-gate 		fcn = AD_POWEROFF;
5347c478bd9Sstevel@tonic-gate 	} else if (strcmp(cmdname, "reboot") == 0) {
5357c478bd9Sstevel@tonic-gate 		(void) audit_reboot_setup();
5367c478bd9Sstevel@tonic-gate 		usage = gettext("usage: %s [ -dlnq ] [ boot args ]\n");
5377c478bd9Sstevel@tonic-gate 		cmd = A_SHUTDOWN;
5387c478bd9Sstevel@tonic-gate 		fcn = AD_BOOT;
5397c478bd9Sstevel@tonic-gate 	} else {
5407c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
5417c478bd9Sstevel@tonic-gate 		    gettext("%s: not installed properly\n"), cmdname);
5427c478bd9Sstevel@tonic-gate 		return (1);
5437c478bd9Sstevel@tonic-gate 	}
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "dlnqy")) != EOF) {
5467c478bd9Sstevel@tonic-gate 		switch (c) {
5477c478bd9Sstevel@tonic-gate 		case 'd':
5487c478bd9Sstevel@tonic-gate 			if (zoneid == GLOBAL_ZONEID)
5497c478bd9Sstevel@tonic-gate 				cmd = A_DUMP;
5507c478bd9Sstevel@tonic-gate 			else {
5517c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
5527c478bd9Sstevel@tonic-gate 				    gettext("%s: -d only valid from global"
5537c478bd9Sstevel@tonic-gate 				    " zone\n"), cmdname);
5547c478bd9Sstevel@tonic-gate 				return (1);
5557c478bd9Sstevel@tonic-gate 			}
5567c478bd9Sstevel@tonic-gate 			break;
5577c478bd9Sstevel@tonic-gate 		case 'l':
5587c478bd9Sstevel@tonic-gate 			needlog = 0;
5597c478bd9Sstevel@tonic-gate 			break;
5607c478bd9Sstevel@tonic-gate 		case 'n':
5617c478bd9Sstevel@tonic-gate 			nosync = 1;
5627c478bd9Sstevel@tonic-gate 			break;
5637c478bd9Sstevel@tonic-gate 		case 'q':
5647c478bd9Sstevel@tonic-gate 			qflag = 1;
5657c478bd9Sstevel@tonic-gate 			break;
5667c478bd9Sstevel@tonic-gate 		case 'y':
5677c478bd9Sstevel@tonic-gate 			ttyn = NULL;
5687c478bd9Sstevel@tonic-gate 			break;
5697c478bd9Sstevel@tonic-gate 		default:
5707c478bd9Sstevel@tonic-gate 			/*
5717c478bd9Sstevel@tonic-gate 			 * TRANSLATION_NOTE
5727c478bd9Sstevel@tonic-gate 			 * Don't translate the words "halt" or "reboot"
5737c478bd9Sstevel@tonic-gate 			 */
5747c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, usage, cmdname);
5757c478bd9Sstevel@tonic-gate 			return (1);
5767c478bd9Sstevel@tonic-gate 		}
5777c478bd9Sstevel@tonic-gate 	}
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	argc -= optind;
5807c478bd9Sstevel@tonic-gate 	argv += optind;
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	if (argc != 0) {
5837c478bd9Sstevel@tonic-gate 		if (fcn != AD_BOOT) {
5847c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, usage, cmdname);
5857c478bd9Sstevel@tonic-gate 			return (1);
5867c478bd9Sstevel@tonic-gate 		}
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 		/* Gather the arguments into bootargs_buf. */
5897c478bd9Sstevel@tonic-gate 		if (gather_args(argv, bootargs_buf, sizeof (bootargs_buf)) !=
5907c478bd9Sstevel@tonic-gate 		    0) {
5917c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
5927c478bd9Sstevel@tonic-gate 			    gettext("%s: Boot arguments too long.\n"), cmdname);
5937c478bd9Sstevel@tonic-gate 			return (1);
5947c478bd9Sstevel@tonic-gate 		}
5957c478bd9Sstevel@tonic-gate 		mdep = (uintptr_t)bootargs_buf;
5967c478bd9Sstevel@tonic-gate 	}
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	if (geteuid() != 0) {
5997c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
6007c478bd9Sstevel@tonic-gate 		    gettext("%s: permission denied\n"), cmdname);
6017c478bd9Sstevel@tonic-gate 		goto fail;
6027c478bd9Sstevel@tonic-gate 	}
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	if (fcn != AD_BOOT && ttyn != NULL &&
6057c478bd9Sstevel@tonic-gate 	    strncmp(ttyn, "/dev/term/", strlen("/dev/term/")) == 0) {
6067c478bd9Sstevel@tonic-gate 		/*
6077c478bd9Sstevel@tonic-gate 		 * TRANSLATION_NOTE
6087c478bd9Sstevel@tonic-gate 		 * Don't translate ``halt -y''
6097c478bd9Sstevel@tonic-gate 		 */
6107c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
6117c478bd9Sstevel@tonic-gate 		    gettext("%s: dangerous on a dialup;"), cmdname);
6127c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
6137c478bd9Sstevel@tonic-gate 		    gettext("use ``%s -y'' if you are really sure\n"), cmdname);
6147c478bd9Sstevel@tonic-gate 		goto fail;
6157c478bd9Sstevel@tonic-gate 	}
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	if (needlog) {
6187c478bd9Sstevel@tonic-gate 		char *user = getlogin();
6197c478bd9Sstevel@tonic-gate 		struct passwd *pw;
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 		openlog(cmdname, 0, LOG_AUTH);
6227c478bd9Sstevel@tonic-gate 		if (user == NULL && (pw = getpwuid(getuid())) != NULL)
6237c478bd9Sstevel@tonic-gate 			user = pw->pw_name;
6247c478bd9Sstevel@tonic-gate 		if (user == NULL)
6257c478bd9Sstevel@tonic-gate 			user = "root";
6267c478bd9Sstevel@tonic-gate 		syslog(LOG_CRIT, "%sed by %s", cmdname, user);
6277c478bd9Sstevel@tonic-gate 	}
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	/*
6307c478bd9Sstevel@tonic-gate 	 * We must assume success and log it before auditd is terminated.
6317c478bd9Sstevel@tonic-gate 	 */
6327c478bd9Sstevel@tonic-gate 	if (fcn == AD_BOOT)
6337c478bd9Sstevel@tonic-gate 		aval = audit_reboot_success();
6347c478bd9Sstevel@tonic-gate 	else
6357c478bd9Sstevel@tonic-gate 		aval = audit_halt_success();
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	if (aval == -1) {
6387c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
6397c478bd9Sstevel@tonic-gate 		    gettext("%s: can't turn off auditd\n"), cmdname);
6407c478bd9Sstevel@tonic-gate 		if (needlog)
6417c478bd9Sstevel@tonic-gate 			(void) sleep(5); /* Give syslogd time to record this */
6427c478bd9Sstevel@tonic-gate 	}
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	(void) signal(SIGHUP, SIG_IGN);	/* for remote connections */
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	if (zone_getattr(getzoneid(), ZONE_ATTR_INITPID, &init_pid,
6477c478bd9Sstevel@tonic-gate 	    sizeof (init_pid)) != sizeof (init_pid)) {
6487c478bd9Sstevel@tonic-gate 		assert(errno == ESRCH);
6497c478bd9Sstevel@tonic-gate 		init_pid = -1;
6507c478bd9Sstevel@tonic-gate 	}
6517c478bd9Sstevel@tonic-gate 
652*26f665e8Sdstaff 	/*
653*26f665e8Sdstaff 	 * We start to fork a bunch of zoneadms to halt any active zones.
654*26f665e8Sdstaff 	 * This will proceed with halt in parallel until we call
655*26f665e8Sdstaff 	 * check_zone_haltedness later on.
656*26f665e8Sdstaff 	 */
657*26f665e8Sdstaff 	if (zoneid == GLOBAL_ZONEID && cmd != A_DUMP) {
658*26f665e8Sdstaff 		need_check_zones = halt_zones(cmdname);
659*26f665e8Sdstaff 	}
660*26f665e8Sdstaff 
661*26f665e8Sdstaff 
6627c478bd9Sstevel@tonic-gate 	/* sync boot archive in the global zone */
6637c478bd9Sstevel@tonic-gate 	if (getzoneid() == GLOBAL_ZONEID && !nosync) {
6647c478bd9Sstevel@tonic-gate 		(void) system("/sbin/bootadm -a update_all");
6657c478bd9Sstevel@tonic-gate 	}
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	/*
6687c478bd9Sstevel@tonic-gate 	 * If we're not forcing a crash dump, mark the system as quiescing for
6697c478bd9Sstevel@tonic-gate 	 * smf(5)'s benefit, and idle the init process.
6707c478bd9Sstevel@tonic-gate 	 */
6717c478bd9Sstevel@tonic-gate 	if (cmd != A_DUMP) {
6727c478bd9Sstevel@tonic-gate 		if (init_pid != -1 && kill(init_pid, SIGTSTP) == -1) {
6737c478bd9Sstevel@tonic-gate 			/*
6747c478bd9Sstevel@tonic-gate 			 * TRANSLATION_NOTE
6757c478bd9Sstevel@tonic-gate 			 * Don't translate the word "init"
6767c478bd9Sstevel@tonic-gate 			 */
6777c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
6787c478bd9Sstevel@tonic-gate 			    gettext("%s: can't idle init\n"), cmdname);
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 			goto fail;
6817c478bd9Sstevel@tonic-gate 		}
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 		if (creat(resetting, 0755) == -1)
6847c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
6857c478bd9Sstevel@tonic-gate 			    gettext("%s: could not create %s.\n"),
6867c478bd9Sstevel@tonic-gate 			    cmdname, resetting);
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 		/*
6897c478bd9Sstevel@tonic-gate 		 * Stop all restarters so they do not try to restart services
6907c478bd9Sstevel@tonic-gate 		 * that are terminated.
6917c478bd9Sstevel@tonic-gate 		 */
6927c478bd9Sstevel@tonic-gate 		stop_restarters();
693*26f665e8Sdstaff 
694*26f665e8Sdstaff 		/*
695*26f665e8Sdstaff 		 * Wait a little while for zones to shutdown.
696*26f665e8Sdstaff 		 */
697*26f665e8Sdstaff 		if (need_check_zones) {
698*26f665e8Sdstaff 			check_zones_haltedness(cmdname);
699*26f665e8Sdstaff 
700*26f665e8Sdstaff 			(void) fprintf(stderr,
701*26f665e8Sdstaff 			    gettext("%s: Completing system halt.\n"),
702*26f665e8Sdstaff 			    cmdname);
703*26f665e8Sdstaff 		}
7047c478bd9Sstevel@tonic-gate 	}
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	/*
7077c478bd9Sstevel@tonic-gate 	 * Make sure we don't get stopped by a jobcontrol shell
7087c478bd9Sstevel@tonic-gate 	 * once we start killing everybody.
7097c478bd9Sstevel@tonic-gate 	 */
7107c478bd9Sstevel@tonic-gate 	(void) signal(SIGTSTP, SIG_IGN);
7117c478bd9Sstevel@tonic-gate 	(void) signal(SIGTTIN, SIG_IGN);
7127c478bd9Sstevel@tonic-gate 	(void) signal(SIGTTOU, SIG_IGN);
7137c478bd9Sstevel@tonic-gate 	(void) signal(SIGTERM, SIG_IGN);
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	/*
7167c478bd9Sstevel@tonic-gate 	 * If we're not forcing a crash dump, give everyone 5 seconds to
7177c478bd9Sstevel@tonic-gate 	 * handle a SIGTERM and clean up properly.
7187c478bd9Sstevel@tonic-gate 	 */
7197c478bd9Sstevel@tonic-gate 	if (cmd != A_DUMP) {
7207c478bd9Sstevel@tonic-gate 		(void) kill(-1, SIGTERM);
7217c478bd9Sstevel@tonic-gate 		(void) sleep(5);
7227c478bd9Sstevel@tonic-gate 	}
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 	if (!qflag && !nosync) {
7257c478bd9Sstevel@tonic-gate 		struct utmpx wtmpx;
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 		bzero(&wtmpx, sizeof (struct utmpx));
7287c478bd9Sstevel@tonic-gate 		(void) strcpy(wtmpx.ut_line, "~");
7297c478bd9Sstevel@tonic-gate 		(void) time(&wtmpx.ut_tv.tv_sec);
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 		if (cmd == A_DUMP)
7327c478bd9Sstevel@tonic-gate 			(void) strcpy(wtmpx.ut_name, "crash dump");
7337c478bd9Sstevel@tonic-gate 		else
7347c478bd9Sstevel@tonic-gate 			(void) strcpy(wtmpx.ut_name, "shutdown");
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 		(void) updwtmpx(WTMPX_FILE, &wtmpx);
7377c478bd9Sstevel@tonic-gate 		sync();
7387c478bd9Sstevel@tonic-gate 	}
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 	if (cmd == A_DUMP && nosync != 0)
7417c478bd9Sstevel@tonic-gate 		(void) uadmin(A_DUMP, AD_NOSYNC, NULL);
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 	(void) uadmin(cmd, fcn, mdep);
7447c478bd9Sstevel@tonic-gate 	perror(cmdname);
7457c478bd9Sstevel@tonic-gate 	do
7467c478bd9Sstevel@tonic-gate 		r = remove(resetting);
7477c478bd9Sstevel@tonic-gate 	while (r != 0 && errno == EINTR);
7487c478bd9Sstevel@tonic-gate 	if (r != 0 && errno != ENOENT)
7497c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("%s: could not remove %s.\n"),
7507c478bd9Sstevel@tonic-gate 		    cmdname, resetting);
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 	continue_restarters();
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	if (init_pid != -1)
7557c478bd9Sstevel@tonic-gate 		/* tell init to restate current level */
7567c478bd9Sstevel@tonic-gate 		(void) kill(init_pid, SIGHUP);
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate fail:
7597c478bd9Sstevel@tonic-gate 	if (fcn == AD_BOOT)
7607c478bd9Sstevel@tonic-gate 		(void) audit_reboot_fail();
7617c478bd9Sstevel@tonic-gate 	else
7627c478bd9Sstevel@tonic-gate 		(void) audit_halt_fail();
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate 	return (1);
7657c478bd9Sstevel@tonic-gate }
766