Home | History | Annotate | Download | only in zonecfg
      1      0    stevel /*
      2      0    stevel  * CDDL HEADER START
      3      0    stevel  *
      4      0    stevel  * The contents of this file are subject to the terms of the
      5   1497        dp  * Common Development and Distribution License (the "License").
      6   1497        dp  * You may not use this file except in compliance with the License.
      7      0    stevel  *
      8      0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0    stevel  * or http://www.opensolaris.org/os/licensing.
     10      0    stevel  * See the License for the specific language governing permissions
     11      0    stevel  * and limitations under the License.
     12      0    stevel  *
     13      0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0    stevel  *
     19      0    stevel  * CDDL HEADER END
     20      0    stevel  */
     21    222     comay 
     22      0    stevel /*
     23   8662    Jordan  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24      0    stevel  * Use is subject to license terms.
     25      0    stevel  */
     26      0    stevel 
     27      0    stevel /*
     28      0    stevel  * zonecfg is a lex/yacc based command interpreter used to manage zone
     29      0    stevel  * configurations.  The lexer (see zonecfg_lex.l) builds up tokens, which
     30      0    stevel  * the grammar (see zonecfg_grammar.y) builds up into commands, some of
     31      0    stevel  * which takes resources and/or properties as arguments.  See the block
     32      0    stevel  * comments near the end of zonecfg_grammar.y for how the data structures
     33      0    stevel  * which keep track of these resources and properties are built up.
     34      0    stevel  *
     35      0    stevel  * The resource/property data structures are inserted into a command
     36      0    stevel  * structure (see zonecfg.h), which also keeps track of command names,
     37      0    stevel  * miscellaneous arguments, and function handlers.  The grammar selects
     38      0    stevel  * the appropriate function handler, each of which takes a pointer to a
     39      0    stevel  * command structure as its sole argument, and invokes it.  The grammar
     40      0    stevel  * itself is "entered" (a la the Matrix) by yyparse(), which is called
     41      0    stevel  * from read_input(), our main driving function.  That in turn is called
     42      0    stevel  * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
     43      0    stevel  * of which is called from main() depending on how the program was invoked.
     44      0    stevel  *
     45      0    stevel  * The rest of this module consists of the various function handlers and
     46      0    stevel  * their helper functions.  Some of these functions, particularly the
     47      0    stevel  * X_to_str() functions, which maps command, resource and property numbers
     48      0    stevel  * to strings, are used quite liberally, as doing so results in a better
     49      0    stevel  * program w/rt I18N, reducing the need for translation notes.
     50      0    stevel  */
     51      0    stevel 
     52      0    stevel #include <sys/mntent.h>
     53      0    stevel #include <sys/varargs.h>
     54      0    stevel #include <sys/sysmacros.h>
     55      0    stevel 
     56      0    stevel #include <errno.h>
     57   2712   nn35248 #include <fcntl.h>
     58      0    stevel #include <strings.h>
     59      0    stevel #include <unistd.h>
     60      0    stevel #include <ctype.h>
     61      0    stevel #include <stdlib.h>
     62      0    stevel #include <assert.h>
     63      0    stevel #include <sys/stat.h>
     64      0    stevel #include <zone.h>
     65      0    stevel #include <arpa/inet.h>
     66      0    stevel #include <netdb.h>
     67      0    stevel #include <locale.h>
     68      0    stevel #include <libintl.h>
     69      0    stevel #include <alloca.h>
     70      0    stevel #include <signal.h>
     71   2712   nn35248 #include <wait.h>
     72      0    stevel #include <libtecla.h>
     73    789    ahrens #include <libzfs.h>
     74   2712   nn35248 #include <sys/brand.h>
     75   2712   nn35248 #include <libbrand.h>
     76   8662    Jordan #include <sys/systeminfo.h>
     77   8083    Jordan #include <libdladm.h>
     78   8083    Jordan #include <libinetutil.h>
     79      0    stevel 
     80      0    stevel #include <libzonecfg.h>
     81      0    stevel #include "zonecfg.h"
     82      0    stevel 
     83      0    stevel #if !defined(TEXT_DOMAIN)		/* should be defined by cc -D */
     84      0    stevel #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it wasn't */
     85      0    stevel #endif
     86      0    stevel 
     87      0    stevel #define	PAGER	"/usr/bin/more"
     88   2712   nn35248 #define	EXEC_PREFIX	"exec "
     89   2712   nn35248 #define	EXEC_LEN	(strlen(EXEC_PREFIX))
     90      0    stevel 
     91      0    stevel struct help {
     92      0    stevel 	uint_t	cmd_num;
     93      0    stevel 	char	*cmd_name;
     94      0    stevel 	uint_t	flags;
     95      0    stevel 	char	*short_usage;
     96      0    stevel };
     97      0    stevel 
     98      0    stevel extern int yyparse(void);
     99      0    stevel extern int lex_lineno;
    100      0    stevel 
    101      0    stevel #define	MAX_LINE_LEN	1024
    102      0    stevel #define	MAX_CMD_HIST	1024
    103   2712   nn35248 #define	MAX_CMD_LEN	1024
    104      0    stevel 
    105   3247  gjelinek #define	ONE_MB		1048576
    106   3247  gjelinek 
    107      0    stevel /*
    108      0    stevel  * Each SHELP_ should be a simple string.
    109      0    stevel  */
    110      0    stevel 
    111      0    stevel #define	SHELP_ADD	"add <resource-type>\n\t(global scope)\n" \
    112      0    stevel 	"add <property-name> <property-value>\n\t(resource scope)"
    113      0    stevel #define	SHELP_CANCEL	"cancel"
    114   3247  gjelinek #define	SHELP_CLEAR	"clear <property-name>"
    115      0    stevel #define	SHELP_COMMIT	"commit"
    116   1507  gjelinek #define	SHELP_CREATE	"create [-F] [ -a <path> | -b | -t <template> ]"
    117      0    stevel #define	SHELP_DELETE	"delete [-F]"
    118      0    stevel #define	SHELP_END	"end"
    119      0    stevel #define	SHELP_EXIT	"exit [-F]"
    120      0    stevel #define	SHELP_EXPORT	"export [-f output-file]"
    121      0    stevel #define	SHELP_HELP	"help [commands] [syntax] [usage] [<command-name>]"
    122      0    stevel #define	SHELP_INFO	"info [<resource-type> [property-name=property-value]*]"
    123   3247  gjelinek #define	SHELP_REMOVE	"remove [-F] <resource-type> " \
    124   3247  gjelinek 	"[ <property-name>=<property-value> ]*\n" \
    125   3247  gjelinek 	"\t(global scope)\n" \
    126   3247  gjelinek 	"remove <property-name> <property-value>\n" \
    127   3247  gjelinek 	"\t(resource scope)"
    128      0    stevel #define	SHELP_REVERT	"revert [-F]"
    129      0    stevel #define	SHELP_SELECT	"select <resource-type> { <property-name>=" \
    130      0    stevel 	"<property-value> }"
    131      0    stevel #define	SHELP_SET	"set <property-name>=<property-value>"
    132      0    stevel #define	SHELP_VERIFY	"verify"
    133      0    stevel 
    134      0    stevel static struct help helptab[] = {
    135      0    stevel 	{ CMD_ADD,	"add",		HELP_RES_PROPS,	SHELP_ADD, },
    136      0    stevel 	{ CMD_CANCEL,	"cancel",	0,		SHELP_CANCEL, },
    137   3247  gjelinek 	{ CMD_CLEAR,	"clear",	HELP_PROPS,	SHELP_CLEAR, },
    138      0    stevel 	{ CMD_COMMIT,	"commit",	0,		SHELP_COMMIT, },
    139      0    stevel 	{ CMD_CREATE,	"create",	0,		SHELP_CREATE, },
    140      0    stevel 	{ CMD_DELETE,	"delete",	0,		SHELP_DELETE, },
    141      0    stevel 	{ CMD_END,	"end",		0,		SHELP_END, },
    142      0    stevel 	{ CMD_EXIT,	"exit",		0,		SHELP_EXIT, },
    143      0    stevel 	{ CMD_EXPORT,	"export",	0,		SHELP_EXPORT, },
    144      0    stevel 	{ CMD_HELP,	"help",		0,		SHELP_HELP },
    145      0    stevel 	{ CMD_INFO,	"info",		HELP_RES_PROPS,	SHELP_INFO, },
    146      0    stevel 	{ CMD_REMOVE,	"remove",	HELP_RES_PROPS,	SHELP_REMOVE, },
    147      0    stevel 	{ CMD_REVERT,	"revert",	0,		SHELP_REVERT, },
    148      0    stevel 	{ CMD_SELECT,	"select",	HELP_RES_PROPS,	SHELP_SELECT, },
    149      0    stevel 	{ CMD_SET,	"set",		HELP_PROPS,	SHELP_SET, },
    150      0    stevel 	{ CMD_VERIFY,	"verify",	0,		SHELP_VERIFY, },
    151      0    stevel 	{ 0 },
    152      0    stevel };
    153      0    stevel 
    154      0    stevel #define	MAX_RT_STRLEN	16
    155      0    stevel 
    156      0    stevel /* These *must* match the order of the RT_ define's from zonecfg.h */
    157  11024    Jordan char *res_types[] = {
    158      0    stevel 	"unknown",
    159    565        dp 	"zonename",
    160      0    stevel 	"zonepath",
    161      0    stevel 	"autoboot",
    162      0    stevel 	"pool",
    163      0    stevel 	"fs",
    164      0    stevel 	"inherit-pkg-dir",
    165      0    stevel 	"net",
    166      0    stevel 	"device",
    167      0    stevel 	"rctl",
    168      0    stevel 	"attr",
    169    789    ahrens 	"dataset",
    170   1645     comay 	"limitpriv",
    171   2267        dp 	"bootargs",
    172   2712   nn35248 	"brand",
    173   3247  gjelinek 	"dedicated-cpu",
    174   3247  gjelinek 	"capped-memory",
    175   3247  gjelinek 	ALIAS_MAXLWPS,
    176   3247  gjelinek 	ALIAS_MAXSHMMEM,
    177   3247  gjelinek 	ALIAS_MAXSHMIDS,
    178   3247  gjelinek 	ALIAS_MAXMSGIDS,
    179   3247  gjelinek 	ALIAS_MAXSEMIDS,
    180   3247  gjelinek 	ALIAS_SHARES,
    181   3247  gjelinek 	"scheduling-class",
    182   3448  dh155122 	"ip-type",
    183   3792     akolb 	"capped-cpu",
    184   8662    Jordan 	"hostid",
    185      0    stevel 	NULL
    186      0    stevel };
    187      0    stevel 
    188      0    stevel /* These *must* match the order of the PT_ define's from zonecfg.h */
    189  11024    Jordan char *prop_types[] = {
    190      0    stevel 	"unknown",
    191    565        dp 	"zonename",
    192      0    stevel 	"zonepath",
    193      0    stevel 	"autoboot",
    194      0    stevel 	"pool",
    195      0    stevel 	"dir",
    196      0    stevel 	"special",
    197      0    stevel 	"type",
    198      0    stevel 	"options",
    199      0    stevel 	"address",
    200      0    stevel 	"physical",
    201      0    stevel 	"name",
    202      0    stevel 	"value",
    203      0    stevel 	"match",
    204      0    stevel 	"priv",
    205      0    stevel 	"limit",
    206      0    stevel 	"action",
    207      0    stevel 	"raw",
    208   1645     comay 	"limitpriv",
    209   2267        dp 	"bootargs",
    210   2712   nn35248 	"brand",
    211   3247  gjelinek 	"ncpus",
    212   3247  gjelinek 	"importance",
    213   3247  gjelinek 	"swap",
    214   3247  gjelinek 	"locked",
    215   3247  gjelinek 	ALIAS_SHARES,
    216   3247  gjelinek 	ALIAS_MAXLWPS,
    217   3247  gjelinek 	ALIAS_MAXSHMMEM,
    218   3247  gjelinek 	ALIAS_MAXSHMIDS,
    219   3247  gjelinek 	ALIAS_MAXMSGIDS,
    220   3247  gjelinek 	ALIAS_MAXSEMIDS,
    221   3247  gjelinek 	ALIAS_MAXLOCKEDMEM,
    222   3247  gjelinek 	ALIAS_MAXSWAP,
    223   3247  gjelinek 	"scheduling-class",
    224   3448  dh155122 	"ip-type",
    225   6076    gfaden 	"defrouter",
    226   8662    Jordan 	"hostid",
    227   1645     comay 	NULL
    228   1645     comay };
    229   1645     comay 
    230   1645     comay /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
    231      0    stevel static char *prop_val_types[] = {
    232      0    stevel 	"simple",
    233      0    stevel 	"complex",
    234      0    stevel 	"list",
    235      0    stevel };
    236      0    stevel 
    237      0    stevel /*
    238      0    stevel  * The various _cmds[] lists below are for command tab-completion.
    239      0    stevel  */
    240      0    stevel 
    241      0    stevel /*
    242      0    stevel  * remove has a space afterwards because it has qualifiers; the other commands
    243   3247  gjelinek  * that have qualifiers (add, select, etc.) don't need a space here because
    244      0    stevel  * they have their own _cmds[] lists below.
    245      0    stevel  */
    246      0    stevel static const char *global_scope_cmds[] = {
    247      0    stevel 	"add",
    248   3247  gjelinek 	"clear",
    249      0    stevel 	"commit",
    250      0    stevel 	"create",
    251      0    stevel 	"delete",
    252      0    stevel 	"exit",
    253      0    stevel 	"export",
    254      0    stevel 	"help",
    255      0    stevel 	"info",
    256      0    stevel 	"remove ",
    257      0    stevel 	"revert",
    258      0    stevel 	"select",
    259      0    stevel 	"set",
    260      0    stevel 	"verify",
    261      0    stevel 	NULL
    262      0    stevel };
    263      0    stevel 
    264      0    stevel static const char *add_cmds[] = {
    265      0    stevel 	"add fs",
    266      0    stevel 	"add inherit-pkg-dir",
    267      0    stevel 	"add net",
    268      0    stevel 	"add device",
    269      0    stevel 	"add rctl",
    270      0    stevel 	"add attr",
    271    789    ahrens 	"add dataset",
    272   3247  gjelinek 	"add dedicated-cpu",
    273   3792     akolb 	"add capped-cpu",
    274   3247  gjelinek 	"add capped-memory",
    275   3247  gjelinek 	NULL
    276   3247  gjelinek };
    277   3247  gjelinek 
    278   3247  gjelinek static const char *clear_cmds[] = {
    279   3247  gjelinek 	"clear autoboot",
    280   3247  gjelinek 	"clear pool",
    281   3247  gjelinek 	"clear limitpriv",
    282   3247  gjelinek 	"clear bootargs",
    283   3247  gjelinek 	"clear scheduling-class",
    284   3448  dh155122 	"clear ip-type",
    285   3247  gjelinek 	"clear " ALIAS_MAXLWPS,
    286   3247  gjelinek 	"clear " ALIAS_MAXSHMMEM,
    287   3247  gjelinek 	"clear " ALIAS_MAXSHMIDS,
    288   3247  gjelinek 	"clear " ALIAS_MAXMSGIDS,
    289   3247  gjelinek 	"clear " ALIAS_MAXSEMIDS,
    290   3247  gjelinek 	"clear " ALIAS_SHARES,
    291      0    stevel 	NULL
    292      0    stevel };
    293      0    stevel 
    294   2607        dp static const char *remove_cmds[] = {
    295   2607        dp 	"remove fs ",
    296   2607        dp 	"remove inherit-pkg-dir ",
    297   2607        dp 	"remove net ",
    298   2607        dp 	"remove device ",
    299   2607        dp 	"remove rctl ",
    300   2607        dp 	"remove attr ",
    301   2607        dp 	"remove dataset ",
    302   3247  gjelinek 	"remove dedicated-cpu ",
    303   3792     akolb 	"remove capped-cpu ",
    304   3247  gjelinek 	"remove capped-memory ",
    305   2607        dp 	NULL
    306   2607        dp };
    307   2607        dp 
    308      0    stevel static const char *select_cmds[] = {
    309    565        dp 	"select fs ",
    310    565        dp 	"select inherit-pkg-dir ",
    311    565        dp 	"select net ",
    312    565        dp 	"select device ",
    313    565        dp 	"select rctl ",
    314    565        dp 	"select attr ",
    315    789    ahrens 	"select dataset ",
    316   3247  gjelinek 	"select dedicated-cpu",
    317   3792     akolb 	"select capped-cpu",
    318   3247  gjelinek 	"select capped-memory",
    319      0    stevel 	NULL
    320      0    stevel };
    321      0    stevel 
    322      0    stevel static const char *set_cmds[] = {
    323    565        dp 	"set zonename=",
    324    565        dp 	"set zonepath=",
    325   2712   nn35248 	"set brand=",
    326    565        dp 	"set autoboot=",
    327    565        dp 	"set pool=",
    328   1645     comay 	"set limitpriv=",
    329   2267        dp 	"set bootargs=",
    330   3247  gjelinek 	"set scheduling-class=",
    331   3448  dh155122 	"set ip-type=",
    332   3247  gjelinek 	"set " ALIAS_MAXLWPS "=",
    333   3247  gjelinek 	"set " ALIAS_MAXSHMMEM "=",
    334   3247  gjelinek 	"set " ALIAS_MAXSHMIDS "=",
    335   3247  gjelinek 	"set " ALIAS_MAXMSGIDS "=",
    336   3247  gjelinek 	"set " ALIAS_MAXSEMIDS "=",
    337   3247  gjelinek 	"set " ALIAS_SHARES "=",
    338   8662    Jordan 	"set hostid=",
    339      0    stevel 	NULL
    340      0    stevel };
    341      0    stevel 
    342   2607        dp static const char *info_cmds[] = {
    343   2607        dp 	"info fs ",
    344   2607        dp 	"info inherit-pkg-dir ",
    345   2607        dp 	"info net ",
    346   2607        dp 	"info device ",
    347   2607        dp 	"info rctl ",
    348   2607        dp 	"info attr ",
    349   2607        dp 	"info dataset ",
    350   3247  gjelinek 	"info capped-memory",
    351   3247  gjelinek 	"info dedicated-cpu",
    352   3792     akolb 	"info capped-cpu",
    353   2607        dp 	"info zonename",
    354   2607        dp 	"info zonepath",
    355   2607        dp 	"info autoboot",
    356   2607        dp 	"info pool",
    357   2607        dp 	"info limitpriv",
    358   2607        dp 	"info bootargs",
    359   3247  gjelinek 	"info brand",
    360   3247  gjelinek 	"info scheduling-class",
    361   3448  dh155122 	"info ip-type",
    362   3247  gjelinek 	"info max-lwps",
    363   3247  gjelinek 	"info max-shm-memory",
    364   3247  gjelinek 	"info max-shm-ids",
    365   3247  gjelinek 	"info max-msg-ids",
    366   3247  gjelinek 	"info max-sem-ids",
    367   3247  gjelinek 	"info cpu-shares",
    368   8662    Jordan 	"info hostid",
    369   2607        dp 	NULL
    370   2607        dp };
    371   2607        dp 
    372      0    stevel static const char *fs_res_scope_cmds[] = {
    373      0    stevel 	"add options ",
    374      0    stevel 	"cancel",
    375      0    stevel 	"end",
    376      0    stevel 	"exit",
    377      0    stevel 	"help",
    378      0    stevel 	"info",
    379   1645     comay 	"remove options ",
    380      0    stevel 	"set dir=",
    381      0    stevel 	"set raw=",
    382      0    stevel 	"set special=",
    383      0    stevel 	"set type=",
    384   3247  gjelinek 	"clear raw",
    385      0    stevel 	NULL
    386      0    stevel };
    387      0    stevel 
    388      0    stevel static const char *net_res_scope_cmds[] = {
    389      0    stevel 	"cancel",
    390      0    stevel 	"end",
    391      0    stevel 	"exit",
    392      0    stevel 	"help",
    393      0    stevel 	"info",
    394      0    stevel 	"set address=",
    395      0    stevel 	"set physical=",
    396      0    stevel 	NULL
    397      0    stevel };
    398      0    stevel 
    399      0    stevel static const char *ipd_res_scope_cmds[] = {
    400      0    stevel 	"cancel",
    401      0    stevel 	"end",
    402      0    stevel 	"exit",
    403      0    stevel 	"help",
    404      0    stevel 	"info",
    405      0    stevel 	"set dir=",
    406      0    stevel 	NULL
    407      0    stevel };
    408      0    stevel 
    409      0    stevel static const char *device_res_scope_cmds[] = {
    410      0    stevel 	"cancel",
    411      0    stevel 	"end",
    412      0    stevel 	"exit",
    413      0    stevel 	"help",
    414      0    stevel 	"info",
    415      0    stevel 	"set match=",
    416      0    stevel 	NULL
    417      0    stevel };
    418      0    stevel 
    419      0    stevel static const char *attr_res_scope_cmds[] = {
    420      0    stevel 	"cancel",
    421      0    stevel 	"end",
    422      0    stevel 	"exit",
    423      0    stevel 	"help",
    424      0    stevel 	"info",
    425      0    stevel 	"set name=",
    426      0    stevel 	"set type=",
    427      0    stevel 	"set value=",
    428      0    stevel 	NULL
    429      0    stevel };
    430      0    stevel 
    431      0    stevel static const char *rctl_res_scope_cmds[] = {
    432      0    stevel 	"add value ",
    433    789    ahrens 	"cancel",
    434    789    ahrens 	"end",
    435    789    ahrens 	"exit",
    436    789    ahrens 	"help",
    437    789    ahrens 	"info",
    438   1645     comay 	"remove value ",
    439    789    ahrens 	"set name=",
    440    789    ahrens 	NULL
    441    789    ahrens };
    442    789    ahrens 
    443    789    ahrens static const char *dataset_res_scope_cmds[] = {
    444      0    stevel 	"cancel",
    445      0    stevel 	"end",
    446      0    stevel 	"exit",
    447      0    stevel 	"help",
    448      0    stevel 	"info",
    449      0    stevel 	"set name=",
    450      0    stevel 	NULL
    451      0    stevel };
    452      0    stevel 
    453   3247  gjelinek static const char *pset_res_scope_cmds[] = {
    454   3247  gjelinek 	"cancel",
    455   3247  gjelinek 	"end",
    456   3247  gjelinek 	"exit",
    457   3247  gjelinek 	"help",
    458   3247  gjelinek 	"info",
    459   3247  gjelinek 	"set ncpus=",
    460   3247  gjelinek 	"set importance=",
    461   3247  gjelinek 	"clear importance",
    462   3247  gjelinek 	NULL
    463   3247  gjelinek };
    464   3247  gjelinek 
    465   3792     akolb static const char *pcap_res_scope_cmds[] = {
    466   3792     akolb 	"cancel",
    467   3792     akolb 	"end",
    468   3792     akolb 	"exit",
    469   3792     akolb 	"help",
    470   3792     akolb 	"info",
    471   3792     akolb 	"set ncpus=",
    472   3792     akolb 	NULL
    473   3792     akolb };
    474   3792     akolb 
    475   3247  gjelinek static const char *mcap_res_scope_cmds[] = {
    476   3247  gjelinek 	"cancel",
    477   3247  gjelinek 	"end",
    478   3247  gjelinek 	"exit",
    479   3247  gjelinek 	"help",
    480   3247  gjelinek 	"info",
    481   3247  gjelinek 	"set physical=",
    482   3247  gjelinek 	"set swap=",
    483   3247  gjelinek 	"set locked=",
    484   3247  gjelinek 	"clear physical",
    485   3247  gjelinek 	"clear swap",
    486   3247  gjelinek 	"clear locked",
    487   3247  gjelinek 	NULL
    488   3247  gjelinek };
    489   3247  gjelinek 
    490      0    stevel /* Global variables */
    491      0    stevel 
    492      0    stevel /* set early in main(), never modified thereafter, used all over the place */
    493      0    stevel static char *execname;
    494      0    stevel 
    495      0    stevel /* set in main(), used all over the place */
    496      0    stevel static zone_dochandle_t handle;
    497      0    stevel 
    498      0    stevel /* used all over the place */
    499    565        dp static char zone[ZONENAME_MAX];
    500    565        dp static char revert_zone[ZONENAME_MAX];
    501   2712   nn35248 
    502   2712   nn35248 /* global brand operations */
    503   2727       edp static brand_handle_t brand;
    504      0    stevel 
    505      0    stevel /* set in modifying functions, checked in read_input() */
    506   6215  gjelinek static boolean_t need_to_commit = B_FALSE;
    507   6215  gjelinek boolean_t saw_error;
    508      0    stevel 
    509      0    stevel /* set in yacc parser, checked in read_input() */
    510   6215  gjelinek boolean_t newline_terminated;
    511      0    stevel 
    512      0    stevel /* set in main(), checked in lex error handler */
    513   6215  gjelinek boolean_t cmd_file_mode;
    514      0    stevel 
    515      0    stevel /* set in exit_func(), checked in read_input() */
    516   6215  gjelinek static boolean_t time_to_exit = B_FALSE, force_exit = B_FALSE;
    517      0    stevel 
    518      0    stevel /* used in short_usage() and zerr() */
    519      0    stevel static char *cmd_file_name = NULL;
    520      0    stevel 
    521      0    stevel /* checked in read_input() and other places */
    522   6215  gjelinek static boolean_t ok_to_prompt = B_FALSE;
    523      0    stevel 
    524      0    stevel /* set and checked in initialize() */
    525   6215  gjelinek static boolean_t got_handle = B_FALSE;
    526      0    stevel 
    527      0    stevel /* initialized in do_interactive(), checked in initialize() */
    528   6215  gjelinek static boolean_t interactive_mode;
    529   3247  gjelinek 
    530   3247  gjelinek /* set if configuring the global zone */
    531   6215  gjelinek static boolean_t global_zone = B_FALSE;
    532      0    stevel 
    533      0    stevel /* set in main(), checked in multiple places */
    534   6215  gjelinek static boolean_t read_only_mode;
    535   6215  gjelinek 
    536   6215  gjelinek /* scope is outer/global or inner/resource */
    537   6215  gjelinek static boolean_t global_scope = B_TRUE;
    538      0    stevel static int resource_scope;	/* should be in the RT_ list from zonecfg.h */
    539      0    stevel static int end_op = -1;		/* operation on end is either add or modify */
    540      0    stevel 
    541      0    stevel int num_prop_vals;		/* for grammar */
    542      0    stevel 
    543      0    stevel /*
    544      0    stevel  * These are for keeping track of resources as they are specified as part of
    545      0    stevel  * the multi-step process.  They should be initialized by add_resource() or
    546      0    stevel  * select_func() and filled in by add_property() or set_func().
    547      0    stevel  */
    548      0    stevel static struct zone_fstab	old_fstab, in_progress_fstab;
    549      0    stevel static struct zone_fstab	old_ipdtab, in_progress_ipdtab;
    550      0    stevel static struct zone_nwiftab	old_nwiftab, in_progress_nwiftab;
    551      0    stevel static struct zone_devtab	old_devtab, in_progress_devtab;
    552      0    stevel static struct zone_rctltab	old_rctltab, in_progress_rctltab;
    553      0    stevel static struct zone_attrtab	old_attrtab, in_progress_attrtab;
    554    789    ahrens static struct zone_dstab	old_dstab, in_progress_dstab;
    555   3247  gjelinek static struct zone_psettab	old_psettab, in_progress_psettab;
    556   3247  gjelinek static struct zone_mcaptab	old_mcaptab, in_progress_mcaptab;
    557      0    stevel 
    558      0    stevel static GetLine *gl;	/* The gl_get_line() resource object */
    559   3247  gjelinek 
    560   3247  gjelinek static void bytes_to_units(char *str, char *buf, int bufsize);
    561      0    stevel 
    562      0    stevel /* Functions begin here */
    563      0    stevel 
    564   6215  gjelinek static boolean_t
    565      0    stevel initial_match(const char *line1, const char *line2, int word_end)
    566      0    stevel {
    567      0    stevel 	if (word_end <= 0)
    568   6215  gjelinek 		return (B_TRUE);
    569      0    stevel 	return (strncmp(line1, line2, word_end) == 0);
    570      0    stevel }
    571      0    stevel 
    572      0    stevel static int
    573      0    stevel add_stuff(WordCompletion *cpl, const char *line1, const char **list,
    574      0    stevel     int word_end)
    575      0    stevel {
    576      0    stevel 	int i, err;
    577      0    stevel 
    578      0    stevel 	for (i = 0; list[i] != NULL; i++) {
    579      0    stevel 		if (initial_match(line1, list[i], word_end)) {
    580      0    stevel 			err = cpl_add_completion(cpl, line1, 0, word_end,
    581      0    stevel 			    list[i] + word_end, "", "");
    582      0    stevel 			if (err != 0)
    583      0    stevel 				return (err);
    584      0    stevel 		}
    585      0    stevel 	}
    586      0    stevel 	return (0);
    587      0    stevel }
    588      0    stevel 
    589      0    stevel static
    590      0    stevel /* ARGSUSED */
    591      0    stevel CPL_MATCH_FN(cmd_cpl_fn)
    592      0    stevel {
    593      0    stevel 	if (global_scope) {
    594      0    stevel 		/*
    595      0    stevel 		 * The MAX/MIN tests below are to make sure we have at least
    596      0    stevel 		 * enough characters to distinguish from other prefixes (MAX)
    597      0    stevel 		 * but only check MIN(what we have, what we're checking).
    598      0    stevel 		 */
    599      0    stevel 		if (strncmp(line, "add ", MAX(MIN(word_end, 4), 1)) == 0)
    600      0    stevel 			return (add_stuff(cpl, line, add_cmds, word_end));
    601   3247  gjelinek 		if (strncmp(line, "clear ", MAX(MIN(word_end, 6), 2)) == 0)
    602   3247  gjelinek 			return (add_stuff(cpl, line, clear_cmds, word_end));
    603      0    stevel 		if (strncmp(line, "select ", MAX(MIN(word_end, 7), 3)) == 0)
    604      0    stevel 			return (add_stuff(cpl, line, select_cmds, word_end));
    605      0    stevel 		if (strncmp(line, "set ", MAX(MIN(word_end, 4), 3)) == 0)
    606      0    stevel 			return (add_stuff(cpl, line, set_cmds, word_end));
    607   2607        dp 		if (strncmp(line, "remove ", MAX(MIN(word_end, 7), 1)) == 0)
    608   2607        dp 			return (add_stuff(cpl, line, remove_cmds, word_end));
    609   2607        dp 		if (strncmp(line, "info ", MAX(MIN(word_end, 5), 1)) == 0)
    610   2607        dp 			return (add_stuff(cpl, line, info_cmds, word_end));
    611      0    stevel 		return (add_stuff(cpl, line, global_scope_cmds, word_end));
    612      0    stevel 	}
    613      0    stevel 	switch (resource_scope) {
    614      0    stevel 	case RT_FS:
    615      0    stevel 		return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
    616      0    stevel 	case RT_IPD:
    617      0    stevel 		return (add_stuff(cpl, line, ipd_res_scope_cmds, word_end));
    618      0    stevel 	case RT_NET:
    619      0    stevel 		return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
    620      0    stevel 	case RT_DEVICE:
    621      0    stevel 		return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
    622      0    stevel 	case RT_RCTL:
    623      0    stevel 		return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
    624      0    stevel 	case RT_ATTR:
    625      0    stevel 		return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
    626    789    ahrens 	case RT_DATASET:
    627    789    ahrens 		return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
    628   3247  gjelinek 	case RT_DCPU:
    629   3247  gjelinek 		return (add_stuff(cpl, line, pset_res_scope_cmds, word_end));
    630   3792     akolb 	case RT_PCAP:
    631   3792     akolb 		return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
    632   3247  gjelinek 	case RT_MCAP:
    633   3247  gjelinek 		return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
    634      0    stevel 	}
    635      0    stevel 	return (0);
    636      0    stevel }
    637      0    stevel 
    638      0    stevel /*
    639      0    stevel  * For the main CMD_func() functions below, several of them call getopt()
    640      0    stevel  * then check optind against argc to make sure an extra parameter was not
    641      0    stevel  * passed in.  The reason this is not caught in the grammar is that the
    642      0    stevel  * grammar just checks for a miscellaneous TOKEN, which is *expected* to
    643      0    stevel  * be "-F" (for example), but could be anything.  So (for example) this
    644      0    stevel  * check will prevent "create bogus".
    645      0    stevel  */
    646      0    stevel 
    647      0    stevel cmd_t *
    648      0    stevel alloc_cmd(void)
    649      0    stevel {
    650      0    stevel 	return (calloc(1, sizeof (cmd_t)));
    651      0    stevel }
    652      0    stevel 
    653      0    stevel void
    654      0    stevel free_cmd(cmd_t *cmd)
    655      0    stevel {
    656      0    stevel 	int i;
    657      0    stevel 
    658      0    stevel 	for (i = 0; i < MAX_EQ_PROP_PAIRS; i++)
    659      0    stevel 		if (cmd->cmd_property_ptr[i] != NULL) {
    660      0    stevel 			property_value_ptr_t pp = cmd->cmd_property_ptr[i];
    661      0    stevel 
    662      0    stevel 			switch (pp->pv_type) {
    663      0    stevel 			case PROP_VAL_SIMPLE:
    664      0    stevel 				free(pp->pv_simple);
    665      0    stevel 				break;
    666      0    stevel 			case PROP_VAL_COMPLEX:
    667      0    stevel 				free_complex(pp->pv_complex);
    668      0    stevel 				break;
    669      0    stevel 			case PROP_VAL_LIST:
    670      0    stevel 				free_list(pp->pv_list);
    671      0    stevel 				break;
    672      0    stevel 			}
    673      0    stevel 		}
    674      0    stevel 	for (i = 0; i < cmd->cmd_argc; i++)
    675      0    stevel 		free(cmd->cmd_argv[i]);
    676      0    stevel 	free(cmd);
    677      0    stevel }
    678      0    stevel 
    679      0    stevel complex_property_ptr_t
    680      0    stevel alloc_complex(void)
    681      0    stevel {
    682      0    stevel 	return (calloc(1, sizeof (complex_property_t)));
    683      0    stevel }
    684      0    stevel 
    685      0    stevel void
    686      0    stevel free_complex(complex_property_ptr_t complex)
    687      0    stevel {
    688      0    stevel 	if (complex == NULL)
    689      0    stevel 		return;
    690      0    stevel 	free_complex(complex->cp_next);
    691      0    stevel 	if (complex->cp_value != NULL)
    692      0    stevel 		free(complex->cp_value);
    693      0    stevel 	free(complex);
    694      0    stevel }
    695      0    stevel 
    696      0    stevel list_property_ptr_t
    697      0    stevel alloc_list(void)
    698      0    stevel {
    699      0    stevel 	return (calloc(1, sizeof (list_property_t)));
    700      0    stevel }
    701      0    stevel 
    702      0    stevel void
    703      0    stevel free_list(list_property_ptr_t list)
    704      0    stevel {
    705      0    stevel 	if (list == NULL)
    706      0    stevel 		return;
    707      0    stevel 	if (list->lp_simple != NULL)
    708      0    stevel 		free(list->lp_simple);
    709      0    stevel 	free_complex(list->lp_complex);
    710      0    stevel 	free_list(list->lp_next);
    711      0    stevel 	free(list);
    712      0    stevel }
    713      0    stevel 
    714      0    stevel void
    715      0    stevel free_outer_list(list_property_ptr_t list)
    716      0    stevel {
    717      0    stevel 	if (list == NULL)
    718      0    stevel 		return;
    719      0    stevel 	free_outer_list(list->lp_next);
    720      0    stevel 	free(list);
    721      0    stevel }
    722      0    stevel 
    723      0    stevel static struct zone_rctlvaltab *
    724      0    stevel alloc_rctlvaltab(void)
    725      0    stevel {
    726      0    stevel 	return (calloc(1, sizeof (struct zone_rctlvaltab)));
    727      0    stevel }
    728      0    stevel 
    729      0    stevel static char *
    730      0    stevel rt_to_str(int res_type)
    731      0    stevel {
    732      0    stevel 	assert(res_type >= RT_MIN && res_type <= RT_MAX);
    733      0    stevel 	return (res_types[res_type]);
    734      0    stevel }
    735      0    stevel 
    736      0    stevel static char *
    737      0    stevel pt_to_str(int prop_type)
    738      0    stevel {
    739      0    stevel 	assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
    740      0    stevel 	return (prop_types[prop_type]);
    741      0    stevel }
    742      0    stevel 
    743      0    stevel static char *
    744      0    stevel pvt_to_str(int pv_type)
    745      0    stevel {
    746      0    stevel 	assert(pv_type >= PROP_VAL_MIN && pv_type <= PROP_VAL_MAX);
    747      0    stevel 	return (prop_val_types[pv_type]);
    748      0    stevel }
    749      0    stevel 
    750      0    stevel static char *
    751      0    stevel cmd_to_str(int cmd_num)
    752      0    stevel {
    753      0    stevel 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
    754      0    stevel 	return (helptab[cmd_num].cmd_name);
    755      0    stevel }
    756      0    stevel 
    757      0    stevel /*
    758      0    stevel  * This is a separate function rather than a set of define's because of the
    759      0    stevel  * gettext() wrapping.
    760      0    stevel  */
    761      0    stevel 
    762      0    stevel /*
    763      0    stevel  * TRANSLATION_NOTE
    764      0    stevel  * Each string below should have \t follow \n whenever needed; the
    765      0    stevel  * initial \t and the terminal \n will be provided by the calling function.
    766      0    stevel  */
    767      0    stevel 
    768      0    stevel static char *
    769      0    stevel long_help(int cmd_num)
    770      0    stevel {
    771      0    stevel 	static char line[1024];	/* arbitrary large amount */
    772      0    stevel 
    773      0    stevel 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
    774      0    stevel 	switch (cmd_num) {
    775      0    stevel 		case CMD_HELP:
    776      0    stevel 			return (gettext("Prints help message."));
    777      0    stevel 		case CMD_CREATE:
    778      0    stevel 			(void) snprintf(line, sizeof (line),
    779      0    stevel 			    gettext("Creates a configuration for the "
    780      0    stevel 			    "specified zone.  %s should be\n\tused to "
    781      0    stevel 			    "begin configuring a new zone.  If overwriting an "
    782      0    stevel 			    "existing\n\tconfiguration, the -F flag can be "
    783      0    stevel 			    "used to force the action.  If\n\t-t template is "
    784      0    stevel 			    "given, creates a configuration identical to the\n"
    785      0    stevel 			    "\tspecified template, except that the zone name "
    786   1634  gjelinek 			    "is changed from\n\ttemplate to zonename.  '%s -a' "
    787   1634  gjelinek 			    "creates a configuration from a\n\tdetached "
    788   1634  gjelinek 			    "zonepath.  '%s -b' results in a blank "
    789   1634  gjelinek 			    "configuration.\n\t'%s' with no arguments applies "
    790   1634  gjelinek 			    "the Sun default settings."),
    791      0    stevel 			    cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE),
    792   1634  gjelinek 			    cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE));
    793      0    stevel 			return (line);
    794      0    stevel 		case CMD_EXIT:
    795      0    stevel 			return (gettext("Exits the program.  The -F flag can "
    796      0    stevel 			    "be used to force the action."));
    797      0    stevel 		case CMD_EXPORT:
    798      0    stevel 			return (gettext("Prints configuration to standard "
    799      0    stevel 			    "output, or to output-file if\n\tspecified, in "
    800      0    stevel 			    "a form suitable for use in a command-file."));
    801      0    stevel 		case CMD_ADD:
    802      0    stevel 			return (gettext("Add specified resource to "
    803      0    stevel 			    "configuration."));
    804      0    stevel 		case CMD_DELETE:
    805      0    stevel 			return (gettext("Deletes the specified zone.  The -F "
    806      0    stevel 			    "flag can be used to force the\n\taction."));
    807      0    stevel 		case CMD_REMOVE:
    808      0    stevel 			return (gettext("Remove specified resource from "
    809   3247  gjelinek 			    "configuration.  The -F flag can be used\n\tto "
    810   3247  gjelinek 			    "force the action."));
    811      0    stevel 		case CMD_SELECT:
    812      0    stevel 			(void) snprintf(line, sizeof (line),
    813      0    stevel 			    gettext("Selects a resource to modify.  "
    814      0    stevel 			    "Resource modification is completed\n\twith the "
    815      0    stevel 			    "command \"%s\".  The property name/value pairs "
    816      0    stevel 			    "must uniquely\n\tidentify a resource.  Note that "
    817      0    stevel 			    "the curly braces ('{', '}') mean one\n\tor more "
    818      0    stevel 			    "of whatever is between them."),
    819      0    stevel 			    cmd_to_str(CMD_END));
    820      0    stevel 			return (line);
    821      0    stevel 		case CMD_SET:
    822      0    stevel 			return (gettext("Sets property values."));
    823   3247  gjelinek 		case CMD_CLEAR:
    824   3247  gjelinek 			return (gettext("Clears property values."));
    825      0    stevel 		case CMD_INFO:
    826      0    stevel 			return (gettext("Displays information about the "
    827      0    stevel 			    "current configuration.  If resource\n\ttype is "
    828      0    stevel 			    "specified, displays only information about "
    829      0    stevel 			    "resources of\n\tthe relevant type.  If resource "
    830      0    stevel 			    "id is specified, displays only\n\tinformation "
    831      0    stevel 			    "about that resource."));
    832      0    stevel 		case CMD_VERIFY:
    833      0    stevel 			return (gettext("Verifies current configuration "
    834      0    stevel 			    "for correctness (some resource types\n\thave "
    835      0    stevel 			    "required properties)."));
    836      0    stevel 		case CMD_COMMIT:
    837      0    stevel 			(void) snprintf(line, sizeof (line),
    838      0    stevel 			    gettext("Commits current configuration.  "
    839      0    stevel 			    "Configuration must be committed to\n\tbe used by "
    840      0    stevel 			    "%s.  Until the configuration is committed, "
    841      0    stevel 			    "changes \n\tcan be removed with the %s "
    842      0    stevel 			    "command.  This operation is\n\tattempted "
    843      0    stevel 			    "automatically upon completion of a %s "
    844      0    stevel 			    "session."), "zoneadm", cmd_to_str(CMD_REVERT),
    845      0    stevel 			    "zonecfg");
    846      0    stevel 			return (line);
    847      0    stevel 		case CMD_REVERT:
    848      0    stevel 			return (gettext("Reverts configuration back to the "
    849      0    stevel 			    "last committed state.  The -F flag\n\tcan be "
    850      0    stevel 			    "used to force the action."));
    851      0    stevel 		case CMD_CANCEL:
    852      0    stevel 			return (gettext("Cancels resource/property "
    853      0    stevel 			    "specification."));
    854      0    stevel 		case CMD_END:
    855      0    stevel 			return (gettext("Ends resource/property "
    856      0    stevel 			    "specification."));
    857      0    stevel 	}
    858      0    stevel 	/* NOTREACHED */
    859    222     comay 	return (NULL);
    860      0    stevel }
    861      0    stevel 
    862      0    stevel /*
    863      0    stevel  * Called with verbose TRUE when help is explicitly requested, FALSE for
    864      0    stevel  * unexpected errors.
    865      0    stevel  */
    866      0    stevel 
    867      0    stevel void
    868   6215  gjelinek usage(boolean_t verbose, uint_t flags)
    869      0    stevel {
    870      0    stevel 	FILE *fp = verbose ? stdout : stderr, *newfp;
    871   6215  gjelinek 	boolean_t need_to_close = B_FALSE;
    872      0    stevel 	char *pager;
    873      0    stevel 	int i;
    874      0    stevel 
    875      0    stevel 	/* don't page error output */
    876      0    stevel 	if (verbose && interactive_mode) {
    877      0    stevel 		if ((pager = getenv("PAGER")) == NULL)
    878      0    stevel 			pager = PAGER;
    879      0    stevel 		if ((newfp = popen(pager, "w")) != NULL) {
    880   6215  gjelinek 			need_to_close = B_TRUE;
    881      0    stevel 			fp = newfp;
    882      0    stevel 		}
    883      0    stevel 	}
    884      0    stevel 	if (flags & HELP_META) {
    885      0    stevel 		(void) fprintf(fp, gettext("More help is available for the "
    886      0    stevel 		    "following:\n"));
    887      0    stevel 		(void) fprintf(fp, "\n\tcommands ('%s commands')\n",
    888      0    stevel 		    cmd_to_str(CMD_HELP));
    889      0    stevel 		(void) fprintf(fp, "\tsyntax ('%s syntax')\n",
    890      0    stevel 		    cmd_to_str(CMD_HELP));
    891      0    stevel 		(void) fprintf(fp, "\tusage ('%s usage')\n\n",
    892      0    stevel 		    cmd_to_str(CMD_HELP));
    893      0    stevel 		(void) fprintf(fp, gettext("You may also obtain help on any "
    894      0    stevel 		    "command by typing '%s <command-name>.'\n"),
    895      0    stevel 		    cmd_to_str(CMD_HELP));
    896      0    stevel 	}
    897      0    stevel 	if (flags & HELP_RES_SCOPE) {
    898      0    stevel 		switch (resource_scope) {
    899      0    stevel 		case RT_FS:
    900      0    stevel 			(void) fprintf(fp, gettext("The '%s' resource scope is "
    901      0    stevel 			    "used to configure a file-system.\n"),
    902      0    stevel 			    rt_to_str(resource_scope));
    903      0    stevel 			(void) fprintf(fp, gettext("Valid commands:\n"));
    904      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    905      0    stevel 			    pt_to_str(PT_DIR), gettext("<path>"));
    906      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    907      0    stevel 			    pt_to_str(PT_SPECIAL), gettext("<path>"));
    908      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    909      0    stevel 			    pt_to_str(PT_RAW), gettext("<raw-device>"));
    910      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    911      0    stevel 			    pt_to_str(PT_TYPE), gettext("<file-system type>"));
    912      0    stevel 			(void) fprintf(fp, "\t%s %s %s\n", cmd_to_str(CMD_ADD),
    913      0    stevel 			    pt_to_str(PT_OPTIONS),
    914      0    stevel 			    gettext("<file-system options>"));
    915   1645     comay 			(void) fprintf(fp, "\t%s %s %s\n",
    916   1645     comay 			    cmd_to_str(CMD_REMOVE), pt_to_str(PT_OPTIONS),
    917   1645     comay 			    gettext("<file-system options>"));
    918      0    stevel 			(void) fprintf(fp, gettext("Consult the file-system "
    919      0    stevel 			    "specific manual page, such as mount_ufs(1M), "
    920      0    stevel 			    "for\ndetails about file-system options.  Note "
    921      0    stevel 			    "that any file-system options with an\nembedded "
    922      0    stevel 			    "'=' character must be enclosed in double quotes, "
    923      0    stevel 			    /*CSTYLED*/
    924      0    stevel 			    "such as \"%s=5\".\n"), MNTOPT_RETRY);
    925      0    stevel 			break;
    926      0    stevel 		case RT_IPD:
    927      0    stevel 			(void) fprintf(fp, gettext("The '%s' resource scope is "
    928      0    stevel 			    "used to configure a directory\ninherited from the "
    929      0    stevel 			    "global zone into a non-global zone in read-only "
    930      0    stevel 			    "mode.\n"), rt_to_str(resource_scope));
    931      0    stevel 			(void) fprintf(fp, gettext("Valid commands:\n"));
    932      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    933      0    stevel 			    pt_to_str(PT_DIR), gettext("<path>"));
    934      0    stevel 			break;
    935      0    stevel 		case RT_NET:
    936      0    stevel 			(void) fprintf(fp, gettext("The '%s' resource scope is "
    937      0    stevel 			    "used to configure a network interface.\n"),
    938      0    stevel 			    rt_to_str(resource_scope));
    939      0    stevel 			(void) fprintf(fp, gettext("Valid commands:\n"));
    940      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    941      0    stevel 			    pt_to_str(PT_ADDRESS), gettext("<IP-address>"));
    942      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    943      0    stevel 			    pt_to_str(PT_PHYSICAL), gettext("<interface>"));
    944      0    stevel 			(void) fprintf(fp, gettext("See ifconfig(1M) for "
    945      0    stevel 			    "details of the <interface> string.\n"));
    946   6076    gfaden 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    947   6076    gfaden 			    pt_to_str(PT_DEFROUTER), gettext("<IP-address>"));
    948   6076    gfaden 			(void) fprintf(fp, gettext("%s %s and %s %s are valid "
    949   6076    gfaden 			    "if the %s property is set to %s, otherwise they "
    950   6076    gfaden 			    "must not be set.\n"),
    951   3448  dh155122 			    cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS),
    952   6076    gfaden 			    cmd_to_str(CMD_SET), pt_to_str(PT_DEFROUTER),
    953   3448  dh155122 			    pt_to_str(PT_IPTYPE), "shared");
    954      0    stevel 			break;
    955      0    stevel 		case RT_DEVICE:
    956      0    stevel 			(void) fprintf(fp, gettext("The '%s' resource scope is "
    957      0    stevel 			    "used to configure a device node.\n"),
    958      0    stevel 			    rt_to_str(resource_scope));
    959      0    stevel 			(void) fprintf(fp, gettext("Valid commands:\n"));
    960      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    961      0    stevel 			    pt_to_str(PT_MATCH), gettext("<device-path>"));
    962      0    stevel 			break;
    963      0    stevel 		case RT_RCTL:
    964      0    stevel 			(void) fprintf(fp, gettext("The '%s' resource scope is "
    965      0    stevel 			    "used to configure a resource control.\n"),
    966      0    stevel 			    rt_to_str(resource_scope));
    967      0    stevel 			(void) fprintf(fp, gettext("Valid commands:\n"));
    968      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    969      0    stevel 			    pt_to_str(PT_NAME), gettext("<string>"));
    970      0    stevel 			(void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
    971      0    stevel 			    cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
    972   1645     comay 			    pt_to_str(PT_PRIV), gettext("<priv-value>"),
    973   1645     comay 			    pt_to_str(PT_LIMIT), gettext("<number>"),
    974   1645     comay 			    pt_to_str(PT_ACTION), gettext("<action-value>"));
    975   1645     comay 			(void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
    976   1645     comay 			    cmd_to_str(CMD_REMOVE), pt_to_str(PT_VALUE),
    977      0    stevel 			    pt_to_str(PT_PRIV), gettext("<priv-value>"),
    978      0    stevel 			    pt_to_str(PT_LIMIT), gettext("<number>"),
    979      0    stevel 			    pt_to_str(PT_ACTION), gettext("<action-value>"));
    980      0    stevel 			(void) fprintf(fp, "%s\n\t%s := privileged\n"
    981      0    stevel 			    "\t%s := none | deny\n", gettext("Where"),
    982      0    stevel 			    gettext("<priv-value>"), gettext("<action-value>"));
    983      0    stevel 			break;
    984      0    stevel 		case RT_ATTR:
    985      0    stevel 			(void) fprintf(fp, gettext("The '%s' resource scope is "
    986      0    stevel 			    "used to configure a generic attribute.\n"),
    987      0    stevel 			    rt_to_str(resource_scope));
    988      0    stevel 			(void) fprintf(fp, gettext("Valid commands:\n"));
    989      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    990      0    stevel 			    pt_to_str(PT_NAME), gettext("<name>"));
    991      0    stevel 			(void) fprintf(fp, "\t%s %s=boolean\n",
    992      0    stevel 			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
    993      0    stevel 			(void) fprintf(fp, "\t%s %s=true | false\n",
    994      0    stevel 			    cmd_to_str(CMD_SET), pt_to_str(PT_VALUE));
    995      0    stevel 			(void) fprintf(fp, gettext("or\n"));
    996      0    stevel 			(void) fprintf(fp, "\t%s %s=int\n", cmd_to_str(CMD_SET),
    997      0    stevel 			    pt_to_str(PT_TYPE));
    998      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
    999      0    stevel 			    pt_to_str(PT_VALUE), gettext("<integer>"));
   1000      0    stevel 			(void) fprintf(fp, gettext("or\n"));
   1001      0    stevel 			(void) fprintf(fp, "\t%s %s=string\n",
   1002      0    stevel 			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
   1003      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
   1004      0    stevel 			    pt_to_str(PT_VALUE), gettext("<string>"));
   1005      0    stevel 			(void) fprintf(fp, gettext("or\n"));
   1006      0    stevel 			(void) fprintf(fp, "\t%s %s=uint\n",
   1007      0    stevel 			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
   1008      0    stevel 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
   1009      0    stevel 			    pt_to_str(PT_VALUE), gettext("<unsigned integer>"));
   1010      0    stevel 			break;
   1011    789    ahrens 		case RT_DATASET:
   1012    789    ahrens 			(void) fprintf(fp, gettext("The '%s' resource scope is "
   1013    789    ahrens 			    "used to export ZFS datasets.\n"),
   1014    789    ahrens 			    rt_to_str(resource_scope));
   1015    789    ahrens 			(void) fprintf(fp, gettext("Valid commands:\n"));
   1016    789    ahrens 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
   1017    789    ahrens 			    pt_to_str(PT_NAME), gettext("<name>"));
   1018    789    ahrens 			break;
   1019   3247  gjelinek 		case RT_DCPU:
   1020   3247  gjelinek 			(void) fprintf(fp, gettext("The '%s' resource scope "
   1021   3247  gjelinek 			    "configures the 'pools' facility to dedicate\na "
   1022   3247  gjelinek 			    "subset of the system's processors to this zone "
   1023   3247  gjelinek 			    "while it is running.\n"),
   1024   3247  gjelinek 			    rt_to_str(resource_scope));
   1025   3247  gjelinek 			(void) fprintf(fp, gettext("Valid commands:\n"));
   1026   3247  gjelinek 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
   1027   3247  gjelinek 			    pt_to_str(PT_NCPUS),
   1028   3247  gjelinek 			    gettext("<unsigned integer | range>"));
   1029   3247  gjelinek 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
   1030   3247  gjelinek 			    pt_to_str(PT_IMPORTANCE),
   1031   3247  gjelinek 			    gettext("<unsigned integer>"));
   1032   3247  gjelinek 			break;
   1033   3792     akolb 		case RT_PCAP:
   1034   3792     akolb 			(void) fprintf(fp, gettext("The '%s' resource scope is "
   1035   3792     akolb 			    "used to set an upper limit (a cap) on the\n"
   1036   3792     akolb 			    "percentage of CPU that can be used by this zone.  "
   1037   3792     akolb 			    "A '%s' value of 1\ncorresponds to one cpu.  The "
   1038   3792     akolb 			    "value can be set higher than 1, up to the total\n"
   1039   3792     akolb 			    "number of CPUs on the system.  The value can "
   1040   3792     akolb 			    "also be less than 1,\nrepresenting a fraction of "
   1041   3792     akolb 			    "a cpu.\n"),
   1042   3792     akolb 			    rt_to_str(resource_scope), pt_to_str(PT_NCPUS));
   1043   3792     akolb 			(void) fprintf(fp, gettext("Valid commands:\n"));
   1044   3792     akolb 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
   1045   3792     akolb 			    pt_to_str(PT_NCPUS), gettext("<unsigned decimal>"));
   1046   3792     akolb 			break;
   1047   3247  gjelinek 		case RT_MCAP:
   1048   3247  gjelinek 			(void) fprintf(fp, gettext("The '%s' resource scope is "
   1049   3247  gjelinek 			    "used to set an upper limit (a cap) on the\n"
   1050   3247  gjelinek 			    "amount of physical memory, swap space and locked "
   1051   3247  gjelinek 			    "memory that can be used by\nthis zone.\n"),
   1052   3247  gjelinek 			    rt_to_str(resource_scope));
   1053   3247  gjelinek 			(void) fprintf(fp, gettext("Valid commands:\n"));
   1054   3247  gjelinek 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
   1055   3247  gjelinek 			    pt_to_str(PT_PHYSICAL),
   1056   3247  gjelinek 			    gettext("<qualified unsigned decimal>"));
   1057   3247  gjelinek 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
   1058   3247  gjelinek 			    pt_to_str(PT_SWAP),
   1059   3247  gjelinek 			    gettext("<qualified unsigned decimal>"));
   1060   3247  gjelinek 			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
   1061   3247  gjelinek 			    pt_to_str(PT_LOCKED),
   1062   3247  gjelinek 			    gettext("<qualified unsigned decimal>"));
   1063   3247  gjelinek 			break;
   1064      0    stevel 		}
   1065      0    stevel 		(void) fprintf(fp, gettext("And from any resource scope, you "
   1066      0    stevel 		    "can:\n"));
   1067      0    stevel 		(void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
   1068      0    stevel 		    gettext("(to conclude this operation)"));
   1069      0    stevel 		(void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
   1070      0    stevel 		    gettext("(to cancel this operation)"));
   1071      0    stevel 		(void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
   1072      0    stevel 		    gettext("(to exit the zonecfg utility)"));
   1073      0    stevel 	}
   1074      0    stevel 	if (flags & HELP_USAGE) {
   1075      0    stevel 		(void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
   1076      0    stevel 		    execname, cmd_to_str(CMD_HELP));
   1077      0    stevel 		(void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
   1078      0    stevel 		    execname, gettext("interactive"));
   1079      0    stevel 		(void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
   1080      0    stevel 		(void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
   1081      0    stevel 		    execname);
   1082      0    stevel 	}
   1083      0    stevel 	if (flags & HELP_SUBCMDS) {
   1084      0    stevel 		(void) fprintf(fp, "%s:\n\n", gettext("Commands"));
   1085      0    stevel 		for (i = 0; i <= CMD_MAX; i++) {
   1086      0    stevel 			(void) fprintf(fp, "%s\n", helptab[i].short_usage);
   1087      0    stevel 			if (verbose)
   1088      0    stevel 				(void) fprintf(fp, "\t%s\n\n", long_help(i));
   1089      0    stevel 		}
   1090      0    stevel 	}
   1091      0    stevel 	if (flags & HELP_SYNTAX) {
   1092      0    stevel 		if (!verbose)
   1093      0    stevel 			(void) fprintf(fp, "\n");
   1094      0    stevel 		(void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
   1095      0    stevel 		(void) fprintf(fp, gettext("\t(except the reserved words "
   1096      0    stevel 		    "'%s' and anything starting with '%s')\n"), "global",
   1097      0    stevel 		    "SUNW");
   1098      0    stevel 		(void) fprintf(fp,
   1099      0    stevel 		    gettext("\tName must be less than %d characters.\n"),
   1100      0    stevel 		    ZONENAME_MAX);
   1101      0    stevel 		if (verbose)
   1102      0    stevel 			(void) fprintf(fp, "\n");
   1103      0    stevel 	}
   1104      0    stevel 	if (flags & HELP_NETADDR) {
   1105      0    stevel 		(void) fprintf(fp, gettext("\n<net-addr> :="));
   1106      0    stevel 		(void) fprintf(fp,
   1107      0    stevel 		    gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n"));
   1108      0    stevel 		(void) fprintf(fp,
   1109      0    stevel 		    gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
   1110      0    stevel 		(void) fprintf(fp,
   1111      0    stevel 		    gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
   1112      0    stevel 		(void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and "
   1113      0    stevel 		    "IPv6 address syntax.\n"));
   1114      0    stevel 		(void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n"));
   1115      0    stevel 		(void) fprintf(fp,
   1116      0    stevel 		    gettext("<IPv6-prefix-length> := [0-128]\n"));
   1117      0    stevel 		(void) fprintf(fp,
   1118      0    stevel 		    gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
   1119      0    stevel 	}
   1120      0    stevel 	if (flags & HELP_RESOURCES) {
   1121   2607        dp 		(void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s | %s |\n\t"
   1122   3792     akolb 		    "%s | %s | %s | %s\n\n",
   1123      0    stevel 		    gettext("resource type"), rt_to_str(RT_FS),
   1124      0    stevel 		    rt_to_str(RT_IPD), rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
   1125   2607        dp 		    rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
   1126   3247  gjelinek 		    rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
   1127   3792     akolb 		    rt_to_str(RT_PCAP), rt_to_str(RT_MCAP));
   1128      0    stevel 	}
   1129      0    stevel 	if (flags & HELP_PROPS) {
   1130      0    stevel 		(void) fprintf(fp, gettext("For resource type ... there are "
   1131      0    stevel 		    "property types ...:\n"));
   1132      0    stevel 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1133    565        dp 		    pt_to_str(PT_ZONENAME));
   1134    565        dp 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1135      0    stevel 		    pt_to_str(PT_ZONEPATH));
   1136      0    stevel 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1137   2712   nn35248 		    pt_to_str(PT_BRAND));
   1138   2712   nn35248 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1139      0    stevel 		    pt_to_str(PT_AUTOBOOT));
   1140      0    stevel 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1141   2267        dp 		    pt_to_str(PT_BOOTARGS));
   1142   2267        dp 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1143      0    stevel 		    pt_to_str(PT_POOL));
   1144   1645     comay 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1145   1645     comay 		    pt_to_str(PT_LIMITPRIV));
   1146   3247  gjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1147   3247  gjelinek 		    pt_to_str(PT_SCHED));
   1148   3448  dh155122 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1149   3448  dh155122 		    pt_to_str(PT_IPTYPE));
   1150   3247  gjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1151   8662    Jordan 		    pt_to_str(PT_HOSTID));
   1152   8662    Jordan 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1153   3247  gjelinek 		    pt_to_str(PT_MAXLWPS));
   1154   3247  gjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1155   3247  gjelinek 		    pt_to_str(PT_MAXSHMMEM));
   1156   3247  gjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1157   3247  gjelinek 		    pt_to_str(PT_MAXSHMIDS));
   1158   3247  gjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1159   3247  gjelinek 		    pt_to_str(PT_MAXMSGIDS));
   1160   3247  gjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1161   3247  gjelinek 		    pt_to_str(PT_MAXSEMIDS));
   1162   3247  gjelinek 		(void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
   1163   3247  gjelinek 		    pt_to_str(PT_SHARES));
   1164      0    stevel 		(void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s\n", rt_to_str(RT_FS),
   1165      0    stevel 		    pt_to_str(PT_DIR), pt_to_str(PT_SPECIAL),
   1166      0    stevel 		    pt_to_str(PT_RAW), pt_to_str(PT_TYPE),
   1167      0    stevel 		    pt_to_str(PT_OPTIONS));
   1168      0    stevel 		(void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_IPD),
   1169      0    stevel 		    pt_to_str(PT_DIR));
   1170   6076    gfaden 		(void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_NET),
   1171   6076    gfaden 		    pt_to_str(PT_ADDRESS), pt_to_str(PT_PHYSICAL),
   1172   6076    gfaden 		    pt_to_str(PT_DEFROUTER));
   1173      0    stevel 		(void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
   1174      0    stevel 		    pt_to_str(PT_MATCH));
   1175      0    stevel 		(void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
   1176      0    stevel 		    pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
   1177      0    stevel 		(void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
   1178      0    stevel 		    pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
   1179      0    stevel 		    pt_to_str(PT_VALUE));
   1180    789    ahrens 		(void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
   1181    789    ahrens 		    pt_to_str(PT_NAME));
   1182   3247  gjelinek 		(void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
   1183   3247  gjelinek 		    pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
   1184   3792     akolb 		(void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
   1185   3792     akolb 		    pt_to_str(PT_NCPUS));
   1186   3247  gjelinek 		(void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
   1187   3247  gjelinek 		    pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
   1188   3247  gjelinek 		    pt_to_str(PT_LOCKED));
   1189      0    stevel 	}
   1190      0    stevel 	if (need_to_close)
   1191      0    stevel 		(void) pclose(fp);
   1192      0    stevel }
   1193      0    stevel 
   1194      0    stevel /* PRINTFLIKE1 */
   1195      0    stevel static void
   1196      0    stevel zerr(const char *fmt, ...)
   1197      0    stevel {
   1198      0    stevel 	va_list alist;
   1199      0    stevel 	static int last_lineno;
   1200      0    stevel 
   1201      0    stevel 	/* lex_lineno has already been incremented in the lexer; compensate */
   1202      0    stevel 	if (cmd_file_mode && lex_lineno > last_lineno) {
   1203      0    stevel 		if (strcmp(cmd_file_name, "-") == 0)
   1204      0    stevel 			(void) fprintf(stderr, gettext("On line %d:\n"),
   1205      0    stevel 			    lex_lineno - 1);
   1206      0    stevel 		else
   1207      0    stevel 			(void) fprintf(stderr, gettext("On line %d of %s:\n"),
   1208      0    stevel 			    lex_lineno - 1, cmd_file_name);
   1209      0    stevel 		last_lineno = lex_lineno;
   1210      0    stevel 	}
   1211      0    stevel 	va_start(alist, fmt);
   1212      0    stevel 	(void) vfprintf(stderr, fmt, alist);
   1213      0    stevel 	(void) fprintf(stderr, "\n");
   1214      0    stevel 	va_end(alist);
   1215      0    stevel }
   1216      0    stevel 
   1217      0    stevel static void
   1218   6215  gjelinek zone_perror(char *prefix, int err, boolean_t set_saw)
   1219      0    stevel {
   1220      0    stevel 	zerr("%s: %s", prefix, zonecfg_strerror(err));
   1221      0    stevel 	if (set_saw)
   1222   6215  gjelinek 		saw_error = B_TRUE;
   1223      0    stevel }
   1224      0    stevel 
   1225      0    stevel /*
   1226      0    stevel  * zone_perror() expects a single string, but for remove and select
   1227      0    stevel  * we have both the command and the resource type, so this wrapper
   1228      0    stevel  * function serves the same purpose in a slightly different way.
   1229      0    stevel  */
   1230      0    stevel 
   1231      0    stevel static void
   1232   6215  gjelinek z_cmd_rt_perror(int cmd_num, int res_num, int err, boolean_t set_saw)
   1233      0    stevel {
   1234      0    stevel 	zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num),
   1235      0    stevel 	    zonecfg_strerror(err));
   1236      0    stevel 	if (set_saw)
   1237   6215  gjelinek 		saw_error = B_TRUE;
   1238      0    stevel }
   1239      0    stevel 
   1240      0    stevel /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
   1241      0    stevel static int
   1242   6215  gjelinek initialize(boolean_t handle_expected)
   1243      0    stevel {
   1244      0    stevel 	int err;
   1245   2712   nn35248 	char brandname[MAXNAMELEN];
   1246      0    stevel 
   1247      0    stevel 	if (zonecfg_check_handle(handle) != Z_OK) {
   1248      0    stevel 		if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) {
   1249   6215  gjelinek 			got_handle = B_TRUE;
   1250   2712   nn35248 			if (zonecfg_get_brand(handle, brandname,
   1251   2712   nn35248 			    sizeof (brandname)) != Z_OK) {
   1252   2712   nn35248 				zerr("Zone %s is inconsistent: missing "
   1253   2712   nn35248 				    "brand attribute", zone);
   1254   2712   nn35248 				exit(Z_ERR);
   1255   2712   nn35248 			}
   1256   2712   nn35248 			if ((brand = brand_open(brandname)) == NULL) {
   1257   2712   nn35248 				zerr("Zone %s uses non-existent brand \"%s\"."
   1258   2712   nn35248 				    "  Unable to continue", zone, brandname);
   1259   2712   nn35248 				exit(Z_ERR);
   1260   2712   nn35248 			}
   1261   3247  gjelinek 		} else if (global_zone && err == Z_NO_ZONE && !got_handle &&
   1262   3247  gjelinek 		    !read_only_mode) {
   1263   3247  gjelinek 			/*
   1264   3247  gjelinek 			 * We implicitly create the global zone config if it
   1265   3247  gjelinek 			 * doesn't exist.
   1266   3247  gjelinek 			 */
   1267   3247  gjelinek 			zone_dochandle_t tmphandle;
   1268   3247  gjelinek 
   1269   3247  gjelinek 			if ((tmphandle = zonecfg_init_handle()) == NULL) {
   1270   6215  gjelinek 				zone_perror(execname, Z_NOMEM, B_TRUE);
   1271   3247  gjelinek 				exit(Z_ERR);
   1272   3247  gjelinek 			}
   1273   3247  gjelinek 
   1274   3247  gjelinek 			err = zonecfg_get_template_handle("SUNWblank", zone,
   1275   3247  gjelinek 			    tmphandle);
   1276   3247  gjelinek 
   1277   3247  gjelinek 			if (err != Z_OK) {
   1278   3247  gjelinek 				zonecfg_fini_handle(tmphandle);
   1279   6215  gjelinek 				zone_perror("SUNWblank", err, B_TRUE);
   1280   3247  gjelinek 				return (err);
   1281   3247  gjelinek 			}
   1282   3247  gjelinek 
   1283   6215  gjelinek 			need_to_commit = B_TRUE;
   1284   3247  gjelinek 			zonecfg_fini_handle(handle);
   1285   3247  gjelinek 			handle = tmphandle;
   1286   6215  gjelinek 			got_handle = B_TRUE;
   1287   3247  gjelinek 
   1288      0    stevel 		} else {
   1289      0    stevel 			zone_perror(zone, err, handle_expected || got_handle);
   1290      0    stevel 			if (err == Z_NO_ZONE && !got_handle &&
   1291      0    stevel 			    interactive_mode && !read_only_mode)
   1292      0    stevel 				(void) printf(gettext("Use '%s' to begin "
   1293      0    stevel 				    "configuring a new zone.\n"),
   1294      0    stevel 				    cmd_to_str(CMD_CREATE));
   1295      0    stevel 			return (err);
   1296      0    stevel 		}
   1297      0    stevel 	}
   1298      0    stevel 	return (Z_OK);
   1299      0    stevel }
   1300      0    stevel 
   1301   6215  gjelinek static boolean_t
   1302    565        dp state_atleast(zone_state_t state)
   1303    565        dp {
   1304    565        dp 	zone_state_t state_num;
   1305    565        dp 	int err;
   1306    565        dp 
   1307    565        dp 	if ((err = zone_get_state(zone, &state_num)) != Z_OK) {
   1308    565        dp 		/* all states are greater than "non-existent" */
   1309    565        dp 		if (err == Z_NO_ZONE)
   1310    565        dp 			return (B_FALSE);
   1311    565        dp 		zerr(gettext("Unexpectedly failed to determine state "
   1312    565        dp 		    "of zone %s: %s"), zone, zonecfg_strerror(err));
   1313    565        dp 		exit(Z_ERR);
   1314    565        dp 	}
   1315    565        dp 	return (state_num >= state);
   1316    565        dp }
   1317    565        dp 
   1318      0    stevel /*
   1319      0    stevel  * short_usage() is for bad syntax: getopt() issues, too many arguments, etc.
   1320      0    stevel  */
   1321      0    stevel 
   1322      0    stevel void
   1323      0    stevel short_usage(int command)
   1324      0    stevel {
   1325      0    stevel 	/* lex_lineno has already been incremented in the lexer; compensate */
   1326      0    stevel 	if (cmd_file_mode) {
   1327      0    stevel 		if (strcmp(cmd_file_name, "-") == 0)
   1328      0    stevel 			(void) fprintf(stderr,
   1329      0    stevel 			    gettext("syntax error on line %d\n"),
   1330      0    stevel 			    lex_lineno - 1);
   1331      0    stevel 		else
   1332      0    stevel 			(void) fprintf(stderr,
   1333      0    stevel 			    gettext("syntax error on line %d of %s\n"),
   1334      0    stevel 			    lex_lineno - 1, cmd_file_name);
   1335      0    stevel 	}
   1336      0    stevel 	(void) fprintf(stderr, "%s:\n%s\n", gettext("usage"),
   1337      0    stevel 	    helptab[command].short_usage);
   1338   6215  gjelinek 	saw_error = B_TRUE;
   1339      0    stevel }
   1340      0    stevel 
   1341      0    stevel /*
   1342      0    stevel  * long_usage() is for bad semantics: e.g., wrong property type for a given
   1343      0    stevel  * resource type.  It is also used by longer_usage() below.
   1344      0    stevel  */
   1345      0    stevel 
   1346      0    stevel void
   1347   6215  gjelinek long_usage(uint_t cmd_num, boolean_t set_saw)
   1348      0    stevel {
   1349      0    stevel 	(void) fprintf(set_saw ? stderr : stdout, "%s:\n%s\n", gettext("usage"),
   1350      0    stevel 	    helptab[cmd_num].short_usage);
   1351      0    stevel 	(void) fprintf(set_saw ? stderr : stdout, "\t%s\n", long_help(cmd_num));
   1352      0    stevel 	if (set_saw)
   1353   6215  gjelinek 		saw_error = B_TRUE;
   1354      0    stevel }
   1355      0    stevel 
   1356      0    stevel /*
   1357      0    stevel  * longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also
   1358      0    stevel  * any extra usage() flags as appropriate for whatever command.
   1359      0    stevel  */
   1360      0    stevel 
   1361      0    stevel void
   1362      0    stevel longer_usage(uint_t cmd_num)
   1363      0    stevel {
   1364   6215  gjelinek 	long_usage(cmd_num, B_FALSE);
   1365      0    stevel 	if (helptab[cmd_num].flags != 0) {
   1366      0    stevel 		(void) printf("\n");
   1367   6215  gjelinek 		usage(B_TRUE, helptab[cmd_num].flags);
   1368      0    stevel 	}
   1369      0    stevel }
   1370      0    stevel 
   1371      0    stevel /*
   1372      0    stevel  * scope_usage() is simply used when a command is called from the wrong scope.
   1373      0    stevel  */
   1374      0    stevel 
   1375      0    stevel static void
   1376      0    stevel scope_usage(uint_t cmd_num)
   1377      0    stevel {
   1378      0    stevel 	zerr(gettext("The %s command only makes sense in the %s scope."),
   1379      0    stevel 	    cmd_to_str(cmd_num),
   1380      0    stevel 	    global_scope ?  gettext("resource") : gettext("global"));
   1381   6215  gjelinek 	saw_error = B_TRUE;
   1382   6215  gjelinek }
   1383   6215  gjelinek 
   1384   6215  gjelinek /*
   1385   6215  gjelinek  * On input, B_TRUE => yes, B_FALSE => no.
   1386   6215  gjelinek  * On return, B_TRUE => 1, B_FALSE => no, could not ask => -1.
   1387   6215  gjelinek  */
   1388   6215  gjelinek 
   1389   6215  gjelinek static int
   1390   6215  gjelinek ask_yesno(boolean_t default_answer, const char *question)
   1391      0    stevel {
   1392      0    stevel 	char line[64];	/* should be enough to answer yes or no */
   1393      0    stevel 
   1394      0    stevel 	if (!ok_to_prompt) {
   1395   6215  gjelinek 		saw_error = B_TRUE;
   1396      0    stevel 		return (-1);
   1397      0    stevel 	}
   1398      0    stevel 	for (;;) {
   1399    565        dp 		if (printf("%s (%s)? ", question,
   1400    565        dp 		    default_answer ? "[y]/n" : "y/[n]") < 0)
   1401    565        dp 			return (-1);
   1402    565        dp 		if (fgets(line, sizeof (line), stdin) == NULL)
   1403    565        dp 			return (-1);
   1404    565        dp 
   1405    565        dp 		if (line[0] == '\n')
   1406      0    stevel 			return (default_answer ? 1 : 0);
   1407      0    stevel 		if (tolower(line[0]) == 'y')
   1408      0    stevel 			return (1);
   1409      0    stevel 		if (tolower(line[0]) == 'n')
   1410      0    stevel 			return (0);
   1411      0    stevel 	}
   1412      0    stevel }
   1413      0    stevel 
   1414      0    stevel /*
   1415      0    stevel  * Prints warning if zone already exists.
   1416      0    stevel  * In interactive mode, prompts if we should continue anyway and returns Z_OK
   1417      0    stevel  * if so, Z_ERR if not.  In non-interactive mode, exits with Z_ERR.
   1418      0    stevel  *
   1419      0    stevel  * Note that if a zone exists and its state is >= INSTALLED, an error message
   1420      0    stevel  * will be printed and this function will return Z_ERR regardless of mode.
   1421      0    stevel  */
   1422      0    stevel 
   1423      0    stevel static int
   1424   6215  gjelinek check_if_zone_already_exists(boolean_t force)
   1425      0    stevel {
   1426      0    stevel 	char line[ZONENAME_MAX + 128];	/* enough to ask a question */
   1427      0    stevel 	zone_dochandle_t tmphandle;
   1428      0    stevel 	int res, answer;
   1429      0    stevel 
   1430      0    stevel 	if ((tmphandle = zonecfg_init_handle()) == NULL) {
   1431   6215  gjelinek 		zone_perror(execname, Z_NOMEM, B_TRUE);
   1432      0    stevel 		exit(Z_ERR);
   1433      0    stevel 	}
   1434      0    stevel 	res = zonecfg_get_handle(zone, tmphandle);
   1435      0    stevel 	zonecfg_fini_handle(tmphandle);
   1436    565        dp 	if (res != Z_OK)
   1437    565        dp 		return (Z_OK);
   1438    565        dp 
   1439    565        dp 	if (state_atleast(ZONE_STATE_INSTALLED)) {
   1440      0    stevel 		zerr(gettext("Zone %s already installed; %s not allowed."),
   1441      0    stevel 		    zone, cmd_to_str(CMD_CREATE));
   1442      0    stevel 		return (Z_ERR);
   1443      0    stevel 	}
   1444      0    stevel 
   1445      0    stevel 	if (force) {
   1446      0    stevel 		(void) printf(gettext("Zone %s already exists; overwriting.\n"),
   1447      0    stevel 		    zone);
   1448      0    stevel 		return (Z_OK);
   1449      0    stevel 	}
   1450      0    stevel 	(void) snprintf(line, sizeof (line),
   1451      0    stevel 	    gettext("Zone %s already exists; %s anyway"), zone,
   1452      0    stevel 	    cmd_to_str(CMD_CREATE));
   1453   6215  gjelinek 	if ((answer = ask_yesno(B_FALSE, line)) == -1) {
   1454      0    stevel 		zerr(gettext("Zone exists, input not from terminal and -F not "
   1455      0    stevel 		    "specified:\n%s command ignored, exiting."),
   1456      0    stevel 		    cmd_to_str(CMD_CREATE));
   1457      0    stevel 		exit(Z_ERR);
   1458      0    stevel 	}
   1459      0    stevel 	return (answer == 1 ? Z_OK : Z_ERR);
   1460      0    stevel }
   1461      0    stevel 
   1462   6215  gjelinek static boolean_t
   1463      0    stevel zone_is_read_only(int cmd_num)
   1464      0    stevel {
   1465      0    stevel 	if (strncmp(zone, "SUNW", 4) == 0) {
   1466      0    stevel 		zerr(gettext("%s: zones beginning with SUNW are read-only."),
   1467      0    stevel 		    zone);
   1468   6215  gjelinek 		saw_error = B_TRUE;
   1469   6215  gjelinek 		return (B_TRUE);
   1470      0    stevel 	}
   1471      0    stevel 	if (read_only_mode) {
   1472      0    stevel 		zerr(gettext("%s: cannot %s in read-only mode."), zone,
   1473      0    stevel 		    cmd_to_str(cmd_num));
   1474   6215  gjelinek 		saw_error = B_TRUE;
   1475   6215  gjelinek 		return (B_TRUE);
   1476   6215  gjelinek 	}
   1477   6215  gjelinek 	return (B_FALSE);
   1478      0    stevel }
   1479      0    stevel 
   1480      0    stevel /*
   1481      0    stevel  * Create a new configuration.
   1482      0    stevel  */
   1483      0    stevel void
   1484      0    stevel create_func(cmd_t *cmd)
   1485      0    stevel {
   1486      0    stevel 	int err, arg;
   1487      0    stevel 	char zone_template[ZONENAME_MAX];
   1488   1507  gjelinek 	char attach_path[MAXPATHLEN];
   1489      0    stevel 	zone_dochandle_t tmphandle;
   1490   6215  gjelinek 	boolean_t force = B_FALSE;
   1491   6215  gjelinek 	boolean_t attach = B_FALSE;
   1492   6215  gjelinek 	boolean_t arg_err = B_FALSE;
   1493      0    stevel 
   1494      0    stevel 	assert(cmd != NULL);
   1495      0    stevel 
   1496      0    stevel 	/* This is the default if no arguments are given. */
   1497      0    stevel 	(void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template));
   1498      0    stevel 
   1499      0    stevel 	optind = 0;
   1500   2712   nn35248 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:"))
   1501   2712   nn35248 	    != EOF) {
   1502      0    stevel 		switch (arg) {
   1503      0    stevel 		case '?':
   1504      0    stevel 			if (optopt == '?')
   1505      0    stevel 				longer_usage(CMD_CREATE);
   1506      0    stevel 			else
   1507      0    stevel 				short_usage(CMD_CREATE);
   1508   6215  gjelinek 			arg_err = B_TRUE;
   1509   3691  gjelinek 			break;
   1510   1507  gjelinek 		case 'a':
   1511   1507  gjelinek 			(void) strlcpy(attach_path, optarg,
   1512   1507  gjelinek 			    sizeof (attach_path));
   1513   6215  gjelinek 			attach = B_TRUE;
   1514   1507  gjelinek 			break;
   1515      0    stevel 		case 'b':
   1516      0    stevel 			(void) strlcpy(zone_template, "SUNWblank",
   1517      0    stevel 			    sizeof (zone_template));
   1518      0    stevel 			break;
   1519      0    stevel 		case 'F':
   1520   6215  gjelinek 			force = B_TRUE;
   1521      0    stevel 			break;
   1522      0    stevel 		case 't':
   1523      0    stevel 			(void) strlcpy(zone_template, optarg,
   1524      0    stevel 			    sizeof (zone_template));
   1525      0    stevel 			break;
   1526      0    stevel 		default:
   1527      0    stevel 			short_usage(CMD_CREATE);
   1528   6215  gjelinek 			arg_err = B_TRUE;
   1529   3691  gjelinek 			break;
   1530   3691  gjelinek 		}
   1531   3691  gjelinek 	}
   1532   3691  gjelinek 	if (arg_err)
   1533   3691  gjelinek 		return;
   1534   3691  gjelinek 
   1535      0    stevel 	if (optind != cmd->cmd_argc) {
   1536      0    stevel 		short_usage(CMD_CREATE);
   1537      0    stevel 		return;
   1538      0    stevel 	}
   1539      0    stevel 
   1540      0    stevel 	if (zone_is_read_only(CMD_CREATE))
   1541      0    stevel 		return;
   1542      0    stevel 
   1543      0    stevel 	if (check_if_zone_already_exists(force) != Z_OK)
   1544      0    stevel 		return;
   1545      0    stevel 
   1546      0    stevel 	/*
   1547      0    stevel 	 * Get a temporary handle first.  If that fails, the old handle
   1548      0    stevel 	 * will not be lost.  Then finish whichever one we don't need,
   1549      0    stevel 	 * to avoid leaks.  Then get the handle for zone_template, and
   1550      0    stevel 	 * set the name to zone: this "copy, rename" method is how
   1551      0    stevel 	 * create -[b|t] works.
   1552      0    stevel 	 */
   1553      0    stevel 	if ((tmphandle = zonecfg_init_handle()) == NULL) {
   1554   6215  gjelinek 		zone_perror(execname, Z_NOMEM, B_TRUE);
   1555      0    stevel 		exit(Z_ERR);
   1556      0    stevel 	}
   1557   1507  gjelinek 
   1558   1507  gjelinek 	if (attach)
   1559   7257  gjelinek 		err = zonecfg_get_attach_handle(attach_path, ZONE_DETACHED,
   1560   7257  gjelinek 		    zone, B_FALSE, tmphandle);
   1561   1507  gjelinek 	else
   1562   1507  gjelinek 		err = zonecfg_get_template_handle(zone_template, zone,
   1563   1507  gjelinek 		    tmphandle);
   1564   1507  gjelinek 
   1565   1507  gjelinek 	if (err != Z_OK) {
   1566      0    stevel 		zonecfg_fini_handle(tmphandle);
   1567   1507  gjelinek 		if (attach && err == Z_NO_ZONE)
   1568   1507  gjelinek 			(void) fprintf(stderr, gettext("invalid path to "
   1569   1507  gjelinek 			    "detached zone\n"));
   1570   1507  gjelinek 		else if (attach && err == Z_INVALID_DOCUMENT)
   1571   1507  gjelinek 			(void) fprintf(stderr, gettext("Cannot attach to an "
   1572   1507  gjelinek 			    "earlier release of the operating system\n"));
   1573   1507  gjelinek 		else
   1574   6215  gjelinek 			zone_perror(zone_template, err, B_TRUE);
   1575   6215  gjelinek 		return;
   1576   6215  gjelinek 	}
   1577   6215  gjelinek 
   1578   6215  gjelinek 	need_to_commit = B_TRUE;
   1579      0    stevel 	zonecfg_fini_handle(handle);
   1580      0    stevel 	handle = tmphandle;
   1581   6215  gjelinek 	got_handle = B_TRUE;
   1582      0    stevel }
   1583      0    stevel 
   1584      0    stevel /*
   1585      0    stevel  * This malloc()'s memory, which must be freed by the caller.
   1586      0    stevel  */
   1587      0    stevel static char *
   1588      0    stevel quoteit(char *instr)
   1589      0    stevel {
   1590      0    stevel 	char *outstr;
   1591      0    stevel 	size_t outstrsize = strlen(instr) + 3;	/* 2 quotes + '\0' */
   1592      0    stevel 
   1593      0    stevel 	if ((outstr = malloc(outstrsize)) == NULL) {
   1594   6215  gjelinek 		zone_perror(zone, Z_NOMEM, B_FALSE);
   1595      0    stevel 		exit(Z_ERR);
   1596      0    stevel 	}
   1597      0    stevel 	if (strchr(instr, ' ') == NULL) {
   1598      0    stevel 		(void) strlcpy(outstr, instr, outstrsize);
   1599      0    stevel 		return (outstr);
   1600      0    stevel 	}
   1601      0    stevel 	(void) snprintf(outstr, outstrsize, "\"%s\"", instr);
   1602      0    stevel 	return (outstr);
   1603      0    stevel }
   1604      0    stevel 
   1605      0    stevel static void
   1606      0    stevel export_prop(FILE *of, int prop_num, char *prop_id)
   1607      0    stevel {
   1608      0    stevel 	char *quote_str;
   1609      0    stevel 
   1610      0    stevel 	if (strlen(prop_id) == 0)
   1611      0    stevel 		return;
   1612      0    stevel 	quote_str = quoteit(prop_id);
   1613      0    stevel 	(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1614      0    stevel 	    pt_to_str(prop_num), quote_str);
   1615      0    stevel 	free(quote_str);
   1616      0    stevel }
   1617      0    stevel 
   1618      0    stevel void
   1619      0    stevel export_func(cmd_t *cmd)
   1620      0    stevel {
   1621      0    stevel 	struct zone_nwiftab nwiftab;
   1622      0    stevel 	struct zone_fstab fstab;
   1623      0    stevel 	struct zone_devtab devtab;
   1624      0    stevel 	struct zone_attrtab attrtab;
   1625      0    stevel 	struct zone_rctltab rctltab;
   1626    789    ahrens 	struct zone_dstab dstab;
   1627   3247  gjelinek 	struct zone_psettab psettab;
   1628   3247  gjelinek 	struct zone_mcaptab mcaptab;
   1629      0    stevel 	struct zone_rctlvaltab *valptr;
   1630      0    stevel 	int err, arg;
   1631      0    stevel 	char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
   1632   2267        dp 	char bootargs[BOOTARGS_MAX];
   1633   3247  gjelinek 	char sched[MAXNAMELEN];
   1634   2712   nn35248 	char brand[MAXNAMELEN];
   1635   8662    Jordan 	char hostidp[HW_HOSTID_LEN];
   1636   1645     comay 	char *limitpriv;
   1637      0    stevel 	FILE *of;
   1638      0    stevel 	boolean_t autoboot;
   1639   3448  dh155122 	zone_iptype_t iptype;
   1640   6215  gjelinek 	boolean_t need_to_close = B_FALSE;
   1641   6215  gjelinek 	boolean_t arg_err = B_FALSE;
   1642      0    stevel 
   1643      0    stevel 	assert(cmd != NULL);
   1644      0    stevel 
   1645      0    stevel 	outfile[0] = '\0';
   1646      0    stevel 	optind = 0;
   1647      0    stevel 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
   1648      0    stevel 		switch (arg) {
   1649      0    stevel 		case '?':
   1650      0    stevel 			if (optopt == '?')
   1651      0    stevel 				longer_usage(CMD_EXPORT);
   1652      0    stevel 			else
   1653      0    stevel 				short_usage(CMD_EXPORT);
   1654   6215  gjelinek 			arg_err = B_TRUE;
   1655   3691  gjelinek 			break;
   1656      0    stevel 		case 'f':
   1657      0    stevel 			(void) strlcpy(outfile, optarg, sizeof (outfile));
   1658      0    stevel 			break;
   1659      0    stevel 		default:
   1660      0    stevel 			short_usage(CMD_EXPORT);
   1661   6215  gjelinek 			arg_err = B_TRUE;
   1662   3691  gjelinek 			break;
   1663   3691  gjelinek 		}
   1664   3691  gjelinek 	}
   1665   3691  gjelinek 	if (arg_err)
   1666   3691  gjelinek 		return;
   1667   3691  gjelinek 
   1668      0    stevel 	if (optind != cmd->cmd_argc) {
   1669      0    stevel 		short_usage(CMD_EXPORT);
   1670      0    stevel 		return;
   1671      0    stevel 	}
   1672      0    stevel 	if (strlen(outfile) == 0) {
   1673      0    stevel 		of = stdout;
   1674      0    stevel 	} else {
   1675      0    stevel 		if ((of = fopen(outfile, "w")) == NULL) {
   1676      0    stevel 			zerr(gettext("opening file %s: %s"),
   1677      0    stevel 			    outfile, strerror(errno));
   1678      0    stevel 			goto done;
   1679      0    stevel 		}
   1680      0    stevel 		setbuf(of, NULL);
   1681   6215  gjelinek 		need_to_close = B_TRUE;
   1682   6215  gjelinek 	}
   1683   6215  gjelinek 
   1684   6215  gjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
   1685      0    stevel 		goto done;
   1686      0    stevel 
   1687      0    stevel 	(void) fprintf(of, "%s -b\n", cmd_to_str(CMD_CREATE));
   1688      0    stevel 
   1689      0    stevel 	if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK &&
   1690      0    stevel 	    strlen(zonepath) > 0)
   1691      0    stevel 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1692      0    stevel 		    pt_to_str(PT_ZONEPATH), zonepath);
   1693   2712   nn35248 
   1694   2712   nn35248 	if ((zone_get_brand(zone, brand, sizeof (brand)) == Z_OK) &&
   1695   2712   nn35248 	    (strcmp(brand, NATIVE_BRAND_NAME) != 0))
   1696   2712   nn35248 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1697   2712   nn35248 		    pt_to_str(PT_BRAND), brand);
   1698      0    stevel 
   1699      0    stevel 	if (zonecfg_get_autoboot(handle, &autoboot) == Z_OK)
   1700      0    stevel 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1701      0    stevel 		    pt_to_str(PT_AUTOBOOT), autoboot ? "true" : "false");
   1702      0    stevel 
   1703   2267        dp 	if (zonecfg_get_bootargs(handle, bootargs, sizeof (bootargs)) == Z_OK &&
   1704   2267        dp 	    strlen(bootargs) > 0) {
   1705   2267        dp 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1706   2267        dp 		    pt_to_str(PT_BOOTARGS), bootargs);
   1707   2267        dp 	}
   1708   2267        dp 
   1709      0    stevel 	if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
   1710      0    stevel 	    strlen(pool) > 0)
   1711      0    stevel 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1712      0    stevel 		    pt_to_str(PT_POOL), pool);
   1713   1645     comay 
   1714   1645     comay 	if (zonecfg_get_limitpriv(handle, &limitpriv) == Z_OK &&
   1715   1645     comay 	    strlen(limitpriv) > 0) {
   1716   1645     comay 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1717   1645     comay 		    pt_to_str(PT_LIMITPRIV), limitpriv);
   1718   1645     comay 		free(limitpriv);
   1719   1645     comay 	}
   1720   2267        dp 
   1721   3247  gjelinek 	if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK &&
   1722   3247  gjelinek 	    strlen(sched) > 0)
   1723   3247  gjelinek 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1724   3247  gjelinek 		    pt_to_str(PT_SCHED), sched);
   1725   3448  dh155122 
   1726   3448  dh155122 	if (zonecfg_get_iptype(handle, &iptype) == Z_OK) {
   1727   3448  dh155122 		switch (iptype) {
   1728   3448  dh155122 		case ZS_SHARED:
   1729   3448  dh155122 			(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1730   3448  dh155122 			    pt_to_str(PT_IPTYPE), "shared");
   1731   3448  dh155122 			break;
   1732   3448  dh155122 		case ZS_EXCLUSIVE:
   1733   3448  dh155122 			(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1734   3448  dh155122 			    pt_to_str(PT_IPTYPE), "exclusive");
   1735   3448  dh155122 			break;
   1736   3448  dh155122 		}
   1737   8662    Jordan 	}
   1738   8662    Jordan 
   1739   8662    Jordan 	if (zonecfg_get_hostid(handle, hostidp, sizeof (hostidp)) == Z_OK) {
   1740   8662    Jordan 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1741   8662    Jordan 		    pt_to_str(PT_HOSTID), hostidp);
   1742   3448  dh155122 	}
   1743      0    stevel 
   1744      0    stevel 	if ((err = zonecfg_setipdent(handle)) != Z_OK) {
   1745   6215  gjelinek 		zone_perror(zone, err, B_FALSE);
   1746      0    stevel 		goto done;
   1747      0    stevel 	}
   1748      0    stevel 	while (zonecfg_getipdent(handle, &fstab) == Z_OK) {
   1749      0    stevel 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
   1750      0    stevel 		    rt_to_str(RT_IPD));
   1751      0    stevel 		export_prop(of, PT_DIR, fstab.zone_fs_dir);
   1752      0    stevel 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
   1753      0    stevel 	}
   1754      0    stevel 	(void) zonecfg_endipdent(handle);
   1755      0    stevel 
   1756      0    stevel 	if ((err = zonecfg_setfsent(handle)) != Z_OK) {
   1757   6215  gjelinek 		zone_perror(zone, err, B_FALSE);
   1758      0    stevel 		goto done;
   1759      0    stevel 	}
   1760      0    stevel 	while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
   1761      0    stevel 		zone_fsopt_t *optptr;
   1762      0    stevel 
   1763      0    stevel 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
   1764      0    stevel 		    rt_to_str(RT_FS));
   1765      0    stevel 		export_prop(of, PT_DIR, fstab.zone_fs_dir);
   1766      0    stevel 		export_prop(of, PT_SPECIAL, fstab.zone_fs_special);
   1767      0    stevel 		export_prop(of, PT_RAW, fstab.zone_fs_raw);
   1768      0    stevel 		export_prop(of, PT_TYPE, fstab.zone_fs_type);
   1769      0    stevel 		for (optptr = fstab.zone_fs_options; optptr != NULL;
   1770      0    stevel 		    optptr = optptr->zone_fsopt_next) {
   1771      0    stevel 			/*
   1772      0    stevel 			 * Simple property values with embedded equal signs
   1773      0    stevel 			 * need to be quoted to prevent the lexer from
   1774      0    stevel 			 * mis-parsing them as complex name=value pairs.
   1775      0    stevel 			 */
   1776      0    stevel 			if (strchr(optptr->zone_fsopt_opt, '='))
   1777      0    stevel 				(void) fprintf(of, "%s %s \"%s\"\n",
   1778      0    stevel 				    cmd_to_str(CMD_ADD),
   1779      0    stevel 				    pt_to_str(PT_OPTIONS),
   1780      0    stevel 				    optptr->zone_fsopt_opt);
   1781      0    stevel 			else
   1782      0    stevel 				(void) fprintf(of, "%s %s %s\n",
   1783      0    stevel 				    cmd_to_str(CMD_ADD),
   1784      0    stevel 				    pt_to_str(PT_OPTIONS),
   1785      0    stevel 				    optptr->zone_fsopt_opt);
   1786      0    stevel 		}
   1787      0    stevel 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
   1788      0    stevel 		zonecfg_free_fs_option_list(fstab.zone_fs_options);
   1789      0    stevel 	}
   1790      0    stevel 	(void) zonecfg_endfsent(handle);
   1791      0    stevel 
   1792      0    stevel 	if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
   1793   6215  gjelinek 		zone_perror(zone, err, B_FALSE);
   1794      0    stevel 		goto done;
   1795      0    stevel 	}
   1796      0    stevel 	while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
   1797      0    stevel 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
   1798      0    stevel 		    rt_to_str(RT_NET));
   1799      0    stevel 		export_prop(of, PT_ADDRESS, nwiftab.zone_nwif_address);
   1800      0    stevel 		export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical);
   1801   6076    gfaden 		export_prop(of, PT_DEFROUTER, nwiftab.zone_nwif_defrouter);
   1802      0    stevel 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
   1803      0    stevel 	}
   1804      0    stevel 	(void) zonecfg_endnwifent(handle);
   1805      0    stevel 
   1806      0    stevel 	if ((err = zonecfg_setdevent(handle)) != Z_OK) {
   1807   6215  gjelinek 		zone_perror(zone, err, B_FALSE);
   1808      0    stevel 		goto done;
   1809      0    stevel 	}
   1810      0    stevel 	while (zonecfg_getdevent(handle, &devtab) == Z_OK) {
   1811      0    stevel 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
   1812      0    stevel 		    rt_to_str(RT_DEVICE));
   1813      0    stevel 		export_prop(of, PT_MATCH, devtab.zone_dev_match);
   1814      0    stevel 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
   1815      0    stevel 	}
   1816      0    stevel 	(void) zonecfg_enddevent(handle);
   1817      0    stevel 
   1818      0    stevel 	if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
   1819   6215  gjelinek 		zone_perror(zone, err, B_FALSE);
   1820      0    stevel 		goto done;
   1821      0    stevel 	}
   1822      0    stevel 	while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
   1823      0    stevel 		(void) fprintf(of, "%s rctl\n", cmd_to_str(CMD_ADD));
   1824      0    stevel 		export_prop(of, PT_NAME, rctltab.zone_rctl_name);
   1825      0    stevel 		for (valptr = rctltab.zone_rctl_valptr; valptr != NULL;
   1826      0    stevel 		    valptr = valptr->zone_rctlval_next) {
   1827      0    stevel 			fprintf(of, "%s %s (%s=%s,%s=%s,%s=%s)\n",
   1828      0    stevel 			    cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
   1829      0    stevel 			    pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
   1830      0    stevel 			    pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
   1831      0    stevel 			    pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
   1832      0    stevel 		}
   1833      0    stevel 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
   1834      0    stevel 		zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
   1835      0    stevel 	}
   1836      0    stevel 	(void) zonecfg_endrctlent(handle);
   1837      0    stevel 
   1838      0    stevel 	if ((err = zonecfg_setattrent(handle)) != Z_OK) {
   1839   6215  gjelinek 		zone_perror(zone, err, B_FALSE);
   1840      0    stevel 		goto done;
   1841      0    stevel 	}
   1842      0    stevel 	while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
   1843      0    stevel 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
   1844      0    stevel 		    rt_to_str(RT_ATTR));
   1845      0    stevel 		export_prop(of, PT_NAME, attrtab.zone_attr_name);
   1846      0    stevel 		export_prop(of, PT_TYPE, attrtab.zone_attr_type);
   1847      0    stevel 		export_prop(of, PT_VALUE, attrtab.zone_attr_value);
   1848      0    stevel 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
   1849      0    stevel 	}
   1850      0    stevel 	(void) zonecfg_endattrent(handle);
   1851      0    stevel 
   1852    789    ahrens 	if ((err = zonecfg_setdsent(handle)) != Z_OK) {
   1853   6215  gjelinek 		zone_perror(zone, err, B_FALSE);
   1854    789    ahrens 		goto done;
   1855    789    ahrens 	}
   1856    789    ahrens 	while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
   1857    789    ahrens 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
   1858    789    ahrens 		    rt_to_str(RT_DATASET));
   1859    789    ahrens 		export_prop(of, PT_NAME, dstab.zone_dataset_name);
   1860    789    ahrens 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
   1861    789    ahrens 	}
   1862    789    ahrens 	(void) zonecfg_enddsent(handle);
   1863    789    ahrens 
   1864   3247  gjelinek 	if (zonecfg_getpsetent(handle, &psettab) == Z_OK) {
   1865   3247  gjelinek 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
   1866   3247  gjelinek 		    rt_to_str(RT_DCPU));
   1867   3247  gjelinek 		if (strcmp(psettab.zone_ncpu_min, psettab.zone_ncpu_max) == 0)
   1868   3247  gjelinek 			(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1869   3247  gjelinek 			    pt_to_str(PT_NCPUS), psettab.zone_ncpu_max);
   1870   3247  gjelinek 		else
   1871   3247  gjelinek 			(void) fprintf(of, "%s %s=%s-%s\n", cmd_to_str(CMD_SET),
   1872   3247  gjelinek 			    pt_to_str(PT_NCPUS), psettab.zone_ncpu_min,
   1873   3247  gjelinek 			    psettab.zone_ncpu_max);
   1874   3247  gjelinek 		if (psettab.zone_importance[0] != '\0')
   1875   3247  gjelinek 			(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1876   3247  gjelinek 			    pt_to_str(PT_IMPORTANCE), psettab.zone_importance);
   1877   3247  gjelinek 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
   1878   3247  gjelinek 	}
   1879   3247  gjelinek 
   1880   3247  gjelinek 	if (zonecfg_getmcapent(handle, &mcaptab) == Z_OK) {
   1881   3247  gjelinek 		char buf[128];
   1882   3247  gjelinek 
   1883   3247  gjelinek 		(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
   1884   3247  gjelinek 		    rt_to_str(RT_MCAP));
   1885   3247  gjelinek 		bytes_to_units(mcaptab.zone_physmem_cap, buf, sizeof (buf));
   1886   3247  gjelinek 		(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
   1887   3247  gjelinek 		    pt_to_str(PT_PHYSICAL), buf);
   1888   3247  gjelinek 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
   1889   3247  gjelinek 	}
   1890   3247  gjelinek 
   1891   3792     akolb 	/*
   1892   3792     akolb 	 * There is nothing to export for pcap since this resource is just
   1893   3792     akolb 	 * a container for an rctl alias.
   1894   3792     akolb 	 */
   1895   3792     akolb 
   1896      0    stevel done:
   1897      0    stevel 	if (need_to_close)
   1898      0    stevel 		(void) fclose(of);
   1899      0    stevel }
   1900      0    stevel 
   1901      0    stevel void
   1902      0    stevel exit_func(cmd_t *cmd)
   1903      0    stevel {
   1904      0    stevel 	int arg, answer;
   1905   6215  gjelinek 	boolean_t arg_err = B_FALSE;
   1906      0    stevel 
   1907      0    stevel 	optind = 0;
   1908      0    stevel 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
   1909      0    stevel 		switch (arg) {
   1910      0    stevel 		case '?':
   1911      0    stevel 			longer_usage(CMD_EXIT);
   1912   6215  gjelinek 			arg_err = B_TRUE;
   1913   6215  gjelinek 			break;
   1914   6215  gjelinek 		case 'F':
   1915   6215  gjelinek 			force_exit = B_TRUE;
   1916      0    stevel 			break;
   1917      0    stevel 		default:
   1918      0    stevel 			short_usage(CMD_EXIT);
   1919   6215  gjelinek 			arg_err = B_TRUE;
   1920   3691  gjelinek 			break;
   1921   3691  gjelinek 		}
   1922   3691  gjelinek 	}
   1923   3691  gjelinek 	if (arg_err)
   1924   3691  gjelinek 		return;
   1925   3691  gjelinek 
   1926      0    stevel 	if (optind < cmd->cmd_argc) {
   1927      0    stevel 		short_usage(CMD_EXIT);
   1928      0    stevel 		return;
   1929      0    stevel 	}
   1930      0    stevel 
   1931      0    stevel 	if (global_scope || force_exit) {
   1932   6215  gjelinek 		time_to_exit = B_TRUE;
   1933   6215  gjelinek 		return;
   1934   6215  gjelinek 	}
   1935   6215  gjelinek 
   1936   6215  gjelinek 	answer = ask_yesno(B_FALSE, "Resource incomplete; really quit");
   1937      0    stevel 	if (answer == -1) {
   1938      0    stevel 		zerr(gettext("Resource incomplete, input "
   1939      0    stevel 		    "not from terminal and -F not specified:\n%s command "
   1940      0    stevel 		    "ignored, but exiting anyway."), cmd_to_str(CMD_EXIT));
   1941      0    stevel 		exit(Z_ERR);
   1942      0    stevel 	} else if (answer == 1) {
   1943   6215  gjelinek 		time_to_exit = B_TRUE;
   1944      0    stevel 	}
   1945      0    stevel 	/* (answer == 0) => just return */
   1946      0    stevel }
   1947      0    stevel 
   1948      0    stevel static int
   1949      0    stevel validate_zonepath_syntax(char *path)
   1950      0    stevel {
   1951      0    stevel 	if (path[0] != '/') {
   1952      0    stevel 		zerr(gettext("%s is not an absolute path."), path);
   1953      0    stevel 		return (Z_ERR);
   1954      0    stevel 	}
   1955      0    stevel 	if (strcmp(path, "/") == 0) {
   1956      0    stevel 		zerr(gettext("/ is not allowed as a %s."),
   1957      0    stevel 		    pt_to_str(PT_ZONEPATH));
   1958      0    stevel 		return (Z_ERR);
   1959      0    stevel 	}
   1960      0    stevel 	return (Z_OK);
   1961      0    stevel }
   1962      0    stevel 
   1963      0    stevel static void
   1964      0    stevel add_resource(cmd_t *cmd)
   1965      0    stevel {
   1966      0    stevel 	int type;
   1967   3247  gjelinek 	struct zone_psettab tmp_psettab;
   1968   3247  gjelinek 	struct zone_mcaptab tmp_mcaptab;
   1969   3792     akolb 	uint64_t tmp;
   1970   3247  gjelinek 	uint64_t tmp_mcap;
   1971   3247  gjelinek 	char pool[MAXNAMELEN];
   1972      0    stevel 
   1973      0    stevel 	if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
   1974   6215  gjelinek 		long_usage(CMD_ADD, B_TRUE);
   1975      0    stevel 		goto bad;
   1976      0    stevel 	}
   1977      0    stevel 
   1978      0    stevel 	switch (type) {
   1979      0    stevel 	case RT_FS:
   1980      0    stevel 		bzero(&in_progress_fstab, sizeof (in_progress_fstab));
   1981      0    stevel 		return;
   1982      0    stevel 	case RT_IPD:
   1983    565        dp 		if (state_atleast(ZONE_STATE_INSTALLED)) {
   1984      0    stevel 			zerr(gettext("Zone %s already installed; %s %s not "
   1985      0    stevel 			    "allowed."), zone, cmd_to_str(CMD_ADD),
   1986      0    stevel 			    rt_to_str(RT_IPD));
   1987      0    stevel 			goto bad;
   1988      0    stevel 		}
   1989      0    stevel 		bzero(&in_progress_ipdtab, sizeof (in_progress_ipdtab));
   1990      0    stevel 		return;
   1991      0    stevel 	case RT_NET:
   1992      0    stevel 		bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
   1993      0    stevel 		return;
   1994      0    stevel 	case RT_DEVICE:
   1995      0    stevel 		bzero(&in_progress_devtab, sizeof (in_progress_devtab));
   1996      0    stevel 		return;
   1997      0    stevel 	case RT_RCTL:
   1998   3247  gjelinek 		if (global_zone)
   1999   3247  gjelinek 			zerr(gettext("WARNING: Setting a global zone resource "
   2000   3247  gjelinek 			    "control too low could deny\nservice "
   2001   3247  gjelinek 			    "to even the root user; "
   2002   3247  gjelinek 			    "this could render the system impossible\n"
   2003   3247  gjelinek 			    "to administer.  Please use caution."));
   2004      0    stevel 		bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
   2005      0    stevel 		return;
   2006      0    stevel 	case RT_ATTR:
   2007      0    stevel 		bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
   2008    789    ahrens 		return;
   2009    789    ahrens 	case RT_DATASET:
   2010    789    ahrens 		bzero(&in_progress_dstab, sizeof (in_progress_dstab));
   2011   3247  gjelinek 		return;
   2012   3247  gjelinek 	case RT_DCPU:
   2013   3792     akolb 		/* Make sure there isn't already a cpu-set or cpu-cap entry. */
   2014   3247  gjelinek 		if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
   2015   3247  gjelinek 			zerr(gettext("The %s resource already exists."),
   2016   3247  gjelinek 			    rt_to_str(RT_DCPU));
   2017   3792     akolb 			goto bad;
   2018   3792     akolb 		}
   2019   3792     akolb 		if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) !=
   2020   3792     akolb 		    Z_NO_ENTRY) {
   2021   3792     akolb 			zerr(gettext("The %s resource already exists."),
   2022   3792     akolb 			    rt_to_str(RT_PCAP));
   2023   3247  gjelinek 			goto bad;
   2024   3247  gjelinek 		}
   2025   3247  gjelinek 
   2026   3247  gjelinek 		/* Make sure the pool property isn't set. */
   2027   3247  gjelinek 		if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
   2028   3247  gjelinek 		    strlen(pool) > 0) {
   2029   3247  gjelinek 			zerr(gettext("The %s property is already set.  "
   2030   3247  gjelinek 			    "A persistent pool is incompatible with\nthe %s "
   2031   3247  gjelinek 			    "resource."),
   2032   3247  gjelinek 			    pt_to_str(PT_POOL), rt_to_str(RT_DCPU));
   2033   3247  gjelinek 			goto bad;
   2034   3247  gjelinek 		}
   2035   3247  gjelinek 
   2036   3247  gjelinek 		bzero(&in_progress_psettab, sizeof (in_progress_psettab));
   2037   3792     akolb 		return;
   2038   3792     akolb 	case RT_PCAP:
   2039   3792     akolb 		/*
   2040   3792     akolb 		 * Make sure there isn't already a cpu-set or incompatible
   2041   3792     akolb 		 * cpu-cap rctls.
   2042   3792     akolb 		 */
   2043   3792     akolb 		if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
   2044   3792     akolb 			zerr(gettext("The %s resource already exists."),
   2045   3792     akolb 			    rt_to_str(RT_DCPU));
   2046   3792     akolb 			goto bad;
   2047   3792     akolb 		}
   2048   3792     akolb 
   2049   3792     akolb 		switch (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp)) {
   2050   3792     akolb 		case Z_ALIAS_DISALLOW:
   2051   3792     akolb 			zone_perror(rt_to_str(RT_PCAP), Z_ALIAS_DISALLOW,
   2052   6215  gjelinek 			    B_FALSE);
   2053   3792     akolb 			goto bad;
   2054   3792     akolb 
   2055   3792     akolb 		case Z_OK:
   2056   3792     akolb 			zerr(gettext("The %s resource already exists."),
   2057   3792     akolb 			    rt_to_str(RT_PCAP));
   2058   3792     akolb 			goto bad;
   2059   3792     akolb 
   2060   3792     akolb 		default:
   2061   3792     akolb 			break;
   2062   3792     akolb 		}
   2063   3247  gjelinek 		return;
   2064   3247  gjelinek 	case RT_MCAP:
   2065   3247  gjelinek 		/*
   2066   3247  gjelinek 		 * Make sure there isn't already a mem-cap entry or max-swap
   2067   3247  gjelinek 		 * or max-locked rctl.
   2068   3247  gjelinek 		 */
   2069   3247  gjelinek 		if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
   2070   3247  gjelinek 		    zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
   2071   3247  gjelinek 		    == Z_OK ||
   2072   3247  gjelinek 		    zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
   2073   3247  gjelinek 		    &tmp_mcap) == Z_OK) {
   2074   3247  gjelinek 			zerr(gettext("The %s resource or a related resource "
   2075   3247  gjelinek 			    "control already exists."), rt_to_str(RT_MCAP));
   2076   3247  gjelinek 			goto bad;
   2077   3247  gjelinek 		}
   2078   3247  gjelinek 		if (global_zone)
   2079   3247  gjelinek 			zerr(gettext("WARNING: Setting a global zone memory "
   2080   3247  gjelinek 			    "cap too low could deny\nservice "
   2081   3247  gjelinek 			    "to even the root user; "
   2082   3247  gjelinek 			    "this could render the system impossible\n"
   2083   3247  gjelinek 			    "to administer.  Please use caution."));
   2084   3247  gjelinek 		bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
   2085      0    stevel 		return;
   2086      0    stevel 	default:
   2087   6215  gjelinek 		zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
   2088   6215  gjelinek 		long_usage(CMD_ADD, B_TRUE);
   2089   6215  gjelinek 		usage(B_FALSE, HELP_RESOURCES);
   2090      0    stevel 	}
   2091      0    stevel bad:
   2092   6215  gjelinek 	global_scope = B_TRUE;
   2093      0    stevel 	end_op = -1;
   2094      0    stevel }
   2095      0    stevel 
   2096      0    stevel static void
   2097      0    stevel do_complex_rctl_val(complex_property_ptr_t cp)
   2098      0    stevel {
   2099      0    stevel 	struct zone_rctlvaltab *rctlvaltab;
   2100      0    stevel 	complex_property_ptr_t cx;
   2101   6215  gjelinek 	boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
   2102   6215  gjelinek 	    seen_action = B_FALSE;
   2103      0    stevel 	rctlblk_t *rctlblk;
   2104      0    stevel 	int err;
   2105      0    stevel 
   2106      0    stevel 	if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
   2107   6215  gjelinek 		zone_perror(zone, Z_NOMEM, B_TRUE);
   2108      0    stevel 		exit(Z_ERR);
   2109      0    stevel 	}
   2110      0    stevel 	for (cx = cp; cx != NULL; cx = cx->cp_next) {
   2111      0    stevel 		switch (cx->cp_type) {
   2112      0    stevel 		case PT_PRIV:
   2113      0    stevel 			if (seen_priv) {
   2114      0    stevel 				zerr(gettext("%s already specified"),
   2115      0    stevel 				    pt_to_str(PT_PRIV));
   2116      0    stevel 				goto bad;
   2117      0    stevel 			}
   2118      0    stevel 			(void) strlcpy(rctlvaltab->zone_rctlval_priv,
   2119      0    stevel 			    cx->cp_value,
   2120      0    stevel 			    sizeof (rctlvaltab->zone_rctlval_priv));
   2121   6215  gjelinek 			seen_priv = B_TRUE;
   2122      0    stevel 			break;
   2123      0    stevel 		case PT_LIMIT:
   2124      0    stevel 			if (seen_limit) {
   2125      0    stevel 				zerr(gettext("%s already specified"),
   2126      0    stevel 				    pt_to_str(PT_LIMIT));
   2127      0    stevel 				goto bad;
   2128      0    stevel 			}
   2129      0    stevel 			(void) strlcpy(rctlvaltab->zone_rctlval_limit,
   2130      0    stevel 			    cx->cp_value,
   2131      0    stevel 			    sizeof (rctlvaltab->zone_rctlval_limit));
   2132   6215  gjelinek 			seen_limit = B_TRUE;
   2133      0    stevel 			break;
   2134      0    stevel 		case PT_ACTION:
   2135      0    stevel 			if (seen_action) {
   2136      0    stevel 				zerr(gettext("%s already specified"),
   2137      0    stevel 				    pt_to_str(PT_ACTION));
   2138      0    stevel 				goto bad;
   2139      0    stevel 			}
   2140      0    stevel 			(void) strlcpy(rctlvaltab->zone_rctlval_action,
   2141      0    stevel 			    cx->cp_value,
   2142      0    stevel 			    sizeof (rctlvaltab->zone_rctlval_action));
   2143   6215  gjelinek 			seen_action = B_TRUE;
   2144      0    stevel 			break;
   2145      0    stevel 		default:
   2146      0    stevel 			zone_perror(pt_to_str(PT_VALUE),
   2147   6215  gjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
   2148   6215  gjelinek 			long_usage(CMD_ADD, B_TRUE);
   2149   6215  gjelinek 			usage(B_FALSE, HELP_PROPS);
   2150      0    stevel 			zonecfg_free_rctl_value_list(rctlvaltab);
   2151      0    stevel 			return;
   2152      0    stevel 		}
   2153      0    stevel 	}
   2154      0    stevel 	if (!seen_priv)
   2155      0    stevel 		zerr(gettext("%s not specified"), pt_to_str(PT_PRIV));
   2156      0    stevel 	if (!seen_limit)
   2157      0    stevel 		zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT));
   2158      0    stevel 	if (!seen_action)
   2159      0    stevel 		zerr(gettext("%s not specified"), pt_to_str(PT_ACTION));
   2160      0    stevel 	if (!seen_priv || !seen_limit || !seen_action)
   2161      0    stevel 		goto bad;
   2162      0    stevel 	rctlvaltab->zone_rctlval_next = NULL;
   2163      0    stevel 	rctlblk = alloca(rctlblk_size());
   2164      0    stevel 	/*
   2165      0    stevel 	 * Make sure the rctl value looks roughly correct; we won't know if
   2166      0    stevel 	 * it's truly OK until we verify the configuration on the target
   2167      0    stevel 	 * system.
   2168      0    stevel 	 */
   2169      0    stevel 	if (zonecfg_construct_rctlblk(rctlvaltab, rctlblk) != Z_OK ||
   2170      0    stevel 	    !zonecfg_valid_rctlblk(rctlblk)) {
   2171      0    stevel 		zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL),
   2172      0    stevel 		    pt_to_str(PT_VALUE));
   2173      0    stevel 		goto bad;
   2174      0    stevel 	}
   2175      0    stevel 	err = zonecfg_add_rctl_value(&in_progress_rctltab, rctlvaltab);
   2176      0    stevel 	if (err != Z_OK)
   2177   6215  gjelinek 		zone_perror(pt_to_str(PT_VALUE), err, B_TRUE);
   2178      0    stevel 	return;
   2179      0    stevel 
   2180      0    stevel bad:
   2181      0    stevel 	zonecfg_free_rctl_value_list(rctlvaltab);
   2182      0    stevel }
   2183      0    stevel 
   2184      0    stevel static void
   2185      0    stevel add_property(cmd_t *cmd)
   2186      0    stevel {
   2187      0    stevel 	char *prop_id;
   2188      0    stevel 	int err, res_type, prop_type;
   2189      0    stevel 	property_value_ptr_t pp;
   2190      0    stevel 	list_property_ptr_t l;
   2191      0    stevel 
   2192      0    stevel 	res_type = resource_scope;
   2193      0    stevel 	prop_type = cmd->cmd_prop_name[0];
   2194      0    stevel 	if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
   2195   6215  gjelinek 		long_usage(CMD_ADD, B_TRUE);
   2196      0    stevel 		return;
   2197      0    stevel 	}
   2198      0    stevel 
   2199      0    stevel 	if (cmd->cmd_prop_nv_pairs != 1) {
   2200   6215  gjelinek 		long_usage(CMD_ADD, B_TRUE);
   2201   6215  gjelinek 		return;
   2202   6215  gjelinek 	}
   2203   6215  gjelinek 
   2204   6215  gjelinek 	if (initialize(B_TRUE) != Z_OK)
   2205      0    stevel 		return;
   2206      0    stevel 
   2207      0    stevel 	switch (res_type) {
   2208      0    stevel 	case RT_FS:
   2209      0    stevel 		if (prop_type != PT_OPTIONS) {
   2210      0    stevel 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
   2211   6215  gjelinek 			    B_TRUE);
   2212   6215  gjelinek 			long_usage(CMD_ADD, B_TRUE);
   2213   6215  gjelinek 			usage(B_FALSE, HELP_PROPS);
   2214      0    stevel 			return;
   2215      0    stevel 		}
   2216      0    stevel 		pp = cmd->cmd_property_ptr[0];
   2217      0    stevel 		if (pp->pv_type != PROP_VAL_SIMPLE &&
   2218      0    stevel 		    pp->pv_type != PROP_VAL_LIST) {
   2219      0    stevel 			zerr(gettext("A %s or %s value was expected here."),
   2220      0    stevel 			    pvt_to_str(PROP_VAL_SIMPLE),
   2221      0    stevel 			    pvt_to_str(PROP_VAL_LIST));
   2222   6215  gjelinek 			saw_error = B_TRUE;
   2223      0    stevel 			return;
   2224      0    stevel 		}
   2225      0    stevel 		if (pp->pv_type == PROP_VAL_SIMPLE) {
   2226      0    stevel 			if (pp->pv_simple == NULL) {
   2227   6215  gjelinek 				long_usage(CMD_ADD, B_TRUE);
   2228      0    stevel 				return;
   2229      0    stevel 			}
   2230      0    stevel 			prop_id = pp->pv_simple;
   2231      0    stevel 			err = zonecfg_add_fs_option(&in_progress_fstab,
   2232      0    stevel 			    prop_id);
   2233      0    stevel 			if (err != Z_OK)
   2234   6215  gjelinek 				zone_perror(pt_to_str(prop_type), err, B_TRUE);
   2235      0    stevel 		} else {
   2236      0    stevel 			list_property_ptr_t list;
   2237      0    stevel 
   2238      0    stevel 			for (list = pp->pv_list; list != NULL;
   2239      0    stevel 			    list = list->lp_next) {
   2240      0    stevel 				prop_id = list->lp_simple;
   2241      0    stevel 				if (prop_id == NULL)
   2242      0    stevel 					break;
   2243      0    stevel 				err = zonecfg_add_fs_option(
   2244      0    stevel 				    &in_progress_fstab, prop_id);
   2245      0    stevel 				if (err != Z_OK)
   2246      0    stevel 					zone_perror(pt_to_str(prop_type), err,
   2247   6215  gjelinek 					    B_TRUE);
   2248      0    stevel 			}
   2249      0    stevel 		}
   2250      0    stevel 		return;
   2251      0    stevel 	case RT_RCTL:
   2252      0    stevel 		if (prop_type != PT_VALUE) {
   2253      0    stevel 			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
   2254   6215  gjelinek 			    B_TRUE);
   2255   6215  gjelinek 			long_usage(CMD_ADD, B_TRUE);
   2256   6215  gjelinek 			usage(B_FALSE, HELP_PROPS);
   2257      0    stevel 			return;
   2258      0    stevel 		}
   2259      0    stevel 		pp = cmd->cmd_property_ptr[0];
   2260      0    stevel 		if (pp->pv_type != PROP_VAL_COMPLEX &&
   2261      0    stevel 		    pp->pv_type != PROP_VAL_LIST) {
   2262      0    stevel 			zerr(gettext("A %s or %s value was expected here."),
   2263      0    stevel 			    pvt_to_str(PROP_VAL_COMPLEX),
   2264      0    stevel 			    pvt_to_str(PROP_VAL_LIST));
   2265   6215  gjelinek 			saw_error = B_TRUE;
   2266      0    stevel 			return;
   2267      0    stevel 		}
   2268      0    stevel 		if (pp->pv_type == PROP_VAL_COMPLEX) {
   2269      0    stevel 			do_complex_rctl_val(pp->pv_complex);
   2270      0    stevel 			return;
   2271      0    stevel 		}
   2272      0    stevel 		for (l = pp->pv_list; l != NULL; l = l->lp_next)
   2273      0    stevel 			do_complex_rctl_val(l->lp_complex);
   2274      0    stevel 		return;
   2275      0    stevel 	default:
   2276   6215  gjelinek 		zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
   2277   6215  gjelinek 		long_usage(CMD_ADD, B_TRUE);
   2278   6215  gjelinek 		usage(B_FALSE, HELP_RESOURCES);
   2279      0    stevel 		return;
   2280      0    stevel 	}
   2281      0    stevel }
   2282      0    stevel 
   2283   3247  gjelinek static boolean_t
   2284   3247  gjelinek gz_invalid_resource(int type)
   2285   3247  gjelinek {
   2286   3247  gjelinek 	return (global_zone && (type == RT_FS || type == RT_IPD ||
   2287   3247  gjelinek 	    type == RT_NET || type == RT_DEVICE || type == RT_ATTR ||
   2288   3247  gjelinek 	    type == RT_DATASET));
   2289   3247  gjelinek }
   2290   3247  gjelinek 
   2291   3247  gjelinek static boolean_t
   2292   3247  gjelinek gz_invalid_rt_property(int type)
   2293   3247  gjelinek {
   2294   3247  gjelinek 	return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH ||
   2295   3247  gjelinek 	    type == RT_AUTOBOOT || type == RT_LIMITPRIV ||
   2296   3448  dh155122 	    type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED ||
   2297   8662    Jordan 	    type == RT_IPTYPE || type == RT_HOSTID));
   2298   3247  gjelinek }
   2299   3247  gjelinek 
   2300   3247  gjelinek static boolean_t
   2301   3247  gjelinek gz_invalid_property(int type)
   2302   3247  gjelinek {
   2303   3247  gjelinek 	return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH ||
   2304   3247  gjelinek 	    type == PT_AUTOBOOT || type == PT_LIMITPRIV ||
   2305   3448  dh155122 	    type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED ||
   2306   8662    Jordan 	    type == PT_IPTYPE || type == PT_HOSTID));
   2307   3247  gjelinek }
   2308   3247  gjelinek 
   2309      0    stevel void
   2310      0    stevel add_func(cmd_t *cmd)
   2311      0    stevel {
   2312      0    stevel 	int arg;
   2313   6215  gjelinek 	boolean_t arg_err = B_FALSE;
   2314   3691  gjelinek 
   2315   3691  gjelinek 	assert(cmd != NULL);
   2316   3691  gjelinek 
   2317   3691  gjelinek 	optind = 0;
   2318   3691  gjelinek 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
   2319      0    stevel 		switch (arg) {
   2320      0    stevel 		case '?':
   2321      0    stevel 			longer_usage(CMD_ADD);
   2322   6215  gjelinek 			arg_err = B_TRUE;
   2323   3691  gjelinek 			break;
   2324      0    stevel 		default:
   2325      0    stevel 			short_usage(CMD_ADD);
   2326   6215  gjelinek 			arg_err = B_TRUE;
   2327   3691  gjelinek 			break;
   2328   3691  gjelinek 		}
   2329   3691  gjelinek 	}
   2330   3691  gjelinek 	if (arg_err)
   2331   3691  gjelinek 		return;
   2332   3691  gjelinek 
   2333      0    stevel 	if (optind != cmd->cmd_argc) {
   2334      0    stevel 		short_usage(CMD_ADD);
   2335      0    stevel 		return;
   2336      0    stevel 	}
   2337      0    stevel 
   2338      0    stevel 	if (zone_is_read_only(CMD_ADD))
   2339      0    stevel 		return;
   2340      0    stevel 
   2341   6215  gjelinek 	if (initialize(B_TRUE) != Z_OK)
   2342      0    stevel 		return;
   2343      0    stevel 	if (global_scope) {
   2344   3247  gjelinek 		if (gz_invalid_resource(cmd->cmd_res_type)) {
   2345   3247  gjelinek 			zerr(gettext("Cannot add a %s resource to the "
   2346   3247  gjelinek 			    "global zone."), rt_to_str(cmd->cmd_res_type));
   2347   6215  gjelinek 			saw_error = B_TRUE;
   2348   6215  gjelinek 			return;
   2349   6215  gjelinek 		}
   2350   6215  gjelinek 
   2351   6215  gjelinek 		global_scope = B_FALSE;
   2352      0    stevel 		resource_scope = cmd->cmd_res_type;
   2353      0    stevel 		end_op = CMD_ADD;
   2354      0    stevel 		add_resource(cmd);
   2355      0    stevel 	} else
   2356      0    stevel 		add_property(cmd);
   2357      0    stevel }
   2358      0    stevel 
   2359    565        dp /*
   2360    565        dp  * This routine has an unusual implementation, because it tries very
   2361    565        dp  * hard to succeed in the face of a variety of failure modes.
   2362    565        dp  * The most common and most vexing occurs when the index file and
   2363    565        dp  * the /etc/zones/<zonename.xml> file are not both present.  In
   2364    565        dp  * this case, delete must eradicate as much of the zone state as is left
   2365    565        dp  * so that the user can later create a new zone with the same name.
   2366    565        dp  */
   2367      0    stevel void
   2368      0    stevel delete_func(cmd_t *cmd)
   2369      0    stevel {
   2370      0    stevel 	int err, arg, answer;
   2371      0    stevel 	char line[ZONENAME_MAX + 128];	/* enough to ask a question */
   2372   6215  gjelinek 	boolean_t force = B_FALSE;
   2373   6215  gjelinek 	boolean_t arg_err = B_FALSE;
   2374      0    stevel 
   2375      0    stevel 	optind = 0;
   2376      0    stevel 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
   2377      0    stevel 		switch (arg) {
   2378      0    stevel 		case '?':
   2379      0    stevel 			longer_usage(CMD_DELETE);
   2380   6215  gjelinek 			arg_err = B_TRUE;
   2381   6215  gjelinek 			break;
   2382   6215  gjelinek 		case 'F':
   2383   6215  gjelinek 			force = B_TRUE;
   2384      0    stevel 			break;
   2385      0    stevel 		default:
   2386      0    stevel 			short_usage(CMD_DELETE);
   2387   6215  gjelinek 			arg_err = B_TRUE;
   2388   3691  gjelinek 			break;
   2389   3691  gjelinek 		}
   2390   3691  gjelinek 	}
   2391   3691  gjelinek 	if (arg_err)
   2392   3691  gjelinek 		return;
   2393   3691  gjelinek 
   2394      0    stevel 	if (optind != cmd->cmd_argc) {
   2395      0    stevel 		short_usage(CMD_DELETE);
   2396      0    stevel 		return;
   2397      0    stevel 	}
   2398      0    stevel 
   2399      0    stevel 	if (zone_is_read_only(CMD_DELETE))
   2400      0    stevel 		return;
   2401      0    stevel 
   2402      0    stevel 	if (!force) {
   2403    565        dp 		/*
   2404    565        dp 		 * Initialize sets up the global called "handle" and warns the
   2405    565        dp 		 * user if the zone is not configured.  In force mode, we don't
   2406    565        dp 		 * trust that evaluation, and hence skip it.  (We don't need the
   2407    565        dp 		 * handle to be loaded anyway, since zonecfg_destroy is done by
   2408    565        dp 		 * zonename).  However, we also have to take care to emulate the
   2409    565        dp 		 * messages spit out by initialize; see below.
   2410    565        dp 		 */
   2411   6215  gjelinek 		if (initialize(B_TRUE) != Z_OK)
   2412    565        dp 			return;
   2413    565        dp 
   2414      0    stevel 		(void) snprintf(line, sizeof (line),
   2415      0    stevel 		    gettext("Are you sure you want to delete zone %s"), zone);
   2416   6215  gjelinek 		if ((answer = ask_yesno(B_FALSE, line)) == -1) {
   2417    565        dp 			zerr(gettext("Input not from terminal and -F not "
   2418    565        dp 			    "specified:\n%s command ignored, exiting."),
   2419    565        dp 			    cmd_to_str(CMD_DELETE));
   2420      0    stevel 			exit(Z_ERR);
   2421      0    stevel 		}
   2422      0    stevel 		if (answer != 1)
   2423      0    stevel 			return;
   2424      0    stevel 	}
   2425      0    stevel 
   2426    565        dp 	if ((err = zonecfg_destroy(zone, force)) != Z_OK) {
   2427    565        dp 		if ((err == Z_BAD_ZONE_STATE) && !force) {
   2428    565        dp 			zerr(gettext("Zone %s not in %s state; %s not "
   2429    565        dp 			    "allowed.  Use -F to force %s."),
   2430    565        dp 			    zone, zone_state_str(ZONE_STATE_CONFIGURED),
   2431    565        dp 			    cmd_to_str(CMD_DELETE), cmd_to_str(CMD_DELETE));
   2432    565        dp 		} else {
   2433   6215  gjelinek 			zone_perror(zone, err, B_TRUE);
   2434   6215  gjelinek 		}
   2435   6215  gjelinek 	}
   2436   6215  gjelinek 	need_to_commit = B_FALSE;
   2437    565        dp 
   2438    565        dp 	/*
   2439    565        dp 	 * Emulate initialize's messaging; if there wasn't a valid handle to
   2440    565        dp 	 * begin with, then user had typed delete (or delete -F) multiple
   2441    565        dp 	 * times.  So we emit a message.
   2442    565        dp 	 *
   2443    565        dp 	 * We only do this in the 'force' case because normally, initialize()
   2444    565        dp 	 * takes care of this for us.
   2445    565        dp 	 */
   2446    565        dp 	if (force && zonecfg_check_handle(handle) != Z_OK && interactive_mode)
   2447    565        dp 		(void) printf(gettext("Use '%s' to begin "
   2448    565        dp 		    "configuring a new zone.\n"), cmd_to_str(CMD_CREATE));
   2449      0    stevel 
   2450      0    stevel 	/*
   2451      0    stevel 	 * Time for a new handle: finish the old one off first
   2452      0    stevel 	 * then get a new one properly to avoid leaks.
   2453      0    stevel 	 */
   2454    565        dp 	if (got_handle) {
   2455    565        dp 		zonecfg_fini_handle(handle);
   2456    565        dp 		if ((handle = zonecfg_init_handle()) == NULL) {
   2457   6215  gjelinek 			zone_perror(execname, Z_NOMEM, B_TRUE);
   2458    565        dp 			exit(Z_ERR);
   2459    565        dp 		}
   2460    565        dp 		if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) {
   2461    565        dp 			/* If there was no zone before, that's OK */
   2462    565        dp 			if (err != Z_NO_ZONE)
   2463   6215  gjelinek 				zone_perror(zone, err, B_TRUE);
   2464   6215  gjelinek 			got_handle = B_FALSE;
   2465   6215  gjelinek 		}
   2466   6215  gjelinek 	}
   2467   6215  gjelinek }
   2468   6215  gjelinek 
   2469   6215  gjelinek static int
   2470   6215  gjelinek fill_in_fstab(cmd_t *cmd, struct zone_fstab *fstab, boolean_t fill_in_only)
   2471   6215  gjelinek {
   2472   6215  gjelinek 	int err, i;
   2473   6215  gjelinek 	property_value_ptr_t pp;
   2474   6215  gjelinek 
   2475   6215  gjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
   2476      0    stevel 		return (err);
   2477      0    stevel 
   2478   1086  vp157776 	bzero(fstab, sizeof (*fstab));
   2479      0    stevel 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
   2480      0    stevel 		pp = cmd->cmd_property_ptr[i];
   2481      0    stevel 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
   2482      0    stevel 			zerr(gettext("A simple value was expected here."));
   2483   6215  gjelinek 			saw_error = B_TRUE;
   2484      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2485      0    stevel 		}
   2486      0    stevel 		switch (cmd->cmd_prop_name[i]) {
   2487      0    stevel 		case PT_DIR:
   2488      0    stevel 			(void) strlcpy(fstab->zone_fs_dir, pp->pv_simple,
   2489      0    stevel 			    sizeof (fstab->zone_fs_dir));
   2490      0    stevel 			break;
   2491      0    stevel 		case PT_SPECIAL:
   2492      0    stevel 			(void) strlcpy(fstab->zone_fs_special, pp->pv_simple,
   2493      0    stevel 			    sizeof (fstab->zone_fs_special));
   2494      0    stevel 			break;
   2495      0    stevel 		case PT_RAW:
   2496      0    stevel 			(void) strlcpy(fstab->zone_fs_raw, pp->pv_simple,
   2497      0    stevel 			    sizeof (fstab->zone_fs_raw));
   2498      0    stevel 			break;
   2499      0    stevel 		case PT_TYPE:
   2500      0    stevel 			(void) strlcpy(fstab->zone_fs_type, pp->pv_simple,
   2501      0    stevel 			    sizeof (fstab->zone_fs_type));
   2502      0    stevel 			break;
   2503      0    stevel 		default:
   2504      0    stevel 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
   2505   6215  gjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
   2506      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2507      0    stevel 		}
   2508      0    stevel 	}
   2509      0    stevel 	if (fill_in_only)
   2510      0    stevel 		return (Z_OK);
   2511      0    stevel 	return (zonecfg_lookup_filesystem(handle, fstab));
   2512      0    stevel }
   2513      0    stevel 
   2514      0    stevel static int
   2515   6215  gjelinek fill_in_ipdtab(cmd_t *cmd, struct zone_fstab *ipdtab, boolean_t fill_in_only)
   2516   6215  gjelinek {
   2517   6215  gjelinek 	int err, i;
   2518   6215  gjelinek 	property_value_ptr_t pp;
   2519   6215  gjelinek 
   2520   6215  gjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
   2521      0    stevel 		return (err);
   2522      0    stevel 
   2523   1086  vp157776 	bzero(ipdtab, sizeof (*ipdtab));
   2524      0    stevel 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
   2525      0    stevel 		pp = cmd->cmd_property_ptr[i];
   2526      0    stevel 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
   2527      0    stevel 			zerr(gettext("A simple value was expected here."));
   2528   6215  gjelinek 			saw_error = B_TRUE;
   2529      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2530      0    stevel 		}
   2531      0    stevel 		switch (cmd->cmd_prop_name[i]) {
   2532      0    stevel 		case PT_DIR:
   2533      0    stevel 			(void) strlcpy(ipdtab->zone_fs_dir, pp->pv_simple,
   2534      0    stevel 			    sizeof (ipdtab->zone_fs_dir));
   2535      0    stevel 			break;
   2536      0    stevel 		default:
   2537      0    stevel 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
   2538   6215  gjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
   2539      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2540      0    stevel 		}
   2541      0    stevel 	}
   2542      0    stevel 	if (fill_in_only)
   2543      0    stevel 		return (Z_OK);
   2544      0    stevel 	return (zonecfg_lookup_ipd(handle, ipdtab));
   2545      0    stevel }
   2546      0    stevel 
   2547      0    stevel static int
   2548   6215  gjelinek fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab,
   2549   6215  gjelinek     boolean_t fill_in_only)
   2550   6215  gjelinek {
   2551   6215  gjelinek 	int err, i;
   2552   6215  gjelinek 	property_value_ptr_t pp;
   2553   6215  gjelinek 
   2554   6215  gjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
   2555      0    stevel 		return (err);
   2556      0    stevel 
   2557   1086  vp157776 	bzero(nwiftab, sizeof (*nwiftab));
   2558      0    stevel 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
   2559      0    stevel 		pp = cmd->cmd_property_ptr[i];
   2560      0    stevel 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
   2561      0    stevel 			zerr(gettext("A simple value was expected here."));
   2562   6215  gjelinek 			saw_error = B_TRUE;
   2563      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2564      0    stevel 		}
   2565      0    stevel 		switch (cmd->cmd_prop_name[i]) {
   2566      0    stevel 		case PT_ADDRESS:
   2567      0    stevel 			(void) strlcpy(nwiftab->zone_nwif_address,
   2568      0    stevel 			    pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
   2569      0    stevel 			break;
   2570      0    stevel 		case PT_PHYSICAL:
   2571      0    stevel 			(void) strlcpy(nwiftab->zone_nwif_physical,
   2572      0    stevel 			    pp->pv_simple,
   2573      0    stevel 			    sizeof (nwiftab->zone_nwif_physical));
   2574      0    stevel 			break;
   2575   6076    gfaden 		case PT_DEFROUTER:
   2576   6076    gfaden 			(void) strlcpy(nwiftab->zone_nwif_defrouter,
   2577   6076    gfaden 			    pp->pv_simple,
   2578   6076    gfaden 			    sizeof (nwiftab->zone_nwif_defrouter));
   2579   6076    gfaden 			break;
   2580      0    stevel 		default:
   2581      0    stevel 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
   2582   6215  gjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
   2583      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2584      0    stevel 		}
   2585      0    stevel 	}
   2586      0    stevel 	if (fill_in_only)
   2587      0    stevel 		return (Z_OK);
   2588      0    stevel 	err = zonecfg_lookup_nwif(handle, nwiftab);
   2589      0    stevel 	return (err);
   2590      0    stevel }
   2591      0    stevel 
   2592      0    stevel static int
   2593   6215  gjelinek fill_in_devtab(cmd_t *cmd, struct zone_devtab *devtab, boolean_t fill_in_only)
   2594   6215  gjelinek {
   2595   6215  gjelinek 	int err, i;
   2596   6215  gjelinek 	property_value_ptr_t pp;
   2597   6215  gjelinek 
   2598   6215  gjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
   2599      0    stevel 		return (err);
   2600      0    stevel 
   2601   1086  vp157776 	bzero(devtab, sizeof (*devtab));
   2602      0    stevel 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
   2603      0    stevel 		pp = cmd->cmd_property_ptr[i];
   2604      0    stevel 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
   2605      0    stevel 			zerr(gettext("A simple value was expected here."));
   2606   6215  gjelinek 			saw_error = B_TRUE;
   2607      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2608      0    stevel 		}
   2609      0    stevel 		switch (cmd->cmd_prop_name[i]) {
   2610      0    stevel 		case PT_MATCH:
   2611      0    stevel 			(void) strlcpy(devtab->zone_dev_match, pp->pv_simple,
   2612      0    stevel 			    sizeof (devtab->zone_dev_match));
   2613      0    stevel 			break;
   2614      0    stevel 		default:
   2615      0    stevel 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
   2616   6215  gjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
   2617      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2618      0    stevel 		}
   2619      0    stevel 	}
   2620      0    stevel 	if (fill_in_only)
   2621      0    stevel 		return (Z_OK);
   2622      0    stevel 	err = zonecfg_lookup_dev(handle, devtab);
   2623      0    stevel 	return (err);
   2624      0    stevel }
   2625      0    stevel 
   2626      0    stevel static int
   2627   6215  gjelinek fill_in_rctltab(cmd_t *cmd, struct zone_rctltab *rctltab,
   2628   6215  gjelinek     boolean_t fill_in_only)
   2629   6215  gjelinek {
   2630   6215  gjelinek 	int err, i;
   2631   6215  gjelinek 	property_value_ptr_t pp;
   2632   6215  gjelinek 
   2633   6215  gjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
   2634      0    stevel 		return (err);
   2635      0    stevel 
   2636   1086  vp157776 	bzero(rctltab, sizeof (*rctltab));
   2637      0    stevel 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
   2638      0    stevel 		pp = cmd->cmd_property_ptr[i];
   2639      0    stevel 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
   2640      0    stevel 			zerr(gettext("A simple value was expected here."));
   2641   6215  gjelinek 			saw_error = B_TRUE;
   2642      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2643      0    stevel 		}
   2644      0    stevel 		switch (cmd->cmd_prop_name[i]) {
   2645      0    stevel 		case PT_NAME:
   2646      0    stevel 			(void) strlcpy(rctltab->zone_rctl_name, pp->pv_simple,
   2647      0    stevel 			    sizeof (rctltab->zone_rctl_name));
   2648      0    stevel 			break;
   2649      0    stevel 		default:
   2650      0    stevel 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
   2651   6215  gjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
   2652      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2653      0    stevel 		}
   2654      0    stevel 	}
   2655      0    stevel 	if (fill_in_only)
   2656      0    stevel 		return (Z_OK);
   2657      0    stevel 	err = zonecfg_lookup_rctl(handle, rctltab);
   2658      0    stevel 	return (err);
   2659      0    stevel }
   2660      0    stevel 
   2661      0    stevel static int
   2662   6215  gjelinek fill_in_attrtab(cmd_t *cmd, struct zone_attrtab *attrtab,
   2663   6215  gjelinek     boolean_t fill_in_only)
   2664   6215  gjelinek {
   2665   6215  gjelinek 	int err, i;
   2666   6215  gjelinek 	property_value_ptr_t pp;
   2667   6215  gjelinek 
   2668   6215  gjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
   2669      0    stevel 		return (err);
   2670      0    stevel 
   2671   1086  vp157776 	bzero(attrtab, sizeof (*attrtab));
   2672      0    stevel 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
   2673      0    stevel 		pp = cmd->cmd_property_ptr[i];
   2674      0    stevel 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
   2675      0    stevel 			zerr(gettext("A simple value was expected here."));
   2676   6215  gjelinek 			saw_error = B_TRUE;
   2677      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2678      0    stevel 		}
   2679      0    stevel 		switch (cmd->cmd_prop_name[i]) {
   2680      0    stevel 		case PT_NAME:
   2681      0    stevel 			(void) strlcpy(attrtab->zone_attr_name, pp->pv_simple,
   2682      0    stevel 			    sizeof (attrtab->zone_attr_name));
   2683      0    stevel 			break;
   2684      0    stevel 		case PT_TYPE:
   2685      0    stevel 			(void) strlcpy(attrtab->zone_attr_type, pp->pv_simple,
   2686      0    stevel 			    sizeof (attrtab->zone_attr_type));
   2687      0    stevel 			break;
   2688      0    stevel 		case PT_VALUE:
   2689      0    stevel 			(void) strlcpy(attrtab->zone_attr_value, pp->pv_simple,
   2690      0    stevel 			    sizeof (attrtab->zone_attr_value));
   2691      0    stevel 			break;
   2692      0    stevel 		default:
   2693      0    stevel 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
   2694   6215  gjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
   2695      0    stevel 			return (Z_INSUFFICIENT_SPEC);
   2696      0    stevel 		}
   2697      0    stevel 	}
   2698      0    stevel 	if (fill_in_only)
   2699      0    stevel 		return (Z_OK);
   2700      0    stevel 	err = zonecfg_lookup_attr(handle, attrtab);
   2701      0    stevel 	return (err);
   2702      0    stevel }
   2703      0    stevel 
   2704    789    ahrens static int
   2705   6215  gjelinek fill_in_dstab(cmd_t *cmd, struct zone_dstab *dstab, boolean_t fill_in_only)
   2706   6215  gjelinek {
   2707   6215  gjelinek 	int err, i;
   2708   6215  gjelinek 	property_value_ptr_t pp;
   2709   6215  gjelinek 
   2710   6215  gjelinek 	if ((err = initialize(B_TRUE)) != Z_OK)
   2711    789    ahrens 		return (err);
   2712    789    ahrens 
   2713    789    ahrens 	dstab->zone_dataset_name[0] = '\0';
   2714    789    ahrens 	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
   2715    789    ahrens 		pp = cmd->cmd_property_ptr[i];
   2716    789    ahrens 		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
   2717    789    ahrens 			zerr(gettext("A simple value was expected here."));
   2718   6215  gjelinek 			saw_error = B_TRUE;
   2719    789    ahrens 			return (Z_INSUFFICIENT_SPEC);
   2720    789    ahrens 		}
   2721    789    ahrens 		switch (cmd->cmd_prop_name[i]) {
   2722    789    ahrens 		case PT_NAME:
   2723    789    ahrens 			(void) strlcpy(dstab->zone_dataset_name, pp->pv_simple,
   2724    789    ahrens 			    sizeof (dstab->zone_dataset_name));
   2725    789    ahrens 			break;
   2726    789    ahrens 		default:
   2727    789    ahrens 			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
   2728   6215  gjelinek 			    Z_NO_PROPERTY_TYPE, B_TRUE);
   2729    789    ahrens 			return (Z_INSUFFICIENT_SPEC);
   2730    789    ahrens 		}
   2731    789    ahrens 	}
   2732    789    ahrens 	if (fill_in_only)
   2733    789    ahrens 		return (Z_OK);
   2734    789    ahrens 	return (zonecfg_lookup_ds(handle, dstab));
   2735    789    ahrens }
   2736    789    ahrens 
   2737      0    stevel static void
   2738   3247  gjelinek remove_aliased_rctl(int type, char *name)
   2739   3247  gjelinek {
   2740   3247  gjelinek 	int err;
   2741   3247  gjelinek 	uint64_t tmp;
   2742   3247  gjelinek 
   2743   3247  gjelinek 	if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) {
   2744   3247  gjelinek 		zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
   2745   3247  gjelinek 		    zonecfg_strerror(err));
   2746   6215  gjelinek 		saw_error = B_TRUE;
   2747   3247  gjelinek 		return;
   2748   3247  gjelinek 	}
   2749   3247  gjelinek 	if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) {
   2750   3247  gjelinek 		zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
   2751   3247  gjelinek 		    zonecfg_strerror(err));
   2752   6215  gjelinek 		saw_error = B_TRUE;
   2753   6215  gjelinek 	} else {
   2754   6215  gjelinek 		need_to_commit = B_TRUE;
   2755   3247  gjelinek 	}
   2756   3247  gjelinek }
   2757   3247  gjelinek 
   2758   3247  gjelinek static boolean_t
   2759   3247  gjelinek prompt_remove_resource(cmd_t *cmd, char *rsrc)
   2760   3247  gjelinek {
   2761   3247  gjelinek 	int num;
   2762   3247  gjelinek 	int answer;
   2763   3247  gjelinek 	int arg;
   2764   3247  gjelinek 	boolean_t force = B_FALSE;
   2765   3247  gjelinek 	char prompt[128];
   2766   6215  gjelinek 	boolean_t arg_err = B_FALSE;
   2767   3247  gjelinek 
   2768   3247  gjelinek 	optind = 0;
   2769   3247  gjelinek 	while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
   2770   3247  gjelinek 		switch (arg) {
   2771   3247  gjelinek 		case 'F':
   2772   3247  gjelinek 			force = B_TRUE;
   2773   3247  gjelinek 			break;
   2774   3247  gjelinek 		default:
   2775   6215  gjelinek 			arg_err = B_TRUE;
   2776   3691  gjelinek 			break;
   2777   3691  gjelinek 		}
   2778   3691  gjelinek 	}
   2779   3691  gjelinek 	if (arg_err)
   2780   3691  gjelinek 		return (B_FALSE);
   2781   3691  gjelinek 
   2782   3247  gjelinek 
   2783   3247  gjelinek 	num = zonecfg_num_resources(handle, rsrc);
   2784   3247  gjelinek 
   2785   3247  gjelinek 	if (num == 0) {
   2786   3247  gjelinek 		z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY,
   2787   6215  gjelinek 		    B_TRUE);
   2788   3247  gjelinek 		return (B_FALSE);
   2789   3247  gjelinek 	}
   2790   3247  gjelinek 	if (num > 1 && !force) {
   2791   3247  gjelinek 		if (!interactive_mode) {
   2792   3247  gjelinek 			zerr(gettext("There are multiple instances of this "
   2793   3247  gjelinek 			    "resource.  Either qualify the resource to\n"
   2794   3247  gjelinek 			    "remove a single instance or use the -F option to "
   2795   3247  gjelinek 			    "remove all instances."));
   2796   6215  gjelinek 			saw_error = B_TRUE;
   2797   3247  gjelinek 			return (B_FALSE);
   2798   3247  gjelinek 		}
   2799   3247  gjelinek 		(void) snprintf(prompt, sizeof (prompt), gettext(
   2800   3247  gjelinek 		    "Are you sure you want to remove ALL '%s' resources"),
   2801   3247  gjelinek 		    rsrc);
   2802   6215  gjelinek 		answer = ask_yesno(B_FALSE, prompt);
   2803   3247  gjelinek 		if (answer == -1) {
   2804   3247  gjelinek 			zerr(gettext("Resource incomplete."));
   2805   3247  gjelinek 			return (B_FALSE);
   2806   3247  gjelinek 		}
   2807   3247  gjelinek 		if (answer != 1)
   2808   3247  gjelinek 			return (B_FALSE);
   2809   3247  gjelinek 	}
   2810   3247  gjelinek 	return (B_TRUE);
   2811   3247  gjelinek }
   2812   3247  gjelinek 
   2813   3247  gjelinek static void
   2814   3247  gjelinek remove_fs(cmd_t *cmd)
   2815   3247  gjelinek {
   2816   3247  gjelinek 	int err;
   2817   3247  gjelinek 
   2818   3247  gjelinek 	/* traditional, qualified fs removal */
   2819   3247  gjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
   2820   3247  gjelinek 		struct zone_fstab fstab;
   2821   3247  gjelinek 
   2822   6215  gjelinek 		if ((err = fill_in_fstab(cmd, &fstab, B_FALSE)) != Z_OK) {
   2823   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
   2824   3247  gjelinek 			return;
   2825   3247  gjelinek 		}
   2826   3247  gjelinek 		if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK)
   2827   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
   2828   6215  gjelinek 		else
   2829   6215  gjelinek 			need_to_commit = B_TRUE;
   2830   3247  gjelinek 		zonecfg_free_fs_option_list(fstab.zone_fs_options);
   2831   3247  gjelinek 		return;
   2832   3247  gjelinek 	}
   2833   3247  gjelinek 
   2834   3247  gjelinek 	/*
   2835   3247  gjelinek 	 * unqualified fs removal.  remove all fs's but prompt if more
   2836   3247  gjelinek 	 * than one.
   2837   3247  gjelinek 	 */
   2838   3247  gjelinek 	if (!prompt_remove_resource(cmd, "fs"))
   2839   3247  gjelinek 		return;
   2840   3247  gjelinek 
   2841   3247  gjelinek 	if ((err = zonecfg_del_all_resources(handle, "fs")) != Z_OK)
   2842   6215  gjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
   2843   6215  gjelinek 	else
   2844   6215  gjelinek 		need_to_commit = B_TRUE;
   2845   3247  gjelinek }
   2846   3247  gjelinek 
   2847   3247  gjelinek static void
   2848   3247  gjelinek remove_ipd(cmd_t *cmd)
   2849   3247  gjelinek {
   2850   3247  gjelinek 	int err;
   2851   3247  gjelinek 
   2852   3247  gjelinek 	if (state_atleast(ZONE_STATE_INSTALLED)) {
   2853   3247  gjelinek 		zerr(gettext("Zone %s already installed; %s %s not allowed."),
   2854   3247  gjelinek 		    zone, cmd_to_str(CMD_REMOVE), rt_to_str(RT_IPD));
   2855   3247  gjelinek 		return;
   2856   3247  gjelinek 	}
   2857   3247  gjelinek 
   2858   3247  gjelinek 	/* traditional, qualified ipd removal */
   2859   3247  gjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
   2860   3247  gjelinek 		struct zone_fstab fstab;
   2861   3247  gjelinek 
   2862   6215  gjelinek 		if ((err = fill_in_ipdtab(cmd, &fstab, B_FALSE)) != Z_OK) {
   2863   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, B_TRUE);
   2864   3247  gjelinek 			return;
   2865   3247  gjelinek 		}
   2866   3247  gjelinek 		if ((err = zonecfg_delete_ipd(handle, &fstab)) != Z_OK)
   2867   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, B_TRUE);
   2868   6215  gjelinek 		else
   2869   6215  gjelinek 			need_to_commit = B_TRUE;
   2870   3247  gjelinek 		return;
   2871   3247  gjelinek 	}
   2872   3247  gjelinek 
   2873   3247  gjelinek 	/*
   2874   3247  gjelinek 	 * unqualified ipd removal.  remove all ipds but prompt if more
   2875   3247  gjelinek 	 * than one.
   2876   3247  gjelinek 	 */
   2877   3247  gjelinek 	if (!prompt_remove_resource(cmd, "inherit-pkg-dir"))
   2878   3247  gjelinek 		return;
   2879   3247  gjelinek 
   2880   3247  gjelinek 	if ((err = zonecfg_del_all_resources(handle, "inherit-pkg-dir"))
   2881   3247  gjelinek 	    != Z_OK)
   2882   6215  gjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, B_TRUE);
   2883   6215  gjelinek 	else
   2884   6215  gjelinek 		need_to_commit = B_TRUE;
   2885   3247  gjelinek }
   2886   3247  gjelinek 
   2887   3247  gjelinek static void
   2888   3247  gjelinek remove_net(cmd_t *cmd)
   2889   3247  gjelinek {
   2890   3247  gjelinek 	int err;
   2891   3247  gjelinek 
   2892   3247  gjelinek 	/* traditional, qualified net removal */
   2893   3247  gjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
   2894   3247  gjelinek 		struct zone_nwiftab nwiftab;
   2895   3247  gjelinek 
   2896   6215  gjelinek 		if ((err = fill_in_nwiftab(cmd, &nwiftab, B_FALSE)) != Z_OK) {
   2897   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
   2898   3247  gjelinek 			return;
   2899   3247  gjelinek 		}
   2900   3247  gjelinek 		if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK)
   2901   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
   2902   6215  gjelinek 		else
   2903   6215  gjelinek 			need_to_commit = B_TRUE;
   2904   3247  gjelinek 		return;
   2905   3247  gjelinek 	}
   2906   3247  gjelinek 
   2907   3247  gjelinek 	/*
   2908   3247  gjelinek 	 * unqualified net removal.  remove all nets but prompt if more
   2909   3247  gjelinek 	 * than one.
   2910   3247  gjelinek 	 */
   2911   3247  gjelinek 	if (!prompt_remove_resource(cmd, "net"))
   2912   3247  gjelinek 		return;
   2913   3247  gjelinek 
   2914   3247  gjelinek 	if ((err = zonecfg_del_all_resources(handle, "net")) != Z_OK)
   2915   6215  gjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
   2916   6215  gjelinek 	else
   2917   6215  gjelinek 		need_to_commit = B_TRUE;
   2918   3247  gjelinek }
   2919   3247  gjelinek 
   2920   3247  gjelinek static void
   2921   3247  gjelinek remove_device(cmd_t *cmd)
   2922   3247  gjelinek {
   2923   3247  gjelinek 	int err;
   2924   3247  gjelinek 
   2925   3247  gjelinek 	/* traditional, qualified device removal */
   2926   3247  gjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
   2927   3247  gjelinek 		struct zone_devtab devtab;
   2928   3247  gjelinek 
   2929   6215  gjelinek 		if ((err = fill_in_devtab(cmd, &devtab, B_FALSE)) != Z_OK) {
   2930   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
   2931   3247  gjelinek 			return;
   2932   3247  gjelinek 		}
   2933   3247  gjelinek 		if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK)
   2934   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
   2935   6215  gjelinek 		else
   2936   6215  gjelinek 			need_to_commit = B_TRUE;
   2937   3247  gjelinek 		return;
   2938   3247  gjelinek 	}
   2939   3247  gjelinek 
   2940   3247  gjelinek 	/*
   2941   3247  gjelinek 	 * unqualified device removal.  remove all devices but prompt if more
   2942   3247  gjelinek 	 * than one.
   2943   3247  gjelinek 	 */
   2944   3247  gjelinek 	if (!prompt_remove_resource(cmd, "device"))
   2945   3247  gjelinek 		return;
   2946   3247  gjelinek 
   2947   3247  gjelinek 	if ((err = zonecfg_del_all_resources(handle, "device")) != Z_OK)
   2948   6215  gjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
   2949   6215  gjelinek 	else
   2950   6215  gjelinek 		need_to_commit = B_TRUE;
   2951   3247  gjelinek }
   2952   3247  gjelinek 
   2953   3247  gjelinek static void
   2954   3247  gjelinek remove_attr(cmd_t *cmd)
   2955   3247  gjelinek {
   2956   3247  gjelinek 	int err;
   2957   3247  gjelinek 
   2958   3247  gjelinek 	/* traditional, qualified attr removal */
   2959   3247  gjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
   2960   3247  gjelinek 		struct zone_attrtab attrtab;
   2961   3247  gjelinek 
   2962   6215  gjelinek 		if ((err = fill_in_attrtab(cmd, &attrtab, B_FALSE)) != Z_OK) {
   2963   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
   2964   3247  gjelinek 			return;
   2965   3247  gjelinek 		}
   2966   3247  gjelinek 		if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK)
   2967   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
   2968   6215  gjelinek 		else
   2969   6215  gjelinek 			need_to_commit = B_TRUE;
   2970   3247  gjelinek 		return;
   2971   3247  gjelinek 	}
   2972   3247  gjelinek 
   2973   3247  gjelinek 	/*
   2974   3247  gjelinek 	 * unqualified attr removal.  remove all attrs but prompt if more
   2975   3247  gjelinek 	 * than one.
   2976   3247  gjelinek 	 */
   2977   3247  gjelinek 	if (!prompt_remove_resource(cmd, "attr"))
   2978   3247  gjelinek 		return;
   2979   3247  gjelinek 
   2980   3247  gjelinek 	if ((err = zonecfg_del_all_resources(handle, "attr")) != Z_OK)
   2981   6215  gjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
   2982   6215  gjelinek 	else
   2983   6215  gjelinek 		need_to_commit = B_TRUE;
   2984   3247  gjelinek }
   2985   3247  gjelinek 
   2986   3247  gjelinek static void
   2987   3247  gjelinek remove_dataset(cmd_t *cmd)
   2988   3247  gjelinek {
   2989   3247  gjelinek 	int err;
   2990   3247  gjelinek 
   2991   3247  gjelinek 	/* traditional, qualified dataset removal */
   2992   3247  gjelinek 	if (cmd->cmd_prop_nv_pairs > 0) {
   2993   3247  gjelinek 		struct zone_dstab dstab;
   2994   3247  gjelinek 
   2995   6215  gjelinek 		if ((err = fill_in_dstab(cmd, &dstab, B_FALSE)) != Z_OK) {
   2996   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
   2997   3247  gjelinek 			return;
   2998   3247  gjelinek 		}
   2999   3247  gjelinek 		if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK)
   3000   6215  gjelinek 			z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
   3001   6215  gjelinek 		else
   3002   6215  gjelinek 			need_to_commit = B_TRUE;
   3003   3247  gjelinek 		return;
   3004   3247  gjelinek 	}
   3005   3247  gjelinek 
   3006   3247  gjelinek 	/*
   3007   3247  gjelinek 	 * unqualified dataset removal.  remove all datasets but prompt if more
   3008   3247  gjelinek 	 * than one.
   3009   3247  gjelinek 	 */
   3010   3247  gjelinek 	if (!prompt_remove_resource(cmd, "dataset"))
   3011   3247  gjelinek 		return;
   3012   3247  gjelinek 
   3013   3247  gjelinek 	if ((err = zonecfg_del_all_resources(handle, "dataset")) != Z_OK)
   3014   6215  gjelinek 		z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
   3015   6215  gjelinek 	else
   3016   6215  gjelinek 		need_to_commit = B_TRUE;
   3017   3247  gjelinek }
   3018   3247  gjelinek 
   3019   3247  gjelinek static void
   3020   3247  gjelinek remove_rctl(cmd_t *cmd)
   3021   3247  gjelinek {
   3022