xref: /illumos-gate/usr/src/cmd/halt/halt.c (revision 8e07a41f6fae3d5b0619bd9c6f9fd19f97ad2c80)
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 (the "License").
6  * You may not use this file except in compliance with the License.
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 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
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
31  * The Regents of the University of California
32  * All Rights Reserved
33  *
34  * University Acknowledgment- Portions of this document are derived from
35  * software developed by the University of California, Berkeley, and its
36  * contributors.
37  * Portions contributed by Juergen Keil, <jk@tools.de>.
38  */
39 
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 
46 #include <stdio.h>
47 #include <procfs.h>
48 #include <sys/types.h>
49 #include <sys/elf.h>
50 #include <sys/systeminfo.h>
51 #include <sys/stat.h>
52 #include <sys/uadmin.h>
53 #include <sys/mntent.h>
54 #include <sys/mnttab.h>
55 #include <sys/mount.h>
56 #include <sys/fs/ufs_mount.h>
57 #include <alloca.h>
58 #include <assert.h>
59 #include <errno.h>
60 #include <fcntl.h>
61 #include <libgen.h>
62 #include <libscf.h>
63 #include <limits.h>
64 #include <locale.h>
65 #include <libintl.h>
66 #include <syslog.h>
67 #include <signal.h>
68 #include <strings.h>
69 #include <unistd.h>
70 #include <stdlib.h>
71 #include <stdio.h>
72 #include <strings.h>
73 #include <time.h>
74 #include <wait.h>
75 #include <ctype.h>
76 #include <utmpx.h>
77 #include <pwd.h>
78 #include <zone.h>
79 
80 #include <libzfs.h>
81 
82 #if !defined(TEXT_DOMAIN)
83 #define	TEXT_DOMAIN	"SYS_TEST"
84 #endif
85 
86 #if defined(__sparc)
87 #define	CUR_ELFDATA	ELFDATA2MSB
88 #elif defined(__i386)
89 #define	CUR_ELFDATA	ELFDATA2LSB
90 #endif
91 
92 static libzfs_handle_t *g_zfs;
93 
94 extern int audit_halt_setup(int, char **);
95 extern int audit_halt_success(void);
96 extern int audit_halt_fail(void);
97 
98 extern int audit_reboot_setup(void);
99 extern int audit_reboot_success(void);
100 extern int audit_reboot_fail(void);
101 
102 static char *cmdname;	/* basename(argv[0]), the name of the command */
103 
104 typedef struct ctidlist_struct {
105 	ctid_t ctid;
106 	struct ctidlist_struct *next;
107 } ctidlist_t;
108 
109 static ctidlist_t *ctidlist = NULL;
110 static ctid_t startdct = -1;
111 
112 #define	FMRI_STARTD_CONTRACT \
113 	"svc:/system/svc/restarter:default/:properties/restarter/contract"
114 
115 #define	ZONEADM_PROG "/usr/sbin/zoneadm"
116 
117 #define	LUUMOUNT_PROG	"/usr/sbin/luumount"
118 #define	LUMOUNT_PROG	"/usr/sbin/lumount"
119 
120 /*
121  * The length of FASTBOOT_MOUNTPOINT must be less than MAXPATHLEN.
122  */
123 #define	FASTBOOT_MOUNTPOINT	"/tmp/.fastboot.root"
124 
125 static char	fastboot_mounted[MAXPATHLEN];
126 
127 static int validate_ufs_disk(char *, char *);
128 static int validate_zfs_pool(char *, char *);
129 
130 static pid_t
131 get_initpid()
132 {
133 	static int init_pid = -1;
134 
135 	if (init_pid == -1) {
136 		if (zone_getattr(getzoneid(), ZONE_ATTR_INITPID, &init_pid,
137 		    sizeof (init_pid)) != sizeof (init_pid)) {
138 			assert(errno == ESRCH);
139 			init_pid = -1;
140 		}
141 	}
142 	return (init_pid);
143 }
144 
145 /*
146  * Quiesce or resume init using /proc.  When stopping init, we can't send
147  * SIGTSTP (since init ignores it) or SIGSTOP (since the kernel won't permit
148  * it).
149  */
150 static int
151 direct_init(long command)
152 {
153 	char ctlfile[MAXPATHLEN];
154 	pid_t pid;
155 	int ctlfd;
156 
157 	assert(command == PCDSTOP || command == PCRUN);
158 	if ((pid = get_initpid()) == -1) {
159 		return (-1);
160 	}
161 
162 	(void) snprintf(ctlfile, sizeof (ctlfile), "/proc/%d/ctl", pid);
163 	if ((ctlfd = open(ctlfile, O_WRONLY)) == -1)
164 		return (-1);
165 
166 	if (command == PCDSTOP) {
167 		if (write(ctlfd, &command, sizeof (long)) == -1) {
168 			(void) close(ctlfd);
169 			return (-1);
170 		}
171 	} else {	/* command == PCRUN */
172 		long cmds[2];
173 		cmds[0] = command;
174 		cmds[1] = 0;
175 		if (write(ctlfd, cmds, sizeof (cmds)) == -1) {
176 			(void) close(ctlfd);
177 			return (-1);
178 		}
179 	}
180 	(void) close(ctlfd);
181 	return (0);
182 }
183 
184 static void
185 stop_startd()
186 {
187 	scf_handle_t *h;
188 	scf_property_t *prop = NULL;
189 	scf_value_t *val = NULL;
190 	uint64_t uint64;
191 
192 	if ((h = scf_handle_create(SCF_VERSION)) == NULL)
193 		return;
194 
195 	if ((scf_handle_bind(h) != 0) ||
196 	    ((prop = scf_property_create(h)) == NULL) ||
197 	    ((val = scf_value_create(h)) == NULL))
198 		goto out;
199 
200 	if (scf_handle_decode_fmri(h, FMRI_STARTD_CONTRACT,
201 	    NULL, NULL, NULL, NULL, prop, SCF_DECODE_FMRI_EXACT) != 0)
202 		goto out;
203 
204 	if (scf_property_is_type(prop, SCF_TYPE_COUNT) != 0 ||
205 	    scf_property_get_value(prop, val) != 0 ||
206 	    scf_value_get_count(val, &uint64) != 0)
207 		goto out;
208 
209 	startdct = (ctid_t)uint64;
210 	(void) sigsend(P_CTID, startdct, SIGSTOP);
211 
212 out:
213 	scf_property_destroy(prop);
214 	scf_value_destroy(val);
215 	scf_handle_destroy(h);
216 }
217 
218 static void
219 continue_startd()
220 {
221 	if (startdct != -1)
222 		(void) sigsend(P_CTID, startdct, SIGCONT);
223 }
224 
225 #define	FMRI_RESTARTER_PROP "/:properties/general/restarter"
226 #define	FMRI_CONTRACT_PROP "/:properties/restarter/contract"
227 
228 static int
229 save_ctid(ctid_t ctid)
230 {
231 	ctidlist_t *next;
232 
233 	for (next = ctidlist; next != NULL; next = next->next)
234 		if (next->ctid == ctid)
235 			return (-1);
236 
237 	next = (ctidlist_t *)malloc(sizeof (ctidlist_t));
238 	if (next == NULL)
239 		return (-1);
240 
241 	next->ctid = ctid;
242 	next->next = ctidlist;
243 	ctidlist = next;
244 	return (0);
245 }
246 
247 static void
248 stop_delegates()
249 {
250 	ctid_t ctid;
251 	scf_handle_t *h;
252 	scf_scope_t *sc = NULL;
253 	scf_service_t *svc = NULL;
254 	scf_instance_t *inst = NULL;
255 	scf_snapshot_t *snap = NULL;
256 	scf_snapshot_t *isnap = NULL;
257 	scf_propertygroup_t *pg = NULL;
258 	scf_property_t *prop = NULL;
259 	scf_value_t *val = NULL;
260 	scf_iter_t *siter = NULL;
261 	scf_iter_t *iiter = NULL;
262 	char *fmri;
263 	ssize_t length;
264 
265 	uint64_t uint64;
266 	ssize_t bytes;
267 
268 	length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
269 	if (length <= 0)
270 		return;
271 
272 	length++;
273 	fmri = alloca(length * sizeof (char));
274 
275 	if ((h = scf_handle_create(SCF_VERSION)) == NULL)
276 		return;
277 
278 	if (scf_handle_bind(h) != 0) {
279 		scf_handle_destroy(h);
280 		return;
281 	}
282 
283 	if ((sc = scf_scope_create(h)) == NULL ||
284 	    (svc = scf_service_create(h)) == NULL ||
285 	    (inst = scf_instance_create(h)) == NULL ||
286 	    (snap = scf_snapshot_create(h)) == NULL ||
287 	    (pg = scf_pg_create(h)) == NULL ||
288 	    (prop = scf_property_create(h)) == NULL ||
289 	    (val = scf_value_create(h)) == NULL ||
290 	    (siter = scf_iter_create(h)) == NULL ||
291 	    (iiter = scf_iter_create(h)) == NULL)
292 		goto out;
293 
294 	if (scf_handle_get_scope(h, SCF_SCOPE_LOCAL, sc) != 0)
295 		goto out;
296 
297 	if (scf_iter_scope_services(siter, sc) != 0)
298 		goto out;
299 
300 	while (scf_iter_next_service(siter, svc) == 1) {
301 
302 		if (scf_iter_service_instances(iiter, svc) != 0)
303 			continue;
304 
305 		while (scf_iter_next_instance(iiter, inst) == 1) {
306 
307 			if ((scf_instance_get_snapshot(inst, "running",
308 			    snap)) != 0)
309 				isnap = NULL;
310 			else
311 				isnap = snap;
312 
313 			if (scf_instance_get_pg_composed(inst, isnap,
314 			    SCF_PG_GENERAL, pg) != 0)
315 				continue;
316 
317 			if (scf_pg_get_property(pg, SCF_PROPERTY_RESTARTER,
318 			    prop) != 0 ||
319 			    scf_property_get_value(prop, val) != 0)
320 				continue;
321 
322 			bytes = scf_value_get_astring(val, fmri, length);
323 			if (bytes <= 0 || bytes >= length)
324 				continue;
325 
326 			if (strlcat(fmri, FMRI_CONTRACT_PROP, length) >=
327 			    length)
328 				continue;
329 
330 			if (scf_handle_decode_fmri(h, fmri, NULL, NULL,
331 			    NULL, NULL, prop, SCF_DECODE_FMRI_EXACT) != 0)
332 				continue;
333 
334 			if (scf_property_is_type(prop, SCF_TYPE_COUNT) != 0 ||
335 			    scf_property_get_value(prop, val) != 0 ||
336 			    scf_value_get_count(val, &uint64) != 0)
337 				continue;
338 
339 			ctid = (ctid_t)uint64;
340 			if (save_ctid(ctid) == 0) {
341 				(void) sigsend(P_CTID, ctid, SIGSTOP);
342 			}
343 		}
344 	}
345 out:
346 	scf_scope_destroy(sc);
347 	scf_service_destroy(svc);
348 	scf_instance_destroy(inst);
349 	scf_snapshot_destroy(snap);
350 	scf_pg_destroy(pg);
351 	scf_property_destroy(prop);
352 	scf_value_destroy(val);
353 	scf_iter_destroy(siter);
354 	scf_iter_destroy(iiter);
355 
356 	(void) scf_handle_unbind(h);
357 	scf_handle_destroy(h);
358 }
359 
360 static void
361 continue_delegates()
362 {
363 	ctidlist_t *next;
364 	for (next = ctidlist; next != NULL; next = next->next)
365 		(void) sigsend(P_CTID, next->ctid, SIGCONT);
366 }
367 
368 static void
369 stop_restarters()
370 {
371 	stop_startd();
372 	stop_delegates();
373 }
374 
375 static void
376 continue_restarters()
377 {
378 	continue_startd();
379 	continue_delegates();
380 }
381 
382 /*
383  * Copy an array of strings into buf, separated by spaces.  Returns 0 on
384  * success.
385  */
386 static int
387 gather_args(char **args, char *buf, size_t buf_sz)
388 {
389 	if (strlcpy(buf, *args, buf_sz) >= buf_sz)
390 		return (-1);
391 
392 	for (++args; *args != NULL; ++args) {
393 		if (strlcat(buf, " ", buf_sz) >= buf_sz)
394 			return (-1);
395 		if (strlcat(buf, *args, buf_sz) >= buf_sz)
396 			return (-1);
397 	}
398 
399 	return (0);
400 }
401 
402 /*
403  * Halt every zone on the system.  We are committed to doing a shutdown
404  * even if something goes wrong here. If something goes wrong, we just
405  * continue with the shutdown.  Return non-zero if we need to wait for zones to
406  * halt later on.
407  */
408 static int
409 halt_zones()
410 {
411 	pid_t pid;
412 	zoneid_t *zones;
413 	size_t nz = 0, old_nz;
414 	int i;
415 	char zname[ZONENAME_MAX];
416 
417 	/*
418 	 * Get a list of zones. If the number of zones changes in between the
419 	 * two zone_list calls, try again.
420 	 */
421 
422 	for (;;) {
423 		(void) zone_list(NULL, &nz);
424 		if (nz == 1)
425 			return (0);
426 		old_nz = nz;
427 		zones = calloc(sizeof (zoneid_t), nz);
428 		if (zones == NULL) {
429 			(void) fprintf(stderr,
430 			    gettext("%s: Could not halt zones"
431 			    " (out of memory).\n"), cmdname);
432 			return (0);
433 		}
434 
435 		(void) zone_list(zones, &nz);
436 		if (old_nz == nz)
437 			break;
438 		free(zones);
439 	}
440 
441 	if (nz == 2) {
442 		(void) fprintf(stderr, gettext("%s: Halting 1 zone.\n"),
443 		    cmdname);
444 	} else {
445 		(void) fprintf(stderr, gettext("%s: Halting %i zones.\n"),
446 		    cmdname, nz - 1);
447 	}
448 
449 	for (i = 0; i < nz; i++) {
450 		if (zones[i] == GLOBAL_ZONEID)
451 			continue;
452 		if (getzonenamebyid(zones[i], zname, sizeof (zname)) < 0) {
453 			/*
454 			 * getzonenamebyid should only fail if we raced with
455 			 * another process trying to shut down the zone.
456 			 * We assume this happened and ignore the error.
457 			 */
458 			if (errno != EINVAL) {
459 				(void) fprintf(stderr,
460 				    gettext("%s: Unexpected error while "
461 				    "looking up zone %ul: %s.\n"),
462 				    cmdname, zones[i], strerror(errno));
463 			}
464 
465 			continue;
466 		}
467 		pid = fork();
468 		if (pid < 0) {
469 			(void) fprintf(stderr,
470 			    gettext("%s: Zone \"%s\" could not be"
471 			    " halted (could not fork(): %s).\n"),
472 			    cmdname, zname, strerror(errno));
473 			continue;
474 		}
475 		if (pid == 0) {
476 			(void) execl(ZONEADM_PROG, ZONEADM_PROG,
477 			    "-z", zname, "halt", NULL);
478 			(void) fprintf(stderr,
479 			    gettext("%s: Zone \"%s\" could not be halted"
480 			    " (cannot exec(" ZONEADM_PROG "): %s).\n"),
481 			    cmdname, zname, strerror(errno));
482 			exit(0);
483 		}
484 	}
485 
486 	return (1);
487 }
488 
489 /*
490  * This function tries to wait for all non-global zones to go away.
491  * It will timeout if no progress is made for 5 seconds, or a total of
492  * 30 seconds elapses.
493  */
494 
495 static void
496 check_zones_haltedness()
497 {
498 	int t = 0, t_prog = 0;
499 	size_t nz = 0, last_nz;
500 
501 	do {
502 		last_nz = nz;
503 		(void) zone_list(NULL, &nz);
504 		if (nz == 1)
505 			return;
506 
507 		(void) sleep(1);
508 
509 		if (last_nz > nz)
510 			t_prog = 0;
511 
512 		t++;
513 		t_prog++;
514 
515 		if (t == 10) {
516 			if (nz == 2) {
517 				(void) fprintf(stderr,
518 				    gettext("%s: Still waiting for 1 zone to "
519 				    "halt. Will wait up to 20 seconds.\n"),
520 				    cmdname);
521 			} else {
522 				(void) fprintf(stderr,
523 				    gettext("%s: Still waiting for %i zones "
524 				    "to halt. Will wait up to 20 seconds.\n"),
525 				    cmdname, nz - 1);
526 			}
527 		}
528 
529 	} while ((t < 30) && (t_prog < 5));
530 }
531 
532 
533 /*
534  * Validate that this is a root disk or dataset
535  * Returns 0 if it is a root disk or dataset;
536  * returns 1 if it is a disk argument or dataset, but not valid or not root;
537  * returns -1 if it is not a valid argument or a disk argument.
538  */
539 static int
540 validate_disk(char *arg, char *mountpoint)
541 {
542 	static char root_dev_path[] = "/dev/dsk";
543 	char kernpath[MAXPATHLEN];
544 	struct stat buf;
545 	struct stat64 statbuf;
546 	int rc = 0;
547 
548 	if (strlen(arg) > MAXPATHLEN) {
549 		(void) fprintf(stderr,
550 		    gettext("%s: argument is too long\n"), cmdname);
551 		return (-1);
552 	}
553 
554 	bcopy(FASTBOOT_MOUNTPOINT, mountpoint, sizeof (FASTBOOT_MOUNTPOINT));
555 
556 	/*
557 	 * Do a force umount just in case some other filesystem has
558 	 * been mounted there.
559 	 */
560 	(void) umount2(mountpoint, MS_FORCE);
561 
562 	/* Create the directory if it doesn't already exist */
563 	if (lstat(mountpoint, &buf) != 0) {
564 		if (mkdirp(mountpoint, 0755) != 0) {
565 			(void) fprintf(stderr,
566 			    gettext("failed to create mountpoint %s\n"),
567 			    mountpoint);
568 			return (-1);
569 		}
570 	}
571 
572 	if (strncmp(arg, root_dev_path, strlen(root_dev_path)) == 0) {
573 		/* ufs root disk argument */
574 		rc = validate_ufs_disk(arg, mountpoint);
575 	} else {
576 		/* zfs root pool argument */
577 		rc = validate_zfs_pool(arg, mountpoint);
578 	}
579 
580 	if (rc != 0)
581 		return (rc);
582 
583 	(void) snprintf(kernpath, MAXPATHLEN, "%s/platform/i86pc/kernel/unix",
584 	    mountpoint);
585 
586 	if (stat64(kernpath, &statbuf) != 0) {
587 		(void) fprintf(stderr,
588 		    gettext("%s: %s is not a root disk or dataset\n"),
589 		    cmdname, arg);
590 		return (1);
591 	}
592 
593 	return (0);
594 }
595 
596 
597 static int
598 validate_ufs_disk(char *arg, char *mountpoint)
599 {
600 	struct ufs_args	ufs_args = { 0 };
601 	char mntopts[MNT_LINE_MAX] = MNTOPT_LARGEFILES;
602 
603 	/* perform the mount */
604 	ufs_args.flags = UFSMNT_LARGEFILES;
605 	if (mount(arg, mountpoint, MS_DATA|MS_OPTIONSTR,
606 	    MNTTYPE_UFS, &ufs_args, sizeof (ufs_args),
607 	    mntopts, sizeof (mntopts)) != 0) {
608 		perror(cmdname);
609 		(void) fprintf(stderr,
610 		    gettext("%s: failed to mount %s\n"), cmdname, arg);
611 		return (-1);
612 	}
613 
614 	return (0);
615 }
616 
617 static int
618 validate_zfs_pool(char *arg, char *mountpoint)
619 {
620 	zfs_handle_t *zhp = NULL;
621 	char mntopts[MNT_LINE_MAX] = { '\0' };
622 	int rc = 0;
623 
624 	if ((g_zfs = libzfs_init()) == NULL) {
625 		(void) fprintf(stderr, gettext("internal error: failed to "
626 		    "initialize ZFS library\n"));
627 		return (-1);
628 	}
629 
630 	/* Try to open the dataset */
631 	if ((zhp = zfs_open(g_zfs, arg,
632 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_DATASET)) == NULL)
633 		return (-1);
634 
635 	/* perform the mount */
636 	if (mount(zfs_get_name(zhp), mountpoint, MS_DATA|MS_OPTIONSTR,
637 	    MNTTYPE_ZFS, NULL, 0, mntopts, sizeof (mntopts)) != 0) {
638 		perror(cmdname);
639 		(void) fprintf(stderr,
640 		    gettext("%s: failed to mount %s\n"), cmdname, arg);
641 		rc = -1;
642 	}
643 
644 validate_zfs_err_out:
645 	if (zhp != NULL)
646 		zfs_close(zhp);
647 
648 	libzfs_fini(g_zfs);
649 	return (rc);
650 }
651 
652 /*
653  * Return 0 if not zfs, or is zfs and have successfully constructed the
654  * boot argument; returns non-zero otherwise.
655  * At successful completion fpth contains pointer where mount point ends.
656  * NOTE: arg is supposed to be the resolved path
657  */
658 static int
659 get_zfs_bootfs_arg(const char *arg, const char ** fpth, int *is_zfs,
660 		char *bootfs_arg)
661 {
662 	zfs_handle_t *zhp = NULL;
663 	zpool_handle_t *zpoolp = NULL;
664 	FILE *mtabp = NULL;
665 	struct mnttab mnt;
666 	char *poolname = NULL;
667 	char physpath[MAXNAMELEN];
668 	char mntsp[ZPOOL_MAXNAMELEN];
669 	char bootfs[ZPOOL_MAXNAMELEN];
670 	int rc = 0;
671 	size_t mntlen = 0;
672 	size_t msz;
673 
674 	*fpth = arg;
675 	*is_zfs = 0;
676 
677 	bzero(physpath, sizeof (physpath));
678 	bzero(bootfs, sizeof (bootfs));
679 
680 	if ((mtabp = fopen(MNTTAB, "r")) == NULL) {
681 		return (-1);
682 	}
683 
684 	while (getmntent(mtabp, &mnt) == 0) {
685 		if (strstr(arg, mnt.mnt_mountp) == arg &&
686 		    (msz = strlen(mnt.mnt_mountp)) > mntlen) {
687 			mntlen = msz;
688 			*is_zfs = strcmp(MNTTYPE_ZFS, mnt.mnt_fstype) == 0;
689 			(void) strlcpy(mntsp, mnt.mnt_special, sizeof (mntsp));
690 		}
691 	}
692 
693 	(void) fclose(mtabp);
694 
695 	if (mntlen > 1)
696 		*fpth += mntlen;
697 
698 	if (!*is_zfs)
699 		return (0);
700 
701 	if ((g_zfs = libzfs_init()) == NULL)
702 		return (-1);
703 
704 	/* Try to open the dataset */
705 	if ((zhp = zfs_open(g_zfs, mntsp,
706 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_DATASET)) == NULL) {
707 		(void) fprintf(stderr, gettext("cannot open %s\n"), mntsp);
708 		rc = -1;
709 		goto validate_zfs_err_out;
710 	}
711 
712 	(void) strlcpy(bootfs, mntsp, sizeof (bootfs));
713 
714 	if ((poolname = strtok(mntsp, "/")) == NULL) {
715 		rc = -1;
716 		goto validate_zfs_err_out;
717 	}
718 
719 	if ((zpoolp = zpool_open(g_zfs, poolname)) == NULL) {
720 		(void) fprintf(stderr, gettext("cannot open %s\n"), poolname);
721 		rc = -1;
722 		goto validate_zfs_err_out;
723 	}
724 
725 	if (zpool_get_physpath(zpoolp, physpath) != 0) {
726 		(void) fprintf(stderr, gettext("cannot find phys_path\n"));
727 		rc = -1;
728 		goto validate_zfs_err_out;
729 	}
730 
731 	if (zpool_set_prop(zpoolp, "bootfs", bootfs) != 0) {
732 		(void) fprintf(stderr, gettext("cannot set bootfs to %s\n"),
733 		    bootfs);
734 		rc = -1;
735 		goto validate_zfs_err_out;
736 	}
737 
738 	(void) snprintf(bootfs_arg, BOOTARGS_MAX,
739 	    "-B zfs-bootfs=%s,bootpath=\"%s\"", bootfs, physpath);
740 
741 validate_zfs_err_out:
742 	if (zhp != NULL)
743 		zfs_close(zhp);
744 
745 	if (zpoolp != NULL)
746 		zpool_close(zpoolp);
747 
748 	libzfs_fini(g_zfs);
749 	return (rc);
750 }
751 
752 /*
753  * Validate that the file exists, and is an ELF file.
754  * Returns 0 on success, -1 on failure.
755  */
756 static int
757 validate_unix(char *arg, int *mplen, int *is_zfs, char *bootfs_arg,
758     int *failsafe)
759 {
760 	const char *location;
761 	int class, format;
762 	unsigned char ident[EI_NIDENT];
763 	char physpath[MAXPATHLEN];
764 	int elffd = -1;
765 	size_t	sz;
766 
767 	if ((sz = resolvepath(arg, physpath, sizeof (physpath) - 1)) ==
768 	    (size_t)-1) {
769 		(void) fprintf(stderr,
770 		    gettext("cannot resolve path for %s: %s\n"),
771 		    arg, strerror(errno));
772 		return (-1);
773 	}
774 	(void) strlcpy(arg, physpath, sz + 1);
775 
776 	if (strlen(arg) > MAXPATHLEN) {
777 		(void) fprintf(stderr,
778 		    gettext("%s: new kernel name is too long\n"), cmdname);
779 		return (-1);
780 	}
781 
782 	if (strncmp(basename(arg), "unix", 4) != 0) {
783 		(void) fprintf(stderr,
784 		    gettext("%s: %s: kernel name must be unix\n"),
785 		    cmdname, arg);
786 		return (-1);
787 	}
788 
789 	if (get_zfs_bootfs_arg(arg, &location, is_zfs, bootfs_arg) != 0)
790 		goto err_out;
791 
792 	*mplen = location - arg;
793 
794 	if ((strstr(location, "/boot/platform")) == location)
795 		*failsafe = 1;
796 	else if ((strstr(location, "/platform")) == location)
797 		*failsafe = 0;
798 	else	{
799 		(void) fprintf(stderr,
800 		    gettext("%s: %s: no /boot/platform or /platform in"
801 		    " file name\n"), cmdname, arg);
802 			goto err_out;
803 	}
804 
805 	if ((elffd = open64(arg, O_RDONLY)) < 0 ||
806 	    (pread64(elffd, ident, EI_NIDENT, 0) != EI_NIDENT)) {
807 		(void) fprintf(stderr, "%s: %s: %s\n",
808 		    cmdname, arg, strerror(errno));
809 		goto err_out;
810 	}
811 
812 	class = ident[EI_CLASS];
813 
814 	if ((class != ELFCLASS32 && class != ELFCLASS64) ||
815 	    ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
816 	    ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) {
817 		(void) fprintf(stderr,
818 		    gettext("%s: %s: not a valid ELF file\n"),
819 		    cmdname, arg);
820 		goto err_out;
821 	}
822 
823 	format = ident[EI_DATA];
824 
825 	if (format != CUR_ELFDATA) {
826 		(void) fprintf(stderr, gettext("%s: %s: invalid data format\n"),
827 		    cmdname, arg);
828 		goto err_out;
829 	}
830 
831 	return (0);
832 
833 err_out:
834 	if (elffd >= 0) {
835 		(void) close(elffd);
836 		elffd = -1;
837 	}
838 	return (-1);
839 }
840 
841 #ifndef	__i386
842 /* ARGSUSED */
843 #endif	/* __i386 */
844 static int
845 is_fastboot_default(uid_t uid)
846 {
847 #if defined(__i386)
848 	int		ret;
849 	struct stat	st;
850 	static const char	fastboot_default[] = "/etc/fastreboot";
851 
852 	ret = (lstat(fastboot_default, &st) == 0 &&
853 	    S_ISREG(st.st_mode) &&
854 	    (st.st_mode & S_IRUSR) != 0 &&
855 	    uid == st.st_uid);
856 
857 	return (ret);
858 #else
859 	return (0);
860 #endif	/* __i386 */
861 }
862 
863 static int
864 halt_exec(const char *path, ...)
865 {
866 	pid_t		pid;
867 	int		i;
868 	int		st;
869 	const char	*arg;
870 	va_list	vp;
871 	const char	*argv[256];
872 
873 	if ((pid = fork()) == -1) {
874 		return (errno);
875 	} else if (pid == 0) {
876 		(void) fclose(stdout);
877 		(void) fclose(stderr);
878 
879 		argv[0] = path;
880 		i = 1;
881 
882 		va_start(vp, path);
883 
884 		do {
885 			arg = va_arg(vp, const char *);
886 			argv[i] = arg;
887 		} while (arg != NULL &&
888 		    ++i != sizeof (argv) / sizeof (argv[0]));
889 
890 		va_end(vp);
891 
892 		(void) execve(path, (char * const *)argv, NULL);
893 		(void) fprintf(stderr, gettext("cannot execute %s: %s\n"),
894 		    path, strerror(errno));
895 		exit(-1);
896 	} else {
897 		if (waitpid(pid, &st, 0) == pid &&
898 		    !WIFSIGNALED(st) && WIFEXITED(st))
899 			st = WEXITSTATUS(st);
900 		else
901 			st = -1;
902 	}
903 	return (st);
904 }
905 
906 /*
907  * Invokes lumount for bename.
908  * At successfull completion returns zero and copies contents of bename
909  * into mountpoint[]
910  */
911 static int
912 fastboot_bename(const char *bename, char *mountpoint, size_t mpsz)
913 {
914 	int rc;
915 
916 	(void) halt_exec(LUUMOUNT_PROG, "-n", bename, NULL);
917 
918 	if ((rc = halt_exec(LUMOUNT_PROG, "-n", bename, FASTBOOT_MOUNTPOINT,
919 	    NULL)) != 0)
920 		(void) fprintf(stderr, gettext("%s: cannot mount BE %s\n"),
921 		    cmdname, bename);
922 	else
923 		(void) strlcpy(mountpoint, FASTBOOT_MOUNTPOINT, mpsz);
924 
925 	return (rc);
926 }
927 
928 /*
929  * Returns 0 on successful parsing of the arguments;
930  * retuens non-zero on failure.
931  */
932 static int
933 parse_fastboot_args(char *bootargs_buf, int *is_dryrun, const char *bename,
934     int *failsafe)
935 {
936 	char mountpoint[MAXPATHLEN];
937 	char bootargs_saved[BOOTARGS_MAX];
938 	char bootargs_scratch[BOOTARGS_MAX];
939 	char bootfs_arg[BOOTARGS_MAX];
940 	char unixfile[BOOTARGS_MAX];
941 	char *head, *newarg;
942 	int buflen;		/* length of the bootargs_buf */
943 	int mplen;		/* length of the mount point */
944 	int rootlen = 0;	/* length of the root argument */
945 	int unixlen = 0;	/* length of the unix argument */
946 	int off = 0;		/* offset into the new boot argument */
947 	int is_zfs = 0;
948 	int rc = 0;
949 
950 	bzero(mountpoint, sizeof (mountpoint));
951 
952 	/*
953 	 * If argc is not 0, buflen is length of the argument being passed in;
954 	 * else it is 0 as bootargs_buf has been initialized to all 0's.
955 	 */
956 	buflen = strlen(bootargs_buf);
957 
958 	/* Save a copy of the original argument */
959 	bcopy(bootargs_buf, bootargs_saved, buflen);
960 	bzero(&bootargs_saved[buflen], sizeof (bootargs_saved) - buflen);
961 
962 	/* Save another copy to be used by strtok */
963 	bcopy(bootargs_buf, bootargs_scratch, buflen);
964 	bzero(&bootargs_scratch[buflen], sizeof (bootargs_scratch) - buflen);
965 	head = &bootargs_scratch[0];
966 
967 	/* Zero out the boot argument buffer as we will reconstruct it */
968 	bzero(bootargs_buf, BOOTARGS_MAX);
969 	bzero(bootfs_arg, BOOTARGS_MAX);
970 	bzero(unixfile, sizeof (unixfile));
971 
972 	/* Get the first argument */
973 	newarg = strtok(bootargs_scratch, " ");
974 
975 	/*
976 	 * If this is a dry run request, verify that the drivers can handle
977 	 * fast reboot.
978 	 */
979 	if (newarg && strncasecmp(newarg, "dryrun", strlen("dryrun")) == 0) {
980 		*is_dryrun = 1;
981 		(void) system("/usr/sbin/devfsadm");
982 	}
983 
984 	/*
985 	 * Always perform a dry run to identify all the drivers that
986 	 * need to implement devo_reset().
987 	 */
988 	if (uadmin(A_SHUTDOWN, AD_FASTREBOOT_DRYRUN,
989 	    (uintptr_t)bootargs_saved) != 0) {
990 		(void) fprintf(stderr, gettext("%s: not all drivers "
991 		    "have implemented quiesce(9E)\n"), cmdname);
992 	} else if (*is_dryrun) {
993 		(void) fprintf(stderr, gettext("%s: all drivers have "
994 		    "implemented quiesce(9E)\n"), cmdname);
995 	}
996 
997 	/*
998 	 * Return if it is a true dry run.
999 	 */
1000 	if (*is_dryrun)
1001 		return (rc);
1002 
1003 	if (bename && (rc = fastboot_bename(bename, mountpoint,
1004 	    sizeof (mountpoint))) != 0)
1005 		return (rc);
1006 
1007 	/*
1008 	 * If BE is not specified, look for disk argument to construct
1009 	 * mountpoint; if BE has been specified, mountpoint has already been
1010 	 * constructed.
1011 	 */
1012 	if (newarg && newarg[0] != '-' && !bename) {
1013 		int tmprc;
1014 
1015 		if ((tmprc = validate_disk(newarg, mountpoint)) == 0) {
1016 			/*
1017 			 * The first argument is a valid root argument.
1018 			 * Get the next argument.
1019 			 */
1020 			newarg = strtok(NULL, " ");
1021 			rootlen = (newarg) ? (newarg - head) : buflen;
1022 			(void) strlcpy(fastboot_mounted, mountpoint,
1023 			    sizeof (fastboot_mounted));
1024 
1025 		} else if (tmprc == -1) {
1026 			/*
1027 			 * Not a disk argument.  Use / as default root.
1028 			 */
1029 			bcopy("/", mountpoint, 1);
1030 			bzero(&mountpoint[1], sizeof (mountpoint) - 1);
1031 		} else {
1032 			/*
1033 			 * Disk argument, but not valid or not root.
1034 			 * Return failure.
1035 			 */
1036 			return (EINVAL);
1037 		}
1038 	}
1039 
1040 	/*
1041 	 * Make mountpoint the first part of unixfile.
1042 	 * If there is not disk argument, and BE has not been specified,
1043 	 * mountpoint could be empty.
1044 	 */
1045 	mplen = strlen(mountpoint);
1046 	bcopy(mountpoint, unixfile, mplen);
1047 
1048 	/*
1049 	 * Look for unix argument
1050 	 */
1051 	if (newarg && newarg[0] != '-') {
1052 		bcopy(newarg, &unixfile[mplen], strlen(newarg));
1053 		newarg = strtok(NULL, " ");
1054 		rootlen = (newarg) ? (newarg - head) : buflen;
1055 	} else if (mplen != 0) {
1056 		/*
1057 		 * No unix argument, but mountpoint is not empty, use
1058 		 * /platform/i86pc/$ISADIR/kernel/unix as default.
1059 		 */
1060 		char isa[20];
1061 
1062 		if (sysinfo(SI_ARCHITECTURE_64, isa, sizeof (isa)) != -1)
1063 			(void) snprintf(&unixfile[mplen],
1064 			    sizeof (unixfile) - mplen,
1065 			    "/platform/i86pc/kernel/%s/unix", isa);
1066 		else if (sysinfo(SI_ARCHITECTURE_32, isa, sizeof (isa)) != -1) {
1067 			(void) snprintf(&unixfile[mplen],
1068 			    sizeof (unixfile) - mplen,
1069 			    "/platform/i86pc/kernel/unix");
1070 		} else {
1071 			(void) fprintf(stderr,
1072 			    gettext("%s: unknown architecture"), cmdname);
1073 			return (EINVAL);
1074 		}
1075 	}
1076 
1077 	/*
1078 	 * We now have the complete unix argument.  Verify that it exists and
1079 	 * is an ELF file.  Split the argument up into mountpoint and unix
1080 	 * portions again.  This is necessary to handle cases where mountpoint
1081 	 * is specified on the command line as part of the unix argument,
1082 	 * such as this:
1083 	 *	# reboot -f /.alt/platform/i86pc/kernel/amd64/unix
1084 	 */
1085 	unixlen = strlen(unixfile);
1086 	if (unixlen > 0) {
1087 		if (validate_unix(unixfile, &mplen, &is_zfs,
1088 		    bootfs_arg, failsafe) != 0) {
1089 			/* Not a valid unix file */
1090 			return (EINVAL);
1091 		} else {
1092 			int space = 0;
1093 			/*
1094 			 * Construct boot argument.
1095 			 */
1096 			unixlen = strlen(unixfile);
1097 
1098 			/*
1099 			 * mdep cannot start with space because bootadm
1100 			 * creates bogus menu entries if it does.
1101 			 */
1102 			if (mplen > 0) {
1103 				bcopy(unixfile, bootargs_buf, mplen);
1104 				(void) strcat(bootargs_buf, " ");
1105 				space = 1;
1106 			}
1107 			bcopy(&unixfile[mplen], &bootargs_buf[mplen + space],
1108 			    unixlen - mplen);
1109 			(void) strcat(bootargs_buf, " ");
1110 			off += unixlen + space + 1;
1111 		}
1112 	} else {
1113 		/* Check to see if root is zfs */
1114 		const char	*dp;
1115 		(void) get_zfs_bootfs_arg("/", &dp, &is_zfs, bootfs_arg);
1116 	}
1117 
1118 	if (is_zfs && (buflen != 0 || bename != NULL))	{
1119 		/* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */
1120 		off += sprintf(bootargs_buf + off, "%s ", bootfs_arg);
1121 	}
1122 
1123 	/*
1124 	 * Copy the rest of the arguments
1125 	 */
1126 	bcopy(&bootargs_saved[rootlen], &bootargs_buf[off], buflen - rootlen);
1127 
1128 	return (rc);
1129 }
1130 
1131 int
1132 main(int argc, char *argv[])
1133 {
1134 	char *ttyn = ttyname(STDERR_FILENO);
1135 
1136 	uid_t	euid;
1137 	int qflag = 0, needlog = 1, nosync = 0;
1138 	int fast_reboot = 0;
1139 	uintptr_t mdep = NULL;
1140 	int cmd, fcn, c, aval, r;
1141 	const char *usage;
1142 	const char *optstring;
1143 	zoneid_t zoneid = getzoneid();
1144 	int need_check_zones = 0;
1145 	char bootargs_buf[BOOTARGS_MAX];
1146 	int failsafe = 0;
1147 	char *bename = NULL;
1148 
1149 	const char * const resetting = "/etc/svc/volatile/resetting";
1150 
1151 	(void) setlocale(LC_ALL, "");
1152 	(void) textdomain(TEXT_DOMAIN);
1153 
1154 	cmdname = basename(argv[0]);
1155 
1156 	if (strcmp(cmdname, "halt") == 0) {
1157 		(void) audit_halt_setup(argc, argv);
1158 		optstring = "dlnqy";
1159 		usage = gettext("usage: %s [ -dlnqy ]\n");
1160 		cmd = A_SHUTDOWN;
1161 		fcn = AD_HALT;
1162 	} else if (strcmp(cmdname, "poweroff") == 0) {
1163 		(void) audit_halt_setup(argc, argv);
1164 		optstring = "dlnqy";
1165 		usage = gettext("usage: %s [ -dlnqy ]\n");
1166 		cmd = A_SHUTDOWN;
1167 		fcn = AD_POWEROFF;
1168 	} else if (strcmp(cmdname, "reboot") == 0) {
1169 		(void) audit_reboot_setup();
1170 #if defined(__i386)
1171 		optstring = "dlnqfe:";
1172 		usage = gettext("usage: %s [ -dlnqfe: ] [ boot args ]\n");
1173 #else
1174 		optstring = "dlnq";
1175 		usage = gettext("usage: %s [ -dlnq ] [ boot args ]\n");
1176 #endif
1177 		cmd = A_SHUTDOWN;
1178 		fcn = AD_BOOT;
1179 	} else {
1180 		(void) fprintf(stderr,
1181 		    gettext("%s: not installed properly\n"), cmdname);
1182 		return (1);
1183 	}
1184 
1185 	while ((c = getopt(argc, argv, optstring)) != EOF) {
1186 		switch (c) {
1187 		case 'd':
1188 			if (zoneid == GLOBAL_ZONEID)
1189 				cmd = A_DUMP;
1190 			else {
1191 				(void) fprintf(stderr,
1192 				    gettext("%s: -d only valid from global"
1193 				    " zone\n"), cmdname);
1194 				return (1);
1195 			}
1196 			break;
1197 		case 'l':
1198 			needlog = 0;
1199 			break;
1200 		case 'n':
1201 			nosync = 1;
1202 			break;
1203 		case 'q':
1204 			qflag = 1;
1205 			break;
1206 		case 'y':
1207 			ttyn = NULL;
1208 			break;
1209 #if defined(__i386)
1210 		case 'f':
1211 			fast_reboot = 1;
1212 			break;
1213 		case 'e':
1214 			bename = optarg;
1215 			break;
1216 #endif
1217 		default:
1218 			/*
1219 			 * TRANSLATION_NOTE
1220 			 * Don't translate the words "halt" or "reboot"
1221 			 */
1222 			(void) fprintf(stderr, usage, cmdname);
1223 			return (1);
1224 		}
1225 	}
1226 
1227 	argc -= optind;
1228 	argv += optind;
1229 
1230 	if (argc != 0) {
1231 		if (fcn != AD_BOOT) {
1232 			(void) fprintf(stderr, usage, cmdname);
1233 			return (1);
1234 		}
1235 
1236 		/* Gather the arguments into bootargs_buf. */
1237 		if (gather_args(argv, bootargs_buf, sizeof (bootargs_buf)) !=
1238 		    0) {
1239 			(void) fprintf(stderr,
1240 			    gettext("%s: Boot arguments too long.\n"), cmdname);
1241 			return (1);
1242 		}
1243 
1244 		mdep = (uintptr_t)bootargs_buf;
1245 	} else {
1246 		/*
1247 		 * Initialize it to 0 in case of fastboot, the buffer
1248 		 * will be used.
1249 		 */
1250 		bzero(bootargs_buf, sizeof (bootargs_buf));
1251 	}
1252 
1253 	if ((euid = geteuid()) != 0) {
1254 		(void) fprintf(stderr,
1255 		    gettext("%s: permission denied\n"), cmdname);
1256 		goto fail;
1257 	}
1258 
1259 	/*
1260 	 * Check whether fast  reboot is the default operating mode
1261 	 */
1262 	if (fcn == AD_BOOT && !fast_reboot)
1263 		fast_reboot = is_fastboot_default(euid);
1264 
1265 	if (bename && !fast_reboot)	{
1266 		(void) fprintf(stderr, gettext("%s: -e only valid with -f\n"),
1267 		    cmdname);
1268 		return (EINVAL);
1269 	}
1270 
1271 
1272 	/*
1273 	 * If fast reboot, do some sanity check on the argument
1274 	 */
1275 	if (fast_reboot) {
1276 		int rc;
1277 		int is_dryrun = 0;
1278 
1279 		if (zoneid != GLOBAL_ZONEID)	{
1280 			(void) fprintf(stderr,
1281 			    gettext("%s: fast reboot only valid from global"
1282 			    " zone\n"), cmdname);
1283 			return (EINVAL);
1284 		}
1285 
1286 		rc = parse_fastboot_args(bootargs_buf, &is_dryrun,
1287 		    bename, &failsafe);
1288 
1289 		/*
1290 		 * If dry run, or if arguments are invalid, return.
1291 		 */
1292 		if (is_dryrun)
1293 			return (rc);
1294 		else if (rc != 0)
1295 			goto fail;
1296 
1297 		/*
1298 		 * For all the other errors, we continue on in case user
1299 		 * user want to force fast reboot.
1300 		 */
1301 		if (strlen(bootargs_buf) != 0)
1302 			mdep = (uintptr_t)bootargs_buf;
1303 	}
1304 
1305 #if 0	/* For debugging */
1306 	if (mdep != NULL)
1307 		(void) fprintf(stderr, "mdep = %s\n", (char *)mdep);
1308 #endif
1309 
1310 	if (fcn != AD_BOOT && ttyn != NULL &&
1311 	    strncmp(ttyn, "/dev/term/", strlen("/dev/term/")) == 0) {
1312 		/*
1313 		 * TRANSLATION_NOTE
1314 		 * Don't translate ``halt -y''
1315 		 */
1316 		(void) fprintf(stderr,
1317 		    gettext("%s: dangerous on a dialup;"), cmdname);
1318 		(void) fprintf(stderr,
1319 		    gettext("use ``%s -y'' if you are really sure\n"), cmdname);
1320 		goto fail;
1321 	}
1322 
1323 	if (needlog) {
1324 		char *user = getlogin();
1325 		struct passwd *pw;
1326 		char *tty;
1327 
1328 		openlog(cmdname, 0, LOG_AUTH);
1329 		if (user == NULL && (pw = getpwuid(getuid())) != NULL)
1330 			user = pw->pw_name;
1331 		if (user == NULL)
1332 			user = "root";
1333 
1334 		tty = ttyname(1);
1335 
1336 		if (tty == NULL)
1337 			syslog(LOG_CRIT, "initiated by %s", user);
1338 		else
1339 			syslog(LOG_CRIT, "initiated by %s on %s", user, tty);
1340 	}
1341 
1342 	/*
1343 	 * We must assume success and log it before auditd is terminated.
1344 	 */
1345 	if (fcn == AD_BOOT)
1346 		aval = audit_reboot_success();
1347 	else
1348 		aval = audit_halt_success();
1349 
1350 	if (aval == -1) {
1351 		(void) fprintf(stderr,
1352 		    gettext("%s: can't turn off auditd\n"), cmdname);
1353 		if (needlog)
1354 			(void) sleep(5); /* Give syslogd time to record this */
1355 	}
1356 
1357 	(void) signal(SIGHUP, SIG_IGN);	/* for remote connections */
1358 
1359 	/*
1360 	 * We start to fork a bunch of zoneadms to halt any active zones.
1361 	 * This will proceed with halt in parallel until we call
1362 	 * check_zone_haltedness later on.
1363 	 */
1364 	if (zoneid == GLOBAL_ZONEID && cmd != A_DUMP) {
1365 		need_check_zones = halt_zones();
1366 	}
1367 
1368 
1369 	/* sync boot archive in the global zone */
1370 	if (zoneid == GLOBAL_ZONEID && !nosync) {
1371 		if (fast_reboot)
1372 			(void) system("/sbin/bootadm -a update_all fastboot");
1373 		else
1374 			(void) system("/sbin/bootadm -a update_all");
1375 	}
1376 
1377 	/*
1378 	 * If we're not forcing a crash dump, mark the system as quiescing for
1379 	 * smf(5)'s benefit, and idle the init process.
1380 	 */
1381 	if (cmd != A_DUMP) {
1382 		if (direct_init(PCDSTOP) == -1) {
1383 			/*
1384 			 * TRANSLATION_NOTE
1385 			 * Don't translate the word "init"
1386 			 */
1387 			(void) fprintf(stderr,
1388 			    gettext("%s: can't idle init\n"), cmdname);
1389 			goto fail;
1390 		}
1391 
1392 		if (creat(resetting, 0755) == -1)
1393 			(void) fprintf(stderr,
1394 			    gettext("%s: could not create %s.\n"),
1395 			    cmdname, resetting);
1396 
1397 		/*
1398 		 * Stop all restarters so they do not try to restart services
1399 		 * that are terminated.
1400 		 */
1401 		stop_restarters();
1402 
1403 		/*
1404 		 * Wait a little while for zones to shutdown.
1405 		 */
1406 		if (need_check_zones) {
1407 			check_zones_haltedness();
1408 
1409 			(void) fprintf(stderr,
1410 			    gettext("%s: Completing system halt.\n"),
1411 			    cmdname);
1412 		}
1413 	}
1414 
1415 	/*
1416 	 * Make sure we don't get stopped by a jobcontrol shell
1417 	 * once we start killing everybody.
1418 	 */
1419 	(void) signal(SIGTSTP, SIG_IGN);
1420 	(void) signal(SIGTTIN, SIG_IGN);
1421 	(void) signal(SIGTTOU, SIG_IGN);
1422 	(void) signal(SIGTERM, SIG_IGN);
1423 
1424 	/*
1425 	 * If we're not forcing a crash dump, give everyone 5 seconds to
1426 	 * handle a SIGTERM and clean up properly.
1427 	 */
1428 	if (cmd != A_DUMP) {
1429 		(void) kill(-1, SIGTERM);
1430 		(void) sleep(5);
1431 	}
1432 
1433 	if (!qflag && !nosync) {
1434 		struct utmpx wtmpx;
1435 
1436 		bzero(&wtmpx, sizeof (struct utmpx));
1437 		(void) strcpy(wtmpx.ut_line, "~");
1438 		(void) time(&wtmpx.ut_tv.tv_sec);
1439 
1440 		if (cmd == A_DUMP)
1441 			(void) strcpy(wtmpx.ut_name, "crash dump");
1442 		else
1443 			(void) strcpy(wtmpx.ut_name, "shutdown");
1444 
1445 		(void) updwtmpx(WTMPX_FILE, &wtmpx);
1446 		sync();
1447 	}
1448 
1449 	if (cmd == A_DUMP && nosync != 0)
1450 		(void) uadmin(A_DUMP, AD_NOSYNC, NULL);
1451 
1452 	if (fast_reboot) {
1453 		if (failsafe)
1454 			(void) fprintf(stderr, "Fast reboot - failsafe.\n");
1455 		else
1456 			(void) fprintf(stderr, "Fast reboot.\n");
1457 
1458 		fcn = AD_FASTREBOOT;
1459 	}
1460 
1461 	if (uadmin(cmd, fcn, mdep) == -1)
1462 		(void) fprintf(stderr, "%s: uadmin failed: %s\n",
1463 		    cmdname, strerror(errno));
1464 	else
1465 		(void) fprintf(stderr, "%s: uadmin unexpectedly returned 0\n",
1466 		    cmdname);
1467 
1468 	do {
1469 		r = remove(resetting);
1470 	} while (r != 0 && errno == EINTR);
1471 
1472 	if (r != 0 && errno != ENOENT)
1473 		(void) fprintf(stderr, gettext("%s: could not remove %s.\n"),
1474 		    cmdname, resetting);
1475 
1476 	if (direct_init(PCRUN) == -1) {
1477 		/*
1478 		 * TRANSLATION_NOTE
1479 		 * Don't translate the word "init"
1480 		 */
1481 		(void) fprintf(stderr,
1482 		    gettext("%s: can't resume init\n"), cmdname);
1483 	}
1484 
1485 	continue_restarters();
1486 
1487 	if (get_initpid() != -1)
1488 		/* tell init to restate current level */
1489 		(void) kill(get_initpid(), SIGHUP);
1490 
1491 fail:
1492 	if (fcn == AD_BOOT)
1493 		(void) audit_reboot_fail();
1494 	else
1495 		(void) audit_halt_fail();
1496 
1497 	if (fast_reboot) {
1498 		if (bename) {
1499 			(void) halt_exec(LUUMOUNT_PROG, "-n", bename, NULL);
1500 
1501 		} else if (strlen(fastboot_mounted) != 0) {
1502 			(void) umount(fastboot_mounted);
1503 		}
1504 	}
1505 
1506 	return (1);
1507 }
1508