xref: /onnv-gate/usr/src/cmd/zonecfg/zonecfg.c (revision 12761:7f5f1632f71d)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51497Sdp  * Common Development and Distribution License (the "License").
61497Sdp  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21222Scomay 
220Sstevel@tonic-gate /*
2312227SFrank.Batschulat@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * zonecfg is a lex/yacc based command interpreter used to manage zone
280Sstevel@tonic-gate  * configurations.  The lexer (see zonecfg_lex.l) builds up tokens, which
290Sstevel@tonic-gate  * the grammar (see zonecfg_grammar.y) builds up into commands, some of
300Sstevel@tonic-gate  * which takes resources and/or properties as arguments.  See the block
310Sstevel@tonic-gate  * comments near the end of zonecfg_grammar.y for how the data structures
320Sstevel@tonic-gate  * which keep track of these resources and properties are built up.
330Sstevel@tonic-gate  *
340Sstevel@tonic-gate  * The resource/property data structures are inserted into a command
350Sstevel@tonic-gate  * structure (see zonecfg.h), which also keeps track of command names,
360Sstevel@tonic-gate  * miscellaneous arguments, and function handlers.  The grammar selects
370Sstevel@tonic-gate  * the appropriate function handler, each of which takes a pointer to a
380Sstevel@tonic-gate  * command structure as its sole argument, and invokes it.  The grammar
390Sstevel@tonic-gate  * itself is "entered" (a la the Matrix) by yyparse(), which is called
400Sstevel@tonic-gate  * from read_input(), our main driving function.  That in turn is called
410Sstevel@tonic-gate  * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
420Sstevel@tonic-gate  * of which is called from main() depending on how the program was invoked.
430Sstevel@tonic-gate  *
440Sstevel@tonic-gate  * The rest of this module consists of the various function handlers and
450Sstevel@tonic-gate  * their helper functions.  Some of these functions, particularly the
460Sstevel@tonic-gate  * X_to_str() functions, which maps command, resource and property numbers
470Sstevel@tonic-gate  * to strings, are used quite liberally, as doing so results in a better
480Sstevel@tonic-gate  * program w/rt I18N, reducing the need for translation notes.
490Sstevel@tonic-gate  */
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #include <sys/mntent.h>
520Sstevel@tonic-gate #include <sys/varargs.h>
530Sstevel@tonic-gate #include <sys/sysmacros.h>
540Sstevel@tonic-gate 
550Sstevel@tonic-gate #include <errno.h>
562712Snn35248 #include <fcntl.h>
570Sstevel@tonic-gate #include <strings.h>
580Sstevel@tonic-gate #include <unistd.h>
590Sstevel@tonic-gate #include <ctype.h>
600Sstevel@tonic-gate #include <stdlib.h>
610Sstevel@tonic-gate #include <assert.h>
620Sstevel@tonic-gate #include <sys/stat.h>
630Sstevel@tonic-gate #include <zone.h>
640Sstevel@tonic-gate #include <arpa/inet.h>
650Sstevel@tonic-gate #include <netdb.h>
660Sstevel@tonic-gate #include <locale.h>
670Sstevel@tonic-gate #include <libintl.h>
680Sstevel@tonic-gate #include <alloca.h>
690Sstevel@tonic-gate #include <signal.h>
702712Snn35248 #include <wait.h>
710Sstevel@tonic-gate #include <libtecla.h>
72789Sahrens #include <libzfs.h>
732712Snn35248 #include <sys/brand.h>
742712Snn35248 #include <libbrand.h>
758662SJordan.Vaughan@Sun.com #include <sys/systeminfo.h>
768083SJordan.Vaughan@Sun.com #include <libdladm.h>
778083SJordan.Vaughan@Sun.com #include <libinetutil.h>
7812578SGlenn.Faden@Sun.COM #include <pwd.h>
7912748SSowmini.Varadhan@oracle.COM #include <inet/ip.h>
800Sstevel@tonic-gate 
810Sstevel@tonic-gate #include <libzonecfg.h>
820Sstevel@tonic-gate #include "zonecfg.h"
830Sstevel@tonic-gate 
840Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* should be defined by cc -D */
850Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it wasn't */
860Sstevel@tonic-gate #endif
870Sstevel@tonic-gate 
880Sstevel@tonic-gate #define	PAGER	"/usr/bin/more"
892712Snn35248 #define	EXEC_PREFIX	"exec "
902712Snn35248 #define	EXEC_LEN	(strlen(EXEC_PREFIX))
910Sstevel@tonic-gate 
920Sstevel@tonic-gate struct help {
930Sstevel@tonic-gate 	uint_t	cmd_num;
940Sstevel@tonic-gate 	char	*cmd_name;
950Sstevel@tonic-gate 	uint_t	flags;
960Sstevel@tonic-gate 	char	*short_usage;
970Sstevel@tonic-gate };
980Sstevel@tonic-gate 
990Sstevel@tonic-gate extern int yyparse(void);
1000Sstevel@tonic-gate extern int lex_lineno;
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate #define	MAX_LINE_LEN	1024
1030Sstevel@tonic-gate #define	MAX_CMD_HIST	1024
1042712Snn35248 #define	MAX_CMD_LEN	1024
1050Sstevel@tonic-gate 
1063247Sgjelinek #define	ONE_MB		1048576
1073247Sgjelinek 
1080Sstevel@tonic-gate /*
1090Sstevel@tonic-gate  * Each SHELP_ should be a simple string.
1100Sstevel@tonic-gate  */
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate #define	SHELP_ADD	"add <resource-type>\n\t(global scope)\n" \
1130Sstevel@tonic-gate 	"add <property-name> <property-value>\n\t(resource scope)"
1140Sstevel@tonic-gate #define	SHELP_CANCEL	"cancel"
1153247Sgjelinek #define	SHELP_CLEAR	"clear <property-name>"
1160Sstevel@tonic-gate #define	SHELP_COMMIT	"commit"
1171507Sgjelinek #define	SHELP_CREATE	"create [-F] [ -a <path> | -b | -t <template> ]"
1180Sstevel@tonic-gate #define	SHELP_DELETE	"delete [-F]"
1190Sstevel@tonic-gate #define	SHELP_END	"end"
1200Sstevel@tonic-gate #define	SHELP_EXIT	"exit [-F]"
1210Sstevel@tonic-gate #define	SHELP_EXPORT	"export [-f output-file]"
1220Sstevel@tonic-gate #define	SHELP_HELP	"help [commands] [syntax] [usage] [<command-name>]"
1230Sstevel@tonic-gate #define	SHELP_INFO	"info [<resource-type> [property-name=property-value]*]"
1243247Sgjelinek #define	SHELP_REMOVE	"remove [-F] <resource-type> " \
1253247Sgjelinek 	"[ <property-name>=<property-value> ]*\n" \
1263247Sgjelinek 	"\t(global scope)\n" \
1273247Sgjelinek 	"remove <property-name> <property-value>\n" \
1283247Sgjelinek 	"\t(resource scope)"
1290Sstevel@tonic-gate #define	SHELP_REVERT	"revert [-F]"
1300Sstevel@tonic-gate #define	SHELP_SELECT	"select <resource-type> { <property-name>=" \
1310Sstevel@tonic-gate 	"<property-value> }"
1320Sstevel@tonic-gate #define	SHELP_SET	"set <property-name>=<property-value>"
1330Sstevel@tonic-gate #define	SHELP_VERIFY	"verify"
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate static struct help helptab[] = {
1360Sstevel@tonic-gate 	{ CMD_ADD,	"add",		HELP_RES_PROPS,	SHELP_ADD, },
1370Sstevel@tonic-gate 	{ CMD_CANCEL,	"cancel",	0,		SHELP_CANCEL, },
1383247Sgjelinek 	{ CMD_CLEAR,	"clear",	HELP_PROPS,	SHELP_CLEAR, },
1390Sstevel@tonic-gate 	{ CMD_COMMIT,	"commit",	0,		SHELP_COMMIT, },
1400Sstevel@tonic-gate 	{ CMD_CREATE,	"create",	0,		SHELP_CREATE, },
1410Sstevel@tonic-gate 	{ CMD_DELETE,	"delete",	0,		SHELP_DELETE, },
1420Sstevel@tonic-gate 	{ CMD_END,	"end",		0,		SHELP_END, },
1430Sstevel@tonic-gate 	{ CMD_EXIT,	"exit",		0,		SHELP_EXIT, },
1440Sstevel@tonic-gate 	{ CMD_EXPORT,	"export",	0,		SHELP_EXPORT, },
1450Sstevel@tonic-gate 	{ CMD_HELP,	"help",		0,		SHELP_HELP },
1460Sstevel@tonic-gate 	{ CMD_INFO,	"info",		HELP_RES_PROPS,	SHELP_INFO, },
1470Sstevel@tonic-gate 	{ CMD_REMOVE,	"remove",	HELP_RES_PROPS,	SHELP_REMOVE, },
1480Sstevel@tonic-gate 	{ CMD_REVERT,	"revert",	0,		SHELP_REVERT, },
1490Sstevel@tonic-gate 	{ CMD_SELECT,	"select",	HELP_RES_PROPS,	SHELP_SELECT, },
1500Sstevel@tonic-gate 	{ CMD_SET,	"set",		HELP_PROPS,	SHELP_SET, },
1510Sstevel@tonic-gate 	{ CMD_VERIFY,	"verify",	0,		SHELP_VERIFY, },
1520Sstevel@tonic-gate 	{ 0 },
1530Sstevel@tonic-gate };
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate #define	MAX_RT_STRLEN	16
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate /* These *must* match the order of the RT_ define's from zonecfg.h */
15811024SJordan.Vaughan@Sun.com char *res_types[] = {
1590Sstevel@tonic-gate 	"unknown",
160565Sdp 	"zonename",
1610Sstevel@tonic-gate 	"zonepath",
1620Sstevel@tonic-gate 	"autoboot",
1630Sstevel@tonic-gate 	"pool",
1640Sstevel@tonic-gate 	"fs",
1650Sstevel@tonic-gate 	"net",
1660Sstevel@tonic-gate 	"device",
1670Sstevel@tonic-gate 	"rctl",
1680Sstevel@tonic-gate 	"attr",
169789Sahrens 	"dataset",
1701645Scomay 	"limitpriv",
1712267Sdp 	"bootargs",
1722712Snn35248 	"brand",
1733247Sgjelinek 	"dedicated-cpu",
1743247Sgjelinek 	"capped-memory",
1753247Sgjelinek 	ALIAS_MAXLWPS,
1763247Sgjelinek 	ALIAS_MAXSHMMEM,
1773247Sgjelinek 	ALIAS_MAXSHMIDS,
1783247Sgjelinek 	ALIAS_MAXMSGIDS,
1793247Sgjelinek 	ALIAS_MAXSEMIDS,
1803247Sgjelinek 	ALIAS_SHARES,
1813247Sgjelinek 	"scheduling-class",
1823448Sdh155122 	"ip-type",
1833792Sakolb 	"capped-cpu",
1848662SJordan.Vaughan@Sun.com 	"hostid",
18512578SGlenn.Faden@Sun.COM 	"admin",
18612633Sjohn.levon@sun.com 	"fs-allowed",
18712725SMenno.Lageman@Sun.COM 	ALIAS_MAXPROCS,
1880Sstevel@tonic-gate 	NULL
1890Sstevel@tonic-gate };
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate /* These *must* match the order of the PT_ define's from zonecfg.h */
19211024SJordan.Vaughan@Sun.com char *prop_types[] = {
1930Sstevel@tonic-gate 	"unknown",
194565Sdp 	"zonename",
1950Sstevel@tonic-gate 	"zonepath",
1960Sstevel@tonic-gate 	"autoboot",
1970Sstevel@tonic-gate 	"pool",
1980Sstevel@tonic-gate 	"dir",
1990Sstevel@tonic-gate 	"special",
2000Sstevel@tonic-gate 	"type",
2010Sstevel@tonic-gate 	"options",
2020Sstevel@tonic-gate 	"address",
2030Sstevel@tonic-gate 	"physical",
2040Sstevel@tonic-gate 	"name",
2050Sstevel@tonic-gate 	"value",
2060Sstevel@tonic-gate 	"match",
2070Sstevel@tonic-gate 	"priv",
2080Sstevel@tonic-gate 	"limit",
2090Sstevel@tonic-gate 	"action",
2100Sstevel@tonic-gate 	"raw",
2111645Scomay 	"limitpriv",
2122267Sdp 	"bootargs",
2132712Snn35248 	"brand",
2143247Sgjelinek 	"ncpus",
2153247Sgjelinek 	"importance",
2163247Sgjelinek 	"swap",
2173247Sgjelinek 	"locked",
2183247Sgjelinek 	ALIAS_SHARES,
2193247Sgjelinek 	ALIAS_MAXLWPS,
2203247Sgjelinek 	ALIAS_MAXSHMMEM,
2213247Sgjelinek 	ALIAS_MAXSHMIDS,
2223247Sgjelinek 	ALIAS_MAXMSGIDS,
2233247Sgjelinek 	ALIAS_MAXSEMIDS,
2243247Sgjelinek 	ALIAS_MAXLOCKEDMEM,
2253247Sgjelinek 	ALIAS_MAXSWAP,
2263247Sgjelinek 	"scheduling-class",
2273448Sdh155122 	"ip-type",
2286076Sgfaden 	"defrouter",
2298662SJordan.Vaughan@Sun.com 	"hostid",
23012578SGlenn.Faden@Sun.COM 	"user",
23112578SGlenn.Faden@Sun.COM 	"auths",
23212633Sjohn.levon@sun.com 	"fs-allowed",
23312725SMenno.Lageman@Sun.COM 	ALIAS_MAXPROCS,
23412748SSowmini.Varadhan@oracle.COM 	"allowed-address",
2350Sstevel@tonic-gate 	NULL
2360Sstevel@tonic-gate };
2370Sstevel@tonic-gate 
2381645Scomay /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
2390Sstevel@tonic-gate static char *prop_val_types[] = {
2400Sstevel@tonic-gate 	"simple",
2410Sstevel@tonic-gate 	"complex",
2420Sstevel@tonic-gate 	"list",
2430Sstevel@tonic-gate };
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate /*
2460Sstevel@tonic-gate  * The various _cmds[] lists below are for command tab-completion.
2470Sstevel@tonic-gate  */
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate /*
2500Sstevel@tonic-gate  * remove has a space afterwards because it has qualifiers; the other commands
2513247Sgjelinek  * that have qualifiers (add, select, etc.) don't need a space here because
2520Sstevel@tonic-gate  * they have their own _cmds[] lists below.
2530Sstevel@tonic-gate  */
2540Sstevel@tonic-gate static const char *global_scope_cmds[] = {
2550Sstevel@tonic-gate 	"add",
2563247Sgjelinek 	"clear",
2570Sstevel@tonic-gate 	"commit",
2580Sstevel@tonic-gate 	"create",
2590Sstevel@tonic-gate 	"delete",
2600Sstevel@tonic-gate 	"exit",
2610Sstevel@tonic-gate 	"export",
2620Sstevel@tonic-gate 	"help",
2630Sstevel@tonic-gate 	"info",
2640Sstevel@tonic-gate 	"remove ",
2650Sstevel@tonic-gate 	"revert",
2660Sstevel@tonic-gate 	"select",
2670Sstevel@tonic-gate 	"set",
2680Sstevel@tonic-gate 	"verify",
2690Sstevel@tonic-gate 	NULL
2700Sstevel@tonic-gate };
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate static const char *add_cmds[] = {
2730Sstevel@tonic-gate 	"add fs",
2740Sstevel@tonic-gate 	"add net",
2750Sstevel@tonic-gate 	"add device",
2760Sstevel@tonic-gate 	"add rctl",
2770Sstevel@tonic-gate 	"add attr",
278789Sahrens 	"add dataset",
2793247Sgjelinek 	"add dedicated-cpu",
2803792Sakolb 	"add capped-cpu",
2813247Sgjelinek 	"add capped-memory",
28212578SGlenn.Faden@Sun.COM 	"add admin",
2833247Sgjelinek 	NULL
2843247Sgjelinek };
2853247Sgjelinek 
2863247Sgjelinek static const char *clear_cmds[] = {
2873247Sgjelinek 	"clear autoboot",
2883247Sgjelinek 	"clear pool",
2893247Sgjelinek 	"clear limitpriv",
2903247Sgjelinek 	"clear bootargs",
2913247Sgjelinek 	"clear scheduling-class",
2923448Sdh155122 	"clear ip-type",
2933247Sgjelinek 	"clear " ALIAS_MAXLWPS,
2943247Sgjelinek 	"clear " ALIAS_MAXSHMMEM,
2953247Sgjelinek 	"clear " ALIAS_MAXSHMIDS,
2963247Sgjelinek 	"clear " ALIAS_MAXMSGIDS,
2973247Sgjelinek 	"clear " ALIAS_MAXSEMIDS,
2983247Sgjelinek 	"clear " ALIAS_SHARES,
29912725SMenno.Lageman@Sun.COM 	"clear " ALIAS_MAXPROCS,
3000Sstevel@tonic-gate 	NULL
3010Sstevel@tonic-gate };
3020Sstevel@tonic-gate 
3032607Sdp static const char *remove_cmds[] = {
3042607Sdp 	"remove fs ",
3052607Sdp 	"remove net ",
3062607Sdp 	"remove device ",
3072607Sdp 	"remove rctl ",
3082607Sdp 	"remove attr ",
3092607Sdp 	"remove dataset ",
3103247Sgjelinek 	"remove dedicated-cpu ",
3113792Sakolb 	"remove capped-cpu ",
3123247Sgjelinek 	"remove capped-memory ",
31312578SGlenn.Faden@Sun.COM 	"remove admin ",
3142607Sdp 	NULL
3152607Sdp };
3162607Sdp 
3170Sstevel@tonic-gate static const char *select_cmds[] = {
318565Sdp 	"select fs ",
319565Sdp 	"select net ",
320565Sdp 	"select device ",
321565Sdp 	"select rctl ",
322565Sdp 	"select attr ",
323789Sahrens 	"select dataset ",
3243247Sgjelinek 	"select dedicated-cpu",
3253792Sakolb 	"select capped-cpu",
3263247Sgjelinek 	"select capped-memory",
32712578SGlenn.Faden@Sun.COM 	"select admin",
3280Sstevel@tonic-gate 	NULL
3290Sstevel@tonic-gate };
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate static const char *set_cmds[] = {
332565Sdp 	"set zonename=",
333565Sdp 	"set zonepath=",
3342712Snn35248 	"set brand=",
335565Sdp 	"set autoboot=",
336565Sdp 	"set pool=",
3371645Scomay 	"set limitpriv=",
3382267Sdp 	"set bootargs=",
3393247Sgjelinek 	"set scheduling-class=",
3403448Sdh155122 	"set ip-type=",
3413247Sgjelinek 	"set " ALIAS_MAXLWPS "=",
3423247Sgjelinek 	"set " ALIAS_MAXSHMMEM "=",
3433247Sgjelinek 	"set " ALIAS_MAXSHMIDS "=",
3443247Sgjelinek 	"set " ALIAS_MAXMSGIDS "=",
3453247Sgjelinek 	"set " ALIAS_MAXSEMIDS "=",
3463247Sgjelinek 	"set " ALIAS_SHARES "=",
3478662SJordan.Vaughan@Sun.com 	"set hostid=",
34812633Sjohn.levon@sun.com 	"set fs-allowed=",
34912725SMenno.Lageman@Sun.COM 	"set " ALIAS_MAXPROCS "=",
3500Sstevel@tonic-gate 	NULL
3510Sstevel@tonic-gate };
3520Sstevel@tonic-gate 
3532607Sdp static const char *info_cmds[] = {
3542607Sdp 	"info fs ",
3552607Sdp 	"info net ",
3562607Sdp 	"info device ",
3572607Sdp 	"info rctl ",
3582607Sdp 	"info attr ",
3592607Sdp 	"info dataset ",
3603247Sgjelinek 	"info capped-memory",
3613247Sgjelinek 	"info dedicated-cpu",
3623792Sakolb 	"info capped-cpu",
3632607Sdp 	"info zonename",
3642607Sdp 	"info zonepath",
3652607Sdp 	"info autoboot",
3662607Sdp 	"info pool",
3672607Sdp 	"info limitpriv",
3682607Sdp 	"info bootargs",
3693247Sgjelinek 	"info brand",
3703247Sgjelinek 	"info scheduling-class",
3713448Sdh155122 	"info ip-type",
3723247Sgjelinek 	"info max-lwps",
3733247Sgjelinek 	"info max-shm-memory",
3743247Sgjelinek 	"info max-shm-ids",
3753247Sgjelinek 	"info max-msg-ids",
3763247Sgjelinek 	"info max-sem-ids",
3773247Sgjelinek 	"info cpu-shares",
3788662SJordan.Vaughan@Sun.com 	"info hostid",
37912578SGlenn.Faden@Sun.COM 	"info admin",
38012633Sjohn.levon@sun.com 	"info fs-allowed",
38112725SMenno.Lageman@Sun.COM 	"info max-processes",
3822607Sdp 	NULL
3832607Sdp };
3842607Sdp 
3850Sstevel@tonic-gate static const char *fs_res_scope_cmds[] = {
3860Sstevel@tonic-gate 	"add options ",
3870Sstevel@tonic-gate 	"cancel",
3880Sstevel@tonic-gate 	"end",
3890Sstevel@tonic-gate 	"exit",
3900Sstevel@tonic-gate 	"help",
3910Sstevel@tonic-gate 	"info",
3921645Scomay 	"remove options ",
3930Sstevel@tonic-gate 	"set dir=",
3940Sstevel@tonic-gate 	"set raw=",
3950Sstevel@tonic-gate 	"set special=",
3960Sstevel@tonic-gate 	"set type=",
3973247Sgjelinek 	"clear raw",
3980Sstevel@tonic-gate 	NULL
3990Sstevel@tonic-gate };
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate static const char *net_res_scope_cmds[] = {
4020Sstevel@tonic-gate 	"cancel",
4030Sstevel@tonic-gate 	"end",
4040Sstevel@tonic-gate 	"exit",
4050Sstevel@tonic-gate 	"help",
4060Sstevel@tonic-gate 	"info",
4070Sstevel@tonic-gate 	"set address=",
4080Sstevel@tonic-gate 	"set physical=",
40912626SGerald.Jelinek@Sun.COM 	"set defrouter=",
4100Sstevel@tonic-gate 	NULL
4110Sstevel@tonic-gate };
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate static const char *device_res_scope_cmds[] = {
4140Sstevel@tonic-gate 	"cancel",
4150Sstevel@tonic-gate 	"end",
4160Sstevel@tonic-gate 	"exit",
4170Sstevel@tonic-gate 	"help",
4180Sstevel@tonic-gate 	"info",
4190Sstevel@tonic-gate 	"set match=",
4200Sstevel@tonic-gate 	NULL
4210Sstevel@tonic-gate };
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate static const char *attr_res_scope_cmds[] = {
4240Sstevel@tonic-gate 	"cancel",
4250Sstevel@tonic-gate 	"end",
4260Sstevel@tonic-gate 	"exit",
4270Sstevel@tonic-gate 	"help",
4280Sstevel@tonic-gate 	"info",
4290Sstevel@tonic-gate 	"set name=",
4300Sstevel@tonic-gate 	"set type=",
4310Sstevel@tonic-gate 	"set value=",
4320Sstevel@tonic-gate 	NULL
4330Sstevel@tonic-gate };
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate static const char *rctl_res_scope_cmds[] = {
4360Sstevel@tonic-gate 	"add value ",
4370Sstevel@tonic-gate 	"cancel",
4380Sstevel@tonic-gate 	"end",
4390Sstevel@tonic-gate 	"exit",
4400Sstevel@tonic-gate 	"help",
4410Sstevel@tonic-gate 	"info",
4421645Scomay 	"remove value ",
4430Sstevel@tonic-gate 	"set name=",
4440Sstevel@tonic-gate 	NULL
4450Sstevel@tonic-gate };
4460Sstevel@tonic-gate 
447789Sahrens static const char *dataset_res_scope_cmds[] = {
448789Sahrens 	"cancel",
449789Sahrens 	"end",
450789Sahrens 	"exit",
451789Sahrens 	"help",
452789Sahrens 	"info",
453789Sahrens 	"set name=",
454789Sahrens 	NULL
455789Sahrens };
456789Sahrens 
4573247Sgjelinek static const char *pset_res_scope_cmds[] = {
4583247Sgjelinek 	"cancel",
4593247Sgjelinek 	"end",
4603247Sgjelinek 	"exit",
4613247Sgjelinek 	"help",
4623247Sgjelinek 	"info",
4633247Sgjelinek 	"set ncpus=",
4643247Sgjelinek 	"set importance=",
4653247Sgjelinek 	"clear importance",
4663247Sgjelinek 	NULL
4673247Sgjelinek };
4683247Sgjelinek 
4693792Sakolb static const char *pcap_res_scope_cmds[] = {
4703792Sakolb 	"cancel",
4713792Sakolb 	"end",
4723792Sakolb 	"exit",
4733792Sakolb 	"help",
4743792Sakolb 	"info",
4753792Sakolb 	"set ncpus=",
4763792Sakolb 	NULL
4773792Sakolb };
4783792Sakolb 
4793247Sgjelinek static const char *mcap_res_scope_cmds[] = {
4803247Sgjelinek 	"cancel",
4813247Sgjelinek 	"end",
4823247Sgjelinek 	"exit",
4833247Sgjelinek 	"help",
4843247Sgjelinek 	"info",
4853247Sgjelinek 	"set physical=",
4863247Sgjelinek 	"set swap=",
4873247Sgjelinek 	"set locked=",
4883247Sgjelinek 	"clear physical",
4893247Sgjelinek 	"clear swap",
4903247Sgjelinek 	"clear locked",
4913247Sgjelinek 	NULL
4923247Sgjelinek };
4933247Sgjelinek 
49412578SGlenn.Faden@Sun.COM static const char *admin_res_scope_cmds[] = {
49512578SGlenn.Faden@Sun.COM 	"cancel",
49612578SGlenn.Faden@Sun.COM 	"end",
49712578SGlenn.Faden@Sun.COM 	"exit",
49812578SGlenn.Faden@Sun.COM 	"help",
49912578SGlenn.Faden@Sun.COM 	"info",
50012578SGlenn.Faden@Sun.COM 	"set user=",
50112578SGlenn.Faden@Sun.COM 	"set auths=",
50212578SGlenn.Faden@Sun.COM 	NULL
50312578SGlenn.Faden@Sun.COM };
50412578SGlenn.Faden@Sun.COM 
50512748SSowmini.Varadhan@oracle.COM struct xif {
50612748SSowmini.Varadhan@oracle.COM 	struct xif	*xif_next;
50712748SSowmini.Varadhan@oracle.COM 	char		xif_name[LIFNAMSIZ];
50812748SSowmini.Varadhan@oracle.COM 	boolean_t	xif_has_address;
50912748SSowmini.Varadhan@oracle.COM 	boolean_t	xif_has_defrouter;
51012748SSowmini.Varadhan@oracle.COM };
51112748SSowmini.Varadhan@oracle.COM 
5120Sstevel@tonic-gate /* Global variables */
5130Sstevel@tonic-gate 
51412748SSowmini.Varadhan@oracle.COM /* list of network interfaces specified for exclusive IP zone */
51512748SSowmini.Varadhan@oracle.COM struct xif *xif;
51612748SSowmini.Varadhan@oracle.COM 
5170Sstevel@tonic-gate /* set early in main(), never modified thereafter, used all over the place */
5180Sstevel@tonic-gate static char *execname;
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate /* set in main(), used all over the place */
5210Sstevel@tonic-gate static zone_dochandle_t handle;
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate /* used all over the place */
524565Sdp static char zone[ZONENAME_MAX];
525565Sdp static char revert_zone[ZONENAME_MAX];
5260Sstevel@tonic-gate 
5272712Snn35248 /* global brand operations */
5282727Sedp static brand_handle_t brand;
5292712Snn35248 
5300Sstevel@tonic-gate /* set in modifying functions, checked in read_input() */
5316215Sgjelinek static boolean_t need_to_commit = B_FALSE;
5326215Sgjelinek boolean_t saw_error;
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate /* set in yacc parser, checked in read_input() */
5356215Sgjelinek boolean_t newline_terminated;
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate /* set in main(), checked in lex error handler */
5386215Sgjelinek boolean_t cmd_file_mode;
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate /* set in exit_func(), checked in read_input() */
5416215Sgjelinek static boolean_t time_to_exit = B_FALSE, force_exit = B_FALSE;
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate /* used in short_usage() and zerr() */
5440Sstevel@tonic-gate static char *cmd_file_name = NULL;
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate /* checked in read_input() and other places */
5476215Sgjelinek static boolean_t ok_to_prompt = B_FALSE;
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate /* set and checked in initialize() */
5506215Sgjelinek static boolean_t got_handle = B_FALSE;
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate /* initialized in do_interactive(), checked in initialize() */
5536215Sgjelinek static boolean_t interactive_mode;
5540Sstevel@tonic-gate 
5553247Sgjelinek /* set if configuring the global zone */
5566215Sgjelinek static boolean_t global_zone = B_FALSE;
5573247Sgjelinek 
5580Sstevel@tonic-gate /* set in main(), checked in multiple places */
5596215Sgjelinek static boolean_t read_only_mode;
5606215Sgjelinek 
5616215Sgjelinek /* scope is outer/global or inner/resource */
5626215Sgjelinek static boolean_t global_scope = B_TRUE;
5630Sstevel@tonic-gate static int resource_scope;	/* should be in the RT_ list from zonecfg.h */
5640Sstevel@tonic-gate static int end_op = -1;		/* operation on end is either add or modify */
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate int num_prop_vals;		/* for grammar */
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate /*
5690Sstevel@tonic-gate  * These are for keeping track of resources as they are specified as part of
5700Sstevel@tonic-gate  * the multi-step process.  They should be initialized by add_resource() or
5710Sstevel@tonic-gate  * select_func() and filled in by add_property() or set_func().
5720Sstevel@tonic-gate  */
5730Sstevel@tonic-gate static struct zone_fstab	old_fstab, in_progress_fstab;
5740Sstevel@tonic-gate static struct zone_nwiftab	old_nwiftab, in_progress_nwiftab;
5750Sstevel@tonic-gate static struct zone_devtab	old_devtab, in_progress_devtab;
5760Sstevel@tonic-gate static struct zone_rctltab	old_rctltab, in_progress_rctltab;
5770Sstevel@tonic-gate static struct zone_attrtab	old_attrtab, in_progress_attrtab;
578789Sahrens static struct zone_dstab	old_dstab, in_progress_dstab;
5793247Sgjelinek static struct zone_psettab	old_psettab, in_progress_psettab;
5803247Sgjelinek static struct zone_mcaptab	old_mcaptab, in_progress_mcaptab;
58112578SGlenn.Faden@Sun.COM static struct zone_admintab	old_admintab, in_progress_admintab;
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate static GetLine *gl;	/* The gl_get_line() resource object */
5840Sstevel@tonic-gate 
5853247Sgjelinek static void bytes_to_units(char *str, char *buf, int bufsize);
5863247Sgjelinek 
5870Sstevel@tonic-gate /* Functions begin here */
5880Sstevel@tonic-gate 
5896215Sgjelinek static boolean_t
initial_match(const char * line1,const char * line2,int word_end)5900Sstevel@tonic-gate initial_match(const char *line1, const char *line2, int word_end)
5910Sstevel@tonic-gate {
5920Sstevel@tonic-gate 	if (word_end <= 0)
5936215Sgjelinek 		return (B_TRUE);
5940Sstevel@tonic-gate 	return (strncmp(line1, line2, word_end) == 0);
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate static int
add_stuff(WordCompletion * cpl,const char * line1,const char ** list,int word_end)5980Sstevel@tonic-gate add_stuff(WordCompletion *cpl, const char *line1, const char **list,
5990Sstevel@tonic-gate     int word_end)
6000Sstevel@tonic-gate {
6010Sstevel@tonic-gate 	int i, err;
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate 	for (i = 0; list[i] != NULL; i++) {
6040Sstevel@tonic-gate 		if (initial_match(line1, list[i], word_end)) {
6050Sstevel@tonic-gate 			err = cpl_add_completion(cpl, line1, 0, word_end,
6060Sstevel@tonic-gate 			    list[i] + word_end, "", "");
6070Sstevel@tonic-gate 			if (err != 0)
6080Sstevel@tonic-gate 				return (err);
6090Sstevel@tonic-gate 		}
6100Sstevel@tonic-gate 	}
6110Sstevel@tonic-gate 	return (0);
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate static
6150Sstevel@tonic-gate /* ARGSUSED */
CPL_MATCH_FN(cmd_cpl_fn)6160Sstevel@tonic-gate CPL_MATCH_FN(cmd_cpl_fn)
6170Sstevel@tonic-gate {
6180Sstevel@tonic-gate 	if (global_scope) {
6190Sstevel@tonic-gate 		/*
6200Sstevel@tonic-gate 		 * The MAX/MIN tests below are to make sure we have at least
6210Sstevel@tonic-gate 		 * enough characters to distinguish from other prefixes (MAX)
6220Sstevel@tonic-gate 		 * but only check MIN(what we have, what we're checking).
6230Sstevel@tonic-gate 		 */
6240Sstevel@tonic-gate 		if (strncmp(line, "add ", MAX(MIN(word_end, 4), 1)) == 0)
6250Sstevel@tonic-gate 			return (add_stuff(cpl, line, add_cmds, word_end));
6263247Sgjelinek 		if (strncmp(line, "clear ", MAX(MIN(word_end, 6), 2)) == 0)
6273247Sgjelinek 			return (add_stuff(cpl, line, clear_cmds, word_end));
6280Sstevel@tonic-gate 		if (strncmp(line, "select ", MAX(MIN(word_end, 7), 3)) == 0)
6290Sstevel@tonic-gate 			return (add_stuff(cpl, line, select_cmds, word_end));
6300Sstevel@tonic-gate 		if (strncmp(line, "set ", MAX(MIN(word_end, 4), 3)) == 0)
6310Sstevel@tonic-gate 			return (add_stuff(cpl, line, set_cmds, word_end));
6322607Sdp 		if (strncmp(line, "remove ", MAX(MIN(word_end, 7), 1)) == 0)
6332607Sdp 			return (add_stuff(cpl, line, remove_cmds, word_end));
6342607Sdp 		if (strncmp(line, "info ", MAX(MIN(word_end, 5), 1)) == 0)
6352607Sdp 			return (add_stuff(cpl, line, info_cmds, word_end));
6360Sstevel@tonic-gate 		return (add_stuff(cpl, line, global_scope_cmds, word_end));
6370Sstevel@tonic-gate 	}
6380Sstevel@tonic-gate 	switch (resource_scope) {
6390Sstevel@tonic-gate 	case RT_FS:
6400Sstevel@tonic-gate 		return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
6410Sstevel@tonic-gate 	case RT_NET:
6420Sstevel@tonic-gate 		return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
6430Sstevel@tonic-gate 	case RT_DEVICE:
6440Sstevel@tonic-gate 		return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
6450Sstevel@tonic-gate 	case RT_RCTL:
6460Sstevel@tonic-gate 		return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
6470Sstevel@tonic-gate 	case RT_ATTR:
6480Sstevel@tonic-gate 		return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
649789Sahrens 	case RT_DATASET:
650789Sahrens 		return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
6513247Sgjelinek 	case RT_DCPU:
6523247Sgjelinek 		return (add_stuff(cpl, line, pset_res_scope_cmds, word_end));
6533792Sakolb 	case RT_PCAP:
6543792Sakolb 		return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
6553247Sgjelinek 	case RT_MCAP:
6563247Sgjelinek 		return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
65712578SGlenn.Faden@Sun.COM 	case RT_ADMIN:
65812578SGlenn.Faden@Sun.COM 		return (add_stuff(cpl, line, admin_res_scope_cmds, word_end));
6590Sstevel@tonic-gate 	}
6600Sstevel@tonic-gate 	return (0);
6610Sstevel@tonic-gate }
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate /*
6640Sstevel@tonic-gate  * For the main CMD_func() functions below, several of them call getopt()
6650Sstevel@tonic-gate  * then check optind against argc to make sure an extra parameter was not
6660Sstevel@tonic-gate  * passed in.  The reason this is not caught in the grammar is that the
6670Sstevel@tonic-gate  * grammar just checks for a miscellaneous TOKEN, which is *expected* to
6680Sstevel@tonic-gate  * be "-F" (for example), but could be anything.  So (for example) this
6690Sstevel@tonic-gate  * check will prevent "create bogus".
6700Sstevel@tonic-gate  */
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate cmd_t *
alloc_cmd(void)6730Sstevel@tonic-gate alloc_cmd(void)
6740Sstevel@tonic-gate {
6750Sstevel@tonic-gate 	return (calloc(1, sizeof (cmd_t)));
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate void
free_cmd(cmd_t * cmd)6790Sstevel@tonic-gate free_cmd(cmd_t *cmd)
6800Sstevel@tonic-gate {
6810Sstevel@tonic-gate 	int i;
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 	for (i = 0; i < MAX_EQ_PROP_PAIRS; i++)
6840Sstevel@tonic-gate 		if (cmd->cmd_property_ptr[i] != NULL) {
6850Sstevel@tonic-gate 			property_value_ptr_t pp = cmd->cmd_property_ptr[i];
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate 			switch (pp->pv_type) {
6880Sstevel@tonic-gate 			case PROP_VAL_SIMPLE:
6890Sstevel@tonic-gate 				free(pp->pv_simple);
6900Sstevel@tonic-gate 				break;
6910Sstevel@tonic-gate 			case PROP_VAL_COMPLEX:
6920Sstevel@tonic-gate 				free_complex(pp->pv_complex);
6930Sstevel@tonic-gate 				break;
6940Sstevel@tonic-gate 			case PROP_VAL_LIST:
6950Sstevel@tonic-gate 				free_list(pp->pv_list);
6960Sstevel@tonic-gate 				break;
6970Sstevel@tonic-gate 			}
6980Sstevel@tonic-gate 		}
6990Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_argc; i++)
7000Sstevel@tonic-gate 		free(cmd->cmd_argv[i]);
7010Sstevel@tonic-gate 	free(cmd);
7020Sstevel@tonic-gate }
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate complex_property_ptr_t
alloc_complex(void)7050Sstevel@tonic-gate alloc_complex(void)
7060Sstevel@tonic-gate {
7070Sstevel@tonic-gate 	return (calloc(1, sizeof (complex_property_t)));
7080Sstevel@tonic-gate }
7090Sstevel@tonic-gate 
7100Sstevel@tonic-gate void
free_complex(complex_property_ptr_t complex)7110Sstevel@tonic-gate free_complex(complex_property_ptr_t complex)
7120Sstevel@tonic-gate {
7130Sstevel@tonic-gate 	if (complex == NULL)
7140Sstevel@tonic-gate 		return;
7150Sstevel@tonic-gate 	free_complex(complex->cp_next);
7160Sstevel@tonic-gate 	if (complex->cp_value != NULL)
7170Sstevel@tonic-gate 		free(complex->cp_value);
7180Sstevel@tonic-gate 	free(complex);
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate list_property_ptr_t
alloc_list(void)7220Sstevel@tonic-gate alloc_list(void)
7230Sstevel@tonic-gate {
7240Sstevel@tonic-gate 	return (calloc(1, sizeof (list_property_t)));
7250Sstevel@tonic-gate }
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate void
free_list(list_property_ptr_t list)7280Sstevel@tonic-gate free_list(list_property_ptr_t list)
7290Sstevel@tonic-gate {
7300Sstevel@tonic-gate 	if (list == NULL)
7310Sstevel@tonic-gate 		return;
7320Sstevel@tonic-gate 	if (list->lp_simple != NULL)
7330Sstevel@tonic-gate 		free(list->lp_simple);
7340Sstevel@tonic-gate 	free_complex(list->lp_complex);
7350Sstevel@tonic-gate 	free_list(list->lp_next);
7360Sstevel@tonic-gate 	free(list);
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate void
free_outer_list(list_property_ptr_t list)7400Sstevel@tonic-gate free_outer_list(list_property_ptr_t list)
7410Sstevel@tonic-gate {
7420Sstevel@tonic-gate 	if (list == NULL)
7430Sstevel@tonic-gate 		return;
7440Sstevel@tonic-gate 	free_outer_list(list->lp_next);
7450Sstevel@tonic-gate 	free(list);
7460Sstevel@tonic-gate }
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate static struct zone_rctlvaltab *
alloc_rctlvaltab(void)7490Sstevel@tonic-gate alloc_rctlvaltab(void)
7500Sstevel@tonic-gate {
7510Sstevel@tonic-gate 	return (calloc(1, sizeof (struct zone_rctlvaltab)));
7520Sstevel@tonic-gate }
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate static char *
rt_to_str(int res_type)7550Sstevel@tonic-gate rt_to_str(int res_type)
7560Sstevel@tonic-gate {
7570Sstevel@tonic-gate 	assert(res_type >= RT_MIN && res_type <= RT_MAX);
7580Sstevel@tonic-gate 	return (res_types[res_type]);
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate static char *
pt_to_str(int prop_type)7620Sstevel@tonic-gate pt_to_str(int prop_type)
7630Sstevel@tonic-gate {
7640Sstevel@tonic-gate 	assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
7650Sstevel@tonic-gate 	return (prop_types[prop_type]);
7660Sstevel@tonic-gate }
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate static char *
pvt_to_str(int pv_type)7690Sstevel@tonic-gate pvt_to_str(int pv_type)
7700Sstevel@tonic-gate {
7710Sstevel@tonic-gate 	assert(pv_type >= PROP_VAL_MIN && pv_type <= PROP_VAL_MAX);
7720Sstevel@tonic-gate 	return (prop_val_types[pv_type]);
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate static char *
cmd_to_str(int cmd_num)7760Sstevel@tonic-gate cmd_to_str(int cmd_num)
7770Sstevel@tonic-gate {
7780Sstevel@tonic-gate 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
7790Sstevel@tonic-gate 	return (helptab[cmd_num].cmd_name);
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate 
78211882SFrank.Batschulat@Sun.COM /* PRINTFLIKE1 */
78311882SFrank.Batschulat@Sun.COM static void
zerr(const char * fmt,...)78411882SFrank.Batschulat@Sun.COM zerr(const char *fmt, ...)
78511882SFrank.Batschulat@Sun.COM {
78611882SFrank.Batschulat@Sun.COM 	va_list alist;
78711882SFrank.Batschulat@Sun.COM 	static int last_lineno;
78811882SFrank.Batschulat@Sun.COM 
78911882SFrank.Batschulat@Sun.COM 	/* lex_lineno has already been incremented in the lexer; compensate */
79011882SFrank.Batschulat@Sun.COM 	if (cmd_file_mode && lex_lineno > last_lineno) {
79111882SFrank.Batschulat@Sun.COM 		if (strcmp(cmd_file_name, "-") == 0)
79211882SFrank.Batschulat@Sun.COM 			(void) fprintf(stderr, gettext("On line %d:\n"),
79311882SFrank.Batschulat@Sun.COM 			    lex_lineno - 1);
79411882SFrank.Batschulat@Sun.COM 		else
79511882SFrank.Batschulat@Sun.COM 			(void) fprintf(stderr, gettext("On line %d of %s:\n"),
79611882SFrank.Batschulat@Sun.COM 			    lex_lineno - 1, cmd_file_name);
79711882SFrank.Batschulat@Sun.COM 		last_lineno = lex_lineno;
79811882SFrank.Batschulat@Sun.COM 	}
79911882SFrank.Batschulat@Sun.COM 	va_start(alist, fmt);
80011882SFrank.Batschulat@Sun.COM 	(void) vfprintf(stderr, fmt, alist);
80111882SFrank.Batschulat@Sun.COM 	(void) fprintf(stderr, "\n");
80211882SFrank.Batschulat@Sun.COM 	va_end(alist);
80311882SFrank.Batschulat@Sun.COM }
80411882SFrank.Batschulat@Sun.COM 
8050Sstevel@tonic-gate /*
8060Sstevel@tonic-gate  * This is a separate function rather than a set of define's because of the
8070Sstevel@tonic-gate  * gettext() wrapping.
8080Sstevel@tonic-gate  */
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate /*
8110Sstevel@tonic-gate  * TRANSLATION_NOTE
8120Sstevel@tonic-gate  * Each string below should have \t follow \n whenever needed; the
8130Sstevel@tonic-gate  * initial \t and the terminal \n will be provided by the calling function.
8140Sstevel@tonic-gate  */
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate static char *
long_help(int cmd_num)8170Sstevel@tonic-gate long_help(int cmd_num)
8180Sstevel@tonic-gate {
8190Sstevel@tonic-gate 	static char line[1024];	/* arbitrary large amount */
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
8220Sstevel@tonic-gate 	switch (cmd_num) {
8230Sstevel@tonic-gate 		case CMD_HELP:
8240Sstevel@tonic-gate 			return (gettext("Prints help message."));
8250Sstevel@tonic-gate 		case CMD_CREATE:
8260Sstevel@tonic-gate 			(void) snprintf(line, sizeof (line),
8270Sstevel@tonic-gate 			    gettext("Creates a configuration for the "
8280Sstevel@tonic-gate 			    "specified zone.  %s should be\n\tused to "
8290Sstevel@tonic-gate 			    "begin configuring a new zone.  If overwriting an "
8300Sstevel@tonic-gate 			    "existing\n\tconfiguration, the -F flag can be "
8310Sstevel@tonic-gate 			    "used to force the action.  If\n\t-t template is "
8320Sstevel@tonic-gate 			    "given, creates a configuration identical to the\n"
8330Sstevel@tonic-gate 			    "\tspecified template, except that the zone name "
8341634Sgjelinek 			    "is changed from\n\ttemplate to zonename.  '%s -a' "
8351634Sgjelinek 			    "creates a configuration from a\n\tdetached "
8361634Sgjelinek 			    "zonepath.  '%s -b' results in a blank "
8371634Sgjelinek 			    "configuration.\n\t'%s' with no arguments applies "
8381634Sgjelinek 			    "the Sun default settings."),
8390Sstevel@tonic-gate 			    cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE),
8401634Sgjelinek 			    cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE));
8410Sstevel@tonic-gate 			return (line);
8420Sstevel@tonic-gate 		case CMD_EXIT:
8430Sstevel@tonic-gate 			return (gettext("Exits the program.  The -F flag can "
8440Sstevel@tonic-gate 			    "be used to force the action."));
8450Sstevel@tonic-gate 		case CMD_EXPORT:
8460Sstevel@tonic-gate 			return (gettext("Prints configuration to standard "
8470Sstevel@tonic-gate 			    "output, or to output-file if\n\tspecified, in "
8480Sstevel@tonic-gate 			    "a form suitable for use in a command-file."));
8490Sstevel@tonic-gate 		case CMD_ADD:
8500Sstevel@tonic-gate 			return (gettext("Add specified resource to "
8510Sstevel@tonic-gate 			    "configuration."));
8520Sstevel@tonic-gate 		case CMD_DELETE:
8530Sstevel@tonic-gate 			return (gettext("Deletes the specified zone.  The -F "
8540Sstevel@tonic-gate 			    "flag can be used to force the\n\taction."));
8550Sstevel@tonic-gate 		case CMD_REMOVE:
8560Sstevel@tonic-gate 			return (gettext("Remove specified resource from "
8573247Sgjelinek 			    "configuration.  The -F flag can be used\n\tto "
8583247Sgjelinek 			    "force the action."));
8590Sstevel@tonic-gate 		case CMD_SELECT:
8600Sstevel@tonic-gate 			(void) snprintf(line, sizeof (line),
8610Sstevel@tonic-gate 			    gettext("Selects a resource to modify.  "
8620Sstevel@tonic-gate 			    "Resource modification is completed\n\twith the "
8630Sstevel@tonic-gate 			    "command \"%s\".  The property name/value pairs "
8640Sstevel@tonic-gate 			    "must uniquely\n\tidentify a resource.  Note that "
8650Sstevel@tonic-gate 			    "the curly braces ('{', '}') mean one\n\tor more "
8660Sstevel@tonic-gate 			    "of whatever is between them."),
8670Sstevel@tonic-gate 			    cmd_to_str(CMD_END));
8680Sstevel@tonic-gate 			return (line);
8690Sstevel@tonic-gate 		case CMD_SET:
8700Sstevel@tonic-gate 			return (gettext("Sets property values."));
8713247Sgjelinek 		case CMD_CLEAR:
8723247Sgjelinek 			return (gettext("Clears property values."));
8730Sstevel@tonic-gate 		case CMD_INFO:
8740Sstevel@tonic-gate 			return (gettext("Displays information about the "
8750Sstevel@tonic-gate 			    "current configuration.  If resource\n\ttype is "
8760Sstevel@tonic-gate 			    "specified, displays only information about "
8770Sstevel@tonic-gate 			    "resources of\n\tthe relevant type.  If resource "
8780Sstevel@tonic-gate 			    "id is specified, displays only\n\tinformation "
8790Sstevel@tonic-gate 			    "about that resource."));
8800Sstevel@tonic-gate 		case CMD_VERIFY:
8810Sstevel@tonic-gate 			return (gettext("Verifies current configuration "
8820Sstevel@tonic-gate 			    "for correctness (some resource types\n\thave "
8830Sstevel@tonic-gate 			    "required properties)."));
8840Sstevel@tonic-gate 		case CMD_COMMIT:
8850Sstevel@tonic-gate 			(void) snprintf(line, sizeof (line),
8860Sstevel@tonic-gate 			    gettext("Commits current configuration.  "
8870Sstevel@tonic-gate 			    "Configuration must be committed to\n\tbe used by "
8880Sstevel@tonic-gate 			    "%s.  Until the configuration is committed, "
8890Sstevel@tonic-gate 			    "changes \n\tcan be removed with the %s "
8900Sstevel@tonic-gate 			    "command.  This operation is\n\tattempted "
8910Sstevel@tonic-gate 			    "automatically upon completion of a %s "
8920Sstevel@tonic-gate 			    "session."), "zoneadm", cmd_to_str(CMD_REVERT),
8930Sstevel@tonic-gate 			    "zonecfg");
8940Sstevel@tonic-gate 			return (line);
8950Sstevel@tonic-gate 		case CMD_REVERT:
8960Sstevel@tonic-gate 			return (gettext("Reverts configuration back to the "
8970Sstevel@tonic-gate 			    "last committed state.  The -F flag\n\tcan be "
8980Sstevel@tonic-gate 			    "used to force the action."));
8990Sstevel@tonic-gate 		case CMD_CANCEL:
9000Sstevel@tonic-gate 			return (gettext("Cancels resource/property "
9010Sstevel@tonic-gate 			    "specification."));
9020Sstevel@tonic-gate 		case CMD_END:
9030Sstevel@tonic-gate 			return (gettext("Ends resource/property "
9040Sstevel@tonic-gate 			    "specification."));
9050Sstevel@tonic-gate 	}
9060Sstevel@tonic-gate 	/* NOTREACHED */
907222Scomay 	return (NULL);
9080Sstevel@tonic-gate }
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate /*
9110Sstevel@tonic-gate  * Called with verbose TRUE when help is explicitly requested, FALSE for
9120Sstevel@tonic-gate  * unexpected errors.
9130Sstevel@tonic-gate  */
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate void
usage(boolean_t verbose,uint_t flags)9166215Sgjelinek usage(boolean_t verbose, uint_t flags)
9170Sstevel@tonic-gate {
91811882SFrank.Batschulat@Sun.COM 	FILE *fp = verbose ? stdout : stderr;
91911882SFrank.Batschulat@Sun.COM 	FILE *newfp;
9206215Sgjelinek 	boolean_t need_to_close = B_FALSE;
921*12761SSusan.Kamm-Worrell@Sun.COM 	char *pager, *space;
9220Sstevel@tonic-gate 	int i;
92311882SFrank.Batschulat@Sun.COM 	struct stat statbuf;
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 	/* don't page error output */
9260Sstevel@tonic-gate 	if (verbose && interactive_mode) {
9270Sstevel@tonic-gate 		if ((pager = getenv("PAGER")) == NULL)
9280Sstevel@tonic-gate 			pager = PAGER;
92911882SFrank.Batschulat@Sun.COM 
930*12761SSusan.Kamm-Worrell@Sun.COM 		space = strchr(pager, ' ');
931*12761SSusan.Kamm-Worrell@Sun.COM 		if (space)
932*12761SSusan.Kamm-Worrell@Sun.COM 			*space = '\0';
93311882SFrank.Batschulat@Sun.COM 		if (stat(pager, &statbuf) == 0) {
934*12761SSusan.Kamm-Worrell@Sun.COM 			if (space)
935*12761SSusan.Kamm-Worrell@Sun.COM 				*space = ' ';
93611882SFrank.Batschulat@Sun.COM 			if ((newfp = popen(pager, "w")) != NULL) {
93711882SFrank.Batschulat@Sun.COM 				need_to_close = B_TRUE;
93811882SFrank.Batschulat@Sun.COM 				fp = newfp;
93911882SFrank.Batschulat@Sun.COM 			}
94011882SFrank.Batschulat@Sun.COM 		} else {
94111882SFrank.Batschulat@Sun.COM 			zerr(gettext("PAGER %s does not exist (%s)."),
94211882SFrank.Batschulat@Sun.COM 			    pager, strerror(errno));
94311882SFrank.Batschulat@Sun.COM 		}
94411882SFrank.Batschulat@Sun.COM 	}
94511882SFrank.Batschulat@Sun.COM 
9460Sstevel@tonic-gate 	if (flags & HELP_META) {
9470Sstevel@tonic-gate 		(void) fprintf(fp, gettext("More help is available for the "
9480Sstevel@tonic-gate 		    "following:\n"));
9490Sstevel@tonic-gate 		(void) fprintf(fp, "\n\tcommands ('%s commands')\n",
9500Sstevel@tonic-gate 		    cmd_to_str(CMD_HELP));
9510Sstevel@tonic-gate 		(void) fprintf(fp, "\tsyntax ('%s syntax')\n",
9520Sstevel@tonic-gate 		    cmd_to_str(CMD_HELP));
9530Sstevel@tonic-gate 		(void) fprintf(fp, "\tusage ('%s usage')\n\n",
9540Sstevel@tonic-gate 		    cmd_to_str(CMD_HELP));
9550Sstevel@tonic-gate 		(void) fprintf(fp, gettext("You may also obtain help on any "
9560Sstevel@tonic-gate 		    "command by typing '%s <command-name>.'\n"),
9570Sstevel@tonic-gate 		    cmd_to_str(CMD_HELP));
9580Sstevel@tonic-gate 	}
9590Sstevel@tonic-gate 	if (flags & HELP_RES_SCOPE) {
9600Sstevel@tonic-gate 		switch (resource_scope) {
9610Sstevel@tonic-gate 		case RT_FS:
9620Sstevel@tonic-gate 			(void) fprintf(fp, gettext("The '%s' resource scope is "
9630Sstevel@tonic-gate 			    "used to configure a file-system.\n"),
9640Sstevel@tonic-gate 			    rt_to_str(resource_scope));
9650Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Valid commands:\n"));
9660Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9670Sstevel@tonic-gate 			    pt_to_str(PT_DIR), gettext("<path>"));
9680Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9690Sstevel@tonic-gate 			    pt_to_str(PT_SPECIAL), gettext("<path>"));
9700Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9710Sstevel@tonic-gate 			    pt_to_str(PT_RAW), gettext("<raw-device>"));
9720Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9730Sstevel@tonic-gate 			    pt_to_str(PT_TYPE), gettext("<file-system type>"));
9740Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s %s\n", cmd_to_str(CMD_ADD),
9750Sstevel@tonic-gate 			    pt_to_str(PT_OPTIONS),
9760Sstevel@tonic-gate 			    gettext("<file-system options>"));
9771645Scomay 			(void) fprintf(fp, "\t%s %s %s\n",
9781645Scomay 			    cmd_to_str(CMD_REMOVE), pt_to_str(PT_OPTIONS),
9791645Scomay 			    gettext("<file-system options>"));
9800Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Consult the file-system "
9810Sstevel@tonic-gate 			    "specific manual page, such as mount_ufs(1M), "
9820Sstevel@tonic-gate 			    "for\ndetails about file-system options.  Note "
9830Sstevel@tonic-gate 			    "that any file-system options with an\nembedded "
9840Sstevel@tonic-gate 			    "'=' character must be enclosed in double quotes, "
9850Sstevel@tonic-gate 			    /*CSTYLED*/
9860Sstevel@tonic-gate 			    "such as \"%s=5\".\n"), MNTOPT_RETRY);
9870Sstevel@tonic-gate 			break;
9880Sstevel@tonic-gate 		case RT_NET:
9890Sstevel@tonic-gate 			(void) fprintf(fp, gettext("The '%s' resource scope is "
9900Sstevel@tonic-gate 			    "used to configure a network interface.\n"),
9910Sstevel@tonic-gate 			    rt_to_str(resource_scope));
9920Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Valid commands:\n"));
9930Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9940Sstevel@tonic-gate 			    pt_to_str(PT_ADDRESS), gettext("<IP-address>"));
9950Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
99612748SSowmini.Varadhan@oracle.COM 			    pt_to_str(PT_ALLOWED_ADDRESS),
99712748SSowmini.Varadhan@oracle.COM 			    gettext("<IP-address>"));
99812748SSowmini.Varadhan@oracle.COM 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9990Sstevel@tonic-gate 			    pt_to_str(PT_PHYSICAL), gettext("<interface>"));
10000Sstevel@tonic-gate 			(void) fprintf(fp, gettext("See ifconfig(1M) for "
10010Sstevel@tonic-gate 			    "details of the <interface> string.\n"));
100212748SSowmini.Varadhan@oracle.COM 			(void) fprintf(fp, gettext("%s %s is valid "
100312748SSowmini.Varadhan@oracle.COM 			    "if the %s property is set to %s, otherwise it "
10046076Sgfaden 			    "must not be set.\n"),
10053448Sdh155122 			    cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS),
100612748SSowmini.Varadhan@oracle.COM 			    pt_to_str(PT_IPTYPE), gettext("shared"));
100712748SSowmini.Varadhan@oracle.COM 			(void) fprintf(fp, gettext("%s %s is valid "
100812748SSowmini.Varadhan@oracle.COM 			    "if the %s property is set to %s, otherwise it "
100912748SSowmini.Varadhan@oracle.COM 			    "must not be set.\n"),
101012748SSowmini.Varadhan@oracle.COM 			    cmd_to_str(CMD_SET), pt_to_str(PT_ALLOWED_ADDRESS),
101112748SSowmini.Varadhan@oracle.COM 			    pt_to_str(PT_IPTYPE), gettext("exclusive"));
101212748SSowmini.Varadhan@oracle.COM 			(void) fprintf(fp, gettext("\t%s %s=%s\n%s %s "
101312748SSowmini.Varadhan@oracle.COM 			    "is valid if the %s or %s property is set, "
101412748SSowmini.Varadhan@oracle.COM 			    "otherwise it must not be set\n"),
101512748SSowmini.Varadhan@oracle.COM 			    cmd_to_str(CMD_SET),
101612748SSowmini.Varadhan@oracle.COM 			    pt_to_str(PT_DEFROUTER), gettext("<IP-address>"),
10176076Sgfaden 			    cmd_to_str(CMD_SET), pt_to_str(PT_DEFROUTER),
101812748SSowmini.Varadhan@oracle.COM 			    gettext(pt_to_str(PT_ADDRESS)),
101912748SSowmini.Varadhan@oracle.COM 			    gettext(pt_to_str(PT_ALLOWED_ADDRESS)));
10200Sstevel@tonic-gate 			break;
10210Sstevel@tonic-gate 		case RT_DEVICE:
10220Sstevel@tonic-gate 			(void) fprintf(fp, gettext("The '%s' resource scope is "
10230Sstevel@tonic-gate 			    "used to configure a device node.\n"),
10240Sstevel@tonic-gate 			    rt_to_str(resource_scope));
10250Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Valid commands:\n"));
10260Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10270Sstevel@tonic-gate 			    pt_to_str(PT_MATCH), gettext("<device-path>"));
10280Sstevel@tonic-gate 			break;
10290Sstevel@tonic-gate 		case RT_RCTL:
10300Sstevel@tonic-gate 			(void) fprintf(fp, gettext("The '%s' resource scope is "
10310Sstevel@tonic-gate 			    "used to configure a resource control.\n"),
10320Sstevel@tonic-gate 			    rt_to_str(resource_scope));
10330Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Valid commands:\n"));
10340Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10350Sstevel@tonic-gate 			    pt_to_str(PT_NAME), gettext("<string>"));
10360Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
10370Sstevel@tonic-gate 			    cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
10380Sstevel@tonic-gate 			    pt_to_str(PT_PRIV), gettext("<priv-value>"),
10390Sstevel@tonic-gate 			    pt_to_str(PT_LIMIT), gettext("<number>"),
10400Sstevel@tonic-gate 			    pt_to_str(PT_ACTION), gettext("<action-value>"));
10411645Scomay 			(void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
10421645Scomay 			    cmd_to_str(CMD_REMOVE), pt_to_str(PT_VALUE),
10431645Scomay 			    pt_to_str(PT_PRIV), gettext("<priv-value>"),
10441645Scomay 			    pt_to_str(PT_LIMIT), gettext("<number>"),
10451645Scomay 			    pt_to_str(PT_ACTION), gettext("<action-value>"));
10460Sstevel@tonic-gate 			(void) fprintf(fp, "%s\n\t%s := privileged\n"
10470Sstevel@tonic-gate 			    "\t%s := none | deny\n", gettext("Where"),
10480Sstevel@tonic-gate 			    gettext("<priv-value>"), gettext("<action-value>"));
10490Sstevel@tonic-gate 			break;
10500Sstevel@tonic-gate 		case RT_ATTR:
10510Sstevel@tonic-gate 			(void) fprintf(fp, gettext("The '%s' resource scope is "
10520Sstevel@tonic-gate 			    "used to configure a generic attribute.\n"),
10530Sstevel@tonic-gate 			    rt_to_str(resource_scope));
10540Sstevel@tonic-gate 			(void) fprintf(fp, gettext("Valid commands:\n"));
10550Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10560Sstevel@tonic-gate 			    pt_to_str(PT_NAME), gettext("<name>"));
10570Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=boolean\n",
10580Sstevel@tonic-gate 			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
10590Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=true | false\n",
10600Sstevel@tonic-gate 			    cmd_to_str(CMD_SET), pt_to_str(PT_VALUE));
10610Sstevel@tonic-gate 			(void) fprintf(fp, gettext("or\n"));
10620Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=int\n", cmd_to_str(CMD_SET),
10630Sstevel@tonic-gate 			    pt_to_str(PT_TYPE));
10640Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10650Sstevel@tonic-gate 			    pt_to_str(PT_VALUE), gettext("<integer>"));
10660Sstevel@tonic-gate 			(void) fprintf(fp, gettext("or\n"));
10670Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=string\n",
10680Sstevel@tonic-gate 			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
10690Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10700Sstevel@tonic-gate 			    pt_to_str(PT_VALUE), gettext("<string>"));
10710Sstevel@tonic-gate 			(void) fprintf(fp, gettext("or\n"));
10720Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=uint\n",
10730Sstevel@tonic-gate 			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
10740Sstevel@tonic-gate 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10750Sstevel@tonic-gate 			    pt_to_str(PT_VALUE), gettext("<unsigned integer>"));
10760Sstevel@tonic-gate 			break;
1077789Sahrens 		case RT_DATASET:
1078789Sahrens 			(void) fprintf(fp, gettext("The '%s' resource scope is "
1079789Sahrens 			    "used to export ZFS datasets.\n"),
1080789Sahrens 			    rt_to_str(resource_scope));
1081789Sahrens 			(void) fprintf(fp, gettext("Valid commands:\n"));
1082789Sahrens 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1083789Sahrens 			    pt_to_str(PT_NAME), gettext("<name>"));
1084789Sahrens 			break;
10853247Sgjelinek 		case RT_DCPU:
10863247Sgjelinek 			(void) fprintf(fp, gettext("The '%s' resource scope "
10873247Sgjelinek 			    "configures the 'pools' facility to dedicate\na "
10883247Sgjelinek 			    "subset of the system's processors to this zone "
10893247Sgjelinek 			    "while it is running.\n"),
10903247Sgjelinek 			    rt_to_str(resource_scope));
10913247Sgjelinek 			(void) fprintf(fp, gettext("Valid commands:\n"));
10923247Sgjelinek 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10933247Sgjelinek 			    pt_to_str(PT_NCPUS),
10943247Sgjelinek 			    gettext("<unsigned integer | range>"));
10953247Sgjelinek 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10963247Sgjelinek 			    pt_to_str(PT_IMPORTANCE),
10973247Sgjelinek 			    gettext("<unsigned integer>"));
10983247Sgjelinek 			break;
10993792Sakolb 		case RT_PCAP:
11003792Sakolb 			(void) fprintf(fp, gettext("The '%s' resource scope is "
11013792Sakolb 			    "used to set an upper limit (a cap) on the\n"
11023792Sakolb 			    "percentage of CPU that can be used by this zone.  "
11033792Sakolb 			    "A '%s' value of 1\ncorresponds to one cpu.  The "
11043792Sakolb 			    "value can be set higher than 1, up to the total\n"
11053792Sakolb 			    "number of CPUs on the system.  The value can "
11063792Sakolb 			    "also be less than 1,\nrepresenting a fraction of "
11073792Sakolb 			    "a cpu.\n"),
11083792Sakolb 			    rt_to_str(resource_scope), pt_to_str(PT_NCPUS));
11093792Sakolb 			(void) fprintf(fp, gettext("Valid commands:\n"));
11103792Sakolb 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11113792Sakolb 			    pt_to_str(PT_NCPUS), gettext("<unsigned decimal>"));
11123792Sakolb 			break;
11133247Sgjelinek 		case RT_MCAP:
11143247Sgjelinek 			(void) fprintf(fp, gettext("The '%s' resource scope is "
11153247Sgjelinek 			    "used to set an upper limit (a cap) on the\n"
11163247Sgjelinek 			    "amount of physical memory, swap space and locked "
11173247Sgjelinek 			    "memory that can be used by\nthis zone.\n"),
11183247Sgjelinek 			    rt_to_str(resource_scope));
11193247Sgjelinek 			(void) fprintf(fp, gettext("Valid commands:\n"));
11203247Sgjelinek 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11213247Sgjelinek 			    pt_to_str(PT_PHYSICAL),
11223247Sgjelinek 			    gettext("<qualified unsigned decimal>"));
11233247Sgjelinek 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11243247Sgjelinek 			    pt_to_str(PT_SWAP),
11253247Sgjelinek 			    gettext("<qualified unsigned decimal>"));
11263247Sgjelinek 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11273247Sgjelinek 			    pt_to_str(PT_LOCKED),
11283247Sgjelinek 			    gettext("<qualified unsigned decimal>"));
11293247Sgjelinek 			break;
113012578SGlenn.Faden@Sun.COM 		case RT_ADMIN:
113112578SGlenn.Faden@Sun.COM 			(void) fprintf(fp, gettext("The '%s' resource scope is "
113212578SGlenn.Faden@Sun.COM 			    "used to delegate specific zone management\n"
113312578SGlenn.Faden@Sun.COM 			    "rights to users and roles. These rights are "
113412578SGlenn.Faden@Sun.COM 			    "only applicable to this zone.\n"),
113512578SGlenn.Faden@Sun.COM 			    rt_to_str(resource_scope));
113612578SGlenn.Faden@Sun.COM 			(void) fprintf(fp, gettext("Valid commands:\n"));
113712578SGlenn.Faden@Sun.COM 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
113812578SGlenn.Faden@Sun.COM 			    pt_to_str(PT_USER),
113912578SGlenn.Faden@Sun.COM 			    gettext("<single user or role name>"));
114012578SGlenn.Faden@Sun.COM 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
114112578SGlenn.Faden@Sun.COM 			    pt_to_str(PT_AUTHS),
114212578SGlenn.Faden@Sun.COM 			    gettext("<comma separated list>"));
114312578SGlenn.Faden@Sun.COM 			break;
11440Sstevel@tonic-gate 		}
11450Sstevel@tonic-gate 		(void) fprintf(fp, gettext("And from any resource scope, you "
11460Sstevel@tonic-gate 		    "can:\n"));
11470Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
11480Sstevel@tonic-gate 		    gettext("(to conclude this operation)"));
11490Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
11500Sstevel@tonic-gate 		    gettext("(to cancel this operation)"));
11510Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
11520Sstevel@tonic-gate 		    gettext("(to exit the zonecfg utility)"));
11530Sstevel@tonic-gate 	}
11540Sstevel@tonic-gate 	if (flags & HELP_USAGE) {
11550Sstevel@tonic-gate 		(void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
11560Sstevel@tonic-gate 		    execname, cmd_to_str(CMD_HELP));
11570Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
11580Sstevel@tonic-gate 		    execname, gettext("interactive"));
11590Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
11600Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
11610Sstevel@tonic-gate 		    execname);
11620Sstevel@tonic-gate 	}
11630Sstevel@tonic-gate 	if (flags & HELP_SUBCMDS) {
11640Sstevel@tonic-gate 		(void) fprintf(fp, "%s:\n\n", gettext("Commands"));
11650Sstevel@tonic-gate 		for (i = 0; i <= CMD_MAX; i++) {
11660Sstevel@tonic-gate 			(void) fprintf(fp, "%s\n", helptab[i].short_usage);
11670Sstevel@tonic-gate 			if (verbose)
11680Sstevel@tonic-gate 				(void) fprintf(fp, "\t%s\n\n", long_help(i));
11690Sstevel@tonic-gate 		}
11700Sstevel@tonic-gate 	}
11710Sstevel@tonic-gate 	if (flags & HELP_SYNTAX) {
11720Sstevel@tonic-gate 		if (!verbose)
11730Sstevel@tonic-gate 			(void) fprintf(fp, "\n");
11740Sstevel@tonic-gate 		(void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
11750Sstevel@tonic-gate 		(void) fprintf(fp, gettext("\t(except the reserved words "
11760Sstevel@tonic-gate 		    "'%s' and anything starting with '%s')\n"), "global",
11770Sstevel@tonic-gate 		    "SUNW");
11780Sstevel@tonic-gate 		(void) fprintf(fp,
11790Sstevel@tonic-gate 		    gettext("\tName must be less than %d characters.\n"),
11800Sstevel@tonic-gate 		    ZONENAME_MAX);
11810Sstevel@tonic-gate 		if (verbose)
11820Sstevel@tonic-gate 			(void) fprintf(fp, "\n");
11830Sstevel@tonic-gate 	}
11840Sstevel@tonic-gate 	if (flags & HELP_NETADDR) {
11850Sstevel@tonic-gate 		(void) fprintf(fp, gettext("\n<net-addr> :="));
11860Sstevel@tonic-gate 		(void) fprintf(fp,
11870Sstevel@tonic-gate 		    gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n"));
11880Sstevel@tonic-gate 		(void) fprintf(fp,
11890Sstevel@tonic-gate 		    gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
11900Sstevel@tonic-gate 		(void) fprintf(fp,
11910Sstevel@tonic-gate 		    gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
11920Sstevel@tonic-gate 		(void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and "
11930Sstevel@tonic-gate 		    "IPv6 address syntax.\n"));
11940Sstevel@tonic-gate 		(void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n"));
11950Sstevel@tonic-gate 		(void) fprintf(fp,
11960Sstevel@tonic-gate 		    gettext("<IPv6-prefix-length> := [0-128]\n"));
11970Sstevel@tonic-gate 		(void) fprintf(fp,
11980Sstevel@tonic-gate 		    gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
11990Sstevel@tonic-gate 	}
12000Sstevel@tonic-gate 	if (flags & HELP_RESOURCES) {
120112734Sgary.pennington@oracle.com 		(void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s |\n\t"
120212578SGlenn.Faden@Sun.COM 		    "%s | %s | %s | %s | %s\n\n",
12030Sstevel@tonic-gate 		    gettext("resource type"), rt_to_str(RT_FS),
120412734Sgary.pennington@oracle.com 		    rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
12052607Sdp 		    rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
12063247Sgjelinek 		    rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
120712578SGlenn.Faden@Sun.COM 		    rt_to_str(RT_PCAP), rt_to_str(RT_MCAP),
120812578SGlenn.Faden@Sun.COM 		    rt_to_str(RT_ADMIN));
12090Sstevel@tonic-gate 	}
12100Sstevel@tonic-gate 	if (flags & HELP_PROPS) {
12110Sstevel@tonic-gate 		(void) fprintf(fp, gettext("For resource type ... there are "
12120Sstevel@tonic-gate 		    "property types ...:\n"));
12130Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1214565Sdp 		    pt_to_str(PT_ZONENAME));
1215565Sdp 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12160Sstevel@tonic-gate 		    pt_to_str(PT_ZONEPATH));
12170Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12182712Snn35248 		    pt_to_str(PT_BRAND));
12192712Snn35248 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12200Sstevel@tonic-gate 		    pt_to_str(PT_AUTOBOOT));
12210Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12222267Sdp 		    pt_to_str(PT_BOOTARGS));
12232267Sdp 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12240Sstevel@tonic-gate 		    pt_to_str(PT_POOL));
12251645Scomay 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12261645Scomay 		    pt_to_str(PT_LIMITPRIV));
12273247Sgjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12283247Sgjelinek 		    pt_to_str(PT_SCHED));
12293247Sgjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12303448Sdh155122 		    pt_to_str(PT_IPTYPE));
12313448Sdh155122 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12328662SJordan.Vaughan@Sun.com 		    pt_to_str(PT_HOSTID));
12338662SJordan.Vaughan@Sun.com 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
123412633Sjohn.levon@sun.com 		    pt_to_str(PT_FS_ALLOWED));
123512633Sjohn.levon@sun.com 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12363247Sgjelinek 		    pt_to_str(PT_MAXLWPS));
12373247Sgjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
123812725SMenno.Lageman@Sun.COM 		    pt_to_str(PT_MAXPROCS));
123912725SMenno.Lageman@Sun.COM 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12403247Sgjelinek 		    pt_to_str(PT_MAXSHMMEM));
12413247Sgjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12423247Sgjelinek 		    pt_to_str(PT_MAXSHMIDS));
12433247Sgjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12443247Sgjelinek 		    pt_to_str(PT_MAXMSGIDS));
12453247Sgjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12463247Sgjelinek 		    pt_to_str(PT_MAXSEMIDS));
12473247Sgjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12483247Sgjelinek 		    pt_to_str(PT_SHARES));
124912227SFrank.Batschulat@Sun.COM 		(void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s\n",
125012227SFrank.Batschulat@Sun.COM 		    rt_to_str(RT_FS), pt_to_str(PT_DIR),
125112227SFrank.Batschulat@Sun.COM 		    pt_to_str(PT_SPECIAL), pt_to_str(PT_RAW),
125212227SFrank.Batschulat@Sun.COM 		    pt_to_str(PT_TYPE), pt_to_str(PT_OPTIONS));
125312748SSowmini.Varadhan@oracle.COM 		(void) fprintf(fp, "\t%s\t\t%s, %s, %s|%s\n", rt_to_str(RT_NET),
125412748SSowmini.Varadhan@oracle.COM 		    pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
125512748SSowmini.Varadhan@oracle.COM 		    pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
12560Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
12570Sstevel@tonic-gate 		    pt_to_str(PT_MATCH));
12580Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
12590Sstevel@tonic-gate 		    pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
12600Sstevel@tonic-gate 		(void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
12610Sstevel@tonic-gate 		    pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
12620Sstevel@tonic-gate 		    pt_to_str(PT_VALUE));
1263789Sahrens 		(void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1264789Sahrens 		    pt_to_str(PT_NAME));
12653247Sgjelinek 		(void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
12663247Sgjelinek 		    pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
12673792Sakolb 		(void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
12683792Sakolb 		    pt_to_str(PT_NCPUS));
12693247Sgjelinek 		(void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
12703247Sgjelinek 		    pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
12713247Sgjelinek 		    pt_to_str(PT_LOCKED));
127212578SGlenn.Faden@Sun.COM 		(void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
127312578SGlenn.Faden@Sun.COM 		    pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
12740Sstevel@tonic-gate 	}
12750Sstevel@tonic-gate 	if (need_to_close)
12760Sstevel@tonic-gate 		(void) pclose(fp);
12770Sstevel@tonic-gate }
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate static void
zone_perror(char * prefix,int err,boolean_t set_saw)12806215Sgjelinek zone_perror(char *prefix, int err, boolean_t set_saw)
12810Sstevel@tonic-gate {
12820Sstevel@tonic-gate 	zerr("%s: %s", prefix, zonecfg_strerror(err));
12830Sstevel@tonic-gate 	if (set_saw)
12846215Sgjelinek 		saw_error = B_TRUE;
12850Sstevel@tonic-gate }
12860Sstevel@tonic-gate 
12870Sstevel@tonic-gate /*
12880Sstevel@tonic-gate  * zone_perror() expects a single string, but for remove and select
12890Sstevel@tonic-gate  * we have both the command and the resource type, so this wrapper
12900Sstevel@tonic-gate  * function serves the same purpose in a slightly different way.
12910Sstevel@tonic-gate  */
12920Sstevel@tonic-gate 
12930Sstevel@tonic-gate static void
z_cmd_rt_perror(int cmd_num,int res_num,int err,boolean_t set_saw)12946215Sgjelinek z_cmd_rt_perror(int cmd_num, int res_num, int err, boolean_t set_saw)
12950Sstevel@tonic-gate {
12960Sstevel@tonic-gate 	zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num),
12970Sstevel@tonic-gate 	    zonecfg_strerror(err));
12980Sstevel@tonic-gate 	if (set_saw)
12996215Sgjelinek 		saw_error = B_TRUE;
13000Sstevel@tonic-gate }
13010Sstevel@tonic-gate 
13020Sstevel@tonic-gate /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
13030Sstevel@tonic-gate static int
initialize(boolean_t handle_expected)13046215Sgjelinek initialize(boolean_t handle_expected)
13050Sstevel@tonic-gate {
13060Sstevel@tonic-gate 	int err;
13072712Snn35248 	char brandname[MAXNAMELEN];
13080Sstevel@tonic-gate 
13090Sstevel@tonic-gate 	if (zonecfg_check_handle(handle) != Z_OK) {
13100Sstevel@tonic-gate 		if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) {
13116215Sgjelinek 			got_handle = B_TRUE;
13122712Snn35248 			if (zonecfg_get_brand(handle, brandname,
13132712Snn35248 			    sizeof (brandname)) != Z_OK) {
13142712Snn35248 				zerr("Zone %s is inconsistent: missing "
13152712Snn35248 				    "brand attribute", zone);
13162712Snn35248 				exit(Z_ERR);
13172712Snn35248 			}
13182712Snn35248 			if ((brand = brand_open(brandname)) == NULL) {
13192712Snn35248 				zerr("Zone %s uses non-existent brand \"%s\"."
13202712Snn35248 				    "  Unable to continue", zone, brandname);
13212712Snn35248 				exit(Z_ERR);
13222712Snn35248 			}
132312578SGlenn.Faden@Sun.COM 			/*
132412578SGlenn.Faden@Sun.COM 			 * If the user_attr file is newer than
132512578SGlenn.Faden@Sun.COM 			 * the zone config file, the admins
132612578SGlenn.Faden@Sun.COM 			 * may need to be updated since the
132712578SGlenn.Faden@Sun.COM 			 * RBAC files are authoritative for
132812578SGlenn.Faden@Sun.COM 			 * authorization checks.
132912578SGlenn.Faden@Sun.COM 			 */
133012578SGlenn.Faden@Sun.COM 			err = zonecfg_update_userauths(handle, zone);
133112578SGlenn.Faden@Sun.COM 			if (err == Z_OK) {
133212578SGlenn.Faden@Sun.COM 				zerr(gettext("The administrative rights "
133312578SGlenn.Faden@Sun.COM 				    "were updated to match "
133412578SGlenn.Faden@Sun.COM 				    "the current RBAC configuration.\n"
133512578SGlenn.Faden@Sun.COM 				    "Use \"info admin\" and \"revert\" to "
133612578SGlenn.Faden@Sun.COM 				    "compare with the previous settings."));
133712578SGlenn.Faden@Sun.COM 				need_to_commit = B_TRUE;
133812578SGlenn.Faden@Sun.COM 			} else if (err != Z_NO_ENTRY) {
133912578SGlenn.Faden@Sun.COM 				zerr(gettext("failed to update "
134012578SGlenn.Faden@Sun.COM 				    "admin  rights."));
134112578SGlenn.Faden@Sun.COM 				exit(Z_ERR);
134212578SGlenn.Faden@Sun.COM 			} else if (need_to_commit) {
134312578SGlenn.Faden@Sun.COM 				zerr(gettext("admin rights were updated "
134412578SGlenn.Faden@Sun.COM 				    "to match RBAC configuration."));
134512578SGlenn.Faden@Sun.COM 			}
134612578SGlenn.Faden@Sun.COM 
13473247Sgjelinek 		} else if (global_zone && err == Z_NO_ZONE && !got_handle &&
13483247Sgjelinek 		    !read_only_mode) {
13493247Sgjelinek 			/*
13503247Sgjelinek 			 * We implicitly create the global zone config if it
13513247Sgjelinek 			 * doesn't exist.
13523247Sgjelinek 			 */
13533247Sgjelinek 			zone_dochandle_t tmphandle;
13543247Sgjelinek 
13553247Sgjelinek 			if ((tmphandle = zonecfg_init_handle()) == NULL) {
13566215Sgjelinek 				zone_perror(execname, Z_NOMEM, B_TRUE);
13573247Sgjelinek 				exit(Z_ERR);
13583247Sgjelinek 			}
13593247Sgjelinek 
13603247Sgjelinek 			err = zonecfg_get_template_handle("SUNWblank", zone,
13613247Sgjelinek 			    tmphandle);
13623247Sgjelinek 
13633247Sgjelinek 			if (err != Z_OK) {
13643247Sgjelinek 				zonecfg_fini_handle(tmphandle);
13656215Sgjelinek 				zone_perror("SUNWblank", err, B_TRUE);
13663247Sgjelinek 				return (err);
13673247Sgjelinek 			}
13683247Sgjelinek 
13696215Sgjelinek 			need_to_commit = B_TRUE;
13703247Sgjelinek 			zonecfg_fini_handle(handle);
13713247Sgjelinek 			handle = tmphandle;
13726215Sgjelinek 			got_handle = B_TRUE;
13733247Sgjelinek 
13740Sstevel@tonic-gate 		} else {
13750Sstevel@tonic-gate 			zone_perror(zone, err, handle_expected || got_handle);
13760Sstevel@tonic-gate 			if (err == Z_NO_ZONE && !got_handle &&
13770Sstevel@tonic-gate 			    interactive_mode && !read_only_mode)
13780Sstevel@tonic-gate 				(void) printf(gettext("Use '%s' to begin "
13790Sstevel@tonic-gate 				    "configuring a new zone.\n"),
13800Sstevel@tonic-gate 				    cmd_to_str(CMD_CREATE));
13810Sstevel@tonic-gate 			return (err);
13820Sstevel@tonic-gate 		}
13830Sstevel@tonic-gate 	}
13840Sstevel@tonic-gate 	return (Z_OK);
13850Sstevel@tonic-gate }
13860Sstevel@tonic-gate 
13876215Sgjelinek static boolean_t
state_atleast(zone_state_t state)1388565Sdp state_atleast(zone_state_t state)
1389565Sdp {
1390565Sdp 	zone_state_t state_num;
1391565Sdp 	int err;
1392565Sdp 
1393565Sdp 	if ((err = zone_get_state(zone, &state_num)) != Z_OK) {
1394565Sdp 		/* all states are greater than "non-existent" */
1395565Sdp 		if (err == Z_NO_ZONE)
1396565Sdp 			return (B_FALSE);
1397565Sdp 		zerr(gettext("Unexpectedly failed to determine state "
1398565Sdp 		    "of zone %s: %s"), zone, zonecfg_strerror(err));
1399565Sdp 		exit(Z_ERR);
1400565Sdp 	}
1401565Sdp 	return (state_num >= state);
1402565Sdp }
1403565Sdp 
14040Sstevel@tonic-gate /*
14050Sstevel@tonic-gate  * short_usage() is for bad syntax: getopt() issues, too many arguments, etc.
14060Sstevel@tonic-gate  */
14070Sstevel@tonic-gate 
14080Sstevel@tonic-gate void
short_usage(int command)14090Sstevel@tonic-gate short_usage(int command)
14100Sstevel@tonic-gate {
14110Sstevel@tonic-gate 	/* lex_lineno has already been incremented in the lexer; compensate */
14120Sstevel@tonic-gate 	if (cmd_file_mode) {
14130Sstevel@tonic-gate 		if (strcmp(cmd_file_name, "-") == 0)
14140Sstevel@tonic-gate 			(void) fprintf(stderr,
14150Sstevel@tonic-gate 			    gettext("syntax error on line %d\n"),
14160Sstevel@tonic-gate 			    lex_lineno - 1);
14170Sstevel@tonic-gate 		else
14180Sstevel@tonic-gate 			(void) fprintf(stderr,
14190Sstevel@tonic-gate 			    gettext("syntax error on line %d of %s\n"),
14200Sstevel@tonic-gate 			    lex_lineno - 1, cmd_file_name);
14210Sstevel@tonic-gate 	}
14220Sstevel@tonic-gate 	(void) fprintf(stderr, "%s:\n%s\n", gettext("usage"),
14230Sstevel@tonic-gate 	    helptab[command].short_usage);
14246215Sgjelinek 	saw_error = B_TRUE;
14250Sstevel@tonic-gate }
14260Sstevel@tonic-gate 
14270Sstevel@tonic-gate /*
14280Sstevel@tonic-gate  * long_usage() is for bad semantics: e.g., wrong property type for a given
14290Sstevel@tonic-gate  * resource type.  It is also used by longer_usage() below.
14300Sstevel@tonic-gate  */
14310Sstevel@tonic-gate 
14320Sstevel@tonic-gate void
long_usage(uint_t cmd_num,boolean_t set_saw)14336215Sgjelinek long_usage(uint_t cmd_num, boolean_t set_saw)
14340Sstevel@tonic-gate {
14350Sstevel@tonic-gate 	(void) fprintf(set_saw ? stderr : stdout, "%s:\n%s\n", gettext("usage"),
14360Sstevel@tonic-gate 	    helptab[cmd_num].short_usage);
14370Sstevel@tonic-gate 	(void) fprintf(set_saw ? stderr : stdout, "\t%s\n", long_help(cmd_num));
14380Sstevel@tonic-gate 	if (set_saw)
14396215Sgjelinek 		saw_error = B_TRUE;
14400Sstevel@tonic-gate }
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate /*
14430Sstevel@tonic-gate  * longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also
14440Sstevel@tonic-gate  * any extra usage() flags as appropriate for whatever command.
14450Sstevel@tonic-gate  */
14460Sstevel@tonic-gate 
14470Sstevel@tonic-gate void
longer_usage(uint_t cmd_num)14480Sstevel@tonic-gate longer_usage(uint_t cmd_num)
14490Sstevel@tonic-gate {
14506215Sgjelinek 	long_usage(cmd_num, B_FALSE);
14510Sstevel@tonic-gate 	if (helptab[cmd_num].flags != 0) {
14520Sstevel@tonic-gate 		(void) printf("\n");
14536215Sgjelinek 		usage(B_TRUE, helptab[cmd_num].flags);
14540Sstevel@tonic-gate 	}
14550Sstevel@tonic-gate }
14560Sstevel@tonic-gate 
14570Sstevel@tonic-gate /*
14580Sstevel@tonic-gate  * scope_usage() is simply used when a command is called from the wrong scope.
14590Sstevel@tonic-gate  */
14600Sstevel@tonic-gate 
14610Sstevel@tonic-gate static void
scope_usage(uint_t cmd_num)14620Sstevel@tonic-gate scope_usage(uint_t cmd_num)
14630Sstevel@tonic-gate {
14640Sstevel@tonic-gate 	zerr(gettext("The %s command only makes sense in the %s scope."),
14650Sstevel@tonic-gate 	    cmd_to_str(cmd_num),
14660Sstevel@tonic-gate 	    global_scope ?  gettext("resource") : gettext("global"));
14676215Sgjelinek 	saw_error = B_TRUE;
14680Sstevel@tonic-gate }
14690Sstevel@tonic-gate 
14700Sstevel@tonic-gate /*
14716215Sgjelinek  * On input, B_TRUE => yes, B_FALSE => no.
14726215Sgjelinek  * On return, B_TRUE => 1, B_FALSE => no, could not ask => -1.
14730Sstevel@tonic-gate  */
14740Sstevel@tonic-gate 
14750Sstevel@tonic-gate static int
ask_yesno(boolean_t default_answer,const char * question)14766215Sgjelinek ask_yesno(boolean_t default_answer, const char *question)
14770Sstevel@tonic-gate {
14780Sstevel@tonic-gate 	char line[64];	/* should be enough to answer yes or no */
14790Sstevel@tonic-gate 
14800Sstevel@tonic-gate 	if (!ok_to_prompt) {
14816215Sgjelinek 		saw_error = B_TRUE;
14820Sstevel@tonic-gate 		return (-1);
14830Sstevel@tonic-gate 	}
14840Sstevel@tonic-gate 	for (;;) {
1485565Sdp 		if (printf("%s (%s)? ", question,
1486565Sdp 		    default_answer ? "[y]/n" : "y/[n]") < 0)
1487565Sdp 			return (-1);
1488565Sdp 		if (fgets(line, sizeof (line), stdin) == NULL)
1489565Sdp 			return (-1);
1490565Sdp 
1491565Sdp 		if (line[0] == '\n')
14920Sstevel@tonic-gate 			return (default_answer ? 1 : 0);
14930Sstevel@tonic-gate 		if (tolower(line[0]) == 'y')
14940Sstevel@tonic-gate 			return (1);
14950Sstevel@tonic-gate 		if (tolower(line[0]) == 'n')
14960Sstevel@tonic-gate 			return (0);
14970Sstevel@tonic-gate 	}
14980Sstevel@tonic-gate }
14990Sstevel@tonic-gate 
15000Sstevel@tonic-gate /*
15010Sstevel@tonic-gate  * Prints warning if zone already exists.
15020Sstevel@tonic-gate  * In interactive mode, prompts if we should continue anyway and returns Z_OK
15030Sstevel@tonic-gate  * if so, Z_ERR if not.  In non-interactive mode, exits with Z_ERR.
15040Sstevel@tonic-gate  *
15050Sstevel@tonic-gate  * Note that if a zone exists and its state is >= INSTALLED, an error message
15060Sstevel@tonic-gate  * will be printed and this function will return Z_ERR regardless of mode.
15070Sstevel@tonic-gate  */
15080Sstevel@tonic-gate 
15090Sstevel@tonic-gate static int
check_if_zone_already_exists(boolean_t force)15106215Sgjelinek check_if_zone_already_exists(boolean_t force)
15110Sstevel@tonic-gate {
15120Sstevel@tonic-gate 	char line[ZONENAME_MAX + 128];	/* enough to ask a question */
15130Sstevel@tonic-gate 	zone_dochandle_t tmphandle;
15140Sstevel@tonic-gate 	int res, answer;
15150Sstevel@tonic-gate 
15160Sstevel@tonic-gate 	if ((tmphandle = zonecfg_init_handle()) == NULL) {
15176215Sgjelinek 		zone_perror(execname, Z_NOMEM, B_TRUE);
15180Sstevel@tonic-gate 		exit(Z_ERR);
15190Sstevel@tonic-gate 	}
15200Sstevel@tonic-gate 	res = zonecfg_get_handle(zone, tmphandle);
15210Sstevel@tonic-gate 	zonecfg_fini_handle(tmphandle);
1522565Sdp 	if (res != Z_OK)
15230Sstevel@tonic-gate 		return (Z_OK);
1524565Sdp 
1525565Sdp 	if (state_atleast(ZONE_STATE_INSTALLED)) {
15260Sstevel@tonic-gate 		zerr(gettext("Zone %s already installed; %s not allowed."),
15270Sstevel@tonic-gate 		    zone, cmd_to_str(CMD_CREATE));
15280Sstevel@tonic-gate 		return (Z_ERR);
15290Sstevel@tonic-gate 	}
15300Sstevel@tonic-gate 
15310Sstevel@tonic-gate 	if (force) {
15320Sstevel@tonic-gate 		(void) printf(gettext("Zone %s already exists; overwriting.\n"),
15330Sstevel@tonic-gate 		    zone);
15340Sstevel@tonic-gate 		return (Z_OK);
15350Sstevel@tonic-gate 	}
15360Sstevel@tonic-gate 	(void) snprintf(line, sizeof (line),
15370Sstevel@tonic-gate 	    gettext("Zone %s already exists; %s anyway"), zone,
15380Sstevel@tonic-gate 	    cmd_to_str(CMD_CREATE));
15396215Sgjelinek 	if ((answer = ask_yesno(B_FALSE, line)) == -1) {
15400Sstevel@tonic-gate 		zerr(gettext("Zone exists, input not from terminal and -F not "
15410Sstevel@tonic-gate 		    "specified:\n%s command ignored, exiting."),
15420Sstevel@tonic-gate 		    cmd_to_str(CMD_CREATE));
15430Sstevel@tonic-gate 		exit(Z_ERR);
15440Sstevel@tonic-gate 	}
15450Sstevel@tonic-gate 	return (answer == 1 ? Z_OK : Z_ERR);
15460Sstevel@tonic-gate }
15470Sstevel@tonic-gate 
15486215Sgjelinek static boolean_t
zone_is_read_only(int cmd_num)15490Sstevel@tonic-gate zone_is_read_only(int cmd_num)
15500Sstevel@tonic-gate {
15510Sstevel@tonic-gate 	if (strncmp(zone, "SUNW", 4) == 0) {
15520Sstevel@tonic-gate 		zerr(gettext("%s: zones beginning with SUNW are read-only."),
15530Sstevel@tonic-gate 		    zone);
15546215Sgjelinek 		saw_error = B_TRUE;
15556215Sgjelinek 		return (B_TRUE);
15560Sstevel@tonic-gate 	}
15570Sstevel@tonic-gate 	if (read_only_mode) {
15580Sstevel@tonic-gate 		zerr(gettext("%s: cannot %s in read-only mode."), zone,
15590Sstevel@tonic-gate 		    cmd_to_str(cmd_num));
15606215Sgjelinek 		saw_error = B_TRUE;
15616215Sgjelinek 		return (B_TRUE);
15626215Sgjelinek 	}
15636215Sgjelinek 	return (B_FALSE);
15640Sstevel@tonic-gate }
15650Sstevel@tonic-gate 
15660Sstevel@tonic-gate /*
15670Sstevel@tonic-gate  * Create a new configuration.
15680Sstevel@tonic-gate  */
15690Sstevel@tonic-gate void
create_func(cmd_t * cmd)15700Sstevel@tonic-gate create_func(cmd_t *cmd)
15710Sstevel@tonic-gate {
15720Sstevel@tonic-gate 	int err, arg;
15730Sstevel@tonic-gate 	char zone_template[ZONENAME_MAX];
15741507Sgjelinek 	char attach_path[MAXPATHLEN];
15750Sstevel@tonic-gate 	zone_dochandle_t tmphandle;
15766215Sgjelinek 	boolean_t force = B_FALSE;
15776215Sgjelinek 	boolean_t attach = B_FALSE;
15786215Sgjelinek 	boolean_t arg_err = B_FALSE;
15790Sstevel@tonic-gate 
15800Sstevel@tonic-gate 	assert(cmd != NULL);
15810Sstevel@tonic-gate 
15820Sstevel@tonic-gate 	/* This is the default if no arguments are given. */
15830Sstevel@tonic-gate 	(void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template));
15840Sstevel@tonic-gate 
15850Sstevel@tonic-gate 	optind = 0;
15862712Snn35248 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:"))
15872712Snn35248 	    != EOF) {
15880Sstevel@tonic-gate 		switch (arg) {
15890Sstevel@tonic-gate 		case '?':
15900Sstevel@tonic-gate 			if (optopt == '?')
15910Sstevel@tonic-gate 				longer_usage(CMD_CREATE);
15920Sstevel@tonic-gate 			else
15930Sstevel@tonic-gate 				short_usage(CMD_CREATE);
15946215Sgjelinek 			arg_err = B_TRUE;
15953691Sgjelinek 			break;
15961507Sgjelinek 		case 'a':
15971507Sgjelinek 			(void) strlcpy(attach_path, optarg,
15981507Sgjelinek 			    sizeof (attach_path));
15996215Sgjelinek 			attach = B_TRUE;
16001507Sgjelinek 			break;
16010Sstevel@tonic-gate 		case 'b':
16020Sstevel@tonic-gate 			(void) strlcpy(zone_template, "SUNWblank",
16030Sstevel@tonic-gate 			    sizeof (zone_template));
16040Sstevel@tonic-gate 			break;
16050Sstevel@tonic-gate 		case 'F':
16066215Sgjelinek 			force = B_TRUE;
16070Sstevel@tonic-gate 			break;
16080Sstevel@tonic-gate 		case 't':
16090Sstevel@tonic-gate 			(void) strlcpy(zone_template, optarg,
16100Sstevel@tonic-gate 			    sizeof (zone_template));
16110Sstevel@tonic-gate 			break;
16120Sstevel@tonic-gate 		default:
16130Sstevel@tonic-gate 			short_usage(CMD_CREATE);
16146215Sgjelinek 			arg_err = B_TRUE;
16153691Sgjelinek 			break;
16163691Sgjelinek 		}
16173691Sgjelinek 	}
16183691Sgjelinek 	if (arg_err)
16193691Sgjelinek 		return;
16203691Sgjelinek 
16210Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
16220Sstevel@tonic-gate 		short_usage(CMD_CREATE);
16230Sstevel@tonic-gate 		return;
16240Sstevel@tonic-gate 	}
16250Sstevel@tonic-gate 
16260Sstevel@tonic-gate 	if (zone_is_read_only(CMD_CREATE))
16270Sstevel@tonic-gate 		return;
16280Sstevel@tonic-gate 
16290Sstevel@tonic-gate 	if (check_if_zone_already_exists(force) != Z_OK)
16300Sstevel@tonic-gate 		return;
16310Sstevel@tonic-gate 
16320Sstevel@tonic-gate 	/*
16330Sstevel@tonic-gate 	 * Get a temporary handle first.  If that fails, the old handle
16340Sstevel@tonic-gate 	 * will not be lost.  Then finish whichever one we don't need,
16350Sstevel@tonic-gate 	 * to avoid leaks.  Then get the handle for zone_template, and
16360Sstevel@tonic-gate 	 * set the name to zone: this "copy, rename" method is how
16370Sstevel@tonic-gate 	 * create -[b|t] works.
16380Sstevel@tonic-gate 	 */
16390Sstevel@tonic-gate 	if ((tmphandle = zonecfg_init_handle()) == NULL) {
16406215Sgjelinek 		zone_perror(execname, Z_NOMEM, B_TRUE);
16410Sstevel@tonic-gate 		exit(Z_ERR);
16420Sstevel@tonic-gate 	}
16431507Sgjelinek 
16441507Sgjelinek 	if (attach)
16457257Sgjelinek 		err = zonecfg_get_attach_handle(attach_path, ZONE_DETACHED,
16467257Sgjelinek 		    zone, B_FALSE, tmphandle);
16471507Sgjelinek 	else
16481507Sgjelinek 		err = zonecfg_get_template_handle(zone_template, zone,
16491507Sgjelinek 		    tmphandle);
16501507Sgjelinek 
16511507Sgjelinek 	if (err != Z_OK) {
16520Sstevel@tonic-gate 		zonecfg_fini_handle(tmphandle);
16531507Sgjelinek 		if (attach && err == Z_NO_ZONE)
16541507Sgjelinek 			(void) fprintf(stderr, gettext("invalid path to "
16551507Sgjelinek 			    "detached zone\n"));
16561507Sgjelinek 		else if (attach && err == Z_INVALID_DOCUMENT)
16571507Sgjelinek 			(void) fprintf(stderr, gettext("Cannot attach to an "
16581507Sgjelinek 			    "earlier release of the operating system\n"));
16591507Sgjelinek 		else
16606215Sgjelinek 			zone_perror(zone_template, err, B_TRUE);
16616215Sgjelinek 		return;
16626215Sgjelinek 	}
16636215Sgjelinek 
16646215Sgjelinek 	need_to_commit = B_TRUE;
16650Sstevel@tonic-gate 	zonecfg_fini_handle(handle);
16660Sstevel@tonic-gate 	handle = tmphandle;
16676215Sgjelinek 	got_handle = B_TRUE;
16680Sstevel@tonic-gate }
16690Sstevel@tonic-gate 
16700Sstevel@tonic-gate /*
16710Sstevel@tonic-gate  * This malloc()'s memory, which must be freed by the caller.
16720Sstevel@tonic-gate  */
16730Sstevel@tonic-gate static char *
quoteit(char * instr)16740Sstevel@tonic-gate quoteit(char *instr)
16750Sstevel@tonic-gate {
16760Sstevel@tonic-gate 	char *outstr;
16770Sstevel@tonic-gate 	size_t outstrsize = strlen(instr) + 3;	/* 2 quotes + '\0' */
16780Sstevel@tonic-gate 
16790Sstevel@tonic-gate 	if ((outstr = malloc(outstrsize)) == NULL) {
16806215Sgjelinek 		zone_perror(zone, Z_NOMEM, B_FALSE);
16810Sstevel@tonic-gate 		exit(Z_ERR);
16820Sstevel@tonic-gate 	}
16830Sstevel@tonic-gate 	if (strchr(instr, ' ') == NULL) {
16840Sstevel@tonic-gate 		(void) strlcpy(outstr, instr, outstrsize);
16850Sstevel@tonic-gate 		return (outstr);
16860Sstevel@tonic-gate 	}
16870Sstevel@tonic-gate 	(void) snprintf(outstr, outstrsize, "\"%s\"", instr);
16880Sstevel@tonic-gate 	return (outstr);
16890Sstevel@tonic-gate }
16900Sstevel@tonic-gate 
16910Sstevel@tonic-gate static void
export_prop(FILE * of,int prop_num,char * prop_id)16920Sstevel@tonic-gate export_prop(FILE *of, int prop_num, char *prop_id)
16930Sstevel@tonic-gate {
16940Sstevel@tonic-gate 	char *quote_str;
16950Sstevel@tonic-gate 
16960Sstevel@tonic-gate 	if (strlen(prop_id) == 0)
16970Sstevel@tonic-gate 		return;
16980Sstevel@tonic-gate 	quote_str = quoteit(prop_id);
16990Sstevel@tonic-gate 	(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
17000Sstevel@tonic-gate 	    pt_to_str(prop_num), quote_str);
17010Sstevel@tonic-gate 	free(quote_str);
17020Sstevel@tonic-gate }
17030Sstevel@tonic-gate 
17040Sstevel@tonic-gate void
export_func(cmd_t * cmd)17050Sstevel@tonic-gate export_func(cmd_t *cmd)
17060Sstevel@tonic-gate {
17070Sstevel@tonic-gate 	struct zone_nwiftab nwiftab;
17080Sstevel@tonic-gate 	struct zone_fstab fstab;
17090Sstevel@tonic-gate 	struct zone_devtab devtab;
17100Sstevel@tonic-gate 	struct zone_attrtab attrtab;
17110Sstevel@tonic-gate 	struct zone_rctltab rctltab;
1712789Sahrens 	struct zone_dstab dstab;
17133247Sgjelinek 	struct zone_psettab psettab;
17143247Sgjelinek 	struct zone_mcaptab mcaptab;
17150Sstevel@tonic-gate 	struct zone_rctlvaltab *valptr;
171612578SGlenn.Faden@Sun.COM 	struct zone_admintab admintab;
17170Sstevel@tonic-gate 	int err, arg;
17180Sstevel@tonic-gate 	char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
17192267Sdp 	char bootargs[BOOTARGS_MAX];
17203247Sgjelinek 	char sched[MAXNAMELEN];
17212712Snn35248 	char brand[MAXNAMELEN];
17228662SJordan.Vaughan@Sun.com 	char hostidp[HW_HOSTID_LEN];
172312633Sjohn.levon@sun.com 	char fsallowedp[ZONE_FS_ALLOWED_MAX];
17241645Scomay 	char *limitpriv;
17250Sstevel@tonic-gate 	FILE *of;
17260Sstevel@tonic-gate 	boolean_t autoboot;
17273448Sdh155122 	zone_iptype_t iptype;
17286215Sgjelinek 	boolean_t need_to_close = B_FALSE;
17296215Sgjelinek 	boolean_t arg_err = B_FALSE;
17300Sstevel@tonic-gate 
17310Sstevel@tonic-gate 	assert(cmd != NULL);
17320Sstevel@tonic-gate 
17330Sstevel@tonic-gate 	outfile[0] = '\0';
17340Sstevel@tonic-gate 	optind = 0;
17350Sstevel@tonic-gate 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
17360Sstevel@tonic-gate 		switch (arg) {
17370Sstevel@tonic-gate 		case '?':
17380Sstevel@tonic-gate 			if (optopt == '?')
17390Sstevel@tonic-gate 				longer_usage(CMD_EXPORT);
17400Sstevel@tonic-gate 			else
17410Sstevel@tonic-gate 				short_usage(CMD_EXPORT);
17426215Sgjelinek 			arg_err = B_TRUE;
17433691Sgjelinek 			break;
17440Sstevel@tonic-gate 		case 'f':
17450Sstevel@tonic-gate 			(void) strlcpy(outfile, optarg, sizeof (outfile));
17460Sstevel@tonic-gate 			break;
17470Sstevel@tonic-gate 		default:
17480Sstevel@tonic-gate 			short_usage(CMD_EXPORT);
17496215Sgjelinek 			arg_err = B_TRUE;
17503691Sgjelinek 			break;
17513691Sgjelinek 		}
17523691Sgjelinek 	}
17533691Sgjelinek 	if (arg_err)
17543691Sgjelinek 		return;
17553691Sgjelinek 
17560Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
17570Sstevel@tonic-gate 		short_usage(CMD_EXPORT);
17580Sstevel@tonic-gate 		return;
17590Sstevel@tonic-gate 	}
17600Sstevel@tonic-gate 	if (strlen(outfile) == 0) {
17610Sstevel@tonic-gate 		of = stdout;
17620Sstevel@tonic-gate 	} else {
17630Sstevel@tonic-gate 		if ((of = fopen(outfile, "w")) == NULL) {
17640Sstevel@tonic-gate 			zerr(gettext("opening file %s: %s"),
17650Sstevel@tonic-gate 			    outfile, strerror(errno));
17660Sstevel@tonic-gate 			goto done;
17670Sstevel@tonic-gate 		}
17680Sstevel@tonic-gate 		setbuf(of, NULL);
17696215Sgjelinek 		need_to_close = B_TRUE;
17706215Sgjelinek 	}
17716215Sgjelinek 
17726215Sgjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
17730Sstevel@tonic-gate 		goto done;
17740Sstevel@tonic-gate 
17750Sstevel@tonic-gate 	(void) fprintf(of, "%s -b\n", cmd_to_str(CMD_CREATE));
17760Sstevel@tonic-gate 
17770Sstevel@tonic-gate 	if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK &&
17780Sstevel@tonic-gate 	    strlen(zonepath) > 0)
17790Sstevel@tonic-gate 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
17800Sstevel@tonic-gate 		    pt_to_str(PT_ZONEPATH), zonepath);
17810Sstevel@tonic-gate 
17822712Snn35248 	if ((zone_get_brand(zone, brand, sizeof (brand)) == Z_OK) &&
17832712Snn35248 	    (strcmp(brand, NATIVE_BRAND_NAME) != 0))
17842712Snn35248 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
17852712Snn35248 		    pt_to_str(PT_BRAND), brand);
17862712Snn35248 
17870Sstevel@tonic-gate 	if (zonecfg_get_autoboot(handle, &autoboot) == Z_OK)
17880Sstevel@tonic-gate 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
17890Sstevel@tonic-gate 		    pt_to_str(PT_AUTOBOOT), autoboot ? "true" : "false");
17900Sstevel@tonic-gate 
17912267Sdp 	if (zonecfg_get_bootargs(handle, bootargs, sizeof (bootargs)) == Z_OK &&
17922267Sdp 	    strlen(bootargs) > 0) {
17932267Sdp 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
17942267Sdp 		    pt_to_str(PT_BOOTARGS), bootargs);
17952267Sdp 	}
17962267Sdp 
17970Sstevel@tonic-gate 	if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
17980Sstevel@tonic-gate 	    strlen(pool) > 0)
17990Sstevel@tonic-gate 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18000Sstevel@tonic-gate 		    pt_to_str(PT_POOL), pool);
18010Sstevel@tonic-gate 
18021645Scomay 	if (zonecfg_get_limitpriv(handle, &limitpriv) == Z_OK &&
18031645Scomay 	    strlen(limitpriv) > 0) {
18041645Scomay 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18051645Scomay 		    pt_to_str(PT_LIMITPRIV), limitpriv);
18061645Scomay 		free(limitpriv);
18071645Scomay 	}
18081645Scomay 
18093247Sgjelinek 	if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK &&
18103247Sgjelinek 	    strlen(sched) > 0)
18113247Sgjelinek 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18123247Sgjelinek 		    pt_to_str(PT_SCHED), sched);
18132267Sdp 
18143448Sdh155122 	if (zonecfg_get_iptype(handle, &iptype) == Z_OK) {
18153448Sdh155122 		switch (iptype) {
18163448Sdh155122 		case ZS_SHARED:
18173448Sdh155122 			(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18183448Sdh155122 			    pt_to_str(PT_IPTYPE), "shared");
18193448Sdh155122 			break;
18203448Sdh155122 		case ZS_EXCLUSIVE:
18213448Sdh155122 			(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18223448Sdh155122 			    pt_to_str(PT_IPTYPE), "exclusive");
18233448Sdh155122 			break;
18243448Sdh155122 		}
18253448Sdh155122 	}
18263448Sdh155122 
18278662SJordan.Vaughan@Sun.com 	if (zonecfg_get_hostid(handle, hostidp, sizeof (hostidp)) == Z_OK) {
18288662SJordan.Vaughan@Sun.com 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18298662SJordan.Vaughan@Sun.com 		    pt_to_str(PT_HOSTID), hostidp);
18308662SJordan.Vaughan@Sun.com 	}
18318662SJordan.Vaughan@Sun.com 
183212633Sjohn.levon@sun.com 	if (zonecfg_get_fs_allowed(handle, fsallowedp,
183312633Sjohn.levon@sun.com 	    sizeof (fsallowedp)) == Z_OK) {
183412633Sjohn.levon@sun.com 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
183512633Sjohn.levon@sun.com 		    pt_to_str(PT_FS_ALLOWED), fsallowedp);
183612633Sjohn.levon@sun.com 	}
183712633Sjohn.levon@sun.com 
18380Sstevel@tonic-gate 	if ((err = zonecfg_setfsent(handle)) != Z_OK) {
18396215Sgjelinek 		zone_perror(zone, err, B_FALSE);
18400Sstevel@tonic-gate 		goto done;
18410Sstevel@tonic-gate 	}
18420Sstevel@tonic-gate 	while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
18430Sstevel@tonic-gate 		zone_fsopt_t *optptr;
18440Sstevel@tonic-gate 
18450Sstevel@tonic-gate 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
18460Sstevel@tonic-gate 		    rt_to_str(RT_FS));
18470Sstevel@tonic-gate 		export_prop(of, PT_DIR, fstab.zone_fs_dir);
18480Sstevel@tonic-gate 		export_prop(of, PT_SPECIAL, fstab.zone_fs_special);
18490Sstevel@tonic-gate 		export_prop(of, PT_RAW, fstab.zone_fs_raw);
18500Sstevel@tonic-gate 		export_prop(of, PT_TYPE, fstab.zone_fs_type);
18510Sstevel@tonic-gate 		for (optptr = fstab.zone_fs_options; optptr != NULL;
18520Sstevel@tonic-gate 		    optptr = optptr->zone_fsopt_next) {
18530Sstevel@tonic-gate 			/*
18540Sstevel@tonic-gate 			 * Simple property values with embedded equal signs
18550Sstevel@tonic-gate 			 * need to be quoted to prevent the lexer from
18560Sstevel@tonic-gate 			 * mis-parsing them as complex name=value pairs.
18570Sstevel@tonic-gate 			 */
18580Sstevel@tonic-gate 			if (strchr(optptr->zone_fsopt_opt, '='))
18590Sstevel@tonic-gate 				(void) fprintf(of, "%s %s \"%s\"\n",
18600Sstevel@tonic-gate 				    cmd_to_str(CMD_ADD),
18610Sstevel@tonic-gate 				    pt_to_str(PT_OPTIONS),
18620Sstevel@tonic-gate 				    optptr->zone_fsopt_opt);
18630Sstevel@tonic-gate 			else
18640Sstevel@tonic-gate 				(void) fprintf(of, "%s %s %s\n",
18650Sstevel@tonic-gate 				    cmd_to_str(CMD_ADD),
18660Sstevel@tonic-gate 				    pt_to_str(PT_OPTIONS),
18670Sstevel@tonic-gate 				    optptr->zone_fsopt_opt);
18680Sstevel@tonic-gate 		}
18690Sstevel@tonic-gate 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
18700Sstevel@tonic-gate 		zonecfg_free_fs_option_list(fstab.zone_fs_options);
18710Sstevel@tonic-gate 	}
18720Sstevel@tonic-gate 	(void) zonecfg_endfsent(handle);
18730Sstevel@tonic-gate 
18740Sstevel@tonic-gate 	if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
18756215Sgjelinek 		zone_perror(zone, err, B_FALSE);
18760Sstevel@tonic-gate 		goto done;
18770Sstevel@tonic-gate 	}
18780Sstevel@tonic-gate 	while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
18790Sstevel@tonic-gate 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
18800Sstevel@tonic-gate 		    rt_to_str(RT_NET));
18810Sstevel@tonic-gate 		export_prop(of, PT_ADDRESS, nwiftab.zone_nwif_address);
188212748SSowmini.Varadhan@oracle.COM 		export_prop(of, PT_ALLOWED_ADDRESS,
188312748SSowmini.Varadhan@oracle.COM 		    nwiftab.zone_nwif_allowed_address);
18840Sstevel@tonic-gate 		export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical);
18856076Sgfaden 		export_prop(of, PT_DEFROUTER, nwiftab.zone_nwif_defrouter);
18860Sstevel@tonic-gate 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
18870Sstevel@tonic-gate 	}
18880Sstevel@tonic-gate 	(void) zonecfg_endnwifent(handle);
18890Sstevel@tonic-gate 
18900Sstevel@tonic-gate 	if ((err = zonecfg_setdevent(handle)) != Z_OK) {
18916215Sgjelinek 		zone_perror(zone, err, B_FALSE);
18920Sstevel@tonic-gate 		goto done;
18930Sstevel@tonic-gate 	}
18940Sstevel@tonic-gate 	while (zonecfg_getdevent(handle, &devtab) == Z_OK) {
18950Sstevel@tonic-gate 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
18960Sstevel@tonic-gate 		    rt_to_str(RT_DEVICE));
18970Sstevel@tonic-gate 		export_prop(of, PT_MATCH, devtab.zone_dev_match);
18980Sstevel@tonic-gate 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
18990Sstevel@tonic-gate 	}
19000Sstevel@tonic-gate 	(void) zonecfg_enddevent(handle);
19010Sstevel@tonic-gate 
190212626SGerald.Jelinek@Sun.COM 	if (zonecfg_getmcapent(handle, &mcaptab) == Z_OK) {
190312626SGerald.Jelinek@Sun.COM 		char buf[128];
190412626SGerald.Jelinek@Sun.COM 
190512626SGerald.Jelinek@Sun.COM 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
190612626SGerald.Jelinek@Sun.COM 		    rt_to_str(RT_MCAP));
190712626SGerald.Jelinek@Sun.COM 		bytes_to_units(mcaptab.zone_physmem_cap, buf, sizeof (buf));
190812626SGerald.Jelinek@Sun.COM 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
190912626SGerald.Jelinek@Sun.COM 		    pt_to_str(PT_PHYSICAL), buf);
191012626SGerald.Jelinek@Sun.COM 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
191112626SGerald.Jelinek@Sun.COM 	}
191212626SGerald.Jelinek@Sun.COM 
19130Sstevel@tonic-gate 	if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
19146215Sgjelinek 		zone_perror(zone, err, B_FALSE);
19150Sstevel@tonic-gate 		goto done;
19160Sstevel@tonic-gate 	}
19170Sstevel@tonic-gate 	while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
19180Sstevel@tonic-gate 		(void) fprintf(of, "%s rctl\n", cmd_to_str(CMD_ADD));
19190Sstevel@tonic-gate 		export_prop(of, PT_NAME, rctltab.zone_rctl_name);
19200Sstevel@tonic-gate 		for (valptr = rctltab.zone_rctl_valptr; valptr != NULL;
19210Sstevel@tonic-gate 		    valptr = valptr->zone_rctlval_next) {
19220Sstevel@tonic-gate 			fprintf(of, "%s %s (%s=%s,%s=%s,%s=%s)\n",
19230Sstevel@tonic-gate 			    cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
19240Sstevel@tonic-gate 			    pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
19250Sstevel@tonic-gate 			    pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
19260Sstevel@tonic-gate 			    pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
19270Sstevel@tonic-gate 		}
19280Sstevel@tonic-gate 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
19290Sstevel@tonic-gate 		zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
19300Sstevel@tonic-gate 	}
19310Sstevel@tonic-gate 	(void) zonecfg_endrctlent(handle);
19320Sstevel@tonic-gate 
19330Sstevel@tonic-gate 	if ((err = zonecfg_setattrent(handle)) != Z_OK) {
19346215Sgjelinek 		zone_perror(zone, err, B_FALSE);
19350Sstevel@tonic-gate 		goto done;
19360Sstevel@tonic-gate 	}
19370Sstevel@tonic-gate 	while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
19380Sstevel@tonic-gate 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
19390Sstevel@tonic-gate 		    rt_to_str(RT_ATTR));
19400Sstevel@tonic-gate 		export_prop(of, PT_NAME, attrtab.zone_attr_name);
19410Sstevel@tonic-gate 		export_prop(of, PT_TYPE, attrtab.zone_attr_type);
19420Sstevel@tonic-gate 		export_prop(of, PT_VALUE, attrtab.zone_attr_value);
19430Sstevel@tonic-gate 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
19440Sstevel@tonic-gate 	}
19450Sstevel@tonic-gate 	(void) zonecfg_endattrent(handle);
19460Sstevel@tonic-gate 
1947789Sahrens 	if ((err = zonecfg_setdsent(handle)) != Z_OK) {
19486215Sgjelinek 		zone_perror(zone, err, B_FALSE);
1949789Sahrens 		goto done;
1950789Sahrens 	}
1951789Sahrens 	while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
1952789Sahrens 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1953789Sahrens 		    rt_to_str(RT_DATASET));
1954789Sahrens 		export_prop(of, PT_NAME, dstab.zone_dataset_name);
1955789Sahrens 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1956789Sahrens 	}
1957789Sahrens 	(void) zonecfg_enddsent(handle);
1958789Sahrens 
19593247Sgjelinek 	if (zonecfg_getpsetent(handle, &psettab) == Z_OK) {
19603247Sgjelinek 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
19613247Sgjelinek 		    rt_to_str(RT_DCPU));
19623247Sgjelinek 		if (strcmp(psettab.zone_ncpu_min, psettab.zone_ncpu_max) == 0)
19633247Sgjelinek 			(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
19643247Sgjelinek 			    pt_to_str(PT_NCPUS), psettab.zone_ncpu_max);
19653247Sgjelinek 		else
19663247Sgjelinek 			(void) fprintf(of, "%s %s=%s-%s\n", cmd_to_str(CMD_SET),
19673247Sgjelinek 			    pt_to_str(PT_NCPUS), psettab.zone_ncpu_min,
19683247Sgjelinek 			    psettab.zone_ncpu_max);
19693247Sgjelinek 		if (psettab.zone_importance[0] != '\0')
19703247Sgjelinek 			(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
19713247Sgjelinek 			    pt_to_str(PT_IMPORTANCE), psettab.zone_importance);
19723247Sgjelinek 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
19733247Sgjelinek 	}
19743247Sgjelinek 
197512578SGlenn.Faden@Sun.COM 	if ((err = zonecfg_setadminent(handle)) != Z_OK) {
197612578SGlenn.Faden@Sun.COM 		zone_perror(zone, err, B_FALSE);
197712578SGlenn.Faden@Sun.COM 		goto done;
197812578SGlenn.Faden@Sun.COM 	}
197912578SGlenn.Faden@Sun.COM 	while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
198012578SGlenn.Faden@Sun.COM 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
198112578SGlenn.Faden@Sun.COM 		    rt_to_str(RT_ADMIN));
198212578SGlenn.Faden@Sun.COM 		export_prop(of, PT_USER, admintab.zone_admin_user);
198312578SGlenn.Faden@Sun.COM 		export_prop(of, PT_AUTHS, admintab.zone_admin_auths);
198412578SGlenn.Faden@Sun.COM 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
198512578SGlenn.Faden@Sun.COM 	}
198612578SGlenn.Faden@Sun.COM 	(void) zonecfg_endadminent(handle);
198712578SGlenn.Faden@Sun.COM 
19883792Sakolb 	/*
19893792Sakolb 	 * There is nothing to export for pcap since this resource is just
19903792Sakolb 	 * a container for an rctl alias.
19913792Sakolb 	 */
19923792Sakolb 
19930Sstevel@tonic-gate done:
19940Sstevel@tonic-gate 	if (need_to_close)
19950Sstevel@tonic-gate 		(void) fclose(of);
19960Sstevel@tonic-gate }
19970Sstevel@tonic-gate 
19980Sstevel@tonic-gate void
exit_func(cmd_t * cmd)19990Sstevel@tonic-gate exit_func(cmd_t *cmd)
20000Sstevel@tonic-gate {
20010Sstevel@tonic-gate 	int arg, answer;
20026215Sgjelinek 	boolean_t arg_err = B_FALSE;
20030Sstevel@tonic-gate 
20040Sstevel@tonic-gate 	optind = 0;
20050Sstevel@tonic-gate 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
20060Sstevel@tonic-gate 		switch (arg) {
20070Sstevel@tonic-gate 		case '?':
20080Sstevel@tonic-gate 			longer_usage(CMD_EXIT);
20096215Sgjelinek 			arg_err = B_TRUE;
20103691Sgjelinek 			break;
20110Sstevel@tonic-gate 		case 'F':
20126215Sgjelinek 			force_exit = B_TRUE;
20130Sstevel@tonic-gate 			break;
20140Sstevel@tonic-gate 		default:
20150Sstevel@tonic-gate 			short_usage(CMD_EXIT);
20166215Sgjelinek 			arg_err = B_TRUE;
20173691Sgjelinek 			break;
20183691Sgjelinek 		}
20193691Sgjelinek 	}
20203691Sgjelinek 	if (arg_err)
20213691Sgjelinek 		return;
20223691Sgjelinek 
20230Sstevel@tonic-gate 	if (optind < cmd->cmd_argc) {
20240Sstevel@tonic-gate 		short_usage(CMD_EXIT);
20250Sstevel@tonic-gate 		return;
20260Sstevel@tonic-gate 	}
20270Sstevel@tonic-gate 
20280Sstevel@tonic-gate 	if (global_scope || force_exit) {
20296215Sgjelinek 		time_to_exit = B_TRUE;
20306215Sgjelinek 		return;
20316215Sgjelinek 	}
20326215Sgjelinek 
20336215Sgjelinek 	answer = ask_yesno(B_FALSE, "Resource incomplete; really quit");
20340Sstevel@tonic-gate 	if (answer == -1) {
20350Sstevel@tonic-gate 		zerr(gettext("Resource incomplete, input "
20360Sstevel@tonic-gate 		    "not from terminal and -F not specified:\n%s command "
20370Sstevel@tonic-gate 		    "ignored, but exiting anyway."), cmd_to_str(CMD_EXIT));
20380Sstevel@tonic-gate 		exit(Z_ERR);
20390Sstevel@tonic-gate 	} else if (answer == 1) {
20406215Sgjelinek 		time_to_exit = B_TRUE;
20410Sstevel@tonic-gate 	}
20420Sstevel@tonic-gate 	/* (answer == 0) => just return */
20430Sstevel@tonic-gate }
20440Sstevel@tonic-gate 
20450Sstevel@tonic-gate static int
validate_zonepath_syntax(char * path)20460Sstevel@tonic-gate validate_zonepath_syntax(char *path)
20470Sstevel@tonic-gate {
20480Sstevel@tonic-gate 	if (path[0] != '/') {
20490Sstevel@tonic-gate 		zerr(gettext("%s is not an absolute path."), path);
20500Sstevel@tonic-gate 		return (Z_ERR);
20510Sstevel@tonic-gate 	}
205212715SSusan.Kamm-Worrell@Sun.COM 	/* If path is all slashes, then fail */
205312715SSusan.Kamm-Worrell@Sun.COM 	if (strspn(path, "/") == strlen(path)) {
20540Sstevel@tonic-gate 		zerr(gettext("/ is not allowed as a %s."),
20550Sstevel@tonic-gate 		    pt_to_str(PT_ZONEPATH));
20560Sstevel@tonic-gate 		return (Z_ERR);
20570Sstevel@tonic-gate 	}
20580Sstevel@tonic-gate 	return (Z_OK);
20590Sstevel@tonic-gate }
20600Sstevel@tonic-gate 
20610Sstevel@tonic-gate static void
add_resource(cmd_t * cmd)20620Sstevel@tonic-gate add_resource(cmd_t *cmd)
20630Sstevel@tonic-gate {
20640Sstevel@tonic-gate 	int type;
20653247Sgjelinek 	struct zone_psettab tmp_psettab;
20663247Sgjelinek 	struct zone_mcaptab tmp_mcaptab;
20673792Sakolb 	uint64_t tmp;
20683247Sgjelinek 	uint64_t tmp_mcap;
20693247Sgjelinek 	char pool[MAXNAMELEN];
20700Sstevel@tonic-gate 
20710Sstevel@tonic-gate 	if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
20726215Sgjelinek 		long_usage(CMD_ADD, B_TRUE);
20730Sstevel@tonic-gate 		goto bad;
20740Sstevel@tonic-gate 	}
20750Sstevel@tonic-gate 
20760Sstevel@tonic-gate 	switch (type) {
20770Sstevel@tonic-gate 	case RT_FS:
20780Sstevel@tonic-gate 		bzero(&in_progress_fstab, sizeof (in_progress_fstab));
20790Sstevel@tonic-gate 		return;
20800Sstevel@tonic-gate 	case RT_NET:
20810Sstevel@tonic-gate 		bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
20820Sstevel@tonic-gate 		return;
20830Sstevel@tonic-gate 	case RT_DEVICE:
20840Sstevel@tonic-gate 		bzero(&in_progress_devtab, sizeof (in_progress_devtab));
20850Sstevel@tonic-gate 		return;
20860Sstevel@tonic-gate 	case RT_RCTL:
20873247Sgjelinek 		if (global_zone)
20883247Sgjelinek 			zerr(gettext("WARNING: Setting a global zone resource "
20893247Sgjelinek 			    "control too low could deny\nservice "
20903247Sgjelinek 			    "to even the root user; "
20913247Sgjelinek 			    "this could render the system impossible\n"
20923247Sgjelinek 			    "to administer.  Please use caution."));
20930Sstevel@tonic-gate 		bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
20940Sstevel@tonic-gate 		return;
20950Sstevel@tonic-gate 	case RT_ATTR:
20960Sstevel@tonic-gate 		bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
20970Sstevel@tonic-gate 		return;
2098789Sahrens 	case RT_DATASET:
2099789Sahrens 		bzero(&in_progress_dstab, sizeof (in_progress_dstab));
2100789Sahrens 		return;
21013247Sgjelinek 	case RT_DCPU:
21023792Sakolb 		/* Make sure there isn't already a cpu-set or cpu-cap entry. */
21033247Sgjelinek 		if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
21043247Sgjelinek 			zerr(gettext("The %s resource already exists."),
21053247Sgjelinek 			    rt_to_str(RT_DCPU));
21063247Sgjelinek 			goto bad;
21073247Sgjelinek 		}
21083792Sakolb 		if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) !=
21093792Sakolb 		    Z_NO_ENTRY) {
21103792Sakolb 			zerr(gettext("The %s resource already exists."),
21113792Sakolb 			    rt_to_str(RT_PCAP));
21123792Sakolb 			goto bad;
21133792Sakolb 		}
21143247Sgjelinek 
21153247Sgjelinek 		/* Make sure the pool property isn't set. */
21163247Sgjelinek 		if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
21173247Sgjelinek 		    strlen(pool) > 0) {
21183247Sgjelinek 			zerr(gettext("The %s property is already set.  "
21193247Sgjelinek 			    "A persistent pool is incompatible with\nthe %s "
21203247Sgjelinek 			    "resource."),
21213247Sgjelinek 			    pt_to_str(PT_POOL), rt_to_str(RT_DCPU));
21223247Sgjelinek 			goto bad;
21233247Sgjelinek 		}
21243247Sgjelinek 
21253247Sgjelinek 		bzero(&in_progress_psettab, sizeof (in_progress_psettab));
21263247Sgjelinek 		return;
21273792Sakolb 	case RT_PCAP:
21283792Sakolb 		/*
21293792Sakolb 		 * Make sure there isn't already a cpu-set or incompatible
21303792Sakolb 		 * cpu-cap rctls.
21313792Sakolb 		 */
21323792Sakolb 		if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
21333792Sakolb 			zerr(gettext("The %s resource already exists."),
21343792Sakolb 			    rt_to_str(RT_DCPU));
21353792Sakolb 			goto bad;
21363792Sakolb 		}
21373792Sakolb 
21383792Sakolb 		switch (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp)) {
21393792Sakolb 		case Z_ALIAS_DISALLOW:
21403792Sakolb 			zone_perror(rt_to_str(RT_PCAP), Z_ALIAS_DISALLOW,
21416215Sgjelinek 			    B_FALSE);
21423792Sakolb 			goto bad;
21433792Sakolb 
21443792Sakolb 		case Z_OK:
21453792Sakolb 			zerr(gettext("The %s resource already exists."),
21463792Sakolb 			    rt_to_str(RT_PCAP));
21473792Sakolb 			goto bad;
21483792Sakolb 
21493792Sakolb 		default:
21503792Sakolb 			break;
21513792Sakolb 		}
21523792Sakolb 		return;
21533247Sgjelinek 	case RT_MCAP:
21543247Sgjelinek 		/*
21553247Sgjelinek 		 * Make sure there isn't already a mem-cap entry or max-swap
21563247Sgjelinek 		 * or max-locked rctl.
21573247Sgjelinek 		 */
21583247Sgjelinek 		if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
21593247Sgjelinek 		    zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
21603247Sgjelinek 		    == Z_OK ||
21613247Sgjelinek 		    zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
21623247Sgjelinek 		    &tmp_mcap) == Z_OK) {
21633247Sgjelinek 			zerr(gettext("The %s resource or a related resource "
21643247Sgjelinek 			    "control already exists."), rt_to_str(RT_MCAP));
21653247Sgjelinek 			goto bad;
21663247Sgjelinek 		}
21673247Sgjelinek 		if (global_zone)
21683247Sgjelinek 			zerr(gettext("WARNING: Setting a global zone memory "
21693247Sgjelinek 			    "cap too low could deny\nservice "
21703247Sgjelinek 			    "to even the root user; "
21713247Sgjelinek 			    "this could render the system impossible\n"
21723247Sgjelinek 			    "to administer.  Please use caution."));
21733247Sgjelinek 		bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
21743247Sgjelinek 		return;
217512578SGlenn.Faden@Sun.COM 	case RT_ADMIN:
217612578SGlenn.Faden@Sun.COM 		bzero(&in_progress_admintab, sizeof (in_progress_admintab));
217712578SGlenn.Faden@Sun.COM 		return;
21780Sstevel@tonic-gate 	default:
21796215Sgjelinek 		zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
21806215Sgjelinek 		long_usage(CMD_ADD, B_TRUE);
21816215Sgjelinek 		usage(B_FALSE, HELP_RESOURCES);
21820Sstevel@tonic-gate 	}
21830Sstevel@tonic-gate bad:
21846215Sgjelinek 	global_scope = B_TRUE;
21850Sstevel@tonic-gate 	end_op = -1;
21860Sstevel@tonic-gate }
21870Sstevel@tonic-gate 
21880Sstevel@tonic-gate static void
do_complex_rctl_val(complex_property_ptr_t cp)21890Sstevel@tonic-gate do_complex_rctl_val(complex_property_ptr_t cp)
21900Sstevel@tonic-gate {
21910Sstevel@tonic-gate 	struct zone_rctlvaltab *rctlvaltab;
21920Sstevel@tonic-gate 	complex_property_ptr_t cx;
21936215Sgjelinek 	boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
21946215Sgjelinek 	    seen_action = B_FALSE;
21950Sstevel@tonic-gate 	rctlblk_t *rctlblk;
21960Sstevel@tonic-gate 	int err;
21970Sstevel@tonic-gate 
21980Sstevel@tonic-gate 	if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
21996215Sgjelinek 		zone_perror(zone, Z_NOMEM, B_TRUE);
22000Sstevel@tonic-gate 		exit(Z_ERR);
22010Sstevel@tonic-gate 	}
22020Sstevel@tonic-gate 	for (cx = cp; cx != NULL; cx = cx->cp_next) {
22030Sstevel@tonic-gate 		switch (cx->cp_type) {
22040Sstevel@tonic-gate 		case PT_PRIV:
22050Sstevel@tonic-gate 			if (seen_priv) {
22060Sstevel@tonic-gate 				zerr(gettext("%s already specified"),
22070Sstevel@tonic-gate 				    pt_to_str(PT_PRIV));
22080Sstevel@tonic-gate 				goto bad;
22090Sstevel@tonic-gate 			}
22100Sstevel@tonic-gate 			(void) strlcpy(rctlvaltab->zone_rctlval_priv,
22110Sstevel@tonic-gate 			    cx->cp_value,
22120Sstevel@tonic-gate 			    sizeof (rctlvaltab->zone_rctlval_priv));
22136215Sgjelinek 			seen_priv = B_TRUE;
22140Sstevel@tonic-gate 			break;
22150Sstevel@tonic-gate 		case PT_LIMIT:
22160Sstevel@tonic-gate 			if (seen_limit) {
22170Sstevel@tonic-gate 				zerr(gettext("%s already specified"),
22180Sstevel@tonic-gate 				    pt_to_str(PT_LIMIT));
22190Sstevel@tonic-gate 				goto bad;
22200Sstevel@tonic-gate 			}
22210Sstevel@tonic-gate 			(void) strlcpy(rctlvaltab->zone_rctlval_limit,
22220Sstevel@tonic-gate 			    cx->cp_value,
22230Sstevel@tonic-gate 			    sizeof (rctlvaltab->zone_rctlval_limit));
22246215Sgjelinek 			seen_limit = B_TRUE;
22250Sstevel@tonic-gate 			break;
22260Sstevel@tonic-gate 		case PT_ACTION:
22270Sstevel@tonic-gate 			if (seen_action) {
22280Sstevel@tonic-gate 				zerr(gettext("%s already specified"),
22290Sstevel@tonic-gate 				    pt_to_str(PT_ACTION));
22300Sstevel@tonic-gate 				goto bad;
22310Sstevel@tonic-gate 			}
22320Sstevel@tonic-gate 			(void) strlcpy(rctlvaltab->zone_rctlval_action,
22330Sstevel@tonic-gate 			    cx->cp_value,
22340Sstevel@tonic-gate 			    sizeof (rctlvaltab->zone_rctlval_action));
22356215Sgjelinek 			seen_action = B_TRUE;
22360Sstevel@tonic-gate 			break;
22370Sstevel@tonic-gate 		default:
22380Sstevel@tonic-gate 			zone_perror(pt_to_str(PT_VALUE),
22396215Sgjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
22406215Sgjelinek 			long_usage(CMD_ADD, B_TRUE);
22416215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
22420Sstevel@tonic-gate 			zonecfg_free_rctl_value_list(rctlvaltab);
22430Sstevel@tonic-gate 			return;
22440Sstevel@tonic-gate 		}
22450Sstevel@tonic-gate 	}
22460Sstevel@tonic-gate 	if (!seen_priv)
22470Sstevel@tonic-gate 		zerr(gettext("%s not specified"), pt_to_str(PT_PRIV));
22480Sstevel@tonic-gate 	if (!seen_limit)
22490Sstevel@tonic-gate 		zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT));
22500Sstevel@tonic-gate 	if (!seen_action)
22510Sstevel@tonic-gate 		zerr(gettext("%s not specified"), pt_to_str(PT_ACTION));
22520Sstevel@tonic-gate 	if (!seen_priv || !seen_limit || !seen_action)
22530Sstevel@tonic-gate 		goto bad;
22540Sstevel@tonic-gate 	rctlvaltab->zone_rctlval_next = NULL;
22550Sstevel@tonic-gate 	rctlblk = alloca(rctlblk_size());
22560Sstevel@tonic-gate 	/*
22570Sstevel@tonic-gate 	 * Make sure the rctl value looks roughly correct; we won't know if
22580Sstevel@tonic-gate 	 * it's truly OK until we verify the configuration on the target
22590Sstevel@tonic-gate 	 * system.
22600Sstevel@tonic-gate 	 */
22610Sstevel@tonic-gate 	if (zonecfg_construct_rctlblk(rctlvaltab, rctlblk) != Z_OK ||
22620Sstevel@tonic-gate 	    !zonecfg_valid_rctlblk(rctlblk)) {
22630Sstevel@tonic-gate 		zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL),
22640Sstevel@tonic-gate 		    pt_to_str(PT_VALUE));
22650Sstevel@tonic-gate 		goto bad;
22660Sstevel@tonic-gate 	}
22670Sstevel@tonic-gate 	err = zonecfg_add_rctl_value(&in_progress_rctltab, rctlvaltab);
22680Sstevel@tonic-gate 	if (err != Z_OK)
22696215Sgjelinek 		zone_perror(pt_to_str(PT_VALUE), err, B_TRUE);
22700Sstevel@tonic-gate 	return;
22710Sstevel@tonic-gate 
22720Sstevel@tonic-gate bad:
22730Sstevel@tonic-gate 	zonecfg_free_rctl_value_list(rctlvaltab);
22740Sstevel@tonic-gate }
22750Sstevel@tonic-gate 
22760Sstevel@tonic-gate static void
add_property(cmd_t * cmd)22770Sstevel@tonic-gate add_property(cmd_t *cmd)
22780Sstevel@tonic-gate {
22790Sstevel@tonic-gate 	char *prop_id;
22800Sstevel@tonic-gate 	int err, res_type, prop_type;
22810Sstevel@tonic-gate 	property_value_ptr_t pp;
22820Sstevel@tonic-gate 	list_property_ptr_t l;
22830Sstevel@tonic-gate 
22840Sstevel@tonic-gate 	res_type = resource_scope;
22850Sstevel@tonic-gate 	prop_type = cmd->cmd_prop_name[0];
22860Sstevel@tonic-gate 	if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
22876215Sgjelinek 		long_usage(CMD_ADD, B_TRUE);
22880Sstevel@tonic-gate 		return;
22890Sstevel@tonic-gate 	}
22900Sstevel@tonic-gate 
22910Sstevel@tonic-gate 	if (cmd->cmd_prop_nv_pairs != 1) {
22926215Sgjelinek 		long_usage(CMD_ADD, B_TRUE);
22936215Sgjelinek 		return;
22946215Sgjelinek 	}
22956215Sgjelinek 
22966215Sgjelinek 	if (initialize(B_TRUE) != Z_OK)
22970Sstevel@tonic-gate 		return;
22980Sstevel@tonic-gate 
22990Sstevel@tonic-gate 	switch (res_type) {
23000Sstevel@tonic-gate 	case RT_FS:
23010Sstevel@tonic-gate 		if (prop_type != PT_OPTIONS) {
23020Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
23036215Sgjelinek 			    B_TRUE);
23046215Sgjelinek 			long_usage(CMD_ADD, B_TRUE);
23056215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
23060Sstevel@tonic-gate 			return;
23070Sstevel@tonic-gate 		}
23080Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[0];
23090Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE &&
23100Sstevel@tonic-gate 		    pp->pv_type != PROP_VAL_LIST) {
23110Sstevel@tonic-gate 			zerr(gettext("A %s or %s value was expected here."),
23120Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_SIMPLE),
23130Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_LIST));
23146215Sgjelinek 			saw_error = B_TRUE;
23150Sstevel@tonic-gate 			return;
23160Sstevel@tonic-gate 		}
23170Sstevel@tonic-gate 		if (pp->pv_type == PROP_VAL_SIMPLE) {
23180Sstevel@tonic-gate 			if (pp->pv_simple == NULL) {
23196215Sgjelinek 				long_usage(CMD_ADD, B_TRUE);
23200Sstevel@tonic-gate 				return;
23210Sstevel@tonic-gate 			}
23220Sstevel@tonic-gate 			prop_id = pp->pv_simple;
23230Sstevel@tonic-gate 			err = zonecfg_add_fs_option(&in_progress_fstab,
23240Sstevel@tonic-gate 			    prop_id);
23250Sstevel@tonic-gate 			if (err != Z_OK)
23266215Sgjelinek 				zone_perror(pt_to_str(prop_type), err, B_TRUE);
23270Sstevel@tonic-gate 		} else {
23280Sstevel@tonic-gate 			list_property_ptr_t list;
23290Sstevel@tonic-gate 
23300Sstevel@tonic-gate 			for (list = pp->pv_list; list != NULL;
23310Sstevel@tonic-gate 			    list = list->lp_next) {
23320Sstevel@tonic-gate 				prop_id = list->lp_simple;
23330Sstevel@tonic-gate 				if (prop_id == NULL)
23340Sstevel@tonic-gate 					break;
23350Sstevel@tonic-gate 				err = zonecfg_add_fs_option(
23360Sstevel@tonic-gate 				    &in_progress_fstab, prop_id);
23370Sstevel@tonic-gate 				if (err != Z_OK)
23380Sstevel@tonic-gate 					zone_perror(pt_to_str(prop_type), err,
23396215Sgjelinek 					    B_TRUE);
23400Sstevel@tonic-gate 			}
23410Sstevel@tonic-gate 		}
23420Sstevel@tonic-gate 		return;
23430Sstevel@tonic-gate 	case RT_RCTL:
23440Sstevel@tonic-gate 		if (prop_type != PT_VALUE) {
23450Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
23466215Sgjelinek 			    B_TRUE);
23476215Sgjelinek 			long_usage(CMD_ADD, B_TRUE);
23486215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
23490Sstevel@tonic-gate 			return;
23500Sstevel@tonic-gate 		}
23510Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[0];
23520Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_COMPLEX &&
23530Sstevel@tonic-gate 		    pp->pv_type != PROP_VAL_LIST) {
23540Sstevel@tonic-gate 			zerr(gettext("A %s or %s value was expected here."),
23550Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_COMPLEX),
23560Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_LIST));
23576215Sgjelinek 			saw_error = B_TRUE;
23580Sstevel@tonic-gate 			return;
23590Sstevel@tonic-gate 		}
23600Sstevel@tonic-gate 		if (pp->pv_type == PROP_VAL_COMPLEX) {
23610Sstevel@tonic-gate 			do_complex_rctl_val(pp->pv_complex);
23620Sstevel@tonic-gate 			return;
23630Sstevel@tonic-gate 		}
23640Sstevel@tonic-gate 		for (l = pp->pv_list; l != NULL; l = l->lp_next)
23650Sstevel@tonic-gate 			do_complex_rctl_val(l->lp_complex);
23660Sstevel@tonic-gate 		return;
23670Sstevel@tonic-gate 	default:
23686215Sgjelinek 		zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
23696215Sgjelinek 		long_usage(CMD_ADD, B_TRUE);
23706215Sgjelinek 		usage(B_FALSE, HELP_RESOURCES);
23710Sstevel@tonic-gate 		return;
23720Sstevel@tonic-gate 	}
23730Sstevel@tonic-gate }
23740Sstevel@tonic-gate 
23753247Sgjelinek static boolean_t
gz_invalid_resource(int type)23763247Sgjelinek gz_invalid_resource(int type)
23773247Sgjelinek {
237812734Sgary.pennington@oracle.com 	return (global_zone && (type == RT_FS ||
23793247Sgjelinek 	    type == RT_NET || type == RT_DEVICE || type == RT_ATTR ||
23803247Sgjelinek 	    type == RT_DATASET));
23813247Sgjelinek }
23823247Sgjelinek 
23833247Sgjelinek static boolean_t
gz_invalid_rt_property(int type)23843247Sgjelinek gz_invalid_rt_property(int type)
23853247Sgjelinek {
23863247Sgjelinek 	return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH ||
23873247Sgjelinek 	    type == RT_AUTOBOOT || type == RT_LIMITPRIV ||
23883448Sdh155122 	    type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED ||
238912633Sjohn.levon@sun.com 	    type == RT_IPTYPE || type == RT_HOSTID || type == RT_FS_ALLOWED));
23903247Sgjelinek }
23913247Sgjelinek 
23923247Sgjelinek static boolean_t
gz_invalid_property(int type)23933247Sgjelinek gz_invalid_property(int type)
23943247Sgjelinek {
23953247Sgjelinek 	return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH ||
23963247Sgjelinek 	    type == PT_AUTOBOOT || type == PT_LIMITPRIV ||
23973448Sdh155122 	    type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED ||
239812633Sjohn.levon@sun.com 	    type == PT_IPTYPE || type == PT_HOSTID || type == PT_FS_ALLOWED));
23993247Sgjelinek }
24003247Sgjelinek 
24010Sstevel@tonic-gate void
add_func(cmd_t * cmd)24020Sstevel@tonic-gate add_func(cmd_t *cmd)
24030Sstevel@tonic-gate {
24040Sstevel@tonic-gate 	int arg;
24056215Sgjelinek 	boolean_t arg_err = B_FALSE;
24060Sstevel@tonic-gate 
24070Sstevel@tonic-gate 	assert(cmd != NULL);
24080Sstevel@tonic-gate 
24090Sstevel@tonic-gate 	optind = 0;
24103691Sgjelinek 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
24110Sstevel@tonic-gate 		switch (arg) {
24120Sstevel@tonic-gate 		case '?':
24130Sstevel@tonic-gate 			longer_usage(CMD_ADD);
24146215Sgjelinek 			arg_err = B_TRUE;
24153691Sgjelinek 			break;
24160Sstevel@tonic-gate 		default:
24170Sstevel@tonic-gate 			short_usage(CMD_ADD);
24186215Sgjelinek 			arg_err = B_TRUE;
24193691Sgjelinek 			break;
24203691Sgjelinek 		}
24213691Sgjelinek 	}
24223691Sgjelinek 	if (arg_err)
24233691Sgjelinek 		return;
24243691Sgjelinek 
24250Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
24260Sstevel@tonic-gate 		short_usage(CMD_ADD);
24270Sstevel@tonic-gate 		return;
24280Sstevel@tonic-gate 	}
24290Sstevel@tonic-gate 
24300Sstevel@tonic-gate 	if (zone_is_read_only(CMD_ADD))
24310Sstevel@tonic-gate 		return;
24320Sstevel@tonic-gate 
24336215Sgjelinek 	if (initialize(B_TRUE) != Z_OK)
24340Sstevel@tonic-gate 		return;
24350Sstevel@tonic-gate 	if (global_scope) {
24363247Sgjelinek 		if (gz_invalid_resource(cmd->cmd_res_type)) {
24373247Sgjelinek 			zerr(gettext("Cannot add a %s resource to the "
24383247Sgjelinek 			    "global zone."), rt_to_str(cmd->cmd_res_type));
24396215Sgjelinek 			saw_error = B_TRUE;
24403247Sgjelinek 			return;
24413247Sgjelinek 		}
24423247Sgjelinek 
24436215Sgjelinek 		global_scope = B_FALSE;
24440Sstevel@tonic-gate 		resource_scope = cmd->cmd_res_type;
24450Sstevel@tonic-gate 		end_op = CMD_ADD;
24460Sstevel@tonic-gate 		add_resource(cmd);
24470Sstevel@tonic-gate 	} else
24480Sstevel@tonic-gate 		add_property(cmd);
24490Sstevel@tonic-gate }
24500Sstevel@tonic-gate 
2451565Sdp /*
2452565Sdp  * This routine has an unusual implementation, because it tries very
2453565Sdp  * hard to succeed in the face of a variety of failure modes.
2454565Sdp  * The most common and most vexing occurs when the index file and
2455565Sdp  * the /etc/zones/<zonename.xml> file are not both present.  In
2456565Sdp  * this case, delete must eradicate as much of the zone state as is left
2457565Sdp  * so that the user can later create a new zone with the same name.
2458565Sdp  */
24590Sstevel@tonic-gate void
delete_func(cmd_t * cmd)24600Sstevel@tonic-gate delete_func(cmd_t *cmd)
24610Sstevel@tonic-gate {
24620Sstevel@tonic-gate 	int err, arg, answer;
24630Sstevel@tonic-gate 	char line[ZONENAME_MAX + 128];	/* enough to ask a question */
24646215Sgjelinek 	boolean_t force = B_FALSE;
24656215Sgjelinek 	boolean_t arg_err = B_FALSE;
24660Sstevel@tonic-gate 
24670Sstevel@tonic-gate 	optind = 0;
24680Sstevel@tonic-gate 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
24690Sstevel@tonic-gate 		switch (arg) {
24700Sstevel@tonic-gate 		case '?':
24710Sstevel@tonic-gate 			longer_usage(CMD_DELETE);
24726215Sgjelinek 			arg_err = B_TRUE;
24733691Sgjelinek 			break;
24740Sstevel@tonic-gate 		case 'F':
24756215Sgjelinek 			force = B_TRUE;
24760Sstevel@tonic-gate 			break;
24770Sstevel@tonic-gate 		default:
24780Sstevel@tonic-gate 			short_usage(CMD_DELETE);
24796215Sgjelinek 			arg_err = B_TRUE;
24803691Sgjelinek 			break;
24813691Sgjelinek 		}
24823691Sgjelinek 	}
24833691Sgjelinek 	if (arg_err)
24843691Sgjelinek 		return;
24853691Sgjelinek 
24860Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
24870Sstevel@tonic-gate 		short_usage(CMD_DELETE);
24880Sstevel@tonic-gate 		return;
24890Sstevel@tonic-gate 	}
24900Sstevel@tonic-gate 
24910Sstevel@tonic-gate 	if (zone_is_read_only(CMD_DELETE))
24920Sstevel@tonic-gate 		return;
24930Sstevel@tonic-gate 
24940Sstevel@tonic-gate 	if (!force) {
2495565Sdp 		/*
2496565Sdp 		 * Initialize sets up the global called "handle" and warns the
2497565Sdp 		 * user if the zone is not configured.  In force mode, we don't
2498565Sdp 		 * trust that evaluation, and hence skip it.  (We don't need the
2499565Sdp 		 * handle to be loaded anyway, since zonecfg_destroy is done by
250012578SGlenn.Faden@Sun.COM 		 * zonename). However, we also have to take care to emulate the
2501565Sdp 		 * messages spit out by initialize; see below.
2502565Sdp 		 */
25036215Sgjelinek 		if (initialize(B_TRUE) != Z_OK)
2504565Sdp 			return;
2505565Sdp 
25060Sstevel@tonic-gate 		(void) snprintf(line, sizeof (line),
25070Sstevel@tonic-gate 		    gettext("Are you sure you want to delete zone %s"), zone);
25086215Sgjelinek 		if ((answer = ask_yesno(B_FALSE, line)) == -1) {
2509565Sdp 			zerr(gettext("Input not from terminal and -F not "
2510565Sdp 			    "specified:\n%s command ignored, exiting."),
2511565Sdp 			    cmd_to_str(CMD_DELETE));
25120Sstevel@tonic-gate 			exit(Z_ERR);
25130Sstevel@tonic-gate 		}
25140Sstevel@tonic-gate 		if (answer != 1)
25150Sstevel@tonic-gate 			return;
25160Sstevel@tonic-gate 	}
25170Sstevel@tonic-gate 
251812578SGlenn.Faden@Sun.COM 	/*
251912578SGlenn.Faden@Sun.COM 	 * This function removes the authorizations from user_attr
252012578SGlenn.Faden@Sun.COM 	 * that correspond to those specified in the configuration
252112578SGlenn.Faden@Sun.COM 	 */
252212578SGlenn.Faden@Sun.COM 	if (initialize(B_TRUE) == Z_OK) {
252312578SGlenn.Faden@Sun.COM 		(void) zonecfg_deauthorize_users(handle, zone);
252412578SGlenn.Faden@Sun.COM 	}
2525565Sdp 	if ((err = zonecfg_destroy(zone, force)) != Z_OK) {
2526565Sdp 		if ((err == Z_BAD_ZONE_STATE) && !force) {
2527565Sdp 			zerr(gettext("Zone %s not in %s state; %s not "
2528565Sdp 			    "allowed.  Use -F to force %s."),
2529565Sdp 			    zone, zone_state_str(ZONE_STATE_CONFIGURED),
2530565Sdp 			    cmd_to_str(CMD_DELETE), cmd_to_str(CMD_DELETE));
2531565Sdp 		} else {
25326215Sgjelinek 			zone_perror(zone, err, B_TRUE);
25336215Sgjelinek 		}
25346215Sgjelinek 	}
25356215Sgjelinek 	need_to_commit = B_FALSE;
2536565Sdp 
2537565Sdp 	/*
2538565Sdp 	 * Emulate initialize's messaging; if there wasn't a valid handle to
2539565Sdp 	 * begin with, then user had typed delete (or delete -F) multiple
2540565Sdp 	 * times.  So we emit a message.
2541565Sdp 	 *
2542565Sdp 	 * We only do this in the 'force' case because normally, initialize()
2543565Sdp 	 * takes care of this for us.
2544565Sdp 	 */
2545565Sdp 	if (force && zonecfg_check_handle(handle) != Z_OK && interactive_mode)
2546565Sdp 		(void) printf(gettext("Use '%s' to begin "
2547565Sdp 		    "configuring a new zone.\n"), cmd_to_str(CMD_CREATE));
25480Sstevel@tonic-gate 
25490Sstevel@tonic-gate 	/*
25500Sstevel@tonic-gate 	 * Time for a new handle: finish the old one off first
25510Sstevel@tonic-gate 	 * then get a new one properly to avoid leaks.
25520Sstevel@tonic-gate 	 */
2553565Sdp 	if (got_handle) {
2554565Sdp 		zonecfg_fini_handle(handle);
2555565Sdp 		if ((handle = zonecfg_init_handle()) == NULL) {
25566215Sgjelinek 			zone_perror(execname, Z_NOMEM, B_TRUE);
2557565Sdp 			exit(Z_ERR);
2558565Sdp 		}
2559565Sdp 		if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) {
2560565Sdp 			/* If there was no zone before, that's OK */
2561565Sdp 			if (err != Z_NO_ZONE)
25626215Sgjelinek 				zone_perror(zone, err, B_TRUE);
25636215Sgjelinek 			got_handle = B_FALSE;
2564565Sdp 		}
25650Sstevel@tonic-gate 	}
25660Sstevel@tonic-gate }
25670Sstevel@tonic-gate 
25680Sstevel@tonic-gate static int
fill_in_fstab(cmd_t * cmd,struct zone_fstab * fstab,boolean_t fill_in_only)25696215Sgjelinek fill_in_fstab(cmd_t *cmd, struct zone_fstab *fstab, boolean_t fill_in_only)
25700Sstevel@tonic-gate {
25710Sstevel@tonic-gate 	int err, i;
25720Sstevel@tonic-gate 	property_value_ptr_t pp;
25730Sstevel@tonic-gate 
25746215Sgjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
25750Sstevel@tonic-gate 		return (err);
25760Sstevel@tonic-gate 
25771086Svp157776 	bzero(fstab, sizeof (*fstab));
25780Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
25790Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[i];
25800Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
25810Sstevel@tonic-gate 			zerr(gettext("A simple value was expected here."));
25826215Sgjelinek 			saw_error = B_TRUE;
25830Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
25840Sstevel@tonic-gate 		}
25850Sstevel@tonic-gate 		switch (cmd->cmd_prop_name[i]) {
25860Sstevel@tonic-gate 		case PT_DIR:
25870Sstevel@tonic-gate 			(void) strlcpy(fstab->zone_fs_dir, pp->pv_simple,
25880Sstevel@tonic-gate 			    sizeof (fstab->zone_fs_dir));
25890Sstevel@tonic-gate 			break;
25900Sstevel@tonic-gate 		case PT_SPECIAL:
25910Sstevel@tonic-gate 			(void) strlcpy(fstab->zone_fs_special, pp->pv_simple,
25920Sstevel@tonic-gate 			    sizeof (fstab->zone_fs_special));
25930Sstevel@tonic-gate 			break;
25940Sstevel@tonic-gate 		case PT_RAW:
25950Sstevel@tonic-gate 			(void) strlcpy(fstab->zone_fs_raw, pp->pv_simple,
25960Sstevel@tonic-gate 			    sizeof (fstab->zone_fs_raw));
25970Sstevel@tonic-gate 			break;
25980Sstevel@tonic-gate 		case PT_TYPE:
25990Sstevel@tonic-gate 			(void) strlcpy(fstab->zone_fs_type, pp->pv_simple,
26000Sstevel@tonic-gate 			    sizeof (fstab->zone_fs_type));
26010Sstevel@tonic-gate 			break;
26020Sstevel@tonic-gate 		default:
26030Sstevel@tonic-gate 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
26046215Sgjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
26050Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
26060Sstevel@tonic-gate 		}
26070Sstevel@tonic-gate 	}
26080Sstevel@tonic-gate 	if (fill_in_only)
26090Sstevel@tonic-gate 		return (Z_OK);
26100Sstevel@tonic-gate 	return (zonecfg_lookup_filesystem(handle, fstab));
26110Sstevel@tonic-gate }
26120Sstevel@tonic-gate 
26130Sstevel@tonic-gate static int
fill_in_nwiftab(cmd_t * cmd,struct zone_nwiftab * nwiftab,boolean_t fill_in_only)26146215Sgjelinek fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab,
26156215Sgjelinek     boolean_t fill_in_only)
26160Sstevel@tonic-gate {
26170Sstevel@tonic-gate 	int err, i;
26180Sstevel@tonic-gate 	property_value_ptr_t pp;
26190Sstevel@tonic-gate 
26206215Sgjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
26210Sstevel@tonic-gate 		return (err);
26220Sstevel@tonic-gate 
26231086Svp157776 	bzero(nwiftab, sizeof (*nwiftab));
26240Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
26250Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[i];
26260Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
26270Sstevel@tonic-gate 			zerr(gettext("A simple value was expected here."));
26286215Sgjelinek 			saw_error = B_TRUE;
26290Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
26300Sstevel@tonic-gate 		}
26310Sstevel@tonic-gate 		switch (cmd->cmd_prop_name[i]) {
26320Sstevel@tonic-gate 		case PT_ADDRESS:
26330Sstevel@tonic-gate 			(void) strlcpy(nwiftab->zone_nwif_address,
26340Sstevel@tonic-gate 			    pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
26350Sstevel@tonic-gate 			break;
263612748SSowmini.Varadhan@oracle.COM 		case PT_ALLOWED_ADDRESS:
263712748SSowmini.Varadhan@oracle.COM 			(void) strlcpy(nwiftab->zone_nwif_allowed_address,
263812748SSowmini.Varadhan@oracle.COM 			    pp->pv_simple,
263912748SSowmini.Varadhan@oracle.COM 			    sizeof (nwiftab->zone_nwif_allowed_address));
264012748SSowmini.Varadhan@oracle.COM 			break;
26410Sstevel@tonic-gate 		case PT_PHYSICAL:
26420Sstevel@tonic-gate 			(void) strlcpy(nwiftab->zone_nwif_physical,
26430Sstevel@tonic-gate 			    pp->pv_simple,
26440Sstevel@tonic-gate 			    sizeof (nwiftab->zone_nwif_physical));
26450Sstevel@tonic-gate 			break;
26466076Sgfaden 		case PT_DEFROUTER:
26476076Sgfaden 			(void) strlcpy(nwiftab->zone_nwif_defrouter,
26486076Sgfaden 			    pp->pv_simple,
26496076Sgfaden 			    sizeof (nwiftab->zone_nwif_defrouter));
26506076Sgfaden 			break;
26510Sstevel@tonic-gate 		default:
26520Sstevel@tonic-gate 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
26536215Sgjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
26540Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
26550Sstevel@tonic-gate 		}
26560Sstevel@tonic-gate 	}
26570Sstevel@tonic-gate 	if (fill_in_only)
26580Sstevel@tonic-gate 		return (Z_OK);
26590Sstevel@tonic-gate 	err = zonecfg_lookup_nwif(handle, nwiftab);
26600Sstevel@tonic-gate 	return (err);
26610Sstevel@tonic-gate }
26620Sstevel@tonic-gate 
26630Sstevel@tonic-gate static int
fill_in_devtab(cmd_t * cmd,struct zone_devtab * devtab,boolean_t fill_in_only)26646215Sgjelinek fill_in_devtab(cmd_t *cmd, struct zone_devtab *devtab, boolean_t fill_in_only)
26650Sstevel@tonic-gate {
26660Sstevel@tonic-gate 	int err, i;
26670Sstevel@tonic-gate 	property_value_ptr_t pp;
26680Sstevel@tonic-gate 
26696215Sgjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
26700Sstevel@tonic-gate 		return (err);
26710Sstevel@tonic-gate 
26721086Svp157776 	bzero(devtab, sizeof (*devtab));
26730Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
26740Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[i];
26750Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
26760Sstevel@tonic-gate 			zerr(gettext("A simple value was expected here."));
26776215Sgjelinek 			saw_error = B_TRUE;
26780Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
26790Sstevel@tonic-gate 		}
26800Sstevel@tonic-gate 		switch (cmd->cmd_prop_name[i]) {
26810Sstevel@tonic-gate 		case PT_MATCH:
26820Sstevel@tonic-gate 			(void) strlcpy(devtab->zone_dev_match, pp->pv_simple,
26830Sstevel@tonic-gate 			    sizeof (devtab->zone_dev_match));
26840Sstevel@tonic-gate 			break;
26850Sstevel@tonic-gate 		default:
26860Sstevel@tonic-gate 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
26876215Sgjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
26880Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
26890Sstevel@tonic-gate 		}
26900Sstevel@tonic-gate 	}
26910Sstevel@tonic-gate 	if (fill_in_only)
26920Sstevel@tonic-gate 		return (Z_OK);
26930Sstevel@tonic-gate 	err = zonecfg_lookup_dev(handle, devtab);
26940Sstevel@tonic-gate 	return (err);
26950Sstevel@tonic-gate }
26960Sstevel@tonic-gate 
26970Sstevel@tonic-gate static int
fill_in_rctltab(cmd_t * cmd,struct zone_rctltab * rctltab,boolean_t fill_in_only)26986215Sgjelinek fill_in_rctltab(cmd_t *cmd, struct zone_rctltab *rctltab,
26996215Sgjelinek     boolean_t fill_in_only)
27000Sstevel@tonic-gate {
27010Sstevel@tonic-gate 	int err, i;
27020Sstevel@tonic-gate 	property_value_ptr_t pp;
27030Sstevel@tonic-gate 
27046215Sgjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
27050Sstevel@tonic-gate 		return (err);
27060Sstevel@tonic-gate 
27071086Svp157776 	bzero(rctltab, sizeof (*rctltab));
27080Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
27090Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[i];
27100Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
27110Sstevel@tonic-gate 			zerr(gettext("A simple value was expected here."));
27126215Sgjelinek 			saw_error = B_TRUE;
27130Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
27140Sstevel@tonic-gate 		}
27150Sstevel@tonic-gate 		switch (cmd->cmd_prop_name[i]) {
27160Sstevel@tonic-gate 		case PT_NAME:
27170Sstevel@tonic-gate 			(void) strlcpy(rctltab->zone_rctl_name, pp->pv_simple,
27180Sstevel@tonic-gate 			    sizeof (rctltab->zone_rctl_name));
27190Sstevel@tonic-gate 			break;
27200Sstevel@tonic-gate 		default:
27210Sstevel@tonic-gate 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
27226215Sgjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
27230Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
27240Sstevel@tonic-gate 		}
27250Sstevel@tonic-gate 	}
27260Sstevel@tonic-gate 	if (fill_in_only)
27270Sstevel@tonic-gate 		return (Z_OK);
27280Sstevel@tonic-gate 	err = zonecfg_lookup_rctl(handle, rctltab);
27290Sstevel@tonic-gate 	return (err);
27300Sstevel@tonic-gate }
27310Sstevel@tonic-gate 
27320Sstevel@tonic-gate static int
fill_in_attrtab(cmd_t * cmd,struct zone_attrtab * attrtab,boolean_t fill_in_only)27336215Sgjelinek fill_in_attrtab(cmd_t *cmd, struct zone_attrtab *attrtab,
27346215Sgjelinek     boolean_t fill_in_only)
27350Sstevel@tonic-gate {
27360Sstevel@tonic-gate 	int err, i;
27370Sstevel@tonic-gate 	property_value_ptr_t pp;
27380Sstevel@tonic-gate 
27396215Sgjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
27400Sstevel@tonic-gate 		return (err);
27410Sstevel@tonic-gate 
27421086Svp157776 	bzero(attrtab, sizeof (*attrtab));
27430Sstevel@tonic-gate 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
27440Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[i];
27450Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
27460Sstevel@tonic-gate 			zerr(gettext("A simple value was expected here."));
27476215Sgjelinek 			saw_error = B_TRUE;
27480Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
27490Sstevel@tonic-gate 		}
27500Sstevel@tonic-gate 		switch (cmd->cmd_prop_name[i]) {
27510Sstevel@tonic-gate 		case PT_NAME:
27520Sstevel@tonic-gate 			(void) strlcpy(attrtab->zone_attr_name, pp->pv_simple,
27530Sstevel@tonic-gate 			    sizeof (attrtab->zone_attr_name));
27540Sstevel@tonic-gate 			break;
27550Sstevel@tonic-gate 		case PT_TYPE:
27560Sstevel@tonic-gate 			(void) strlcpy(attrtab->zone_attr_type, pp->pv_simple,
27570Sstevel@tonic-gate 			    sizeof (attrtab->zone_attr_type));
27580Sstevel@tonic-gate 			break;
27590Sstevel@tonic-gate 		case PT_VALUE:
27600Sstevel@tonic-gate 			(void) strlcpy(attrtab->zone_attr_value, pp->pv_simple,
27610Sstevel@tonic-gate 			    sizeof (attrtab->zone_attr_value));
27620Sstevel@tonic-gate 			break;
27630Sstevel@tonic-gate 		default:
27640Sstevel@tonic-gate 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
27656215Sgjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
27660Sstevel@tonic-gate 			return (Z_INSUFFICIENT_SPEC);
27670Sstevel@tonic-gate 		}
27680Sstevel@tonic-gate 	}
27690Sstevel@tonic-gate 	if (fill_in_only)
27700Sstevel@tonic-gate 		return (Z_OK);
27710Sstevel@tonic-gate 	err = zonecfg_lookup_attr(handle, attrtab);
27720Sstevel@tonic-gate 	return (err);
27730Sstevel@tonic-gate }
27740Sstevel@tonic-gate 
2775789Sahrens static int
fill_in_dstab(cmd_t * cmd,struct zone_dstab * dstab,boolean_t fill_in_only)27766215Sgjelinek fill_in_dstab(cmd_t *cmd, struct zone_dstab *dstab, boolean_t fill_in_only)
2777789Sahrens {
2778789Sahrens 	int err, i;
2779789Sahrens 	property_value_ptr_t pp;
2780789Sahrens 
27816215Sgjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
2782789Sahrens 		return (err);
2783789Sahrens 
2784789Sahrens 	dstab->zone_dataset_name[0] = '\0';
2785789Sahrens 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2786789Sahrens 		pp = cmd->cmd_property_ptr[i];
2787789Sahrens 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2788789Sahrens 			zerr(gettext("A simple value was expected here."));
27896215Sgjelinek 			saw_error = B_TRUE;
2790789Sahrens 			return (Z_INSUFFICIENT_SPEC);
2791789Sahrens 		}
2792789Sahrens 		switch (cmd->cmd_prop_name[i]) {
2793789Sahrens 		case PT_NAME:
2794789Sahrens 			(void) strlcpy(dstab->zone_dataset_name, pp->pv_simple,
2795789Sahrens 			    sizeof (dstab->zone_dataset_name));
2796789Sahrens 			break;
2797789Sahrens 		default:
2798789Sahrens 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
27996215Sgjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
2800789Sahrens 			return (Z_INSUFFICIENT_SPEC);
2801789Sahrens 		}
2802789Sahrens 	}
2803789Sahrens 	if (fill_in_only)
2804789Sahrens 		return (Z_OK);
2805789Sahrens 	return (zonecfg_lookup_ds(handle, dstab));
2806789Sahrens }
2807789Sahrens 
280812578SGlenn.Faden@Sun.COM static int
fill_in_admintab(cmd_t * cmd,struct zone_admintab * admintab,boolean_t fill_in_only)280912578SGlenn.Faden@Sun.COM fill_in_admintab(cmd_t *cmd, struct zone_admintab *admintab,
281012578SGlenn.Faden@Sun.COM     boolean_t fill_in_only)
281112578SGlenn.Faden@Sun.COM {
281212578SGlenn.Faden@Sun.COM 	int err, i;
281312578SGlenn.Faden@Sun.COM 	property_value_ptr_t pp;
281412578SGlenn.Faden@Sun.COM 
281512578SGlenn.Faden@Sun.COM 	if ((err = initialize(B_TRUE)) != Z_OK)
281612578SGlenn.Faden@Sun.COM 		return (err);
281712578SGlenn.Faden@Sun.COM 
281812578SGlenn.Faden@Sun.COM 	bzero(admintab, sizeof (*admintab));
281912578SGlenn.Faden@Sun.COM 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
282012578SGlenn.Faden@Sun.COM 		pp = cmd->cmd_property_ptr[i];
282112578SGlenn.Faden@Sun.COM 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
282212578SGlenn.Faden@Sun.COM 			zerr(gettext("A simple value was expected here."));
282312578SGlenn.Faden@Sun.COM 			saw_error = B_TRUE;
282412578SGlenn.Faden@Sun.COM 			return (Z_INSUFFICIENT_SPEC);
282512578SGlenn.Faden@Sun.COM 		}
282612578SGlenn.Faden@Sun.COM 		switch (cmd->cmd_prop_name[i]) {
282712578SGlenn.Faden@Sun.COM 		case PT_USER:
282812578SGlenn.Faden@Sun.COM 			(void) strlcpy(admintab->zone_admin_user, pp->pv_simple,
282912578SGlenn.Faden@Sun.COM 			    sizeof (admintab->zone_admin_user));
283012578SGlenn.Faden@Sun.COM 			break;
283112578SGlenn.Faden@Sun.COM 		case PT_AUTHS:
283212578SGlenn.Faden@Sun.COM 			(void) strlcpy(admintab->zone_admin_auths,
283312578SGlenn.Faden@Sun.COM 			    pp->pv_simple, sizeof (admintab->zone_admin_auths));
283412578SGlenn.Faden@Sun.COM 			break;
283512578SGlenn.Faden@Sun.COM 		default:
283612578SGlenn.Faden@Sun.COM 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
283712578SGlenn.Faden@Sun.COM 			    Z_NO_PROPERTY_TYPE, B_TRUE);
283812578SGlenn.Faden@Sun.COM 			return (Z_INSUFFICIENT_SPEC);
283912578SGlenn.Faden@Sun.COM 		}
284012578SGlenn.Faden@Sun.COM 	}
284112578SGlenn.Faden@Sun.COM 	if (fill_in_only)
284212578SGlenn.Faden@Sun.COM 		return (Z_OK);
284312578SGlenn.Faden@Sun.COM 	err = zonecfg_lookup_admin(handle, admintab);
284412578SGlenn.Faden@Sun.COM 	return (err);
284512578SGlenn.Faden@Sun.COM }
284612578SGlenn.Faden@Sun.COM 
28470Sstevel@tonic-gate static void
remove_aliased_rctl(int type,char * name)28483247Sgjelinek remove_aliased_rctl(int type, char *name)
28493247Sgjelinek {
28503247Sgjelinek 	int err;
28513247Sgjelinek 	uint64_t tmp;
28523247Sgjelinek 
28533247Sgjelinek 	if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) {
28543247Sgjelinek 		zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
28553247Sgjelinek 		    zonecfg_strerror(err));
28566215Sgjelinek 		saw_error = B_TRUE;
28573247Sgjelinek 		return;
28583247Sgjelinek 	}
28593247Sgjelinek 	if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) {
28603247Sgjelinek 		zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
28613247Sgjelinek 		    zonecfg_strerror(err));
28626215Sgjelinek 		saw_error = B_TRUE;
28633247Sgjelinek 	} else {
28646215Sgjelinek 		need_to_commit = B_TRUE;
28653247Sgjelinek 	}
28663247Sgjelinek }
28673247Sgjelinek 
28683247Sgjelinek static boolean_t
prompt_remove_resource(cmd_t * cmd,char * rsrc)28693247Sgjelinek prompt_remove_resource(cmd_t *cmd, char *rsrc)
28700Sstevel@tonic-gate {
28713247Sgjelinek 	int num;
28723247Sgjelinek 	int answer;
28733247Sgjelinek 	int arg;
28743247Sgjelinek 	boolean_t force = B_FALSE;
28753247Sgjelinek 	char prompt[128];
28766215Sgjelinek 	boolean_t arg_err = B_FALSE;
28773247Sgjelinek 
28783247Sgjelinek 	optind = 0;
28793247Sgjelinek 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
28803247Sgjelinek 		switch (arg) {
28813247Sgjelinek 		case 'F':
28823247Sgjelinek 			force = B_TRUE;
28833247Sgjelinek 			break;
28843247Sgjelinek 		default:
28856215Sgjelinek 			arg_err = B_TRUE;
28863691Sgjelinek 			break;
28873691Sgjelinek 		}
28883691Sgjelinek 	}
28893691Sgjelinek 	if (arg_err)
28903691Sgjelinek 		return (B_FALSE);
28913691Sgjelinek 
28923247Sgjelinek 
28933247Sgjelinek 	num = zonecfg_num_resources(handle, rsrc);
28943247Sgjelinek 
28953247Sgjelinek 	if (num == 0) {
28963247Sgjelinek 		z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY,
28976215Sgjelinek 		    B_TRUE);
28983247Sgjelinek 		return (B_FALSE);
28993247Sgjelinek 	}
29003247Sgjelinek 	if (num > 1 && !force) {
29013247Sgjelinek 		if (!interactive_mode) {
29023247Sgjelinek 			zerr(gettext("There are multiple instances of this "
29033247Sgjelinek 			    "resource.  Either qualify the resource to\n"
29043247Sgjelinek 			    "remove a single instance or use the -F option to "
29053247Sgjelinek 			    "remove all instances."));
29066215Sgjelinek 			saw_error = B_TRUE;
29073247Sgjelinek 			return (B_FALSE);
29083247Sgjelinek 		}
29093247Sgjelinek 		(void) snprintf(prompt, sizeof (prompt), gettext(
29103247Sgjelinek 		    "Are you sure you want to remove ALL '%s' resources"),
29113247Sgjelinek 		    rsrc);
29126215Sgjelinek 		answer = ask_yesno(B_FALSE, prompt);
29133247Sgjelinek 		if (answer == -1) {
29143247Sgjelinek 			zerr(gettext("Resource incomplete."));
29153247Sgjelinek 			return (B_FALSE);
29163247Sgjelinek 		}
29173247Sgjelinek 		if (answer != 1)
29183247Sgjelinek 			return (B_FALSE);
29193247Sgjelinek 	}
29203247Sgjelinek 	return (B_TRUE);
29213247Sgjelinek }
29223247Sgjelinek 
29233247Sgjelinek static void
remove_fs(cmd_t * cmd)29243247Sgjelinek remove_fs(cmd_t *cmd)
29253247Sgjelinek {
29263247Sgjelinek 	int err;
29273247Sgjelinek 
29283247Sgjelinek 	/* traditional, qualified fs removal */
29293247Sgjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
29303247Sgjelinek 		struct zone_fstab fstab;
29313247Sgjelinek 
29326215Sgjelinek 		if ((err = fill_in_fstab(cmd, &fstab, B_FALSE)) != Z_OK) {
29336215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
29340Sstevel@tonic-gate 			return;
29350Sstevel@tonic-gate 		}
29360Sstevel@tonic-gate 		if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK)
29376215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
29380Sstevel@tonic-gate 		else
29396215Sgjelinek 			need_to_commit = B_TRUE;
29400Sstevel@tonic-gate 		zonecfg_free_fs_option_list(fstab.zone_fs_options);
29410Sstevel@tonic-gate 		return;
29423247Sgjelinek 	}
29433247Sgjelinek 
29443247Sgjelinek 	/*
29453247Sgjelinek 	 * unqualified fs removal.  remove all fs's but prompt if more
29463247Sgjelinek 	 * than one.
29473247Sgjelinek 	 */
29483247Sgjelinek 	if (!prompt_remove_resource(cmd, "fs"))
29493247Sgjelinek 		return;
29503247Sgjelinek 
29513247Sgjelinek 	if ((err = zonecfg_del_all_resources(handle, "fs")) != Z_OK)
29526215Sgjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
29533247Sgjelinek 	else
29546215Sgjelinek 		need_to_commit = B_TRUE;
29553247Sgjelinek }
29563247Sgjelinek 
29573247Sgjelinek static void
remove_net(cmd_t * cmd)29583247Sgjelinek remove_net(cmd_t *cmd)
29593247Sgjelinek {
29603247Sgjelinek 	int err;
29613247Sgjelinek 
29623247Sgjelinek 	/* traditional, qualified net removal */
29633247Sgjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
29643247Sgjelinek 		struct zone_nwiftab nwiftab;
29653247Sgjelinek 
29666215Sgjelinek 		if ((err = fill_in_nwiftab(cmd, &nwiftab, B_FALSE)) != Z_OK) {
29676215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
29680Sstevel@tonic-gate 			return;
29690Sstevel@tonic-gate 		}
29700Sstevel@tonic-gate 		if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK)
29716215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
29720Sstevel@tonic-gate 		else
29736215Sgjelinek 			need_to_commit = B_TRUE;
29740Sstevel@tonic-gate 		return;
29753247Sgjelinek 	}
29763247Sgjelinek 
29773247Sgjelinek 	/*
29783247Sgjelinek 	 * unqualified net removal.  remove all nets but prompt if more
29793247Sgjelinek 	 * than one.
29803247Sgjelinek 	 */
29813247Sgjelinek 	if (!prompt_remove_resource(cmd, "net"))
29823247Sgjelinek 		return;
29833247Sgjelinek 
29843247Sgjelinek 	if ((err = zonecfg_del_all_resources(handle, "net")) != Z_OK)
29856215Sgjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
29863247Sgjelinek 	else
29876215Sgjelinek 		need_to_commit = B_TRUE;
29883247Sgjelinek }
29893247Sgjelinek 
29903247Sgjelinek static void
remove_device(cmd_t * cmd)29913247Sgjelinek remove_device(cmd_t *cmd)
29923247Sgjelinek {
29933247Sgjelinek 	int err;
29943247Sgjelinek 
29953247Sgjelinek 	/* traditional, qualified device removal */
29963247Sgjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
29973247Sgjelinek 		struct zone_devtab devtab;
29983247Sgjelinek 
29996215Sgjelinek 		if ((err = fill_in_devtab(cmd, &devtab, B_FALSE)) != Z_OK) {
30006215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
30010Sstevel@tonic-gate 			return;
30020Sstevel@tonic-gate 		}
30030Sstevel@tonic-gate 		if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK)
30046215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
30050Sstevel@tonic-gate 		else
30066215Sgjelinek 			need_to_commit = B_TRUE;
30070Sstevel@tonic-gate 		return;
30083247Sgjelinek 	}
30093247Sgjelinek 
30103247Sgjelinek 	/*
30113247Sgjelinek 	 * unqualified device removal.  remove all devices but prompt if more
30123247Sgjelinek 	 * than one.
30133247Sgjelinek 	 */
30143247Sgjelinek 	if (!prompt_remove_resource(cmd, "device"))
30153247Sgjelinek 		return;
30163247Sgjelinek 
30173247Sgjelinek 	if ((err = zonecfg_del_all_resources(handle, "device")) != Z_OK)
30186215Sgjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
30193247Sgjelinek 	else
30206215Sgjelinek 		need_to_commit = B_TRUE;
30213247Sgjelinek }
30223247Sgjelinek 
30233247Sgjelinek static void
remove_attr(cmd_t * cmd)30243247Sgjelinek remove_attr(cmd_t *cmd)
30253247Sgjelinek {
30263247Sgjelinek 	int err;
30273247Sgjelinek 
30283247Sgjelinek 	/* traditional, qualified attr removal */
30293247Sgjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
30303247Sgjelinek 		struct zone_attrtab attrtab;
30313247Sgjelinek 
30326215Sgjelinek 		if ((err = fill_in_attrtab(cmd, &attrtab, B_FALSE)) != Z_OK) {
30336215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
30343247Sgjelinek 			return;
30353247Sgjelinek 		}
30363247Sgjelinek 		if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK)
30376215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
30383247Sgjelinek 		else
30396215Sgjelinek 			need_to_commit = B_TRUE;
30403247Sgjelinek 		return;
30413247Sgjelinek 	}
30423247Sgjelinek 
30433247Sgjelinek 	/*
30443247Sgjelinek 	 * unqualified attr removal.  remove all attrs but prompt if more
30453247Sgjelinek 	 * than one.
30463247Sgjelinek 	 */
30473247Sgjelinek 	if (!prompt_remove_resource(cmd, "attr"))
30483247Sgjelinek 		return;
30493247Sgjelinek 
30503247Sgjelinek 	if ((err = zonecfg_del_all_resources(handle, "attr")) != Z_OK)
30516215Sgjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
30523247Sgjelinek 	else
30536215Sgjelinek 		need_to_commit = B_TRUE;
30543247Sgjelinek }
30553247Sgjelinek 
30563247Sgjelinek static void
remove_dataset(cmd_t * cmd)30573247Sgjelinek remove_dataset(cmd_t *cmd)
30583247Sgjelinek {
30593247Sgjelinek 	int err;
30603247Sgjelinek 
30613247Sgjelinek 	/* traditional, qualified dataset removal */
30623247Sgjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
30633247Sgjelinek 		struct zone_dstab dstab;
30643247Sgjelinek 
30656215Sgjelinek 		if ((err = fill_in_dstab(cmd, &dstab, B_FALSE)) != Z_OK) {
30666215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
30673247Sgjelinek 			return;
30683247Sgjelinek 		}
30693247Sgjelinek 		if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK)
30706215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
30713247Sgjelinek 		else
30726215Sgjelinek 			need_to_commit = B_TRUE;
30733247Sgjelinek 		return;
30743247Sgjelinek 	}
30753247Sgjelinek 
30763247Sgjelinek 	/*
30773247Sgjelinek 	 * unqualified dataset removal.  remove all datasets but prompt if more
30783247Sgjelinek 	 * than one.
30793247Sgjelinek 	 */
30803247Sgjelinek 	if (!prompt_remove_resource(cmd, "dataset"))
30813247Sgjelinek 		return;
30823247Sgjelinek 
30833247Sgjelinek 	if ((err = zonecfg_del_all_resources(handle, "dataset")) != Z_OK)
30846215Sgjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
30853247Sgjelinek 	else
30866215Sgjelinek 		need_to_commit = B_TRUE;
30873247Sgjelinek }
30883247Sgjelinek 
30893247Sgjelinek static void
remove_rctl(cmd_t * cmd)30903247Sgjelinek remove_rctl(cmd_t *cmd)
30913247Sgjelinek {
30923247Sgjelinek 	int err;
30933247Sgjelinek 
30943247Sgjelinek 	/* traditional, qualified rctl removal */
30953247Sgjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
30963247Sgjelinek 		struct zone_rctltab rctltab;
30973247Sgjelinek 
30986215Sgjelinek 		if ((err = fill_in_rctltab(cmd, &rctltab, B_FALSE)) != Z_OK) {
30996215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
31000Sstevel@tonic-gate 			return;
31010Sstevel@tonic-gate 		}
31020Sstevel@tonic-gate 		if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK)
31036215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
31040Sstevel@tonic-gate 		else
31056215Sgjelinek 			need_to_commit = B_TRUE;
31060Sstevel@tonic-gate 		zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
31070Sstevel@tonic-gate 		return;
31083247Sgjelinek 	}
31093247Sgjelinek 
31103247Sgjelinek 	/*
31113247Sgjelinek 	 * unqualified rctl removal.  remove all rctls but prompt if more
31123247Sgjelinek 	 * than one.
31133247Sgjelinek 	 */
31143247Sgjelinek 	if (!prompt_remove_resource(cmd, "rctl"))
31153247Sgjelinek 		return;
31163247Sgjelinek 
31173247Sgjelinek 	if ((err = zonecfg_del_all_resources(handle, "rctl")) != Z_OK)
31186215Sgjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
31193247Sgjelinek 	else
31206215Sgjelinek 		need_to_commit = B_TRUE;
31213247Sgjelinek }
31223247Sgjelinek 
31233247Sgjelinek static void
remove_pset()31243247Sgjelinek remove_pset()
31253247Sgjelinek {
31263247Sgjelinek 	int err;
31273247Sgjelinek 	struct zone_psettab psettab;
31283247Sgjelinek 
31293247Sgjelinek 	if ((err = zonecfg_lookup_pset(handle, &psettab)) != Z_OK) {
31306215Sgjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
31313247Sgjelinek 		return;
31323247Sgjelinek 	}
31333247Sgjelinek 	if ((err = zonecfg_delete_pset(handle)) != Z_OK)
31346215Sgjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
31353247Sgjelinek 	else
31366215Sgjelinek 		need_to_commit = B_TRUE;
31373247Sgjelinek }
31383247Sgjelinek 
31393247Sgjelinek static void
remove_pcap()31403792Sakolb remove_pcap()
31413792Sakolb {
31423792Sakolb 	int err;
31433792Sakolb 	uint64_t tmp;
31443792Sakolb 
31453792Sakolb 	if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) {
31463792Sakolb 		zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_PCAP),
31473792Sakolb 		    zonecfg_strerror(Z_NO_RESOURCE_TYPE));
31486215Sgjelinek 		saw_error = B_TRUE;
31493792Sakolb 		return;
31503792Sakolb 	}
31513792Sakolb 
31523792Sakolb 	if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK)
31536215Sgjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE);
31543792Sakolb 	else
31556215Sgjelinek 		need_to_commit = B_TRUE;
31563792Sakolb }
31573792Sakolb 
31583792Sakolb static void
remove_mcap()31593247Sgjelinek remove_mcap()
31603247Sgjelinek {
31613247Sgjelinek 	int err, res1, res2, res3;
31623247Sgjelinek 	uint64_t tmp;
31633247Sgjelinek 	struct zone_mcaptab mcaptab;
31643247Sgjelinek 	boolean_t revert = B_FALSE;
31653247Sgjelinek 
31663247Sgjelinek 	res1 = zonecfg_lookup_mcap(handle, &mcaptab);
31673247Sgjelinek 	res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp);
31683247Sgjelinek 	res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp);
31693247Sgjelinek 
31703247Sgjelinek 	/* if none of these exist, there is no resource to remove */
31713247Sgjelinek 	if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
31723247Sgjelinek 		zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_MCAP),
31733247Sgjelinek 		    zonecfg_strerror(Z_NO_RESOURCE_TYPE));
31746215Sgjelinek 		saw_error = B_TRUE;
31753247Sgjelinek 		return;
31763247Sgjelinek 	}
31773247Sgjelinek 	if (res1 == Z_OK) {
31783247Sgjelinek 		if ((err = zonecfg_delete_mcap(handle)) != Z_OK) {
31796215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
31803247Sgjelinek 			revert = B_TRUE;
31813247Sgjelinek 		} else {
31826215Sgjelinek 			need_to_commit = B_TRUE;
31833247Sgjelinek 		}
31843247Sgjelinek 	}
31853247Sgjelinek 	if (res2 == Z_OK) {
31863247Sgjelinek 		if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP))
31873247Sgjelinek 		    != Z_OK) {
31886215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
31893247Sgjelinek 			revert = B_TRUE;
31903247Sgjelinek 		} else {
31916215Sgjelinek 			need_to_commit = B_TRUE;
31923247Sgjelinek 		}
31933247Sgjelinek 	}
31943247Sgjelinek 	if (res3 == Z_OK) {
31953247Sgjelinek 		if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM))
31963247Sgjelinek 		    != Z_OK) {
31976215Sgjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
31983247Sgjelinek 			revert = B_TRUE;
31993247Sgjelinek 		} else {
32006215Sgjelinek 			need_to_commit = B_TRUE;
32013247Sgjelinek 		}
32023247Sgjelinek 	}
32033247Sgjelinek 
32043247Sgjelinek 	if (revert)
32056215Sgjelinek 		need_to_commit = B_FALSE;
32063247Sgjelinek }
32073247Sgjelinek 
32083247Sgjelinek static void
remove_admin(cmd_t * cmd)320912578SGlenn.Faden@Sun.COM remove_admin(cmd_t *cmd)
321012578SGlenn.Faden@Sun.COM {
321112578SGlenn.Faden@Sun.COM 	int err;
321212578SGlenn.Faden@Sun.COM 
321312578SGlenn.Faden@Sun.COM 	/* traditional, qualified attr removal */
321412578SGlenn.Faden@Sun.COM 	if (cmd->cmd_prop_nv_pairs > 0) {
321512578SGlenn.Faden@Sun.COM 		struct zone_admintab admintab;
321612578SGlenn.Faden@Sun.COM 
321712578SGlenn.Faden@Sun.COM 		if ((err = fill_in_admintab(cmd, &admintab, B_FALSE)) != Z_OK) {
321812578SGlenn.Faden@Sun.COM 			z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
321912578SGlenn.Faden@Sun.COM 			    err, B_TRUE);
322012578SGlenn.Faden@Sun.COM 			return;
322112578SGlenn.Faden@Sun.COM 		}
322212578SGlenn.Faden@Sun.COM 		if ((err = zonecfg_delete_admin(handle, &admintab,
322312578SGlenn.Faden@Sun.COM 		    zone))
322412578SGlenn.Faden@Sun.COM 		    != Z_OK)
322512578SGlenn.Faden@Sun.COM 			z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
322612578SGlenn.Faden@Sun.COM 			    err, B_TRUE);
322712578SGlenn.Faden@Sun.COM 		else
322812578SGlenn.Faden@Sun.COM 			need_to_commit = B_TRUE;
322912578SGlenn.Faden@Sun.COM 		return;
323012578SGlenn.Faden@Sun.COM 	} else {
323112578SGlenn.Faden@Sun.COM 		/*
323212578SGlenn.Faden@Sun.COM 		 * unqualified admin removal.
323312578SGlenn.Faden@Sun.COM 		 * remove all admins but prompt if more
323412578SGlenn.Faden@Sun.COM 		 * than one.
323512578SGlenn.Faden@Sun.COM 		 */
323612578SGlenn.Faden@Sun.COM 		if (!prompt_remove_resource(cmd, "admin"))
323712578SGlenn.Faden@Sun.COM 			return;
323812578SGlenn.Faden@Sun.COM 
323912578SGlenn.Faden@Sun.COM 		if ((err = zonecfg_delete_admins(handle, zone))
324012578SGlenn.Faden@Sun.COM 		    != Z_OK)
324112578SGlenn.Faden@Sun.COM 			z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
324212578SGlenn.Faden@Sun.COM 			    err, B_TRUE);
324312578SGlenn.Faden@Sun.COM 		else
324412578SGlenn.Faden@Sun.COM 			need_to_commit = B_TRUE;
324512578SGlenn.Faden@Sun.COM 	}
324612578SGlenn.Faden@Sun.COM }
324712578SGlenn.Faden@Sun.COM 
324812578SGlenn.Faden@Sun.COM static void
remove_resource(cmd_t * cmd)32493247Sgjelinek remove_resource(cmd_t *cmd)
32503247Sgjelinek {
32513247Sgjelinek 	int type;
32523247Sgjelinek 	int arg;
32536215Sgjelinek 	boolean_t arg_err = B_FALSE;
32543247Sgjelinek 
32553247Sgjelinek 	if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
32566215Sgjelinek 		long_usage(CMD_REMOVE, B_TRUE);
32573247Sgjelinek 		return;
32583247Sgjelinek 	}
32593247Sgjelinek 
32603247Sgjelinek 	optind = 0;
32613247Sgjelinek 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
32623247Sgjelinek 		switch (arg) {
32633247Sgjelinek 		case '?':
32643247Sgjelinek 			longer_usage(CMD_REMOVE);
32656215Sgjelinek 			arg_err = B_TRUE;
32663691Sgjelinek 			break;
32673247Sgjelinek 		case 'F':
32683247Sgjelinek 			break;
32693247Sgjelinek 		default:
32703247Sgjelinek 			short_usage(CMD_REMOVE);
32716215Sgjelinek 			arg_err = B_TRUE;
32723691Sgjelinek 			break;
32733691Sgjelinek 		}
32743691Sgjelinek 	}
32753691Sgjelinek 	if (arg_err)
32763691Sgjelinek 		return;
32773247Sgjelinek 
32786215Sgjelinek 	if (initialize(B_TRUE) != Z_OK)
32793247Sgjelinek 		return;
32803247Sgjelinek 
32813247Sgjelinek 	switch (type) {
32823247Sgjelinek 	case RT_FS:
32833247Sgjelinek 		remove_fs(cmd);
32843247Sgjelinek 		return;
32853247Sgjelinek 	case RT_NET:
32863247Sgjelinek 		remove_net(cmd);
32873247Sgjelinek 		return;
32883247Sgjelinek 	case RT_DEVICE:
32893247Sgjelinek 		remove_device(cmd);
32903247Sgjelinek 		return;
32913247Sgjelinek 	case RT_RCTL:
32923247Sgjelinek 		remove_rctl(cmd);
32933247Sgjelinek 		return;
32943247Sgjelinek 	case RT_ATTR:
32953247Sgjelinek 		remove_attr(cmd);
32960Sstevel@tonic-gate 		return;
3297789Sahrens 	case RT_DATASET:
32983247Sgjelinek 		remove_dataset(cmd);
32993247Sgjelinek 		return;
33003247Sgjelinek 	case RT_DCPU:
33013247Sgjelinek 		remove_pset();
33023247Sgjelinek 		return;
33033792Sakolb 	case RT_PCAP:
33043792Sakolb 		remove_pcap();
33053792Sakolb 		return;
33063247Sgjelinek 	case RT_MCAP:
33073247Sgjelinek 		remove_mcap();
3308789Sahrens 		return;
330912578SGlenn.Faden@Sun.COM 	case RT_ADMIN:
331012578SGlenn.Faden@Sun.COM 		remove_admin(cmd);
331112578SGlenn.Faden@Sun.COM 		return;
33120Sstevel@tonic-gate 	default:
33136215Sgjelinek 		zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
33146215Sgjelinek 		long_usage(CMD_REMOVE, B_TRUE);
33156215Sgjelinek 		usage(B_FALSE, HELP_RESOURCES);
33160Sstevel@tonic-gate 		return;
33170Sstevel@tonic-gate 	}
33180Sstevel@tonic-gate }
33190Sstevel@tonic-gate 
33200Sstevel@tonic-gate static void
remove_property(cmd_t * cmd)33210Sstevel@tonic-gate remove_property(cmd_t *cmd)
33220Sstevel@tonic-gate {
33230Sstevel@tonic-gate 	char *prop_id;
33240Sstevel@tonic-gate 	int err, res_type, prop_type;
33250Sstevel@tonic-gate 	property_value_ptr_t pp;
33260Sstevel@tonic-gate 	struct zone_rctlvaltab *rctlvaltab;
33270Sstevel@tonic-gate 	complex_property_ptr_t cx;
33280Sstevel@tonic-gate 
33290Sstevel@tonic-gate 	res_type = resource_scope;
33300Sstevel@tonic-gate 	prop_type = cmd->cmd_prop_name[0];
33310Sstevel@tonic-gate 	if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
33326215Sgjelinek 		long_usage(CMD_REMOVE, B_TRUE);
33330Sstevel@tonic-gate 		return;
33340Sstevel@tonic-gate 	}
33350Sstevel@tonic-gate 
33360Sstevel@tonic-gate 	if (cmd->cmd_prop_nv_pairs != 1) {
33376215Sgjelinek 		long_usage(CMD_ADD, B_TRUE);
33386215Sgjelinek 		return;
33396215Sgjelinek 	}
33406215Sgjelinek 
33416215Sgjelinek 	if (initialize(B_TRUE) != Z_OK)
33420Sstevel@tonic-gate 		return;
33430Sstevel@tonic-gate 
33440Sstevel@tonic-gate 	switch (res_type) {
33450Sstevel@tonic-gate 	case RT_FS:
33460Sstevel@tonic-gate 		if (prop_type != PT_OPTIONS) {
33470Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
33486215Sgjelinek 			    B_TRUE);
33496215Sgjelinek 			long_usage(CMD_REMOVE, B_TRUE);
33506215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
33510Sstevel@tonic-gate 			return;
33520Sstevel@tonic-gate 		}
33530Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[0];
33540Sstevel@tonic-gate 		if (pp->pv_type == PROP_VAL_COMPLEX) {
33550Sstevel@tonic-gate 			zerr(gettext("A %s or %s value was expected here."),
33560Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_SIMPLE),
33570Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_LIST));
33586215Sgjelinek 			saw_error = B_TRUE;
33590Sstevel@tonic-gate 			return;
33600Sstevel@tonic-gate 		}
33610Sstevel@tonic-gate 		if (pp->pv_type == PROP_VAL_SIMPLE) {
33620Sstevel@tonic-gate 			if (pp->pv_simple == NULL) {
33636215Sgjelinek 				long_usage(CMD_ADD, B_TRUE);
33640Sstevel@tonic-gate 				return;
33650Sstevel@tonic-gate 			}
33660Sstevel@tonic-gate 			prop_id = pp->pv_simple;
33670Sstevel@tonic-gate 			err = zonecfg_remove_fs_option(&in_progress_fstab,
33680Sstevel@tonic-gate 			    prop_id);
33690Sstevel@tonic-gate 			if (err != Z_OK)
33706215Sgjelinek 				zone_perror(pt_to_str(prop_type), err, B_TRUE);
33710Sstevel@tonic-gate 		} else {
33720Sstevel@tonic-gate 			list_property_ptr_t list;
33730Sstevel@tonic-gate 
33740Sstevel@tonic-gate 			for (list = pp->pv_list; list != NULL;
33750Sstevel@tonic-gate 			    list = list->lp_next) {
33760Sstevel@tonic-gate 				prop_id = list->lp_simple;
33770Sstevel@tonic-gate 				if (prop_id == NULL)
33780Sstevel@tonic-gate 					break;
33790Sstevel@tonic-gate 				err = zonecfg_remove_fs_option(
33800Sstevel@tonic-gate 				    &in_progress_fstab, prop_id);
33810Sstevel@tonic-gate 				if (err != Z_OK)
33820Sstevel@tonic-gate 					zone_perror(pt_to_str(prop_type), err,
33836215Sgjelinek 					    B_TRUE);
33840Sstevel@tonic-gate 			}
33850Sstevel@tonic-gate 		}
33860Sstevel@tonic-gate 		return;
33870Sstevel@tonic-gate 	case RT_RCTL:
33880Sstevel@tonic-gate 		if (prop_type != PT_VALUE) {
33890Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
33906215Sgjelinek 			    B_TRUE);
33916215Sgjelinek 			long_usage(CMD_REMOVE, B_TRUE);
33926215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
33930Sstevel@tonic-gate 			return;
33940Sstevel@tonic-gate 		}
33950Sstevel@tonic-gate 		pp = cmd->cmd_property_ptr[0];
33960Sstevel@tonic-gate 		if (pp->pv_type != PROP_VAL_COMPLEX) {
33970Sstevel@tonic-gate 			zerr(gettext("A %s value was expected here."),
33980Sstevel@tonic-gate 			    pvt_to_str(PROP_VAL_COMPLEX));
33996215Sgjelinek 			saw_error = B_TRUE;
34000Sstevel@tonic-gate 			return;
34010Sstevel@tonic-gate 		}
34020Sstevel@tonic-gate 		if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
34036215Sgjelinek 			zone_perror(zone, Z_NOMEM, B_TRUE);
34040Sstevel@tonic-gate 			exit(Z_ERR);
34050Sstevel@tonic-gate 		}
34060Sstevel@tonic-gate 		for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) {
34070Sstevel@tonic-gate 			switch (cx->cp_type) {
34080Sstevel@tonic-gate 			case PT_PRIV:
34090Sstevel@tonic-gate 				(void) strlcpy(rctlvaltab->zone_rctlval_priv,
34100Sstevel@tonic-gate 				    cx->cp_value,
34110Sstevel@tonic-gate 				    sizeof (rctlvaltab->zone_rctlval_priv));
34120Sstevel@tonic-gate 				break;
34130Sstevel@tonic-gate 			case PT_LIMIT:
34140Sstevel@tonic-gate 				(void) strlcpy(rctlvaltab->zone_rctlval_limit,
34150Sstevel@tonic-gate 				    cx->cp_value,
34160Sstevel@tonic-gate 				    sizeof (rctlvaltab->zone_rctlval_limit));
34170Sstevel@tonic-gate 				break;
34180Sstevel@tonic-gate 			case PT_ACTION:
34190Sstevel@tonic-gate 				(void) strlcpy(rctlvaltab->zone_rctlval_action,
34200Sstevel@tonic-gate 				    cx->cp_value,
34210Sstevel@tonic-gate 				    sizeof (rctlvaltab->zone_rctlval_action));
34220Sstevel@tonic-gate 				break;
34230Sstevel@tonic-gate 			default:
34240Sstevel@tonic-gate 				zone_perror(pt_to_str(prop_type),
34256215Sgjelinek 				    Z_NO_PROPERTY_TYPE, B_TRUE);
34266215Sgjelinek 				long_usage(CMD_ADD, B_TRUE);
34276215Sgjelinek 				usage(B_FALSE, HELP_PROPS);
34280Sstevel@tonic-gate 				zonecfg_free_rctl_value_list(rctlvaltab);
34290Sstevel@tonic-gate 				return;
34300Sstevel@tonic-gate 			}
34310Sstevel@tonic-gate 		}
34320Sstevel@tonic-gate 		rctlvaltab->zone_rctlval_next = NULL;
34330Sstevel@tonic-gate 		err = zonecfg_remove_rctl_value(&in_progress_rctltab,
34340Sstevel@tonic-gate 		    rctlvaltab);
34350Sstevel@tonic-gate 		if (err != Z_OK)
34366215Sgjelinek 			zone_perror(pt_to_str(prop_type), err, B_TRUE);
34370Sstevel@tonic-gate 		zonecfg_free_rctl_value_list(rctlvaltab);
34380Sstevel@tonic-gate 		return;
34396076Sgfaden 	case RT_NET:
34406076Sgfaden 		if (prop_type != PT_DEFROUTER) {
34416076Sgfaden 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
34426215Sgjelinek 			    B_TRUE);
34436215Sgjelinek 			long_usage(CMD_REMOVE, B_TRUE);
34446215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
34456076Sgfaden 			return;
34466076Sgfaden 		} else {
34476076Sgfaden 			bzero(&in_progress_nwiftab.zone_nwif_defrouter,
34486076Sgfaden 			    sizeof (in_progress_nwiftab.zone_nwif_defrouter));
34496076Sgfaden 			return;
34506076Sgfaden 		}
34510Sstevel@tonic-gate 	default:
34526215Sgjelinek 		zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
34536215Sgjelinek 		long_usage(CMD_REMOVE, B_TRUE);
34546215Sgjelinek 		usage(B_FALSE, HELP_RESOURCES);
34550Sstevel@tonic-gate 		return;
34560Sstevel@tonic-gate 	}
34570Sstevel@tonic-gate }
34580Sstevel@tonic-gate 
34590Sstevel@tonic-gate void
remove_func(cmd_t * cmd)34600Sstevel@tonic-gate remove_func(cmd_t *cmd)
34610Sstevel@tonic-gate {
34620Sstevel@tonic-gate 	if (zone_is_read_only(CMD_REMOVE))
34630Sstevel@tonic-gate 		return;
34640Sstevel@tonic-gate 
34650Sstevel@tonic-gate 	assert(cmd != NULL);
34660Sstevel@tonic-gate 
34673247Sgjelinek 	if (global_scope) {
34683247Sgjelinek 		if (gz_invalid_resource(cmd->cmd_res_type)) {
34693247Sgjelinek 			zerr(gettext("%s is not a valid resource for the "
34703247Sgjelinek 			    "global zone."), rt_to_str(cmd->cmd_res_type));
34716215Sgjelinek 			saw_error = B_TRUE;
34723247Sgjelinek 			return;
34733247Sgjelinek 		}
34740Sstevel@tonic-gate 		remove_resource(cmd);
34753247Sgjelinek 	} else {
34760Sstevel@tonic-gate 		remove_property(cmd);
34773247Sgjelinek 	}
34783247Sgjelinek }
34793247Sgjelinek 
34803247Sgjelinek static void
clear_property(cmd_t * cmd)34813247Sgjelinek clear_property(cmd_t *cmd)
34823247Sgjelinek {
34833247Sgjelinek 	int res_type, prop_type;
34843247Sgjelinek 
34853247Sgjelinek 	res_type = resource_scope;
34863247Sgjelinek 	prop_type = cmd->cmd_res_type;
34873247Sgjelinek 	if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
34886215Sgjelinek 		long_usage(CMD_CLEAR, B_TRUE);
34896215Sgjelinek 		return;
34906215Sgjelinek 	}
34916215Sgjelinek 
34926215Sgjelinek 	if (initialize(B_TRUE) != Z_OK)
34933247Sgjelinek 		return;
34943247Sgjelinek 
34953247Sgjelinek 	switch (res_type) {
34963247Sgjelinek 	case RT_FS:
34973247Sgjelinek 		if (prop_type == PT_RAW) {
34983247Sgjelinek 			in_progress_fstab.zone_fs_raw[0] = '\0';
34996215Sgjelinek 			need_to_commit = B_TRUE;
35003247Sgjelinek 			return;
35013247Sgjelinek 		}
35023247Sgjelinek 		break;
35033247Sgjelinek 	case RT_DCPU:
35043247Sgjelinek 		if (prop_type == PT_IMPORTANCE) {
35053247Sgjelinek 			in_progress_psettab.zone_importance[0] = '\0';
35066215Sgjelinek 			need_to_commit = B_TRUE;
35073247Sgjelinek 			return;
35083247Sgjelinek 		}
35093247Sgjelinek 		break;
35103247Sgjelinek 	case RT_MCAP:
35113247Sgjelinek 		switch (prop_type) {
35123247Sgjelinek 		case PT_PHYSICAL:
35133247Sgjelinek 			in_progress_mcaptab.zone_physmem_cap[0] = '\0';
35146215Sgjelinek 			need_to_commit = B_TRUE;
35153247Sgjelinek 			return;
35163247Sgjelinek 		case PT_SWAP:
35173247Sgjelinek 			remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
35183247Sgjelinek 			return;
35193247Sgjelinek 		case PT_LOCKED:
35203247Sgjelinek 			remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
35213247Sgjelinek 			return;
35223247Sgjelinek 		}
35233247Sgjelinek 		break;
35243247Sgjelinek 	default:
35253247Sgjelinek 		break;
35263247Sgjelinek 	}
35273247Sgjelinek 
35286215Sgjelinek 	zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE);
35293247Sgjelinek }
35303247Sgjelinek 
35313247Sgjelinek static void
clear_global(cmd_t * cmd)35323247Sgjelinek clear_global(cmd_t *cmd)
35333247Sgjelinek {
35343247Sgjelinek 	int err, type;
35353247Sgjelinek 
35363247Sgjelinek 	if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
35376215Sgjelinek 		long_usage(CMD_CLEAR, B_TRUE);
35386215Sgjelinek 		return;
35396215Sgjelinek 	}
35406215Sgjelinek 
35416215Sgjelinek 	if (initialize(B_TRUE) != Z_OK)
35423247Sgjelinek 		return;
35433247Sgjelinek 
35443247Sgjelinek 	switch (type) {
35453247Sgjelinek 	case PT_ZONENAME:
35463247Sgjelinek 		/* FALLTHRU */
35473247Sgjelinek 	case PT_ZONEPATH:
35483247Sgjelinek 		/* FALLTHRU */
35493247Sgjelinek 	case PT_BRAND:
35506215Sgjelinek 		zone_perror(pt_to_str(type), Z_CLEAR_DISALLOW, B_TRUE);
35513247Sgjelinek 		return;
35523247Sgjelinek 	case PT_AUTOBOOT:
35533247Sgjelinek 		/* false is default; we'll treat as equivalent to clearing */
35543247Sgjelinek 		if ((err = zonecfg_set_autoboot(handle, B_FALSE)) != Z_OK)
35556215Sgjelinek 			z_cmd_rt_perror(CMD_CLEAR, RT_AUTOBOOT, err, B_TRUE);
35563247Sgjelinek 		else
35576215Sgjelinek 			need_to_commit = B_TRUE;
35583247Sgjelinek 		return;
35593247Sgjelinek 	case PT_POOL:
35603247Sgjelinek 		if ((err = zonecfg_set_pool(handle, NULL)) != Z_OK)
35616215Sgjelinek 			z_cmd_rt_perror(CMD_CLEAR, RT_POOL, err, B_TRUE);
35623247Sgjelinek 		else
35636215Sgjelinek 			need_to_commit = B_TRUE;
35643247Sgjelinek 		return;
35653247Sgjelinek 	case PT_LIMITPRIV:
35663247Sgjelinek 		if ((err = zonecfg_set_limitpriv(handle, NULL)) != Z_OK)
35676215Sgjelinek 			z_cmd_rt_perror(CMD_CLEAR, RT_LIMITPRIV, err, B_TRUE);
35683247Sgjelinek 		else
35696215Sgjelinek 			need_to_commit = B_TRUE;
35703247Sgjelinek 		return;
35713247Sgjelinek 	case PT_BOOTARGS:
35723247Sgjelinek 		if ((err = zonecfg_set_bootargs(handle, NULL)) != Z_OK)
35736215Sgjelinek 			z_cmd_rt_perror(CMD_CLEAR, RT_BOOTARGS, err, B_TRUE);
35743247Sgjelinek 		else
35756215Sgjelinek 			need_to_commit = B_TRUE;
35763247Sgjelinek 		return;
35773247Sgjelinek 	case PT_SCHED:
35783247Sgjelinek 		if ((err = zonecfg_set_sched(handle, NULL)) != Z_OK)
35796215Sgjelinek 			z_cmd_rt_perror(CMD_CLEAR, RT_SCHED, err, B_TRUE);
35803247Sgjelinek 		else
35816215Sgjelinek 			need_to_commit = B_TRUE;
35823247Sgjelinek 		return;
35833448Sdh155122 	case PT_IPTYPE:
35843448Sdh155122 		/* shared is default; we'll treat as equivalent to clearing */
35853448Sdh155122 		if ((err = zonecfg_set_iptype(handle, ZS_SHARED)) != Z_OK)
35866215Sgjelinek 			z_cmd_rt_perror(CMD_CLEAR, RT_IPTYPE, err, B_TRUE);
35873448Sdh155122 		else
35886215Sgjelinek 			need_to_commit = B_TRUE;
35893448Sdh155122 		return;
35903247Sgjelinek 	case PT_MAXLWPS:
35913247Sgjelinek 		remove_aliased_rctl(PT_MAXLWPS, ALIAS_MAXLWPS);
35923247Sgjelinek 		return;
359312725SMenno.Lageman@Sun.COM 	case PT_MAXPROCS:
359412725SMenno.Lageman@Sun.COM 		remove_aliased_rctl(PT_MAXPROCS, ALIAS_MAXPROCS);
359512725SMenno.Lageman@Sun.COM 		return;
35963247Sgjelinek 	case PT_MAXSHMMEM:
35973247Sgjelinek 		remove_aliased_rctl(PT_MAXSHMMEM, ALIAS_MAXSHMMEM);
35983247Sgjelinek 		return;
35993247Sgjelinek 	case PT_MAXSHMIDS:
36003247Sgjelinek 		remove_aliased_rctl(PT_MAXSHMIDS, ALIAS_MAXSHMIDS);
36013247Sgjelinek 		return;
36023247Sgjelinek 	case PT_MAXMSGIDS:
36033247Sgjelinek 		remove_aliased_rctl(PT_MAXMSGIDS, ALIAS_MAXMSGIDS);
36043247Sgjelinek 		return;
36053247Sgjelinek 	case PT_MAXSEMIDS:
36063247Sgjelinek 		remove_aliased_rctl(PT_MAXSEMIDS, ALIAS_MAXSEMIDS);
36073247Sgjelinek 		return;
36083247Sgjelinek 	case PT_SHARES:
36093247Sgjelinek 		remove_aliased_rctl(PT_SHARES, ALIAS_SHARES);
36103247Sgjelinek 		return;
36118662SJordan.Vaughan@Sun.com 	case PT_HOSTID:
36128662SJordan.Vaughan@Sun.com 		if ((err = zonecfg_set_hostid(handle, NULL)) != Z_OK)
36138662SJordan.Vaughan@Sun.com 			z_cmd_rt_perror(CMD_CLEAR, RT_HOSTID, err, B_TRUE);
36148662SJordan.Vaughan@Sun.com 		else
36158662SJordan.Vaughan@Sun.com 			need_to_commit = B_TRUE;
36168662SJordan.Vaughan@Sun.com 		return;
361712633Sjohn.levon@sun.com 	case PT_FS_ALLOWED:
361812633Sjohn.levon@sun.com 		if ((err = zonecfg_set_fs_allowed(handle, NULL)) != Z_OK)
361912633Sjohn.levon@sun.com 			z_cmd_rt_perror(CMD_CLEAR, RT_FS_ALLOWED, err, B_TRUE);
362012633Sjohn.levon@sun.com 		else
362112633Sjohn.levon@sun.com 			need_to_commit = B_TRUE;
362212633Sjohn.levon@sun.com 		return;
36233247Sgjelinek 	default:
36246215Sgjelinek 		zone_perror(pt_to_str(type), Z_NO_PROPERTY_TYPE, B_TRUE);
36256215Sgjelinek 		long_usage(CMD_CLEAR, B_TRUE);
36266215Sgjelinek 		usage(B_FALSE, HELP_PROPS);
36273247Sgjelinek 		return;
36283247Sgjelinek 	}
36293247Sgjelinek }
36303247Sgjelinek 
36313247Sgjelinek void
clear_func(cmd_t * cmd)36323247Sgjelinek clear_func(cmd_t *cmd)
36333247Sgjelinek {
36343247Sgjelinek 	if (zone_is_read_only(CMD_CLEAR))
36353247Sgjelinek 		return;
36363247Sgjelinek 
36373247Sgjelinek 	assert(cmd != NULL);
36383247Sgjelinek 
36393247Sgjelinek 	if (global_scope) {
36403247Sgjelinek 		if (gz_invalid_property(cmd->cmd_res_type)) {
36413247Sgjelinek 			zerr(gettext("%s is not a valid property for the "
36423247Sgjelinek 			    "global zone."), pt_to_str(cmd->cmd_res_type));
36436215Sgjelinek 			saw_error = B_TRUE;
36443247Sgjelinek 			return;
36453247Sgjelinek 		}
36463247Sgjelinek 
36473247Sgjelinek 		clear_global(cmd);
36483247Sgjelinek 	} else {
36493247Sgjelinek 		clear_property(cmd);
36503247Sgjelinek 	}
36510Sstevel@tonic-gate }
36520Sstevel@tonic-gate 
36530Sstevel@tonic-gate void
select_func(cmd_t * cmd)36540Sstevel@tonic-gate select_func(cmd_t *cmd)
36550Sstevel@tonic-gate {
36563247Sgjelinek 	int type, err, res;
36573247Sgjelinek 	uint64_t limit;
36583792Sakolb 	uint64_t tmp;
36590Sstevel@tonic-gate 
36600Sstevel@tonic-gate 	if (zone_is_read_only(CMD_SELECT))
36610Sstevel@tonic-gate 		return;
36620Sstevel@tonic-gate 
36630Sstevel@tonic-gate 	assert(cmd != NULL);
36640Sstevel@tonic-gate 
36650Sstevel@tonic-gate 	if (global_scope) {
36666215Sgjelinek 		global_scope = B_FALSE;
36670Sstevel@tonic-gate 		resource_scope = cmd->cmd_res_type;
36680Sstevel@tonic-gate 		end_op = CMD_SELECT;
36690Sstevel@tonic-gate 	} else {
36700Sstevel@tonic-gate 		scope_usage(CMD_SELECT);
36710Sstevel@tonic-gate 		return;
36720Sstevel@tonic-gate 	}
36730Sstevel@tonic-gate 
36740Sstevel@tonic-gate 	if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
36756215Sgjelinek 		long_usage(CMD_SELECT, B_TRUE);
36766215Sgjelinek 		return;
36776215Sgjelinek 	}
36786215Sgjelinek 
36796215Sgjelinek 	if (initialize(B_TRUE) != Z_OK)
36800Sstevel@tonic-gate 		return;
36810Sstevel@tonic-gate 
36820Sstevel@tonic-gate 	switch (type) {
36830Sstevel@tonic-gate 	case RT_FS:
36846215Sgjelinek 		if ((err = fill_in_fstab(cmd, &old_fstab, B_FALSE)) != Z_OK) {
36856215Sgjelinek 			z_cmd_rt_perror(CMD_SELECT, RT_FS, err, B_TRUE);
36866215Sgjelinek 			global_scope = B_TRUE;
36870Sstevel@tonic-gate 		}
36880Sstevel@tonic-gate 		bcopy(&old_fstab, &in_progress_fstab,
36890Sstevel@tonic-gate 		    sizeof (struct zone_fstab));
36900Sstevel@tonic-gate 		return;
36910Sstevel@tonic-gate 	case RT_NET:
36926215Sgjelinek 		if ((err = fill_in_nwiftab(cmd, &old_nwiftab, B_FALSE))
36936215Sgjelinek 		    != Z_OK) {
36946215Sgjelinek 			z_cmd_rt_perror(CMD_SELECT, RT_NET, err, B_TRUE);
36956215Sgjelinek 			global_scope = B_TRUE;
36960Sstevel@tonic-gate 		}
36970Sstevel@tonic-gate 		bcopy(&old_nwiftab, &in_progress_nwiftab,
36980Sstevel@tonic-gate 		    sizeof (struct zone_nwiftab));
36990Sstevel@tonic-gate 		return;
37000Sstevel@tonic-gate 	case RT_DEVICE:
37016215Sgjelinek 		if ((err = fill_in_devtab(cmd, &old_devtab, B_FALSE)) != Z_OK) {
37026215Sgjelinek 			z_cmd_rt_perror(CMD_SELECT, RT_DEVICE, err, B_TRUE);
37036215Sgjelinek 			global_scope = B_TRUE;
37040Sstevel@tonic-gate 		}
37050Sstevel@tonic-gate 		bcopy(&old_devtab, &in_progress_devtab,
37060Sstevel@tonic-gate 		    sizeof (struct zone_devtab));
37070Sstevel@tonic-gate 		return;
37080Sstevel@tonic-gate 	case RT_RCTL:
37096215Sgjelinek 		if ((err = fill_in_rctltab(cmd, &old_rctltab, B_FALSE))
37106215Sgjelinek 		    != Z_OK) {
37116215Sgjelinek 			z_cmd_rt_perror(CMD_SELECT, RT_RCTL, err, B_TRUE);
37126215Sgjelinek 			global_scope = B_TRUE;
37130Sstevel@tonic-gate 		}
37140Sstevel@tonic-gate 		bcopy(&old_rctltab, &in_progress_rctltab,
37150Sstevel@tonic-gate 		    sizeof (struct zone_rctltab));
37160Sstevel@tonic-gate 		return;
37170Sstevel@tonic-gate 	case RT_ATTR:
37186215Sgjelinek 		if ((err = fill_in_attrtab(cmd, &old_attrtab, B_FALSE))
37196215Sgjelinek 		    != Z_OK) {
37206215Sgjelinek 			z_cmd_rt_perror(CMD_SELECT, RT_ATTR, err, B_TRUE);
37216215Sgjelinek 			global_scope = B_TRUE;
37220Sstevel@tonic-gate 		}
37230Sstevel@tonic-gate 		bcopy(&old_attrtab, &in_progress_attrtab,
37240Sstevel@tonic-gate 		    sizeof (struct zone_attrtab));
37250Sstevel@tonic-gate 		return;
3726789Sahrens 	case RT_DATASET:
37276215Sgjelinek 		if ((err = fill_in_dstab(cmd, &old_dstab, B_FALSE)) != Z_OK) {
37286215Sgjelinek 			z_cmd_rt_perror(CMD_SELECT, RT_DATASET, err, B_TRUE);
37296215Sgjelinek 			global_scope = B_TRUE;
3730789Sahrens 		}
3731789Sahrens 		bcopy(&old_dstab, &in_progress_dstab,
3732789Sahrens 		    sizeof (struct zone_dstab));
3733789Sahrens 		return;
37343247Sgjelinek 	case RT_DCPU:
37353247Sgjelinek 		if ((err = zonecfg_lookup_pset(handle, &old_psettab)) != Z_OK) {
37366215Sgjelinek 			z_cmd_rt_perror(CMD_SELECT, RT_DCPU, err, B_TRUE);
37376215Sgjelinek 			global_scope = B_TRUE;
37383247Sgjelinek 		}
37393247Sgjelinek 		bcopy(&old_psettab, &in_progress_psettab,
37403247Sgjelinek 		    sizeof (struct zone_psettab));
37413247Sgjelinek 		return;
37423792Sakolb 	case RT_PCAP:
37433792Sakolb 		if ((err = zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp))
37443792Sakolb 		    != Z_OK) {
37456215Sgjelinek 			z_cmd_rt_perror(CMD_SELECT, RT_PCAP, err, B_TRUE);
37466215Sgjelinek 			global_scope = B_TRUE;
37473792Sakolb 		}
37483792Sakolb 		return;
37493247Sgjelinek 	case RT_MCAP:
37503247Sgjelinek 		/* if none of these exist, there is no resource to select */
37513247Sgjelinek 		if ((res = zonecfg_lookup_mcap(handle, &old_mcaptab)) != Z_OK &&
37523247Sgjelinek 		    zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &limit)
37533247Sgjelinek 		    != Z_OK &&
37543247Sgjelinek 		    zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &limit)
37553247Sgjelinek 		    != Z_OK) {
37563247Sgjelinek 			z_cmd_rt_perror(CMD_SELECT, RT_MCAP, Z_NO_RESOURCE_TYPE,
37576215Sgjelinek 			    B_TRUE);
37586215Sgjelinek 			global_scope = B_TRUE;
37593247Sgjelinek 		}
37603247Sgjelinek 		if (res == Z_OK)
37613247Sgjelinek 			bcopy(&old_mcaptab, &in_progress_mcaptab,
37623247Sgjelinek 			    sizeof (struct zone_mcaptab));
37633247Sgjelinek 		else
37643247Sgjelinek 			bzero(&in_progress_mcaptab,
37653247Sgjelinek 			    sizeof (in_progress_mcaptab));
37663247Sgjelinek 		return;
376712578SGlenn.Faden@Sun.COM 	case RT_ADMIN:
376812578SGlenn.Faden@Sun.COM 		if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
376912578SGlenn.Faden@Sun.COM 		    != Z_OK) {
377012578SGlenn.Faden@Sun.COM 			z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
377112578SGlenn.Faden@Sun.COM 			    B_TRUE);
377212578SGlenn.Faden@Sun.COM 			global_scope = B_TRUE;
377312578SGlenn.Faden@Sun.COM 		}
377412578SGlenn.Faden@Sun.COM 		bcopy(&old_admintab, &in_progress_admintab,
377512578SGlenn.Faden@Sun.COM 		    sizeof (struct zone_admintab));
377612578SGlenn.Faden@Sun.COM 		return;
37770Sstevel@tonic-gate 	default:
37786215Sgjelinek 		zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
37796215Sgjelinek 		long_usage(CMD_SELECT, B_TRUE);
37806215Sgjelinek 		usage(B_FALSE, HELP_RESOURCES);
37810Sstevel@tonic-gate 		return;
37820Sstevel@tonic-gate 	}
37830Sstevel@tonic-gate }
37840Sstevel@tonic-gate 
37850Sstevel@tonic-gate /*
37860Sstevel@tonic-gate  * Network "addresses" can be one of the following forms:
37870Sstevel@tonic-gate  *	<IPv4 address>
37880Sstevel@tonic-gate  *	<IPv4 address>/<prefix length>
37890Sstevel@tonic-gate  *	<IPv6 address>/<prefix length>
37900Sstevel@tonic-gate  *	<host name>
37910Sstevel@tonic-gate  *	<host name>/<prefix length>
37920Sstevel@tonic-gate  * In other words, the "/" followed by a prefix length is allowed but not
37930Sstevel@tonic-gate  * required for IPv4 addresses and host names, and required for IPv6 addresses.
37940Sstevel@tonic-gate  * If a prefix length is given, it must be in the allowable range: 0 to 32 for
37950Sstevel@tonic-gate  * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
37960Sstevel@tonic-gate  * Host names must start with an alpha-numeric character, and all subsequent
37970Sstevel@tonic-gate  * characters must be either alpha-numeric or "-".
379812748SSowmini.Varadhan@oracle.COM  *
379912748SSowmini.Varadhan@oracle.COM  * In some cases, e.g., the nexthop for the defrouter, the context indicates
380012748SSowmini.Varadhan@oracle.COM  * that this is the IPV4_ABITS or IPV6_ABITS netmask, in which case we don't
380112748SSowmini.Varadhan@oracle.COM  * require the /<prefix length> (and should ignore it if provided).
38020Sstevel@tonic-gate  */
38030Sstevel@tonic-gate 
38040Sstevel@tonic-gate static int
validate_net_address_syntax(char * address,boolean_t ishost)380512748SSowmini.Varadhan@oracle.COM validate_net_address_syntax(char *address, boolean_t ishost)
38060Sstevel@tonic-gate {
38070Sstevel@tonic-gate 	char *slashp, part1[MAXHOSTNAMELEN];
38080Sstevel@tonic-gate 	struct in6_addr in6;
38090Sstevel@tonic-gate 	struct in_addr in4;
38100Sstevel@tonic-gate 	int prefixlen, i;
38110Sstevel@tonic-gate 
38120Sstevel@tonic-gate 	/*
38130Sstevel@tonic-gate 	 * Copy the part before any '/' into part1 or copy the whole
38140Sstevel@tonic-gate 	 * thing if there is no '/'.
38150Sstevel@tonic-gate 	 */
38160Sstevel@tonic-gate 	if ((slashp = strchr(address, '/')) != NULL) {
38170Sstevel@tonic-gate 		*slashp = '\0';
38180Sstevel@tonic-gate 		(void) strlcpy(part1, address, sizeof (part1));
38190Sstevel@tonic-gate 		*slashp = '/';
38200Sstevel@tonic-gate 		prefixlen = atoi(++slashp);
38210Sstevel@tonic-gate 	} else {
38220Sstevel@tonic-gate 		(void) strlcpy(part1, address, sizeof (part1));
38230Sstevel@tonic-gate 	}
38240Sstevel@tonic-gate 
382512748SSowmini.Varadhan@oracle.COM 	if (ishost && slashp != NULL) {
382612748SSowmini.Varadhan@oracle.COM 		zerr(gettext("Warning: prefix length in %s is not required and "
382712748SSowmini.Varadhan@oracle.COM 		    "will be ignored. The default host-prefix length "
382812748SSowmini.Varadhan@oracle.COM 		    "will be used"), address);
382912748SSowmini.Varadhan@oracle.COM 	}
383012748SSowmini.Varadhan@oracle.COM 
383112748SSowmini.Varadhan@oracle.COM 
38320Sstevel@tonic-gate 	if (inet_pton(AF_INET6, part1, &in6) == 1) {
383312748SSowmini.Varadhan@oracle.COM 		if (ishost) {
383412748SSowmini.Varadhan@oracle.COM 			prefixlen = IPV6_ABITS;
383512748SSowmini.Varadhan@oracle.COM 		} else if (slashp == NULL) {
38360Sstevel@tonic-gate 			zerr(gettext("%s: IPv6 addresses "
38370Sstevel@tonic-gate 			    "require /prefix-length suffix."), address);
38380Sstevel@tonic-gate 			return (Z_ERR);
38390Sstevel@tonic-gate 		}
38400Sstevel@tonic-gate 		if (prefixlen < 0 || prefixlen > 128) {
38410Sstevel@tonic-gate 			zerr(gettext("%s: IPv6 address "
38420Sstevel@tonic-gate 			    "prefix lengths must be 0 - 128."), address);
38430Sstevel@tonic-gate 			return (Z_ERR);
38440Sstevel@tonic-gate 		}
38450Sstevel@tonic-gate 		return (Z_OK);
38460Sstevel@tonic-gate 	}
38470Sstevel@tonic-gate 
38480Sstevel@tonic-gate 	/* At this point, any /prefix must be for IPv4. */
384912748SSowmini.Varadhan@oracle.COM 	if (ishost)
385012748SSowmini.Varadhan@oracle.COM 		prefixlen = IPV4_ABITS;
385112748SSowmini.Varadhan@oracle.COM 	else if (slashp != NULL) {
38520Sstevel@tonic-gate 		if (prefixlen < 0 || prefixlen > 32) {
38530Sstevel@tonic-gate 			zerr(gettext("%s: IPv4 address "
38540Sstevel@tonic-gate 			    "prefix lengths must be 0 - 32."), address);
38550Sstevel@tonic-gate 			return (Z_ERR);
38560Sstevel@tonic-gate 		}
38570Sstevel@tonic-gate 	}
385812748SSowmini.Varadhan@oracle.COM 
38590Sstevel@tonic-gate 	if (inet_pton(AF_INET, part1, &in4) == 1)
38600Sstevel@tonic-gate 		return (Z_OK);
38610Sstevel@tonic-gate 
38620Sstevel@tonic-gate 	/* address may also be a host name */
38630Sstevel@tonic-gate 	if (!isalnum(part1[0])) {
38640Sstevel@tonic-gate 		zerr(gettext("%s: bogus host name or network address syntax"),
38650Sstevel@tonic-gate 		    part1);
38666215Sgjelinek 		saw_error = B_TRUE;
38676215Sgjelinek 		usage(B_FALSE, HELP_NETADDR);
38680Sstevel@tonic-gate 		return (Z_ERR);
38690Sstevel@tonic-gate 	}
38700Sstevel@tonic-gate 	for (i = 1; part1[i]; i++)
38710Sstevel@tonic-gate 		if (!isalnum(part1[i]) && part1[i] != '-' && part1[i] != '.') {
38720Sstevel@tonic-gate 			zerr(gettext("%s: bogus host name or "
38730Sstevel@tonic-gate 			    "network address syntax"), part1);
38746215Sgjelinek 			saw_error = B_TRUE;
38756215Sgjelinek 			usage(B_FALSE, HELP_NETADDR);
38760Sstevel@tonic-gate 			return (Z_ERR);
38770Sstevel@tonic-gate 		}
38780Sstevel@tonic-gate 	return (Z_OK);
38790Sstevel@tonic-gate }
38800Sstevel@tonic-gate 
38810Sstevel@tonic-gate static int
validate_net_physical_syntax(const char * ifname)38828083SJordan.Vaughan@Sun.com validate_net_physical_syntax(const char *ifname)
38830Sstevel@tonic-gate {
38848083SJordan.Vaughan@Sun.com 	ifspec_t ifnameprop;
38858083SJordan.Vaughan@Sun.com 	zone_iptype_t iptype;
38868087SJordan.Vaughan@Sun.com 
38878087SJordan.Vaughan@Sun.com 	if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
38888083SJordan.Vaughan@Sun.com 		zerr(gettext("zone configuration has an invalid or nonexistent "
38898083SJordan.Vaughan@Sun.com 		    "ip-type property"));
38908083SJordan.Vaughan@Sun.com 		return (Z_ERR);
38918083SJordan.Vaughan@Sun.com 	}
38928083SJordan.Vaughan@Sun.com 	switch (iptype) {
38938083SJordan.Vaughan@Sun.com 	case ZS_SHARED:
38948083SJordan.Vaughan@Sun.com 		if (ifparse_ifspec(ifname, &ifnameprop) == B_FALSE) {
38958083SJordan.Vaughan@Sun.com 			zerr(gettext("%s: invalid physical interface name"),
38968083SJordan.Vaughan@Sun.com 			    ifname);
38978083SJordan.Vaughan@Sun.com 			return (Z_ERR);
38988083SJordan.Vaughan@Sun.com 		}
38998083SJordan.Vaughan@Sun.com 		if (ifnameprop.ifsp_lunvalid) {
39008083SJordan.Vaughan@Sun.com 			zerr(gettext("%s: LUNs not allowed in physical "
39018083SJordan.Vaughan@Sun.com 			    "interface names"), ifname);
39028083SJordan.Vaughan@Sun.com 			return (Z_ERR);
39038083SJordan.Vaughan@Sun.com 		}
39048083SJordan.Vaughan@Sun.com 		break;
39058083SJordan.Vaughan@Sun.com 	case ZS_EXCLUSIVE:
39068083SJordan.Vaughan@Sun.com 		if (dladm_valid_linkname(ifname) == B_FALSE) {
39078083SJordan.Vaughan@Sun.com 			if (strchr(ifname, ':') != NULL)
39088083SJordan.Vaughan@Sun.com 				zerr(gettext("%s: physical interface name "
39098083SJordan.Vaughan@Sun.com 				    "required; logical interface name not "
39108083SJordan.Vaughan@Sun.com 				    "allowed"), ifname);
39118083SJordan.Vaughan@Sun.com 			else
39128083SJordan.Vaughan@Sun.com 				zerr(gettext("%s: invalid physical interface "
39138083SJordan.Vaughan@Sun.com 				    "name"), ifname);
39148083SJordan.Vaughan@Sun.com 			return (Z_ERR);
39158083SJordan.Vaughan@Sun.com 		}
39168083SJordan.Vaughan@Sun.com 		break;
39178083SJordan.Vaughan@Sun.com 	}
39188083SJordan.Vaughan@Sun.com 	return (Z_OK);
39190Sstevel@tonic-gate }
39200Sstevel@tonic-gate 
39210Sstevel@tonic-gate static boolean_t
valid_fs_type(const char * type)39220Sstevel@tonic-gate valid_fs_type(const char *type)
39230Sstevel@tonic-gate {
39240Sstevel@tonic-gate 	/*
39250Sstevel@tonic-gate 	 * Is this a valid path component?
39260Sstevel@tonic-gate 	 */
39270Sstevel@tonic-gate 	if (strlen(type) + 1 > MAXNAMELEN)
39280Sstevel@tonic-gate 		return (B_FALSE);
39290Sstevel@tonic-gate 	/*
39300Sstevel@tonic-gate 	 * Make sure a bad value for "type" doesn't make
39310Sstevel@tonic-gate 	 * /usr/lib/fs/<type>/mount turn into something else.
39320Sstevel@tonic-gate 	 */
39330Sstevel@tonic-gate 	if (strchr(type, '/') != NULL || type[0] == '\0' ||
39340Sstevel@tonic-gate 	    strcmp(type, ".") == 0 || strcmp(type, "..") == 0)
3935565Sdp 		return (B_FALSE);
39360Sstevel@tonic-gate 	/*
39370Sstevel@tonic-gate 	 * More detailed verification happens later by zoneadm(1m).
39380Sstevel@tonic-gate 	 */
39390Sstevel@tonic-gate 	return (B_TRUE);
39400Sstevel@tonic-gate }
39410Sstevel@tonic-gate 
39423448Sdh155122 static boolean_t
allow_exclusive()39433448Sdh155122 allow_exclusive()
39443448Sdh155122 {
39453448Sdh155122 	brand_handle_t	bh;
39463448Sdh155122 	char		brand[MAXNAMELEN];
39473448Sdh155122 	boolean_t	ret;
39483448Sdh155122 
39493448Sdh155122 	if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
39503448Sdh155122 		zerr("%s: %s\n", zone, gettext("could not get zone brand"));
39513448Sdh155122 		return (B_FALSE);
39523448Sdh155122 	}
39533448Sdh155122 	if ((bh = brand_open(brand)) == NULL) {
39543448Sdh155122 		zerr("%s: %s\n", zone, gettext("unknown brand."));
39553448Sdh155122 		return (B_FALSE);
39563448Sdh155122 	}
39573448Sdh155122 	ret = brand_allow_exclusive_ip(bh);
39583448Sdh155122 	brand_close(bh);
39593448Sdh155122 	if (!ret)
39603448Sdh155122 		zerr(gettext("%s cannot be '%s' when %s is '%s'."),
39613448Sdh155122 		    pt_to_str(PT_IPTYPE), "exclusive",
39623448Sdh155122 		    pt_to_str(PT_BRAND), brand);
39633448Sdh155122 	return (ret);
39643448Sdh155122 }
39653448Sdh155122 
39663247Sgjelinek static void
set_aliased_rctl(char * alias,int prop_type,char * s)39673247Sgjelinek set_aliased_rctl(char *alias, int prop_type, char *s)
39683247Sgjelinek {
39693247Sgjelinek 	uint64_t limit;
39703247Sgjelinek 	int err;
39713247Sgjelinek 	char tmp[128];
39723247Sgjelinek 
39733247Sgjelinek 	if (global_zone && strcmp(alias, ALIAS_SHARES) != 0)
39743247Sgjelinek 		zerr(gettext("WARNING: Setting a global zone resource "
39753247Sgjelinek 		    "control too low could deny\nservice "
39763247Sgjelinek 		    "to even the root user; "
39773247Sgjelinek 		    "this could render the system impossible\n"
39783247Sgjelinek 		    "to administer.  Please use caution."));
39793247Sgjelinek 
39803247Sgjelinek 	/* convert memory based properties */
39813247Sgjelinek 	if (prop_type == PT_MAXSHMMEM) {
39823247Sgjelinek 		if (!zonecfg_valid_memlimit(s, &limit)) {
39833247Sgjelinek 			zerr(gettext("A non-negative number with a required "
39843247Sgjelinek 			    "scale suffix (K, M, G or T) was expected\nhere."));
39856215Sgjelinek 			saw_error = B_TRUE;
39863247Sgjelinek 			return;
39873247Sgjelinek 		}
39883247Sgjelinek 
39893247Sgjelinek 		(void) snprintf(tmp, sizeof (tmp), "%llu", limit);
39903247Sgjelinek 		s = tmp;
39913247Sgjelinek 	}
39923247Sgjelinek 
39933247Sgjelinek 	if (!zonecfg_aliased_rctl_ok(handle, alias)) {
39946215Sgjelinek 		zone_perror(pt_to_str(prop_type), Z_ALIAS_DISALLOW, B_FALSE);
39956215Sgjelinek 		saw_error = B_TRUE;
39963247Sgjelinek 	} else if (!zonecfg_valid_alias_limit(alias, s, &limit)) {
39973247Sgjelinek 		zerr(gettext("%s property is out of range."),
39983247Sgjelinek 		    pt_to_str(prop_type));
39996215Sgjelinek 		saw_error = B_TRUE;
40003247Sgjelinek 	} else if ((err = zonecfg_set_aliased_rctl(handle, alias, limit))
40013247Sgjelinek 	    != Z_OK) {
40026215Sgjelinek 		zone_perror(zone, err, B_TRUE);
40036215Sgjelinek 		saw_error = B_TRUE;
40043247Sgjelinek 	} else {
40056215Sgjelinek 		need_to_commit = B_TRUE;
40063247Sgjelinek 	}
40073247Sgjelinek }
40083247Sgjelinek 
400912748SSowmini.Varadhan@oracle.COM static void
set_in_progress_nwiftab_address(char * prop_id,int prop_type)401012748SSowmini.Varadhan@oracle.COM set_in_progress_nwiftab_address(char *prop_id, int prop_type)
401112748SSowmini.Varadhan@oracle.COM {
401212748SSowmini.Varadhan@oracle.COM 	if (prop_type == PT_ADDRESS) {
401312748SSowmini.Varadhan@oracle.COM 		(void) strlcpy(in_progress_nwiftab.zone_nwif_address, prop_id,
401412748SSowmini.Varadhan@oracle.COM 		    sizeof (in_progress_nwiftab.zone_nwif_address));
401512748SSowmini.Varadhan@oracle.COM 	} else {
401612748SSowmini.Varadhan@oracle.COM 		assert(prop_type == PT_ALLOWED_ADDRESS);
401712748SSowmini.Varadhan@oracle.COM 		(void) strlcpy(in_progress_nwiftab.zone_nwif_allowed_address,
401812748SSowmini.Varadhan@oracle.COM 		    prop_id,
401912748SSowmini.Varadhan@oracle.COM 		    sizeof (in_progress_nwiftab.zone_nwif_allowed_address));
402012748SSowmini.Varadhan@oracle.COM 	}
402112748SSowmini.Varadhan@oracle.COM }
402212748SSowmini.Varadhan@oracle.COM 
40230Sstevel@tonic-gate void
set_func(cmd_t * cmd)40240Sstevel@tonic-gate set_func(cmd_t *cmd)
40250Sstevel@tonic-gate {
40260Sstevel@tonic-gate 	char *prop_id;
40272303Scarlsonj 	int arg, err, res_type, prop_type;
40280Sstevel@tonic-gate 	property_value_ptr_t pp;
40290Sstevel@tonic-gate 	boolean_t autoboot;
40303448Sdh155122 	zone_iptype_t iptype;
40316215Sgjelinek 	boolean_t force_set = B_FALSE;
40323247Sgjelinek 	size_t physmem_size = sizeof (in_progress_mcaptab.zone_physmem_cap);
40333247Sgjelinek 	uint64_t mem_cap, mem_limit;
40343792Sakolb 	float cap;
40353792Sakolb 	char *unitp;
40363247Sgjelinek 	struct zone_psettab tmp_psettab;
40376215Sgjelinek 	boolean_t arg_err = B_FALSE;
40380Sstevel@tonic-gate 
40390Sstevel@tonic-gate 	if (zone_is_read_only(CMD_SET))
40400Sstevel@tonic-gate 		return;
40410Sstevel@tonic-gate 
40420Sstevel@tonic-gate 	assert(cmd != NULL);
40430Sstevel@tonic-gate 
40442303Scarlsonj 	optind = opterr = 0;
40452303Scarlsonj 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
40462303Scarlsonj 		switch (arg) {
40472303Scarlsonj 		case 'F':
40486215Sgjelinek 			force_set = B_TRUE;
40492303Scarlsonj 			break;
40502303Scarlsonj 		default:
40512303Scarlsonj 			if (optopt == '?')
40522303Scarlsonj 				longer_usage(CMD_SET);
40532303Scarlsonj 			else
40542303Scarlsonj 				short_usage(CMD_SET);
40556215Sgjelinek 			arg_err = B_TRUE;
40563691Sgjelinek 			break;
40573691Sgjelinek 		}
40583691Sgjelinek 	}
40593691Sgjelinek 	if (arg_err)
40603691Sgjelinek 		return;
40612303Scarlsonj 
40620Sstevel@tonic-gate 	prop_type = cmd->cmd_prop_name[0];
40630Sstevel@tonic-gate 	if (global_scope) {
40643247Sgjelinek 		if (gz_invalid_property(prop_type)) {
40653247Sgjelinek 			zerr(gettext("%s is not a valid property for the "
40663247Sgjelinek 			    "global zone."), pt_to_str(prop_type));
40676215Sgjelinek 			saw_error = B_TRUE;
40683247Sgjelinek 			return;
40693247Sgjelinek 		}
40703247Sgjelinek 
4071565Sdp 		if (prop_type == PT_ZONENAME) {
4072565Sdp 			res_type = RT_ZONENAME;
4073565Sdp 		} else if (prop_type == PT_ZONEPATH) {
40740Sstevel@tonic-gate 			res_type = RT_ZONEPATH;
40750Sstevel@tonic-gate 		} else if (prop_type == PT_AUTOBOOT) {
40760Sstevel@tonic-gate 			res_type = RT_AUTOBOOT;
40772712Snn35248 		} else if (prop_type == PT_BRAND) {
40782712Snn35248 			res_type = RT_BRAND;
40790Sstevel@tonic-gate 		} else if (prop_type == PT_POOL) {
40800Sstevel@tonic-gate 			res_type = RT_POOL;
40811645Scomay 		} else if (prop_type == PT_LIMITPRIV) {
40821645Scomay 			res_type = RT_LIMITPRIV;
40832267Sdp 		} else if (prop_type == PT_BOOTARGS) {
40842267Sdp 			res_type = RT_BOOTARGS;
40853247Sgjelinek 		} else if (prop_type == PT_SCHED) {
40863247Sgjelinek 			res_type = RT_SCHED;
40873448Sdh155122 		} else if (prop_type == PT_IPTYPE) {
40883448Sdh155122 			res_type = RT_IPTYPE;
40893247Sgjelinek 		} else if (prop_type == PT_MAXLWPS) {
40903247Sgjelinek 			res_type = RT_MAXLWPS;
409112725SMenno.Lageman@Sun.COM 		} else if (prop_type == PT_MAXPROCS) {
409212725SMenno.Lageman@Sun.COM 			res_type = RT_MAXPROCS;
40933247Sgjelinek 		} else if (prop_type == PT_MAXSHMMEM) {
40943247Sgjelinek 			res_type = RT_MAXSHMMEM;
40953247Sgjelinek 		} else if (prop_type == PT_MAXSHMIDS) {
40963247Sgjelinek 			res_type = RT_MAXSHMIDS;
40973247Sgjelinek 		} else if (prop_type == PT_MAXMSGIDS) {
40983247Sgjelinek 			res_type = RT_MAXMSGIDS;
40993247Sgjelinek 		} else if (prop_type == PT_MAXSEMIDS) {
41003247Sgjelinek 			res_type = RT_MAXSEMIDS;
41013247Sgjelinek 		} else if (prop_type == PT_SHARES) {
41023247Sgjelinek 			res_type = RT_SHARES;
41038662SJordan.Vaughan@Sun.com 		} else if (prop_type == PT_HOSTID) {
41048662SJordan.Vaughan@Sun.com 			res_type = RT_HOSTID;
410512633Sjohn.levon@sun.com 		} else if (prop_type == PT_FS_ALLOWED) {
410612633Sjohn.levon@sun.com 			res_type = RT_FS_ALLOWED;
41070Sstevel@tonic-gate 		} else {
41080Sstevel@tonic-gate 			zerr(gettext("Cannot set a resource-specific property "
41090Sstevel@tonic-gate 			    "from the global scope."));
41106215Sgjelinek 			saw_error = B_TRUE;
41110Sstevel@tonic-gate 			return;
41120Sstevel@tonic-gate 		}
41130Sstevel@tonic-gate 	} else {
41140Sstevel@tonic-gate 		res_type = resource_scope;
41150Sstevel@tonic-gate 	}
41160Sstevel@tonic-gate 
41172303Scarlsonj 	if (force_set) {
41182303Scarlsonj 		if (res_type != RT_ZONEPATH) {
41192303Scarlsonj 			zerr(gettext("Only zonepath setting can be forced."));
41206215Sgjelinek 			saw_error = B_TRUE;
41212303Scarlsonj 			return;
41222303Scarlsonj 		}
41232303Scarlsonj 		if (!zonecfg_in_alt_root()) {
41242303Scarlsonj 			zerr(gettext("Zonepath is changeable only in an "
41252303Scarlsonj 			    "alternate root."));
41266215Sgjelinek 			saw_error = B_TRUE;
41272303Scarlsonj 			return;
41282303Scarlsonj 		}
41292303Scarlsonj 	}
41302303Scarlsonj 
41310Sstevel@tonic-gate 	pp = cmd->cmd_property_ptr[0];
41320Sstevel@tonic-gate 	/*
41330Sstevel@tonic-gate 	 * A nasty expression but not that complicated:
41340Sstevel@tonic-gate 	 * 1. fs options are simple or list (tested below)
41350Sstevel@tonic-gate 	 * 2. rctl value's are complex or list (tested below)
41360Sstevel@tonic-gate 	 * Anything else should be simple.
41370Sstevel@tonic-gate 	 */
41380Sstevel@tonic-gate 	if (!(res_type == RT_FS && prop_type == PT_OPTIONS) &&
41390Sstevel@tonic-gate 	    !(res_type == RT_RCTL && prop_type == PT_VALUE) &&
41400Sstevel@tonic-gate 	    (pp->pv_type != PROP_VAL_SIMPLE ||
41410Sstevel@tonic-gate 	    (prop_id = pp->pv_simple) == NULL)) {
41420Sstevel@tonic-gate 		zerr(gettext("A %s value was expected here."),
41430Sstevel@tonic-gate 		    pvt_to_str(PROP_VAL_SIMPLE));
41446215Sgjelinek 		saw_error = B_TRUE;
41450Sstevel@tonic-gate 		return;
41460Sstevel@tonic-gate 	}
41470Sstevel@tonic-gate 	if (prop_type == PT_UNKNOWN) {
41486215Sgjelinek 		long_usage(CMD_SET, B_TRUE);
41490Sstevel@tonic-gate 		return;
41500Sstevel@tonic-gate 	}
41510Sstevel@tonic-gate 
4152565Sdp 	/*
4153565Sdp 	 * Special case: the user can change the zone name prior to 'create';
4154565Sdp 	 * if the zone already exists, we fall through letting initialize()
4155565Sdp 	 * and the rest of the logic run.
4156565Sdp 	 */
41576215Sgjelinek 	if (res_type == RT_ZONENAME && got_handle == B_FALSE &&
4158565Sdp 	    !state_atleast(ZONE_STATE_CONFIGURED)) {
41591497Sdp 		if ((err = zonecfg_validate_zonename(prop_id)) != Z_OK) {
41606215Sgjelinek 			zone_perror(prop_id, err, B_TRUE);
41616215Sgjelinek 			usage(B_FALSE, HELP_SYNTAX);
41621497Sdp 			return;
41631497Sdp 		}
4164565Sdp 		(void) strlcpy(zone, prop_id, sizeof (zone));
4165565Sdp 		return;
4166565Sdp 	}
4167565Sdp 
41686215Sgjelinek 	if (initialize(B_TRUE) != Z_OK)
41690Sstevel@tonic-gate 		return;
41700Sstevel@tonic-gate 
41710Sstevel@tonic-gate 	switch (res_type) {
4172565Sdp 	case RT_ZONENAME:
4173565Sdp 		if ((err = zonecfg_set_name(handle, prop_id)) != Z_OK) {
4174565Sdp 			/*
4175565Sdp 			 * Use prop_id instead of 'zone' here, since we're
4176565Sdp 			 * reporting a problem about the *new* zonename.
4177565Sdp 			 */
41786215Sgjelinek 			zone_perror(prop_id, err, B_TRUE);
41796215Sgjelinek 			usage(B_FALSE, HELP_SYNTAX);
4180565Sdp 		} else {
41816215Sgjelinek 			need_to_commit = B_TRUE;
4182565Sdp 			(void) strlcpy(zone, prop_id, sizeof (zone));
4183565Sdp 		}
4184565Sdp 		return;
41850Sstevel@tonic-gate 	case RT_ZONEPATH:
41862303Scarlsonj 		if (!force_set && state_atleast(ZONE_STATE_INSTALLED)) {
41870Sstevel@tonic-gate 			zerr(gettext("Zone %s already installed; %s %s not "
41880Sstevel@tonic-gate 			    "allowed."), zone, cmd_to_str(CMD_SET),
41890Sstevel@tonic-gate 			    rt_to_str(RT_ZONEPATH));
41900Sstevel@tonic-gate 			return;
41910Sstevel@tonic-gate 		}
41920Sstevel@tonic-gate 		if (validate_zonepath_syntax(prop_id) != Z_OK) {
41936215Sgjelinek 			saw_error = B_TRUE;
41940Sstevel@tonic-gate 			return;
41950Sstevel@tonic-gate 		}
41960Sstevel@tonic-gate 		if ((err = zonecfg_set_zonepath(handle, prop_id)) != Z_OK)
41976215Sgjelinek 			zone_perror(zone, err, B_TRUE);
41980Sstevel@tonic-gate 		else
41996215Sgjelinek 			need_to_commit = B_TRUE;
42000Sstevel@tonic-gate 		return;
42012712Snn35248 	case RT_BRAND:
42022712Snn35248 		if (state_atleast(ZONE_STATE_INSTALLED)) {
42032712Snn35248 			zerr(gettext("Zone %s already installed; %s %s not "
42042712Snn35248 			    "allowed."), zone, cmd_to_str(CMD_SET),
42052712Snn35248 			    rt_to_str(RT_BRAND));
42062712Snn35248 			return;
42072712Snn35248 		}
42082712Snn35248 		if ((err = zonecfg_set_brand(handle, prop_id)) != Z_OK)
42096215Sgjelinek 			zone_perror(zone, err, B_TRUE);
42102712Snn35248 		else
42116215Sgjelinek 			need_to_commit = B_TRUE;
42122712Snn35248 		return;
42130Sstevel@tonic-gate 	case RT_AUTOBOOT:
42140Sstevel@tonic-gate 		if (strcmp(prop_id, "true") == 0) {
42150Sstevel@tonic-gate 			autoboot = B_TRUE;
42160Sstevel@tonic-gate 		} else if (strcmp(prop_id, "false") == 0) {
42170Sstevel@tonic-gate 			autoboot = B_FALSE;
42180Sstevel@tonic-gate 		} else {
42190Sstevel@tonic-gate 			zerr(gettext("%s value must be '%s' or '%s'."),
42200Sstevel@tonic-gate 			    pt_to_str(PT_AUTOBOOT), "true", "false");
42216215Sgjelinek 			saw_error = B_TRUE;
42220Sstevel@tonic-gate 			return;
42230Sstevel@tonic-gate 		}
42240Sstevel@tonic-gate 		if ((err = zonecfg_set_autoboot(handle, autoboot)) != Z_OK)
42256215Sgjelinek 			zone_perror(zone, err, B_TRUE);
42260Sstevel@tonic-gate 		else
42276215Sgjelinek 			need_to_commit = B_TRUE;
42280Sstevel@tonic-gate 		return;
42290Sstevel@tonic-gate 	case RT_POOL:
42303247Sgjelinek 		/* don't allow use of the reserved temporary pool names */
42313247Sgjelinek 		if (strncmp("SUNW", prop_id, 4) == 0) {
42323247Sgjelinek 			zerr(gettext("pool names starting with SUNW are "
42333247Sgjelinek 			    "reserved."));
42346215Sgjelinek 			saw_error = B_TRUE;
42353247Sgjelinek 			return;
42363247Sgjelinek 		}
42373247Sgjelinek 
42383247Sgjelinek 		/* can't set pool if dedicated-cpu exists */
42393247Sgjelinek 		if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
42403247Sgjelinek 			zerr(gettext("The %s resource already exists.  "
42413247Sgjelinek 			    "A persistent pool is incompatible\nwith the %s "
42423247Sgjelinek 			    "resource."), rt_to_str(RT_DCPU),
42433247Sgjelinek 			    rt_to_str(RT_DCPU));
42446215Sgjelinek 			saw_error = B_TRUE;
42453247Sgjelinek 			return;
42463247Sgjelinek 		}
42473247Sgjelinek 
42480Sstevel@tonic-gate 		if ((err = zonecfg_set_pool(handle, prop_id)) != Z_OK)
42496215Sgjelinek 			zone_perror(zone, err, B_TRUE);
42500Sstevel@tonic-gate 		else
42516215Sgjelinek 			need_to_commit = B_TRUE;
42520Sstevel@tonic-gate 		return;
42531645Scomay 	case RT_LIMITPRIV:
42541645Scomay 		if ((err = zonecfg_set_limitpriv(handle, prop_id)) != Z_OK)
42556215Sgjelinek 			zone_perror(zone, err, B_TRUE);
42561645Scomay 		else
42576215Sgjelinek 			need_to_commit = B_TRUE;
42581645Scomay 		return;
42592267Sdp 	case RT_BOOTARGS:
42602267Sdp 		if ((err = zonecfg_set_bootargs(handle, prop_id)) != Z_OK)
42616215Sgjelinek 			zone_perror(zone, err, B_TRUE);
42622267Sdp 		else
42636215Sgjelinek 			need_to_commit = B_TRUE;
42642267Sdp 		return;
42653247Sgjelinek 	case RT_SCHED:
42663247Sgjelinek 		if ((err = zonecfg_set_sched(handle, prop_id)) != Z_OK)
42676215Sgjelinek 			zone_perror(zone, err, B_TRUE);
42683247Sgjelinek 		else
42696215Sgjelinek 			need_to_commit = B_TRUE;
42703247Sgjelinek 		return;
42713448Sdh155122 	case RT_IPTYPE:
42723448Sdh155122 		if (strcmp(prop_id, "shared") == 0) {
42733448Sdh155122 			iptype = ZS_SHARED;
42743448Sdh155122 		} else if (strcmp(prop_id, "exclusive") == 0) {
42753448Sdh155122 			iptype = ZS_EXCLUSIVE;
42763448Sdh155122 		} else {
42773448Sdh155122 			zerr(gettext("%s value must be '%s' or '%s'."),
42783448Sdh155122 			    pt_to_str(PT_IPTYPE), "shared", "exclusive");
42796215Sgjelinek 			saw_error = B_TRUE;
42803448Sdh155122 			return;
42813448Sdh155122 		}
42823448Sdh155122 		if (iptype == ZS_EXCLUSIVE && !allow_exclusive()) {
42836215Sgjelinek 			saw_error = B_TRUE;
42843448Sdh155122 			return;
42853448Sdh155122 		}
42863448Sdh155122 		if ((err = zonecfg_set_iptype(handle, iptype)) != Z_OK)
42876215Sgjelinek 			zone_perror(zone, err, B_TRUE);
42883448Sdh155122 		else
42896215Sgjelinek 			need_to_commit = B_TRUE;
42903448Sdh155122 		return;
42913247Sgjelinek 	case RT_MAXLWPS:
42923247Sgjelinek 		set_aliased_rctl(ALIAS_MAXLWPS, prop_type, prop_id);
42933247Sgjelinek 		return;
429412725SMenno.Lageman@Sun.COM 	case RT_MAXPROCS:
429512725SMenno.Lageman@Sun.COM 		set_aliased_rctl(ALIAS_MAXPROCS, prop_type, prop_id);
429612725SMenno.Lageman@Sun.COM 		return;
42973247Sgjelinek 	case RT_MAXSHMMEM:
42983247Sgjelinek 		set_aliased_rctl(ALIAS_MAXSHMMEM, prop_type, prop_id);
42993247Sgjelinek 		return;
43003247Sgjelinek 	case RT_MAXSHMIDS:
43013247Sgjelinek 		set_aliased_rctl(ALIAS_MAXSHMIDS, prop_type, prop_id);
43023247Sgjelinek 		return;
43033247Sgjelinek 	case RT_MAXMSGIDS:
43043247Sgjelinek 		set_aliased_rctl(ALIAS_MAXMSGIDS, prop_type, prop_id);
43053247Sgjelinek 		return;
43063247Sgjelinek 	case RT_MAXSEMIDS:
43073247Sgjelinek 		set_aliased_rctl(ALIAS_MAXSEMIDS, prop_type, prop_id);
43083247Sgjelinek 		return;
43093247Sgjelinek 	case RT_SHARES:
43103247Sgjelinek 		set_aliased_rctl(ALIAS_SHARES, prop_type, prop_id);
43113247Sgjelinek 		return;
43128662SJordan.Vaughan@Sun.com 	case RT_HOSTID:
43138662SJordan.Vaughan@Sun.com 		if ((err = zonecfg_set_hostid(handle, prop_id)) != Z_OK) {
43148662SJordan.Vaughan@Sun.com 			if (err == Z_TOO_BIG) {
43158662SJordan.Vaughan@Sun.com 				zerr(gettext("hostid string is too large: %s"),
43168662SJordan.Vaughan@Sun.com 				    prop_id);
43178662SJordan.Vaughan@Sun.com 				saw_error = B_TRUE;
43188662SJordan.Vaughan@Sun.com 			} else {
43198662SJordan.Vaughan@Sun.com 				zone_perror(pt_to_str(prop_type), err, B_TRUE);
43208662SJordan.Vaughan@Sun.com 			}
43218662SJordan.Vaughan@Sun.com 			return;
43228662SJordan.Vaughan@Sun.com 		}
43238662SJordan.Vaughan@Sun.com 		need_to_commit = B_TRUE;
43248662SJordan.Vaughan@Sun.com 		return;
432512633Sjohn.levon@sun.com 	case RT_FS_ALLOWED:
432612633Sjohn.levon@sun.com 		if ((err = zonecfg_set_fs_allowed(handle, prop_id)) != Z_OK)
432712633Sjohn.levon@sun.com 			zone_perror(zone, err, B_TRUE);
432812633Sjohn.levon@sun.com 		else
432912633Sjohn.levon@sun.com 			need_to_commit = B_TRUE;
433012633Sjohn.levon@sun.com 		return;
43310Sstevel@tonic-gate 	case RT_FS:
43320Sstevel@tonic-gate 		switch (prop_type) {
43330Sstevel@tonic-gate 		case PT_DIR:
43340Sstevel@tonic-gate 			(void) strlcpy(in_progress_fstab.zone_fs_dir, prop_id,
43350Sstevel@tonic-gate 			    sizeof (in_progress_fstab.zone_fs_dir));
43360Sstevel@tonic-gate 			return;
43370Sstevel@tonic-gate 		case PT_SPECIAL:
43380Sstevel@tonic-gate 			(void) strlcpy(in_progress_fstab.zone_fs_special,
43390Sstevel@tonic-gate 			    prop_id,
43400Sstevel@tonic-gate 			    sizeof (in_progress_fstab.zone_fs_special));
43410Sstevel@tonic-gate 			return;
43420Sstevel@tonic-gate 		case PT_RAW:
43430Sstevel@tonic-gate 			(void) strlcpy(in_progress_fstab.zone_fs_raw,
43440Sstevel@tonic-gate 			    prop_id, sizeof (in_progress_fstab.zone_fs_raw));
43450Sstevel@tonic-gate 			return;
43460Sstevel@tonic-gate 		case PT_TYPE:
43470Sstevel@tonic-gate 			if (!valid_fs_type(prop_id)) {
43480Sstevel@tonic-gate 				zerr(gettext("\"%s\" is not a valid %s."),
43490Sstevel@tonic-gate 				    prop_id, pt_to_str(PT_TYPE));
43506215Sgjelinek 				saw_error = B_TRUE;
43510Sstevel@tonic-gate 				return;
43520Sstevel@tonic-gate 			}
43530Sstevel@tonic-gate 			(void) strlcpy(in_progress_fstab.zone_fs_type, prop_id,
43540Sstevel@tonic-gate 			    sizeof (in_progress_fstab.zone_fs_type));
43550Sstevel@tonic-gate 			return;
43560Sstevel@tonic-gate 		case PT_OPTIONS:
43570Sstevel@tonic-gate 			if (pp->pv_type != PROP_VAL_SIMPLE &&
43580Sstevel@tonic-gate 			    pp->pv_type != PROP_VAL_LIST) {
43590Sstevel@tonic-gate 				zerr(gettext("A %s or %s value was expected "
43600Sstevel@tonic-gate 				    "here."), pvt_to_str(PROP_VAL_SIMPLE),
43610Sstevel@tonic-gate 				    pvt_to_str(PROP_VAL_LIST));
43626215Sgjelinek 				saw_error = B_TRUE;
43630Sstevel@tonic-gate 				return;
43640Sstevel@tonic-gate 			}
43650Sstevel@tonic-gate 			zonecfg_free_fs_option_list(
43660Sstevel@tonic-gate 			    in_progress_fstab.zone_fs_options);
43670Sstevel@tonic-gate 			in_progress_fstab.zone_fs_options = NULL;
43680Sstevel@tonic-gate 			if (!(pp->pv_type == PROP_VAL_LIST &&
43690Sstevel@tonic-gate 			    pp->pv_list == NULL))
43700Sstevel@tonic-gate 				add_property(cmd);
43710Sstevel@tonic-gate 			return;
43720Sstevel@tonic-gate 		default:
43730Sstevel@tonic-gate 			break;
43740Sstevel@tonic-gate 		}
43756215Sgjelinek 		zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
43766215Sgjelinek 		long_usage(CMD_SET, B_TRUE);
43776215Sgjelinek 		usage(B_FALSE, HELP_PROPS);
43780Sstevel@tonic-gate 		return;
43790Sstevel@tonic-gate 	case RT_NET:
43800Sstevel@tonic-gate 		switch (prop_type) {
43810Sstevel@tonic-gate 		case PT_ADDRESS:
438212748SSowmini.Varadhan@oracle.COM 		case PT_ALLOWED_ADDRESS:
438312748SSowmini.Varadhan@oracle.COM 			if (validate_net_address_syntax(prop_id, B_FALSE)
438412748SSowmini.Varadhan@oracle.COM 			    != Z_OK) {
43856215Sgjelinek 				saw_error = B_TRUE;
43860Sstevel@tonic-gate 				return;
43870Sstevel@tonic-gate 			}
438812748SSowmini.Varadhan@oracle.COM 			set_in_progress_nwiftab_address(prop_id, prop_type);
43890Sstevel@tonic-gate 			break;
43900Sstevel@tonic-gate 		case PT_PHYSICAL:
43910Sstevel@tonic-gate 			if (validate_net_physical_syntax(prop_id) != Z_OK) {
43926215Sgjelinek 				saw_error = B_TRUE;
43930Sstevel@tonic-gate 				return;
43940Sstevel@tonic-gate 			}
43950Sstevel@tonic-gate 			(void) strlcpy(in_progress_nwiftab.zone_nwif_physical,
43960Sstevel@tonic-gate 			    prop_id,
43970Sstevel@tonic-gate 			    sizeof (in_progress_nwiftab.zone_nwif_physical));
43980Sstevel@tonic-gate 			break;
43996076Sgfaden 		case PT_DEFROUTER:
440012748SSowmini.Varadhan@oracle.COM 			if (validate_net_address_syntax(prop_id, B_TRUE)
440112748SSowmini.Varadhan@oracle.COM 			    != Z_OK) {
44026215Sgjelinek 				saw_error = B_TRUE;
44036076Sgfaden 				return;
44046076Sgfaden 			}
44056076Sgfaden 			(void) strlcpy(in_progress_nwiftab.zone_nwif_defrouter,
44066076Sgfaden 			    prop_id,
44076076Sgfaden 			    sizeof (in_progress_nwiftab.zone_nwif_defrouter));
44086076Sgfaden 			break;
44090Sstevel@tonic-gate 		default:
44100Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
44116215Sgjelinek 			    B_TRUE);
44126215Sgjelinek 			long_usage(CMD_SET, B_TRUE);
44136215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
44140Sstevel@tonic-gate 			return;
44150Sstevel@tonic-gate 		}
44160Sstevel@tonic-gate 		return;
44170Sstevel@tonic-gate 	case RT_DEVICE:
44180Sstevel@tonic-gate 		switch (prop_type) {
44190Sstevel@tonic-gate 		case PT_MATCH:
44200Sstevel@tonic-gate 			(void) strlcpy(in_progress_devtab.zone_dev_match,
44210Sstevel@tonic-gate 			    prop_id,
44220Sstevel@tonic-gate 			    sizeof (in_progress_devtab.zone_dev_match));
44230Sstevel@tonic-gate 			break;
44240Sstevel@tonic-gate 		default:
44250Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
44266215Sgjelinek 			    B_TRUE);
44276215Sgjelinek 			long_usage(CMD_SET, B_TRUE);
44286215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
44290Sstevel@tonic-gate 			return;
44300Sstevel@tonic-gate 		}
44310Sstevel@tonic-gate 		return;
44320Sstevel@tonic-gate 	case RT_RCTL:
44330Sstevel@tonic-gate 		switch (prop_type) {
44340Sstevel@tonic-gate 		case PT_NAME:
44350Sstevel@tonic-gate 			if (!zonecfg_valid_rctlname(prop_id)) {
44360Sstevel@tonic-gate 				zerr(gettext("'%s' is not a valid zone %s "
44370Sstevel@tonic-gate 				    "name."), prop_id, rt_to_str(RT_RCTL));
44380Sstevel@tonic-gate 				return;
44390Sstevel@tonic-gate 			}
44400Sstevel@tonic-gate 			(void) strlcpy(in_progress_rctltab.zone_rctl_name,
44410Sstevel@tonic-gate 			    prop_id,
44420Sstevel@tonic-gate 			    sizeof (in_progress_rctltab.zone_rctl_name));
44430Sstevel@tonic-gate 			break;
44440Sstevel@tonic-gate 		case PT_VALUE:
44450Sstevel@tonic-gate 			if (pp->pv_type != PROP_VAL_COMPLEX &&
44460Sstevel@tonic-gate 			    pp->pv_type != PROP_VAL_LIST) {
44470Sstevel@tonic-gate 				zerr(gettext("A %s or %s value was expected "
44480Sstevel@tonic-gate 				    "here."), pvt_to_str(PROP_VAL_COMPLEX),
44490Sstevel@tonic-gate 				    pvt_to_str(PROP_VAL_LIST));
44506215Sgjelinek 				saw_error = B_TRUE;
44510Sstevel@tonic-gate 				return;
44520Sstevel@tonic-gate 			}
44530Sstevel@tonic-gate 			zonecfg_free_rctl_value_list(
44540Sstevel@tonic-gate 			    in_progress_rctltab.zone_rctl_valptr);
44550Sstevel@tonic-gate 			in_progress_rctltab.zone_rctl_valptr = NULL;
44560Sstevel@tonic-gate 			if (!(pp->pv_type == PROP_VAL_LIST &&
44570Sstevel@tonic-gate 			    pp->pv_list == NULL))
44580Sstevel@tonic-gate 				add_property(cmd);
44590Sstevel@tonic-gate 			break;
44600Sstevel@tonic-gate 		default:
44610Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
44626215Sgjelinek 			    B_TRUE);
44636215Sgjelinek 			long_usage(CMD_SET, B_TRUE);
44646215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
44650Sstevel@tonic-gate 			return;
44660Sstevel@tonic-gate 		}
44670Sstevel@tonic-gate 		return;
44680Sstevel@tonic-gate 	case RT_ATTR:
44690Sstevel@tonic-gate 		switch (prop_type) {
44700Sstevel@tonic-gate 		case PT_NAME:
44710Sstevel@tonic-gate 			(void) strlcpy(in_progress_attrtab.zone_attr_name,
44720Sstevel@tonic-gate 			    prop_id,
44730Sstevel@tonic-gate 			    sizeof (in_progress_attrtab.zone_attr_name));
44740Sstevel@tonic-gate 			break;
44750Sstevel@tonic-gate 		case PT_TYPE:
44760Sstevel@tonic-gate 			(void) strlcpy(in_progress_attrtab.zone_attr_type,
44770Sstevel@tonic-gate 			    prop_id,
44780Sstevel@tonic-gate 			    sizeof (in_progress_attrtab.zone_attr_type));
44790Sstevel@tonic-gate 			break;
44800Sstevel@tonic-gate 		case PT_VALUE:
44810Sstevel@tonic-gate 			(void) strlcpy(in_progress_attrtab.zone_attr_value,
44820Sstevel@tonic-gate 			    prop_id,
44830Sstevel@tonic-gate 			    sizeof (in_progress_attrtab.zone_attr_value));
44840Sstevel@tonic-gate 			break;
44850Sstevel@tonic-gate 		default:
44860Sstevel@tonic-gate 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
44876215Sgjelinek 			    B_TRUE);
44886215Sgjelinek 			long_usage(CMD_SET, B_TRUE);
44896215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
44900Sstevel@tonic-gate 			return;
44910Sstevel@tonic-gate 		}
44920Sstevel@tonic-gate 		return;
4493789Sahrens 	case RT_DATASET:
4494789Sahrens 		switch (prop_type) {
4495789Sahrens 		case PT_NAME:
4496789Sahrens 			(void) strlcpy(in_progress_dstab.zone_dataset_name,
4497789Sahrens 			    prop_id,
4498789Sahrens 			    sizeof (in_progress_dstab.zone_dataset_name));
4499789Sahrens 			return;
4500789Sahrens 		default:
4501789Sahrens 			break;
4502789Sahrens 		}
45036215Sgjelinek 		zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
45046215Sgjelinek 		long_usage(CMD_SET, B_TRUE);
45056215Sgjelinek 		usage(B_FALSE, HELP_PROPS);
4506789Sahrens 		return;
45073247Sgjelinek 	case RT_DCPU:
45083247Sgjelinek 		switch (prop_type) {
45093247Sgjelinek 		char *lowp, *highp;
45103247Sgjelinek 
45113247Sgjelinek 		case PT_NCPUS:
45123247Sgjelinek 			lowp = prop_id;
45133247Sgjelinek 			if ((highp = strchr(prop_id, '-')) != NULL)
45143247Sgjelinek 				*highp++ = '\0';
45153247Sgjelinek 			else
45163247Sgjelinek 				highp = lowp;
45173247Sgjelinek 
45183247Sgjelinek 			/* Make sure the input makes sense. */
45193247Sgjelinek 			if (!zonecfg_valid_ncpus(lowp, highp)) {
45203247Sgjelinek 				zerr(gettext("%s property is out of range."),
45213247Sgjelinek 				    pt_to_str(PT_NCPUS));
45226215Sgjelinek 				saw_error = B_TRUE;
45233247Sgjelinek 				return;
45243247Sgjelinek 			}
45253247Sgjelinek 
45263247Sgjelinek 			(void) strlcpy(
45273247Sgjelinek 			    in_progress_psettab.zone_ncpu_min, lowp,
45283247Sgjelinek 			    sizeof (in_progress_psettab.zone_ncpu_min));
45293247Sgjelinek 			(void) strlcpy(
45303247Sgjelinek 			    in_progress_psettab.zone_ncpu_max, highp,
45313247Sgjelinek 			    sizeof (in_progress_psettab.zone_ncpu_max));
45323247Sgjelinek 			return;
45333247Sgjelinek 		case PT_IMPORTANCE:
45343247Sgjelinek 			/* Make sure the value makes sense. */
45353247Sgjelinek 			if (!zonecfg_valid_importance(prop_id)) {
45363247Sgjelinek 				zerr(gettext("%s property is out of range."),
45373247Sgjelinek 				    pt_to_str(PT_IMPORTANCE));
45386215Sgjelinek 				saw_error = B_TRUE;
45393247Sgjelinek 				return;
45403247Sgjelinek 			}
45413247Sgjelinek 
45423247Sgjelinek 			(void) strlcpy(in_progress_psettab.zone_importance,
45433247Sgjelinek 			    prop_id,
45443247Sgjelinek 			    sizeof (in_progress_psettab.zone_importance));
45453247Sgjelinek 			return;
45463247Sgjelinek 		default:
45473247Sgjelinek 			break;
45483247Sgjelinek 		}
45496215Sgjelinek 		zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
45506215Sgjelinek 		long_usage(CMD_SET, B_TRUE);
45516215Sgjelinek 		usage(B_FALSE, HELP_PROPS);
45523247Sgjelinek 		return;
45533792Sakolb 	case RT_PCAP:
45543792Sakolb 		if (prop_type != PT_NCPUS) {
45553792Sakolb 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
45566215Sgjelinek 			    B_TRUE);
45576215Sgjelinek 			long_usage(CMD_SET, B_TRUE);
45586215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
45593792Sakolb 			return;
45603792Sakolb 		}
45613792Sakolb 
45623792Sakolb 		/*
45633792Sakolb 		 * We already checked that an rctl alias is allowed in
45643792Sakolb 		 * the add_resource() function.
45653792Sakolb 		 */
45663792Sakolb 
45673792Sakolb 		if ((cap = strtof(prop_id, &unitp)) <= 0 || *unitp != '\0' ||
45683792Sakolb 		    (int)(cap * 100) < 1) {
45693792Sakolb 			zerr(gettext("%s property is out of range."),
45703792Sakolb 			    pt_to_str(PT_NCPUS));
45716215Sgjelinek 			saw_error = B_TRUE;
45723792Sakolb 			return;
45733792Sakolb 		}
45743792Sakolb 
45753792Sakolb 		if ((err = zonecfg_set_aliased_rctl(handle, ALIAS_CPUCAP,
45763792Sakolb 		    (int)(cap * 100))) != Z_OK)
45776215Sgjelinek 			zone_perror(zone, err, B_TRUE);
45783792Sakolb 		else
45796215Sgjelinek 			need_to_commit = B_TRUE;
45803792Sakolb 		return;
45813247Sgjelinek 	case RT_MCAP:
45823247Sgjelinek 		switch (prop_type) {
45833247Sgjelinek 		case PT_PHYSICAL:
45843247Sgjelinek 			if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
45853247Sgjelinek 				zerr(gettext("A positive number with a "
45863247Sgjelinek 				    "required scale suffix (K, M, G or T) was "
45873247Sgjelinek 				    "expected here."));
45886215Sgjelinek 				saw_error = B_TRUE;
45893247Sgjelinek 			} else if (mem_cap < ONE_MB) {
45903247Sgjelinek 				zerr(gettext("%s value is too small.  It must "
45913247Sgjelinek 				    "be at least 1M."), pt_to_str(PT_PHYSICAL));
45926215Sgjelinek 				saw_error = B_TRUE;
45933247Sgjelinek 			} else {
45943247Sgjelinek 				snprintf(in_progress_mcaptab.zone_physmem_cap,
45953247Sgjelinek 				    physmem_size, "%llu", mem_cap);
45963247Sgjelinek 			}
45973247Sgjelinek 			break;
45983247Sgjelinek 		case PT_SWAP:
45993247Sgjelinek 			/*
46003247Sgjelinek 			 * We have to check if an rctl is allowed here since
46013247Sgjelinek 			 * there might already be a rctl defined that blocks
46023247Sgjelinek 			 * the alias.
46033247Sgjelinek 			 */
46043247Sgjelinek 			if (!zonecfg_aliased_rctl_ok(handle, ALIAS_MAXSWAP)) {
46053247Sgjelinek 				zone_perror(pt_to_str(PT_MAXSWAP),
46066215Sgjelinek 				    Z_ALIAS_DISALLOW, B_FALSE);
46076215Sgjelinek 				saw_error = B_TRUE;
46083247Sgjelinek 				return;
46093247Sgjelinek 			}
46103247Sgjelinek 
46113247Sgjelinek 			if (global_zone)
46123247Sgjelinek 				mem_limit = ONE_MB * 100;
46133247Sgjelinek 			else
46143247Sgjelinek 				mem_limit = ONE_MB * 50;
46153247Sgjelinek 
46163247Sgjelinek 			if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
46173247Sgjelinek 				zerr(gettext("A positive number with a "
46183247Sgjelinek 				    "required scale suffix (K, M, G or T) was "
46193247Sgjelinek 				    "expected here."));
46206215Sgjelinek 				saw_error = B_TRUE;
46213247Sgjelinek 			} else if (mem_cap < mem_limit) {
46223247Sgjelinek 				char buf[128];
46233247Sgjelinek 
46243247Sgjelinek 				(void) snprintf(buf, sizeof (buf), "%llu",
46253247Sgjelinek 				    mem_limit);
46263247Sgjelinek 				bytes_to_units(buf, buf, sizeof (buf));
46273247Sgjelinek 				zerr(gettext("%s value is too small.  It must "
46283247Sgjelinek 				    "be at least %s."), pt_to_str(PT_SWAP),
46293247Sgjelinek 				    buf);
46306215Sgjelinek 				saw_error = B_TRUE;
46313247Sgjelinek 			} else {
46323247Sgjelinek 				if ((err = zonecfg_set_aliased_rctl(handle,
46333247Sgjelinek 				    ALIAS_MAXSWAP, mem_cap)) != Z_OK)
46346215Sgjelinek 					zone_perror(zone, err, B_TRUE);
46353247Sgjelinek 				else
46366215Sgjelinek 					need_to_commit = B_TRUE;
46373247Sgjelinek 			}
46383247Sgjelinek 			break;
46393247Sgjelinek 		case PT_LOCKED:
46403247Sgjelinek 			/*
46413247Sgjelinek 			 * We have to check if an rctl is allowed here since
46423247Sgjelinek 			 * there might already be a rctl defined that blocks
46433247Sgjelinek 			 * the alias.
46443247Sgjelinek 			 */
46453247Sgjelinek 			if (!zonecfg_aliased_rctl_ok(handle,
46463247Sgjelinek 			    ALIAS_MAXLOCKEDMEM)) {
46473247Sgjelinek 				zone_perror(pt_to_str(PT_LOCKED),
46486215Sgjelinek 				    Z_ALIAS_DISALLOW, B_FALSE);
46496215Sgjelinek 				saw_error = B_TRUE;
46503247Sgjelinek 				return;
46513247Sgjelinek 			}
46523247Sgjelinek 
46533247Sgjelinek 			if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
46543247Sgjelinek 				zerr(gettext("A non-negative number with a "
46553247Sgjelinek 				    "required scale suffix (K, M, G or T) was "
46563247Sgjelinek 				    "expected\nhere."));
46576215Sgjelinek 				saw_error = B_TRUE;
46583247Sgjelinek 			} else {
46593247Sgjelinek 				if ((err = zonecfg_set_aliased_rctl(handle,
46603247Sgjelinek 				    ALIAS_MAXLOCKEDMEM, mem_cap)) != Z_OK)
46616215Sgjelinek 					zone_perror(zone, err, B_TRUE);
46623247Sgjelinek 				else
46636215Sgjelinek 					need_to_commit = B_TRUE;
46643247Sgjelinek 			}
46653247Sgjelinek 			break;
46663247Sgjelinek 		default:
46673247Sgjelinek 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
46686215Sgjelinek 			    B_TRUE);
46696215Sgjelinek 			long_usage(CMD_SET, B_TRUE);
46706215Sgjelinek 			usage(B_FALSE, HELP_PROPS);
46713247Sgjelinek 			return;
46723247Sgjelinek 		}
467312578SGlenn.Faden@Sun.COM 		return;
467412578SGlenn.Faden@Sun.COM 	case RT_ADMIN:
467512578SGlenn.Faden@Sun.COM 		switch (prop_type) {
467612578SGlenn.Faden@Sun.COM 		case PT_USER:
467712578SGlenn.Faden@Sun.COM 			(void) strlcpy(in_progress_admintab.zone_admin_user,
467812578SGlenn.Faden@Sun.COM 			    prop_id,
467912578SGlenn.Faden@Sun.COM 			    sizeof (in_progress_admintab.zone_admin_user));
468012578SGlenn.Faden@Sun.COM 			return;
468112578SGlenn.Faden@Sun.COM 		case PT_AUTHS:
468212578SGlenn.Faden@Sun.COM 			(void) strlcpy(in_progress_admintab.zone_admin_auths,
468312578SGlenn.Faden@Sun.COM 			    prop_id,
468412578SGlenn.Faden@Sun.COM 			    sizeof (in_progress_admintab.zone_admin_auths));
468512578SGlenn.Faden@Sun.COM 			return;
468612578SGlenn.Faden@Sun.COM 		default:
468712578SGlenn.Faden@Sun.COM 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
468812578SGlenn.Faden@Sun.COM 			    B_TRUE);
468912578SGlenn.Faden@Sun.COM 			long_usage(CMD_SET, B_TRUE);
469012578SGlenn.Faden@Sun.COM 			usage(B_FALSE, HELP_PROPS);
469112578SGlenn.Faden@Sun.COM 			return;
469212578SGlenn.Faden@Sun.COM 		}
46930Sstevel@tonic-gate 	default:
46946215Sgjelinek 		zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
46956215Sgjelinek 		long_usage(CMD_SET, B_TRUE);
46966215Sgjelinek 		usage(B_FALSE, HELP_RESOURCES);
46970Sstevel@tonic-gate 		return;
46980Sstevel@tonic-gate 	}
46990Sstevel@tonic-gate }
47000Sstevel@tonic-gate 
47010Sstevel@tonic-gate static void
output_prop(FILE * fp,int pnum,char * pval,boolean_t print_notspec)47026215Sgjelinek output_prop(FILE *fp, int pnum, char *pval, boolean_t print_notspec)
47030Sstevel@tonic-gate {
47040Sstevel@tonic-gate 	char *qstr;
47050Sstevel@tonic-gate 
47060Sstevel@tonic-gate 	if (*pval != '\0') {
47070Sstevel@tonic-gate 		qstr = quoteit(pval);
47083247Sgjelinek 		if (pnum == PT_SWAP || pnum == PT_LOCKED)
47093247Sgjelinek 			(void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(pnum),
47103247Sgjelinek 			    qstr);
47113247Sgjelinek 		else
47123247Sgjelinek 			(void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);
47130Sstevel@tonic-gate 		free(qstr);
47140Sstevel@tonic-gate 	} else if (print_notspec)
4715565Sdp 		(void) fprintf(fp, gettext("\t%s not specified\n"),
4716565Sdp 		    pt_to_str(pnum));
4717565Sdp }
4718565Sdp 
4719565Sdp static void
info_zonename(zone_dochandle_t handle,FILE * fp)4720565Sdp info_zonename(zone_dochandle_t handle, FILE *fp)
4721565Sdp {
4722565Sdp 	char zonename[ZONENAME_MAX];
4723565Sdp 
4724565Sdp 	if (zonecfg_get_name(handle, zonename, sizeof (zonename)) == Z_OK)
4725565Sdp 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONENAME),
4726565Sdp 		    zonename);
4727565Sdp 	else
4728565Sdp 		(void) fprintf(fp, gettext("%s not specified\n"),
4729565Sdp 		    pt_to_str(PT_ZONENAME));
47300Sstevel@tonic-gate }
47310Sstevel@tonic-gate 
47320Sstevel@tonic-gate static void
info_zonepath(zone_dochandle_t handle,FILE * fp)47330Sstevel@tonic-gate info_zonepath(zone_dochandle_t handle, FILE *fp)
47340Sstevel@tonic-gate {
47350Sstevel@tonic-gate 	char zonepath[MAXPATHLEN];
47360Sstevel@tonic-gate 
47370Sstevel@tonic-gate 	if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK)
47380Sstevel@tonic-gate 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONEPATH),
47390Sstevel@tonic-gate 		    zonepath);
4740565Sdp 	else {
4741565Sdp 		(void) fprintf(fp, gettext("%s not specified\n"),
4742565Sdp 		    pt_to_str(PT_ZONEPATH));
4743565Sdp 	}
47440Sstevel@tonic-gate }
47450Sstevel@tonic-gate 
47460Sstevel@tonic-gate static void
info_brand(zone_dochandle_t handle,FILE * fp)47472712Snn35248 info_brand(zone_dochandle_t handle, FILE *fp)
47482712Snn35248 {
47492712Snn35248 	char brand[MAXNAMELEN];
47502712Snn35248 
47512712Snn35248 	if (zonecfg_get_brand(handle, brand, sizeof (brand)) == Z_OK)
47522712Snn35248 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BRAND),
47532712Snn35248 		    brand);
47542712Snn35248 	else
47552712Snn35248 		(void) fprintf(fp, "%s %s\n", pt_to_str(PT_BRAND),
47562712Snn35248 		    gettext("not specified"));
47572712Snn35248 }
47582712Snn35248 
47592712Snn35248 static void
info_autoboot(zone_dochandle_t handle,FILE * fp)47600Sstevel@tonic-gate info_autoboot(zone_dochandle_t handle, FILE *fp)
47610Sstevel@tonic-gate {
47620Sstevel@tonic-gate 	boolean_t autoboot;
47630Sstevel@tonic-gate 	int err;
47640Sstevel@tonic-gate 
47650Sstevel@tonic-gate 	if ((err = zonecfg_get_autoboot(handle, &autoboot)) == Z_OK)
47660Sstevel@tonic-gate 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_AUTOBOOT),
47670Sstevel@tonic-gate 		    autoboot ? "true" : "false");
47680Sstevel@tonic-gate 	else
47696215Sgjelinek 		zone_perror(zone, err, B_TRUE);
47700Sstevel@tonic-gate }
47710Sstevel@tonic-gate 
47720Sstevel@tonic-gate static void
info_pool(zone_dochandle_t handle,FILE * fp)47730Sstevel@tonic-gate info_pool(zone_dochandle_t handle, FILE *fp)
47740Sstevel@tonic-gate {
47750Sstevel@tonic-gate 	char pool[MAXNAMELEN];
47760Sstevel@tonic-gate 	int err;
47770Sstevel@tonic-gate 
47780Sstevel@tonic-gate 	if ((err = zonecfg_get_pool(handle, pool, sizeof (pool))) == Z_OK)
47790Sstevel@tonic-gate 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_POOL), pool);
47800Sstevel@tonic-gate 	else
47816215Sgjelinek 		zone_perror(zone, err, B_TRUE);
47820Sstevel@tonic-gate }
47830Sstevel@tonic-gate 
47840Sstevel@tonic-gate static void
info_limitpriv(zone_dochandle_t handle,FILE * fp)47851645Scomay info_limitpriv(zone_dochandle_t handle, FILE *fp)
47861645Scomay {
47871645Scomay 	char *limitpriv;
47881645Scomay 	int err;
47891645Scomay 
47901645Scomay 	if ((err = zonecfg_get_limitpriv(handle, &limitpriv)) == Z_OK) {
47911645Scomay 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_LIMITPRIV),
47921645Scomay 		    limitpriv);
47931645Scomay 		free(limitpriv);
47941645Scomay 	} else {
47956215Sgjelinek 		zone_perror(zone, err, B_TRUE);
47961645Scomay 	}
47971645Scomay }
47981645Scomay 
47991645Scomay static void
info_bootargs(zone_dochandle_t handle,FILE * fp)48002267Sdp info_bootargs(zone_dochandle_t handle, FILE *fp)
48012267Sdp {
48022267Sdp 	char bootargs[BOOTARGS_MAX];
48032267Sdp 	int err;
48042267Sdp 
48052267Sdp 	if ((err = zonecfg_get_bootargs(handle, bootargs,
48062267Sdp 	    sizeof (bootargs))) == Z_OK) {
48072267Sdp 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BOOTARGS),
48082267Sdp 		    bootargs);
48092267Sdp 	} else {
48106215Sgjelinek 		zone_perror(zone, err, B_TRUE);
48112267Sdp 	}
48122267Sdp }
48132267Sdp 
48142267Sdp static void
info_sched(zone_dochandle_t handle,FILE * fp)48153247Sgjelinek info_sched(zone_dochandle_t handle, FILE *fp)
48163247Sgjelinek {
48173247Sgjelinek 	char sched[MAXNAMELEN];
48183247Sgjelinek 	int err;
48193247Sgjelinek 
48203247Sgjelinek 	if ((err = zonecfg_get_sched_class(handle, sched, sizeof (sched)))
48213247Sgjelinek 	    == Z_OK) {
48223247Sgjelinek 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_SCHED), sched);
48233247Sgjelinek 	} else {
48246215Sgjelinek 		zone_perror(zone, err, B_TRUE);
48253247Sgjelinek 	}
48263247Sgjelinek }
48273247Sgjelinek 
48283247Sgjelinek static void
info_iptype(zone_dochandle_t handle,FILE * fp)48293448Sdh155122 info_iptype(zone_dochandle_t handle, FILE *fp)
48303448Sdh155122 {
48313448Sdh155122 	zone_iptype_t iptype;
48323448Sdh155122 	int err;
48333448Sdh155122 
48343448Sdh155122 	if ((err = zonecfg_get_iptype(handle, &iptype)) == Z_OK) {
48353448Sdh155122 		switch (iptype) {
48363448Sdh155122 		case ZS_SHARED:
48373448Sdh155122 			(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
48383448Sdh155122 			    "shared");
48393448Sdh155122 			break;
48403448Sdh155122 		case ZS_EXCLUSIVE:
48413448Sdh155122 			(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
48423448Sdh155122 			    "exclusive");
48433448Sdh155122 			break;
48443448Sdh155122 		}
48453448Sdh155122 	} else {
48466215Sgjelinek 		zone_perror(zone, err, B_TRUE);
48473448Sdh155122 	}
48483448Sdh155122 }
48493448Sdh155122 
48503448Sdh155122 static void
info_hostid(zone_dochandle_t handle,FILE * fp)48518662SJordan.Vaughan@Sun.com info_hostid(zone_dochandle_t handle, FILE *fp)
48528662SJordan.Vaughan@Sun.com {
48538662SJordan.Vaughan@Sun.com 	char hostidp[HW_HOSTID_LEN];
485412633Sjohn.levon@sun.com 	int err;
485512633Sjohn.levon@sun.com 
485612633Sjohn.levon@sun.com 	if ((err = zonecfg_get_hostid(handle, hostidp,
485712633Sjohn.levon@sun.com 	    sizeof (hostidp))) == Z_OK) {
485812633Sjohn.levon@sun.com 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_HOSTID), hostidp);
485912633Sjohn.levon@sun.com 	} else if (err == Z_BAD_PROPERTY) {
486012633Sjohn.levon@sun.com 		(void) fprintf(fp, "%s: \n", pt_to_str(PT_HOSTID));
486112633Sjohn.levon@sun.com 	} else {
486212633Sjohn.levon@sun.com 		zone_perror(zone, err, B_TRUE);
486312633Sjohn.levon@sun.com 	}
486412633Sjohn.levon@sun.com }
486512633Sjohn.levon@sun.com 
486612633Sjohn.levon@sun.com static void
info_fs_allowed(zone_dochandle_t handle,FILE * fp)486712633Sjohn.levon@sun.com info_fs_allowed(zone_dochandle_t handle, FILE *fp)
486812633Sjohn.levon@sun.com {
486912633Sjohn.levon@sun.com 	char fsallowedp[ZONE_FS_ALLOWED_MAX];
487012633Sjohn.levon@sun.com 	int err;
487112633Sjohn.levon@sun.com 
487212633Sjohn.levon@sun.com 	if ((err = zonecfg_get_fs_allowed(handle, fsallowedp,
487312633Sjohn.levon@sun.com 	    sizeof (fsallowedp))) == Z_OK) {
487412633Sjohn.levon@sun.com 		(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_FS_ALLOWED),
487512633Sjohn.levon@sun.com 		    fsallowedp);
487612633Sjohn.levon@sun.com 	} else if (err == Z_BAD_PROPERTY) {
487712633Sjohn.levon@sun.com 		(void) fprintf(fp, "%s: \n", pt_to_str(PT_FS_ALLOWED));
487812633Sjohn.levon@sun.com 	} else {
487912633Sjohn.levon@sun.com 		zone_perror(zone, err, B_TRUE);
488012633Sjohn.levon@sun.com 	}
48818662SJordan.Vaughan@Sun.com }
48828662SJordan.Vaughan@Sun.com 
48838662SJordan.Vaughan@Sun.com static void
output_fs(FILE * fp,struct zone_fstab * fstab)48840Sstevel@tonic-gate output_fs(FILE *fp, struct zone_fstab *fstab)
48850Sstevel@tonic-gate {
48860Sstevel@tonic-gate 	zone_fsopt_t *this;
48870Sstevel@tonic-gate 
48880Sstevel@tonic-gate 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_FS));
48890Sstevel@tonic-gate 	output_prop(fp, PT_DIR, fstab->zone_fs_dir, B_TRUE);
48900Sstevel@tonic-gate 	output_prop(fp, PT_SPECIAL, fstab->zone_fs_special, B_TRUE);
48910Sstevel@tonic-gate 	output_prop(fp, PT_RAW, fstab->zone_fs_raw, B_TRUE);
48920Sstevel@tonic-gate 	output_prop(fp, PT_TYPE, fstab->zone_fs_type, B_TRUE);
48930Sstevel@tonic-gate 	(void) fprintf(fp, "\t%s: [", pt_to_str(PT_OPTIONS));
48940Sstevel@tonic-gate 	for (this = fstab->zone_fs_options; this != NULL;
48950Sstevel@tonic-gate 	    this = this->zone_fsopt_next) {
48960Sstevel@tonic-gate 		if (strchr(this->zone_fsopt_opt, '='))
48970Sstevel@tonic-gate 			(void) fprintf(fp, "\"%s\"", this->zone_fsopt_opt);
48980Sstevel@tonic-gate 		else
48990Sstevel@tonic-gate 			(void) fprintf(fp, "%s", this->zone_fsopt_opt);
49000Sstevel@tonic-gate 		if (this->zone_fsopt_next != NULL)
49010Sstevel@tonic-gate 			(void) fprintf(fp, ",");
49020Sstevel@tonic-gate 	}
49030Sstevel@tonic-gate 	(void) fprintf(fp, "]\n");
49040Sstevel@tonic-gate }
49050Sstevel@tonic-gate 
49060Sstevel@tonic-gate static void
info_fs(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)49070Sstevel@tonic-gate info_fs(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
49080Sstevel@tonic-gate {
49090Sstevel@tonic-gate 	struct zone_fstab lookup, user;
49106215Sgjelinek 	boolean_t output = B_FALSE;
49110Sstevel@tonic-gate 
49120Sstevel@tonic-gate 	if (zonecfg_setfsent(handle) != Z_OK)
49130Sstevel@tonic-gate 		return;
49140Sstevel@tonic-gate 	while (zonecfg_getfsent(handle, &lookup) == Z_OK) {
49150Sstevel@tonic-gate 		if (cmd->cmd_prop_nv_pairs == 0) {
49160Sstevel@tonic-gate 			output_fs(fp, &lookup);
49170Sstevel@tonic-gate 			goto loopend;
49180Sstevel@tonic-gate 		}
49196215Sgjelinek 		if (fill_in_fstab(cmd, &user, B_TRUE) != Z_OK)
49200Sstevel@tonic-gate 			goto loopend;
49210Sstevel@tonic-gate 		if (strlen(user.zone_fs_dir) > 0 &&
49220Sstevel@tonic-gate 		    strcmp(user.zone_fs_dir, lookup.zone_fs_dir) != 0)
49230Sstevel@tonic-gate 			goto loopend;	/* no match */
49240Sstevel@tonic-gate 		if (strlen(user.zone_fs_special) > 0 &&
49250Sstevel@tonic-gate 		    strcmp(user.zone_fs_special, lookup.zone_fs_special) != 0)
49260Sstevel@tonic-gate 			goto loopend;	/* no match */
49270Sstevel@tonic-gate 		if (strlen(user.zone_fs_type) > 0 &&
49280Sstevel@tonic-gate 		    strcmp(user.zone_fs_type, lookup.zone_fs_type) != 0)
49290Sstevel@tonic-gate 			goto loopend;	/* no match */
49300Sstevel@tonic-gate 		output_fs(fp, &lookup);
49316215Sgjelinek 		output = B_TRUE;
49320Sstevel@tonic-gate loopend:
49330Sstevel@tonic-gate 		zonecfg_free_fs_option_list(lookup.zone_fs_options);
49340Sstevel@tonic-gate 	}
49350Sstevel@tonic-gate 	(void) zonecfg_endfsent(handle);
49360Sstevel@tonic-gate 	/*
49370Sstevel@tonic-gate 	 * If a property n/v pair was specified, warn the user if there was
49380Sstevel@tonic-gate 	 * nothing to output.
49390Sstevel@tonic-gate 	 */
49400Sstevel@tonic-gate 	if (!output && cmd->cmd_prop_nv_pairs > 0)
49410Sstevel@tonic-gate 		(void) printf(gettext("No such %s resource.\n"),
49420Sstevel@tonic-gate 		    rt_to_str(RT_FS));
49430Sstevel@tonic-gate }
49440Sstevel@tonic-gate 
49450Sstevel@tonic-gate static void
output_net(FILE * fp,struct zone_nwiftab * nwiftab)49460Sstevel@tonic-gate output_net(FILE *fp, struct zone_nwiftab *nwiftab)
49470Sstevel@tonic-gate {
49480Sstevel@tonic-gate 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_NET));
49490Sstevel@tonic-gate 	output_prop(fp, PT_ADDRESS, nwiftab->zone_nwif_address, B_TRUE);
495012748SSowmini.Varadhan@oracle.COM 	output_prop(fp, PT_ALLOWED_ADDRESS,
495112748SSowmini.Varadhan@oracle.COM 	    nwiftab->zone_nwif_allowed_address, B_TRUE);
49520Sstevel@tonic-gate 	output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE);
49536076Sgfaden 	output_prop(fp, PT_DEFROUTER, nwiftab->zone_nwif_defrouter, B_TRUE);
49540Sstevel@tonic-gate }
49550Sstevel@tonic-gate 
49560Sstevel@tonic-gate static void
info_net(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)49570Sstevel@tonic-gate info_net(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
49580Sstevel@tonic-gate {
49590Sstevel@tonic-gate 	struct zone_nwiftab lookup, user;
49606215Sgjelinek 	boolean_t output = B_FALSE;
49610Sstevel@tonic-gate 
49620Sstevel@tonic-gate 	if (zonecfg_setnwifent(handle) != Z_OK)
49630Sstevel@tonic-gate 		return;
49640Sstevel@tonic-gate 	while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
49650Sstevel@tonic-gate 		if (cmd->cmd_prop_nv_pairs == 0) {
49660Sstevel@tonic-gate 			output_net(fp, &lookup);
49670Sstevel@tonic-gate 			continue;
49680Sstevel@tonic-gate 		}
49696215Sgjelinek 		if (fill_in_nwiftab(cmd, &user, B_TRUE) != Z_OK)
49700Sstevel@tonic-gate 			continue;
49710Sstevel@tonic-gate 		if (strlen(user.zone_nwif_physical) > 0 &&
49720Sstevel@tonic-gate 		    strcmp(user.zone_nwif_physical,
49730Sstevel@tonic-gate 		    lookup.zone_nwif_physical) != 0)
49740Sstevel@tonic-gate 			continue;	/* no match */
49753448Sdh155122 		/* If present make sure it matches */
49760Sstevel@tonic-gate 		if (strlen(user.zone_nwif_address) > 0 &&
49770Sstevel@tonic-gate 		    !zonecfg_same_net_address(user.zone_nwif_address,
49780Sstevel@tonic-gate 		    lookup.zone_nwif_address))
49790Sstevel@tonic-gate 			continue;	/* no match */
49800Sstevel@tonic-gate 		output_net(fp, &lookup);
49816215Sgjelinek 		output = B_TRUE;
49820Sstevel@tonic-gate 	}
49830Sstevel@tonic-gate 	(void) zonecfg_endnwifent(handle);
49840Sstevel@tonic-gate 	/*
49850Sstevel@tonic-gate 	 * If a property n/v pair was specified, warn the user if there was
49860Sstevel@tonic-gate 	 * nothing to output.
49870Sstevel@tonic-gate 	 */
49880Sstevel@tonic-gate 	if (!output && cmd->cmd_prop_nv_pairs > 0)
49890Sstevel@tonic-gate 		(void) printf(gettext("No such %s resource.\n"),
49900Sstevel@tonic-gate 		    rt_to_str(RT_NET));
49910Sstevel@tonic-gate }
49920Sstevel@tonic-gate 
49930Sstevel@tonic-gate static void
output_dev(FILE * fp,struct zone_devtab * devtab)49940Sstevel@tonic-gate output_dev(FILE *fp, struct zone_devtab *devtab)
49950Sstevel@tonic-gate {
49963813Sdp 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_DEVICE));
49970Sstevel@tonic-gate 	output_prop(fp, PT_MATCH, devtab->zone_dev_match, B_TRUE);
49980Sstevel@tonic-gate }
49990Sstevel@tonic-gate 
50000Sstevel@tonic-gate static void
info_dev(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)50010Sstevel@tonic-gate info_dev(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
50020Sstevel@tonic-gate {
50030Sstevel@tonic-gate 	struct zone_devtab lookup, user;
50046215Sgjelinek 	boolean_t output = B_FALSE;
50050Sstevel@tonic-gate 
50060Sstevel@tonic-gate 	if (zonecfg_setdevent(handle) != Z_OK)
50070Sstevel@tonic-gate 		return;
50080Sstevel@tonic-gate 	while (zonecfg_getdevent(handle, &lookup) == Z_OK) {
50090Sstevel@tonic-gate 		if (cmd->cmd_prop_nv_pairs == 0) {
50100Sstevel@tonic-gate 			output_dev(fp, &lookup);
50110Sstevel@tonic-gate 			continue;
50120Sstevel@tonic-gate 		}
50136215Sgjelinek 		if (fill_in_devtab(cmd, &user, B_TRUE) != Z_OK)
50140Sstevel@tonic-gate 			continue;
50150Sstevel@tonic-gate 		if (strlen(user.zone_dev_match) > 0 &&
50160Sstevel@tonic-gate 		    strcmp(user.zone_dev_match, lookup.zone_dev_match) != 0)
50170Sstevel@tonic-gate 			continue;	/* no match */
50180Sstevel@tonic-gate 		output_dev(fp, &lookup);
50196215Sgjelinek 		output = B_TRUE;
50200Sstevel@tonic-gate 	}
50210Sstevel@tonic-gate 	(void) zonecfg_enddevent(handle);
50220Sstevel@tonic-gate 	/*
50230Sstevel@tonic-gate 	 * If a property n/v pair was specified, warn the user if there was
50240Sstevel@tonic-gate 	 * nothing to output.
50250Sstevel@tonic-gate 	 */
50260Sstevel@tonic-gate 	if (!output && cmd->cmd_prop_nv_pairs > 0)
50270Sstevel@tonic-gate 		(void) printf(gettext("No such %s resource.\n"),
50280Sstevel@tonic-gate 		    rt_to_str(RT_DEVICE));
50290Sstevel@tonic-gate }
50300Sstevel@tonic-gate 
50310Sstevel@tonic-gate static void
output_rctl(FILE * fp,struct zone_rctltab * rctltab)50320Sstevel@tonic-gate output_rctl(FILE *fp, struct zone_rctltab *rctltab)
50330Sstevel@tonic-gate {
50340Sstevel@tonic-gate 	struct zone_rctlvaltab *valptr;
50350Sstevel@tonic-gate 
50360Sstevel@tonic-gate 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_RCTL));
50370Sstevel@tonic-gate 	output_prop(fp, PT_NAME, rctltab->zone_rctl_name, B_TRUE);
50380Sstevel@tonic-gate 	for (valptr = rctltab->zone_rctl_valptr; valptr != NULL;
50390Sstevel@tonic-gate 	    valptr = valptr->zone_rctlval_next) {
50400Sstevel@tonic-gate 		fprintf(fp, "\t%s: (%s=%s,%s=%s,%s=%s)\n",
50410Sstevel@tonic-gate 		    pt_to_str(PT_VALUE),
50420Sstevel@tonic-gate 		    pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
50430Sstevel@tonic-gate 		    pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
50440Sstevel@tonic-gate 		    pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
50450Sstevel@tonic-gate 	}
50460Sstevel@tonic-gate }
50470Sstevel@tonic-gate 
50480Sstevel@tonic-gate static void
info_rctl(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)50490Sstevel@tonic-gate info_rctl(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
50500Sstevel@tonic-gate {
50510Sstevel@tonic-gate 	struct zone_rctltab lookup, user;
50526215Sgjelinek 	boolean_t output = B_FALSE;
50530Sstevel@tonic-gate 
50540Sstevel@tonic-gate 	if (zonecfg_setrctlent(handle) != Z_OK)
50550Sstevel@tonic-gate 		return;
50560Sstevel@tonic-gate 	while (zonecfg_getrctlent(handle, &lookup) == Z_OK) {
50570Sstevel@tonic-gate 		if (cmd->cmd_prop_nv_pairs == 0) {
50580Sstevel@tonic-gate 			output_rctl(fp, &lookup);
50596215Sgjelinek 		} else if (fill_in_rctltab(cmd, &user, B_TRUE) == Z_OK &&
50600Sstevel@tonic-gate 		    (strlen(user.zone_rctl_name) == 0 ||
50610Sstevel@tonic-gate 		    strcmp(user.zone_rctl_name, lookup.zone_rctl_name) == 0)) {
50620Sstevel@tonic-gate 			output_rctl(fp, &lookup);
50636215Sgjelinek 			output = B_TRUE;
50640Sstevel@tonic-gate 		}
50650Sstevel@tonic-gate 		zonecfg_free_rctl_value_list(lookup.zone_rctl_valptr);
50660Sstevel@tonic-gate 	}
50670Sstevel@tonic-gate 	(void) zonecfg_endrctlent(handle);
50680Sstevel@tonic-gate 	/*
50690Sstevel@tonic-gate 	 * If a property n/v pair was specified, warn the user if there was
50700Sstevel@tonic-gate 	 * nothing to output.
50710Sstevel@tonic-gate 	 */
50720Sstevel@tonic-gate 	if (!output && cmd->cmd_prop_nv_pairs > 0)
50730Sstevel@tonic-gate 		(void) printf(gettext("No such %s resource.\n"),
50740Sstevel@tonic-gate 		    rt_to_str(RT_RCTL));
50750Sstevel@tonic-gate }
50760Sstevel@tonic-gate 
50770Sstevel@tonic-gate static void
output_attr(FILE * fp,struct zone_attrtab * attrtab)50780Sstevel@tonic-gate output_attr(FILE *fp, struct zone_attrtab *attrtab)
50790Sstevel@tonic-gate {
50800Sstevel@tonic-gate 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_ATTR));
50810Sstevel@tonic-gate 	output_prop(fp, PT_NAME, attrtab->zone_attr_name, B_TRUE);
50820Sstevel@tonic-gate 	output_prop(fp, PT_TYPE, attrtab->zone_attr_type, B_TRUE);
50830Sstevel@tonic-gate 	output_prop(fp, PT_VALUE, attrtab->zone_attr_value, B_TRUE);
50840Sstevel@tonic-gate }
50850Sstevel@tonic-gate 
50860Sstevel@tonic-gate static void
info_attr(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)50870Sstevel@tonic-gate info_attr(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
50880Sstevel@tonic-gate {
50890Sstevel@tonic-gate 	struct zone_attrtab lookup, user;
50906215Sgjelinek 	boolean_t output = B_FALSE;
50910Sstevel@tonic-gate 
50920Sstevel@tonic-gate 	if (zonecfg_setattrent(handle) != Z_OK)
50930Sstevel@tonic-gate 		return;
50940Sstevel@tonic-gate 	while (zonecfg_getattrent(handle, &lookup) == Z_OK) {
50950Sstevel@tonic-gate 		if (cmd->cmd_prop_nv_pairs == 0) {
50960Sstevel@tonic-gate 			output_attr(fp, &lookup);
50970Sstevel@tonic-gate 			continue;
50980Sstevel@tonic-gate 		}
50996215Sgjelinek 		if (fill_in_attrtab(cmd, &user, B_TRUE) != Z_OK)
51000Sstevel@tonic-gate 			continue;
51010Sstevel@tonic-gate 		if (strlen(user.zone_attr_name) > 0 &&
51020Sstevel@tonic-gate 		    strcmp(user.zone_attr_name, lookup.zone_attr_name) != 0)
51030Sstevel@tonic-gate 			continue;	/* no match */
51040Sstevel@tonic-gate 		if (strlen(user.zone_attr_type) > 0 &&
51050Sstevel@tonic-gate 		    strcmp(user.zone_attr_type, lookup.zone_attr_type) != 0)
51060Sstevel@tonic-gate 			continue;	/* no match */
51070Sstevel@tonic-gate 		if (strlen(user.zone_attr_value) > 0 &&
51080Sstevel@tonic-gate 		    strcmp(user.zone_attr_value, lookup.zone_attr_value) != 0)
51090Sstevel@tonic-gate 			continue;	/* no match */
51100Sstevel@tonic-gate 		output_attr(fp, &lookup);
51116215Sgjelinek 		output = B_TRUE;
51120Sstevel@tonic-gate 	}
51130Sstevel@tonic-gate 	(void) zonecfg_endattrent(handle);
51140Sstevel@tonic-gate 	/*
51150Sstevel@tonic-gate 	 * If a property n/v pair was specified, warn the user if there was
51160Sstevel@tonic-gate 	 * nothing to output.
51170Sstevel@tonic-gate 	 */
51180Sstevel@tonic-gate 	if (!output && cmd->cmd_prop_nv_pairs > 0)
51190Sstevel@tonic-gate 		(void) printf(gettext("No such %s resource.\n"),
51200Sstevel@tonic-gate 		    rt_to_str(RT_ATTR));
51210Sstevel@tonic-gate }
51220Sstevel@tonic-gate 
5123789Sahrens static void
output_ds(FILE * fp,struct zone_dstab * dstab)5124789Sahrens output_ds(FILE *fp, struct zone_dstab *dstab)
5125789Sahrens {
5126789Sahrens 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_DATASET));
5127789Sahrens 	output_prop(fp, PT_NAME, dstab->zone_dataset_name, B_TRUE);
5128789Sahrens }
5129789Sahrens 
5130789Sahrens static void
info_ds(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)5131789Sahrens info_ds(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5132789Sahrens {
5133789Sahrens 	struct zone_dstab lookup, user;
51346215Sgjelinek 	boolean_t output = B_FALSE;
5135789Sahrens 
51363247Sgjelinek 	if (zonecfg_setdsent(handle) != Z_OK)
5137789Sahrens 		return;
5138789Sahrens 	while (zonecfg_getdsent(handle, &lookup) == Z_OK) {
5139789Sahrens 		if (cmd->cmd_prop_nv_pairs == 0) {
5140789Sahrens 			output_ds(fp, &lookup);
5141789Sahrens 			continue;
5142789Sahrens 		}
51436215Sgjelinek 		if (fill_in_dstab(cmd, &user, B_TRUE) != Z_OK)
5144789Sahrens 			continue;
5145789Sahrens 		if (strlen(user.zone_dataset_name) > 0 &&
5146789Sahrens 		    strcmp(user.zone_dataset_name,
5147789Sahrens 		    lookup.zone_dataset_name) != 0)
5148789Sahrens 			continue;	/* no match */
5149789Sahrens 		output_ds(fp, &lookup);
51506215Sgjelinek 		output = B_TRUE;
5151789Sahrens 	}
5152789Sahrens 	(void) zonecfg_enddsent(handle);
5153789Sahrens 	/*
5154789Sahrens 	 * If a property n/v pair was specified, warn the user if there was
5155789Sahrens 	 * nothing to output.
5156789Sahrens 	 */
5157789Sahrens 	if (!output && cmd->cmd_prop_nv_pairs > 0)
5158789Sahrens 		(void) printf(gettext("No such %s resource.\n"),
5159789Sahrens 		    rt_to_str(RT_DATASET));
5160789Sahrens }
5161789Sahrens 
51623247Sgjelinek static void
output_pset(FILE * fp,struct zone_psettab * psettab)51633247Sgjelinek output_pset(FILE *fp, struct zone_psettab *psettab)
51643247Sgjelinek {
51653247Sgjelinek 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_DCPU));
51663247Sgjelinek 	if (strcmp(psettab->zone_ncpu_min, psettab->zone_ncpu_max) == 0)
51673247Sgjelinek 		(void) fprintf(fp, "\t%s: %s\n", pt_to_str(PT_NCPUS),
51683247Sgjelinek 		    psettab->zone_ncpu_max);
51693247Sgjelinek 	else
51703247Sgjelinek 		(void) fprintf(fp, "\t%s: %s-%s\n", pt_to_str(PT_NCPUS),
51713247Sgjelinek 		    psettab->zone_ncpu_min, psettab->zone_ncpu_max);
51723247Sgjelinek 	if (psettab->zone_importance[0] != '\0')
51733247Sgjelinek 		(void) fprintf(fp, "\t%s: %s\n", pt_to_str(PT_IMPORTANCE),
51743247Sgjelinek 		    psettab->zone_importance);
51753247Sgjelinek }
51763247Sgjelinek 
51773247Sgjelinek static void
info_pset(zone_dochandle_t handle,FILE * fp)51783247Sgjelinek info_pset(zone_dochandle_t handle, FILE *fp)
51793247Sgjelinek {
51803247Sgjelinek 	struct zone_psettab lookup;
51813247Sgjelinek 
51823247Sgjelinek 	if (zonecfg_getpsetent(handle, &lookup) == Z_OK)
51833247Sgjelinek 		output_pset(fp, &lookup);
51843247Sgjelinek }
51853247Sgjelinek 
51863247Sgjelinek static void
output_pcap(FILE * fp)51873792Sakolb output_pcap(FILE *fp)
51883792Sakolb {
51893792Sakolb 	uint64_t cap;
51903792Sakolb 
51913792Sakolb 	if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &cap) == Z_OK) {
51923792Sakolb 		float scaled = (float)cap / 100;
51933792Sakolb 		(void) fprintf(fp, "%s:\n", rt_to_str(RT_PCAP));
51943792Sakolb 		(void) fprintf(fp, "\t[%s: %.2f]\n", pt_to_str(PT_NCPUS),
51953792Sakolb 		    scaled);
51963792Sakolb 	}
51973792Sakolb }
51983792Sakolb 
51993792Sakolb static void
info_pcap(FILE * fp)52003792Sakolb info_pcap(FILE *fp)
52013792Sakolb {
52023792Sakolb 	output_pcap(fp);
52033792Sakolb }
52043792Sakolb 
52053792Sakolb 
52063792Sakolb static void
info_aliased_rctl(zone_dochandle_t handle,FILE * fp,char * alias)52073247Sgjelinek info_aliased_rctl(zone_dochandle_t handle, FILE *fp, char *alias)
52083247Sgjelinek {
52093247Sgjelinek 	uint64_t limit;
52103247Sgjelinek 
52113247Sgjelinek 	if (zonecfg_get_aliased_rctl(handle, alias, &limit) == Z_OK) {
52123247Sgjelinek 		/* convert memory based properties */
52133247Sgjelinek 		if (strcmp(alias, ALIAS_MAXSHMMEM) == 0) {
52143247Sgjelinek 			char buf[128];
52153247Sgjelinek 
52163247Sgjelinek 			(void) snprintf(buf, sizeof (buf), "%llu", limit);
52173247Sgjelinek 			bytes_to_units(buf, buf, sizeof (buf));
52183247Sgjelinek 			(void) fprintf(fp, "[%s: %s]\n", alias, buf);
52193247Sgjelinek 			return;
52203247Sgjelinek 		}
52213247Sgjelinek 
52223247Sgjelinek 		(void) fprintf(fp, "[%s: %llu]\n", alias, limit);
52233247Sgjelinek 	}
52243247Sgjelinek }
52253247Sgjelinek 
52263247Sgjelinek static void
bytes_to_units(char * str,char * buf,int bufsize)52273247Sgjelinek bytes_to_units(char *str, char *buf, int bufsize)
52283247Sgjelinek {
52293247Sgjelinek 	unsigned long long num;
52303247Sgjelinek 	unsigned long long save = 0;
52313247Sgjelinek 	char *units = "BKMGT";
52323247Sgjelinek 	char *up = units;
52333247Sgjelinek 
52343247Sgjelinek 	num = strtoll(str, NULL, 10);
52353247Sgjelinek 
52363247Sgjelinek 	if (num < 1024) {
52373247Sgjelinek 		(void) snprintf(buf, bufsize, "%llu", num);
52383247Sgjelinek 		return;
52393247Sgjelinek 	}
52403247Sgjelinek 
52413247Sgjelinek 	while ((num >= 1024) && (*up != 'T')) {
52423247Sgjelinek 		up++; /* next unit of measurement */
52433247Sgjelinek 		save = num;
52443247Sgjelinek 		num = (num + 512) >> 10;
52453247Sgjelinek 	}
52463247Sgjelinek 
52473247Sgjelinek 	/* check if we should output a fraction.  snprintf will round for us */
52483247Sgjelinek 	if (save % 1024 != 0 && ((save >> 10) < 10))
52493247Sgjelinek 		(void) snprintf(buf, bufsize, "%2.1f%c", ((float)save / 1024),
52503247Sgjelinek 		    *up);
52513247Sgjelinek 	else
52523247Sgjelinek 		(void) snprintf(buf, bufsize, "%llu%c", num, *up);
52533247Sgjelinek }
52543247Sgjelinek 
52553247Sgjelinek static void
output_mcap(FILE * fp,struct zone_mcaptab * mcaptab,int showswap,uint64_t maxswap,int showlocked,uint64_t maxlocked)52563247Sgjelinek output_mcap(FILE *fp, struct zone_mcaptab *mcaptab, int showswap,
52573247Sgjelinek     uint64_t maxswap, int showlocked, uint64_t maxlocked)
52583247Sgjelinek {
52593247Sgjelinek 	char buf[128];
52603247Sgjelinek 
52613247Sgjelinek 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_MCAP));
52623247Sgjelinek 	if (mcaptab->zone_physmem_cap[0] != '\0') {
52633247Sgjelinek 		bytes_to_units(mcaptab->zone_physmem_cap, buf, sizeof (buf));
52643247Sgjelinek 		output_prop(fp, PT_PHYSICAL, buf, B_TRUE);
52653247Sgjelinek 	}
52663247Sgjelinek 
52673247Sgjelinek 	if (showswap == Z_OK) {
52683247Sgjelinek 		(void) snprintf(buf, sizeof (buf), "%llu", maxswap);
52693247Sgjelinek 		bytes_to_units(buf, buf, sizeof (buf));
52703247Sgjelinek 		output_prop(fp, PT_SWAP, buf, B_TRUE);
52713247Sgjelinek 	}
52723247Sgjelinek 
52733247Sgjelinek 	if (showlocked == Z_OK) {
52743247Sgjelinek 		(void) snprintf(buf, sizeof (buf), "%llu", maxlocked);
52753247Sgjelinek 		bytes_to_units(buf, buf, sizeof (buf));
52763247Sgjelinek 		output_prop(fp, PT_LOCKED, buf, B_TRUE);
52773247Sgjelinek 	}
52783247Sgjelinek }
52793247Sgjelinek 
52803247Sgjelinek static void
info_mcap(zone_dochandle_t handle,FILE * fp)52813247Sgjelinek info_mcap(zone_dochandle_t handle, FILE *fp)
52823247Sgjelinek {
52833247Sgjelinek 	int res1, res2, res3;
52843247Sgjelinek 	uint64_t swap_limit;
52853247Sgjelinek 	uint64_t locked_limit;
52863247Sgjelinek 	struct zone_mcaptab lookup;
52873247Sgjelinek 
52883247Sgjelinek 	bzero(&lookup, sizeof (lookup));
52893247Sgjelinek 	res1 = zonecfg_getmcapent(handle, &lookup);
52903247Sgjelinek 	res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
52913247Sgjelinek 	res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
52923247Sgjelinek 	    &locked_limit);
52933247Sgjelinek 
52943247Sgjelinek 	if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
52953247Sgjelinek 		output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
52963247Sgjelinek }
52973247Sgjelinek 
529812578SGlenn.Faden@Sun.COM static void
output_auth(FILE * fp,struct zone_admintab * admintab)529912578SGlenn.Faden@Sun.COM output_auth(FILE *fp, struct zone_admintab *admintab)
530012578SGlenn.Faden@Sun.COM {
530112578SGlenn.Faden@Sun.COM 	(void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
530212578SGlenn.Faden@Sun.COM 	output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
530312578SGlenn.Faden@Sun.COM 	output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
530412578SGlenn.Faden@Sun.COM }
530512578SGlenn.Faden@Sun.COM 
530612578SGlenn.Faden@Sun.COM static void
info_auth(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)530712578SGlenn.Faden@Sun.COM info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
530812578SGlenn.Faden@Sun.COM {
530912578SGlenn.Faden@Sun.COM 	struct zone_admintab lookup, user;
531012578SGlenn.Faden@Sun.COM 	boolean_t output = B_FALSE;
531112578SGlenn.Faden@Sun.COM 	int err;
531212578SGlenn.Faden@Sun.COM 
531312578SGlenn.Faden@Sun.COM 	if ((err = zonecfg_setadminent(handle)) != Z_OK) {
531412578SGlenn.Faden@Sun.COM 		zone_perror(zone, err, B_TRUE);
531512578SGlenn.Faden@Sun.COM 		return;
531612578SGlenn.Faden@Sun.COM 	}
531712578SGlenn.Faden@Sun.COM 	while (zonecfg_getadminent(handle, &lookup) == Z_OK) {
531812578SGlenn.Faden@Sun.COM 		if (cmd->cmd_prop_nv_pairs == 0) {
531912578SGlenn.Faden@Sun.COM 			output_auth(fp, &lookup);
532012578SGlenn.Faden@Sun.COM 			continue;
532112578SGlenn.Faden@Sun.COM 		}
532212578SGlenn.Faden@Sun.COM 		if (fill_in_admintab(cmd, &user, B_TRUE) != Z_OK)
532312578SGlenn.Faden@Sun.COM 			continue;
532412578SGlenn.Faden@Sun.COM 		if (strlen(user.zone_admin_user) > 0 &&
532512578SGlenn.Faden@Sun.COM 		    strcmp(user.zone_admin_user, lookup.zone_admin_user) != 0)
532612578SGlenn.Faden@Sun.COM 			continue;	/* no match */
532712578SGlenn.Faden@Sun.COM 		output_auth(fp, &lookup);
532812578SGlenn.Faden@Sun.COM 		output = B_TRUE;
532912578SGlenn.Faden@Sun.COM 	}
533012578SGlenn.Faden@Sun.COM 	(void) zonecfg_endadminent(handle);
533112578SGlenn.Faden@Sun.COM 	/*
533212578SGlenn.Faden@Sun.COM 	 * If a property n/v pair was specified, warn the user if there was
533312578SGlenn.Faden@Sun.COM 	 * nothing to output.
533412578SGlenn.Faden@Sun.COM 	 */
533512578SGlenn.Faden@Sun.COM 	if (!output && cmd->cmd_prop_nv_pairs > 0)
533612578SGlenn.Faden@Sun.COM 		(void) printf(gettext("No such %s resource.\n"),
533712578SGlenn.Faden@Sun.COM 		    rt_to_str(RT_ADMIN));
533812578SGlenn.Faden@Sun.COM }
533912578SGlenn.Faden@Sun.COM 
53400Sstevel@tonic-gate void
info_func(cmd_t * cmd)53410Sstevel@tonic-gate info_func(cmd_t *cmd)
53420Sstevel@tonic-gate {
53430Sstevel@tonic-gate 	FILE *fp = stdout;
53446215Sgjelinek 	boolean_t need_to_close = B_FALSE;
5345*12761SSusan.Kamm-Worrell@Sun.COM 	char *pager, *space;
53463247Sgjelinek 	int type;
53473247Sgjelinek 	int res1, res2;
53483247Sgjelinek 	uint64_t swap_limit;
53493247Sgjelinek 	uint64_t locked_limit;
535011882SFrank.Batschulat@Sun.COM 	struct stat statbuf;
53510Sstevel@tonic-gate 
53520Sstevel@tonic-gate 	assert(cmd != NULL);
53530Sstevel@tonic-gate 
53546215Sgjelinek 	if (initialize(B_TRUE) != Z_OK)
53550Sstevel@tonic-gate 		return;
53560Sstevel@tonic-gate 
53570Sstevel@tonic-gate 	/* don't page error output */
53580Sstevel@tonic-gate 	if (interactive_mode) {
53590Sstevel@tonic-gate 		if ((pager = getenv("PAGER")) == NULL)
53600Sstevel@tonic-gate 			pager = PAGER;
5361*12761SSusan.Kamm-Worrell@Sun.COM 		space = strchr(pager, ' ');
5362*12761SSusan.Kamm-Worrell@Sun.COM 		if (space)
5363*12761SSusan.Kamm-Worrell@Sun.COM 			*space = '\0';
536411882SFrank.Batschulat@Sun.COM 		if (stat(pager, &statbuf) == 0) {
5365*12761SSusan.Kamm-Worrell@Sun.COM 			if (space)
5366*12761SSusan.Kamm-Worrell@Sun.COM 				*space = ' ';
536711882SFrank.Batschulat@Sun.COM 			if ((fp = popen(pager, "w")) != NULL)
536811882SFrank.Batschulat@Sun.COM 				need_to_close = B_TRUE;
536911882SFrank.Batschulat@Sun.COM 			else
537011882SFrank.Batschulat@Sun.COM 				fp = stdout;
537111882SFrank.Batschulat@Sun.COM 		} else {
537211882SFrank.Batschulat@Sun.COM 			zerr(gettext("PAGER %s does not exist (%s)."),
537311882SFrank.Batschulat@Sun.COM 			    pager, strerror(errno));
537411882SFrank.Batschulat@Sun.COM 		}
537511882SFrank.Batschulat@Sun.COM 
53760Sstevel@tonic-gate 		setbuf(fp, NULL);
53770Sstevel@tonic-gate 	}
53780Sstevel@tonic-gate 
53790Sstevel@tonic-gate 	if (!global_scope) {
53800Sstevel@tonic-gate 		switch (resource_scope) {
53810Sstevel@tonic-gate 		case RT_FS:
53820Sstevel@tonic-gate 			output_fs(fp, &in_progress_fstab);
53830Sstevel@tonic-gate 			break;
53840Sstevel@tonic-gate 		case RT_NET:
53850Sstevel@tonic-gate 			output_net(fp, &in_progress_nwiftab);
53860Sstevel@tonic-gate 			break;
53870Sstevel@tonic-gate 		case RT_DEVICE:
53880Sstevel@tonic-gate 			output_dev(fp, &in_progress_devtab);
53890Sstevel@tonic-gate 			break;
53900Sstevel@tonic-gate 		case RT_RCTL:
53910Sstevel@tonic-gate 			output_rctl(fp, &in_progress_rctltab);
53920Sstevel@tonic-gate 			break;
53930Sstevel@tonic-gate 		case RT_ATTR:
53940Sstevel@tonic-gate 			output_attr(fp, &in_progress_attrtab);
53950Sstevel@tonic-gate 			break;
5396789Sahrens 		case RT_DATASET:
5397789Sahrens 			output_ds(fp, &in_progress_dstab);
5398789Sahrens 			break;
53993247Sgjelinek 		case RT_DCPU:
54003247Sgjelinek 			output_pset(fp, &in_progress_psettab);
54013247Sgjelinek 			break;
54023792Sakolb 		case RT_PCAP:
54033792Sakolb 			output_pcap(fp);
54043792Sakolb 			break;
54053247Sgjelinek 		case RT_MCAP:
54063247Sgjelinek 			res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
54073247Sgjelinek 			    &swap_limit);
54083247Sgjelinek 			res2 = zonecfg_get_aliased_rctl(handle,
54093247Sgjelinek 			    ALIAS_MAXLOCKEDMEM, &locked_limit);
54103247Sgjelinek 			output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
54113247Sgjelinek 			    res2, locked_limit);
54123247Sgjelinek 			break;
541312578SGlenn.Faden@Sun.COM 		case RT_ADMIN:
541412578SGlenn.Faden@Sun.COM 			output_auth(fp, &in_progress_admintab);
541512578SGlenn.Faden@Sun.COM 			break;
54163247Sgjelinek 		}
54173247Sgjelinek 		goto cleanup;
54183247Sgjelinek 	}
54193247Sgjelinek 
54203247Sgjelinek 	type = cmd->cmd_res_type;
54213247Sgjelinek 
54223247Sgjelinek 	if (gz_invalid_rt_property(type)) {
54233247Sgjelinek 		zerr(gettext("%s is not a valid property for the global zone."),
54243247Sgjelinek 		    rt_to_str(type));
54253247Sgjelinek 		goto cleanup;
54263247Sgjelinek 	}
54273247Sgjelinek 
54283247Sgjelinek 	if (gz_invalid_resource(type)) {
54293247Sgjelinek 		zerr(gettext("%s is not a valid resource for the global zone."),
54303247Sgjelinek 		    rt_to_str(type));
54310Sstevel@tonic-gate 		goto cleanup;
54320Sstevel@tonic-gate 	}
54330Sstevel@tonic-gate 
54340Sstevel@tonic-gate 	switch (cmd->cmd_res_type) {
54350Sstevel@tonic-gate 	case RT_UNKNOWN:
5436565Sdp 		info_zonename(handle, fp);
54373247Sgjelinek 		if (!global_zone) {
54383247Sgjelinek 			info_zonepath(handle, fp);
54393247Sgjelinek 			info_brand(handle, fp);
54403247Sgjelinek 			info_autoboot(handle, fp);
54413247Sgjelinek 			info_bootargs(handle, fp);
54423247Sgjelinek 		}
54430Sstevel@tonic-gate 		info_pool(handle, fp);
54443247Sgjelinek 		if (!global_zone) {
54453247Sgjelinek 			info_limitpriv(handle, fp);
54463247Sgjelinek 			info_sched(handle, fp);
54473448Sdh155122 			info_iptype(handle, fp);
54488662SJordan.Vaughan@Sun.com 			info_hostid(handle, fp);
544912633Sjohn.levon@sun.com 			info_fs_allowed(handle, fp);
54503247Sgjelinek 		}
54513247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
545212725SMenno.Lageman@Sun.COM 		info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
54533247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
54543247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
54553247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
54563247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
54573247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_SHARES);
54583247Sgjelinek 		if (!global_zone) {
54593247Sgjelinek 			info_fs(handle, fp, cmd);
54603247Sgjelinek 			info_net(handle, fp, cmd);
54613247Sgjelinek 			info_dev(handle, fp, cmd);
54623247Sgjelinek 		}
54633247Sgjelinek 		info_pset(handle, fp);
54643792Sakolb 		info_pcap(fp);
54653247Sgjelinek 		info_mcap(handle, fp);
54663247Sgjelinek 		if (!global_zone) {
54673247Sgjelinek 			info_attr(handle, fp, cmd);
54683247Sgjelinek 			info_ds(handle, fp, cmd);
546912578SGlenn.Faden@Sun.COM 			info_auth(handle, fp, cmd);
54703247Sgjelinek 		}
54710Sstevel@tonic-gate 		info_rctl(handle, fp, cmd);
54720Sstevel@tonic-gate 		break;
5473565Sdp 	case RT_ZONENAME:
5474565Sdp 		info_zonename(handle, fp);
5475565Sdp 		break;
54760Sstevel@tonic-gate 	case RT_ZONEPATH:
54770Sstevel@tonic-gate 		info_zonepath(handle, fp);
54780Sstevel@tonic-gate 		break;
54792712Snn35248 	case RT_BRAND:
54802712Snn35248 		info_brand(handle, fp);
54812712Snn35248 		break;
54820Sstevel@tonic-gate 	case RT_AUTOBOOT:
54830Sstevel@tonic-gate 		info_autoboot(handle, fp);
54840Sstevel@tonic-gate 		break;
54850Sstevel@tonic-gate 	case RT_POOL:
54860Sstevel@tonic-gate 		info_pool(handle, fp);
54870Sstevel@tonic-gate 		break;
54881645Scomay 	case RT_LIMITPRIV:
54891645Scomay 		info_limitpriv(handle, fp);
54901645Scomay 		break;
54912267Sdp 	case RT_BOOTARGS:
54922267Sdp 		info_bootargs(handle, fp);
54932267Sdp 		break;
54943247Sgjelinek 	case RT_SCHED:
54953247Sgjelinek 		info_sched(handle, fp);
54963247Sgjelinek 		break;
54973448Sdh155122 	case RT_IPTYPE:
54983448Sdh155122 		info_iptype(handle, fp);
54993448Sdh155122 		break;
55003247Sgjelinek 	case RT_MAXLWPS:
55013247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
55023247Sgjelinek 		break;
550312725SMenno.Lageman@Sun.COM 	case RT_MAXPROCS:
550412725SMenno.Lageman@Sun.COM 		info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
550512725SMenno.Lageman@Sun.COM 		break;
55063247Sgjelinek 	case RT_MAXSHMMEM:
55073247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
55083247Sgjelinek 		break;
55093247Sgjelinek 	case RT_MAXSHMIDS:
55103247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
55113247Sgjelinek 		break;
55123247Sgjelinek 	case RT_MAXMSGIDS:
55133247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
55143247Sgjelinek 		break;
55153247Sgjelinek 	case RT_MAXSEMIDS:
55163247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
55173247Sgjelinek 		break;
55183247Sgjelinek 	case RT_SHARES:
55193247Sgjelinek 		info_aliased_rctl(handle, fp, ALIAS_SHARES);
55203247Sgjelinek 		break;
55210Sstevel@tonic-gate 	case RT_FS:
55220Sstevel@tonic-gate 		info_fs(handle, fp, cmd);
55230Sstevel@tonic-gate 		break;
55240Sstevel@tonic-gate 	case RT_NET:
55250Sstevel@tonic-gate 		info_net(handle, fp, cmd);
55260Sstevel@tonic-gate 		break;
55270Sstevel@tonic-gate 	case RT_DEVICE:
55280Sstevel@tonic-gate 		info_dev(handle, fp, cmd);
55290Sstevel@tonic-gate 		break;
55300Sstevel@tonic-gate 	case RT_RCTL:
55310Sstevel@tonic-gate 		info_rctl(handle, fp, cmd);
55320Sstevel@tonic-gate 		break;
55330Sstevel@tonic-gate 	case RT_ATTR:
55340Sstevel@tonic-gate 		info_attr(handle, fp, cmd);
55350Sstevel@tonic-gate 		break;
5536789Sahrens 	case RT_DATASET:
5537789Sahrens 		info_ds(handle, fp, cmd);
5538789Sahrens 		break;
55393247Sgjelinek 	case RT_DCPU:
55403247Sgjelinek 		info_pset(handle, fp);
55413247Sgjelinek 		break;
55423792Sakolb 	case RT_PCAP:
55433792Sakolb 		info_pcap(fp);
55443792Sakolb 		break;
55453247Sgjelinek 	case RT_MCAP:
55463247Sgjelinek 		info_mcap(handle, fp);
55473247Sgjelinek 		break;
55488662SJordan.Vaughan@Sun.com 	case RT_HOSTID:
55498662SJordan.Vaughan@Sun.com 		info_hostid(handle, fp);
55508662SJordan.Vaughan@Sun.com 		break;
555112578SGlenn.Faden@Sun.COM 	case RT_ADMIN:
555212578SGlenn.Faden@Sun.COM 		info_auth(handle, fp, cmd);
555312578SGlenn.Faden@Sun.COM 		break;
555412633Sjohn.levon@sun.com 	case RT_FS_ALLOWED:
555512633Sjohn.levon@sun.com 		info_fs_allowed(handle, fp);
555612633Sjohn.levon@sun.com 		break;
55570Sstevel@tonic-gate 	default:
55580Sstevel@tonic-gate 		zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
55596215Sgjelinek 		    B_TRUE);
55600Sstevel@tonic-gate 	}
55610Sstevel@tonic-gate 
55620Sstevel@tonic-gate cleanup:
55630Sstevel@tonic-gate 	if (need_to_close)
55640Sstevel@tonic-gate 		(void) pclose(fp);
55650Sstevel@tonic-gate }
55660Sstevel@tonic-gate 
5567565Sdp /*
5568565Sdp  * Helper function for verify-- checks that a required string property
5569565Sdp  * exists.
5570565Sdp  */
5571565Sdp static void
check_reqd_prop(char * attr,int rt,int pt,int * ret_val)5572565Sdp check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
55730Sstevel@tonic-gate {
5574565Sdp 	if (strlen(attr) == 0) {
5575565Sdp 		zerr(gettext("%s: %s not specified"), rt_to_str(rt),
5576565Sdp 		    pt_to_str(pt));
55776215Sgjelinek 		saw_error = B_TRUE;
5578565Sdp 		if (*ret_val == Z_OK)
5579565Sdp 			*ret_val = Z_REQD_PROPERTY_MISSING;
55800Sstevel@tonic-gate 	}
55810Sstevel@tonic-gate }
55820Sstevel@tonic-gate 
55832712Snn35248 static int
do_subproc(char * cmdbuf)55842712Snn35248 do_subproc(char *cmdbuf)
55852712Snn35248 {
55862712Snn35248 	char inbuf[MAX_CMD_LEN];
55872712Snn35248 	FILE *file;
55882712Snn35248 	int status;
55892712Snn35248 
55902712Snn35248 	file = popen(cmdbuf, "r");
55912712Snn35248 	if (file == NULL) {
55922712Snn35248 		zerr(gettext("Could not launch: %s"), cmdbuf);
55932712Snn35248 		return (-1);
55942712Snn35248 	}
55952712Snn35248 
55962712Snn35248 	while (fgets(inbuf, sizeof (inbuf), file) != NULL)
55972712Snn35248 		fprintf(stderr, "%s", inbuf);
55982712Snn35248 	status = pclose(file);
55992712Snn35248 
56002712Snn35248 	if (WIFSIGNALED(status)) {
56012712Snn35248 		zerr(gettext("%s unexpectedly terminated due to signal %d"),
56022712Snn35248 		    cmdbuf, WTERMSIG(status));
56032712Snn35248 		return (-1);
56042712Snn35248 	}
56052712Snn35248 	assert(WIFEXITED(status));
56062712Snn35248 	return (WEXITSTATUS(status));
56072712Snn35248 }
56082712Snn35248 
56092712Snn35248 static int
brand_verify(zone_dochandle_t handle)56102712Snn35248 brand_verify(zone_dochandle_t handle)
56112712Snn35248 {
56122814Snn35248 	char xml_file[32];
56132712Snn35248 	char cmdbuf[MAX_CMD_LEN];
56142727Sedp 	brand_handle_t bh;
56152712Snn35248 	char brand[MAXNAMELEN];
56162712Snn35248 	int err;
56172712Snn35248 
56182712Snn35248 	if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
56192712Snn35248 		zerr("%s: %s\n", zone, gettext("could not get zone brand"));
56202712Snn35248 		return (Z_INVALID_DOCUMENT);
56212712Snn35248 	}
56222727Sedp 	if ((bh = brand_open(brand)) == NULL) {
56232712Snn35248 		zerr("%s: %s\n", zone, gettext("unknown brand."));
56242712Snn35248 		return (Z_INVALID_DOCUMENT);
56252712Snn35248 	}
56262712Snn35248 
56272712Snn35248 	/*
56282712Snn35248 	 * Fetch the verify command, if any, from the brand configuration
56292712Snn35248 	 * and build the command line to execute it.
56302712Snn35248 	 */
56312712Snn35248 	strcpy(cmdbuf, EXEC_PREFIX);
56322727Sedp 	err = brand_get_verify_cfg(bh, cmdbuf + EXEC_LEN,
56332712Snn35248 	    sizeof (cmdbuf) - (EXEC_LEN + (strlen(xml_file) + 1)));
56342727Sedp 	brand_close(bh);
56352712Snn35248 	if (err != Z_OK) {
56362712Snn35248 		zerr("%s: %s\n", zone,
56372712Snn35248 		    gettext("could not get brand verification command"));
56382712Snn35248 		return (Z_INVALID_DOCUMENT);
56392712Snn35248 	}
56402712Snn35248 
56412712Snn35248 	/*
56422712Snn35248 	 * If the brand doesn't provide a verification routine, we just
56432712Snn35248 	 * return success.
56442712Snn35248 	 */
56452712Snn35248 	if (strlen(cmdbuf) == EXEC_LEN)
56462712Snn35248 		return (Z_OK);
56472712Snn35248 
56482712Snn35248 	/*
56492712Snn35248 	 * Dump the current config information for this zone to a file.
56502712Snn35248 	 */
56512814Snn35248 	strcpy(xml_file, "/tmp/zonecfg_verify.XXXXXX");
56522712Snn35248 	if (mkstemp(xml_file) == NULL)
56532712Snn35248 		return (Z_TEMP_FILE);
56542712Snn35248 	if ((err = zonecfg_verify_save(handle, xml_file)) != Z_OK) {
56552712Snn35248 		(void) unlink(xml_file);
56562712Snn35248 		return (err);
56572712Snn35248 	}
56582712Snn35248 
56592712Snn35248 	/*
56602712Snn35248 	 * Execute the verification command.
56612712Snn35248 	 */
56622712Snn35248 	if ((strlcat(cmdbuf, " ", MAX_CMD_LEN) >= MAX_CMD_LEN) ||
56632712Snn35248 	    (strlcat(cmdbuf, xml_file, MAX_CMD_LEN) >= MAX_CMD_LEN)) {
56642712Snn35248 		err = Z_BRAND_ERROR;
56652712Snn35248 	} else {
56662712Snn35248 		err = do_subproc(cmdbuf);
56672712Snn35248 	}
56682712Snn35248 
56692712Snn35248 	(void) unlink(xml_file);
56702712Snn35248 	return ((err == Z_OK) ? Z_OK : Z_BRAND_ERROR);
56712712Snn35248 }
56722712Snn35248 
56730Sstevel@tonic-gate /*
567412748SSowmini.Varadhan@oracle.COM  * Track the network interfaces listed in zonecfg(1m) in a linked list
567512748SSowmini.Varadhan@oracle.COM  * so that we can later check that defrouter is specified for an exclusive IP
567612748SSowmini.Varadhan@oracle.COM  * zone if and only if at least one allowed-address has been specified.
567712748SSowmini.Varadhan@oracle.COM  */
567812748SSowmini.Varadhan@oracle.COM static boolean_t
add_nwif(struct zone_nwiftab * nwif)567912748SSowmini.Varadhan@oracle.COM add_nwif(struct zone_nwiftab *nwif)
568012748SSowmini.Varadhan@oracle.COM {
568112748SSowmini.Varadhan@oracle.COM 	struct xif *tmp;
568212748SSowmini.Varadhan@oracle.COM 
568312748SSowmini.Varadhan@oracle.COM 	for (tmp = xif; tmp != NULL; tmp = tmp->xif_next) {
568412748SSowmini.Varadhan@oracle.COM 		if (strcmp(tmp->xif_name, nwif->zone_nwif_physical) == 0) {
568512748SSowmini.Varadhan@oracle.COM 			if (strlen(nwif->zone_nwif_allowed_address) > 0)
568612748SSowmini.Varadhan@oracle.COM 				tmp->xif_has_address = B_TRUE;
568712748SSowmini.Varadhan@oracle.COM 			if (strlen(nwif->zone_nwif_defrouter) > 0)
568812748SSowmini.Varadhan@oracle.COM 				tmp->xif_has_defrouter = B_TRUE;
568912748SSowmini.Varadhan@oracle.COM 			return (B_TRUE);
569012748SSowmini.Varadhan@oracle.COM 		}
569112748SSowmini.Varadhan@oracle.COM 	}
569212748SSowmini.Varadhan@oracle.COM 
569312748SSowmini.Varadhan@oracle.COM 	tmp = malloc(sizeof (*tmp));
569412748SSowmini.Varadhan@oracle.COM 	if (tmp == NULL) {
569512748SSowmini.Varadhan@oracle.COM 		zerr(gettext("memory allocation failed for %s"),
569612748SSowmini.Varadhan@oracle.COM 		    nwif->zone_nwif_physical);
569712748SSowmini.Varadhan@oracle.COM 		return (B_FALSE);
569812748SSowmini.Varadhan@oracle.COM 	}
569912748SSowmini.Varadhan@oracle.COM 	strlcpy(tmp->xif_name, nwif->zone_nwif_physical,
570012748SSowmini.Varadhan@oracle.COM 	    sizeof (tmp->xif_name));
570112748SSowmini.Varadhan@oracle.COM 	tmp->xif_has_defrouter = (strlen(nwif->zone_nwif_defrouter) > 0);
570212748SSowmini.Varadhan@oracle.COM 	tmp->xif_has_address = (strlen(nwif->zone_nwif_allowed_address) > 0);
570312748SSowmini.Varadhan@oracle.COM 	tmp->xif_next = xif;
570412748SSowmini.Varadhan@oracle.COM 	xif = tmp;
570512748SSowmini.Varadhan@oracle.COM 	return (B_TRUE);
570612748SSowmini.Varadhan@oracle.COM }
570712748SSowmini.Varadhan@oracle.COM 
570812748SSowmini.Varadhan@oracle.COM /*
57090Sstevel@tonic-gate  * See the DTD for which attributes are required for which resources.
57100Sstevel@tonic-gate  *
57110Sstevel@tonic-gate  * This function can be called by commit_func(), which needs to save things,
57120Sstevel@tonic-gate  * in addition to the general call from parse_and_run(), which doesn't need
57130Sstevel@tonic-gate  * things saved.  Since the parameters are standardized, we distinguish by
57140Sstevel@tonic-gate  * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
57150Sstevel@tonic-gate  * that a save is needed.
57160Sstevel@tonic-gate  */
57170Sstevel@tonic-gate void
verify_func(cmd_t * cmd)57180Sstevel@tonic-gate verify_func(cmd_t *cmd)
57190Sstevel@tonic-gate {
57200Sstevel@tonic-gate 	struct zone_nwiftab nwiftab;
57210Sstevel@tonic-gate 	struct zone_fstab fstab;
57220Sstevel@tonic-gate 	struct zone_attrtab attrtab;
57230Sstevel@tonic-gate 	struct zone_rctltab rctltab;
5724789Sahrens 	struct zone_dstab dstab;
57253247Sgjelinek 	struct zone_psettab psettab;
572612578SGlenn.Faden@Sun.COM 	struct zone_admintab admintab;
57270Sstevel@tonic-gate 	char zonepath[MAXPATHLEN];
57283247Sgjelinek 	char sched[MAXNAMELEN];
57292712Snn35248 	char brand[MAXNAMELEN];
57308662SJordan.Vaughan@Sun.com 	char hostidp[HW_HOSTID_LEN];
573112633Sjohn.levon@sun.com 	char fsallowedp[ZONE_FS_ALLOWED_MAX];
57320Sstevel@tonic-gate 	int err, ret_val = Z_OK, arg;
57333792Sakolb 	int pset_res;
57346215Sgjelinek 	boolean_t save = B_FALSE;
57356215Sgjelinek 	boolean_t arg_err = B_FALSE;
57363448Sdh155122 	zone_iptype_t iptype;
57373247Sgjelinek 	boolean_t has_cpu_shares = B_FALSE;
57383792Sakolb 	boolean_t has_cpu_cap = B_FALSE;
573912748SSowmini.Varadhan@oracle.COM 	struct xif *tmp;
57400Sstevel@tonic-gate 
57410Sstevel@tonic-gate 	optind = 0;
57423691Sgjelinek 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
57430Sstevel@tonic-gate 		switch (arg) {
57440Sstevel@tonic-gate 		case '?':
57450Sstevel@tonic-gate 			longer_usage(CMD_VERIFY);
57466215Sgjelinek 			arg_err = B_TRUE;
57473691Sgjelinek 			break;
57480Sstevel@tonic-gate 		default:
57490Sstevel@tonic-gate 			short_usage(CMD_VERIFY);
57506215Sgjelinek 			arg_err = B_TRUE;
57513691Sgjelinek 			break;
57523691Sgjelinek 		}
57533691Sgjelinek 	}
57543691Sgjelinek 	if (arg_err)
57553691Sgjelinek 		return;
57563691Sgjelinek 
57570Sstevel@tonic-gate 	if (optind > cmd->cmd_argc) {
57580Sstevel@tonic-gate 		short_usage(CMD_VERIFY);
57590Sstevel@tonic-gate 		return;
57600Sstevel@tonic-gate 	}
57610Sstevel@tonic-gate 
57620Sstevel@tonic-gate 	if (zone_is_read_only(CMD_VERIFY))
57630Sstevel@tonic-gate 		return;
57640Sstevel@tonic-gate 
57650Sstevel@tonic-gate 	assert(cmd != NULL);
57660Sstevel@tonic-gate 
57670Sstevel@tonic-gate 	if (cmd->cmd_argc > 0 && (strcmp(cmd->cmd_argv[0], "save") == 0))
57686215Sgjelinek 		save = B_TRUE;
57696215Sgjelinek 	if (initialize(B_TRUE) != Z_OK)
57700Sstevel@tonic-gate 		return;
57710Sstevel@tonic-gate 
57723247Sgjelinek 	if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) != Z_OK &&
57733247Sgjelinek 	    !global_zone) {
5774565Sdp 		zerr(gettext("%s not specified"), pt_to_str(PT_ZONEPATH));
57750Sstevel@tonic-gate 		ret_val = Z_REQD_RESOURCE_MISSING;
57766215Sgjelinek 		saw_error = B_TRUE;
57770Sstevel@tonic-gate 	}
57783247Sgjelinek 	if (strlen(zonepath) == 0 && !global_zone) {
5779565Sdp 		zerr(gettext("%s cannot be empty."), pt_to_str(PT_ZONEPATH));
57800Sstevel@tonic-gate 		ret_val = Z_REQD_RESOURCE_MISSING;
57816215Sgjelinek 		saw_error = B_TRUE;
57820Sstevel@tonic-gate 	}
57830Sstevel@tonic-gate 
57842712Snn35248 	if ((err = zonecfg_get_brand(handle, brand, sizeof (brand))) != Z_OK) {
57856215Sgjelinek 		zone_perror(zone, err, B_TRUE);
57862712Snn35248 		return;
57872712Snn35248 	}
57889954SEdward.Pilatowicz@Sun.COM 	if ((err = brand_verify(handle)) != Z_OK) {
57899954SEdward.Pilatowicz@Sun.COM 		zone_perror(zone, err, B_TRUE);
57909954SEdward.Pilatowicz@Sun.COM 		return;
57912712Snn35248 	}
57922712Snn35248 
57933448Sdh155122 	if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
57943448Sdh155122 		zerr("%s %s", gettext("cannot get"), pt_to_str(PT_IPTYPE));
57953448Sdh155122 		ret_val = Z_REQD_RESOURCE_MISSING;
57966215Sgjelinek 		saw_error = B_TRUE;
57973448Sdh155122 	}
57980Sstevel@tonic-gate 
579912633Sjohn.levon@sun.com 	if (zonecfg_get_hostid(handle, hostidp,
580012633Sjohn.levon@sun.com 	    sizeof (hostidp)) == Z_INVALID_PROPERTY) {
580112633Sjohn.levon@sun.com 		zerr(gettext("%s: invalid hostid: %s"),
580212633Sjohn.levon@sun.com 		    zone, hostidp);
580312633Sjohn.levon@sun.com 		return;
580412633Sjohn.levon@sun.com 	}
580512633Sjohn.levon@sun.com 
580612633Sjohn.levon@sun.com 	if (zonecfg_get_fs_allowed(handle, fsallowedp,
580712633Sjohn.levon@sun.com 	    sizeof (fsallowedp)) == Z_INVALID_PROPERTY) {
580812633Sjohn.levon@sun.com 		zerr(gettext("%s: invalid fs-allowed: %s"),
580912633Sjohn.levon@sun.com 		    zone, fsallowedp);
58108662SJordan.Vaughan@Sun.com 		return;
58118662SJordan.Vaughan@Sun.com 	}
58128662SJordan.Vaughan@Sun.com 
58130Sstevel@tonic-gate 	if ((err = zonecfg_setfsent(handle)) != Z_OK) {
58146215Sgjelinek 		zone_perror(zone, err, B_TRUE);
58150Sstevel@tonic-gate 		return;
58160Sstevel@tonic-gate 	}
58170Sstevel@tonic-gate 	while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
5818565Sdp 		check_reqd_prop(fstab.zone_fs_dir, RT_FS, PT_DIR, &ret_val);
5819565Sdp 		check_reqd_prop(fstab.zone_fs_special, RT_FS, PT_SPECIAL,
5820565Sdp 		    &ret_val);
5821565Sdp 		check_reqd_prop(fstab.zone_fs_type, RT_FS, PT_TYPE, &ret_val);
5822565Sdp 
58230Sstevel@tonic-gate 		zonecfg_free_fs_option_list(fstab.zone_fs_options);
58240Sstevel@tonic-gate 	}
58250Sstevel@tonic-gate 	(void) zonecfg_endfsent(handle);
58260Sstevel@tonic-gate 
58270Sstevel@tonic-gate 	if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
58286215Sgjelinek 		zone_perror(zone, err, B_TRUE);
58290Sstevel@tonic-gate 		return;
58300Sstevel@tonic-gate 	}
58310Sstevel@tonic-gate 	while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
58323448Sdh155122 		/*
58333448Sdh155122 		 * physical is required in all cases.
58346076Sgfaden 		 * A shared IP requires an address,
58356076Sgfaden 		 * and may include a default router, while
58366076Sgfaden 		 * an exclusive IP must have neither an address
58376076Sgfaden 		 * nor a default router.
58388457SJordan.Vaughan@Sun.com 		 * The physical interface name must be valid in all cases.
58393448Sdh155122 		 */
5840565Sdp 		check_reqd_prop(nwiftab.zone_nwif_physical, RT_NET,
5841565Sdp 		    PT_PHYSICAL, &ret_val);
58428457SJordan.Vaughan@Sun.com 		if (validate_net_physical_syntax(nwiftab.zone_nwif_physical) !=
58438457SJordan.Vaughan@Sun.com 		    Z_OK) {
58448457SJordan.Vaughan@Sun.com 			saw_error = B_TRUE;
58458457SJordan.Vaughan@Sun.com 			if (ret_val == Z_OK)
58468457SJordan.Vaughan@Sun.com 				ret_val = Z_INVAL;
58478457SJordan.Vaughan@Sun.com 		}
58483448Sdh155122 
58493448Sdh155122 		switch (iptype) {
58503448Sdh155122 		case ZS_SHARED:
58513448Sdh155122 			check_reqd_prop(nwiftab.zone_nwif_address, RT_NET,
58523448Sdh155122 			    PT_ADDRESS, &ret_val);
585312748SSowmini.Varadhan@oracle.COM 			if (strlen(nwiftab.zone_nwif_allowed_address) > 0) {
585412748SSowmini.Varadhan@oracle.COM 				zerr(gettext("%s: %s cannot be specified "
585512748SSowmini.Varadhan@oracle.COM 				    "for a shared IP type"),
585612748SSowmini.Varadhan@oracle.COM 				    rt_to_str(RT_NET),
585712748SSowmini.Varadhan@oracle.COM 				    pt_to_str(PT_ALLOWED_ADDRESS));
585812748SSowmini.Varadhan@oracle.COM 				saw_error = B_TRUE;
585912748SSowmini.Varadhan@oracle.COM 				if (ret_val == Z_OK)
586012748SSowmini.Varadhan@oracle.COM 					ret_val = Z_INVAL;
586112748SSowmini.Varadhan@oracle.COM 			}
58623448Sdh155122 			break;
58633448Sdh155122 		case ZS_EXCLUSIVE:
58643448Sdh155122 			if (strlen(nwiftab.zone_nwif_address) > 0) {
58653448Sdh155122 				zerr(gettext("%s: %s cannot be specified "
58663448Sdh155122 				    "for an exclusive IP type"),
58673448Sdh155122 				    rt_to_str(RT_NET), pt_to_str(PT_ADDRESS));
58686215Sgjelinek 				saw_error = B_TRUE;
58693448Sdh155122 				if (ret_val == Z_OK)
58703448Sdh155122 					ret_val = Z_INVAL;
587112748SSowmini.Varadhan@oracle.COM 			} else {
587212748SSowmini.Varadhan@oracle.COM 				if (!add_nwif(&nwiftab)) {
587312748SSowmini.Varadhan@oracle.COM 					saw_error = B_TRUE;
587412748SSowmini.Varadhan@oracle.COM 					if (ret_val == Z_OK)
587512748SSowmini.Varadhan@oracle.COM 						ret_val = Z_INVAL;
587612748SSowmini.Varadhan@oracle.COM 				}
58776076Sgfaden 			}
58783448Sdh155122 			break;
58793448Sdh155122 		}
58800Sstevel@tonic-gate 	}
588112748SSowmini.Varadhan@oracle.COM 	for (tmp = xif; tmp != NULL; tmp = tmp->xif_next) {
588212748SSowmini.Varadhan@oracle.COM 		if (!tmp->xif_has_address && tmp->xif_has_defrouter) {
588312748SSowmini.Varadhan@oracle.COM 			zerr(gettext("%s: %s for %s cannot be specified "
588412748SSowmini.Varadhan@oracle.COM 			    "without %s for an exclusive IP type"),
588512748SSowmini.Varadhan@oracle.COM 			    rt_to_str(RT_NET), pt_to_str(PT_DEFROUTER),
588612748SSowmini.Varadhan@oracle.COM 			    tmp->xif_name, pt_to_str(PT_ALLOWED_ADDRESS));
588712748SSowmini.Varadhan@oracle.COM 			saw_error = B_TRUE;
588812748SSowmini.Varadhan@oracle.COM 			ret_val = Z_INVAL;
588912748SSowmini.Varadhan@oracle.COM 		}
589012748SSowmini.Varadhan@oracle.COM 	}
589112748SSowmini.Varadhan@oracle.COM 	free(xif);
589212748SSowmini.Varadhan@oracle.COM 	xif = NULL;
58930Sstevel@tonic-gate 	(void) zonecfg_endnwifent(handle);
58940Sstevel@tonic-gate 
58950Sstevel@tonic-gate 	if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
58966215Sgjelinek 		zone_perror(zone, err, B_TRUE);
58970Sstevel@tonic-gate 		return;
58980Sstevel@tonic-gate 	}
58990Sstevel@tonic-gate 	while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
5900565Sdp 		check_reqd_prop(rctltab.zone_rctl_name, RT_RCTL, PT_NAME,
5901565Sdp 		    &ret_val);
5902565Sdp 
59033247Sgjelinek 		if (strcmp(rctltab.zone_rctl_name, "zone.cpu-shares") == 0)
59043247Sgjelinek 			has_cpu_shares = B_TRUE;
59053247Sgjelinek 
59063792Sakolb 		if (strcmp(rctltab.zone_rctl_name, "zone.cpu-cap") == 0)
59073792Sakolb 			has_cpu_cap = B_TRUE;
59083792Sakolb 
59090Sstevel@tonic-gate 		if (rctltab.zone_rctl_valptr == NULL) {
59100Sstevel@tonic-gate 			zerr(gettext("%s: no %s specified"),
59110Sstevel@tonic-gate 			    rt_to_str(RT_RCTL), pt_to_str(PT_VALUE));
59126215Sgjelinek 			saw_error = B_TRUE;
59130Sstevel@tonic-gate 			if (ret_val == Z_OK)
59140Sstevel@tonic-gate 				ret_val = Z_REQD_PROPERTY_MISSING;
59150Sstevel@tonic-gate 		} else {
59160Sstevel@tonic-gate 			zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
59170Sstevel@tonic-gate 		}
59180Sstevel@tonic-gate 	}
59190Sstevel@tonic-gate 	(void) zonecfg_endrctlent(handle);
59200Sstevel@tonic-gate 
59213792Sakolb 	if ((pset_res = zonecfg_lookup_pset(handle, &psettab)) == Z_OK &&
59223792Sakolb 	    has_cpu_shares) {
59233247Sgjelinek 		zerr(gettext("%s zone.cpu-shares and %s are incompatible."),
59243247Sgjelinek 		    rt_to_str(RT_RCTL), rt_to_str(RT_DCPU));
59256215Sgjelinek 		saw_error = B_TRUE;
59263247Sgjelinek 		if (ret_val == Z_OK)
59273247Sgjelinek 			ret_val = Z_INCOMPATIBLE;
59283247Sgjelinek 	}
59293247Sgjelinek 
59303247Sgjelinek 	if (has_cpu_shares && zonecfg_get_sched_class(handle, sched,
59313247Sgjelinek 	    sizeof (sched)) == Z_OK && strlen(sched) > 0 &&
59323247Sgjelinek 	    strcmp(sched, "FSS") != 0) {
59333247Sgjelinek 		zerr(gettext("WARNING: %s zone.cpu-shares and %s=%s are "
59343247Sgjelinek 		    "incompatible"),
59353247Sgjelinek 		    rt_to_str(RT_RCTL), rt_to_str(RT_SCHED), sched);
59366215Sgjelinek 		saw_error = B_TRUE;
59373247Sgjelinek 		if (ret_val == Z_OK)
59383247Sgjelinek 			ret_val = Z_INCOMPATIBLE;
59393247Sgjelinek 	}
59403247Sgjelinek 
59413792Sakolb 	if (pset_res == Z_OK && has_cpu_cap) {
59423792Sakolb 		zerr(gettext("%s zone.cpu-cap and the %s are incompatible."),
59433792Sakolb 		    rt_to_str(RT_RCTL), rt_to_str(RT_DCPU));
59446215Sgjelinek 		saw_error = B_TRUE;
59453792Sakolb 		if (ret_val == Z_OK)
59463792Sakolb 			ret_val = Z_INCOMPATIBLE;
59473792Sakolb 	}
59483792Sakolb 
59490Sstevel@tonic-gate 	if ((err = zonecfg_setattrent(handle)) != Z_OK) {
59506215Sgjelinek 		zone_perror(zone, err, B_TRUE);
59510Sstevel@tonic-gate 		return;
59520Sstevel@tonic-gate 	}
59530Sstevel@tonic-gate 	while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
5954565Sdp 		check_reqd_prop(attrtab.zone_attr_name, RT_ATTR, PT_NAME,
5955565Sdp 		    &ret_val);
5956565Sdp 		check_reqd_prop(attrtab.zone_attr_type, RT_ATTR, PT_TYPE,
5957565Sdp 		    &ret_val);
5958565Sdp 		check_reqd_prop(attrtab.zone_attr_value, RT_ATTR, PT_VALUE,
5959565Sdp 		    &ret_val);
59600Sstevel@tonic-gate 	}
59610Sstevel@tonic-gate 	(void) zonecfg_endattrent(handle);
59620Sstevel@tonic-gate 
5963789Sahrens 	if ((err = zonecfg_setdsent(handle)) != Z_OK) {
59646215Sgjelinek 		zone_perror(zone, err, B_TRUE);
5965789Sahrens 		return;
5966789Sahrens 	}
5967789Sahrens 	while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
5968789Sahrens 		if (strlen(dstab.zone_dataset_name) == 0) {
5969789Sahrens 			zerr("%s: %s %s", rt_to_str(RT_DATASET),
5970789Sahrens 			    pt_to_str(PT_NAME), gettext("not specified"));
59716215Sgjelinek 			saw_error = B_TRUE;
5972789Sahrens 			if (ret_val == Z_OK)
5973789Sahrens 				ret_val = Z_REQD_PROPERTY_MISSING;
5974789Sahrens 		} else if (!zfs_name_valid(dstab.zone_dataset_name,
5975789Sahrens 		    ZFS_TYPE_FILESYSTEM)) {
5976789Sahrens 			zerr("%s: %s %s", rt_to_str(RT_DATASET),
5977789Sahrens 			    pt_to_str(PT_NAME), gettext("invalid"));
59786215Sgjelinek 			saw_error = B_TRUE;
5979789Sahrens 			if (ret_val == Z_OK)
5980789Sahrens 				ret_val = Z_BAD_PROPERTY;
5981789Sahrens 		}
5982789Sahrens 
5983789Sahrens 	}
5984789Sahrens 	(void) zonecfg_enddsent(handle);
5985789Sahrens 
598612578SGlenn.Faden@Sun.COM 	if ((err = zonecfg_setadminent(handle)) != Z_OK) {
598712578SGlenn.Faden@Sun.COM 		zone_perror(zone, err, B_TRUE);
598812578SGlenn.Faden@Sun.COM 		return;
598912578SGlenn.Faden@Sun.COM 	}
599012578SGlenn.Faden@Sun.COM 	while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
599112578SGlenn.Faden@Sun.COM 		check_reqd_prop(admintab.zone_admin_user, RT_ADMIN,
599212578SGlenn.Faden@Sun.COM 		    PT_USER, &ret_val);
599312578SGlenn.Faden@Sun.COM 		check_reqd_prop(admintab.zone_admin_auths, RT_ADMIN,
599412578SGlenn.Faden@Sun.COM 		    PT_AUTHS, &ret_val);
599512578SGlenn.Faden@Sun.COM 		if ((ret_val == Z_OK) && (getpwnam(admintab.zone_admin_user)
599612578SGlenn.Faden@Sun.COM 		    == NULL)) {
599712578SGlenn.Faden@Sun.COM 			zerr(gettext("%s %s is not a valid username"),
599812578SGlenn.Faden@Sun.COM 			    pt_to_str(PT_USER),
599912578SGlenn.Faden@Sun.COM 			    admintab.zone_admin_user);
600012578SGlenn.Faden@Sun.COM 			ret_val = Z_BAD_PROPERTY;
600112578SGlenn.Faden@Sun.COM 		}
600212578SGlenn.Faden@Sun.COM 		if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
600312578SGlenn.Faden@Sun.COM 		    admintab.zone_admin_auths, zone))) {
600412578SGlenn.Faden@Sun.COM 			ret_val = Z_BAD_PROPERTY;
600512578SGlenn.Faden@Sun.COM 		}
600612578SGlenn.Faden@Sun.COM 	}
600712578SGlenn.Faden@Sun.COM 	(void) zonecfg_endadminent(handle);
600812578SGlenn.Faden@Sun.COM 
60090Sstevel@tonic-gate 	if (!global_scope) {
60100Sstevel@tonic-gate 		zerr(gettext("resource specification incomplete"));
60116215Sgjelinek 		saw_error = B_TRUE;
60120Sstevel@tonic-gate 		if (ret_val == Z_OK)
60130Sstevel@tonic-gate 			ret_val = Z_INSUFFICIENT_SPEC;
60140Sstevel@tonic-gate 	}
60150Sstevel@tonic-gate 
60160Sstevel@tonic-gate 	if (save) {
6017565Sdp 		if (ret_val == Z_OK) {
6018565Sdp 			if ((ret_val = zonecfg_save(handle)) == Z_OK) {
60196215Sgjelinek 				need_to_commit = B_FALSE;
6020565Sdp 				(void) strlcpy(revert_zone, zone,
6021565Sdp 				    sizeof (revert_zone));
6022565Sdp 			}
6023565Sdp 		} else {
6024565Sdp 			zerr(gettext("Zone %s failed to verify"), zone);
6025565Sdp 		}
60260Sstevel@tonic-gate 	}
60270Sstevel@tonic-gate 	if (ret_val != Z_OK)
60286215Sgjelinek 		zone_perror(zone, ret_val, B_TRUE);
60290Sstevel@tonic-gate }
60300Sstevel@tonic-gate 
60310Sstevel@tonic-gate void
cancel_func(cmd_t * cmd)60320Sstevel@tonic-gate cancel_func(cmd_t *cmd)
60330Sstevel@tonic-gate {
60340Sstevel@tonic-gate 	int arg;
60356215Sgjelinek 	boolean_t arg_err = B_FALSE;
60360Sstevel@tonic-gate 
60370Sstevel@tonic-gate 	assert(cmd != NULL);
60380Sstevel@tonic-gate 
60390Sstevel@tonic-gate 	optind = 0;
60403691Sgjelinek 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
60410Sstevel@tonic-gate 		switch (arg) {
60420Sstevel@tonic-gate 		case '?':
60430Sstevel@tonic-gate 			longer_usage(CMD_CANCEL);
60446215Sgjelinek 			arg_err = B_TRUE;
60453691Sgjelinek 			break;
60460Sstevel@tonic-gate 		default:
60470Sstevel@tonic-gate 			short_usage(CMD_CANCEL);
60486215Sgjelinek 			arg_err = B_TRUE;
60493691Sgjelinek 			break;
60503691Sgjelinek 		}
60513691Sgjelinek 	}
60523691Sgjelinek 	if (arg_err)
60533691Sgjelinek 		return;
60543691Sgjelinek 
60550Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
60560Sstevel@tonic-gate 		short_usage(CMD_CANCEL);
60570Sstevel@tonic-gate 		return;
60580Sstevel@tonic-gate 	}
60590Sstevel@tonic-gate 
60600Sstevel@tonic-gate 	if (global_scope)
60610Sstevel@tonic-gate 		scope_usage(CMD_CANCEL);
60626215Sgjelinek 	global_scope = B_TRUE;
60630Sstevel@tonic-gate 	zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
60640Sstevel@tonic-gate 	bzero(&in_progress_fstab, sizeof (in_progress_fstab));
60650Sstevel@tonic-gate 	bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
60660Sstevel@tonic-gate 	bzero(&in_progress_devtab, sizeof (in_progress_devtab));
60670Sstevel@tonic-gate 	zonecfg_free_rctl_value_list(in_progress_rctltab.zone_rctl_valptr);
60680Sstevel@tonic-gate 	bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
60690Sstevel@tonic-gate 	bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
6070789Sahrens 	bzero(&in_progress_dstab, sizeof (in_progress_dstab));
60710Sstevel@tonic-gate }
60720Sstevel@tonic-gate 
60730Sstevel@tonic-gate static int
validate_attr_name(char * name)60740Sstevel@tonic-gate validate_attr_name(char *name)
60750Sstevel@tonic-gate {
60760Sstevel@tonic-gate 	int i;
60770Sstevel@tonic-gate 
60780Sstevel@tonic-gate 	if (!isalnum(name[0])) {
60790Sstevel@tonic-gate 		zerr(gettext("Invalid %s %s %s: must start with an alpha-"
60800Sstevel@tonic-gate 		    "numeric character."), rt_to_str(RT_ATTR),
60810Sstevel@tonic-gate 		    pt_to_str(PT_NAME), name);
60820Sstevel@tonic-gate 		return (Z_INVAL);
60830Sstevel@tonic-gate 	}
60840Sstevel@tonic-gate 	for (i = 1; name[i]; i++)
60850Sstevel@tonic-gate 		if (!isalnum(name[i]) && name[i] != '-' && name[i] != '.') {
60860Sstevel@tonic-gate 			zerr(gettext("Invalid %s %s %s: can only contain "
60870Sstevel@tonic-gate 			    "alpha-numeric characters, plus '-' and '.'."),
60880Sstevel@tonic-gate 			    rt_to_str(RT_ATTR), pt_to_str(PT_NAME), name);
60890Sstevel@tonic-gate 			return (Z_INVAL);
60900Sstevel@tonic-gate 		}
60910Sstevel@tonic-gate 	return (Z_OK);
60920Sstevel@tonic-gate }
60930Sstevel@tonic-gate 
60940Sstevel@tonic-gate static int
validate_attr_type_val(struct zone_attrtab * attrtab)60950Sstevel@tonic-gate validate_attr_type_val(struct zone_attrtab *attrtab)
60960Sstevel@tonic-gate {
60970Sstevel@tonic-gate 	boolean_t boolval;
60980Sstevel@tonic-gate 	int64_t intval;
60990Sstevel@tonic-gate 	char strval[MAXNAMELEN];
61000Sstevel@tonic-gate 	uint64_t uintval;
61010Sstevel@tonic-gate 
61020Sstevel@tonic-gate 	if (strcmp(attrtab->zone_attr_type, "boolean") == 0) {
61030Sstevel@tonic-gate 		if (zonecfg_get_attr_boolean(attrtab, &boolval) == Z_OK)
61040Sstevel@tonic-gate 			return (Z_OK);
61050Sstevel@tonic-gate 		zerr(gettext("invalid %s value for %s=%s"),
61060Sstevel@tonic-gate 		    rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "boolean");
61070Sstevel@tonic-gate 		return (Z_ERR);
61080Sstevel@tonic-gate 	}
61090Sstevel@tonic-gate 
61100Sstevel@tonic-gate 	if (strcmp(attrtab->zone_attr_type, "int") == 0) {
61110Sstevel@tonic-gate 		if (zonecfg_get_attr_int(attrtab, &intval) == Z_OK)
61120Sstevel@tonic-gate 			return (Z_OK);
61130Sstevel@tonic-gate 		zerr(gettext("invalid %s value for %s=%s"),
61140Sstevel@tonic-gate 		    rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "int");
61150Sstevel@tonic-gate 		return (Z_ERR);
61160Sstevel@tonic-gate 	}
61170Sstevel@tonic-gate 
61180Sstevel@tonic-gate 	if (strcmp(attrtab->zone_attr_type, "string") == 0) {
61190Sstevel@tonic-gate 		if (zonecfg_get_attr_string(attrtab, strval,
61200Sstevel@tonic-gate 		    sizeof (strval)) == Z_OK)
61210Sstevel@tonic-gate 			return (Z_OK);
61220Sstevel@tonic-gate 		zerr(gettext("invalid %s value for %s=%s"),
61230Sstevel@tonic-gate 		    rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "string");
61240Sstevel@tonic-gate 		return (Z_ERR);
61250Sstevel@tonic-gate 	}
61260Sstevel@tonic-gate 
61270Sstevel@tonic-gate 	if (strcmp(attrtab->zone_attr_type, "uint") == 0) {
61280Sstevel@tonic-gate 		if (zonecfg_get_attr_uint(attrtab, &uintval) == Z_OK)
61290Sstevel@tonic-gate 			return (Z_OK);
61300Sstevel@tonic-gate 		zerr(gettext("invalid %s value for %s=%s"),
61310Sstevel@tonic-gate 		    rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "uint");
61320Sstevel@tonic-gate 		return (Z_ERR);
61330Sstevel@tonic-gate 	}
61340Sstevel@tonic-gate 
61350Sstevel@tonic-gate 	zerr(gettext("invalid %s %s '%s'"), rt_to_str(RT_ATTR),
61360Sstevel@tonic-gate 	    pt_to_str(PT_TYPE), attrtab->zone_attr_type);
61370Sstevel@tonic-gate 	return (Z_ERR);
61380Sstevel@tonic-gate }
61390Sstevel@tonic-gate 
6140565Sdp /*
6141565Sdp  * Helper function for end_func-- checks the existence of a given property
6142565Sdp  * and emits a message if not specified.
6143565Sdp  */
6144565Sdp static int
end_check_reqd(char * attr,int pt,boolean_t * validation_failed)61456215Sgjelinek end_check_reqd(char *attr, int pt, boolean_t *validation_failed)
6146565Sdp {
6147565Sdp 	if (strlen(attr) == 0) {
61486215Sgjelinek 		*validation_failed = B_TRUE;
6149565Sdp 		zerr(gettext("%s not specified"), pt_to_str(pt));
6150565Sdp 		return (Z_ERR);
6151565Sdp 	}
6152565Sdp 	return (Z_OK);
6153565Sdp }
6154565Sdp 
615512748SSowmini.Varadhan@oracle.COM static void
net_exists_error(struct zone_nwiftab nwif)615612748SSowmini.Varadhan@oracle.COM net_exists_error(struct zone_nwiftab nwif)
615712748SSowmini.Varadhan@oracle.COM {
615812748SSowmini.Varadhan@oracle.COM 	if (strlen(nwif.zone_nwif_address) > 0) {
615912748SSowmini.Varadhan@oracle.COM 		zerr(gettext("A %s resource with the %s '%s', "
616012748SSowmini.Varadhan@oracle.COM 		    "and %s '%s' already exists."),
616112748SSowmini.Varadhan@oracle.COM 		    rt_to_str(RT_NET),
616212748SSowmini.Varadhan@oracle.COM 		    pt_to_str(PT_PHYSICAL),
616312748SSowmini.Varadhan@oracle.COM 		    nwif.zone_nwif_physical,
616412748SSowmini.Varadhan@oracle.COM 		    pt_to_str(PT_ADDRESS),
616512748SSowmini.Varadhan@oracle.COM 		    in_progress_nwiftab.zone_nwif_address);
616612748SSowmini.Varadhan@oracle.COM 	} else {
616712748SSowmini.Varadhan@oracle.COM 		zerr(gettext("A %s resource with the %s '%s', "
616812748SSowmini.Varadhan@oracle.COM 		    "and %s '%s' already exists."),
616912748SSowmini.Varadhan@oracle.COM 		    rt_to_str(RT_NET),
617012748SSowmini.Varadhan@oracle.COM 		    pt_to_str(PT_PHYSICAL),
617112748SSowmini.Varadhan@oracle.COM 		    nwif.zone_nwif_physical,
617212748SSowmini.Varadhan@oracle.COM 		    pt_to_str(PT_ALLOWED_ADDRESS),
617312748SSowmini.Varadhan@oracle.COM 		    nwif.zone_nwif_allowed_address);
617412748SSowmini.Varadhan@oracle.COM 	}
617512748SSowmini.Varadhan@oracle.COM }
617612748SSowmini.Varadhan@oracle.COM 
61770Sstevel@tonic-gate void
end_func(cmd_t * cmd)61780Sstevel@tonic-gate end_func(cmd_t *cmd)
61790Sstevel@tonic-gate {
61806215Sgjelinek 	boolean_t validation_failed = B_FALSE;
61816215Sgjelinek 	boolean_t arg_err = B_FALSE;
61820Sstevel@tonic-gate 	struct zone_fstab tmp_fstab;
61830Sstevel@tonic-gate 	struct zone_nwiftab tmp_nwiftab;
61840Sstevel@tonic-gate 	struct zone_devtab tmp_devtab;
61850Sstevel@tonic-gate 	struct zone_rctltab tmp_rctltab;
61860Sstevel@tonic-gate 	struct zone_attrtab tmp_attrtab;
6187789Sahrens 	struct zone_dstab tmp_dstab;
618812578SGlenn.Faden@Sun.COM 	struct zone_admintab tmp_admintab;
61893247Sgjelinek 	int err, arg, res1, res2, res3;
61903247Sgjelinek 	uint64_t swap_limit;
61913247Sgjelinek 	uint64_t locked_limit;
61923792Sakolb 	uint64_t proc_cap;
61930Sstevel@tonic-gate 
61940Sstevel@tonic-gate 	assert(cmd != NULL);
61950Sstevel@tonic-gate 
61960Sstevel@tonic-gate 	optind = 0;
61973691Sgjelinek 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
61980Sstevel@tonic-gate 		switch (arg) {
61990Sstevel@tonic-gate 		case '?':
62000Sstevel@tonic-gate 			longer_usage(CMD_END);
62016215Sgjelinek 			arg_err = B_TRUE;
62023691Sgjelinek 			break;
62030Sstevel@tonic-gate 		default:
62040Sstevel@tonic-gate 			short_usage(CMD_END);
62056215Sgjelinek 			arg_err = B_TRUE;
62063691Sgjelinek 			break;
62073691Sgjelinek 		}
62083691Sgjelinek 	}
62093691Sgjelinek 	if (arg_err)
62103691Sgjelinek 		return;
62113691Sgjelinek 
62120Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
62130Sstevel@tonic-gate 		short_usage(CMD_END);
62140Sstevel@tonic-gate 		return;
62150Sstevel@tonic-gate 	}
62160Sstevel@tonic-gate 
62170Sstevel@tonic-gate 	if (global_scope) {
62180Sstevel@tonic-gate 		scope_usage(CMD_END);
62190Sstevel@tonic-gate 		return;
62200Sstevel@tonic-gate 	}
62210Sstevel@tonic-gate 
62220Sstevel@tonic-gate 	assert(end_op == CMD_ADD || end_op == CMD_SELECT);
62230Sstevel@tonic-gate 
62240Sstevel@tonic-gate 	switch (resource_scope) {
62250Sstevel@tonic-gate 	case RT_FS:
62260Sstevel@tonic-gate 		/* First make sure everything was filled in. */
6227565Sdp 		if (end_check_reqd(in_progress_fstab.zone_fs_dir,
6228565Sdp 		    PT_DIR, &validation_failed) == Z_OK) {
6229565Sdp 			if (in_progress_fstab.zone_fs_dir[0] != '/') {
6230565Sdp 				zerr(gettext("%s %s is not an absolute path."),
6231565Sdp 				    pt_to_str(PT_DIR),
6232565Sdp 				    in_progress_fstab.zone_fs_dir);
62336215Sgjelinek 				validation_failed = B_TRUE;
6234565Sdp 			}
62350Sstevel@tonic-gate 		}
6236565Sdp 
6237565Sdp 		(void) end_check_reqd(in_progress_fstab.zone_fs_special,
6238565Sdp 		    PT_SPECIAL, &validation_failed);
6239565Sdp 
6240565Sdp 		if (in_progress_fstab.zone_fs_raw[0] != '\0' &&
6241565Sdp 		    in_progress_fstab.zone_fs_raw[0] != '/') {
6242565Sdp 			zerr(gettext("%s %s is not an absolute path."),
6243565Sdp 			    pt_to_str(PT_RAW),
6244565Sdp 			    in_progress_fstab.zone_fs_raw);
62456215Sgjelinek 			validation_failed = B_TRUE;
62460Sstevel@tonic-gate 		}
6247565Sdp 
6248565Sdp 		(void) end_check_reqd(in_progress_fstab.zone_fs_type, PT_TYPE,
6249565Sdp 		    &validation_failed);
6250565Sdp 
6251565Sdp 		if (validation_failed) {
62526215Sgjelinek 			saw_error = B_TRUE;
6253565Sdp 			return;
62540Sstevel@tonic-gate 		}
6255565Sdp 
62560Sstevel@tonic-gate 		if (end_op == CMD_ADD) {
62570Sstevel@tonic-gate 			/* Make sure there isn't already one like this. */
62580Sstevel@tonic-gate 			bzero(&tmp_fstab, sizeof (tmp_fstab));
62590Sstevel@tonic-gate 			(void) strlcpy(tmp_fstab.zone_fs_dir,
62600Sstevel@tonic-gate 			    in_progress_fstab.zone_fs_dir,
62610Sstevel@tonic-gate 			    sizeof (tmp_fstab.zone_fs_dir));
62620Sstevel@tonic-gate 			err = zonecfg_lookup_filesystem(handle, &tmp_fstab);
62630Sstevel@tonic-gate 			zonecfg_free_fs_option_list(tmp_fstab.zone_fs_options);
62640Sstevel@tonic-gate 			if (err == Z_OK) {
62650Sstevel@tonic-gate 				zerr(gettext("A %s resource "
62660Sstevel@tonic-gate 				    "with the %s '%s' already exists."),
62670Sstevel@tonic-gate 				    rt_to_str(RT_FS), pt_to_str(PT_DIR),
62680Sstevel@tonic-gate 				    in_progress_fstab.zone_fs_dir);
62696215Sgjelinek 				saw_error = B_TRUE;
62700Sstevel@tonic-gate 				return;
62710Sstevel@tonic-gate 			}
62720Sstevel@tonic-gate 			err = zonecfg_add_filesystem(handle,
62730Sstevel@tonic-gate 			    &in_progress_fstab);
62740Sstevel@tonic-gate 		} else {
62750Sstevel@tonic-gate 			err = zonecfg_modify_filesystem(handle, &old_fstab,
62760Sstevel@tonic-gate 			    &in_progress_fstab);
62770Sstevel@tonic-gate 		}
62780Sstevel@tonic-gate 		zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
62790Sstevel@tonic-gate 		in_progress_fstab.zone_fs_options = NULL;
62800Sstevel@tonic-gate 		break;
6281565Sdp 
62820Sstevel@tonic-gate 	case RT_NET:
62833448Sdh155122 		/*
62843448Sdh155122 		 * First make sure everything was filled in.
62853448Sdh155122 		 * Since we don't know whether IP will be shared
62863448Sdh155122 		 * or exclusive here, some checks are deferred until
62873448Sdh155122 		 * the verify command.
62883448Sdh155122 		 */
6289565Sdp 		(void) end_check_reqd(in_progress_nwiftab.zone_nwif_physical,
6290565Sdp 		    PT_PHYSICAL, &validation_failed);
6291565Sdp 
6292565Sdp 		if (validation_failed) {
62936215Sgjelinek 			saw_error = B_TRUE;
6294565Sdp 			return;
62950Sstevel@tonic-gate 		}
62960Sstevel@tonic-gate 		if (end_op == CMD_ADD) {
62970Sstevel@tonic-gate 			/* Make sure there isn't already one like this. */
62980Sstevel@tonic-gate 			bzero(&tmp_nwiftab, sizeof (tmp_nwiftab));
62993448Sdh155122 			(void) strlcpy(tmp_nwiftab.zone_nwif_physical,
63003448Sdh155122 			    in_progress_nwiftab.zone_nwif_physical,
63013448Sdh155122 			    sizeof (tmp_nwiftab.zone_nwif_physical));
63020Sstevel@tonic-gate 			(void) strlcpy(tmp_nwiftab.zone_nwif_address,
63030Sstevel@tonic-gate 			    in_progress_nwiftab.zone_nwif_address,
63040Sstevel@tonic-gate 			    sizeof (tmp_nwiftab.zone_nwif_address));
630512748SSowmini.Varadhan@oracle.COM 			(void) strlcpy(tmp_nwiftab.zone_nwif_allowed_address,
630612748SSowmini.Varadhan@oracle.COM 			    in_progress_nwiftab.zone_nwif_allowed_address,
630712748SSowmini.Varadhan@oracle.COM 			    sizeof (tmp_nwiftab.zone_nwif_allowed_address));
630812748SSowmini.Varadhan@oracle.COM 			(void) strlcpy(tmp_nwiftab.zone_nwif_defrouter,
630912748SSowmini.Varadhan@oracle.COM 			    in_progress_nwiftab.zone_nwif_defrouter,
631012748SSowmini.Varadhan@oracle.COM 			    sizeof (tmp_nwiftab.zone_nwif_defrouter));
63110Sstevel@tonic-gate 			if (zonecfg_lookup_nwif(handle, &tmp_nwiftab) == Z_OK) {
631212748SSowmini.Varadhan@oracle.COM 				net_exists_error(in_progress_nwiftab);
63136215Sgjelinek 				saw_error = B_TRUE;
63140Sstevel@tonic-gate 				return;
63150Sstevel@tonic-gate 			}
63160Sstevel@tonic-gate 			err = zonecfg_add_nwif(handle, &in_progress_nwiftab);
63170Sstevel@tonic-gate 		} else {
63180Sstevel@tonic-gate 			err = zonecfg_modify_nwif(handle, &old_nwiftab,
63190Sstevel@tonic-gate 			    &in_progress_nwiftab);
63200Sstevel@tonic-gate 		}
63210Sstevel@tonic-gate 		break;
6322565Sdp 
63230Sstevel@tonic-gate 	case RT_DEVICE:
63240Sstevel@tonic-gate 		/* First make sure everything was filled in. */
6325565Sdp 		(void) end_check_reqd(in_progress_devtab.zone_dev_match,
6326565Sdp 		    PT_MATCH, &validation_failed);
6327565Sdp 
6328565Sdp 		if (validation_failed) {
63296215Sgjelinek 			saw_error = B_TRUE;
6330565Sdp 			return;
63310Sstevel@tonic-gate 		}
6332565Sdp 
63330Sstevel@tonic-gate 		if (end_op == CMD_ADD) {
63340Sstevel@tonic-gate 			/* Make sure there isn't already one like this. */
63350Sstevel@tonic-gate 			(void) strlcpy(tmp_devtab.zone_dev_match,
63360Sstevel@tonic-gate 			    in_progress_devtab.zone_dev_match,
63370Sstevel@tonic-gate 			    sizeof (tmp_devtab.zone_dev_match));
63380Sstevel@tonic-gate 			if (zonecfg_lookup_dev(handle, &tmp_devtab) == Z_OK) {
63390Sstevel@tonic-gate 				zerr(gettext("A %s resource with the %s '%s' "
63400Sstevel@tonic-gate 				    "already exists."), rt_to_str(RT_DEVICE),
63410Sstevel@tonic-gate 				    pt_to_str(PT_MATCH),
63420Sstevel@tonic-gate 				    in_progress_devtab.zone_dev_match);
63436215Sgjelinek 				saw_error = B_TRUE;
63440Sstevel@tonic-gate 				return;
63450Sstevel@tonic-gate 			}
63460Sstevel@tonic-gate 			err = zonecfg_add_dev(handle, &in_progress_devtab);
63470Sstevel@tonic-gate 		} else {
63480Sstevel@tonic-gate 			err = zonecfg_modify_dev(handle, &old_devtab,
63490Sstevel@tonic-gate 			    &in_progress_devtab);
63500Sstevel@tonic-gate 		}
63510Sstevel@tonic-gate 		break;
6352565Sdp 
63530Sstevel@tonic-gate 	case RT_RCTL:
63540Sstevel@tonic-gate 		/* First make sure everything was filled in. */
6355565Sdp 		(void) end_check_reqd(in_progress_rctltab.zone_rctl_name,
6356565Sdp 		    PT_NAME, &validation_failed);
6357565Sdp 
6358565Sdp 		if (in_progress_rctltab.zone_rctl_valptr == NULL) {
6359565Sdp 			zerr(gettext("no %s specified"), pt_to_str(PT_VALUE));
63606215Sgjelinek 			validation_failed = B_TRUE;
63610Sstevel@tonic-gate 		}
6362565Sdp 
6363565Sdp 		if (validation_failed) {
63646215Sgjelinek 			saw_error = B_TRUE;
6365565Sdp 			return;
63660Sstevel@tonic-gate 		}
6367565Sdp 
63680Sstevel@tonic-gate 		if (end_op == CMD_ADD) {
63690Sstevel@tonic-gate 			/* Make sure there isn't already one like this. */
63700Sstevel@tonic-gate 			(void) strlcpy(tmp_rctltab.zone_rctl_name,
63710Sstevel@tonic-gate 			    in_progress_rctltab.zone_rctl_name,
63720Sstevel@tonic-gate 			    sizeof (tmp_rctltab.zone_rctl_name));
63730Sstevel@tonic-gate 			tmp_rctltab.zone_rctl_valptr = NULL;
63740Sstevel@tonic-gate 			err = zonecfg_lookup_rctl(handle, &tmp_rctltab);
63750Sstevel@tonic-gate 			zonecfg_free_rctl_value_list(
63760Sstevel@tonic-gate 			    tmp_rctltab.zone_rctl_valptr);
63770Sstevel@tonic-gate 			if (err == Z_OK) {
63780Sstevel@tonic-gate 				zerr(gettext("A %s resource "
63790Sstevel@tonic-gate 				    "with the %s '%s' already exists."),
63800Sstevel@tonic-gate 				    rt_to_str(RT_RCTL), pt_to_str(PT_NAME),
63810Sstevel@tonic-gate 				    in_progress_rctltab.zone_rctl_name);
63826215Sgjelinek 				saw_error = B_TRUE;
63830Sstevel@tonic-gate 				return;
63840Sstevel@tonic-gate 			}
63850Sstevel@tonic-gate 			err = zonecfg_add_rctl(handle, &in_progress_rctltab);
63860Sstevel@tonic-gate 		} else {
63870Sstevel@tonic-gate 			err = zonecfg_modify_rctl(handle, &old_rctltab,
63880Sstevel@tonic-gate 			    &in_progress_rctltab);
63890Sstevel@tonic-gate 		}
63900Sstevel@tonic-gate 		if (err == Z_OK) {
63910Sstevel@tonic-gate 			zonecfg_free_rctl_value_list(
63920Sstevel@tonic-gate 			    in_progress_rctltab.zone_rctl_valptr);
63930Sstevel@tonic-gate 			in_progress_rctltab.zone_rctl_valptr = NULL;
63940Sstevel@tonic-gate 		}
63950Sstevel@tonic-gate 		break;
6396565Sdp 
63970Sstevel@tonic-gate 	case RT_ATTR:
63980Sstevel@tonic-gate 		/* First make sure everything was filled in. */
6399565Sdp 		(void) end_check_reqd(in_progress_attrtab.zone_attr_name,
6400565Sdp 		    PT_NAME, &validation_failed);
6401565Sdp 		(void) end_check_reqd(in_progress_attrtab.zone_attr_type,
6402565Sdp 		    PT_TYPE, &validation_failed);
6403565Sdp 		(void) end_check_reqd(in_progress_attrtab.zone_attr_value,
6404565Sdp 		    PT_VALUE, &validation_failed);
6405565Sdp 
6406565Sdp 		if (validate_attr_name(in_progress_attrtab.zone_attr_name) !=
6407565Sdp 		    Z_OK)
64086215Sgjelinek 			validation_failed = B_TRUE;
6409565Sdp 
6410565Sdp 		if (validate_attr_type_val(&in_progress_attrtab) != Z_OK)
64116215Sgjelinek 			validation_failed = B_TRUE;
6412565Sdp 
6413565Sdp 		if (validation_failed) {
64146215Sgjelinek 			saw_error = B_TRUE;
6415565Sdp 			return;
64160Sstevel@tonic-gate 		}
64170Sstevel@tonic-gate 		if (end_op == CMD_ADD) {
64180Sstevel@tonic-gate 			/* Make sure there isn't already one like this. */
64190Sstevel@tonic-gate 			bzero(&tmp_attrtab, sizeof (tmp_attrtab));
64200Sstevel@tonic-gate 			(void) strlcpy(tmp_attrtab.zone_attr_name,
64210Sstevel@tonic-gate 			    in_progress_attrtab.zone_attr_name,
64220Sstevel@tonic-gate 			    sizeof (tmp_attrtab.zone_attr_name));
64230Sstevel@tonic-gate 			if (zonecfg_lookup_attr(handle, &tmp_attrtab) == Z_OK) {
64240Sstevel@tonic-gate 				zerr(gettext("An %s resource "
64250Sstevel@tonic-gate 				    "with the %s '%s' already exists."),
64260Sstevel@tonic-gate 				    rt_to_str(RT_ATTR), pt_to_str(PT_NAME),
64270Sstevel@tonic-gate 				    in_progress_attrtab.zone_attr_name);
64286215Sgjelinek 				saw_error = B_TRUE;
64290Sstevel@tonic-gate 				return;
64300Sstevel@tonic-gate 			}
64310Sstevel@tonic-gate 			err = zonecfg_add_attr(handle, &in_progress_attrtab);
64320Sstevel@tonic-gate 		} else {
64330Sstevel@tonic-gate 			err = zonecfg_modify_attr(handle, &old_attrtab,
64340Sstevel@tonic-gate 			    &in_progress_attrtab);
64350Sstevel@tonic-gate 		}
64360Sstevel@tonic-gate 		break;
6437789Sahrens 	case RT_DATASET:
6438789Sahrens 		/* First make sure everything was filled in. */
6439789Sahrens 		if (strlen(in_progress_dstab.zone_dataset_name) == 0) {
6440789Sahrens 			zerr("%s %s", pt_to_str(PT_NAME),
6441789Sahrens 			    gettext("not specified"));
64426215Sgjelinek 			saw_error = B_TRUE;
64436215Sgjelinek 			validation_failed = B_TRUE;
6444789Sahrens 		}
6445789Sahrens 		if (validation_failed)
6446789Sahrens 			return;
6447789Sahrens 		if (end_op == CMD_ADD) {
6448789Sahrens 			/* Make sure there isn't already one like this. */
6449789Sahrens 			bzero(&tmp_dstab, sizeof (tmp_dstab));
6450789Sahrens 			(void) strlcpy(tmp_dstab.zone_dataset_name,
6451789Sahrens 			    in_progress_dstab.zone_dataset_name,
6452789Sahrens 			    sizeof (tmp_dstab.zone_dataset_name));
6453789Sahrens 			err = zonecfg_lookup_ds(handle, &tmp_dstab);
6454789Sahrens 			if (err == Z_OK) {
6455789Sahrens 				zerr(gettext("A %s resource "
6456789Sahrens 				    "with the %s '%s' already exists."),
6457789Sahrens 				    rt_to_str(RT_DATASET), pt_to_str(PT_NAME),
6458789Sahrens 				    in_progress_dstab.zone_dataset_name);
64596215Sgjelinek 				saw_error = B_TRUE;
6460789Sahrens 				return;
6461789Sahrens 			}
6462789Sahrens 			err = zonecfg_add_ds(handle, &in_progress_dstab);
6463789Sahrens 		} else {
6464789Sahrens 			err = zonecfg_modify_ds(handle, &old_dstab,
6465789Sahrens 			    &in_progress_dstab);
6466789Sahrens 		}
6467789Sahrens 		break;
64683247Sgjelinek 	case RT_DCPU:
64693247Sgjelinek 		/* Make sure everything was filled in. */
64703247Sgjelinek 		if (end_check_reqd(in_progress_psettab.zone_ncpu_min,
64713247Sgjelinek 		    PT_NCPUS, &validation_failed) != Z_OK) {
64726215Sgjelinek 			saw_error = B_TRUE;
64733247Sgjelinek 			return;
64743247Sgjelinek 		}
64753247Sgjelinek 
64763247Sgjelinek 		if (end_op == CMD_ADD) {
64773247Sgjelinek 			err = zonecfg_add_pset(handle, &in_progress_psettab);
64783247Sgjelinek 		} else {
64793247Sgjelinek 			err = zonecfg_modify_pset(handle, &in_progress_psettab);
64803247Sgjelinek 		}
64813247Sgjelinek 		break;
64823792Sakolb 	case RT_PCAP:
64833792Sakolb 		/* Make sure everything was filled in. */
64843792Sakolb 		if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &proc_cap)
64853792Sakolb 		    != Z_OK) {
64863792Sakolb 			zerr(gettext("%s not specified"), pt_to_str(PT_NCPUS));
64876215Sgjelinek 			saw_error = B_TRUE;
64886215Sgjelinek 			validation_failed = B_TRUE;
64893792Sakolb 			return;
64903792Sakolb 		}
64913792Sakolb 		err = Z_OK;
64923792Sakolb 		break;
64933247Sgjelinek 	case RT_MCAP:
64943247Sgjelinek 		/* Make sure everything was filled in. */
64953247Sgjelinek 		res1 = strlen(in_progress_mcaptab.zone_physmem_cap) == 0 ?
64963247Sgjelinek 		    Z_ERR : Z_OK;
64973247Sgjelinek 		res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
64983247Sgjelinek 		    &swap_limit);
64993247Sgjelinek 		res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
65003247Sgjelinek 		    &locked_limit);
65013247Sgjelinek 
65023247Sgjelinek 		if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
65033247Sgjelinek 			zerr(gettext("No property was specified.  One of %s, "
65043247Sgjelinek 			    "%s or %s is required."), pt_to_str(PT_PHYSICAL),
65053247Sgjelinek 			    pt_to_str(PT_SWAP), pt_to_str(PT_LOCKED));
65066215Sgjelinek 			saw_error = B_TRUE;
65073247Sgjelinek 			return;
65083247Sgjelinek 		}
65093247Sgjelinek 
65103247Sgjelinek 		/* if phys & locked are both set, verify locked <= phys */
65113247Sgjelinek 		if (res1 == Z_OK && res3 == Z_OK) {
65123247Sgjelinek 			uint64_t phys_limit;
65133247Sgjelinek 			char *endp;
65143247Sgjelinek 
65153247Sgjelinek 			phys_limit = strtoull(
65163247Sgjelinek 			    in_progress_mcaptab.zone_physmem_cap, &endp, 10);
65173247Sgjelinek 			if (phys_limit < locked_limit) {
65183247Sgjelinek 				zerr(gettext("The %s cap must be less than or "
65193247Sgjelinek 				    "equal to the %s cap."),
65203247Sgjelinek 				    pt_to_str(PT_LOCKED),
65213247Sgjelinek 				    pt_to_str(PT_PHYSICAL));
65226215Sgjelinek 				saw_error = B_TRUE;
65233247Sgjelinek 				return;
65243247Sgjelinek 			}
65253247Sgjelinek 		}
65263247Sgjelinek 
65273247Sgjelinek 		err = Z_OK;
65283247Sgjelinek 		if (res1 == Z_OK) {
65293247Sgjelinek 			/*
65303247Sgjelinek 			 * We could be ending from either an add operation
65313247Sgjelinek 			 * or a select operation.  Since all of the properties
65323247Sgjelinek 			 * within this resource are optional, we always use
65333247Sgjelinek 			 * modify on the mcap entry.  zonecfg_modify_mcap()
65343247Sgjelinek 			 * will handle both adding and modifying a memory cap.
65353247Sgjelinek 			 */
65363247Sgjelinek 			err = zonecfg_modify_mcap(handle, &in_progress_mcaptab);
65373247Sgjelinek 		} else if (end_op == CMD_SELECT) {
65383247Sgjelinek 			/*
65393247Sgjelinek 			 * If we're ending from a select and the physical
65403247Sgjelinek 			 * memory cap is empty then the user could have cleared
65413247Sgjelinek 			 * the physical cap value, so try to delete the entry.
65423247Sgjelinek 			 */
65433247Sgjelinek 			(void) zonecfg_delete_mcap(handle);
65443247Sgjelinek 		}
65453247Sgjelinek 		break;
654612578SGlenn.Faden@Sun.COM 	case RT_ADMIN:
654712578SGlenn.Faden@Sun.COM 		/* First make sure everything was filled in. */
654812578SGlenn.Faden@Sun.COM 		if (end_check_reqd(in_progress_admintab.zone_admin_user,
654912578SGlenn.Faden@Sun.COM 		    PT_USER, &validation_failed) == Z_OK) {
655012578SGlenn.Faden@Sun.COM 			if (getpwnam(in_progress_admintab.zone_admin_user)
655112578SGlenn.Faden@Sun.COM 			    == NULL) {
655212578SGlenn.Faden@Sun.COM 				zerr(gettext("%s %s is not a valid username"),
655312578SGlenn.Faden@Sun.COM 				    pt_to_str(PT_USER),
655412578SGlenn.Faden@Sun.COM 				    in_progress_admintab.zone_admin_user);
655512578SGlenn.Faden@Sun.COM 				validation_failed = B_TRUE;
655612578SGlenn.Faden@Sun.COM 			}
655712578SGlenn.Faden@Sun.COM 		}
655812578SGlenn.Faden@Sun.COM 
655912578SGlenn.Faden@Sun.COM 		if (end_check_reqd(in_progress_admintab.zone_admin_auths,
656012578SGlenn.Faden@Sun.COM 		    PT_AUTHS, &validation_failed) == Z_OK) {
656112578SGlenn.Faden@Sun.COM 			if (!zonecfg_valid_auths(
656212578SGlenn.Faden@Sun.COM 			    in_progress_admintab.zone_admin_auths,
656312578SGlenn.Faden@Sun.COM 			    zone)) {
656412578SGlenn.Faden@Sun.COM 				validation_failed = B_TRUE;
656512578SGlenn.Faden@Sun.COM 			}
656612578SGlenn.Faden@Sun.COM 		}
656712578SGlenn.Faden@Sun.COM 
656812578SGlenn.Faden@Sun.COM 		if (validation_failed) {
656912578SGlenn.Faden@Sun.COM 			saw_error = B_TRUE;
657012578SGlenn.Faden@Sun.COM 			return;
657112578SGlenn.Faden@Sun.COM 		}
657212578SGlenn.Faden@Sun.COM 
657312578SGlenn.Faden@Sun.COM 		if (end_op == CMD_ADD) {
657412578SGlenn.Faden@Sun.COM 			/* Make sure there isn't already one like this. */
657512578SGlenn.Faden@Sun.COM 			bzero(&tmp_admintab, sizeof (tmp_admintab));
657612578SGlenn.Faden@Sun.COM 			(void) strlcpy(tmp_admintab.zone_admin_user,
657712578SGlenn.Faden@Sun.COM 			    in_progress_admintab.zone_admin_user,
657812578SGlenn.Faden@Sun.COM 			    sizeof (tmp_admintab.zone_admin_user));
657912578SGlenn.Faden@Sun.COM 			err = zonecfg_lookup_admin(
658012578SGlenn.Faden@Sun.COM 			    handle, &tmp_admintab);
658112578SGlenn.Faden@Sun.COM 			if (err == Z_OK) {
658212578SGlenn.Faden@Sun.COM 				zerr(gettext("A %s resource "
658312578SGlenn.Faden@Sun.COM 				    "with the %s '%s' already exists."),
658412578SGlenn.Faden@Sun.COM 				    rt_to_str(RT_ADMIN),
658512578SGlenn.Faden@Sun.COM 				    pt_to_str(PT_USER),
658612578SGlenn.Faden@Sun.COM 				    in_progress_admintab.zone_admin_user);
658712578SGlenn.Faden@Sun.COM 				saw_error = B_TRUE;
658812578SGlenn.Faden@Sun.COM 				return;
658912578SGlenn.Faden@Sun.COM 			}
659012578SGlenn.Faden@Sun.COM 			err = zonecfg_add_admin(handle,
659112578SGlenn.Faden@Sun.COM 			    &in_progress_admintab, zone);
659212578SGlenn.Faden@Sun.COM 		} else {
659312578SGlenn.Faden@Sun.COM 			err = zonecfg_modify_admin(handle,
659412578SGlenn.Faden@Sun.COM 			    &old_admintab, &in_progress_admintab,
659512578SGlenn.Faden@Sun.COM 			    zone);
659612578SGlenn.Faden@Sun.COM 		}
659712578SGlenn.Faden@Sun.COM 		break;
65980Sstevel@tonic-gate 	default:
65990Sstevel@tonic-gate 		zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
66006215Sgjelinek 		    B_TRUE);
66016215Sgjelinek 		saw_error = B_TRUE;
66020Sstevel@tonic-gate 		return;
66030Sstevel@tonic-gate 	}
66040Sstevel@tonic-gate 
66050Sstevel@tonic-gate 	if (err != Z_OK) {
66066215Sgjelinek 		zone_perror(zone, err, B_TRUE);
66070Sstevel@tonic-gate 	} else {
66086215Sgjelinek 		need_to_commit = B_TRUE;
66096215Sgjelinek 		global_scope = B_TRUE;
66100Sstevel@tonic-gate 		end_op = -1;
66110Sstevel@tonic-gate 	}
66120Sstevel@tonic-gate }
66130Sstevel@tonic-gate 
66140Sstevel@tonic-gate void
commit_func(cmd_t * cmd)66150Sstevel@tonic-gate commit_func(cmd_t *cmd)
66160Sstevel@tonic-gate {
66170Sstevel@tonic-gate 	int arg;
66186215Sgjelinek 	boolean_t arg_err = B_FALSE;
66190Sstevel@tonic-gate 
66200Sstevel@tonic-gate 	optind = 0;
66213691Sgjelinek 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
66220Sstevel@tonic-gate 		switch (arg) {
66230Sstevel@tonic-gate 		case '?':
66240Sstevel@tonic-gate 			longer_usage(CMD_COMMIT);
66256215Sgjelinek 			arg_err = B_TRUE;
66263691Sgjelinek 			break;
66270Sstevel@tonic-gate 		default:
66280Sstevel@tonic-gate 			short_usage(CMD_COMMIT);
66296215Sgjelinek 			arg_err = B_TRUE;
66303691Sgjelinek 			break;
66313691Sgjelinek 		}
66323691Sgjelinek 	}
66333691Sgjelinek 	if (arg_err)
66343691Sgjelinek 		return;
66353691Sgjelinek 
66360Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
66370Sstevel@tonic-gate 		short_usage(CMD_COMMIT);
66380Sstevel@tonic-gate 		return;
66390Sstevel@tonic-gate 	}
66400Sstevel@tonic-gate 
66410Sstevel@tonic-gate 	if (zone_is_read_only(CMD_COMMIT))
66420Sstevel@tonic-gate 		return;
66430Sstevel@tonic-gate 
66440Sstevel@tonic-gate 	assert(cmd != NULL);
66450Sstevel@tonic-gate 
66460Sstevel@tonic-gate 	cmd->cmd_argc = 1;
66470Sstevel@tonic-gate 	/*
66480Sstevel@tonic-gate 	 * cmd_arg normally comes from a strdup() in the lexer, and the
66490Sstevel@tonic-gate 	 * whole cmd structure and its (char *) attributes are freed at
66500Sstevel@tonic-gate 	 * the completion of each command, so the strdup() below is needed
66510Sstevel@tonic-gate 	 * to match this and prevent a core dump from trying to free()
66520Sstevel@tonic-gate 	 * something that can't be.
66530Sstevel@tonic-gate 	 */
66540Sstevel@tonic-gate 	if ((cmd->cmd_argv[0] = strdup("save")) == NULL) {
66556215Sgjelinek 		zone_perror(zone, Z_NOMEM, B_TRUE);
66560Sstevel@tonic-gate 		exit(Z_ERR);
66570Sstevel@tonic-gate 	}
66580Sstevel@tonic-gate 	cmd->cmd_argv[1] = NULL;
66590Sstevel@tonic-gate 	verify_func(cmd);
66600Sstevel@tonic-gate }
66610Sstevel@tonic-gate 
66620Sstevel@tonic-gate void
revert_func(cmd_t * cmd)66630Sstevel@tonic-gate revert_func(cmd_t *cmd)
66640Sstevel@tonic-gate {
66650Sstevel@tonic-gate 	char line[128];	/* enough to ask a question */
66666215Sgjelinek 	boolean_t force = B_FALSE;
66676215Sgjelinek 	boolean_t arg_err = B_FALSE;
66680Sstevel@tonic-gate 	int err, arg, answer;
66690Sstevel@tonic-gate 
66700Sstevel@tonic-gate 	optind = 0;
66710Sstevel@tonic-gate 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
66720Sstevel@tonic-gate 		switch (arg) {
66730Sstevel@tonic-gate 		case '?':
66740Sstevel@tonic-gate 			longer_usage(CMD_REVERT);
66756215Sgjelinek 			arg_err = B_TRUE;
66763691Sgjelinek 			break;
66770Sstevel@tonic-gate 		case 'F':
66786215Sgjelinek 			force = B_TRUE;
66790Sstevel@tonic-gate 			break;
66800Sstevel@tonic-gate 		default:
66810Sstevel@tonic-gate 			short_usage(CMD_REVERT);
66826215Sgjelinek 			arg_err = B_TRUE;
66833691Sgjelinek 			break;
66843691Sgjelinek 		}
66853691Sgjelinek 	}
66863691Sgjelinek 	if (arg_err)
66873691Sgjelinek 		return;
66883691Sgjelinek 
66890Sstevel@tonic-gate 	if (optind != cmd->cmd_argc) {
66900Sstevel@tonic-gate 		short_usage(CMD_REVERT);
66910Sstevel@tonic-gate 		return;
66920Sstevel@tonic-gate 	}
66930Sstevel@tonic-gate 
66940Sstevel@tonic-gate 	if (zone_is_read_only(CMD_REVERT))
66950Sstevel@tonic-gate 		return;
66960Sstevel@tonic-gate 
66978113SJordan.Vaughan@Sun.com 	if (!global_scope) {
66988113SJordan.Vaughan@Sun.com 		zerr(gettext("You can only use %s in the global scope.\nUse"
66998113SJordan.Vaughan@Sun.com 		    " '%s' to cancel changes to a resource specification."),
67008113SJordan.Vaughan@Sun.com 		    cmd_to_str(CMD_REVERT), cmd_to_str(CMD_CANCEL));
67018113SJordan.Vaughan@Sun.com 		saw_error = B_TRUE;
67028113SJordan.Vaughan@Sun.com 		return;
67038113SJordan.Vaughan@Sun.com 	}
67048113SJordan.Vaughan@Sun.com 
67050Sstevel@tonic-gate 	if (zonecfg_check_handle(handle) != Z_OK) {
67060Sstevel@tonic-gate 		zerr(gettext("No changes to revert."));
67076215Sgjelinek 		saw_error = B_TRUE;
67080Sstevel@tonic-gate 		return;
67090Sstevel@tonic-gate 	}
67100Sstevel@tonic-gate 
67110Sstevel@tonic-gate 	if (!force) {
67120Sstevel@tonic-gate 		(void) snprintf(line, sizeof (line),
67130Sstevel@tonic-gate 		    gettext("Are you sure you want to revert"));
67146215Sgjelinek 		if ((answer = ask_yesno(B_FALSE, line)) == -1) {
67150Sstevel@tonic-gate 			zerr(gettext("Input not from terminal and -F not "
67160Sstevel@tonic-gate 			    "specified:\n%s command ignored, exiting."),
67170Sstevel@tonic-gate 			    cmd_to_str(CMD_REVERT));
67180Sstevel@tonic-gate 			exit(Z_ERR);
67190Sstevel@tonic-gate 		}
67200Sstevel@tonic-gate 		if (answer != 1)
67210Sstevel@tonic-gate 			return;
67220Sstevel@tonic-gate 	}
67230Sstevel@tonic-gate 
67240Sstevel@tonic-gate 	/*
672512578SGlenn.Faden@Sun.COM 	 * Reset any pending admins that were
672612578SGlenn.Faden@Sun.COM 	 * removed from the previous zone
672712578SGlenn.Faden@Sun.COM 	 */
672812578SGlenn.Faden@Sun.COM 	zonecfg_remove_userauths(handle, "", zone, B_FALSE);
672912578SGlenn.Faden@Sun.COM 
673012578SGlenn.Faden@Sun.COM 	/*
67310Sstevel@tonic-gate 	 * Time for a new handle: finish the old one off first
67320Sstevel@tonic-gate 	 * then get a new one properly to avoid leaks.
67330Sstevel@tonic-gate 	 */
67340Sstevel@tonic-gate 	zonecfg_fini_handle(handle);
67350Sstevel@tonic-gate 	if ((handle = zonecfg_init_handle()) == NULL) {
67366215Sgjelinek 		zone_perror(execname, Z_NOMEM, B_TRUE);
67370Sstevel@tonic-gate 		exit(Z_ERR);
67380Sstevel@tonic-gate 	}
673912578SGlenn.Faden@Sun.COM 
6740565Sdp 	if ((err = zonecfg_get_handle(revert_zone, handle)) != Z_OK) {
67416215Sgjelinek 		saw_error = B_TRUE;
67426215Sgjelinek 		got_handle = B_FALSE;
67430Sstevel@tonic-gate 		if (err == Z_NO_ZONE)
67440Sstevel@tonic-gate 			zerr(gettext("%s: no such saved zone to revert to."),
6745565Sdp 			    revert_zone);
67460Sstevel@tonic-gate 		else
67476215Sgjelinek 			zone_perror(zone, err, B_TRUE);
67480Sstevel@tonic-gate 	}
6749565Sdp 	(void) strlcpy(zone, revert_zone, sizeof (zone));
67500Sstevel@tonic-gate }
67510Sstevel@tonic-gate 
67520Sstevel@tonic-gate void
help_func(cmd_t * cmd)67530Sstevel@tonic-gate help_func(cmd_t *cmd)
67540Sstevel@tonic-gate {
67550Sstevel@tonic-gate 	int i;
67560Sstevel@tonic-gate 
67570Sstevel@tonic-gate 	assert(cmd != NULL);
67580Sstevel@tonic-gate 
67590Sstevel@tonic-gate 	if (cmd->cmd_argc == 0) {
67606215Sgjelinek 		usage(B_TRUE, global_scope ? HELP_SUBCMDS : HELP_RES_SCOPE);
67610Sstevel@tonic-gate 		return;
67620Sstevel@tonic-gate 	}
67630Sstevel@tonic-gate 	if (strcmp(cmd->cmd_argv[0], "usage") == 0) {
67646215Sgjelinek 		usage(B_TRUE, HELP_USAGE);
67650Sstevel@tonic-gate 		return;
67660Sstevel@tonic-gate 	}
67670Sstevel@tonic-gate 	if (strcmp(cmd->cmd_argv[0], "commands") == 0) {
67686215Sgjelinek 		usage(B_TRUE, HELP_SUBCMDS);
67690Sstevel@tonic-gate 		return;
67700Sstevel@tonic-gate 	}
67710Sstevel@tonic-gate 	if (strcmp(cmd->cmd_argv[0], "syntax") == 0) {
67726215Sgjelinek 		usage(B_TRUE, HELP_SYNTAX | HELP_RES_PROPS);
67730Sstevel@tonic-gate 		return;
67740Sstevel@tonic-gate 	}
67750Sstevel@tonic-gate 	if (strcmp(cmd->cmd_argv[0], "-?") == 0) {
67760Sstevel@tonic-gate 		longer_usage(CMD_HELP);
67770Sstevel@tonic-gate 		return;
67780Sstevel@tonic-gate 	}
67790Sstevel@tonic-gate 
67800Sstevel@tonic-gate 	for (i = 0; i <= CMD_MAX; i++) {
67810Sstevel@tonic-gate 		if (strcmp(cmd->cmd_argv[0], cmd_to_str(i)) == 0) {
67820Sstevel@tonic-gate 			longer_usage(i);
67830Sstevel@tonic-gate 			return;
67840Sstevel@tonic-gate 		}
67850Sstevel@tonic-gate 	}
67860Sstevel@tonic-gate 	/* We do not use zerr() here because we do not want its extra \n. */
67870Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("Unknown help subject %s.  "),
67880Sstevel@tonic-gate 	    cmd->cmd_argv[0]);
67896215Sgjelinek 	usage(B_FALSE, HELP_META);
67900Sstevel@tonic-gate }
67910Sstevel@tonic-gate 
67920Sstevel@tonic-gate static int
string_to_yyin(char * string)67930Sstevel@tonic-gate string_to_yyin(char *string)
67940Sstevel@tonic-gate {
67950Sstevel@tonic-gate 	if ((yyin = tmpfile()) == NULL) {
67966215Sgjelinek 		zone_perror(execname, Z_TEMP_FILE, B_TRUE);
67970Sstevel@tonic-gate 		return (Z_ERR);
67980Sstevel@tonic-gate 	}
67990Sstevel@tonic-gate 	if (fwrite(string, strlen(string), 1, yyin) != 1) {
68006215Sgjelinek 		zone_perror(execname, Z_TEMP_FILE, B_TRUE);
68010Sstevel@tonic-gate 		return (Z_ERR);
68020Sstevel@tonic-gate 	}
68030Sstevel@tonic-gate 	if (fseek(yyin, 0, SEEK_SET) != 0) {
68046215Sgjelinek 		zone_perror(execname, Z_TEMP_FILE, B_TRUE);
68050Sstevel@tonic-gate 		return (Z_ERR);
68060Sstevel@tonic-gate 	}
68070Sstevel@tonic-gate 	return (Z_OK);
68080Sstevel@tonic-gate }
68090Sstevel@tonic-gate 
68100Sstevel@tonic-gate /* This is the back-end helper function for read_input() below. */
68110Sstevel@tonic-gate 
68120Sstevel@tonic-gate static int
cleanup()68130Sstevel@tonic-gate cleanup()
68140Sstevel@tonic-gate {
68150Sstevel@tonic-gate 	int answer;
68160Sstevel@tonic-gate 	cmd_t *cmd;
68170Sstevel@tonic-gate 
68180Sstevel@tonic-gate 	if (!interactive_mode && !cmd_file_mode) {
68190Sstevel@tonic-gate 		/*
68200Sstevel@tonic-gate 		 * If we're not in interactive mode, and we're not in command
68210Sstevel@tonic-gate 		 * file mode, then we must be in commands-from-the-command-line
68220Sstevel@tonic-gate 		 * mode.  As such, we can't loop back and ask for more input.
68230Sstevel@tonic-gate 		 * It was OK to prompt for such things as whether or not to
68240Sstevel@tonic-gate 		 * really delete a zone in the command handler called from
68250Sstevel@tonic-gate 		 * yyparse() above, but "really quit?" makes no sense in this
68260Sstevel@tonic-gate 		 * context.  So disable prompting.
68270Sstevel@tonic-gate 		 */
68286215Sgjelinek 		ok_to_prompt = B_FALSE;
68290Sstevel@tonic-gate 	}
68300Sstevel@tonic-gate 	if (!global_scope) {
68310Sstevel@tonic-gate 		if (!time_to_exit) {
68320Sstevel@tonic-gate 			/*
68330Sstevel@tonic-gate 			 * Just print a simple error message in the -1 case,
68340Sstevel@tonic-gate 			 * since exit_func() already handles that case, and
68350Sstevel@tonic-gate 			 * EOF means we are finished anyway.
68360Sstevel@tonic-gate 			 */
68376215Sgjelinek 			answer = ask_yesno(B_FALSE,
68380Sstevel@tonic-gate 			    gettext("Resource incomplete; really quit"));
68390Sstevel@tonic-gate 			if (answer == -1) {
68400Sstevel@tonic-gate 				zerr(gettext("Resource incomplete."));
68410Sstevel@tonic-gate 				return (Z_ERR);
68420Sstevel@tonic-gate 			}
68430Sstevel@tonic-gate 			if (answer != 1) {
68440Sstevel@tonic-gate 				yyin = stdin;
68450Sstevel@tonic-gate 				return (Z_REPEAT);
68460Sstevel@tonic-gate 			}
68470Sstevel@tonic-gate 		} else {
68486215Sgjelinek 			saw_error = B_TRUE;
68490Sstevel@tonic-gate 		}
68500Sstevel@tonic-gate 	}
68510Sstevel@tonic-gate 	/*
68520Sstevel@tonic-gate 	 * Make sure we tried something and that the handle checks
68530Sstevel@tonic-gate 	 * out, or we would get a false error trying to commit.
68540Sstevel@tonic-gate 	 */
68550Sstevel@tonic-gate 	if (need_to_commit && zonecfg_check_handle(handle) == Z_OK) {
68560Sstevel@tonic-gate 		if ((cmd = alloc_cmd()) == NULL) {
68576215Sgjelinek 			zone_perror(zone, Z_NOMEM, B_TRUE);
68580Sstevel@tonic-gate 			return (Z_ERR);
68590Sstevel@tonic-gate 		}
68600Sstevel@tonic-gate 		cmd->cmd_argc = 0;
68610Sstevel@tonic-gate 		cmd->cmd_argv[0] = NULL;
68620Sstevel@tonic-gate 		commit_func(cmd);
68630Sstevel@tonic-gate 		free_cmd(cmd);
68640Sstevel@tonic-gate 		/*
68650Sstevel@tonic-gate 		 * need_to_commit will get set back to FALSE if the
68660Sstevel@tonic-gate 		 * configuration is saved successfully.
68670Sstevel@tonic-gate 		 */
68680Sstevel@tonic-gate 		if (need_to_commit) {
68690Sstevel@tonic-gate 			if (force_exit) {
68700Sstevel@tonic-gate 				zerr(gettext("Configuration not saved."));
68710Sstevel@tonic-gate 				return (Z_ERR);
68720Sstevel@tonic-gate 			}
68736215Sgjelinek 			answer = ask_yesno(B_FALSE,
68740Sstevel@tonic-gate 			    gettext("Configuration not saved; really quit"));
68750Sstevel@tonic-gate 			if (answer == -1) {
68760Sstevel@tonic-gate 				zerr(gettext("Configuration not saved."));
68770Sstevel@tonic-gate 				return (Z_ERR);
68780Sstevel@tonic-gate 			}
68790Sstevel@tonic-gate 			if (answer != 1) {
68806215Sgjelinek 				time_to_exit = B_FALSE;
68810Sstevel@tonic-gate 				yyin = stdin;
68820Sstevel@tonic-gate 				return (Z_REPEAT);
68830Sstevel@tonic-gate 			}
68840Sstevel@tonic-gate 		}
68850Sstevel@tonic-gate 	}
68860Sstevel@tonic-gate 	return ((need_to_commit || saw_error) ? Z_ERR : Z_OK);
68870Sstevel@tonic-gate }
68880Sstevel@tonic-gate 
68890Sstevel@tonic-gate /*
68900Sstevel@tonic-gate  * read_input() is the driver of this program.  It is a wrapper around
68910Sstevel@tonic-gate  * yyparse(), printing appropriate prompts when needed, checking for
68920Sstevel@tonic-gate  * exit conditions and reacting appropriately [the latter in its cleanup()
68930Sstevel@tonic-gate  * helper function].
68940Sstevel@tonic-gate  *
68950Sstevel@tonic-gate  * Like most zonecfg functions, it returns Z_OK or Z_ERR, *or* Z_REPEAT
68960Sstevel@tonic-gate  * so do_interactive() knows that we are not really done (i.e, we asked
68970Sstevel@tonic-gate  * the user if we should really quit and the user said no).
68980Sstevel@tonic-gate  */
68990Sstevel@tonic-gate static int
read_input()69000Sstevel@tonic-gate read_input()
69010Sstevel@tonic-gate {
69026215Sgjelinek 	boolean_t yyin_is_a_tty = isatty(fileno(yyin));
69030Sstevel@tonic-gate 	/*
69040Sstevel@tonic-gate 	 * The prompt is "e:z> " or "e:z:r> " where e is execname, z is zone
69050Sstevel@tonic-gate 	 * and r is resource_scope: 5 is for the two ":"s + "> " + terminator.
69060Sstevel@tonic-gate 	 */
69070Sstevel@tonic-gate 	char prompt[MAXPATHLEN + ZONENAME_MAX + MAX_RT_STRLEN + 5], *line;
69080Sstevel@tonic-gate 
69090Sstevel@tonic-gate 	/* yyin should have been set to the appropriate (FILE *) if not stdin */
69106215Sgjelinek 	newline_terminated = B_TRUE;
69110Sstevel@tonic-gate 	for (;;) {
69120Sstevel@tonic-gate 		if (yyin_is_a_tty) {
69130Sstevel@tonic-gate 			if (newline_terminated) {
69140Sstevel@tonic-gate 				if (global_scope)
69150Sstevel@tonic-gate 					(void) snprintf(prompt, sizeof (prompt),
69160Sstevel@tonic-gate 					    "%s:%s> ", execname, zone);
69170Sstevel@tonic-gate 				else
69180Sstevel@tonic-gate 					(void) snprintf(prompt, sizeof (prompt),
69190Sstevel@tonic-gate 					    "%s:%s:%s> ", execname, zone,
69200Sstevel@tonic-gate 					    rt_to_str(resource_scope));
69210Sstevel@tonic-gate 			}
69220Sstevel@tonic-gate 			/*
69230Sstevel@tonic-gate 			 * If the user hits ^C then we want to catch it and
69240Sstevel@tonic-gate 			 * start over.  If the user hits EOF then we want to
69250Sstevel@tonic-gate 			 * bail out.
69260Sstevel@tonic-gate 			 */
69270Sstevel@tonic-gate 			line = gl_get_line(gl, prompt, NULL, -1);
69280Sstevel@tonic-gate 			if (gl_return_status(gl) == GLR_SIGNAL) {
69290Sstevel@tonic-gate 				gl_abandon_line(gl);
69300Sstevel@tonic-gate 				continue;
69310Sstevel@tonic-gate 			}
69320Sstevel@tonic-gate 			if (line == NULL)
69330Sstevel@tonic-gate 				break;
69340Sstevel@tonic-gate 			(void) string_to_yyin(line);
69350Sstevel@tonic-gate 			while (!feof(yyin))
69360Sstevel@tonic-gate 				yyparse();
69370Sstevel@tonic-gate 		} else {
69380Sstevel@tonic-gate 			yyparse();
69390Sstevel@tonic-gate 		}
69400Sstevel@tonic-gate 		/* Bail out on an error in command file mode. */
69410Sstevel@tonic-gate 		if (saw_error && cmd_file_mode && !interactive_mode)
69426215Sgjelinek 			time_to_exit = B_TRUE;
69430Sstevel@tonic-gate 		if (time_to_exit || (!yyin_is_a_tty && feof(yyin)))
69440Sstevel@tonic-gate 			break;
69450Sstevel@tonic-gate 	}
69460Sstevel@tonic-gate 	return (cleanup());
69470Sstevel@tonic-gate }
69480Sstevel@tonic-gate 
69490Sstevel@tonic-gate /*
69500Sstevel@tonic-gate  * This function is used in the zonecfg-interactive-mode scenario: it just
69510Sstevel@tonic-gate  * calls read_input() until we are done.
69520Sstevel@tonic-gate  */
69530Sstevel@tonic-gate 
69540Sstevel@tonic-gate static int
do_interactive(void)69550Sstevel@tonic-gate do_interactive(void)
69560Sstevel@tonic-gate {
69570Sstevel@tonic-gate 	int err;
69580Sstevel@tonic-gate 
69596215Sgjelinek 	interactive_mode = B_TRUE;
69600Sstevel@tonic-gate 	if (!read_only_mode) {
69610Sstevel@tonic-gate 		/*
69620Sstevel@tonic-gate 		 * Try to set things up proactively in interactive mode, so
69630Sstevel@tonic-gate 		 * that if the zone in question does not exist yet, we can
69640Sstevel@tonic-gate 		 * provide the user with a clue.
69650Sstevel@tonic-gate 		 */
69666215Sgjelinek 		(void) initialize(B_FALSE);
69670Sstevel@tonic-gate 	}
6968565Sdp 	do {
69690Sstevel@tonic-gate 		err = read_input();
6970565Sdp 	} while (err == Z_REPEAT);
69710Sstevel@tonic-gate 	return (err);
69720Sstevel@tonic-gate }
69730Sstevel@tonic-gate 
69740Sstevel@tonic-gate /*
69750Sstevel@tonic-gate  * cmd_file is slightly more complicated, as it has to open the command file
69760Sstevel@tonic-gate  * and set yyin appropriately.  Once that is done, though, it just calls
69770Sstevel@tonic-gate  * read_input(), and only once, since prompting is not possible.
69780Sstevel@tonic-gate  */
69790Sstevel@tonic-gate 
69800Sstevel@tonic-gate static int
cmd_file(char * file)69810Sstevel@tonic-gate cmd_file(char *file)
69820Sstevel@tonic-gate {
69830Sstevel@tonic-gate 	FILE *infile;
69840Sstevel@tonic-gate 	int err;
69850Sstevel@tonic-gate 	struct stat statbuf;
69866215Sgjelinek 	boolean_t using_real_file = (strcmp(file, "-") != 0);
69870Sstevel@tonic-gate 
69880Sstevel@tonic-gate 	if (using_real_file) {
69890Sstevel@tonic-gate 		/*
69900Sstevel@tonic-gate 		 * zerr() prints a line number in cmd_file_mode, which we do
69910Sstevel@tonic-gate 		 * not want here, so temporarily unset it.
69920Sstevel@tonic-gate 		 */
69936215Sgjelinek 		cmd_file_mode = B_FALSE;
69940Sstevel@tonic-gate 		if ((infile = fopen(file, "r")) == NULL) {
69950Sstevel@tonic-gate 			zerr(gettext("could not open file %s: %s"),
69960Sstevel@tonic-gate 			    file, strerror(errno));
69970Sstevel@tonic-gate 			return (Z_ERR);
69980Sstevel@tonic-gate 		}
69990Sstevel@tonic-gate 		if ((err = fstat(fileno(infile), &statbuf)) != 0) {
70000Sstevel@tonic-gate 			zerr(gettext("could not stat file %s: %s"),
70010Sstevel@tonic-gate 			    file, strerror(errno));
70020Sstevel@tonic-gate 			err = Z_ERR;
70030Sstevel@tonic-gate 			goto done;
70040Sstevel@tonic-gate 		}
70050Sstevel@tonic-gate 		if (!S_ISREG(statbuf.st_mode)) {
70060Sstevel@tonic-gate 			zerr(gettext("%s is not a regular file."), file);
70070Sstevel@tonic-gate 			err = Z_ERR;
70080Sstevel@tonic-gate 			goto done;
70090Sstevel@tonic-gate 		}
70100Sstevel@tonic-gate 		yyin = infile;
70116215Sgjelinek 		cmd_file_mode = B_TRUE;
70126215Sgjelinek 		ok_to_prompt = B_FALSE;
70130Sstevel@tonic-gate 	} else {
70140Sstevel@tonic-gate 		/*
70150Sstevel@tonic-gate 		 * "-f -" is essentially the same as interactive mode,
70160Sstevel@tonic-gate 		 * so treat it that way.
70170Sstevel@tonic-gate 		 */
70186215Sgjelinek 		interactive_mode = B_TRUE;
70190Sstevel@tonic-gate 	}
70200Sstevel@tonic-gate 	/* Z_REPEAT is for interactive mode; treat it like Z_ERR here. */
70210Sstevel@tonic-gate 	if ((err = read_input()) == Z_REPEAT)
70220Sstevel@tonic-gate 		err = Z_ERR;
70230Sstevel@tonic-gate done:
70240Sstevel@tonic-gate 	if (using_real_file)
70250Sstevel@tonic-gate 		(void) fclose(infile);
70260Sstevel@tonic-gate 	return (err);
70270Sstevel@tonic-gate }
70280Sstevel@tonic-gate 
70290Sstevel@tonic-gate /*
70300Sstevel@tonic-gate  * Since yacc is based on reading from a (FILE *) whereas what we get from
70310Sstevel@tonic-gate  * the command line is in argv format, we need to convert when the user
70320Sstevel@tonic-gate  * gives us commands directly from the command line.  That is done here by
70330Sstevel@tonic-gate  * concatenating the argv list into a space-separated string, writing it
70340Sstevel@tonic-gate  * to a temp file, and rewinding the file so yyin can be set to it.  Then
70350Sstevel@tonic-gate  * we call read_input(), and only once, since prompting about whether to
70360Sstevel@tonic-gate  * continue or quit would make no sense in this context.
70370Sstevel@tonic-gate  */
70380Sstevel@tonic-gate 
70390Sstevel@tonic-gate static int
one_command_at_a_time(int argc,char * argv[])70400Sstevel@tonic-gate one_command_at_a_time(int argc, char *argv[])
70410Sstevel@tonic-gate {
70420Sstevel@tonic-gate 	char *command;
70430Sstevel@tonic-gate 	size_t len = 2; /* terminal \n\0 */
70440Sstevel@tonic-gate 	int i, err;
70450Sstevel@tonic-gate 
70460Sstevel@tonic-gate 	for (i = 0; i < argc; i++)
70470Sstevel@tonic-gate 		len += strlen(argv[i]) + 1;
70480Sstevel@tonic-gate 	if ((command = malloc(len)) == NULL) {
70496215Sgjelinek 		zone_perror(execname, Z_NOMEM, B_TRUE);
70500Sstevel@tonic-gate 		return (Z_ERR);
70510Sstevel@tonic-gate 	}
70520Sstevel@tonic-gate 	(void) strlcpy(command, argv[0], len);
70530Sstevel@tonic-gate 	for (i = 1; i < argc; i++) {
70540Sstevel@tonic-gate 		(void) strlcat(command, " ", len);
70550Sstevel@tonic-gate 		(void) strlcat(command, argv[i], len);
70560Sstevel@tonic-gate 	}
70570Sstevel@tonic-gate 	(void) strlcat(command, "\n", len);
70580Sstevel@tonic-gate 	err = string_to_yyin(command);
70590Sstevel@tonic-gate 	free(command);
70600Sstevel@tonic-gate 	if (err != Z_OK)
70610Sstevel@tonic-gate 		return (err);
70620Sstevel@tonic-gate 	while (!feof(yyin))
70630Sstevel@tonic-gate 		yyparse();
70640Sstevel@tonic-gate 	return (cleanup());
70650Sstevel@tonic-gate }
70660Sstevel@tonic-gate 
70670Sstevel@tonic-gate static char *
get_execbasename(char * execfullname)70680Sstevel@tonic-gate get_execbasename(char *execfullname)
70690Sstevel@tonic-gate {
70700Sstevel@tonic-gate 	char *last_slash, *execbasename;
70710Sstevel@tonic-gate 
70720Sstevel@tonic-gate 	/* guard against '/' at end of command invocation */
70730Sstevel@tonic-gate 	for (;;) {
70740Sstevel@tonic-gate 		last_slash = strrchr(execfullname, '/');
70750Sstevel@tonic-gate 		if (last_slash == NULL) {
70760Sstevel@tonic-gate 			execbasename = execfullname;
70770Sstevel@tonic-gate 			break;
70780Sstevel@tonic-gate 		} else {
70790Sstevel@tonic-gate 			execbasename = last_slash + 1;
70800Sstevel@tonic-gate 			if (*execbasename == '\0') {
70810Sstevel@tonic-gate 				*last_slash = '\0';
70820Sstevel@tonic-gate 				continue;
70830Sstevel@tonic-gate 			}
70840Sstevel@tonic-gate 			break;
70850Sstevel@tonic-gate 		}
70860Sstevel@tonic-gate 	}
70870Sstevel@tonic-gate 	return (execbasename);
70880Sstevel@tonic-gate }
70890Sstevel@tonic-gate 
70900Sstevel@tonic-gate int
main(int argc,char * argv[])70910Sstevel@tonic-gate main(int argc, char *argv[])
70920Sstevel@tonic-gate {
70930Sstevel@tonic-gate 	int err, arg;
70942303Scarlsonj 	struct stat st;
70950Sstevel@tonic-gate 
70960Sstevel@tonic-gate 	/* This must be before anything goes to stdout. */
70970Sstevel@tonic-gate 	setbuf(stdout, NULL);
70980Sstevel@tonic-gate 
70996215Sgjelinek 	saw_error = B_FALSE;
71006215Sgjelinek 	cmd_file_mode = B_FALSE;
71010Sstevel@tonic-gate 	execname = get_execbasename(argv[0]);
71020Sstevel@tonic-gate 
71030Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
71040Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
71050Sstevel@tonic-gate 
71060Sstevel@tonic-gate 	if (getzoneid() != GLOBAL_ZONEID) {
71070Sstevel@tonic-gate 		zerr(gettext("%s can only be run from the global zone."),
71080Sstevel@tonic-gate 		    execname);
71090Sstevel@tonic-gate 		exit(Z_ERR);
71100Sstevel@tonic-gate 	}
71110Sstevel@tonic-gate 
71120Sstevel@tonic-gate 	if (argc < 2) {
71136215Sgjelinek 		usage(B_FALSE, HELP_USAGE | HELP_SUBCMDS);
71140Sstevel@tonic-gate 		exit(Z_USAGE);
71150Sstevel@tonic-gate 	}
71160Sstevel@tonic-gate 	if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) {
71170Sstevel@tonic-gate 		(void) one_command_at_a_time(argc - 1, &(argv[1]));
71180Sstevel@tonic-gate 		exit(Z_OK);
71190Sstevel@tonic-gate 	}
71200Sstevel@tonic-gate 
71212303Scarlsonj 	while ((arg = getopt(argc, argv, "?f:R:z:")) != EOF) {
71220Sstevel@tonic-gate 		switch (arg) {
71230Sstevel@tonic-gate 		case '?':
71240Sstevel@tonic-gate 			if (optopt == '?')
71256215Sgjelinek 				usage(B_TRUE, HELP_USAGE | HELP_SUBCMDS);
71260Sstevel@tonic-gate 			else
71276215Sgjelinek 				usage(B_FALSE, HELP_USAGE);
71280Sstevel@tonic-gate 			exit(Z_USAGE);
71290Sstevel@tonic-gate 			/* NOTREACHED */
71300Sstevel@tonic-gate 		case 'f':
71310Sstevel@tonic-gate 			cmd_file_name = optarg;
71326215Sgjelinek 			cmd_file_mode = B_TRUE;
71330Sstevel@tonic-gate 			break;
71342303Scarlsonj 		case 'R':
71352303Scarlsonj 			if (*optarg != '/') {
71362303Scarlsonj 				zerr(gettext("root path must be absolute: %s"),
71372303Scarlsonj 				    optarg);
71382303Scarlsonj 				exit(Z_USAGE);
71392303Scarlsonj 			}
71402303Scarlsonj 			if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
71412303Scarlsonj 				zerr(gettext(
71422303Scarlsonj 				    "root path must be a directory: %s"),
71432303Scarlsonj 				    optarg);
71442303Scarlsonj 				exit(Z_USAGE);
71452303Scarlsonj 			}
71462303Scarlsonj 			zonecfg_set_root(optarg);
71472303Scarlsonj 			break;
71480Sstevel@tonic-gate 		case 'z':
71493247Sgjelinek 			if (strcmp(optarg, GLOBAL_ZONENAME) == 0) {
71506215Sgjelinek 				global_zone = B_TRUE;
71513247Sgjelinek 			} else if (zonecfg_validate_zonename(optarg) != Z_OK) {
71526215Sgjelinek 				zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE);
71536215Sgjelinek 				usage(B_FALSE, HELP_SYNTAX);
7154565Sdp 				exit(Z_USAGE);
7155565Sdp 			}
7156565Sdp 			(void) strlcpy(zone, optarg, sizeof (zone));
7157565Sdp 			(void) strlcpy(revert_zone, optarg, sizeof (zone));
71580Sstevel@tonic-gate 			break;
71590Sstevel@tonic-gate 		default:
71606215Sgjelinek 			usage(B_FALSE, HELP_USAGE);
71610Sstevel@tonic-gate 			exit(Z_USAGE);
71620Sstevel@tonic-gate 		}
71630Sstevel@tonic-gate 	}
71640Sstevel@tonic-gate 
7165565Sdp 	if (optind > argc || strcmp(zone, "") == 0) {
71666215Sgjelinek 		usage(B_FALSE, HELP_USAGE);
71670Sstevel@tonic-gate 		exit(Z_USAGE);
71680Sstevel@tonic-gate 	}
71690Sstevel@tonic-gate 
7170565Sdp 	if ((err = zonecfg_access(zone, W_OK)) == Z_OK) {
71716215Sgjelinek 		read_only_mode = B_FALSE;
7172565Sdp 	} else if (err == Z_ACCES) {
71736215Sgjelinek 		read_only_mode = B_TRUE;
71740Sstevel@tonic-gate 		/* skip this message in one-off from command line mode */
71750Sstevel@tonic-gate 		if (optind == argc)
71760Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("WARNING: you do not "
71770Sstevel@tonic-gate 			    "have write access to this zone's configuration "
71780Sstevel@tonic-gate 			    "file;\ngoing into read-only mode.\n"));
7179565Sdp 	} else {
7180565Sdp 		fprintf(stderr, "%s: Could not access zone configuration "
7181565Sdp 		    "store: %s\n", execname, zonecfg_strerror(err));
7182565Sdp 		exit(Z_ERR);
71830Sstevel@tonic-gate 	}
71840Sstevel@tonic-gate 
71850Sstevel@tonic-gate 	if ((handle = zonecfg_init_handle()) == NULL) {
71866215Sgjelinek 		zone_perror(execname, Z_NOMEM, B_TRUE);
71870Sstevel@tonic-gate 		exit(Z_ERR);
71880Sstevel@tonic-gate 	}
71890Sstevel@tonic-gate 
71900Sstevel@tonic-gate 	/*
71910Sstevel@tonic-gate 	 * This may get set back to FALSE again in cmd_file() if cmd_file_name
71920Sstevel@tonic-gate 	 * is a "real" file as opposed to "-" (i.e. meaning use stdin).
71930Sstevel@tonic-gate 	 */
71940Sstevel@tonic-gate 	if (isatty(STDIN_FILENO))
71956215Sgjelinek 		ok_to_prompt = B_TRUE;
71960Sstevel@tonic-gate 	if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL)
71970Sstevel@tonic-gate 		exit(Z_ERR);
71980Sstevel@tonic-gate 	if (gl_customize_completion(gl, NULL, cmd_cpl_fn) != 0)
71990Sstevel@tonic-gate 		exit(Z_ERR);
72000Sstevel@tonic-gate 	(void) sigset(SIGINT, SIG_IGN);
72010Sstevel@tonic-gate 	if (optind == argc) {
72020Sstevel@tonic-gate 		if (!cmd_file_mode)
72030Sstevel@tonic-gate 			err = do_interactive();
72040Sstevel@tonic-gate 		else
72050Sstevel@tonic-gate 			err = cmd_file(cmd_file_name);
72060Sstevel@tonic-gate 	} else {
72070Sstevel@tonic-gate 		err = one_command_at_a_time(argc - optind, &(argv[optind]));
72080Sstevel@tonic-gate 	}
72090Sstevel@tonic-gate 	zonecfg_fini_handle(handle);
72102712Snn35248 	if (brand != NULL)
72112712Snn35248 		brand_close(brand);
72120Sstevel@tonic-gate 	(void) del_GetLine(gl);
72130Sstevel@tonic-gate 	return (err);
72140Sstevel@tonic-gate }
7215