1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * zonecfg is a lex/yacc based command interpreter used to manage zone 31*7c478bd9Sstevel@tonic-gate * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which 32*7c478bd9Sstevel@tonic-gate * the grammar (see zonecfg_grammar.y) builds up into commands, some of 33*7c478bd9Sstevel@tonic-gate * which takes resources and/or properties as arguments. See the block 34*7c478bd9Sstevel@tonic-gate * comments near the end of zonecfg_grammar.y for how the data structures 35*7c478bd9Sstevel@tonic-gate * which keep track of these resources and properties are built up. 36*7c478bd9Sstevel@tonic-gate * 37*7c478bd9Sstevel@tonic-gate * The resource/property data structures are inserted into a command 38*7c478bd9Sstevel@tonic-gate * structure (see zonecfg.h), which also keeps track of command names, 39*7c478bd9Sstevel@tonic-gate * miscellaneous arguments, and function handlers. The grammar selects 40*7c478bd9Sstevel@tonic-gate * the appropriate function handler, each of which takes a pointer to a 41*7c478bd9Sstevel@tonic-gate * command structure as its sole argument, and invokes it. The grammar 42*7c478bd9Sstevel@tonic-gate * itself is "entered" (a la the Matrix) by yyparse(), which is called 43*7c478bd9Sstevel@tonic-gate * from read_input(), our main driving function. That in turn is called 44*7c478bd9Sstevel@tonic-gate * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each 45*7c478bd9Sstevel@tonic-gate * of which is called from main() depending on how the program was invoked. 46*7c478bd9Sstevel@tonic-gate * 47*7c478bd9Sstevel@tonic-gate * The rest of this module consists of the various function handlers and 48*7c478bd9Sstevel@tonic-gate * their helper functions. Some of these functions, particularly the 49*7c478bd9Sstevel@tonic-gate * X_to_str() functions, which maps command, resource and property numbers 50*7c478bd9Sstevel@tonic-gate * to strings, are used quite liberally, as doing so results in a better 51*7c478bd9Sstevel@tonic-gate * program w/rt I18N, reducing the need for translation notes. 52*7c478bd9Sstevel@tonic-gate */ 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/varargs.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate #include <errno.h> 59*7c478bd9Sstevel@tonic-gate #include <strings.h> 60*7c478bd9Sstevel@tonic-gate #include <unistd.h> 61*7c478bd9Sstevel@tonic-gate #include <ctype.h> 62*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 63*7c478bd9Sstevel@tonic-gate #include <assert.h> 64*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 65*7c478bd9Sstevel@tonic-gate #include <zone.h> 66*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 67*7c478bd9Sstevel@tonic-gate #include <netdb.h> 68*7c478bd9Sstevel@tonic-gate #include <locale.h> 69*7c478bd9Sstevel@tonic-gate #include <libintl.h> 70*7c478bd9Sstevel@tonic-gate #include <alloca.h> 71*7c478bd9Sstevel@tonic-gate #include <regex.h> 72*7c478bd9Sstevel@tonic-gate #include <signal.h> 73*7c478bd9Sstevel@tonic-gate #include <libtecla.h> 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate #include <libzonecfg.h> 76*7c478bd9Sstevel@tonic-gate #include "zonecfg.h" 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */ 79*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 80*7c478bd9Sstevel@tonic-gate #endif 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate #define PAGER "/usr/bin/more" 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate struct help { 85*7c478bd9Sstevel@tonic-gate uint_t cmd_num; 86*7c478bd9Sstevel@tonic-gate char *cmd_name; 87*7c478bd9Sstevel@tonic-gate uint_t flags; 88*7c478bd9Sstevel@tonic-gate char *short_usage; 89*7c478bd9Sstevel@tonic-gate }; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate extern int yyparse(void); 92*7c478bd9Sstevel@tonic-gate extern int lex_lineno; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate #define MAX_LINE_LEN 1024 95*7c478bd9Sstevel@tonic-gate #define MAX_CMD_HIST 1024 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* 98*7c478bd9Sstevel@tonic-gate * Each SHELP_ should be a simple string. 99*7c478bd9Sstevel@tonic-gate */ 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate #define SHELP_ADD "add <resource-type>\n\t(global scope)\n" \ 102*7c478bd9Sstevel@tonic-gate "add <property-name> <property-value>\n\t(resource scope)" 103*7c478bd9Sstevel@tonic-gate #define SHELP_CANCEL "cancel" 104*7c478bd9Sstevel@tonic-gate #define SHELP_COMMIT "commit" 105*7c478bd9Sstevel@tonic-gate #define SHELP_CREATE "create [-F] [ -b | -t <template> ]" 106*7c478bd9Sstevel@tonic-gate #define SHELP_DELETE "delete [-F]" 107*7c478bd9Sstevel@tonic-gate #define SHELP_END "end" 108*7c478bd9Sstevel@tonic-gate #define SHELP_EXIT "exit [-F]" 109*7c478bd9Sstevel@tonic-gate #define SHELP_EXPORT "export [-f output-file]" 110*7c478bd9Sstevel@tonic-gate #define SHELP_HELP "help [commands] [syntax] [usage] [<command-name>]" 111*7c478bd9Sstevel@tonic-gate #define SHELP_INFO "info [<resource-type> [property-name=property-value]*]" 112*7c478bd9Sstevel@tonic-gate #define SHELP_REMOVE "remove <resource-type> { <property-name>=<property-" \ 113*7c478bd9Sstevel@tonic-gate "value> }\n\t(global scope)\nremove <property-name>=<property-value>" \ 114*7c478bd9Sstevel@tonic-gate "\n\t(resource scope)" 115*7c478bd9Sstevel@tonic-gate #define SHELP_REVERT "revert [-F]" 116*7c478bd9Sstevel@tonic-gate #define SHELP_SELECT "select <resource-type> { <property-name>=" \ 117*7c478bd9Sstevel@tonic-gate "<property-value> }" 118*7c478bd9Sstevel@tonic-gate #define SHELP_SET "set <property-name>=<property-value>" 119*7c478bd9Sstevel@tonic-gate #define SHELP_VERIFY "verify" 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate static struct help helptab[] = { 122*7c478bd9Sstevel@tonic-gate { CMD_ADD, "add", HELP_RES_PROPS, SHELP_ADD, }, 123*7c478bd9Sstevel@tonic-gate { CMD_CANCEL, "cancel", 0, SHELP_CANCEL, }, 124*7c478bd9Sstevel@tonic-gate { CMD_COMMIT, "commit", 0, SHELP_COMMIT, }, 125*7c478bd9Sstevel@tonic-gate { CMD_CREATE, "create", 0, SHELP_CREATE, }, 126*7c478bd9Sstevel@tonic-gate { CMD_DELETE, "delete", 0, SHELP_DELETE, }, 127*7c478bd9Sstevel@tonic-gate { CMD_END, "end", 0, SHELP_END, }, 128*7c478bd9Sstevel@tonic-gate { CMD_EXIT, "exit", 0, SHELP_EXIT, }, 129*7c478bd9Sstevel@tonic-gate { CMD_EXPORT, "export", 0, SHELP_EXPORT, }, 130*7c478bd9Sstevel@tonic-gate { CMD_HELP, "help", 0, SHELP_HELP }, 131*7c478bd9Sstevel@tonic-gate { CMD_INFO, "info", HELP_RES_PROPS, SHELP_INFO, }, 132*7c478bd9Sstevel@tonic-gate { CMD_REMOVE, "remove", HELP_RES_PROPS, SHELP_REMOVE, }, 133*7c478bd9Sstevel@tonic-gate { CMD_REVERT, "revert", 0, SHELP_REVERT, }, 134*7c478bd9Sstevel@tonic-gate { CMD_SELECT, "select", HELP_RES_PROPS, SHELP_SELECT, }, 135*7c478bd9Sstevel@tonic-gate { CMD_SET, "set", HELP_PROPS, SHELP_SET, }, 136*7c478bd9Sstevel@tonic-gate { CMD_VERIFY, "verify", 0, SHELP_VERIFY, }, 137*7c478bd9Sstevel@tonic-gate { 0 }, 138*7c478bd9Sstevel@tonic-gate }; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate #define MAX_RT_STRLEN 16 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* These *must* match the order of the RT_ define's from zonecfg.h */ 143*7c478bd9Sstevel@tonic-gate static char *res_types[] = { 144*7c478bd9Sstevel@tonic-gate "unknown", 145*7c478bd9Sstevel@tonic-gate "zonepath", 146*7c478bd9Sstevel@tonic-gate "autoboot", 147*7c478bd9Sstevel@tonic-gate "pool", 148*7c478bd9Sstevel@tonic-gate "fs", 149*7c478bd9Sstevel@tonic-gate "inherit-pkg-dir", 150*7c478bd9Sstevel@tonic-gate "net", 151*7c478bd9Sstevel@tonic-gate "device", 152*7c478bd9Sstevel@tonic-gate "rctl", 153*7c478bd9Sstevel@tonic-gate "attr", 154*7c478bd9Sstevel@tonic-gate NULL 155*7c478bd9Sstevel@tonic-gate }; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate /* These *must* match the order of the PT_ define's from zonecfg.h */ 158*7c478bd9Sstevel@tonic-gate static char *prop_types[] = { 159*7c478bd9Sstevel@tonic-gate "unknown", 160*7c478bd9Sstevel@tonic-gate "zonepath", 161*7c478bd9Sstevel@tonic-gate "autoboot", 162*7c478bd9Sstevel@tonic-gate "pool", 163*7c478bd9Sstevel@tonic-gate "dir", 164*7c478bd9Sstevel@tonic-gate "special", 165*7c478bd9Sstevel@tonic-gate "type", 166*7c478bd9Sstevel@tonic-gate "options", 167*7c478bd9Sstevel@tonic-gate "address", 168*7c478bd9Sstevel@tonic-gate "physical", 169*7c478bd9Sstevel@tonic-gate "name", 170*7c478bd9Sstevel@tonic-gate "value", 171*7c478bd9Sstevel@tonic-gate "match", 172*7c478bd9Sstevel@tonic-gate "priv", 173*7c478bd9Sstevel@tonic-gate "limit", 174*7c478bd9Sstevel@tonic-gate "action", 175*7c478bd9Sstevel@tonic-gate "raw", 176*7c478bd9Sstevel@tonic-gate NULL 177*7c478bd9Sstevel@tonic-gate }; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate /* These *must* match the order of the PT_ define's from zonecfg.h */ 180*7c478bd9Sstevel@tonic-gate static char *prop_val_types[] = { 181*7c478bd9Sstevel@tonic-gate "simple", 182*7c478bd9Sstevel@tonic-gate "complex", 183*7c478bd9Sstevel@tonic-gate "list", 184*7c478bd9Sstevel@tonic-gate }; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* 187*7c478bd9Sstevel@tonic-gate * The various _cmds[] lists below are for command tab-completion. 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate /* 191*7c478bd9Sstevel@tonic-gate * remove has a space afterwards because it has qualifiers; the other commands 192*7c478bd9Sstevel@tonic-gate * that have qualifiers (add, select and set) don't need a space here because 193*7c478bd9Sstevel@tonic-gate * they have their own _cmds[] lists below. 194*7c478bd9Sstevel@tonic-gate */ 195*7c478bd9Sstevel@tonic-gate static const char *global_scope_cmds[] = { 196*7c478bd9Sstevel@tonic-gate "add", 197*7c478bd9Sstevel@tonic-gate "commit", 198*7c478bd9Sstevel@tonic-gate "create", 199*7c478bd9Sstevel@tonic-gate "delete", 200*7c478bd9Sstevel@tonic-gate "exit", 201*7c478bd9Sstevel@tonic-gate "export", 202*7c478bd9Sstevel@tonic-gate "help", 203*7c478bd9Sstevel@tonic-gate "info", 204*7c478bd9Sstevel@tonic-gate "remove ", 205*7c478bd9Sstevel@tonic-gate "revert", 206*7c478bd9Sstevel@tonic-gate "select", 207*7c478bd9Sstevel@tonic-gate "set", 208*7c478bd9Sstevel@tonic-gate "verify", 209*7c478bd9Sstevel@tonic-gate NULL 210*7c478bd9Sstevel@tonic-gate }; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate static const char *add_cmds[] = { 213*7c478bd9Sstevel@tonic-gate "add fs", 214*7c478bd9Sstevel@tonic-gate "add inherit-pkg-dir", 215*7c478bd9Sstevel@tonic-gate "add net", 216*7c478bd9Sstevel@tonic-gate "add device", 217*7c478bd9Sstevel@tonic-gate "add rctl", 218*7c478bd9Sstevel@tonic-gate "add attr", 219*7c478bd9Sstevel@tonic-gate NULL 220*7c478bd9Sstevel@tonic-gate }; 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate static const char *select_cmds[] = { 223*7c478bd9Sstevel@tonic-gate "select fs", 224*7c478bd9Sstevel@tonic-gate "select inherit-pkg-dir", 225*7c478bd9Sstevel@tonic-gate "select net", 226*7c478bd9Sstevel@tonic-gate "select device", 227*7c478bd9Sstevel@tonic-gate "select rctl", 228*7c478bd9Sstevel@tonic-gate "select attr", 229*7c478bd9Sstevel@tonic-gate NULL 230*7c478bd9Sstevel@tonic-gate }; 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate static const char *set_cmds[] = { 233*7c478bd9Sstevel@tonic-gate "set zonepath", 234*7c478bd9Sstevel@tonic-gate "set autoboot", 235*7c478bd9Sstevel@tonic-gate "set pool", 236*7c478bd9Sstevel@tonic-gate NULL 237*7c478bd9Sstevel@tonic-gate }; 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate static const char *fs_res_scope_cmds[] = { 240*7c478bd9Sstevel@tonic-gate "add options ", 241*7c478bd9Sstevel@tonic-gate "cancel", 242*7c478bd9Sstevel@tonic-gate "end", 243*7c478bd9Sstevel@tonic-gate "exit", 244*7c478bd9Sstevel@tonic-gate "help", 245*7c478bd9Sstevel@tonic-gate "info", 246*7c478bd9Sstevel@tonic-gate "set dir=", 247*7c478bd9Sstevel@tonic-gate "set raw=", 248*7c478bd9Sstevel@tonic-gate "set special=", 249*7c478bd9Sstevel@tonic-gate "set type=", 250*7c478bd9Sstevel@tonic-gate NULL 251*7c478bd9Sstevel@tonic-gate }; 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate static const char *net_res_scope_cmds[] = { 254*7c478bd9Sstevel@tonic-gate "cancel", 255*7c478bd9Sstevel@tonic-gate "end", 256*7c478bd9Sstevel@tonic-gate "exit", 257*7c478bd9Sstevel@tonic-gate "help", 258*7c478bd9Sstevel@tonic-gate "info", 259*7c478bd9Sstevel@tonic-gate "set address=", 260*7c478bd9Sstevel@tonic-gate "set physical=", 261*7c478bd9Sstevel@tonic-gate NULL 262*7c478bd9Sstevel@tonic-gate }; 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate static const char *ipd_res_scope_cmds[] = { 265*7c478bd9Sstevel@tonic-gate "cancel", 266*7c478bd9Sstevel@tonic-gate "end", 267*7c478bd9Sstevel@tonic-gate "exit", 268*7c478bd9Sstevel@tonic-gate "help", 269*7c478bd9Sstevel@tonic-gate "info", 270*7c478bd9Sstevel@tonic-gate "set dir=", 271*7c478bd9Sstevel@tonic-gate NULL 272*7c478bd9Sstevel@tonic-gate }; 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate static const char *device_res_scope_cmds[] = { 275*7c478bd9Sstevel@tonic-gate "cancel", 276*7c478bd9Sstevel@tonic-gate "end", 277*7c478bd9Sstevel@tonic-gate "exit", 278*7c478bd9Sstevel@tonic-gate "help", 279*7c478bd9Sstevel@tonic-gate "info", 280*7c478bd9Sstevel@tonic-gate "set match=", 281*7c478bd9Sstevel@tonic-gate NULL 282*7c478bd9Sstevel@tonic-gate }; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate static const char *attr_res_scope_cmds[] = { 285*7c478bd9Sstevel@tonic-gate "cancel", 286*7c478bd9Sstevel@tonic-gate "end", 287*7c478bd9Sstevel@tonic-gate "exit", 288*7c478bd9Sstevel@tonic-gate "help", 289*7c478bd9Sstevel@tonic-gate "info", 290*7c478bd9Sstevel@tonic-gate "set name=", 291*7c478bd9Sstevel@tonic-gate "set type=", 292*7c478bd9Sstevel@tonic-gate "set value=", 293*7c478bd9Sstevel@tonic-gate NULL 294*7c478bd9Sstevel@tonic-gate }; 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate static const char *rctl_res_scope_cmds[] = { 297*7c478bd9Sstevel@tonic-gate "add value ", 298*7c478bd9Sstevel@tonic-gate "cancel", 299*7c478bd9Sstevel@tonic-gate "end", 300*7c478bd9Sstevel@tonic-gate "exit", 301*7c478bd9Sstevel@tonic-gate "help", 302*7c478bd9Sstevel@tonic-gate "info", 303*7c478bd9Sstevel@tonic-gate "set name=", 304*7c478bd9Sstevel@tonic-gate NULL 305*7c478bd9Sstevel@tonic-gate }; 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate /* Global variables */ 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate /* set early in main(), never modified thereafter, used all over the place */ 310*7c478bd9Sstevel@tonic-gate static char *execname; 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate /* set in main(), used all over the place */ 313*7c478bd9Sstevel@tonic-gate static zone_dochandle_t handle; 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate /* used all over the place */ 316*7c478bd9Sstevel@tonic-gate static char *zone; 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate /* set in modifying functions, checked in read_input() */ 319*7c478bd9Sstevel@tonic-gate static bool need_to_commit = FALSE; 320*7c478bd9Sstevel@tonic-gate bool saw_error; 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate /* set in yacc parser, checked in read_input() */ 323*7c478bd9Sstevel@tonic-gate bool newline_terminated; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* set in main(), checked in lex error handler */ 326*7c478bd9Sstevel@tonic-gate bool cmd_file_mode; 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate /* set in exit_func(), checked in read_input() */ 329*7c478bd9Sstevel@tonic-gate static bool time_to_exit = FALSE, force_exit = FALSE; 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate /* used in short_usage() and zerr() */ 332*7c478bd9Sstevel@tonic-gate static char *cmd_file_name = NULL; 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate /* checked in read_input() and other places */ 335*7c478bd9Sstevel@tonic-gate static bool ok_to_prompt = FALSE; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* set and checked in initialize() */ 338*7c478bd9Sstevel@tonic-gate static bool got_handle = FALSE; 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate /* initialized in do_interactive(), checked in initialize() */ 341*7c478bd9Sstevel@tonic-gate static bool interactive_mode; 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate /* set in main(), checked in multiple places */ 344*7c478bd9Sstevel@tonic-gate static bool read_only_mode; 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate /* set in check_if_zone_already_exists(), checked in save_it() */ 347*7c478bd9Sstevel@tonic-gate static bool new_zone = FALSE; 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate static bool global_scope = TRUE; /* scope is outer/global or inner/resource */ 350*7c478bd9Sstevel@tonic-gate static int resource_scope; /* should be in the RT_ list from zonecfg.h */ 351*7c478bd9Sstevel@tonic-gate static int end_op = -1; /* operation on end is either add or modify */ 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate int num_prop_vals; /* for grammar */ 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate /* 356*7c478bd9Sstevel@tonic-gate * These are for keeping track of resources as they are specified as part of 357*7c478bd9Sstevel@tonic-gate * the multi-step process. They should be initialized by add_resource() or 358*7c478bd9Sstevel@tonic-gate * select_func() and filled in by add_property() or set_func(). 359*7c478bd9Sstevel@tonic-gate */ 360*7c478bd9Sstevel@tonic-gate static struct zone_fstab old_fstab, in_progress_fstab; 361*7c478bd9Sstevel@tonic-gate static struct zone_fstab old_ipdtab, in_progress_ipdtab; 362*7c478bd9Sstevel@tonic-gate static struct zone_nwiftab old_nwiftab, in_progress_nwiftab; 363*7c478bd9Sstevel@tonic-gate static struct zone_devtab old_devtab, in_progress_devtab; 364*7c478bd9Sstevel@tonic-gate static struct zone_rctltab old_rctltab, in_progress_rctltab; 365*7c478bd9Sstevel@tonic-gate static struct zone_attrtab old_attrtab, in_progress_attrtab; 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate static GetLine *gl; /* The gl_get_line() resource object */ 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate /* Functions begin here */ 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate static bool 372*7c478bd9Sstevel@tonic-gate initial_match(const char *line1, const char *line2, int word_end) 373*7c478bd9Sstevel@tonic-gate { 374*7c478bd9Sstevel@tonic-gate if (word_end <= 0) 375*7c478bd9Sstevel@tonic-gate return (TRUE); 376*7c478bd9Sstevel@tonic-gate return (strncmp(line1, line2, word_end) == 0); 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate static int 380*7c478bd9Sstevel@tonic-gate add_stuff(WordCompletion *cpl, const char *line1, const char **list, 381*7c478bd9Sstevel@tonic-gate int word_end) 382*7c478bd9Sstevel@tonic-gate { 383*7c478bd9Sstevel@tonic-gate int i, err; 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate for (i = 0; list[i] != NULL; i++) { 386*7c478bd9Sstevel@tonic-gate if (initial_match(line1, list[i], word_end)) { 387*7c478bd9Sstevel@tonic-gate err = cpl_add_completion(cpl, line1, 0, word_end, 388*7c478bd9Sstevel@tonic-gate list[i] + word_end, "", ""); 389*7c478bd9Sstevel@tonic-gate if (err != 0) 390*7c478bd9Sstevel@tonic-gate return (err); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate return (0); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate static 397*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 398*7c478bd9Sstevel@tonic-gate CPL_MATCH_FN(cmd_cpl_fn) 399*7c478bd9Sstevel@tonic-gate { 400*7c478bd9Sstevel@tonic-gate if (global_scope) { 401*7c478bd9Sstevel@tonic-gate /* 402*7c478bd9Sstevel@tonic-gate * The MAX/MIN tests below are to make sure we have at least 403*7c478bd9Sstevel@tonic-gate * enough characters to distinguish from other prefixes (MAX) 404*7c478bd9Sstevel@tonic-gate * but only check MIN(what we have, what we're checking). 405*7c478bd9Sstevel@tonic-gate */ 406*7c478bd9Sstevel@tonic-gate if (strncmp(line, "add ", MAX(MIN(word_end, 4), 1)) == 0) 407*7c478bd9Sstevel@tonic-gate return (add_stuff(cpl, line, add_cmds, word_end)); 408*7c478bd9Sstevel@tonic-gate if (strncmp(line, "select ", MAX(MIN(word_end, 7), 3)) == 0) 409*7c478bd9Sstevel@tonic-gate return (add_stuff(cpl, line, select_cmds, word_end)); 410*7c478bd9Sstevel@tonic-gate if (strncmp(line, "set ", MAX(MIN(word_end, 4), 3)) == 0) 411*7c478bd9Sstevel@tonic-gate return (add_stuff(cpl, line, set_cmds, word_end)); 412*7c478bd9Sstevel@tonic-gate return (add_stuff(cpl, line, global_scope_cmds, word_end)); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate switch (resource_scope) { 415*7c478bd9Sstevel@tonic-gate case RT_FS: 416*7c478bd9Sstevel@tonic-gate return (add_stuff(cpl, line, fs_res_scope_cmds, word_end)); 417*7c478bd9Sstevel@tonic-gate case RT_IPD: 418*7c478bd9Sstevel@tonic-gate return (add_stuff(cpl, line, ipd_res_scope_cmds, word_end)); 419*7c478bd9Sstevel@tonic-gate case RT_NET: 420*7c478bd9Sstevel@tonic-gate return (add_stuff(cpl, line, net_res_scope_cmds, word_end)); 421*7c478bd9Sstevel@tonic-gate case RT_DEVICE: 422*7c478bd9Sstevel@tonic-gate return (add_stuff(cpl, line, device_res_scope_cmds, word_end)); 423*7c478bd9Sstevel@tonic-gate case RT_RCTL: 424*7c478bd9Sstevel@tonic-gate return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end)); 425*7c478bd9Sstevel@tonic-gate case RT_ATTR: 426*7c478bd9Sstevel@tonic-gate return (add_stuff(cpl, line, attr_res_scope_cmds, word_end)); 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate return (0); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate /* 432*7c478bd9Sstevel@tonic-gate * For the main CMD_func() functions below, several of them call getopt() 433*7c478bd9Sstevel@tonic-gate * then check optind against argc to make sure an extra parameter was not 434*7c478bd9Sstevel@tonic-gate * passed in. The reason this is not caught in the grammar is that the 435*7c478bd9Sstevel@tonic-gate * grammar just checks for a miscellaneous TOKEN, which is *expected* to 436*7c478bd9Sstevel@tonic-gate * be "-F" (for example), but could be anything. So (for example) this 437*7c478bd9Sstevel@tonic-gate * check will prevent "create bogus". 438*7c478bd9Sstevel@tonic-gate */ 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate cmd_t * 441*7c478bd9Sstevel@tonic-gate alloc_cmd(void) 442*7c478bd9Sstevel@tonic-gate { 443*7c478bd9Sstevel@tonic-gate return (calloc(1, sizeof (cmd_t))); 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate void 447*7c478bd9Sstevel@tonic-gate free_cmd(cmd_t *cmd) 448*7c478bd9Sstevel@tonic-gate { 449*7c478bd9Sstevel@tonic-gate int i; 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_EQ_PROP_PAIRS; i++) 452*7c478bd9Sstevel@tonic-gate if (cmd->cmd_property_ptr[i] != NULL) { 453*7c478bd9Sstevel@tonic-gate property_value_ptr_t pp = cmd->cmd_property_ptr[i]; 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate switch (pp->pv_type) { 456*7c478bd9Sstevel@tonic-gate case PROP_VAL_SIMPLE: 457*7c478bd9Sstevel@tonic-gate free(pp->pv_simple); 458*7c478bd9Sstevel@tonic-gate break; 459*7c478bd9Sstevel@tonic-gate case PROP_VAL_COMPLEX: 460*7c478bd9Sstevel@tonic-gate free_complex(pp->pv_complex); 461*7c478bd9Sstevel@tonic-gate break; 462*7c478bd9Sstevel@tonic-gate case PROP_VAL_LIST: 463*7c478bd9Sstevel@tonic-gate free_list(pp->pv_list); 464*7c478bd9Sstevel@tonic-gate break; 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate for (i = 0; i < cmd->cmd_argc; i++) 468*7c478bd9Sstevel@tonic-gate free(cmd->cmd_argv[i]); 469*7c478bd9Sstevel@tonic-gate free(cmd); 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate complex_property_ptr_t 473*7c478bd9Sstevel@tonic-gate alloc_complex(void) 474*7c478bd9Sstevel@tonic-gate { 475*7c478bd9Sstevel@tonic-gate return (calloc(1, sizeof (complex_property_t))); 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate void 479*7c478bd9Sstevel@tonic-gate free_complex(complex_property_ptr_t complex) 480*7c478bd9Sstevel@tonic-gate { 481*7c478bd9Sstevel@tonic-gate if (complex == NULL) 482*7c478bd9Sstevel@tonic-gate return; 483*7c478bd9Sstevel@tonic-gate free_complex(complex->cp_next); 484*7c478bd9Sstevel@tonic-gate if (complex->cp_value != NULL) 485*7c478bd9Sstevel@tonic-gate free(complex->cp_value); 486*7c478bd9Sstevel@tonic-gate free(complex); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate list_property_ptr_t 490*7c478bd9Sstevel@tonic-gate alloc_list(void) 491*7c478bd9Sstevel@tonic-gate { 492*7c478bd9Sstevel@tonic-gate return (calloc(1, sizeof (list_property_t))); 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate void 496*7c478bd9Sstevel@tonic-gate free_list(list_property_ptr_t list) 497*7c478bd9Sstevel@tonic-gate { 498*7c478bd9Sstevel@tonic-gate if (list == NULL) 499*7c478bd9Sstevel@tonic-gate return; 500*7c478bd9Sstevel@tonic-gate if (list->lp_simple != NULL) 501*7c478bd9Sstevel@tonic-gate free(list->lp_simple); 502*7c478bd9Sstevel@tonic-gate free_complex(list->lp_complex); 503*7c478bd9Sstevel@tonic-gate free_list(list->lp_next); 504*7c478bd9Sstevel@tonic-gate free(list); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate void 508*7c478bd9Sstevel@tonic-gate free_outer_list(list_property_ptr_t list) 509*7c478bd9Sstevel@tonic-gate { 510*7c478bd9Sstevel@tonic-gate if (list == NULL) 511*7c478bd9Sstevel@tonic-gate return; 512*7c478bd9Sstevel@tonic-gate free_outer_list(list->lp_next); 513*7c478bd9Sstevel@tonic-gate free(list); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate static struct zone_rctlvaltab * 517*7c478bd9Sstevel@tonic-gate alloc_rctlvaltab(void) 518*7c478bd9Sstevel@tonic-gate { 519*7c478bd9Sstevel@tonic-gate return (calloc(1, sizeof (struct zone_rctlvaltab))); 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate static char * 523*7c478bd9Sstevel@tonic-gate rt_to_str(int res_type) 524*7c478bd9Sstevel@tonic-gate { 525*7c478bd9Sstevel@tonic-gate assert(res_type >= RT_MIN && res_type <= RT_MAX); 526*7c478bd9Sstevel@tonic-gate return (res_types[res_type]); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate static char * 530*7c478bd9Sstevel@tonic-gate pt_to_str(int prop_type) 531*7c478bd9Sstevel@tonic-gate { 532*7c478bd9Sstevel@tonic-gate assert(prop_type >= PT_MIN && prop_type <= PT_MAX); 533*7c478bd9Sstevel@tonic-gate return (prop_types[prop_type]); 534*7c478bd9Sstevel@tonic-gate } 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate static char * 537*7c478bd9Sstevel@tonic-gate pvt_to_str(int pv_type) 538*7c478bd9Sstevel@tonic-gate { 539*7c478bd9Sstevel@tonic-gate assert(pv_type >= PROP_VAL_MIN && pv_type <= PROP_VAL_MAX); 540*7c478bd9Sstevel@tonic-gate return (prop_val_types[pv_type]); 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate static char * 544*7c478bd9Sstevel@tonic-gate cmd_to_str(int cmd_num) 545*7c478bd9Sstevel@tonic-gate { 546*7c478bd9Sstevel@tonic-gate assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 547*7c478bd9Sstevel@tonic-gate return (helptab[cmd_num].cmd_name); 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate /* 551*7c478bd9Sstevel@tonic-gate * This is a separate function rather than a set of define's because of the 552*7c478bd9Sstevel@tonic-gate * gettext() wrapping. 553*7c478bd9Sstevel@tonic-gate */ 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate /* 556*7c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 557*7c478bd9Sstevel@tonic-gate * Each string below should have \t follow \n whenever needed; the 558*7c478bd9Sstevel@tonic-gate * initial \t and the terminal \n will be provided by the calling function. 559*7c478bd9Sstevel@tonic-gate */ 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate static char * 562*7c478bd9Sstevel@tonic-gate long_help(int cmd_num) 563*7c478bd9Sstevel@tonic-gate { 564*7c478bd9Sstevel@tonic-gate static char line[1024]; /* arbitrary large amount */ 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX); 567*7c478bd9Sstevel@tonic-gate switch (cmd_num) { 568*7c478bd9Sstevel@tonic-gate case CMD_HELP: 569*7c478bd9Sstevel@tonic-gate return (gettext("Prints help message.")); 570*7c478bd9Sstevel@tonic-gate case CMD_CREATE: 571*7c478bd9Sstevel@tonic-gate (void) snprintf(line, sizeof (line), 572*7c478bd9Sstevel@tonic-gate gettext("Creates a configuration for the " 573*7c478bd9Sstevel@tonic-gate "specified zone. %s should be\n\tused to " 574*7c478bd9Sstevel@tonic-gate "begin configuring a new zone. If overwriting an " 575*7c478bd9Sstevel@tonic-gate "existing\n\tconfiguration, the -F flag can be " 576*7c478bd9Sstevel@tonic-gate "used to force the action. If\n\t-t template is " 577*7c478bd9Sstevel@tonic-gate "given, creates a configuration identical to the\n" 578*7c478bd9Sstevel@tonic-gate "\tspecified template, except that the zone name " 579*7c478bd9Sstevel@tonic-gate "is changed from\n\ttemplate to zonename. '%s -b' " 580*7c478bd9Sstevel@tonic-gate "results in a blank configuration.\n\t'%s' with no " 581*7c478bd9Sstevel@tonic-gate "arguments applies the Sun default settings."), 582*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE), 583*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_CREATE)); 584*7c478bd9Sstevel@tonic-gate return (line); 585*7c478bd9Sstevel@tonic-gate case CMD_EXIT: 586*7c478bd9Sstevel@tonic-gate return (gettext("Exits the program. The -F flag can " 587*7c478bd9Sstevel@tonic-gate "be used to force the action.")); 588*7c478bd9Sstevel@tonic-gate case CMD_EXPORT: 589*7c478bd9Sstevel@tonic-gate return (gettext("Prints configuration to standard " 590*7c478bd9Sstevel@tonic-gate "output, or to output-file if\n\tspecified, in " 591*7c478bd9Sstevel@tonic-gate "a form suitable for use in a command-file.")); 592*7c478bd9Sstevel@tonic-gate case CMD_ADD: 593*7c478bd9Sstevel@tonic-gate return (gettext("Add specified resource to " 594*7c478bd9Sstevel@tonic-gate "configuration.")); 595*7c478bd9Sstevel@tonic-gate case CMD_DELETE: 596*7c478bd9Sstevel@tonic-gate return (gettext("Deletes the specified zone. The -F " 597*7c478bd9Sstevel@tonic-gate "flag can be used to force the\n\taction.")); 598*7c478bd9Sstevel@tonic-gate case CMD_REMOVE: 599*7c478bd9Sstevel@tonic-gate return (gettext("Remove specified resource from " 600*7c478bd9Sstevel@tonic-gate "configuration. Note that the curly\n\tbraces " 601*7c478bd9Sstevel@tonic-gate "('{', '}') mean one or more of whatever " 602*7c478bd9Sstevel@tonic-gate "is between them.")); 603*7c478bd9Sstevel@tonic-gate case CMD_SELECT: 604*7c478bd9Sstevel@tonic-gate (void) snprintf(line, sizeof (line), 605*7c478bd9Sstevel@tonic-gate gettext("Selects a resource to modify. " 606*7c478bd9Sstevel@tonic-gate "Resource modification is completed\n\twith the " 607*7c478bd9Sstevel@tonic-gate "command \"%s\". The property name/value pairs " 608*7c478bd9Sstevel@tonic-gate "must uniquely\n\tidentify a resource. Note that " 609*7c478bd9Sstevel@tonic-gate "the curly braces ('{', '}') mean one\n\tor more " 610*7c478bd9Sstevel@tonic-gate "of whatever is between them."), 611*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_END)); 612*7c478bd9Sstevel@tonic-gate return (line); 613*7c478bd9Sstevel@tonic-gate case CMD_SET: 614*7c478bd9Sstevel@tonic-gate return (gettext("Sets property values.")); 615*7c478bd9Sstevel@tonic-gate case CMD_INFO: 616*7c478bd9Sstevel@tonic-gate return (gettext("Displays information about the " 617*7c478bd9Sstevel@tonic-gate "current configuration. If resource\n\ttype is " 618*7c478bd9Sstevel@tonic-gate "specified, displays only information about " 619*7c478bd9Sstevel@tonic-gate "resources of\n\tthe relevant type. If resource " 620*7c478bd9Sstevel@tonic-gate "id is specified, displays only\n\tinformation " 621*7c478bd9Sstevel@tonic-gate "about that resource.")); 622*7c478bd9Sstevel@tonic-gate case CMD_VERIFY: 623*7c478bd9Sstevel@tonic-gate return (gettext("Verifies current configuration " 624*7c478bd9Sstevel@tonic-gate "for correctness (some resource types\n\thave " 625*7c478bd9Sstevel@tonic-gate "required properties).")); 626*7c478bd9Sstevel@tonic-gate case CMD_COMMIT: 627*7c478bd9Sstevel@tonic-gate (void) snprintf(line, sizeof (line), 628*7c478bd9Sstevel@tonic-gate gettext("Commits current configuration. " 629*7c478bd9Sstevel@tonic-gate "Configuration must be committed to\n\tbe used by " 630*7c478bd9Sstevel@tonic-gate "%s. Until the configuration is committed, " 631*7c478bd9Sstevel@tonic-gate "changes \n\tcan be removed with the %s " 632*7c478bd9Sstevel@tonic-gate "command. This operation is\n\tattempted " 633*7c478bd9Sstevel@tonic-gate "automatically upon completion of a %s " 634*7c478bd9Sstevel@tonic-gate "session."), "zoneadm", cmd_to_str(CMD_REVERT), 635*7c478bd9Sstevel@tonic-gate "zonecfg"); 636*7c478bd9Sstevel@tonic-gate return (line); 637*7c478bd9Sstevel@tonic-gate case CMD_REVERT: 638*7c478bd9Sstevel@tonic-gate return (gettext("Reverts configuration back to the " 639*7c478bd9Sstevel@tonic-gate "last committed state. The -F flag\n\tcan be " 640*7c478bd9Sstevel@tonic-gate "used to force the action.")); 641*7c478bd9Sstevel@tonic-gate case CMD_CANCEL: 642*7c478bd9Sstevel@tonic-gate return (gettext("Cancels resource/property " 643*7c478bd9Sstevel@tonic-gate "specification.")); 644*7c478bd9Sstevel@tonic-gate case CMD_END: 645*7c478bd9Sstevel@tonic-gate return (gettext("Ends resource/property " 646*7c478bd9Sstevel@tonic-gate "specification.")); 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate /* 652*7c478bd9Sstevel@tonic-gate * Called with verbose TRUE when help is explicitly requested, FALSE for 653*7c478bd9Sstevel@tonic-gate * unexpected errors. 654*7c478bd9Sstevel@tonic-gate */ 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate void 657*7c478bd9Sstevel@tonic-gate usage(bool verbose, uint_t flags) 658*7c478bd9Sstevel@tonic-gate { 659*7c478bd9Sstevel@tonic-gate FILE *fp = verbose ? stdout : stderr, *newfp; 660*7c478bd9Sstevel@tonic-gate bool need_to_close = FALSE; 661*7c478bd9Sstevel@tonic-gate char *pager; 662*7c478bd9Sstevel@tonic-gate int i; 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate /* don't page error output */ 665*7c478bd9Sstevel@tonic-gate if (verbose && interactive_mode) { 666*7c478bd9Sstevel@tonic-gate if ((pager = getenv("PAGER")) == NULL) 667*7c478bd9Sstevel@tonic-gate pager = PAGER; 668*7c478bd9Sstevel@tonic-gate if ((newfp = popen(pager, "w")) != NULL) { 669*7c478bd9Sstevel@tonic-gate need_to_close = TRUE; 670*7c478bd9Sstevel@tonic-gate fp = newfp; 671*7c478bd9Sstevel@tonic-gate } 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate if (flags & HELP_META) { 674*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("More help is available for the " 675*7c478bd9Sstevel@tonic-gate "following:\n")); 676*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n\tcommands ('%s commands')\n", 677*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_HELP)); 678*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\tsyntax ('%s syntax')\n", 679*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_HELP)); 680*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\tusage ('%s usage')\n\n", 681*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_HELP)); 682*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("You may also obtain help on any " 683*7c478bd9Sstevel@tonic-gate "command by typing '%s <command-name>.'\n"), 684*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_HELP)); 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate if (flags & HELP_RES_SCOPE) { 687*7c478bd9Sstevel@tonic-gate switch (resource_scope) { 688*7c478bd9Sstevel@tonic-gate case RT_FS: 689*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("The '%s' resource scope is " 690*7c478bd9Sstevel@tonic-gate "used to configure a file-system.\n"), 691*7c478bd9Sstevel@tonic-gate rt_to_str(resource_scope)); 692*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("Valid commands:\n")); 693*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 694*7c478bd9Sstevel@tonic-gate pt_to_str(PT_DIR), gettext("<path>")); 695*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 696*7c478bd9Sstevel@tonic-gate pt_to_str(PT_SPECIAL), gettext("<path>")); 697*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 698*7c478bd9Sstevel@tonic-gate pt_to_str(PT_RAW), gettext("<raw-device>")); 699*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 700*7c478bd9Sstevel@tonic-gate pt_to_str(PT_TYPE), gettext("<file-system type>")); 701*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s %s\n", cmd_to_str(CMD_ADD), 702*7c478bd9Sstevel@tonic-gate pt_to_str(PT_OPTIONS), 703*7c478bd9Sstevel@tonic-gate gettext("<file-system options>")); 704*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("Consult the file-system " 705*7c478bd9Sstevel@tonic-gate "specific manual page, such as mount_ufs(1M), " 706*7c478bd9Sstevel@tonic-gate "for\ndetails about file-system options. Note " 707*7c478bd9Sstevel@tonic-gate "that any file-system options with an\nembedded " 708*7c478bd9Sstevel@tonic-gate "'=' character must be enclosed in double quotes, " 709*7c478bd9Sstevel@tonic-gate /*CSTYLED*/ 710*7c478bd9Sstevel@tonic-gate "such as \"%s=5\".\n"), MNTOPT_RETRY); 711*7c478bd9Sstevel@tonic-gate break; 712*7c478bd9Sstevel@tonic-gate case RT_IPD: 713*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("The '%s' resource scope is " 714*7c478bd9Sstevel@tonic-gate "used to configure a directory\ninherited from the " 715*7c478bd9Sstevel@tonic-gate "global zone into a non-global zone in read-only " 716*7c478bd9Sstevel@tonic-gate "mode.\n"), rt_to_str(resource_scope)); 717*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("Valid commands:\n")); 718*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 719*7c478bd9Sstevel@tonic-gate pt_to_str(PT_DIR), gettext("<path>")); 720*7c478bd9Sstevel@tonic-gate break; 721*7c478bd9Sstevel@tonic-gate case RT_NET: 722*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("The '%s' resource scope is " 723*7c478bd9Sstevel@tonic-gate "used to configure a network interface.\n"), 724*7c478bd9Sstevel@tonic-gate rt_to_str(resource_scope)); 725*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("Valid commands:\n")); 726*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 727*7c478bd9Sstevel@tonic-gate pt_to_str(PT_ADDRESS), gettext("<IP-address>")); 728*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 729*7c478bd9Sstevel@tonic-gate pt_to_str(PT_PHYSICAL), gettext("<interface>")); 730*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("See ifconfig(1M) for " 731*7c478bd9Sstevel@tonic-gate "details of the <interface> string.\n")); 732*7c478bd9Sstevel@tonic-gate break; 733*7c478bd9Sstevel@tonic-gate case RT_DEVICE: 734*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("The '%s' resource scope is " 735*7c478bd9Sstevel@tonic-gate "used to configure a device node.\n"), 736*7c478bd9Sstevel@tonic-gate rt_to_str(resource_scope)); 737*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("Valid commands:\n")); 738*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 739*7c478bd9Sstevel@tonic-gate pt_to_str(PT_MATCH), gettext("<device-path>")); 740*7c478bd9Sstevel@tonic-gate break; 741*7c478bd9Sstevel@tonic-gate case RT_RCTL: 742*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("The '%s' resource scope is " 743*7c478bd9Sstevel@tonic-gate "used to configure a resource control.\n"), 744*7c478bd9Sstevel@tonic-gate rt_to_str(resource_scope)); 745*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("Valid commands:\n")); 746*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 747*7c478bd9Sstevel@tonic-gate pt_to_str(PT_NAME), gettext("<string>")); 748*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n", 749*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE), 750*7c478bd9Sstevel@tonic-gate pt_to_str(PT_PRIV), gettext("<priv-value>"), 751*7c478bd9Sstevel@tonic-gate pt_to_str(PT_LIMIT), gettext("<number>"), 752*7c478bd9Sstevel@tonic-gate pt_to_str(PT_ACTION), gettext("<action-value>")); 753*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n\t%s := privileged\n" 754*7c478bd9Sstevel@tonic-gate "\t%s := none | deny\n", gettext("Where"), 755*7c478bd9Sstevel@tonic-gate gettext("<priv-value>"), gettext("<action-value>")); 756*7c478bd9Sstevel@tonic-gate break; 757*7c478bd9Sstevel@tonic-gate case RT_ATTR: 758*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("The '%s' resource scope is " 759*7c478bd9Sstevel@tonic-gate "used to configure a generic attribute.\n"), 760*7c478bd9Sstevel@tonic-gate rt_to_str(resource_scope)); 761*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("Valid commands:\n")); 762*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 763*7c478bd9Sstevel@tonic-gate pt_to_str(PT_NAME), gettext("<name>")); 764*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=boolean\n", 765*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_SET), pt_to_str(PT_TYPE)); 766*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=true | false\n", 767*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_SET), pt_to_str(PT_VALUE)); 768*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("or\n")); 769*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=int\n", cmd_to_str(CMD_SET), 770*7c478bd9Sstevel@tonic-gate pt_to_str(PT_TYPE)); 771*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 772*7c478bd9Sstevel@tonic-gate pt_to_str(PT_VALUE), gettext("<integer>")); 773*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("or\n")); 774*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=string\n", 775*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_SET), pt_to_str(PT_TYPE)); 776*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 777*7c478bd9Sstevel@tonic-gate pt_to_str(PT_VALUE), gettext("<string>")); 778*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("or\n")); 779*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=uint\n", 780*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_SET), pt_to_str(PT_TYPE)); 781*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET), 782*7c478bd9Sstevel@tonic-gate pt_to_str(PT_VALUE), gettext("<unsigned integer>")); 783*7c478bd9Sstevel@tonic-gate break; 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("And from any resource scope, you " 786*7c478bd9Sstevel@tonic-gate "can:\n")); 787*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END), 788*7c478bd9Sstevel@tonic-gate gettext("(to conclude this operation)")); 789*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL), 790*7c478bd9Sstevel@tonic-gate gettext("(to cancel this operation)")); 791*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT), 792*7c478bd9Sstevel@tonic-gate gettext("(to exit the zonecfg utility)")); 793*7c478bd9Sstevel@tonic-gate } 794*7c478bd9Sstevel@tonic-gate if (flags & HELP_USAGE) { 795*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"), 796*7c478bd9Sstevel@tonic-gate execname, cmd_to_str(CMD_HELP)); 797*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n", 798*7c478bd9Sstevel@tonic-gate execname, gettext("interactive")); 799*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname); 800*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n", 801*7c478bd9Sstevel@tonic-gate execname); 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate if (flags & HELP_SUBCMDS) { 804*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s:\n\n", gettext("Commands")); 805*7c478bd9Sstevel@tonic-gate for (i = 0; i <= CMD_MAX; i++) { 806*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", helptab[i].short_usage); 807*7c478bd9Sstevel@tonic-gate if (verbose) 808*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\n\n", long_help(i)); 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate if (flags & HELP_SYNTAX) { 812*7c478bd9Sstevel@tonic-gate if (!verbose) 813*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n"); 814*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n"); 815*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("\t(except the reserved words " 816*7c478bd9Sstevel@tonic-gate "'%s' and anything starting with '%s')\n"), "global", 817*7c478bd9Sstevel@tonic-gate "SUNW"); 818*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, 819*7c478bd9Sstevel@tonic-gate gettext("\tName must be less than %d characters.\n"), 820*7c478bd9Sstevel@tonic-gate ZONENAME_MAX); 821*7c478bd9Sstevel@tonic-gate if (verbose) 822*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n"); 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate if (flags & HELP_NETADDR) { 825*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("\n<net-addr> :=")); 826*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, 827*7c478bd9Sstevel@tonic-gate gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n")); 828*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, 829*7c478bd9Sstevel@tonic-gate gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n")); 830*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, 831*7c478bd9Sstevel@tonic-gate gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n")); 832*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and " 833*7c478bd9Sstevel@tonic-gate "IPv6 address syntax.\n")); 834*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n")); 835*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, 836*7c478bd9Sstevel@tonic-gate gettext("<IPv6-prefix-length> := [0-128]\n")); 837*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, 838*7c478bd9Sstevel@tonic-gate gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n")); 839*7c478bd9Sstevel@tonic-gate } 840*7c478bd9Sstevel@tonic-gate if (flags & HELP_RESOURCES) { 841*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s | %s\n\n", 842*7c478bd9Sstevel@tonic-gate gettext("resource type"), rt_to_str(RT_FS), 843*7c478bd9Sstevel@tonic-gate rt_to_str(RT_IPD), rt_to_str(RT_NET), rt_to_str(RT_DEVICE), 844*7c478bd9Sstevel@tonic-gate rt_to_str(RT_RCTL), rt_to_str(RT_ATTR)); 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate if (flags & HELP_PROPS) { 847*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, gettext("For resource type ... there are " 848*7c478bd9Sstevel@tonic-gate "property types ...:\n")); 849*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 850*7c478bd9Sstevel@tonic-gate pt_to_str(PT_ZONEPATH)); 851*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 852*7c478bd9Sstevel@tonic-gate pt_to_str(PT_AUTOBOOT)); 853*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"), 854*7c478bd9Sstevel@tonic-gate pt_to_str(PT_POOL)); 855*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s\n", rt_to_str(RT_FS), 856*7c478bd9Sstevel@tonic-gate pt_to_str(PT_DIR), pt_to_str(PT_SPECIAL), 857*7c478bd9Sstevel@tonic-gate pt_to_str(PT_RAW), pt_to_str(PT_TYPE), 858*7c478bd9Sstevel@tonic-gate pt_to_str(PT_OPTIONS)); 859*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_IPD), 860*7c478bd9Sstevel@tonic-gate pt_to_str(PT_DIR)); 861*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_NET), 862*7c478bd9Sstevel@tonic-gate pt_to_str(PT_ADDRESS), pt_to_str(PT_PHYSICAL)); 863*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE), 864*7c478bd9Sstevel@tonic-gate pt_to_str(PT_MATCH)); 865*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL), 866*7c478bd9Sstevel@tonic-gate pt_to_str(PT_NAME), pt_to_str(PT_VALUE)); 867*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR), 868*7c478bd9Sstevel@tonic-gate pt_to_str(PT_NAME), pt_to_str(PT_TYPE), 869*7c478bd9Sstevel@tonic-gate pt_to_str(PT_VALUE)); 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate if (need_to_close) 872*7c478bd9Sstevel@tonic-gate (void) pclose(fp); 873*7c478bd9Sstevel@tonic-gate } 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate /* PRINTFLIKE1 */ 876*7c478bd9Sstevel@tonic-gate static void 877*7c478bd9Sstevel@tonic-gate zerr(const char *fmt, ...) 878*7c478bd9Sstevel@tonic-gate { 879*7c478bd9Sstevel@tonic-gate va_list alist; 880*7c478bd9Sstevel@tonic-gate static int last_lineno; 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate /* lex_lineno has already been incremented in the lexer; compensate */ 883*7c478bd9Sstevel@tonic-gate if (cmd_file_mode && lex_lineno > last_lineno) { 884*7c478bd9Sstevel@tonic-gate if (strcmp(cmd_file_name, "-") == 0) 885*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("On line %d:\n"), 886*7c478bd9Sstevel@tonic-gate lex_lineno - 1); 887*7c478bd9Sstevel@tonic-gate else 888*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("On line %d of %s:\n"), 889*7c478bd9Sstevel@tonic-gate lex_lineno - 1, cmd_file_name); 890*7c478bd9Sstevel@tonic-gate last_lineno = lex_lineno; 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate va_start(alist, fmt); 893*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, alist); 894*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 895*7c478bd9Sstevel@tonic-gate va_end(alist); 896*7c478bd9Sstevel@tonic-gate } 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate static void 899*7c478bd9Sstevel@tonic-gate zone_perror(char *prefix, int err, bool set_saw) 900*7c478bd9Sstevel@tonic-gate { 901*7c478bd9Sstevel@tonic-gate zerr("%s: %s", prefix, zonecfg_strerror(err)); 902*7c478bd9Sstevel@tonic-gate if (set_saw) 903*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 904*7c478bd9Sstevel@tonic-gate } 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate /* 907*7c478bd9Sstevel@tonic-gate * zone_perror() expects a single string, but for remove and select 908*7c478bd9Sstevel@tonic-gate * we have both the command and the resource type, so this wrapper 909*7c478bd9Sstevel@tonic-gate * function serves the same purpose in a slightly different way. 910*7c478bd9Sstevel@tonic-gate */ 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate static void 913*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(int cmd_num, int res_num, int err, bool set_saw) 914*7c478bd9Sstevel@tonic-gate { 915*7c478bd9Sstevel@tonic-gate zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num), 916*7c478bd9Sstevel@tonic-gate zonecfg_strerror(err)); 917*7c478bd9Sstevel@tonic-gate if (set_saw) 918*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 919*7c478bd9Sstevel@tonic-gate } 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */ 922*7c478bd9Sstevel@tonic-gate static int 923*7c478bd9Sstevel@tonic-gate initialize(bool handle_expected) 924*7c478bd9Sstevel@tonic-gate { 925*7c478bd9Sstevel@tonic-gate int err; 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate if (zonecfg_check_handle(handle) != Z_OK) { 928*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) { 929*7c478bd9Sstevel@tonic-gate got_handle = TRUE; 930*7c478bd9Sstevel@tonic-gate } else { 931*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, handle_expected || got_handle); 932*7c478bd9Sstevel@tonic-gate if (err == Z_NO_ZONE && !got_handle && 933*7c478bd9Sstevel@tonic-gate interactive_mode && !read_only_mode) 934*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Use '%s' to begin " 935*7c478bd9Sstevel@tonic-gate "configuring a new zone.\n"), 936*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_CREATE)); 937*7c478bd9Sstevel@tonic-gate return (err); 938*7c478bd9Sstevel@tonic-gate } 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate return (Z_OK); 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate /* 944*7c478bd9Sstevel@tonic-gate * short_usage() is for bad syntax: getopt() issues, too many arguments, etc. 945*7c478bd9Sstevel@tonic-gate */ 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate void 948*7c478bd9Sstevel@tonic-gate short_usage(int command) 949*7c478bd9Sstevel@tonic-gate { 950*7c478bd9Sstevel@tonic-gate /* lex_lineno has already been incremented in the lexer; compensate */ 951*7c478bd9Sstevel@tonic-gate if (cmd_file_mode) { 952*7c478bd9Sstevel@tonic-gate if (strcmp(cmd_file_name, "-") == 0) 953*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 954*7c478bd9Sstevel@tonic-gate gettext("syntax error on line %d\n"), 955*7c478bd9Sstevel@tonic-gate lex_lineno - 1); 956*7c478bd9Sstevel@tonic-gate else 957*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 958*7c478bd9Sstevel@tonic-gate gettext("syntax error on line %d of %s\n"), 959*7c478bd9Sstevel@tonic-gate lex_lineno - 1, cmd_file_name); 960*7c478bd9Sstevel@tonic-gate } 961*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s:\n%s\n", gettext("usage"), 962*7c478bd9Sstevel@tonic-gate helptab[command].short_usage); 963*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 964*7c478bd9Sstevel@tonic-gate } 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate /* 967*7c478bd9Sstevel@tonic-gate * long_usage() is for bad semantics: e.g., wrong property type for a given 968*7c478bd9Sstevel@tonic-gate * resource type. It is also used by longer_usage() below. 969*7c478bd9Sstevel@tonic-gate */ 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate void 972*7c478bd9Sstevel@tonic-gate long_usage(uint_t cmd_num, bool set_saw) 973*7c478bd9Sstevel@tonic-gate { 974*7c478bd9Sstevel@tonic-gate (void) fprintf(set_saw ? stderr : stdout, "%s:\n%s\n", gettext("usage"), 975*7c478bd9Sstevel@tonic-gate helptab[cmd_num].short_usage); 976*7c478bd9Sstevel@tonic-gate (void) fprintf(set_saw ? stderr : stdout, "\t%s\n", long_help(cmd_num)); 977*7c478bd9Sstevel@tonic-gate if (set_saw) 978*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 979*7c478bd9Sstevel@tonic-gate } 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate /* 982*7c478bd9Sstevel@tonic-gate * longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also 983*7c478bd9Sstevel@tonic-gate * any extra usage() flags as appropriate for whatever command. 984*7c478bd9Sstevel@tonic-gate */ 985*7c478bd9Sstevel@tonic-gate 986*7c478bd9Sstevel@tonic-gate void 987*7c478bd9Sstevel@tonic-gate longer_usage(uint_t cmd_num) 988*7c478bd9Sstevel@tonic-gate { 989*7c478bd9Sstevel@tonic-gate long_usage(cmd_num, FALSE); 990*7c478bd9Sstevel@tonic-gate if (helptab[cmd_num].flags != 0) { 991*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 992*7c478bd9Sstevel@tonic-gate usage(TRUE, helptab[cmd_num].flags); 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate /* 997*7c478bd9Sstevel@tonic-gate * scope_usage() is simply used when a command is called from the wrong scope. 998*7c478bd9Sstevel@tonic-gate */ 999*7c478bd9Sstevel@tonic-gate 1000*7c478bd9Sstevel@tonic-gate static void 1001*7c478bd9Sstevel@tonic-gate scope_usage(uint_t cmd_num) 1002*7c478bd9Sstevel@tonic-gate { 1003*7c478bd9Sstevel@tonic-gate zerr(gettext("The %s command only makes sense in the %s scope."), 1004*7c478bd9Sstevel@tonic-gate cmd_to_str(cmd_num), 1005*7c478bd9Sstevel@tonic-gate global_scope ? gettext("resource") : gettext("global")); 1006*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1007*7c478bd9Sstevel@tonic-gate } 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate /* 1010*7c478bd9Sstevel@tonic-gate * On input, TRUE => yes, FALSE => no. 1011*7c478bd9Sstevel@tonic-gate * On return, TRUE => 1, FALSE => no, could not ask => -1. 1012*7c478bd9Sstevel@tonic-gate */ 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate static int 1015*7c478bd9Sstevel@tonic-gate ask_yesno(bool default_answer, const char *question) 1016*7c478bd9Sstevel@tonic-gate { 1017*7c478bd9Sstevel@tonic-gate char line[64]; /* should be enough to answer yes or no */ 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate if (!ok_to_prompt) { 1020*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1021*7c478bd9Sstevel@tonic-gate return (-1); 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate for (;;) { 1024*7c478bd9Sstevel@tonic-gate (void) printf("%s (%s)? ", question, 1025*7c478bd9Sstevel@tonic-gate default_answer ? "[y]/n" : "y/[n]"); 1026*7c478bd9Sstevel@tonic-gate if (fgets(line, sizeof (line), stdin) == NULL || 1027*7c478bd9Sstevel@tonic-gate line[0] == '\n') 1028*7c478bd9Sstevel@tonic-gate return (default_answer ? 1 : 0); 1029*7c478bd9Sstevel@tonic-gate if (tolower(line[0]) == 'y') 1030*7c478bd9Sstevel@tonic-gate return (1); 1031*7c478bd9Sstevel@tonic-gate if (tolower(line[0]) == 'n') 1032*7c478bd9Sstevel@tonic-gate return (0); 1033*7c478bd9Sstevel@tonic-gate } 1034*7c478bd9Sstevel@tonic-gate } 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate /* 1037*7c478bd9Sstevel@tonic-gate * Prints warning if zone already exists. 1038*7c478bd9Sstevel@tonic-gate * In interactive mode, prompts if we should continue anyway and returns Z_OK 1039*7c478bd9Sstevel@tonic-gate * if so, Z_ERR if not. In non-interactive mode, exits with Z_ERR. 1040*7c478bd9Sstevel@tonic-gate * 1041*7c478bd9Sstevel@tonic-gate * Note that if a zone exists and its state is >= INSTALLED, an error message 1042*7c478bd9Sstevel@tonic-gate * will be printed and this function will return Z_ERR regardless of mode. 1043*7c478bd9Sstevel@tonic-gate */ 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate static int 1046*7c478bd9Sstevel@tonic-gate check_if_zone_already_exists(bool force) 1047*7c478bd9Sstevel@tonic-gate { 1048*7c478bd9Sstevel@tonic-gate char line[ZONENAME_MAX + 128]; /* enough to ask a question */ 1049*7c478bd9Sstevel@tonic-gate zone_state_t state_num; 1050*7c478bd9Sstevel@tonic-gate zone_dochandle_t tmphandle; 1051*7c478bd9Sstevel@tonic-gate int res, answer; 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate if ((tmphandle = zonecfg_init_handle()) == NULL) { 1054*7c478bd9Sstevel@tonic-gate zone_perror(execname, Z_NOMEM, TRUE); 1055*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 1056*7c478bd9Sstevel@tonic-gate } 1057*7c478bd9Sstevel@tonic-gate res = zonecfg_get_handle(zone, tmphandle); 1058*7c478bd9Sstevel@tonic-gate zonecfg_fini_handle(tmphandle); 1059*7c478bd9Sstevel@tonic-gate if (res != Z_OK) { 1060*7c478bd9Sstevel@tonic-gate new_zone = TRUE; 1061*7c478bd9Sstevel@tonic-gate return (Z_OK); 1062*7c478bd9Sstevel@tonic-gate } 1063*7c478bd9Sstevel@tonic-gate if (zone_get_state(zone, &state_num) == Z_OK && 1064*7c478bd9Sstevel@tonic-gate state_num >= ZONE_STATE_INSTALLED) { 1065*7c478bd9Sstevel@tonic-gate zerr(gettext("Zone %s already installed; %s not allowed."), 1066*7c478bd9Sstevel@tonic-gate zone, cmd_to_str(CMD_CREATE)); 1067*7c478bd9Sstevel@tonic-gate return (Z_ERR); 1068*7c478bd9Sstevel@tonic-gate } 1069*7c478bd9Sstevel@tonic-gate 1070*7c478bd9Sstevel@tonic-gate if (force) { 1071*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Zone %s already exists; overwriting.\n"), 1072*7c478bd9Sstevel@tonic-gate zone); 1073*7c478bd9Sstevel@tonic-gate return (Z_OK); 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate (void) snprintf(line, sizeof (line), 1076*7c478bd9Sstevel@tonic-gate gettext("Zone %s already exists; %s anyway"), zone, 1077*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_CREATE)); 1078*7c478bd9Sstevel@tonic-gate if ((answer = ask_yesno(FALSE, line)) == -1) { 1079*7c478bd9Sstevel@tonic-gate zerr(gettext("Zone exists, input not from terminal and -F not " 1080*7c478bd9Sstevel@tonic-gate "specified:\n%s command ignored, exiting."), 1081*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_CREATE)); 1082*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 1083*7c478bd9Sstevel@tonic-gate } 1084*7c478bd9Sstevel@tonic-gate return (answer == 1 ? Z_OK : Z_ERR); 1085*7c478bd9Sstevel@tonic-gate } 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate static bool 1088*7c478bd9Sstevel@tonic-gate zone_is_read_only(int cmd_num) 1089*7c478bd9Sstevel@tonic-gate { 1090*7c478bd9Sstevel@tonic-gate if (strncmp(zone, "SUNW", 4) == 0) { 1091*7c478bd9Sstevel@tonic-gate zerr(gettext("%s: zones beginning with SUNW are read-only."), 1092*7c478bd9Sstevel@tonic-gate zone); 1093*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1094*7c478bd9Sstevel@tonic-gate return (TRUE); 1095*7c478bd9Sstevel@tonic-gate } 1096*7c478bd9Sstevel@tonic-gate if (read_only_mode) { 1097*7c478bd9Sstevel@tonic-gate zerr(gettext("%s: cannot %s in read-only mode."), zone, 1098*7c478bd9Sstevel@tonic-gate cmd_to_str(cmd_num)); 1099*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1100*7c478bd9Sstevel@tonic-gate return (TRUE); 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate return (FALSE); 1103*7c478bd9Sstevel@tonic-gate } 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate /* 1106*7c478bd9Sstevel@tonic-gate * Create a new configuration. 1107*7c478bd9Sstevel@tonic-gate */ 1108*7c478bd9Sstevel@tonic-gate void 1109*7c478bd9Sstevel@tonic-gate create_func(cmd_t *cmd) 1110*7c478bd9Sstevel@tonic-gate { 1111*7c478bd9Sstevel@tonic-gate int err, arg; 1112*7c478bd9Sstevel@tonic-gate char zone_template[ZONENAME_MAX]; 1113*7c478bd9Sstevel@tonic-gate zone_dochandle_t tmphandle; 1114*7c478bd9Sstevel@tonic-gate bool force = FALSE; 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 1117*7c478bd9Sstevel@tonic-gate 1118*7c478bd9Sstevel@tonic-gate /* This is the default if no arguments are given. */ 1119*7c478bd9Sstevel@tonic-gate (void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template)); 1120*7c478bd9Sstevel@tonic-gate 1121*7c478bd9Sstevel@tonic-gate optind = 0; 1122*7c478bd9Sstevel@tonic-gate while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?bFt:")) != EOF) { 1123*7c478bd9Sstevel@tonic-gate switch (arg) { 1124*7c478bd9Sstevel@tonic-gate case '?': 1125*7c478bd9Sstevel@tonic-gate if (optopt == '?') 1126*7c478bd9Sstevel@tonic-gate longer_usage(CMD_CREATE); 1127*7c478bd9Sstevel@tonic-gate else 1128*7c478bd9Sstevel@tonic-gate short_usage(CMD_CREATE); 1129*7c478bd9Sstevel@tonic-gate return; 1130*7c478bd9Sstevel@tonic-gate case 'b': 1131*7c478bd9Sstevel@tonic-gate (void) strlcpy(zone_template, "SUNWblank", 1132*7c478bd9Sstevel@tonic-gate sizeof (zone_template)); 1133*7c478bd9Sstevel@tonic-gate break; 1134*7c478bd9Sstevel@tonic-gate case 'F': 1135*7c478bd9Sstevel@tonic-gate force = TRUE; 1136*7c478bd9Sstevel@tonic-gate break; 1137*7c478bd9Sstevel@tonic-gate case 't': 1138*7c478bd9Sstevel@tonic-gate (void) strlcpy(zone_template, optarg, 1139*7c478bd9Sstevel@tonic-gate sizeof (zone_template)); 1140*7c478bd9Sstevel@tonic-gate break; 1141*7c478bd9Sstevel@tonic-gate default: 1142*7c478bd9Sstevel@tonic-gate short_usage(CMD_CREATE); 1143*7c478bd9Sstevel@tonic-gate return; 1144*7c478bd9Sstevel@tonic-gate } 1145*7c478bd9Sstevel@tonic-gate } 1146*7c478bd9Sstevel@tonic-gate if (optind != cmd->cmd_argc) { 1147*7c478bd9Sstevel@tonic-gate short_usage(CMD_CREATE); 1148*7c478bd9Sstevel@tonic-gate return; 1149*7c478bd9Sstevel@tonic-gate } 1150*7c478bd9Sstevel@tonic-gate 1151*7c478bd9Sstevel@tonic-gate if (zone_is_read_only(CMD_CREATE)) 1152*7c478bd9Sstevel@tonic-gate return; 1153*7c478bd9Sstevel@tonic-gate 1154*7c478bd9Sstevel@tonic-gate if (check_if_zone_already_exists(force) != Z_OK) 1155*7c478bd9Sstevel@tonic-gate return; 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate /* 1158*7c478bd9Sstevel@tonic-gate * Get a temporary handle first. If that fails, the old handle 1159*7c478bd9Sstevel@tonic-gate * will not be lost. Then finish whichever one we don't need, 1160*7c478bd9Sstevel@tonic-gate * to avoid leaks. Then get the handle for zone_template, and 1161*7c478bd9Sstevel@tonic-gate * set the name to zone: this "copy, rename" method is how 1162*7c478bd9Sstevel@tonic-gate * create -[b|t] works. 1163*7c478bd9Sstevel@tonic-gate */ 1164*7c478bd9Sstevel@tonic-gate if ((tmphandle = zonecfg_init_handle()) == NULL) { 1165*7c478bd9Sstevel@tonic-gate zone_perror(execname, Z_NOMEM, TRUE); 1166*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 1167*7c478bd9Sstevel@tonic-gate } 1168*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_get_handle(zone_template, tmphandle)) != Z_OK) { 1169*7c478bd9Sstevel@tonic-gate zonecfg_fini_handle(tmphandle); 1170*7c478bd9Sstevel@tonic-gate zone_perror(zone_template, err, TRUE); 1171*7c478bd9Sstevel@tonic-gate return; 1172*7c478bd9Sstevel@tonic-gate } 1173*7c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 1174*7c478bd9Sstevel@tonic-gate handle = tmphandle; 1175*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_set_name(handle, zone)) == Z_OK) 1176*7c478bd9Sstevel@tonic-gate need_to_commit = TRUE; 1177*7c478bd9Sstevel@tonic-gate else 1178*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate /* 1182*7c478bd9Sstevel@tonic-gate * This malloc()'s memory, which must be freed by the caller. 1183*7c478bd9Sstevel@tonic-gate */ 1184*7c478bd9Sstevel@tonic-gate static char * 1185*7c478bd9Sstevel@tonic-gate quoteit(char *instr) 1186*7c478bd9Sstevel@tonic-gate { 1187*7c478bd9Sstevel@tonic-gate char *outstr; 1188*7c478bd9Sstevel@tonic-gate size_t outstrsize = strlen(instr) + 3; /* 2 quotes + '\0' */ 1189*7c478bd9Sstevel@tonic-gate 1190*7c478bd9Sstevel@tonic-gate if ((outstr = malloc(outstrsize)) == NULL) { 1191*7c478bd9Sstevel@tonic-gate zone_perror(zone, Z_NOMEM, FALSE); 1192*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 1193*7c478bd9Sstevel@tonic-gate } 1194*7c478bd9Sstevel@tonic-gate if (strchr(instr, ' ') == NULL) { 1195*7c478bd9Sstevel@tonic-gate (void) strlcpy(outstr, instr, outstrsize); 1196*7c478bd9Sstevel@tonic-gate return (outstr); 1197*7c478bd9Sstevel@tonic-gate } 1198*7c478bd9Sstevel@tonic-gate (void) snprintf(outstr, outstrsize, "\"%s\"", instr); 1199*7c478bd9Sstevel@tonic-gate return (outstr); 1200*7c478bd9Sstevel@tonic-gate } 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate static void 1203*7c478bd9Sstevel@tonic-gate export_prop(FILE *of, int prop_num, char *prop_id) 1204*7c478bd9Sstevel@tonic-gate { 1205*7c478bd9Sstevel@tonic-gate char *quote_str; 1206*7c478bd9Sstevel@tonic-gate 1207*7c478bd9Sstevel@tonic-gate if (strlen(prop_id) == 0) 1208*7c478bd9Sstevel@tonic-gate return; 1209*7c478bd9Sstevel@tonic-gate quote_str = quoteit(prop_id); 1210*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1211*7c478bd9Sstevel@tonic-gate pt_to_str(prop_num), quote_str); 1212*7c478bd9Sstevel@tonic-gate free(quote_str); 1213*7c478bd9Sstevel@tonic-gate } 1214*7c478bd9Sstevel@tonic-gate 1215*7c478bd9Sstevel@tonic-gate void 1216*7c478bd9Sstevel@tonic-gate export_func(cmd_t *cmd) 1217*7c478bd9Sstevel@tonic-gate { 1218*7c478bd9Sstevel@tonic-gate struct zone_nwiftab nwiftab; 1219*7c478bd9Sstevel@tonic-gate struct zone_fstab fstab; 1220*7c478bd9Sstevel@tonic-gate struct zone_devtab devtab; 1221*7c478bd9Sstevel@tonic-gate struct zone_attrtab attrtab; 1222*7c478bd9Sstevel@tonic-gate struct zone_rctltab rctltab; 1223*7c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 1224*7c478bd9Sstevel@tonic-gate int err, arg; 1225*7c478bd9Sstevel@tonic-gate char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN]; 1226*7c478bd9Sstevel@tonic-gate FILE *of; 1227*7c478bd9Sstevel@tonic-gate boolean_t autoboot; 1228*7c478bd9Sstevel@tonic-gate bool need_to_close = FALSE; 1229*7c478bd9Sstevel@tonic-gate 1230*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 1231*7c478bd9Sstevel@tonic-gate 1232*7c478bd9Sstevel@tonic-gate outfile[0] = '\0'; 1233*7c478bd9Sstevel@tonic-gate optind = 0; 1234*7c478bd9Sstevel@tonic-gate while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) { 1235*7c478bd9Sstevel@tonic-gate switch (arg) { 1236*7c478bd9Sstevel@tonic-gate case '?': 1237*7c478bd9Sstevel@tonic-gate if (optopt == '?') 1238*7c478bd9Sstevel@tonic-gate longer_usage(CMD_EXPORT); 1239*7c478bd9Sstevel@tonic-gate else 1240*7c478bd9Sstevel@tonic-gate short_usage(CMD_EXPORT); 1241*7c478bd9Sstevel@tonic-gate return; 1242*7c478bd9Sstevel@tonic-gate case 'f': 1243*7c478bd9Sstevel@tonic-gate (void) strlcpy(outfile, optarg, sizeof (outfile)); 1244*7c478bd9Sstevel@tonic-gate break; 1245*7c478bd9Sstevel@tonic-gate default: 1246*7c478bd9Sstevel@tonic-gate short_usage(CMD_EXPORT); 1247*7c478bd9Sstevel@tonic-gate return; 1248*7c478bd9Sstevel@tonic-gate } 1249*7c478bd9Sstevel@tonic-gate } 1250*7c478bd9Sstevel@tonic-gate if (optind != cmd->cmd_argc) { 1251*7c478bd9Sstevel@tonic-gate short_usage(CMD_EXPORT); 1252*7c478bd9Sstevel@tonic-gate return; 1253*7c478bd9Sstevel@tonic-gate } 1254*7c478bd9Sstevel@tonic-gate if (strlen(outfile) == 0) { 1255*7c478bd9Sstevel@tonic-gate of = stdout; 1256*7c478bd9Sstevel@tonic-gate } else { 1257*7c478bd9Sstevel@tonic-gate if ((of = fopen(outfile, "w")) == NULL) { 1258*7c478bd9Sstevel@tonic-gate zerr(gettext("opening file %s: %s"), 1259*7c478bd9Sstevel@tonic-gate outfile, strerror(errno)); 1260*7c478bd9Sstevel@tonic-gate goto done; 1261*7c478bd9Sstevel@tonic-gate } 1262*7c478bd9Sstevel@tonic-gate setbuf(of, NULL); 1263*7c478bd9Sstevel@tonic-gate need_to_close = TRUE; 1264*7c478bd9Sstevel@tonic-gate } 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate if ((err = initialize(TRUE)) != Z_OK) 1267*7c478bd9Sstevel@tonic-gate goto done; 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s -b\n", cmd_to_str(CMD_CREATE)); 1270*7c478bd9Sstevel@tonic-gate 1271*7c478bd9Sstevel@tonic-gate if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK && 1272*7c478bd9Sstevel@tonic-gate strlen(zonepath) > 0) 1273*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1274*7c478bd9Sstevel@tonic-gate pt_to_str(PT_ZONEPATH), zonepath); 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate if (zonecfg_get_autoboot(handle, &autoboot) == Z_OK) 1277*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1278*7c478bd9Sstevel@tonic-gate pt_to_str(PT_AUTOBOOT), autoboot ? "true" : "false"); 1279*7c478bd9Sstevel@tonic-gate 1280*7c478bd9Sstevel@tonic-gate if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK && 1281*7c478bd9Sstevel@tonic-gate strlen(pool) > 0) 1282*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET), 1283*7c478bd9Sstevel@tonic-gate pt_to_str(PT_POOL), pool); 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_setipdent(handle)) != Z_OK) { 1286*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, FALSE); 1287*7c478bd9Sstevel@tonic-gate goto done; 1288*7c478bd9Sstevel@tonic-gate } 1289*7c478bd9Sstevel@tonic-gate while (zonecfg_getipdent(handle, &fstab) == Z_OK) { 1290*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1291*7c478bd9Sstevel@tonic-gate rt_to_str(RT_IPD)); 1292*7c478bd9Sstevel@tonic-gate export_prop(of, PT_DIR, fstab.zone_fs_dir); 1293*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1294*7c478bd9Sstevel@tonic-gate } 1295*7c478bd9Sstevel@tonic-gate (void) zonecfg_endipdent(handle); 1296*7c478bd9Sstevel@tonic-gate 1297*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_setfsent(handle)) != Z_OK) { 1298*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, FALSE); 1299*7c478bd9Sstevel@tonic-gate goto done; 1300*7c478bd9Sstevel@tonic-gate } 1301*7c478bd9Sstevel@tonic-gate while (zonecfg_getfsent(handle, &fstab) == Z_OK) { 1302*7c478bd9Sstevel@tonic-gate zone_fsopt_t *optptr; 1303*7c478bd9Sstevel@tonic-gate 1304*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1305*7c478bd9Sstevel@tonic-gate rt_to_str(RT_FS)); 1306*7c478bd9Sstevel@tonic-gate export_prop(of, PT_DIR, fstab.zone_fs_dir); 1307*7c478bd9Sstevel@tonic-gate export_prop(of, PT_SPECIAL, fstab.zone_fs_special); 1308*7c478bd9Sstevel@tonic-gate export_prop(of, PT_RAW, fstab.zone_fs_raw); 1309*7c478bd9Sstevel@tonic-gate export_prop(of, PT_TYPE, fstab.zone_fs_type); 1310*7c478bd9Sstevel@tonic-gate for (optptr = fstab.zone_fs_options; optptr != NULL; 1311*7c478bd9Sstevel@tonic-gate optptr = optptr->zone_fsopt_next) { 1312*7c478bd9Sstevel@tonic-gate /* 1313*7c478bd9Sstevel@tonic-gate * Simple property values with embedded equal signs 1314*7c478bd9Sstevel@tonic-gate * need to be quoted to prevent the lexer from 1315*7c478bd9Sstevel@tonic-gate * mis-parsing them as complex name=value pairs. 1316*7c478bd9Sstevel@tonic-gate */ 1317*7c478bd9Sstevel@tonic-gate if (strchr(optptr->zone_fsopt_opt, '=')) 1318*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s %s \"%s\"\n", 1319*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_ADD), 1320*7c478bd9Sstevel@tonic-gate pt_to_str(PT_OPTIONS), 1321*7c478bd9Sstevel@tonic-gate optptr->zone_fsopt_opt); 1322*7c478bd9Sstevel@tonic-gate else 1323*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s %s %s\n", 1324*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_ADD), 1325*7c478bd9Sstevel@tonic-gate pt_to_str(PT_OPTIONS), 1326*7c478bd9Sstevel@tonic-gate optptr->zone_fsopt_opt); 1327*7c478bd9Sstevel@tonic-gate } 1328*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1329*7c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(fstab.zone_fs_options); 1330*7c478bd9Sstevel@tonic-gate } 1331*7c478bd9Sstevel@tonic-gate (void) zonecfg_endfsent(handle); 1332*7c478bd9Sstevel@tonic-gate 1333*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_setnwifent(handle)) != Z_OK) { 1334*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, FALSE); 1335*7c478bd9Sstevel@tonic-gate goto done; 1336*7c478bd9Sstevel@tonic-gate } 1337*7c478bd9Sstevel@tonic-gate while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) { 1338*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1339*7c478bd9Sstevel@tonic-gate rt_to_str(RT_NET)); 1340*7c478bd9Sstevel@tonic-gate export_prop(of, PT_ADDRESS, nwiftab.zone_nwif_address); 1341*7c478bd9Sstevel@tonic-gate export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical); 1342*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1343*7c478bd9Sstevel@tonic-gate } 1344*7c478bd9Sstevel@tonic-gate (void) zonecfg_endnwifent(handle); 1345*7c478bd9Sstevel@tonic-gate 1346*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_setdevent(handle)) != Z_OK) { 1347*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, FALSE); 1348*7c478bd9Sstevel@tonic-gate goto done; 1349*7c478bd9Sstevel@tonic-gate } 1350*7c478bd9Sstevel@tonic-gate while (zonecfg_getdevent(handle, &devtab) == Z_OK) { 1351*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1352*7c478bd9Sstevel@tonic-gate rt_to_str(RT_DEVICE)); 1353*7c478bd9Sstevel@tonic-gate export_prop(of, PT_MATCH, devtab.zone_dev_match); 1354*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1355*7c478bd9Sstevel@tonic-gate } 1356*7c478bd9Sstevel@tonic-gate (void) zonecfg_enddevent(handle); 1357*7c478bd9Sstevel@tonic-gate 1358*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_setrctlent(handle)) != Z_OK) { 1359*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, FALSE); 1360*7c478bd9Sstevel@tonic-gate goto done; 1361*7c478bd9Sstevel@tonic-gate } 1362*7c478bd9Sstevel@tonic-gate while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) { 1363*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s rctl\n", cmd_to_str(CMD_ADD)); 1364*7c478bd9Sstevel@tonic-gate export_prop(of, PT_NAME, rctltab.zone_rctl_name); 1365*7c478bd9Sstevel@tonic-gate for (valptr = rctltab.zone_rctl_valptr; valptr != NULL; 1366*7c478bd9Sstevel@tonic-gate valptr = valptr->zone_rctlval_next) { 1367*7c478bd9Sstevel@tonic-gate fprintf(of, "%s %s (%s=%s,%s=%s,%s=%s)\n", 1368*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE), 1369*7c478bd9Sstevel@tonic-gate pt_to_str(PT_PRIV), valptr->zone_rctlval_priv, 1370*7c478bd9Sstevel@tonic-gate pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit, 1371*7c478bd9Sstevel@tonic-gate pt_to_str(PT_ACTION), valptr->zone_rctlval_action); 1372*7c478bd9Sstevel@tonic-gate } 1373*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1374*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 1375*7c478bd9Sstevel@tonic-gate } 1376*7c478bd9Sstevel@tonic-gate (void) zonecfg_endrctlent(handle); 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_setattrent(handle)) != Z_OK) { 1379*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, FALSE); 1380*7c478bd9Sstevel@tonic-gate goto done; 1381*7c478bd9Sstevel@tonic-gate } 1382*7c478bd9Sstevel@tonic-gate while (zonecfg_getattrent(handle, &attrtab) == Z_OK) { 1383*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD), 1384*7c478bd9Sstevel@tonic-gate rt_to_str(RT_ATTR)); 1385*7c478bd9Sstevel@tonic-gate export_prop(of, PT_NAME, attrtab.zone_attr_name); 1386*7c478bd9Sstevel@tonic-gate export_prop(of, PT_TYPE, attrtab.zone_attr_type); 1387*7c478bd9Sstevel@tonic-gate export_prop(of, PT_VALUE, attrtab.zone_attr_value); 1388*7c478bd9Sstevel@tonic-gate (void) fprintf(of, "%s\n", cmd_to_str(CMD_END)); 1389*7c478bd9Sstevel@tonic-gate } 1390*7c478bd9Sstevel@tonic-gate (void) zonecfg_endattrent(handle); 1391*7c478bd9Sstevel@tonic-gate 1392*7c478bd9Sstevel@tonic-gate done: 1393*7c478bd9Sstevel@tonic-gate if (need_to_close) 1394*7c478bd9Sstevel@tonic-gate (void) fclose(of); 1395*7c478bd9Sstevel@tonic-gate } 1396*7c478bd9Sstevel@tonic-gate 1397*7c478bd9Sstevel@tonic-gate void 1398*7c478bd9Sstevel@tonic-gate exit_func(cmd_t *cmd) 1399*7c478bd9Sstevel@tonic-gate { 1400*7c478bd9Sstevel@tonic-gate int arg, answer; 1401*7c478bd9Sstevel@tonic-gate 1402*7c478bd9Sstevel@tonic-gate optind = 0; 1403*7c478bd9Sstevel@tonic-gate while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) { 1404*7c478bd9Sstevel@tonic-gate switch (arg) { 1405*7c478bd9Sstevel@tonic-gate case '?': 1406*7c478bd9Sstevel@tonic-gate longer_usage(CMD_EXIT); 1407*7c478bd9Sstevel@tonic-gate return; 1408*7c478bd9Sstevel@tonic-gate case 'F': 1409*7c478bd9Sstevel@tonic-gate force_exit = TRUE; 1410*7c478bd9Sstevel@tonic-gate break; 1411*7c478bd9Sstevel@tonic-gate default: 1412*7c478bd9Sstevel@tonic-gate short_usage(CMD_EXIT); 1413*7c478bd9Sstevel@tonic-gate return; 1414*7c478bd9Sstevel@tonic-gate } 1415*7c478bd9Sstevel@tonic-gate } 1416*7c478bd9Sstevel@tonic-gate if (optind < cmd->cmd_argc) { 1417*7c478bd9Sstevel@tonic-gate short_usage(CMD_EXIT); 1418*7c478bd9Sstevel@tonic-gate return; 1419*7c478bd9Sstevel@tonic-gate } 1420*7c478bd9Sstevel@tonic-gate 1421*7c478bd9Sstevel@tonic-gate if (global_scope || force_exit) { 1422*7c478bd9Sstevel@tonic-gate time_to_exit = TRUE; 1423*7c478bd9Sstevel@tonic-gate return; 1424*7c478bd9Sstevel@tonic-gate } 1425*7c478bd9Sstevel@tonic-gate 1426*7c478bd9Sstevel@tonic-gate answer = ask_yesno(FALSE, "Resource incomplete; really quit"); 1427*7c478bd9Sstevel@tonic-gate if (answer == -1) { 1428*7c478bd9Sstevel@tonic-gate zerr(gettext("Resource incomplete, input " 1429*7c478bd9Sstevel@tonic-gate "not from terminal and -F not specified:\n%s command " 1430*7c478bd9Sstevel@tonic-gate "ignored, but exiting anyway."), cmd_to_str(CMD_EXIT)); 1431*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 1432*7c478bd9Sstevel@tonic-gate } else if (answer == 1) { 1433*7c478bd9Sstevel@tonic-gate time_to_exit = TRUE; 1434*7c478bd9Sstevel@tonic-gate } 1435*7c478bd9Sstevel@tonic-gate /* (answer == 0) => just return */ 1436*7c478bd9Sstevel@tonic-gate } 1437*7c478bd9Sstevel@tonic-gate 1438*7c478bd9Sstevel@tonic-gate static int 1439*7c478bd9Sstevel@tonic-gate validate_zonepath_syntax(char *path) 1440*7c478bd9Sstevel@tonic-gate { 1441*7c478bd9Sstevel@tonic-gate if (path[0] != '/') { 1442*7c478bd9Sstevel@tonic-gate zerr(gettext("%s is not an absolute path."), path); 1443*7c478bd9Sstevel@tonic-gate return (Z_ERR); 1444*7c478bd9Sstevel@tonic-gate } 1445*7c478bd9Sstevel@tonic-gate if (strcmp(path, "/") == 0) { 1446*7c478bd9Sstevel@tonic-gate zerr(gettext("/ is not allowed as a %s."), 1447*7c478bd9Sstevel@tonic-gate pt_to_str(PT_ZONEPATH)); 1448*7c478bd9Sstevel@tonic-gate return (Z_ERR); 1449*7c478bd9Sstevel@tonic-gate } 1450*7c478bd9Sstevel@tonic-gate return (Z_OK); 1451*7c478bd9Sstevel@tonic-gate } 1452*7c478bd9Sstevel@tonic-gate 1453*7c478bd9Sstevel@tonic-gate static void 1454*7c478bd9Sstevel@tonic-gate add_resource(cmd_t *cmd) 1455*7c478bd9Sstevel@tonic-gate { 1456*7c478bd9Sstevel@tonic-gate int type; 1457*7c478bd9Sstevel@tonic-gate zone_state_t state_num; 1458*7c478bd9Sstevel@tonic-gate 1459*7c478bd9Sstevel@tonic-gate if ((type = cmd->cmd_res_type) == RT_UNKNOWN) { 1460*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 1461*7c478bd9Sstevel@tonic-gate goto bad; 1462*7c478bd9Sstevel@tonic-gate } 1463*7c478bd9Sstevel@tonic-gate 1464*7c478bd9Sstevel@tonic-gate switch (type) { 1465*7c478bd9Sstevel@tonic-gate case RT_FS: 1466*7c478bd9Sstevel@tonic-gate bzero(&in_progress_fstab, sizeof (in_progress_fstab)); 1467*7c478bd9Sstevel@tonic-gate return; 1468*7c478bd9Sstevel@tonic-gate case RT_IPD: 1469*7c478bd9Sstevel@tonic-gate if (zone_get_state(zone, &state_num) == Z_OK && 1470*7c478bd9Sstevel@tonic-gate state_num >= ZONE_STATE_INSTALLED) { 1471*7c478bd9Sstevel@tonic-gate zerr(gettext("Zone %s already installed; %s %s not " 1472*7c478bd9Sstevel@tonic-gate "allowed."), zone, cmd_to_str(CMD_ADD), 1473*7c478bd9Sstevel@tonic-gate rt_to_str(RT_IPD)); 1474*7c478bd9Sstevel@tonic-gate goto bad; 1475*7c478bd9Sstevel@tonic-gate } 1476*7c478bd9Sstevel@tonic-gate bzero(&in_progress_ipdtab, sizeof (in_progress_ipdtab)); 1477*7c478bd9Sstevel@tonic-gate return; 1478*7c478bd9Sstevel@tonic-gate case RT_NET: 1479*7c478bd9Sstevel@tonic-gate bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab)); 1480*7c478bd9Sstevel@tonic-gate return; 1481*7c478bd9Sstevel@tonic-gate case RT_DEVICE: 1482*7c478bd9Sstevel@tonic-gate bzero(&in_progress_devtab, sizeof (in_progress_devtab)); 1483*7c478bd9Sstevel@tonic-gate return; 1484*7c478bd9Sstevel@tonic-gate case RT_RCTL: 1485*7c478bd9Sstevel@tonic-gate bzero(&in_progress_rctltab, sizeof (in_progress_rctltab)); 1486*7c478bd9Sstevel@tonic-gate return; 1487*7c478bd9Sstevel@tonic-gate case RT_ATTR: 1488*7c478bd9Sstevel@tonic-gate bzero(&in_progress_attrtab, sizeof (in_progress_attrtab)); 1489*7c478bd9Sstevel@tonic-gate return; 1490*7c478bd9Sstevel@tonic-gate default: 1491*7c478bd9Sstevel@tonic-gate zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, TRUE); 1492*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 1493*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_RESOURCES); 1494*7c478bd9Sstevel@tonic-gate } 1495*7c478bd9Sstevel@tonic-gate bad: 1496*7c478bd9Sstevel@tonic-gate global_scope = TRUE; 1497*7c478bd9Sstevel@tonic-gate end_op = -1; 1498*7c478bd9Sstevel@tonic-gate } 1499*7c478bd9Sstevel@tonic-gate 1500*7c478bd9Sstevel@tonic-gate static void 1501*7c478bd9Sstevel@tonic-gate do_complex_rctl_val(complex_property_ptr_t cp) 1502*7c478bd9Sstevel@tonic-gate { 1503*7c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *rctlvaltab; 1504*7c478bd9Sstevel@tonic-gate complex_property_ptr_t cx; 1505*7c478bd9Sstevel@tonic-gate bool seen_priv = FALSE, seen_limit = FALSE, seen_action = FALSE; 1506*7c478bd9Sstevel@tonic-gate rctlblk_t *rctlblk; 1507*7c478bd9Sstevel@tonic-gate int err; 1508*7c478bd9Sstevel@tonic-gate 1509*7c478bd9Sstevel@tonic-gate if ((rctlvaltab = alloc_rctlvaltab()) == NULL) { 1510*7c478bd9Sstevel@tonic-gate zone_perror(zone, Z_NOMEM, TRUE); 1511*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 1512*7c478bd9Sstevel@tonic-gate } 1513*7c478bd9Sstevel@tonic-gate for (cx = cp; cx != NULL; cx = cx->cp_next) { 1514*7c478bd9Sstevel@tonic-gate switch (cx->cp_type) { 1515*7c478bd9Sstevel@tonic-gate case PT_PRIV: 1516*7c478bd9Sstevel@tonic-gate if (seen_priv) { 1517*7c478bd9Sstevel@tonic-gate zerr(gettext("%s already specified"), 1518*7c478bd9Sstevel@tonic-gate pt_to_str(PT_PRIV)); 1519*7c478bd9Sstevel@tonic-gate goto bad; 1520*7c478bd9Sstevel@tonic-gate } 1521*7c478bd9Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_priv, 1522*7c478bd9Sstevel@tonic-gate cx->cp_value, 1523*7c478bd9Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_priv)); 1524*7c478bd9Sstevel@tonic-gate seen_priv = TRUE; 1525*7c478bd9Sstevel@tonic-gate break; 1526*7c478bd9Sstevel@tonic-gate case PT_LIMIT: 1527*7c478bd9Sstevel@tonic-gate if (seen_limit) { 1528*7c478bd9Sstevel@tonic-gate zerr(gettext("%s already specified"), 1529*7c478bd9Sstevel@tonic-gate pt_to_str(PT_LIMIT)); 1530*7c478bd9Sstevel@tonic-gate goto bad; 1531*7c478bd9Sstevel@tonic-gate } 1532*7c478bd9Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_limit, 1533*7c478bd9Sstevel@tonic-gate cx->cp_value, 1534*7c478bd9Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_limit)); 1535*7c478bd9Sstevel@tonic-gate seen_limit = TRUE; 1536*7c478bd9Sstevel@tonic-gate break; 1537*7c478bd9Sstevel@tonic-gate case PT_ACTION: 1538*7c478bd9Sstevel@tonic-gate if (seen_action) { 1539*7c478bd9Sstevel@tonic-gate zerr(gettext("%s already specified"), 1540*7c478bd9Sstevel@tonic-gate pt_to_str(PT_ACTION)); 1541*7c478bd9Sstevel@tonic-gate goto bad; 1542*7c478bd9Sstevel@tonic-gate } 1543*7c478bd9Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_action, 1544*7c478bd9Sstevel@tonic-gate cx->cp_value, 1545*7c478bd9Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_action)); 1546*7c478bd9Sstevel@tonic-gate seen_action = TRUE; 1547*7c478bd9Sstevel@tonic-gate break; 1548*7c478bd9Sstevel@tonic-gate default: 1549*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(PT_VALUE), 1550*7c478bd9Sstevel@tonic-gate Z_NO_PROPERTY_TYPE, TRUE); 1551*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 1552*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 1553*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctlvaltab); 1554*7c478bd9Sstevel@tonic-gate return; 1555*7c478bd9Sstevel@tonic-gate } 1556*7c478bd9Sstevel@tonic-gate } 1557*7c478bd9Sstevel@tonic-gate if (!seen_priv) 1558*7c478bd9Sstevel@tonic-gate zerr(gettext("%s not specified"), pt_to_str(PT_PRIV)); 1559*7c478bd9Sstevel@tonic-gate if (!seen_limit) 1560*7c478bd9Sstevel@tonic-gate zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT)); 1561*7c478bd9Sstevel@tonic-gate if (!seen_action) 1562*7c478bd9Sstevel@tonic-gate zerr(gettext("%s not specified"), pt_to_str(PT_ACTION)); 1563*7c478bd9Sstevel@tonic-gate if (!seen_priv || !seen_limit || !seen_action) 1564*7c478bd9Sstevel@tonic-gate goto bad; 1565*7c478bd9Sstevel@tonic-gate rctlvaltab->zone_rctlval_next = NULL; 1566*7c478bd9Sstevel@tonic-gate rctlblk = alloca(rctlblk_size()); 1567*7c478bd9Sstevel@tonic-gate /* 1568*7c478bd9Sstevel@tonic-gate * Make sure the rctl value looks roughly correct; we won't know if 1569*7c478bd9Sstevel@tonic-gate * it's truly OK until we verify the configuration on the target 1570*7c478bd9Sstevel@tonic-gate * system. 1571*7c478bd9Sstevel@tonic-gate */ 1572*7c478bd9Sstevel@tonic-gate if (zonecfg_construct_rctlblk(rctlvaltab, rctlblk) != Z_OK || 1573*7c478bd9Sstevel@tonic-gate !zonecfg_valid_rctlblk(rctlblk)) { 1574*7c478bd9Sstevel@tonic-gate zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL), 1575*7c478bd9Sstevel@tonic-gate pt_to_str(PT_VALUE)); 1576*7c478bd9Sstevel@tonic-gate goto bad; 1577*7c478bd9Sstevel@tonic-gate } 1578*7c478bd9Sstevel@tonic-gate err = zonecfg_add_rctl_value(&in_progress_rctltab, rctlvaltab); 1579*7c478bd9Sstevel@tonic-gate if (err != Z_OK) 1580*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(PT_VALUE), err, TRUE); 1581*7c478bd9Sstevel@tonic-gate return; 1582*7c478bd9Sstevel@tonic-gate 1583*7c478bd9Sstevel@tonic-gate bad: 1584*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctlvaltab); 1585*7c478bd9Sstevel@tonic-gate } 1586*7c478bd9Sstevel@tonic-gate 1587*7c478bd9Sstevel@tonic-gate static void 1588*7c478bd9Sstevel@tonic-gate add_property(cmd_t *cmd) 1589*7c478bd9Sstevel@tonic-gate { 1590*7c478bd9Sstevel@tonic-gate char *prop_id; 1591*7c478bd9Sstevel@tonic-gate int err, res_type, prop_type; 1592*7c478bd9Sstevel@tonic-gate property_value_ptr_t pp; 1593*7c478bd9Sstevel@tonic-gate list_property_ptr_t l; 1594*7c478bd9Sstevel@tonic-gate 1595*7c478bd9Sstevel@tonic-gate res_type = resource_scope; 1596*7c478bd9Sstevel@tonic-gate prop_type = cmd->cmd_prop_name[0]; 1597*7c478bd9Sstevel@tonic-gate if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) { 1598*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 1599*7c478bd9Sstevel@tonic-gate return; 1600*7c478bd9Sstevel@tonic-gate } 1601*7c478bd9Sstevel@tonic-gate 1602*7c478bd9Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs != 1) { 1603*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 1604*7c478bd9Sstevel@tonic-gate return; 1605*7c478bd9Sstevel@tonic-gate } 1606*7c478bd9Sstevel@tonic-gate 1607*7c478bd9Sstevel@tonic-gate if (initialize(TRUE) != Z_OK) 1608*7c478bd9Sstevel@tonic-gate return; 1609*7c478bd9Sstevel@tonic-gate 1610*7c478bd9Sstevel@tonic-gate switch (res_type) { 1611*7c478bd9Sstevel@tonic-gate case RT_FS: 1612*7c478bd9Sstevel@tonic-gate if (prop_type != PT_OPTIONS) { 1613*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 1614*7c478bd9Sstevel@tonic-gate TRUE); 1615*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 1616*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 1617*7c478bd9Sstevel@tonic-gate return; 1618*7c478bd9Sstevel@tonic-gate } 1619*7c478bd9Sstevel@tonic-gate pp = cmd->cmd_property_ptr[0]; 1620*7c478bd9Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE && 1621*7c478bd9Sstevel@tonic-gate pp->pv_type != PROP_VAL_LIST) { 1622*7c478bd9Sstevel@tonic-gate zerr(gettext("A %s or %s value was expected here."), 1623*7c478bd9Sstevel@tonic-gate pvt_to_str(PROP_VAL_SIMPLE), 1624*7c478bd9Sstevel@tonic-gate pvt_to_str(PROP_VAL_LIST)); 1625*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1626*7c478bd9Sstevel@tonic-gate return; 1627*7c478bd9Sstevel@tonic-gate } 1628*7c478bd9Sstevel@tonic-gate if (pp->pv_type == PROP_VAL_SIMPLE) { 1629*7c478bd9Sstevel@tonic-gate if (pp->pv_simple == NULL) { 1630*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 1631*7c478bd9Sstevel@tonic-gate return; 1632*7c478bd9Sstevel@tonic-gate } 1633*7c478bd9Sstevel@tonic-gate prop_id = pp->pv_simple; 1634*7c478bd9Sstevel@tonic-gate err = zonecfg_add_fs_option(&in_progress_fstab, 1635*7c478bd9Sstevel@tonic-gate prop_id); 1636*7c478bd9Sstevel@tonic-gate if (err != Z_OK) 1637*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), err, TRUE); 1638*7c478bd9Sstevel@tonic-gate } else { 1639*7c478bd9Sstevel@tonic-gate list_property_ptr_t list; 1640*7c478bd9Sstevel@tonic-gate 1641*7c478bd9Sstevel@tonic-gate for (list = pp->pv_list; list != NULL; 1642*7c478bd9Sstevel@tonic-gate list = list->lp_next) { 1643*7c478bd9Sstevel@tonic-gate prop_id = list->lp_simple; 1644*7c478bd9Sstevel@tonic-gate if (prop_id == NULL) 1645*7c478bd9Sstevel@tonic-gate break; 1646*7c478bd9Sstevel@tonic-gate err = zonecfg_add_fs_option( 1647*7c478bd9Sstevel@tonic-gate &in_progress_fstab, prop_id); 1648*7c478bd9Sstevel@tonic-gate if (err != Z_OK) 1649*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), err, 1650*7c478bd9Sstevel@tonic-gate TRUE); 1651*7c478bd9Sstevel@tonic-gate } 1652*7c478bd9Sstevel@tonic-gate } 1653*7c478bd9Sstevel@tonic-gate return; 1654*7c478bd9Sstevel@tonic-gate case RT_RCTL: 1655*7c478bd9Sstevel@tonic-gate if (prop_type != PT_VALUE) { 1656*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 1657*7c478bd9Sstevel@tonic-gate TRUE); 1658*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 1659*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 1660*7c478bd9Sstevel@tonic-gate return; 1661*7c478bd9Sstevel@tonic-gate } 1662*7c478bd9Sstevel@tonic-gate pp = cmd->cmd_property_ptr[0]; 1663*7c478bd9Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_COMPLEX && 1664*7c478bd9Sstevel@tonic-gate pp->pv_type != PROP_VAL_LIST) { 1665*7c478bd9Sstevel@tonic-gate zerr(gettext("A %s or %s value was expected here."), 1666*7c478bd9Sstevel@tonic-gate pvt_to_str(PROP_VAL_COMPLEX), 1667*7c478bd9Sstevel@tonic-gate pvt_to_str(PROP_VAL_LIST)); 1668*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1669*7c478bd9Sstevel@tonic-gate return; 1670*7c478bd9Sstevel@tonic-gate } 1671*7c478bd9Sstevel@tonic-gate if (pp->pv_type == PROP_VAL_COMPLEX) { 1672*7c478bd9Sstevel@tonic-gate do_complex_rctl_val(pp->pv_complex); 1673*7c478bd9Sstevel@tonic-gate return; 1674*7c478bd9Sstevel@tonic-gate } 1675*7c478bd9Sstevel@tonic-gate for (l = pp->pv_list; l != NULL; l = l->lp_next) 1676*7c478bd9Sstevel@tonic-gate do_complex_rctl_val(l->lp_complex); 1677*7c478bd9Sstevel@tonic-gate return; 1678*7c478bd9Sstevel@tonic-gate default: 1679*7c478bd9Sstevel@tonic-gate zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, TRUE); 1680*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 1681*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_RESOURCES); 1682*7c478bd9Sstevel@tonic-gate return; 1683*7c478bd9Sstevel@tonic-gate } 1684*7c478bd9Sstevel@tonic-gate } 1685*7c478bd9Sstevel@tonic-gate 1686*7c478bd9Sstevel@tonic-gate void 1687*7c478bd9Sstevel@tonic-gate add_func(cmd_t *cmd) 1688*7c478bd9Sstevel@tonic-gate { 1689*7c478bd9Sstevel@tonic-gate int arg; 1690*7c478bd9Sstevel@tonic-gate 1691*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 1692*7c478bd9Sstevel@tonic-gate 1693*7c478bd9Sstevel@tonic-gate optind = 0; 1694*7c478bd9Sstevel@tonic-gate if ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) { 1695*7c478bd9Sstevel@tonic-gate switch (arg) { 1696*7c478bd9Sstevel@tonic-gate case '?': 1697*7c478bd9Sstevel@tonic-gate longer_usage(CMD_ADD); 1698*7c478bd9Sstevel@tonic-gate return; 1699*7c478bd9Sstevel@tonic-gate default: 1700*7c478bd9Sstevel@tonic-gate short_usage(CMD_ADD); 1701*7c478bd9Sstevel@tonic-gate return; 1702*7c478bd9Sstevel@tonic-gate } 1703*7c478bd9Sstevel@tonic-gate } 1704*7c478bd9Sstevel@tonic-gate if (optind != cmd->cmd_argc) { 1705*7c478bd9Sstevel@tonic-gate short_usage(CMD_ADD); 1706*7c478bd9Sstevel@tonic-gate return; 1707*7c478bd9Sstevel@tonic-gate } 1708*7c478bd9Sstevel@tonic-gate 1709*7c478bd9Sstevel@tonic-gate if (zone_is_read_only(CMD_ADD)) 1710*7c478bd9Sstevel@tonic-gate return; 1711*7c478bd9Sstevel@tonic-gate 1712*7c478bd9Sstevel@tonic-gate if (initialize(TRUE) != Z_OK) 1713*7c478bd9Sstevel@tonic-gate return; 1714*7c478bd9Sstevel@tonic-gate if (global_scope) { 1715*7c478bd9Sstevel@tonic-gate global_scope = FALSE; 1716*7c478bd9Sstevel@tonic-gate resource_scope = cmd->cmd_res_type; 1717*7c478bd9Sstevel@tonic-gate end_op = CMD_ADD; 1718*7c478bd9Sstevel@tonic-gate add_resource(cmd); 1719*7c478bd9Sstevel@tonic-gate } else 1720*7c478bd9Sstevel@tonic-gate add_property(cmd); 1721*7c478bd9Sstevel@tonic-gate } 1722*7c478bd9Sstevel@tonic-gate 1723*7c478bd9Sstevel@tonic-gate void 1724*7c478bd9Sstevel@tonic-gate delete_func(cmd_t *cmd) 1725*7c478bd9Sstevel@tonic-gate { 1726*7c478bd9Sstevel@tonic-gate int err, arg, answer; 1727*7c478bd9Sstevel@tonic-gate char line[ZONENAME_MAX + 128]; /* enough to ask a question */ 1728*7c478bd9Sstevel@tonic-gate bool force = FALSE; 1729*7c478bd9Sstevel@tonic-gate zone_state_t state_num; 1730*7c478bd9Sstevel@tonic-gate 1731*7c478bd9Sstevel@tonic-gate optind = 0; 1732*7c478bd9Sstevel@tonic-gate while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) { 1733*7c478bd9Sstevel@tonic-gate switch (arg) { 1734*7c478bd9Sstevel@tonic-gate case '?': 1735*7c478bd9Sstevel@tonic-gate longer_usage(CMD_DELETE); 1736*7c478bd9Sstevel@tonic-gate return; 1737*7c478bd9Sstevel@tonic-gate case 'F': 1738*7c478bd9Sstevel@tonic-gate force = TRUE; 1739*7c478bd9Sstevel@tonic-gate break; 1740*7c478bd9Sstevel@tonic-gate default: 1741*7c478bd9Sstevel@tonic-gate short_usage(CMD_DELETE); 1742*7c478bd9Sstevel@tonic-gate return; 1743*7c478bd9Sstevel@tonic-gate } 1744*7c478bd9Sstevel@tonic-gate } 1745*7c478bd9Sstevel@tonic-gate if (optind != cmd->cmd_argc) { 1746*7c478bd9Sstevel@tonic-gate short_usage(CMD_DELETE); 1747*7c478bd9Sstevel@tonic-gate return; 1748*7c478bd9Sstevel@tonic-gate } 1749*7c478bd9Sstevel@tonic-gate 1750*7c478bd9Sstevel@tonic-gate if (zone_is_read_only(CMD_DELETE)) 1751*7c478bd9Sstevel@tonic-gate return; 1752*7c478bd9Sstevel@tonic-gate 1753*7c478bd9Sstevel@tonic-gate if (zone_get_state(zone, &state_num) == Z_OK && 1754*7c478bd9Sstevel@tonic-gate state_num >= ZONE_STATE_INCOMPLETE) { 1755*7c478bd9Sstevel@tonic-gate zerr(gettext("Zone %s not in %s state; %s not allowed."), 1756*7c478bd9Sstevel@tonic-gate zone, zone_state_str(ZONE_STATE_CONFIGURED), 1757*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_DELETE)); 1758*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1759*7c478bd9Sstevel@tonic-gate return; 1760*7c478bd9Sstevel@tonic-gate } 1761*7c478bd9Sstevel@tonic-gate 1762*7c478bd9Sstevel@tonic-gate if (initialize(TRUE) != Z_OK) 1763*7c478bd9Sstevel@tonic-gate return; 1764*7c478bd9Sstevel@tonic-gate 1765*7c478bd9Sstevel@tonic-gate if (!force) { 1766*7c478bd9Sstevel@tonic-gate (void) snprintf(line, sizeof (line), 1767*7c478bd9Sstevel@tonic-gate gettext("Are you sure you want to delete zone %s"), zone); 1768*7c478bd9Sstevel@tonic-gate if ((answer = ask_yesno(FALSE, line)) == -1) { 1769*7c478bd9Sstevel@tonic-gate zerr(gettext("Input not from " 1770*7c478bd9Sstevel@tonic-gate "terminal and -F not specified:\n%s command " 1771*7c478bd9Sstevel@tonic-gate "ignored, exiting."), cmd_to_str(CMD_DELETE)); 1772*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 1773*7c478bd9Sstevel@tonic-gate } 1774*7c478bd9Sstevel@tonic-gate if (answer != 1) 1775*7c478bd9Sstevel@tonic-gate return; 1776*7c478bd9Sstevel@tonic-gate } 1777*7c478bd9Sstevel@tonic-gate 1778*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_index(zone)) != Z_OK) { 1779*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 1780*7c478bd9Sstevel@tonic-gate return; 1781*7c478bd9Sstevel@tonic-gate } 1782*7c478bd9Sstevel@tonic-gate 1783*7c478bd9Sstevel@tonic-gate need_to_commit = FALSE; 1784*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_destroy(zone)) != Z_OK) 1785*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 1786*7c478bd9Sstevel@tonic-gate 1787*7c478bd9Sstevel@tonic-gate /* 1788*7c478bd9Sstevel@tonic-gate * Time for a new handle: finish the old one off first 1789*7c478bd9Sstevel@tonic-gate * then get a new one properly to avoid leaks. 1790*7c478bd9Sstevel@tonic-gate */ 1791*7c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 1792*7c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) { 1793*7c478bd9Sstevel@tonic-gate zone_perror(execname, Z_NOMEM, TRUE); 1794*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 1795*7c478bd9Sstevel@tonic-gate } 1796*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) { 1797*7c478bd9Sstevel@tonic-gate /* If there was no zone before, that's OK */ 1798*7c478bd9Sstevel@tonic-gate if (err != Z_NO_ZONE) 1799*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 1800*7c478bd9Sstevel@tonic-gate got_handle = FALSE; 1801*7c478bd9Sstevel@tonic-gate } 1802*7c478bd9Sstevel@tonic-gate } 1803*7c478bd9Sstevel@tonic-gate 1804*7c478bd9Sstevel@tonic-gate static int 1805*7c478bd9Sstevel@tonic-gate fill_in_fstab(cmd_t *cmd, struct zone_fstab *fstab, bool fill_in_only) 1806*7c478bd9Sstevel@tonic-gate { 1807*7c478bd9Sstevel@tonic-gate int err, i; 1808*7c478bd9Sstevel@tonic-gate property_value_ptr_t pp; 1809*7c478bd9Sstevel@tonic-gate 1810*7c478bd9Sstevel@tonic-gate if ((err = initialize(TRUE)) != Z_OK) 1811*7c478bd9Sstevel@tonic-gate return (err); 1812*7c478bd9Sstevel@tonic-gate 1813*7c478bd9Sstevel@tonic-gate fstab->zone_fs_dir[0] = '\0'; 1814*7c478bd9Sstevel@tonic-gate fstab->zone_fs_special[0] = '\0'; 1815*7c478bd9Sstevel@tonic-gate fstab->zone_fs_type[0] = '\0'; 1816*7c478bd9Sstevel@tonic-gate fstab->zone_fs_options = NULL; 1817*7c478bd9Sstevel@tonic-gate for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 1818*7c478bd9Sstevel@tonic-gate pp = cmd->cmd_property_ptr[i]; 1819*7c478bd9Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 1820*7c478bd9Sstevel@tonic-gate zerr(gettext("A simple value was expected here.")); 1821*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1822*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 1823*7c478bd9Sstevel@tonic-gate } 1824*7c478bd9Sstevel@tonic-gate switch (cmd->cmd_prop_name[i]) { 1825*7c478bd9Sstevel@tonic-gate case PT_DIR: 1826*7c478bd9Sstevel@tonic-gate (void) strlcpy(fstab->zone_fs_dir, pp->pv_simple, 1827*7c478bd9Sstevel@tonic-gate sizeof (fstab->zone_fs_dir)); 1828*7c478bd9Sstevel@tonic-gate break; 1829*7c478bd9Sstevel@tonic-gate case PT_SPECIAL: 1830*7c478bd9Sstevel@tonic-gate (void) strlcpy(fstab->zone_fs_special, pp->pv_simple, 1831*7c478bd9Sstevel@tonic-gate sizeof (fstab->zone_fs_special)); 1832*7c478bd9Sstevel@tonic-gate break; 1833*7c478bd9Sstevel@tonic-gate case PT_RAW: 1834*7c478bd9Sstevel@tonic-gate (void) strlcpy(fstab->zone_fs_raw, pp->pv_simple, 1835*7c478bd9Sstevel@tonic-gate sizeof (fstab->zone_fs_raw)); 1836*7c478bd9Sstevel@tonic-gate break; 1837*7c478bd9Sstevel@tonic-gate case PT_TYPE: 1838*7c478bd9Sstevel@tonic-gate (void) strlcpy(fstab->zone_fs_type, pp->pv_simple, 1839*7c478bd9Sstevel@tonic-gate sizeof (fstab->zone_fs_type)); 1840*7c478bd9Sstevel@tonic-gate break; 1841*7c478bd9Sstevel@tonic-gate default: 1842*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 1843*7c478bd9Sstevel@tonic-gate Z_NO_PROPERTY_TYPE, TRUE); 1844*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 1845*7c478bd9Sstevel@tonic-gate } 1846*7c478bd9Sstevel@tonic-gate } 1847*7c478bd9Sstevel@tonic-gate if (fill_in_only) 1848*7c478bd9Sstevel@tonic-gate return (Z_OK); 1849*7c478bd9Sstevel@tonic-gate return (zonecfg_lookup_filesystem(handle, fstab)); 1850*7c478bd9Sstevel@tonic-gate } 1851*7c478bd9Sstevel@tonic-gate 1852*7c478bd9Sstevel@tonic-gate static int 1853*7c478bd9Sstevel@tonic-gate fill_in_ipdtab(cmd_t *cmd, struct zone_fstab *ipdtab, bool fill_in_only) 1854*7c478bd9Sstevel@tonic-gate { 1855*7c478bd9Sstevel@tonic-gate int err, i; 1856*7c478bd9Sstevel@tonic-gate property_value_ptr_t pp; 1857*7c478bd9Sstevel@tonic-gate 1858*7c478bd9Sstevel@tonic-gate if ((err = initialize(TRUE)) != Z_OK) 1859*7c478bd9Sstevel@tonic-gate return (err); 1860*7c478bd9Sstevel@tonic-gate 1861*7c478bd9Sstevel@tonic-gate ipdtab->zone_fs_dir[0] = '\0'; 1862*7c478bd9Sstevel@tonic-gate for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 1863*7c478bd9Sstevel@tonic-gate pp = cmd->cmd_property_ptr[i]; 1864*7c478bd9Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 1865*7c478bd9Sstevel@tonic-gate zerr(gettext("A simple value was expected here.")); 1866*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1867*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 1868*7c478bd9Sstevel@tonic-gate } 1869*7c478bd9Sstevel@tonic-gate switch (cmd->cmd_prop_name[i]) { 1870*7c478bd9Sstevel@tonic-gate case PT_DIR: 1871*7c478bd9Sstevel@tonic-gate (void) strlcpy(ipdtab->zone_fs_dir, pp->pv_simple, 1872*7c478bd9Sstevel@tonic-gate sizeof (ipdtab->zone_fs_dir)); 1873*7c478bd9Sstevel@tonic-gate break; 1874*7c478bd9Sstevel@tonic-gate default: 1875*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 1876*7c478bd9Sstevel@tonic-gate Z_NO_PROPERTY_TYPE, TRUE); 1877*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 1878*7c478bd9Sstevel@tonic-gate } 1879*7c478bd9Sstevel@tonic-gate } 1880*7c478bd9Sstevel@tonic-gate if (fill_in_only) 1881*7c478bd9Sstevel@tonic-gate return (Z_OK); 1882*7c478bd9Sstevel@tonic-gate return (zonecfg_lookup_ipd(handle, ipdtab)); 1883*7c478bd9Sstevel@tonic-gate } 1884*7c478bd9Sstevel@tonic-gate 1885*7c478bd9Sstevel@tonic-gate static int 1886*7c478bd9Sstevel@tonic-gate fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab, bool fill_in_only) 1887*7c478bd9Sstevel@tonic-gate { 1888*7c478bd9Sstevel@tonic-gate int err, i; 1889*7c478bd9Sstevel@tonic-gate property_value_ptr_t pp; 1890*7c478bd9Sstevel@tonic-gate 1891*7c478bd9Sstevel@tonic-gate if ((err = initialize(TRUE)) != Z_OK) 1892*7c478bd9Sstevel@tonic-gate return (err); 1893*7c478bd9Sstevel@tonic-gate 1894*7c478bd9Sstevel@tonic-gate nwiftab->zone_nwif_address[0] = '\0'; 1895*7c478bd9Sstevel@tonic-gate nwiftab->zone_nwif_physical[0] = '\0'; 1896*7c478bd9Sstevel@tonic-gate for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 1897*7c478bd9Sstevel@tonic-gate pp = cmd->cmd_property_ptr[i]; 1898*7c478bd9Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 1899*7c478bd9Sstevel@tonic-gate zerr(gettext("A simple value was expected here.")); 1900*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1901*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 1902*7c478bd9Sstevel@tonic-gate } 1903*7c478bd9Sstevel@tonic-gate switch (cmd->cmd_prop_name[i]) { 1904*7c478bd9Sstevel@tonic-gate case PT_ADDRESS: 1905*7c478bd9Sstevel@tonic-gate (void) strlcpy(nwiftab->zone_nwif_address, 1906*7c478bd9Sstevel@tonic-gate pp->pv_simple, sizeof (nwiftab->zone_nwif_address)); 1907*7c478bd9Sstevel@tonic-gate break; 1908*7c478bd9Sstevel@tonic-gate case PT_PHYSICAL: 1909*7c478bd9Sstevel@tonic-gate (void) strlcpy(nwiftab->zone_nwif_physical, 1910*7c478bd9Sstevel@tonic-gate pp->pv_simple, 1911*7c478bd9Sstevel@tonic-gate sizeof (nwiftab->zone_nwif_physical)); 1912*7c478bd9Sstevel@tonic-gate break; 1913*7c478bd9Sstevel@tonic-gate default: 1914*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 1915*7c478bd9Sstevel@tonic-gate Z_NO_PROPERTY_TYPE, TRUE); 1916*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 1917*7c478bd9Sstevel@tonic-gate } 1918*7c478bd9Sstevel@tonic-gate } 1919*7c478bd9Sstevel@tonic-gate if (fill_in_only) 1920*7c478bd9Sstevel@tonic-gate return (Z_OK); 1921*7c478bd9Sstevel@tonic-gate err = zonecfg_lookup_nwif(handle, nwiftab); 1922*7c478bd9Sstevel@tonic-gate return (err); 1923*7c478bd9Sstevel@tonic-gate } 1924*7c478bd9Sstevel@tonic-gate 1925*7c478bd9Sstevel@tonic-gate static int 1926*7c478bd9Sstevel@tonic-gate fill_in_devtab(cmd_t *cmd, struct zone_devtab *devtab, bool fill_in_only) 1927*7c478bd9Sstevel@tonic-gate { 1928*7c478bd9Sstevel@tonic-gate int err, i; 1929*7c478bd9Sstevel@tonic-gate property_value_ptr_t pp; 1930*7c478bd9Sstevel@tonic-gate 1931*7c478bd9Sstevel@tonic-gate if ((err = initialize(TRUE)) != Z_OK) 1932*7c478bd9Sstevel@tonic-gate return (err); 1933*7c478bd9Sstevel@tonic-gate 1934*7c478bd9Sstevel@tonic-gate devtab->zone_dev_match[0] = '\0'; 1935*7c478bd9Sstevel@tonic-gate for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 1936*7c478bd9Sstevel@tonic-gate pp = cmd->cmd_property_ptr[i]; 1937*7c478bd9Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 1938*7c478bd9Sstevel@tonic-gate zerr(gettext("A simple value was expected here.")); 1939*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1940*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 1941*7c478bd9Sstevel@tonic-gate } 1942*7c478bd9Sstevel@tonic-gate switch (cmd->cmd_prop_name[i]) { 1943*7c478bd9Sstevel@tonic-gate case PT_MATCH: 1944*7c478bd9Sstevel@tonic-gate (void) strlcpy(devtab->zone_dev_match, pp->pv_simple, 1945*7c478bd9Sstevel@tonic-gate sizeof (devtab->zone_dev_match)); 1946*7c478bd9Sstevel@tonic-gate break; 1947*7c478bd9Sstevel@tonic-gate default: 1948*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 1949*7c478bd9Sstevel@tonic-gate Z_NO_PROPERTY_TYPE, TRUE); 1950*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 1951*7c478bd9Sstevel@tonic-gate } 1952*7c478bd9Sstevel@tonic-gate } 1953*7c478bd9Sstevel@tonic-gate if (fill_in_only) 1954*7c478bd9Sstevel@tonic-gate return (Z_OK); 1955*7c478bd9Sstevel@tonic-gate err = zonecfg_lookup_dev(handle, devtab); 1956*7c478bd9Sstevel@tonic-gate return (err); 1957*7c478bd9Sstevel@tonic-gate } 1958*7c478bd9Sstevel@tonic-gate 1959*7c478bd9Sstevel@tonic-gate static int 1960*7c478bd9Sstevel@tonic-gate fill_in_rctltab(cmd_t *cmd, struct zone_rctltab *rctltab, bool fill_in_only) 1961*7c478bd9Sstevel@tonic-gate { 1962*7c478bd9Sstevel@tonic-gate int err, i; 1963*7c478bd9Sstevel@tonic-gate property_value_ptr_t pp; 1964*7c478bd9Sstevel@tonic-gate 1965*7c478bd9Sstevel@tonic-gate if ((err = initialize(TRUE)) != Z_OK) 1966*7c478bd9Sstevel@tonic-gate return (err); 1967*7c478bd9Sstevel@tonic-gate 1968*7c478bd9Sstevel@tonic-gate rctltab->zone_rctl_name[0] = '\0'; 1969*7c478bd9Sstevel@tonic-gate for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 1970*7c478bd9Sstevel@tonic-gate pp = cmd->cmd_property_ptr[i]; 1971*7c478bd9Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 1972*7c478bd9Sstevel@tonic-gate zerr(gettext("A simple value was expected here.")); 1973*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 1974*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 1975*7c478bd9Sstevel@tonic-gate } 1976*7c478bd9Sstevel@tonic-gate switch (cmd->cmd_prop_name[i]) { 1977*7c478bd9Sstevel@tonic-gate case PT_NAME: 1978*7c478bd9Sstevel@tonic-gate (void) strlcpy(rctltab->zone_rctl_name, pp->pv_simple, 1979*7c478bd9Sstevel@tonic-gate sizeof (rctltab->zone_rctl_name)); 1980*7c478bd9Sstevel@tonic-gate break; 1981*7c478bd9Sstevel@tonic-gate default: 1982*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 1983*7c478bd9Sstevel@tonic-gate Z_NO_PROPERTY_TYPE, TRUE); 1984*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 1985*7c478bd9Sstevel@tonic-gate } 1986*7c478bd9Sstevel@tonic-gate } 1987*7c478bd9Sstevel@tonic-gate if (fill_in_only) 1988*7c478bd9Sstevel@tonic-gate return (Z_OK); 1989*7c478bd9Sstevel@tonic-gate err = zonecfg_lookup_rctl(handle, rctltab); 1990*7c478bd9Sstevel@tonic-gate return (err); 1991*7c478bd9Sstevel@tonic-gate } 1992*7c478bd9Sstevel@tonic-gate 1993*7c478bd9Sstevel@tonic-gate static int 1994*7c478bd9Sstevel@tonic-gate fill_in_attrtab(cmd_t *cmd, struct zone_attrtab *attrtab, bool fill_in_only) 1995*7c478bd9Sstevel@tonic-gate { 1996*7c478bd9Sstevel@tonic-gate int err, i; 1997*7c478bd9Sstevel@tonic-gate property_value_ptr_t pp; 1998*7c478bd9Sstevel@tonic-gate 1999*7c478bd9Sstevel@tonic-gate if ((err = initialize(TRUE)) != Z_OK) 2000*7c478bd9Sstevel@tonic-gate return (err); 2001*7c478bd9Sstevel@tonic-gate 2002*7c478bd9Sstevel@tonic-gate attrtab->zone_attr_name[0] = '\0'; 2003*7c478bd9Sstevel@tonic-gate attrtab->zone_attr_type[0] = '\0'; 2004*7c478bd9Sstevel@tonic-gate attrtab->zone_attr_value[0] = '\0'; 2005*7c478bd9Sstevel@tonic-gate for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) { 2006*7c478bd9Sstevel@tonic-gate pp = cmd->cmd_property_ptr[i]; 2007*7c478bd9Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) { 2008*7c478bd9Sstevel@tonic-gate zerr(gettext("A simple value was expected here.")); 2009*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2010*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 2011*7c478bd9Sstevel@tonic-gate } 2012*7c478bd9Sstevel@tonic-gate switch (cmd->cmd_prop_name[i]) { 2013*7c478bd9Sstevel@tonic-gate case PT_NAME: 2014*7c478bd9Sstevel@tonic-gate (void) strlcpy(attrtab->zone_attr_name, pp->pv_simple, 2015*7c478bd9Sstevel@tonic-gate sizeof (attrtab->zone_attr_name)); 2016*7c478bd9Sstevel@tonic-gate break; 2017*7c478bd9Sstevel@tonic-gate case PT_TYPE: 2018*7c478bd9Sstevel@tonic-gate (void) strlcpy(attrtab->zone_attr_type, pp->pv_simple, 2019*7c478bd9Sstevel@tonic-gate sizeof (attrtab->zone_attr_type)); 2020*7c478bd9Sstevel@tonic-gate break; 2021*7c478bd9Sstevel@tonic-gate case PT_VALUE: 2022*7c478bd9Sstevel@tonic-gate (void) strlcpy(attrtab->zone_attr_value, pp->pv_simple, 2023*7c478bd9Sstevel@tonic-gate sizeof (attrtab->zone_attr_value)); 2024*7c478bd9Sstevel@tonic-gate break; 2025*7c478bd9Sstevel@tonic-gate default: 2026*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(cmd->cmd_prop_name[i]), 2027*7c478bd9Sstevel@tonic-gate Z_NO_PROPERTY_TYPE, TRUE); 2028*7c478bd9Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC); 2029*7c478bd9Sstevel@tonic-gate } 2030*7c478bd9Sstevel@tonic-gate } 2031*7c478bd9Sstevel@tonic-gate if (fill_in_only) 2032*7c478bd9Sstevel@tonic-gate return (Z_OK); 2033*7c478bd9Sstevel@tonic-gate err = zonecfg_lookup_attr(handle, attrtab); 2034*7c478bd9Sstevel@tonic-gate return (err); 2035*7c478bd9Sstevel@tonic-gate } 2036*7c478bd9Sstevel@tonic-gate 2037*7c478bd9Sstevel@tonic-gate static void 2038*7c478bd9Sstevel@tonic-gate remove_resource(cmd_t *cmd) 2039*7c478bd9Sstevel@tonic-gate { 2040*7c478bd9Sstevel@tonic-gate int err, type; 2041*7c478bd9Sstevel@tonic-gate struct zone_fstab fstab; 2042*7c478bd9Sstevel@tonic-gate struct zone_nwiftab nwiftab; 2043*7c478bd9Sstevel@tonic-gate struct zone_devtab devtab; 2044*7c478bd9Sstevel@tonic-gate struct zone_attrtab attrtab; 2045*7c478bd9Sstevel@tonic-gate struct zone_rctltab rctltab; 2046*7c478bd9Sstevel@tonic-gate zone_state_t state_num; 2047*7c478bd9Sstevel@tonic-gate 2048*7c478bd9Sstevel@tonic-gate if ((type = cmd->cmd_res_type) == RT_UNKNOWN) { 2049*7c478bd9Sstevel@tonic-gate long_usage(CMD_REMOVE, TRUE); 2050*7c478bd9Sstevel@tonic-gate return; 2051*7c478bd9Sstevel@tonic-gate } 2052*7c478bd9Sstevel@tonic-gate 2053*7c478bd9Sstevel@tonic-gate if (initialize(TRUE) != Z_OK) 2054*7c478bd9Sstevel@tonic-gate return; 2055*7c478bd9Sstevel@tonic-gate 2056*7c478bd9Sstevel@tonic-gate switch (type) { 2057*7c478bd9Sstevel@tonic-gate case RT_FS: 2058*7c478bd9Sstevel@tonic-gate if ((err = fill_in_fstab(cmd, &fstab, FALSE)) != Z_OK) { 2059*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, TRUE); 2060*7c478bd9Sstevel@tonic-gate return; 2061*7c478bd9Sstevel@tonic-gate } 2062*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK) 2063*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, TRUE); 2064*7c478bd9Sstevel@tonic-gate else 2065*7c478bd9Sstevel@tonic-gate need_to_commit = TRUE; 2066*7c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(fstab.zone_fs_options); 2067*7c478bd9Sstevel@tonic-gate return; 2068*7c478bd9Sstevel@tonic-gate case RT_IPD: 2069*7c478bd9Sstevel@tonic-gate if (zone_get_state(zone, &state_num) == Z_OK && 2070*7c478bd9Sstevel@tonic-gate state_num >= ZONE_STATE_INSTALLED) { 2071*7c478bd9Sstevel@tonic-gate zerr(gettext("Zone %s already installed; %s %s not " 2072*7c478bd9Sstevel@tonic-gate "allowed."), zone, cmd_to_str(CMD_REMOVE), 2073*7c478bd9Sstevel@tonic-gate rt_to_str(RT_IPD)); 2074*7c478bd9Sstevel@tonic-gate return; 2075*7c478bd9Sstevel@tonic-gate } 2076*7c478bd9Sstevel@tonic-gate if ((err = fill_in_ipdtab(cmd, &fstab, FALSE)) != Z_OK) { 2077*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, TRUE); 2078*7c478bd9Sstevel@tonic-gate return; 2079*7c478bd9Sstevel@tonic-gate } 2080*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_ipd(handle, &fstab)) != Z_OK) 2081*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, TRUE); 2082*7c478bd9Sstevel@tonic-gate else 2083*7c478bd9Sstevel@tonic-gate need_to_commit = TRUE; 2084*7c478bd9Sstevel@tonic-gate return; 2085*7c478bd9Sstevel@tonic-gate case RT_NET: 2086*7c478bd9Sstevel@tonic-gate if ((err = fill_in_nwiftab(cmd, &nwiftab, FALSE)) != Z_OK) { 2087*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, TRUE); 2088*7c478bd9Sstevel@tonic-gate return; 2089*7c478bd9Sstevel@tonic-gate } 2090*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK) 2091*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, TRUE); 2092*7c478bd9Sstevel@tonic-gate else 2093*7c478bd9Sstevel@tonic-gate need_to_commit = TRUE; 2094*7c478bd9Sstevel@tonic-gate return; 2095*7c478bd9Sstevel@tonic-gate case RT_DEVICE: 2096*7c478bd9Sstevel@tonic-gate if ((err = fill_in_devtab(cmd, &devtab, FALSE)) != Z_OK) { 2097*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, TRUE); 2098*7c478bd9Sstevel@tonic-gate return; 2099*7c478bd9Sstevel@tonic-gate } 2100*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK) 2101*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, TRUE); 2102*7c478bd9Sstevel@tonic-gate else 2103*7c478bd9Sstevel@tonic-gate need_to_commit = TRUE; 2104*7c478bd9Sstevel@tonic-gate return; 2105*7c478bd9Sstevel@tonic-gate case RT_RCTL: 2106*7c478bd9Sstevel@tonic-gate if ((err = fill_in_rctltab(cmd, &rctltab, FALSE)) != Z_OK) { 2107*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, TRUE); 2108*7c478bd9Sstevel@tonic-gate return; 2109*7c478bd9Sstevel@tonic-gate } 2110*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK) 2111*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, TRUE); 2112*7c478bd9Sstevel@tonic-gate else 2113*7c478bd9Sstevel@tonic-gate need_to_commit = TRUE; 2114*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 2115*7c478bd9Sstevel@tonic-gate return; 2116*7c478bd9Sstevel@tonic-gate case RT_ATTR: 2117*7c478bd9Sstevel@tonic-gate if ((err = fill_in_attrtab(cmd, &attrtab, FALSE)) != Z_OK) { 2118*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, TRUE); 2119*7c478bd9Sstevel@tonic-gate return; 2120*7c478bd9Sstevel@tonic-gate } 2121*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK) 2122*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, TRUE); 2123*7c478bd9Sstevel@tonic-gate else 2124*7c478bd9Sstevel@tonic-gate need_to_commit = TRUE; 2125*7c478bd9Sstevel@tonic-gate return; 2126*7c478bd9Sstevel@tonic-gate default: 2127*7c478bd9Sstevel@tonic-gate zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, TRUE); 2128*7c478bd9Sstevel@tonic-gate long_usage(CMD_REMOVE, TRUE); 2129*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_RESOURCES); 2130*7c478bd9Sstevel@tonic-gate return; 2131*7c478bd9Sstevel@tonic-gate } 2132*7c478bd9Sstevel@tonic-gate } 2133*7c478bd9Sstevel@tonic-gate 2134*7c478bd9Sstevel@tonic-gate static void 2135*7c478bd9Sstevel@tonic-gate remove_property(cmd_t *cmd) 2136*7c478bd9Sstevel@tonic-gate { 2137*7c478bd9Sstevel@tonic-gate char *prop_id; 2138*7c478bd9Sstevel@tonic-gate int err, res_type, prop_type; 2139*7c478bd9Sstevel@tonic-gate property_value_ptr_t pp; 2140*7c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *rctlvaltab; 2141*7c478bd9Sstevel@tonic-gate complex_property_ptr_t cx; 2142*7c478bd9Sstevel@tonic-gate 2143*7c478bd9Sstevel@tonic-gate res_type = resource_scope; 2144*7c478bd9Sstevel@tonic-gate prop_type = cmd->cmd_prop_name[0]; 2145*7c478bd9Sstevel@tonic-gate if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) { 2146*7c478bd9Sstevel@tonic-gate long_usage(CMD_REMOVE, TRUE); 2147*7c478bd9Sstevel@tonic-gate return; 2148*7c478bd9Sstevel@tonic-gate } 2149*7c478bd9Sstevel@tonic-gate 2150*7c478bd9Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs != 1) { 2151*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 2152*7c478bd9Sstevel@tonic-gate return; 2153*7c478bd9Sstevel@tonic-gate } 2154*7c478bd9Sstevel@tonic-gate 2155*7c478bd9Sstevel@tonic-gate if (initialize(TRUE) != Z_OK) 2156*7c478bd9Sstevel@tonic-gate return; 2157*7c478bd9Sstevel@tonic-gate 2158*7c478bd9Sstevel@tonic-gate switch (res_type) { 2159*7c478bd9Sstevel@tonic-gate case RT_FS: 2160*7c478bd9Sstevel@tonic-gate if (prop_type != PT_OPTIONS) { 2161*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 2162*7c478bd9Sstevel@tonic-gate TRUE); 2163*7c478bd9Sstevel@tonic-gate long_usage(CMD_REMOVE, TRUE); 2164*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 2165*7c478bd9Sstevel@tonic-gate return; 2166*7c478bd9Sstevel@tonic-gate } 2167*7c478bd9Sstevel@tonic-gate pp = cmd->cmd_property_ptr[0]; 2168*7c478bd9Sstevel@tonic-gate if (pp->pv_type == PROP_VAL_COMPLEX) { 2169*7c478bd9Sstevel@tonic-gate zerr(gettext("A %s or %s value was expected here."), 2170*7c478bd9Sstevel@tonic-gate pvt_to_str(PROP_VAL_SIMPLE), 2171*7c478bd9Sstevel@tonic-gate pvt_to_str(PROP_VAL_LIST)); 2172*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2173*7c478bd9Sstevel@tonic-gate return; 2174*7c478bd9Sstevel@tonic-gate } 2175*7c478bd9Sstevel@tonic-gate if (pp->pv_type == PROP_VAL_SIMPLE) { 2176*7c478bd9Sstevel@tonic-gate if (pp->pv_simple == NULL) { 2177*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 2178*7c478bd9Sstevel@tonic-gate return; 2179*7c478bd9Sstevel@tonic-gate } 2180*7c478bd9Sstevel@tonic-gate prop_id = pp->pv_simple; 2181*7c478bd9Sstevel@tonic-gate err = zonecfg_remove_fs_option(&in_progress_fstab, 2182*7c478bd9Sstevel@tonic-gate prop_id); 2183*7c478bd9Sstevel@tonic-gate if (err != Z_OK) 2184*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), err, TRUE); 2185*7c478bd9Sstevel@tonic-gate } else { 2186*7c478bd9Sstevel@tonic-gate list_property_ptr_t list; 2187*7c478bd9Sstevel@tonic-gate 2188*7c478bd9Sstevel@tonic-gate for (list = pp->pv_list; list != NULL; 2189*7c478bd9Sstevel@tonic-gate list = list->lp_next) { 2190*7c478bd9Sstevel@tonic-gate prop_id = list->lp_simple; 2191*7c478bd9Sstevel@tonic-gate if (prop_id == NULL) 2192*7c478bd9Sstevel@tonic-gate break; 2193*7c478bd9Sstevel@tonic-gate err = zonecfg_remove_fs_option( 2194*7c478bd9Sstevel@tonic-gate &in_progress_fstab, prop_id); 2195*7c478bd9Sstevel@tonic-gate if (err != Z_OK) 2196*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), err, 2197*7c478bd9Sstevel@tonic-gate TRUE); 2198*7c478bd9Sstevel@tonic-gate } 2199*7c478bd9Sstevel@tonic-gate } 2200*7c478bd9Sstevel@tonic-gate return; 2201*7c478bd9Sstevel@tonic-gate case RT_RCTL: 2202*7c478bd9Sstevel@tonic-gate if (prop_type != PT_VALUE) { 2203*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 2204*7c478bd9Sstevel@tonic-gate TRUE); 2205*7c478bd9Sstevel@tonic-gate long_usage(CMD_REMOVE, TRUE); 2206*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 2207*7c478bd9Sstevel@tonic-gate return; 2208*7c478bd9Sstevel@tonic-gate } 2209*7c478bd9Sstevel@tonic-gate pp = cmd->cmd_property_ptr[0]; 2210*7c478bd9Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_COMPLEX) { 2211*7c478bd9Sstevel@tonic-gate zerr(gettext("A %s value was expected here."), 2212*7c478bd9Sstevel@tonic-gate pvt_to_str(PROP_VAL_COMPLEX)); 2213*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2214*7c478bd9Sstevel@tonic-gate return; 2215*7c478bd9Sstevel@tonic-gate } 2216*7c478bd9Sstevel@tonic-gate if ((rctlvaltab = alloc_rctlvaltab()) == NULL) { 2217*7c478bd9Sstevel@tonic-gate zone_perror(zone, Z_NOMEM, TRUE); 2218*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 2219*7c478bd9Sstevel@tonic-gate } 2220*7c478bd9Sstevel@tonic-gate for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) { 2221*7c478bd9Sstevel@tonic-gate switch (cx->cp_type) { 2222*7c478bd9Sstevel@tonic-gate case PT_PRIV: 2223*7c478bd9Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_priv, 2224*7c478bd9Sstevel@tonic-gate cx->cp_value, 2225*7c478bd9Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_priv)); 2226*7c478bd9Sstevel@tonic-gate break; 2227*7c478bd9Sstevel@tonic-gate case PT_LIMIT: 2228*7c478bd9Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_limit, 2229*7c478bd9Sstevel@tonic-gate cx->cp_value, 2230*7c478bd9Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_limit)); 2231*7c478bd9Sstevel@tonic-gate break; 2232*7c478bd9Sstevel@tonic-gate case PT_ACTION: 2233*7c478bd9Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_action, 2234*7c478bd9Sstevel@tonic-gate cx->cp_value, 2235*7c478bd9Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_action)); 2236*7c478bd9Sstevel@tonic-gate break; 2237*7c478bd9Sstevel@tonic-gate default: 2238*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), 2239*7c478bd9Sstevel@tonic-gate Z_NO_PROPERTY_TYPE, TRUE); 2240*7c478bd9Sstevel@tonic-gate long_usage(CMD_ADD, TRUE); 2241*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 2242*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctlvaltab); 2243*7c478bd9Sstevel@tonic-gate return; 2244*7c478bd9Sstevel@tonic-gate } 2245*7c478bd9Sstevel@tonic-gate } 2246*7c478bd9Sstevel@tonic-gate rctlvaltab->zone_rctlval_next = NULL; 2247*7c478bd9Sstevel@tonic-gate err = zonecfg_remove_rctl_value(&in_progress_rctltab, 2248*7c478bd9Sstevel@tonic-gate rctlvaltab); 2249*7c478bd9Sstevel@tonic-gate if (err != Z_OK) 2250*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), err, TRUE); 2251*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctlvaltab); 2252*7c478bd9Sstevel@tonic-gate return; 2253*7c478bd9Sstevel@tonic-gate default: 2254*7c478bd9Sstevel@tonic-gate zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, TRUE); 2255*7c478bd9Sstevel@tonic-gate long_usage(CMD_REMOVE, TRUE); 2256*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_RESOURCES); 2257*7c478bd9Sstevel@tonic-gate return; 2258*7c478bd9Sstevel@tonic-gate } 2259*7c478bd9Sstevel@tonic-gate } 2260*7c478bd9Sstevel@tonic-gate 2261*7c478bd9Sstevel@tonic-gate void 2262*7c478bd9Sstevel@tonic-gate remove_func(cmd_t *cmd) 2263*7c478bd9Sstevel@tonic-gate { 2264*7c478bd9Sstevel@tonic-gate if (zone_is_read_only(CMD_REMOVE)) 2265*7c478bd9Sstevel@tonic-gate return; 2266*7c478bd9Sstevel@tonic-gate 2267*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 2268*7c478bd9Sstevel@tonic-gate 2269*7c478bd9Sstevel@tonic-gate if (global_scope) 2270*7c478bd9Sstevel@tonic-gate remove_resource(cmd); 2271*7c478bd9Sstevel@tonic-gate else 2272*7c478bd9Sstevel@tonic-gate remove_property(cmd); 2273*7c478bd9Sstevel@tonic-gate } 2274*7c478bd9Sstevel@tonic-gate 2275*7c478bd9Sstevel@tonic-gate void 2276*7c478bd9Sstevel@tonic-gate select_func(cmd_t *cmd) 2277*7c478bd9Sstevel@tonic-gate { 2278*7c478bd9Sstevel@tonic-gate int type, err; 2279*7c478bd9Sstevel@tonic-gate zone_state_t state_num; 2280*7c478bd9Sstevel@tonic-gate 2281*7c478bd9Sstevel@tonic-gate if (zone_is_read_only(CMD_SELECT)) 2282*7c478bd9Sstevel@tonic-gate return; 2283*7c478bd9Sstevel@tonic-gate 2284*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 2285*7c478bd9Sstevel@tonic-gate 2286*7c478bd9Sstevel@tonic-gate if (global_scope) { 2287*7c478bd9Sstevel@tonic-gate global_scope = FALSE; 2288*7c478bd9Sstevel@tonic-gate resource_scope = cmd->cmd_res_type; 2289*7c478bd9Sstevel@tonic-gate end_op = CMD_SELECT; 2290*7c478bd9Sstevel@tonic-gate } else { 2291*7c478bd9Sstevel@tonic-gate scope_usage(CMD_SELECT); 2292*7c478bd9Sstevel@tonic-gate return; 2293*7c478bd9Sstevel@tonic-gate } 2294*7c478bd9Sstevel@tonic-gate 2295*7c478bd9Sstevel@tonic-gate if ((type = cmd->cmd_res_type) == RT_UNKNOWN) { 2296*7c478bd9Sstevel@tonic-gate long_usage(CMD_SELECT, TRUE); 2297*7c478bd9Sstevel@tonic-gate return; 2298*7c478bd9Sstevel@tonic-gate } 2299*7c478bd9Sstevel@tonic-gate 2300*7c478bd9Sstevel@tonic-gate if (initialize(TRUE) != Z_OK) 2301*7c478bd9Sstevel@tonic-gate return; 2302*7c478bd9Sstevel@tonic-gate 2303*7c478bd9Sstevel@tonic-gate switch (type) { 2304*7c478bd9Sstevel@tonic-gate case RT_FS: 2305*7c478bd9Sstevel@tonic-gate if ((err = fill_in_fstab(cmd, &old_fstab, FALSE)) != Z_OK) { 2306*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_SELECT, RT_FS, err, TRUE); 2307*7c478bd9Sstevel@tonic-gate global_scope = TRUE; 2308*7c478bd9Sstevel@tonic-gate } 2309*7c478bd9Sstevel@tonic-gate bcopy(&old_fstab, &in_progress_fstab, 2310*7c478bd9Sstevel@tonic-gate sizeof (struct zone_fstab)); 2311*7c478bd9Sstevel@tonic-gate return; 2312*7c478bd9Sstevel@tonic-gate case RT_IPD: 2313*7c478bd9Sstevel@tonic-gate if (zone_get_state(zone, &state_num) == Z_OK && 2314*7c478bd9Sstevel@tonic-gate state_num >= ZONE_STATE_INCOMPLETE) { 2315*7c478bd9Sstevel@tonic-gate zerr(gettext("Zone %s not in %s state; %s %s not " 2316*7c478bd9Sstevel@tonic-gate "allowed."), zone, 2317*7c478bd9Sstevel@tonic-gate zone_state_str(ZONE_STATE_CONFIGURED), 2318*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_SELECT), rt_to_str(RT_IPD)); 2319*7c478bd9Sstevel@tonic-gate global_scope = TRUE; 2320*7c478bd9Sstevel@tonic-gate end_op = -1; 2321*7c478bd9Sstevel@tonic-gate return; 2322*7c478bd9Sstevel@tonic-gate } 2323*7c478bd9Sstevel@tonic-gate if ((err = fill_in_ipdtab(cmd, &old_ipdtab, FALSE)) != Z_OK) { 2324*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_SELECT, RT_IPD, err, TRUE); 2325*7c478bd9Sstevel@tonic-gate global_scope = TRUE; 2326*7c478bd9Sstevel@tonic-gate } 2327*7c478bd9Sstevel@tonic-gate bcopy(&old_ipdtab, &in_progress_ipdtab, 2328*7c478bd9Sstevel@tonic-gate sizeof (struct zone_fstab)); 2329*7c478bd9Sstevel@tonic-gate return; 2330*7c478bd9Sstevel@tonic-gate case RT_NET: 2331*7c478bd9Sstevel@tonic-gate if ((err = fill_in_nwiftab(cmd, &old_nwiftab, FALSE)) != Z_OK) { 2332*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_SELECT, RT_NET, err, TRUE); 2333*7c478bd9Sstevel@tonic-gate global_scope = TRUE; 2334*7c478bd9Sstevel@tonic-gate } 2335*7c478bd9Sstevel@tonic-gate bcopy(&old_nwiftab, &in_progress_nwiftab, 2336*7c478bd9Sstevel@tonic-gate sizeof (struct zone_nwiftab)); 2337*7c478bd9Sstevel@tonic-gate return; 2338*7c478bd9Sstevel@tonic-gate case RT_DEVICE: 2339*7c478bd9Sstevel@tonic-gate if ((err = fill_in_devtab(cmd, &old_devtab, FALSE)) != Z_OK) { 2340*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_SELECT, RT_DEVICE, err, TRUE); 2341*7c478bd9Sstevel@tonic-gate global_scope = TRUE; 2342*7c478bd9Sstevel@tonic-gate } 2343*7c478bd9Sstevel@tonic-gate bcopy(&old_devtab, &in_progress_devtab, 2344*7c478bd9Sstevel@tonic-gate sizeof (struct zone_devtab)); 2345*7c478bd9Sstevel@tonic-gate return; 2346*7c478bd9Sstevel@tonic-gate case RT_RCTL: 2347*7c478bd9Sstevel@tonic-gate if ((err = fill_in_rctltab(cmd, &old_rctltab, FALSE)) != Z_OK) { 2348*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_SELECT, RT_RCTL, err, TRUE); 2349*7c478bd9Sstevel@tonic-gate global_scope = TRUE; 2350*7c478bd9Sstevel@tonic-gate } 2351*7c478bd9Sstevel@tonic-gate bcopy(&old_rctltab, &in_progress_rctltab, 2352*7c478bd9Sstevel@tonic-gate sizeof (struct zone_rctltab)); 2353*7c478bd9Sstevel@tonic-gate return; 2354*7c478bd9Sstevel@tonic-gate case RT_ATTR: 2355*7c478bd9Sstevel@tonic-gate if ((err = fill_in_attrtab(cmd, &old_attrtab, FALSE)) != Z_OK) { 2356*7c478bd9Sstevel@tonic-gate z_cmd_rt_perror(CMD_SELECT, RT_ATTR, err, TRUE); 2357*7c478bd9Sstevel@tonic-gate global_scope = TRUE; 2358*7c478bd9Sstevel@tonic-gate } 2359*7c478bd9Sstevel@tonic-gate bcopy(&old_attrtab, &in_progress_attrtab, 2360*7c478bd9Sstevel@tonic-gate sizeof (struct zone_attrtab)); 2361*7c478bd9Sstevel@tonic-gate return; 2362*7c478bd9Sstevel@tonic-gate default: 2363*7c478bd9Sstevel@tonic-gate zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, TRUE); 2364*7c478bd9Sstevel@tonic-gate long_usage(CMD_SELECT, TRUE); 2365*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_RESOURCES); 2366*7c478bd9Sstevel@tonic-gate return; 2367*7c478bd9Sstevel@tonic-gate } 2368*7c478bd9Sstevel@tonic-gate } 2369*7c478bd9Sstevel@tonic-gate 2370*7c478bd9Sstevel@tonic-gate /* 2371*7c478bd9Sstevel@tonic-gate * Network "addresses" can be one of the following forms: 2372*7c478bd9Sstevel@tonic-gate * <IPv4 address> 2373*7c478bd9Sstevel@tonic-gate * <IPv4 address>/<prefix length> 2374*7c478bd9Sstevel@tonic-gate * <IPv6 address>/<prefix length> 2375*7c478bd9Sstevel@tonic-gate * <host name> 2376*7c478bd9Sstevel@tonic-gate * <host name>/<prefix length> 2377*7c478bd9Sstevel@tonic-gate * In other words, the "/" followed by a prefix length is allowed but not 2378*7c478bd9Sstevel@tonic-gate * required for IPv4 addresses and host names, and required for IPv6 addresses. 2379*7c478bd9Sstevel@tonic-gate * If a prefix length is given, it must be in the allowable range: 0 to 32 for 2380*7c478bd9Sstevel@tonic-gate * IPv4 addresses and host names, 0 to 128 for IPv6 addresses. 2381*7c478bd9Sstevel@tonic-gate * Host names must start with an alpha-numeric character, and all subsequent 2382*7c478bd9Sstevel@tonic-gate * characters must be either alpha-numeric or "-". 2383*7c478bd9Sstevel@tonic-gate */ 2384*7c478bd9Sstevel@tonic-gate 2385*7c478bd9Sstevel@tonic-gate static int 2386*7c478bd9Sstevel@tonic-gate validate_net_address_syntax(char *address) 2387*7c478bd9Sstevel@tonic-gate { 2388*7c478bd9Sstevel@tonic-gate char *slashp, part1[MAXHOSTNAMELEN]; 2389*7c478bd9Sstevel@tonic-gate struct in6_addr in6; 2390*7c478bd9Sstevel@tonic-gate struct in_addr in4; 2391*7c478bd9Sstevel@tonic-gate int prefixlen, i; 2392*7c478bd9Sstevel@tonic-gate 2393*7c478bd9Sstevel@tonic-gate /* 2394*7c478bd9Sstevel@tonic-gate * Copy the part before any '/' into part1 or copy the whole 2395*7c478bd9Sstevel@tonic-gate * thing if there is no '/'. 2396*7c478bd9Sstevel@tonic-gate */ 2397*7c478bd9Sstevel@tonic-gate if ((slashp = strchr(address, '/')) != NULL) { 2398*7c478bd9Sstevel@tonic-gate *slashp = '\0'; 2399*7c478bd9Sstevel@tonic-gate (void) strlcpy(part1, address, sizeof (part1)); 2400*7c478bd9Sstevel@tonic-gate *slashp = '/'; 2401*7c478bd9Sstevel@tonic-gate prefixlen = atoi(++slashp); 2402*7c478bd9Sstevel@tonic-gate } else { 2403*7c478bd9Sstevel@tonic-gate (void) strlcpy(part1, address, sizeof (part1)); 2404*7c478bd9Sstevel@tonic-gate } 2405*7c478bd9Sstevel@tonic-gate 2406*7c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET6, part1, &in6) == 1) { 2407*7c478bd9Sstevel@tonic-gate if (slashp == NULL) { 2408*7c478bd9Sstevel@tonic-gate zerr(gettext("%s: IPv6 addresses " 2409*7c478bd9Sstevel@tonic-gate "require /prefix-length suffix."), address); 2410*7c478bd9Sstevel@tonic-gate return (Z_ERR); 2411*7c478bd9Sstevel@tonic-gate } 2412*7c478bd9Sstevel@tonic-gate if (prefixlen < 0 || prefixlen > 128) { 2413*7c478bd9Sstevel@tonic-gate zerr(gettext("%s: IPv6 address " 2414*7c478bd9Sstevel@tonic-gate "prefix lengths must be 0 - 128."), address); 2415*7c478bd9Sstevel@tonic-gate return (Z_ERR); 2416*7c478bd9Sstevel@tonic-gate } 2417*7c478bd9Sstevel@tonic-gate return (Z_OK); 2418*7c478bd9Sstevel@tonic-gate } 2419*7c478bd9Sstevel@tonic-gate 2420*7c478bd9Sstevel@tonic-gate /* At this point, any /prefix must be for IPv4. */ 2421*7c478bd9Sstevel@tonic-gate if (slashp != NULL) { 2422*7c478bd9Sstevel@tonic-gate if (prefixlen < 0 || prefixlen > 32) { 2423*7c478bd9Sstevel@tonic-gate zerr(gettext("%s: IPv4 address " 2424*7c478bd9Sstevel@tonic-gate "prefix lengths must be 0 - 32."), address); 2425*7c478bd9Sstevel@tonic-gate return (Z_ERR); 2426*7c478bd9Sstevel@tonic-gate } 2427*7c478bd9Sstevel@tonic-gate } 2428*7c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET, part1, &in4) == 1) 2429*7c478bd9Sstevel@tonic-gate return (Z_OK); 2430*7c478bd9Sstevel@tonic-gate 2431*7c478bd9Sstevel@tonic-gate /* address may also be a host name */ 2432*7c478bd9Sstevel@tonic-gate if (!isalnum(part1[0])) { 2433*7c478bd9Sstevel@tonic-gate zerr(gettext("%s: bogus host name or network address syntax"), 2434*7c478bd9Sstevel@tonic-gate part1); 2435*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2436*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_NETADDR); 2437*7c478bd9Sstevel@tonic-gate return (Z_ERR); 2438*7c478bd9Sstevel@tonic-gate } 2439*7c478bd9Sstevel@tonic-gate for (i = 1; part1[i]; i++) 2440*7c478bd9Sstevel@tonic-gate if (!isalnum(part1[i]) && part1[i] != '-' && part1[i] != '.') { 2441*7c478bd9Sstevel@tonic-gate zerr(gettext("%s: bogus host name or " 2442*7c478bd9Sstevel@tonic-gate "network address syntax"), part1); 2443*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2444*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_NETADDR); 2445*7c478bd9Sstevel@tonic-gate return (Z_ERR); 2446*7c478bd9Sstevel@tonic-gate } 2447*7c478bd9Sstevel@tonic-gate return (Z_OK); 2448*7c478bd9Sstevel@tonic-gate } 2449*7c478bd9Sstevel@tonic-gate 2450*7c478bd9Sstevel@tonic-gate static int 2451*7c478bd9Sstevel@tonic-gate validate_net_physical_syntax(char *ifname) 2452*7c478bd9Sstevel@tonic-gate { 2453*7c478bd9Sstevel@tonic-gate if (strchr(ifname, ':') == NULL) 2454*7c478bd9Sstevel@tonic-gate return (Z_OK); 2455*7c478bd9Sstevel@tonic-gate zerr(gettext("%s: physical interface name required; " 2456*7c478bd9Sstevel@tonic-gate "logical interface name not allowed"), ifname); 2457*7c478bd9Sstevel@tonic-gate return (Z_ERR); 2458*7c478bd9Sstevel@tonic-gate } 2459*7c478bd9Sstevel@tonic-gate 2460*7c478bd9Sstevel@tonic-gate static boolean_t 2461*7c478bd9Sstevel@tonic-gate valid_fs_type(const char *type) 2462*7c478bd9Sstevel@tonic-gate { 2463*7c478bd9Sstevel@tonic-gate /* 2464*7c478bd9Sstevel@tonic-gate * Is this a valid path component? 2465*7c478bd9Sstevel@tonic-gate */ 2466*7c478bd9Sstevel@tonic-gate if (strlen(type) + 1 > MAXNAMELEN) 2467*7c478bd9Sstevel@tonic-gate return (B_FALSE); 2468*7c478bd9Sstevel@tonic-gate /* 2469*7c478bd9Sstevel@tonic-gate * Make sure a bad value for "type" doesn't make 2470*7c478bd9Sstevel@tonic-gate * /usr/lib/fs/<type>/mount turn into something else. 2471*7c478bd9Sstevel@tonic-gate */ 2472*7c478bd9Sstevel@tonic-gate if (strchr(type, '/') != NULL || type[0] == '\0' || 2473*7c478bd9Sstevel@tonic-gate strcmp(type, ".") == 0 || strcmp(type, "..") == 0) 2474*7c478bd9Sstevel@tonic-gate return (B_FALSE); 2475*7c478bd9Sstevel@tonic-gate /* 2476*7c478bd9Sstevel@tonic-gate * More detailed verification happens later by zoneadm(1m). 2477*7c478bd9Sstevel@tonic-gate */ 2478*7c478bd9Sstevel@tonic-gate return (B_TRUE); 2479*7c478bd9Sstevel@tonic-gate } 2480*7c478bd9Sstevel@tonic-gate 2481*7c478bd9Sstevel@tonic-gate void 2482*7c478bd9Sstevel@tonic-gate set_func(cmd_t *cmd) 2483*7c478bd9Sstevel@tonic-gate { 2484*7c478bd9Sstevel@tonic-gate char *prop_id; 2485*7c478bd9Sstevel@tonic-gate int err, res_type, prop_type; 2486*7c478bd9Sstevel@tonic-gate property_value_ptr_t pp; 2487*7c478bd9Sstevel@tonic-gate zone_state_t state_num; 2488*7c478bd9Sstevel@tonic-gate boolean_t autoboot; 2489*7c478bd9Sstevel@tonic-gate 2490*7c478bd9Sstevel@tonic-gate if (zone_is_read_only(CMD_SET)) 2491*7c478bd9Sstevel@tonic-gate return; 2492*7c478bd9Sstevel@tonic-gate 2493*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 2494*7c478bd9Sstevel@tonic-gate 2495*7c478bd9Sstevel@tonic-gate prop_type = cmd->cmd_prop_name[0]; 2496*7c478bd9Sstevel@tonic-gate if (global_scope) { 2497*7c478bd9Sstevel@tonic-gate if (prop_type == PT_ZONEPATH) { 2498*7c478bd9Sstevel@tonic-gate res_type = RT_ZONEPATH; 2499*7c478bd9Sstevel@tonic-gate } else if (prop_type == PT_AUTOBOOT) { 2500*7c478bd9Sstevel@tonic-gate res_type = RT_AUTOBOOT; 2501*7c478bd9Sstevel@tonic-gate } else if (prop_type == PT_POOL) { 2502*7c478bd9Sstevel@tonic-gate res_type = RT_POOL; 2503*7c478bd9Sstevel@tonic-gate } else { 2504*7c478bd9Sstevel@tonic-gate zerr(gettext("Cannot set a resource-specific property " 2505*7c478bd9Sstevel@tonic-gate "from the global scope.")); 2506*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2507*7c478bd9Sstevel@tonic-gate return; 2508*7c478bd9Sstevel@tonic-gate } 2509*7c478bd9Sstevel@tonic-gate } else { 2510*7c478bd9Sstevel@tonic-gate res_type = resource_scope; 2511*7c478bd9Sstevel@tonic-gate } 2512*7c478bd9Sstevel@tonic-gate 2513*7c478bd9Sstevel@tonic-gate pp = cmd->cmd_property_ptr[0]; 2514*7c478bd9Sstevel@tonic-gate /* 2515*7c478bd9Sstevel@tonic-gate * A nasty expression but not that complicated: 2516*7c478bd9Sstevel@tonic-gate * 1. fs options are simple or list (tested below) 2517*7c478bd9Sstevel@tonic-gate * 2. rctl value's are complex or list (tested below) 2518*7c478bd9Sstevel@tonic-gate * Anything else should be simple. 2519*7c478bd9Sstevel@tonic-gate */ 2520*7c478bd9Sstevel@tonic-gate if (!(res_type == RT_FS && prop_type == PT_OPTIONS) && 2521*7c478bd9Sstevel@tonic-gate !(res_type == RT_RCTL && prop_type == PT_VALUE) && 2522*7c478bd9Sstevel@tonic-gate (pp->pv_type != PROP_VAL_SIMPLE || 2523*7c478bd9Sstevel@tonic-gate (prop_id = pp->pv_simple) == NULL)) { 2524*7c478bd9Sstevel@tonic-gate zerr(gettext("A %s value was expected here."), 2525*7c478bd9Sstevel@tonic-gate pvt_to_str(PROP_VAL_SIMPLE)); 2526*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2527*7c478bd9Sstevel@tonic-gate return; 2528*7c478bd9Sstevel@tonic-gate } 2529*7c478bd9Sstevel@tonic-gate if (prop_type == PT_UNKNOWN) { 2530*7c478bd9Sstevel@tonic-gate long_usage(CMD_SET, TRUE); 2531*7c478bd9Sstevel@tonic-gate return; 2532*7c478bd9Sstevel@tonic-gate } 2533*7c478bd9Sstevel@tonic-gate 2534*7c478bd9Sstevel@tonic-gate if (initialize(TRUE) != Z_OK) 2535*7c478bd9Sstevel@tonic-gate return; 2536*7c478bd9Sstevel@tonic-gate 2537*7c478bd9Sstevel@tonic-gate switch (res_type) { 2538*7c478bd9Sstevel@tonic-gate case RT_ZONEPATH: 2539*7c478bd9Sstevel@tonic-gate if (zone_get_state(zone, &state_num) == Z_OK && 2540*7c478bd9Sstevel@tonic-gate state_num >= ZONE_STATE_INSTALLED) { 2541*7c478bd9Sstevel@tonic-gate zerr(gettext("Zone %s already installed; %s %s not " 2542*7c478bd9Sstevel@tonic-gate "allowed."), zone, cmd_to_str(CMD_SET), 2543*7c478bd9Sstevel@tonic-gate rt_to_str(RT_ZONEPATH)); 2544*7c478bd9Sstevel@tonic-gate return; 2545*7c478bd9Sstevel@tonic-gate } 2546*7c478bd9Sstevel@tonic-gate if (validate_zonepath_syntax(prop_id) != Z_OK) { 2547*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2548*7c478bd9Sstevel@tonic-gate return; 2549*7c478bd9Sstevel@tonic-gate } 2550*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_set_zonepath(handle, prop_id)) != Z_OK) 2551*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 2552*7c478bd9Sstevel@tonic-gate else 2553*7c478bd9Sstevel@tonic-gate need_to_commit = TRUE; 2554*7c478bd9Sstevel@tonic-gate return; 2555*7c478bd9Sstevel@tonic-gate case RT_AUTOBOOT: 2556*7c478bd9Sstevel@tonic-gate if (strcmp(prop_id, "true") == 0) { 2557*7c478bd9Sstevel@tonic-gate autoboot = B_TRUE; 2558*7c478bd9Sstevel@tonic-gate } else if (strcmp(prop_id, "false") == 0) { 2559*7c478bd9Sstevel@tonic-gate autoboot = B_FALSE; 2560*7c478bd9Sstevel@tonic-gate } else { 2561*7c478bd9Sstevel@tonic-gate zerr(gettext("%s value must be '%s' or '%s'."), 2562*7c478bd9Sstevel@tonic-gate pt_to_str(PT_AUTOBOOT), "true", "false"); 2563*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2564*7c478bd9Sstevel@tonic-gate return; 2565*7c478bd9Sstevel@tonic-gate } 2566*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_set_autoboot(handle, autoboot)) != Z_OK) 2567*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 2568*7c478bd9Sstevel@tonic-gate else 2569*7c478bd9Sstevel@tonic-gate need_to_commit = TRUE; 2570*7c478bd9Sstevel@tonic-gate return; 2571*7c478bd9Sstevel@tonic-gate case RT_POOL: 2572*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_set_pool(handle, prop_id)) != Z_OK) 2573*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 2574*7c478bd9Sstevel@tonic-gate else 2575*7c478bd9Sstevel@tonic-gate need_to_commit = TRUE; 2576*7c478bd9Sstevel@tonic-gate return; 2577*7c478bd9Sstevel@tonic-gate case RT_FS: 2578*7c478bd9Sstevel@tonic-gate switch (prop_type) { 2579*7c478bd9Sstevel@tonic-gate case PT_DIR: 2580*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_fstab.zone_fs_dir, prop_id, 2581*7c478bd9Sstevel@tonic-gate sizeof (in_progress_fstab.zone_fs_dir)); 2582*7c478bd9Sstevel@tonic-gate return; 2583*7c478bd9Sstevel@tonic-gate case PT_SPECIAL: 2584*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_fstab.zone_fs_special, 2585*7c478bd9Sstevel@tonic-gate prop_id, 2586*7c478bd9Sstevel@tonic-gate sizeof (in_progress_fstab.zone_fs_special)); 2587*7c478bd9Sstevel@tonic-gate return; 2588*7c478bd9Sstevel@tonic-gate case PT_RAW: 2589*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_fstab.zone_fs_raw, 2590*7c478bd9Sstevel@tonic-gate prop_id, sizeof (in_progress_fstab.zone_fs_raw)); 2591*7c478bd9Sstevel@tonic-gate return; 2592*7c478bd9Sstevel@tonic-gate case PT_TYPE: 2593*7c478bd9Sstevel@tonic-gate if (!valid_fs_type(prop_id)) { 2594*7c478bd9Sstevel@tonic-gate zerr(gettext("\"%s\" is not a valid %s."), 2595*7c478bd9Sstevel@tonic-gate prop_id, pt_to_str(PT_TYPE)); 2596*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2597*7c478bd9Sstevel@tonic-gate return; 2598*7c478bd9Sstevel@tonic-gate } 2599*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_fstab.zone_fs_type, prop_id, 2600*7c478bd9Sstevel@tonic-gate sizeof (in_progress_fstab.zone_fs_type)); 2601*7c478bd9Sstevel@tonic-gate return; 2602*7c478bd9Sstevel@tonic-gate case PT_OPTIONS: 2603*7c478bd9Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE && 2604*7c478bd9Sstevel@tonic-gate pp->pv_type != PROP_VAL_LIST) { 2605*7c478bd9Sstevel@tonic-gate zerr(gettext("A %s or %s value was expected " 2606*7c478bd9Sstevel@tonic-gate "here."), pvt_to_str(PROP_VAL_SIMPLE), 2607*7c478bd9Sstevel@tonic-gate pvt_to_str(PROP_VAL_LIST)); 2608*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2609*7c478bd9Sstevel@tonic-gate return; 2610*7c478bd9Sstevel@tonic-gate } 2611*7c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list( 2612*7c478bd9Sstevel@tonic-gate in_progress_fstab.zone_fs_options); 2613*7c478bd9Sstevel@tonic-gate in_progress_fstab.zone_fs_options = NULL; 2614*7c478bd9Sstevel@tonic-gate if (!(pp->pv_type == PROP_VAL_LIST && 2615*7c478bd9Sstevel@tonic-gate pp->pv_list == NULL)) 2616*7c478bd9Sstevel@tonic-gate add_property(cmd); 2617*7c478bd9Sstevel@tonic-gate return; 2618*7c478bd9Sstevel@tonic-gate default: 2619*7c478bd9Sstevel@tonic-gate break; 2620*7c478bd9Sstevel@tonic-gate } 2621*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, TRUE); 2622*7c478bd9Sstevel@tonic-gate long_usage(CMD_SET, TRUE); 2623*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 2624*7c478bd9Sstevel@tonic-gate return; 2625*7c478bd9Sstevel@tonic-gate case RT_IPD: 2626*7c478bd9Sstevel@tonic-gate switch (prop_type) { 2627*7c478bd9Sstevel@tonic-gate case PT_DIR: 2628*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_ipdtab.zone_fs_dir, prop_id, 2629*7c478bd9Sstevel@tonic-gate sizeof (in_progress_ipdtab.zone_fs_dir)); 2630*7c478bd9Sstevel@tonic-gate return; 2631*7c478bd9Sstevel@tonic-gate default: 2632*7c478bd9Sstevel@tonic-gate break; 2633*7c478bd9Sstevel@tonic-gate } 2634*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, TRUE); 2635*7c478bd9Sstevel@tonic-gate long_usage(CMD_SET, TRUE); 2636*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 2637*7c478bd9Sstevel@tonic-gate return; 2638*7c478bd9Sstevel@tonic-gate case RT_NET: 2639*7c478bd9Sstevel@tonic-gate switch (prop_type) { 2640*7c478bd9Sstevel@tonic-gate case PT_ADDRESS: 2641*7c478bd9Sstevel@tonic-gate if (validate_net_address_syntax(prop_id) != Z_OK) { 2642*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2643*7c478bd9Sstevel@tonic-gate return; 2644*7c478bd9Sstevel@tonic-gate } 2645*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_nwiftab.zone_nwif_address, 2646*7c478bd9Sstevel@tonic-gate prop_id, 2647*7c478bd9Sstevel@tonic-gate sizeof (in_progress_nwiftab.zone_nwif_address)); 2648*7c478bd9Sstevel@tonic-gate break; 2649*7c478bd9Sstevel@tonic-gate case PT_PHYSICAL: 2650*7c478bd9Sstevel@tonic-gate if (validate_net_physical_syntax(prop_id) != Z_OK) { 2651*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2652*7c478bd9Sstevel@tonic-gate return; 2653*7c478bd9Sstevel@tonic-gate } 2654*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_nwiftab.zone_nwif_physical, 2655*7c478bd9Sstevel@tonic-gate prop_id, 2656*7c478bd9Sstevel@tonic-gate sizeof (in_progress_nwiftab.zone_nwif_physical)); 2657*7c478bd9Sstevel@tonic-gate break; 2658*7c478bd9Sstevel@tonic-gate default: 2659*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 2660*7c478bd9Sstevel@tonic-gate TRUE); 2661*7c478bd9Sstevel@tonic-gate long_usage(CMD_SET, TRUE); 2662*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 2663*7c478bd9Sstevel@tonic-gate return; 2664*7c478bd9Sstevel@tonic-gate } 2665*7c478bd9Sstevel@tonic-gate return; 2666*7c478bd9Sstevel@tonic-gate case RT_DEVICE: 2667*7c478bd9Sstevel@tonic-gate switch (prop_type) { 2668*7c478bd9Sstevel@tonic-gate case PT_MATCH: 2669*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_devtab.zone_dev_match, 2670*7c478bd9Sstevel@tonic-gate prop_id, 2671*7c478bd9Sstevel@tonic-gate sizeof (in_progress_devtab.zone_dev_match)); 2672*7c478bd9Sstevel@tonic-gate break; 2673*7c478bd9Sstevel@tonic-gate default: 2674*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 2675*7c478bd9Sstevel@tonic-gate TRUE); 2676*7c478bd9Sstevel@tonic-gate long_usage(CMD_SET, TRUE); 2677*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 2678*7c478bd9Sstevel@tonic-gate return; 2679*7c478bd9Sstevel@tonic-gate } 2680*7c478bd9Sstevel@tonic-gate return; 2681*7c478bd9Sstevel@tonic-gate case RT_RCTL: 2682*7c478bd9Sstevel@tonic-gate switch (prop_type) { 2683*7c478bd9Sstevel@tonic-gate case PT_NAME: 2684*7c478bd9Sstevel@tonic-gate if (!zonecfg_valid_rctlname(prop_id)) { 2685*7c478bd9Sstevel@tonic-gate zerr(gettext("'%s' is not a valid zone %s " 2686*7c478bd9Sstevel@tonic-gate "name."), prop_id, rt_to_str(RT_RCTL)); 2687*7c478bd9Sstevel@tonic-gate return; 2688*7c478bd9Sstevel@tonic-gate } 2689*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_rctltab.zone_rctl_name, 2690*7c478bd9Sstevel@tonic-gate prop_id, 2691*7c478bd9Sstevel@tonic-gate sizeof (in_progress_rctltab.zone_rctl_name)); 2692*7c478bd9Sstevel@tonic-gate break; 2693*7c478bd9Sstevel@tonic-gate case PT_VALUE: 2694*7c478bd9Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_COMPLEX && 2695*7c478bd9Sstevel@tonic-gate pp->pv_type != PROP_VAL_LIST) { 2696*7c478bd9Sstevel@tonic-gate zerr(gettext("A %s or %s value was expected " 2697*7c478bd9Sstevel@tonic-gate "here."), pvt_to_str(PROP_VAL_COMPLEX), 2698*7c478bd9Sstevel@tonic-gate pvt_to_str(PROP_VAL_LIST)); 2699*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 2700*7c478bd9Sstevel@tonic-gate return; 2701*7c478bd9Sstevel@tonic-gate } 2702*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list( 2703*7c478bd9Sstevel@tonic-gate in_progress_rctltab.zone_rctl_valptr); 2704*7c478bd9Sstevel@tonic-gate in_progress_rctltab.zone_rctl_valptr = NULL; 2705*7c478bd9Sstevel@tonic-gate if (!(pp->pv_type == PROP_VAL_LIST && 2706*7c478bd9Sstevel@tonic-gate pp->pv_list == NULL)) 2707*7c478bd9Sstevel@tonic-gate add_property(cmd); 2708*7c478bd9Sstevel@tonic-gate break; 2709*7c478bd9Sstevel@tonic-gate default: 2710*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 2711*7c478bd9Sstevel@tonic-gate TRUE); 2712*7c478bd9Sstevel@tonic-gate long_usage(CMD_SET, TRUE); 2713*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 2714*7c478bd9Sstevel@tonic-gate return; 2715*7c478bd9Sstevel@tonic-gate } 2716*7c478bd9Sstevel@tonic-gate return; 2717*7c478bd9Sstevel@tonic-gate case RT_ATTR: 2718*7c478bd9Sstevel@tonic-gate switch (prop_type) { 2719*7c478bd9Sstevel@tonic-gate case PT_NAME: 2720*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_attrtab.zone_attr_name, 2721*7c478bd9Sstevel@tonic-gate prop_id, 2722*7c478bd9Sstevel@tonic-gate sizeof (in_progress_attrtab.zone_attr_name)); 2723*7c478bd9Sstevel@tonic-gate break; 2724*7c478bd9Sstevel@tonic-gate case PT_TYPE: 2725*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_attrtab.zone_attr_type, 2726*7c478bd9Sstevel@tonic-gate prop_id, 2727*7c478bd9Sstevel@tonic-gate sizeof (in_progress_attrtab.zone_attr_type)); 2728*7c478bd9Sstevel@tonic-gate break; 2729*7c478bd9Sstevel@tonic-gate case PT_VALUE: 2730*7c478bd9Sstevel@tonic-gate (void) strlcpy(in_progress_attrtab.zone_attr_value, 2731*7c478bd9Sstevel@tonic-gate prop_id, 2732*7c478bd9Sstevel@tonic-gate sizeof (in_progress_attrtab.zone_attr_value)); 2733*7c478bd9Sstevel@tonic-gate break; 2734*7c478bd9Sstevel@tonic-gate default: 2735*7c478bd9Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, 2736*7c478bd9Sstevel@tonic-gate TRUE); 2737*7c478bd9Sstevel@tonic-gate long_usage(CMD_SET, TRUE); 2738*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_PROPS); 2739*7c478bd9Sstevel@tonic-gate return; 2740*7c478bd9Sstevel@tonic-gate } 2741*7c478bd9Sstevel@tonic-gate return; 2742*7c478bd9Sstevel@tonic-gate default: 2743*7c478bd9Sstevel@tonic-gate zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, TRUE); 2744*7c478bd9Sstevel@tonic-gate long_usage(CMD_SET, TRUE); 2745*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_RESOURCES); 2746*7c478bd9Sstevel@tonic-gate return; 2747*7c478bd9Sstevel@tonic-gate } 2748*7c478bd9Sstevel@tonic-gate } 2749*7c478bd9Sstevel@tonic-gate 2750*7c478bd9Sstevel@tonic-gate static void 2751*7c478bd9Sstevel@tonic-gate output_prop(FILE *fp, int pnum, char *pval, bool print_notspec) 2752*7c478bd9Sstevel@tonic-gate { 2753*7c478bd9Sstevel@tonic-gate char *qstr; 2754*7c478bd9Sstevel@tonic-gate 2755*7c478bd9Sstevel@tonic-gate if (*pval != '\0') { 2756*7c478bd9Sstevel@tonic-gate qstr = quoteit(pval); 2757*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr); 2758*7c478bd9Sstevel@tonic-gate free(qstr); 2759*7c478bd9Sstevel@tonic-gate } else if (print_notspec) 2760*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s\n", pt_to_str(pnum), 2761*7c478bd9Sstevel@tonic-gate gettext("not specified")); 2762*7c478bd9Sstevel@tonic-gate } 2763*7c478bd9Sstevel@tonic-gate 2764*7c478bd9Sstevel@tonic-gate static void 2765*7c478bd9Sstevel@tonic-gate info_zonepath(zone_dochandle_t handle, FILE *fp) 2766*7c478bd9Sstevel@tonic-gate { 2767*7c478bd9Sstevel@tonic-gate char zonepath[MAXPATHLEN]; 2768*7c478bd9Sstevel@tonic-gate 2769*7c478bd9Sstevel@tonic-gate if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK) 2770*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONEPATH), 2771*7c478bd9Sstevel@tonic-gate zonepath); 2772*7c478bd9Sstevel@tonic-gate else 2773*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s %s\n", pt_to_str(PT_ZONEPATH), 2774*7c478bd9Sstevel@tonic-gate gettext("not specified")); 2775*7c478bd9Sstevel@tonic-gate } 2776*7c478bd9Sstevel@tonic-gate 2777*7c478bd9Sstevel@tonic-gate static void 2778*7c478bd9Sstevel@tonic-gate info_autoboot(zone_dochandle_t handle, FILE *fp) 2779*7c478bd9Sstevel@tonic-gate { 2780*7c478bd9Sstevel@tonic-gate boolean_t autoboot; 2781*7c478bd9Sstevel@tonic-gate int err; 2782*7c478bd9Sstevel@tonic-gate 2783*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_get_autoboot(handle, &autoboot)) == Z_OK) 2784*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_AUTOBOOT), 2785*7c478bd9Sstevel@tonic-gate autoboot ? "true" : "false"); 2786*7c478bd9Sstevel@tonic-gate else 2787*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 2788*7c478bd9Sstevel@tonic-gate } 2789*7c478bd9Sstevel@tonic-gate 2790*7c478bd9Sstevel@tonic-gate static void 2791*7c478bd9Sstevel@tonic-gate info_pool(zone_dochandle_t handle, FILE *fp) 2792*7c478bd9Sstevel@tonic-gate { 2793*7c478bd9Sstevel@tonic-gate char pool[MAXNAMELEN]; 2794*7c478bd9Sstevel@tonic-gate int err; 2795*7c478bd9Sstevel@tonic-gate 2796*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_get_pool(handle, pool, sizeof (pool))) == Z_OK) 2797*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_POOL), pool); 2798*7c478bd9Sstevel@tonic-gate else 2799*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 2800*7c478bd9Sstevel@tonic-gate } 2801*7c478bd9Sstevel@tonic-gate 2802*7c478bd9Sstevel@tonic-gate static void 2803*7c478bd9Sstevel@tonic-gate output_fs(FILE *fp, struct zone_fstab *fstab) 2804*7c478bd9Sstevel@tonic-gate { 2805*7c478bd9Sstevel@tonic-gate zone_fsopt_t *this; 2806*7c478bd9Sstevel@tonic-gate 2807*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s:\n", rt_to_str(RT_FS)); 2808*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_DIR, fstab->zone_fs_dir, B_TRUE); 2809*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_SPECIAL, fstab->zone_fs_special, B_TRUE); 2810*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_RAW, fstab->zone_fs_raw, B_TRUE); 2811*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_TYPE, fstab->zone_fs_type, B_TRUE); 2812*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\t%s: [", pt_to_str(PT_OPTIONS)); 2813*7c478bd9Sstevel@tonic-gate for (this = fstab->zone_fs_options; this != NULL; 2814*7c478bd9Sstevel@tonic-gate this = this->zone_fsopt_next) { 2815*7c478bd9Sstevel@tonic-gate if (strchr(this->zone_fsopt_opt, '=')) 2816*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\"%s\"", this->zone_fsopt_opt); 2817*7c478bd9Sstevel@tonic-gate else 2818*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s", this->zone_fsopt_opt); 2819*7c478bd9Sstevel@tonic-gate if (this->zone_fsopt_next != NULL) 2820*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, ","); 2821*7c478bd9Sstevel@tonic-gate } 2822*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "]\n"); 2823*7c478bd9Sstevel@tonic-gate } 2824*7c478bd9Sstevel@tonic-gate 2825*7c478bd9Sstevel@tonic-gate static void 2826*7c478bd9Sstevel@tonic-gate output_ipd(FILE *fp, struct zone_fstab *ipdtab) 2827*7c478bd9Sstevel@tonic-gate { 2828*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s:\n", rt_to_str(RT_IPD)); 2829*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_DIR, ipdtab->zone_fs_dir, B_TRUE); 2830*7c478bd9Sstevel@tonic-gate } 2831*7c478bd9Sstevel@tonic-gate 2832*7c478bd9Sstevel@tonic-gate static void 2833*7c478bd9Sstevel@tonic-gate info_fs(zone_dochandle_t handle, FILE *fp, cmd_t *cmd) 2834*7c478bd9Sstevel@tonic-gate { 2835*7c478bd9Sstevel@tonic-gate struct zone_fstab lookup, user; 2836*7c478bd9Sstevel@tonic-gate bool output = FALSE; 2837*7c478bd9Sstevel@tonic-gate 2838*7c478bd9Sstevel@tonic-gate if (zonecfg_setfsent(handle) != Z_OK) 2839*7c478bd9Sstevel@tonic-gate return; 2840*7c478bd9Sstevel@tonic-gate while (zonecfg_getfsent(handle, &lookup) == Z_OK) { 2841*7c478bd9Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs == 0) { 2842*7c478bd9Sstevel@tonic-gate output_fs(fp, &lookup); 2843*7c478bd9Sstevel@tonic-gate goto loopend; 2844*7c478bd9Sstevel@tonic-gate } 2845*7c478bd9Sstevel@tonic-gate if (fill_in_fstab(cmd, &user, TRUE) != Z_OK) 2846*7c478bd9Sstevel@tonic-gate goto loopend; 2847*7c478bd9Sstevel@tonic-gate if (strlen(user.zone_fs_dir) > 0 && 2848*7c478bd9Sstevel@tonic-gate strcmp(user.zone_fs_dir, lookup.zone_fs_dir) != 0) 2849*7c478bd9Sstevel@tonic-gate goto loopend; /* no match */ 2850*7c478bd9Sstevel@tonic-gate if (strlen(user.zone_fs_special) > 0 && 2851*7c478bd9Sstevel@tonic-gate strcmp(user.zone_fs_special, lookup.zone_fs_special) != 0) 2852*7c478bd9Sstevel@tonic-gate goto loopend; /* no match */ 2853*7c478bd9Sstevel@tonic-gate if (strlen(user.zone_fs_type) > 0 && 2854*7c478bd9Sstevel@tonic-gate strcmp(user.zone_fs_type, lookup.zone_fs_type) != 0) 2855*7c478bd9Sstevel@tonic-gate goto loopend; /* no match */ 2856*7c478bd9Sstevel@tonic-gate output_fs(fp, &lookup); 2857*7c478bd9Sstevel@tonic-gate output = TRUE; 2858*7c478bd9Sstevel@tonic-gate loopend: 2859*7c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(lookup.zone_fs_options); 2860*7c478bd9Sstevel@tonic-gate } 2861*7c478bd9Sstevel@tonic-gate (void) zonecfg_endfsent(handle); 2862*7c478bd9Sstevel@tonic-gate /* 2863*7c478bd9Sstevel@tonic-gate * If a property n/v pair was specified, warn the user if there was 2864*7c478bd9Sstevel@tonic-gate * nothing to output. 2865*7c478bd9Sstevel@tonic-gate */ 2866*7c478bd9Sstevel@tonic-gate if (!output && cmd->cmd_prop_nv_pairs > 0) 2867*7c478bd9Sstevel@tonic-gate (void) printf(gettext("No such %s resource.\n"), 2868*7c478bd9Sstevel@tonic-gate rt_to_str(RT_FS)); 2869*7c478bd9Sstevel@tonic-gate } 2870*7c478bd9Sstevel@tonic-gate 2871*7c478bd9Sstevel@tonic-gate static void 2872*7c478bd9Sstevel@tonic-gate info_ipd(zone_dochandle_t handle, FILE *fp, cmd_t *cmd) 2873*7c478bd9Sstevel@tonic-gate { 2874*7c478bd9Sstevel@tonic-gate struct zone_fstab lookup, user; 2875*7c478bd9Sstevel@tonic-gate bool output = FALSE; 2876*7c478bd9Sstevel@tonic-gate 2877*7c478bd9Sstevel@tonic-gate if (zonecfg_setipdent(handle) != Z_OK) 2878*7c478bd9Sstevel@tonic-gate return; 2879*7c478bd9Sstevel@tonic-gate while (zonecfg_getipdent(handle, &lookup) == Z_OK) { 2880*7c478bd9Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs == 0) { 2881*7c478bd9Sstevel@tonic-gate output_ipd(fp, &lookup); 2882*7c478bd9Sstevel@tonic-gate continue; 2883*7c478bd9Sstevel@tonic-gate } 2884*7c478bd9Sstevel@tonic-gate if (fill_in_ipdtab(cmd, &user, TRUE) != Z_OK) 2885*7c478bd9Sstevel@tonic-gate continue; 2886*7c478bd9Sstevel@tonic-gate if (strlen(user.zone_fs_dir) > 0 && 2887*7c478bd9Sstevel@tonic-gate strcmp(user.zone_fs_dir, lookup.zone_fs_dir) != 0) 2888*7c478bd9Sstevel@tonic-gate continue; /* no match */ 2889*7c478bd9Sstevel@tonic-gate output_ipd(fp, &lookup); 2890*7c478bd9Sstevel@tonic-gate output = TRUE; 2891*7c478bd9Sstevel@tonic-gate } 2892*7c478bd9Sstevel@tonic-gate (void) zonecfg_endipdent(handle); 2893*7c478bd9Sstevel@tonic-gate /* 2894*7c478bd9Sstevel@tonic-gate * If a property n/v pair was specified, warn the user if there was 2895*7c478bd9Sstevel@tonic-gate * nothing to output. 2896*7c478bd9Sstevel@tonic-gate */ 2897*7c478bd9Sstevel@tonic-gate if (!output && cmd->cmd_prop_nv_pairs > 0) 2898*7c478bd9Sstevel@tonic-gate (void) printf(gettext("No such %s resource.\n"), 2899*7c478bd9Sstevel@tonic-gate rt_to_str(RT_IPD)); 2900*7c478bd9Sstevel@tonic-gate } 2901*7c478bd9Sstevel@tonic-gate 2902*7c478bd9Sstevel@tonic-gate static void 2903*7c478bd9Sstevel@tonic-gate output_net(FILE *fp, struct zone_nwiftab *nwiftab) 2904*7c478bd9Sstevel@tonic-gate { 2905*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s:\n", rt_to_str(RT_NET)); 2906*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_ADDRESS, nwiftab->zone_nwif_address, B_TRUE); 2907*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE); 2908*7c478bd9Sstevel@tonic-gate } 2909*7c478bd9Sstevel@tonic-gate 2910*7c478bd9Sstevel@tonic-gate static void 2911*7c478bd9Sstevel@tonic-gate info_net(zone_dochandle_t handle, FILE *fp, cmd_t *cmd) 2912*7c478bd9Sstevel@tonic-gate { 2913*7c478bd9Sstevel@tonic-gate struct zone_nwiftab lookup, user; 2914*7c478bd9Sstevel@tonic-gate bool output = FALSE; 2915*7c478bd9Sstevel@tonic-gate 2916*7c478bd9Sstevel@tonic-gate if (zonecfg_setnwifent(handle) != Z_OK) 2917*7c478bd9Sstevel@tonic-gate return; 2918*7c478bd9Sstevel@tonic-gate while (zonecfg_getnwifent(handle, &lookup) == Z_OK) { 2919*7c478bd9Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs == 0) { 2920*7c478bd9Sstevel@tonic-gate output_net(fp, &lookup); 2921*7c478bd9Sstevel@tonic-gate continue; 2922*7c478bd9Sstevel@tonic-gate } 2923*7c478bd9Sstevel@tonic-gate if (fill_in_nwiftab(cmd, &user, TRUE) != Z_OK) 2924*7c478bd9Sstevel@tonic-gate continue; 2925*7c478bd9Sstevel@tonic-gate if (strlen(user.zone_nwif_physical) > 0 && 2926*7c478bd9Sstevel@tonic-gate strcmp(user.zone_nwif_physical, 2927*7c478bd9Sstevel@tonic-gate lookup.zone_nwif_physical) != 0) 2928*7c478bd9Sstevel@tonic-gate continue; /* no match */ 2929*7c478bd9Sstevel@tonic-gate if (strlen(user.zone_nwif_address) > 0 && 2930*7c478bd9Sstevel@tonic-gate !zonecfg_same_net_address(user.zone_nwif_address, 2931*7c478bd9Sstevel@tonic-gate lookup.zone_nwif_address)) 2932*7c478bd9Sstevel@tonic-gate continue; /* no match */ 2933*7c478bd9Sstevel@tonic-gate output_net(fp, &lookup); 2934*7c478bd9Sstevel@tonic-gate output = TRUE; 2935*7c478bd9Sstevel@tonic-gate } 2936*7c478bd9Sstevel@tonic-gate (void) zonecfg_endnwifent(handle); 2937*7c478bd9Sstevel@tonic-gate /* 2938*7c478bd9Sstevel@tonic-gate * If a property n/v pair was specified, warn the user if there was 2939*7c478bd9Sstevel@tonic-gate * nothing to output. 2940*7c478bd9Sstevel@tonic-gate */ 2941*7c478bd9Sstevel@tonic-gate if (!output && cmd->cmd_prop_nv_pairs > 0) 2942*7c478bd9Sstevel@tonic-gate (void) printf(gettext("No such %s resource.\n"), 2943*7c478bd9Sstevel@tonic-gate rt_to_str(RT_NET)); 2944*7c478bd9Sstevel@tonic-gate } 2945*7c478bd9Sstevel@tonic-gate 2946*7c478bd9Sstevel@tonic-gate static void 2947*7c478bd9Sstevel@tonic-gate output_dev(FILE *fp, struct zone_devtab *devtab) 2948*7c478bd9Sstevel@tonic-gate { 2949*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", rt_to_str(RT_DEVICE)); 2950*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_MATCH, devtab->zone_dev_match, B_TRUE); 2951*7c478bd9Sstevel@tonic-gate } 2952*7c478bd9Sstevel@tonic-gate 2953*7c478bd9Sstevel@tonic-gate static void 2954*7c478bd9Sstevel@tonic-gate info_dev(zone_dochandle_t handle, FILE *fp, cmd_t *cmd) 2955*7c478bd9Sstevel@tonic-gate { 2956*7c478bd9Sstevel@tonic-gate struct zone_devtab lookup, user; 2957*7c478bd9Sstevel@tonic-gate bool output = FALSE; 2958*7c478bd9Sstevel@tonic-gate 2959*7c478bd9Sstevel@tonic-gate if (zonecfg_setdevent(handle) != Z_OK) 2960*7c478bd9Sstevel@tonic-gate return; 2961*7c478bd9Sstevel@tonic-gate while (zonecfg_getdevent(handle, &lookup) == Z_OK) { 2962*7c478bd9Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs == 0) { 2963*7c478bd9Sstevel@tonic-gate output_dev(fp, &lookup); 2964*7c478bd9Sstevel@tonic-gate continue; 2965*7c478bd9Sstevel@tonic-gate } 2966*7c478bd9Sstevel@tonic-gate if (fill_in_devtab(cmd, &user, TRUE) != Z_OK) 2967*7c478bd9Sstevel@tonic-gate continue; 2968*7c478bd9Sstevel@tonic-gate if (strlen(user.zone_dev_match) > 0 && 2969*7c478bd9Sstevel@tonic-gate strcmp(user.zone_dev_match, lookup.zone_dev_match) != 0) 2970*7c478bd9Sstevel@tonic-gate continue; /* no match */ 2971*7c478bd9Sstevel@tonic-gate output_dev(fp, &lookup); 2972*7c478bd9Sstevel@tonic-gate output = TRUE; 2973*7c478bd9Sstevel@tonic-gate } 2974*7c478bd9Sstevel@tonic-gate (void) zonecfg_enddevent(handle); 2975*7c478bd9Sstevel@tonic-gate /* 2976*7c478bd9Sstevel@tonic-gate * If a property n/v pair was specified, warn the user if there was 2977*7c478bd9Sstevel@tonic-gate * nothing to output. 2978*7c478bd9Sstevel@tonic-gate */ 2979*7c478bd9Sstevel@tonic-gate if (!output && cmd->cmd_prop_nv_pairs > 0) 2980*7c478bd9Sstevel@tonic-gate (void) printf(gettext("No such %s resource.\n"), 2981*7c478bd9Sstevel@tonic-gate rt_to_str(RT_DEVICE)); 2982*7c478bd9Sstevel@tonic-gate } 2983*7c478bd9Sstevel@tonic-gate 2984*7c478bd9Sstevel@tonic-gate static void 2985*7c478bd9Sstevel@tonic-gate output_rctl(FILE *fp, struct zone_rctltab *rctltab) 2986*7c478bd9Sstevel@tonic-gate { 2987*7c478bd9Sstevel@tonic-gate struct zone_rctlvaltab *valptr; 2988*7c478bd9Sstevel@tonic-gate 2989*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s:\n", rt_to_str(RT_RCTL)); 2990*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_NAME, rctltab->zone_rctl_name, B_TRUE); 2991*7c478bd9Sstevel@tonic-gate for (valptr = rctltab->zone_rctl_valptr; valptr != NULL; 2992*7c478bd9Sstevel@tonic-gate valptr = valptr->zone_rctlval_next) { 2993*7c478bd9Sstevel@tonic-gate fprintf(fp, "\t%s: (%s=%s,%s=%s,%s=%s)\n", 2994*7c478bd9Sstevel@tonic-gate pt_to_str(PT_VALUE), 2995*7c478bd9Sstevel@tonic-gate pt_to_str(PT_PRIV), valptr->zone_rctlval_priv, 2996*7c478bd9Sstevel@tonic-gate pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit, 2997*7c478bd9Sstevel@tonic-gate pt_to_str(PT_ACTION), valptr->zone_rctlval_action); 2998*7c478bd9Sstevel@tonic-gate } 2999*7c478bd9Sstevel@tonic-gate } 3000*7c478bd9Sstevel@tonic-gate 3001*7c478bd9Sstevel@tonic-gate static void 3002*7c478bd9Sstevel@tonic-gate info_rctl(zone_dochandle_t handle, FILE *fp, cmd_t *cmd) 3003*7c478bd9Sstevel@tonic-gate { 3004*7c478bd9Sstevel@tonic-gate struct zone_rctltab lookup, user; 3005*7c478bd9Sstevel@tonic-gate bool output = FALSE; 3006*7c478bd9Sstevel@tonic-gate 3007*7c478bd9Sstevel@tonic-gate if (zonecfg_setrctlent(handle) != Z_OK) 3008*7c478bd9Sstevel@tonic-gate return; 3009*7c478bd9Sstevel@tonic-gate while (zonecfg_getrctlent(handle, &lookup) == Z_OK) { 3010*7c478bd9Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs == 0) { 3011*7c478bd9Sstevel@tonic-gate output_rctl(fp, &lookup); 3012*7c478bd9Sstevel@tonic-gate } else if (fill_in_rctltab(cmd, &user, TRUE) == Z_OK && 3013*7c478bd9Sstevel@tonic-gate (strlen(user.zone_rctl_name) == 0 || 3014*7c478bd9Sstevel@tonic-gate strcmp(user.zone_rctl_name, lookup.zone_rctl_name) == 0)) { 3015*7c478bd9Sstevel@tonic-gate output_rctl(fp, &lookup); 3016*7c478bd9Sstevel@tonic-gate output = TRUE; 3017*7c478bd9Sstevel@tonic-gate } 3018*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(lookup.zone_rctl_valptr); 3019*7c478bd9Sstevel@tonic-gate } 3020*7c478bd9Sstevel@tonic-gate (void) zonecfg_endrctlent(handle); 3021*7c478bd9Sstevel@tonic-gate /* 3022*7c478bd9Sstevel@tonic-gate * If a property n/v pair was specified, warn the user if there was 3023*7c478bd9Sstevel@tonic-gate * nothing to output. 3024*7c478bd9Sstevel@tonic-gate */ 3025*7c478bd9Sstevel@tonic-gate if (!output && cmd->cmd_prop_nv_pairs > 0) 3026*7c478bd9Sstevel@tonic-gate (void) printf(gettext("No such %s resource.\n"), 3027*7c478bd9Sstevel@tonic-gate rt_to_str(RT_RCTL)); 3028*7c478bd9Sstevel@tonic-gate } 3029*7c478bd9Sstevel@tonic-gate 3030*7c478bd9Sstevel@tonic-gate static void 3031*7c478bd9Sstevel@tonic-gate output_attr(FILE *fp, struct zone_attrtab *attrtab) 3032*7c478bd9Sstevel@tonic-gate { 3033*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s:\n", rt_to_str(RT_ATTR)); 3034*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_NAME, attrtab->zone_attr_name, B_TRUE); 3035*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_TYPE, attrtab->zone_attr_type, B_TRUE); 3036*7c478bd9Sstevel@tonic-gate output_prop(fp, PT_VALUE, attrtab->zone_attr_value, B_TRUE); 3037*7c478bd9Sstevel@tonic-gate } 3038*7c478bd9Sstevel@tonic-gate 3039*7c478bd9Sstevel@tonic-gate static void 3040*7c478bd9Sstevel@tonic-gate info_attr(zone_dochandle_t handle, FILE *fp, cmd_t *cmd) 3041*7c478bd9Sstevel@tonic-gate { 3042*7c478bd9Sstevel@tonic-gate struct zone_attrtab lookup, user; 3043*7c478bd9Sstevel@tonic-gate bool output = FALSE; 3044*7c478bd9Sstevel@tonic-gate 3045*7c478bd9Sstevel@tonic-gate if (zonecfg_setattrent(handle) != Z_OK) 3046*7c478bd9Sstevel@tonic-gate return; 3047*7c478bd9Sstevel@tonic-gate while (zonecfg_getattrent(handle, &lookup) == Z_OK) { 3048*7c478bd9Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs == 0) { 3049*7c478bd9Sstevel@tonic-gate output_attr(fp, &lookup); 3050*7c478bd9Sstevel@tonic-gate continue; 3051*7c478bd9Sstevel@tonic-gate } 3052*7c478bd9Sstevel@tonic-gate if (fill_in_attrtab(cmd, &user, TRUE) != Z_OK) 3053*7c478bd9Sstevel@tonic-gate continue; 3054*7c478bd9Sstevel@tonic-gate if (strlen(user.zone_attr_name) > 0 && 3055*7c478bd9Sstevel@tonic-gate strcmp(user.zone_attr_name, lookup.zone_attr_name) != 0) 3056*7c478bd9Sstevel@tonic-gate continue; /* no match */ 3057*7c478bd9Sstevel@tonic-gate if (strlen(user.zone_attr_type) > 0 && 3058*7c478bd9Sstevel@tonic-gate strcmp(user.zone_attr_type, lookup.zone_attr_type) != 0) 3059*7c478bd9Sstevel@tonic-gate continue; /* no match */ 3060*7c478bd9Sstevel@tonic-gate if (strlen(user.zone_attr_value) > 0 && 3061*7c478bd9Sstevel@tonic-gate strcmp(user.zone_attr_value, lookup.zone_attr_value) != 0) 3062*7c478bd9Sstevel@tonic-gate continue; /* no match */ 3063*7c478bd9Sstevel@tonic-gate output_attr(fp, &lookup); 3064*7c478bd9Sstevel@tonic-gate output = TRUE; 3065*7c478bd9Sstevel@tonic-gate } 3066*7c478bd9Sstevel@tonic-gate (void) zonecfg_endattrent(handle); 3067*7c478bd9Sstevel@tonic-gate /* 3068*7c478bd9Sstevel@tonic-gate * If a property n/v pair was specified, warn the user if there was 3069*7c478bd9Sstevel@tonic-gate * nothing to output. 3070*7c478bd9Sstevel@tonic-gate */ 3071*7c478bd9Sstevel@tonic-gate if (!output && cmd->cmd_prop_nv_pairs > 0) 3072*7c478bd9Sstevel@tonic-gate (void) printf(gettext("No such %s resource.\n"), 3073*7c478bd9Sstevel@tonic-gate rt_to_str(RT_ATTR)); 3074*7c478bd9Sstevel@tonic-gate } 3075*7c478bd9Sstevel@tonic-gate 3076*7c478bd9Sstevel@tonic-gate void 3077*7c478bd9Sstevel@tonic-gate info_func(cmd_t *cmd) 3078*7c478bd9Sstevel@tonic-gate { 3079*7c478bd9Sstevel@tonic-gate FILE *fp = stdout; 3080*7c478bd9Sstevel@tonic-gate bool need_to_close = FALSE; 3081*7c478bd9Sstevel@tonic-gate char *pager; 3082*7c478bd9Sstevel@tonic-gate 3083*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 3084*7c478bd9Sstevel@tonic-gate 3085*7c478bd9Sstevel@tonic-gate if (initialize(TRUE) != Z_OK) 3086*7c478bd9Sstevel@tonic-gate return; 3087*7c478bd9Sstevel@tonic-gate 3088*7c478bd9Sstevel@tonic-gate /* don't page error output */ 3089*7c478bd9Sstevel@tonic-gate if (interactive_mode) { 3090*7c478bd9Sstevel@tonic-gate if ((pager = getenv("PAGER")) == NULL) 3091*7c478bd9Sstevel@tonic-gate pager = PAGER; 3092*7c478bd9Sstevel@tonic-gate if ((fp = popen(pager, "w")) != NULL) 3093*7c478bd9Sstevel@tonic-gate need_to_close = TRUE; 3094*7c478bd9Sstevel@tonic-gate else 3095*7c478bd9Sstevel@tonic-gate fp = stdout; 3096*7c478bd9Sstevel@tonic-gate setbuf(fp, NULL); 3097*7c478bd9Sstevel@tonic-gate } 3098*7c478bd9Sstevel@tonic-gate 3099*7c478bd9Sstevel@tonic-gate if (!global_scope) { 3100*7c478bd9Sstevel@tonic-gate switch (resource_scope) { 3101*7c478bd9Sstevel@tonic-gate case RT_FS: 3102*7c478bd9Sstevel@tonic-gate output_fs(fp, &in_progress_fstab); 3103*7c478bd9Sstevel@tonic-gate break; 3104*7c478bd9Sstevel@tonic-gate case RT_IPD: 3105*7c478bd9Sstevel@tonic-gate output_ipd(fp, &in_progress_ipdtab); 3106*7c478bd9Sstevel@tonic-gate break; 3107*7c478bd9Sstevel@tonic-gate case RT_NET: 3108*7c478bd9Sstevel@tonic-gate output_net(fp, &in_progress_nwiftab); 3109*7c478bd9Sstevel@tonic-gate break; 3110*7c478bd9Sstevel@tonic-gate case RT_DEVICE: 3111*7c478bd9Sstevel@tonic-gate output_dev(fp, &in_progress_devtab); 3112*7c478bd9Sstevel@tonic-gate break; 3113*7c478bd9Sstevel@tonic-gate case RT_RCTL: 3114*7c478bd9Sstevel@tonic-gate output_rctl(fp, &in_progress_rctltab); 3115*7c478bd9Sstevel@tonic-gate break; 3116*7c478bd9Sstevel@tonic-gate case RT_ATTR: 3117*7c478bd9Sstevel@tonic-gate output_attr(fp, &in_progress_attrtab); 3118*7c478bd9Sstevel@tonic-gate break; 3119*7c478bd9Sstevel@tonic-gate } 3120*7c478bd9Sstevel@tonic-gate goto cleanup; 3121*7c478bd9Sstevel@tonic-gate } 3122*7c478bd9Sstevel@tonic-gate 3123*7c478bd9Sstevel@tonic-gate switch (cmd->cmd_res_type) { 3124*7c478bd9Sstevel@tonic-gate case RT_UNKNOWN: 3125*7c478bd9Sstevel@tonic-gate info_zonepath(handle, fp); 3126*7c478bd9Sstevel@tonic-gate info_autoboot(handle, fp); 3127*7c478bd9Sstevel@tonic-gate info_pool(handle, fp); 3128*7c478bd9Sstevel@tonic-gate info_ipd(handle, fp, cmd); 3129*7c478bd9Sstevel@tonic-gate info_fs(handle, fp, cmd); 3130*7c478bd9Sstevel@tonic-gate info_net(handle, fp, cmd); 3131*7c478bd9Sstevel@tonic-gate info_dev(handle, fp, cmd); 3132*7c478bd9Sstevel@tonic-gate info_rctl(handle, fp, cmd); 3133*7c478bd9Sstevel@tonic-gate info_attr(handle, fp, cmd); 3134*7c478bd9Sstevel@tonic-gate break; 3135*7c478bd9Sstevel@tonic-gate case RT_ZONEPATH: 3136*7c478bd9Sstevel@tonic-gate info_zonepath(handle, fp); 3137*7c478bd9Sstevel@tonic-gate break; 3138*7c478bd9Sstevel@tonic-gate case RT_AUTOBOOT: 3139*7c478bd9Sstevel@tonic-gate info_autoboot(handle, fp); 3140*7c478bd9Sstevel@tonic-gate break; 3141*7c478bd9Sstevel@tonic-gate case RT_POOL: 3142*7c478bd9Sstevel@tonic-gate info_pool(handle, fp); 3143*7c478bd9Sstevel@tonic-gate break; 3144*7c478bd9Sstevel@tonic-gate case RT_FS: 3145*7c478bd9Sstevel@tonic-gate info_fs(handle, fp, cmd); 3146*7c478bd9Sstevel@tonic-gate break; 3147*7c478bd9Sstevel@tonic-gate case RT_IPD: 3148*7c478bd9Sstevel@tonic-gate info_ipd(handle, fp, cmd); 3149*7c478bd9Sstevel@tonic-gate break; 3150*7c478bd9Sstevel@tonic-gate case RT_NET: 3151*7c478bd9Sstevel@tonic-gate info_net(handle, fp, cmd); 3152*7c478bd9Sstevel@tonic-gate break; 3153*7c478bd9Sstevel@tonic-gate case RT_DEVICE: 3154*7c478bd9Sstevel@tonic-gate info_dev(handle, fp, cmd); 3155*7c478bd9Sstevel@tonic-gate break; 3156*7c478bd9Sstevel@tonic-gate case RT_RCTL: 3157*7c478bd9Sstevel@tonic-gate info_rctl(handle, fp, cmd); 3158*7c478bd9Sstevel@tonic-gate break; 3159*7c478bd9Sstevel@tonic-gate case RT_ATTR: 3160*7c478bd9Sstevel@tonic-gate info_attr(handle, fp, cmd); 3161*7c478bd9Sstevel@tonic-gate break; 3162*7c478bd9Sstevel@tonic-gate default: 3163*7c478bd9Sstevel@tonic-gate zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE, 3164*7c478bd9Sstevel@tonic-gate TRUE); 3165*7c478bd9Sstevel@tonic-gate } 3166*7c478bd9Sstevel@tonic-gate 3167*7c478bd9Sstevel@tonic-gate cleanup: 3168*7c478bd9Sstevel@tonic-gate if (need_to_close) 3169*7c478bd9Sstevel@tonic-gate (void) pclose(fp); 3170*7c478bd9Sstevel@tonic-gate } 3171*7c478bd9Sstevel@tonic-gate 3172*7c478bd9Sstevel@tonic-gate static int 3173*7c478bd9Sstevel@tonic-gate save_it(char *zonepath) 3174*7c478bd9Sstevel@tonic-gate { 3175*7c478bd9Sstevel@tonic-gate int err; 3176*7c478bd9Sstevel@tonic-gate 3177*7c478bd9Sstevel@tonic-gate if (new_zone) { 3178*7c478bd9Sstevel@tonic-gate err = zonecfg_add_index(zone, zonepath); 3179*7c478bd9Sstevel@tonic-gate if (err != Z_OK) { 3180*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 3181*7c478bd9Sstevel@tonic-gate return (err); 3182*7c478bd9Sstevel@tonic-gate } 3183*7c478bd9Sstevel@tonic-gate new_zone = FALSE; 3184*7c478bd9Sstevel@tonic-gate } 3185*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_save(handle)) == Z_OK) 3186*7c478bd9Sstevel@tonic-gate need_to_commit = FALSE; 3187*7c478bd9Sstevel@tonic-gate return (err); 3188*7c478bd9Sstevel@tonic-gate } 3189*7c478bd9Sstevel@tonic-gate 3190*7c478bd9Sstevel@tonic-gate /* 3191*7c478bd9Sstevel@tonic-gate * See the DTD for which attributes are required for which resources. 3192*7c478bd9Sstevel@tonic-gate * 3193*7c478bd9Sstevel@tonic-gate * This function can be called by commit_func(), which needs to save things, 3194*7c478bd9Sstevel@tonic-gate * in addition to the general call from parse_and_run(), which doesn't need 3195*7c478bd9Sstevel@tonic-gate * things saved. Since the parameters are standardized, we distinguish by 3196*7c478bd9Sstevel@tonic-gate * having commit_func() call here with cmd->cmd_arg set to "save" to indicate 3197*7c478bd9Sstevel@tonic-gate * that a save is needed. 3198*7c478bd9Sstevel@tonic-gate */ 3199*7c478bd9Sstevel@tonic-gate void 3200*7c478bd9Sstevel@tonic-gate verify_func(cmd_t *cmd) 3201*7c478bd9Sstevel@tonic-gate { 3202*7c478bd9Sstevel@tonic-gate struct zone_nwiftab nwiftab; 3203*7c478bd9Sstevel@tonic-gate struct zone_fstab fstab; 3204*7c478bd9Sstevel@tonic-gate struct zone_attrtab attrtab; 3205*7c478bd9Sstevel@tonic-gate struct zone_rctltab rctltab; 3206*7c478bd9Sstevel@tonic-gate char zonepath[MAXPATHLEN]; 3207*7c478bd9Sstevel@tonic-gate int err, ret_val = Z_OK, arg; 3208*7c478bd9Sstevel@tonic-gate bool save = FALSE; 3209*7c478bd9Sstevel@tonic-gate 3210*7c478bd9Sstevel@tonic-gate optind = 0; 3211*7c478bd9Sstevel@tonic-gate if ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) { 3212*7c478bd9Sstevel@tonic-gate switch (arg) { 3213*7c478bd9Sstevel@tonic-gate case '?': 3214*7c478bd9Sstevel@tonic-gate longer_usage(CMD_VERIFY); 3215*7c478bd9Sstevel@tonic-gate return; 3216*7c478bd9Sstevel@tonic-gate default: 3217*7c478bd9Sstevel@tonic-gate short_usage(CMD_VERIFY); 3218*7c478bd9Sstevel@tonic-gate return; 3219*7c478bd9Sstevel@tonic-gate } 3220*7c478bd9Sstevel@tonic-gate } 3221*7c478bd9Sstevel@tonic-gate if (optind > cmd->cmd_argc) { 3222*7c478bd9Sstevel@tonic-gate short_usage(CMD_VERIFY); 3223*7c478bd9Sstevel@tonic-gate return; 3224*7c478bd9Sstevel@tonic-gate } 3225*7c478bd9Sstevel@tonic-gate 3226*7c478bd9Sstevel@tonic-gate if (zone_is_read_only(CMD_VERIFY)) 3227*7c478bd9Sstevel@tonic-gate return; 3228*7c478bd9Sstevel@tonic-gate 3229*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 3230*7c478bd9Sstevel@tonic-gate 3231*7c478bd9Sstevel@tonic-gate if (cmd->cmd_argc > 0 && (strcmp(cmd->cmd_argv[0], "save") == 0)) 3232*7c478bd9Sstevel@tonic-gate save = TRUE; 3233*7c478bd9Sstevel@tonic-gate if (initialize(TRUE) != Z_OK) 3234*7c478bd9Sstevel@tonic-gate return; 3235*7c478bd9Sstevel@tonic-gate 3236*7c478bd9Sstevel@tonic-gate if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) != Z_OK) { 3237*7c478bd9Sstevel@tonic-gate zerr("%s %s", pt_to_str(PT_ZONEPATH), gettext("not specified")); 3238*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_RESOURCE_MISSING; 3239*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3240*7c478bd9Sstevel@tonic-gate } 3241*7c478bd9Sstevel@tonic-gate if (strlen(zonepath) == 0) { 3242*7c478bd9Sstevel@tonic-gate zerr("%s %s", pt_to_str(PT_ZONEPATH), 3243*7c478bd9Sstevel@tonic-gate gettext("cannot be empty.")); 3244*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_RESOURCE_MISSING; 3245*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3246*7c478bd9Sstevel@tonic-gate } 3247*7c478bd9Sstevel@tonic-gate 3248*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_setipdent(handle)) != Z_OK) { 3249*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 3250*7c478bd9Sstevel@tonic-gate return; 3251*7c478bd9Sstevel@tonic-gate } 3252*7c478bd9Sstevel@tonic-gate while (zonecfg_getipdent(handle, &fstab) == Z_OK) { 3253*7c478bd9Sstevel@tonic-gate if (strlen(fstab.zone_fs_dir) == 0) { 3254*7c478bd9Sstevel@tonic-gate zerr("%s: %s %s", rt_to_str(RT_IPD), pt_to_str(PT_DIR), 3255*7c478bd9Sstevel@tonic-gate gettext("not specified")); 3256*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3257*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3258*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING; 3259*7c478bd9Sstevel@tonic-gate } 3260*7c478bd9Sstevel@tonic-gate } 3261*7c478bd9Sstevel@tonic-gate (void) zonecfg_endipdent(handle); 3262*7c478bd9Sstevel@tonic-gate 3263*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_setfsent(handle)) != Z_OK) { 3264*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 3265*7c478bd9Sstevel@tonic-gate return; 3266*7c478bd9Sstevel@tonic-gate } 3267*7c478bd9Sstevel@tonic-gate while (zonecfg_getfsent(handle, &fstab) == Z_OK) { 3268*7c478bd9Sstevel@tonic-gate if (strlen(fstab.zone_fs_dir) == 0) { 3269*7c478bd9Sstevel@tonic-gate zerr("%s: %s %s", rt_to_str(RT_FS), pt_to_str(PT_DIR), 3270*7c478bd9Sstevel@tonic-gate gettext("not specified")); 3271*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3272*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3273*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING; 3274*7c478bd9Sstevel@tonic-gate } 3275*7c478bd9Sstevel@tonic-gate if (strlen(fstab.zone_fs_special) == 0) { 3276*7c478bd9Sstevel@tonic-gate zerr("%s: %s %s", rt_to_str(RT_FS), 3277*7c478bd9Sstevel@tonic-gate pt_to_str(PT_SPECIAL), gettext("not specified")); 3278*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3279*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3280*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING; 3281*7c478bd9Sstevel@tonic-gate } 3282*7c478bd9Sstevel@tonic-gate if (strlen(fstab.zone_fs_type) == 0) { 3283*7c478bd9Sstevel@tonic-gate zerr("%s: %s %s", rt_to_str(RT_FS), pt_to_str(PT_TYPE), 3284*7c478bd9Sstevel@tonic-gate gettext("not specified")); 3285*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3286*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3287*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING; 3288*7c478bd9Sstevel@tonic-gate } 3289*7c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(fstab.zone_fs_options); 3290*7c478bd9Sstevel@tonic-gate } 3291*7c478bd9Sstevel@tonic-gate (void) zonecfg_endfsent(handle); 3292*7c478bd9Sstevel@tonic-gate 3293*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_setnwifent(handle)) != Z_OK) { 3294*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 3295*7c478bd9Sstevel@tonic-gate return; 3296*7c478bd9Sstevel@tonic-gate } 3297*7c478bd9Sstevel@tonic-gate while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) { 3298*7c478bd9Sstevel@tonic-gate if (strlen(nwiftab.zone_nwif_address) == 0) { 3299*7c478bd9Sstevel@tonic-gate zerr("%s: %s %s", rt_to_str(RT_NET), 3300*7c478bd9Sstevel@tonic-gate pt_to_str(PT_ADDRESS), gettext("not specified")); 3301*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3302*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3303*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING; 3304*7c478bd9Sstevel@tonic-gate } 3305*7c478bd9Sstevel@tonic-gate if (strlen(nwiftab.zone_nwif_physical) == 0) { 3306*7c478bd9Sstevel@tonic-gate zerr("%s: %s %s", rt_to_str(RT_NET), 3307*7c478bd9Sstevel@tonic-gate pt_to_str(PT_PHYSICAL), gettext("not specified")); 3308*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3309*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3310*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING; 3311*7c478bd9Sstevel@tonic-gate } 3312*7c478bd9Sstevel@tonic-gate } 3313*7c478bd9Sstevel@tonic-gate (void) zonecfg_endnwifent(handle); 3314*7c478bd9Sstevel@tonic-gate 3315*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_setrctlent(handle)) != Z_OK) { 3316*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 3317*7c478bd9Sstevel@tonic-gate return; 3318*7c478bd9Sstevel@tonic-gate } 3319*7c478bd9Sstevel@tonic-gate while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) { 3320*7c478bd9Sstevel@tonic-gate if (strlen(rctltab.zone_rctl_name) == 0) { 3321*7c478bd9Sstevel@tonic-gate zerr("%s: %s %s", rt_to_str(RT_RCTL), 3322*7c478bd9Sstevel@tonic-gate pt_to_str(PT_NAME), gettext("not specified")); 3323*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3324*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3325*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING; 3326*7c478bd9Sstevel@tonic-gate } 3327*7c478bd9Sstevel@tonic-gate if (rctltab.zone_rctl_valptr == NULL) { 3328*7c478bd9Sstevel@tonic-gate zerr(gettext("%s: no %s specified"), 3329*7c478bd9Sstevel@tonic-gate rt_to_str(RT_RCTL), pt_to_str(PT_VALUE)); 3330*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3331*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3332*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING; 3333*7c478bd9Sstevel@tonic-gate } else { 3334*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr); 3335*7c478bd9Sstevel@tonic-gate } 3336*7c478bd9Sstevel@tonic-gate } 3337*7c478bd9Sstevel@tonic-gate (void) zonecfg_endrctlent(handle); 3338*7c478bd9Sstevel@tonic-gate 3339*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_setattrent(handle)) != Z_OK) { 3340*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 3341*7c478bd9Sstevel@tonic-gate return; 3342*7c478bd9Sstevel@tonic-gate } 3343*7c478bd9Sstevel@tonic-gate while (zonecfg_getattrent(handle, &attrtab) == Z_OK) { 3344*7c478bd9Sstevel@tonic-gate if (strlen(attrtab.zone_attr_name) == 0) { 3345*7c478bd9Sstevel@tonic-gate zerr("%s: %s %s", rt_to_str(RT_ATTR), 3346*7c478bd9Sstevel@tonic-gate pt_to_str(PT_NAME), gettext("not specified")); 3347*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3348*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3349*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING; 3350*7c478bd9Sstevel@tonic-gate } 3351*7c478bd9Sstevel@tonic-gate if (strlen(attrtab.zone_attr_type) == 0) { 3352*7c478bd9Sstevel@tonic-gate zerr("%s: %s %s", rt_to_str(RT_ATTR), 3353*7c478bd9Sstevel@tonic-gate pt_to_str(PT_TYPE), gettext("not specified")); 3354*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3355*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3356*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING; 3357*7c478bd9Sstevel@tonic-gate } 3358*7c478bd9Sstevel@tonic-gate if (strlen(attrtab.zone_attr_value) == 0) { 3359*7c478bd9Sstevel@tonic-gate zerr("%s: %s %s", rt_to_str(RT_ATTR), 3360*7c478bd9Sstevel@tonic-gate pt_to_str(PT_VALUE), gettext("not specified")); 3361*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3362*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3363*7c478bd9Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING; 3364*7c478bd9Sstevel@tonic-gate } 3365*7c478bd9Sstevel@tonic-gate } 3366*7c478bd9Sstevel@tonic-gate (void) zonecfg_endattrent(handle); 3367*7c478bd9Sstevel@tonic-gate 3368*7c478bd9Sstevel@tonic-gate if (!global_scope) { 3369*7c478bd9Sstevel@tonic-gate zerr(gettext("resource specification incomplete")); 3370*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3371*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3372*7c478bd9Sstevel@tonic-gate ret_val = Z_INSUFFICIENT_SPEC; 3373*7c478bd9Sstevel@tonic-gate } 3374*7c478bd9Sstevel@tonic-gate 3375*7c478bd9Sstevel@tonic-gate if (save) { 3376*7c478bd9Sstevel@tonic-gate if (ret_val == Z_OK) 3377*7c478bd9Sstevel@tonic-gate ret_val = save_it(zonepath); 3378*7c478bd9Sstevel@tonic-gate else 3379*7c478bd9Sstevel@tonic-gate zerr("zone %s %s", zone, gettext("failed to verify")); 3380*7c478bd9Sstevel@tonic-gate } 3381*7c478bd9Sstevel@tonic-gate if (ret_val != Z_OK) 3382*7c478bd9Sstevel@tonic-gate zone_perror(zone, ret_val, TRUE); 3383*7c478bd9Sstevel@tonic-gate } 3384*7c478bd9Sstevel@tonic-gate 3385*7c478bd9Sstevel@tonic-gate void 3386*7c478bd9Sstevel@tonic-gate cancel_func(cmd_t *cmd) 3387*7c478bd9Sstevel@tonic-gate { 3388*7c478bd9Sstevel@tonic-gate int arg; 3389*7c478bd9Sstevel@tonic-gate 3390*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 3391*7c478bd9Sstevel@tonic-gate 3392*7c478bd9Sstevel@tonic-gate optind = 0; 3393*7c478bd9Sstevel@tonic-gate if ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) { 3394*7c478bd9Sstevel@tonic-gate switch (arg) { 3395*7c478bd9Sstevel@tonic-gate case '?': 3396*7c478bd9Sstevel@tonic-gate longer_usage(CMD_CANCEL); 3397*7c478bd9Sstevel@tonic-gate return; 3398*7c478bd9Sstevel@tonic-gate default: 3399*7c478bd9Sstevel@tonic-gate short_usage(CMD_CANCEL); 3400*7c478bd9Sstevel@tonic-gate return; 3401*7c478bd9Sstevel@tonic-gate } 3402*7c478bd9Sstevel@tonic-gate } 3403*7c478bd9Sstevel@tonic-gate if (optind != cmd->cmd_argc) { 3404*7c478bd9Sstevel@tonic-gate short_usage(CMD_CANCEL); 3405*7c478bd9Sstevel@tonic-gate return; 3406*7c478bd9Sstevel@tonic-gate } 3407*7c478bd9Sstevel@tonic-gate 3408*7c478bd9Sstevel@tonic-gate if (global_scope) 3409*7c478bd9Sstevel@tonic-gate scope_usage(CMD_CANCEL); 3410*7c478bd9Sstevel@tonic-gate global_scope = TRUE; 3411*7c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options); 3412*7c478bd9Sstevel@tonic-gate bzero(&in_progress_fstab, sizeof (in_progress_fstab)); 3413*7c478bd9Sstevel@tonic-gate bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab)); 3414*7c478bd9Sstevel@tonic-gate bzero(&in_progress_devtab, sizeof (in_progress_devtab)); 3415*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list(in_progress_rctltab.zone_rctl_valptr); 3416*7c478bd9Sstevel@tonic-gate bzero(&in_progress_rctltab, sizeof (in_progress_rctltab)); 3417*7c478bd9Sstevel@tonic-gate bzero(&in_progress_attrtab, sizeof (in_progress_attrtab)); 3418*7c478bd9Sstevel@tonic-gate } 3419*7c478bd9Sstevel@tonic-gate 3420*7c478bd9Sstevel@tonic-gate static int 3421*7c478bd9Sstevel@tonic-gate validate_attr_name(char *name) 3422*7c478bd9Sstevel@tonic-gate { 3423*7c478bd9Sstevel@tonic-gate int i; 3424*7c478bd9Sstevel@tonic-gate 3425*7c478bd9Sstevel@tonic-gate if (!isalnum(name[0])) { 3426*7c478bd9Sstevel@tonic-gate zerr(gettext("Invalid %s %s %s: must start with an alpha-" 3427*7c478bd9Sstevel@tonic-gate "numeric character."), rt_to_str(RT_ATTR), 3428*7c478bd9Sstevel@tonic-gate pt_to_str(PT_NAME), name); 3429*7c478bd9Sstevel@tonic-gate return (Z_INVAL); 3430*7c478bd9Sstevel@tonic-gate } 3431*7c478bd9Sstevel@tonic-gate for (i = 1; name[i]; i++) 3432*7c478bd9Sstevel@tonic-gate if (!isalnum(name[i]) && name[i] != '-' && name[i] != '.') { 3433*7c478bd9Sstevel@tonic-gate zerr(gettext("Invalid %s %s %s: can only contain " 3434*7c478bd9Sstevel@tonic-gate "alpha-numeric characters, plus '-' and '.'."), 3435*7c478bd9Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_NAME), name); 3436*7c478bd9Sstevel@tonic-gate return (Z_INVAL); 3437*7c478bd9Sstevel@tonic-gate } 3438*7c478bd9Sstevel@tonic-gate return (Z_OK); 3439*7c478bd9Sstevel@tonic-gate } 3440*7c478bd9Sstevel@tonic-gate 3441*7c478bd9Sstevel@tonic-gate static int 3442*7c478bd9Sstevel@tonic-gate validate_attr_type_val(struct zone_attrtab *attrtab) 3443*7c478bd9Sstevel@tonic-gate { 3444*7c478bd9Sstevel@tonic-gate boolean_t boolval; 3445*7c478bd9Sstevel@tonic-gate int64_t intval; 3446*7c478bd9Sstevel@tonic-gate char strval[MAXNAMELEN]; 3447*7c478bd9Sstevel@tonic-gate uint64_t uintval; 3448*7c478bd9Sstevel@tonic-gate 3449*7c478bd9Sstevel@tonic-gate if (strcmp(attrtab->zone_attr_type, "boolean") == 0) { 3450*7c478bd9Sstevel@tonic-gate if (zonecfg_get_attr_boolean(attrtab, &boolval) == Z_OK) 3451*7c478bd9Sstevel@tonic-gate return (Z_OK); 3452*7c478bd9Sstevel@tonic-gate zerr(gettext("invalid %s value for %s=%s"), 3453*7c478bd9Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "boolean"); 3454*7c478bd9Sstevel@tonic-gate return (Z_ERR); 3455*7c478bd9Sstevel@tonic-gate } 3456*7c478bd9Sstevel@tonic-gate 3457*7c478bd9Sstevel@tonic-gate if (strcmp(attrtab->zone_attr_type, "int") == 0) { 3458*7c478bd9Sstevel@tonic-gate if (zonecfg_get_attr_int(attrtab, &intval) == Z_OK) 3459*7c478bd9Sstevel@tonic-gate return (Z_OK); 3460*7c478bd9Sstevel@tonic-gate zerr(gettext("invalid %s value for %s=%s"), 3461*7c478bd9Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "int"); 3462*7c478bd9Sstevel@tonic-gate return (Z_ERR); 3463*7c478bd9Sstevel@tonic-gate } 3464*7c478bd9Sstevel@tonic-gate 3465*7c478bd9Sstevel@tonic-gate if (strcmp(attrtab->zone_attr_type, "string") == 0) { 3466*7c478bd9Sstevel@tonic-gate if (zonecfg_get_attr_string(attrtab, strval, 3467*7c478bd9Sstevel@tonic-gate sizeof (strval)) == Z_OK) 3468*7c478bd9Sstevel@tonic-gate return (Z_OK); 3469*7c478bd9Sstevel@tonic-gate zerr(gettext("invalid %s value for %s=%s"), 3470*7c478bd9Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "string"); 3471*7c478bd9Sstevel@tonic-gate return (Z_ERR); 3472*7c478bd9Sstevel@tonic-gate } 3473*7c478bd9Sstevel@tonic-gate 3474*7c478bd9Sstevel@tonic-gate if (strcmp(attrtab->zone_attr_type, "uint") == 0) { 3475*7c478bd9Sstevel@tonic-gate if (zonecfg_get_attr_uint(attrtab, &uintval) == Z_OK) 3476*7c478bd9Sstevel@tonic-gate return (Z_OK); 3477*7c478bd9Sstevel@tonic-gate zerr(gettext("invalid %s value for %s=%s"), 3478*7c478bd9Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "uint"); 3479*7c478bd9Sstevel@tonic-gate return (Z_ERR); 3480*7c478bd9Sstevel@tonic-gate } 3481*7c478bd9Sstevel@tonic-gate 3482*7c478bd9Sstevel@tonic-gate zerr(gettext("invalid %s %s '%s'"), rt_to_str(RT_ATTR), 3483*7c478bd9Sstevel@tonic-gate pt_to_str(PT_TYPE), attrtab->zone_attr_type); 3484*7c478bd9Sstevel@tonic-gate return (Z_ERR); 3485*7c478bd9Sstevel@tonic-gate } 3486*7c478bd9Sstevel@tonic-gate 3487*7c478bd9Sstevel@tonic-gate void 3488*7c478bd9Sstevel@tonic-gate end_func(cmd_t *cmd) 3489*7c478bd9Sstevel@tonic-gate { 3490*7c478bd9Sstevel@tonic-gate bool validation_failed = FALSE; 3491*7c478bd9Sstevel@tonic-gate struct zone_fstab tmp_fstab; 3492*7c478bd9Sstevel@tonic-gate struct zone_nwiftab tmp_nwiftab; 3493*7c478bd9Sstevel@tonic-gate struct zone_devtab tmp_devtab; 3494*7c478bd9Sstevel@tonic-gate struct zone_rctltab tmp_rctltab; 3495*7c478bd9Sstevel@tonic-gate struct zone_attrtab tmp_attrtab; 3496*7c478bd9Sstevel@tonic-gate int err, arg; 3497*7c478bd9Sstevel@tonic-gate 3498*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 3499*7c478bd9Sstevel@tonic-gate 3500*7c478bd9Sstevel@tonic-gate optind = 0; 3501*7c478bd9Sstevel@tonic-gate if ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) { 3502*7c478bd9Sstevel@tonic-gate switch (arg) { 3503*7c478bd9Sstevel@tonic-gate case '?': 3504*7c478bd9Sstevel@tonic-gate longer_usage(CMD_END); 3505*7c478bd9Sstevel@tonic-gate return; 3506*7c478bd9Sstevel@tonic-gate default: 3507*7c478bd9Sstevel@tonic-gate short_usage(CMD_END); 3508*7c478bd9Sstevel@tonic-gate return; 3509*7c478bd9Sstevel@tonic-gate } 3510*7c478bd9Sstevel@tonic-gate } 3511*7c478bd9Sstevel@tonic-gate if (optind != cmd->cmd_argc) { 3512*7c478bd9Sstevel@tonic-gate short_usage(CMD_END); 3513*7c478bd9Sstevel@tonic-gate return; 3514*7c478bd9Sstevel@tonic-gate } 3515*7c478bd9Sstevel@tonic-gate 3516*7c478bd9Sstevel@tonic-gate if (global_scope) { 3517*7c478bd9Sstevel@tonic-gate scope_usage(CMD_END); 3518*7c478bd9Sstevel@tonic-gate return; 3519*7c478bd9Sstevel@tonic-gate } 3520*7c478bd9Sstevel@tonic-gate 3521*7c478bd9Sstevel@tonic-gate assert(end_op == CMD_ADD || end_op == CMD_SELECT); 3522*7c478bd9Sstevel@tonic-gate 3523*7c478bd9Sstevel@tonic-gate switch (resource_scope) { 3524*7c478bd9Sstevel@tonic-gate case RT_FS: 3525*7c478bd9Sstevel@tonic-gate /* First make sure everything was filled in. */ 3526*7c478bd9Sstevel@tonic-gate if (strlen(in_progress_fstab.zone_fs_dir) == 0) { 3527*7c478bd9Sstevel@tonic-gate zerr("dir %s", gettext("not specified")); 3528*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3529*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3530*7c478bd9Sstevel@tonic-gate } else if (in_progress_fstab.zone_fs_dir[0] != '/') { 3531*7c478bd9Sstevel@tonic-gate zerr("dir %s %s", in_progress_fstab.zone_fs_dir, 3532*7c478bd9Sstevel@tonic-gate gettext("is not an absolute path.")); 3533*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3534*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3535*7c478bd9Sstevel@tonic-gate } 3536*7c478bd9Sstevel@tonic-gate if (strlen(in_progress_fstab.zone_fs_special) == 0) { 3537*7c478bd9Sstevel@tonic-gate zerr("special %s", gettext("not specified")); 3538*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3539*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3540*7c478bd9Sstevel@tonic-gate } 3541*7c478bd9Sstevel@tonic-gate if (in_progress_fstab.zone_fs_raw[0] != '\0' && 3542*7c478bd9Sstevel@tonic-gate in_progress_fstab.zone_fs_raw[0] != '/') { 3543*7c478bd9Sstevel@tonic-gate zerr("raw device %s %s", 3544*7c478bd9Sstevel@tonic-gate in_progress_fstab.zone_fs_raw, 3545*7c478bd9Sstevel@tonic-gate gettext("is not an absolute path.")); 3546*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3547*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3548*7c478bd9Sstevel@tonic-gate } 3549*7c478bd9Sstevel@tonic-gate if (strlen(in_progress_fstab.zone_fs_type) == 0) { 3550*7c478bd9Sstevel@tonic-gate zerr("type %s", gettext("not specified")); 3551*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3552*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3553*7c478bd9Sstevel@tonic-gate } 3554*7c478bd9Sstevel@tonic-gate if (validation_failed) 3555*7c478bd9Sstevel@tonic-gate return; 3556*7c478bd9Sstevel@tonic-gate if (end_op == CMD_ADD) { 3557*7c478bd9Sstevel@tonic-gate /* Make sure there isn't already one like this. */ 3558*7c478bd9Sstevel@tonic-gate bzero(&tmp_fstab, sizeof (tmp_fstab)); 3559*7c478bd9Sstevel@tonic-gate (void) strlcpy(tmp_fstab.zone_fs_dir, 3560*7c478bd9Sstevel@tonic-gate in_progress_fstab.zone_fs_dir, 3561*7c478bd9Sstevel@tonic-gate sizeof (tmp_fstab.zone_fs_dir)); 3562*7c478bd9Sstevel@tonic-gate err = zonecfg_lookup_filesystem(handle, &tmp_fstab); 3563*7c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(tmp_fstab.zone_fs_options); 3564*7c478bd9Sstevel@tonic-gate if (err == Z_OK) { 3565*7c478bd9Sstevel@tonic-gate zerr(gettext("A %s resource " 3566*7c478bd9Sstevel@tonic-gate "with the %s '%s' already exists."), 3567*7c478bd9Sstevel@tonic-gate rt_to_str(RT_FS), pt_to_str(PT_DIR), 3568*7c478bd9Sstevel@tonic-gate in_progress_fstab.zone_fs_dir); 3569*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3570*7c478bd9Sstevel@tonic-gate return; 3571*7c478bd9Sstevel@tonic-gate } 3572*7c478bd9Sstevel@tonic-gate err = zonecfg_add_filesystem(handle, 3573*7c478bd9Sstevel@tonic-gate &in_progress_fstab); 3574*7c478bd9Sstevel@tonic-gate } else { 3575*7c478bd9Sstevel@tonic-gate err = zonecfg_modify_filesystem(handle, &old_fstab, 3576*7c478bd9Sstevel@tonic-gate &in_progress_fstab); 3577*7c478bd9Sstevel@tonic-gate } 3578*7c478bd9Sstevel@tonic-gate zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options); 3579*7c478bd9Sstevel@tonic-gate in_progress_fstab.zone_fs_options = NULL; 3580*7c478bd9Sstevel@tonic-gate break; 3581*7c478bd9Sstevel@tonic-gate case RT_IPD: 3582*7c478bd9Sstevel@tonic-gate /* First make sure everything was filled in. */ 3583*7c478bd9Sstevel@tonic-gate if (strlen(in_progress_ipdtab.zone_fs_dir) == 0) { 3584*7c478bd9Sstevel@tonic-gate zerr("dir %s", gettext("not specified")); 3585*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3586*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3587*7c478bd9Sstevel@tonic-gate } else if (in_progress_ipdtab.zone_fs_dir[0] != '/') { 3588*7c478bd9Sstevel@tonic-gate zerr("dir %s %s", in_progress_ipdtab.zone_fs_dir, 3589*7c478bd9Sstevel@tonic-gate gettext("is not an absolute path.")); 3590*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3591*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3592*7c478bd9Sstevel@tonic-gate } 3593*7c478bd9Sstevel@tonic-gate if (validation_failed) 3594*7c478bd9Sstevel@tonic-gate return; 3595*7c478bd9Sstevel@tonic-gate if (end_op == CMD_ADD) { 3596*7c478bd9Sstevel@tonic-gate /* Make sure there isn't already one like this. */ 3597*7c478bd9Sstevel@tonic-gate bzero(&tmp_fstab, sizeof (tmp_fstab)); 3598*7c478bd9Sstevel@tonic-gate (void) strlcpy(tmp_fstab.zone_fs_dir, 3599*7c478bd9Sstevel@tonic-gate in_progress_ipdtab.zone_fs_dir, 3600*7c478bd9Sstevel@tonic-gate sizeof (tmp_fstab.zone_fs_dir)); 3601*7c478bd9Sstevel@tonic-gate err = zonecfg_lookup_ipd(handle, &tmp_fstab); 3602*7c478bd9Sstevel@tonic-gate if (err == Z_OK) { 3603*7c478bd9Sstevel@tonic-gate zerr(gettext("An %s resource " 3604*7c478bd9Sstevel@tonic-gate "with the %s '%s' already exists."), 3605*7c478bd9Sstevel@tonic-gate rt_to_str(RT_IPD), pt_to_str(PT_DIR), 3606*7c478bd9Sstevel@tonic-gate in_progress_ipdtab.zone_fs_dir); 3607*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3608*7c478bd9Sstevel@tonic-gate return; 3609*7c478bd9Sstevel@tonic-gate } 3610*7c478bd9Sstevel@tonic-gate err = zonecfg_add_ipd(handle, &in_progress_ipdtab); 3611*7c478bd9Sstevel@tonic-gate } else { 3612*7c478bd9Sstevel@tonic-gate err = zonecfg_modify_ipd(handle, &old_ipdtab, 3613*7c478bd9Sstevel@tonic-gate &in_progress_ipdtab); 3614*7c478bd9Sstevel@tonic-gate } 3615*7c478bd9Sstevel@tonic-gate break; 3616*7c478bd9Sstevel@tonic-gate case RT_NET: 3617*7c478bd9Sstevel@tonic-gate /* First make sure everything was filled in. */ 3618*7c478bd9Sstevel@tonic-gate if (strlen(in_progress_nwiftab.zone_nwif_physical) == 0) { 3619*7c478bd9Sstevel@tonic-gate zerr("physical %s", gettext("not specified")); 3620*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3621*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3622*7c478bd9Sstevel@tonic-gate } 3623*7c478bd9Sstevel@tonic-gate if (strlen(in_progress_nwiftab.zone_nwif_address) == 0) { 3624*7c478bd9Sstevel@tonic-gate zerr("address %s", gettext("not specified")); 3625*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3626*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3627*7c478bd9Sstevel@tonic-gate } 3628*7c478bd9Sstevel@tonic-gate if (validation_failed) 3629*7c478bd9Sstevel@tonic-gate return; 3630*7c478bd9Sstevel@tonic-gate if (end_op == CMD_ADD) { 3631*7c478bd9Sstevel@tonic-gate /* Make sure there isn't already one like this. */ 3632*7c478bd9Sstevel@tonic-gate bzero(&tmp_nwiftab, sizeof (tmp_nwiftab)); 3633*7c478bd9Sstevel@tonic-gate (void) strlcpy(tmp_nwiftab.zone_nwif_address, 3634*7c478bd9Sstevel@tonic-gate in_progress_nwiftab.zone_nwif_address, 3635*7c478bd9Sstevel@tonic-gate sizeof (tmp_nwiftab.zone_nwif_address)); 3636*7c478bd9Sstevel@tonic-gate if (zonecfg_lookup_nwif(handle, &tmp_nwiftab) == Z_OK) { 3637*7c478bd9Sstevel@tonic-gate zerr(gettext("A %s resource " 3638*7c478bd9Sstevel@tonic-gate "with the %s '%s' already exists."), 3639*7c478bd9Sstevel@tonic-gate rt_to_str(RT_NET), pt_to_str(PT_ADDRESS), 3640*7c478bd9Sstevel@tonic-gate in_progress_nwiftab.zone_nwif_address); 3641*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3642*7c478bd9Sstevel@tonic-gate return; 3643*7c478bd9Sstevel@tonic-gate } 3644*7c478bd9Sstevel@tonic-gate err = zonecfg_add_nwif(handle, &in_progress_nwiftab); 3645*7c478bd9Sstevel@tonic-gate } else { 3646*7c478bd9Sstevel@tonic-gate err = zonecfg_modify_nwif(handle, &old_nwiftab, 3647*7c478bd9Sstevel@tonic-gate &in_progress_nwiftab); 3648*7c478bd9Sstevel@tonic-gate } 3649*7c478bd9Sstevel@tonic-gate break; 3650*7c478bd9Sstevel@tonic-gate case RT_DEVICE: 3651*7c478bd9Sstevel@tonic-gate /* First make sure everything was filled in. */ 3652*7c478bd9Sstevel@tonic-gate if (strlen(in_progress_devtab.zone_dev_match) == 0) { 3653*7c478bd9Sstevel@tonic-gate zerr("match %s", gettext("not specified")); 3654*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3655*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3656*7c478bd9Sstevel@tonic-gate } 3657*7c478bd9Sstevel@tonic-gate if (validation_failed) 3658*7c478bd9Sstevel@tonic-gate return; 3659*7c478bd9Sstevel@tonic-gate if (end_op == CMD_ADD) { 3660*7c478bd9Sstevel@tonic-gate /* Make sure there isn't already one like this. */ 3661*7c478bd9Sstevel@tonic-gate (void) strlcpy(tmp_devtab.zone_dev_match, 3662*7c478bd9Sstevel@tonic-gate in_progress_devtab.zone_dev_match, 3663*7c478bd9Sstevel@tonic-gate sizeof (tmp_devtab.zone_dev_match)); 3664*7c478bd9Sstevel@tonic-gate if (zonecfg_lookup_dev(handle, &tmp_devtab) == Z_OK) { 3665*7c478bd9Sstevel@tonic-gate zerr(gettext("A %s resource with the %s '%s' " 3666*7c478bd9Sstevel@tonic-gate "already exists."), rt_to_str(RT_DEVICE), 3667*7c478bd9Sstevel@tonic-gate pt_to_str(PT_MATCH), 3668*7c478bd9Sstevel@tonic-gate in_progress_devtab.zone_dev_match); 3669*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3670*7c478bd9Sstevel@tonic-gate return; 3671*7c478bd9Sstevel@tonic-gate } 3672*7c478bd9Sstevel@tonic-gate err = zonecfg_add_dev(handle, &in_progress_devtab); 3673*7c478bd9Sstevel@tonic-gate } else { 3674*7c478bd9Sstevel@tonic-gate err = zonecfg_modify_dev(handle, &old_devtab, 3675*7c478bd9Sstevel@tonic-gate &in_progress_devtab); 3676*7c478bd9Sstevel@tonic-gate } 3677*7c478bd9Sstevel@tonic-gate break; 3678*7c478bd9Sstevel@tonic-gate case RT_RCTL: 3679*7c478bd9Sstevel@tonic-gate /* First make sure everything was filled in. */ 3680*7c478bd9Sstevel@tonic-gate if (strlen(in_progress_rctltab.zone_rctl_name) == 0) { 3681*7c478bd9Sstevel@tonic-gate zerr("name %s", gettext("not specified")); 3682*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3683*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3684*7c478bd9Sstevel@tonic-gate } 3685*7c478bd9Sstevel@tonic-gate if (in_progress_rctltab.zone_rctl_valptr == NULL) { 3686*7c478bd9Sstevel@tonic-gate zerr(gettext("no %s specified"), pt_to_str(PT_VALUE)); 3687*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3688*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3689*7c478bd9Sstevel@tonic-gate } 3690*7c478bd9Sstevel@tonic-gate if (validation_failed) 3691*7c478bd9Sstevel@tonic-gate return; 3692*7c478bd9Sstevel@tonic-gate if (end_op == CMD_ADD) { 3693*7c478bd9Sstevel@tonic-gate /* Make sure there isn't already one like this. */ 3694*7c478bd9Sstevel@tonic-gate (void) strlcpy(tmp_rctltab.zone_rctl_name, 3695*7c478bd9Sstevel@tonic-gate in_progress_rctltab.zone_rctl_name, 3696*7c478bd9Sstevel@tonic-gate sizeof (tmp_rctltab.zone_rctl_name)); 3697*7c478bd9Sstevel@tonic-gate tmp_rctltab.zone_rctl_valptr = NULL; 3698*7c478bd9Sstevel@tonic-gate err = zonecfg_lookup_rctl(handle, &tmp_rctltab); 3699*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list( 3700*7c478bd9Sstevel@tonic-gate tmp_rctltab.zone_rctl_valptr); 3701*7c478bd9Sstevel@tonic-gate if (err == Z_OK) { 3702*7c478bd9Sstevel@tonic-gate zerr(gettext("A %s resource " 3703*7c478bd9Sstevel@tonic-gate "with the %s '%s' already exists."), 3704*7c478bd9Sstevel@tonic-gate rt_to_str(RT_RCTL), pt_to_str(PT_NAME), 3705*7c478bd9Sstevel@tonic-gate in_progress_rctltab.zone_rctl_name); 3706*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3707*7c478bd9Sstevel@tonic-gate return; 3708*7c478bd9Sstevel@tonic-gate } 3709*7c478bd9Sstevel@tonic-gate err = zonecfg_add_rctl(handle, &in_progress_rctltab); 3710*7c478bd9Sstevel@tonic-gate } else { 3711*7c478bd9Sstevel@tonic-gate err = zonecfg_modify_rctl(handle, &old_rctltab, 3712*7c478bd9Sstevel@tonic-gate &in_progress_rctltab); 3713*7c478bd9Sstevel@tonic-gate } 3714*7c478bd9Sstevel@tonic-gate if (err == Z_OK) { 3715*7c478bd9Sstevel@tonic-gate zonecfg_free_rctl_value_list( 3716*7c478bd9Sstevel@tonic-gate in_progress_rctltab.zone_rctl_valptr); 3717*7c478bd9Sstevel@tonic-gate in_progress_rctltab.zone_rctl_valptr = NULL; 3718*7c478bd9Sstevel@tonic-gate } 3719*7c478bd9Sstevel@tonic-gate break; 3720*7c478bd9Sstevel@tonic-gate case RT_ATTR: 3721*7c478bd9Sstevel@tonic-gate /* First make sure everything was filled in. */ 3722*7c478bd9Sstevel@tonic-gate if (strlen(in_progress_attrtab.zone_attr_name) == 0) { 3723*7c478bd9Sstevel@tonic-gate zerr("name %s", gettext("not specified")); 3724*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3725*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3726*7c478bd9Sstevel@tonic-gate } 3727*7c478bd9Sstevel@tonic-gate if (strlen(in_progress_attrtab.zone_attr_type) == 0) { 3728*7c478bd9Sstevel@tonic-gate zerr("type %s", gettext("not specified")); 3729*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3730*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3731*7c478bd9Sstevel@tonic-gate } 3732*7c478bd9Sstevel@tonic-gate if (strlen(in_progress_attrtab.zone_attr_value) == 0) { 3733*7c478bd9Sstevel@tonic-gate zerr("value %s", gettext("not specified")); 3734*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3735*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3736*7c478bd9Sstevel@tonic-gate } 3737*7c478bd9Sstevel@tonic-gate if (validate_attr_name(in_progress_attrtab.zone_attr_name) != 3738*7c478bd9Sstevel@tonic-gate Z_OK) { 3739*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3740*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3741*7c478bd9Sstevel@tonic-gate } 3742*7c478bd9Sstevel@tonic-gate if (validate_attr_type_val(&in_progress_attrtab) != Z_OK) { 3743*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3744*7c478bd9Sstevel@tonic-gate validation_failed = TRUE; 3745*7c478bd9Sstevel@tonic-gate } 3746*7c478bd9Sstevel@tonic-gate if (validation_failed) 3747*7c478bd9Sstevel@tonic-gate return; 3748*7c478bd9Sstevel@tonic-gate if (end_op == CMD_ADD) { 3749*7c478bd9Sstevel@tonic-gate /* Make sure there isn't already one like this. */ 3750*7c478bd9Sstevel@tonic-gate bzero(&tmp_attrtab, sizeof (tmp_attrtab)); 3751*7c478bd9Sstevel@tonic-gate (void) strlcpy(tmp_attrtab.zone_attr_name, 3752*7c478bd9Sstevel@tonic-gate in_progress_attrtab.zone_attr_name, 3753*7c478bd9Sstevel@tonic-gate sizeof (tmp_attrtab.zone_attr_name)); 3754*7c478bd9Sstevel@tonic-gate if (zonecfg_lookup_attr(handle, &tmp_attrtab) == Z_OK) { 3755*7c478bd9Sstevel@tonic-gate zerr(gettext("An %s resource " 3756*7c478bd9Sstevel@tonic-gate "with the %s '%s' already exists."), 3757*7c478bd9Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_NAME), 3758*7c478bd9Sstevel@tonic-gate in_progress_attrtab.zone_attr_name); 3759*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3760*7c478bd9Sstevel@tonic-gate return; 3761*7c478bd9Sstevel@tonic-gate } 3762*7c478bd9Sstevel@tonic-gate err = zonecfg_add_attr(handle, &in_progress_attrtab); 3763*7c478bd9Sstevel@tonic-gate } else { 3764*7c478bd9Sstevel@tonic-gate err = zonecfg_modify_attr(handle, &old_attrtab, 3765*7c478bd9Sstevel@tonic-gate &in_progress_attrtab); 3766*7c478bd9Sstevel@tonic-gate } 3767*7c478bd9Sstevel@tonic-gate break; 3768*7c478bd9Sstevel@tonic-gate default: 3769*7c478bd9Sstevel@tonic-gate zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE, 3770*7c478bd9Sstevel@tonic-gate TRUE); 3771*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3772*7c478bd9Sstevel@tonic-gate return; 3773*7c478bd9Sstevel@tonic-gate } 3774*7c478bd9Sstevel@tonic-gate 3775*7c478bd9Sstevel@tonic-gate if (err != Z_OK) { 3776*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 3777*7c478bd9Sstevel@tonic-gate } else { 3778*7c478bd9Sstevel@tonic-gate need_to_commit = TRUE; 3779*7c478bd9Sstevel@tonic-gate global_scope = TRUE; 3780*7c478bd9Sstevel@tonic-gate end_op = -1; 3781*7c478bd9Sstevel@tonic-gate } 3782*7c478bd9Sstevel@tonic-gate } 3783*7c478bd9Sstevel@tonic-gate 3784*7c478bd9Sstevel@tonic-gate void 3785*7c478bd9Sstevel@tonic-gate commit_func(cmd_t *cmd) 3786*7c478bd9Sstevel@tonic-gate { 3787*7c478bd9Sstevel@tonic-gate int arg; 3788*7c478bd9Sstevel@tonic-gate 3789*7c478bd9Sstevel@tonic-gate optind = 0; 3790*7c478bd9Sstevel@tonic-gate if ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) { 3791*7c478bd9Sstevel@tonic-gate switch (arg) { 3792*7c478bd9Sstevel@tonic-gate case '?': 3793*7c478bd9Sstevel@tonic-gate longer_usage(CMD_COMMIT); 3794*7c478bd9Sstevel@tonic-gate return; 3795*7c478bd9Sstevel@tonic-gate default: 3796*7c478bd9Sstevel@tonic-gate short_usage(CMD_COMMIT); 3797*7c478bd9Sstevel@tonic-gate return; 3798*7c478bd9Sstevel@tonic-gate } 3799*7c478bd9Sstevel@tonic-gate } 3800*7c478bd9Sstevel@tonic-gate if (optind != cmd->cmd_argc) { 3801*7c478bd9Sstevel@tonic-gate short_usage(CMD_COMMIT); 3802*7c478bd9Sstevel@tonic-gate return; 3803*7c478bd9Sstevel@tonic-gate } 3804*7c478bd9Sstevel@tonic-gate 3805*7c478bd9Sstevel@tonic-gate if (zone_is_read_only(CMD_COMMIT)) 3806*7c478bd9Sstevel@tonic-gate return; 3807*7c478bd9Sstevel@tonic-gate 3808*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 3809*7c478bd9Sstevel@tonic-gate 3810*7c478bd9Sstevel@tonic-gate cmd->cmd_argc = 1; 3811*7c478bd9Sstevel@tonic-gate /* 3812*7c478bd9Sstevel@tonic-gate * cmd_arg normally comes from a strdup() in the lexer, and the 3813*7c478bd9Sstevel@tonic-gate * whole cmd structure and its (char *) attributes are freed at 3814*7c478bd9Sstevel@tonic-gate * the completion of each command, so the strdup() below is needed 3815*7c478bd9Sstevel@tonic-gate * to match this and prevent a core dump from trying to free() 3816*7c478bd9Sstevel@tonic-gate * something that can't be. 3817*7c478bd9Sstevel@tonic-gate */ 3818*7c478bd9Sstevel@tonic-gate if ((cmd->cmd_argv[0] = strdup("save")) == NULL) { 3819*7c478bd9Sstevel@tonic-gate zone_perror(zone, Z_NOMEM, TRUE); 3820*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 3821*7c478bd9Sstevel@tonic-gate } 3822*7c478bd9Sstevel@tonic-gate cmd->cmd_argv[1] = NULL; 3823*7c478bd9Sstevel@tonic-gate verify_func(cmd); 3824*7c478bd9Sstevel@tonic-gate } 3825*7c478bd9Sstevel@tonic-gate 3826*7c478bd9Sstevel@tonic-gate void 3827*7c478bd9Sstevel@tonic-gate revert_func(cmd_t *cmd) 3828*7c478bd9Sstevel@tonic-gate { 3829*7c478bd9Sstevel@tonic-gate char line[128]; /* enough to ask a question */ 3830*7c478bd9Sstevel@tonic-gate bool force = FALSE; 3831*7c478bd9Sstevel@tonic-gate int err, arg, answer; 3832*7c478bd9Sstevel@tonic-gate 3833*7c478bd9Sstevel@tonic-gate optind = 0; 3834*7c478bd9Sstevel@tonic-gate while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) { 3835*7c478bd9Sstevel@tonic-gate switch (arg) { 3836*7c478bd9Sstevel@tonic-gate case '?': 3837*7c478bd9Sstevel@tonic-gate longer_usage(CMD_REVERT); 3838*7c478bd9Sstevel@tonic-gate return; 3839*7c478bd9Sstevel@tonic-gate case 'F': 3840*7c478bd9Sstevel@tonic-gate force = TRUE; 3841*7c478bd9Sstevel@tonic-gate break; 3842*7c478bd9Sstevel@tonic-gate default: 3843*7c478bd9Sstevel@tonic-gate short_usage(CMD_REVERT); 3844*7c478bd9Sstevel@tonic-gate return; 3845*7c478bd9Sstevel@tonic-gate } 3846*7c478bd9Sstevel@tonic-gate } 3847*7c478bd9Sstevel@tonic-gate if (optind != cmd->cmd_argc) { 3848*7c478bd9Sstevel@tonic-gate short_usage(CMD_REVERT); 3849*7c478bd9Sstevel@tonic-gate return; 3850*7c478bd9Sstevel@tonic-gate } 3851*7c478bd9Sstevel@tonic-gate 3852*7c478bd9Sstevel@tonic-gate if (zone_is_read_only(CMD_REVERT)) 3853*7c478bd9Sstevel@tonic-gate return; 3854*7c478bd9Sstevel@tonic-gate 3855*7c478bd9Sstevel@tonic-gate if (zonecfg_check_handle(handle) != Z_OK) { 3856*7c478bd9Sstevel@tonic-gate zerr(gettext("No changes to revert.")); 3857*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3858*7c478bd9Sstevel@tonic-gate return; 3859*7c478bd9Sstevel@tonic-gate } 3860*7c478bd9Sstevel@tonic-gate 3861*7c478bd9Sstevel@tonic-gate if (!force) { 3862*7c478bd9Sstevel@tonic-gate (void) snprintf(line, sizeof (line), 3863*7c478bd9Sstevel@tonic-gate gettext("Are you sure you want to revert")); 3864*7c478bd9Sstevel@tonic-gate if ((answer = ask_yesno(FALSE, line)) == -1) { 3865*7c478bd9Sstevel@tonic-gate zerr(gettext("Input not from terminal and -F not " 3866*7c478bd9Sstevel@tonic-gate "specified:\n%s command ignored, exiting."), 3867*7c478bd9Sstevel@tonic-gate cmd_to_str(CMD_REVERT)); 3868*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 3869*7c478bd9Sstevel@tonic-gate } 3870*7c478bd9Sstevel@tonic-gate if (answer != 1) 3871*7c478bd9Sstevel@tonic-gate return; 3872*7c478bd9Sstevel@tonic-gate } 3873*7c478bd9Sstevel@tonic-gate 3874*7c478bd9Sstevel@tonic-gate /* 3875*7c478bd9Sstevel@tonic-gate * Time for a new handle: finish the old one off first 3876*7c478bd9Sstevel@tonic-gate * then get a new one properly to avoid leaks. 3877*7c478bd9Sstevel@tonic-gate */ 3878*7c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 3879*7c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) { 3880*7c478bd9Sstevel@tonic-gate zone_perror(execname, Z_NOMEM, TRUE); 3881*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 3882*7c478bd9Sstevel@tonic-gate } 3883*7c478bd9Sstevel@tonic-gate if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) { 3884*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3885*7c478bd9Sstevel@tonic-gate got_handle = FALSE; 3886*7c478bd9Sstevel@tonic-gate if (err == Z_NO_ZONE) 3887*7c478bd9Sstevel@tonic-gate zerr(gettext("%s: no such saved zone to revert to."), 3888*7c478bd9Sstevel@tonic-gate zone); 3889*7c478bd9Sstevel@tonic-gate else 3890*7c478bd9Sstevel@tonic-gate zone_perror(zone, err, TRUE); 3891*7c478bd9Sstevel@tonic-gate } 3892*7c478bd9Sstevel@tonic-gate } 3893*7c478bd9Sstevel@tonic-gate 3894*7c478bd9Sstevel@tonic-gate void 3895*7c478bd9Sstevel@tonic-gate help_func(cmd_t *cmd) 3896*7c478bd9Sstevel@tonic-gate { 3897*7c478bd9Sstevel@tonic-gate int i; 3898*7c478bd9Sstevel@tonic-gate 3899*7c478bd9Sstevel@tonic-gate assert(cmd != NULL); 3900*7c478bd9Sstevel@tonic-gate 3901*7c478bd9Sstevel@tonic-gate if (cmd->cmd_argc == 0) { 3902*7c478bd9Sstevel@tonic-gate usage(TRUE, global_scope ? HELP_SUBCMDS : HELP_RES_SCOPE); 3903*7c478bd9Sstevel@tonic-gate return; 3904*7c478bd9Sstevel@tonic-gate } 3905*7c478bd9Sstevel@tonic-gate if (strcmp(cmd->cmd_argv[0], "usage") == 0) { 3906*7c478bd9Sstevel@tonic-gate usage(TRUE, HELP_USAGE); 3907*7c478bd9Sstevel@tonic-gate return; 3908*7c478bd9Sstevel@tonic-gate } 3909*7c478bd9Sstevel@tonic-gate if (strcmp(cmd->cmd_argv[0], "commands") == 0) { 3910*7c478bd9Sstevel@tonic-gate usage(TRUE, HELP_SUBCMDS); 3911*7c478bd9Sstevel@tonic-gate return; 3912*7c478bd9Sstevel@tonic-gate } 3913*7c478bd9Sstevel@tonic-gate if (strcmp(cmd->cmd_argv[0], "syntax") == 0) { 3914*7c478bd9Sstevel@tonic-gate usage(TRUE, HELP_SYNTAX | HELP_RES_PROPS); 3915*7c478bd9Sstevel@tonic-gate return; 3916*7c478bd9Sstevel@tonic-gate } 3917*7c478bd9Sstevel@tonic-gate if (strcmp(cmd->cmd_argv[0], "-?") == 0) { 3918*7c478bd9Sstevel@tonic-gate longer_usage(CMD_HELP); 3919*7c478bd9Sstevel@tonic-gate return; 3920*7c478bd9Sstevel@tonic-gate } 3921*7c478bd9Sstevel@tonic-gate 3922*7c478bd9Sstevel@tonic-gate for (i = 0; i <= CMD_MAX; i++) { 3923*7c478bd9Sstevel@tonic-gate if (strcmp(cmd->cmd_argv[0], cmd_to_str(i)) == 0) { 3924*7c478bd9Sstevel@tonic-gate longer_usage(i); 3925*7c478bd9Sstevel@tonic-gate return; 3926*7c478bd9Sstevel@tonic-gate } 3927*7c478bd9Sstevel@tonic-gate } 3928*7c478bd9Sstevel@tonic-gate /* We do not use zerr() here because we do not want its extra \n. */ 3929*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Unknown help subject %s. "), 3930*7c478bd9Sstevel@tonic-gate cmd->cmd_argv[0]); 3931*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_META); 3932*7c478bd9Sstevel@tonic-gate } 3933*7c478bd9Sstevel@tonic-gate 3934*7c478bd9Sstevel@tonic-gate static int 3935*7c478bd9Sstevel@tonic-gate string_to_yyin(char *string) 3936*7c478bd9Sstevel@tonic-gate { 3937*7c478bd9Sstevel@tonic-gate if ((yyin = tmpfile()) == NULL) { 3938*7c478bd9Sstevel@tonic-gate zone_perror(execname, Z_TEMP_FILE, TRUE); 3939*7c478bd9Sstevel@tonic-gate return (Z_ERR); 3940*7c478bd9Sstevel@tonic-gate } 3941*7c478bd9Sstevel@tonic-gate if (fwrite(string, strlen(string), 1, yyin) != 1) { 3942*7c478bd9Sstevel@tonic-gate zone_perror(execname, Z_TEMP_FILE, TRUE); 3943*7c478bd9Sstevel@tonic-gate return (Z_ERR); 3944*7c478bd9Sstevel@tonic-gate } 3945*7c478bd9Sstevel@tonic-gate if (fseek(yyin, 0, SEEK_SET) != 0) { 3946*7c478bd9Sstevel@tonic-gate zone_perror(execname, Z_TEMP_FILE, TRUE); 3947*7c478bd9Sstevel@tonic-gate return (Z_ERR); 3948*7c478bd9Sstevel@tonic-gate } 3949*7c478bd9Sstevel@tonic-gate return (Z_OK); 3950*7c478bd9Sstevel@tonic-gate } 3951*7c478bd9Sstevel@tonic-gate 3952*7c478bd9Sstevel@tonic-gate /* This is the back-end helper function for read_input() below. */ 3953*7c478bd9Sstevel@tonic-gate 3954*7c478bd9Sstevel@tonic-gate static int 3955*7c478bd9Sstevel@tonic-gate cleanup() 3956*7c478bd9Sstevel@tonic-gate { 3957*7c478bd9Sstevel@tonic-gate int answer; 3958*7c478bd9Sstevel@tonic-gate cmd_t *cmd; 3959*7c478bd9Sstevel@tonic-gate 3960*7c478bd9Sstevel@tonic-gate if (!interactive_mode && !cmd_file_mode) { 3961*7c478bd9Sstevel@tonic-gate /* 3962*7c478bd9Sstevel@tonic-gate * If we're not in interactive mode, and we're not in command 3963*7c478bd9Sstevel@tonic-gate * file mode, then we must be in commands-from-the-command-line 3964*7c478bd9Sstevel@tonic-gate * mode. As such, we can't loop back and ask for more input. 3965*7c478bd9Sstevel@tonic-gate * It was OK to prompt for such things as whether or not to 3966*7c478bd9Sstevel@tonic-gate * really delete a zone in the command handler called from 3967*7c478bd9Sstevel@tonic-gate * yyparse() above, but "really quit?" makes no sense in this 3968*7c478bd9Sstevel@tonic-gate * context. So disable prompting. 3969*7c478bd9Sstevel@tonic-gate */ 3970*7c478bd9Sstevel@tonic-gate ok_to_prompt = FALSE; 3971*7c478bd9Sstevel@tonic-gate } 3972*7c478bd9Sstevel@tonic-gate if (!global_scope) { 3973*7c478bd9Sstevel@tonic-gate if (!time_to_exit) { 3974*7c478bd9Sstevel@tonic-gate /* 3975*7c478bd9Sstevel@tonic-gate * Just print a simple error message in the -1 case, 3976*7c478bd9Sstevel@tonic-gate * since exit_func() already handles that case, and 3977*7c478bd9Sstevel@tonic-gate * EOF means we are finished anyway. 3978*7c478bd9Sstevel@tonic-gate */ 3979*7c478bd9Sstevel@tonic-gate answer = ask_yesno(FALSE, 3980*7c478bd9Sstevel@tonic-gate gettext("Resource incomplete; really quit")); 3981*7c478bd9Sstevel@tonic-gate if (answer == -1) { 3982*7c478bd9Sstevel@tonic-gate zerr(gettext("Resource incomplete.")); 3983*7c478bd9Sstevel@tonic-gate return (Z_ERR); 3984*7c478bd9Sstevel@tonic-gate } 3985*7c478bd9Sstevel@tonic-gate if (answer != 1) { 3986*7c478bd9Sstevel@tonic-gate yyin = stdin; 3987*7c478bd9Sstevel@tonic-gate return (Z_REPEAT); 3988*7c478bd9Sstevel@tonic-gate } 3989*7c478bd9Sstevel@tonic-gate } else { 3990*7c478bd9Sstevel@tonic-gate saw_error = TRUE; 3991*7c478bd9Sstevel@tonic-gate } 3992*7c478bd9Sstevel@tonic-gate } 3993*7c478bd9Sstevel@tonic-gate /* 3994*7c478bd9Sstevel@tonic-gate * Make sure we tried something and that the handle checks 3995*7c478bd9Sstevel@tonic-gate * out, or we would get a false error trying to commit. 3996*7c478bd9Sstevel@tonic-gate */ 3997*7c478bd9Sstevel@tonic-gate if (need_to_commit && zonecfg_check_handle(handle) == Z_OK) { 3998*7c478bd9Sstevel@tonic-gate if ((cmd = alloc_cmd()) == NULL) { 3999*7c478bd9Sstevel@tonic-gate zone_perror(zone, Z_NOMEM, TRUE); 4000*7c478bd9Sstevel@tonic-gate return (Z_ERR); 4001*7c478bd9Sstevel@tonic-gate } 4002*7c478bd9Sstevel@tonic-gate cmd->cmd_argc = 0; 4003*7c478bd9Sstevel@tonic-gate cmd->cmd_argv[0] = NULL; 4004*7c478bd9Sstevel@tonic-gate commit_func(cmd); 4005*7c478bd9Sstevel@tonic-gate free_cmd(cmd); 4006*7c478bd9Sstevel@tonic-gate /* 4007*7c478bd9Sstevel@tonic-gate * need_to_commit will get set back to FALSE if the 4008*7c478bd9Sstevel@tonic-gate * configuration is saved successfully. 4009*7c478bd9Sstevel@tonic-gate */ 4010*7c478bd9Sstevel@tonic-gate if (need_to_commit) { 4011*7c478bd9Sstevel@tonic-gate if (force_exit) { 4012*7c478bd9Sstevel@tonic-gate zerr(gettext("Configuration not saved.")); 4013*7c478bd9Sstevel@tonic-gate return (Z_ERR); 4014*7c478bd9Sstevel@tonic-gate } 4015*7c478bd9Sstevel@tonic-gate answer = ask_yesno(FALSE, 4016*7c478bd9Sstevel@tonic-gate gettext("Configuration not saved; really quit")); 4017*7c478bd9Sstevel@tonic-gate if (answer == -1) { 4018*7c478bd9Sstevel@tonic-gate zerr(gettext("Configuration not saved.")); 4019*7c478bd9Sstevel@tonic-gate return (Z_ERR); 4020*7c478bd9Sstevel@tonic-gate } 4021*7c478bd9Sstevel@tonic-gate if (answer != 1) { 4022*7c478bd9Sstevel@tonic-gate time_to_exit = FALSE; 4023*7c478bd9Sstevel@tonic-gate yyin = stdin; 4024*7c478bd9Sstevel@tonic-gate return (Z_REPEAT); 4025*7c478bd9Sstevel@tonic-gate } 4026*7c478bd9Sstevel@tonic-gate } 4027*7c478bd9Sstevel@tonic-gate } 4028*7c478bd9Sstevel@tonic-gate return ((need_to_commit || saw_error) ? Z_ERR : Z_OK); 4029*7c478bd9Sstevel@tonic-gate } 4030*7c478bd9Sstevel@tonic-gate 4031*7c478bd9Sstevel@tonic-gate /* 4032*7c478bd9Sstevel@tonic-gate * read_input() is the driver of this program. It is a wrapper around 4033*7c478bd9Sstevel@tonic-gate * yyparse(), printing appropriate prompts when needed, checking for 4034*7c478bd9Sstevel@tonic-gate * exit conditions and reacting appropriately [the latter in its cleanup() 4035*7c478bd9Sstevel@tonic-gate * helper function]. 4036*7c478bd9Sstevel@tonic-gate * 4037*7c478bd9Sstevel@tonic-gate * Like most zonecfg functions, it returns Z_OK or Z_ERR, *or* Z_REPEAT 4038*7c478bd9Sstevel@tonic-gate * so do_interactive() knows that we are not really done (i.e, we asked 4039*7c478bd9Sstevel@tonic-gate * the user if we should really quit and the user said no). 4040*7c478bd9Sstevel@tonic-gate */ 4041*7c478bd9Sstevel@tonic-gate static int 4042*7c478bd9Sstevel@tonic-gate read_input() 4043*7c478bd9Sstevel@tonic-gate { 4044*7c478bd9Sstevel@tonic-gate bool yyin_is_a_tty = isatty(fileno(yyin)); 4045*7c478bd9Sstevel@tonic-gate /* 4046*7c478bd9Sstevel@tonic-gate * The prompt is "e:z> " or "e:z:r> " where e is execname, z is zone 4047*7c478bd9Sstevel@tonic-gate * and r is resource_scope: 5 is for the two ":"s + "> " + terminator. 4048*7c478bd9Sstevel@tonic-gate */ 4049*7c478bd9Sstevel@tonic-gate char prompt[MAXPATHLEN + ZONENAME_MAX + MAX_RT_STRLEN + 5], *line; 4050*7c478bd9Sstevel@tonic-gate 4051*7c478bd9Sstevel@tonic-gate /* yyin should have been set to the appropriate (FILE *) if not stdin */ 4052*7c478bd9Sstevel@tonic-gate newline_terminated = TRUE; 4053*7c478bd9Sstevel@tonic-gate for (;;) { 4054*7c478bd9Sstevel@tonic-gate if (yyin_is_a_tty) { 4055*7c478bd9Sstevel@tonic-gate if (newline_terminated) { 4056*7c478bd9Sstevel@tonic-gate if (global_scope) 4057*7c478bd9Sstevel@tonic-gate (void) snprintf(prompt, sizeof (prompt), 4058*7c478bd9Sstevel@tonic-gate "%s:%s> ", execname, zone); 4059*7c478bd9Sstevel@tonic-gate else 4060*7c478bd9Sstevel@tonic-gate (void) snprintf(prompt, sizeof (prompt), 4061*7c478bd9Sstevel@tonic-gate "%s:%s:%s> ", execname, zone, 4062*7c478bd9Sstevel@tonic-gate rt_to_str(resource_scope)); 4063*7c478bd9Sstevel@tonic-gate } 4064*7c478bd9Sstevel@tonic-gate /* 4065*7c478bd9Sstevel@tonic-gate * If the user hits ^C then we want to catch it and 4066*7c478bd9Sstevel@tonic-gate * start over. If the user hits EOF then we want to 4067*7c478bd9Sstevel@tonic-gate * bail out. 4068*7c478bd9Sstevel@tonic-gate */ 4069*7c478bd9Sstevel@tonic-gate line = gl_get_line(gl, prompt, NULL, -1); 4070*7c478bd9Sstevel@tonic-gate if (gl_return_status(gl) == GLR_SIGNAL) { 4071*7c478bd9Sstevel@tonic-gate gl_abandon_line(gl); 4072*7c478bd9Sstevel@tonic-gate continue; 4073*7c478bd9Sstevel@tonic-gate } 4074*7c478bd9Sstevel@tonic-gate if (line == NULL) 4075*7c478bd9Sstevel@tonic-gate break; 4076*7c478bd9Sstevel@tonic-gate (void) string_to_yyin(line); 4077*7c478bd9Sstevel@tonic-gate while (!feof(yyin)) 4078*7c478bd9Sstevel@tonic-gate yyparse(); 4079*7c478bd9Sstevel@tonic-gate } else { 4080*7c478bd9Sstevel@tonic-gate yyparse(); 4081*7c478bd9Sstevel@tonic-gate } 4082*7c478bd9Sstevel@tonic-gate /* Bail out on an error in command file mode. */ 4083*7c478bd9Sstevel@tonic-gate if (saw_error && cmd_file_mode && !interactive_mode) 4084*7c478bd9Sstevel@tonic-gate time_to_exit = TRUE; 4085*7c478bd9Sstevel@tonic-gate if (time_to_exit || (!yyin_is_a_tty && feof(yyin))) 4086*7c478bd9Sstevel@tonic-gate break; 4087*7c478bd9Sstevel@tonic-gate } 4088*7c478bd9Sstevel@tonic-gate return (cleanup()); 4089*7c478bd9Sstevel@tonic-gate } 4090*7c478bd9Sstevel@tonic-gate 4091*7c478bd9Sstevel@tonic-gate /* 4092*7c478bd9Sstevel@tonic-gate * This function is used in the zonecfg-interactive-mode scenario: it just 4093*7c478bd9Sstevel@tonic-gate * calls read_input() until we are done. 4094*7c478bd9Sstevel@tonic-gate */ 4095*7c478bd9Sstevel@tonic-gate 4096*7c478bd9Sstevel@tonic-gate static int 4097*7c478bd9Sstevel@tonic-gate do_interactive(void) 4098*7c478bd9Sstevel@tonic-gate { 4099*7c478bd9Sstevel@tonic-gate int err; 4100*7c478bd9Sstevel@tonic-gate 4101*7c478bd9Sstevel@tonic-gate interactive_mode = TRUE; 4102*7c478bd9Sstevel@tonic-gate if (!read_only_mode) { 4103*7c478bd9Sstevel@tonic-gate /* 4104*7c478bd9Sstevel@tonic-gate * Try to set things up proactively in interactive mode, so 4105*7c478bd9Sstevel@tonic-gate * that if the zone in question does not exist yet, we can 4106*7c478bd9Sstevel@tonic-gate * provide the user with a clue. 4107*7c478bd9Sstevel@tonic-gate */ 4108*7c478bd9Sstevel@tonic-gate (void) initialize(FALSE); 4109*7c478bd9Sstevel@tonic-gate } 4110*7c478bd9Sstevel@tonic-gate do 4111*7c478bd9Sstevel@tonic-gate err = read_input(); 4112*7c478bd9Sstevel@tonic-gate while (err == Z_REPEAT); 4113*7c478bd9Sstevel@tonic-gate return (err); 4114*7c478bd9Sstevel@tonic-gate } 4115*7c478bd9Sstevel@tonic-gate 4116*7c478bd9Sstevel@tonic-gate /* 4117*7c478bd9Sstevel@tonic-gate * cmd_file is slightly more complicated, as it has to open the command file 4118*7c478bd9Sstevel@tonic-gate * and set yyin appropriately. Once that is done, though, it just calls 4119*7c478bd9Sstevel@tonic-gate * read_input(), and only once, since prompting is not possible. 4120*7c478bd9Sstevel@tonic-gate */ 4121*7c478bd9Sstevel@tonic-gate 4122*7c478bd9Sstevel@tonic-gate static int 4123*7c478bd9Sstevel@tonic-gate cmd_file(char *file) 4124*7c478bd9Sstevel@tonic-gate { 4125*7c478bd9Sstevel@tonic-gate FILE *infile; 4126*7c478bd9Sstevel@tonic-gate int err; 4127*7c478bd9Sstevel@tonic-gate struct stat statbuf; 4128*7c478bd9Sstevel@tonic-gate bool using_real_file = (strcmp(file, "-") != 0); 4129*7c478bd9Sstevel@tonic-gate 4130*7c478bd9Sstevel@tonic-gate if (using_real_file) { 4131*7c478bd9Sstevel@tonic-gate /* 4132*7c478bd9Sstevel@tonic-gate * zerr() prints a line number in cmd_file_mode, which we do 4133*7c478bd9Sstevel@tonic-gate * not want here, so temporarily unset it. 4134*7c478bd9Sstevel@tonic-gate */ 4135*7c478bd9Sstevel@tonic-gate cmd_file_mode = FALSE; 4136*7c478bd9Sstevel@tonic-gate if ((infile = fopen(file, "r")) == NULL) { 4137*7c478bd9Sstevel@tonic-gate zerr(gettext("could not open file %s: %s"), 4138*7c478bd9Sstevel@tonic-gate file, strerror(errno)); 4139*7c478bd9Sstevel@tonic-gate return (Z_ERR); 4140*7c478bd9Sstevel@tonic-gate } 4141*7c478bd9Sstevel@tonic-gate if ((err = fstat(fileno(infile), &statbuf)) != 0) { 4142*7c478bd9Sstevel@tonic-gate zerr(gettext("could not stat file %s: %s"), 4143*7c478bd9Sstevel@tonic-gate file, strerror(errno)); 4144*7c478bd9Sstevel@tonic-gate err = Z_ERR; 4145*7c478bd9Sstevel@tonic-gate goto done; 4146*7c478bd9Sstevel@tonic-gate } 4147*7c478bd9Sstevel@tonic-gate if (!S_ISREG(statbuf.st_mode)) { 4148*7c478bd9Sstevel@tonic-gate zerr(gettext("%s is not a regular file."), file); 4149*7c478bd9Sstevel@tonic-gate err = Z_ERR; 4150*7c478bd9Sstevel@tonic-gate goto done; 4151*7c478bd9Sstevel@tonic-gate } 4152*7c478bd9Sstevel@tonic-gate yyin = infile; 4153*7c478bd9Sstevel@tonic-gate cmd_file_mode = TRUE; 4154*7c478bd9Sstevel@tonic-gate ok_to_prompt = FALSE; 4155*7c478bd9Sstevel@tonic-gate } else { 4156*7c478bd9Sstevel@tonic-gate /* 4157*7c478bd9Sstevel@tonic-gate * "-f -" is essentially the same as interactive mode, 4158*7c478bd9Sstevel@tonic-gate * so treat it that way. 4159*7c478bd9Sstevel@tonic-gate */ 4160*7c478bd9Sstevel@tonic-gate interactive_mode = TRUE; 4161*7c478bd9Sstevel@tonic-gate } 4162*7c478bd9Sstevel@tonic-gate /* Z_REPEAT is for interactive mode; treat it like Z_ERR here. */ 4163*7c478bd9Sstevel@tonic-gate if ((err = read_input()) == Z_REPEAT) 4164*7c478bd9Sstevel@tonic-gate err = Z_ERR; 4165*7c478bd9Sstevel@tonic-gate done: 4166*7c478bd9Sstevel@tonic-gate if (using_real_file) 4167*7c478bd9Sstevel@tonic-gate (void) fclose(infile); 4168*7c478bd9Sstevel@tonic-gate return (err); 4169*7c478bd9Sstevel@tonic-gate } 4170*7c478bd9Sstevel@tonic-gate 4171*7c478bd9Sstevel@tonic-gate /* 4172*7c478bd9Sstevel@tonic-gate * Since yacc is based on reading from a (FILE *) whereas what we get from 4173*7c478bd9Sstevel@tonic-gate * the command line is in argv format, we need to convert when the user 4174*7c478bd9Sstevel@tonic-gate * gives us commands directly from the command line. That is done here by 4175*7c478bd9Sstevel@tonic-gate * concatenating the argv list into a space-separated string, writing it 4176*7c478bd9Sstevel@tonic-gate * to a temp file, and rewinding the file so yyin can be set to it. Then 4177*7c478bd9Sstevel@tonic-gate * we call read_input(), and only once, since prompting about whether to 4178*7c478bd9Sstevel@tonic-gate * continue or quit would make no sense in this context. 4179*7c478bd9Sstevel@tonic-gate */ 4180*7c478bd9Sstevel@tonic-gate 4181*7c478bd9Sstevel@tonic-gate static int 4182*7c478bd9Sstevel@tonic-gate one_command_at_a_time(int argc, char *argv[]) 4183*7c478bd9Sstevel@tonic-gate { 4184*7c478bd9Sstevel@tonic-gate char *command; 4185*7c478bd9Sstevel@tonic-gate size_t len = 2; /* terminal \n\0 */ 4186*7c478bd9Sstevel@tonic-gate int i, err; 4187*7c478bd9Sstevel@tonic-gate 4188*7c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) 4189*7c478bd9Sstevel@tonic-gate len += strlen(argv[i]) + 1; 4190*7c478bd9Sstevel@tonic-gate if ((command = malloc(len)) == NULL) { 4191*7c478bd9Sstevel@tonic-gate zone_perror(execname, Z_NOMEM, TRUE); 4192*7c478bd9Sstevel@tonic-gate return (Z_ERR); 4193*7c478bd9Sstevel@tonic-gate } 4194*7c478bd9Sstevel@tonic-gate (void) strlcpy(command, argv[0], len); 4195*7c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 4196*7c478bd9Sstevel@tonic-gate (void) strlcat(command, " ", len); 4197*7c478bd9Sstevel@tonic-gate (void) strlcat(command, argv[i], len); 4198*7c478bd9Sstevel@tonic-gate } 4199*7c478bd9Sstevel@tonic-gate (void) strlcat(command, "\n", len); 4200*7c478bd9Sstevel@tonic-gate err = string_to_yyin(command); 4201*7c478bd9Sstevel@tonic-gate free(command); 4202*7c478bd9Sstevel@tonic-gate if (err != Z_OK) 4203*7c478bd9Sstevel@tonic-gate return (err); 4204*7c478bd9Sstevel@tonic-gate while (!feof(yyin)) 4205*7c478bd9Sstevel@tonic-gate yyparse(); 4206*7c478bd9Sstevel@tonic-gate return (cleanup()); 4207*7c478bd9Sstevel@tonic-gate } 4208*7c478bd9Sstevel@tonic-gate 4209*7c478bd9Sstevel@tonic-gate static char * 4210*7c478bd9Sstevel@tonic-gate get_execbasename(char *execfullname) 4211*7c478bd9Sstevel@tonic-gate { 4212*7c478bd9Sstevel@tonic-gate char *last_slash, *execbasename; 4213*7c478bd9Sstevel@tonic-gate 4214*7c478bd9Sstevel@tonic-gate /* guard against '/' at end of command invocation */ 4215*7c478bd9Sstevel@tonic-gate for (;;) { 4216*7c478bd9Sstevel@tonic-gate last_slash = strrchr(execfullname, '/'); 4217*7c478bd9Sstevel@tonic-gate if (last_slash == NULL) { 4218*7c478bd9Sstevel@tonic-gate execbasename = execfullname; 4219*7c478bd9Sstevel@tonic-gate break; 4220*7c478bd9Sstevel@tonic-gate } else { 4221*7c478bd9Sstevel@tonic-gate execbasename = last_slash + 1; 4222*7c478bd9Sstevel@tonic-gate if (*execbasename == '\0') { 4223*7c478bd9Sstevel@tonic-gate *last_slash = '\0'; 4224*7c478bd9Sstevel@tonic-gate continue; 4225*7c478bd9Sstevel@tonic-gate } 4226*7c478bd9Sstevel@tonic-gate break; 4227*7c478bd9Sstevel@tonic-gate } 4228*7c478bd9Sstevel@tonic-gate } 4229*7c478bd9Sstevel@tonic-gate return (execbasename); 4230*7c478bd9Sstevel@tonic-gate } 4231*7c478bd9Sstevel@tonic-gate 4232*7c478bd9Sstevel@tonic-gate static void 4233*7c478bd9Sstevel@tonic-gate validate_zone_name() 4234*7c478bd9Sstevel@tonic-gate { 4235*7c478bd9Sstevel@tonic-gate regex_t reg; 4236*7c478bd9Sstevel@tonic-gate char *locale = NULL, locale_buf[MAXPATHLEN]; 4237*7c478bd9Sstevel@tonic-gate 4238*7c478bd9Sstevel@tonic-gate if (strcmp(zone, GLOBAL_ZONENAME) == 0) 4239*7c478bd9Sstevel@tonic-gate goto err; 4240*7c478bd9Sstevel@tonic-gate 4241*7c478bd9Sstevel@tonic-gate /* 4242*7c478bd9Sstevel@tonic-gate * The regex(5) functions below are locale-sensitive, so save the 4243*7c478bd9Sstevel@tonic-gate * user's locale, then set it to "C" for the regex's, and restore 4244*7c478bd9Sstevel@tonic-gate * it afterwards. 4245*7c478bd9Sstevel@tonic-gate */ 4246*7c478bd9Sstevel@tonic-gate if ((locale = setlocale(LC_ALL, NULL)) != NULL) { 4247*7c478bd9Sstevel@tonic-gate (void) strlcpy(locale_buf, locale, sizeof (locale_buf)); 4248*7c478bd9Sstevel@tonic-gate locale = locale_buf; 4249*7c478bd9Sstevel@tonic-gate } 4250*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "C"); 4251*7c478bd9Sstevel@tonic-gate if (regcomp(®, "^" ZONENAME_REGEXP "$", REG_EXTENDED|REG_NOSUB) != 0) 4252*7c478bd9Sstevel@tonic-gate goto err; 4253*7c478bd9Sstevel@tonic-gate 4254*7c478bd9Sstevel@tonic-gate if (regexec(®, zone, (size_t)0, NULL, 0) != 0) 4255*7c478bd9Sstevel@tonic-gate goto err; 4256*7c478bd9Sstevel@tonic-gate 4257*7c478bd9Sstevel@tonic-gate regfree(®); 4258*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, locale); 4259*7c478bd9Sstevel@tonic-gate return; 4260*7c478bd9Sstevel@tonic-gate 4261*7c478bd9Sstevel@tonic-gate err: 4262*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, locale); 4263*7c478bd9Sstevel@tonic-gate zone_perror(zone, Z_BOGUS_ZONE_NAME, TRUE); 4264*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_SYNTAX); 4265*7c478bd9Sstevel@tonic-gate exit(Z_USAGE); 4266*7c478bd9Sstevel@tonic-gate } 4267*7c478bd9Sstevel@tonic-gate 4268*7c478bd9Sstevel@tonic-gate int 4269*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 4270*7c478bd9Sstevel@tonic-gate { 4271*7c478bd9Sstevel@tonic-gate int err, arg; 4272*7c478bd9Sstevel@tonic-gate 4273*7c478bd9Sstevel@tonic-gate /* This must be before anything goes to stdout. */ 4274*7c478bd9Sstevel@tonic-gate setbuf(stdout, NULL); 4275*7c478bd9Sstevel@tonic-gate 4276*7c478bd9Sstevel@tonic-gate saw_error = FALSE; 4277*7c478bd9Sstevel@tonic-gate cmd_file_mode = FALSE; 4278*7c478bd9Sstevel@tonic-gate execname = get_execbasename(argv[0]); 4279*7c478bd9Sstevel@tonic-gate 4280*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 4281*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 4282*7c478bd9Sstevel@tonic-gate 4283*7c478bd9Sstevel@tonic-gate if (getzoneid() != GLOBAL_ZONEID) { 4284*7c478bd9Sstevel@tonic-gate zerr(gettext("%s can only be run from the global zone."), 4285*7c478bd9Sstevel@tonic-gate execname); 4286*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 4287*7c478bd9Sstevel@tonic-gate } 4288*7c478bd9Sstevel@tonic-gate 4289*7c478bd9Sstevel@tonic-gate if (argc < 2) { 4290*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_USAGE | HELP_SUBCMDS); 4291*7c478bd9Sstevel@tonic-gate exit(Z_USAGE); 4292*7c478bd9Sstevel@tonic-gate } 4293*7c478bd9Sstevel@tonic-gate if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) { 4294*7c478bd9Sstevel@tonic-gate (void) one_command_at_a_time(argc - 1, &(argv[1])); 4295*7c478bd9Sstevel@tonic-gate exit(Z_OK); 4296*7c478bd9Sstevel@tonic-gate } 4297*7c478bd9Sstevel@tonic-gate 4298*7c478bd9Sstevel@tonic-gate zone = NULL; 4299*7c478bd9Sstevel@tonic-gate while ((arg = getopt(argc, argv, "?f:z:")) != EOF) { 4300*7c478bd9Sstevel@tonic-gate switch (arg) { 4301*7c478bd9Sstevel@tonic-gate case '?': 4302*7c478bd9Sstevel@tonic-gate if (optopt == '?') 4303*7c478bd9Sstevel@tonic-gate usage(TRUE, HELP_USAGE | HELP_SUBCMDS); 4304*7c478bd9Sstevel@tonic-gate else 4305*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_USAGE); 4306*7c478bd9Sstevel@tonic-gate exit(Z_USAGE); 4307*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 4308*7c478bd9Sstevel@tonic-gate case 'f': 4309*7c478bd9Sstevel@tonic-gate cmd_file_name = optarg; 4310*7c478bd9Sstevel@tonic-gate cmd_file_mode = TRUE; 4311*7c478bd9Sstevel@tonic-gate break; 4312*7c478bd9Sstevel@tonic-gate case 'z': 4313*7c478bd9Sstevel@tonic-gate zone = optarg; 4314*7c478bd9Sstevel@tonic-gate break; 4315*7c478bd9Sstevel@tonic-gate default: 4316*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_USAGE); 4317*7c478bd9Sstevel@tonic-gate exit(Z_USAGE); 4318*7c478bd9Sstevel@tonic-gate } 4319*7c478bd9Sstevel@tonic-gate } 4320*7c478bd9Sstevel@tonic-gate 4321*7c478bd9Sstevel@tonic-gate if (optind > argc || zone == NULL) { 4322*7c478bd9Sstevel@tonic-gate usage(FALSE, HELP_USAGE); 4323*7c478bd9Sstevel@tonic-gate exit(Z_USAGE); 4324*7c478bd9Sstevel@tonic-gate } 4325*7c478bd9Sstevel@tonic-gate 4326*7c478bd9Sstevel@tonic-gate validate_zone_name(); 4327*7c478bd9Sstevel@tonic-gate if (zonecfg_access(zone, W_OK) == Z_OK) { 4328*7c478bd9Sstevel@tonic-gate read_only_mode = FALSE; 4329*7c478bd9Sstevel@tonic-gate } else { 4330*7c478bd9Sstevel@tonic-gate read_only_mode = TRUE; 4331*7c478bd9Sstevel@tonic-gate /* skip this message in one-off from command line mode */ 4332*7c478bd9Sstevel@tonic-gate if (optind == argc) 4333*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("WARNING: you do not " 4334*7c478bd9Sstevel@tonic-gate "have write access to this zone's configuration " 4335*7c478bd9Sstevel@tonic-gate "file;\ngoing into read-only mode.\n")); 4336*7c478bd9Sstevel@tonic-gate } 4337*7c478bd9Sstevel@tonic-gate 4338*7c478bd9Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) { 4339*7c478bd9Sstevel@tonic-gate zone_perror(execname, Z_NOMEM, TRUE); 4340*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 4341*7c478bd9Sstevel@tonic-gate } 4342*7c478bd9Sstevel@tonic-gate 4343*7c478bd9Sstevel@tonic-gate /* 4344*7c478bd9Sstevel@tonic-gate * This may get set back to FALSE again in cmd_file() if cmd_file_name 4345*7c478bd9Sstevel@tonic-gate * is a "real" file as opposed to "-" (i.e. meaning use stdin). 4346*7c478bd9Sstevel@tonic-gate */ 4347*7c478bd9Sstevel@tonic-gate if (isatty(STDIN_FILENO)) 4348*7c478bd9Sstevel@tonic-gate ok_to_prompt = TRUE; 4349*7c478bd9Sstevel@tonic-gate if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL) 4350*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 4351*7c478bd9Sstevel@tonic-gate if (gl_customize_completion(gl, NULL, cmd_cpl_fn) != 0) 4352*7c478bd9Sstevel@tonic-gate exit(Z_ERR); 4353*7c478bd9Sstevel@tonic-gate (void) sigset(SIGINT, SIG_IGN); 4354*7c478bd9Sstevel@tonic-gate if (optind == argc) { 4355*7c478bd9Sstevel@tonic-gate if (!cmd_file_mode) 4356*7c478bd9Sstevel@tonic-gate err = do_interactive(); 4357*7c478bd9Sstevel@tonic-gate else 4358*7c478bd9Sstevel@tonic-gate err = cmd_file(cmd_file_name); 4359*7c478bd9Sstevel@tonic-gate } else { 4360*7c478bd9Sstevel@tonic-gate err = one_command_at_a_time(argc - optind, &(argv[optind])); 4361*7c478bd9Sstevel@tonic-gate } 4362*7c478bd9Sstevel@tonic-gate zonecfg_fini_handle(handle); 4363*7c478bd9Sstevel@tonic-gate (void) del_GetLine(gl); 4364*7c478bd9Sstevel@tonic-gate return (err); 4365*7c478bd9Sstevel@tonic-gate } 4366