zonecfg.c revision 27e6fb2101ae37ba3de6dbb1567bf7558ffaccad
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * CDDL HEADER START
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * The contents of this file are subject to the terms of the
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * Common Development and Distribution License (the "License").
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * You may not use this file except in compliance with the License.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * or http://www.opensolaris.org/os/licensing.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * See the License for the specific language governing permissions
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * and limitations under the License.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * When distributing Covered Code, include this CDDL HEADER in each
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * If applicable, add the following below this CDDL HEADER, with the
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * fields enclosed by brackets "[]" replaced with your own identifying
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * information: Portions Copyright [yyyy] [name of copyright owner]
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * CDDL HEADER END
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * Use is subject to license terms.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#pragma ident "%Z%%M% %I% %E% SMI"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * zonecfg is a lex/yacc based command interpreter used to manage zone
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * the grammar (see zonecfg_grammar.y) builds up into commands, some of
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * which takes resources and/or properties as arguments. See the block
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * comments near the end of zonecfg_grammar.y for how the data structures
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * which keep track of these resources and properties are built up.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * The resource/property data structures are inserted into a command
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * structure (see zonecfg.h), which also keeps track of command names,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * miscellaneous arguments, and function handlers. The grammar selects
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * the appropriate function handler, each of which takes a pointer to a
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * command structure as its sole argument, and invokes it. The grammar
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * itself is "entered" (a la the Matrix) by yyparse(), which is called
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * from read_input(), our main driving function. That in turn is called
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * of which is called from main() depending on how the program was invoked.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * The rest of this module consists of the various function handlers and
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * their helper functions. Some of these functions, particularly the
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * X_to_str() functions, which maps command, resource and property numbers
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * to strings, are used quite liberally, as doing so results in a better
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * program w/rt I18N, reducing the need for translation notes.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <sys/mntent.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <sys/varargs.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <sys/sysmacros.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <errno.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <fcntl.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <strings.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <unistd.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <ctype.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <stdlib.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <assert.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <sys/stat.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <zone.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <arpa/inet.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <netdb.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <locale.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <libintl.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <alloca.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <signal.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <wait.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <libtecla.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <libzfs.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <sys/brand.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <libbrand.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <libzonecfg.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include "zonecfg.h"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#endif
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define PAGER "/usr/bin/more"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define EXEC_PREFIX "exec "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define EXEC_LEN (strlen(EXEC_PREFIX))
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistruct help {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi uint_t cmd_num;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi char *cmd_name;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi uint_t flags;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi char *short_usage;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiextern int yyparse(void);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiextern int lex_lineno;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define MAX_LINE_LEN 1024
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define MAX_CMD_HIST 1024
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define MAX_CMD_LEN 1024
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define ONE_MB 1048576
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * Each SHELP_ should be a simple string.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_ADD "add <resource-type>\n\t(global scope)\n" \
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add <property-name> <property-value>\n\t(resource scope)"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_CANCEL "cancel"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_CLEAR "clear <property-name>"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_COMMIT "commit"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_CREATE "create [-F] [ -a <path> | -b | -t <template> ]"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_DELETE "delete [-F]"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_END "end"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_EXIT "exit [-F]"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_EXPORT "export [-f output-file]"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_HELP "help [commands] [syntax] [usage] [<command-name>]"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_INFO "info [<resource-type> [property-name=property-value]*]"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_REMOVE "remove [-F] <resource-type> " \
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "[ <property-name>=<property-value> ]*\n" \
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "\t(global scope)\n" \
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove <property-name> <property-value>\n" \
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "\t(resource scope)"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_REVERT "revert [-F]"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_SELECT "select <resource-type> { <property-name>=" \
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "<property-value> }"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_SET "set <property-name>=<property-value>"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define SHELP_VERIFY "verify"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic struct help helptab[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_ADD, "add", HELP_RES_PROPS, SHELP_ADD, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_CANCEL, "cancel", 0, SHELP_CANCEL, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_CLEAR, "clear", HELP_PROPS, SHELP_CLEAR, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_COMMIT, "commit", 0, SHELP_COMMIT, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_CREATE, "create", 0, SHELP_CREATE, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_DELETE, "delete", 0, SHELP_DELETE, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_END, "end", 0, SHELP_END, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_EXIT, "exit", 0, SHELP_EXIT, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_EXPORT, "export", 0, SHELP_EXPORT, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_HELP, "help", 0, SHELP_HELP },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_INFO, "info", HELP_RES_PROPS, SHELP_INFO, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_REMOVE, "remove", HELP_RES_PROPS, SHELP_REMOVE, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_REVERT, "revert", 0, SHELP_REVERT, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_SELECT, "select", HELP_RES_PROPS, SHELP_SELECT, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_SET, "set", HELP_PROPS, SHELP_SET, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { CMD_VERIFY, "verify", 0, SHELP_VERIFY, },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi { 0 },
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#define MAX_RT_STRLEN 16
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* These *must* match the order of the RT_ define's from zonecfg.h */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char *res_types[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "unknown",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "zonename",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "zonepath",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "autoboot",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "pool",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "fs",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "inherit-pkg-dir",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "net",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "device",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "rctl",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "attr",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "dataset",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "limitpriv",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "bootargs",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "brand",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "dedicated-cpu",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "capped-memory",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXLWPS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXSHMMEM,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXSHMIDS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXMSGIDS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXSEMIDS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_SHARES,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "scheduling-class",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "ip-type",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "capped-cpu",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* These *must* match the order of the PT_ define's from zonecfg.h */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char *prop_types[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "unknown",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "zonename",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "zonepath",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "autoboot",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "pool",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "dir",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "special",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "type",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "options",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "address",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "physical",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "name",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "value",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "match",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "priv",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "limit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "action",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "raw",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "limitpriv",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "bootargs",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "brand",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "ncpus",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "importance",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "swap",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "locked",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_SHARES,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXLWPS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXSHMMEM,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXSHMIDS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXMSGIDS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXSEMIDS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXLOCKEDMEM,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ALIAS_MAXSWAP,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "scheduling-class",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "ip-type",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char *prop_val_types[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "simple",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "complex",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "list",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * The various _cmds[] lists below are for command tab-completion.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * remove has a space afterwards because it has qualifiers; the other commands
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * that have qualifiers (add, select, etc.) don't need a space here because
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * they have their own _cmds[] lists below.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *global_scope_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "commit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "create",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "delete",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "exit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "export",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "help",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "revert",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "select",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "verify",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *add_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add fs",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add inherit-pkg-dir",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add net",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add device",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add rctl",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add attr",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add dataset",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add dedicated-cpu",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add capped-cpu",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add capped-memory",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *clear_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear autoboot",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear pool",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear limitpriv",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear bootargs",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear scheduling-class",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear ip-type",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear " ALIAS_MAXLWPS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear " ALIAS_MAXSHMMEM,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear " ALIAS_MAXSHMIDS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear " ALIAS_MAXMSGIDS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear " ALIAS_MAXSEMIDS,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear " ALIAS_SHARES,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *remove_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove fs ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove inherit-pkg-dir ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove net ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove device ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove rctl ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove attr ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove dataset ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove dedicated-cpu ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove capped-cpu ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove capped-memory ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *select_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "select fs ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "select inherit-pkg-dir ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "select net ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "select device ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "select rctl ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "select attr ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "select dataset ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "select dedicated-cpu",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "select capped-cpu",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "select capped-memory",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *set_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set zonename=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set zonepath=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set brand=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set autoboot=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set pool=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set limitpriv=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set bootargs=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set scheduling-class=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set ip-type=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set " ALIAS_MAXLWPS "=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set " ALIAS_MAXSHMMEM "=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set " ALIAS_MAXSHMIDS "=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set " ALIAS_MAXMSGIDS "=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set " ALIAS_MAXSEMIDS "=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set " ALIAS_SHARES "=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *info_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info fs ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info inherit-pkg-dir ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info net ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info device ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info rctl ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info attr ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info dataset ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info capped-memory",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info dedicated-cpu",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info capped-cpu",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info zonename",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info zonepath",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info autoboot",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info pool",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info limitpriv",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info bootargs",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info brand",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info scheduling-class",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info ip-type",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info max-lwps",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info max-shm-memory",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info max-shm-ids",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info max-msg-ids",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info max-sem-ids",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info cpu-shares",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *fs_res_scope_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add options ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "cancel",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "end",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "exit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "help",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove options ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set dir=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set raw=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set special=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set type=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear raw",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *net_res_scope_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "cancel",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "end",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "exit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "help",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set address=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set physical=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *ipd_res_scope_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "cancel",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "end",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "exit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "help",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set dir=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *device_res_scope_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "cancel",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "end",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "exit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "help",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set match=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *attr_res_scope_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "cancel",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "end",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "exit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "help",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set name=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set type=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set value=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *rctl_res_scope_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "add value ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "cancel",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "end",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "exit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "help",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "remove value ",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set name=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *dataset_res_scope_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "cancel",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "end",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "exit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "help",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set name=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *pset_res_scope_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "cancel",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "end",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "exit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "help",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set ncpus=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set importance=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear importance",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *pcap_res_scope_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "cancel",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "end",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "exit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "help",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set ncpus=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic const char *mcap_res_scope_cmds[] = {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "cancel",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "end",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "exit",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "help",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "info",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set physical=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set swap=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set locked=",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear physical",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear swap",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "clear locked",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi NULL
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* Global variables */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* set early in main(), never modified thereafter, used all over the place */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char *execname;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* set in main(), used all over the place */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic zone_dochandle_t handle;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* used all over the place */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char zone[ZONENAME_MAX];
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char revert_zone[ZONENAME_MAX];
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* global brand operations */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic brand_handle_t brand;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* set in modifying functions, checked in read_input() */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic bool need_to_commit = FALSE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchibool saw_error;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* set in yacc parser, checked in read_input() */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchibool newline_terminated;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* set in main(), checked in lex error handler */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchibool cmd_file_mode;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* set in exit_func(), checked in read_input() */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic bool time_to_exit = FALSE, force_exit = FALSE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* used in short_usage() and zerr() */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char *cmd_file_name = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* checked in read_input() and other places */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic bool ok_to_prompt = FALSE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* set and checked in initialize() */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic bool got_handle = FALSE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* initialized in do_interactive(), checked in initialize() */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic bool interactive_mode;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* set if configuring the global zone */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic bool global_zone = FALSE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* set in main(), checked in multiple places */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic bool read_only_mode;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic bool global_scope = TRUE; /* scope is outer/global or inner/resource */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic int resource_scope; /* should be in the RT_ list from zonecfg.h */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic int end_op = -1; /* operation on end is either add or modify */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiint num_prop_vals; /* for grammar */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * These are for keeping track of resources as they are specified as part of
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * the multi-step process. They should be initialized by add_resource() or
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * select_func() and filled in by add_property() or set_func().
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic struct zone_fstab old_fstab, in_progress_fstab;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic struct zone_fstab old_ipdtab, in_progress_ipdtab;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic struct zone_nwiftab old_nwiftab, in_progress_nwiftab;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic struct zone_devtab old_devtab, in_progress_devtab;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic struct zone_rctltab old_rctltab, in_progress_rctltab;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic struct zone_attrtab old_attrtab, in_progress_attrtab;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic struct zone_dstab old_dstab, in_progress_dstab;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic struct zone_psettab old_psettab, in_progress_psettab;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic struct zone_mcaptab old_mcaptab, in_progress_mcaptab;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic GetLine *gl; /* The gl_get_line() resource object */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic void bytes_to_units(char *str, char *buf, int bufsize);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* Functions begin here */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic bool
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiinitial_match(const char *line1, const char *line2, int word_end)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (word_end <= 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (TRUE);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (strncmp(line1, line2, word_end) == 0);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic int
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiadd_stuff(WordCompletion *cpl, const char *line1, const char **list,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int word_end)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int i, err;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi for (i = 0; list[i] != NULL; i++) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (initial_match(line1, list[i], word_end)) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi err = cpl_add_completion(cpl, line1, 0, word_end,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi list[i] + word_end, "", "");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (err != 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (err);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (0);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* ARGSUSED */
d14abf155341d55053c76eeec58b787a456b753bRobert MustacchiCPL_MATCH_FN(cmd_cpl_fn)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (global_scope) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * The MAX/MIN tests below are to make sure we have at least
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * enough characters to distinguish from other prefixes (MAX)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * but only check MIN(what we have, what we're checking).
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (strncmp(line, "add ", MAX(MIN(word_end, 4), 1)) == 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, add_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (strncmp(line, "clear ", MAX(MIN(word_end, 6), 2)) == 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, clear_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (strncmp(line, "select ", MAX(MIN(word_end, 7), 3)) == 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, select_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (strncmp(line, "set ", MAX(MIN(word_end, 4), 3)) == 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, set_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (strncmp(line, "remove ", MAX(MIN(word_end, 7), 1)) == 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, remove_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (strncmp(line, "info ", MAX(MIN(word_end, 5), 1)) == 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, info_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, global_scope_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi switch (resource_scope) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_FS:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_IPD:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, ipd_res_scope_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_NET:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_DEVICE:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_RCTL:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_ATTR:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_DATASET:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_DCPU:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, pset_res_scope_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_PCAP:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_MCAP:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (0);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * For the main CMD_func() functions below, several of them call getopt()
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * then check optind against argc to make sure an extra parameter was not
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * passed in. The reason this is not caught in the grammar is that the
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * grammar just checks for a miscellaneous TOKEN, which is *expected* to
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * be "-F" (for example), but could be anything. So (for example) this
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * check will prevent "create bogus".
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchicmd_t *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchialloc_cmd(void)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (calloc(1, sizeof (cmd_t)));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchivoid
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchifree_cmd(cmd_t *cmd)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int i;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi for (i = 0; i < MAX_EQ_PROP_PAIRS; i++)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (cmd->cmd_property_ptr[i] != NULL) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi property_value_ptr_t pp = cmd->cmd_property_ptr[i];
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi switch (pp->pv_type) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case PROP_VAL_SIMPLE:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(pp->pv_simple);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case PROP_VAL_COMPLEX:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free_complex(pp->pv_complex);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case PROP_VAL_LIST:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free_list(pp->pv_list);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi for (i = 0; i < cmd->cmd_argc; i++)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(cmd->cmd_argv[i]);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(cmd);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchicomplex_property_ptr_t
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchialloc_complex(void)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (calloc(1, sizeof (complex_property_t)));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchivoid
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchifree_complex(complex_property_ptr_t complex)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (complex == NULL)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free_complex(complex->cp_next);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (complex->cp_value != NULL)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(complex->cp_value);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(complex);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchilist_property_ptr_t
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchialloc_list(void)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (calloc(1, sizeof (list_property_t)));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchivoid
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchifree_list(list_property_ptr_t list)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (list == NULL)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (list->lp_simple != NULL)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(list->lp_simple);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free_complex(list->lp_complex);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free_list(list->lp_next);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(list);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchivoid
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchifree_outer_list(list_property_ptr_t list)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (list == NULL)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free_outer_list(list->lp_next);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(list);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic struct zone_rctlvaltab *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchialloc_rctlvaltab(void)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (calloc(1, sizeof (struct zone_rctlvaltab)));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchirt_to_str(int res_type)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(res_type >= RT_MIN && res_type <= RT_MAX);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (res_types[res_type]);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchipt_to_str(int prop_type)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (prop_types[prop_type]);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchipvt_to_str(int pv_type)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(pv_type >= PROP_VAL_MIN && pv_type <= PROP_VAL_MAX);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (prop_val_types[pv_type]);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchicmd_to_str(int cmd_num)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (helptab[cmd_num].cmd_name);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * This is a separate function rather than a set of define's because of the
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * gettext() wrapping.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * TRANSLATION_NOTE
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * Each string below should have \t follow \n whenever needed; the
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * initial \t and the terminal \n will be provided by the calling function.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic char *
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchilong_help(int cmd_num)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi static char line[1024]; /* arbitrary large amount */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi switch (cmd_num) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_HELP:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Prints help message."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_CREATE:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) snprintf(line, sizeof (line),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("Creates a configuration for the "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "specified zone. %s should be\n\tused to "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "begin configuring a new zone. If overwriting an "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "existing\n\tconfiguration, the -F flag can be "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "used to force the action. If\n\t-t template is "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "given, creates a configuration identical to the\n"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "\tspecified template, except that the zone name "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "is changed from\n\ttemplate to zonename. '%s -a' "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "creates a configuration from a\n\tdetached "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "zonepath. '%s -b' results in a blank "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "configuration.\n\t'%s' with no arguments applies "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "the Sun default settings."),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (line);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_EXIT:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Exits the program. The -F flag can "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "be used to force the action."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_EXPORT:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Prints configuration to standard "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "output, or to output-file if\n\tspecified, in "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "a form suitable for use in a command-file."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_ADD:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Add specified resource to "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "configuration."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_DELETE:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Deletes the specified zone. The -F "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "flag can be used to force the\n\taction."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_REMOVE:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Remove specified resource from "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "configuration. The -F flag can be used\n\tto "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "force the action."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_SELECT:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) snprintf(line, sizeof (line),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("Selects a resource to modify. "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "Resource modification is completed\n\twith the "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "command \"%s\". The property name/value pairs "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "must uniquely\n\tidentify a resource. Note that "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "the curly braces ('{', '}') mean one\n\tor more "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "of whatever is between them."),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_END));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (line);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_SET:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Sets property values."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_CLEAR:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Clears property values."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_INFO:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Displays information about the "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "current configuration. If resource\n\ttype is "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "specified, displays only information about "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "resources of\n\tthe relevant type. If resource "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "id is specified, displays only\n\tinformation "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "about that resource."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_VERIFY:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Verifies current configuration "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "for correctness (some resource types\n\thave "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "required properties)."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_COMMIT:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) snprintf(line, sizeof (line),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("Commits current configuration. "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "Configuration must be committed to\n\tbe used by "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "%s. Until the configuration is committed, "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "changes \n\tcan be removed with the %s "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "command. This operation is\n\tattempted "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "automatically upon completion of a %s "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "session."), "zoneadm", cmd_to_str(CMD_REVERT),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "zonecfg");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (line);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_REVERT:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Reverts configuration back to the "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "last committed state. The -F flag\n\tcan be "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "used to force the action."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_CANCEL:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Cancels resource/property "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "specification."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case CMD_END:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (gettext("Ends resource/property "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "specification."));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* NOTREACHED */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (NULL);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * Called with verbose TRUE when help is explicitly requested, FALSE for
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * unexpected errors.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchivoid
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiusage(bool verbose, uint_t flags)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi FILE *fp = verbose ? stdout : stderr, *newfp;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi bool need_to_close = FALSE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi char *pager;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int i;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* don't page error output */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (verbose && interactive_mode) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if ((pager = getenv("PAGER")) == NULL)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pager = PAGER;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if ((newfp = popen(pager, "w")) != NULL) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi need_to_close = TRUE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi fp = newfp;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (flags & HELP_META) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("More help is available for the "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "following:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\n\tcommands ('%s commands')\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_HELP));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\tsyntax ('%s syntax')\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_HELP));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\tusage ('%s usage')\n\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_HELP));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("You may also obtain help on any "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "command by typing '%s <command-name>.'\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_HELP));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (flags & HELP_RES_SCOPE) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi switch (resource_scope) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_FS:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("The '%s' resource scope is "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "used to configure a file-system.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(resource_scope));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("Valid commands:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_DIR), gettext("<path>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_SPECIAL), gettext("<path>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_RAW), gettext("<raw-device>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_TYPE), gettext("<file-system type>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s %s\n", cmd_to_str(CMD_ADD),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_OPTIONS),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("<file-system options>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s %s\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_REMOVE), pt_to_str(PT_OPTIONS),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("<file-system options>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("Consult the file-system "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "specific manual page, such as mount_ufs(1M), "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "for\ndetails about file-system options. Note "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "that any file-system options with an\nembedded "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "'=' character must be enclosed in double quotes, "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /*CSTYLED*/
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "such as \"%s=5\".\n"), MNTOPT_RETRY);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_IPD:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("The '%s' resource scope is "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "used to configure a directory\ninherited from the "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "global zone into a non-global zone in read-only "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "mode.\n"), rt_to_str(resource_scope));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("Valid commands:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_DIR), gettext("<path>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_NET:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("The '%s' resource scope is "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "used to configure a network interface.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(resource_scope));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("Valid commands:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_ADDRESS), gettext("<IP-address>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_PHYSICAL), gettext("<interface>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("See ifconfig(1M) for "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "details of the <interface> string.\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("%s %s is valid if the %s "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "property is set to %s, otherwise it must not be "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "set.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_IPTYPE), "shared");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_DEVICE:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("The '%s' resource scope is "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "used to configure a device node.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(resource_scope));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("Valid commands:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_MATCH), gettext("<device-path>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_RCTL:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("The '%s' resource scope is "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "used to configure a resource control.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(resource_scope));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("Valid commands:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_NAME), gettext("<string>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_PRIV), gettext("<priv-value>"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_LIMIT), gettext("<number>"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_ACTION), gettext("<action-value>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_REMOVE), pt_to_str(PT_VALUE),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_PRIV), gettext("<priv-value>"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_LIMIT), gettext("<number>"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_ACTION), gettext("<action-value>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "%s\n\t%s := privileged\n"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "\t%s := none | deny\n", gettext("Where"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("<priv-value>"), gettext("<action-value>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_ATTR:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("The '%s' resource scope is "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "used to configure a generic attribute.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(resource_scope));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("Valid commands:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_NAME), gettext("<name>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=boolean\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=true | false\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_SET), pt_to_str(PT_VALUE));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("or\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=int\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_TYPE));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_VALUE), gettext("<integer>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("or\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=string\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_VALUE), gettext("<string>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("or\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=uint\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_VALUE), gettext("<unsigned integer>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_DATASET:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("The '%s' resource scope is "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "used to export ZFS datasets.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(resource_scope));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("Valid commands:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_NAME), gettext("<name>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_DCPU:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("The '%s' resource scope "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "configures the 'pools' facility to dedicate\na "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "subset of the system's processors to this zone "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "while it is running.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(resource_scope));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("Valid commands:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_NCPUS),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("<unsigned integer | range>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_IMPORTANCE),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("<unsigned integer>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_PCAP:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("The '%s' resource scope is "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "used to set an upper limit (a cap) on the\n"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "percentage of CPU that can be used by this zone. "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "A '%s' value of 1\ncorresponds to one cpu. The "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "value can be set higher than 1, up to the total\n"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "number of CPUs on the system. The value can "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "also be less than 1,\nrepresenting a fraction of "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "a cpu.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(resource_scope), pt_to_str(PT_NCPUS));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("Valid commands:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_NCPUS), gettext("<unsigned decimal>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case RT_MCAP:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("The '%s' resource scope is "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "used to set an upper limit (a cap) on the\n"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "amount of physical memory, swap space and locked "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "memory that can be used by\nthis zone.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(resource_scope));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("Valid commands:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_PHYSICAL),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("<qualified unsigned decimal>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_SWAP),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("<qualified unsigned decimal>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_LOCKED),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("<qualified unsigned decimal>"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi break;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("And from any resource scope, you "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "can:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("(to conclude this operation)"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("(to cancel this operation)"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("(to exit the zonecfg utility)"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (flags & HELP_USAGE) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi execname, cmd_to_str(CMD_HELP));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi execname, gettext("interactive"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi execname);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (flags & HELP_SUBCMDS) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "%s:\n\n", gettext("Commands"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi for (i = 0; i <= CMD_MAX; i++) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "%s\n", helptab[i].short_usage);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (verbose)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\n\n", long_help(i));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (flags & HELP_SYNTAX) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (!verbose)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\n");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("\t(except the reserved words "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "'%s' and anything starting with '%s')\n"), "global",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "SUNW");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("\tName must be less than %d characters.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi ZONENAME_MAX);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (verbose)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\n");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (flags & HELP_NETADDR) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("\n<net-addr> :="));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "IPv6 address syntax.\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("<IPv6-prefix-length> := [0-128]\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (flags & HELP_RESOURCES) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s | %s |\n\t"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "%s | %s | %s | %s\n\n",
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("resource type"), rt_to_str(RT_FS),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(RT_IPD), rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi rt_to_str(RT_PCAP), rt_to_str(RT_MCAP));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (flags & HELP_PROPS) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, gettext("For resource type ... there are "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "property types ...:\n"));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_ZONENAME));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_ZONEPATH));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_BRAND));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_AUTOBOOT));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_BOOTARGS));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_POOL));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_LIMITPRIV));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_SCHED));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_IPTYPE));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_MAXLWPS));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_MAXSHMMEM));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_MAXSHMIDS));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_MAXMSGIDS));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_MAXSEMIDS));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_SHARES));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s\n", rt_to_str(RT_FS),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_DIR), pt_to_str(PT_SPECIAL),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_RAW), pt_to_str(PT_TYPE),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_OPTIONS));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_IPD),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_DIR));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_NET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_ADDRESS), pt_to_str(PT_PHYSICAL));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_MATCH));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_VALUE));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_NAME));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_NCPUS));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi pt_to_str(PT_LOCKED));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (need_to_close)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) pclose(fp);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* PRINTFLIKE1 */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic void
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchizerr(const char *fmt, ...)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi va_list alist;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi static int last_lineno;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* lex_lineno has already been incremented in the lexer; compensate */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (cmd_file_mode && lex_lineno > last_lineno) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (strcmp(cmd_file_name, "-") == 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(stderr, gettext("On line %d:\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi lex_lineno - 1);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi else
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(stderr, gettext("On line %d of %s:\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi lex_lineno - 1, cmd_file_name);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi last_lineno = lex_lineno;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi va_start(alist, fmt);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) vfprintf(stderr, fmt, alist);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(stderr, "\n");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi va_end(alist);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic void
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchizone_perror(char *prefix, int err, bool set_saw)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zerr("%s: %s", prefix, zonecfg_strerror(err));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (set_saw)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi saw_error = TRUE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * zone_perror() expects a single string, but for remove and select
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * we have both the command and the resource type, so this wrapper
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * function serves the same purpose in a slightly different way.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic void
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiz_cmd_rt_perror(int cmd_num, int res_num, int err, bool set_saw)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zonecfg_strerror(err));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (set_saw)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi saw_error = TRUE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic int
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiinitialize(bool handle_expected)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int err;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi char brandname[MAXNAMELEN];
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (zonecfg_check_handle(handle) != Z_OK) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi got_handle = TRUE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (zonecfg_get_brand(handle, brandname,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi sizeof (brandname)) != Z_OK) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zerr("Zone %s is inconsistent: missing "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "brand attribute", zone);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi exit(Z_ERR);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if ((brand = brand_open(brandname)) == NULL) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zerr("Zone %s uses non-existent brand \"%s\"."
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi " Unable to continue", zone, brandname);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi exit(Z_ERR);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi } else if (global_zone && err == Z_NO_ZONE && !got_handle &&
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi !read_only_mode) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * We implicitly create the global zone config if it
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * doesn't exist.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zone_dochandle_t tmphandle;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if ((tmphandle = zonecfg_init_handle()) == NULL) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zone_perror(execname, Z_NOMEM, TRUE);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi exit(Z_ERR);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi err = zonecfg_get_template_handle("SUNWblank", zone,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi tmphandle);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (err != Z_OK) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zonecfg_fini_handle(tmphandle);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zone_perror("SUNWblank", err, TRUE);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (err);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi need_to_commit = TRUE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zonecfg_fini_handle(handle);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi handle = tmphandle;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi got_handle = TRUE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi } else {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zone_perror(zone, err, handle_expected || got_handle);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (err == Z_NO_ZONE && !got_handle &&
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi interactive_mode && !read_only_mode)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) printf(gettext("Use '%s' to begin "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "configuring a new zone.\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi cmd_to_str(CMD_CREATE));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (err);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (Z_OK);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic bool
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistate_atleast(zone_state_t state)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zone_state_t state_num;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int err;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if ((err = zone_get_state(zone, &state_num)) != Z_OK) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* all states are greater than "non-existent" */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (err == Z_NO_ZONE)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (B_FALSE);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi zerr(gettext("Unexpectedly failed to determine state "
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "of zone %s: %s"), zone, zonecfg_strerror(err));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi exit(Z_ERR);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (state_num >= state);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * short_usage() is for bad syntax: getopt() issues, too many arguments, etc.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchivoid
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchishort_usage(int command)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi{
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* lex_lineno has already been incremented in the lexer; compensate */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (cmd_file_mode) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (strcmp(cmd_file_name, "-") == 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(stderr,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("syntax error on line %d\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi lex_lineno - 1);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi else
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(stderr,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi gettext("syntax error on line %d of %s\n"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi lex_lineno - 1, cmd_file_name);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (void) fprintf(stderr, "%s:\n%s\n", gettext("usage"),
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi helptab[command].short_usage);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi saw_error = TRUE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * long_usage() is for bad semantics: e.g., wrong property type for a given
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * resource type. It is also used by longer_usage() below.
*/
void
long_usage(uint_t cmd_num, bool set_saw)
{
(void) fprintf(set_saw ? stderr : stdout, "%s:\n%s\n", gettext("usage"),
helptab[cmd_num].short_usage);
(void) fprintf(set_saw ? stderr : stdout, "\t%s\n", long_help(cmd_num));
if (set_saw)
saw_error = TRUE;
}
/*
* longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also
* any extra usage() flags as appropriate for whatever command.
*/
void
longer_usage(uint_t cmd_num)
{
long_usage(cmd_num, FALSE);
if (helptab[cmd_num].flags != 0) {
(void) printf("\n");
usage(TRUE, helptab[cmd_num].flags);
}
}
/*
* scope_usage() is simply used when a command is called from the wrong scope.
*/
static void
scope_usage(uint_t cmd_num)
{
zerr(gettext("The %s command only makes sense in the %s scope."),
cmd_to_str(cmd_num),
global_scope ? gettext("resource") : gettext("global"));
saw_error = TRUE;
}
/*
* On input, TRUE => yes, FALSE => no.
* On return, TRUE => 1, FALSE => no, could not ask => -1.
*/
static int
ask_yesno(bool default_answer, const char *question)
{
char line[64]; /* should be enough to answer yes or no */
if (!ok_to_prompt) {
saw_error = TRUE;
return (-1);
}
for (;;) {
if (printf("%s (%s)? ", question,
default_answer ? "[y]/n" : "y/[n]") < 0)
return (-1);
if (fgets(line, sizeof (line), stdin) == NULL)
return (-1);
if (line[0] == '\n')
return (default_answer ? 1 : 0);
if (tolower(line[0]) == 'y')
return (1);
if (tolower(line[0]) == 'n')
return (0);
}
}
/*
* Prints warning if zone already exists.
* In interactive mode, prompts if we should continue anyway and returns Z_OK
* if so, Z_ERR if not. In non-interactive mode, exits with Z_ERR.
*
* Note that if a zone exists and its state is >= INSTALLED, an error message
* will be printed and this function will return Z_ERR regardless of mode.
*/
static int
check_if_zone_already_exists(bool force)
{
char line[ZONENAME_MAX + 128]; /* enough to ask a question */
zone_dochandle_t tmphandle;
int res, answer;
if ((tmphandle = zonecfg_init_handle()) == NULL) {
zone_perror(execname, Z_NOMEM, TRUE);
exit(Z_ERR);
}
res = zonecfg_get_handle(zone, tmphandle);
zonecfg_fini_handle(tmphandle);
if (res != Z_OK)
return (Z_OK);
if (state_atleast(ZONE_STATE_INSTALLED)) {
zerr(gettext("Zone %s already installed; %s not allowed."),
zone, cmd_to_str(CMD_CREATE));
return (Z_ERR);
}
if (force) {
(void) printf(gettext("Zone %s already exists; overwriting.\n"),
zone);
return (Z_OK);
}
(void) snprintf(line, sizeof (line),
gettext("Zone %s already exists; %s anyway"), zone,
cmd_to_str(CMD_CREATE));
if ((answer = ask_yesno(FALSE, line)) == -1) {
zerr(gettext("Zone exists, input not from terminal and -F not "
"specified:\n%s command ignored, exiting."),
cmd_to_str(CMD_CREATE));
exit(Z_ERR);
}
return (answer == 1 ? Z_OK : Z_ERR);
}
static bool
zone_is_read_only(int cmd_num)
{
if (strncmp(zone, "SUNW", 4) == 0) {
zerr(gettext("%s: zones beginning with SUNW are read-only."),
zone);
saw_error = TRUE;
return (TRUE);
}
if (read_only_mode) {
zerr(gettext("%s: cannot %s in read-only mode."), zone,
cmd_to_str(cmd_num));
saw_error = TRUE;
return (TRUE);
}
return (FALSE);
}
/*
* Create a new configuration.
*/
void
create_func(cmd_t *cmd)
{
int err, arg;
char zone_template[ZONENAME_MAX];
char attach_path[MAXPATHLEN];
zone_dochandle_t tmphandle;
bool force = FALSE;
bool attach = FALSE;
bool arg_err = FALSE;
assert(cmd != NULL);
/* This is the default if no arguments are given. */
(void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template));
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:"))
!= EOF) {
switch (arg) {
case '?':
if (optopt == '?')
longer_usage(CMD_CREATE);
else
short_usage(CMD_CREATE);
arg_err = TRUE;
break;
case 'a':
(void) strlcpy(attach_path, optarg,
sizeof (attach_path));
attach = TRUE;
break;
case 'b':
(void) strlcpy(zone_template, "SUNWblank",
sizeof (zone_template));
break;
case 'F':
force = TRUE;
break;
case 't':
(void) strlcpy(zone_template, optarg,
sizeof (zone_template));
break;
default:
short_usage(CMD_CREATE);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
if (optind != cmd->cmd_argc) {
short_usage(CMD_CREATE);
return;
}
if (zone_is_read_only(CMD_CREATE))
return;
if (check_if_zone_already_exists(force) != Z_OK)
return;
/*
* Get a temporary handle first. If that fails, the old handle
* will not be lost. Then finish whichever one we don't need,
* to avoid leaks. Then get the handle for zone_template, and
* set the name to zone: this "copy, rename" method is how
* create -[b|t] works.
*/
if ((tmphandle = zonecfg_init_handle()) == NULL) {
zone_perror(execname, Z_NOMEM, TRUE);
exit(Z_ERR);
}
if (attach)
err = zonecfg_get_attach_handle(attach_path, zone, B_FALSE,
tmphandle);
else
err = zonecfg_get_template_handle(zone_template, zone,
tmphandle);
if (err != Z_OK) {
zonecfg_fini_handle(tmphandle);
if (attach && err == Z_NO_ZONE)
(void) fprintf(stderr, gettext("invalid path to "
"detached zone\n"));
else if (attach && err == Z_INVALID_DOCUMENT)
(void) fprintf(stderr, gettext("Cannot attach to an "
"earlier release of the operating system\n"));
else
zone_perror(zone_template, err, TRUE);
return;
}
need_to_commit = TRUE;
zonecfg_fini_handle(handle);
handle = tmphandle;
got_handle = TRUE;
}
/*
* This malloc()'s memory, which must be freed by the caller.
*/
static char *
quoteit(char *instr)
{
char *outstr;
size_t outstrsize = strlen(instr) + 3; /* 2 quotes + '\0' */
if ((outstr = malloc(outstrsize)) == NULL) {
zone_perror(zone, Z_NOMEM, FALSE);
exit(Z_ERR);
}
if (strchr(instr, ' ') == NULL) {
(void) strlcpy(outstr, instr, outstrsize);
return (outstr);
}
(void) snprintf(outstr, outstrsize, "\"%s\"", instr);
return (outstr);
}
static void
export_prop(FILE *of, int prop_num, char *prop_id)
{
char *quote_str;
if (strlen(prop_id) == 0)
return;
quote_str = quoteit(prop_id);
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(prop_num), quote_str);
free(quote_str);
}
void
export_func(cmd_t *cmd)
{
struct zone_nwiftab nwiftab;
struct zone_fstab fstab;
struct zone_devtab devtab;
struct zone_attrtab attrtab;
struct zone_rctltab rctltab;
struct zone_dstab dstab;
struct zone_psettab psettab;
struct zone_mcaptab mcaptab;
struct zone_rctlvaltab *valptr;
int err, arg;
char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
char bootargs[BOOTARGS_MAX];
char sched[MAXNAMELEN];
char brand[MAXNAMELEN];
char *limitpriv;
FILE *of;
boolean_t autoboot;
zone_iptype_t iptype;
bool need_to_close = FALSE;
bool arg_err = FALSE;
assert(cmd != NULL);
outfile[0] = '\0';
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
switch (arg) {
case '?':
if (optopt == '?')
longer_usage(CMD_EXPORT);
else
short_usage(CMD_EXPORT);
arg_err = TRUE;
break;
case 'f':
(void) strlcpy(outfile, optarg, sizeof (outfile));
break;
default:
short_usage(CMD_EXPORT);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
if (optind != cmd->cmd_argc) {
short_usage(CMD_EXPORT);
return;
}
if (strlen(outfile) == 0) {
of = stdout;
} else {
if ((of = fopen(outfile, "w")) == NULL) {
zerr(gettext("opening file %s: %s"),
outfile, strerror(errno));
goto done;
}
setbuf(of, NULL);
need_to_close = TRUE;
}
if ((err = initialize(TRUE)) != Z_OK)
goto done;
(void) fprintf(of, "%s -b\n", cmd_to_str(CMD_CREATE));
if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK &&
strlen(zonepath) > 0)
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_ZONEPATH), zonepath);
if ((zone_get_brand(zone, brand, sizeof (brand)) == Z_OK) &&
(strcmp(brand, NATIVE_BRAND_NAME) != 0))
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_BRAND), brand);
if (zonecfg_get_autoboot(handle, &autoboot) == Z_OK)
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_AUTOBOOT), autoboot ? "true" : "false");
if (zonecfg_get_bootargs(handle, bootargs, sizeof (bootargs)) == Z_OK &&
strlen(bootargs) > 0) {
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_BOOTARGS), bootargs);
}
if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
strlen(pool) > 0)
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_POOL), pool);
if (zonecfg_get_limitpriv(handle, &limitpriv) == Z_OK &&
strlen(limitpriv) > 0) {
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_LIMITPRIV), limitpriv);
free(limitpriv);
}
if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK &&
strlen(sched) > 0)
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_SCHED), sched);
if (zonecfg_get_iptype(handle, &iptype) == Z_OK) {
switch (iptype) {
case ZS_SHARED:
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_IPTYPE), "shared");
break;
case ZS_EXCLUSIVE:
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_IPTYPE), "exclusive");
break;
}
}
if ((err = zonecfg_setipdent(handle)) != Z_OK) {
zone_perror(zone, err, FALSE);
goto done;
}
while (zonecfg_getipdent(handle, &fstab) == Z_OK) {
(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
rt_to_str(RT_IPD));
export_prop(of, PT_DIR, fstab.zone_fs_dir);
(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
}
(void) zonecfg_endipdent(handle);
if ((err = zonecfg_setfsent(handle)) != Z_OK) {
zone_perror(zone, err, FALSE);
goto done;
}
while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
zone_fsopt_t *optptr;
(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
rt_to_str(RT_FS));
export_prop(of, PT_DIR, fstab.zone_fs_dir);
export_prop(of, PT_SPECIAL, fstab.zone_fs_special);
export_prop(of, PT_RAW, fstab.zone_fs_raw);
export_prop(of, PT_TYPE, fstab.zone_fs_type);
for (optptr = fstab.zone_fs_options; optptr != NULL;
optptr = optptr->zone_fsopt_next) {
/*
* Simple property values with embedded equal signs
* need to be quoted to prevent the lexer from
* mis-parsing them as complex name=value pairs.
*/
if (strchr(optptr->zone_fsopt_opt, '='))
(void) fprintf(of, "%s %s \"%s\"\n",
cmd_to_str(CMD_ADD),
pt_to_str(PT_OPTIONS),
optptr->zone_fsopt_opt);
else
(void) fprintf(of, "%s %s %s\n",
cmd_to_str(CMD_ADD),
pt_to_str(PT_OPTIONS),
optptr->zone_fsopt_opt);
}
(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
zonecfg_free_fs_option_list(fstab.zone_fs_options);
}
(void) zonecfg_endfsent(handle);
if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
zone_perror(zone, err, FALSE);
goto done;
}
while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
rt_to_str(RT_NET));
export_prop(of, PT_ADDRESS, nwiftab.zone_nwif_address);
export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical);
(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
}
(void) zonecfg_endnwifent(handle);
if ((err = zonecfg_setdevent(handle)) != Z_OK) {
zone_perror(zone, err, FALSE);
goto done;
}
while (zonecfg_getdevent(handle, &devtab) == Z_OK) {
(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
rt_to_str(RT_DEVICE));
export_prop(of, PT_MATCH, devtab.zone_dev_match);
(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
}
(void) zonecfg_enddevent(handle);
if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
zone_perror(zone, err, FALSE);
goto done;
}
while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
(void) fprintf(of, "%s rctl\n", cmd_to_str(CMD_ADD));
export_prop(of, PT_NAME, rctltab.zone_rctl_name);
for (valptr = rctltab.zone_rctl_valptr; valptr != NULL;
valptr = valptr->zone_rctlval_next) {
fprintf(of, "%s %s (%s=%s,%s=%s,%s=%s)\n",
cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
}
(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
}
(void) zonecfg_endrctlent(handle);
if ((err = zonecfg_setattrent(handle)) != Z_OK) {
zone_perror(zone, err, FALSE);
goto done;
}
while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
rt_to_str(RT_ATTR));
export_prop(of, PT_NAME, attrtab.zone_attr_name);
export_prop(of, PT_TYPE, attrtab.zone_attr_type);
export_prop(of, PT_VALUE, attrtab.zone_attr_value);
(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
}
(void) zonecfg_endattrent(handle);
if ((err = zonecfg_setdsent(handle)) != Z_OK) {
zone_perror(zone, err, FALSE);
goto done;
}
while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
rt_to_str(RT_DATASET));
export_prop(of, PT_NAME, dstab.zone_dataset_name);
(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
}
(void) zonecfg_enddsent(handle);
if (zonecfg_getpsetent(handle, &psettab) == Z_OK) {
(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
rt_to_str(RT_DCPU));
if (strcmp(psettab.zone_ncpu_min, psettab.zone_ncpu_max) == 0)
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_NCPUS), psettab.zone_ncpu_max);
else
(void) fprintf(of, "%s %s=%s-%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_NCPUS), psettab.zone_ncpu_min,
psettab.zone_ncpu_max);
if (psettab.zone_importance[0] != '\0')
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_IMPORTANCE), psettab.zone_importance);
(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
}
if (zonecfg_getmcapent(handle, &mcaptab) == Z_OK) {
char buf[128];
(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
rt_to_str(RT_MCAP));
bytes_to_units(mcaptab.zone_physmem_cap, buf, sizeof (buf));
(void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
pt_to_str(PT_PHYSICAL), buf);
(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
}
/*
* There is nothing to export for pcap since this resource is just
* a container for an rctl alias.
*/
done:
if (need_to_close)
(void) fclose(of);
}
void
exit_func(cmd_t *cmd)
{
int arg, answer;
bool arg_err = FALSE;
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
switch (arg) {
case '?':
longer_usage(CMD_EXIT);
arg_err = TRUE;
break;
case 'F':
force_exit = TRUE;
break;
default:
short_usage(CMD_EXIT);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
if (optind < cmd->cmd_argc) {
short_usage(CMD_EXIT);
return;
}
if (global_scope || force_exit) {
time_to_exit = TRUE;
return;
}
answer = ask_yesno(FALSE, "Resource incomplete; really quit");
if (answer == -1) {
zerr(gettext("Resource incomplete, input "
"not from terminal and -F not specified:\n%s command "
"ignored, but exiting anyway."), cmd_to_str(CMD_EXIT));
exit(Z_ERR);
} else if (answer == 1) {
time_to_exit = TRUE;
}
/* (answer == 0) => just return */
}
static int
validate_zonepath_syntax(char *path)
{
if (path[0] != '/') {
zerr(gettext("%s is not an absolute path."), path);
return (Z_ERR);
}
if (strcmp(path, "/") == 0) {
zerr(gettext("/ is not allowed as a %s."),
pt_to_str(PT_ZONEPATH));
return (Z_ERR);
}
return (Z_OK);
}
static void
add_resource(cmd_t *cmd)
{
int type;
struct zone_psettab tmp_psettab;
struct zone_mcaptab tmp_mcaptab;
uint64_t tmp;
uint64_t tmp_mcap;
char pool[MAXNAMELEN];
if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
long_usage(CMD_ADD, TRUE);
goto bad;
}
switch (type) {
case RT_FS:
bzero(&in_progress_fstab, sizeof (in_progress_fstab));
return;
case RT_IPD:
if (state_atleast(ZONE_STATE_INSTALLED)) {
zerr(gettext("Zone %s already installed; %s %s not "
"allowed."), zone, cmd_to_str(CMD_ADD),
rt_to_str(RT_IPD));
goto bad;
}
bzero(&in_progress_ipdtab, sizeof (in_progress_ipdtab));
return;
case RT_NET:
bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
return;
case RT_DEVICE:
bzero(&in_progress_devtab, sizeof (in_progress_devtab));
return;
case RT_RCTL:
if (global_zone)
zerr(gettext("WARNING: Setting a global zone resource "
"control too low could deny\nservice "
"to even the root user; "
"this could render the system impossible\n"
"to administer. Please use caution."));
bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
return;
case RT_ATTR:
bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
return;
case RT_DATASET:
bzero(&in_progress_dstab, sizeof (in_progress_dstab));
return;
case RT_DCPU:
/* Make sure there isn't already a cpu-set or cpu-cap entry. */
if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
zerr(gettext("The %s resource already exists."),
rt_to_str(RT_DCPU));
goto bad;
}
if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) !=
Z_NO_ENTRY) {
zerr(gettext("The %s resource already exists."),
rt_to_str(RT_PCAP));
goto bad;
}
/* Make sure the pool property isn't set. */
if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
strlen(pool) > 0) {
zerr(gettext("The %s property is already set. "
"A persistent pool is incompatible with\nthe %s "
"resource."),
pt_to_str(PT_POOL), rt_to_str(RT_DCPU));
goto bad;
}
bzero(&in_progress_psettab, sizeof (in_progress_psettab));
return;
case RT_PCAP:
/*
* Make sure there isn't already a cpu-set or incompatible
* cpu-cap rctls.
*/
if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
zerr(gettext("The %s resource already exists."),
rt_to_str(RT_DCPU));
goto bad;
}
switch (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp)) {
case Z_ALIAS_DISALLOW:
zone_perror(rt_to_str(RT_PCAP), Z_ALIAS_DISALLOW,
FALSE);
goto bad;
case Z_OK:
zerr(gettext("The %s resource already exists."),
rt_to_str(RT_PCAP));
goto bad;
default:
break;
}
return;
case RT_MCAP:
/*
* Make sure there isn't already a mem-cap entry or max-swap
* or max-locked rctl.
*/
if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
== Z_OK ||
zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
&tmp_mcap) == Z_OK) {
zerr(gettext("The %s resource or a related resource "
"control already exists."), rt_to_str(RT_MCAP));
goto bad;
}
if (global_zone)
zerr(gettext("WARNING: Setting a global zone memory "
"cap too low could deny\nservice "
"to even the root user; "
"this could render the system impossible\n"
"to administer. Please use caution."));
bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
return;
default:
zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, TRUE);
long_usage(CMD_ADD, TRUE);
usage(FALSE, HELP_RESOURCES);
}
bad:
global_scope = TRUE;
end_op = -1;
}
static void
do_complex_rctl_val(complex_property_ptr_t cp)
{
struct zone_rctlvaltab *rctlvaltab;
complex_property_ptr_t cx;
bool seen_priv = FALSE, seen_limit = FALSE, seen_action = FALSE;
rctlblk_t *rctlblk;
int err;
if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
zone_perror(zone, Z_NOMEM, TRUE);
exit(Z_ERR);
}
for (cx = cp; cx != NULL; cx = cx->cp_next) {
switch (cx->cp_type) {
case PT_PRIV:
if (seen_priv) {
zerr(gettext("%s already specified"),
pt_to_str(PT_PRIV));
goto bad;
}
(void) strlcpy(rctlvaltab->zone_rctlval_priv,
cx->cp_value,
sizeof (rctlvaltab->zone_rctlval_priv));
seen_priv = TRUE;
break;
case PT_LIMIT:
if (seen_limit) {
zerr(gettext("%s already specified"),
pt_to_str(PT_LIMIT));
goto bad;
}
(void) strlcpy(rctlvaltab->zone_rctlval_limit,
cx->cp_value,
sizeof (rctlvaltab->zone_rctlval_limit));
seen_limit = TRUE;
break;
case PT_ACTION:
if (seen_action) {
zerr(gettext("%s already specified"),
pt_to_str(PT_ACTION));
goto bad;
}
(void) strlcpy(rctlvaltab->zone_rctlval_action,
cx->cp_value,
sizeof (rctlvaltab->zone_rctlval_action));
seen_action = TRUE;
break;
default:
zone_perror(pt_to_str(PT_VALUE),
Z_NO_PROPERTY_TYPE, TRUE);
long_usage(CMD_ADD, TRUE);
usage(FALSE, HELP_PROPS);
zonecfg_free_rctl_value_list(rctlvaltab);
return;
}
}
if (!seen_priv)
zerr(gettext("%s not specified"), pt_to_str(PT_PRIV));
if (!seen_limit)
zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT));
if (!seen_action)
zerr(gettext("%s not specified"), pt_to_str(PT_ACTION));
if (!seen_priv || !seen_limit || !seen_action)
goto bad;
rctlvaltab->zone_rctlval_next = NULL;
rctlblk = alloca(rctlblk_size());
/*
* Make sure the rctl value looks roughly correct; we won't know if
* it's truly OK until we verify the configuration on the target
* system.
*/
if (zonecfg_construct_rctlblk(rctlvaltab, rctlblk) != Z_OK ||
!zonecfg_valid_rctlblk(rctlblk)) {
zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL),
pt_to_str(PT_VALUE));
goto bad;
}
err = zonecfg_add_rctl_value(&in_progress_rctltab, rctlvaltab);
if (err != Z_OK)
zone_perror(pt_to_str(PT_VALUE), err, TRUE);
return;
bad:
zonecfg_free_rctl_value_list(rctlvaltab);
}
static void
add_property(cmd_t *cmd)
{
char *prop_id;
int err, res_type, prop_type;
property_value_ptr_t pp;
list_property_ptr_t l;
res_type = resource_scope;
prop_type = cmd->cmd_prop_name[0];
if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
long_usage(CMD_ADD, TRUE);
return;
}
if (cmd->cmd_prop_nv_pairs != 1) {
long_usage(CMD_ADD, TRUE);
return;
}
if (initialize(TRUE) != Z_OK)
return;
switch (res_type) {
case RT_FS:
if (prop_type != PT_OPTIONS) {
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
TRUE);
long_usage(CMD_ADD, TRUE);
usage(FALSE, HELP_PROPS);
return;
}
pp = cmd->cmd_property_ptr[0];
if (pp->pv_type != PROP_VAL_SIMPLE &&
pp->pv_type != PROP_VAL_LIST) {
zerr(gettext("A %s or %s value was expected here."),
pvt_to_str(PROP_VAL_SIMPLE),
pvt_to_str(PROP_VAL_LIST));
saw_error = TRUE;
return;
}
if (pp->pv_type == PROP_VAL_SIMPLE) {
if (pp->pv_simple == NULL) {
long_usage(CMD_ADD, TRUE);
return;
}
prop_id = pp->pv_simple;
err = zonecfg_add_fs_option(&in_progress_fstab,
prop_id);
if (err != Z_OK)
zone_perror(pt_to_str(prop_type), err, TRUE);
} else {
list_property_ptr_t list;
for (list = pp->pv_list; list != NULL;
list = list->lp_next) {
prop_id = list->lp_simple;
if (prop_id == NULL)
break;
err = zonecfg_add_fs_option(
&in_progress_fstab, prop_id);
if (err != Z_OK)
zone_perror(pt_to_str(prop_type), err,
TRUE);
}
}
return;
case RT_RCTL:
if (prop_type != PT_VALUE) {
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
TRUE);
long_usage(CMD_ADD, TRUE);
usage(FALSE, HELP_PROPS);
return;
}
pp = cmd->cmd_property_ptr[0];
if (pp->pv_type != PROP_VAL_COMPLEX &&
pp->pv_type != PROP_VAL_LIST) {
zerr(gettext("A %s or %s value was expected here."),
pvt_to_str(PROP_VAL_COMPLEX),
pvt_to_str(PROP_VAL_LIST));
saw_error = TRUE;
return;
}
if (pp->pv_type == PROP_VAL_COMPLEX) {
do_complex_rctl_val(pp->pv_complex);
return;
}
for (l = pp->pv_list; l != NULL; l = l->lp_next)
do_complex_rctl_val(l->lp_complex);
return;
default:
zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, TRUE);
long_usage(CMD_ADD, TRUE);
usage(FALSE, HELP_RESOURCES);
return;
}
}
static boolean_t
gz_invalid_resource(int type)
{
return (global_zone && (type == RT_FS || type == RT_IPD ||
type == RT_NET || type == RT_DEVICE || type == RT_ATTR ||
type == RT_DATASET));
}
static boolean_t
gz_invalid_rt_property(int type)
{
return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH ||
type == RT_AUTOBOOT || type == RT_LIMITPRIV ||
type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED ||
type == RT_IPTYPE));
}
static boolean_t
gz_invalid_property(int type)
{
return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH ||
type == PT_AUTOBOOT || type == PT_LIMITPRIV ||
type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED ||
type == PT_IPTYPE));
}
void
add_func(cmd_t *cmd)
{
int arg;
bool arg_err = FALSE;
assert(cmd != NULL);
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
switch (arg) {
case '?':
longer_usage(CMD_ADD);
arg_err = TRUE;
break;
default:
short_usage(CMD_ADD);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
if (optind != cmd->cmd_argc) {
short_usage(CMD_ADD);
return;
}
if (zone_is_read_only(CMD_ADD))
return;
if (initialize(TRUE) != Z_OK)
return;
if (global_scope) {
if (gz_invalid_resource(cmd->cmd_res_type)) {
zerr(gettext("Cannot add a %s resource to the "
"global zone."), rt_to_str(cmd->cmd_res_type));
saw_error = TRUE;
return;
}
global_scope = FALSE;
resource_scope = cmd->cmd_res_type;
end_op = CMD_ADD;
add_resource(cmd);
} else
add_property(cmd);
}
/*
* This routine has an unusual implementation, because it tries very
* hard to succeed in the face of a variety of failure modes.
* The most common and most vexing occurs when the index file and
* the /etc/zones/<zonename.xml> file are not both present. In
* this case, delete must eradicate as much of the zone state as is left
* so that the user can later create a new zone with the same name.
*/
void
delete_func(cmd_t *cmd)
{
int err, arg, answer;
char line[ZONENAME_MAX + 128]; /* enough to ask a question */
bool force = FALSE;
bool arg_err = FALSE;
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
switch (arg) {
case '?':
longer_usage(CMD_DELETE);
arg_err = TRUE;
break;
case 'F':
force = TRUE;
break;
default:
short_usage(CMD_DELETE);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
if (optind != cmd->cmd_argc) {
short_usage(CMD_DELETE);
return;
}
if (zone_is_read_only(CMD_DELETE))
return;
if (!force) {
/*
* Initialize sets up the global called "handle" and warns the
* user if the zone is not configured. In force mode, we don't
* trust that evaluation, and hence skip it. (We don't need the
* handle to be loaded anyway, since zonecfg_destroy is done by
* zonename). However, we also have to take care to emulate the
* messages spit out by initialize; see below.
*/
if (initialize(TRUE) != Z_OK)
return;
(void) snprintf(line, sizeof (line),
gettext("Are you sure you want to delete zone %s"), zone);
if ((answer = ask_yesno(FALSE, line)) == -1) {
zerr(gettext("Input not from terminal and -F not "
"specified:\n%s command ignored, exiting."),
cmd_to_str(CMD_DELETE));
exit(Z_ERR);
}
if (answer != 1)
return;
}
if ((err = zonecfg_destroy(zone, force)) != Z_OK) {
if ((err == Z_BAD_ZONE_STATE) && !force) {
zerr(gettext("Zone %s not in %s state; %s not "
"allowed. Use -F to force %s."),
zone, zone_state_str(ZONE_STATE_CONFIGURED),
cmd_to_str(CMD_DELETE), cmd_to_str(CMD_DELETE));
} else {
zone_perror(zone, err, TRUE);
}
}
need_to_commit = FALSE;
/*
* Emulate initialize's messaging; if there wasn't a valid handle to
* begin with, then user had typed delete (or delete -F) multiple
* times. So we emit a message.
*
* We only do this in the 'force' case because normally, initialize()
* takes care of this for us.
*/
if (force && zonecfg_check_handle(handle) != Z_OK && interactive_mode)
(void) printf(gettext("Use '%s' to begin "
"configuring a new zone.\n"), cmd_to_str(CMD_CREATE));
/*
* Time for a new handle: finish the old one off first
* then get a new one properly to avoid leaks.
*/
if (got_handle) {
zonecfg_fini_handle(handle);
if ((handle = zonecfg_init_handle()) == NULL) {
zone_perror(execname, Z_NOMEM, TRUE);
exit(Z_ERR);
}
if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) {
/* If there was no zone before, that's OK */
if (err != Z_NO_ZONE)
zone_perror(zone, err, TRUE);
got_handle = FALSE;
}
}
}
static int
fill_in_fstab(cmd_t *cmd, struct zone_fstab *fstab, bool fill_in_only)
{
int err, i;
property_value_ptr_t pp;
if ((err = initialize(TRUE)) != Z_OK)
return (err);
bzero(fstab, sizeof (*fstab));
for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
pp = cmd->cmd_property_ptr[i];
if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
zerr(gettext("A simple value was expected here."));
saw_error = TRUE;
return (Z_INSUFFICIENT_SPEC);
}
switch (cmd->cmd_prop_name[i]) {
case PT_DIR:
(void) strlcpy(fstab->zone_fs_dir, pp->pv_simple,
sizeof (fstab->zone_fs_dir));
break;
case PT_SPECIAL:
(void) strlcpy(fstab->zone_fs_special, pp->pv_simple,
sizeof (fstab->zone_fs_special));
break;
case PT_RAW:
(void) strlcpy(fstab->zone_fs_raw, pp->pv_simple,
sizeof (fstab->zone_fs_raw));
break;
case PT_TYPE:
(void) strlcpy(fstab->zone_fs_type, pp->pv_simple,
sizeof (fstab->zone_fs_type));
break;
default:
zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
Z_NO_PROPERTY_TYPE, TRUE);
return (Z_INSUFFICIENT_SPEC);
}
}
if (fill_in_only)
return (Z_OK);
return (zonecfg_lookup_filesystem(handle, fstab));
}
static int
fill_in_ipdtab(cmd_t *cmd, struct zone_fstab *ipdtab, bool fill_in_only)
{
int err, i;
property_value_ptr_t pp;
if ((err = initialize(TRUE)) != Z_OK)
return (err);
bzero(ipdtab, sizeof (*ipdtab));
for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
pp = cmd->cmd_property_ptr[i];
if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
zerr(gettext("A simple value was expected here."));
saw_error = TRUE;
return (Z_INSUFFICIENT_SPEC);
}
switch (cmd->cmd_prop_name[i]) {
case PT_DIR:
(void) strlcpy(ipdtab->zone_fs_dir, pp->pv_simple,
sizeof (ipdtab->zone_fs_dir));
break;
default:
zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
Z_NO_PROPERTY_TYPE, TRUE);
return (Z_INSUFFICIENT_SPEC);
}
}
if (fill_in_only)
return (Z_OK);
return (zonecfg_lookup_ipd(handle, ipdtab));
}
static int
fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab, bool fill_in_only)
{
int err, i;
property_value_ptr_t pp;
if ((err = initialize(TRUE)) != Z_OK)
return (err);
bzero(nwiftab, sizeof (*nwiftab));
for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
pp = cmd->cmd_property_ptr[i];
if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
zerr(gettext("A simple value was expected here."));
saw_error = TRUE;
return (Z_INSUFFICIENT_SPEC);
}
switch (cmd->cmd_prop_name[i]) {
case PT_ADDRESS:
(void) strlcpy(nwiftab->zone_nwif_address,
pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
break;
case PT_PHYSICAL:
(void) strlcpy(nwiftab->zone_nwif_physical,
pp->pv_simple,
sizeof (nwiftab->zone_nwif_physical));
break;
default:
zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
Z_NO_PROPERTY_TYPE, TRUE);
return (Z_INSUFFICIENT_SPEC);
}
}
if (fill_in_only)
return (Z_OK);
err = zonecfg_lookup_nwif(handle, nwiftab);
return (err);
}
static int
fill_in_devtab(cmd_t *cmd, struct zone_devtab *devtab, bool fill_in_only)
{
int err, i;
property_value_ptr_t pp;
if ((err = initialize(TRUE)) != Z_OK)
return (err);
bzero(devtab, sizeof (*devtab));
for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
pp = cmd->cmd_property_ptr[i];
if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
zerr(gettext("A simple value was expected here."));
saw_error = TRUE;
return (Z_INSUFFICIENT_SPEC);
}
switch (cmd->cmd_prop_name[i]) {
case PT_MATCH:
(void) strlcpy(devtab->zone_dev_match, pp->pv_simple,
sizeof (devtab->zone_dev_match));
break;
default:
zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
Z_NO_PROPERTY_TYPE, TRUE);
return (Z_INSUFFICIENT_SPEC);
}
}
if (fill_in_only)
return (Z_OK);
err = zonecfg_lookup_dev(handle, devtab);
return (err);
}
static int
fill_in_rctltab(cmd_t *cmd, struct zone_rctltab *rctltab, bool fill_in_only)
{
int err, i;
property_value_ptr_t pp;
if ((err = initialize(TRUE)) != Z_OK)
return (err);
bzero(rctltab, sizeof (*rctltab));
for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
pp = cmd->cmd_property_ptr[i];
if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
zerr(gettext("A simple value was expected here."));
saw_error = TRUE;
return (Z_INSUFFICIENT_SPEC);
}
switch (cmd->cmd_prop_name[i]) {
case PT_NAME:
(void) strlcpy(rctltab->zone_rctl_name, pp->pv_simple,
sizeof (rctltab->zone_rctl_name));
break;
default:
zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
Z_NO_PROPERTY_TYPE, TRUE);
return (Z_INSUFFICIENT_SPEC);
}
}
if (fill_in_only)
return (Z_OK);
err = zonecfg_lookup_rctl(handle, rctltab);
return (err);
}
static int
fill_in_attrtab(cmd_t *cmd, struct zone_attrtab *attrtab, bool fill_in_only)
{
int err, i;
property_value_ptr_t pp;
if ((err = initialize(TRUE)) != Z_OK)
return (err);
bzero(attrtab, sizeof (*attrtab));
for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
pp = cmd->cmd_property_ptr[i];
if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
zerr(gettext("A simple value was expected here."));
saw_error = TRUE;
return (Z_INSUFFICIENT_SPEC);
}
switch (cmd->cmd_prop_name[i]) {
case PT_NAME:
(void) strlcpy(attrtab->zone_attr_name, pp->pv_simple,
sizeof (attrtab->zone_attr_name));
break;
case PT_TYPE:
(void) strlcpy(attrtab->zone_attr_type, pp->pv_simple,
sizeof (attrtab->zone_attr_type));
break;
case PT_VALUE:
(void) strlcpy(attrtab->zone_attr_value, pp->pv_simple,
sizeof (attrtab->zone_attr_value));
break;
default:
zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
Z_NO_PROPERTY_TYPE, TRUE);
return (Z_INSUFFICIENT_SPEC);
}
}
if (fill_in_only)
return (Z_OK);
err = zonecfg_lookup_attr(handle, attrtab);
return (err);
}
static int
fill_in_dstab(cmd_t *cmd, struct zone_dstab *dstab, bool fill_in_only)
{
int err, i;
property_value_ptr_t pp;
if ((err = initialize(TRUE)) != Z_OK)
return (err);
dstab->zone_dataset_name[0] = '\0';
for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
pp = cmd->cmd_property_ptr[i];
if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
zerr(gettext("A simple value was expected here."));
saw_error = TRUE;
return (Z_INSUFFICIENT_SPEC);
}
switch (cmd->cmd_prop_name[i]) {
case PT_NAME:
(void) strlcpy(dstab->zone_dataset_name, pp->pv_simple,
sizeof (dstab->zone_dataset_name));
break;
default:
zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
Z_NO_PROPERTY_TYPE, TRUE);
return (Z_INSUFFICIENT_SPEC);
}
}
if (fill_in_only)
return (Z_OK);
return (zonecfg_lookup_ds(handle, dstab));
}
static void
remove_aliased_rctl(int type, char *name)
{
int err;
uint64_t tmp;
if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) {
zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
zonecfg_strerror(err));
saw_error = TRUE;
return;
}
if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) {
zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
zonecfg_strerror(err));
saw_error = TRUE;
} else {
need_to_commit = TRUE;
}
}
static boolean_t
prompt_remove_resource(cmd_t *cmd, char *rsrc)
{
int num;
int answer;
int arg;
boolean_t force = B_FALSE;
char prompt[128];
bool arg_err = FALSE;
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
switch (arg) {
case 'F':
force = B_TRUE;
break;
default:
arg_err = TRUE;
break;
}
}
if (arg_err)
return (B_FALSE);
num = zonecfg_num_resources(handle, rsrc);
if (num == 0) {
z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY,
TRUE);
return (B_FALSE);
}
if (num > 1 && !force) {
if (!interactive_mode) {
zerr(gettext("There are multiple instances of this "
"resource. Either qualify the resource to\n"
"remove a single instance or use the -F option to "
"remove all instances."));
saw_error = TRUE;
return (B_FALSE);
}
(void) snprintf(prompt, sizeof (prompt), gettext(
"Are you sure you want to remove ALL '%s' resources"),
rsrc);
answer = ask_yesno(FALSE, prompt);
if (answer == -1) {
zerr(gettext("Resource incomplete."));
return (B_FALSE);
}
if (answer != 1)
return (B_FALSE);
}
return (B_TRUE);
}
static void
remove_fs(cmd_t *cmd)
{
int err;
/* traditional, qualified fs removal */
if (cmd->cmd_prop_nv_pairs > 0) {
struct zone_fstab fstab;
if ((err = fill_in_fstab(cmd, &fstab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, TRUE);
return;
}
if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, TRUE);
else
need_to_commit = TRUE;
zonecfg_free_fs_option_list(fstab.zone_fs_options);
return;
}
/*
* unqualified fs removal. remove all fs's but prompt if more
* than one.
*/
if (!prompt_remove_resource(cmd, "fs"))
return;
if ((err = zonecfg_del_all_resources(handle, "fs")) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, TRUE);
else
need_to_commit = TRUE;
}
static void
remove_ipd(cmd_t *cmd)
{
int err;
if (state_atleast(ZONE_STATE_INSTALLED)) {
zerr(gettext("Zone %s already installed; %s %s not allowed."),
zone, cmd_to_str(CMD_REMOVE), rt_to_str(RT_IPD));
return;
}
/* traditional, qualified ipd removal */
if (cmd->cmd_prop_nv_pairs > 0) {
struct zone_fstab fstab;
if ((err = fill_in_ipdtab(cmd, &fstab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, TRUE);
return;
}
if ((err = zonecfg_delete_ipd(handle, &fstab)) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, TRUE);
else
need_to_commit = TRUE;
return;
}
/*
* unqualified ipd removal. remove all ipds but prompt if more
* than one.
*/
if (!prompt_remove_resource(cmd, "inherit-pkg-dir"))
return;
if ((err = zonecfg_del_all_resources(handle, "inherit-pkg-dir"))
!= Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_IPD, err, TRUE);
else
need_to_commit = TRUE;
}
static void
remove_net(cmd_t *cmd)
{
int err;
/* traditional, qualified net removal */
if (cmd->cmd_prop_nv_pairs > 0) {
struct zone_nwiftab nwiftab;
if ((err = fill_in_nwiftab(cmd, &nwiftab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, TRUE);
return;
}
if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, TRUE);
else
need_to_commit = TRUE;
return;
}
/*
* unqualified net removal. remove all nets but prompt if more
* than one.
*/
if (!prompt_remove_resource(cmd, "net"))
return;
if ((err = zonecfg_del_all_resources(handle, "net")) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, TRUE);
else
need_to_commit = TRUE;
}
static void
remove_device(cmd_t *cmd)
{
int err;
/* traditional, qualified device removal */
if (cmd->cmd_prop_nv_pairs > 0) {
struct zone_devtab devtab;
if ((err = fill_in_devtab(cmd, &devtab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, TRUE);
return;
}
if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, TRUE);
else
need_to_commit = TRUE;
return;
}
/*
* unqualified device removal. remove all devices but prompt if more
* than one.
*/
if (!prompt_remove_resource(cmd, "device"))
return;
if ((err = zonecfg_del_all_resources(handle, "device")) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, TRUE);
else
need_to_commit = TRUE;
}
static void
remove_attr(cmd_t *cmd)
{
int err;
/* traditional, qualified attr removal */
if (cmd->cmd_prop_nv_pairs > 0) {
struct zone_attrtab attrtab;
if ((err = fill_in_attrtab(cmd, &attrtab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, TRUE);
return;
}
if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, TRUE);
else
need_to_commit = TRUE;
return;
}
/*
* unqualified attr removal. remove all attrs but prompt if more
* than one.
*/
if (!prompt_remove_resource(cmd, "attr"))
return;
if ((err = zonecfg_del_all_resources(handle, "attr")) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, TRUE);
else
need_to_commit = TRUE;
}
static void
remove_dataset(cmd_t *cmd)
{
int err;
/* traditional, qualified dataset removal */
if (cmd->cmd_prop_nv_pairs > 0) {
struct zone_dstab dstab;
if ((err = fill_in_dstab(cmd, &dstab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, TRUE);
return;
}
if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, TRUE);
else
need_to_commit = TRUE;
return;
}
/*
* unqualified dataset removal. remove all datasets but prompt if more
* than one.
*/
if (!prompt_remove_resource(cmd, "dataset"))
return;
if ((err = zonecfg_del_all_resources(handle, "dataset")) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, TRUE);
else
need_to_commit = TRUE;
}
static void
remove_rctl(cmd_t *cmd)
{
int err;
/* traditional, qualified rctl removal */
if (cmd->cmd_prop_nv_pairs > 0) {
struct zone_rctltab rctltab;
if ((err = fill_in_rctltab(cmd, &rctltab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, TRUE);
return;
}
if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, TRUE);
else
need_to_commit = TRUE;
zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
return;
}
/*
* unqualified rctl removal. remove all rctls but prompt if more
* than one.
*/
if (!prompt_remove_resource(cmd, "rctl"))
return;
if ((err = zonecfg_del_all_resources(handle, "rctl")) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, TRUE);
else
need_to_commit = TRUE;
}
static void
remove_pset()
{
int err;
struct zone_psettab psettab;
if ((err = zonecfg_lookup_pset(handle, &psettab)) != Z_OK) {
z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, TRUE);
return;
}
if ((err = zonecfg_delete_pset(handle)) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, TRUE);
else
need_to_commit = TRUE;
}
static void
remove_pcap()
{
int err;
uint64_t tmp;
if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) {
zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_PCAP),
zonecfg_strerror(Z_NO_RESOURCE_TYPE));
saw_error = TRUE;
return;
}
if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK)
z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, TRUE);
else
need_to_commit = TRUE;
}
static void
remove_mcap()
{
int err, res1, res2, res3;
uint64_t tmp;
struct zone_mcaptab mcaptab;
boolean_t revert = B_FALSE;
res1 = zonecfg_lookup_mcap(handle, &mcaptab);
res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp);
res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp);
/* if none of these exist, there is no resource to remove */
if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_MCAP),
zonecfg_strerror(Z_NO_RESOURCE_TYPE));
saw_error = TRUE;
return;
}
if (res1 == Z_OK) {
if ((err = zonecfg_delete_mcap(handle)) != Z_OK) {
z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, TRUE);
revert = B_TRUE;
} else {
need_to_commit = TRUE;
}
}
if (res2 == Z_OK) {
if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP))
!= Z_OK) {
z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, TRUE);
revert = B_TRUE;
} else {
need_to_commit = TRUE;
}
}
if (res3 == Z_OK) {
if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM))
!= Z_OK) {
z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, TRUE);
revert = B_TRUE;
} else {
need_to_commit = TRUE;
}
}
if (revert)
need_to_commit = FALSE;
}
static void
remove_resource(cmd_t *cmd)
{
int type;
int arg;
bool arg_err = FALSE;
if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
long_usage(CMD_REMOVE, TRUE);
return;
}
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
switch (arg) {
case '?':
longer_usage(CMD_REMOVE);
arg_err = TRUE;
break;
case 'F':
break;
default:
short_usage(CMD_REMOVE);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
if (initialize(TRUE) != Z_OK)
return;
switch (type) {
case RT_FS:
remove_fs(cmd);
return;
case RT_IPD:
remove_ipd(cmd);
return;
case RT_NET:
remove_net(cmd);
return;
case RT_DEVICE:
remove_device(cmd);
return;
case RT_RCTL:
remove_rctl(cmd);
return;
case RT_ATTR:
remove_attr(cmd);
return;
case RT_DATASET:
remove_dataset(cmd);
return;
case RT_DCPU:
remove_pset();
return;
case RT_PCAP:
remove_pcap();
return;
case RT_MCAP:
remove_mcap();
return;
default:
zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, TRUE);
long_usage(CMD_REMOVE, TRUE);
usage(FALSE, HELP_RESOURCES);
return;
}
}
static void
remove_property(cmd_t *cmd)
{
char *prop_id;
int err, res_type, prop_type;
property_value_ptr_t pp;
struct zone_rctlvaltab *rctlvaltab;
complex_property_ptr_t cx;
res_type = resource_scope;
prop_type = cmd->cmd_prop_name[0];
if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
long_usage(CMD_REMOVE, TRUE);
return;
}
if (cmd->cmd_prop_nv_pairs != 1) {
long_usage(CMD_ADD, TRUE);
return;
}
if (initialize(TRUE) != Z_OK)
return;
switch (res_type) {
case RT_FS:
if (prop_type != PT_OPTIONS) {
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
TRUE);
long_usage(CMD_REMOVE, TRUE);
usage(FALSE, HELP_PROPS);
return;
}
pp = cmd->cmd_property_ptr[0];
if (pp->pv_type == PROP_VAL_COMPLEX) {
zerr(gettext("A %s or %s value was expected here."),
pvt_to_str(PROP_VAL_SIMPLE),
pvt_to_str(PROP_VAL_LIST));
saw_error = TRUE;
return;
}
if (pp->pv_type == PROP_VAL_SIMPLE) {
if (pp->pv_simple == NULL) {
long_usage(CMD_ADD, TRUE);
return;
}
prop_id = pp->pv_simple;
err = zonecfg_remove_fs_option(&in_progress_fstab,
prop_id);
if (err != Z_OK)
zone_perror(pt_to_str(prop_type), err, TRUE);
} else {
list_property_ptr_t list;
for (list = pp->pv_list; list != NULL;
list = list->lp_next) {
prop_id = list->lp_simple;
if (prop_id == NULL)
break;
err = zonecfg_remove_fs_option(
&in_progress_fstab, prop_id);
if (err != Z_OK)
zone_perror(pt_to_str(prop_type), err,
TRUE);
}
}
return;
case RT_RCTL:
if (prop_type != PT_VALUE) {
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
TRUE);
long_usage(CMD_REMOVE, TRUE);
usage(FALSE, HELP_PROPS);
return;
}
pp = cmd->cmd_property_ptr[0];
if (pp->pv_type != PROP_VAL_COMPLEX) {
zerr(gettext("A %s value was expected here."),
pvt_to_str(PROP_VAL_COMPLEX));
saw_error = TRUE;
return;
}
if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
zone_perror(zone, Z_NOMEM, TRUE);
exit(Z_ERR);
}
for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) {
switch (cx->cp_type) {
case PT_PRIV:
(void) strlcpy(rctlvaltab->zone_rctlval_priv,
cx->cp_value,
sizeof (rctlvaltab->zone_rctlval_priv));
break;
case PT_LIMIT:
(void) strlcpy(rctlvaltab->zone_rctlval_limit,
cx->cp_value,
sizeof (rctlvaltab->zone_rctlval_limit));
break;
case PT_ACTION:
(void) strlcpy(rctlvaltab->zone_rctlval_action,
cx->cp_value,
sizeof (rctlvaltab->zone_rctlval_action));
break;
default:
zone_perror(pt_to_str(prop_type),
Z_NO_PROPERTY_TYPE, TRUE);
long_usage(CMD_ADD, TRUE);
usage(FALSE, HELP_PROPS);
zonecfg_free_rctl_value_list(rctlvaltab);
return;
}
}
rctlvaltab->zone_rctlval_next = NULL;
err = zonecfg_remove_rctl_value(&in_progress_rctltab,
rctlvaltab);
if (err != Z_OK)
zone_perror(pt_to_str(prop_type), err, TRUE);
zonecfg_free_rctl_value_list(rctlvaltab);
return;
default:
zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, TRUE);
long_usage(CMD_REMOVE, TRUE);
usage(FALSE, HELP_RESOURCES);
return;
}
}
void
remove_func(cmd_t *cmd)
{
if (zone_is_read_only(CMD_REMOVE))
return;
assert(cmd != NULL);
if (global_scope) {
if (gz_invalid_resource(cmd->cmd_res_type)) {
zerr(gettext("%s is not a valid resource for the "
"global zone."), rt_to_str(cmd->cmd_res_type));
saw_error = TRUE;
return;
}
remove_resource(cmd);
} else {
remove_property(cmd);
}
}
static void
clear_property(cmd_t *cmd)
{
int res_type, prop_type;
res_type = resource_scope;
prop_type = cmd->cmd_res_type;
if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
long_usage(CMD_CLEAR, TRUE);
return;
}
if (initialize(TRUE) != Z_OK)
return;
switch (res_type) {
case RT_FS:
if (prop_type == PT_RAW) {
in_progress_fstab.zone_fs_raw[0] = '\0';
need_to_commit = TRUE;
return;
}
break;
case RT_DCPU:
if (prop_type == PT_IMPORTANCE) {
in_progress_psettab.zone_importance[0] = '\0';
need_to_commit = TRUE;
return;
}
break;
case RT_MCAP:
switch (prop_type) {
case PT_PHYSICAL:
in_progress_mcaptab.zone_physmem_cap[0] = '\0';
need_to_commit = TRUE;
return;
case PT_SWAP:
remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
return;
case PT_LOCKED:
remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
return;
}
break;
default:
break;
}
zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, TRUE);
}
static void
clear_global(cmd_t *cmd)
{
int err, type;
if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
long_usage(CMD_CLEAR, TRUE);
return;
}
if (initialize(TRUE) != Z_OK)
return;
switch (type) {
case PT_ZONENAME:
/* FALLTHRU */
case PT_ZONEPATH:
/* FALLTHRU */
case PT_BRAND:
zone_perror(pt_to_str(type), Z_CLEAR_DISALLOW, TRUE);
return;
case PT_AUTOBOOT:
/* false is default; we'll treat as equivalent to clearing */
if ((err = zonecfg_set_autoboot(handle, B_FALSE)) != Z_OK)
z_cmd_rt_perror(CMD_CLEAR, RT_AUTOBOOT, err, TRUE);
else
need_to_commit = TRUE;
return;
case PT_POOL:
if ((err = zonecfg_set_pool(handle, NULL)) != Z_OK)
z_cmd_rt_perror(CMD_CLEAR, RT_POOL, err, TRUE);
else
need_to_commit = TRUE;
return;
case PT_LIMITPRIV:
if ((err = zonecfg_set_limitpriv(handle, NULL)) != Z_OK)
z_cmd_rt_perror(CMD_CLEAR, RT_LIMITPRIV, err, TRUE);
else
need_to_commit = TRUE;
return;
case PT_BOOTARGS:
if ((err = zonecfg_set_bootargs(handle, NULL)) != Z_OK)
z_cmd_rt_perror(CMD_CLEAR, RT_BOOTARGS, err, TRUE);
else
need_to_commit = TRUE;
return;
case PT_SCHED:
if ((err = zonecfg_set_sched(handle, NULL)) != Z_OK)
z_cmd_rt_perror(CMD_CLEAR, RT_SCHED, err, TRUE);
else
need_to_commit = TRUE;
return;
case PT_IPTYPE:
/* shared is default; we'll treat as equivalent to clearing */
if ((err = zonecfg_set_iptype(handle, ZS_SHARED)) != Z_OK)
z_cmd_rt_perror(CMD_CLEAR, RT_IPTYPE, err, TRUE);
else
need_to_commit = TRUE;
return;
case PT_MAXLWPS:
remove_aliased_rctl(PT_MAXLWPS, ALIAS_MAXLWPS);
return;
case PT_MAXSHMMEM:
remove_aliased_rctl(PT_MAXSHMMEM, ALIAS_MAXSHMMEM);
return;
case PT_MAXSHMIDS:
remove_aliased_rctl(PT_MAXSHMIDS, ALIAS_MAXSHMIDS);
return;
case PT_MAXMSGIDS:
remove_aliased_rctl(PT_MAXMSGIDS, ALIAS_MAXMSGIDS);
return;
case PT_MAXSEMIDS:
remove_aliased_rctl(PT_MAXSEMIDS, ALIAS_MAXSEMIDS);
return;
case PT_SHARES:
remove_aliased_rctl(PT_SHARES, ALIAS_SHARES);
return;
default:
zone_perror(pt_to_str(type), Z_NO_PROPERTY_TYPE, TRUE);
long_usage(CMD_CLEAR, TRUE);
usage(FALSE, HELP_PROPS);
return;
}
}
void
clear_func(cmd_t *cmd)
{
if (zone_is_read_only(CMD_CLEAR))
return;
assert(cmd != NULL);
if (global_scope) {
if (gz_invalid_property(cmd->cmd_res_type)) {
zerr(gettext("%s is not a valid property for the "
"global zone."), pt_to_str(cmd->cmd_res_type));
saw_error = TRUE;
return;
}
clear_global(cmd);
} else {
clear_property(cmd);
}
}
void
select_func(cmd_t *cmd)
{
int type, err, res;
uint64_t limit;
uint64_t tmp;
if (zone_is_read_only(CMD_SELECT))
return;
assert(cmd != NULL);
if (global_scope) {
global_scope = FALSE;
resource_scope = cmd->cmd_res_type;
end_op = CMD_SELECT;
} else {
scope_usage(CMD_SELECT);
return;
}
if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
long_usage(CMD_SELECT, TRUE);
return;
}
if (initialize(TRUE) != Z_OK)
return;
switch (type) {
case RT_FS:
if ((err = fill_in_fstab(cmd, &old_fstab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_SELECT, RT_FS, err, TRUE);
global_scope = TRUE;
}
bcopy(&old_fstab, &in_progress_fstab,
sizeof (struct zone_fstab));
return;
case RT_IPD:
if (state_atleast(ZONE_STATE_INCOMPLETE)) {
zerr(gettext("Zone %s not in %s state; %s %s not "
"allowed."), zone,
zone_state_str(ZONE_STATE_CONFIGURED),
cmd_to_str(CMD_SELECT), rt_to_str(RT_IPD));
global_scope = TRUE;
end_op = -1;
return;
}
if ((err = fill_in_ipdtab(cmd, &old_ipdtab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_SELECT, RT_IPD, err, TRUE);
global_scope = TRUE;
}
bcopy(&old_ipdtab, &in_progress_ipdtab,
sizeof (struct zone_fstab));
return;
case RT_NET:
if ((err = fill_in_nwiftab(cmd, &old_nwiftab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_SELECT, RT_NET, err, TRUE);
global_scope = TRUE;
}
bcopy(&old_nwiftab, &in_progress_nwiftab,
sizeof (struct zone_nwiftab));
return;
case RT_DEVICE:
if ((err = fill_in_devtab(cmd, &old_devtab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_SELECT, RT_DEVICE, err, TRUE);
global_scope = TRUE;
}
bcopy(&old_devtab, &in_progress_devtab,
sizeof (struct zone_devtab));
return;
case RT_RCTL:
if ((err = fill_in_rctltab(cmd, &old_rctltab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_SELECT, RT_RCTL, err, TRUE);
global_scope = TRUE;
}
bcopy(&old_rctltab, &in_progress_rctltab,
sizeof (struct zone_rctltab));
return;
case RT_ATTR:
if ((err = fill_in_attrtab(cmd, &old_attrtab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_SELECT, RT_ATTR, err, TRUE);
global_scope = TRUE;
}
bcopy(&old_attrtab, &in_progress_attrtab,
sizeof (struct zone_attrtab));
return;
case RT_DATASET:
if ((err = fill_in_dstab(cmd, &old_dstab, FALSE)) != Z_OK) {
z_cmd_rt_perror(CMD_SELECT, RT_DATASET, err, TRUE);
global_scope = TRUE;
}
bcopy(&old_dstab, &in_progress_dstab,
sizeof (struct zone_dstab));
return;
case RT_DCPU:
if ((err = zonecfg_lookup_pset(handle, &old_psettab)) != Z_OK) {
z_cmd_rt_perror(CMD_SELECT, RT_DCPU, err, TRUE);
global_scope = TRUE;
}
bcopy(&old_psettab, &in_progress_psettab,
sizeof (struct zone_psettab));
return;
case RT_PCAP:
if ((err = zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp))
!= Z_OK) {
z_cmd_rt_perror(CMD_SELECT, RT_PCAP, err, TRUE);
global_scope = TRUE;
}
return;
case RT_MCAP:
/* if none of these exist, there is no resource to select */
if ((res = zonecfg_lookup_mcap(handle, &old_mcaptab)) != Z_OK &&
zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &limit)
!= Z_OK &&
zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &limit)
!= Z_OK) {
z_cmd_rt_perror(CMD_SELECT, RT_MCAP, Z_NO_RESOURCE_TYPE,
TRUE);
global_scope = TRUE;
}
if (res == Z_OK)
bcopy(&old_mcaptab, &in_progress_mcaptab,
sizeof (struct zone_mcaptab));
else
bzero(&in_progress_mcaptab,
sizeof (in_progress_mcaptab));
return;
default:
zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, TRUE);
long_usage(CMD_SELECT, TRUE);
usage(FALSE, HELP_RESOURCES);
return;
}
}
/*
* Network "addresses" can be one of the following forms:
* <IPv4 address>
* <IPv4 address>/<prefix length>
* <IPv6 address>/<prefix length>
* <host name>
* <host name>/<prefix length>
* In other words, the "/" followed by a prefix length is allowed but not
* required for IPv4 addresses and host names, and required for IPv6 addresses.
* If a prefix length is given, it must be in the allowable range: 0 to 32 for
* IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
* Host names must start with an alpha-numeric character, and all subsequent
* characters must be either alpha-numeric or "-".
*/
static int
validate_net_address_syntax(char *address)
{
char *slashp, part1[MAXHOSTNAMELEN];
struct in6_addr in6;
struct in_addr in4;
int prefixlen, i;
/*
* Copy the part before any '/' into part1 or copy the whole
* thing if there is no '/'.
*/
if ((slashp = strchr(address, '/')) != NULL) {
*slashp = '\0';
(void) strlcpy(part1, address, sizeof (part1));
*slashp = '/';
prefixlen = atoi(++slashp);
} else {
(void) strlcpy(part1, address, sizeof (part1));
}
if (inet_pton(AF_INET6, part1, &in6) == 1) {
if (slashp == NULL) {
zerr(gettext("%s: IPv6 addresses "
"require /prefix-length suffix."), address);
return (Z_ERR);
}
if (prefixlen < 0 || prefixlen > 128) {
zerr(gettext("%s: IPv6 address "
"prefix lengths must be 0 - 128."), address);
return (Z_ERR);
}
return (Z_OK);
}
/* At this point, any /prefix must be for IPv4. */
if (slashp != NULL) {
if (prefixlen < 0 || prefixlen > 32) {
zerr(gettext("%s: IPv4 address "
"prefix lengths must be 0 - 32."), address);
return (Z_ERR);
}
}
if (inet_pton(AF_INET, part1, &in4) == 1)
return (Z_OK);
/* address may also be a host name */
if (!isalnum(part1[0])) {
zerr(gettext("%s: bogus host name or network address syntax"),
part1);
saw_error = TRUE;
usage(FALSE, HELP_NETADDR);
return (Z_ERR);
}
for (i = 1; part1[i]; i++)
if (!isalnum(part1[i]) && part1[i] != '-' && part1[i] != '.') {
zerr(gettext("%s: bogus host name or "
"network address syntax"), part1);
saw_error = TRUE;
usage(FALSE, HELP_NETADDR);
return (Z_ERR);
}
return (Z_OK);
}
static int
validate_net_physical_syntax(char *ifname)
{
if (strchr(ifname, ':') == NULL)
return (Z_OK);
zerr(gettext("%s: physical interface name required; "
"logical interface name not allowed"), ifname);
return (Z_ERR);
}
static boolean_t
valid_fs_type(const char *type)
{
/*
* Is this a valid path component?
*/
if (strlen(type) + 1 > MAXNAMELEN)
return (B_FALSE);
/*
* Make sure a bad value for "type" doesn't make
* /usr/lib/fs/<type>/mount turn into something else.
*/
if (strchr(type, '/') != NULL || type[0] == '\0' ||
strcmp(type, ".") == 0 || strcmp(type, "..") == 0)
return (B_FALSE);
/*
* More detailed verification happens later by zoneadm(1m).
*/
return (B_TRUE);
}
static boolean_t
allow_exclusive()
{
brand_handle_t bh;
char brand[MAXNAMELEN];
boolean_t ret;
if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
zerr("%s: %s\n", zone, gettext("could not get zone brand"));
return (B_FALSE);
}
if ((bh = brand_open(brand)) == NULL) {
zerr("%s: %s\n", zone, gettext("unknown brand."));
return (B_FALSE);
}
ret = brand_allow_exclusive_ip(bh);
brand_close(bh);
if (!ret)
zerr(gettext("%s cannot be '%s' when %s is '%s'."),
pt_to_str(PT_IPTYPE), "exclusive",
pt_to_str(PT_BRAND), brand);
return (ret);
}
static void
set_aliased_rctl(char *alias, int prop_type, char *s)
{
uint64_t limit;
int err;
char tmp[128];
if (global_zone && strcmp(alias, ALIAS_SHARES) != 0)
zerr(gettext("WARNING: Setting a global zone resource "
"control too low could deny\nservice "
"to even the root user; "
"this could render the system impossible\n"
"to administer. Please use caution."));
/* convert memory based properties */
if (prop_type == PT_MAXSHMMEM) {
if (!zonecfg_valid_memlimit(s, &limit)) {
zerr(gettext("A non-negative number with a required "
"scale suffix (K, M, G or T) was expected\nhere."));
saw_error = TRUE;
return;
}
(void) snprintf(tmp, sizeof (tmp), "%llu", limit);
s = tmp;
}
if (!zonecfg_aliased_rctl_ok(handle, alias)) {
zone_perror(pt_to_str(prop_type), Z_ALIAS_DISALLOW, FALSE);
saw_error = TRUE;
} else if (!zonecfg_valid_alias_limit(alias, s, &limit)) {
zerr(gettext("%s property is out of range."),
pt_to_str(prop_type));
saw_error = TRUE;
} else if ((err = zonecfg_set_aliased_rctl(handle, alias, limit))
!= Z_OK) {
zone_perror(zone, err, TRUE);
saw_error = TRUE;
} else {
need_to_commit = TRUE;
}
}
void
set_func(cmd_t *cmd)
{
char *prop_id;
int arg, err, res_type, prop_type;
property_value_ptr_t pp;
boolean_t autoboot;
zone_iptype_t iptype;
boolean_t force_set = FALSE;
size_t physmem_size = sizeof (in_progress_mcaptab.zone_physmem_cap);
uint64_t mem_cap, mem_limit;
float cap;
char *unitp;
struct zone_psettab tmp_psettab;
bool arg_err = FALSE;
if (zone_is_read_only(CMD_SET))
return;
assert(cmd != NULL);
optind = opterr = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
switch (arg) {
case 'F':
force_set = TRUE;
break;
default:
if (optopt == '?')
longer_usage(CMD_SET);
else
short_usage(CMD_SET);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
prop_type = cmd->cmd_prop_name[0];
if (global_scope) {
if (gz_invalid_property(prop_type)) {
zerr(gettext("%s is not a valid property for the "
"global zone."), pt_to_str(prop_type));
saw_error = TRUE;
return;
}
if (prop_type == PT_ZONENAME) {
res_type = RT_ZONENAME;
} else if (prop_type == PT_ZONEPATH) {
res_type = RT_ZONEPATH;
} else if (prop_type == PT_AUTOBOOT) {
res_type = RT_AUTOBOOT;
} else if (prop_type == PT_BRAND) {
res_type = RT_BRAND;
} else if (prop_type == PT_POOL) {
res_type = RT_POOL;
} else if (prop_type == PT_LIMITPRIV) {
res_type = RT_LIMITPRIV;
} else if (prop_type == PT_BOOTARGS) {
res_type = RT_BOOTARGS;
} else if (prop_type == PT_SCHED) {
res_type = RT_SCHED;
} else if (prop_type == PT_IPTYPE) {
res_type = RT_IPTYPE;
} else if (prop_type == PT_MAXLWPS) {
res_type = RT_MAXLWPS;
} else if (prop_type == PT_MAXSHMMEM) {
res_type = RT_MAXSHMMEM;
} else if (prop_type == PT_MAXSHMIDS) {
res_type = RT_MAXSHMIDS;
} else if (prop_type == PT_MAXMSGIDS) {
res_type = RT_MAXMSGIDS;
} else if (prop_type == PT_MAXSEMIDS) {
res_type = RT_MAXSEMIDS;
} else if (prop_type == PT_SHARES) {
res_type = RT_SHARES;
} else {
zerr(gettext("Cannot set a resource-specific property "
"from the global scope."));
saw_error = TRUE;
return;
}
} else {
res_type = resource_scope;
}
if (force_set) {
if (res_type != RT_ZONEPATH) {
zerr(gettext("Only zonepath setting can be forced."));
saw_error = TRUE;
return;
}
if (!zonecfg_in_alt_root()) {
zerr(gettext("Zonepath is changeable only in an "
"alternate root."));
saw_error = TRUE;
return;
}
}
pp = cmd->cmd_property_ptr[0];
/*
* A nasty expression but not that complicated:
* 1. fs options are simple or list (tested below)
* 2. rctl value's are complex or list (tested below)
* Anything else should be simple.
*/
if (!(res_type == RT_FS && prop_type == PT_OPTIONS) &&
!(res_type == RT_RCTL && prop_type == PT_VALUE) &&
(pp->pv_type != PROP_VAL_SIMPLE ||
(prop_id = pp->pv_simple) == NULL)) {
zerr(gettext("A %s value was expected here."),
pvt_to_str(PROP_VAL_SIMPLE));
saw_error = TRUE;
return;
}
if (prop_type == PT_UNKNOWN) {
long_usage(CMD_SET, TRUE);
return;
}
/*
* Special case: the user can change the zone name prior to 'create';
* if the zone already exists, we fall through letting initialize()
* and the rest of the logic run.
*/
if (res_type == RT_ZONENAME && got_handle == FALSE &&
!state_atleast(ZONE_STATE_CONFIGURED)) {
if ((err = zonecfg_validate_zonename(prop_id)) != Z_OK) {
zone_perror(prop_id, err, TRUE);
usage(FALSE, HELP_SYNTAX);
return;
}
(void) strlcpy(zone, prop_id, sizeof (zone));
return;
}
if (initialize(TRUE) != Z_OK)
return;
switch (res_type) {
case RT_ZONENAME:
if ((err = zonecfg_set_name(handle, prop_id)) != Z_OK) {
/*
* Use prop_id instead of 'zone' here, since we're
* reporting a problem about the *new* zonename.
*/
zone_perror(prop_id, err, TRUE);
usage(FALSE, HELP_SYNTAX);
} else {
need_to_commit = TRUE;
(void) strlcpy(zone, prop_id, sizeof (zone));
}
return;
case RT_ZONEPATH:
if (!force_set && state_atleast(ZONE_STATE_INSTALLED)) {
zerr(gettext("Zone %s already installed; %s %s not "
"allowed."), zone, cmd_to_str(CMD_SET),
rt_to_str(RT_ZONEPATH));
return;
}
if (validate_zonepath_syntax(prop_id) != Z_OK) {
saw_error = TRUE;
return;
}
if ((err = zonecfg_set_zonepath(handle, prop_id)) != Z_OK)
zone_perror(zone, err, TRUE);
else
need_to_commit = TRUE;
return;
case RT_BRAND:
if (state_atleast(ZONE_STATE_INSTALLED)) {
zerr(gettext("Zone %s already installed; %s %s not "
"allowed."), zone, cmd_to_str(CMD_SET),
rt_to_str(RT_BRAND));
return;
}
if ((err = zonecfg_set_brand(handle, prop_id)) != Z_OK)
zone_perror(zone, err, TRUE);
else
need_to_commit = TRUE;
return;
case RT_AUTOBOOT:
if (strcmp(prop_id, "true") == 0) {
autoboot = B_TRUE;
} else if (strcmp(prop_id, "false") == 0) {
autoboot = B_FALSE;
} else {
zerr(gettext("%s value must be '%s' or '%s'."),
pt_to_str(PT_AUTOBOOT), "true", "false");
saw_error = TRUE;
return;
}
if ((err = zonecfg_set_autoboot(handle, autoboot)) != Z_OK)
zone_perror(zone, err, TRUE);
else
need_to_commit = TRUE;
return;
case RT_POOL:
/* don't allow use of the reserved temporary pool names */
if (strncmp("SUNW", prop_id, 4) == 0) {
zerr(gettext("pool names starting with SUNW are "
"reserved."));
saw_error = TRUE;
return;
}
/* can't set pool if dedicated-cpu exists */
if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
zerr(gettext("The %s resource already exists. "
"A persistent pool is incompatible\nwith the %s "
"resource."), rt_to_str(RT_DCPU),
rt_to_str(RT_DCPU));
saw_error = TRUE;
return;
}
if ((err = zonecfg_set_pool(handle, prop_id)) != Z_OK)
zone_perror(zone, err, TRUE);
else
need_to_commit = TRUE;
return;
case RT_LIMITPRIV:
if ((err = zonecfg_set_limitpriv(handle, prop_id)) != Z_OK)
zone_perror(zone, err, TRUE);
else
need_to_commit = TRUE;
return;
case RT_BOOTARGS:
if ((err = zonecfg_set_bootargs(handle, prop_id)) != Z_OK)
zone_perror(zone, err, TRUE);
else
need_to_commit = TRUE;
return;
case RT_SCHED:
if ((err = zonecfg_set_sched(handle, prop_id)) != Z_OK)
zone_perror(zone, err, TRUE);
else
need_to_commit = TRUE;
return;
case RT_IPTYPE:
if (strcmp(prop_id, "shared") == 0) {
iptype = ZS_SHARED;
} else if (strcmp(prop_id, "exclusive") == 0) {
iptype = ZS_EXCLUSIVE;
} else {
zerr(gettext("%s value must be '%s' or '%s'."),
pt_to_str(PT_IPTYPE), "shared", "exclusive");
saw_error = TRUE;
return;
}
if (iptype == ZS_EXCLUSIVE && !allow_exclusive()) {
saw_error = TRUE;
return;
}
if ((err = zonecfg_set_iptype(handle, iptype)) != Z_OK)
zone_perror(zone, err, TRUE);
else
need_to_commit = TRUE;
return;
case RT_MAXLWPS:
set_aliased_rctl(ALIAS_MAXLWPS, prop_type, prop_id);
return;
case RT_MAXSHMMEM:
set_aliased_rctl(ALIAS_MAXSHMMEM, prop_type, prop_id);
return;
case RT_MAXSHMIDS:
set_aliased_rctl(ALIAS_MAXSHMIDS, prop_type, prop_id);
return;
case RT_MAXMSGIDS:
set_aliased_rctl(ALIAS_MAXMSGIDS, prop_type, prop_id);
return;
case RT_MAXSEMIDS:
set_aliased_rctl(ALIAS_MAXSEMIDS, prop_type, prop_id);
return;
case RT_SHARES:
set_aliased_rctl(ALIAS_SHARES, prop_type, prop_id);
return;
case RT_FS:
switch (prop_type) {
case PT_DIR:
(void) strlcpy(in_progress_fstab.zone_fs_dir, prop_id,
sizeof (in_progress_fstab.zone_fs_dir));
return;
case PT_SPECIAL:
(void) strlcpy(in_progress_fstab.zone_fs_special,
prop_id,
sizeof (in_progress_fstab.zone_fs_special));
return;
case PT_RAW:
(void) strlcpy(in_progress_fstab.zone_fs_raw,
prop_id, sizeof (in_progress_fstab.zone_fs_raw));
return;
case PT_TYPE:
if (!valid_fs_type(prop_id)) {
zerr(gettext("\"%s\" is not a valid %s."),
prop_id, pt_to_str(PT_TYPE));
saw_error = TRUE;
return;
}
(void) strlcpy(in_progress_fstab.zone_fs_type, prop_id,
sizeof (in_progress_fstab.zone_fs_type));
return;
case PT_OPTIONS:
if (pp->pv_type != PROP_VAL_SIMPLE &&
pp->pv_type != PROP_VAL_LIST) {
zerr(gettext("A %s or %s value was expected "
"here."), pvt_to_str(PROP_VAL_SIMPLE),
pvt_to_str(PROP_VAL_LIST));
saw_error = TRUE;
return;
}
zonecfg_free_fs_option_list(
in_progress_fstab.zone_fs_options);
in_progress_fstab.zone_fs_options = NULL;
if (!(pp->pv_type == PROP_VAL_LIST &&
pp->pv_list == NULL))
add_property(cmd);
return;
default:
break;
}
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, TRUE);
long_usage(CMD_SET, TRUE);
usage(FALSE, HELP_PROPS);
return;
case RT_IPD:
switch (prop_type) {
case PT_DIR:
(void) strlcpy(in_progress_ipdtab.zone_fs_dir, prop_id,
sizeof (in_progress_ipdtab.zone_fs_dir));
return;
default:
break;
}
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, TRUE);
long_usage(CMD_SET, TRUE);
usage(FALSE, HELP_PROPS);
return;
case RT_NET:
switch (prop_type) {
case PT_ADDRESS:
if (validate_net_address_syntax(prop_id) != Z_OK) {
saw_error = TRUE;
return;
}
(void) strlcpy(in_progress_nwiftab.zone_nwif_address,
prop_id,
sizeof (in_progress_nwiftab.zone_nwif_address));
break;
case PT_PHYSICAL:
if (validate_net_physical_syntax(prop_id) != Z_OK) {
saw_error = TRUE;
return;
}
(void) strlcpy(in_progress_nwiftab.zone_nwif_physical,
prop_id,
sizeof (in_progress_nwiftab.zone_nwif_physical));
break;
default:
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
TRUE);
long_usage(CMD_SET, TRUE);
usage(FALSE, HELP_PROPS);
return;
}
return;
case RT_DEVICE:
switch (prop_type) {
case PT_MATCH:
(void) strlcpy(in_progress_devtab.zone_dev_match,
prop_id,
sizeof (in_progress_devtab.zone_dev_match));
break;
default:
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
TRUE);
long_usage(CMD_SET, TRUE);
usage(FALSE, HELP_PROPS);
return;
}
return;
case RT_RCTL:
switch (prop_type) {
case PT_NAME:
if (!zonecfg_valid_rctlname(prop_id)) {
zerr(gettext("'%s' is not a valid zone %s "
"name."), prop_id, rt_to_str(RT_RCTL));
return;
}
(void) strlcpy(in_progress_rctltab.zone_rctl_name,
prop_id,
sizeof (in_progress_rctltab.zone_rctl_name));
break;
case PT_VALUE:
if (pp->pv_type != PROP_VAL_COMPLEX &&
pp->pv_type != PROP_VAL_LIST) {
zerr(gettext("A %s or %s value was expected "
"here."), pvt_to_str(PROP_VAL_COMPLEX),
pvt_to_str(PROP_VAL_LIST));
saw_error = TRUE;
return;
}
zonecfg_free_rctl_value_list(
in_progress_rctltab.zone_rctl_valptr);
in_progress_rctltab.zone_rctl_valptr = NULL;
if (!(pp->pv_type == PROP_VAL_LIST &&
pp->pv_list == NULL))
add_property(cmd);
break;
default:
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
TRUE);
long_usage(CMD_SET, TRUE);
usage(FALSE, HELP_PROPS);
return;
}
return;
case RT_ATTR:
switch (prop_type) {
case PT_NAME:
(void) strlcpy(in_progress_attrtab.zone_attr_name,
prop_id,
sizeof (in_progress_attrtab.zone_attr_name));
break;
case PT_TYPE:
(void) strlcpy(in_progress_attrtab.zone_attr_type,
prop_id,
sizeof (in_progress_attrtab.zone_attr_type));
break;
case PT_VALUE:
(void) strlcpy(in_progress_attrtab.zone_attr_value,
prop_id,
sizeof (in_progress_attrtab.zone_attr_value));
break;
default:
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
TRUE);
long_usage(CMD_SET, TRUE);
usage(FALSE, HELP_PROPS);
return;
}
return;
case RT_DATASET:
switch (prop_type) {
case PT_NAME:
(void) strlcpy(in_progress_dstab.zone_dataset_name,
prop_id,
sizeof (in_progress_dstab.zone_dataset_name));
return;
default:
break;
}
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, TRUE);
long_usage(CMD_SET, TRUE);
usage(FALSE, HELP_PROPS);
return;
case RT_DCPU:
switch (prop_type) {
char *lowp, *highp;
case PT_NCPUS:
lowp = prop_id;
if ((highp = strchr(prop_id, '-')) != NULL)
*highp++ = '\0';
else
highp = lowp;
/* Make sure the input makes sense. */
if (!zonecfg_valid_ncpus(lowp, highp)) {
zerr(gettext("%s property is out of range."),
pt_to_str(PT_NCPUS));
saw_error = TRUE;
return;
}
(void) strlcpy(
in_progress_psettab.zone_ncpu_min, lowp,
sizeof (in_progress_psettab.zone_ncpu_min));
(void) strlcpy(
in_progress_psettab.zone_ncpu_max, highp,
sizeof (in_progress_psettab.zone_ncpu_max));
return;
case PT_IMPORTANCE:
/* Make sure the value makes sense. */
if (!zonecfg_valid_importance(prop_id)) {
zerr(gettext("%s property is out of range."),
pt_to_str(PT_IMPORTANCE));
saw_error = TRUE;
return;
}
(void) strlcpy(in_progress_psettab.zone_importance,
prop_id,
sizeof (in_progress_psettab.zone_importance));
return;
default:
break;
}
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, TRUE);
long_usage(CMD_SET, TRUE);
usage(FALSE, HELP_PROPS);
return;
case RT_PCAP:
if (prop_type != PT_NCPUS) {
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
TRUE);
long_usage(CMD_SET, TRUE);
usage(FALSE, HELP_PROPS);
return;
}
/*
* We already checked that an rctl alias is allowed in
* the add_resource() function.
*/
if ((cap = strtof(prop_id, &unitp)) <= 0 || *unitp != '\0' ||
(int)(cap * 100) < 1) {
zerr(gettext("%s property is out of range."),
pt_to_str(PT_NCPUS));
saw_error = TRUE;
return;
}
if ((err = zonecfg_set_aliased_rctl(handle, ALIAS_CPUCAP,
(int)(cap * 100))) != Z_OK)
zone_perror(zone, err, TRUE);
else
need_to_commit = TRUE;
return;
case RT_MCAP:
switch (prop_type) {
case PT_PHYSICAL:
if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
zerr(gettext("A positive number with a "
"required scale suffix (K, M, G or T) was "
"expected here."));
saw_error = TRUE;
} else if (mem_cap < ONE_MB) {
zerr(gettext("%s value is too small. It must "
"be at least 1M."), pt_to_str(PT_PHYSICAL));
saw_error = TRUE;
} else {
snprintf(in_progress_mcaptab.zone_physmem_cap,
physmem_size, "%llu", mem_cap);
}
break;
case PT_SWAP:
/*
* We have to check if an rctl is allowed here since
* there might already be a rctl defined that blocks
* the alias.
*/
if (!zonecfg_aliased_rctl_ok(handle, ALIAS_MAXSWAP)) {
zone_perror(pt_to_str(PT_MAXSWAP),
Z_ALIAS_DISALLOW, FALSE);
saw_error = TRUE;
return;
}
if (global_zone)
mem_limit = ONE_MB * 100;
else
mem_limit = ONE_MB * 50;
if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
zerr(gettext("A positive number with a "
"required scale suffix (K, M, G or T) was "
"expected here."));
saw_error = TRUE;
} else if (mem_cap < mem_limit) {
char buf[128];
(void) snprintf(buf, sizeof (buf), "%llu",
mem_limit);
bytes_to_units(buf, buf, sizeof (buf));
zerr(gettext("%s value is too small. It must "
"be at least %s."), pt_to_str(PT_SWAP),
buf);
saw_error = TRUE;
} else {
if ((err = zonecfg_set_aliased_rctl(handle,
ALIAS_MAXSWAP, mem_cap)) != Z_OK)
zone_perror(zone, err, TRUE);
else
need_to_commit = TRUE;
}
break;
case PT_LOCKED:
/*
* We have to check if an rctl is allowed here since
* there might already be a rctl defined that blocks
* the alias.
*/
if (!zonecfg_aliased_rctl_ok(handle,
ALIAS_MAXLOCKEDMEM)) {
zone_perror(pt_to_str(PT_LOCKED),
Z_ALIAS_DISALLOW, FALSE);
saw_error = TRUE;
return;
}
if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
zerr(gettext("A non-negative number with a "
"required scale suffix (K, M, G or T) was "
"expected\nhere."));
saw_error = TRUE;
} else {
if ((err = zonecfg_set_aliased_rctl(handle,
ALIAS_MAXLOCKEDMEM, mem_cap)) != Z_OK)
zone_perror(zone, err, TRUE);
else
need_to_commit = TRUE;
}
break;
default:
zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
TRUE);
long_usage(CMD_SET, TRUE);
usage(FALSE, HELP_PROPS);
return;
}
return;
default:
zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, TRUE);
long_usage(CMD_SET, TRUE);
usage(FALSE, HELP_RESOURCES);
return;
}
}
static void
output_prop(FILE *fp, int pnum, char *pval, bool print_notspec)
{
char *qstr;
if (*pval != '\0') {
qstr = quoteit(pval);
if (pnum == PT_SWAP || pnum == PT_LOCKED)
(void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(pnum),
qstr);
else
(void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);
free(qstr);
} else if (print_notspec)
(void) fprintf(fp, gettext("\t%s not specified\n"),
pt_to_str(pnum));
}
static void
info_zonename(zone_dochandle_t handle, FILE *fp)
{
char zonename[ZONENAME_MAX];
if (zonecfg_get_name(handle, zonename, sizeof (zonename)) == Z_OK)
(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONENAME),
zonename);
else
(void) fprintf(fp, gettext("%s not specified\n"),
pt_to_str(PT_ZONENAME));
}
static void
info_zonepath(zone_dochandle_t handle, FILE *fp)
{
char zonepath[MAXPATHLEN];
if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK)
(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONEPATH),
zonepath);
else {
(void) fprintf(fp, gettext("%s not specified\n"),
pt_to_str(PT_ZONEPATH));
}
}
static void
info_brand(zone_dochandle_t handle, FILE *fp)
{
char brand[MAXNAMELEN];
if (zonecfg_get_brand(handle, brand, sizeof (brand)) == Z_OK)
(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BRAND),
brand);
else
(void) fprintf(fp, "%s %s\n", pt_to_str(PT_BRAND),
gettext("not specified"));
}
static void
info_autoboot(zone_dochandle_t handle, FILE *fp)
{
boolean_t autoboot;
int err;
if ((err = zonecfg_get_autoboot(handle, &autoboot)) == Z_OK)
(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_AUTOBOOT),
autoboot ? "true" : "false");
else
zone_perror(zone, err, TRUE);
}
static void
info_pool(zone_dochandle_t handle, FILE *fp)
{
char pool[MAXNAMELEN];
int err;
if ((err = zonecfg_get_pool(handle, pool, sizeof (pool))) == Z_OK)
(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_POOL), pool);
else
zone_perror(zone, err, TRUE);
}
static void
info_limitpriv(zone_dochandle_t handle, FILE *fp)
{
char *limitpriv;
int err;
if ((err = zonecfg_get_limitpriv(handle, &limitpriv)) == Z_OK) {
(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_LIMITPRIV),
limitpriv);
free(limitpriv);
} else {
zone_perror(zone, err, TRUE);
}
}
static void
info_bootargs(zone_dochandle_t handle, FILE *fp)
{
char bootargs[BOOTARGS_MAX];
int err;
if ((err = zonecfg_get_bootargs(handle, bootargs,
sizeof (bootargs))) == Z_OK) {
(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BOOTARGS),
bootargs);
} else {
zone_perror(zone, err, TRUE);
}
}
static void
info_sched(zone_dochandle_t handle, FILE *fp)
{
char sched[MAXNAMELEN];
int err;
if ((err = zonecfg_get_sched_class(handle, sched, sizeof (sched)))
== Z_OK) {
(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_SCHED), sched);
} else {
zone_perror(zone, err, TRUE);
}
}
static void
info_iptype(zone_dochandle_t handle, FILE *fp)
{
zone_iptype_t iptype;
int err;
if ((err = zonecfg_get_iptype(handle, &iptype)) == Z_OK) {
switch (iptype) {
case ZS_SHARED:
(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
"shared");
break;
case ZS_EXCLUSIVE:
(void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
"exclusive");
break;
}
} else {
zone_perror(zone, err, TRUE);
}
}
static void
output_fs(FILE *fp, struct zone_fstab *fstab)
{
zone_fsopt_t *this;
(void) fprintf(fp, "%s:\n", rt_to_str(RT_FS));
output_prop(fp, PT_DIR, fstab->zone_fs_dir, B_TRUE);
output_prop(fp, PT_SPECIAL, fstab->zone_fs_special, B_TRUE);
output_prop(fp, PT_RAW, fstab->zone_fs_raw, B_TRUE);
output_prop(fp, PT_TYPE, fstab->zone_fs_type, B_TRUE);
(void) fprintf(fp, "\t%s: [", pt_to_str(PT_OPTIONS));
for (this = fstab->zone_fs_options; this != NULL;
this = this->zone_fsopt_next) {
if (strchr(this->zone_fsopt_opt, '='))
(void) fprintf(fp, "\"%s\"", this->zone_fsopt_opt);
else
(void) fprintf(fp, "%s", this->zone_fsopt_opt);
if (this->zone_fsopt_next != NULL)
(void) fprintf(fp, ",");
}
(void) fprintf(fp, "]\n");
}
static void
output_ipd(FILE *fp, struct zone_fstab *ipdtab)
{
(void) fprintf(fp, "%s:\n", rt_to_str(RT_IPD));
output_prop(fp, PT_DIR, ipdtab->zone_fs_dir, B_TRUE);
}
static void
info_fs(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
{
struct zone_fstab lookup, user;
bool output = FALSE;
if (zonecfg_setfsent(handle) != Z_OK)
return;
while (zonecfg_getfsent(handle, &lookup) == Z_OK) {
if (cmd->cmd_prop_nv_pairs == 0) {
output_fs(fp, &lookup);
goto loopend;
}
if (fill_in_fstab(cmd, &user, TRUE) != Z_OK)
goto loopend;
if (strlen(user.zone_fs_dir) > 0 &&
strcmp(user.zone_fs_dir, lookup.zone_fs_dir) != 0)
goto loopend; /* no match */
if (strlen(user.zone_fs_special) > 0 &&
strcmp(user.zone_fs_special, lookup.zone_fs_special) != 0)
goto loopend; /* no match */
if (strlen(user.zone_fs_type) > 0 &&
strcmp(user.zone_fs_type, lookup.zone_fs_type) != 0)
goto loopend; /* no match */
output_fs(fp, &lookup);
output = TRUE;
loopend:
zonecfg_free_fs_option_list(lookup.zone_fs_options);
}
(void) zonecfg_endfsent(handle);
/*
* If a property n/v pair was specified, warn the user if there was
* nothing to output.
*/
if (!output && cmd->cmd_prop_nv_pairs > 0)
(void) printf(gettext("No such %s resource.\n"),
rt_to_str(RT_FS));
}
static void
info_ipd(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
{
struct zone_fstab lookup, user;
bool output = FALSE;
if (zonecfg_setipdent(handle) != Z_OK)
return;
while (zonecfg_getipdent(handle, &lookup) == Z_OK) {
if (cmd->cmd_prop_nv_pairs == 0) {
output_ipd(fp, &lookup);
continue;
}
if (fill_in_ipdtab(cmd, &user, TRUE) != Z_OK)
continue;
if (strlen(user.zone_fs_dir) > 0 &&
strcmp(user.zone_fs_dir, lookup.zone_fs_dir) != 0)
continue; /* no match */
output_ipd(fp, &lookup);
output = TRUE;
}
(void) zonecfg_endipdent(handle);
/*
* If a property n/v pair was specified, warn the user if there was
* nothing to output.
*/
if (!output && cmd->cmd_prop_nv_pairs > 0)
(void) printf(gettext("No such %s resource.\n"),
rt_to_str(RT_IPD));
}
static void
output_net(FILE *fp, struct zone_nwiftab *nwiftab)
{
(void) fprintf(fp, "%s:\n", rt_to_str(RT_NET));
output_prop(fp, PT_ADDRESS, nwiftab->zone_nwif_address, B_TRUE);
output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE);
}
static void
info_net(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
{
struct zone_nwiftab lookup, user;
bool output = FALSE;
if (zonecfg_setnwifent(handle) != Z_OK)
return;
while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
if (cmd->cmd_prop_nv_pairs == 0) {
output_net(fp, &lookup);
continue;
}
if (fill_in_nwiftab(cmd, &user, TRUE) != Z_OK)
continue;
if (strlen(user.zone_nwif_physical) > 0 &&
strcmp(user.zone_nwif_physical,
lookup.zone_nwif_physical) != 0)
continue; /* no match */
/* If present make sure it matches */
if (strlen(user.zone_nwif_address) > 0 &&
!zonecfg_same_net_address(user.zone_nwif_address,
lookup.zone_nwif_address))
continue; /* no match */
output_net(fp, &lookup);
output = TRUE;
}
(void) zonecfg_endnwifent(handle);
/*
* If a property n/v pair was specified, warn the user if there was
* nothing to output.
*/
if (!output && cmd->cmd_prop_nv_pairs > 0)
(void) printf(gettext("No such %s resource.\n"),
rt_to_str(RT_NET));
}
static void
output_dev(FILE *fp, struct zone_devtab *devtab)
{
(void) fprintf(fp, "%s:\n", rt_to_str(RT_DEVICE));
output_prop(fp, PT_MATCH, devtab->zone_dev_match, B_TRUE);
}
static void
info_dev(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
{
struct zone_devtab lookup, user;
bool output = FALSE;
if (zonecfg_setdevent(handle) != Z_OK)
return;
while (zonecfg_getdevent(handle, &lookup) == Z_OK) {
if (cmd->cmd_prop_nv_pairs == 0) {
output_dev(fp, &lookup);
continue;
}
if (fill_in_devtab(cmd, &user, TRUE) != Z_OK)
continue;
if (strlen(user.zone_dev_match) > 0 &&
strcmp(user.zone_dev_match, lookup.zone_dev_match) != 0)
continue; /* no match */
output_dev(fp, &lookup);
output = TRUE;
}
(void) zonecfg_enddevent(handle);
/*
* If a property n/v pair was specified, warn the user if there was
* nothing to output.
*/
if (!output && cmd->cmd_prop_nv_pairs > 0)
(void) printf(gettext("No such %s resource.\n"),
rt_to_str(RT_DEVICE));
}
static void
output_rctl(FILE *fp, struct zone_rctltab *rctltab)
{
struct zone_rctlvaltab *valptr;
(void) fprintf(fp, "%s:\n", rt_to_str(RT_RCTL));
output_prop(fp, PT_NAME, rctltab->zone_rctl_name, B_TRUE);
for (valptr = rctltab->zone_rctl_valptr; valptr != NULL;
valptr = valptr->zone_rctlval_next) {
fprintf(fp, "\t%s: (%s=%s,%s=%s,%s=%s)\n",
pt_to_str(PT_VALUE),
pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
}
}
static void
info_rctl(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
{
struct zone_rctltab lookup, user;
bool output = FALSE;
if (zonecfg_setrctlent(handle) != Z_OK)
return;
while (zonecfg_getrctlent(handle, &lookup) == Z_OK) {
if (cmd->cmd_prop_nv_pairs == 0) {
output_rctl(fp, &lookup);
} else if (fill_in_rctltab(cmd, &user, TRUE) == Z_OK &&
(strlen(user.zone_rctl_name) == 0 ||
strcmp(user.zone_rctl_name, lookup.zone_rctl_name) == 0)) {
output_rctl(fp, &lookup);
output = TRUE;
}
zonecfg_free_rctl_value_list(lookup.zone_rctl_valptr);
}
(void) zonecfg_endrctlent(handle);
/*
* If a property n/v pair was specified, warn the user if there was
* nothing to output.
*/
if (!output && cmd->cmd_prop_nv_pairs > 0)
(void) printf(gettext("No such %s resource.\n"),
rt_to_str(RT_RCTL));
}
static void
output_attr(FILE *fp, struct zone_attrtab *attrtab)
{
(void) fprintf(fp, "%s:\n", rt_to_str(RT_ATTR));
output_prop(fp, PT_NAME, attrtab->zone_attr_name, B_TRUE);
output_prop(fp, PT_TYPE, attrtab->zone_attr_type, B_TRUE);
output_prop(fp, PT_VALUE, attrtab->zone_attr_value, B_TRUE);
}
static void
info_attr(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
{
struct zone_attrtab lookup, user;
bool output = FALSE;
if (zonecfg_setattrent(handle) != Z_OK)
return;
while (zonecfg_getattrent(handle, &lookup) == Z_OK) {
if (cmd->cmd_prop_nv_pairs == 0) {
output_attr(fp, &lookup);
continue;
}
if (fill_in_attrtab(cmd, &user, TRUE) != Z_OK)
continue;
if (strlen(user.zone_attr_name) > 0 &&
strcmp(user.zone_attr_name, lookup.zone_attr_name) != 0)
continue; /* no match */
if (strlen(user.zone_attr_type) > 0 &&
strcmp(user.zone_attr_type, lookup.zone_attr_type) != 0)
continue; /* no match */
if (strlen(user.zone_attr_value) > 0 &&
strcmp(user.zone_attr_value, lookup.zone_attr_value) != 0)
continue; /* no match */
output_attr(fp, &lookup);
output = TRUE;
}
(void) zonecfg_endattrent(handle);
/*
* If a property n/v pair was specified, warn the user if there was
* nothing to output.
*/
if (!output && cmd->cmd_prop_nv_pairs > 0)
(void) printf(gettext("No such %s resource.\n"),
rt_to_str(RT_ATTR));
}
static void
output_ds(FILE *fp, struct zone_dstab *dstab)
{
(void) fprintf(fp, "%s:\n", rt_to_str(RT_DATASET));
output_prop(fp, PT_NAME, dstab->zone_dataset_name, B_TRUE);
}
static void
info_ds(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
{
struct zone_dstab lookup, user;
bool output = FALSE;
if (zonecfg_setdsent(handle) != Z_OK)
return;
while (zonecfg_getdsent(handle, &lookup) == Z_OK) {
if (cmd->cmd_prop_nv_pairs == 0) {
output_ds(fp, &lookup);
continue;
}
if (fill_in_dstab(cmd, &user, TRUE) != Z_OK)
continue;
if (strlen(user.zone_dataset_name) > 0 &&
strcmp(user.zone_dataset_name,
lookup.zone_dataset_name) != 0)
continue; /* no match */
output_ds(fp, &lookup);
output = TRUE;
}
(void) zonecfg_enddsent(handle);
/*
* If a property n/v pair was specified, warn the user if there was
* nothing to output.
*/
if (!output && cmd->cmd_prop_nv_pairs > 0)
(void) printf(gettext("No such %s resource.\n"),
rt_to_str(RT_DATASET));
}
static void
output_pset(FILE *fp, struct zone_psettab *psettab)
{
(void) fprintf(fp, "%s:\n", rt_to_str(RT_DCPU));
if (strcmp(psettab->zone_ncpu_min, psettab->zone_ncpu_max) == 0)
(void) fprintf(fp, "\t%s: %s\n", pt_to_str(PT_NCPUS),
psettab->zone_ncpu_max);
else
(void) fprintf(fp, "\t%s: %s-%s\n", pt_to_str(PT_NCPUS),
psettab->zone_ncpu_min, psettab->zone_ncpu_max);
if (psettab->zone_importance[0] != '\0')
(void) fprintf(fp, "\t%s: %s\n", pt_to_str(PT_IMPORTANCE),
psettab->zone_importance);
}
static void
info_pset(zone_dochandle_t handle, FILE *fp)
{
struct zone_psettab lookup;
if (zonecfg_getpsetent(handle, &lookup) == Z_OK)
output_pset(fp, &lookup);
}
static void
output_pcap(FILE *fp)
{
uint64_t cap;
if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &cap) == Z_OK) {
float scaled = (float)cap / 100;
(void) fprintf(fp, "%s:\n", rt_to_str(RT_PCAP));
(void) fprintf(fp, "\t[%s: %.2f]\n", pt_to_str(PT_NCPUS),
scaled);
}
}
static void
info_pcap(FILE *fp)
{
output_pcap(fp);
}
static void
info_aliased_rctl(zone_dochandle_t handle, FILE *fp, char *alias)
{
uint64_t limit;
if (zonecfg_get_aliased_rctl(handle, alias, &limit) == Z_OK) {
/* convert memory based properties */
if (strcmp(alias, ALIAS_MAXSHMMEM) == 0) {
char buf[128];
(void) snprintf(buf, sizeof (buf), "%llu", limit);
bytes_to_units(buf, buf, sizeof (buf));
(void) fprintf(fp, "[%s: %s]\n", alias, buf);
return;
}
(void) fprintf(fp, "[%s: %llu]\n", alias, limit);
}
}
static void
bytes_to_units(char *str, char *buf, int bufsize)
{
unsigned long long num;
unsigned long long save = 0;
char *units = "BKMGT";
char *up = units;
num = strtoll(str, NULL, 10);
if (num < 1024) {
(void) snprintf(buf, bufsize, "%llu", num);
return;
}
while ((num >= 1024) && (*up != 'T')) {
up++; /* next unit of measurement */
save = num;
num = (num + 512) >> 10;
}
/* check if we should output a fraction. snprintf will round for us */
if (save % 1024 != 0 && ((save >> 10) < 10))
(void) snprintf(buf, bufsize, "%2.1f%c", ((float)save / 1024),
*up);
else
(void) snprintf(buf, bufsize, "%llu%c", num, *up);
}
static void
output_mcap(FILE *fp, struct zone_mcaptab *mcaptab, int showswap,
uint64_t maxswap, int showlocked, uint64_t maxlocked)
{
char buf[128];
(void) fprintf(fp, "%s:\n", rt_to_str(RT_MCAP));
if (mcaptab->zone_physmem_cap[0] != '\0') {
bytes_to_units(mcaptab->zone_physmem_cap, buf, sizeof (buf));
output_prop(fp, PT_PHYSICAL, buf, B_TRUE);
}
if (showswap == Z_OK) {
(void) snprintf(buf, sizeof (buf), "%llu", maxswap);
bytes_to_units(buf, buf, sizeof (buf));
output_prop(fp, PT_SWAP, buf, B_TRUE);
}
if (showlocked == Z_OK) {
(void) snprintf(buf, sizeof (buf), "%llu", maxlocked);
bytes_to_units(buf, buf, sizeof (buf));
output_prop(fp, PT_LOCKED, buf, B_TRUE);
}
}
static void
info_mcap(zone_dochandle_t handle, FILE *fp)
{
int res1, res2, res3;
uint64_t swap_limit;
uint64_t locked_limit;
struct zone_mcaptab lookup;
bzero(&lookup, sizeof (lookup));
res1 = zonecfg_getmcapent(handle, &lookup);
res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
&locked_limit);
if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
}
void
info_func(cmd_t *cmd)
{
FILE *fp = stdout;
bool need_to_close = FALSE;
char *pager;
int type;
int res1, res2;
uint64_t swap_limit;
uint64_t locked_limit;
assert(cmd != NULL);
if (initialize(TRUE) != Z_OK)
return;
/* don't page error output */
if (interactive_mode) {
if ((pager = getenv("PAGER")) == NULL)
pager = PAGER;
if ((fp = popen(pager, "w")) != NULL)
need_to_close = TRUE;
setbuf(fp, NULL);
}
if (!global_scope) {
switch (resource_scope) {
case RT_FS:
output_fs(fp, &in_progress_fstab);
break;
case RT_IPD:
output_ipd(fp, &in_progress_ipdtab);
break;
case RT_NET:
output_net(fp, &in_progress_nwiftab);
break;
case RT_DEVICE:
output_dev(fp, &in_progress_devtab);
break;
case RT_RCTL:
output_rctl(fp, &in_progress_rctltab);
break;
case RT_ATTR:
output_attr(fp, &in_progress_attrtab);
break;
case RT_DATASET:
output_ds(fp, &in_progress_dstab);
break;
case RT_DCPU:
output_pset(fp, &in_progress_psettab);
break;
case RT_PCAP:
output_pcap(fp);
break;
case RT_MCAP:
res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
&swap_limit);
res2 = zonecfg_get_aliased_rctl(handle,
ALIAS_MAXLOCKEDMEM, &locked_limit);
output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
res2, locked_limit);
break;
}
goto cleanup;
}
type = cmd->cmd_res_type;
if (gz_invalid_rt_property(type)) {
zerr(gettext("%s is not a valid property for the global zone."),
rt_to_str(type));
goto cleanup;
}
if (gz_invalid_resource(type)) {
zerr(gettext("%s is not a valid resource for the global zone."),
rt_to_str(type));
goto cleanup;
}
switch (cmd->cmd_res_type) {
case RT_UNKNOWN:
info_zonename(handle, fp);
if (!global_zone) {
info_zonepath(handle, fp);
info_brand(handle, fp);
info_autoboot(handle, fp);
info_bootargs(handle, fp);
}
info_pool(handle, fp);
if (!global_zone) {
info_limitpriv(handle, fp);
info_sched(handle, fp);
info_iptype(handle, fp);
}
info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
info_aliased_rctl(handle, fp, ALIAS_SHARES);
if (!global_zone) {
info_ipd(handle, fp, cmd);
info_fs(handle, fp, cmd);
info_net(handle, fp, cmd);
info_dev(handle, fp, cmd);
}
info_pset(handle, fp);
info_pcap(fp);
info_mcap(handle, fp);
if (!global_zone) {
info_attr(handle, fp, cmd);
info_ds(handle, fp, cmd);
}
info_rctl(handle, fp, cmd);
break;
case RT_ZONENAME:
info_zonename(handle, fp);
break;
case RT_ZONEPATH:
info_zonepath(handle, fp);
break;
case RT_BRAND:
info_brand(handle, fp);
break;
case RT_AUTOBOOT:
info_autoboot(handle, fp);
break;
case RT_POOL:
info_pool(handle, fp);
break;
case RT_LIMITPRIV:
info_limitpriv(handle, fp);
break;
case RT_BOOTARGS:
info_bootargs(handle, fp);
break;
case RT_SCHED:
info_sched(handle, fp);
break;
case RT_IPTYPE:
info_iptype(handle, fp);
break;
case RT_MAXLWPS:
info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
break;
case RT_MAXSHMMEM:
info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
break;
case RT_MAXSHMIDS:
info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
break;
case RT_MAXMSGIDS:
info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
break;
case RT_MAXSEMIDS:
info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
break;
case RT_SHARES:
info_aliased_rctl(handle, fp, ALIAS_SHARES);
break;
case RT_FS:
info_fs(handle, fp, cmd);
break;
case RT_IPD:
info_ipd(handle, fp, cmd);
break;
case RT_NET:
info_net(handle, fp, cmd);
break;
case RT_DEVICE:
info_dev(handle, fp, cmd);
break;
case RT_RCTL:
info_rctl(handle, fp, cmd);
break;
case RT_ATTR:
info_attr(handle, fp, cmd);
break;
case RT_DATASET:
info_ds(handle, fp, cmd);
break;
case RT_DCPU:
info_pset(handle, fp);
break;
case RT_PCAP:
info_pcap(fp);
break;
case RT_MCAP:
info_mcap(handle, fp);
break;
default:
zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
TRUE);
}
cleanup:
if (need_to_close)
(void) pclose(fp);
}
/*
* Helper function for verify-- checks that a required string property
* exists.
*/
static void
check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
{
if (strlen(attr) == 0) {
zerr(gettext("%s: %s not specified"), rt_to_str(rt),
pt_to_str(pt));
saw_error = TRUE;
if (*ret_val == Z_OK)
*ret_val = Z_REQD_PROPERTY_MISSING;
}
}
static int
do_subproc(char *cmdbuf)
{
char inbuf[MAX_CMD_LEN];
FILE *file;
int status;
file = popen(cmdbuf, "r");
if (file == NULL) {
zerr(gettext("Could not launch: %s"), cmdbuf);
return (-1);
}
while (fgets(inbuf, sizeof (inbuf), file) != NULL)
fprintf(stderr, "%s", inbuf);
status = pclose(file);
if (WIFSIGNALED(status)) {
zerr(gettext("%s unexpectedly terminated due to signal %d"),
cmdbuf, WTERMSIG(status));
return (-1);
}
assert(WIFEXITED(status));
return (WEXITSTATUS(status));
}
static int
brand_verify(zone_dochandle_t handle)
{
char xml_file[32];
char cmdbuf[MAX_CMD_LEN];
brand_handle_t bh;
char brand[MAXNAMELEN];
int err;
if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
zerr("%s: %s\n", zone, gettext("could not get zone brand"));
return (Z_INVALID_DOCUMENT);
}
if ((bh = brand_open(brand)) == NULL) {
zerr("%s: %s\n", zone, gettext("unknown brand."));
return (Z_INVALID_DOCUMENT);
}
/*
* Fetch the verify command, if any, from the brand configuration
* and build the command line to execute it.
*/
strcpy(cmdbuf, EXEC_PREFIX);
err = brand_get_verify_cfg(bh, cmdbuf + EXEC_LEN,
sizeof (cmdbuf) - (EXEC_LEN + (strlen(xml_file) + 1)));
brand_close(bh);
if (err != Z_OK) {
zerr("%s: %s\n", zone,
gettext("could not get brand verification command"));
return (Z_INVALID_DOCUMENT);
}
/*
* If the brand doesn't provide a verification routine, we just
* return success.
*/
if (strlen(cmdbuf) == EXEC_LEN)
return (Z_OK);
/*
* Dump the current config information for this zone to a file.
*/
strcpy(xml_file, "/tmp/zonecfg_verify.XXXXXX");
if (mkstemp(xml_file) == NULL)
return (Z_TEMP_FILE);
if ((err = zonecfg_verify_save(handle, xml_file)) != Z_OK) {
(void) unlink(xml_file);
return (err);
}
/*
* Execute the verification command.
*/
if ((strlcat(cmdbuf, " ", MAX_CMD_LEN) >= MAX_CMD_LEN) ||
(strlcat(cmdbuf, xml_file, MAX_CMD_LEN) >= MAX_CMD_LEN)) {
err = Z_BRAND_ERROR;
} else {
err = do_subproc(cmdbuf);
}
(void) unlink(xml_file);
return ((err == Z_OK) ? Z_OK : Z_BRAND_ERROR);
}
/*
* See the DTD for which attributes are required for which resources.
*
* This function can be called by commit_func(), which needs to save things,
* in addition to the general call from parse_and_run(), which doesn't need
* things saved. Since the parameters are standardized, we distinguish by
* having commit_func() call here with cmd->cmd_arg set to "save" to indicate
* that a save is needed.
*/
void
verify_func(cmd_t *cmd)
{
struct zone_nwiftab nwiftab;
struct zone_fstab fstab;
struct zone_attrtab attrtab;
struct zone_rctltab rctltab;
struct zone_dstab dstab;
struct zone_psettab psettab;
char zonepath[MAXPATHLEN];
char sched[MAXNAMELEN];
char brand[MAXNAMELEN];
int err, ret_val = Z_OK, arg;
int pset_res;
bool save = FALSE;
bool arg_err = FALSE;
zone_iptype_t iptype;
boolean_t has_cpu_shares = B_FALSE;
boolean_t has_cpu_cap = B_FALSE;
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
switch (arg) {
case '?':
longer_usage(CMD_VERIFY);
arg_err = TRUE;
break;
default:
short_usage(CMD_VERIFY);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
if (optind > cmd->cmd_argc) {
short_usage(CMD_VERIFY);
return;
}
if (zone_is_read_only(CMD_VERIFY))
return;
assert(cmd != NULL);
if (cmd->cmd_argc > 0 && (strcmp(cmd->cmd_argv[0], "save") == 0))
save = TRUE;
if (initialize(TRUE) != Z_OK)
return;
if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) != Z_OK &&
!global_zone) {
zerr(gettext("%s not specified"), pt_to_str(PT_ZONEPATH));
ret_val = Z_REQD_RESOURCE_MISSING;
saw_error = TRUE;
}
if (strlen(zonepath) == 0 && !global_zone) {
zerr(gettext("%s cannot be empty."), pt_to_str(PT_ZONEPATH));
ret_val = Z_REQD_RESOURCE_MISSING;
saw_error = TRUE;
}
if ((err = zonecfg_get_brand(handle, brand, sizeof (brand))) != Z_OK) {
zone_perror(zone, err, TRUE);
return;
}
if (strcmp(brand, NATIVE_BRAND_NAME) != 0) {
if ((err = brand_verify(handle)) != Z_OK) {
zone_perror(zone, err, TRUE);
return;
}
}
if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
zerr("%s %s", gettext("cannot get"), pt_to_str(PT_IPTYPE));
ret_val = Z_REQD_RESOURCE_MISSING;
saw_error = TRUE;
}
if ((err = zonecfg_setipdent(handle)) != Z_OK) {
zone_perror(zone, err, TRUE);
return;
}
while (zonecfg_getipdent(handle, &fstab) == Z_OK) {
check_reqd_prop(fstab.zone_fs_dir, RT_IPD, PT_DIR, &ret_val);
}
(void) zonecfg_endipdent(handle);
if ((err = zonecfg_setfsent(handle)) != Z_OK) {
zone_perror(zone, err, TRUE);
return;
}
while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
check_reqd_prop(fstab.zone_fs_dir, RT_FS, PT_DIR, &ret_val);
check_reqd_prop(fstab.zone_fs_special, RT_FS, PT_SPECIAL,
&ret_val);
check_reqd_prop(fstab.zone_fs_type, RT_FS, PT_TYPE, &ret_val);
zonecfg_free_fs_option_list(fstab.zone_fs_options);
}
(void) zonecfg_endfsent(handle);
if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
zone_perror(zone, err, TRUE);
return;
}
while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
/*
* physical is required in all cases.
* A shared IP requires an address, while
* an exclusive IP must not have an address.
*/
check_reqd_prop(nwiftab.zone_nwif_physical, RT_NET,
PT_PHYSICAL, &ret_val);
switch (iptype) {
case ZS_SHARED:
check_reqd_prop(nwiftab.zone_nwif_address, RT_NET,
PT_ADDRESS, &ret_val);
break;
case ZS_EXCLUSIVE:
if (strlen(nwiftab.zone_nwif_address) > 0) {
zerr(gettext("%s: %s cannot be specified "
"for an exclusive IP type"),
rt_to_str(RT_NET), pt_to_str(PT_ADDRESS));
saw_error = TRUE;
if (ret_val == Z_OK)
ret_val = Z_INVAL;
}
break;
}
}
(void) zonecfg_endnwifent(handle);
if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
zone_perror(zone, err, TRUE);
return;
}
while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
check_reqd_prop(rctltab.zone_rctl_name, RT_RCTL, PT_NAME,
&ret_val);
if (strcmp(rctltab.zone_rctl_name, "zone.cpu-shares") == 0)
has_cpu_shares = B_TRUE;
if (strcmp(rctltab.zone_rctl_name, "zone.cpu-cap") == 0)
has_cpu_cap = B_TRUE;
if (rctltab.zone_rctl_valptr == NULL) {
zerr(gettext("%s: no %s specified"),
rt_to_str(RT_RCTL), pt_to_str(PT_VALUE));
saw_error = TRUE;
if (ret_val == Z_OK)
ret_val = Z_REQD_PROPERTY_MISSING;
} else {
zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
}
}
(void) zonecfg_endrctlent(handle);
if ((pset_res = zonecfg_lookup_pset(handle, &psettab)) == Z_OK &&
has_cpu_shares) {
zerr(gettext("%s zone.cpu-shares and %s are incompatible."),
rt_to_str(RT_RCTL), rt_to_str(RT_DCPU));
saw_error = TRUE;
if (ret_val == Z_OK)
ret_val = Z_INCOMPATIBLE;
}
if (has_cpu_shares && zonecfg_get_sched_class(handle, sched,
sizeof (sched)) == Z_OK && strlen(sched) > 0 &&
strcmp(sched, "FSS") != 0) {
zerr(gettext("WARNING: %s zone.cpu-shares and %s=%s are "
"incompatible"),
rt_to_str(RT_RCTL), rt_to_str(RT_SCHED), sched);
saw_error = TRUE;
if (ret_val == Z_OK)
ret_val = Z_INCOMPATIBLE;
}
if (pset_res == Z_OK && has_cpu_cap) {
zerr(gettext("%s zone.cpu-cap and the %s are incompatible."),
rt_to_str(RT_RCTL), rt_to_str(RT_DCPU));
saw_error = TRUE;
if (ret_val == Z_OK)
ret_val = Z_INCOMPATIBLE;
}
if ((err = zonecfg_setattrent(handle)) != Z_OK) {
zone_perror(zone, err, TRUE);
return;
}
while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
check_reqd_prop(attrtab.zone_attr_name, RT_ATTR, PT_NAME,
&ret_val);
check_reqd_prop(attrtab.zone_attr_type, RT_ATTR, PT_TYPE,
&ret_val);
check_reqd_prop(attrtab.zone_attr_value, RT_ATTR, PT_VALUE,
&ret_val);
}
(void) zonecfg_endattrent(handle);
if ((err = zonecfg_setdsent(handle)) != Z_OK) {
zone_perror(zone, err, TRUE);
return;
}
while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
if (strlen(dstab.zone_dataset_name) == 0) {
zerr("%s: %s %s", rt_to_str(RT_DATASET),
pt_to_str(PT_NAME), gettext("not specified"));
saw_error = TRUE;
if (ret_val == Z_OK)
ret_val = Z_REQD_PROPERTY_MISSING;
} else if (!zfs_name_valid(dstab.zone_dataset_name,
ZFS_TYPE_FILESYSTEM)) {
zerr("%s: %s %s", rt_to_str(RT_DATASET),
pt_to_str(PT_NAME), gettext("invalid"));
saw_error = TRUE;
if (ret_val == Z_OK)
ret_val = Z_BAD_PROPERTY;
}
}
(void) zonecfg_enddsent(handle);
if (!global_scope) {
zerr(gettext("resource specification incomplete"));
saw_error = TRUE;
if (ret_val == Z_OK)
ret_val = Z_INSUFFICIENT_SPEC;
}
if (save) {
if (ret_val == Z_OK) {
if ((ret_val = zonecfg_save(handle)) == Z_OK) {
need_to_commit = FALSE;
(void) strlcpy(revert_zone, zone,
sizeof (revert_zone));
}
} else {
zerr(gettext("Zone %s failed to verify"), zone);
}
}
if (ret_val != Z_OK)
zone_perror(zone, ret_val, TRUE);
}
void
cancel_func(cmd_t *cmd)
{
int arg;
bool arg_err = FALSE;
assert(cmd != NULL);
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
switch (arg) {
case '?':
longer_usage(CMD_CANCEL);
arg_err = TRUE;
break;
default:
short_usage(CMD_CANCEL);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
if (optind != cmd->cmd_argc) {
short_usage(CMD_CANCEL);
return;
}
if (global_scope)
scope_usage(CMD_CANCEL);
global_scope = TRUE;
zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
bzero(&in_progress_fstab, sizeof (in_progress_fstab));
bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
bzero(&in_progress_ipdtab, sizeof (in_progress_ipdtab));
bzero(&in_progress_devtab, sizeof (in_progress_devtab));
zonecfg_free_rctl_value_list(in_progress_rctltab.zone_rctl_valptr);
bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
bzero(&in_progress_dstab, sizeof (in_progress_dstab));
}
static int
validate_attr_name(char *name)
{
int i;
if (!isalnum(name[0])) {
zerr(gettext("Invalid %s %s %s: must start with an alpha-"
"numeric character."), rt_to_str(RT_ATTR),
pt_to_str(PT_NAME), name);
return (Z_INVAL);
}
for (i = 1; name[i]; i++)
if (!isalnum(name[i]) && name[i] != '-' && name[i] != '.') {
zerr(gettext("Invalid %s %s %s: can only contain "
"alpha-numeric characters, plus '-' and '.'."),
rt_to_str(RT_ATTR), pt_to_str(PT_NAME), name);
return (Z_INVAL);
}
return (Z_OK);
}
static int
validate_attr_type_val(struct zone_attrtab *attrtab)
{
boolean_t boolval;
int64_t intval;
char strval[MAXNAMELEN];
uint64_t uintval;
if (strcmp(attrtab->zone_attr_type, "boolean") == 0) {
if (zonecfg_get_attr_boolean(attrtab, &boolval) == Z_OK)
return (Z_OK);
zerr(gettext("invalid %s value for %s=%s"),
rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "boolean");
return (Z_ERR);
}
if (strcmp(attrtab->zone_attr_type, "int") == 0) {
if (zonecfg_get_attr_int(attrtab, &intval) == Z_OK)
return (Z_OK);
zerr(gettext("invalid %s value for %s=%s"),
rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "int");
return (Z_ERR);
}
if (strcmp(attrtab->zone_attr_type, "string") == 0) {
if (zonecfg_get_attr_string(attrtab, strval,
sizeof (strval)) == Z_OK)
return (Z_OK);
zerr(gettext("invalid %s value for %s=%s"),
rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "string");
return (Z_ERR);
}
if (strcmp(attrtab->zone_attr_type, "uint") == 0) {
if (zonecfg_get_attr_uint(attrtab, &uintval) == Z_OK)
return (Z_OK);
zerr(gettext("invalid %s value for %s=%s"),
rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "uint");
return (Z_ERR);
}
zerr(gettext("invalid %s %s '%s'"), rt_to_str(RT_ATTR),
pt_to_str(PT_TYPE), attrtab->zone_attr_type);
return (Z_ERR);
}
/*
* Helper function for end_func-- checks the existence of a given property
* and emits a message if not specified.
*/
static int
end_check_reqd(char *attr, int pt, bool *validation_failed)
{
if (strlen(attr) == 0) {
*validation_failed = TRUE;
zerr(gettext("%s not specified"), pt_to_str(pt));
return (Z_ERR);
}
return (Z_OK);
}
void
end_func(cmd_t *cmd)
{
bool validation_failed = FALSE;
bool arg_err = FALSE;
struct zone_fstab tmp_fstab;
struct zone_nwiftab tmp_nwiftab;
struct zone_devtab tmp_devtab;
struct zone_rctltab tmp_rctltab;
struct zone_attrtab tmp_attrtab;
struct zone_dstab tmp_dstab;
int err, arg, res1, res2, res3;
uint64_t swap_limit;
uint64_t locked_limit;
uint64_t proc_cap;
assert(cmd != NULL);
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
switch (arg) {
case '?':
longer_usage(CMD_END);
arg_err = TRUE;
break;
default:
short_usage(CMD_END);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
if (optind != cmd->cmd_argc) {
short_usage(CMD_END);
return;
}
if (global_scope) {
scope_usage(CMD_END);
return;
}
assert(end_op == CMD_ADD || end_op == CMD_SELECT);
switch (resource_scope) {
case RT_FS:
/* First make sure everything was filled in. */
if (end_check_reqd(in_progress_fstab.zone_fs_dir,
PT_DIR, &validation_failed) == Z_OK) {
if (in_progress_fstab.zone_fs_dir[0] != '/') {
zerr(gettext("%s %s is not an absolute path."),
pt_to_str(PT_DIR),
in_progress_fstab.zone_fs_dir);
validation_failed = TRUE;
}
}
(void) end_check_reqd(in_progress_fstab.zone_fs_special,
PT_SPECIAL, &validation_failed);
if (in_progress_fstab.zone_fs_raw[0] != '\0' &&
in_progress_fstab.zone_fs_raw[0] != '/') {
zerr(gettext("%s %s is not an absolute path."),
pt_to_str(PT_RAW),
in_progress_fstab.zone_fs_raw);
validation_failed = TRUE;
}
(void) end_check_reqd(in_progress_fstab.zone_fs_type, PT_TYPE,
&validation_failed);
if (validation_failed) {
saw_error = TRUE;
return;
}
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
bzero(&tmp_fstab, sizeof (tmp_fstab));
(void) strlcpy(tmp_fstab.zone_fs_dir,
in_progress_fstab.zone_fs_dir,
sizeof (tmp_fstab.zone_fs_dir));
err = zonecfg_lookup_filesystem(handle, &tmp_fstab);
zonecfg_free_fs_option_list(tmp_fstab.zone_fs_options);
if (err == Z_OK) {
zerr(gettext("A %s resource "
"with the %s '%s' already exists."),
rt_to_str(RT_FS), pt_to_str(PT_DIR),
in_progress_fstab.zone_fs_dir);
saw_error = TRUE;
return;
}
err = zonecfg_add_filesystem(handle,
&in_progress_fstab);
} else {
err = zonecfg_modify_filesystem(handle, &old_fstab,
&in_progress_fstab);
}
zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
in_progress_fstab.zone_fs_options = NULL;
break;
case RT_IPD:
/* First make sure everything was filled in. */
if (end_check_reqd(in_progress_ipdtab.zone_fs_dir, PT_DIR,
&validation_failed) == Z_OK) {
if (in_progress_ipdtab.zone_fs_dir[0] != '/') {
zerr(gettext("%s %s is not an absolute path."),
pt_to_str(PT_DIR),
in_progress_ipdtab.zone_fs_dir);
validation_failed = TRUE;
}
}
if (validation_failed) {
saw_error = TRUE;
return;
}
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
bzero(&tmp_fstab, sizeof (tmp_fstab));
(void) strlcpy(tmp_fstab.zone_fs_dir,
in_progress_ipdtab.zone_fs_dir,
sizeof (tmp_fstab.zone_fs_dir));
err = zonecfg_lookup_ipd(handle, &tmp_fstab);
if (err == Z_OK) {
zerr(gettext("An %s resource "
"with the %s '%s' already exists."),
rt_to_str(RT_IPD), pt_to_str(PT_DIR),
in_progress_ipdtab.zone_fs_dir);
saw_error = TRUE;
return;
}
err = zonecfg_add_ipd(handle, &in_progress_ipdtab);
} else {
err = zonecfg_modify_ipd(handle, &old_ipdtab,
&in_progress_ipdtab);
}
break;
case RT_NET:
/*
* First make sure everything was filled in.
* Since we don't know whether IP will be shared
* or exclusive here, some checks are deferred until
* the verify command.
*/
(void) end_check_reqd(in_progress_nwiftab.zone_nwif_physical,
PT_PHYSICAL, &validation_failed);
if (validation_failed) {
saw_error = TRUE;
return;
}
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
bzero(&tmp_nwiftab, sizeof (tmp_nwiftab));
(void) strlcpy(tmp_nwiftab.zone_nwif_physical,
in_progress_nwiftab.zone_nwif_physical,
sizeof (tmp_nwiftab.zone_nwif_physical));
(void) strlcpy(tmp_nwiftab.zone_nwif_address,
in_progress_nwiftab.zone_nwif_address,
sizeof (tmp_nwiftab.zone_nwif_address));
if (zonecfg_lookup_nwif(handle, &tmp_nwiftab) == Z_OK) {
zerr(gettext("A %s resource with the %s '%s', "
"and %s '%s' already exists."),
rt_to_str(RT_NET),
pt_to_str(PT_PHYSICAL),
in_progress_nwiftab.zone_nwif_physical,
pt_to_str(PT_ADDRESS),
in_progress_nwiftab.zone_nwif_address);
saw_error = TRUE;
return;
}
err = zonecfg_add_nwif(handle, &in_progress_nwiftab);
} else {
err = zonecfg_modify_nwif(handle, &old_nwiftab,
&in_progress_nwiftab);
}
break;
case RT_DEVICE:
/* First make sure everything was filled in. */
(void) end_check_reqd(in_progress_devtab.zone_dev_match,
PT_MATCH, &validation_failed);
if (validation_failed) {
saw_error = TRUE;
return;
}
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
(void) strlcpy(tmp_devtab.zone_dev_match,
in_progress_devtab.zone_dev_match,
sizeof (tmp_devtab.zone_dev_match));
if (zonecfg_lookup_dev(handle, &tmp_devtab) == Z_OK) {
zerr(gettext("A %s resource with the %s '%s' "
"already exists."), rt_to_str(RT_DEVICE),
pt_to_str(PT_MATCH),
in_progress_devtab.zone_dev_match);
saw_error = TRUE;
return;
}
err = zonecfg_add_dev(handle, &in_progress_devtab);
} else {
err = zonecfg_modify_dev(handle, &old_devtab,
&in_progress_devtab);
}
break;
case RT_RCTL:
/* First make sure everything was filled in. */
(void) end_check_reqd(in_progress_rctltab.zone_rctl_name,
PT_NAME, &validation_failed);
if (in_progress_rctltab.zone_rctl_valptr == NULL) {
zerr(gettext("no %s specified"), pt_to_str(PT_VALUE));
validation_failed = TRUE;
}
if (validation_failed) {
saw_error = TRUE;
return;
}
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
(void) strlcpy(tmp_rctltab.zone_rctl_name,
in_progress_rctltab.zone_rctl_name,
sizeof (tmp_rctltab.zone_rctl_name));
tmp_rctltab.zone_rctl_valptr = NULL;
err = zonecfg_lookup_rctl(handle, &tmp_rctltab);
zonecfg_free_rctl_value_list(
tmp_rctltab.zone_rctl_valptr);
if (err == Z_OK) {
zerr(gettext("A %s resource "
"with the %s '%s' already exists."),
rt_to_str(RT_RCTL), pt_to_str(PT_NAME),
in_progress_rctltab.zone_rctl_name);
saw_error = TRUE;
return;
}
err = zonecfg_add_rctl(handle, &in_progress_rctltab);
} else {
err = zonecfg_modify_rctl(handle, &old_rctltab,
&in_progress_rctltab);
}
if (err == Z_OK) {
zonecfg_free_rctl_value_list(
in_progress_rctltab.zone_rctl_valptr);
in_progress_rctltab.zone_rctl_valptr = NULL;
}
break;
case RT_ATTR:
/* First make sure everything was filled in. */
(void) end_check_reqd(in_progress_attrtab.zone_attr_name,
PT_NAME, &validation_failed);
(void) end_check_reqd(in_progress_attrtab.zone_attr_type,
PT_TYPE, &validation_failed);
(void) end_check_reqd(in_progress_attrtab.zone_attr_value,
PT_VALUE, &validation_failed);
if (validate_attr_name(in_progress_attrtab.zone_attr_name) !=
Z_OK)
validation_failed = TRUE;
if (validate_attr_type_val(&in_progress_attrtab) != Z_OK)
validation_failed = TRUE;
if (validation_failed) {
saw_error = TRUE;
return;
}
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
bzero(&tmp_attrtab, sizeof (tmp_attrtab));
(void) strlcpy(tmp_attrtab.zone_attr_name,
in_progress_attrtab.zone_attr_name,
sizeof (tmp_attrtab.zone_attr_name));
if (zonecfg_lookup_attr(handle, &tmp_attrtab) == Z_OK) {
zerr(gettext("An %s resource "
"with the %s '%s' already exists."),
rt_to_str(RT_ATTR), pt_to_str(PT_NAME),
in_progress_attrtab.zone_attr_name);
saw_error = TRUE;
return;
}
err = zonecfg_add_attr(handle, &in_progress_attrtab);
} else {
err = zonecfg_modify_attr(handle, &old_attrtab,
&in_progress_attrtab);
}
break;
case RT_DATASET:
/* First make sure everything was filled in. */
if (strlen(in_progress_dstab.zone_dataset_name) == 0) {
zerr("%s %s", pt_to_str(PT_NAME),
gettext("not specified"));
saw_error = TRUE;
validation_failed = TRUE;
}
if (validation_failed)
return;
if (end_op == CMD_ADD) {
/* Make sure there isn't already one like this. */
bzero(&tmp_dstab, sizeof (tmp_dstab));
(void) strlcpy(tmp_dstab.zone_dataset_name,
in_progress_dstab.zone_dataset_name,
sizeof (tmp_dstab.zone_dataset_name));
err = zonecfg_lookup_ds(handle, &tmp_dstab);
if (err == Z_OK) {
zerr(gettext("A %s resource "
"with the %s '%s' already exists."),
rt_to_str(RT_DATASET), pt_to_str(PT_NAME),
in_progress_dstab.zone_dataset_name);
saw_error = TRUE;
return;
}
err = zonecfg_add_ds(handle, &in_progress_dstab);
} else {
err = zonecfg_modify_ds(handle, &old_dstab,
&in_progress_dstab);
}
break;
case RT_DCPU:
/* Make sure everything was filled in. */
if (end_check_reqd(in_progress_psettab.zone_ncpu_min,
PT_NCPUS, &validation_failed) != Z_OK) {
saw_error = TRUE;
return;
}
if (end_op == CMD_ADD) {
err = zonecfg_add_pset(handle, &in_progress_psettab);
} else {
err = zonecfg_modify_pset(handle, &in_progress_psettab);
}
break;
case RT_PCAP:
/* Make sure everything was filled in. */
if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &proc_cap)
!= Z_OK) {
zerr(gettext("%s not specified"), pt_to_str(PT_NCPUS));
saw_error = TRUE;
validation_failed = TRUE;
return;
}
err = Z_OK;
break;
case RT_MCAP:
/* Make sure everything was filled in. */
res1 = strlen(in_progress_mcaptab.zone_physmem_cap) == 0 ?
Z_ERR : Z_OK;
res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
&swap_limit);
res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
&locked_limit);
if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
zerr(gettext("No property was specified. One of %s, "
"%s or %s is required."), pt_to_str(PT_PHYSICAL),
pt_to_str(PT_SWAP), pt_to_str(PT_LOCKED));
saw_error = TRUE;
return;
}
/* if phys & locked are both set, verify locked <= phys */
if (res1 == Z_OK && res3 == Z_OK) {
uint64_t phys_limit;
char *endp;
phys_limit = strtoull(
in_progress_mcaptab.zone_physmem_cap, &endp, 10);
if (phys_limit < locked_limit) {
zerr(gettext("The %s cap must be less than or "
"equal to the %s cap."),
pt_to_str(PT_LOCKED),
pt_to_str(PT_PHYSICAL));
saw_error = TRUE;
return;
}
}
err = Z_OK;
if (res1 == Z_OK) {
/*
* We could be ending from either an add operation
* or a select operation. Since all of the properties
* within this resource are optional, we always use
* modify on the mcap entry. zonecfg_modify_mcap()
* will handle both adding and modifying a memory cap.
*/
err = zonecfg_modify_mcap(handle, &in_progress_mcaptab);
} else if (end_op == CMD_SELECT) {
/*
* If we're ending from a select and the physical
* memory cap is empty then the user could have cleared
* the physical cap value, so try to delete the entry.
*/
(void) zonecfg_delete_mcap(handle);
}
break;
default:
zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
TRUE);
saw_error = TRUE;
return;
}
if (err != Z_OK) {
zone_perror(zone, err, TRUE);
} else {
need_to_commit = TRUE;
global_scope = TRUE;
end_op = -1;
}
}
void
commit_func(cmd_t *cmd)
{
int arg;
bool arg_err = FALSE;
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
switch (arg) {
case '?':
longer_usage(CMD_COMMIT);
arg_err = TRUE;
break;
default:
short_usage(CMD_COMMIT);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
if (optind != cmd->cmd_argc) {
short_usage(CMD_COMMIT);
return;
}
if (zone_is_read_only(CMD_COMMIT))
return;
assert(cmd != NULL);
cmd->cmd_argc = 1;
/*
* cmd_arg normally comes from a strdup() in the lexer, and the
* whole cmd structure and its (char *) attributes are freed at
* the completion of each command, so the strdup() below is needed
* to match this and prevent a core dump from trying to free()
* something that can't be.
*/
if ((cmd->cmd_argv[0] = strdup("save")) == NULL) {
zone_perror(zone, Z_NOMEM, TRUE);
exit(Z_ERR);
}
cmd->cmd_argv[1] = NULL;
verify_func(cmd);
}
void
revert_func(cmd_t *cmd)
{
char line[128]; /* enough to ask a question */
bool force = FALSE;
bool arg_err = FALSE;
int err, arg, answer;
optind = 0;
while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
switch (arg) {
case '?':
longer_usage(CMD_REVERT);
arg_err = TRUE;
break;
case 'F':
force = TRUE;
break;
default:
short_usage(CMD_REVERT);
arg_err = TRUE;
break;
}
}
if (arg_err)
return;
if (optind != cmd->cmd_argc) {
short_usage(CMD_REVERT);
return;
}
if (zone_is_read_only(CMD_REVERT))
return;
if (zonecfg_check_handle(handle) != Z_OK) {
zerr(gettext("No changes to revert."));
saw_error = TRUE;
return;
}
if (!force) {
(void) snprintf(line, sizeof (line),
gettext("Are you sure you want to revert"));
if ((answer = ask_yesno(FALSE, line)) == -1) {
zerr(gettext("Input not from terminal and -F not "
"specified:\n%s command ignored, exiting."),
cmd_to_str(CMD_REVERT));
exit(Z_ERR);
}
if (answer != 1)
return;
}
/*
* Time for a new handle: finish the old one off first
* then get a new one properly to avoid leaks.
*/
zonecfg_fini_handle(handle);
if ((handle = zonecfg_init_handle()) == NULL) {
zone_perror(execname, Z_NOMEM, TRUE);
exit(Z_ERR);
}
if ((err = zonecfg_get_handle(revert_zone, handle)) != Z_OK) {
saw_error = TRUE;
got_handle = FALSE;
if (err == Z_NO_ZONE)
zerr(gettext("%s: no such saved zone to revert to."),
revert_zone);
else
zone_perror(zone, err, TRUE);
}
(void) strlcpy(zone, revert_zone, sizeof (zone));
}
void
help_func(cmd_t *cmd)
{
int i;
assert(cmd != NULL);
if (cmd->cmd_argc == 0) {
usage(TRUE, global_scope ? HELP_SUBCMDS : HELP_RES_SCOPE);
return;
}
if (strcmp(cmd->cmd_argv[0], "usage") == 0) {
usage(TRUE, HELP_USAGE);
return;
}
if (strcmp(cmd->cmd_argv[0], "commands") == 0) {
usage(TRUE, HELP_SUBCMDS);
return;
}
if (strcmp(cmd->cmd_argv[0], "syntax") == 0) {
usage(TRUE, HELP_SYNTAX | HELP_RES_PROPS);
return;
}
if (strcmp(cmd->cmd_argv[0], "-?") == 0) {
longer_usage(CMD_HELP);
return;
}
for (i = 0; i <= CMD_MAX; i++) {
if (strcmp(cmd->cmd_argv[0], cmd_to_str(i)) == 0) {
longer_usage(i);
return;
}
}
/* We do not use zerr() here because we do not want its extra \n. */
(void) fprintf(stderr, gettext("Unknown help subject %s. "),
cmd->cmd_argv[0]);
usage(FALSE, HELP_META);
}
static int
string_to_yyin(char *string)
{
if ((yyin = tmpfile()) == NULL) {
zone_perror(execname, Z_TEMP_FILE, TRUE);
return (Z_ERR);
}
if (fwrite(string, strlen(string), 1, yyin) != 1) {
zone_perror(execname, Z_TEMP_FILE, TRUE);
return (Z_ERR);
}
if (fseek(yyin, 0, SEEK_SET) != 0) {
zone_perror(execname, Z_TEMP_FILE, TRUE);
return (Z_ERR);
}
return (Z_OK);
}
/* This is the back-end helper function for read_input() below. */
static int
cleanup()
{
int answer;
cmd_t *cmd;
if (!interactive_mode && !cmd_file_mode) {
/*
* If we're not in interactive mode, and we're not in command
* file mode, then we must be in commands-from-the-command-line
* mode. As such, we can't loop back and ask for more input.
* It was OK to prompt for such things as whether or not to
* really delete a zone in the command handler called from
* yyparse() above, but "really quit?" makes no sense in this
* context. So disable prompting.
*/
ok_to_prompt = FALSE;
}
if (!global_scope) {
if (!time_to_exit) {
/*
* Just print a simple error message in the -1 case,
* since exit_func() already handles that case, and
* EOF means we are finished anyway.
*/
answer = ask_yesno(FALSE,
gettext("Resource incomplete; really quit"));
if (answer == -1) {
zerr(gettext("Resource incomplete."));
return (Z_ERR);
}
if (answer != 1) {
yyin = stdin;
return (Z_REPEAT);
}
} else {
saw_error = TRUE;
}
}
/*
* Make sure we tried something and that the handle checks
* out, or we would get a false error trying to commit.
*/
if (need_to_commit && zonecfg_check_handle(handle) == Z_OK) {
if ((cmd = alloc_cmd()) == NULL) {
zone_perror(zone, Z_NOMEM, TRUE);
return (Z_ERR);
}
cmd->cmd_argc = 0;
cmd->cmd_argv[0] = NULL;
commit_func(cmd);
free_cmd(cmd);
/*
* need_to_commit will get set back to FALSE if the
* configuration is saved successfully.
*/
if (need_to_commit) {
if (force_exit) {
zerr(gettext("Configuration not saved."));
return (Z_ERR);
}
answer = ask_yesno(FALSE,
gettext("Configuration not saved; really quit"));
if (answer == -1) {
zerr(gettext("Configuration not saved."));
return (Z_ERR);
}
if (answer != 1) {
time_to_exit = FALSE;
yyin = stdin;
return (Z_REPEAT);
}
}
}
return ((need_to_commit || saw_error) ? Z_ERR : Z_OK);
}
/*
* read_input() is the driver of this program. It is a wrapper around
* yyparse(), printing appropriate prompts when needed, checking for
* exit conditions and reacting appropriately [the latter in its cleanup()
* helper function].
*
* Like most zonecfg functions, it returns Z_OK or Z_ERR, *or* Z_REPEAT
* so do_interactive() knows that we are not really done (i.e, we asked
* the user if we should really quit and the user said no).
*/
static int
read_input()
{
bool yyin_is_a_tty = isatty(fileno(yyin));
/*
* The prompt is "e:z> " or "e:z:r> " where e is execname, z is zone
* and r is resource_scope: 5 is for the two ":"s + "> " + terminator.
*/
char prompt[MAXPATHLEN + ZONENAME_MAX + MAX_RT_STRLEN + 5], *line;
/* yyin should have been set to the appropriate (FILE *) if not stdin */
newline_terminated = TRUE;
for (;;) {
if (yyin_is_a_tty) {
if (newline_terminated) {
if (global_scope)
(void) snprintf(prompt, sizeof (prompt),
"%s:%s> ", execname, zone);
else
(void) snprintf(prompt, sizeof (prompt),
"%s:%s:%s> ", execname, zone,
rt_to_str(resource_scope));
}
/*
* If the user hits ^C then we want to catch it and
* start over. If the user hits EOF then we want to
* bail out.
*/
line = gl_get_line(gl, prompt, NULL, -1);
if (gl_return_status(gl) == GLR_SIGNAL) {
gl_abandon_line(gl);
continue;
}
if (line == NULL)
break;
(void) string_to_yyin(line);
while (!feof(yyin))
yyparse();
} else {
yyparse();
}
/* Bail out on an error in command file mode. */
if (saw_error && cmd_file_mode && !interactive_mode)
time_to_exit = TRUE;
if (time_to_exit || (!yyin_is_a_tty && feof(yyin)))
break;
}
return (cleanup());
}
/*
* This function is used in the zonecfg-interactive-mode scenario: it just
* calls read_input() until we are done.
*/
static int
do_interactive(void)
{
int err;
interactive_mode = TRUE;
if (!read_only_mode) {
/*
* Try to set things up proactively in interactive mode, so
* that if the zone in question does not exist yet, we can
* provide the user with a clue.
*/
(void) initialize(FALSE);
}
do {
err = read_input();
} while (err == Z_REPEAT);
return (err);
}
/*
* cmd_file is slightly more complicated, as it has to open the command file
* and set yyin appropriately. Once that is done, though, it just calls
* read_input(), and only once, since prompting is not possible.
*/
static int
cmd_file(char *file)
{
FILE *infile;
int err;
struct stat statbuf;
bool using_real_file = (strcmp(file, "-") != 0);
if (using_real_file) {
/*
* zerr() prints a line number in cmd_file_mode, which we do
* not want here, so temporarily unset it.
*/
cmd_file_mode = FALSE;
if ((infile = fopen(file, "r")) == NULL) {
zerr(gettext("could not open file %s: %s"),
file, strerror(errno));
return (Z_ERR);
}
if ((err = fstat(fileno(infile), &statbuf)) != 0) {
zerr(gettext("could not stat file %s: %s"),
file, strerror(errno));
err = Z_ERR;
goto done;
}
if (!S_ISREG(statbuf.st_mode)) {
zerr(gettext("%s is not a regular file."), file);
err = Z_ERR;
goto done;
}
yyin = infile;
cmd_file_mode = TRUE;
ok_to_prompt = FALSE;
} else {
/*
* "-f -" is essentially the same as interactive mode,
* so treat it that way.
*/
interactive_mode = TRUE;
}
/* Z_REPEAT is for interactive mode; treat it like Z_ERR here. */
if ((err = read_input()) == Z_REPEAT)
err = Z_ERR;
done:
if (using_real_file)
(void) fclose(infile);
return (err);
}
/*
* Since yacc is based on reading from a (FILE *) whereas what we get from
* the command line is in argv format, we need to convert when the user
* gives us commands directly from the command line. That is done here by
* concatenating the argv list into a space-separated string, writing it
* to a temp file, and rewinding the file so yyin can be set to it. Then
* we call read_input(), and only once, since prompting about whether to
* continue or quit would make no sense in this context.
*/
static int
one_command_at_a_time(int argc, char *argv[])
{
char *command;
size_t len = 2; /* terminal \n\0 */
int i, err;
for (i = 0; i < argc; i++)
len += strlen(argv[i]) + 1;
if ((command = malloc(len)) == NULL) {
zone_perror(execname, Z_NOMEM, TRUE);
return (Z_ERR);
}
(void) strlcpy(command, argv[0], len);
for (i = 1; i < argc; i++) {
(void) strlcat(command, " ", len);
(void) strlcat(command, argv[i], len);
}
(void) strlcat(command, "\n", len);
err = string_to_yyin(command);
free(command);
if (err != Z_OK)
return (err);
while (!feof(yyin))
yyparse();
return (cleanup());
}
static char *
get_execbasename(char *execfullname)
{
char *last_slash, *execbasename;
/* guard against '/' at end of command invocation */
for (;;) {
last_slash = strrchr(execfullname, '/');
if (last_slash == NULL) {
execbasename = execfullname;
break;
} else {
execbasename = last_slash + 1;
if (*execbasename == '\0') {
*last_slash = '\0';
continue;
}
break;
}
}
return (execbasename);
}
int
main(int argc, char *argv[])
{
int err, arg;
struct stat st;
/* This must be before anything goes to stdout. */
setbuf(stdout, NULL);
saw_error = FALSE;
cmd_file_mode = FALSE;
execname = get_execbasename(argv[0]);
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
if (getzoneid() != GLOBAL_ZONEID) {
zerr(gettext("%s can only be run from the global zone."),
execname);
exit(Z_ERR);
}
if (argc < 2) {
usage(FALSE, HELP_USAGE | HELP_SUBCMDS);
exit(Z_USAGE);
}
if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) {
(void) one_command_at_a_time(argc - 1, &(argv[1]));
exit(Z_OK);
}
while ((arg = getopt(argc, argv, "?f:R:z:")) != EOF) {
switch (arg) {
case '?':
if (optopt == '?')
usage(TRUE, HELP_USAGE | HELP_SUBCMDS);
else
usage(FALSE, HELP_USAGE);
exit(Z_USAGE);
/* NOTREACHED */
case 'f':
cmd_file_name = optarg;
cmd_file_mode = TRUE;
break;
case 'R':
if (*optarg != '/') {
zerr(gettext("root path must be absolute: %s"),
optarg);
exit(Z_USAGE);
}
if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
zerr(gettext(
"root path must be a directory: %s"),
optarg);
exit(Z_USAGE);
}
zonecfg_set_root(optarg);
break;
case 'z':
if (strcmp(optarg, GLOBAL_ZONENAME) == 0) {
global_zone = TRUE;
} else if (zonecfg_validate_zonename(optarg) != Z_OK) {
zone_perror(optarg, Z_BOGUS_ZONE_NAME, TRUE);
usage(FALSE, HELP_SYNTAX);
exit(Z_USAGE);
}
(void) strlcpy(zone, optarg, sizeof (zone));
(void) strlcpy(revert_zone, optarg, sizeof (zone));
break;
default:
usage(FALSE, HELP_USAGE);
exit(Z_USAGE);
}
}
if (optind > argc || strcmp(zone, "") == 0) {
usage(FALSE, HELP_USAGE);
exit(Z_USAGE);
}
if ((err = zonecfg_access(zone, W_OK)) == Z_OK) {
read_only_mode = FALSE;
} else if (err == Z_ACCES) {
read_only_mode = TRUE;
/* skip this message in one-off from command line mode */
if (optind == argc)
(void) fprintf(stderr, gettext("WARNING: you do not "
"have write access to this zone's configuration "
"file;\ngoing into read-only mode.\n"));
} else {
fprintf(stderr, "%s: Could not access zone configuration "
"store: %s\n", execname, zonecfg_strerror(err));
exit(Z_ERR);
}
if ((handle = zonecfg_init_handle()) == NULL) {
zone_perror(execname, Z_NOMEM, TRUE);
exit(Z_ERR);
}
/*
* This may get set back to FALSE again in cmd_file() if cmd_file_name
* is a "real" file as opposed to "-" (i.e. meaning use stdin).
*/
if (isatty(STDIN_FILENO))
ok_to_prompt = TRUE;
if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL)
exit(Z_ERR);
if (gl_customize_completion(gl, NULL, cmd_cpl_fn) != 0)
exit(Z_ERR);
(void) sigset(SIGINT, SIG_IGN);
if (optind == argc) {
if (!cmd_file_mode)
err = do_interactive();
else
err = cmd_file(cmd_file_name);
} else {
err = one_command_at_a_time(argc - optind, &(argv[optind]));
}
zonecfg_fini_handle(handle);
if (brand != NULL)
brand_close(brand);
(void) del_GetLine(gl);
return (err);
}