xref: /illumos-gate/usr/src/cmd/zonecfg/zonecfg.c (revision 9acbbeaf)
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
5fb03efaaSdp  * Common Development and Distribution License (the "License").
6fb03efaaSdp  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217e362f58Scomay 
227c478bd9Sstevel@tonic-gate /*
23fb03efaaSdp  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * zonecfg is a lex/yacc based command interpreter used to manage zone
317c478bd9Sstevel@tonic-gate  * configurations.  The lexer (see zonecfg_lex.l) builds up tokens, which
327c478bd9Sstevel@tonic-gate  * the grammar (see zonecfg_grammar.y) builds up into commands, some of
337c478bd9Sstevel@tonic-gate  * which takes resources and/or properties as arguments.  See the block
347c478bd9Sstevel@tonic-gate  * comments near the end of zonecfg_grammar.y for how the data structures
357c478bd9Sstevel@tonic-gate  * which keep track of these resources and properties are built up.
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  * The resource/property data structures are inserted into a command
387c478bd9Sstevel@tonic-gate  * structure (see zonecfg.h), which also keeps track of command names,
397c478bd9Sstevel@tonic-gate  * miscellaneous arguments, and function handlers.  The grammar selects
407c478bd9Sstevel@tonic-gate  * the appropriate function handler, each of which takes a pointer to a
417c478bd9Sstevel@tonic-gate  * command structure as its sole argument, and invokes it.  The grammar
427c478bd9Sstevel@tonic-gate  * itself is "entered" (a la the Matrix) by yyparse(), which is called
437c478bd9Sstevel@tonic-gate  * from read_input(), our main driving function.  That in turn is called
447c478bd9Sstevel@tonic-gate  * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
457c478bd9Sstevel@tonic-gate  * of which is called from main() depending on how the program was invoked.
467c478bd9Sstevel@tonic-gate  *
477c478bd9Sstevel@tonic-gate  * The rest of this module consists of the various function handlers and
487c478bd9Sstevel@tonic-gate  * their helper functions.  Some of these functions, particularly the
497c478bd9Sstevel@tonic-gate  * X_to_str() functions, which maps command, resource and property numbers
507c478bd9Sstevel@tonic-gate  * to strings, are used quite liberally, as doing so results in a better
517c478bd9Sstevel@tonic-gate  * program w/rt I18N, reducing the need for translation notes.
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
557c478bd9Sstevel@tonic-gate #include <sys/varargs.h>
567c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #include <errno.h>
59*9acbbeafSnn #include <fcntl.h>
607c478bd9Sstevel@tonic-gate #include <strings.h>
617c478bd9Sstevel@tonic-gate #include <unistd.h>
627c478bd9Sstevel@tonic-gate #include <ctype.h>
637c478bd9Sstevel@tonic-gate #include <stdlib.h>
647c478bd9Sstevel@tonic-gate #include <assert.h>
657c478bd9Sstevel@tonic-gate #include <sys/stat.h>
667c478bd9Sstevel@tonic-gate #include <zone.h>
677c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
687c478bd9Sstevel@tonic-gate #include <netdb.h>
697c478bd9Sstevel@tonic-gate #include <locale.h>
707c478bd9Sstevel@tonic-gate #include <libintl.h>
717c478bd9Sstevel@tonic-gate #include <alloca.h>
727c478bd9Sstevel@tonic-gate #include <signal.h>
73*9acbbeafSnn #include <wait.h>
747c478bd9Sstevel@tonic-gate #include <libtecla.h>
75fa9e4066Sahrens #include <libzfs.h>
76*9acbbeafSnn #include <sys/brand.h>
77*9acbbeafSnn #include <libbrand.h>
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #include <libzonecfg.h>
807c478bd9Sstevel@tonic-gate #include "zonecfg.h"
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* should be defined by cc -D */
837c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it wasn't */
847c478bd9Sstevel@tonic-gate #endif
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate #define	PAGER	"/usr/bin/more"
87*9acbbeafSnn #define	EXEC_PREFIX	"exec "
88*9acbbeafSnn #define	EXEC_LEN	(strlen(EXEC_PREFIX))
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate struct help {
917c478bd9Sstevel@tonic-gate 	uint_t	cmd_num;
927c478bd9Sstevel@tonic-gate 	char	*cmd_name;
937c478bd9Sstevel@tonic-gate 	uint_t	flags;
947c478bd9Sstevel@tonic-gate 	char	*short_usage;
957c478bd9Sstevel@tonic-gate };
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate extern int yyparse(void);
987c478bd9Sstevel@tonic-gate extern int lex_lineno;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate #define	MAX_LINE_LEN	1024
1017c478bd9Sstevel@tonic-gate #define	MAX_CMD_HIST	1024
102*9acbbeafSnn #define	MAX_CMD_LEN	1024
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate /*
1057c478bd9Sstevel@tonic-gate  * Each SHELP_ should be a simple string.
1067c478bd9Sstevel@tonic-gate  */
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate #define	SHELP_ADD	"add <resource-type>\n\t(global scope)\n" \
1097c478bd9Sstevel@tonic-gate 	"add <property-name> <property-value>\n\t(resource scope)"
1107c478bd9Sstevel@tonic-gate #define	SHELP_CANCEL	"cancel"
1117c478bd9Sstevel@tonic-gate #define	SHELP_COMMIT	"commit"
112ee519a1fSgjelinek #define	SHELP_CREATE	"create [-F] [ -a <path> | -b | -t <template> ]"
1137c478bd9Sstevel@tonic-gate #define	SHELP_DELETE	"delete [-F]"
1147c478bd9Sstevel@tonic-gate #define	SHELP_END	"end"
1157c478bd9Sstevel@tonic-gate #define	SHELP_EXIT	"exit [-F]"
1167c478bd9Sstevel@tonic-gate #define	SHELP_EXPORT	"export [-f output-file]"
1177c478bd9Sstevel@tonic-gate #define	SHELP_HELP	"help [commands] [syntax] [usage] [<command-name>]"
1187c478bd9Sstevel@tonic-gate #define	SHELP_INFO	"info [<resource-type> [property-name=property-value]*]"
1197c478bd9Sstevel@tonic-gate #define	SHELP_REMOVE	"remove <resource-type> { <property-name>=<property-" \
120ffbafc53Scomay 	"value> }\n\t(global scope)\nremove <property-name> <property-value>" \
1217c478bd9Sstevel@tonic-gate 	"\n\t(resource scope)"
1227c478bd9Sstevel@tonic-gate #define	SHELP_REVERT	"revert [-F]"
1237c478bd9Sstevel@tonic-gate #define	SHELP_SELECT	"select <resource-type> { <property-name>=" \
1247c478bd9Sstevel@tonic-gate 	"<property-value> }"
1257c478bd9Sstevel@tonic-gate #define	SHELP_SET	"set <property-name>=<property-value>"
1267c478bd9Sstevel@tonic-gate #define	SHELP_VERIFY	"verify"
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate static struct help helptab[] = {
1297c478bd9Sstevel@tonic-gate 	{ CMD_ADD,	"add",		HELP_RES_PROPS,	SHELP_ADD, },
1307c478bd9Sstevel@tonic-gate 	{ CMD_CANCEL,	"cancel",	0,		SHELP_CANCEL, },
1317c478bd9Sstevel@tonic-gate 	{ CMD_COMMIT,	"commit",	0,		SHELP_COMMIT, },
1327c478bd9Sstevel@tonic-gate 	{ CMD_CREATE,	"create",	0,		SHELP_CREATE, },
1337c478bd9Sstevel@tonic-gate 	{ CMD_DELETE,	"delete",	0,		SHELP_DELETE, },
1347c478bd9Sstevel@tonic-gate 	{ CMD_END,	"end",		0,		SHELP_END, },
1357c478bd9Sstevel@tonic-gate 	{ CMD_EXIT,	"exit",		0,		SHELP_EXIT, },
1367c478bd9Sstevel@tonic-gate 	{ CMD_EXPORT,	"export",	0,		SHELP_EXPORT, },
1377c478bd9Sstevel@tonic-gate 	{ CMD_HELP,	"help",		0,		SHELP_HELP },
1387c478bd9Sstevel@tonic-gate 	{ CMD_INFO,	"info",		HELP_RES_PROPS,	SHELP_INFO, },
1397c478bd9Sstevel@tonic-gate 	{ CMD_REMOVE,	"remove",	HELP_RES_PROPS,	SHELP_REMOVE, },
1407c478bd9Sstevel@tonic-gate 	{ CMD_REVERT,	"revert",	0,		SHELP_REVERT, },
1417c478bd9Sstevel@tonic-gate 	{ CMD_SELECT,	"select",	HELP_RES_PROPS,	SHELP_SELECT, },
1427c478bd9Sstevel@tonic-gate 	{ CMD_SET,	"set",		HELP_PROPS,	SHELP_SET, },
1437c478bd9Sstevel@tonic-gate 	{ CMD_VERIFY,	"verify",	0,		SHELP_VERIFY, },
1447c478bd9Sstevel@tonic-gate 	{ 0 },
1457c478bd9Sstevel@tonic-gate };
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate #define	MAX_RT_STRLEN	16
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate /* These *must* match the order of the RT_ define's from zonecfg.h */
1507c478bd9Sstevel@tonic-gate static char *res_types[] = {
1517c478bd9Sstevel@tonic-gate 	"unknown",
152087719fdSdp 	"zonename",
1537c478bd9Sstevel@tonic-gate 	"zonepath",
1547c478bd9Sstevel@tonic-gate 	"autoboot",
1557c478bd9Sstevel@tonic-gate 	"pool",
1567c478bd9Sstevel@tonic-gate 	"fs",
1577c478bd9Sstevel@tonic-gate 	"inherit-pkg-dir",
1587c478bd9Sstevel@tonic-gate 	"net",
1597c478bd9Sstevel@tonic-gate 	"device",
1607c478bd9Sstevel@tonic-gate 	"rctl",
1617c478bd9Sstevel@tonic-gate 	"attr",
162fa9e4066Sahrens 	"dataset",
163ffbafc53Scomay 	"limitpriv",
1643f2f09c1Sdp 	"bootargs",
165*9acbbeafSnn 	"brand",
1667c478bd9Sstevel@tonic-gate 	NULL
1677c478bd9Sstevel@tonic-gate };
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate /* These *must* match the order of the PT_ define's from zonecfg.h */
1707c478bd9Sstevel@tonic-gate static char *prop_types[] = {
1717c478bd9Sstevel@tonic-gate 	"unknown",
172087719fdSdp 	"zonename",
1737c478bd9Sstevel@tonic-gate 	"zonepath",
1747c478bd9Sstevel@tonic-gate 	"autoboot",
1757c478bd9Sstevel@tonic-gate 	"pool",
1767c478bd9Sstevel@tonic-gate 	"dir",
1777c478bd9Sstevel@tonic-gate 	"special",
1787c478bd9Sstevel@tonic-gate 	"type",
1797c478bd9Sstevel@tonic-gate 	"options",
1807c478bd9Sstevel@tonic-gate 	"address",
1817c478bd9Sstevel@tonic-gate 	"physical",
1827c478bd9Sstevel@tonic-gate 	"name",
1837c478bd9Sstevel@tonic-gate 	"value",
1847c478bd9Sstevel@tonic-gate 	"match",
1857c478bd9Sstevel@tonic-gate 	"priv",
1867c478bd9Sstevel@tonic-gate 	"limit",
1877c478bd9Sstevel@tonic-gate 	"action",
1887c478bd9Sstevel@tonic-gate 	"raw",
189ffbafc53Scomay 	"limitpriv",
1903f2f09c1Sdp 	"bootargs",
191*9acbbeafSnn 	"brand",
1927c478bd9Sstevel@tonic-gate 	NULL
1937c478bd9Sstevel@tonic-gate };
1947c478bd9Sstevel@tonic-gate 
195ffbafc53Scomay /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
1967c478bd9Sstevel@tonic-gate static char *prop_val_types[] = {
1977c478bd9Sstevel@tonic-gate 	"simple",
1987c478bd9Sstevel@tonic-gate 	"complex",
1997c478bd9Sstevel@tonic-gate 	"list",
2007c478bd9Sstevel@tonic-gate };
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate /*
2037c478bd9Sstevel@tonic-gate  * The various _cmds[] lists below are for command tab-completion.
2047c478bd9Sstevel@tonic-gate  */
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate /*
2077c478bd9Sstevel@tonic-gate  * remove has a space afterwards because it has qualifiers; the other commands
2087c478bd9Sstevel@tonic-gate  * that have qualifiers (add, select and set) don't need a space here because
2097c478bd9Sstevel@tonic-gate  * they have their own _cmds[] lists below.
2107c478bd9Sstevel@tonic-gate  */
2117c478bd9Sstevel@tonic-gate static const char *global_scope_cmds[] = {
2127c478bd9Sstevel@tonic-gate 	"add",
2137c478bd9Sstevel@tonic-gate 	"commit",
2147c478bd9Sstevel@tonic-gate 	"create",
2157c478bd9Sstevel@tonic-gate 	"delete",
2167c478bd9Sstevel@tonic-gate 	"exit",
2177c478bd9Sstevel@tonic-gate 	"export",
2187c478bd9Sstevel@tonic-gate 	"help",
2197c478bd9Sstevel@tonic-gate 	"info",
2207c478bd9Sstevel@tonic-gate 	"remove ",
2217c478bd9Sstevel@tonic-gate 	"revert",
2227c478bd9Sstevel@tonic-gate 	"select",
2237c478bd9Sstevel@tonic-gate 	"set",
2247c478bd9Sstevel@tonic-gate 	"verify",
2257c478bd9Sstevel@tonic-gate 	NULL
2267c478bd9Sstevel@tonic-gate };
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate static const char *add_cmds[] = {
2297c478bd9Sstevel@tonic-gate 	"add fs",
2307c478bd9Sstevel@tonic-gate 	"add inherit-pkg-dir",
2317c478bd9Sstevel@tonic-gate 	"add net",
2327c478bd9Sstevel@tonic-gate 	"add device",
2337c478bd9Sstevel@tonic-gate 	"add rctl",
2347c478bd9Sstevel@tonic-gate 	"add attr",
235fa9e4066Sahrens 	"add dataset",
2367c478bd9Sstevel@tonic-gate 	NULL
2377c478bd9Sstevel@tonic-gate };
2387c478bd9Sstevel@tonic-gate 
2399e7542f4Sdp static const char *remove_cmds[] = {
2409e7542f4Sdp 	"remove fs ",
2419e7542f4Sdp 	"remove inherit-pkg-dir ",
2429e7542f4Sdp 	"remove net ",
2439e7542f4Sdp 	"remove device ",
2449e7542f4Sdp 	"remove rctl ",
2459e7542f4Sdp 	"remove attr ",
2469e7542f4Sdp 	"remove dataset ",
2479e7542f4Sdp 	NULL
2489e7542f4Sdp };
2499e7542f4Sdp 
2507c478bd9Sstevel@tonic-gate static const char *select_cmds[] = {
251087719fdSdp 	"select fs ",
252087719fdSdp 	"select inherit-pkg-dir ",
253087719fdSdp 	"select net ",
254087719fdSdp 	"select device ",
255087719fdSdp 	"select rctl ",
256087719fdSdp 	"select attr ",
257fa9e4066Sahrens 	"select dataset ",
2587c478bd9Sstevel@tonic-gate 	NULL
2597c478bd9Sstevel@tonic-gate };
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate static const char *set_cmds[] = {
262087719fdSdp 	"set zonename=",
263087719fdSdp 	"set zonepath=",
264*9acbbeafSnn 	"set brand=",
265087719fdSdp 	"set autoboot=",
266087719fdSdp 	"set pool=",
267ffbafc53Scomay 	"set limitpriv=",
2683f2f09c1Sdp 	"set bootargs=",
2697c478bd9Sstevel@tonic-gate 	NULL
2707c478bd9Sstevel@tonic-gate };
2717c478bd9Sstevel@tonic-gate 
2729e7542f4Sdp static const char *info_cmds[] = {
2739e7542f4Sdp 	"info fs ",
2749e7542f4Sdp 	"info inherit-pkg-dir ",
2759e7542f4Sdp 	"info net ",
2769e7542f4Sdp 	"info device ",
2779e7542f4Sdp 	"info rctl ",
2789e7542f4Sdp 	"info attr ",
2799e7542f4Sdp 	"info dataset ",
2809e7542f4Sdp 	"info zonename",
2819e7542f4Sdp 	"info zonepath",
2829e7542f4Sdp 	"info autoboot",
2839e7542f4Sdp 	"info pool",
2849e7542f4Sdp 	"info limitpriv",
2859e7542f4Sdp 	"info bootargs",
2869e7542f4Sdp 	NULL
2879e7542f4Sdp };
2889e7542f4Sdp 
2897c478bd9Sstevel@tonic-gate static const char *fs_res_scope_cmds[] = {
2907c478bd9Sstevel@tonic-gate 	"add options ",
2917c478bd9Sstevel@tonic-gate 	"cancel",
2927c478bd9Sstevel@tonic-gate 	"end",
2937c478bd9Sstevel@tonic-gate 	"exit",
2947c478bd9Sstevel@tonic-gate 	"help",
2957c478bd9Sstevel@tonic-gate 	"info",
296ffbafc53Scomay 	"remove options ",
2977c478bd9Sstevel@tonic-gate 	"set dir=",
2987c478bd9Sstevel@tonic-gate 	"set raw=",
2997c478bd9Sstevel@tonic-gate 	"set special=",
3007c478bd9Sstevel@tonic-gate 	"set type=",
3017c478bd9Sstevel@tonic-gate 	NULL
3027c478bd9Sstevel@tonic-gate };
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate static const char *net_res_scope_cmds[] = {
3057c478bd9Sstevel@tonic-gate 	"cancel",
3067c478bd9Sstevel@tonic-gate 	"end",
3077c478bd9Sstevel@tonic-gate 	"exit",
3087c478bd9Sstevel@tonic-gate 	"help",
3097c478bd9Sstevel@tonic-gate 	"info",
3107c478bd9Sstevel@tonic-gate 	"set address=",
3117c478bd9Sstevel@tonic-gate 	"set physical=",
3127c478bd9Sstevel@tonic-gate 	NULL
3137c478bd9Sstevel@tonic-gate };
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate static const char *ipd_res_scope_cmds[] = {
3167c478bd9Sstevel@tonic-gate 	"cancel",
3177c478bd9Sstevel@tonic-gate 	"end",
3187c478bd9Sstevel@tonic-gate 	"exit",
3197c478bd9Sstevel@tonic-gate 	"help",
3207c478bd9Sstevel@tonic-gate 	"info",
3217c478bd9Sstevel@tonic-gate 	"set dir=",
3227c478bd9Sstevel@tonic-gate 	NULL
3237c478bd9Sstevel@tonic-gate };
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate static const char *device_res_scope_cmds[] = {
3267c478bd9Sstevel@tonic-gate 	"cancel",
3277c478bd9Sstevel@tonic-gate 	"end",
3287c478bd9Sstevel@tonic-gate 	"exit",
3297c478bd9Sstevel@tonic-gate 	"help",
3307c478bd9Sstevel@tonic-gate 	"info",
3317c478bd9Sstevel@tonic-gate 	"set match=",
3327c478bd9Sstevel@tonic-gate 	NULL
3337c478bd9Sstevel@tonic-gate };
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate static const char *attr_res_scope_cmds[] = {
3367c478bd9Sstevel@tonic-gate 	"cancel",
3377c478bd9Sstevel@tonic-gate 	"end",
3387c478bd9Sstevel@tonic-gate 	"exit",
3397c478bd9Sstevel@tonic-gate 	"help",
3407c478bd9Sstevel@tonic-gate 	"info",
3417c478bd9Sstevel@tonic-gate 	"set name=",
3427c478bd9Sstevel@tonic-gate 	"set type=",
3437c478bd9Sstevel@tonic-gate 	"set value=",
3447c478bd9Sstevel@tonic-gate 	NULL
3457c478bd9Sstevel@tonic-gate };
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate static const char *rctl_res_scope_cmds[] = {
3487c478bd9Sstevel@tonic-gate 	"add value ",
3497c478bd9Sstevel@tonic-gate 	"cancel",
3507c478bd9Sstevel@tonic-gate 	"end",
3517c478bd9Sstevel@tonic-gate 	"exit",
3527c478bd9Sstevel@tonic-gate 	"help",
3537c478bd9Sstevel@tonic-gate 	"info",
354ffbafc53Scomay 	"remove value ",
3557c478bd9Sstevel@tonic-gate 	"set name=",
3567c478bd9Sstevel@tonic-gate 	NULL
3577c478bd9Sstevel@tonic-gate };
3587c478bd9Sstevel@tonic-gate 
359fa9e4066Sahrens static const char *dataset_res_scope_cmds[] = {
360fa9e4066Sahrens 	"cancel",
361fa9e4066Sahrens 	"end",
362fa9e4066Sahrens 	"exit",
363fa9e4066Sahrens 	"help",
364fa9e4066Sahrens 	"info",
365fa9e4066Sahrens 	"set name=",
366fa9e4066Sahrens 	NULL
367fa9e4066Sahrens };
368fa9e4066Sahrens 
3697c478bd9Sstevel@tonic-gate /* Global variables */
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate /* set early in main(), never modified thereafter, used all over the place */
3727c478bd9Sstevel@tonic-gate static char *execname;
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate /* set in main(), used all over the place */
3757c478bd9Sstevel@tonic-gate static zone_dochandle_t handle;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate /* used all over the place */
378087719fdSdp static char zone[ZONENAME_MAX];
379087719fdSdp static char revert_zone[ZONENAME_MAX];
3807c478bd9Sstevel@tonic-gate 
381*9acbbeafSnn /* global brand operations */
382*9acbbeafSnn static brand_handle_t *brand;
383*9acbbeafSnn 
3847c478bd9Sstevel@tonic-gate /* set in modifying functions, checked in read_input() */
3857c478bd9Sstevel@tonic-gate static bool need_to_commit = FALSE;
3867c478bd9Sstevel@tonic-gate bool saw_error;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate /* set in yacc parser, checked in read_input() */
3897c478bd9Sstevel@tonic-gate bool newline_terminated;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate /* set in main(), checked in lex error handler */
3927c478bd9Sstevel@tonic-gate bool cmd_file_mode;
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate /* set in exit_func(), checked in read_input() */
3957c478bd9Sstevel@tonic-gate static bool time_to_exit = FALSE, force_exit = FALSE;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate /* used in short_usage() and zerr() */
3987c478bd9Sstevel@tonic-gate static char *cmd_file_name = NULL;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate /* checked in read_input() and other places */
4017c478bd9Sstevel@tonic-gate static bool ok_to_prompt = FALSE;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate /* set and checked in initialize() */
4047c478bd9Sstevel@tonic-gate static bool got_handle = FALSE;
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate /* initialized in do_interactive(), checked in initialize() */
4077c478bd9Sstevel@tonic-gate static bool interactive_mode;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate /* set in main(), checked in multiple places */
4107c478bd9Sstevel@tonic-gate static bool read_only_mode;
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate static bool global_scope = TRUE; /* scope is outer/global or inner/resource */
4137c478bd9Sstevel@tonic-gate static int resource_scope;	/* should be in the RT_ list from zonecfg.h */
4147c478bd9Sstevel@tonic-gate static int end_op = -1;		/* operation on end is either add or modify */
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate int num_prop_vals;		/* for grammar */
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate /*
4197c478bd9Sstevel@tonic-gate  * These are for keeping track of resources as they are specified as part of
4207c478bd9Sstevel@tonic-gate  * the multi-step process.  They should be initialized by add_resource() or
4217c478bd9Sstevel@tonic-gate  * select_func() and filled in by add_property() or set_func().
4227c478bd9Sstevel@tonic-gate  */
4237c478bd9Sstevel@tonic-gate static struct zone_fstab	old_fstab, in_progress_fstab;
4247c478bd9Sstevel@tonic-gate static struct zone_fstab	old_ipdtab, in_progress_ipdtab;
4257c478bd9Sstevel@tonic-gate static struct zone_nwiftab	old_nwiftab, in_progress_nwiftab;
4267c478bd9Sstevel@tonic-gate static struct zone_devtab	old_devtab, in_progress_devtab;
4277c478bd9Sstevel@tonic-gate static struct zone_rctltab	old_rctltab, in_progress_rctltab;
4287c478bd9Sstevel@tonic-gate static struct zone_attrtab	old_attrtab, in_progress_attrtab;
429fa9e4066Sahrens static struct zone_dstab	old_dstab, in_progress_dstab;
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate static GetLine *gl;	/* The gl_get_line() resource object */
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate /* Functions begin here */
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate static bool
4367c478bd9Sstevel@tonic-gate initial_match(const char *line1, const char *line2, int word_end)
4377c478bd9Sstevel@tonic-gate {
4387c478bd9Sstevel@tonic-gate 	if (word_end <= 0)
4397c478bd9Sstevel@tonic-gate 		return (TRUE);
4407c478bd9Sstevel@tonic-gate 	return (strncmp(line1, line2, word_end) == 0);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate static int
4447c478bd9Sstevel@tonic-gate add_stuff(WordCompletion *cpl, const char *line1, const char **list,
4457c478bd9Sstevel@tonic-gate     int word_end)
4467c478bd9Sstevel@tonic-gate {
4477c478bd9Sstevel@tonic-gate 	int i, err;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	for (i = 0; list[i] != NULL; i++) {
4507c478bd9Sstevel@tonic-gate 		if (initial_match(line1, list[i], word_end)) {
4517c478bd9Sstevel@tonic-gate 			err = cpl_add_completion(cpl, line1, 0, word_end,
4527c478bd9Sstevel@tonic-gate 			    list[i] + word_end, "", "");
4537c478bd9Sstevel@tonic-gate 			if (err != 0)
4547c478bd9Sstevel@tonic-gate 				return (err);
4557c478bd9Sstevel@tonic-gate 		}
4567c478bd9Sstevel@tonic-gate 	}
4577c478bd9Sstevel@tonic-gate 	return (0);
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate static
4617c478bd9Sstevel@tonic-gate /* ARGSUSED */
4627c478bd9Sstevel@tonic-gate CPL_MATCH_FN(cmd_cpl_fn)
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate 	if (global_scope) {
4657c478bd9Sstevel@tonic-gate 		/*
4667c478bd9Sstevel@tonic-gate 		 * The MAX/MIN tests below are to make sure we have at least
4677c478bd9Sstevel@tonic-gate 		 * enough characters to distinguish from other prefixes (MAX)
4687c478bd9Sstevel@tonic-gate 		 * but only check MIN(what we have, what we're checking).
4697c478bd9Sstevel@tonic-gate 		 */
4707c478bd9Sstevel@tonic-gate 		if (strncmp(line, "add ", MAX(MIN(word_end, 4), 1)) == 0)
4717c478bd9Sstevel@tonic-gate 			return (add_stuff(cpl, line, add_cmds, word_end));
4727c478bd9Sstevel@tonic-gate 		if (strncmp(line, "select ", MAX(MIN(word_end, 7), 3)) == 0)
4737c478bd9Sstevel@tonic-gate 			return (add_stuff(cpl, line, select_cmds, word_end));
4747c478bd9Sstevel@tonic-gate 		if (strncmp(line, "set ", MAX(MIN(word_end, 4), 3)) == 0)
4757c478bd9Sstevel@tonic-gate 			return (add_stuff(cpl, line, set_cmds, word_end));
4769e7542f4Sdp 		if (strncmp(line, "remove ", MAX(MIN(word_end, 7), 1)) == 0)
4779e7542f4Sdp 			return (add_stuff(cpl, line, remove_cmds, word_end));
4789e7542f4Sdp 		if (strncmp(line, "info ", MAX(MIN(word_end, 5), 1)) == 0)
4799e7542f4Sdp 			return (add_stuff(cpl, line, info_cmds, word_end));
4807c478bd9Sstevel@tonic-gate 		return (add_stuff(cpl, line, global_scope_cmds, word_end));
4817c478bd9Sstevel@tonic-gate 	}
4827c478bd9Sstevel@tonic-gate 	switch (resource_scope) {
4837c478bd9Sstevel@tonic-gate 	case RT_FS:
4847c478bd9Sstevel@tonic-gate 		return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
4857c478bd9Sstevel@tonic-gate 	case RT_IPD:
4867c478bd9Sstevel@tonic-gate 		return (add_stuff(cpl, line, ipd_res_scope_cmds, word_end));
4877c478bd9Sstevel@tonic-gate 	case RT_NET:
4887c478bd9Sstevel@tonic-gate 		return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
4897c478bd9Sstevel@tonic-gate 	case RT_DEVICE:
4907c478bd9Sstevel@tonic-gate 		return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
4917c478bd9Sstevel@tonic-gate 	case RT_RCTL:
4927c478bd9Sstevel@tonic-gate 		return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
4937c478bd9Sstevel@tonic-gate 	case RT_ATTR:
4947c478bd9Sstevel@tonic-gate 		return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
495fa9e4066Sahrens 	case RT_DATASET:
496fa9e4066Sahrens 		return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
4977c478bd9Sstevel@tonic-gate 	}
4987c478bd9Sstevel@tonic-gate 	return (0);
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate /*
5027c478bd9Sstevel@tonic-gate  * For the main CMD_func() functions below, several of them call getopt()
5037c478bd9Sstevel@tonic-gate  * then check optind against argc to make sure an extra parameter was not
5047c478bd9Sstevel@tonic-gate  * passed in.  The reason this is not caught in the grammar is that the
5057c478bd9Sstevel@tonic-gate  * grammar just checks for a miscellaneous TOKEN, which is *expected* to
5067c478bd9Sstevel@tonic-gate  * be "-F" (for example), but could be anything.  So (for example) this
5077c478bd9Sstevel@tonic-gate  * check will prevent "create bogus".
5087c478bd9Sstevel@tonic-gate  */
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate cmd_t *
5117c478bd9Sstevel@tonic-gate alloc_cmd(void)
5127c478bd9Sstevel@tonic-gate {
5137c478bd9Sstevel@tonic-gate 	return (calloc(1, sizeof (cmd_t)));
5147c478bd9Sstevel@tonic-gate }
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate void
5177c478bd9Sstevel@tonic-gate free_cmd(cmd_t *cmd)
5187c478bd9Sstevel@tonic-gate {
5197c478bd9Sstevel@tonic-gate 	int i;
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAX_EQ_PROP_PAIRS; i++)
5227c478bd9Sstevel@tonic-gate 		if (cmd->cmd_property_ptr[i] != NULL) {
5237c478bd9Sstevel@tonic-gate 			property_value_ptr_t pp = cmd->cmd_property_ptr[i];
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 			switch (pp->pv_type) {
5267c478bd9Sstevel@tonic-gate 			case PROP_VAL_SIMPLE:
5277c478bd9Sstevel@tonic-gate 				free(pp->pv_simple);
5287c478bd9Sstevel@tonic-gate 				break;
5297c478bd9Sstevel@tonic-gate 			case PROP_VAL_COMPLEX:
5307c478bd9Sstevel@tonic-gate 				free_complex(pp->pv_complex);
5317c478bd9Sstevel@tonic-gate 				break;
5327c478bd9Sstevel@tonic-gate 			case PROP_VAL_LIST:
5337c478bd9Sstevel@tonic-gate 				free_list(pp->pv_list);
5347c478bd9Sstevel@tonic-gate 				break;
5357c478bd9Sstevel@tonic-gate 			}
5367c478bd9Sstevel@tonic-gate 		}
5377c478bd9Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_argc; i++)
5387c478bd9Sstevel@tonic-gate 		free(cmd->cmd_argv[i]);
5397c478bd9Sstevel@tonic-gate 	free(cmd);
5407c478bd9Sstevel@tonic-gate }
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate complex_property_ptr_t
5437c478bd9Sstevel@tonic-gate alloc_complex(void)
5447c478bd9Sstevel@tonic-gate {
5457c478bd9Sstevel@tonic-gate 	return (calloc(1, sizeof (complex_property_t)));
5467c478bd9Sstevel@tonic-gate }
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate void
5497c478bd9Sstevel@tonic-gate free_complex(complex_property_ptr_t complex)
5507c478bd9Sstevel@tonic-gate {
5517c478bd9Sstevel@tonic-gate 	if (complex == NULL)
5527c478bd9Sstevel@tonic-gate 		return;
5537c478bd9Sstevel@tonic-gate 	free_complex(complex->cp_next);
5547c478bd9Sstevel@tonic-gate 	if (complex->cp_value != NULL)
5557c478bd9Sstevel@tonic-gate 		free(complex->cp_value);
5567c478bd9Sstevel@tonic-gate 	free(complex);
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate list_property_ptr_t
5607c478bd9Sstevel@tonic-gate alloc_list(void)
5617c478bd9Sstevel@tonic-gate {
5627c478bd9Sstevel@tonic-gate 	return (calloc(1, sizeof (list_property_t)));
5637c478bd9Sstevel@tonic-gate }
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate void
5667c478bd9Sstevel@tonic-gate free_list(list_property_ptr_t list)
5677c478bd9Sstevel@tonic-gate {
5687c478bd9Sstevel@tonic-gate 	if (list == NULL)
5697c478bd9Sstevel@tonic-gate 		return;
5707c478bd9Sstevel@tonic-gate 	if (list->lp_simple != NULL)
5717c478bd9Sstevel@tonic-gate 		free(list->lp_simple);
5727c478bd9Sstevel@tonic-gate 	free_complex(list->lp_complex);
5737c478bd9Sstevel@tonic-gate 	free_list(list->lp_next);
5747c478bd9Sstevel@tonic-gate 	free(list);
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate void
5787c478bd9Sstevel@tonic-gate free_outer_list(list_property_ptr_t list)
5797c478bd9Sstevel@tonic-gate {
5807c478bd9Sstevel@tonic-gate 	if (list == NULL)
5817c478bd9Sstevel@tonic-gate 		return;
5827c478bd9Sstevel@tonic-gate 	free_outer_list(list->lp_next);
5837c478bd9Sstevel@tonic-gate 	free(list);
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate static struct zone_rctlvaltab *
5877c478bd9Sstevel@tonic-gate alloc_rctlvaltab(void)
5887c478bd9Sstevel@tonic-gate {
5897c478bd9Sstevel@tonic-gate 	return (calloc(1, sizeof (struct zone_rctlvaltab)));
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate static char *
5937c478bd9Sstevel@tonic-gate rt_to_str(int res_type)
5947c478bd9Sstevel@tonic-gate {
5957c478bd9Sstevel@tonic-gate 	assert(res_type >= RT_MIN && res_type <= RT_MAX);
5967c478bd9Sstevel@tonic-gate 	return (res_types[res_type]);
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate static char *
6007c478bd9Sstevel@tonic-gate pt_to_str(int prop_type)
6017c478bd9Sstevel@tonic-gate {
6027c478bd9Sstevel@tonic-gate 	assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
6037c478bd9Sstevel@tonic-gate 	return (prop_types[prop_type]);
6047c478bd9Sstevel@tonic-gate }
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate static char *
6077c478bd9Sstevel@tonic-gate pvt_to_str(int pv_type)
6087c478bd9Sstevel@tonic-gate {
6097c478bd9Sstevel@tonic-gate 	assert(pv_type >= PROP_VAL_MIN && pv_type <= PROP_VAL_MAX);
6107c478bd9Sstevel@tonic-gate 	return (prop_val_types[pv_type]);
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate static char *
6147c478bd9Sstevel@tonic-gate cmd_to_str(int cmd_num)
6157c478bd9Sstevel@tonic-gate {
6167c478bd9Sstevel@tonic-gate 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
6177c478bd9Sstevel@tonic-gate 	return (helptab[cmd_num].cmd_name);
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate /*
6217c478bd9Sstevel@tonic-gate  * This is a separate function rather than a set of define's because of the
6227c478bd9Sstevel@tonic-gate  * gettext() wrapping.
6237c478bd9Sstevel@tonic-gate  */
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate /*
6267c478bd9Sstevel@tonic-gate  * TRANSLATION_NOTE
6277c478bd9Sstevel@tonic-gate  * Each string below should have \t follow \n whenever needed; the
6287c478bd9Sstevel@tonic-gate  * initial \t and the terminal \n will be provided by the calling function.
6297c478bd9Sstevel@tonic-gate  */
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate static char *
6327c478bd9Sstevel@tonic-gate long_help(int cmd_num)
6337c478bd9Sstevel@tonic-gate {
6347c478bd9Sstevel@tonic-gate 	static char line[1024];	/* arbitrary large amount */
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
6377c478bd9Sstevel@tonic-gate 	switch (cmd_num) {
6387c478bd9Sstevel@tonic-gate 		case CMD_HELP:
6397c478bd9Sstevel@tonic-gate 			return (gettext("Prints help message."));
6407c478bd9Sstevel@tonic-gate 		case CMD_CREATE:
6417c478bd9Sstevel@tonic-gate 			(void) snprintf(line, sizeof (line),
6427c478bd9Sstevel@tonic-gate 			    gettext("Creates a configuration for the "
6437c478bd9Sstevel@tonic-gate 			    "specified zone.  %s should be\n\tused to "
6447c478bd9Sstevel@tonic-gate 			    "begin configuring a new zone.  If overwriting an "
6457c478bd9Sstevel@tonic-gate 			    "existing\n\tconfiguration, the -F flag can be "
6467c478bd9Sstevel@tonic-gate 			    "used to force the action.  If\n\t-t template is "
6477c478bd9Sstevel@tonic-gate 			    "given, creates a configuration identical to the\n"
6487c478bd9Sstevel@tonic-gate 			    "\tspecified template, except that the zone name "
6499e518655Sgjelinek 			    "is changed from\n\ttemplate to zonename.  '%s -a' "
6509e518655Sgjelinek 			    "creates a configuration from a\n\tdetached "
6519e518655Sgjelinek 			    "zonepath.  '%s -b' results in a blank "
6529e518655Sgjelinek 			    "configuration.\n\t'%s' with no arguments applies "
6539e518655Sgjelinek 			    "the Sun default settings."),
6547c478bd9Sstevel@tonic-gate 			    cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE),
6559e518655Sgjelinek 			    cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE));
6567c478bd9Sstevel@tonic-gate 			return (line);
6577c478bd9Sstevel@tonic-gate 		case CMD_EXIT:
6587c478bd9Sstevel@tonic-gate 			return (gettext("Exits the program.  The -F flag can "
6597c478bd9Sstevel@tonic-gate 			    "be used to force the action."));
6607c478bd9Sstevel@tonic-gate 		case CMD_EXPORT:
6617c478bd9Sstevel@tonic-gate 			return (gettext("Prints configuration to standard "
6627c478bd9Sstevel@tonic-gate 			    "output, or to output-file if\n\tspecified, in "
6637c478bd9Sstevel@tonic-gate 			    "a form suitable for use in a command-file."));
6647c478bd9Sstevel@tonic-gate 		case CMD_ADD:
6657c478bd9Sstevel@tonic-gate 			return (gettext("Add specified resource to "
6667c478bd9Sstevel@tonic-gate 			    "configuration."));
6677c478bd9Sstevel@tonic-gate 		case CMD_DELETE:
6687c478bd9Sstevel@tonic-gate 			return (gettext("Deletes the specified zone.  The -F "
6697c478bd9Sstevel@tonic-gate 			    "flag can be used to force the\n\taction."));
6707c478bd9Sstevel@tonic-gate 		case CMD_REMOVE:
6717c478bd9Sstevel@tonic-gate 			return (gettext("Remove specified resource from "
6727c478bd9Sstevel@tonic-gate 			    "configuration.  Note that the curly\n\tbraces "
6737c478bd9Sstevel@tonic-gate 			    "('{', '}') mean one or more of whatever "
6747c478bd9Sstevel@tonic-gate 			    "is between them."));
6757c478bd9Sstevel@tonic-gate 		case CMD_SELECT:
6767c478bd9Sstevel@tonic-gate 			(void) snprintf(line, sizeof (line),
6777c478bd9Sstevel@tonic-gate 			    gettext("Selects a resource to modify.  "
6787c478bd9Sstevel@tonic-gate 			    "Resource modification is completed\n\twith the "
6797c478bd9Sstevel@tonic-gate 			    "command \"%s\".  The property name/value pairs "
6807c478bd9Sstevel@tonic-gate 			    "must uniquely\n\tidentify a resource.  Note that "
6817c478bd9Sstevel@tonic-gate 			    "the curly braces ('{', '}') mean one\n\tor more "
6827c478bd9Sstevel@tonic-gate 			    "of whatever is between them."),
6837c478bd9Sstevel@tonic-gate 			    cmd_to_str(CMD_END));
6847c478bd9Sstevel@tonic-gate 			return (line);
6857c478bd9Sstevel@tonic-gate 		case CMD_SET:
6867c478bd9Sstevel@tonic-gate 			return (gettext("Sets property values."));
6877c478bd9Sstevel@tonic-gate 		case CMD_INFO:
6887c478bd9Sstevel@tonic-gate 			return (gettext("Displays information about the "
6897c478bd9Sstevel@tonic-gate 			    "current configuration.  If resource\n\ttype is "
6907c478bd9Sstevel@tonic-gate 			    "specified, displays only information about "
6917c478bd9Sstevel@tonic-gate 			    "resources of\n\tthe relevant type.  If resource "
6927c478bd9Sstevel@tonic-gate 			    "id is specified, displays only\n\tinformation "
6937c478bd9Sstevel@tonic-gate 			    "about that resource."));
6947c478bd9Sstevel@tonic-gate 		case CMD_VERIFY:
6957c478bd9Sstevel@tonic-gate 			return (gettext("Verifies current configuration "
6967c478bd9Sstevel@tonic-gate 			    "for correctness (some resource types\n\thave "
6977c478bd9Sstevel@tonic-gate 			    "required properties)."));
6987c478bd9Sstevel@tonic-gate 		case CMD_COMMIT:
6997c478bd9Sstevel@tonic-gate 			(void) snprintf(line, sizeof (line),
7007c478bd9Sstevel@tonic-gate 			    gettext("Commits current configuration.  "
7017c478bd9Sstevel@tonic-gate 			    "Configuration must be committed to\n\tbe used by "
7027c478bd9Sstevel@tonic-gate 			    "%s.  Until the configuration is committed, "
7037c478bd9Sstevel@tonic-gate 			    "changes \n\tcan be removed with the %s "
7047c478bd9Sstevel@tonic-gate 			    "command.  This operation is\n\tattempted "
7057c478bd9Sstevel@tonic-gate 			    "automatically upon completion of a %s "
7067c478bd9Sstevel@tonic-gate 			    "session."), "zoneadm", cmd_to_str(CMD_REVERT),
7077c478bd9Sstevel@tonic-gate 			    "zonecfg");
7087c478bd9Sstevel@tonic-gate 			return (line);
7097c478bd9Sstevel@tonic-gate 		case CMD_REVERT:
7107c478bd9Sstevel@tonic-gate 			return (gettext("Reverts configuration back to the "
7117c478bd9Sstevel@tonic-gate 			    "last committed state.  The -F flag\n\tcan be "
7127c478bd9Sstevel@tonic-gate 			    "used to force the action."));
7137c478bd9Sstevel@tonic-gate 		case CMD_CANCEL:
7147c478bd9Sstevel@tonic-gate 			return (gettext("Cancels resource/property "
7157c478bd9Sstevel@tonic-gate 			    "specification."));
7167c478bd9Sstevel@tonic-gate 		case CMD_END:
7177c478bd9Sstevel@tonic-gate 			return (gettext("Ends resource/property "
7187c478bd9Sstevel@tonic-gate 			    "specification."));
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
7217e362f58Scomay 	return (NULL);
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate /*
7257c478bd9Sstevel@tonic-gate  * Called with verbose TRUE when help is explicitly requested, FALSE for
7267c478bd9Sstevel@tonic-gate  * unexpected errors.
7277c478bd9Sstevel@tonic-gate  */
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate void
7307c478bd9Sstevel@tonic-gate usage(bool verbose, uint_t flags)
7317c478bd9Sstevel@tonic-gate {
7327c478bd9Sstevel@tonic-gate 	FILE *fp = verbose ? stdout : stderr, *newfp;
7337c478bd9Sstevel@tonic-gate 	bool need_to_close = FALSE;
7347c478bd9Sstevel@tonic-gate 	char *pager;
7357c478bd9Sstevel@tonic-gate 	int i;
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 	/* don't page error output */
7387c478bd9Sstevel@tonic-gate 	if (verbose && interactive_mode) {
7397c478bd9Sstevel@tonic-gate 		if ((pager = getenv("PAGER")) == NULL)
7407c478bd9Sstevel@tonic-gate 			pager = PAGER;
7417c478bd9Sstevel@tonic-gate 		if ((newfp = popen(pager, "w")) != NULL) {
7427c478bd9Sstevel@tonic-gate 			need_to_close = TRUE;
7437c478bd9Sstevel@tonic-gate 			fp = newfp;
7447c478bd9Sstevel@tonic-gate 		}
7457c478bd9Sstevel@tonic-gate 	}
7467c478bd9Sstevel@tonic-gate 	if (flags & HELP_META) {
7477c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, gettext("More help is available for the "
7487c478bd9Sstevel@tonic-gate 		    "following:\n"));
7497c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\n\tcommands ('%s commands')\n",
7507c478bd9Sstevel@tonic-gate 		    cmd_to_str(CMD_HELP));
7517c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\tsyntax ('%s syntax')\n",
7527c478bd9Sstevel@tonic-gate 		    cmd_to_str(CMD_HELP));
7537c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\tusage ('%s usage')\n\n",
7547c478bd9Sstevel@tonic-gate 		    cmd_to_str(CMD_HELP));
7557c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, gettext("You may also obtain help on any "
7567c478bd9Sstevel@tonic-gate 		    "command by typing '%s <command-name>.'\n"),
7577c478bd9Sstevel@tonic-gate 		    cmd_to_str(CMD_HELP));
7587c478bd9Sstevel@tonic-gate 	}
7597c478bd9Sstevel@tonic-gate 	if (flags & HELP_RES_SCOPE) {
7607c478bd9Sstevel@tonic-gate 		switch (resource_scope) {
7617c478bd9Sstevel@tonic-gate 		case RT_FS:
7627c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("The '%s' resource scope is "
7637c478bd9Sstevel@tonic-gate 			    "used to configure a file-system.\n"),
7647c478bd9Sstevel@tonic-gate 			    rt_to_str(resource_scope));
7657c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Valid commands:\n"));
7667c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
7677c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_DIR), gettext("<path>"));
7687c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
7697c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_SPECIAL), gettext("<path>"));
7707c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
7717c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_RAW), gettext("<raw-device>"));
7727c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
7737c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_TYPE), gettext("<file-system type>"));
7747c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s %s\n", cmd_to_str(CMD_ADD),
7757c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_OPTIONS),
7767c478bd9Sstevel@tonic-gate 			    gettext("<file-system options>"));
777ffbafc53Scomay 			(void) fprintf(fp, "\t%s %s %s\n",
778ffbafc53Scomay 			    cmd_to_str(CMD_REMOVE), pt_to_str(PT_OPTIONS),
779ffbafc53Scomay 			    gettext("<file-system options>"));
7807c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Consult the file-system "
7817c478bd9Sstevel@tonic-gate 			    "specific manual page, such as mount_ufs(1M), "
7827c478bd9Sstevel@tonic-gate 			    "for\ndetails about file-system options.  Note "
7837c478bd9Sstevel@tonic-gate 			    "that any file-system options with an\nembedded "
7847c478bd9Sstevel@tonic-gate 			    "'=' character must be enclosed in double quotes, "
7857c478bd9Sstevel@tonic-gate 			    /*CSTYLED*/
7867c478bd9Sstevel@tonic-gate 			    "such as \"%s=5\".\n"), MNTOPT_RETRY);
7877c478bd9Sstevel@tonic-gate 			break;
7887c478bd9Sstevel@tonic-gate 		case RT_IPD:
7897c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("The '%s' resource scope is "
7907c478bd9Sstevel@tonic-gate 			    "used to configure a directory\ninherited from the "
7917c478bd9Sstevel@tonic-gate 			    "global zone into a non-global zone in read-only "
7927c478bd9Sstevel@tonic-gate 			    "mode.\n"), rt_to_str(resource_scope));
7937c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Valid commands:\n"));
7947c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
7957c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_DIR), gettext("<path>"));
7967c478bd9Sstevel@tonic-gate 			break;
7977c478bd9Sstevel@tonic-gate 		case RT_NET:
7987c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("The '%s' resource scope is "
7997c478bd9Sstevel@tonic-gate 			    "used to configure a network interface.\n"),
8007c478bd9Sstevel@tonic-gate 			    rt_to_str(resource_scope));
8017c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Valid commands:\n"));
8027c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
8037c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_ADDRESS), gettext("<IP-address>"));
8047c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
8057c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_PHYSICAL), gettext("<interface>"));
8067c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("See ifconfig(1M) for "
8077c478bd9Sstevel@tonic-gate 			    "details of the <interface> string.\n"));
8087c478bd9Sstevel@tonic-gate 			break;
8097c478bd9Sstevel@tonic-gate 		case RT_DEVICE:
8107c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("The '%s' resource scope is "
8117c478bd9Sstevel@tonic-gate 			    "used to configure a device node.\n"),
8127c478bd9Sstevel@tonic-gate 			    rt_to_str(resource_scope));
8137c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Valid commands:\n"));
8147c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
8157c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_MATCH), gettext("<device-path>"));
8167c478bd9Sstevel@tonic-gate 			break;
8177c478bd9Sstevel@tonic-gate 		case RT_RCTL:
8187c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("The '%s' resource scope is "
8197c478bd9Sstevel@tonic-gate 			    "used to configure a resource control.\n"),
8207c478bd9Sstevel@tonic-gate 			    rt_to_str(resource_scope));
8217c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Valid commands:\n"));
8227c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
8237c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_NAME), gettext("<string>"));
8247c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
8257c478bd9Sstevel@tonic-gate 			    cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
8267c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_PRIV), gettext("<priv-value>"),
8277c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_LIMIT), gettext("<number>"),
8287c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_ACTION), gettext("<action-value>"));
829ffbafc53Scomay 			(void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
830ffbafc53Scomay 			    cmd_to_str(CMD_REMOVE), pt_to_str(PT_VALUE),
831ffbafc53Scomay 			    pt_to_str(PT_PRIV), gettext("<priv-value>"),
832ffbafc53Scomay 			    pt_to_str(PT_LIMIT), gettext("<number>"),
833ffbafc53Scomay 			    pt_to_str(PT_ACTION), gettext("<action-value>"));
8347c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "%s\n\t%s := privileged\n"
8357c478bd9Sstevel@tonic-gate 			    "\t%s := none | deny\n", gettext("Where"),
8367c478bd9Sstevel@tonic-gate 			    gettext("<priv-value>"), gettext("<action-value>"));
8377c478bd9Sstevel@tonic-gate 			break;
8387c478bd9Sstevel@tonic-gate 		case RT_ATTR:
8397c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("The '%s' resource scope is "
8407c478bd9Sstevel@tonic-gate 			    "used to configure a generic attribute.\n"),
8417c478bd9Sstevel@tonic-gate 			    rt_to_str(resource_scope));
8427c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Valid commands:\n"));
8437c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
8447c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_NAME), gettext("<name>"));
8457c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=boolean\n",
8467c478bd9Sstevel@tonic-gate 			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
8477c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=true | false\n",
8487c478bd9Sstevel@tonic-gate 			    cmd_to_str(CMD_SET), pt_to_str(PT_VALUE));
8497c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("or\n"));
8507c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=int\n", cmd_to_str(CMD_SET),
8517c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_TYPE));
8527c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
8537c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_VALUE), gettext("<integer>"));
8547c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("or\n"));
8557c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=string\n",
8567c478bd9Sstevel@tonic-gate 			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
8577c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
8587c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_VALUE), gettext("<string>"));
8597c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, gettext("or\n"));
8607c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=uint\n",
8617c478bd9Sstevel@tonic-gate 			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
8627c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
8637c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_VALUE), gettext("<unsigned integer>"));
8647c478bd9Sstevel@tonic-gate 			break;
865fa9e4066Sahrens 		case RT_DATASET:
866fa9e4066Sahrens 			(void) fprintf(fp, gettext("The '%s' resource scope is "
867fa9e4066Sahrens 			    "used to export ZFS datasets.\n"),
868fa9e4066Sahrens 			    rt_to_str(resource_scope));
869fa9e4066Sahrens 			(void) fprintf(fp, gettext("Valid commands:\n"));
870fa9e4066Sahrens 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
871fa9e4066Sahrens 			    pt_to_str(PT_NAME), gettext("<name>"));
872fa9e4066Sahrens 			break;
8737c478bd9Sstevel@tonic-gate 		}
8747c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, gettext("And from any resource scope, you "
8757c478bd9Sstevel@tonic-gate 		    "can:\n"));
8767c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
8777c478bd9Sstevel@tonic-gate 		    gettext("(to conclude this operation)"));
8787c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
8797c478bd9Sstevel@tonic-gate 		    gettext("(to cancel this operation)"));
8807c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
8817c478bd9Sstevel@tonic-gate 		    gettext("(to exit the zonecfg utility)"));
8827c478bd9Sstevel@tonic-gate 	}
8837c478bd9Sstevel@tonic-gate 	if (flags & HELP_USAGE) {
8847c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
8857c478bd9Sstevel@tonic-gate 		    execname, cmd_to_str(CMD_HELP));
8867c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
8877c478bd9Sstevel@tonic-gate 		    execname, gettext("interactive"));
8887c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
8897c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
8907c478bd9Sstevel@tonic-gate 		    execname);
8917c478bd9Sstevel@tonic-gate 	}
8927c478bd9Sstevel@tonic-gate 	if (flags & HELP_SUBCMDS) {
8937c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s:\n\n", gettext("Commands"));
8947c478bd9Sstevel@tonic-gate 		for (i = 0; i <= CMD_MAX; i++) {
8957c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "%s\n", helptab[i].short_usage);
8967c478bd9Sstevel@tonic-gate 			if (verbose)
8977c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "\t%s\n\n", long_help(i));
8987c478bd9Sstevel@tonic-gate 		}
8997c478bd9Sstevel@tonic-gate 	}
9007c478bd9Sstevel@tonic-gate 	if (flags & HELP_SYNTAX) {
9017c478bd9Sstevel@tonic-gate 		if (!verbose)
9027c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\n");
9037c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
9047c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, gettext("\t(except the reserved words "
9057c478bd9Sstevel@tonic-gate 		    "'%s' and anything starting with '%s')\n"), "global",
9067c478bd9Sstevel@tonic-gate 		    "SUNW");
9077c478bd9Sstevel@tonic-gate 		(void) fprintf(fp,
9087c478bd9Sstevel@tonic-gate 		    gettext("\tName must be less than %d characters.\n"),
9097c478bd9Sstevel@tonic-gate 		    ZONENAME_MAX);
9107c478bd9Sstevel@tonic-gate 		if (verbose)
9117c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\n");
9127c478bd9Sstevel@tonic-gate 	}
9137c478bd9Sstevel@tonic-gate 	if (flags & HELP_NETADDR) {
9147c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, gettext("\n<net-addr> :="));
9157c478bd9Sstevel@tonic-gate 		(void) fprintf(fp,
9167c478bd9Sstevel@tonic-gate 		    gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n"));
9177c478bd9Sstevel@tonic-gate 		(void) fprintf(fp,
9187c478bd9Sstevel@tonic-gate 		    gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
9197c478bd9Sstevel@tonic-gate 		(void) fprintf(fp,
9207c478bd9Sstevel@tonic-gate 		    gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
9217c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and "
9227c478bd9Sstevel@tonic-gate 		    "IPv6 address syntax.\n"));
9237c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n"));
9247c478bd9Sstevel@tonic-gate 		(void) fprintf(fp,
9257c478bd9Sstevel@tonic-gate 		    gettext("<IPv6-prefix-length> := [0-128]\n"));
9267c478bd9Sstevel@tonic-gate 		(void) fprintf(fp,
9277c478bd9Sstevel@tonic-gate 		    gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
9287c478bd9Sstevel@tonic-gate 	}
9297c478bd9Sstevel@tonic-gate 	if (flags & HELP_RESOURCES) {
9309e7542f4Sdp 		(void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s | %s |\n\t"
9319e7542f4Sdp 		    "%s\n\n",
9327c478bd9Sstevel@tonic-gate 		    gettext("resource type"), rt_to_str(RT_FS),
9337c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_IPD), rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
9349e7542f4Sdp 		    rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
9359e7542f4Sdp 		    rt_to_str(RT_DATASET));
9367c478bd9Sstevel@tonic-gate 	}
9377c478bd9Sstevel@tonic-gate 	if (flags & HELP_PROPS) {
9387c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, gettext("For resource type ... there are "
9397c478bd9Sstevel@tonic-gate 		    "property types ...:\n"));
940087719fdSdp 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
941087719fdSdp 		    pt_to_str(PT_ZONENAME));
9427c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
9437c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_ZONEPATH));
944*9acbbeafSnn 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
945*9acbbeafSnn 		    pt_to_str(PT_BRAND));
9467c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
9477c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_AUTOBOOT));
9483f2f09c1Sdp 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
9493f2f09c1Sdp 		    pt_to_str(PT_BOOTARGS));
9507c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
9517c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_POOL));
952ffbafc53Scomay 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
953ffbafc53Scomay 		    pt_to_str(PT_LIMITPRIV));
9547c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s\n", rt_to_str(RT_FS),
9557c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_DIR), pt_to_str(PT_SPECIAL),
9567c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_RAW), pt_to_str(PT_TYPE),
9577c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_OPTIONS));
9587c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_IPD),
9597c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_DIR));
9607c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_NET),
9617c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_ADDRESS), pt_to_str(PT_PHYSICAL));
9627c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
9637c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_MATCH));
9647c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
9657c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
9667c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
9677c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
9687c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_VALUE));
969fa9e4066Sahrens 		(void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
970fa9e4066Sahrens 		    pt_to_str(PT_NAME));
9717c478bd9Sstevel@tonic-gate 	}
9727c478bd9Sstevel@tonic-gate 	if (need_to_close)
9737c478bd9Sstevel@tonic-gate 		(void) pclose(fp);
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate /* PRINTFLIKE1 */
9777c478bd9Sstevel@tonic-gate static void
9787c478bd9Sstevel@tonic-gate zerr(const char *fmt, ...)
9797c478bd9Sstevel@tonic-gate {
9807c478bd9Sstevel@tonic-gate 	va_list alist;
9817c478bd9Sstevel@tonic-gate 	static int last_lineno;
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate 	/* lex_lineno has already been incremented in the lexer; compensate */
9847c478bd9Sstevel@tonic-gate 	if (cmd_file_mode && lex_lineno > last_lineno) {
9857c478bd9Sstevel@tonic-gate 		if (strcmp(cmd_file_name, "-") == 0)
9867c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("On line %d:\n"),
9877c478bd9Sstevel@tonic-gate 			    lex_lineno - 1);
9887c478bd9Sstevel@tonic-gate 		else
9897c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("On line %d of %s:\n"),
9907c478bd9Sstevel@tonic-gate 			    lex_lineno - 1, cmd_file_name);
9917c478bd9Sstevel@tonic-gate 		last_lineno = lex_lineno;
9927c478bd9Sstevel@tonic-gate 	}
9937c478bd9Sstevel@tonic-gate 	va_start(alist, fmt);
9947c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, fmt, alist);
9957c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\n");
9967c478bd9Sstevel@tonic-gate 	va_end(alist);
9977c478bd9Sstevel@tonic-gate }
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate static void
10007c478bd9Sstevel@tonic-gate zone_perror(char *prefix, int err, bool set_saw)
10017c478bd9Sstevel@tonic-gate {
10027c478bd9Sstevel@tonic-gate 	zerr("%s: %s", prefix, zonecfg_strerror(err));
10037c478bd9Sstevel@tonic-gate 	if (set_saw)
10047c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
10057c478bd9Sstevel@tonic-gate }
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate /*
10087c478bd9Sstevel@tonic-gate  * zone_perror() expects a single string, but for remove and select
10097c478bd9Sstevel@tonic-gate  * we have both the command and the resource type, so this wrapper
10107c478bd9Sstevel@tonic-gate  * function serves the same purpose in a slightly different way.
10117c478bd9Sstevel@tonic-gate  */
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate static void
10147c478bd9Sstevel@tonic-gate z_cmd_rt_perror(int cmd_num, int res_num, int err, bool set_saw)
10157c478bd9Sstevel@tonic-gate {
10167c478bd9Sstevel@tonic-gate 	zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num),
10177c478bd9Sstevel@tonic-gate 	    zonecfg_strerror(err));
10187c478bd9Sstevel@tonic-gate 	if (set_saw)
10197c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
10207c478bd9Sstevel@tonic-gate }
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
10237c478bd9Sstevel@tonic-gate static int
10247c478bd9Sstevel@tonic-gate initialize(bool handle_expected)
10257c478bd9Sstevel@tonic-gate {
10267c478bd9Sstevel@tonic-gate 	int err;
1027*9acbbeafSnn 	char brandname[MAXNAMELEN];
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	if (zonecfg_check_handle(handle) != Z_OK) {
10307c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) {
10317c478bd9Sstevel@tonic-gate 			got_handle = TRUE;
1032*9acbbeafSnn 			if (zonecfg_get_brand(handle, brandname,
1033*9acbbeafSnn 			    sizeof (brandname)) != Z_OK) {
1034*9acbbeafSnn 				zerr("Zone %s is inconsistent: missing "
1035*9acbbeafSnn 				    "brand attribute", zone);
1036*9acbbeafSnn 				exit(Z_ERR);
1037*9acbbeafSnn 			}
1038*9acbbeafSnn 			if ((brand = brand_open(brandname)) == NULL) {
1039*9acbbeafSnn 				zerr("Zone %s uses non-existent brand \"%s\"."
1040*9acbbeafSnn 				    "  Unable to continue", zone, brandname);
1041*9acbbeafSnn 				exit(Z_ERR);
1042*9acbbeafSnn 			}
10437c478bd9Sstevel@tonic-gate 		} else {
10447c478bd9Sstevel@tonic-gate 			zone_perror(zone, err, handle_expected || got_handle);
10457c478bd9Sstevel@tonic-gate 			if (err == Z_NO_ZONE && !got_handle &&
10467c478bd9Sstevel@tonic-gate 			    interactive_mode && !read_only_mode)
10477c478bd9Sstevel@tonic-gate 				(void) printf(gettext("Use '%s' to begin "
10487c478bd9Sstevel@tonic-gate 				    "configuring a new zone.\n"),
10497c478bd9Sstevel@tonic-gate 				    cmd_to_str(CMD_CREATE));
10507c478bd9Sstevel@tonic-gate 			return (err);
10517c478bd9Sstevel@tonic-gate 		}
10527c478bd9Sstevel@tonic-gate 	}
10537c478bd9Sstevel@tonic-gate 	return (Z_OK);
10547c478bd9Sstevel@tonic-gate }
10557c478bd9Sstevel@tonic-gate 
1056087719fdSdp static bool
1057087719fdSdp state_atleast(zone_state_t state)
1058087719fdSdp {
1059087719fdSdp 	zone_state_t state_num;
1060087719fdSdp 	int err;
1061087719fdSdp 
1062087719fdSdp 	if ((err = zone_get_state(zone, &state_num)) != Z_OK) {
1063087719fdSdp 		/* all states are greater than "non-existent" */
1064087719fdSdp 		if (err == Z_NO_ZONE)
1065087719fdSdp 			return (B_FALSE);
1066087719fdSdp 		zerr(gettext("Unexpectedly failed to determine state "
1067087719fdSdp 		    "of zone %s: %s"), zone, zonecfg_strerror(err));
1068087719fdSdp 		exit(Z_ERR);
1069087719fdSdp 	}
1070087719fdSdp 	return (state_num >= state);
1071087719fdSdp }
1072087719fdSdp 
10737c478bd9Sstevel@tonic-gate /*
10747c478bd9Sstevel@tonic-gate  * short_usage() is for bad syntax: getopt() issues, too many arguments, etc.
10757c478bd9Sstevel@tonic-gate  */
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate void
10787c478bd9Sstevel@tonic-gate short_usage(int command)
10797c478bd9Sstevel@tonic-gate {
10807c478bd9Sstevel@tonic-gate 	/* lex_lineno has already been incremented in the lexer; compensate */
10817c478bd9Sstevel@tonic-gate 	if (cmd_file_mode) {
10827c478bd9Sstevel@tonic-gate 		if (strcmp(cmd_file_name, "-") == 0)
10837c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
10847c478bd9Sstevel@tonic-gate 			    gettext("syntax error on line %d\n"),
10857c478bd9Sstevel@tonic-gate 			    lex_lineno - 1);
10867c478bd9Sstevel@tonic-gate 		else
10877c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
10887c478bd9Sstevel@tonic-gate 			    gettext("syntax error on line %d of %s\n"),
10897c478bd9Sstevel@tonic-gate 			    lex_lineno - 1, cmd_file_name);
10907c478bd9Sstevel@tonic-gate 	}
10917c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s:\n%s\n", gettext("usage"),
10927c478bd9Sstevel@tonic-gate 	    helptab[command].short_usage);
10937c478bd9Sstevel@tonic-gate 	saw_error = TRUE;
10947c478bd9Sstevel@tonic-gate }
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate /*
10977c478bd9Sstevel@tonic-gate  * long_usage() is for bad semantics: e.g., wrong property type for a given
10987c478bd9Sstevel@tonic-gate  * resource type.  It is also used by longer_usage() below.
10997c478bd9Sstevel@tonic-gate  */
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate void
11027c478bd9Sstevel@tonic-gate long_usage(uint_t cmd_num, bool set_saw)
11037c478bd9Sstevel@tonic-gate {
11047c478bd9Sstevel@tonic-gate 	(void) fprintf(set_saw ? stderr : stdout, "%s:\n%s\n", gettext("usage"),
11057c478bd9Sstevel@tonic-gate 	    helptab[cmd_num].short_usage);
11067c478bd9Sstevel@tonic-gate 	(void) fprintf(set_saw ? stderr : stdout, "\t%s\n", long_help(cmd_num));
11077c478bd9Sstevel@tonic-gate 	if (set_saw)
11087c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
11097c478bd9Sstevel@tonic-gate }
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate /*
11127c478bd9Sstevel@tonic-gate  * longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also
11137c478bd9Sstevel@tonic-gate  * any extra usage() flags as appropriate for whatever command.
11147c478bd9Sstevel@tonic-gate  */
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate void
11177c478bd9Sstevel@tonic-gate longer_usage(uint_t cmd_num)
11187c478bd9Sstevel@tonic-gate {
11197c478bd9Sstevel@tonic-gate 	long_usage(cmd_num, FALSE);
11207c478bd9Sstevel@tonic-gate 	if (helptab[cmd_num].flags != 0) {
11217c478bd9Sstevel@tonic-gate 		(void) printf("\n");
11227c478bd9Sstevel@tonic-gate 		usage(TRUE, helptab[cmd_num].flags);
11237c478bd9Sstevel@tonic-gate 	}
11247c478bd9Sstevel@tonic-gate }
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate /*
11277c478bd9Sstevel@tonic-gate  * scope_usage() is simply used when a command is called from the wrong scope.
11287c478bd9Sstevel@tonic-gate  */
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate static void
11317c478bd9Sstevel@tonic-gate scope_usage(uint_t cmd_num)
11327c478bd9Sstevel@tonic-gate {
11337c478bd9Sstevel@tonic-gate 	zerr(gettext("The %s command only makes sense in the %s scope."),
11347c478bd9Sstevel@tonic-gate 	    cmd_to_str(cmd_num),
11357c478bd9Sstevel@tonic-gate 	    global_scope ?  gettext("resource") : gettext("global"));
11367c478bd9Sstevel@tonic-gate 	saw_error = TRUE;
11377c478bd9Sstevel@tonic-gate }
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate /*
11407c478bd9Sstevel@tonic-gate  * On input, TRUE => yes, FALSE => no.
11417c478bd9Sstevel@tonic-gate  * On return, TRUE => 1, FALSE => no, could not ask => -1.
11427c478bd9Sstevel@tonic-gate  */
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate static int
11457c478bd9Sstevel@tonic-gate ask_yesno(bool default_answer, const char *question)
11467c478bd9Sstevel@tonic-gate {
11477c478bd9Sstevel@tonic-gate 	char line[64];	/* should be enough to answer yes or no */
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate 	if (!ok_to_prompt) {
11507c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
11517c478bd9Sstevel@tonic-gate 		return (-1);
11527c478bd9Sstevel@tonic-gate 	}
11537c478bd9Sstevel@tonic-gate 	for (;;) {
1154087719fdSdp 		if (printf("%s (%s)? ", question,
1155087719fdSdp 		    default_answer ? "[y]/n" : "y/[n]") < 0)
1156087719fdSdp 			return (-1);
1157087719fdSdp 		if (fgets(line, sizeof (line), stdin) == NULL)
1158087719fdSdp 			return (-1);
1159087719fdSdp 
1160087719fdSdp 		if (line[0] == '\n')
11617c478bd9Sstevel@tonic-gate 			return (default_answer ? 1 : 0);
11627c478bd9Sstevel@tonic-gate 		if (tolower(line[0]) == 'y')
11637c478bd9Sstevel@tonic-gate 			return (1);
11647c478bd9Sstevel@tonic-gate 		if (tolower(line[0]) == 'n')
11657c478bd9Sstevel@tonic-gate 			return (0);
11667c478bd9Sstevel@tonic-gate 	}
11677c478bd9Sstevel@tonic-gate }
11687c478bd9Sstevel@tonic-gate 
11697c478bd9Sstevel@tonic-gate /*
11707c478bd9Sstevel@tonic-gate  * Prints warning if zone already exists.
11717c478bd9Sstevel@tonic-gate  * In interactive mode, prompts if we should continue anyway and returns Z_OK
11727c478bd9Sstevel@tonic-gate  * if so, Z_ERR if not.  In non-interactive mode, exits with Z_ERR.
11737c478bd9Sstevel@tonic-gate  *
11747c478bd9Sstevel@tonic-gate  * Note that if a zone exists and its state is >= INSTALLED, an error message
11757c478bd9Sstevel@tonic-gate  * will be printed and this function will return Z_ERR regardless of mode.
11767c478bd9Sstevel@tonic-gate  */
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate static int
11797c478bd9Sstevel@tonic-gate check_if_zone_already_exists(bool force)
11807c478bd9Sstevel@tonic-gate {
11817c478bd9Sstevel@tonic-gate 	char line[ZONENAME_MAX + 128];	/* enough to ask a question */
11827c478bd9Sstevel@tonic-gate 	zone_dochandle_t tmphandle;
11837c478bd9Sstevel@tonic-gate 	int res, answer;
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 	if ((tmphandle = zonecfg_init_handle()) == NULL) {
11867c478bd9Sstevel@tonic-gate 		zone_perror(execname, Z_NOMEM, TRUE);
11877c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
11887c478bd9Sstevel@tonic-gate 	}
11897c478bd9Sstevel@tonic-gate 	res = zonecfg_get_handle(zone, tmphandle);
11907c478bd9Sstevel@tonic-gate 	zonecfg_fini_handle(tmphandle);
1191087719fdSdp 	if (res != Z_OK)
11927c478bd9Sstevel@tonic-gate 		return (Z_OK);
1193087719fdSdp 
1194087719fdSdp 	if (state_atleast(ZONE_STATE_INSTALLED)) {
11957c478bd9Sstevel@tonic-gate 		zerr(gettext("Zone %s already installed; %s not allowed."),
11967c478bd9Sstevel@tonic-gate 		    zone, cmd_to_str(CMD_CREATE));
11977c478bd9Sstevel@tonic-gate 		return (Z_ERR);
11987c478bd9Sstevel@tonic-gate 	}
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 	if (force) {
12017c478bd9Sstevel@tonic-gate 		(void) printf(gettext("Zone %s already exists; overwriting.\n"),
12027c478bd9Sstevel@tonic-gate 		    zone);
12037c478bd9Sstevel@tonic-gate 		return (Z_OK);
12047c478bd9Sstevel@tonic-gate 	}
12057c478bd9Sstevel@tonic-gate 	(void) snprintf(line, sizeof (line),
12067c478bd9Sstevel@tonic-gate 	    gettext("Zone %s already exists; %s anyway"), zone,
12077c478bd9Sstevel@tonic-gate 	    cmd_to_str(CMD_CREATE));
12087c478bd9Sstevel@tonic-gate 	if ((answer = ask_yesno(FALSE, line)) == -1) {
12097c478bd9Sstevel@tonic-gate 		zerr(gettext("Zone exists, input not from terminal and -F not "
12107c478bd9Sstevel@tonic-gate 		    "specified:\n%s command ignored, exiting."),
12117c478bd9Sstevel@tonic-gate 		    cmd_to_str(CMD_CREATE));
12127c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
12137c478bd9Sstevel@tonic-gate 	}
12147c478bd9Sstevel@tonic-gate 	return (answer == 1 ? Z_OK : Z_ERR);
12157c478bd9Sstevel@tonic-gate }
12167c478bd9Sstevel@tonic-gate 
12177c478bd9Sstevel@tonic-gate static bool
12187c478bd9Sstevel@tonic-gate zone_is_read_only(int cmd_num)
12197c478bd9Sstevel@tonic-gate {
12207c478bd9Sstevel@tonic-gate 	if (strncmp(zone, "SUNW", 4) == 0) {
12217c478bd9Sstevel@tonic-gate 		zerr(gettext("%s: zones beginning with SUNW are read-only."),
12227c478bd9Sstevel@tonic-gate 		    zone);
12237c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
12247c478bd9Sstevel@tonic-gate 		return (TRUE);
12257c478bd9Sstevel@tonic-gate 	}
12267c478bd9Sstevel@tonic-gate 	if (read_only_mode) {
12277c478bd9Sstevel@tonic-gate 		zerr(gettext("%s: cannot %s in read-only mode."), zone,
12287c478bd9Sstevel@tonic-gate 		    cmd_to_str(cmd_num));
12297c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
12307c478bd9Sstevel@tonic-gate 		return (TRUE);
12317c478bd9Sstevel@tonic-gate 	}
12327c478bd9Sstevel@tonic-gate 	return (FALSE);
12337c478bd9Sstevel@tonic-gate }
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate /*
12367c478bd9Sstevel@tonic-gate  * Create a new configuration.
12377c478bd9Sstevel@tonic-gate  */
12387c478bd9Sstevel@tonic-gate void
12397c478bd9Sstevel@tonic-gate create_func(cmd_t *cmd)
12407c478bd9Sstevel@tonic-gate {
12417c478bd9Sstevel@tonic-gate 	int err, arg;
12427c478bd9Sstevel@tonic-gate 	char zone_template[ZONENAME_MAX];
1243ee519a1fSgjelinek 	char attach_path[MAXPATHLEN];
12447c478bd9Sstevel@tonic-gate 	zone_dochandle_t tmphandle;
12457c478bd9Sstevel@tonic-gate 	bool force = FALSE;
1246ee519a1fSgjelinek 	bool attach = FALSE;
12477c478bd9Sstevel@tonic-gate 
12487c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 	/* This is the default if no arguments are given. */
12517c478bd9Sstevel@tonic-gate 	(void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template));
12527c478bd9Sstevel@tonic-gate 
12537c478bd9Sstevel@tonic-gate 	optind = 0;
1254*9acbbeafSnn 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:"))
1255*9acbbeafSnn 	    != EOF) {
12567c478bd9Sstevel@tonic-gate 		switch (arg) {
12577c478bd9Sstevel@tonic-gate 		case '?':
12587c478bd9Sstevel@tonic-gate 			if (optopt == '?')
12597c478bd9Sstevel@tonic-gate 				longer_usage(CMD_CREATE);
12607c478bd9Sstevel@tonic-gate 			else
12617c478bd9Sstevel@tonic-gate 				short_usage(CMD_CREATE);
12627c478bd9Sstevel@tonic-gate 			return;
1263ee519a1fSgjelinek 		case 'a':
1264ee519a1fSgjelinek 			(void) strlcpy(attach_path, optarg,
1265ee519a1fSgjelinek 			    sizeof (attach_path));
1266ee519a1fSgjelinek 			attach = TRUE;
1267ee519a1fSgjelinek 			break;
12687c478bd9Sstevel@tonic-gate 		case 'b':
12697c478bd9Sstevel@tonic-gate 			(void) strlcpy(zone_template, "SUNWblank",
12707c478bd9Sstevel@tonic-gate 			    sizeof (zone_template));
12717c478bd9Sstevel@tonic-gate 			break;
12727c478bd9Sstevel@tonic-gate 		case 'F':
12737c478bd9Sstevel@tonic-gate 			force = TRUE;
12747c478bd9Sstevel@tonic-gate 			break;
12757c478bd9Sstevel@tonic-gate 		case 't':
12767c478bd9Sstevel@tonic-gate 			(void) strlcpy(zone_template, optarg,
12777c478bd9Sstevel@tonic-gate 			    sizeof (zone_template));
12787c478bd9Sstevel@tonic-gate 			break;
12797c478bd9Sstevel@tonic-gate 		default:
12807c478bd9Sstevel@tonic-gate 			short_usage(CMD_CREATE);
12817c478bd9Sstevel@tonic-gate 			return;
12827c478bd9Sstevel@tonic-gate 		}
12837c478bd9Sstevel@tonic-gate 	}
12847c478bd9Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
12857c478bd9Sstevel@tonic-gate 		short_usage(CMD_CREATE);
12867c478bd9Sstevel@tonic-gate 		return;
12877c478bd9Sstevel@tonic-gate 	}
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 	if (zone_is_read_only(CMD_CREATE))
12907c478bd9Sstevel@tonic-gate 		return;
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 	if (check_if_zone_already_exists(force) != Z_OK)
12937c478bd9Sstevel@tonic-gate 		return;
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 	/*
12967c478bd9Sstevel@tonic-gate 	 * Get a temporary handle first.  If that fails, the old handle
12977c478bd9Sstevel@tonic-gate 	 * will not be lost.  Then finish whichever one we don't need,
12987c478bd9Sstevel@tonic-gate 	 * to avoid leaks.  Then get the handle for zone_template, and
12997c478bd9Sstevel@tonic-gate 	 * set the name to zone: this "copy, rename" method is how
13007c478bd9Sstevel@tonic-gate 	 * create -[b|t] works.
13017c478bd9Sstevel@tonic-gate 	 */
13027c478bd9Sstevel@tonic-gate 	if ((tmphandle = zonecfg_init_handle()) == NULL) {
13037c478bd9Sstevel@tonic-gate 		zone_perror(execname, Z_NOMEM, TRUE);
13047c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
13057c478bd9Sstevel@tonic-gate 	}
1306ee519a1fSgjelinek 
1307ee519a1fSgjelinek 	if (attach)
1308ee519a1fSgjelinek 		err = zonecfg_get_attach_handle(attach_path, zone, B_FALSE,
1309ee519a1fSgjelinek 		    tmphandle);
1310ee519a1fSgjelinek 	else
1311ee519a1fSgjelinek 		err = zonecfg_get_template_handle(zone_template, zone,
1312ee519a1fSgjelinek 		    tmphandle);
1313ee519a1fSgjelinek 
1314ee519a1fSgjelinek 	if (err != Z_OK) {
13157c478bd9Sstevel@tonic-gate 		zonecfg_fini_handle(tmphandle);
1316ee519a1fSgjelinek 		if (attach && err == Z_NO_ZONE)
1317ee519a1fSgjelinek 			(void) fprintf(stderr, gettext("invalid path to "
1318ee519a1fSgjelinek 			    "detached zone\n"));
1319ee519a1fSgjelinek 		else if (attach && err == Z_INVALID_DOCUMENT)
1320ee519a1fSgjelinek 			(void) fprintf(stderr, gettext("Cannot attach to an "
1321ee519a1fSgjelinek 			    "earlier release of the operating system\n"));
1322ee519a1fSgjelinek 		else
1323ee519a1fSgjelinek 			zone_perror(zone_template, err, TRUE);
13247c478bd9Sstevel@tonic-gate 		return;
13257c478bd9Sstevel@tonic-gate 	}
1326087719fdSdp 
1327087719fdSdp 	need_to_commit = TRUE;
13287c478bd9Sstevel@tonic-gate 	zonecfg_fini_handle(handle);
13297c478bd9Sstevel@tonic-gate 	handle = tmphandle;
1330087719fdSdp 	got_handle = TRUE;
13317c478bd9Sstevel@tonic-gate }
13327c478bd9Sstevel@tonic-gate 
13337c478bd9Sstevel@tonic-gate /*
13347c478bd9Sstevel@tonic-gate  * This malloc()'s memory, which must be freed by the caller.
13357c478bd9Sstevel@tonic-gate  */
13367c478bd9Sstevel@tonic-gate static char *
13377c478bd9Sstevel@tonic-gate quoteit(char *instr)
13387c478bd9Sstevel@tonic-gate {
13397c478bd9Sstevel@tonic-gate 	char *outstr;
13407c478bd9Sstevel@tonic-gate 	size_t outstrsize = strlen(instr) + 3;	/* 2 quotes + '\0' */
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate 	if ((outstr = malloc(outstrsize)) == NULL) {
13437c478bd9Sstevel@tonic-gate 		zone_perror(zone, Z_NOMEM, FALSE);
13447c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
13457c478bd9Sstevel@tonic-gate 	}
13467c478bd9Sstevel@tonic-gate 	if (strchr(instr, ' ') == NULL) {
13477c478bd9Sstevel@tonic-gate 		(void) strlcpy(outstr, instr, outstrsize);
13487c478bd9Sstevel@tonic-gate 		return (outstr);
13497c478bd9Sstevel@tonic-gate 	}
13507c478bd9Sstevel@tonic-gate 	(void) snprintf(outstr, outstrsize, "\"%s\"", instr);
13517c478bd9Sstevel@tonic-gate 	return (outstr);
13527c478bd9Sstevel@tonic-gate }
13537c478bd9Sstevel@tonic-gate 
13547c478bd9Sstevel@tonic-gate static void
13557c478bd9Sstevel@tonic-gate export_prop(FILE *of, int prop_num, char *prop_id)
13567c478bd9Sstevel@tonic-gate {
13577c478bd9Sstevel@tonic-gate 	char *quote_str;
13587c478bd9Sstevel@tonic-gate 
13597c478bd9Sstevel@tonic-gate 	if (strlen(prop_id) == 0)
13607c478bd9Sstevel@tonic-gate 		return;
13617c478bd9Sstevel@tonic-gate 	quote_str = quoteit(prop_id);
13627c478bd9Sstevel@tonic-gate 	(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
13637c478bd9Sstevel@tonic-gate 	    pt_to_str(prop_num), quote_str);
13647c478bd9Sstevel@tonic-gate 	free(quote_str);
13657c478bd9Sstevel@tonic-gate }
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate void
13687c478bd9Sstevel@tonic-gate export_func(cmd_t *cmd)
13697c478bd9Sstevel@tonic-gate {
13707c478bd9Sstevel@tonic-gate 	struct zone_nwiftab nwiftab;
13717c478bd9Sstevel@tonic-gate 	struct zone_fstab fstab;
13727c478bd9Sstevel@tonic-gate 	struct zone_devtab devtab;
13737c478bd9Sstevel@tonic-gate 	struct zone_attrtab attrtab;
13747c478bd9Sstevel@tonic-gate 	struct zone_rctltab rctltab;
1375fa9e4066Sahrens 	struct zone_dstab dstab;
13767c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valptr;
13777c478bd9Sstevel@tonic-gate 	int err, arg;
13787c478bd9Sstevel@tonic-gate 	char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
13793f2f09c1Sdp 	char bootargs[BOOTARGS_MAX];
1380*9acbbeafSnn 	char brand[MAXNAMELEN];
1381ffbafc53Scomay 	char *limitpriv;
13827c478bd9Sstevel@tonic-gate 	FILE *of;
13837c478bd9Sstevel@tonic-gate 	boolean_t autoboot;
13847c478bd9Sstevel@tonic-gate 	bool need_to_close = FALSE;
13857c478bd9Sstevel@tonic-gate 
13867c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate 	outfile[0] = '\0';
13897c478bd9Sstevel@tonic-gate 	optind = 0;
13907c478bd9Sstevel@tonic-gate 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
13917c478bd9Sstevel@tonic-gate 		switch (arg) {
13927c478bd9Sstevel@tonic-gate 		case '?':
13937c478bd9Sstevel@tonic-gate 			if (optopt == '?')
13947c478bd9Sstevel@tonic-gate 				longer_usage(CMD_EXPORT);
13957c478bd9Sstevel@tonic-gate 			else
13967c478bd9Sstevel@tonic-gate 				short_usage(CMD_EXPORT);
13977c478bd9Sstevel@tonic-gate 			return;
13987c478bd9Sstevel@tonic-gate 		case 'f':
13997c478bd9Sstevel@tonic-gate 			(void) strlcpy(outfile, optarg, sizeof (outfile));
14007c478bd9Sstevel@tonic-gate 			break;
14017c478bd9Sstevel@tonic-gate 		default:
14027c478bd9Sstevel@tonic-gate 			short_usage(CMD_EXPORT);
14037c478bd9Sstevel@tonic-gate 			return;
14047c478bd9Sstevel@tonic-gate 		}
14057c478bd9Sstevel@tonic-gate 	}
14067c478bd9Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
14077c478bd9Sstevel@tonic-gate 		short_usage(CMD_EXPORT);
14087c478bd9Sstevel@tonic-gate 		return;
14097c478bd9Sstevel@tonic-gate 	}
14107c478bd9Sstevel@tonic-gate 	if (strlen(outfile) == 0) {
14117c478bd9Sstevel@tonic-gate 		of = stdout;
14127c478bd9Sstevel@tonic-gate 	} else {
14137c478bd9Sstevel@tonic-gate 		if ((of = fopen(outfile, "w")) == NULL) {
14147c478bd9Sstevel@tonic-gate 			zerr(gettext("opening file %s: %s"),
14157c478bd9Sstevel@tonic-gate 			    outfile, strerror(errno));
14167c478bd9Sstevel@tonic-gate 			goto done;
14177c478bd9Sstevel@tonic-gate 		}
14187c478bd9Sstevel@tonic-gate 		setbuf(of, NULL);
14197c478bd9Sstevel@tonic-gate 		need_to_close = TRUE;
14207c478bd9Sstevel@tonic-gate 	}
14217c478bd9Sstevel@tonic-gate 
14227c478bd9Sstevel@tonic-gate 	if ((err = initialize(TRUE)) != Z_OK)
14237c478bd9Sstevel@tonic-gate 		goto done;
14247c478bd9Sstevel@tonic-gate 
14257c478bd9Sstevel@tonic-gate 	(void) fprintf(of, "%s -b\n", cmd_to_str(CMD_CREATE));
14267c478bd9Sstevel@tonic-gate 
14277c478bd9Sstevel@tonic-gate 	if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK &&
14287c478bd9Sstevel@tonic-gate 	    strlen(zonepath) > 0)
14297c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
14307c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_ZONEPATH), zonepath);
14317c478bd9Sstevel@tonic-gate 
1432*9acbbeafSnn 	if ((zone_get_brand(zone, brand, sizeof (brand)) == Z_OK) &&
1433*9acbbeafSnn 	    (strcmp(brand, NATIVE_BRAND_NAME) != 0))
1434*9acbbeafSnn 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1435*9acbbeafSnn 		    pt_to_str(PT_BRAND), brand);
1436*9acbbeafSnn 
14377c478bd9Sstevel@tonic-gate 	if (zonecfg_get_autoboot(handle, &autoboot) == Z_OK)
14387c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
14397c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_AUTOBOOT), autoboot ? "true" : "false");
14407c478bd9Sstevel@tonic-gate 
14413f2f09c1Sdp 	if (zonecfg_get_bootargs(handle, bootargs, sizeof (bootargs)) == Z_OK &&
14423f2f09c1Sdp 	    strlen(bootargs) > 0) {
14433f2f09c1Sdp 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
14443f2f09c1Sdp 		    pt_to_str(PT_BOOTARGS), bootargs);
14453f2f09c1Sdp 	}
14463f2f09c1Sdp 
14477c478bd9Sstevel@tonic-gate 	if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
14487c478bd9Sstevel@tonic-gate 	    strlen(pool) > 0)
14497c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
14507c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_POOL), pool);
14517c478bd9Sstevel@tonic-gate 
1452ffbafc53Scomay 	if (zonecfg_get_limitpriv(handle, &limitpriv) == Z_OK &&
1453ffbafc53Scomay 	    strlen(limitpriv) > 0) {
1454ffbafc53Scomay 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1455ffbafc53Scomay 		    pt_to_str(PT_LIMITPRIV), limitpriv);
1456ffbafc53Scomay 		free(limitpriv);
1457ffbafc53Scomay 	}
1458ffbafc53Scomay 
14593f2f09c1Sdp 
14607c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_setipdent(handle)) != Z_OK) {
14617c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, FALSE);
14627c478bd9Sstevel@tonic-gate 		goto done;
14637c478bd9Sstevel@tonic-gate 	}
14647c478bd9Sstevel@tonic-gate 	while (zonecfg_getipdent(handle, &fstab) == Z_OK) {
14657c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
14667c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_IPD));
14677c478bd9Sstevel@tonic-gate 		export_prop(of, PT_DIR, fstab.zone_fs_dir);
14687c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
14697c478bd9Sstevel@tonic-gate 	}
14707c478bd9Sstevel@tonic-gate 	(void) zonecfg_endipdent(handle);
14717c478bd9Sstevel@tonic-gate 
14727c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_setfsent(handle)) != Z_OK) {
14737c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, FALSE);
14747c478bd9Sstevel@tonic-gate 		goto done;
14757c478bd9Sstevel@tonic-gate 	}
14767c478bd9Sstevel@tonic-gate 	while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
14777c478bd9Sstevel@tonic-gate 		zone_fsopt_t *optptr;
14787c478bd9Sstevel@tonic-gate 
14797c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
14807c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_FS));
14817c478bd9Sstevel@tonic-gate 		export_prop(of, PT_DIR, fstab.zone_fs_dir);
14827c478bd9Sstevel@tonic-gate 		export_prop(of, PT_SPECIAL, fstab.zone_fs_special);
14837c478bd9Sstevel@tonic-gate 		export_prop(of, PT_RAW, fstab.zone_fs_raw);
14847c478bd9Sstevel@tonic-gate 		export_prop(of, PT_TYPE, fstab.zone_fs_type);
14857c478bd9Sstevel@tonic-gate 		for (optptr = fstab.zone_fs_options; optptr != NULL;
14867c478bd9Sstevel@tonic-gate 		    optptr = optptr->zone_fsopt_next) {
14877c478bd9Sstevel@tonic-gate 			/*
14887c478bd9Sstevel@tonic-gate 			 * Simple property values with embedded equal signs
14897c478bd9Sstevel@tonic-gate 			 * need to be quoted to prevent the lexer from
14907c478bd9Sstevel@tonic-gate 			 * mis-parsing them as complex name=value pairs.
14917c478bd9Sstevel@tonic-gate 			 */
14927c478bd9Sstevel@tonic-gate 			if (strchr(optptr->zone_fsopt_opt, '='))
14937c478bd9Sstevel@tonic-gate 				(void) fprintf(of, "%s %s \"%s\"\n",
14947c478bd9Sstevel@tonic-gate 				    cmd_to_str(CMD_ADD),
14957c478bd9Sstevel@tonic-gate 				    pt_to_str(PT_OPTIONS),
14967c478bd9Sstevel@tonic-gate 				    optptr->zone_fsopt_opt);
14977c478bd9Sstevel@tonic-gate 			else
14987c478bd9Sstevel@tonic-gate 				(void) fprintf(of, "%s %s %s\n",
14997c478bd9Sstevel@tonic-gate 				    cmd_to_str(CMD_ADD),
15007c478bd9Sstevel@tonic-gate 				    pt_to_str(PT_OPTIONS),
15017c478bd9Sstevel@tonic-gate 				    optptr->zone_fsopt_opt);
15027c478bd9Sstevel@tonic-gate 		}
15037c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
15047c478bd9Sstevel@tonic-gate 		zonecfg_free_fs_option_list(fstab.zone_fs_options);
15057c478bd9Sstevel@tonic-gate 	}
15067c478bd9Sstevel@tonic-gate 	(void) zonecfg_endfsent(handle);
15077c478bd9Sstevel@tonic-gate 
15087c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
15097c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, FALSE);
15107c478bd9Sstevel@tonic-gate 		goto done;
15117c478bd9Sstevel@tonic-gate 	}
15127c478bd9Sstevel@tonic-gate 	while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
15137c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
15147c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_NET));
15157c478bd9Sstevel@tonic-gate 		export_prop(of, PT_ADDRESS, nwiftab.zone_nwif_address);
15167c478bd9Sstevel@tonic-gate 		export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical);
15177c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
15187c478bd9Sstevel@tonic-gate 	}
15197c478bd9Sstevel@tonic-gate 	(void) zonecfg_endnwifent(handle);
15207c478bd9Sstevel@tonic-gate 
15217c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_setdevent(handle)) != Z_OK) {
15227c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, FALSE);
15237c478bd9Sstevel@tonic-gate 		goto done;
15247c478bd9Sstevel@tonic-gate 	}
15257c478bd9Sstevel@tonic-gate 	while (zonecfg_getdevent(handle, &devtab) == Z_OK) {
15267c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
15277c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_DEVICE));
15287c478bd9Sstevel@tonic-gate 		export_prop(of, PT_MATCH, devtab.zone_dev_match);
15297c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
15307c478bd9Sstevel@tonic-gate 	}
15317c478bd9Sstevel@tonic-gate 	(void) zonecfg_enddevent(handle);
15327c478bd9Sstevel@tonic-gate 
15337c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
15347c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, FALSE);
15357c478bd9Sstevel@tonic-gate 		goto done;
15367c478bd9Sstevel@tonic-gate 	}
15377c478bd9Sstevel@tonic-gate 	while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
15387c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s rctl\n", cmd_to_str(CMD_ADD));
15397c478bd9Sstevel@tonic-gate 		export_prop(of, PT_NAME, rctltab.zone_rctl_name);
15407c478bd9Sstevel@tonic-gate 		for (valptr = rctltab.zone_rctl_valptr; valptr != NULL;
15417c478bd9Sstevel@tonic-gate 		    valptr = valptr->zone_rctlval_next) {
15427c478bd9Sstevel@tonic-gate 			fprintf(of, "%s %s (%s=%s,%s=%s,%s=%s)\n",
15437c478bd9Sstevel@tonic-gate 			    cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
15447c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
15457c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
15467c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
15477c478bd9Sstevel@tonic-gate 		}
15487c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
15497c478bd9Sstevel@tonic-gate 		zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
15507c478bd9Sstevel@tonic-gate 	}
15517c478bd9Sstevel@tonic-gate 	(void) zonecfg_endrctlent(handle);
15527c478bd9Sstevel@tonic-gate 
15537c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_setattrent(handle)) != Z_OK) {
15547c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, FALSE);
15557c478bd9Sstevel@tonic-gate 		goto done;
15567c478bd9Sstevel@tonic-gate 	}
15577c478bd9Sstevel@tonic-gate 	while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
15587c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
15597c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_ATTR));
15607c478bd9Sstevel@tonic-gate 		export_prop(of, PT_NAME, attrtab.zone_attr_name);
15617c478bd9Sstevel@tonic-gate 		export_prop(of, PT_TYPE, attrtab.zone_attr_type);
15627c478bd9Sstevel@tonic-gate 		export_prop(of, PT_VALUE, attrtab.zone_attr_value);
15637c478bd9Sstevel@tonic-gate 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
15647c478bd9Sstevel@tonic-gate 	}
15657c478bd9Sstevel@tonic-gate 	(void) zonecfg_endattrent(handle);
15667c478bd9Sstevel@tonic-gate 
1567fa9e4066Sahrens 	if ((err = zonecfg_setdsent(handle)) != Z_OK) {
1568fa9e4066Sahrens 		zone_perror(zone, err, FALSE);
1569fa9e4066Sahrens 		goto done;
1570fa9e4066Sahrens 	}
1571fa9e4066Sahrens 	while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
1572fa9e4066Sahrens 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1573fa9e4066Sahrens 		    rt_to_str(RT_DATASET));
1574fa9e4066Sahrens 		export_prop(of, PT_NAME, dstab.zone_dataset_name);
1575fa9e4066Sahrens 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1576fa9e4066Sahrens 	}
1577fa9e4066Sahrens 	(void) zonecfg_enddsent(handle);
1578fa9e4066Sahrens 
15797c478bd9Sstevel@tonic-gate done:
15807c478bd9Sstevel@tonic-gate 	if (need_to_close)
15817c478bd9Sstevel@tonic-gate 		(void) fclose(of);
15827c478bd9Sstevel@tonic-gate }
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate void
15857c478bd9Sstevel@tonic-gate exit_func(cmd_t *cmd)
15867c478bd9Sstevel@tonic-gate {
15877c478bd9Sstevel@tonic-gate 	int arg, answer;
15887c478bd9Sstevel@tonic-gate 
15897c478bd9Sstevel@tonic-gate 	optind = 0;
15907c478bd9Sstevel@tonic-gate 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
15917c478bd9Sstevel@tonic-gate 		switch (arg) {
15927c478bd9Sstevel@tonic-gate 		case '?':
15937c478bd9Sstevel@tonic-gate 			longer_usage(CMD_EXIT);
15947c478bd9Sstevel@tonic-gate 			return;
15957c478bd9Sstevel@tonic-gate 		case 'F':
15967c478bd9Sstevel@tonic-gate 			force_exit = TRUE;
15977c478bd9Sstevel@tonic-gate 			break;
15987c478bd9Sstevel@tonic-gate 		default:
15997c478bd9Sstevel@tonic-gate 			short_usage(CMD_EXIT);
16007c478bd9Sstevel@tonic-gate 			return;
16017c478bd9Sstevel@tonic-gate 		}
16027c478bd9Sstevel@tonic-gate 	}
16037c478bd9Sstevel@tonic-gate 	if (optind < cmd->cmd_argc) {
16047c478bd9Sstevel@tonic-gate 		short_usage(CMD_EXIT);
16057c478bd9Sstevel@tonic-gate 		return;
16067c478bd9Sstevel@tonic-gate 	}
16077c478bd9Sstevel@tonic-gate 
16087c478bd9Sstevel@tonic-gate 	if (global_scope || force_exit) {
16097c478bd9Sstevel@tonic-gate 		time_to_exit = TRUE;
16107c478bd9Sstevel@tonic-gate 		return;
16117c478bd9Sstevel@tonic-gate 	}
16127c478bd9Sstevel@tonic-gate 
16137c478bd9Sstevel@tonic-gate 	answer = ask_yesno(FALSE, "Resource incomplete; really quit");
16147c478bd9Sstevel@tonic-gate 	if (answer == -1) {
16157c478bd9Sstevel@tonic-gate 		zerr(gettext("Resource incomplete, input "
16167c478bd9Sstevel@tonic-gate 		    "not from terminal and -F not specified:\n%s command "
16177c478bd9Sstevel@tonic-gate 		    "ignored, but exiting anyway."), cmd_to_str(CMD_EXIT));
16187c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
16197c478bd9Sstevel@tonic-gate 	} else if (answer == 1) {
16207c478bd9Sstevel@tonic-gate 		time_to_exit = TRUE;
16217c478bd9Sstevel@tonic-gate 	}
16227c478bd9Sstevel@tonic-gate 	/* (answer == 0) => just return */
16237c478bd9Sstevel@tonic-gate }
16247c478bd9Sstevel@tonic-gate 
16257c478bd9Sstevel@tonic-gate static int
16267c478bd9Sstevel@tonic-gate validate_zonepath_syntax(char *path)
16277c478bd9Sstevel@tonic-gate {
16287c478bd9Sstevel@tonic-gate 	if (path[0] != '/') {
16297c478bd9Sstevel@tonic-gate 		zerr(gettext("%s is not an absolute path."), path);
16307c478bd9Sstevel@tonic-gate 		return (Z_ERR);
16317c478bd9Sstevel@tonic-gate 	}
16327c478bd9Sstevel@tonic-gate 	if (strcmp(path, "/") == 0) {
16337c478bd9Sstevel@tonic-gate 		zerr(gettext("/ is not allowed as a %s."),
16347c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_ZONEPATH));
16357c478bd9Sstevel@tonic-gate 		return (Z_ERR);
16367c478bd9Sstevel@tonic-gate 	}
16377c478bd9Sstevel@tonic-gate 	return (Z_OK);
16387c478bd9Sstevel@tonic-gate }
16397c478bd9Sstevel@tonic-gate 
16407c478bd9Sstevel@tonic-gate static void
16417c478bd9Sstevel@tonic-gate add_resource(cmd_t *cmd)
16427c478bd9Sstevel@tonic-gate {
16437c478bd9Sstevel@tonic-gate 	int type;
16447c478bd9Sstevel@tonic-gate 
16457c478bd9Sstevel@tonic-gate 	if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
16467c478bd9Sstevel@tonic-gate 		long_usage(CMD_ADD, TRUE);
16477c478bd9Sstevel@tonic-gate 		goto bad;
16487c478bd9Sstevel@tonic-gate 	}
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate 	switch (type) {
16517c478bd9Sstevel@tonic-gate 	case RT_FS:
16527c478bd9Sstevel@tonic-gate 		bzero(&in_progress_fstab, sizeof (in_progress_fstab));
16537c478bd9Sstevel@tonic-gate 		return;
16547c478bd9Sstevel@tonic-gate 	case RT_IPD:
1655087719fdSdp 		if (state_atleast(ZONE_STATE_INSTALLED)) {
16567c478bd9Sstevel@tonic-gate 			zerr(gettext("Zone %s already installed; %s %s not "
16577c478bd9Sstevel@tonic-gate 			    "allowed."), zone, cmd_to_str(CMD_ADD),
16587c478bd9Sstevel@tonic-gate 			    rt_to_str(RT_IPD));
16597c478bd9Sstevel@tonic-gate 			goto bad;
16607c478bd9Sstevel@tonic-gate 		}
16617c478bd9Sstevel@tonic-gate 		bzero(&in_progress_ipdtab, sizeof (in_progress_ipdtab));
16627c478bd9Sstevel@tonic-gate 		return;
16637c478bd9Sstevel@tonic-gate 	case RT_NET:
16647c478bd9Sstevel@tonic-gate 		bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
16657c478bd9Sstevel@tonic-gate 		return;
16667c478bd9Sstevel@tonic-gate 	case RT_DEVICE:
16677c478bd9Sstevel@tonic-gate 		bzero(&in_progress_devtab, sizeof (in_progress_devtab));
16687c478bd9Sstevel@tonic-gate 		return;
16697c478bd9Sstevel@tonic-gate 	case RT_RCTL:
16707c478bd9Sstevel@tonic-gate 		bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
16717c478bd9Sstevel@tonic-gate 		return;
16727c478bd9Sstevel@tonic-gate 	case RT_ATTR:
16737c478bd9Sstevel@tonic-gate 		bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
16747c478bd9Sstevel@tonic-gate 		return;
1675fa9e4066Sahrens 	case RT_DATASET:
1676fa9e4066Sahrens 		bzero(&in_progress_dstab, sizeof (in_progress_dstab));
1677fa9e4066Sahrens 		return;
16787c478bd9Sstevel@tonic-gate 	default:
16797c478bd9Sstevel@tonic-gate 		zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, TRUE);
16807c478bd9Sstevel@tonic-gate 		long_usage(CMD_ADD, TRUE);
16817c478bd9Sstevel@tonic-gate 		usage(FALSE, HELP_RESOURCES);
16827c478bd9Sstevel@tonic-gate 	}
16837c478bd9Sstevel@tonic-gate bad:
16847c478bd9Sstevel@tonic-gate 	global_scope = TRUE;
16857c478bd9Sstevel@tonic-gate 	end_op = -1;
16867c478bd9Sstevel@tonic-gate }
16877c478bd9Sstevel@tonic-gate 
16887c478bd9Sstevel@tonic-gate static void
16897c478bd9Sstevel@tonic-gate do_complex_rctl_val(complex_property_ptr_t cp)
16907c478bd9Sstevel@tonic-gate {
16917c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *rctlvaltab;
16927c478bd9Sstevel@tonic-gate 	complex_property_ptr_t cx;
16937c478bd9Sstevel@tonic-gate 	bool seen_priv = FALSE, seen_limit = FALSE, seen_action = FALSE;
16947c478bd9Sstevel@tonic-gate 	rctlblk_t *rctlblk;
16957c478bd9Sstevel@tonic-gate 	int err;
16967c478bd9Sstevel@tonic-gate 
16977c478bd9Sstevel@tonic-gate 	if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
16987c478bd9Sstevel@tonic-gate 		zone_perror(zone, Z_NOMEM, TRUE);
16997c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
17007c478bd9Sstevel@tonic-gate 	}
17017c478bd9Sstevel@tonic-gate 	for (cx = cp; cx != NULL; cx = cx->cp_next) {
17027c478bd9Sstevel@tonic-gate 		switch (cx->cp_type) {
17037c478bd9Sstevel@tonic-gate 		case PT_PRIV:
17047c478bd9Sstevel@tonic-gate 			if (seen_priv) {
17057c478bd9Sstevel@tonic-gate 				zerr(gettext("%s already specified"),
17067c478bd9Sstevel@tonic-gate 				    pt_to_str(PT_PRIV));
17077c478bd9Sstevel@tonic-gate 				goto bad;
17087c478bd9Sstevel@tonic-gate 			}
17097c478bd9Sstevel@tonic-gate 			(void) strlcpy(rctlvaltab->zone_rctlval_priv,
17107c478bd9Sstevel@tonic-gate 			    cx->cp_value,
17117c478bd9Sstevel@tonic-gate 			    sizeof (rctlvaltab->zone_rctlval_priv));
17127c478bd9Sstevel@tonic-gate 			seen_priv = TRUE;
17137c478bd9Sstevel@tonic-gate 			break;
17147c478bd9Sstevel@tonic-gate 		case PT_LIMIT:
17157c478bd9Sstevel@tonic-gate 			if (seen_limit) {
17167c478bd9Sstevel@tonic-gate 				zerr(gettext("%s already specified"),
17177c478bd9Sstevel@tonic-gate 				    pt_to_str(PT_LIMIT));
17187c478bd9Sstevel@tonic-gate 				goto bad;
17197c478bd9Sstevel@tonic-gate 			}
17207c478bd9Sstevel@tonic-gate 			(void) strlcpy(rctlvaltab->zone_rctlval_limit,
17217c478bd9Sstevel@tonic-gate 			    cx->cp_value,
17227c478bd9Sstevel@tonic-gate 			    sizeof (rctlvaltab->zone_rctlval_limit));
17237c478bd9Sstevel@tonic-gate 			seen_limit = TRUE;
17247c478bd9Sstevel@tonic-gate 			break;
17257c478bd9Sstevel@tonic-gate 		case PT_ACTION:
17267c478bd9Sstevel@tonic-gate 			if (seen_action) {
17277c478bd9Sstevel@tonic-gate 				zerr(gettext("%s already specified"),
17287c478bd9Sstevel@tonic-gate 				    pt_to_str(PT_ACTION));
17297c478bd9Sstevel@tonic-gate 				goto bad;
17307c478bd9Sstevel@tonic-gate 			}
17317c478bd9Sstevel@tonic-gate 			(void) strlcpy(rctlvaltab->zone_rctlval_action,
17327c478bd9Sstevel@tonic-gate 			    cx->cp_value,
17337c478bd9Sstevel@tonic-gate 			    sizeof (rctlvaltab->zone_rctlval_action));
17347c478bd9Sstevel@tonic-gate 			seen_action = TRUE;
17357c478bd9Sstevel@tonic-gate 			break;
17367c478bd9Sstevel@tonic-gate 		default:
17377c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(PT_VALUE),
17387c478bd9Sstevel@tonic-gate 			    Z_NO_PROPERTY_TYPE, TRUE);
17397c478bd9Sstevel@tonic-gate 			long_usage(CMD_ADD, TRUE);
17407c478bd9Sstevel@tonic-gate 			usage(FALSE, HELP_PROPS);
17417c478bd9Sstevel@tonic-gate 			zonecfg_free_rctl_value_list(rctlvaltab);
17427c478bd9Sstevel@tonic-gate 			return;
17437c478bd9Sstevel@tonic-gate 		}
17447c478bd9Sstevel@tonic-gate 	}
17457c478bd9Sstevel@tonic-gate 	if (!seen_priv)
17467c478bd9Sstevel@tonic-gate 		zerr(gettext("%s not specified"), pt_to_str(PT_PRIV));
17477c478bd9Sstevel@tonic-gate 	if (!seen_limit)
17487c478bd9Sstevel@tonic-gate 		zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT));
17497c478bd9Sstevel@tonic-gate 	if (!seen_action)
17507c478bd9Sstevel@tonic-gate 		zerr(gettext("%s not specified"), pt_to_str(PT_ACTION));
17517c478bd9Sstevel@tonic-gate 	if (!seen_priv || !seen_limit || !seen_action)
17527c478bd9Sstevel@tonic-gate 		goto bad;
17537c478bd9Sstevel@tonic-gate 	rctlvaltab->zone_rctlval_next = NULL;
17547c478bd9Sstevel@tonic-gate 	rctlblk = alloca(rctlblk_size());
17557c478bd9Sstevel@tonic-gate 	/*
17567c478bd9Sstevel@tonic-gate 	 * Make sure the rctl value looks roughly correct; we won't know if
17577c478bd9Sstevel@tonic-gate 	 * it's truly OK until we verify the configuration on the target
17587c478bd9Sstevel@tonic-gate 	 * system.
17597c478bd9Sstevel@tonic-gate 	 */
17607c478bd9Sstevel@tonic-gate 	if (zonecfg_construct_rctlblk(rctlvaltab, rctlblk) != Z_OK ||
17617c478bd9Sstevel@tonic-gate 	    !zonecfg_valid_rctlblk(rctlblk)) {
17627c478bd9Sstevel@tonic-gate 		zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL),
17637c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_VALUE));
17647c478bd9Sstevel@tonic-gate 		goto bad;
17657c478bd9Sstevel@tonic-gate 	}
17667c478bd9Sstevel@tonic-gate 	err = zonecfg_add_rctl_value(&in_progress_rctltab, rctlvaltab);
17677c478bd9Sstevel@tonic-gate 	if (err != Z_OK)
17687c478bd9Sstevel@tonic-gate 		zone_perror(pt_to_str(PT_VALUE), err, TRUE);
17697c478bd9Sstevel@tonic-gate 	return;
17707c478bd9Sstevel@tonic-gate 
17717c478bd9Sstevel@tonic-gate bad:
17727c478bd9Sstevel@tonic-gate 	zonecfg_free_rctl_value_list(rctlvaltab);
17737c478bd9Sstevel@tonic-gate }
17747c478bd9Sstevel@tonic-gate 
17757c478bd9Sstevel@tonic-gate static void
17767c478bd9Sstevel@tonic-gate add_property(cmd_t *cmd)
17777c478bd9Sstevel@tonic-gate {
17787c478bd9Sstevel@tonic-gate 	char *prop_id;
17797c478bd9Sstevel@tonic-gate 	int err, res_type, prop_type;
17807c478bd9Sstevel@tonic-gate 	property_value_ptr_t pp;
17817c478bd9Sstevel@tonic-gate 	list_property_ptr_t l;
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 	res_type = resource_scope;
17847c478bd9Sstevel@tonic-gate 	prop_type = cmd->cmd_prop_name[0];
17857c478bd9Sstevel@tonic-gate 	if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
17867c478bd9Sstevel@tonic-gate 		long_usage(CMD_ADD, TRUE);
17877c478bd9Sstevel@tonic-gate 		return;
17887c478bd9Sstevel@tonic-gate 	}
17897c478bd9Sstevel@tonic-gate 
17907c478bd9Sstevel@tonic-gate 	if (cmd->cmd_prop_nv_pairs != 1) {
17917c478bd9Sstevel@tonic-gate 		long_usage(CMD_ADD, TRUE);
17927c478bd9Sstevel@tonic-gate 		return;
17937c478bd9Sstevel@tonic-gate 	}
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate 	if (initialize(TRUE) != Z_OK)
17967c478bd9Sstevel@tonic-gate 		return;
17977c478bd9Sstevel@tonic-gate 
17987c478bd9Sstevel@tonic-gate 	switch (res_type) {
17997c478bd9Sstevel@tonic-gate 	case RT_FS:
18007c478bd9Sstevel@tonic-gate 		if (prop_type != PT_OPTIONS) {
18017c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
18027c478bd9Sstevel@tonic-gate 			    TRUE);
18037c478bd9Sstevel@tonic-gate 			long_usage(CMD_ADD, TRUE);
18047c478bd9Sstevel@tonic-gate 			usage(FALSE, HELP_PROPS);
18057c478bd9Sstevel@tonic-gate 			return;
18067c478bd9Sstevel@tonic-gate 		}
18077c478bd9Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[0];
18087c478bd9Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE &&
18097c478bd9Sstevel@tonic-gate 		    pp->pv_type != PROP_VAL_LIST) {
18107c478bd9Sstevel@tonic-gate 			zerr(gettext("A %s or %s value was expected here."),
18117c478bd9Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_SIMPLE),
18127c478bd9Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_LIST));
18137c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
18147c478bd9Sstevel@tonic-gate 			return;
18157c478bd9Sstevel@tonic-gate 		}
18167c478bd9Sstevel@tonic-gate 		if (pp->pv_type == PROP_VAL_SIMPLE) {
18177c478bd9Sstevel@tonic-gate 			if (pp->pv_simple == NULL) {
18187c478bd9Sstevel@tonic-gate 				long_usage(CMD_ADD, TRUE);
18197c478bd9Sstevel@tonic-gate 				return;
18207c478bd9Sstevel@tonic-gate 			}
18217c478bd9Sstevel@tonic-gate 			prop_id = pp->pv_simple;
18227c478bd9Sstevel@tonic-gate 			err = zonecfg_add_fs_option(&in_progress_fstab,
18237c478bd9Sstevel@tonic-gate 			    prop_id);
18247c478bd9Sstevel@tonic-gate 			if (err != Z_OK)
18257c478bd9Sstevel@tonic-gate 				zone_perror(pt_to_str(prop_type), err, TRUE);
18267c478bd9Sstevel@tonic-gate 		} else {
18277c478bd9Sstevel@tonic-gate 			list_property_ptr_t list;
18287c478bd9Sstevel@tonic-gate 
18297c478bd9Sstevel@tonic-gate 			for (list = pp->pv_list; list != NULL;
18307c478bd9Sstevel@tonic-gate 			    list = list->lp_next) {
18317c478bd9Sstevel@tonic-gate 				prop_id = list->lp_simple;
18327c478bd9Sstevel@tonic-gate 				if (prop_id == NULL)
18337c478bd9Sstevel@tonic-gate 					break;
18347c478bd9Sstevel@tonic-gate 				err = zonecfg_add_fs_option(
18357c478bd9Sstevel@tonic-gate 				    &in_progress_fstab, prop_id);
18367c478bd9Sstevel@tonic-gate 				if (err != Z_OK)
18377c478bd9Sstevel@tonic-gate 					zone_perror(pt_to_str(prop_type), err,
18387c478bd9Sstevel@tonic-gate 					    TRUE);
18397c478bd9Sstevel@tonic-gate 			}
18407c478bd9Sstevel@tonic-gate 		}
18417c478bd9Sstevel@tonic-gate 		return;
18427c478bd9Sstevel@tonic-gate 	case RT_RCTL:
18437c478bd9Sstevel@tonic-gate 		if (prop_type != PT_VALUE) {
18447c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
18457c478bd9Sstevel@tonic-gate 			    TRUE);
18467c478bd9Sstevel@tonic-gate 			long_usage(CMD_ADD, TRUE);
18477c478bd9Sstevel@tonic-gate 			usage(FALSE, HELP_PROPS);
18487c478bd9Sstevel@tonic-gate 			return;
18497c478bd9Sstevel@tonic-gate 		}
18507c478bd9Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[0];
18517c478bd9Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_COMPLEX &&
18527c478bd9Sstevel@tonic-gate 		    pp->pv_type != PROP_VAL_LIST) {
18537c478bd9Sstevel@tonic-gate 			zerr(gettext("A %s or %s value was expected here."),
18547c478bd9Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_COMPLEX),
18557c478bd9Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_LIST));
18567c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
18577c478bd9Sstevel@tonic-gate 			return;
18587c478bd9Sstevel@tonic-gate 		}
18597c478bd9Sstevel@tonic-gate 		if (pp->pv_type == PROP_VAL_COMPLEX) {
18607c478bd9Sstevel@tonic-gate 			do_complex_rctl_val(pp->pv_complex);
18617c478bd9Sstevel@tonic-gate 			return;
18627c478bd9Sstevel@tonic-gate 		}
18637c478bd9Sstevel@tonic-gate 		for (l = pp->pv_list; l != NULL; l = l->lp_next)
18647c478bd9Sstevel@tonic-gate 			do_complex_rctl_val(l->lp_complex);
18657c478bd9Sstevel@tonic-gate 		return;
18667c478bd9Sstevel@tonic-gate 	default:
18677c478bd9Sstevel@tonic-gate 		zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, TRUE);
18687c478bd9Sstevel@tonic-gate 		long_usage(CMD_ADD, TRUE);
18697c478bd9Sstevel@tonic-gate 		usage(FALSE, HELP_RESOURCES);
18707c478bd9Sstevel@tonic-gate 		return;
18717c478bd9Sstevel@tonic-gate 	}
18727c478bd9Sstevel@tonic-gate }
18737c478bd9Sstevel@tonic-gate 
18747c478bd9Sstevel@tonic-gate void
18757c478bd9Sstevel@tonic-gate add_func(cmd_t *cmd)
18767c478bd9Sstevel@tonic-gate {
18777c478bd9Sstevel@tonic-gate 	int arg;
18787c478bd9Sstevel@tonic-gate 
18797c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
18807c478bd9Sstevel@tonic-gate 
18817c478bd9Sstevel@tonic-gate 	optind = 0;
18827c478bd9Sstevel@tonic-gate 	if ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
18837c478bd9Sstevel@tonic-gate 		switch (arg) {
18847c478bd9Sstevel@tonic-gate 		case '?':
18857c478bd9Sstevel@tonic-gate 			longer_usage(CMD_ADD);
18867c478bd9Sstevel@tonic-gate 			return;
18877c478bd9Sstevel@tonic-gate 		default:
18887c478bd9Sstevel@tonic-gate 			short_usage(CMD_ADD);
18897c478bd9Sstevel@tonic-gate 			return;
18907c478bd9Sstevel@tonic-gate 		}
18917c478bd9Sstevel@tonic-gate 	}
18927c478bd9Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
18937c478bd9Sstevel@tonic-gate 		short_usage(CMD_ADD);
18947c478bd9Sstevel@tonic-gate 		return;
18957c478bd9Sstevel@tonic-gate 	}
18967c478bd9Sstevel@tonic-gate 
18977c478bd9Sstevel@tonic-gate 	if (zone_is_read_only(CMD_ADD))
18987c478bd9Sstevel@tonic-gate 		return;
18997c478bd9Sstevel@tonic-gate 
19007c478bd9Sstevel@tonic-gate 	if (initialize(TRUE) != Z_OK)
19017c478bd9Sstevel@tonic-gate 		return;
19027c478bd9Sstevel@tonic-gate 	if (global_scope) {
19037c478bd9Sstevel@tonic-gate 		global_scope = FALSE;
19047c478bd9Sstevel@tonic-gate 		resource_scope = cmd->cmd_res_type;
19057c478bd9Sstevel@tonic-gate 		end_op = CMD_ADD;
19067c478bd9Sstevel@tonic-gate 		add_resource(cmd);
19077c478bd9Sstevel@tonic-gate 	} else
19087c478bd9Sstevel@tonic-gate 		add_property(cmd);
19097c478bd9Sstevel@tonic-gate }
19107c478bd9Sstevel@tonic-gate 
1911087719fdSdp /*
1912087719fdSdp  * This routine has an unusual implementation, because it tries very
1913087719fdSdp  * hard to succeed in the face of a variety of failure modes.
1914087719fdSdp  * The most common and most vexing occurs when the index file and
1915087719fdSdp  * the /etc/zones/<zonename.xml> file are not both present.  In
1916087719fdSdp  * this case, delete must eradicate as much of the zone state as is left
1917087719fdSdp  * so that the user can later create a new zone with the same name.
1918087719fdSdp  */
19197c478bd9Sstevel@tonic-gate void
19207c478bd9Sstevel@tonic-gate delete_func(cmd_t *cmd)
19217c478bd9Sstevel@tonic-gate {
19227c478bd9Sstevel@tonic-gate 	int err, arg, answer;
19237c478bd9Sstevel@tonic-gate 	char line[ZONENAME_MAX + 128];	/* enough to ask a question */
19247c478bd9Sstevel@tonic-gate 	bool force = FALSE;
19257c478bd9Sstevel@tonic-gate 
19267c478bd9Sstevel@tonic-gate 	optind = 0;
19277c478bd9Sstevel@tonic-gate 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
19287c478bd9Sstevel@tonic-gate 		switch (arg) {
19297c478bd9Sstevel@tonic-gate 		case '?':
19307c478bd9Sstevel@tonic-gate 			longer_usage(CMD_DELETE);
19317c478bd9Sstevel@tonic-gate 			return;
19327c478bd9Sstevel@tonic-gate 		case 'F':
19337c478bd9Sstevel@tonic-gate 			force = TRUE;
19347c478bd9Sstevel@tonic-gate 			break;
19357c478bd9Sstevel@tonic-gate 		default:
19367c478bd9Sstevel@tonic-gate 			short_usage(CMD_DELETE);
19377c478bd9Sstevel@tonic-gate 			return;
19387c478bd9Sstevel@tonic-gate 		}
19397c478bd9Sstevel@tonic-gate 	}
19407c478bd9Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
19417c478bd9Sstevel@tonic-gate 		short_usage(CMD_DELETE);
19427c478bd9Sstevel@tonic-gate 		return;
19437c478bd9Sstevel@tonic-gate 	}
19447c478bd9Sstevel@tonic-gate 
19457c478bd9Sstevel@tonic-gate 	if (zone_is_read_only(CMD_DELETE))
19467c478bd9Sstevel@tonic-gate 		return;
19477c478bd9Sstevel@tonic-gate 
19487c478bd9Sstevel@tonic-gate 	if (!force) {
1949087719fdSdp 		/*
1950087719fdSdp 		 * Initialize sets up the global called "handle" and warns the
1951087719fdSdp 		 * user if the zone is not configured.  In force mode, we don't
1952087719fdSdp 		 * trust that evaluation, and hence skip it.  (We don't need the
1953087719fdSdp 		 * handle to be loaded anyway, since zonecfg_destroy is done by
1954087719fdSdp 		 * zonename).  However, we also have to take care to emulate the
1955087719fdSdp 		 * messages spit out by initialize; see below.
1956087719fdSdp 		 */
1957087719fdSdp 		if (initialize(TRUE) != Z_OK)
1958087719fdSdp 			return;
1959087719fdSdp 
19607c478bd9Sstevel@tonic-gate 		(void) snprintf(line, sizeof (line),
19617c478bd9Sstevel@tonic-gate 		    gettext("Are you sure you want to delete zone %s"), zone);
19627c478bd9Sstevel@tonic-gate 		if ((answer = ask_yesno(FALSE, line)) == -1) {
1963087719fdSdp 			zerr(gettext("Input not from terminal and -F not "
1964087719fdSdp 			    "specified:\n%s command ignored, exiting."),
1965087719fdSdp 			    cmd_to_str(CMD_DELETE));
19667c478bd9Sstevel@tonic-gate 			exit(Z_ERR);
19677c478bd9Sstevel@tonic-gate 		}
19687c478bd9Sstevel@tonic-gate 		if (answer != 1)
19697c478bd9Sstevel@tonic-gate 			return;
19707c478bd9Sstevel@tonic-gate 	}
19717c478bd9Sstevel@tonic-gate 
1972087719fdSdp 	if ((err = zonecfg_destroy(zone, force)) != Z_OK) {
1973087719fdSdp 		if ((err == Z_BAD_ZONE_STATE) && !force) {
1974087719fdSdp 			zerr(gettext("Zone %s not in %s state; %s not "
1975087719fdSdp 			    "allowed.  Use -F to force %s."),
1976087719fdSdp 			    zone, zone_state_str(ZONE_STATE_CONFIGURED),
1977087719fdSdp 			    cmd_to_str(CMD_DELETE), cmd_to_str(CMD_DELETE));
1978087719fdSdp 		} else {
1979087719fdSdp 			zone_perror(zone, err, TRUE);
1980087719fdSdp 		}
19817c478bd9Sstevel@tonic-gate 	}
19827c478bd9Sstevel@tonic-gate 	need_to_commit = FALSE;
1983087719fdSdp 
1984087719fdSdp 	/*
1985087719fdSdp 	 * Emulate initialize's messaging; if there wasn't a valid handle to
1986087719fdSdp 	 * begin with, then user had typed delete (or delete -F) multiple
1987087719fdSdp 	 * times.  So we emit a message.
1988087719fdSdp 	 *
1989087719fdSdp 	 * We only do this in the 'force' case because normally, initialize()
1990087719fdSdp 	 * takes care of this for us.
1991087719fdSdp 	 */
1992087719fdSdp 	if (force && zonecfg_check_handle(handle) != Z_OK && interactive_mode)
1993087719fdSdp 		(void) printf(gettext("Use '%s' to begin "
1994087719fdSdp 		    "configuring a new zone.\n"), cmd_to_str(CMD_CREATE));
19957c478bd9Sstevel@tonic-gate 
19967c478bd9Sstevel@tonic-gate 	/*
19977c478bd9Sstevel@tonic-gate 	 * Time for a new handle: finish the old one off first
19987c478bd9Sstevel@tonic-gate 	 * then get a new one properly to avoid leaks.
19997c478bd9Sstevel@tonic-gate 	 */
2000087719fdSdp 	if (got_handle) {
2001087719fdSdp 		zonecfg_fini_handle(handle);
2002087719fdSdp 		if ((handle = zonecfg_init_handle()) == NULL) {
2003087719fdSdp 			zone_perror(execname, Z_NOMEM, TRUE);
2004087719fdSdp 			exit(Z_ERR);
2005087719fdSdp 		}
2006087719fdSdp 		if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) {
2007087719fdSdp 			/* If there was no zone before, that's OK */
2008087719fdSdp 			if (err != Z_NO_ZONE)
2009087719fdSdp 				zone_perror(zone, err, TRUE);
2010087719fdSdp 			got_handle = FALSE;
2011087719fdSdp 		}
20127c478bd9Sstevel@tonic-gate 	}
20137c478bd9Sstevel@tonic-gate }
20147c478bd9Sstevel@tonic-gate 
20157c478bd9Sstevel@tonic-gate static int
20167c478bd9Sstevel@tonic-gate fill_in_fstab(cmd_t *cmd, struct zone_fstab *fstab, bool fill_in_only)
20177c478bd9Sstevel@tonic-gate {
20187c478bd9Sstevel@tonic-gate 	int err, i;
20197c478bd9Sstevel@tonic-gate 	property_value_ptr_t pp;
20207c478bd9Sstevel@tonic-gate 
20217c478bd9Sstevel@tonic-gate 	if ((err = initialize(TRUE)) != Z_OK)
20227c478bd9Sstevel@tonic-gate 		return (err);
20237c478bd9Sstevel@tonic-gate 
2024e193d1e6Svp 	bzero(fstab, sizeof (*fstab));
20257c478bd9Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
20267c478bd9Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[i];
20277c478bd9Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
20287c478bd9Sstevel@tonic-gate 			zerr(gettext("A simple value was expected here."));
20297c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
20307c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
20317c478bd9Sstevel@tonic-gate 		}
20327c478bd9Sstevel@tonic-gate 		switch (cmd->cmd_prop_name[i]) {
20337c478bd9Sstevel@tonic-gate 		case PT_DIR:
20347c478bd9Sstevel@tonic-gate 			(void) strlcpy(fstab->zone_fs_dir, pp->pv_simple,
20357c478bd9Sstevel@tonic-gate 			    sizeof (fstab->zone_fs_dir));
20367c478bd9Sstevel@tonic-gate 			break;
20377c478bd9Sstevel@tonic-gate 		case PT_SPECIAL:
20387c478bd9Sstevel@tonic-gate 			(void) strlcpy(fstab->zone_fs_special, pp->pv_simple,
20397c478bd9Sstevel@tonic-gate 			    sizeof (fstab->zone_fs_special));
20407c478bd9Sstevel@tonic-gate 			break;
20417c478bd9Sstevel@tonic-gate 		case PT_RAW:
20427c478bd9Sstevel@tonic-gate 			(void) strlcpy(fstab->zone_fs_raw, pp->pv_simple,
20437c478bd9Sstevel@tonic-gate 			    sizeof (fstab->zone_fs_raw));
20447c478bd9Sstevel@tonic-gate 			break;
20457c478bd9Sstevel@tonic-gate 		case PT_TYPE:
20467c478bd9Sstevel@tonic-gate 			(void) strlcpy(fstab->zone_fs_type, pp->pv_simple,
20477c478bd9Sstevel@tonic-gate 			    sizeof (fstab->zone_fs_type));
20487c478bd9Sstevel@tonic-gate 			break;
20497c478bd9Sstevel@tonic-gate 		default:
20507c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
20517c478bd9Sstevel@tonic-gate 			    Z_NO_PROPERTY_TYPE, TRUE);
20527c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
20537c478bd9Sstevel@tonic-gate 		}
20547c478bd9Sstevel@tonic-gate 	}
20557c478bd9Sstevel@tonic-gate 	if (fill_in_only)
20567c478bd9Sstevel@tonic-gate 		return (Z_OK);
20577c478bd9Sstevel@tonic-gate 	return (zonecfg_lookup_filesystem(handle, fstab));
20587c478bd9Sstevel@tonic-gate }
20597c478bd9Sstevel@tonic-gate 
20607c478bd9Sstevel@tonic-gate static int
20617c478bd9Sstevel@tonic-gate fill_in_ipdtab(cmd_t *cmd, struct zone_fstab *ipdtab, bool fill_in_only)
20627c478bd9Sstevel@tonic-gate {
20637c478bd9Sstevel@tonic-gate 	int err, i;
20647c478bd9Sstevel@tonic-gate 	property_value_ptr_t pp;
20657c478bd9Sstevel@tonic-gate 
20667c478bd9Sstevel@tonic-gate 	if ((err = initialize(TRUE)) != Z_OK)
20677c478bd9Sstevel@tonic-gate 		return (err);
20687c478bd9Sstevel@tonic-gate 
2069e193d1e6Svp 	bzero(ipdtab, sizeof (*ipdtab));
20707c478bd9Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
20717c478bd9Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[i];
20727c478bd9Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
20737c478bd9Sstevel@tonic-gate 			zerr(gettext("A simple value was expected here."));
20747c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
20757c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
20767c478bd9Sstevel@tonic-gate 		}
20777c478bd9Sstevel@tonic-gate 		switch (cmd->cmd_prop_name[i]) {
20787c478bd9Sstevel@tonic-gate 		case PT_DIR:
20797c478bd9Sstevel@tonic-gate 			(void) strlcpy(ipdtab->zone_fs_dir, pp->pv_simple,
20807c478bd9Sstevel@tonic-gate 			    sizeof (ipdtab->zone_fs_dir));
20817c478bd9Sstevel@tonic-gate 			break;
20827c478bd9Sstevel@tonic-gate 		default:
20837c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
20847c478bd9Sstevel@tonic-gate 			    Z_NO_PROPERTY_TYPE, TRUE);
20857c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
20867c478bd9Sstevel@tonic-gate 		}
20877c478bd9Sstevel@tonic-gate 	}
20887c478bd9Sstevel@tonic-gate 	if (fill_in_only)
20897c478bd9Sstevel@tonic-gate 		return (Z_OK);
20907c478bd9Sstevel@tonic-gate 	return (zonecfg_lookup_ipd(handle, ipdtab));
20917c478bd9Sstevel@tonic-gate }
20927c478bd9Sstevel@tonic-gate 
20937c478bd9Sstevel@tonic-gate static int
20947c478bd9Sstevel@tonic-gate fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab, bool fill_in_only)
20957c478bd9Sstevel@tonic-gate {
20967c478bd9Sstevel@tonic-gate 	int err, i;
20977c478bd9Sstevel@tonic-gate 	property_value_ptr_t pp;
20987c478bd9Sstevel@tonic-gate 
20997c478bd9Sstevel@tonic-gate 	if ((err = initialize(TRUE)) != Z_OK)
21007c478bd9Sstevel@tonic-gate 		return (err);
21017c478bd9Sstevel@tonic-gate 
2102e193d1e6Svp 	bzero(nwiftab, sizeof (*nwiftab));
21037c478bd9Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
21047c478bd9Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[i];
21057c478bd9Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
21067c478bd9Sstevel@tonic-gate 			zerr(gettext("A simple value was expected here."));
21077c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
21087c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
21097c478bd9Sstevel@tonic-gate 		}
21107c478bd9Sstevel@tonic-gate 		switch (cmd->cmd_prop_name[i]) {
21117c478bd9Sstevel@tonic-gate 		case PT_ADDRESS:
21127c478bd9Sstevel@tonic-gate 			(void) strlcpy(nwiftab->zone_nwif_address,
21137c478bd9Sstevel@tonic-gate 			    pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
21147c478bd9Sstevel@tonic-gate 			break;
21157c478bd9Sstevel@tonic-gate 		case PT_PHYSICAL:
21167c478bd9Sstevel@tonic-gate 			(void) strlcpy(nwiftab->zone_nwif_physical,
21177c478bd9Sstevel@tonic-gate 			    pp->pv_simple,
21187c478bd9Sstevel@tonic-gate 			    sizeof (nwiftab->zone_nwif_physical));
21197c478bd9Sstevel@tonic-gate 			break;
21207c478bd9Sstevel@tonic-gate 		default:
21217c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
21227c478bd9Sstevel@tonic-gate 			    Z_NO_PROPERTY_TYPE, TRUE);
21237c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
21247c478bd9Sstevel@tonic-gate 		}
21257c478bd9Sstevel@tonic-gate 	}
21267c478bd9Sstevel@tonic-gate 	if (fill_in_only)
21277c478bd9Sstevel@tonic-gate 		return (Z_OK);
21287c478bd9Sstevel@tonic-gate 	err = zonecfg_lookup_nwif(handle, nwiftab);
21297c478bd9Sstevel@tonic-gate 	return (err);
21307c478bd9Sstevel@tonic-gate }
21317c478bd9Sstevel@tonic-gate 
21327c478bd9Sstevel@tonic-gate static int
21337c478bd9Sstevel@tonic-gate fill_in_devtab(cmd_t *cmd, struct zone_devtab *devtab, bool fill_in_only)
21347c478bd9Sstevel@tonic-gate {
21357c478bd9Sstevel@tonic-gate 	int err, i;
21367c478bd9Sstevel@tonic-gate 	property_value_ptr_t pp;
21377c478bd9Sstevel@tonic-gate 
21387c478bd9Sstevel@tonic-gate 	if ((err = initialize(TRUE)) != Z_OK)
21397c478bd9Sstevel@tonic-gate 		return (err);
21407c478bd9Sstevel@tonic-gate 
2141e193d1e6Svp 	bzero(devtab, sizeof (*devtab));
21427c478bd9Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
21437c478bd9Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[i];
21447c478bd9Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
21457c478bd9Sstevel@tonic-gate 			zerr(gettext("A simple value was expected here."));
21467c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
21477c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
21487c478bd9Sstevel@tonic-gate 		}
21497c478bd9Sstevel@tonic-gate 		switch (cmd->cmd_prop_name[i]) {
21507c478bd9Sstevel@tonic-gate 		case PT_MATCH:
21517c478bd9Sstevel@tonic-gate 			(void) strlcpy(devtab->zone_dev_match, pp->pv_simple,
21527c478bd9Sstevel@tonic-gate 			    sizeof (devtab->zone_dev_match));
21537c478bd9Sstevel@tonic-gate 			break;
21547c478bd9Sstevel@tonic-gate 		default:
21557c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
21567c478bd9Sstevel@tonic-gate 			    Z_NO_PROPERTY_TYPE, TRUE);
21577c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
21587c478bd9Sstevel@tonic-gate 		}
21597c478bd9Sstevel@tonic-gate 	}
21607c478bd9Sstevel@tonic-gate 	if (fill_in_only)
21617c478bd9Sstevel@tonic-gate 		return (Z_OK);
21627c478bd9Sstevel@tonic-gate 	err = zonecfg_lookup_dev(handle, devtab);
21637c478bd9Sstevel@tonic-gate 	return (err);
21647c478bd9Sstevel@tonic-gate }
21657c478bd9Sstevel@tonic-gate 
21667c478bd9Sstevel@tonic-gate static int
21677c478bd9Sstevel@tonic-gate fill_in_rctltab(cmd_t *cmd, struct zone_rctltab *rctltab, bool fill_in_only)
21687c478bd9Sstevel@tonic-gate {
21697c478bd9Sstevel@tonic-gate 	int err, i;
21707c478bd9Sstevel@tonic-gate 	property_value_ptr_t pp;
21717c478bd9Sstevel@tonic-gate 
21727c478bd9Sstevel@tonic-gate 	if ((err = initialize(TRUE)) != Z_OK)
21737c478bd9Sstevel@tonic-gate 		return (err);
21747c478bd9Sstevel@tonic-gate 
2175e193d1e6Svp 	bzero(rctltab, sizeof (*rctltab));
21767c478bd9Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
21777c478bd9Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[i];
21787c478bd9Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
21797c478bd9Sstevel@tonic-gate 			zerr(gettext("A simple value was expected here."));
21807c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
21817c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
21827c478bd9Sstevel@tonic-gate 		}
21837c478bd9Sstevel@tonic-gate 		switch (cmd->cmd_prop_name[i]) {
21847c478bd9Sstevel@tonic-gate 		case PT_NAME:
21857c478bd9Sstevel@tonic-gate 			(void) strlcpy(rctltab->zone_rctl_name, pp->pv_simple,
21867c478bd9Sstevel@tonic-gate 			    sizeof (rctltab->zone_rctl_name));
21877c478bd9Sstevel@tonic-gate 			break;
21887c478bd9Sstevel@tonic-gate 		default:
21897c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
21907c478bd9Sstevel@tonic-gate 			    Z_NO_PROPERTY_TYPE, TRUE);
21917c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
21927c478bd9Sstevel@tonic-gate 		}
21937c478bd9Sstevel@tonic-gate 	}
21947c478bd9Sstevel@tonic-gate 	if (fill_in_only)
21957c478bd9Sstevel@tonic-gate 		return (Z_OK);
21967c478bd9Sstevel@tonic-gate 	err = zonecfg_lookup_rctl(handle, rctltab);
21977c478bd9Sstevel@tonic-gate 	return (err);
21987c478bd9Sstevel@tonic-gate }
21997c478bd9Sstevel@tonic-gate 
22007c478bd9Sstevel@tonic-gate static int
22017c478bd9Sstevel@tonic-gate fill_in_attrtab(cmd_t *cmd, struct zone_attrtab *attrtab, bool fill_in_only)
22027c478bd9Sstevel@tonic-gate {
22037c478bd9Sstevel@tonic-gate 	int err, i;
22047c478bd9Sstevel@tonic-gate 	property_value_ptr_t pp;
22057c478bd9Sstevel@tonic-gate 
22067c478bd9Sstevel@tonic-gate 	if ((err = initialize(TRUE)) != Z_OK)
22077c478bd9Sstevel@tonic-gate 		return (err);
22087c478bd9Sstevel@tonic-gate 
2209e193d1e6Svp 	bzero(attrtab, sizeof (*attrtab));
22107c478bd9Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
22117c478bd9Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[i];
22127c478bd9Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
22137c478bd9Sstevel@tonic-gate 			zerr(gettext("A simple value was expected here."));
22147c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
22157c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
22167c478bd9Sstevel@tonic-gate 		}
22177c478bd9Sstevel@tonic-gate 		switch (cmd->cmd_prop_name[i]) {
22187c478bd9Sstevel@tonic-gate 		case PT_NAME:
22197c478bd9Sstevel@tonic-gate 			(void) strlcpy(attrtab->zone_attr_name, pp->pv_simple,
22207c478bd9Sstevel@tonic-gate 			    sizeof (attrtab->zone_attr_name));
22217c478bd9Sstevel@tonic-gate 			break;
22227c478bd9Sstevel@tonic-gate 		case PT_TYPE:
22237c478bd9Sstevel@tonic-gate 			(void) strlcpy(attrtab->zone_attr_type, pp->pv_simple,
22247c478bd9Sstevel@tonic-gate 			    sizeof (attrtab->zone_attr_type));
22257c478bd9Sstevel@tonic-gate 			break;
22267c478bd9Sstevel@tonic-gate 		case PT_VALUE:
22277c478bd9Sstevel@tonic-gate 			(void) strlcpy(attrtab->zone_attr_value, pp->pv_simple,
22287c478bd9Sstevel@tonic-gate 			    sizeof (attrtab->zone_attr_value));
22297c478bd9Sstevel@tonic-gate 			break;
22307c478bd9Sstevel@tonic-gate 		default:
22317c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
22327c478bd9Sstevel@tonic-gate 			    Z_NO_PROPERTY_TYPE, TRUE);
22337c478bd9Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
22347c478bd9Sstevel@tonic-gate 		}
22357c478bd9Sstevel@tonic-gate 	}
22367c478bd9Sstevel@tonic-gate 	if (fill_in_only)
22377c478bd9Sstevel@tonic-gate 		return (Z_OK);
22387c478bd9Sstevel@tonic-gate 	err = zonecfg_lookup_attr(handle, attrtab);
22397c478bd9Sstevel@tonic-gate 	return (err);
22407c478bd9Sstevel@tonic-gate }
22417c478bd9Sstevel@tonic-gate 
2242fa9e4066Sahrens static int
2243fa9e4066Sahrens fill_in_dstab(cmd_t *cmd, struct zone_dstab *dstab, bool fill_in_only)
2244fa9e4066Sahrens {
2245fa9e4066Sahrens 	int err, i;
2246fa9e4066Sahrens 	property_value_ptr_t pp;
2247fa9e4066Sahrens 
2248fa9e4066Sahrens 	if ((err = initialize(TRUE)) != Z_OK)
2249fa9e4066Sahrens 		return (err);
2250fa9e4066Sahrens 
2251fa9e4066Sahrens 	dstab->zone_dataset_name[0] = '\0';
2252fa9e4066Sahrens 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2253fa9e4066Sahrens 		pp = cmd->cmd_property_ptr[i];
2254fa9e4066Sahrens 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2255fa9e4066Sahrens 			zerr(gettext("A simple value was expected here."));
2256fa9e4066Sahrens 			saw_error = TRUE;
2257fa9e4066Sahrens 			return (Z_INSUFFICIENT_SPEC);
2258fa9e4066Sahrens 		}
2259fa9e4066Sahrens 		switch (cmd->cmd_prop_name[i]) {
2260fa9e4066Sahrens 		case PT_NAME:
2261fa9e4066Sahrens 			(void) strlcpy(dstab->zone_dataset_name, pp->pv_simple,
2262fa9e4066Sahrens 			    sizeof (dstab->zone_dataset_name));
2263fa9e4066Sahrens 			break;
2264fa9e4066Sahrens 		default:
2265fa9e4066Sahrens 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2266fa9e4066Sahrens 			    Z_NO_PROPERTY_TYPE, TRUE);
2267fa9e4066Sahrens 			return (Z_INSUFFICIENT_SPEC);
2268fa9e4066Sahrens 		}
2269fa9e4066Sahrens 	}
2270fa9e4066Sahrens 	if (fill_in_only)
2271fa9e4066Sahrens 		return (Z_OK);
2272fa9e4066Sahrens 	return (zonecfg_lookup_ds(handle, dstab));
2273fa9e4066Sahrens }
2274fa9e4066Sahrens 
22757c478bd9Sstevel@tonic-gate static void
22767c478bd9Sstevel@tonic-gate remove_resource(cmd_t *cmd)
22777c478bd9Sstevel@tonic-gate {
22787c478bd9Sstevel@tonic-gate 	int err, type;
22797c478bd9Sstevel@tonic-gate 	struct zone_fstab fstab;
22807c478bd9Sstevel@tonic-gate 	struct zone_nwiftab nwiftab;
22817c478bd9Sstevel@tonic-gate 	struct zone_devtab devtab;
22827c478bd9Sstevel@tonic-gate 	struct zone_attrtab attrtab;
22837c478bd9Sstevel@tonic-gate 	struct zone_rctltab rctltab;
2284fa9e4066Sahrens 	struct zone_dstab dstab;
22857c478bd9Sstevel@tonic-gate 
22867c478bd9Sstevel@tonic-gate 	if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
22877c478bd9Sstevel@tonic-gate 		long_usage(CMD_REMOVE, TRUE);
22887c478bd9Sstevel@tonic-gate 		return;
22897c478bd9Sstevel@tonic-gate 	}
22907c478bd9Sstevel@tonic-gate 
22917c478bd9Sstevel@tonic-gate 	if (initialize(TRUE) != Z_OK)
22927c478bd9Sstevel@tonic-gate 		return;
22937c478bd9Sstevel@tonic-gate 
22947c478bd9Sstevel@tonic-gate 	switch (type) {
22957c478bd9Sstevel@tonic-gate 	case RT_FS:
22967c478bd9Sstevel@tonic-gate 		if ((err = fill_in_fstab(cmd, &fstab, FALSE)) != Z_OK) {
22977c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, TRUE);
22987c478bd9Sstevel@tonic-gate 			return;
22997c478bd9Sstevel@tonic-gate 		}
23007c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK)
23017c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, TRUE);
23027c478bd9Sstevel@tonic-gate 		else
23037c478bd9Sstevel@tonic-gate 			need_to_commit = TRUE;
23047c478bd9Sstevel@tonic-gate 		zonecfg_free_fs_option_list(fstab.zone_fs_options);
23057c478bd9Sstevel@tonic-gate 		return;
23067c478bd9Sstevel@tonic-gate 	case RT_IPD:
2307087719fdSdp 		if (state_atleast(ZONE_STATE_INSTALLED)) {
23087c478bd9Sstevel@tonic-gate 			zerr(gettext("Zone %s already installed; %s %s not "
23097c478bd9Sstevel@tonic-gate 			    "allowed."), zone, cmd_to_str(CMD_REMOVE),
23107c478bd9Sstevel@tonic-gate 			    rt_to_str(RT_IPD));
23117c478bd9Sstevel@tonic-gate 			return;
23127c478bd9Sstevel@tonic-gate 		}
23137c478bd9Sstevel@tonic-gate 		if ((err = fill_in_ipdtab(cmd, &fstab, FALSE)) != Z_OK) {
23147c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, TRUE);
23157c478bd9Sstevel@tonic-gate 			return;
23167c478bd9Sstevel@tonic-gate 		}
23177c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_delete_ipd(handle, &fstab)) != Z_OK)
23187c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, TRUE);
23197c478bd9Sstevel@tonic-gate 		else
23207c478bd9Sstevel@tonic-gate 			need_to_commit = TRUE;
23217c478bd9Sstevel@tonic-gate 		return;
23227c478bd9Sstevel@tonic-gate 	case RT_NET:
23237c478bd9Sstevel@tonic-gate 		if ((err = fill_in_nwiftab(cmd, &nwiftab, FALSE)) != Z_OK) {
23247c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, TRUE);
23257c478bd9Sstevel@tonic-gate 			return;
23267c478bd9Sstevel@tonic-gate 		}
23277c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK)
23287c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, TRUE);
23297c478bd9Sstevel@tonic-gate 		else
23307c478bd9Sstevel@tonic-gate 			need_to_commit = TRUE;
23317c478bd9Sstevel@tonic-gate 		return;
23327c478bd9Sstevel@tonic-gate 	case RT_DEVICE:
23337c478bd9Sstevel@tonic-gate 		if ((err = fill_in_devtab(cmd, &devtab, FALSE)) != Z_OK) {
23347c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, TRUE);
23357c478bd9Sstevel@tonic-gate 			return;
23367c478bd9Sstevel@tonic-gate 		}
23377c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK)
23387c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, TRUE);
23397c478bd9Sstevel@tonic-gate 		else
23407c478bd9Sstevel@tonic-gate 			need_to_commit = TRUE;
23417c478bd9Sstevel@tonic-gate 		return;
23427c478bd9Sstevel@tonic-gate 	case RT_RCTL:
23437c478bd9Sstevel@tonic-gate 		if ((err = fill_in_rctltab(cmd, &rctltab, FALSE)) != Z_OK) {
23447c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, TRUE);
23457c478bd9Sstevel@tonic-gate 			return;
23467c478bd9Sstevel@tonic-gate 		}
23477c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK)
23487c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, TRUE);
23497c478bd9Sstevel@tonic-gate 		else
23507c478bd9Sstevel@tonic-gate 			need_to_commit = TRUE;
23517c478bd9Sstevel@tonic-gate 		zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
23527c478bd9Sstevel@tonic-gate 		return;
23537c478bd9Sstevel@tonic-gate 	case RT_ATTR:
23547c478bd9Sstevel@tonic-gate 		if ((err = fill_in_attrtab(cmd, &attrtab, FALSE)) != Z_OK) {
23557c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, TRUE);
23567c478bd9Sstevel@tonic-gate 			return;
23577c478bd9Sstevel@tonic-gate 		}
23587c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK)
23597c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, TRUE);
23607c478bd9Sstevel@tonic-gate 		else
23617c478bd9Sstevel@tonic-gate 			need_to_commit = TRUE;
23627c478bd9Sstevel@tonic-gate 		return;
2363fa9e4066Sahrens 	case RT_DATASET:
2364fa9e4066Sahrens 		if ((err = fill_in_dstab(cmd, &dstab, FALSE)) != Z_OK) {
2365fa9e4066Sahrens 			z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, TRUE);
2366fa9e4066Sahrens 			return;
2367fa9e4066Sahrens 		}
2368fa9e4066Sahrens 		if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK)
2369fa9e4066Sahrens 			z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, TRUE);
2370fa9e4066Sahrens 		else
2371fa9e4066Sahrens 			need_to_commit = TRUE;
2372fa9e4066Sahrens 		return;
23737c478bd9Sstevel@tonic-gate 	default:
23747c478bd9Sstevel@tonic-gate 		zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, TRUE);
23757c478bd9Sstevel@tonic-gate 		long_usage(CMD_REMOVE, TRUE);
23767c478bd9Sstevel@tonic-gate 		usage(FALSE, HELP_RESOURCES);
23777c478bd9Sstevel@tonic-gate 		return;
23787c478bd9Sstevel@tonic-gate 	}
23797c478bd9Sstevel@tonic-gate }
23807c478bd9Sstevel@tonic-gate 
23817c478bd9Sstevel@tonic-gate static void
23827c478bd9Sstevel@tonic-gate remove_property(cmd_t *cmd)
23837c478bd9Sstevel@tonic-gate {
23847c478bd9Sstevel@tonic-gate 	char *prop_id;
23857c478bd9Sstevel@tonic-gate 	int err, res_type, prop_type;
23867c478bd9Sstevel@tonic-gate 	property_value_ptr_t pp;
23877c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *rctlvaltab;
23887c478bd9Sstevel@tonic-gate 	complex_property_ptr_t cx;
23897c478bd9Sstevel@tonic-gate 
23907c478bd9Sstevel@tonic-gate 	res_type = resource_scope;
23917c478bd9Sstevel@tonic-gate 	prop_type = cmd->cmd_prop_name[0];
23927c478bd9Sstevel@tonic-gate 	if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
23937c478bd9Sstevel@tonic-gate 		long_usage(CMD_REMOVE, TRUE);
23947c478bd9Sstevel@tonic-gate 		return;
23957c478bd9Sstevel@tonic-gate 	}
23967c478bd9Sstevel@tonic-gate 
23977c478bd9Sstevel@tonic-gate 	if (cmd->cmd_prop_nv_pairs != 1) {
23987c478bd9Sstevel@tonic-gate 		long_usage(CMD_ADD, TRUE);
23997c478bd9Sstevel@tonic-gate 		return;
24007c478bd9Sstevel@tonic-gate 	}
24017c478bd9Sstevel@tonic-gate 
24027c478bd9Sstevel@tonic-gate 	if (initialize(TRUE) != Z_OK)
24037c478bd9Sstevel@tonic-gate 		return;
24047c478bd9Sstevel@tonic-gate 
24057c478bd9Sstevel@tonic-gate 	switch (res_type) {
24067c478bd9Sstevel@tonic-gate 	case RT_FS:
24077c478bd9Sstevel@tonic-gate 		if (prop_type != PT_OPTIONS) {
24087c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
24097c478bd9Sstevel@tonic-gate 			    TRUE);
24107c478bd9Sstevel@tonic-gate 			long_usage(CMD_REMOVE, TRUE);
24117c478bd9Sstevel@tonic-gate 			usage(FALSE, HELP_PROPS);
24127c478bd9Sstevel@tonic-gate 			return;
24137c478bd9Sstevel@tonic-gate 		}
24147c478bd9Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[0];
24157c478bd9Sstevel@tonic-gate 		if (pp->pv_type == PROP_VAL_COMPLEX) {
24167c478bd9Sstevel@tonic-gate 			zerr(gettext("A %s or %s value was expected here."),
24177c478bd9Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_SIMPLE),
24187c478bd9Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_LIST));
24197c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
24207c478bd9Sstevel@tonic-gate 			return;
24217c478bd9Sstevel@tonic-gate 		}
24227c478bd9Sstevel@tonic-gate 		if (pp->pv_type == PROP_VAL_SIMPLE) {
24237c478bd9Sstevel@tonic-gate 			if (pp->pv_simple == NULL) {
24247c478bd9Sstevel@tonic-gate 				long_usage(CMD_ADD, TRUE);
24257c478bd9Sstevel@tonic-gate 				return;
24267c478bd9Sstevel@tonic-gate 			}
24277c478bd9Sstevel@tonic-gate 			prop_id = pp->pv_simple;
24287c478bd9Sstevel@tonic-gate 			err = zonecfg_remove_fs_option(&in_progress_fstab,
24297c478bd9Sstevel@tonic-gate 			    prop_id);
24307c478bd9Sstevel@tonic-gate 			if (err != Z_OK)
24317c478bd9Sstevel@tonic-gate 				zone_perror(pt_to_str(prop_type), err, TRUE);
24327c478bd9Sstevel@tonic-gate 		} else {
24337c478bd9Sstevel@tonic-gate 			list_property_ptr_t list;
24347c478bd9Sstevel@tonic-gate 
24357c478bd9Sstevel@tonic-gate 			for (list = pp->pv_list; list != NULL;
24367c478bd9Sstevel@tonic-gate 			    list = list->lp_next) {
24377c478bd9Sstevel@tonic-gate 				prop_id = list->lp_simple;
24387c478bd9Sstevel@tonic-gate 				if (prop_id == NULL)
24397c478bd9Sstevel@tonic-gate 					break;
24407c478bd9Sstevel@tonic-gate 				err = zonecfg_remove_fs_option(
24417c478bd9Sstevel@tonic-gate 				    &in_progress_fstab, prop_id);
24427c478bd9Sstevel@tonic-gate 				if (err != Z_OK)
24437c478bd9Sstevel@tonic-gate 					zone_perror(pt_to_str(prop_type), err,
24447c478bd9Sstevel@tonic-gate 					    TRUE);
24457c478bd9Sstevel@tonic-gate 			}
24467c478bd9Sstevel@tonic-gate 		}
24477c478bd9Sstevel@tonic-gate 		return;
24487c478bd9Sstevel@tonic-gate 	case RT_RCTL:
24497c478bd9Sstevel@tonic-gate 		if (prop_type != PT_VALUE) {
24507c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
24517c478bd9Sstevel@tonic-gate 			    TRUE);
24527c478bd9Sstevel@tonic-gate 			long_usage(CMD_REMOVE, TRUE);
24537c478bd9Sstevel@tonic-gate 			usage(FALSE, HELP_PROPS);
24547c478bd9Sstevel@tonic-gate 			return;
24557c478bd9Sstevel@tonic-gate 		}
24567c478bd9Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[0];
24577c478bd9Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_COMPLEX) {
24587c478bd9Sstevel@tonic-gate 			zerr(gettext("A %s value was expected here."),
24597c478bd9Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_COMPLEX));
24607c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
24617c478bd9Sstevel@tonic-gate 			return;
24627c478bd9Sstevel@tonic-gate 		}
24637c478bd9Sstevel@tonic-gate 		if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
24647c478bd9Sstevel@tonic-gate 			zone_perror(zone, Z_NOMEM, TRUE);
24657c478bd9Sstevel@tonic-gate 			exit(Z_ERR);
24667c478bd9Sstevel@tonic-gate 		}
24677c478bd9Sstevel@tonic-gate 		for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) {
24687c478bd9Sstevel@tonic-gate 			switch (cx->cp_type) {
24697c478bd9Sstevel@tonic-gate 			case PT_PRIV:
24707c478bd9Sstevel@tonic-gate 				(void) strlcpy(rctlvaltab->zone_rctlval_priv,
24717c478bd9Sstevel@tonic-gate 				    cx->cp_value,
24727c478bd9Sstevel@tonic-gate 				    sizeof (rctlvaltab->zone_rctlval_priv));
24737c478bd9Sstevel@tonic-gate 				break;
24747c478bd9Sstevel@tonic-gate 			case PT_LIMIT:
24757c478bd9Sstevel@tonic-gate 				(void) strlcpy(rctlvaltab->zone_rctlval_limit,
24767c478bd9Sstevel@tonic-gate 				    cx->cp_value,
24777c478bd9Sstevel@tonic-gate 				    sizeof (rctlvaltab->zone_rctlval_limit));
24787c478bd9Sstevel@tonic-gate 				break;
24797c478bd9Sstevel@tonic-gate 			case PT_ACTION:
24807c478bd9Sstevel@tonic-gate 				(void) strlcpy(rctlvaltab->zone_rctlval_action,
24817c478bd9Sstevel@tonic-gate 				    cx->cp_value,
24827c478bd9Sstevel@tonic-gate 				    sizeof (rctlvaltab->zone_rctlval_action));
24837c478bd9Sstevel@tonic-gate 				break;
24847c478bd9Sstevel@tonic-gate 			default:
24857c478bd9Sstevel@tonic-gate 				zone_perror(pt_to_str(prop_type),
24867c478bd9Sstevel@tonic-gate 				    Z_NO_PROPERTY_TYPE, TRUE);
24877c478bd9Sstevel@tonic-gate 				long_usage(CMD_ADD, TRUE);
24887c478bd9Sstevel@tonic-gate 				usage(FALSE, HELP_PROPS);
24897c478bd9Sstevel@tonic-gate 				zonecfg_free_rctl_value_list(rctlvaltab);
24907c478bd9Sstevel@tonic-gate 				return;
24917c478bd9Sstevel@tonic-gate 			}
24927c478bd9Sstevel@tonic-gate 		}
24937c478bd9Sstevel@tonic-gate 		rctlvaltab->zone_rctlval_next = NULL;
24947c478bd9Sstevel@tonic-gate 		err = zonecfg_remove_rctl_value(&in_progress_rctltab,
24957c478bd9Sstevel@tonic-gate 		    rctlvaltab);
24967c478bd9Sstevel@tonic-gate 		if (err != Z_OK)
24977c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), err, TRUE);
24987c478bd9Sstevel@tonic-gate 		zonecfg_free_rctl_value_list(rctlvaltab);
24997c478bd9Sstevel@tonic-gate 		return;
25007c478bd9Sstevel@tonic-gate 	default:
25017c478bd9Sstevel@tonic-gate 		zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, TRUE);
25027c478bd9Sstevel@tonic-gate 		long_usage(CMD_REMOVE, TRUE);
25037c478bd9Sstevel@tonic-gate 		usage(FALSE, HELP_RESOURCES);
25047c478bd9Sstevel@tonic-gate 		return;
25057c478bd9Sstevel@tonic-gate 	}
25067c478bd9Sstevel@tonic-gate }
25077c478bd9Sstevel@tonic-gate 
25087c478bd9Sstevel@tonic-gate void
25097c478bd9Sstevel@tonic-gate remove_func(cmd_t *cmd)
25107c478bd9Sstevel@tonic-gate {
25117c478bd9Sstevel@tonic-gate 	if (zone_is_read_only(CMD_REMOVE))
25127c478bd9Sstevel@tonic-gate 		return;
25137c478bd9Sstevel@tonic-gate 
25147c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
25157c478bd9Sstevel@tonic-gate 
25167c478bd9Sstevel@tonic-gate 	if (global_scope)
25177c478bd9Sstevel@tonic-gate 		remove_resource(cmd);
25187c478bd9Sstevel@tonic-gate 	else
25197c478bd9Sstevel@tonic-gate 		remove_property(cmd);
25207c478bd9Sstevel@tonic-gate }
25217c478bd9Sstevel@tonic-gate 
25227c478bd9Sstevel@tonic-gate void
25237c478bd9Sstevel@tonic-gate select_func(cmd_t *cmd)
25247c478bd9Sstevel@tonic-gate {
25257c478bd9Sstevel@tonic-gate 	int type, err;
25267c478bd9Sstevel@tonic-gate 
25277c478bd9Sstevel@tonic-gate 	if (zone_is_read_only(CMD_SELECT))
25287c478bd9Sstevel@tonic-gate 		return;
25297c478bd9Sstevel@tonic-gate 
25307c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
25317c478bd9Sstevel@tonic-gate 
25327c478bd9Sstevel@tonic-gate 	if (global_scope) {
25337c478bd9Sstevel@tonic-gate 		global_scope = FALSE;
25347c478bd9Sstevel@tonic-gate 		resource_scope = cmd->cmd_res_type;
25357c478bd9Sstevel@tonic-gate 		end_op = CMD_SELECT;
25367c478bd9Sstevel@tonic-gate 	} else {
25377c478bd9Sstevel@tonic-gate 		scope_usage(CMD_SELECT);
25387c478bd9Sstevel@tonic-gate 		return;
25397c478bd9Sstevel@tonic-gate 	}
25407c478bd9Sstevel@tonic-gate 
25417c478bd9Sstevel@tonic-gate 	if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
25427c478bd9Sstevel@tonic-gate 		long_usage(CMD_SELECT, TRUE);
25437c478bd9Sstevel@tonic-gate 		return;
25447c478bd9Sstevel@tonic-gate 	}
25457c478bd9Sstevel@tonic-gate 
25467c478bd9Sstevel@tonic-gate 	if (initialize(TRUE) != Z_OK)
25477c478bd9Sstevel@tonic-gate 		return;
25487c478bd9Sstevel@tonic-gate 
25497c478bd9Sstevel@tonic-gate 	switch (type) {
25507c478bd9Sstevel@tonic-gate 	case RT_FS:
25517c478bd9Sstevel@tonic-gate 		if ((err = fill_in_fstab(cmd, &old_fstab, FALSE)) != Z_OK) {
25527c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_SELECT, RT_FS, err, TRUE);
25537c478bd9Sstevel@tonic-gate 			global_scope = TRUE;
25547c478bd9Sstevel@tonic-gate 		}
25557c478bd9Sstevel@tonic-gate 		bcopy(&old_fstab, &in_progress_fstab,
25567c478bd9Sstevel@tonic-gate 		    sizeof (struct zone_fstab));
25577c478bd9Sstevel@tonic-gate 		return;
25587c478bd9Sstevel@tonic-gate 	case RT_IPD:
2559087719fdSdp 		if (state_atleast(ZONE_STATE_INCOMPLETE)) {
25607c478bd9Sstevel@tonic-gate 			zerr(gettext("Zone %s not in %s state; %s %s not "
25617c478bd9Sstevel@tonic-gate 			    "allowed."), zone,
25627c478bd9Sstevel@tonic-gate 			    zone_state_str(ZONE_STATE_CONFIGURED),
25637c478bd9Sstevel@tonic-gate 			    cmd_to_str(CMD_SELECT), rt_to_str(RT_IPD));
25647c478bd9Sstevel@tonic-gate 			global_scope = TRUE;
25657c478bd9Sstevel@tonic-gate 			end_op = -1;
25667c478bd9Sstevel@tonic-gate 			return;
25677c478bd9Sstevel@tonic-gate 		}
25687c478bd9Sstevel@tonic-gate 		if ((err = fill_in_ipdtab(cmd, &old_ipdtab, FALSE)) != Z_OK) {
25697c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_SELECT, RT_IPD, err, TRUE);
25707c478bd9Sstevel@tonic-gate 			global_scope = TRUE;
25717c478bd9Sstevel@tonic-gate 		}
25727c478bd9Sstevel@tonic-gate 		bcopy(&old_ipdtab, &in_progress_ipdtab,
25737c478bd9Sstevel@tonic-gate 		    sizeof (struct zone_fstab));
25747c478bd9Sstevel@tonic-gate 		return;
25757c478bd9Sstevel@tonic-gate 	case RT_NET:
25767c478bd9Sstevel@tonic-gate 		if ((err = fill_in_nwiftab(cmd, &old_nwiftab, FALSE)) != Z_OK) {
25777c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_SELECT, RT_NET, err, TRUE);
25787c478bd9Sstevel@tonic-gate 			global_scope = TRUE;
25797c478bd9Sstevel@tonic-gate 		}
25807c478bd9Sstevel@tonic-gate 		bcopy(&old_nwiftab, &in_progress_nwiftab,
25817c478bd9Sstevel@tonic-gate 		    sizeof (struct zone_nwiftab));
25827c478bd9Sstevel@tonic-gate 		return;
25837c478bd9Sstevel@tonic-gate 	case RT_DEVICE:
25847c478bd9Sstevel@tonic-gate 		if ((err = fill_in_devtab(cmd, &old_devtab, FALSE)) != Z_OK) {
25857c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_SELECT, RT_DEVICE, err, TRUE);
25867c478bd9Sstevel@tonic-gate 			global_scope = TRUE;
25877c478bd9Sstevel@tonic-gate 		}
25887c478bd9Sstevel@tonic-gate 		bcopy(&old_devtab, &in_progress_devtab,
25897c478bd9Sstevel@tonic-gate 		    sizeof (struct zone_devtab));
25907c478bd9Sstevel@tonic-gate 		return;
25917c478bd9Sstevel@tonic-gate 	case RT_RCTL:
25927c478bd9Sstevel@tonic-gate 		if ((err = fill_in_rctltab(cmd, &old_rctltab, FALSE)) != Z_OK) {
25937c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_SELECT, RT_RCTL, err, TRUE);
25947c478bd9Sstevel@tonic-gate 			global_scope = TRUE;
25957c478bd9Sstevel@tonic-gate 		}
25967c478bd9Sstevel@tonic-gate 		bcopy(&old_rctltab, &in_progress_rctltab,
25977c478bd9Sstevel@tonic-gate 		    sizeof (struct zone_rctltab));
25987c478bd9Sstevel@tonic-gate 		return;
25997c478bd9Sstevel@tonic-gate 	case RT_ATTR:
26007c478bd9Sstevel@tonic-gate 		if ((err = fill_in_attrtab(cmd, &old_attrtab, FALSE)) != Z_OK) {
26017c478bd9Sstevel@tonic-gate 			z_cmd_rt_perror(CMD_SELECT, RT_ATTR, err, TRUE);
26027c478bd9Sstevel@tonic-gate 			global_scope = TRUE;
26037c478bd9Sstevel@tonic-gate 		}
26047c478bd9Sstevel@tonic-gate 		bcopy(&old_attrtab, &in_progress_attrtab,
26057c478bd9Sstevel@tonic-gate 		    sizeof (struct zone_attrtab));
26067c478bd9Sstevel@tonic-gate 		return;
2607fa9e4066Sahrens 	case RT_DATASET:
2608fa9e4066Sahrens 		if ((err = fill_in_dstab(cmd, &old_dstab, FALSE)) != Z_OK) {
2609fa9e4066Sahrens 			z_cmd_rt_perror(CMD_SELECT, RT_DATASET, err, TRUE);
2610fa9e4066Sahrens 			global_scope = TRUE;
2611fa9e4066Sahrens 		}
2612fa9e4066Sahrens 		bcopy(&old_dstab, &in_progress_dstab,
2613fa9e4066Sahrens 		    sizeof (struct zone_dstab));
2614fa9e4066Sahrens 		return;
26157c478bd9Sstevel@tonic-gate 	default:
26167c478bd9Sstevel@tonic-gate 		zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, TRUE);
26177c478bd9Sstevel@tonic-gate 		long_usage(CMD_SELECT, TRUE);
26187c478bd9Sstevel@tonic-gate 		usage(FALSE, HELP_RESOURCES);
26197c478bd9Sstevel@tonic-gate 		return;
26207c478bd9Sstevel@tonic-gate 	}
26217c478bd9Sstevel@tonic-gate }
26227c478bd9Sstevel@tonic-gate 
26237c478bd9Sstevel@tonic-gate /*
26247c478bd9Sstevel@tonic-gate  * Network "addresses" can be one of the following forms:
26257c478bd9Sstevel@tonic-gate  *	<IPv4 address>
26267c478bd9Sstevel@tonic-gate  *	<IPv4 address>/<prefix length>
26277c478bd9Sstevel@tonic-gate  *	<IPv6 address>/<prefix length>
26287c478bd9Sstevel@tonic-gate  *	<host name>
26297c478bd9Sstevel@tonic-gate  *	<host name>/<prefix length>
26307c478bd9Sstevel@tonic-gate  * In other words, the "/" followed by a prefix length is allowed but not
26317c478bd9Sstevel@tonic-gate  * required for IPv4 addresses and host names, and required for IPv6 addresses.
26327c478bd9Sstevel@tonic-gate  * If a prefix length is given, it must be in the allowable range: 0 to 32 for
26337c478bd9Sstevel@tonic-gate  * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
26347c478bd9Sstevel@tonic-gate  * Host names must start with an alpha-numeric character, and all subsequent
26357c478bd9Sstevel@tonic-gate  * characters must be either alpha-numeric or "-".
26367c478bd9Sstevel@tonic-gate  */
26377c478bd9Sstevel@tonic-gate 
26387c478bd9Sstevel@tonic-gate static int
26397c478bd9Sstevel@tonic-gate validate_net_address_syntax(char *address)
26407c478bd9Sstevel@tonic-gate {
26417c478bd9Sstevel@tonic-gate 	char *slashp, part1[MAXHOSTNAMELEN];
26427c478bd9Sstevel@tonic-gate 	struct in6_addr in6;
26437c478bd9Sstevel@tonic-gate 	struct in_addr in4;
26447c478bd9Sstevel@tonic-gate 	int prefixlen, i;
26457c478bd9Sstevel@tonic-gate 
26467c478bd9Sstevel@tonic-gate 	/*
26477c478bd9Sstevel@tonic-gate 	 * Copy the part before any '/' into part1 or copy the whole
26487c478bd9Sstevel@tonic-gate 	 * thing if there is no '/'.
26497c478bd9Sstevel@tonic-gate 	 */
26507c478bd9Sstevel@tonic-gate 	if ((slashp = strchr(address, '/')) != NULL) {
26517c478bd9Sstevel@tonic-gate 		*slashp = '\0';
26527c478bd9Sstevel@tonic-gate 		(void) strlcpy(part1, address, sizeof (part1));
26537c478bd9Sstevel@tonic-gate 		*slashp = '/';
26547c478bd9Sstevel@tonic-gate 		prefixlen = atoi(++slashp);
26557c478bd9Sstevel@tonic-gate 	} else {
26567c478bd9Sstevel@tonic-gate 		(void) strlcpy(part1, address, sizeof (part1));
26577c478bd9Sstevel@tonic-gate 	}
26587c478bd9Sstevel@tonic-gate 
26597c478bd9Sstevel@tonic-gate 	if (inet_pton(AF_INET6, part1, &in6) == 1) {
26607c478bd9Sstevel@tonic-gate 		if (slashp == NULL) {
26617c478bd9Sstevel@tonic-gate 			zerr(gettext("%s: IPv6 addresses "
26627c478bd9Sstevel@tonic-gate 			    "require /prefix-length suffix."), address);
26637c478bd9Sstevel@tonic-gate 			return (Z_ERR);
26647c478bd9Sstevel@tonic-gate 		}
26657c478bd9Sstevel@tonic-gate 		if (prefixlen < 0 || prefixlen > 128) {
26667c478bd9Sstevel@tonic-gate 			zerr(gettext("%s: IPv6 address "
26677c478bd9Sstevel@tonic-gate 			    "prefix lengths must be 0 - 128."), address);
26687c478bd9Sstevel@tonic-gate 			return (Z_ERR);
26697c478bd9Sstevel@tonic-gate 		}
26707c478bd9Sstevel@tonic-gate 		return (Z_OK);
26717c478bd9Sstevel@tonic-gate 	}
26727c478bd9Sstevel@tonic-gate 
26737c478bd9Sstevel@tonic-gate 	/* At this point, any /prefix must be for IPv4. */
26747c478bd9Sstevel@tonic-gate 	if (slashp != NULL) {
26757c478bd9Sstevel@tonic-gate 		if (prefixlen < 0 || prefixlen > 32) {
26767c478bd9Sstevel@tonic-gate 			zerr(gettext("%s: IPv4 address "
26777c478bd9Sstevel@tonic-gate 			    "prefix lengths must be 0 - 32."), address);
26787c478bd9Sstevel@tonic-gate 			return (Z_ERR);
26797c478bd9Sstevel@tonic-gate 		}
26807c478bd9Sstevel@tonic-gate 	}
26817c478bd9Sstevel@tonic-gate 	if (inet_pton(AF_INET, part1, &in4) == 1)
26827c478bd9Sstevel@tonic-gate 		return (Z_OK);
26837c478bd9Sstevel@tonic-gate 
26847c478bd9Sstevel@tonic-gate 	/* address may also be a host name */
26857c478bd9Sstevel@tonic-gate 	if (!isalnum(part1[0])) {
26867c478bd9Sstevel@tonic-gate 		zerr(gettext("%s: bogus host name or network address syntax"),
26877c478bd9Sstevel@tonic-gate 		    part1);
26887c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
26897c478bd9Sstevel@tonic-gate 		usage(FALSE, HELP_NETADDR);
26907c478bd9Sstevel@tonic-gate 		return (Z_ERR);
26917c478bd9Sstevel@tonic-gate 	}
26927c478bd9Sstevel@tonic-gate 	for (i = 1; part1[i]; i++)
26937c478bd9Sstevel@tonic-gate 		if (!isalnum(part1[i]) && part1[i] != '-' && part1[i] != '.') {
26947c478bd9Sstevel@tonic-gate 			zerr(gettext("%s: bogus host name or "
26957c478bd9Sstevel@tonic-gate 			    "network address syntax"), part1);
26967c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
26977c478bd9Sstevel@tonic-gate 			usage(FALSE, HELP_NETADDR);
26987c478bd9Sstevel@tonic-gate 			return (Z_ERR);
26997c478bd9Sstevel@tonic-gate 		}
27007c478bd9Sstevel@tonic-gate 	return (Z_OK);
27017c478bd9Sstevel@tonic-gate }
27027c478bd9Sstevel@tonic-gate 
27037c478bd9Sstevel@tonic-gate static int
27047c478bd9Sstevel@tonic-gate validate_net_physical_syntax(char *ifname)
27057c478bd9Sstevel@tonic-gate {
27067c478bd9Sstevel@tonic-gate 	if (strchr(ifname, ':') == NULL)
27077c478bd9Sstevel@tonic-gate 		return (Z_OK);
27087c478bd9Sstevel@tonic-gate 	zerr(gettext("%s: physical interface name required; "
27097c478bd9Sstevel@tonic-gate 	    "logical interface name not allowed"), ifname);
27107c478bd9Sstevel@tonic-gate 	return (Z_ERR);
27117c478bd9Sstevel@tonic-gate }
27127c478bd9Sstevel@tonic-gate 
27137c478bd9Sstevel@tonic-gate static boolean_t
27147c478bd9Sstevel@tonic-gate valid_fs_type(const char *type)
27157c478bd9Sstevel@tonic-gate {
27167c478bd9Sstevel@tonic-gate 	/*
27177c478bd9Sstevel@tonic-gate 	 * Is this a valid path component?
27187c478bd9Sstevel@tonic-gate 	 */
27197c478bd9Sstevel@tonic-gate 	if (strlen(type) + 1 > MAXNAMELEN)
27207c478bd9Sstevel@tonic-gate 		return (B_FALSE);
27217c478bd9Sstevel@tonic-gate 	/*
27227c478bd9Sstevel@tonic-gate 	 * Make sure a bad value for "type" doesn't make
27237c478bd9Sstevel@tonic-gate 	 * /usr/lib/fs/<type>/mount turn into something else.
27247c478bd9Sstevel@tonic-gate 	 */
27257c478bd9Sstevel@tonic-gate 	if (strchr(type, '/') != NULL || type[0] == '\0' ||
27267c478bd9Sstevel@tonic-gate 	    strcmp(type, ".") == 0 || strcmp(type, "..") == 0)
2727087719fdSdp 		return (B_FALSE);
27287c478bd9Sstevel@tonic-gate 	/*
27297c478bd9Sstevel@tonic-gate 	 * More detailed verification happens later by zoneadm(1m).
27307c478bd9Sstevel@tonic-gate 	 */
27317c478bd9Sstevel@tonic-gate 	return (B_TRUE);
27327c478bd9Sstevel@tonic-gate }
27337c478bd9Sstevel@tonic-gate 
27347c478bd9Sstevel@tonic-gate void
27357c478bd9Sstevel@tonic-gate set_func(cmd_t *cmd)
27367c478bd9Sstevel@tonic-gate {
27377c478bd9Sstevel@tonic-gate 	char *prop_id;
2738555afedfScarlsonj 	int arg, err, res_type, prop_type;
27397c478bd9Sstevel@tonic-gate 	property_value_ptr_t pp;
27407c478bd9Sstevel@tonic-gate 	boolean_t autoboot;
2741555afedfScarlsonj 	boolean_t force_set = FALSE;
27427c478bd9Sstevel@tonic-gate 
27437c478bd9Sstevel@tonic-gate 	if (zone_is_read_only(CMD_SET))
27447c478bd9Sstevel@tonic-gate 		return;
27457c478bd9Sstevel@tonic-gate 
27467c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
27477c478bd9Sstevel@tonic-gate 
2748555afedfScarlsonj 	optind = opterr = 0;
2749555afedfScarlsonj 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
2750555afedfScarlsonj 		switch (arg) {
2751555afedfScarlsonj 		case 'F':
2752555afedfScarlsonj 			force_set = TRUE;
2753555afedfScarlsonj 			break;
2754555afedfScarlsonj 		default:
2755555afedfScarlsonj 			if (optopt == '?')
2756555afedfScarlsonj 				longer_usage(CMD_SET);
2757555afedfScarlsonj 			else
2758555afedfScarlsonj 				short_usage(CMD_SET);
2759555afedfScarlsonj 			return;
2760555afedfScarlsonj 		}
2761555afedfScarlsonj 	}
2762555afedfScarlsonj 
27637c478bd9Sstevel@tonic-gate 	prop_type = cmd->cmd_prop_name[0];
27647c478bd9Sstevel@tonic-gate 	if (global_scope) {
2765087719fdSdp 		if (prop_type == PT_ZONENAME) {
2766087719fdSdp 			res_type = RT_ZONENAME;
2767087719fdSdp 		} else if (prop_type == PT_ZONEPATH) {
27687c478bd9Sstevel@tonic-gate 			res_type = RT_ZONEPATH;
27697c478bd9Sstevel@tonic-gate 		} else if (prop_type == PT_AUTOBOOT) {
27707c478bd9Sstevel@tonic-gate 			res_type = RT_AUTOBOOT;
2771*9acbbeafSnn 		} else if (prop_type == PT_BRAND) {
2772*9acbbeafSnn 			res_type = RT_BRAND;
27737c478bd9Sstevel@tonic-gate 		} else if (prop_type == PT_POOL) {
27747c478bd9Sstevel@tonic-gate 			res_type = RT_POOL;
2775ffbafc53Scomay 		} else if (prop_type == PT_LIMITPRIV) {
2776ffbafc53Scomay 			res_type = RT_LIMITPRIV;
27773f2f09c1Sdp 		} else if (prop_type == PT_BOOTARGS) {
27783f2f09c1Sdp 			res_type = RT_BOOTARGS;
27797c478bd9Sstevel@tonic-gate 		} else {
27807c478bd9Sstevel@tonic-gate 			zerr(gettext("Cannot set a resource-specific property "
27817c478bd9Sstevel@tonic-gate 			    "from the global scope."));
27827c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
27837c478bd9Sstevel@tonic-gate 			return;
27847c478bd9Sstevel@tonic-gate 		}
27857c478bd9Sstevel@tonic-gate 	} else {
27867c478bd9Sstevel@tonic-gate 		res_type = resource_scope;
27877c478bd9Sstevel@tonic-gate 	}
27887c478bd9Sstevel@tonic-gate 
2789555afedfScarlsonj 	if (force_set) {
2790555afedfScarlsonj 		if (res_type != RT_ZONEPATH) {
2791555afedfScarlsonj 			zerr(gettext("Only zonepath setting can be forced."));
2792555afedfScarlsonj 			saw_error = TRUE;
2793555afedfScarlsonj 			return;
2794555afedfScarlsonj 		}
2795555afedfScarlsonj 		if (!zonecfg_in_alt_root()) {
2796555afedfScarlsonj 			zerr(gettext("Zonepath is changeable only in an "
2797555afedfScarlsonj 			    "alternate root."));
2798555afedfScarlsonj 			saw_error = TRUE;
2799555afedfScarlsonj 			return;
2800555afedfScarlsonj 		}
2801555afedfScarlsonj 	}
2802555afedfScarlsonj 
28037c478bd9Sstevel@tonic-gate 	pp = cmd->cmd_property_ptr[0];
28047c478bd9Sstevel@tonic-gate 	/*
28057c478bd9Sstevel@tonic-gate 	 * A nasty expression but not that complicated:
28067c478bd9Sstevel@tonic-gate 	 * 1. fs options are simple or list (tested below)
28077c478bd9Sstevel@tonic-gate 	 * 2. rctl value's are complex or list (tested below)
28087c478bd9Sstevel@tonic-gate 	 * Anything else should be simple.
28097c478bd9Sstevel@tonic-gate 	 */
28107c478bd9Sstevel@tonic-gate 	if (!(res_type == RT_FS && prop_type == PT_OPTIONS) &&
28117c478bd9Sstevel@tonic-gate 	    !(res_type == RT_RCTL && prop_type == PT_VALUE) &&
28127c478bd9Sstevel@tonic-gate 	    (pp->pv_type != PROP_VAL_SIMPLE ||
28137c478bd9Sstevel@tonic-gate 	    (prop_id = pp->pv_simple) == NULL)) {
28147c478bd9Sstevel@tonic-gate 		zerr(gettext("A %s value was expected here."),
28157c478bd9Sstevel@tonic-gate 		    pvt_to_str(PROP_VAL_SIMPLE));
28167c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
28177c478bd9Sstevel@tonic-gate 		return;
28187c478bd9Sstevel@tonic-gate 	}
28197c478bd9Sstevel@tonic-gate 	if (prop_type == PT_UNKNOWN) {
28207c478bd9Sstevel@tonic-gate 		long_usage(CMD_SET, TRUE);
28217c478bd9Sstevel@tonic-gate 		return;
28227c478bd9Sstevel@tonic-gate 	}
28237c478bd9Sstevel@tonic-gate 
2824087719fdSdp 	/*
2825087719fdSdp 	 * Special case: the user can change the zone name prior to 'create';
2826087719fdSdp 	 * if the zone already exists, we fall through letting initialize()
2827087719fdSdp 	 * and the rest of the logic run.
2828087719fdSdp 	 */
2829087719fdSdp 	if (res_type == RT_ZONENAME && got_handle == FALSE &&
2830087719fdSdp 	    !state_atleast(ZONE_STATE_CONFIGURED)) {
2831fb03efaaSdp 		if ((err = zonecfg_validate_zonename(prop_id)) != Z_OK) {
2832fb03efaaSdp 			zone_perror(prop_id, err, TRUE);
2833fb03efaaSdp 			usage(FALSE, HELP_SYNTAX);
2834fb03efaaSdp 			return;
2835fb03efaaSdp 		}
2836087719fdSdp 		(void) strlcpy(zone, prop_id, sizeof (zone));
2837087719fdSdp 		return;
2838087719fdSdp 	}
2839087719fdSdp 
28407c478bd9Sstevel@tonic-gate 	if (initialize(TRUE) != Z_OK)
28417c478bd9Sstevel@tonic-gate 		return;
28427c478bd9Sstevel@tonic-gate 
28437c478bd9Sstevel@tonic-gate 	switch (res_type) {
2844087719fdSdp 	case RT_ZONENAME:
2845087719fdSdp 		if ((err = zonecfg_set_name(handle, prop_id)) != Z_OK) {
2846087719fdSdp 			/*
2847087719fdSdp 			 * Use prop_id instead of 'zone' here, since we're
2848087719fdSdp 			 * reporting a problem about the *new* zonename.
2849087719fdSdp 			 */
2850087719fdSdp 			zone_perror(prop_id, err, TRUE);
2851fb03efaaSdp 			usage(FALSE, HELP_SYNTAX);
2852087719fdSdp 		} else {
2853087719fdSdp 			need_to_commit = TRUE;
2854087719fdSdp 			(void) strlcpy(zone, prop_id, sizeof (zone));
2855087719fdSdp 		}
2856087719fdSdp 		return;
28577c478bd9Sstevel@tonic-gate 	case RT_ZONEPATH:
2858555afedfScarlsonj 		if (!force_set && state_atleast(ZONE_STATE_INSTALLED)) {
28597c478bd9Sstevel@tonic-gate 			zerr(gettext("Zone %s already installed; %s %s not "
28607c478bd9Sstevel@tonic-gate 			    "allowed."), zone, cmd_to_str(CMD_SET),
28617c478bd9Sstevel@tonic-gate 			    rt_to_str(RT_ZONEPATH));
28627c478bd9Sstevel@tonic-gate 			return;
28637c478bd9Sstevel@tonic-gate 		}
28647c478bd9Sstevel@tonic-gate 		if (validate_zonepath_syntax(prop_id) != Z_OK) {
28657c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
28667c478bd9Sstevel@tonic-gate 			return;
28677c478bd9Sstevel@tonic-gate 		}
28687c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_set_zonepath(handle, prop_id)) != Z_OK)
28697c478bd9Sstevel@tonic-gate 			zone_perror(zone, err, TRUE);
28707c478bd9Sstevel@tonic-gate 		else
28717c478bd9Sstevel@tonic-gate 			need_to_commit = TRUE;
28727c478bd9Sstevel@tonic-gate 		return;
2873*9acbbeafSnn 	case RT_BRAND:
2874*9acbbeafSnn 		if (state_atleast(ZONE_STATE_INSTALLED)) {
2875*9acbbeafSnn 			zerr(gettext("Zone %s already installed; %s %s not "
2876*9acbbeafSnn 			    "allowed."), zone, cmd_to_str(CMD_SET),
2877*9acbbeafSnn 			    rt_to_str(RT_BRAND));
2878*9acbbeafSnn 			return;
2879*9acbbeafSnn 		}
2880*9acbbeafSnn 		if ((err = zonecfg_set_brand(handle, prop_id)) != Z_OK)
2881*9acbbeafSnn 			zone_perror(zone, err, TRUE);
2882*9acbbeafSnn 		else
2883*9acbbeafSnn 			need_to_commit = TRUE;
2884*9acbbeafSnn 		return;
28857c478bd9Sstevel@tonic-gate 	case RT_AUTOBOOT:
28867c478bd9Sstevel@tonic-gate 		if (strcmp(prop_id, "true") == 0) {
28877c478bd9Sstevel@tonic-gate 			autoboot = B_TRUE;
28887c478bd9Sstevel@tonic-gate 		} else if (strcmp(prop_id, "false") == 0) {
28897c478bd9Sstevel@tonic-gate 			autoboot = B_FALSE;
28907c478bd9Sstevel@tonic-gate 		} else {
28917c478bd9Sstevel@tonic-gate 			zerr(gettext("%s value must be '%s' or '%s'."),
28927c478bd9Sstevel@tonic-gate 			    pt_to_str(PT_AUTOBOOT), "true", "false");
28937c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
28947c478bd9Sstevel@tonic-gate 			return;
28957c478bd9Sstevel@tonic-gate 		}
28967c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_set_autoboot(handle, autoboot)) != Z_OK)
28977c478bd9Sstevel@tonic-gate 			zone_perror(zone, err, TRUE);
28987c478bd9Sstevel@tonic-gate 		else
28997c478bd9Sstevel@tonic-gate 			need_to_commit = TRUE;
29007c478bd9Sstevel@tonic-gate 		return;
29017c478bd9Sstevel@tonic-gate 	case RT_POOL:
29027c478bd9Sstevel@tonic-gate 		if ((err = zonecfg_set_pool(handle, prop_id)) != Z_OK)
29037c478bd9Sstevel@tonic-gate 			zone_perror(zone, err, TRUE);
29047c478bd9Sstevel@tonic-gate 		else
29057c478bd9Sstevel@tonic-gate 			need_to_commit = TRUE;
29067c478bd9Sstevel@tonic-gate 		return;
2907ffbafc53Scomay 	case RT_LIMITPRIV:
2908ffbafc53Scomay 		if ((err = zonecfg_set_limitpriv(handle, prop_id)) != Z_OK)
2909ffbafc53Scomay 			zone_perror(zone, err, TRUE);
2910ffbafc53Scomay 		else
2911ffbafc53Scomay 			need_to_commit = TRUE;
2912ffbafc53Scomay 		return;
29133f2f09c1Sdp 	case RT_BOOTARGS:
29143f2f09c1Sdp 		if ((err = zonecfg_set_bootargs(handle, prop_id)) != Z_OK)
29153f2f09c1Sdp 			zone_perror(zone, err, TRUE);
29163f2f09c1Sdp 		else
29173f2f09c1Sdp 			need_to_commit = TRUE;
29183f2f09c1Sdp 		return;
29197c478bd9Sstevel@tonic-gate 	case RT_FS:
29207c478bd9Sstevel@tonic-gate 		switch (prop_type) {
29217c478bd9Sstevel@tonic-gate 		case PT_DIR:
29227c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_fstab.zone_fs_dir, prop_id,
29237c478bd9Sstevel@tonic-gate 			    sizeof (in_progress_fstab.zone_fs_dir));
29247c478bd9Sstevel@tonic-gate 			return;
29257c478bd9Sstevel@tonic-gate 		case PT_SPECIAL:
29267c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_fstab.zone_fs_special,
29277c478bd9Sstevel@tonic-gate 			    prop_id,
29287c478bd9Sstevel@tonic-gate 			    sizeof (in_progress_fstab.zone_fs_special));
29297c478bd9Sstevel@tonic-gate 			return;
29307c478bd9Sstevel@tonic-gate 		case PT_RAW:
29317c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_fstab.zone_fs_raw,
29327c478bd9Sstevel@tonic-gate 			    prop_id, sizeof (in_progress_fstab.zone_fs_raw));
29337c478bd9Sstevel@tonic-gate 			return;
29347c478bd9Sstevel@tonic-gate 		case PT_TYPE:
29357c478bd9Sstevel@tonic-gate 			if (!valid_fs_type(prop_id)) {
29367c478bd9Sstevel@tonic-gate 				zerr(gettext("\"%s\" is not a valid %s."),
29377c478bd9Sstevel@tonic-gate 				    prop_id, pt_to_str(PT_TYPE));
29387c478bd9Sstevel@tonic-gate 				saw_error = TRUE;
29397c478bd9Sstevel@tonic-gate 				return;
29407c478bd9Sstevel@tonic-gate 			}
29417c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_fstab.zone_fs_type, prop_id,
29427c478bd9Sstevel@tonic-gate 			    sizeof (in_progress_fstab.zone_fs_type));
29437c478bd9Sstevel@tonic-gate 			return;
29447c478bd9Sstevel@tonic-gate 		case PT_OPTIONS:
29457c478bd9Sstevel@tonic-gate 			if (pp->pv_type != PROP_VAL_SIMPLE &&
29467c478bd9Sstevel@tonic-gate 			    pp->pv_type != PROP_VAL_LIST) {
29477c478bd9Sstevel@tonic-gate 				zerr(gettext("A %s or %s value was expected "
29487c478bd9Sstevel@tonic-gate 				    "here."), pvt_to_str(PROP_VAL_SIMPLE),
29497c478bd9Sstevel@tonic-gate 				    pvt_to_str(PROP_VAL_LIST));
29507c478bd9Sstevel@tonic-gate 				saw_error = TRUE;
29517c478bd9Sstevel@tonic-gate 				return;
29527c478bd9Sstevel@tonic-gate 			}
29537c478bd9Sstevel@tonic-gate 			zonecfg_free_fs_option_list(
29547c478bd9Sstevel@tonic-gate 			    in_progress_fstab.zone_fs_options);
29557c478bd9Sstevel@tonic-gate 			in_progress_fstab.zone_fs_options = NULL;
29567c478bd9Sstevel@tonic-gate 			if (!(pp->pv_type == PROP_VAL_LIST &&
29577c478bd9Sstevel@tonic-gate 			    pp->pv_list == NULL))
29587c478bd9Sstevel@tonic-gate 				add_property(cmd);
29597c478bd9Sstevel@tonic-gate 			return;
29607c478bd9Sstevel@tonic-gate 		default:
29617c478bd9Sstevel@tonic-gate 			break;
29627c478bd9Sstevel@tonic-gate 		}
29637c478bd9Sstevel@tonic-gate 		zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, TRUE);
29647c478bd9Sstevel@tonic-gate 		long_usage(CMD_SET, TRUE);
29657c478bd9Sstevel@tonic-gate 		usage(FALSE, HELP_PROPS);
29667c478bd9Sstevel@tonic-gate 		return;
29677c478bd9Sstevel@tonic-gate 	case RT_IPD:
29687c478bd9Sstevel@tonic-gate 		switch (prop_type) {
29697c478bd9Sstevel@tonic-gate 		case PT_DIR:
29707c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_ipdtab.zone_fs_dir, prop_id,
29717c478bd9Sstevel@tonic-gate 			    sizeof (in_progress_ipdtab.zone_fs_dir));
29727c478bd9Sstevel@tonic-gate 			return;
29737c478bd9Sstevel@tonic-gate 		default:
29747c478bd9Sstevel@tonic-gate 			break;
29757c478bd9Sstevel@tonic-gate 		}
29767c478bd9Sstevel@tonic-gate 		zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, TRUE);
29777c478bd9Sstevel@tonic-gate 		long_usage(CMD_SET, TRUE);
29787c478bd9Sstevel@tonic-gate 		usage(FALSE, HELP_PROPS);
29797c478bd9Sstevel@tonic-gate 		return;
29807c478bd9Sstevel@tonic-gate 	case RT_NET:
29817c478bd9Sstevel@tonic-gate 		switch (prop_type) {
29827c478bd9Sstevel@tonic-gate 		case PT_ADDRESS:
29837c478bd9Sstevel@tonic-gate 			if (validate_net_address_syntax(prop_id) != Z_OK) {
29847c478bd9Sstevel@tonic-gate 				saw_error = TRUE;
29857c478bd9Sstevel@tonic-gate 				return;
29867c478bd9Sstevel@tonic-gate 			}
29877c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_nwiftab.zone_nwif_address,
29887c478bd9Sstevel@tonic-gate 			    prop_id,
29897c478bd9Sstevel@tonic-gate 			    sizeof (in_progress_nwiftab.zone_nwif_address));
29907c478bd9Sstevel@tonic-gate 			break;
29917c478bd9Sstevel@tonic-gate 		case PT_PHYSICAL:
29927c478bd9Sstevel@tonic-gate 			if (validate_net_physical_syntax(prop_id) != Z_OK) {
29937c478bd9Sstevel@tonic-gate 				saw_error = TRUE;
29947c478bd9Sstevel@tonic-gate 				return;
29957c478bd9Sstevel@tonic-gate 			}
29967c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_nwiftab.zone_nwif_physical,
29977c478bd9Sstevel@tonic-gate 			    prop_id,
29987c478bd9Sstevel@tonic-gate 			    sizeof (in_progress_nwiftab.zone_nwif_physical));
29997c478bd9Sstevel@tonic-gate 			break;
30007c478bd9Sstevel@tonic-gate 		default:
30017c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
30027c478bd9Sstevel@tonic-gate 			    TRUE);
30037c478bd9Sstevel@tonic-gate 			long_usage(CMD_SET, TRUE);
30047c478bd9Sstevel@tonic-gate 			usage(FALSE, HELP_PROPS);
30057c478bd9Sstevel@tonic-gate 			return;
30067c478bd9Sstevel@tonic-gate 		}
30077c478bd9Sstevel@tonic-gate 		return;
30087c478bd9Sstevel@tonic-gate 	case RT_DEVICE:
30097c478bd9Sstevel@tonic-gate 		switch (prop_type) {
30107c478bd9Sstevel@tonic-gate 		case PT_MATCH:
30117c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_devtab.zone_dev_match,
30127c478bd9Sstevel@tonic-gate 			    prop_id,
30137c478bd9Sstevel@tonic-gate 			    sizeof (in_progress_devtab.zone_dev_match));
30147c478bd9Sstevel@tonic-gate 			break;
30157c478bd9Sstevel@tonic-gate 		default:
30167c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
30177c478bd9Sstevel@tonic-gate 			    TRUE);
30187c478bd9Sstevel@tonic-gate 			long_usage(CMD_SET, TRUE);
30197c478bd9Sstevel@tonic-gate 			usage(FALSE, HELP_PROPS);
30207c478bd9Sstevel@tonic-gate 			return;
30217c478bd9Sstevel@tonic-gate 		}
30227c478bd9Sstevel@tonic-gate 		return;
30237c478bd9Sstevel@tonic-gate 	case RT_RCTL:
30247c478bd9Sstevel@tonic-gate 		switch (prop_type) {
30257c478bd9Sstevel@tonic-gate 		case PT_NAME:
30267c478bd9Sstevel@tonic-gate 			if (!zonecfg_valid_rctlname(prop_id)) {
30277c478bd9Sstevel@tonic-gate 				zerr(gettext("'%s' is not a valid zone %s "
30287c478bd9Sstevel@tonic-gate 				    "name."), prop_id, rt_to_str(RT_RCTL));
30297c478bd9Sstevel@tonic-gate 				return;
30307c478bd9Sstevel@tonic-gate 			}
30317c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_rctltab.zone_rctl_name,
30327c478bd9Sstevel@tonic-gate 			    prop_id,
30337c478bd9Sstevel@tonic-gate 			    sizeof (in_progress_rctltab.zone_rctl_name));
30347c478bd9Sstevel@tonic-gate 			break;
30357c478bd9Sstevel@tonic-gate 		case PT_VALUE:
30367c478bd9Sstevel@tonic-gate 			if (pp->pv_type != PROP_VAL_COMPLEX &&
30377c478bd9Sstevel@tonic-gate 			    pp->pv_type != PROP_VAL_LIST) {
30387c478bd9Sstevel@tonic-gate 				zerr(gettext("A %s or %s value was expected "
30397c478bd9Sstevel@tonic-gate 				    "here."), pvt_to_str(PROP_VAL_COMPLEX),
30407c478bd9Sstevel@tonic-gate 				    pvt_to_str(PROP_VAL_LIST));
30417c478bd9Sstevel@tonic-gate 				saw_error = TRUE;
30427c478bd9Sstevel@tonic-gate 				return;
30437c478bd9Sstevel@tonic-gate 			}
30447c478bd9Sstevel@tonic-gate 			zonecfg_free_rctl_value_list(
30457c478bd9Sstevel@tonic-gate 			    in_progress_rctltab.zone_rctl_valptr);
30467c478bd9Sstevel@tonic-gate 			in_progress_rctltab.zone_rctl_valptr = NULL;
30477c478bd9Sstevel@tonic-gate 			if (!(pp->pv_type == PROP_VAL_LIST &&
30487c478bd9Sstevel@tonic-gate 			    pp->pv_list == NULL))
30497c478bd9Sstevel@tonic-gate 				add_property(cmd);
30507c478bd9Sstevel@tonic-gate 			break;
30517c478bd9Sstevel@tonic-gate 		default:
30527c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
30537c478bd9Sstevel@tonic-gate 			    TRUE);
30547c478bd9Sstevel@tonic-gate 			long_usage(CMD_SET, TRUE);
30557c478bd9Sstevel@tonic-gate 			usage(FALSE, HELP_PROPS);
30567c478bd9Sstevel@tonic-gate 			return;
30577c478bd9Sstevel@tonic-gate 		}
30587c478bd9Sstevel@tonic-gate 		return;
30597c478bd9Sstevel@tonic-gate 	case RT_ATTR:
30607c478bd9Sstevel@tonic-gate 		switch (prop_type) {
30617c478bd9Sstevel@tonic-gate 		case PT_NAME:
30627c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_attrtab.zone_attr_name,
30637c478bd9Sstevel@tonic-gate 			    prop_id,
30647c478bd9Sstevel@tonic-gate 			    sizeof (in_progress_attrtab.zone_attr_name));
30657c478bd9Sstevel@tonic-gate 			break;
30667c478bd9Sstevel@tonic-gate 		case PT_TYPE:
30677c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_attrtab.zone_attr_type,
30687c478bd9Sstevel@tonic-gate 			    prop_id,
30697c478bd9Sstevel@tonic-gate 			    sizeof (in_progress_attrtab.zone_attr_type));
30707c478bd9Sstevel@tonic-gate 			break;
30717c478bd9Sstevel@tonic-gate 		case PT_VALUE:
30727c478bd9Sstevel@tonic-gate 			(void) strlcpy(in_progress_attrtab.zone_attr_value,
30737c478bd9Sstevel@tonic-gate 			    prop_id,
30747c478bd9Sstevel@tonic-gate 			    sizeof (in_progress_attrtab.zone_attr_value));
30757c478bd9Sstevel@tonic-gate 			break;
30767c478bd9Sstevel@tonic-gate 		default:
30777c478bd9Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
30787c478bd9Sstevel@tonic-gate 			    TRUE);
30797c478bd9Sstevel@tonic-gate 			long_usage(CMD_SET, TRUE);
30807c478bd9Sstevel@tonic-gate 			usage(FALSE, HELP_PROPS);
30817c478bd9Sstevel@tonic-gate 			return;
30827c478bd9Sstevel@tonic-gate 		}
30837c478bd9Sstevel@tonic-gate 		return;
3084fa9e4066Sahrens 	case RT_DATASET:
3085fa9e4066Sahrens 		switch (prop_type) {
3086fa9e4066Sahrens 		case PT_NAME:
3087fa9e4066Sahrens 			(void) strlcpy(in_progress_dstab.zone_dataset_name,
3088fa9e4066Sahrens 			    prop_id,
3089fa9e4066Sahrens 			    sizeof (in_progress_dstab.zone_dataset_name));
3090fa9e4066Sahrens 			return;
3091fa9e4066Sahrens 		default:
3092fa9e4066Sahrens 			break;
3093fa9e4066Sahrens 		}
3094fa9e4066Sahrens 		zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, TRUE);
3095fa9e4066Sahrens 		long_usage(CMD_SET, TRUE);
3096fa9e4066Sahrens 		usage(FALSE, HELP_PROPS);
3097fa9e4066Sahrens 		return;
30987c478bd9Sstevel@tonic-gate 	default:
30997c478bd9Sstevel@tonic-gate 		zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, TRUE);
31007c478bd9Sstevel@tonic-gate 		long_usage(CMD_SET, TRUE);
31017c478bd9Sstevel@tonic-gate 		usage(FALSE, HELP_RESOURCES);
31027c478bd9Sstevel@tonic-gate 		return;
31037c478bd9Sstevel@tonic-gate 	}
31047c478bd9Sstevel@tonic-gate }
31057c478bd9Sstevel@tonic-gate 
31067c478bd9Sstevel@tonic-gate static void
31077c478bd9Sstevel@tonic-gate output_prop(FILE *fp, int pnum, char *pval, bool print_notspec)
31087c478bd9Sstevel@tonic-gate {
31097c478bd9Sstevel@tonic-gate 	char *qstr;
31107c478bd9Sstevel@tonic-gate 
31117c478bd9Sstevel@tonic-gate 	if (*pval != '\0') {
31127c478bd9Sstevel@tonic-gate 		qstr = quoteit(pval);
31137c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);
31147c478bd9Sstevel@tonic-gate 		free(qstr);
31157c478bd9Sstevel@tonic-gate 	} else if (print_notspec)
3116087719fdSdp 		(void) fprintf(fp, gettext("\t%s not specified\n"),
3117087719fdSdp 		    pt_to_str(pnum));
3118087719fdSdp }
3119087719fdSdp 
3120087719fdSdp static void
3121087719fdSdp info_zonename(zone_dochandle_t handle, FILE *fp)
3122087719fdSdp {
3123087719fdSdp 	char zonename[ZONENAME_MAX];
3124087719fdSdp 
3125087719fdSdp 	if (zonecfg_get_name(handle, zonename, sizeof (zonename)) == Z_OK)
3126087719fdSdp 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONENAME),
3127087719fdSdp 		    zonename);
3128087719fdSdp 	else
3129087719fdSdp 		(void) fprintf(fp, gettext("%s not specified\n"),
3130087719fdSdp 		    pt_to_str(PT_ZONENAME));
31317c478bd9Sstevel@tonic-gate }
31327c478bd9Sstevel@tonic-gate 
31337c478bd9Sstevel@tonic-gate static void
31347c478bd9Sstevel@tonic-gate info_zonepath(zone_dochandle_t handle, FILE *fp)
31357c478bd9Sstevel@tonic-gate {
31367c478bd9Sstevel@tonic-gate 	char zonepath[MAXPATHLEN];
31377c478bd9Sstevel@tonic-gate 
31387c478bd9Sstevel@tonic-gate 	if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK)
31397c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONEPATH),
31407c478bd9Sstevel@tonic-gate 		    zonepath);
3141087719fdSdp 	else {
3142087719fdSdp 		(void) fprintf(fp, gettext("%s not specified\n"),
3143087719fdSdp 		    pt_to_str(PT_ZONEPATH));
3144087719fdSdp 	}
31457c478bd9Sstevel@tonic-gate }
31467c478bd9Sstevel@tonic-gate 
3147*9acbbeafSnn static void
3148*9acbbeafSnn info_brand(zone_dochandle_t handle, FILE *fp)
3149*9acbbeafSnn {
3150*9acbbeafSnn 	char brand[MAXNAMELEN];
3151*9acbbeafSnn 
3152*9acbbeafSnn 	if (zonecfg_get_brand(handle, brand, sizeof (brand)) == Z_OK)
3153*9acbbeafSnn 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BRAND),
3154*9acbbeafSnn 		    brand);
3155*9acbbeafSnn 	else
3156*9acbbeafSnn 		(void) fprintf(fp, "%s %s\n", pt_to_str(PT_BRAND),
3157*9acbbeafSnn 		    gettext("not specified"));
3158*9acbbeafSnn }
3159*9acbbeafSnn 
31607c478bd9Sstevel@tonic-gate static void
31617c478bd9Sstevel@tonic-gate info_autoboot(zone_dochandle_t handle, FILE *fp)
31627c478bd9Sstevel@tonic-gate {
31637c478bd9Sstevel@tonic-gate 	boolean_t autoboot;
31647c478bd9Sstevel@tonic-gate 	int err;
31657c478bd9Sstevel@tonic-gate 
31667c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_get_autoboot(handle, &autoboot)) == Z_OK)
31677c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_AUTOBOOT),
31687c478bd9Sstevel@tonic-gate 		    autoboot ? "true" : "false");
31697c478bd9Sstevel@tonic-gate 	else
31707c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, TRUE);
31717c478bd9Sstevel@tonic-gate }
31727c478bd9Sstevel@tonic-gate 
31737c478bd9Sstevel@tonic-gate static void
31747c478bd9Sstevel@tonic-gate info_pool(zone_dochandle_t handle, FILE *fp)
31757c478bd9Sstevel@tonic-gate {
31767c478bd9Sstevel@tonic-gate 	char pool[MAXNAMELEN];
31777c478bd9Sstevel@tonic-gate 	int err;
31787c478bd9Sstevel@tonic-gate 
31797c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_get_pool(handle, pool, sizeof (pool))) == Z_OK)
31807c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_POOL), pool);
31817c478bd9Sstevel@tonic-gate 	else
31827c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, TRUE);
31837c478bd9Sstevel@tonic-gate }
31847c478bd9Sstevel@tonic-gate 
3185ffbafc53Scomay static void
3186ffbafc53Scomay info_limitpriv(zone_dochandle_t handle, FILE *fp)
3187ffbafc53Scomay {
3188ffbafc53Scomay 	char *limitpriv;
3189ffbafc53Scomay 	int err;
3190ffbafc53Scomay 
3191ffbafc53Scomay 	if ((err = zonecfg_get_limitpriv(handle, &limitpriv)) == Z_OK) {
3192ffbafc53Scomay 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_LIMITPRIV),
3193ffbafc53Scomay 		    limitpriv);
3194ffbafc53Scomay 		free(limitpriv);
3195ffbafc53Scomay 	} else {
3196ffbafc53Scomay 		zone_perror(zone, err, TRUE);
3197ffbafc53Scomay 	}
3198ffbafc53Scomay }
3199ffbafc53Scomay 
32003f2f09c1Sdp static void
32013f2f09c1Sdp info_bootargs(zone_dochandle_t handle, FILE *fp)
32023f2f09c1Sdp {
32033f2f09c1Sdp 	char bootargs[BOOTARGS_MAX];
32043f2f09c1Sdp 	int err;
32053f2f09c1Sdp 
32063f2f09c1Sdp 	if ((err = zonecfg_get_bootargs(handle, bootargs,
32073f2f09c1Sdp 	    sizeof (bootargs))) == Z_OK) {
32083f2f09c1Sdp 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BOOTARGS),
32093f2f09c1Sdp 		    bootargs);
32103f2f09c1Sdp 	} else {
32113f2f09c1Sdp 		zone_perror(zone, err, TRUE);
32123f2f09c1Sdp 	}
32133f2f09c1Sdp }
32143f2f09c1Sdp 
32157c478bd9Sstevel@tonic-gate static void
32167c478bd9Sstevel@tonic-gate output_fs(FILE *fp, struct zone_fstab *fstab)
32177c478bd9Sstevel@tonic-gate {
32187c478bd9Sstevel@tonic-gate 	zone_fsopt_t *this;
32197c478bd9Sstevel@tonic-gate 
32207c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_FS));
32217c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_DIR, fstab->zone_fs_dir, B_TRUE);
32227c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_SPECIAL, fstab->zone_fs_special, B_TRUE);
32237c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_RAW, fstab->zone_fs_raw, B_TRUE);
32247c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_TYPE, fstab->zone_fs_type, B_TRUE);
32257c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "\t%s: [", pt_to_str(PT_OPTIONS));
32267c478bd9Sstevel@tonic-gate 	for (this = fstab->zone_fs_options; this != NULL;
32277c478bd9Sstevel@tonic-gate 	    this = this->zone_fsopt_next) {
32287c478bd9Sstevel@tonic-gate 		if (strchr(this->zone_fsopt_opt, '='))
32297c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "\"%s\"", this->zone_fsopt_opt);
32307c478bd9Sstevel@tonic-gate 		else
32317c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "%s", this->zone_fsopt_opt);
32327c478bd9Sstevel@tonic-gate 		if (this->zone_fsopt_next != NULL)
32337c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, ",");
32347c478bd9Sstevel@tonic-gate 	}
32357c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "]\n");
32367c478bd9Sstevel@tonic-gate }
32377c478bd9Sstevel@tonic-gate 
32387c478bd9Sstevel@tonic-gate static void
32397c478bd9Sstevel@tonic-gate output_ipd(FILE *fp, struct zone_fstab *ipdtab)
32407c478bd9Sstevel@tonic-gate {
32417c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_IPD));
32427c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_DIR, ipdtab->zone_fs_dir, B_TRUE);
32437c478bd9Sstevel@tonic-gate }
32447c478bd9Sstevel@tonic-gate 
32457c478bd9Sstevel@tonic-gate static void
32467c478bd9Sstevel@tonic-gate info_fs(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
32477c478bd9Sstevel@tonic-gate {
32487c478bd9Sstevel@tonic-gate 	struct zone_fstab lookup, user;
32497c478bd9Sstevel@tonic-gate 	bool output = FALSE;
32507c478bd9Sstevel@tonic-gate 
32517c478bd9Sstevel@tonic-gate 	if (zonecfg_setfsent(handle) != Z_OK)
32527c478bd9Sstevel@tonic-gate 		return;
32537c478bd9Sstevel@tonic-gate 	while (zonecfg_getfsent(handle, &lookup) == Z_OK) {
32547c478bd9Sstevel@tonic-gate 		if (cmd->cmd_prop_nv_pairs == 0) {
32557c478bd9Sstevel@tonic-gate 			output_fs(fp, &lookup);
32567c478bd9Sstevel@tonic-gate 			goto loopend;
32577c478bd9Sstevel@tonic-gate 		}
32587c478bd9Sstevel@tonic-gate 		if (fill_in_fstab(cmd, &user, TRUE) != Z_OK)
32597c478bd9Sstevel@tonic-gate 			goto loopend;
32607c478bd9Sstevel@tonic-gate 		if (strlen(user.zone_fs_dir) > 0 &&
32617c478bd9Sstevel@tonic-gate 		    strcmp(user.zone_fs_dir, lookup.zone_fs_dir) != 0)
32627c478bd9Sstevel@tonic-gate 			goto loopend;	/* no match */
32637c478bd9Sstevel@tonic-gate 		if (strlen(user.zone_fs_special) > 0 &&
32647c478bd9Sstevel@tonic-gate 		    strcmp(user.zone_fs_special, lookup.zone_fs_special) != 0)
32657c478bd9Sstevel@tonic-gate 			goto loopend;	/* no match */
32667c478bd9Sstevel@tonic-gate 		if (strlen(user.zone_fs_type) > 0 &&
32677c478bd9Sstevel@tonic-gate 		    strcmp(user.zone_fs_type, lookup.zone_fs_type) != 0)
32687c478bd9Sstevel@tonic-gate 			goto loopend;	/* no match */
32697c478bd9Sstevel@tonic-gate 		output_fs(fp, &lookup);
32707c478bd9Sstevel@tonic-gate 		output = TRUE;
32717c478bd9Sstevel@tonic-gate loopend:
32727c478bd9Sstevel@tonic-gate 		zonecfg_free_fs_option_list(lookup.zone_fs_options);
32737c478bd9Sstevel@tonic-gate 	}
32747c478bd9Sstevel@tonic-gate 	(void) zonecfg_endfsent(handle);
32757c478bd9Sstevel@tonic-gate 	/*
32767c478bd9Sstevel@tonic-gate 	 * If a property n/v pair was specified, warn the user if there was
32777c478bd9Sstevel@tonic-gate 	 * nothing to output.
32787c478bd9Sstevel@tonic-gate 	 */
32797c478bd9Sstevel@tonic-gate 	if (!output && cmd->cmd_prop_nv_pairs > 0)
32807c478bd9Sstevel@tonic-gate 		(void) printf(gettext("No such %s resource.\n"),
32817c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_FS));
32827c478bd9Sstevel@tonic-gate }
32837c478bd9Sstevel@tonic-gate 
32847c478bd9Sstevel@tonic-gate static void
32857c478bd9Sstevel@tonic-gate info_ipd(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
32867c478bd9Sstevel@tonic-gate {
32877c478bd9Sstevel@tonic-gate 	struct zone_fstab lookup, user;
32887c478bd9Sstevel@tonic-gate 	bool output = FALSE;
32897c478bd9Sstevel@tonic-gate 
32907c478bd9Sstevel@tonic-gate 	if (zonecfg_setipdent(handle) != Z_OK)
32917c478bd9Sstevel@tonic-gate 		return;
32927c478bd9Sstevel@tonic-gate 	while (zonecfg_getipdent(handle, &lookup) == Z_OK) {
32937c478bd9Sstevel@tonic-gate 		if (cmd->cmd_prop_nv_pairs == 0) {
32947c478bd9Sstevel@tonic-gate 			output_ipd(fp, &lookup);
32957c478bd9Sstevel@tonic-gate 			continue;
32967c478bd9Sstevel@tonic-gate 		}
32977c478bd9Sstevel@tonic-gate 		if (fill_in_ipdtab(cmd, &user, TRUE) != Z_OK)
32987c478bd9Sstevel@tonic-gate 			continue;
32997c478bd9Sstevel@tonic-gate 		if (strlen(user.zone_fs_dir) > 0 &&
33007c478bd9Sstevel@tonic-gate 		    strcmp(user.zone_fs_dir, lookup.zone_fs_dir) != 0)
33017c478bd9Sstevel@tonic-gate 			continue;	/* no match */
33027c478bd9Sstevel@tonic-gate 		output_ipd(fp, &lookup);
33037c478bd9Sstevel@tonic-gate 		output = TRUE;
33047c478bd9Sstevel@tonic-gate 	}
33057c478bd9Sstevel@tonic-gate 	(void) zonecfg_endipdent(handle);
33067c478bd9Sstevel@tonic-gate 	/*
33077c478bd9Sstevel@tonic-gate 	 * If a property n/v pair was specified, warn the user if there was
33087c478bd9Sstevel@tonic-gate 	 * nothing to output.
33097c478bd9Sstevel@tonic-gate 	 */
33107c478bd9Sstevel@tonic-gate 	if (!output && cmd->cmd_prop_nv_pairs > 0)
33117c478bd9Sstevel@tonic-gate 		(void) printf(gettext("No such %s resource.\n"),
33127c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_IPD));
33137c478bd9Sstevel@tonic-gate }
33147c478bd9Sstevel@tonic-gate 
33157c478bd9Sstevel@tonic-gate static void
33167c478bd9Sstevel@tonic-gate output_net(FILE *fp, struct zone_nwiftab *nwiftab)
33177c478bd9Sstevel@tonic-gate {
33187c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_NET));
33197c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_ADDRESS, nwiftab->zone_nwif_address, B_TRUE);
33207c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE);
33217c478bd9Sstevel@tonic-gate }
33227c478bd9Sstevel@tonic-gate 
33237c478bd9Sstevel@tonic-gate static void
33247c478bd9Sstevel@tonic-gate info_net(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
33257c478bd9Sstevel@tonic-gate {
33267c478bd9Sstevel@tonic-gate 	struct zone_nwiftab lookup, user;
33277c478bd9Sstevel@tonic-gate 	bool output = FALSE;
33287c478bd9Sstevel@tonic-gate 
33297c478bd9Sstevel@tonic-gate 	if (zonecfg_setnwifent(handle) != Z_OK)
33307c478bd9Sstevel@tonic-gate 		return;
33317c478bd9Sstevel@tonic-gate 	while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
33327c478bd9Sstevel@tonic-gate 		if (cmd->cmd_prop_nv_pairs == 0) {
33337c478bd9Sstevel@tonic-gate 			output_net(fp, &lookup);
33347c478bd9Sstevel@tonic-gate 			continue;
33357c478bd9Sstevel@tonic-gate 		}
33367c478bd9Sstevel@tonic-gate 		if (fill_in_nwiftab(cmd, &user, TRUE) != Z_OK)
33377c478bd9Sstevel@tonic-gate 			continue;
33387c478bd9Sstevel@tonic-gate 		if (strlen(user.zone_nwif_physical) > 0 &&
33397c478bd9Sstevel@tonic-gate 		    strcmp(user.zone_nwif_physical,
33407c478bd9Sstevel@tonic-gate 		    lookup.zone_nwif_physical) != 0)
33417c478bd9Sstevel@tonic-gate 			continue;	/* no match */
33427c478bd9Sstevel@tonic-gate 		if (strlen(user.zone_nwif_address) > 0 &&
33437c478bd9Sstevel@tonic-gate 		    !zonecfg_same_net_address(user.zone_nwif_address,
33447c478bd9Sstevel@tonic-gate 		    lookup.zone_nwif_address))
33457c478bd9Sstevel@tonic-gate 			continue;	/* no match */
33467c478bd9Sstevel@tonic-gate 		output_net(fp, &lookup);
33477c478bd9Sstevel@tonic-gate 		output = TRUE;
33487c478bd9Sstevel@tonic-gate 	}
33497c478bd9Sstevel@tonic-gate 	(void) zonecfg_endnwifent(handle);
33507c478bd9Sstevel@tonic-gate 	/*
33517c478bd9Sstevel@tonic-gate 	 * If a property n/v pair was specified, warn the user if there was
33527c478bd9Sstevel@tonic-gate 	 * nothing to output.
33537c478bd9Sstevel@tonic-gate 	 */
33547c478bd9Sstevel@tonic-gate 	if (!output && cmd->cmd_prop_nv_pairs > 0)
33557c478bd9Sstevel@tonic-gate 		(void) printf(gettext("No such %s resource.\n"),
33567c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_NET));
33577c478bd9Sstevel@tonic-gate }
33587c478bd9Sstevel@tonic-gate 
33597c478bd9Sstevel@tonic-gate static void
33607c478bd9Sstevel@tonic-gate output_dev(FILE *fp, struct zone_devtab *devtab)
33617c478bd9Sstevel@tonic-gate {
33627c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%s\n", rt_to_str(RT_DEVICE));
33637c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_MATCH, devtab->zone_dev_match, B_TRUE);
33647c478bd9Sstevel@tonic-gate }
33657c478bd9Sstevel@tonic-gate 
33667c478bd9Sstevel@tonic-gate static void
33677c478bd9Sstevel@tonic-gate info_dev(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
33687c478bd9Sstevel@tonic-gate {
33697c478bd9Sstevel@tonic-gate 	struct zone_devtab lookup, user;
33707c478bd9Sstevel@tonic-gate 	bool output = FALSE;
33717c478bd9Sstevel@tonic-gate 
33727c478bd9Sstevel@tonic-gate 	if (zonecfg_setdevent(handle) != Z_OK)
33737c478bd9Sstevel@tonic-gate 		return;
33747c478bd9Sstevel@tonic-gate 	while (zonecfg_getdevent(handle, &lookup) == Z_OK) {
33757c478bd9Sstevel@tonic-gate 		if (cmd->cmd_prop_nv_pairs == 0) {
33767c478bd9Sstevel@tonic-gate 			output_dev(fp, &lookup);
33777c478bd9Sstevel@tonic-gate 			continue;
33787c478bd9Sstevel@tonic-gate 		}
33797c478bd9Sstevel@tonic-gate 		if (fill_in_devtab(cmd, &user, TRUE) != Z_OK)
33807c478bd9Sstevel@tonic-gate 			continue;
33817c478bd9Sstevel@tonic-gate 		if (strlen(user.zone_dev_match) > 0 &&
33827c478bd9Sstevel@tonic-gate 		    strcmp(user.zone_dev_match, lookup.zone_dev_match) != 0)
33837c478bd9Sstevel@tonic-gate 			continue;	/* no match */
33847c478bd9Sstevel@tonic-gate 		output_dev(fp, &lookup);
33857c478bd9Sstevel@tonic-gate 		output = TRUE;
33867c478bd9Sstevel@tonic-gate 	}
33877c478bd9Sstevel@tonic-gate 	(void) zonecfg_enddevent(handle);
33887c478bd9Sstevel@tonic-gate 	/*
33897c478bd9Sstevel@tonic-gate 	 * If a property n/v pair was specified, warn the user if there was
33907c478bd9Sstevel@tonic-gate 	 * nothing to output.
33917c478bd9Sstevel@tonic-gate 	 */
33927c478bd9Sstevel@tonic-gate 	if (!output && cmd->cmd_prop_nv_pairs > 0)
33937c478bd9Sstevel@tonic-gate 		(void) printf(gettext("No such %s resource.\n"),
33947c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_DEVICE));
33957c478bd9Sstevel@tonic-gate }
33967c478bd9Sstevel@tonic-gate 
33977c478bd9Sstevel@tonic-gate static void
33987c478bd9Sstevel@tonic-gate output_rctl(FILE *fp, struct zone_rctltab *rctltab)
33997c478bd9Sstevel@tonic-gate {
34007c478bd9Sstevel@tonic-gate 	struct zone_rctlvaltab *valptr;
34017c478bd9Sstevel@tonic-gate 
34027c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_RCTL));
34037c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_NAME, rctltab->zone_rctl_name, B_TRUE);
34047c478bd9Sstevel@tonic-gate 	for (valptr = rctltab->zone_rctl_valptr; valptr != NULL;
34057c478bd9Sstevel@tonic-gate 	    valptr = valptr->zone_rctlval_next) {
34067c478bd9Sstevel@tonic-gate 		fprintf(fp, "\t%s: (%s=%s,%s=%s,%s=%s)\n",
34077c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_VALUE),
34087c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
34097c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
34107c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
34117c478bd9Sstevel@tonic-gate 	}
34127c478bd9Sstevel@tonic-gate }
34137c478bd9Sstevel@tonic-gate 
34147c478bd9Sstevel@tonic-gate static void
34157c478bd9Sstevel@tonic-gate info_rctl(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
34167c478bd9Sstevel@tonic-gate {
34177c478bd9Sstevel@tonic-gate 	struct zone_rctltab lookup, user;
34187c478bd9Sstevel@tonic-gate 	bool output = FALSE;
34197c478bd9Sstevel@tonic-gate 
34207c478bd9Sstevel@tonic-gate 	if (zonecfg_setrctlent(handle) != Z_OK)
34217c478bd9Sstevel@tonic-gate 		return;
34227c478bd9Sstevel@tonic-gate 	while (zonecfg_getrctlent(handle, &lookup) == Z_OK) {
34237c478bd9Sstevel@tonic-gate 		if (cmd->cmd_prop_nv_pairs == 0) {
34247c478bd9Sstevel@tonic-gate 			output_rctl(fp, &lookup);
34257c478bd9Sstevel@tonic-gate 		} else if (fill_in_rctltab(cmd, &user, TRUE) == Z_OK &&
34267c478bd9Sstevel@tonic-gate 		    (strlen(user.zone_rctl_name) == 0 ||
34277c478bd9Sstevel@tonic-gate 		    strcmp(user.zone_rctl_name, lookup.zone_rctl_name) == 0)) {
34287c478bd9Sstevel@tonic-gate 			output_rctl(fp, &lookup);
34297c478bd9Sstevel@tonic-gate 			output = TRUE;
34307c478bd9Sstevel@tonic-gate 		}
34317c478bd9Sstevel@tonic-gate 		zonecfg_free_rctl_value_list(lookup.zone_rctl_valptr);
34327c478bd9Sstevel@tonic-gate 	}
34337c478bd9Sstevel@tonic-gate 	(void) zonecfg_endrctlent(handle);
34347c478bd9Sstevel@tonic-gate 	/*
34357c478bd9Sstevel@tonic-gate 	 * If a property n/v pair was specified, warn the user if there was
34367c478bd9Sstevel@tonic-gate 	 * nothing to output.
34377c478bd9Sstevel@tonic-gate 	 */
34387c478bd9Sstevel@tonic-gate 	if (!output && cmd->cmd_prop_nv_pairs > 0)
34397c478bd9Sstevel@tonic-gate 		(void) printf(gettext("No such %s resource.\n"),
34407c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_RCTL));
34417c478bd9Sstevel@tonic-gate }
34427c478bd9Sstevel@tonic-gate 
34437c478bd9Sstevel@tonic-gate static void
34447c478bd9Sstevel@tonic-gate output_attr(FILE *fp, struct zone_attrtab *attrtab)
34457c478bd9Sstevel@tonic-gate {
34467c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_ATTR));
34477c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_NAME, attrtab->zone_attr_name, B_TRUE);
34487c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_TYPE, attrtab->zone_attr_type, B_TRUE);
34497c478bd9Sstevel@tonic-gate 	output_prop(fp, PT_VALUE, attrtab->zone_attr_value, B_TRUE);
34507c478bd9Sstevel@tonic-gate }
34517c478bd9Sstevel@tonic-gate 
34527c478bd9Sstevel@tonic-gate static void
34537c478bd9Sstevel@tonic-gate info_attr(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
34547c478bd9Sstevel@tonic-gate {
34557c478bd9Sstevel@tonic-gate 	struct zone_attrtab lookup, user;
34567c478bd9Sstevel@tonic-gate 	bool output = FALSE;
34577c478bd9Sstevel@tonic-gate 
34587c478bd9Sstevel@tonic-gate 	if (zonecfg_setattrent(handle) != Z_OK)
34597c478bd9Sstevel@tonic-gate 		return;
34607c478bd9Sstevel@tonic-gate 	while (zonecfg_getattrent(handle, &lookup) == Z_OK) {
34617c478bd9Sstevel@tonic-gate 		if (cmd->cmd_prop_nv_pairs == 0) {
34627c478bd9Sstevel@tonic-gate 			output_attr(fp, &lookup);
34637c478bd9Sstevel@tonic-gate 			continue;
34647c478bd9Sstevel@tonic-gate 		}
34657c478bd9Sstevel@tonic-gate 		if (fill_in_attrtab(cmd, &user, TRUE) != Z_OK)
34667c478bd9Sstevel@tonic-gate 			continue;
34677c478bd9Sstevel@tonic-gate 		if (strlen(user.zone_attr_name) > 0 &&
34687c478bd9Sstevel@tonic-gate 		    strcmp(user.zone_attr_name, lookup.zone_attr_name) != 0)
34697c478bd9Sstevel@tonic-gate 			continue;	/* no match */
34707c478bd9Sstevel@tonic-gate 		if (strlen(user.zone_attr_type) > 0 &&
34717c478bd9Sstevel@tonic-gate 		    strcmp(user.zone_attr_type, lookup.zone_attr_type) != 0)
34727c478bd9Sstevel@tonic-gate 			continue;	/* no match */
34737c478bd9Sstevel@tonic-gate 		if (strlen(user.zone_attr_value) > 0 &&
34747c478bd9Sstevel@tonic-gate 		    strcmp(user.zone_attr_value, lookup.zone_attr_value) != 0)
34757c478bd9Sstevel@tonic-gate 			continue;	/* no match */
34767c478bd9Sstevel@tonic-gate 		output_attr(fp, &lookup);
34777c478bd9Sstevel@tonic-gate 		output = TRUE;
34787c478bd9Sstevel@tonic-gate 	}
34797c478bd9Sstevel@tonic-gate 	(void) zonecfg_endattrent(handle);
34807c478bd9Sstevel@tonic-gate 	/*
34817c478bd9Sstevel@tonic-gate 	 * If a property n/v pair was specified, warn the user if there was
34827c478bd9Sstevel@tonic-gate 	 * nothing to output.
34837c478bd9Sstevel@tonic-gate 	 */
34847c478bd9Sstevel@tonic-gate 	if (!output && cmd->cmd_prop_nv_pairs > 0)
34857c478bd9Sstevel@tonic-gate 		(void) printf(gettext("No such %s resource.\n"),
34867c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_ATTR));
34877c478bd9Sstevel@tonic-gate }
34887c478bd9Sstevel@tonic-gate 
3489fa9e4066Sahrens static void
3490fa9e4066Sahrens output_ds(FILE *fp, struct zone_dstab *dstab)
3491fa9e4066Sahrens {
3492fa9e4066Sahrens 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_DATASET));
3493fa9e4066Sahrens 	output_prop(fp, PT_NAME, dstab->zone_dataset_name, B_TRUE);
3494fa9e4066Sahrens }
3495fa9e4066Sahrens 
3496fa9e4066Sahrens static void
3497fa9e4066Sahrens info_ds(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
3498fa9e4066Sahrens {
3499fa9e4066Sahrens 	struct zone_dstab lookup, user;
3500fa9e4066Sahrens 	bool output = FALSE;
3501fa9e4066Sahrens 
3502fa9e4066Sahrens 	if (zonecfg_setdevent(handle) != Z_OK)
3503fa9e4066Sahrens 		return;
3504fa9e4066Sahrens 	while (zonecfg_getdsent(handle, &lookup) == Z_OK) {
3505fa9e4066Sahrens 		if (cmd->cmd_prop_nv_pairs == 0) {
3506fa9e4066Sahrens 			output_ds(fp, &lookup);
3507fa9e4066Sahrens 			continue;
3508fa9e4066Sahrens 		}
3509fa9e4066Sahrens 		if (fill_in_dstab(cmd, &user, TRUE) != Z_OK)
3510fa9e4066Sahrens 			continue;
3511fa9e4066Sahrens 		if (strlen(user.zone_dataset_name) > 0 &&
3512fa9e4066Sahrens 		    strcmp(user.zone_dataset_name,
3513fa9e4066Sahrens 		    lookup.zone_dataset_name) != 0)
3514fa9e4066Sahrens 			continue;	/* no match */
3515fa9e4066Sahrens 		output_ds(fp, &lookup);
3516fa9e4066Sahrens 		output = TRUE;
3517fa9e4066Sahrens 	}
3518fa9e4066Sahrens 	(void) zonecfg_enddsent(handle);
3519fa9e4066Sahrens 	/*
3520fa9e4066Sahrens 	 * If a property n/v pair was specified, warn the user if there was
3521fa9e4066Sahrens 	 * nothing to output.
3522fa9e4066Sahrens 	 */
3523fa9e4066Sahrens 	if (!output && cmd->cmd_prop_nv_pairs > 0)
3524fa9e4066Sahrens 		(void) printf(gettext("No such %s resource.\n"),
3525fa9e4066Sahrens 		    rt_to_str(RT_DATASET));
3526fa9e4066Sahrens }
3527fa9e4066Sahrens 
35287c478bd9Sstevel@tonic-gate void
35297c478bd9Sstevel@tonic-gate info_func(cmd_t *cmd)
35307c478bd9Sstevel@tonic-gate {
35317c478bd9Sstevel@tonic-gate 	FILE *fp = stdout;
35327c478bd9Sstevel@tonic-gate 	bool need_to_close = FALSE;
35337c478bd9Sstevel@tonic-gate 	char *pager;
35347c478bd9Sstevel@tonic-gate 
35357c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
35367c478bd9Sstevel@tonic-gate 
35377c478bd9Sstevel@tonic-gate 	if (initialize(TRUE) != Z_OK)
35387c478bd9Sstevel@tonic-gate 		return;
35397c478bd9Sstevel@tonic-gate 
35407c478bd9Sstevel@tonic-gate 	/* don't page error output */
35417c478bd9Sstevel@tonic-gate 	if (interactive_mode) {
35427c478bd9Sstevel@tonic-gate 		if ((pager = getenv("PAGER")) == NULL)
35437c478bd9Sstevel@tonic-gate 			pager = PAGER;
35447c478bd9Sstevel@tonic-gate 		if ((fp = popen(pager, "w")) != NULL)
35457c478bd9Sstevel@tonic-gate 			need_to_close = TRUE;
35467c478bd9Sstevel@tonic-gate 		setbuf(fp, NULL);
35477c478bd9Sstevel@tonic-gate 	}
35487c478bd9Sstevel@tonic-gate 
35497c478bd9Sstevel@tonic-gate 	if (!global_scope) {
35507c478bd9Sstevel@tonic-gate 		switch (resource_scope) {
35517c478bd9Sstevel@tonic-gate 		case RT_FS:
35527c478bd9Sstevel@tonic-gate 			output_fs(fp, &in_progress_fstab);
35537c478bd9Sstevel@tonic-gate 			break;
35547c478bd9Sstevel@tonic-gate 		case RT_IPD:
35557c478bd9Sstevel@tonic-gate 			output_ipd(fp, &in_progress_ipdtab);
35567c478bd9Sstevel@tonic-gate 			break;
35577c478bd9Sstevel@tonic-gate 		case RT_NET:
35587c478bd9Sstevel@tonic-gate 			output_net(fp, &in_progress_nwiftab);
35597c478bd9Sstevel@tonic-gate 			break;
35607c478bd9Sstevel@tonic-gate 		case RT_DEVICE:
35617c478bd9Sstevel@tonic-gate 			output_dev(fp, &in_progress_devtab);
35627c478bd9Sstevel@tonic-gate 			break;
35637c478bd9Sstevel@tonic-gate 		case RT_RCTL:
35647c478bd9Sstevel@tonic-gate 			output_rctl(fp, &in_progress_rctltab);
35657c478bd9Sstevel@tonic-gate 			break;
35667c478bd9Sstevel@tonic-gate 		case RT_ATTR:
35677c478bd9Sstevel@tonic-gate 			output_attr(fp, &in_progress_attrtab);
35687c478bd9Sstevel@tonic-gate 			break;
3569fa9e4066Sahrens 		case RT_DATASET:
3570fa9e4066Sahrens 			output_ds(fp, &in_progress_dstab);
3571fa9e4066Sahrens 			break;
35727c478bd9Sstevel@tonic-gate 		}
35737c478bd9Sstevel@tonic-gate 		goto cleanup;
35747c478bd9Sstevel@tonic-gate 	}
35757c478bd9Sstevel@tonic-gate 
35767c478bd9Sstevel@tonic-gate 	switch (cmd->cmd_res_type) {
35777c478bd9Sstevel@tonic-gate 	case RT_UNKNOWN:
3578087719fdSdp 		info_zonename(handle, fp);
35797c478bd9Sstevel@tonic-gate 		info_zonepath(handle, fp);
3580*9acbbeafSnn 		info_brand(handle, fp);
35817c478bd9Sstevel@tonic-gate 		info_autoboot(handle, fp);
35823f2f09c1Sdp 		info_bootargs(handle, fp);
35837c478bd9Sstevel@tonic-gate 		info_pool(handle, fp);
3584ffbafc53Scomay 		info_limitpriv(handle, fp);
35857c478bd9Sstevel@tonic-gate 		info_ipd(handle, fp, cmd);
35867c478bd9Sstevel@tonic-gate 		info_fs(handle, fp, cmd);
35877c478bd9Sstevel@tonic-gate 		info_net(handle, fp, cmd);
35887c478bd9Sstevel@tonic-gate 		info_dev(handle, fp, cmd);
35897c478bd9Sstevel@tonic-gate 		info_rctl(handle, fp, cmd);
35907c478bd9Sstevel@tonic-gate 		info_attr(handle, fp, cmd);
3591fa9e4066Sahrens 		info_ds(handle, fp, cmd);
35927c478bd9Sstevel@tonic-gate 		break;
3593087719fdSdp 	case RT_ZONENAME:
3594087719fdSdp 		info_zonename(handle, fp);
3595087719fdSdp 		break;
35967c478bd9Sstevel@tonic-gate 	case RT_ZONEPATH:
35977c478bd9Sstevel@tonic-gate 		info_zonepath(handle, fp);
35987c478bd9Sstevel@tonic-gate 		break;
3599*9acbbeafSnn 	case RT_BRAND:
3600*9acbbeafSnn 		info_brand(handle, fp);
3601*9acbbeafSnn 		break;
36027c478bd9Sstevel@tonic-gate 	case RT_AUTOBOOT:
36037c478bd9Sstevel@tonic-gate 		info_autoboot(handle, fp);
36047c478bd9Sstevel@tonic-gate 		break;
36057c478bd9Sstevel@tonic-gate 	case RT_POOL:
36067c478bd9Sstevel@tonic-gate 		info_pool(handle, fp);
36077c478bd9Sstevel@tonic-gate 		break;
3608ffbafc53Scomay 	case RT_LIMITPRIV:
3609ffbafc53Scomay 		info_limitpriv(handle, fp);
3610ffbafc53Scomay 		break;
36113f2f09c1Sdp 	case RT_BOOTARGS:
36123f2f09c1Sdp 		info_bootargs(handle, fp);
36133f2f09c1Sdp 		break;
36147c478bd9Sstevel@tonic-gate 	case RT_FS:
36157c478bd9Sstevel@tonic-gate 		info_fs(handle, fp, cmd);
36167c478bd9Sstevel@tonic-gate 		break;
36177c478bd9Sstevel@tonic-gate 	case RT_IPD:
36187c478bd9Sstevel@tonic-gate 		info_ipd(handle, fp, cmd);
36197c478bd9Sstevel@tonic-gate 		break;
36207c478bd9Sstevel@tonic-gate 	case RT_NET:
36217c478bd9Sstevel@tonic-gate 		info_net(handle, fp, cmd);
36227c478bd9Sstevel@tonic-gate 		break;
36237c478bd9Sstevel@tonic-gate 	case RT_DEVICE:
36247c478bd9Sstevel@tonic-gate 		info_dev(handle, fp, cmd);
36257c478bd9Sstevel@tonic-gate 		break;
36267c478bd9Sstevel@tonic-gate 	case RT_RCTL:
36277c478bd9Sstevel@tonic-gate 		info_rctl(handle, fp, cmd);
36287c478bd9Sstevel@tonic-gate 		break;
36297c478bd9Sstevel@tonic-gate 	case RT_ATTR:
36307c478bd9Sstevel@tonic-gate 		info_attr(handle, fp, cmd);
36317c478bd9Sstevel@tonic-gate 		break;
3632fa9e4066Sahrens 	case RT_DATASET:
3633fa9e4066Sahrens 		info_ds(handle, fp, cmd);
3634fa9e4066Sahrens 		break;
36357c478bd9Sstevel@tonic-gate 	default:
36367c478bd9Sstevel@tonic-gate 		zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
36377c478bd9Sstevel@tonic-gate 		    TRUE);
36387c478bd9Sstevel@tonic-gate 	}
36397c478bd9Sstevel@tonic-gate 
36407c478bd9Sstevel@tonic-gate cleanup:
36417c478bd9Sstevel@tonic-gate 	if (need_to_close)
36427c478bd9Sstevel@tonic-gate 		(void) pclose(fp);
36437c478bd9Sstevel@tonic-gate }
36447c478bd9Sstevel@tonic-gate 
3645087719fdSdp /*
3646087719fdSdp  * Helper function for verify-- checks that a required string property
3647087719fdSdp  * exists.
3648087719fdSdp  */
3649087719fdSdp static void
3650087719fdSdp check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
36517c478bd9Sstevel@tonic-gate {
3652087719fdSdp 	if (strlen(attr) == 0) {
3653087719fdSdp 		zerr(gettext("%s: %s not specified"), rt_to_str(rt),
3654087719fdSdp 		    pt_to_str(pt));
3655087719fdSdp 		saw_error = TRUE;
3656087719fdSdp 		if (*ret_val == Z_OK)
3657087719fdSdp 			*ret_val = Z_REQD_PROPERTY_MISSING;
36587c478bd9Sstevel@tonic-gate 	}
36597c478bd9Sstevel@tonic-gate }
36607c478bd9Sstevel@tonic-gate 
3661*9acbbeafSnn static int
3662*9acbbeafSnn do_subproc(char *cmdbuf)
3663*9acbbeafSnn {
3664*9acbbeafSnn 	char inbuf[MAX_CMD_LEN];
3665*9acbbeafSnn 	FILE *file;
3666*9acbbeafSnn 	int status;
3667*9acbbeafSnn 
3668*9acbbeafSnn 	file = popen(cmdbuf, "r");
3669*9acbbeafSnn 	if (file == NULL) {
3670*9acbbeafSnn 		zerr(gettext("Could not launch: %s"), cmdbuf);
3671*9acbbeafSnn 		return (-1);
3672*9acbbeafSnn 	}
3673*9acbbeafSnn 
3674*9acbbeafSnn 	while (fgets(inbuf, sizeof (inbuf), file) != NULL)
3675*9acbbeafSnn 		fprintf(stderr, "%s", inbuf);
3676*9acbbeafSnn 	status = pclose(file);
3677*9acbbeafSnn 
3678*9acbbeafSnn 	if (WIFSIGNALED(status)) {
3679*9acbbeafSnn 		zerr(gettext("%s unexpectedly terminated due to signal %d"),
3680*9acbbeafSnn 		    cmdbuf, WTERMSIG(status));
3681*9acbbeafSnn 		return (-1);
3682*9acbbeafSnn 	}
3683*9acbbeafSnn 	assert(WIFEXITED(status));
3684*9acbbeafSnn 	return (WEXITSTATUS(status));
3685*9acbbeafSnn }
3686*9acbbeafSnn 
3687*9acbbeafSnn static int
3688*9acbbeafSnn brand_verify(zone_dochandle_t handle)
3689*9acbbeafSnn {
3690*9acbbeafSnn 	char *xml_file = "/tmp/zonecfg_verify.XXXXXX";
3691*9acbbeafSnn 	char cmdbuf[MAX_CMD_LEN];
3692*9acbbeafSnn 	brand_handle_t *bhp;
3693*9acbbeafSnn 	char brand[MAXNAMELEN];
3694*9acbbeafSnn 	int err;
3695*9acbbeafSnn 
3696*9acbbeafSnn 	if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
3697*9acbbeafSnn 		zerr("%s: %s\n", zone, gettext("could not get zone brand"));
3698*9acbbeafSnn 		return (Z_INVALID_DOCUMENT);
3699*9acbbeafSnn 	}
3700*9acbbeafSnn 	if ((bhp = brand_open(brand)) == NULL) {
3701*9acbbeafSnn 		zerr("%s: %s\n", zone, gettext("unknown brand."));
3702*9acbbeafSnn 		return (Z_INVALID_DOCUMENT);
3703*9acbbeafSnn 	}
3704*9acbbeafSnn 
3705*9acbbeafSnn 	/*
3706*9acbbeafSnn 	 * Fetch the verify command, if any, from the brand configuration
3707*9acbbeafSnn 	 * and build the command line to execute it.
3708*9acbbeafSnn 	 */
3709*9acbbeafSnn 	strcpy(cmdbuf, EXEC_PREFIX);
3710*9acbbeafSnn 	err = brand_get_verify_cfg(bhp, cmdbuf + EXEC_LEN,
3711*9acbbeafSnn 	    sizeof (cmdbuf) - (EXEC_LEN + (strlen(xml_file) + 1)));
3712*9acbbeafSnn 	brand_close(bhp);
3713*9acbbeafSnn 	if (err != Z_OK) {
3714*9acbbeafSnn 		zerr("%s: %s\n", zone,
3715*9acbbeafSnn 		    gettext("could not get brand verification command"));
3716*9acbbeafSnn 		return (Z_INVALID_DOCUMENT);
3717*9acbbeafSnn 	}
3718*9acbbeafSnn 
3719*9acbbeafSnn 	/*
3720*9acbbeafSnn 	 * If the brand doesn't provide a verification routine, we just
3721*9acbbeafSnn 	 * return success.
3722*9acbbeafSnn 	 */
3723*9acbbeafSnn 	if (strlen(cmdbuf) == EXEC_LEN)
3724*9acbbeafSnn 		return (Z_OK);
3725*9acbbeafSnn 
3726*9acbbeafSnn 	/*
3727*9acbbeafSnn 	 * Dump the current config information for this zone to a file.
3728*9acbbeafSnn 	 */
3729*9acbbeafSnn 	if (mkstemp(xml_file) == NULL)
3730*9acbbeafSnn 		return (Z_TEMP_FILE);
3731*9acbbeafSnn 	if ((err = zonecfg_verify_save(handle, xml_file)) != Z_OK) {
3732*9acbbeafSnn 		(void) unlink(xml_file);
3733*9acbbeafSnn 		return (err);
3734*9acbbeafSnn 	}
3735*9acbbeafSnn 
3736*9acbbeafSnn 	/*
3737*9acbbeafSnn 	 * Execute the verification command.
3738*9acbbeafSnn 	 */
3739*9acbbeafSnn 	if ((strlcat(cmdbuf, " ", MAX_CMD_LEN) >= MAX_CMD_LEN) ||
3740*9acbbeafSnn 	    (strlcat(cmdbuf, xml_file, MAX_CMD_LEN) >= MAX_CMD_LEN)) {
3741*9acbbeafSnn 		err = Z_BRAND_ERROR;
3742*9acbbeafSnn 	} else {
3743*9acbbeafSnn 		err = do_subproc(cmdbuf);
3744*9acbbeafSnn 	}
3745*9acbbeafSnn 
3746*9acbbeafSnn 	(void) unlink(xml_file);
3747*9acbbeafSnn 	return ((err == Z_OK) ? Z_OK : Z_BRAND_ERROR);
3748*9acbbeafSnn }
3749*9acbbeafSnn 
37507c478bd9Sstevel@tonic-gate /*
37517c478bd9Sstevel@tonic-gate  * See the DTD for which attributes are required for which resources.
37527c478bd9Sstevel@tonic-gate  *
37537c478bd9Sstevel@tonic-gate  * This function can be called by commit_func(), which needs to save things,
37547c478bd9Sstevel@tonic-gate  * in addition to the general call from parse_and_run(), which doesn't need
37557c478bd9Sstevel@tonic-gate  * things saved.  Since the parameters are standardized, we distinguish by
37567c478bd9Sstevel@tonic-gate  * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
37577c478bd9Sstevel@tonic-gate  * that a save is needed.
37587c478bd9Sstevel@tonic-gate  */
37597c478bd9Sstevel@tonic-gate void
37607c478bd9Sstevel@tonic-gate verify_func(cmd_t *cmd)
37617c478bd9Sstevel@tonic-gate {
37627c478bd9Sstevel@tonic-gate 	struct zone_nwiftab nwiftab;
37637c478bd9Sstevel@tonic-gate 	struct zone_fstab fstab;
37647c478bd9Sstevel@tonic-gate 	struct zone_attrtab attrtab;
37657c478bd9Sstevel@tonic-gate 	struct zone_rctltab rctltab;
3766fa9e4066Sahrens 	struct zone_dstab dstab;
37677c478bd9Sstevel@tonic-gate 	char zonepath[MAXPATHLEN];
3768*9acbbeafSnn 	char brand[MAXNAMELEN];
37697c478bd9Sstevel@tonic-gate 	int err, ret_val = Z_OK, arg;
37707c478bd9Sstevel@tonic-gate 	bool save = FALSE;
37717c478bd9Sstevel@tonic-gate 
37727c478bd9Sstevel@tonic-gate 	optind = 0;
37737c478bd9Sstevel@tonic-gate 	if ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
37747c478bd9Sstevel@tonic-gate 		switch (arg) {
37757c478bd9Sstevel@tonic-gate 		case '?':
37767c478bd9Sstevel@tonic-gate 			longer_usage(CMD_VERIFY);
37777c478bd9Sstevel@tonic-gate 			return;
37787c478bd9Sstevel@tonic-gate 		default:
37797c478bd9Sstevel@tonic-gate 			short_usage(CMD_VERIFY);
37807c478bd9Sstevel@tonic-gate 			return;
37817c478bd9Sstevel@tonic-gate 		}
37827c478bd9Sstevel@tonic-gate 	}
37837c478bd9Sstevel@tonic-gate 	if (optind > cmd->cmd_argc) {
37847c478bd9Sstevel@tonic-gate 		short_usage(CMD_VERIFY);
37857c478bd9Sstevel@tonic-gate 		return;
37867c478bd9Sstevel@tonic-gate 	}
37877c478bd9Sstevel@tonic-gate 
37887c478bd9Sstevel@tonic-gate 	if (zone_is_read_only(CMD_VERIFY))
37897c478bd9Sstevel@tonic-gate 		return;
37907c478bd9Sstevel@tonic-gate 
37917c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
37927c478bd9Sstevel@tonic-gate 
37937c478bd9Sstevel@tonic-gate 	if (cmd->cmd_argc > 0 && (strcmp(cmd->cmd_argv[0], "save") == 0))
37947c478bd9Sstevel@tonic-gate 		save = TRUE;
37957c478bd9Sstevel@tonic-gate 	if (initialize(TRUE) != Z_OK)
37967c478bd9Sstevel@tonic-gate 		return;
37977c478bd9Sstevel@tonic-gate 
37987c478bd9Sstevel@tonic-gate 	if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) != Z_OK) {
3799087719fdSdp 		zerr(gettext("%s not specified"), pt_to_str(PT_ZONEPATH));
38007c478bd9Sstevel@tonic-gate 		ret_val = Z_REQD_RESOURCE_MISSING;
38017c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
38027c478bd9Sstevel@tonic-gate 	}
38037c478bd9Sstevel@tonic-gate 	if (strlen(zonepath) == 0) {
3804087719fdSdp 		zerr(gettext("%s cannot be empty."), pt_to_str(PT_ZONEPATH));
38057c478bd9Sstevel@tonic-gate 		ret_val = Z_REQD_RESOURCE_MISSING;
38067c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
38077c478bd9Sstevel@tonic-gate 	}
38087c478bd9Sstevel@tonic-gate 
3809*9acbbeafSnn 	if ((err = zonecfg_get_brand(handle, brand, sizeof (brand))) != Z_OK) {
3810*9acbbeafSnn 		zone_perror(zone, err, TRUE);
3811*9acbbeafSnn 		return;
3812*9acbbeafSnn 	}
3813*9acbbeafSnn 	if (strcmp(brand, NATIVE_BRAND_NAME) != 0) {
3814*9acbbeafSnn 		if ((err = brand_verify(handle)) != Z_OK) {
3815*9acbbeafSnn 			zone_perror(zone, err, TRUE);
3816*9acbbeafSnn 			return;
3817*9acbbeafSnn 		}
3818*9acbbeafSnn 	}
3819*9acbbeafSnn 
38207c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_setipdent(handle)) != Z_OK) {
38217c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, TRUE);
38227c478bd9Sstevel@tonic-gate 		return;
38237c478bd9Sstevel@tonic-gate 	}
38247c478bd9Sstevel@tonic-gate 	while (zonecfg_getipdent(handle, &fstab) == Z_OK) {
3825087719fdSdp 		check_reqd_prop(fstab.zone_fs_dir, RT_IPD, PT_DIR, &ret_val);
38267c478bd9Sstevel@tonic-gate 	}
38277c478bd9Sstevel@tonic-gate 	(void) zonecfg_endipdent(handle);
38287c478bd9Sstevel@tonic-gate 
38297c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_setfsent(handle)) != Z_OK) {
38307c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, TRUE);
38317c478bd9Sstevel@tonic-gate 		return;
38327c478bd9Sstevel@tonic-gate 	}
38337c478bd9Sstevel@tonic-gate 	while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
3834087719fdSdp 		check_reqd_prop(fstab.zone_fs_dir, RT_FS, PT_DIR, &ret_val);
3835087719fdSdp 		check_reqd_prop(fstab.zone_fs_special, RT_FS, PT_SPECIAL,
3836087719fdSdp 		    &ret_val);
3837087719fdSdp 		check_reqd_prop(fstab.zone_fs_type, RT_FS, PT_TYPE, &ret_val);
3838087719fdSdp 
38397c478bd9Sstevel@tonic-gate 		zonecfg_free_fs_option_list(fstab.zone_fs_options);
38407c478bd9Sstevel@tonic-gate 	}
38417c478bd9Sstevel@tonic-gate 	(void) zonecfg_endfsent(handle);
38427c478bd9Sstevel@tonic-gate 
38437c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
38447c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, TRUE);
38457c478bd9Sstevel@tonic-gate 		return;
38467c478bd9Sstevel@tonic-gate 	}
38477c478bd9Sstevel@tonic-gate 	while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
3848087719fdSdp 		check_reqd_prop(nwiftab.zone_nwif_address, RT_NET,
3849087719fdSdp 		    PT_ADDRESS, &ret_val);
3850087719fdSdp 		check_reqd_prop(nwiftab.zone_nwif_physical, RT_NET,
3851087719fdSdp 		    PT_PHYSICAL, &ret_val);
38527c478bd9Sstevel@tonic-gate 	}
38537c478bd9Sstevel@tonic-gate 	(void) zonecfg_endnwifent(handle);
38547c478bd9Sstevel@tonic-gate 
38557c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
38567c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, TRUE);
38577c478bd9Sstevel@tonic-gate 		return;
38587c478bd9Sstevel@tonic-gate 	}
38597c478bd9Sstevel@tonic-gate 	while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
3860087719fdSdp 		check_reqd_prop(rctltab.zone_rctl_name, RT_RCTL, PT_NAME,
3861087719fdSdp 		    &ret_val);
3862087719fdSdp 
38637c478bd9Sstevel@tonic-gate 		if (rctltab.zone_rctl_valptr == NULL) {
38647c478bd9Sstevel@tonic-gate 			zerr(gettext("%s: no %s specified"),
38657c478bd9Sstevel@tonic-gate 			    rt_to_str(RT_RCTL), pt_to_str(PT_VALUE));
38667c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
38677c478bd9Sstevel@tonic-gate 			if (ret_val == Z_OK)
38687c478bd9Sstevel@tonic-gate 				ret_val = Z_REQD_PROPERTY_MISSING;
38697c478bd9Sstevel@tonic-gate 		} else {
38707c478bd9Sstevel@tonic-gate 			zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
38717c478bd9Sstevel@tonic-gate 		}
38727c478bd9Sstevel@tonic-gate 	}
38737c478bd9Sstevel@tonic-gate 	(void) zonecfg_endrctlent(handle);
38747c478bd9Sstevel@tonic-gate 
38757c478bd9Sstevel@tonic-gate 	if ((err = zonecfg_setattrent(handle)) != Z_OK) {
38767c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, TRUE);
38777c478bd9Sstevel@tonic-gate 		return;
38787c478bd9Sstevel@tonic-gate 	}
38797c478bd9Sstevel@tonic-gate 	while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
3880087719fdSdp 		check_reqd_prop(attrtab.zone_attr_name, RT_ATTR, PT_NAME,
3881087719fdSdp 		    &ret_val);
3882087719fdSdp 		check_reqd_prop(attrtab.zone_attr_type, RT_ATTR, PT_TYPE,
3883087719fdSdp 		    &ret_val);
3884087719fdSdp 		check_reqd_prop(attrtab.zone_attr_value, RT_ATTR, PT_VALUE,
3885087719fdSdp 		    &ret_val);
38867c478bd9Sstevel@tonic-gate 	}
38877c478bd9Sstevel@tonic-gate 	(void) zonecfg_endattrent(handle);
38887c478bd9Sstevel@tonic-gate 
3889fa9e4066Sahrens 	if ((err = zonecfg_setdsent(handle)) != Z_OK) {
3890fa9e4066Sahrens 		zone_perror(zone, err, TRUE);
3891fa9e4066Sahrens 		return;
3892fa9e4066Sahrens 	}
3893fa9e4066Sahrens 	while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
3894fa9e4066Sahrens 		if (strlen(dstab.zone_dataset_name) == 0) {
3895fa9e4066Sahrens 			zerr("%s: %s %s", rt_to_str(RT_DATASET),
3896fa9e4066Sahrens 			    pt_to_str(PT_NAME), gettext("not specified"));
3897fa9e4066Sahrens 			saw_error = TRUE;
3898fa9e4066Sahrens 			if (ret_val == Z_OK)
3899fa9e4066Sahrens 				ret_val = Z_REQD_PROPERTY_MISSING;
3900fa9e4066Sahrens 		} else if (!zfs_name_valid(dstab.zone_dataset_name,
3901fa9e4066Sahrens 		    ZFS_TYPE_FILESYSTEM)) {
3902fa9e4066Sahrens 			zerr("%s: %s %s", rt_to_str(RT_DATASET),
3903fa9e4066Sahrens 			    pt_to_str(PT_NAME), gettext("invalid"));
3904fa9e4066Sahrens 			saw_error = TRUE;
3905fa9e4066Sahrens 			if (ret_val == Z_OK)
3906fa9e4066Sahrens 				ret_val = Z_BAD_PROPERTY;
3907fa9e4066Sahrens 		}
3908fa9e4066Sahrens 
3909fa9e4066Sahrens 	}
3910fa9e4066Sahrens 	(void) zonecfg_enddsent(handle);
3911fa9e4066Sahrens 
39127c478bd9Sstevel@tonic-gate 	if (!global_scope) {
39137c478bd9Sstevel@tonic-gate 		zerr(gettext("resource specification incomplete"));
39147c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
39157c478bd9Sstevel@tonic-gate 		if (ret_val == Z_OK)
39167c478bd9Sstevel@tonic-gate 			ret_val = Z_INSUFFICIENT_SPEC;
39177c478bd9Sstevel@tonic-gate 	}
39187c478bd9Sstevel@tonic-gate 
39197c478bd9Sstevel@tonic-gate 	if (save) {
3920087719fdSdp 		if (ret_val == Z_OK) {
3921087719fdSdp 			if ((ret_val = zonecfg_save(handle)) == Z_OK) {
3922087719fdSdp 				need_to_commit = FALSE;
3923087719fdSdp 				(void) strlcpy(revert_zone, zone,
3924087719fdSdp 				    sizeof (revert_zone));
3925087719fdSdp 			}
3926087719fdSdp 		} else {
3927087719fdSdp 			zerr(gettext("Zone %s failed to verify"), zone);
3928087719fdSdp 		}
39297c478bd9Sstevel@tonic-gate 	}
39307c478bd9Sstevel@tonic-gate 	if (ret_val != Z_OK)
39317c478bd9Sstevel@tonic-gate 		zone_perror(zone, ret_val, TRUE);
39327c478bd9Sstevel@tonic-gate }
39337c478bd9Sstevel@tonic-gate 
39347c478bd9Sstevel@tonic-gate void
39357c478bd9Sstevel@tonic-gate cancel_func(cmd_t *cmd)
39367c478bd9Sstevel@tonic-gate {
39377c478bd9Sstevel@tonic-gate 	int arg;
39387c478bd9Sstevel@tonic-gate 
39397c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
39407c478bd9Sstevel@tonic-gate 
39417c478bd9Sstevel@tonic-gate 	optind = 0;
39427c478bd9Sstevel@tonic-gate 	if ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
39437c478bd9Sstevel@tonic-gate 		switch (arg) {
39447c478bd9Sstevel@tonic-gate 		case '?':
39457c478bd9Sstevel@tonic-gate 			longer_usage(CMD_CANCEL);
39467c478bd9Sstevel@tonic-gate 			return;
39477c478bd9Sstevel@tonic-gate 		default:
39487c478bd9Sstevel@tonic-gate 			short_usage(CMD_CANCEL);
39497c478bd9Sstevel@tonic-gate 			return;
39507c478bd9Sstevel@tonic-gate 		}
39517c478bd9Sstevel@tonic-gate 	}
39527c478bd9Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
39537c478bd9Sstevel@tonic-gate 		short_usage(CMD_CANCEL);
39547c478bd9Sstevel@tonic-gate 		return;
39557c478bd9Sstevel@tonic-gate 	}
39567c478bd9Sstevel@tonic-gate 
39577c478bd9Sstevel@tonic-gate 	if (global_scope)
39587c478bd9Sstevel@tonic-gate 		scope_usage(CMD_CANCEL);
39597c478bd9Sstevel@tonic-gate 	global_scope = TRUE;
39607c478bd9Sstevel@tonic-gate 	zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
39617c478bd9Sstevel@tonic-gate 	bzero(&in_progress_fstab, sizeof (in_progress_fstab));
39627c478bd9Sstevel@tonic-gate 	bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
3963fa9e4066Sahrens 	bzero(&in_progress_ipdtab, sizeof (in_progress_ipdtab));
39647c478bd9Sstevel@tonic-gate 	bzero(&in_progress_devtab, sizeof (in_progress_devtab));
39657c478bd9Sstevel@tonic-gate 	zonecfg_free_rctl_value_list(in_progress_rctltab.zone_rctl_valptr);
39667c478bd9Sstevel@tonic-gate 	bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
39677c478bd9Sstevel@tonic-gate 	bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
3968fa9e4066Sahrens 	bzero(&in_progress_dstab, sizeof (in_progress_dstab));
39697c478bd9Sstevel@tonic-gate }
39707c478bd9Sstevel@tonic-gate 
39717c478bd9Sstevel@tonic-gate static int
39727c478bd9Sstevel@tonic-gate validate_attr_name(char *name)
39737c478bd9Sstevel@tonic-gate {
39747c478bd9Sstevel@tonic-gate 	int i;
39757c478bd9Sstevel@tonic-gate 
39767c478bd9Sstevel@tonic-gate 	if (!isalnum(name[0])) {
39777c478bd9Sstevel@tonic-gate 		zerr(gettext("Invalid %s %s %s: must start with an alpha-"
39787c478bd9Sstevel@tonic-gate 		    "numeric character."), rt_to_str(RT_ATTR),
39797c478bd9Sstevel@tonic-gate 		    pt_to_str(PT_NAME), name);
39807c478bd9Sstevel@tonic-gate 		return (Z_INVAL);
39817c478bd9Sstevel@tonic-gate 	}
39827c478bd9Sstevel@tonic-gate 	for (i = 1; name[i]; i++)
39837c478bd9Sstevel@tonic-gate 		if (!isalnum(name[i]) && name[i] != '-' && name[i] != '.') {
39847c478bd9Sstevel@tonic-gate 			zerr(gettext("Invalid %s %s %s: can only contain "
39857c478bd9Sstevel@tonic-gate 			    "alpha-numeric characters, plus '-' and '.'."),
39867c478bd9Sstevel@tonic-gate 			    rt_to_str(RT_ATTR), pt_to_str(PT_NAME), name);
39877c478bd9Sstevel@tonic-gate 			return (Z_INVAL);
39887c478bd9Sstevel@tonic-gate 		}
39897c478bd9Sstevel@tonic-gate 	return (Z_OK);
39907c478bd9Sstevel@tonic-gate }
39917c478bd9Sstevel@tonic-gate 
39927c478bd9Sstevel@tonic-gate static int
39937c478bd9Sstevel@tonic-gate validate_attr_type_val(struct zone_attrtab *attrtab)
39947c478bd9Sstevel@tonic-gate {
39957c478bd9Sstevel@tonic-gate 	boolean_t boolval;
39967c478bd9Sstevel@tonic-gate 	int64_t intval;
39977c478bd9Sstevel@tonic-gate 	char strval[MAXNAMELEN];
39987c478bd9Sstevel@tonic-gate 	uint64_t uintval;
39997c478bd9Sstevel@tonic-gate 
40007c478bd9Sstevel@tonic-gate 	if (strcmp(attrtab->zone_attr_type, "boolean") == 0) {
40017c478bd9Sstevel@tonic-gate 		if (zonecfg_get_attr_boolean(attrtab, &boolval) == Z_OK)
40027c478bd9Sstevel@tonic-gate 			return (Z_OK);
40037c478bd9Sstevel@tonic-gate 		zerr(gettext("invalid %s value for %s=%s"),
40047c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "boolean");
40057c478bd9Sstevel@tonic-gate 		return (Z_ERR);
40067c478bd9Sstevel@tonic-gate 	}
40077c478bd9Sstevel@tonic-gate 
40087c478bd9Sstevel@tonic-gate 	if (strcmp(attrtab->zone_attr_type, "int") == 0) {
40097c478bd9Sstevel@tonic-gate 		if (zonecfg_get_attr_int(attrtab, &intval) == Z_OK)
40107c478bd9Sstevel@tonic-gate 			return (Z_OK);
40117c478bd9Sstevel@tonic-gate 		zerr(gettext("invalid %s value for %s=%s"),
40127c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "int");
40137c478bd9Sstevel@tonic-gate 		return (Z_ERR);
40147c478bd9Sstevel@tonic-gate 	}
40157c478bd9Sstevel@tonic-gate 
40167c478bd9Sstevel@tonic-gate 	if (strcmp(attrtab->zone_attr_type, "string") == 0) {
40177c478bd9Sstevel@tonic-gate 		if (zonecfg_get_attr_string(attrtab, strval,
40187c478bd9Sstevel@tonic-gate 		    sizeof (strval)) == Z_OK)
40197c478bd9Sstevel@tonic-gate 			return (Z_OK);
40207c478bd9Sstevel@tonic-gate 		zerr(gettext("invalid %s value for %s=%s"),
40217c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "string");
40227c478bd9Sstevel@tonic-gate 		return (Z_ERR);
40237c478bd9Sstevel@tonic-gate 	}
40247c478bd9Sstevel@tonic-gate 
40257c478bd9Sstevel@tonic-gate 	if (strcmp(attrtab->zone_attr_type, "uint") == 0) {
40267c478bd9Sstevel@tonic-gate 		if (zonecfg_get_attr_uint(attrtab, &uintval) == Z_OK)
40277c478bd9Sstevel@tonic-gate 			return (Z_OK);
40287c478bd9Sstevel@tonic-gate 		zerr(gettext("invalid %s value for %s=%s"),
40297c478bd9Sstevel@tonic-gate 		    rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "uint");
40307c478bd9Sstevel@tonic-gate 		return (Z_ERR);
40317c478bd9Sstevel@tonic-gate 	}
40327c478bd9Sstevel@tonic-gate 
40337c478bd9Sstevel@tonic-gate 	zerr(gettext("invalid %s %s '%s'"), rt_to_str(RT_ATTR),
40347c478bd9Sstevel@tonic-gate 	    pt_to_str(PT_TYPE), attrtab->zone_attr_type);
40357c478bd9Sstevel@tonic-gate 	return (Z_ERR);
40367c478bd9Sstevel@tonic-gate }
40377c478bd9Sstevel@tonic-gate 
4038087719fdSdp /*
4039087719fdSdp  * Helper function for end_func-- checks the existence of a given property
4040087719fdSdp  * and emits a message if not specified.
4041087719fdSdp  */
4042087719fdSdp static int
4043087719fdSdp end_check_reqd(char *attr, int pt, bool *validation_failed)
4044087719fdSdp {
4045087719fdSdp 	if (strlen(attr) == 0) {
4046087719fdSdp 		*validation_failed = TRUE;
4047087719fdSdp 		zerr(gettext("%s not specified"), pt_to_str(pt));
4048087719fdSdp 		return (Z_ERR);
4049087719fdSdp 	}
4050087719fdSdp 	return (Z_OK);
4051087719fdSdp }
4052087719fdSdp 
40537c478bd9Sstevel@tonic-gate void
40547c478bd9Sstevel@tonic-gate end_func(cmd_t *cmd)
40557c478bd9Sstevel@tonic-gate {
40567c478bd9Sstevel@tonic-gate 	bool validation_failed = FALSE;
40577c478bd9Sstevel@tonic-gate 	struct zone_fstab tmp_fstab;
40587c478bd9Sstevel@tonic-gate 	struct zone_nwiftab tmp_nwiftab;
40597c478bd9Sstevel@tonic-gate 	struct zone_devtab tmp_devtab;
40607c478bd9Sstevel@tonic-gate 	struct zone_rctltab tmp_rctltab;
40617c478bd9Sstevel@tonic-gate 	struct zone_attrtab tmp_attrtab;
4062fa9e4066Sahrens 	struct zone_dstab tmp_dstab;
40637c478bd9Sstevel@tonic-gate 	int err, arg;
40647c478bd9Sstevel@tonic-gate 
40657c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
40667c478bd9Sstevel@tonic-gate 
40677c478bd9Sstevel@tonic-gate 	optind = 0;
40687c478bd9Sstevel@tonic-gate 	if ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
40697c478bd9Sstevel@tonic-gate 		switch (arg) {
40707c478bd9Sstevel@tonic-gate 		case '?':
40717c478bd9Sstevel@tonic-gate 			longer_usage(CMD_END);
40727c478bd9Sstevel@tonic-gate 			return;
40737c478bd9Sstevel@tonic-gate 		default:
40747c478bd9Sstevel@tonic-gate 			short_usage(CMD_END);
40757c478bd9Sstevel@tonic-gate 			return;
40767c478bd9Sstevel@tonic-gate 		}
40777c478bd9Sstevel@tonic-gate 	}
40787c478bd9Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
40797c478bd9Sstevel@tonic-gate 		short_usage(CMD_END);
40807c478bd9Sstevel@tonic-gate 		return;
40817c478bd9Sstevel@tonic-gate 	}
40827c478bd9Sstevel@tonic-gate 
40837c478bd9Sstevel@tonic-gate 	if (global_scope) {
40847c478bd9Sstevel@tonic-gate 		scope_usage(CMD_END);
40857c478bd9Sstevel@tonic-gate 		return;
40867c478bd9Sstevel@tonic-gate 	}
40877c478bd9Sstevel@tonic-gate 
40887c478bd9Sstevel@tonic-gate 	assert(end_op == CMD_ADD || end_op == CMD_SELECT);
40897c478bd9Sstevel@tonic-gate 
40907c478bd9Sstevel@tonic-gate 	switch (resource_scope) {
40917c478bd9Sstevel@tonic-gate 	case RT_FS:
40927c478bd9Sstevel@tonic-gate 		/* First make sure everything was filled in. */
4093087719fdSdp 		if (end_check_reqd(in_progress_fstab.zone_fs_dir,
4094087719fdSdp 		    PT_DIR, &validation_failed) == Z_OK) {
4095087719fdSdp 			if (in_progress_fstab.zone_fs_dir[0] != '/') {
4096087719fdSdp 				zerr(gettext("%s %s is not an absolute path."),
4097087719fdSdp 				    pt_to_str(PT_DIR),
4098087719fdSdp 				    in_progress_fstab.zone_fs_dir);
4099087719fdSdp 				validation_failed = TRUE;
4100087719fdSdp 			}
41017c478bd9Sstevel@tonic-gate 		}
4102087719fdSdp 
4103087719fdSdp 		(void) end_check_reqd(in_progress_fstab.zone_fs_special,
4104087719fdSdp 		    PT_SPECIAL, &validation_failed);
4105087719fdSdp 
41067c478bd9Sstevel@tonic-gate 		if (in_progress_fstab.zone_fs_raw[0] != '\0' &&
41077c478bd9Sstevel@tonic-gate 		    in_progress_fstab.zone_fs_raw[0] != '/') {
4108087719fdSdp 			zerr(gettext("%s %s is not an absolute path."),
4109087719fdSdp 			    pt_to_str(PT_RAW),
4110087719fdSdp 			    in_progress_fstab.zone_fs_raw);
41117c478bd9Sstevel@tonic-gate 			validation_failed = TRUE;
41127c478bd9Sstevel@tonic-gate 		}
4113087719fdSdp 
4114087719fdSdp 		(void) end_check_reqd(in_progress_fstab.zone_fs_type, PT_TYPE,
4115087719fdSdp 		    &validation_failed);
4116087719fdSdp 
4117087719fdSdp 		if (validation_failed) {
41187c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
41197c478bd9Sstevel@tonic-gate 			return;
4120087719fdSdp 		}
4121087719fdSdp 
41227c478bd9Sstevel@tonic-gate 		if (end_op == CMD_ADD) {
41237c478bd9Sstevel@tonic-gate 			/* Make sure there isn't already one like this. */
41247c478bd9Sstevel@tonic-gate 			bzero(&tmp_fstab, sizeof (tmp_fstab));
41257c478bd9Sstevel@tonic-gate 			(void) strlcpy(tmp_fstab.zone_fs_dir,
41267c478bd9Sstevel@tonic-gate 			    in_progress_fstab.zone_fs_dir,
41277c478bd9Sstevel@tonic-gate 			    sizeof (tmp_fstab.zone_fs_dir));
41287c478bd9Sstevel@tonic-gate 			err = zonecfg_lookup_filesystem(handle, &tmp_fstab);
41297c478bd9Sstevel@tonic-gate 			zonecfg_free_fs_option_list(tmp_fstab.zone_fs_options);
41307c478bd9Sstevel@tonic-gate 			if (err == Z_OK) {
41317c478bd9Sstevel@tonic-gate 				zerr(gettext("A %s resource "
41327c478bd9Sstevel@tonic-gate 				    "with the %s '%s' already exists."),
41337c478bd9Sstevel@tonic-gate 				    rt_to_str(RT_FS), pt_to_str(PT_DIR),
41347c478bd9Sstevel@tonic-gate 				    in_progress_fstab.zone_fs_dir);
41357c478bd9Sstevel@tonic-gate 				saw_error = TRUE;
41367c478bd9Sstevel@tonic-gate 				return;
41377c478bd9Sstevel@tonic-gate 			}
41387c478bd9Sstevel@tonic-gate 			err = zonecfg_add_filesystem(handle,
41397c478bd9Sstevel@tonic-gate 			    &in_progress_fstab);
41407c478bd9Sstevel@tonic-gate 		} else {
41417c478bd9Sstevel@tonic-gate 			err = zonecfg_modify_filesystem(handle, &old_fstab,
41427c478bd9Sstevel@tonic-gate 			    &in_progress_fstab);
41437c478bd9Sstevel@tonic-gate 		}
41447c478bd9Sstevel@tonic-gate 		zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
41457c478bd9Sstevel@tonic-gate 		in_progress_fstab.zone_fs_options = NULL;
41467c478bd9Sstevel@tonic-gate 		break;
4147087719fdSdp 
41487c478bd9Sstevel@tonic-gate 	case RT_IPD:
41497c478bd9Sstevel@tonic-gate 		/* First make sure everything was filled in. */
4150087719fdSdp 		if (end_check_reqd(in_progress_ipdtab.zone_fs_dir, PT_DIR,
4151087719fdSdp 		    &validation_failed) == Z_OK) {
4152087719fdSdp 			if (in_progress_ipdtab.zone_fs_dir[0] != '/') {
4153087719fdSdp 				zerr(gettext("%s %s is not an absolute path."),
4154087719fdSdp 				    pt_to_str(PT_DIR),
4155087719fdSdp 				    in_progress_ipdtab.zone_fs_dir);
4156087719fdSdp 				validation_failed = TRUE;
4157087719fdSdp 			}
41587c478bd9Sstevel@tonic-gate 		}
4159087719fdSdp 		if (validation_failed) {
4160087719fdSdp 			saw_error = TRUE;
41617c478bd9Sstevel@tonic-gate 			return;
4162087719fdSdp 		}
4163087719fdSdp 
41647c478bd9Sstevel@tonic-gate 		if (end_op == CMD_ADD) {
41657c478bd9Sstevel@tonic-gate 			/* Make sure there isn't already one like this. */
41667c478bd9Sstevel@tonic-gate 			bzero(&tmp_fstab, sizeof (tmp_fstab));
41677c478bd9Sstevel@tonic-gate 			(void) strlcpy(tmp_fstab.zone_fs_dir,
41687c478bd9Sstevel@tonic-gate 			    in_progress_ipdtab.zone_fs_dir,
41697c478bd9Sstevel@tonic-gate 			    sizeof (tmp_fstab.zone_fs_dir));
41707c478bd9Sstevel@tonic-gate 			err = zonecfg_lookup_ipd(handle, &tmp_fstab);
41717c478bd9Sstevel@tonic-gate 			if (err == Z_OK) {
41727c478bd9Sstevel@tonic-gate 				zerr(gettext("An %s resource "
41737c478bd9Sstevel@tonic-gate 				    "with the %s '%s' already exists."),
41747c478bd9Sstevel@tonic-gate 				    rt_to_str(RT_IPD), pt_to_str(PT_DIR),
41757c478bd9Sstevel@tonic-gate 				    in_progress_ipdtab.zone_fs_dir);
41767c478bd9Sstevel@tonic-gate 				saw_error = TRUE;
41777c478bd9Sstevel@tonic-gate 				return;
41787c478bd9Sstevel@tonic-gate 			}
41797c478bd9Sstevel@tonic-gate 			err = zonecfg_add_ipd(handle, &in_progress_ipdtab);
41807c478bd9Sstevel@tonic-gate 		} else {
41817c478bd9Sstevel@tonic-gate 			err = zonecfg_modify_ipd(handle, &old_ipdtab,
41827c478bd9Sstevel@tonic-gate 			    &in_progress_ipdtab);
41837c478bd9Sstevel@tonic-gate 		}
41847c478bd9Sstevel@tonic-gate 		break;
41857c478bd9Sstevel@tonic-gate 	case RT_NET:
41867c478bd9Sstevel@tonic-gate 		/* First make sure everything was filled in. */
4187087719fdSdp 		(void) end_check_reqd(in_progress_nwiftab.zone_nwif_physical,
4188087719fdSdp 		    PT_PHYSICAL, &validation_failed);
4189087719fdSdp 		(void) end_check_reqd(in_progress_nwiftab.zone_nwif_address,
4190087719fdSdp 		    PT_ADDRESS, &validation_failed);
4191087719fdSdp 
4192087719fdSdp 		if (validation_failed) {
41937c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
41947c478bd9Sstevel@tonic-gate 			return;
4195087719fdSdp 		}
4196087719fdSdp 
41977c478bd9Sstevel@tonic-gate 		if (end_op == CMD_ADD) {
41987c478bd9Sstevel@tonic-gate 			/* Make sure there isn't already one like this. */
41997c478bd9Sstevel@tonic-gate 			bzero(&tmp_nwiftab, sizeof (tmp_nwiftab));
42007c478bd9Sstevel@tonic-gate 			(void) strlcpy(tmp_nwiftab.zone_nwif_address,
42017c478bd9Sstevel@tonic-gate 			    in_progress_nwiftab.zone_nwif_address,
42027c478bd9Sstevel@tonic-gate 			    sizeof (tmp_nwiftab.zone_nwif_address));
42037c478bd9Sstevel@tonic-gate 			if (zonecfg_lookup_nwif(handle, &tmp_nwiftab) == Z_OK) {
42047c478bd9Sstevel@tonic-gate 				zerr(gettext("A %s resource "
42057c478bd9Sstevel@tonic-gate 				    "with the %s '%s' already exists."),
42067c478bd9Sstevel@tonic-gate 				    rt_to_str(RT_NET), pt_to_str(PT_ADDRESS),
42077c478bd9Sstevel@tonic-gate 				    in_progress_nwiftab.zone_nwif_address);
42087c478bd9Sstevel@tonic-gate 				saw_error = TRUE;
42097c478bd9Sstevel@tonic-gate 				return;
42107c478bd9Sstevel@tonic-gate 			}
42117c478bd9Sstevel@tonic-gate 			err = zonecfg_add_nwif(handle, &in_progress_nwiftab);
42127c478bd9Sstevel@tonic-gate 		} else {
42137c478bd9Sstevel@tonic-gate 			err = zonecfg_modify_nwif(handle, &old_nwiftab,
42147c478bd9Sstevel@tonic-gate 			    &in_progress_nwiftab);
42157c478bd9Sstevel@tonic-gate 		}
42167c478bd9Sstevel@tonic-gate 		break;
4217087719fdSdp 
42187c478bd9Sstevel@tonic-gate 	case RT_DEVICE:
42197c478bd9Sstevel@tonic-gate 		/* First make sure everything was filled in. */
4220087719fdSdp 		(void) end_check_reqd(in_progress_devtab.zone_dev_match,
4221087719fdSdp 		    PT_MATCH, &validation_failed);
4222087719fdSdp 
4223087719fdSdp 		if (validation_failed) {
42247c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
42257c478bd9Sstevel@tonic-gate 			return;
4226087719fdSdp 		}
4227087719fdSdp 
42287c478bd9Sstevel@tonic-gate 		if (end_op == CMD_ADD) {
42297c478bd9Sstevel@tonic-gate 			/* Make sure there isn't already one like this. */
42307c478bd9Sstevel@tonic-gate 			(void) strlcpy(tmp_devtab.zone_dev_match,
42317c478bd9Sstevel@tonic-gate 			    in_progress_devtab.zone_dev_match,
42327c478bd9Sstevel@tonic-gate 			    sizeof (tmp_devtab.zone_dev_match));
42337c478bd9Sstevel@tonic-gate 			if (zonecfg_lookup_dev(handle, &tmp_devtab) == Z_OK) {
42347c478bd9Sstevel@tonic-gate 				zerr(gettext("A %s resource with the %s '%s' "
42357c478bd9Sstevel@tonic-gate 				    "already exists."), rt_to_str(RT_DEVICE),
42367c478bd9Sstevel@tonic-gate 				    pt_to_str(PT_MATCH),
42377c478bd9Sstevel@tonic-gate 				    in_progress_devtab.zone_dev_match);
42387c478bd9Sstevel@tonic-gate 				saw_error = TRUE;
42397c478bd9Sstevel@tonic-gate 				return;
42407c478bd9Sstevel@tonic-gate 			}
42417c478bd9Sstevel@tonic-gate 			err = zonecfg_add_dev(handle, &in_progress_devtab);
42427c478bd9Sstevel@tonic-gate 		} else {
42437c478bd9Sstevel@tonic-gate 			err = zonecfg_modify_dev(handle, &old_devtab,
42447c478bd9Sstevel@tonic-gate 			    &in_progress_devtab);
42457c478bd9Sstevel@tonic-gate 		}
42467c478bd9Sstevel@tonic-gate 		break;
4247087719fdSdp 
42487c478bd9Sstevel@tonic-gate 	case RT_RCTL:
42497c478bd9Sstevel@tonic-gate 		/* First make sure everything was filled in. */
4250087719fdSdp 		(void) end_check_reqd(in_progress_rctltab.zone_rctl_name,
4251087719fdSdp 		    PT_NAME, &validation_failed);
4252087719fdSdp 
42537c478bd9Sstevel@tonic-gate 		if (in_progress_rctltab.zone_rctl_valptr == NULL) {
42547c478bd9Sstevel@tonic-gate 			zerr(gettext("no %s specified"), pt_to_str(PT_VALUE));
42557c478bd9Sstevel@tonic-gate 			validation_failed = TRUE;
42567c478bd9Sstevel@tonic-gate 		}
4257087719fdSdp 
4258087719fdSdp 		if (validation_failed) {
4259087719fdSdp 			saw_error = TRUE;
42607c478bd9Sstevel@tonic-gate 			return;
4261087719fdSdp 		}
4262087719fdSdp 
42637c478bd9Sstevel@tonic-gate 		if (end_op == CMD_ADD) {
42647c478bd9Sstevel@tonic-gate 			/* Make sure there isn't already one like this. */
42657c478bd9Sstevel@tonic-gate 			(void) strlcpy(tmp_rctltab.zone_rctl_name,
42667c478bd9Sstevel@tonic-gate 			    in_progress_rctltab.zone_rctl_name,
42677c478bd9Sstevel@tonic-gate 			    sizeof (tmp_rctltab.zone_rctl_name));
42687c478bd9Sstevel@tonic-gate 			tmp_rctltab.zone_rctl_valptr = NULL;
42697c478bd9Sstevel@tonic-gate 			err = zonecfg_lookup_rctl(handle, &tmp_rctltab);
42707c478bd9Sstevel@tonic-gate 			zonecfg_free_rctl_value_list(
42717c478bd9Sstevel@tonic-gate 			    tmp_rctltab.zone_rctl_valptr);
42727c478bd9Sstevel@tonic-gate 			if (err == Z_OK) {
42737c478bd9Sstevel@tonic-gate 				zerr(gettext("A %s resource "
42747c478bd9Sstevel@tonic-gate 				    "with the %s '%s' already exists."),
42757c478bd9Sstevel@tonic-gate 				    rt_to_str(RT_RCTL), pt_to_str(PT_NAME),
42767c478bd9Sstevel@tonic-gate 				    in_progress_rctltab.zone_rctl_name);
42777c478bd9Sstevel@tonic-gate 				saw_error = TRUE;
42787c478bd9Sstevel@tonic-gate 				return;
42797c478bd9Sstevel@tonic-gate 			}
42807c478bd9Sstevel@tonic-gate 			err = zonecfg_add_rctl(handle, &in_progress_rctltab);
42817c478bd9Sstevel@tonic-gate 		} else {
42827c478bd9Sstevel@tonic-gate 			err = zonecfg_modify_rctl(handle, &old_rctltab,
42837c478bd9Sstevel@tonic-gate 			    &in_progress_rctltab);
42847c478bd9Sstevel@tonic-gate 		}
42857c478bd9Sstevel@tonic-gate 		if (err == Z_OK) {
42867c478bd9Sstevel@tonic-gate 			zonecfg_free_rctl_value_list(
42877c478bd9Sstevel@tonic-gate 			    in_progress_rctltab.zone_rctl_valptr);
42887c478bd9Sstevel@tonic-gate 			in_progress_rctltab.zone_rctl_valptr = NULL;
42897c478bd9Sstevel@tonic-gate 		}
42907c478bd9Sstevel@tonic-gate 		break;
4291087719fdSdp 
42927c478bd9Sstevel@tonic-gate 	case RT_ATTR:
42937c478bd9Sstevel@tonic-gate 		/* First make sure everything was filled in. */
4294087719fdSdp 		(void) end_check_reqd(in_progress_attrtab.zone_attr_name,
4295087719fdSdp 		    PT_NAME, &validation_failed);
4296087719fdSdp 		(void) end_check_reqd(in_progress_attrtab.zone_attr_type,
4297087719fdSdp 		    PT_TYPE, &validation_failed);
4298087719fdSdp 		(void) end_check_reqd(in_progress_attrtab.zone_attr_value,
4299087719fdSdp 		    PT_VALUE, &validation_failed);
4300087719fdSdp 
43017c478bd9Sstevel@tonic-gate 		if (validate_attr_name(in_progress_attrtab.zone_attr_name) !=
4302087719fdSdp 		    Z_OK)
43037c478bd9Sstevel@tonic-gate 			validation_failed = TRUE;
4304087719fdSdp 
4305087719fdSdp 		if (validate_attr_type_val(&in_progress_attrtab) != Z_OK)
43067c478bd9Sstevel@tonic-gate 			validation_failed = TRUE;
4307087719fdSdp 
4308087719fdSdp 		if (validation_failed) {
4309087719fdSdp 			saw_error = TRUE;
43107c478bd9Sstevel@tonic-gate 			return;
4311087719fdSdp 		}
43127c478bd9Sstevel@tonic-gate 		if (end_op == CMD_ADD) {
43137c478bd9Sstevel@tonic-gate 			/* Make sure there isn't already one like this. */
43147c478bd9Sstevel@tonic-gate 			bzero(&tmp_attrtab, sizeof (tmp_attrtab));
43157c478bd9Sstevel@tonic-gate 			(void) strlcpy(tmp_attrtab.zone_attr_name,
43167c478bd9Sstevel@tonic-gate 			    in_progress_attrtab.zone_attr_name,
43177c478bd9Sstevel@tonic-gate 			    sizeof (tmp_attrtab.zone_attr_name));
43187c478bd9Sstevel@tonic-gate 			if (zonecfg_lookup_attr(handle, &tmp_attrtab) == Z_OK) {
43197c478bd9Sstevel@tonic-gate 				zerr(gettext("An %s resource "
43207c478bd9Sstevel@tonic-gate 				    "with the %s '%s' already exists."),
43217c478bd9Sstevel@tonic-gate 				    rt_to_str(RT_ATTR), pt_to_str(PT_NAME),
43227c478bd9Sstevel@tonic-gate 				    in_progress_attrtab.zone_attr_name);
43237c478bd9Sstevel@tonic-gate 				saw_error = TRUE;
43247c478bd9Sstevel@tonic-gate 				return;
43257c478bd9Sstevel@tonic-gate 			}
43267c478bd9Sstevel@tonic-gate 			err = zonecfg_add_attr(handle, &in_progress_attrtab);
43277c478bd9Sstevel@tonic-gate 		} else {
43287c478bd9Sstevel@tonic-gate 			err = zonecfg_modify_attr(handle, &old_attrtab,
43297c478bd9Sstevel@tonic-gate 			    &in_progress_attrtab);
43307c478bd9Sstevel@tonic-gate 		}
43317c478bd9Sstevel@tonic-gate 		break;
4332fa9e4066Sahrens 	case RT_DATASET:
4333fa9e4066Sahrens 		/* First make sure everything was filled in. */
4334fa9e4066Sahrens 		if (strlen(in_progress_dstab.zone_dataset_name) == 0) {
4335fa9e4066Sahrens 			zerr("%s %s", pt_to_str(PT_NAME),
4336fa9e4066Sahrens 			    gettext("not specified"));
4337fa9e4066Sahrens 			saw_error = TRUE;
4338fa9e4066Sahrens 			validation_failed = TRUE;
4339fa9e4066Sahrens 		}
4340fa9e4066Sahrens 		if (validation_failed)
4341fa9e4066Sahrens 			return;
4342fa9e4066Sahrens 		if (end_op == CMD_ADD) {
4343fa9e4066Sahrens 			/* Make sure there isn't already one like this. */
4344fa9e4066Sahrens 			bzero(&tmp_dstab, sizeof (tmp_dstab));
4345fa9e4066Sahrens 			(void) strlcpy(tmp_dstab.zone_dataset_name,
4346fa9e4066Sahrens 			    in_progress_dstab.zone_dataset_name,
4347fa9e4066Sahrens 			    sizeof (tmp_dstab.zone_dataset_name));
4348fa9e4066Sahrens 			err = zonecfg_lookup_ds(handle, &tmp_dstab);
4349fa9e4066Sahrens 			if (err == Z_OK) {
4350fa9e4066Sahrens 				zerr(gettext("A %s resource "
4351fa9e4066Sahrens 				    "with the %s '%s' already exists."),
4352fa9e4066Sahrens 				    rt_to_str(RT_DATASET), pt_to_str(PT_NAME),
4353fa9e4066Sahrens 				    in_progress_dstab.zone_dataset_name);
4354fa9e4066Sahrens 				saw_error = TRUE;
4355fa9e4066Sahrens 				return;
4356fa9e4066Sahrens 			}
4357fa9e4066Sahrens 			err = zonecfg_add_ds(handle, &in_progress_dstab);
4358fa9e4066Sahrens 		} else {
4359fa9e4066Sahrens 			err = zonecfg_modify_ds(handle, &old_dstab,
4360fa9e4066Sahrens 			    &in_progress_dstab);
4361fa9e4066Sahrens 		}
4362fa9e4066Sahrens 		break;
43637c478bd9Sstevel@tonic-gate 	default:
43647c478bd9Sstevel@tonic-gate 		zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
43657c478bd9Sstevel@tonic-gate 		    TRUE);
43667c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
43677c478bd9Sstevel@tonic-gate 		return;
43687c478bd9Sstevel@tonic-gate 	}
43697c478bd9Sstevel@tonic-gate 
43707c478bd9Sstevel@tonic-gate 	if (err != Z_OK) {
43717c478bd9Sstevel@tonic-gate 		zone_perror(zone, err, TRUE);
43727c478bd9Sstevel@tonic-gate 	} else {
43737c478bd9Sstevel@tonic-gate 		need_to_commit = TRUE;
43747c478bd9Sstevel@tonic-gate 		global_scope = TRUE;
43757c478bd9Sstevel@tonic-gate 		end_op = -1;
43767c478bd9Sstevel@tonic-gate 	}
43777c478bd9Sstevel@tonic-gate }
43787c478bd9Sstevel@tonic-gate 
43797c478bd9Sstevel@tonic-gate void
43807c478bd9Sstevel@tonic-gate commit_func(cmd_t *cmd)
43817c478bd9Sstevel@tonic-gate {
43827c478bd9Sstevel@tonic-gate 	int arg;
43837c478bd9Sstevel@tonic-gate 
43847c478bd9Sstevel@tonic-gate 	optind = 0;
43857c478bd9Sstevel@tonic-gate 	if ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
43867c478bd9Sstevel@tonic-gate 		switch (arg) {
43877c478bd9Sstevel@tonic-gate 		case '?':
43887c478bd9Sstevel@tonic-gate 			longer_usage(CMD_COMMIT);
43897c478bd9Sstevel@tonic-gate 			return;
43907c478bd9Sstevel@tonic-gate 		default:
43917c478bd9Sstevel@tonic-gate 			short_usage(CMD_COMMIT);
43927c478bd9Sstevel@tonic-gate 			return;
43937c478bd9Sstevel@tonic-gate 		}
43947c478bd9Sstevel@tonic-gate 	}
43957c478bd9Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
43967c478bd9Sstevel@tonic-gate 		short_usage(CMD_COMMIT);
43977c478bd9Sstevel@tonic-gate 		return;
43987c478bd9Sstevel@tonic-gate 	}
43997c478bd9Sstevel@tonic-gate 
44007c478bd9Sstevel@tonic-gate 	if (zone_is_read_only(CMD_COMMIT))
44017c478bd9Sstevel@tonic-gate 		return;
44027c478bd9Sstevel@tonic-gate 
44037c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
44047c478bd9Sstevel@tonic-gate 
44057c478bd9Sstevel@tonic-gate 	cmd->cmd_argc = 1;
44067c478bd9Sstevel@tonic-gate 	/*
44077c478bd9Sstevel@tonic-gate 	 * cmd_arg normally comes from a strdup() in the lexer, and the
44087c478bd9Sstevel@tonic-gate 	 * whole cmd structure and its (char *) attributes are freed at
44097c478bd9Sstevel@tonic-gate 	 * the completion of each command, so the strdup() below is needed
44107c478bd9Sstevel@tonic-gate 	 * to match this and prevent a core dump from trying to free()
44117c478bd9Sstevel@tonic-gate 	 * something that can't be.
44127c478bd9Sstevel@tonic-gate 	 */
44137c478bd9Sstevel@tonic-gate 	if ((cmd->cmd_argv[0] = strdup("save")) == NULL) {
44147c478bd9Sstevel@tonic-gate 		zone_perror(zone, Z_NOMEM, TRUE);
44157c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
44167c478bd9Sstevel@tonic-gate 	}
44177c478bd9Sstevel@tonic-gate 	cmd->cmd_argv[1] = NULL;
44187c478bd9Sstevel@tonic-gate 	verify_func(cmd);
44197c478bd9Sstevel@tonic-gate }
44207c478bd9Sstevel@tonic-gate 
44217c478bd9Sstevel@tonic-gate void
44227c478bd9Sstevel@tonic-gate revert_func(cmd_t *cmd)
44237c478bd9Sstevel@tonic-gate {
44247c478bd9Sstevel@tonic-gate 	char line[128];	/* enough to ask a question */
44257c478bd9Sstevel@tonic-gate 	bool force = FALSE;
44267c478bd9Sstevel@tonic-gate 	int err, arg, answer;
44277c478bd9Sstevel@tonic-gate 
44287c478bd9Sstevel@tonic-gate 	optind = 0;
44297c478bd9Sstevel@tonic-gate 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
44307c478bd9Sstevel@tonic-gate 		switch (arg) {
44317c478bd9Sstevel@tonic-gate 		case '?':
44327c478bd9Sstevel@tonic-gate 			longer_usage(CMD_REVERT);
44337c478bd9Sstevel@tonic-gate 			return;
44347c478bd9Sstevel@tonic-gate 		case 'F':
44357c478bd9Sstevel@tonic-gate 			force = TRUE;
44367c478bd9Sstevel@tonic-gate 			break;
44377c478bd9Sstevel@tonic-gate 		default:
44387c478bd9Sstevel@tonic-gate 			short_usage(CMD_REVERT);
44397c478bd9Sstevel@tonic-gate 			return;
44407c478bd9Sstevel@tonic-gate 		}
44417c478bd9Sstevel@tonic-gate 	}
44427c478bd9Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
44437c478bd9Sstevel@tonic-gate 		short_usage(CMD_REVERT);
44447c478bd9Sstevel@tonic-gate 		return;
44457c478bd9Sstevel@tonic-gate 	}
44467c478bd9Sstevel@tonic-gate 
44477c478bd9Sstevel@tonic-gate 	if (zone_is_read_only(CMD_REVERT))
44487c478bd9Sstevel@tonic-gate 		return;
44497c478bd9Sstevel@tonic-gate 
44507c478bd9Sstevel@tonic-gate 	if (zonecfg_check_handle(handle) != Z_OK) {
44517c478bd9Sstevel@tonic-gate 		zerr(gettext("No changes to revert."));
44527c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
44537c478bd9Sstevel@tonic-gate 		return;
44547c478bd9Sstevel@tonic-gate 	}
44557c478bd9Sstevel@tonic-gate 
44567c478bd9Sstevel@tonic-gate 	if (!force) {
44577c478bd9Sstevel@tonic-gate 		(void) snprintf(line, sizeof (line),
44587c478bd9Sstevel@tonic-gate 		    gettext("Are you sure you want to revert"));
44597c478bd9Sstevel@tonic-gate 		if ((answer = ask_yesno(FALSE, line)) == -1) {
44607c478bd9Sstevel@tonic-gate 			zerr(gettext("Input not from terminal and -F not "
44617c478bd9Sstevel@tonic-gate 			    "specified:\n%s command ignored, exiting."),
44627c478bd9Sstevel@tonic-gate 			    cmd_to_str(CMD_REVERT));
44637c478bd9Sstevel@tonic-gate 			exit(Z_ERR);
44647c478bd9Sstevel@tonic-gate 		}
44657c478bd9Sstevel@tonic-gate 		if (answer != 1)
44667c478bd9Sstevel@tonic-gate 			return;
44677c478bd9Sstevel@tonic-gate 	}
44687c478bd9Sstevel@tonic-gate 
44697c478bd9Sstevel@tonic-gate 	/*
44707c478bd9Sstevel@tonic-gate 	 * Time for a new handle: finish the old one off first
44717c478bd9Sstevel@tonic-gate 	 * then get a new one properly to avoid leaks.
44727c478bd9Sstevel@tonic-gate 	 */
44737c478bd9Sstevel@tonic-gate 	zonecfg_fini_handle(handle);
44747c478bd9Sstevel@tonic-gate 	if ((handle = zonecfg_init_handle()) == NULL) {
44757c478bd9Sstevel@tonic-gate 		zone_perror(execname, Z_NOMEM, TRUE);
44767c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
44777c478bd9Sstevel@tonic-gate 	}
4478087719fdSdp 	if ((err = zonecfg_get_handle(revert_zone, handle)) != Z_OK) {
44797c478bd9Sstevel@tonic-gate 		saw_error = TRUE;
44807c478bd9Sstevel@tonic-gate 		got_handle = FALSE;
44817c478bd9Sstevel@tonic-gate 		if (err == Z_NO_ZONE)
44827c478bd9Sstevel@tonic-gate 			zerr(gettext("%s: no such saved zone to revert to."),
4483087719fdSdp 			    revert_zone);
44847c478bd9Sstevel@tonic-gate 		else
44857c478bd9Sstevel@tonic-gate 			zone_perror(zone, err, TRUE);
44867c478bd9Sstevel@tonic-gate 	}
4487087719fdSdp 	(void) strlcpy(zone, revert_zone, sizeof (zone));
44887c478bd9Sstevel@tonic-gate }
44897c478bd9Sstevel@tonic-gate 
44907c478bd9Sstevel@tonic-gate void
44917c478bd9Sstevel@tonic-gate help_func(cmd_t *cmd)
44927c478bd9Sstevel@tonic-gate {
44937c478bd9Sstevel@tonic-gate 	int i;
44947c478bd9Sstevel@tonic-gate 
44957c478bd9Sstevel@tonic-gate 	assert(cmd != NULL);
44967c478bd9Sstevel@tonic-gate 
44977c478bd9Sstevel@tonic-gate 	if (cmd->cmd_argc == 0) {
44987c478bd9Sstevel@tonic-gate 		usage(TRUE, global_scope ? HELP_SUBCMDS : HELP_RES_SCOPE);
44997c478bd9Sstevel@tonic-gate 		return;
45007c478bd9Sstevel@tonic-gate 	}
45017c478bd9Sstevel@tonic-gate 	if (strcmp(cmd->cmd_argv[0], "usage") == 0) {
45027c478bd9Sstevel@tonic-gate 		usage(TRUE, HELP_USAGE);
45037c478bd9Sstevel@tonic-gate 		return;
45047c478bd9Sstevel@tonic-gate 	}
45057c478bd9Sstevel@tonic-gate 	if (strcmp(cmd->cmd_argv[0], "commands") == 0) {
45067c478bd9Sstevel@tonic-gate 		usage(TRUE, HELP_SUBCMDS);
45077c478bd9Sstevel@tonic-gate 		return;
45087c478bd9Sstevel@tonic-gate 	}
45097c478bd9Sstevel@tonic-gate 	if (strcmp(cmd->cmd_argv[0], "syntax") == 0) {
45107c478bd9Sstevel@tonic-gate 		usage(TRUE, HELP_SYNTAX | HELP_RES_PROPS);
45117c478bd9Sstevel@tonic-gate 		return;
45127c478bd9Sstevel@tonic-gate 	}
45137c478bd9Sstevel@tonic-gate 	if (strcmp(cmd->cmd_argv[0], "-?") == 0) {
45147c478bd9Sstevel@tonic-gate 		longer_usage(CMD_HELP);
45157c478bd9Sstevel@tonic-gate 		return;
45167c478bd9Sstevel@tonic-gate 	}
45177c478bd9Sstevel@tonic-gate 
45187c478bd9Sstevel@tonic-gate 	for (i = 0; i <= CMD_MAX; i++) {
45197c478bd9Sstevel@tonic-gate 		if (strcmp(cmd->cmd_argv[0], cmd_to_str(i)) == 0) {
45207c478bd9Sstevel@tonic-gate 			longer_usage(i);
45217c478bd9Sstevel@tonic-gate 			return;
45227c478bd9Sstevel@tonic-gate 		}
45237c478bd9Sstevel@tonic-gate 	}
45247c478bd9Sstevel@tonic-gate 	/* We do not use zerr() here because we do not want its extra \n. */
45257c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("Unknown help subject %s.  "),
45267c478bd9Sstevel@tonic-gate 	    cmd->cmd_argv[0]);
45277c478bd9Sstevel@tonic-gate 	usage(FALSE, HELP_META);
45287c478bd9Sstevel@tonic-gate }
45297c478bd9Sstevel@tonic-gate 
45307c478bd9Sstevel@tonic-gate static int
45317c478bd9Sstevel@tonic-gate string_to_yyin(char *string)
45327c478bd9Sstevel@tonic-gate {
45337c478bd9Sstevel@tonic-gate 	if ((yyin = tmpfile()) == NULL) {
45347c478bd9Sstevel@tonic-gate 		zone_perror(execname, Z_TEMP_FILE, TRUE);
45357c478bd9Sstevel@tonic-gate 		return (Z_ERR);
45367c478bd9Sstevel@tonic-gate 	}
45377c478bd9Sstevel@tonic-gate 	if (fwrite(string, strlen(string), 1, yyin) != 1) {
45387c478bd9Sstevel@tonic-gate 		zone_perror(execname, Z_TEMP_FILE, TRUE);
45397c478bd9Sstevel@tonic-gate 		return (Z_ERR);
45407c478bd9Sstevel@tonic-gate 	}
45417c478bd9Sstevel@tonic-gate 	if (fseek(yyin, 0, SEEK_SET) != 0) {
45427c478bd9Sstevel@tonic-gate 		zone_perror(execname, Z_TEMP_FILE, TRUE);
45437c478bd9Sstevel@tonic-gate 		return (Z_ERR);
45447c478bd9Sstevel@tonic-gate 	}
45457c478bd9Sstevel@tonic-gate 	return (Z_OK);
45467c478bd9Sstevel@tonic-gate }
45477c478bd9Sstevel@tonic-gate 
45487c478bd9Sstevel@tonic-gate /* This is the back-end helper function for read_input() below. */
45497c478bd9Sstevel@tonic-gate 
45507c478bd9Sstevel@tonic-gate static int
45517c478bd9Sstevel@tonic-gate cleanup()
45527c478bd9Sstevel@tonic-gate {
45537c478bd9Sstevel@tonic-gate 	int answer;
45547c478bd9Sstevel@tonic-gate 	cmd_t *cmd;
45557c478bd9Sstevel@tonic-gate 
45567c478bd9Sstevel@tonic-gate 	if (!interactive_mode && !cmd_file_mode) {
45577c478bd9Sstevel@tonic-gate 		/*
45587c478bd9Sstevel@tonic-gate 		 * If we're not in interactive mode, and we're not in command
45597c478bd9Sstevel@tonic-gate 		 * file mode, then we must be in commands-from-the-command-line
45607c478bd9Sstevel@tonic-gate 		 * mode.  As such, we can't loop back and ask for more input.
45617c478bd9Sstevel@tonic-gate 		 * It was OK to prompt for such things as whether or not to
45627c478bd9Sstevel@tonic-gate 		 * really delete a zone in the command handler called from
45637c478bd9Sstevel@tonic-gate 		 * yyparse() above, but "really quit?" makes no sense in this
45647c478bd9Sstevel@tonic-gate 		 * context.  So disable prompting.
45657c478bd9Sstevel@tonic-gate 		 */
45667c478bd9Sstevel@tonic-gate 		ok_to_prompt = FALSE;
45677c478bd9Sstevel@tonic-gate 	}
45687c478bd9Sstevel@tonic-gate 	if (!global_scope) {
45697c478bd9Sstevel@tonic-gate 		if (!time_to_exit) {
45707c478bd9Sstevel@tonic-gate 			/*
45717c478bd9Sstevel@tonic-gate 			 * Just print a simple error message in the -1 case,
45727c478bd9Sstevel@tonic-gate 			 * since exit_func() already handles that case, and
45737c478bd9Sstevel@tonic-gate 			 * EOF means we are finished anyway.
45747c478bd9Sstevel@tonic-gate 			 */
45757c478bd9Sstevel@tonic-gate 			answer = ask_yesno(FALSE,
45767c478bd9Sstevel@tonic-gate 			    gettext("Resource incomplete; really quit"));
45777c478bd9Sstevel@tonic-gate 			if (answer == -1) {
45787c478bd9Sstevel@tonic-gate 				zerr(gettext("Resource incomplete."));
45797c478bd9Sstevel@tonic-gate 				return (Z_ERR);
45807c478bd9Sstevel@tonic-gate 			}
45817c478bd9Sstevel@tonic-gate 			if (answer != 1) {
45827c478bd9Sstevel@tonic-gate 				yyin = stdin;
45837c478bd9Sstevel@tonic-gate 				return (Z_REPEAT);
45847c478bd9Sstevel@tonic-gate 			}
45857c478bd9Sstevel@tonic-gate 		} else {
45867c478bd9Sstevel@tonic-gate 			saw_error = TRUE;
45877c478bd9Sstevel@tonic-gate 		}
45887c478bd9Sstevel@tonic-gate 	}
45897c478bd9Sstevel@tonic-gate 	/*
45907c478bd9Sstevel@tonic-gate 	 * Make sure we tried something and that the handle checks
45917c478bd9Sstevel@tonic-gate 	 * out, or we would get a false error trying to commit.
45927c478bd9Sstevel@tonic-gate 	 */
45937c478bd9Sstevel@tonic-gate 	if (need_to_commit && zonecfg_check_handle(handle) == Z_OK) {
45947c478bd9Sstevel@tonic-gate 		if ((cmd = alloc_cmd()) == NULL) {
45957c478bd9Sstevel@tonic-gate 			zone_perror(zone, Z_NOMEM, TRUE);
45967c478bd9Sstevel@tonic-gate 			return (Z_ERR);
45977c478bd9Sstevel@tonic-gate 		}
45987c478bd9Sstevel@tonic-gate 		cmd->cmd_argc = 0;
45997c478bd9Sstevel@tonic-gate 		cmd->cmd_argv[0] = NULL;
46007c478bd9Sstevel@tonic-gate 		commit_func(cmd);
46017c478bd9Sstevel@tonic-gate 		free_cmd(cmd);
46027c478bd9Sstevel@tonic-gate 		/*
46037c478bd9Sstevel@tonic-gate 		 * need_to_commit will get set back to FALSE if the
46047c478bd9Sstevel@tonic-gate 		 * configuration is saved successfully.
46057c478bd9Sstevel@tonic-gate 		 */
46067c478bd9Sstevel@tonic-gate 		if (need_to_commit) {
46077c478bd9Sstevel@tonic-gate 			if (force_exit) {
46087c478bd9Sstevel@tonic-gate 				zerr(gettext("Configuration not saved."));
46097c478bd9Sstevel@tonic-gate 				return (Z_ERR);
46107c478bd9Sstevel@tonic-gate 			}
46117c478bd9Sstevel@tonic-gate 			answer = ask_yesno(FALSE,
46127c478bd9Sstevel@tonic-gate 			    gettext("Configuration not saved; really quit"));
46137c478bd9Sstevel@tonic-gate 			if (answer == -1) {
46147c478bd9Sstevel@tonic-gate 				zerr(gettext("Configuration not saved."));
46157c478bd9Sstevel@tonic-gate 				return (Z_ERR);
46167c478bd9Sstevel@tonic-gate 			}
46177c478bd9Sstevel@tonic-gate 			if (answer != 1) {
46187c478bd9Sstevel@tonic-gate 				time_to_exit = FALSE;
46197c478bd9Sstevel@tonic-gate 				yyin = stdin;
46207c478bd9Sstevel@tonic-gate 				return (Z_REPEAT);
46217c478bd9Sstevel@tonic-gate 			}
46227c478bd9Sstevel@tonic-gate 		}
46237c478bd9Sstevel@tonic-gate 	}
46247c478bd9Sstevel@tonic-gate 	return ((need_to_commit || saw_error) ? Z_ERR : Z_OK);
46257c478bd9Sstevel@tonic-gate }
46267c478bd9Sstevel@tonic-gate 
46277c478bd9Sstevel@tonic-gate /*
46287c478bd9Sstevel@tonic-gate  * read_input() is the driver of this program.  It is a wrapper around
46297c478bd9Sstevel@tonic-gate  * yyparse(), printing appropriate prompts when needed, checking for
46307c478bd9Sstevel@tonic-gate  * exit conditions and reacting appropriately [the latter in its cleanup()
46317c478bd9Sstevel@tonic-gate  * helper function].
46327c478bd9Sstevel@tonic-gate  *
46337c478bd9Sstevel@tonic-gate  * Like most zonecfg functions, it returns Z_OK or Z_ERR, *or* Z_REPEAT
46347c478bd9Sstevel@tonic-gate  * so do_interactive() knows that we are not really done (i.e, we asked
46357c478bd9Sstevel@tonic-gate  * the user if we should really quit and the user said no).
46367c478bd9Sstevel@tonic-gate  */
46377c478bd9Sstevel@tonic-gate static int
46387c478bd9Sstevel@tonic-gate read_input()
46397c478bd9Sstevel@tonic-gate {
46407c478bd9Sstevel@tonic-gate 	bool yyin_is_a_tty = isatty(fileno(yyin));
46417c478bd9Sstevel@tonic-gate 	/*
46427c478bd9Sstevel@tonic-gate 	 * The prompt is "e:z> " or "e:z:r> " where e is execname, z is zone
46437c478bd9Sstevel@tonic-gate 	 * and r is resource_scope: 5 is for the two ":"s + "> " + terminator.
46447c478bd9Sstevel@tonic-gate 	 */
46457c478bd9Sstevel@tonic-gate 	char prompt[MAXPATHLEN + ZONENAME_MAX + MAX_RT_STRLEN + 5], *line;
46467c478bd9Sstevel@tonic-gate 
46477c478bd9Sstevel@tonic-gate 	/* yyin should have been set to the appropriate (FILE *) if not stdin */
46487c478bd9Sstevel@tonic-gate 	newline_terminated = TRUE;
46497c478bd9Sstevel@tonic-gate 	for (;;) {
46507c478bd9Sstevel@tonic-gate 		if (yyin_is_a_tty) {
46517c478bd9Sstevel@tonic-gate 			if (newline_terminated) {
46527c478bd9Sstevel@tonic-gate 				if (global_scope)
46537c478bd9Sstevel@tonic-gate 					(void) snprintf(prompt, sizeof (prompt),
46547c478bd9Sstevel@tonic-gate 					    "%s:%s> ", execname, zone);
46557c478bd9Sstevel@tonic-gate 				else
46567c478bd9Sstevel@tonic-gate 					(void) snprintf(prompt, sizeof (prompt),
46577c478bd9Sstevel@tonic-gate 					    "%s:%s:%s> ", execname, zone,
46587c478bd9Sstevel@tonic-gate 					    rt_to_str(resource_scope));
46597c478bd9Sstevel@tonic-gate 			}
46607c478bd9Sstevel@tonic-gate 			/*
46617c478bd9Sstevel@tonic-gate 			 * If the user hits ^C then we want to catch it and
46627c478bd9Sstevel@tonic-gate 			 * start over.  If the user hits EOF then we want to
46637c478bd9Sstevel@tonic-gate 			 * bail out.
46647c478bd9Sstevel@tonic-gate 			 */
46657c478bd9Sstevel@tonic-gate 			line = gl_get_line(gl, prompt, NULL, -1);
46667c478bd9Sstevel@tonic-gate 			if (gl_return_status(gl) == GLR_SIGNAL) {
46677c478bd9Sstevel@tonic-gate 				gl_abandon_line(gl);
46687c478bd9Sstevel@tonic-gate 				continue;
46697c478bd9Sstevel@tonic-gate 			}
46707c478bd9Sstevel@tonic-gate 			if (line == NULL)
46717c478bd9Sstevel@tonic-gate 				break;
46727c478bd9Sstevel@tonic-gate 			(void) string_to_yyin(line);
46737c478bd9Sstevel@tonic-gate 			while (!feof(yyin))
46747c478bd9Sstevel@tonic-gate 				yyparse();
46757c478bd9Sstevel@tonic-gate 		} else {
46767c478bd9Sstevel@tonic-gate 			yyparse();
46777c478bd9Sstevel@tonic-gate 		}
46787c478bd9Sstevel@tonic-gate 		/* Bail out on an error in command file mode. */
46797c478bd9Sstevel@tonic-gate 		if (saw_error && cmd_file_mode && !interactive_mode)
46807c478bd9Sstevel@tonic-gate 			time_to_exit = TRUE;
46817c478bd9Sstevel@tonic-gate 		if (time_to_exit || (!yyin_is_a_tty && feof(yyin)))
46827c478bd9Sstevel@tonic-gate 			break;
46837c478bd9Sstevel@tonic-gate 	}
46847c478bd9Sstevel@tonic-gate 	return (cleanup());
46857c478bd9Sstevel@tonic-gate }
46867c478bd9Sstevel@tonic-gate 
46877c478bd9Sstevel@tonic-gate /*
46887c478bd9Sstevel@tonic-gate  * This function is used in the zonecfg-interactive-mode scenario: it just
46897c478bd9Sstevel@tonic-gate  * calls read_input() until we are done.
46907c478bd9Sstevel@tonic-gate  */
46917c478bd9Sstevel@tonic-gate 
46927c478bd9Sstevel@tonic-gate static int
46937c478bd9Sstevel@tonic-gate do_interactive(void)
46947c478bd9Sstevel@tonic-gate {
46957c478bd9Sstevel@tonic-gate 	int err;
46967c478bd9Sstevel@tonic-gate 
46977c478bd9Sstevel@tonic-gate 	interactive_mode = TRUE;
46987c478bd9Sstevel@tonic-gate 	if (!read_only_mode) {
46997c478bd9Sstevel@tonic-gate 		/*
47007c478bd9Sstevel@tonic-gate 		 * Try to set things up proactively in interactive mode, so
47017c478bd9Sstevel@tonic-gate 		 * that if the zone in question does not exist yet, we can
47027c478bd9Sstevel@tonic-gate 		 * provide the user with a clue.
47037c478bd9Sstevel@tonic-gate 		 */
47047c478bd9Sstevel@tonic-gate 		(void) initialize(FALSE);
47057c478bd9Sstevel@tonic-gate 	}
4706087719fdSdp 	do {
47077c478bd9Sstevel@tonic-gate 		err = read_input();
4708087719fdSdp 	} while (err == Z_REPEAT);
47097c478bd9Sstevel@tonic-gate 	return (err);
47107c478bd9Sstevel@tonic-gate }
47117c478bd9Sstevel@tonic-gate 
47127c478bd9Sstevel@tonic-gate /*
47137c478bd9Sstevel@tonic-gate  * cmd_file is slightly more complicated, as it has to open the command file
47147c478bd9Sstevel@tonic-gate  * and set yyin appropriately.  Once that is done, though, it just calls
47157c478bd9Sstevel@tonic-gate  * read_input(), and only once, since prompting is not possible.
47167c478bd9Sstevel@tonic-gate  */
47177c478bd9Sstevel@tonic-gate 
47187c478bd9Sstevel@tonic-gate static int
47197c478bd9Sstevel@tonic-gate cmd_file(char *file)
47207c478bd9Sstevel@tonic-gate {
47217c478bd9Sstevel@tonic-gate 	FILE *infile;
47227c478bd9Sstevel@tonic-gate 	int err;
47237c478bd9Sstevel@tonic-gate 	struct stat statbuf;
47247c478bd9Sstevel@tonic-gate 	bool using_real_file = (strcmp(file, "-") != 0);
47257c478bd9Sstevel@tonic-gate 
47267c478bd9Sstevel@tonic-gate 	if (using_real_file) {
47277c478bd9Sstevel@tonic-gate 		/*
47287c478bd9Sstevel@tonic-gate 		 * zerr() prints a line number in cmd_file_mode, which we do
47297c478bd9Sstevel@tonic-gate 		 * not want here, so temporarily unset it.
47307c478bd9Sstevel@tonic-gate 		 */
47317c478bd9Sstevel@tonic-gate 		cmd_file_mode = FALSE;
47327c478bd9Sstevel@tonic-gate 		if ((infile = fopen(file, "r")) == NULL) {
47337c478bd9Sstevel@tonic-gate 			zerr(gettext("could not open file %s: %s"),
47347c478bd9Sstevel@tonic-gate 			    file, strerror(errno));
47357c478bd9Sstevel@tonic-gate 			return (Z_ERR);
47367c478bd9Sstevel@tonic-gate 		}
47377c478bd9Sstevel@tonic-gate 		if ((err = fstat(fileno(infile), &statbuf)) != 0) {
47387c478bd9Sstevel@tonic-gate 			zerr(gettext("could not stat file %s: %s"),
47397c478bd9Sstevel@tonic-gate 			    file, strerror(errno));
47407c478bd9Sstevel@tonic-gate 			err = Z_ERR;
47417c478bd9Sstevel@tonic-gate 			goto done;
47427c478bd9Sstevel@tonic-gate 		}
47437c478bd9Sstevel@tonic-gate 		if (!S_ISREG(statbuf.st_mode)) {
47447c478bd9Sstevel@tonic-gate 			zerr(gettext("%s is not a regular file."), file);
47457c478bd9Sstevel@tonic-gate 			err = Z_ERR;
47467c478bd9Sstevel@tonic-gate 			goto done;
47477c478bd9Sstevel@tonic-gate 		}
47487c478bd9Sstevel@tonic-gate 		yyin = infile;
47497c478bd9Sstevel@tonic-gate 		cmd_file_mode = TRUE;
47507c478bd9Sstevel@tonic-gate 		ok_to_prompt = FALSE;
47517c478bd9Sstevel@tonic-gate 	} else {
47527c478bd9Sstevel@tonic-gate 		/*
47537c478bd9Sstevel@tonic-gate 		 * "-f -" is essentially the same as interactive mode,
47547c478bd9Sstevel@tonic-gate 		 * so treat it that way.
47557c478bd9Sstevel@tonic-gate 		 */
47567c478bd9Sstevel@tonic-gate 		interactive_mode = TRUE;
47577c478bd9Sstevel@tonic-gate 	}
47587c478bd9Sstevel@tonic-gate 	/* Z_REPEAT is for interactive mode; treat it like Z_ERR here. */
47597c478bd9Sstevel@tonic-gate 	if ((err = read_input()) == Z_REPEAT)
47607c478bd9Sstevel@tonic-gate 		err = Z_ERR;
47617c478bd9Sstevel@tonic-gate done:
47627c478bd9Sstevel@tonic-gate 	if (using_real_file)
47637c478bd9Sstevel@tonic-gate 		(void) fclose(infile);
47647c478bd9Sstevel@tonic-gate 	return (err);
47657c478bd9Sstevel@tonic-gate }
47667c478bd9Sstevel@tonic-gate 
47677c478bd9Sstevel@tonic-gate /*
47687c478bd9Sstevel@tonic-gate  * Since yacc is based on reading from a (FILE *) whereas what we get from
47697c478bd9Sstevel@tonic-gate  * the command line is in argv format, we need to convert when the user
47707c478bd9Sstevel@tonic-gate  * gives us commands directly from the command line.  That is done here by
47717c478bd9Sstevel@tonic-gate  * concatenating the argv list into a space-separated string, writing it
47727c478bd9Sstevel@tonic-gate  * to a temp file, and rewinding the file so yyin can be set to it.  Then
47737c478bd9Sstevel@tonic-gate  * we call read_input(), and only once, since prompting about whether to
47747c478bd9Sstevel@tonic-gate  * continue or quit would make no sense in this context.
47757c478bd9Sstevel@tonic-gate  */
47767c478bd9Sstevel@tonic-gate 
47777c478bd9Sstevel@tonic-gate static int
47787c478bd9Sstevel@tonic-gate one_command_at_a_time(int argc, char *argv[])
47797c478bd9Sstevel@tonic-gate {
47807c478bd9Sstevel@tonic-gate 	char *command;
47817c478bd9Sstevel@tonic-gate 	size_t len = 2; /* terminal \n\0 */
47827c478bd9Sstevel@tonic-gate 	int i, err;
47837c478bd9Sstevel@tonic-gate 
47847c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc; i++)
47857c478bd9Sstevel@tonic-gate 		len += strlen(argv[i]) + 1;
47867c478bd9Sstevel@tonic-gate 	if ((command = malloc(len)) == NULL) {
47877c478bd9Sstevel@tonic-gate 		zone_perror(execname, Z_NOMEM, TRUE);
47887c478bd9Sstevel@tonic-gate 		return (Z_ERR);
47897c478bd9Sstevel@tonic-gate 	}
47907c478bd9Sstevel@tonic-gate 	(void) strlcpy(command, argv[0], len);
47917c478bd9Sstevel@tonic-gate 	for (i = 1; i < argc; i++) {
47927c478bd9Sstevel@tonic-gate 		(void) strlcat(command, " ", len);
47937c478bd9Sstevel@tonic-gate 		(void) strlcat(command, argv[i], len);
47947c478bd9Sstevel@tonic-gate 	}
47957c478bd9Sstevel@tonic-gate 	(void) strlcat(command, "\n", len);
47967c478bd9Sstevel@tonic-gate 	err = string_to_yyin(command);
47977c478bd9Sstevel@tonic-gate 	free(command);
47987c478bd9Sstevel@tonic-gate 	if (err != Z_OK)
47997c478bd9Sstevel@tonic-gate 		return (err);
48007c478bd9Sstevel@tonic-gate 	while (!feof(yyin))
48017c478bd9Sstevel@tonic-gate 		yyparse();
48027c478bd9Sstevel@tonic-gate 	return (cleanup());
48037c478bd9Sstevel@tonic-gate }
48047c478bd9Sstevel@tonic-gate 
48057c478bd9Sstevel@tonic-gate static char *
48067c478bd9Sstevel@tonic-gate get_execbasename(char *execfullname)
48077c478bd9Sstevel@tonic-gate {
48087c478bd9Sstevel@tonic-gate 	char *last_slash, *execbasename;
48097c478bd9Sstevel@tonic-gate 
48107c478bd9Sstevel@tonic-gate 	/* guard against '/' at end of command invocation */
48117c478bd9Sstevel@tonic-gate 	for (;;) {
48127c478bd9Sstevel@tonic-gate 		last_slash = strrchr(execfullname, '/');
48137c478bd9Sstevel@tonic-gate 		if (last_slash == NULL) {
48147c478bd9Sstevel@tonic-gate 			execbasename = execfullname;
48157c478bd9Sstevel@tonic-gate 			break;
48167c478bd9Sstevel@tonic-gate 		} else {
48177c478bd9Sstevel@tonic-gate 			execbasename = last_slash + 1;
48187c478bd9Sstevel@tonic-gate 			if (*execbasename == '\0') {
48197c478bd9Sstevel@tonic-gate 				*last_slash = '\0';
48207c478bd9Sstevel@tonic-gate 				continue;
48217c478bd9Sstevel@tonic-gate 			}
48227c478bd9Sstevel@tonic-gate 			break;
48237c478bd9Sstevel@tonic-gate 		}
48247c478bd9Sstevel@tonic-gate 	}
48257c478bd9Sstevel@tonic-gate 	return (execbasename);
48267c478bd9Sstevel@tonic-gate }
48277c478bd9Sstevel@tonic-gate 
48287c478bd9Sstevel@tonic-gate int
48297c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
48307c478bd9Sstevel@tonic-gate {
48317c478bd9Sstevel@tonic-gate 	int err, arg;
4832555afedfScarlsonj 	struct stat st;
48337c478bd9Sstevel@tonic-gate 
48347c478bd9Sstevel@tonic-gate 	/* This must be before anything goes to stdout. */
48357c478bd9Sstevel@tonic-gate 	setbuf(stdout, NULL);
48367c478bd9Sstevel@tonic-gate 
48377c478bd9Sstevel@tonic-gate 	saw_error = FALSE;
48387c478bd9Sstevel@tonic-gate 	cmd_file_mode = FALSE;
48397c478bd9Sstevel@tonic-gate 	execname = get_execbasename(argv[0]);
48407c478bd9Sstevel@tonic-gate 
48417c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
48427c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
48437c478bd9Sstevel@tonic-gate 
48447c478bd9Sstevel@tonic-gate 	if (getzoneid() != GLOBAL_ZONEID) {
48457c478bd9Sstevel@tonic-gate 		zerr(gettext("%s can only be run from the global zone."),
48467c478bd9Sstevel@tonic-gate 		    execname);
48477c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
48487c478bd9Sstevel@tonic-gate 	}
48497c478bd9Sstevel@tonic-gate 
48507c478bd9Sstevel@tonic-gate 	if (argc < 2) {
48517c478bd9Sstevel@tonic-gate 		usage(FALSE, HELP_USAGE | HELP_SUBCMDS);
48527c478bd9Sstevel@tonic-gate 		exit(Z_USAGE);
48537c478bd9Sstevel@tonic-gate 	}
48547c478bd9Sstevel@tonic-gate 	if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) {
48557c478bd9Sstevel@tonic-gate 		(void) one_command_at_a_time(argc - 1, &(argv[1]));
48567c478bd9Sstevel@tonic-gate 		exit(Z_OK);
48577c478bd9Sstevel@tonic-gate 	}
48587c478bd9Sstevel@tonic-gate 
4859555afedfScarlsonj 	while ((arg = getopt(argc, argv, "?f:R:z:")) != EOF) {
48607c478bd9Sstevel@tonic-gate 		switch (arg) {
48617c478bd9Sstevel@tonic-gate 		case '?':
48627c478bd9Sstevel@tonic-gate 			if (optopt == '?')
48637c478bd9Sstevel@tonic-gate 				usage(TRUE, HELP_USAGE | HELP_SUBCMDS);
48647c478bd9Sstevel@tonic-gate 			else
48657c478bd9Sstevel@tonic-gate 				usage(FALSE, HELP_USAGE);
48667c478bd9Sstevel@tonic-gate 			exit(Z_USAGE);
48677c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
48687c478bd9Sstevel@tonic-gate 		case 'f':
48697c478bd9Sstevel@tonic-gate 			cmd_file_name = optarg;
48707c478bd9Sstevel@tonic-gate 			cmd_file_mode = TRUE;
48717c478bd9Sstevel@tonic-gate 			break;
4872555afedfScarlsonj 		case 'R':
4873555afedfScarlsonj 			if (*optarg != '/') {
4874555afedfScarlsonj 				zerr(gettext("root path must be absolute: %s"),
4875555afedfScarlsonj 				    optarg);
4876555afedfScarlsonj 				exit(Z_USAGE);
4877555afedfScarlsonj 			}
4878555afedfScarlsonj 			if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
4879555afedfScarlsonj 				zerr(gettext(
4880555afedfScarlsonj 				    "root path must be a directory: %s"),
4881555afedfScarlsonj 				    optarg);
4882555afedfScarlsonj 				exit(Z_USAGE);
4883555afedfScarlsonj 			}
4884555afedfScarlsonj 			zonecfg_set_root(optarg);
4885555afedfScarlsonj 			break;
48867c478bd9Sstevel@tonic-gate 		case 'z':
4887087719fdSdp 			if (zonecfg_validate_zonename(optarg) != Z_OK) {
4888087719fdSdp 				zone_perror(optarg, Z_BOGUS_ZONE_NAME, TRUE);
4889087719fdSdp 				usage(FALSE, HELP_SYNTAX);
4890087719fdSdp 				exit(Z_USAGE);
4891087719fdSdp 			}
4892087719fdSdp 			(void) strlcpy(zone, optarg, sizeof (zone));
4893087719fdSdp 			(void) strlcpy(revert_zone, optarg, sizeof (zone));
48947c478bd9Sstevel@tonic-gate 			break;
48957c478bd9Sstevel@tonic-gate 		default:
48967c478bd9Sstevel@tonic-gate 			usage(FALSE, HELP_USAGE);
48977c478bd9Sstevel@tonic-gate 			exit(Z_USAGE);
48987c478bd9Sstevel@tonic-gate 		}
48997c478bd9Sstevel@tonic-gate 	}
49007c478bd9Sstevel@tonic-gate 
4901087719fdSdp 	if (optind > argc || strcmp(zone, "") == 0) {
49027c478bd9Sstevel@tonic-gate 		usage(FALSE, HELP_USAGE);
49037c478bd9Sstevel@tonic-gate 		exit(Z_USAGE);
49047c478bd9Sstevel@tonic-gate 	}
49057c478bd9Sstevel@tonic-gate 
4906087719fdSdp 	if ((err = zonecfg_access(zone, W_OK)) == Z_OK) {
49077c478bd9Sstevel@tonic-gate 		read_only_mode = FALSE;
4908087719fdSdp 	} else if (err == Z_ACCES) {
49097c478bd9Sstevel@tonic-gate 		read_only_mode = TRUE;
49107c478bd9Sstevel@tonic-gate 		/* skip this message in one-off from command line mode */
49117c478bd9Sstevel@tonic-gate 		if (optind == argc)
49127c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("WARNING: you do not "
49137c478bd9Sstevel@tonic-gate 			    "have write access to this zone's configuration "
49147c478bd9Sstevel@tonic-gate 			    "file;\ngoing into read-only mode.\n"));
4915087719fdSdp 	} else {
4916087719fdSdp 		fprintf(stderr, "%s: Could not access zone configuration "
4917087719fdSdp 		    "store: %s\n", execname, zonecfg_strerror(err));
4918087719fdSdp 		exit(Z_ERR);
49197c478bd9Sstevel@tonic-gate 	}
49207c478bd9Sstevel@tonic-gate 
49217c478bd9Sstevel@tonic-gate 	if ((handle = zonecfg_init_handle()) == NULL) {
49227c478bd9Sstevel@tonic-gate 		zone_perror(execname, Z_NOMEM, TRUE);
49237c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
49247c478bd9Sstevel@tonic-gate 	}
49257c478bd9Sstevel@tonic-gate 
49267c478bd9Sstevel@tonic-gate 	/*
49277c478bd9Sstevel@tonic-gate 	 * This may get set back to FALSE again in cmd_file() if cmd_file_name
49287c478bd9Sstevel@tonic-gate 	 * is a "real" file as opposed to "-" (i.e. meaning use stdin).
49297c478bd9Sstevel@tonic-gate 	 */
49307c478bd9Sstevel@tonic-gate 	if (isatty(STDIN_FILENO))
49317c478bd9Sstevel@tonic-gate 		ok_to_prompt = TRUE;
49327c478bd9Sstevel@tonic-gate 	if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL)
49337c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
49347c478bd9Sstevel@tonic-gate 	if (gl_customize_completion(gl, NULL, cmd_cpl_fn) != 0)
49357c478bd9Sstevel@tonic-gate 		exit(Z_ERR);
49367c478bd9Sstevel@tonic-gate 	(void) sigset(SIGINT, SIG_IGN);
49377c478bd9Sstevel@tonic-gate 	if (optind == argc) {
49387c478bd9Sstevel@tonic-gate 		if (!cmd_file_mode)
49397c478bd9Sstevel@tonic-gate 			err = do_interactive();
49407c478bd9Sstevel@tonic-gate 		else
49417c478bd9Sstevel@tonic-gate 			err = cmd_file(cmd_file_name);
49427c478bd9Sstevel@tonic-gate 	} else {
49437c478bd9Sstevel@tonic-gate 		err = one_command_at_a_time(argc - optind, &(argv[optind]));
49447c478bd9Sstevel@tonic-gate 	}
49457c478bd9Sstevel@tonic-gate 	zonecfg_fini_handle(handle);
4946*9acbbeafSnn 	if (brand != NULL)
4947*9acbbeafSnn 		brand_close(brand);
49487c478bd9Sstevel@tonic-gate 	(void) del_GetLine(gl);
49497c478bd9Sstevel@tonic-gate 	return (err);
49507c478bd9Sstevel@tonic-gate }
4951