17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
5fb03efadp * Common Development and Distribution License (the "License").
6fb03efadp * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217e362f5comay
227c478bdstevel@tonic-gate/*
236d4d1c0batschul * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24f93d2c1Alexander Eremin * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
25944b13eGary Mills * Copyright 2014 Gary Mills
26c8236eaBrian Bennett * Copyright 2019 Joyent, Inc.
277c478bdstevel@tonic-gate */
287c478bdstevel@tonic-gate
297c478bdstevel@tonic-gate/*
307c478bdstevel@tonic-gate * zonecfg is a lex/yacc based command interpreter used to manage zone
317c478bdstevel@tonic-gate * configurations.  The lexer (see zonecfg_lex.l) builds up tokens, which
327c478bdstevel@tonic-gate * the grammar (see zonecfg_grammar.y) builds up into commands, some of
337c478bdstevel@tonic-gate * which takes resources and/or properties as arguments.  See the block
347c478bdstevel@tonic-gate * comments near the end of zonecfg_grammar.y for how the data structures
357c478bdstevel@tonic-gate * which keep track of these resources and properties are built up.
367c478bdstevel@tonic-gate *
377c478bdstevel@tonic-gate * The resource/property data structures are inserted into a command
387c478bdstevel@tonic-gate * structure (see zonecfg.h), which also keeps track of command names,
397c478bdstevel@tonic-gate * miscellaneous arguments, and function handlers.  The grammar selects
407c478bdstevel@tonic-gate * the appropriate function handler, each of which takes a pointer to a
417c478bdstevel@tonic-gate * command structure as its sole argument, and invokes it.  The grammar
427c478bdstevel@tonic-gate * itself is "entered" (a la the Matrix) by yyparse(), which is called
437c478bdstevel@tonic-gate * from read_input(), our main driving function.  That in turn is called
447c478bdstevel@tonic-gate * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
457c478bdstevel@tonic-gate * of which is called from main() depending on how the program was invoked.
467c478bdstevel@tonic-gate *
477c478bdstevel@tonic-gate * The rest of this module consists of the various function handlers and
487c478bdstevel@tonic-gate * their helper functions.  Some of these functions, particularly the
497c478bdstevel@tonic-gate * X_to_str() functions, which maps command, resource and property numbers
507c478bdstevel@tonic-gate * to strings, are used quite liberally, as doing so results in a better
517c478bdstevel@tonic-gate * program w/rt I18N, reducing the need for translation notes.
527c478bdstevel@tonic-gate */
537c478bdstevel@tonic-gate
547c478bdstevel@tonic-gate#include <sys/mntent.h>
557c478bdstevel@tonic-gate#include <sys/varargs.h>
567c478bdstevel@tonic-gate#include <sys/sysmacros.h>
57d2a7078Richard Lowe#include <sys/secflags.h>
587c478bdstevel@tonic-gate
597c478bdstevel@tonic-gate#include <errno.h>
609acbbeann#include <fcntl.h>
617c478bdstevel@tonic-gate#include <strings.h>
627c478bdstevel@tonic-gate#include <unistd.h>
637c478bdstevel@tonic-gate#include <ctype.h>
647c478bdstevel@tonic-gate#include <stdlib.h>
657c478bdstevel@tonic-gate#include <assert.h>
667c478bdstevel@tonic-gate#include <sys/stat.h>
677c478bdstevel@tonic-gate#include <zone.h>
687c478bdstevel@tonic-gate#include <arpa/inet.h>
697c478bdstevel@tonic-gate#include <netdb.h>
707c478bdstevel@tonic-gate#include <locale.h>
717c478bdstevel@tonic-gate#include <libintl.h>
727c478bdstevel@tonic-gate#include <alloca.h>
737c478bdstevel@tonic-gate#include <signal.h>
749acbbeann#include <wait.h>
757c478bdstevel@tonic-gate#include <libtecla.h>
76fa9e406ahrens#include <libzfs.h>
779acbbeann#include <sys/brand.h>
789acbbeann#include <libbrand.h>
795679c89jv#include <sys/systeminfo.h>
80c9f134ejv#include <libdladm.h>
81c9f134ejv#include <libinetutil.h>
82cb8a054Glenn Faden#include <pwd.h>
83550b6e4Sowmini Varadhan#include <inet/ip.h>
847c478bdstevel@tonic-gate
857c478bdstevel@tonic-gate#include <libzonecfg.h>
867c478bdstevel@tonic-gate#include "zonecfg.h"
877c478bdstevel@tonic-gate
887c478bdstevel@tonic-gate#if !defined(TEXT_DOMAIN)		/* should be defined by cc -D */
897c478bdstevel@tonic-gate#define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it wasn't */
907c478bdstevel@tonic-gate#endif
917c478bdstevel@tonic-gate
927c478bdstevel@tonic-gate#define	PAGER	"/usr/bin/more"
939acbbeann#define	EXEC_PREFIX	"exec "
949acbbeann#define	EXEC_LEN	(strlen(EXEC_PREFIX))
957c478bdstevel@tonic-gate
967c478bdstevel@tonic-gatestruct help {
977c478bdstevel@tonic-gate	uint_t	cmd_num;
987c478bdstevel@tonic-gate	char	*cmd_name;
997c478bdstevel@tonic-gate	uint_t	flags;
1007c478bdstevel@tonic-gate	char	*short_usage;
1017c478bdstevel@tonic-gate};
1027c478bdstevel@tonic-gate
1037c478bdstevel@tonic-gateextern int yyparse(void);
1047c478bdstevel@tonic-gateextern int lex_lineno;
1057c478bdstevel@tonic-gate
1067c478bdstevel@tonic-gate#define	MAX_LINE_LEN	1024
1077c478bdstevel@tonic-gate#define	MAX_CMD_HIST	1024
1089acbbeann#define	MAX_CMD_LEN	1024
1097c478bdstevel@tonic-gate
1100209230gjelinek#define	ONE_MB		1048576
1110209230gjelinek
1127c478bdstevel@tonic-gate/*
1137c478bdstevel@tonic-gate * Each SHELP_ should be a simple string.
1147c478bdstevel@tonic-gate */
1157c478bdstevel@tonic-gate
1167c478bdstevel@tonic-gate#define	SHELP_ADD	"add <resource-type>\n\t(global scope)\n" \
1177c478bdstevel@tonic-gate	"add <property-name> <property-value>\n\t(resource scope)"
1187c478bdstevel@tonic-gate#define	SHELP_CANCEL	"cancel"
1190209230gjelinek#define	SHELP_CLEAR	"clear <property-name>"
1207c478bdstevel@tonic-gate#define	SHELP_COMMIT	"commit"
121ee519a1gjelinek#define	SHELP_CREATE	"create [-F] [ -a <path> | -b | -t <template> ]"
1227c478bdstevel@tonic-gate#define	SHELP_DELETE	"delete [-F]"
1237c478bdstevel@tonic-gate#define	SHELP_END	"end"
1247c478bdstevel@tonic-gate#define	SHELP_EXIT	"exit [-F]"
1257c478bdstevel@tonic-gate#define	SHELP_EXPORT	"export [-f output-file]"
1267c478bdstevel@tonic-gate#define	SHELP_HELP	"help [commands] [syntax] [usage] [<command-name>]"
1277c478bdstevel@tonic-gate#define	SHELP_INFO	"info [<resource-type> [property-name=property-value]*]"
1280209230gjelinek#define	SHELP_REMOVE	"remove [-F] <resource-type> " \
1290209230gjelinek	"[ <property-name>=<property-value> ]*\n" \
1300209230gjelinek	"\t(global scope)\n" \
1310209230gjelinek	"remove <property-name> <property-value>\n" \
1320209230gjelinek	"\t(resource scope)"
1337c478bdstevel@tonic-gate#define	SHELP_REVERT	"revert [-F]"
1347c478bdstevel@tonic-gate#define	SHELP_SELECT	"select <resource-type> { <property-name>=" \
1357c478bdstevel@tonic-gate	"<property-value> }"
1367c478bdstevel@tonic-gate#define	SHELP_SET	"set <property-name>=<property-value>"
1377c478bdstevel@tonic-gate#define	SHELP_VERIFY	"verify"
1387c478bdstevel@tonic-gate
1397c478bdstevel@tonic-gatestatic struct help helptab[] = {
1407c478bdstevel@tonic-gate	{ CMD_ADD,	"add",		HELP_RES_PROPS,	SHELP_ADD, },
1417c478bdstevel@tonic-gate	{ CMD_CANCEL,	"cancel",	0,		SHELP_CANCEL, },
1420209230gjelinek	{ CMD_CLEAR,	"clear",	HELP_PROPS,	SHELP_CLEAR, },
1437c478bdstevel@tonic-gate	{ CMD_COMMIT,	"commit",	0,		SHELP_COMMIT, },
1447c478bdstevel@tonic-gate	{ CMD_CREATE,	"create",	0,		SHELP_CREATE, },
1457c478bdstevel@tonic-gate	{ CMD_DELETE,	"delete",	0,		SHELP_DELETE, },
1467c478bdstevel@tonic-gate	{ CMD_END,	"end",		0,		SHELP_END, },
1477c478bdstevel@tonic-gate	{ CMD_EXIT,	"exit",		0,		SHELP_EXIT, },
1487c478bdstevel@tonic-gate	{ CMD_EXPORT,	"export",	0,		SHELP_EXPORT, },
1497c478bdstevel@tonic-gate	{ CMD_HELP,	"help",		0,		SHELP_HELP },
1507c478bdstevel@tonic-gate	{ CMD_INFO,	"info",		HELP_RES_PROPS,	SHELP_INFO, },
1517c478bdstevel@tonic-gate	{ CMD_REMOVE,	"remove",	HELP_RES_PROPS,	SHELP_REMOVE, },
1527c478bdstevel@tonic-gate	{ CMD_REVERT,	"revert",	0,		SHELP_REVERT, },
1537c478bdstevel@tonic-gate	{ CMD_SELECT,	"select",	HELP_RES_PROPS,	SHELP_SELECT, },
1547c478bdstevel@tonic-gate	{ CMD_SET,	"set",		HELP_PROPS,	SHELP_SET, },
1557c478bdstevel@tonic-gate	{ CMD_VERIFY,	"verify",	0,		SHELP_VERIFY, },
1567c478bdstevel@tonic-gate	{ 0 },
1577c478bdstevel@tonic-gate};
1587c478bdstevel@tonic-gate
1597c478bdstevel@tonic-gate#define	MAX_RT_STRLEN	16
1607c478bdstevel@tonic-gate
1617c478bdstevel@tonic-gate/* These *must* match the order of the RT_ define's from zonecfg.h */
162c94c1efjvchar *res_types[] = {
1637c478bdstevel@tonic-gate	"unknown",
164087719fdp	"zonename",
1657c478bdstevel@tonic-gate	"zonepath",
1667c478bdstevel@tonic-gate	"autoboot",
1677c478bdstevel@tonic-gate	"pool",
1687c478bdstevel@tonic-gate	"fs",
1697c478bdstevel@tonic-gate	"net",
1707c478bdstevel@tonic-gate	"device",
1717c478bdstevel@tonic-gate	"rctl",
1727c478bdstevel@tonic-gate	"attr",
173fa9e406ahrens	"dataset",
174ffbafc5comay	"limitpriv",
1753f2f09cdp	"bootargs",
1769acbbeann	"brand",
1770209230gjelinek	"dedicated-cpu",
1780209230gjelinek	"capped-memory",
1790209230gjelinek	ALIAS_MAXLWPS,
1800209230gjelinek	ALIAS_MAXSHMMEM,
1810209230gjelinek	ALIAS_MAXSHMIDS,
1820209230gjelinek	ALIAS_MAXMSGIDS,
1830209230gjelinek	ALIAS_MAXSEMIDS,
1840209230gjelinek	ALIAS_SHARES,
1850209230gjelinek	"scheduling-class",
186f4b3ec6dh	"ip-type",
187c97ad5cakolb	"capped-cpu",
1885679c89jv	"hostid",
189cb8a054Glenn Faden	"admin",
1900fbb751John Levon	"fs-allowed",
191ff19e02Menno Lageman	ALIAS_MAXPROCS,
192d2a7078Richard Lowe	"security-flags",
1937c478bdstevel@tonic-gate	NULL
1947c478bdstevel@tonic-gate};
1957c478bdstevel@tonic-gate
1967c478bdstevel@tonic-gate/* These *must* match the order of the PT_ define's from zonecfg.h */
197c94c1efjvchar *prop_types[] = {
1987c478bdstevel@tonic-gate	"unknown",
199087719fdp	"zonename",
2007c478bdstevel@tonic-gate	"zonepath",
2017c478bdstevel@tonic-gate	"autoboot",
2027c478bdstevel@tonic-gate	"pool",
2037c478bdstevel@tonic-gate	"dir",
2047c478bdstevel@tonic-gate	"special",
2057c478bdstevel@tonic-gate	"type",
2067c478bdstevel@tonic-gate	"options",
2077c478bdstevel@tonic-gate	"address",
2087c478bdstevel@tonic-gate	"physical",
2097c478bdstevel@tonic-gate	"name",
2107c478bdstevel@tonic-gate	"value",
2117c478bdstevel@tonic-gate	"match",
2127c478bdstevel@tonic-gate	"priv",
2137c478bdstevel@tonic-gate	"limit",
2147c478bdstevel@tonic-gate	"action",
2157c478bdstevel@tonic-gate	"raw",
216ffbafc5comay	"limitpriv",
2173f2f09cdp	"bootargs",
2189acbbeann	"brand",
2190209230gjelinek	"ncpus",
2200209230gjelinek	"importance",
2210209230gjelinek	"swap",
2220209230gjelinek	"locked",
2230209230gjelinek	ALIAS_SHARES,
2240209230gjelinek	ALIAS_MAXLWPS,
2250209230gjelinek	ALIAS_MAXSHMMEM,
2260209230gjelinek	ALIAS_MAXSHMIDS,
2270209230gjelinek	ALIAS_MAXMSGIDS,
2280209230gjelinek	ALIAS_MAXSEMIDS,
2290209230gjelinek	ALIAS_MAXLOCKEDMEM,
2300209230gjelinek	ALIAS_MAXSWAP,
2310209230gjelinek	"scheduling-class",
232f4b3ec6dh	"ip-type",
233de860bdgfaden	"defrouter",
2345679c89jv	"hostid",
235cb8a054Glenn Faden	"user",
236cb8a054Glenn Faden	"auths",
2370fbb751John Levon	"fs-allowed",
238ff19e02Menno Lageman	ALIAS_MAXPROCS,
239550b6e4Sowmini Varadhan	"allowed-address",
240d2a7078Richard Lowe	"default",
241d2a7078Richard Lowe	"lower",
242d2a7078Richard Lowe	"upper",
2437c478bdstevel@tonic-gate	NULL
2447c478bdstevel@tonic-gate};
2457c478bdstevel@tonic-gate
246ffbafc5comay/* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
2477c478bdstevel@tonic-gatestatic char *prop_val_types[] = {
2487c478bdstevel@tonic-gate	"simple",
2497c478bdstevel@tonic-gate	"complex",
2507c478bdstevel@tonic-gate	"list",
2517c478bdstevel@tonic-gate};
2527c478bdstevel@tonic-gate
2537c478bdstevel@tonic-gate/*
2547c478bdstevel@tonic-gate * The various _cmds[] lists below are for command tab-completion.
2557c478bdstevel@tonic-gate */
2567c478bdstevel@tonic-gate
2577c478bdstevel@tonic-gate/*
2587c478bdstevel@tonic-gate * remove has a space afterwards because it has qualifiers; the other commands
2590209230gjelinek * that have qualifiers (add, select, etc.) don't need a space here because
2607c478bdstevel@tonic-gate * they have their own _cmds[] lists below.
2617c478bdstevel@tonic-gate */
2627c478bdstevel@tonic-gatestatic const char *global_scope_cmds[] = {
2637c478bdstevel@tonic-gate	"add",
2640209230gjelinek	"clear",
2657c478bdstevel@tonic-gate	"commit",
2667c478bdstevel@tonic-gate	"create",
2677c478bdstevel@tonic-gate	"delete",
2687c478bdstevel@tonic-gate	"exit",
2697c478bdstevel@tonic-gate	"export",
2707c478bdstevel@tonic-gate	"help",
2717c478bdstevel@tonic-gate	"info",
2727c478bdstevel@tonic-gate	"remove ",
2737c478bdstevel@tonic-gate	"revert",
2747c478bdstevel@tonic-gate	"select",
2757c478bdstevel@tonic-gate	"set",
2767c478bdstevel@tonic-gate	"verify",
2777c478bdstevel@tonic-gate	NULL
2787c478bdstevel@tonic-gate};
2797c478bdstevel@tonic-gate
2807c478bdstevel@tonic-gatestatic const char *add_cmds[] = {
2817c478bdstevel@tonic-gate	"add fs",
2827c478bdstevel@tonic-gate	"add net",
2837c478bdstevel@tonic-gate	"add device",
2847c478bdstevel@tonic-gate	"add rctl",
2857c478bdstevel@tonic-gate	"add attr",
286fa9e406ahrens	"add dataset",
2870209230gjelinek	"add dedicated-cpu",
288c97ad5cakolb	"add capped-cpu",
2890209230gjelinek	"add capped-memory",
290cb8a054Glenn Faden	"add admin",
291d2a7078Richard Lowe	"add security-flags",
2920209230gjelinek	NULL
2930209230gjelinek};
2940209230gjelinek
2950209230gjelinekstatic const char *clear_cmds[] = {
2960209230gjelinek	"clear autoboot",
2970209230gjelinek	"clear pool",
2980209230gjelinek	"clear limitpriv",
2990209230gjelinek	"clear bootargs",
3000209230gjelinek	"clear scheduling-class",
301f4b3ec6dh	"clear ip-type",
3020209230gjelinek	"clear " ALIAS_MAXLWPS,
3030209230gjelinek	"clear " ALIAS_MAXSHMMEM,
3040209230gjelinek	"clear " ALIAS_MAXSHMIDS,
3050209230gjelinek	"clear " ALIAS_MAXMSGIDS,
3060209230gjelinek	"clear " ALIAS_MAXSEMIDS,
3070209230gjelinek	"clear " ALIAS_SHARES,
308ff19e02Menno Lageman	"clear " ALIAS_MAXPROCS,
3097c478bdstevel@tonic-gate	NULL
3107c478bdstevel@tonic-gate};
3117c478bdstevel@tonic-gate
3129e7542fdpstatic const char *remove_cmds[] = {
3139e7542fdp	"remove fs ",
3149e7542fdp	"remove net ",
3159e7542fdp	"remove device ",
3169e7542fdp	"remove rctl ",
3179e7542fdp	"remove attr ",
3189e7542fdp	"remove dataset ",
3190209230gjelinek	"remove dedicated-cpu ",
320c97ad5cakolb	"remove capped-cpu ",
3210209230gjelinek	"remove capped-memory ",
322cb8a054Glenn Faden	"remove admin ",
323d2a7078Richard Lowe	"remove security-flags",
3249e7542fdp	NULL
3259e7542fdp};
3269e7542fdp
3277c478bdstevel@tonic-gatestatic const char *select_cmds[] = {
328087719fdp	"select fs ",
329087719fdp	"select net ",
330087719fdp	"select device ",
331087719fdp	"select rctl ",
332087719fdp	"select attr ",
333fa9e406ahrens	"select dataset ",
3340209230gjelinek	"select dedicated-cpu",
335c97ad5cakolb	"select capped-cpu",
3360209230gjelinek	"select capped-memory",
337cb8a054Glenn Faden	"select admin",
338d2a7078Richard Lowe	"select security-flags",
3397c478bdstevel@tonic-gate	NULL
3407c478bdstevel@tonic-gate};
3417c478bdstevel@tonic-gate
3427c478bdstevel@tonic-gatestatic const char *set_cmds[] = {
343087719fdp	"set zonename=",
344087719fdp	"set zonepath=",
3459acbbeann	"set brand=",
346087719fdp	"set autoboot=",
347087719fdp	"set pool=",
348ffbafc5comay	"set limitpriv=",
3493f2f09cdp	"set bootargs=",
3500209230gjelinek	"set scheduling-class=",
351f4b3ec6dh	"set ip-type=",
3520209230gjelinek	"set " ALIAS_MAXLWPS "=",
3530209230gjelinek	"set " ALIAS_MAXSHMMEM "=",
3540209230gjelinek	"set " ALIAS_MAXSHMIDS "=",
3550209230gjelinek	"set " ALIAS_MAXMSGIDS "=",
3560209230gjelinek	"set " ALIAS_MAXSEMIDS "=",
3570209230gjelinek	"set " ALIAS_SHARES "=",
3585679c89jv	"set hostid=",
3590fbb751John Levon	"set fs-allowed=",
360ff19e02Menno Lageman	"set " ALIAS_MAXPROCS "=",
3617c478bdstevel@tonic-gate	NULL
3627c478bdstevel@tonic-gate};
3637c478bdstevel@tonic-gate
3649e7542fdpstatic const char *info_cmds[] = {
3659e7542fdp	"info fs ",
3669e7542fdp	"info net ",
3679e7542fdp	"info device ",
3689e7542fdp	"info rctl ",
3699e7542fdp	"info attr ",
3709e7542fdp	"info dataset ",
3710209230gjelinek	"info capped-memory",
3720209230gjelinek	"info dedicated-cpu",
373c97ad5cakolb	"info capped-cpu",
374d2a7078Richard Lowe	"info security-flags",
3759e7542fdp	"info zonename",
3769e7542fdp	"info zonepath",
3779e7542fdp	"info autoboot",
3789e7542fdp	"info pool",
3799e7542fdp	"info limitpriv",
3809e7542fdp	"info bootargs",
3810209230gjelinek	"info brand",
3820209230gjelinek	"info scheduling-class",
383f4b3ec6dh	"info ip-type",
3840209230gjelinek	"info max-lwps",
3850209230gjelinek	"info max-shm-memory",
3860209230gjelinek	"info max-shm-ids",
3870209230gjelinek	"info max-msg-ids",
3880209230gjelinek	"info max-sem-ids",
3890209230gjelinek	"info cpu-shares",
3905679c89jv	"info hostid",
391cb8a054Glenn Faden	"info admin",
3920fbb751John Levon	"info fs-allowed",
393ff19e02Menno Lageman	"info max-processes",
3949e7542fdp	NULL
3959e7542fdp};
3969e7542fdp
3977c478bdstevel@tonic-gatestatic const char *fs_res_scope_cmds[] = {
3987c478bdstevel@tonic-gate	"add options ",
3997c478bdstevel@tonic-gate	"cancel",
4007c478bdstevel@tonic-gate	"end",
4017c478bdstevel@tonic-gate	"exit",
4027c478bdstevel@tonic-gate	"help",
4037c478bdstevel@tonic-gate	"info",
404ffbafc5comay	"remove options ",
4057c478bdstevel@tonic-gate	"set dir=",
4067c478bdstevel@tonic-gate	"set raw=",
4077c478bdstevel@tonic-gate	"set special=",
4087c478bdstevel@tonic-gate	"set type=",
4090209230gjelinek	"clear raw",
4107c478bdstevel@tonic-gate	NULL
4117c478bdstevel@tonic-gate};
4127c478bdstevel@tonic-gate
4137c478bdstevel@tonic-gatestatic const char *net_res_scope_cmds[] = {
4147c478bdstevel@tonic-gate	"cancel",
4157c478bdstevel@tonic-gate	"end",
4167c478bdstevel@tonic-gate	"exit",
4177c478bdstevel@tonic-gate	"help",
4187c478bdstevel@tonic-gate	"info",
4197c478bdstevel@tonic-gate	"set address=",
4203a1c41dPeter Tribble	"set allowed-address=",
4217c478bdstevel@tonic-gate	"set physical=",
4221b3281cGerald Jelinek	"set defrouter=",
4237c478bdstevel@tonic-gate	NULL
4247c478bdstevel@tonic-gate};
4257c478bdstevel@tonic-gate
4267c478bdstevel@tonic-gatestatic const char *device_res_scope_cmds[] = {
4277c478bdstevel@tonic-gate	"cancel",
4287c478bdstevel@tonic-gate	"end",
4297c478bdstevel@tonic-gate	"exit",
4307c478bdstevel@tonic-gate	"help",
4317c478bdstevel@tonic-gate	"info",
4327c478bdstevel@tonic-gate	"set match=",
4337c478bdstevel@tonic-gate	NULL
4347c478bdstevel@tonic-gate};
4357c478bdstevel@tonic-gate
4367c478bdstevel@tonic-gatestatic const char *attr_res_scope_cmds[] = {
4377c478bdstevel@tonic-gate	"cancel",
4387c478bdstevel@tonic-gate	"end",
4397c478bdstevel@tonic-gate	"exit",
4407c478bdstevel@tonic-gate	"help",
4417c478bdstevel@tonic-gate	"info",
4427c478bdstevel@tonic-gate	"set name=",
4437c478bdstevel@tonic-gate	"set type=",
4447c478bdstevel@tonic-gate	"set value=",
4457c478bdstevel@tonic-gate	NULL
4467c478bdstevel@tonic-gate};
4477c478bdstevel@tonic-gate
4487c478bdstevel@tonic-gatestatic const char *rctl_res_scope_cmds[] = {
4497c478bdstevel@tonic-gate	"add value ",
4507c478bdstevel@tonic-gate	"cancel",
4517c478bdstevel@tonic-gate	"end",
4527c478bdstevel@tonic-gate	"exit",
4537c478bdstevel@tonic-gate	"help",
4547c478bdstevel@tonic-gate	"info",
455ffbafc5comay	"remove value ",
4567c478bdstevel@tonic-gate	"set name=",
4577c478bdstevel@tonic-gate	NULL
4587c478bdstevel@tonic-gate};
4597c478bdstevel@tonic-gate
460fa9e406ahrensstatic const char *dataset_res_scope_cmds[] = {
461fa9e406ahrens	"cancel",
462fa9e406ahrens	"end",
463fa9e406ahrens	"exit",
464fa9e406ahrens	"help",
465fa9e406ahrens	"info",
466fa9e406ahrens	"set name=",
467fa9e406ahrens	NULL
468fa9e406ahrens};
469fa9e406ahrens
4700209230gjelinekstatic const char *pset_res_scope_cmds[] = {
4710209230gjelinek	"cancel",
4720209230gjelinek	"end",
4730209230gjelinek	"exit",
4740209230gjelinek	"help",
4750209230gjelinek	"info",
4760209230gjelinek	"set ncpus=",
4770209230gjelinek	"set importance=",
4780209230gjelinek	"clear importance",
4790209230gjelinek	NULL
4800209230gjelinek};
4810209230gjelinek
482c97ad5cakolbstatic const char *pcap_res_scope_cmds[] = {
483c97ad5cakolb	"cancel",
484c97ad5cakolb	"end",
485c97ad5cakolb	"exit",
486c97ad5cakolb	"help",
487c97ad5cakolb	"info",
488c97ad5cakolb	"set ncpus=",
489c97ad5cakolb	NULL
490c97ad5cakolb};
491c97ad5cakolb
4920209230gjelinekstatic const char *mcap_res_scope_cmds[] = {
4930209230gjelinek	"cancel",
4940209230gjelinek	"end",
4950209230gjelinek	"exit",
4960209230gjelinek	"help",
4970209230gjelinek	"info",
4980209230gjelinek	"set physical=",
4990209230gjelinek	"set swap=",
5000209230gjelinek	"set locked=",
5010209230gjelinek	"clear physical",
5020209230gjelinek	"clear swap",
5030209230gjelinek	"clear locked",
5040209230gjelinek	NULL
5050209230gjelinek};
5060209230gjelinek
507cb8a054Glenn Fadenstatic const char *admin_res_scope_cmds[] = {
508cb8a054Glenn Faden	"cancel",
509cb8a054Glenn Faden	"end",
510cb8a054Glenn Faden	"exit",
511cb8a054Glenn Faden	"help",
512cb8a054Glenn Faden	"info",
513cb8a054Glenn Faden	"set user=",
514cb8a054Glenn Faden	"set auths=",
515cb8a054Glenn Faden	NULL
516cb8a054Glenn Faden};
517cb8a054Glenn Faden
518d2a7078Richard Lowestatic const char *secflags_res_scope_cmds[] = {
519d2a7078Richard Lowe	"cancel",
520d2a7078Richard Lowe	"end",
521d2a7078Richard Lowe	"exit",
522d2a7078Richard Lowe	"set default=",
523d2a7078Richard Lowe	"set lower=",
524d2a7078Richard Lowe	"set upper=",
525d2a7078Richard Lowe	NULL
526d2a7078Richard Lowe};
527d2a7078Richard Lowe
528550b6e4Sowmini Varadhanstruct xif {
529550b6e4Sowmini Varadhan	struct xif	*xif_next;
530550b6e4Sowmini Varadhan	char		xif_name[LIFNAMSIZ];
531550b6e4Sowmini Varadhan	boolean_t	xif_has_address;
532550b6e4Sowmini Varadhan	boolean_t	xif_has_defrouter;
533550b6e4Sowmini Varadhan};
534550b6e4Sowmini Varadhan
5357c478bdstevel@tonic-gate/* Global variables */
5367c478bdstevel@tonic-gate
537550b6e4Sowmini Varadhan/* list of network interfaces specified for exclusive IP zone */
538550b6e4Sowmini Varadhanstruct xif *xif;
539550b6e4Sowmini Varadhan
5407c478bdstevel@tonic-gate/* set early in main(), never modified thereafter, used all over the place */
5417c478bdstevel@tonic-gatestatic char *execname;
5427c478bdstevel@tonic-gate
5437c478bdstevel@tonic-gate/* set in main(), used all over the place */
5447c478bdstevel@tonic-gatestatic zone_dochandle_t handle;
5457c478bdstevel@tonic-gate
5467c478bdstevel@tonic-gate/* used all over the place */
547087719fdpstatic char zone[ZONENAME_MAX];
548087719fdpstatic char revert_zone[ZONENAME_MAX];
5497c478bdstevel@tonic-gate
5509acbbeann/* global brand operations */
551123807fedpstatic brand_handle_t brand;
5529acbbeann
5537c478bdstevel@tonic-gate/* set in modifying functions, checked in read_input() */
554bbec428gjelinekstatic boolean_t need_to_commit = B_FALSE;
555bbec428gjelinekboolean_t saw_error;
5567c478bdstevel@tonic-gate
5577c478bdstevel@tonic-gate/* set in yacc parser, checked in read_input() */
558bbec428gjelinekboolean_t newline_terminated;
5597c478bdstevel@tonic-gate
5607c478bdstevel@tonic-gate/* set in main(), checked in lex error handler */
561bbec428gjelinekboolean_t cmd_file_mode;
5627c478bdstevel@tonic-gate
5637c478bdstevel@tonic-gate/* set in exit_func(), checked in read_input() */
564bbec428gjelinekstatic boolean_t time_to_exit = B_FALSE, force_exit = B_FALSE;
5657c478bdstevel@tonic-gate
5667c478bdstevel@tonic-gate/* used in short_usage() and zerr() */
5677c478bdstevel@tonic-gatestatic char *cmd_file_name = NULL;
5687c478bdstevel@tonic-gate
5697c478bdstevel@tonic-gate/* checked in read_input() and other places */
570bbec428gjelinekstatic boolean_t ok_to_prompt = B_FALSE;
5717c478bdstevel@tonic-gate
5727c478bdstevel@tonic-gate/* set and checked in initialize() */
573bbec428gjelinekstatic boolean_t got_handle = B_FALSE;
5747c478bdstevel@tonic-gate
5757c478bdstevel@tonic-gate/* initialized in do_interactive(), checked in initialize() */
576bbec428gjelinekstatic boolean_t interactive_mode;
5777c478bdstevel@tonic-gate
5780209230gjelinek/* set if configuring the global zone */
579bbec428gjelinekstatic boolean_t global_zone = B_FALSE;
5800209230gjelinek
5817c478bdstevel@tonic-gate/* set in main(), checked in multiple places */
582bbec428gjelinekstatic boolean_t read_only_mode;
5837c478bdstevel@tonic-gate
584bbec428gjelinek/* scope is outer/global or inner/resource */
585bbec428gjelinekstatic boolean_t global_scope = B_TRUE;
5867c478bdstevel@tonic-gatestatic int resource_scope;	/* should be in the RT_ list from zonecfg.h */
5877c478bdstevel@tonic-gatestatic int end_op = -1;		/* operation on end is either add or modify */
5887c478bdstevel@tonic-gate
5897c478bdstevel@tonic-gateint num_prop_vals;		/* for grammar */
5907c478bdstevel@tonic-gate
5917c478bdstevel@tonic-gate/*
5927c478bdstevel@tonic-gate * These are for keeping track of resources as they are specified as part of
5937c478bdstevel@tonic-gate * the multi-step process.  They should be initialized by add_resource() or
5947c478bdstevel@tonic-gate * select_func() and filled in by add_property() or set_func().
5957c478bdstevel@tonic-gate */
5967c478bdstevel@tonic-gatestatic struct zone_fstab	old_fstab, in_progress_fstab;
5977c478bdstevel@tonic-gatestatic struct zone_nwiftab	old_nwiftab, in_progress_nwiftab;
5987c478bdstevel@tonic-gatestatic struct zone_devtab	old_devtab, in_progress_devtab;
5997c478bdstevel@tonic-gatestatic struct zone_rctltab	old_rctltab, in_progress_rctltab;
6007c478bdstevel@tonic-gatestatic struct zone_attrtab	old_attrtab, in_progress_attrtab;
601fa9e406ahrensstatic struct zone_dstab	old_dstab, in_progress_dstab;
6020209230gjelinekstatic struct zone_psettab	old_psettab, in_progress_psettab;
6030209230gjelinekstatic struct zone_mcaptab	old_mcaptab, in_progress_mcaptab;
604cb8a054Glenn Fadenstatic struct zone_admintab	old_admintab, in_progress_admintab;
605d2a7078Richard Lowestatic struct zone_secflagstab	old_secflagstab, in_progress_secflagstab;
6067c478bdstevel@tonic-gate
6077c478bdstevel@tonic-gatestatic GetLine *gl;	/* The gl_get_line() resource object */
6087c478bdstevel@tonic-gate
6090209230gjelinekstatic void bytes_to_units(char *str, char *buf, int bufsize);
6100209230gjelinek
6117c478bdstevel@tonic-gate/* Functions begin here */
6127c478bdstevel@tonic-gate
613bbec428gjelinekstatic boolean_t
6147c478bdstevel@tonic-gateinitial_match(const char *line1, const char *line2, int word_end)
6157c478bdstevel@tonic-gate{
6167c478bdstevel@tonic-gate	if (word_end <= 0)
617bbec428gjelinek		return (B_TRUE);
6187c478bdstevel@tonic-gate	return (strncmp(line1, line2, word_end) == 0);
6197c478bdstevel@tonic-gate}
6207c478bdstevel@tonic-gate
6217c478bdstevel@tonic-gatestatic int
6227c478bdstevel@tonic-gateadd_stuff(WordCompletion *cpl, const char *line1, const char **list,
6237c478bdstevel@tonic-gate    int word_end)
6247c478bdstevel@tonic-gate{
6257c478bdstevel@tonic-gate	int i, err;
6267c478bdstevel@tonic-gate
6277c478bdstevel@tonic-gate	for (i = 0; list[i] != NULL; i++) {
6287c478bdstevel@tonic-gate		if (initial_match(line1, list[i], word_end)) {
6297c478bdstevel@tonic-gate			err = cpl_add_completion(cpl, line1, 0, word_end,
6307c478bdstevel@tonic-gate			    list[i] + word_end, "", "");
6317c478bdstevel@tonic-gate			if (err != 0)
6327c478bdstevel@tonic-gate				return (err);
6337c478bdstevel@tonic-gate		}
6347c478bdstevel@tonic-gate	}
6357c478bdstevel@tonic-gate	return (0);
6367c478bdstevel@tonic-gate}
6377c478bdstevel@tonic-gate
6387c478bdstevel@tonic-gatestatic
6397c478bdstevel@tonic-gate/* ARGSUSED */
6407c478bdstevel@tonic-gateCPL_MATCH_FN(cmd_cpl_fn)
6417c478bdstevel@tonic-gate{
6427c478bdstevel@tonic-gate	if (global_scope) {
6437c478bdstevel@tonic-gate		/*
6447c478bdstevel@tonic-gate		 * The MAX/MIN tests below are to make sure we have at least
6457c478bdstevel@tonic-gate		 * enough characters to distinguish from other prefixes (MAX)
6467c478bdstevel@tonic-gate		 * but only check MIN(what we have, what we're checking).
6477c478bdstevel@tonic-gate		 */
6487c478bdstevel@tonic-gate		if (strncmp(line, "add ", MAX(MIN(word_end, 4), 1)) == 0)
6497c478bdstevel@tonic-gate			return (add_stuff(cpl, line, add_cmds, word_end));
6500209230gjelinek		if (strncmp(line, "clear ", MAX(MIN(word_end, 6), 2)) == 0)
6510209230gjelinek			return (add_stuff(cpl, line, clear_cmds, word_end));
6527c478bdstevel@tonic-gate		if (strncmp(line, "select ", MAX(MIN(word_end, 7), 3)) == 0)
6537c478bdstevel@tonic-gate			return (add_stuff(cpl, line, select_cmds, word_end));
6547c478bdstevel@tonic-gate		if (strncmp(line, "set ", MAX(MIN(word_end, 4), 3)) == 0)
6557c478bdstevel@tonic-gate			return (add_stuff(cpl, line, set_cmds, word_end));
6569e7542fdp		if (strncmp(line, "remove ", MAX(MIN(word_end, 7), 1)) == 0)
6579e7542fdp			return (add_stuff(cpl, line, remove_cmds, word_end));
6589e7542fdp		if (strncmp(line, "info ", MAX(MIN(word_end, 5), 1)) == 0)
6599e7542fdp			return (add_stuff(cpl, line, info_cmds, word_end));
6607c478bdstevel@tonic-gate		return (add_stuff(cpl, line, global_scope_cmds, word_end));
6617c478bdstevel@tonic-gate	}
6627c478bdstevel@tonic-gate	switch (resource_scope) {
6637c478bdstevel@tonic-gate	case RT_FS:
6647c478bdstevel@tonic-gate		return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
6657c478bdstevel@tonic-gate	case RT_NET:
6667c478bdstevel@tonic-gate		return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
6677c478bdstevel@tonic-gate	case RT_DEVICE:
6687c478bdstevel@tonic-gate		return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
6697c478bdstevel@tonic-gate	case RT_RCTL:
6707c478bdstevel@tonic-gate		return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
6717c478bdstevel@tonic-gate	case RT_ATTR:
6727c478bdstevel@tonic-gate		return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
673fa9e406ahrens	case RT_DATASET:
674fa9e406ahrens		return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
6750209230gjelinek	case RT_DCPU:
6760209230gjelinek		return (add_stuff(cpl, line, pset_res_scope_cmds, word_end));
677c97ad5cakolb	case RT_PCAP:
678c97ad5cakolb		return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
6790209230gjelinek	case RT_MCAP:
6800209230gjelinek		return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
681cb8a054Glenn Faden	case RT_ADMIN:
682cb8a054Glenn Faden		return (add_stuff(cpl, line, admin_res_scope_cmds, word_end));
683d2a7078Richard Lowe	case RT_SECFLAGS:
684d2a7078Richard Lowe		return (add_stuff(cpl, line, secflags_res_scope_cmds,
685d2a7078Richard Lowe		    word_end));
686d2a7078Richard Lowe
6877c478bdstevel@tonic-gate	}
6887c478bdstevel@tonic-gate	return (0);
6897c478bdstevel@tonic-gate}
6907c478bdstevel@tonic-gate
6917c478bdstevel@tonic-gate/*
6927c478bdstevel@tonic-gate * For the main CMD_func() functions below, several of them call getopt()
6937c478bdstevel@tonic-gate * then check optind against argc to make sure an extra parameter was not
6947c478bdstevel@tonic-gate * passed in.  The reason this is not caught in the grammar is that the
6957c478bdstevel@tonic-gate * grammar just checks for a miscellaneous TOKEN, which is *expected* to
6967c478bdstevel@tonic-gate * be "-F" (for example), but could be anything.  So (for example) this
6977c478bdstevel@tonic-gate * check will prevent "create bogus".
6987c478bdstevel@tonic-gate */
6997c478bdstevel@tonic-gate
7007c478bdstevel@tonic-gatecmd_t *
7017c478bdstevel@tonic-gatealloc_cmd(void)
7027c478bdstevel@tonic-gate{
7037c478bdstevel@tonic-gate	return (calloc(1, sizeof (cmd_t)));
7047c478bdstevel@tonic-gate}
7057c478bdstevel@tonic-gate
7067c478bdstevel@tonic-gatevoid
7077c478bdstevel@tonic-gatefree_cmd(cmd_t *cmd)
7087c478bdstevel@tonic-gate{
7097c478bdstevel@tonic-gate	int i;
7107c478bdstevel@tonic-gate
7117c478bdstevel@tonic-gate	for (i = 0; i < MAX_EQ_PROP_PAIRS; i++)
7127c478bdstevel@tonic-gate		if (cmd->cmd_property_ptr[i] != NULL) {
7137c478bdstevel@tonic-gate			property_value_ptr_t pp = cmd->cmd_property_ptr[i];
7147c478bdstevel@tonic-gate
7157c478bdstevel@tonic-gate			switch (pp->pv_type) {
7167c478bdstevel@tonic-gate			case PROP_VAL_SIMPLE:
7177c478bdstevel@tonic-gate				free(pp->pv_simple);
7187c478bdstevel@tonic-gate				break;
7197c478bdstevel@tonic-gate			case PROP_VAL_COMPLEX:
7207c478bdstevel@tonic-gate				free_complex(pp->pv_complex);
7217c478bdstevel@tonic-gate				break;
7227c478bdstevel@tonic-gate			case PROP_VAL_LIST:
7237c478bdstevel@tonic-gate				free_list(pp->pv_list);
7247c478bdstevel@tonic-gate				break;
7257c478bdstevel@tonic-gate			}
7267c478bdstevel@tonic-gate		}
7277c478bdstevel@tonic-gate	for (i = 0; i < cmd->cmd_argc; i++)
7287c478bdstevel@tonic-gate		free(cmd->cmd_argv[i]);
7297c478bdstevel@tonic-gate	free(cmd);
7307c478bdstevel@tonic-gate}
7317c478bdstevel@tonic-gate
7327c478bdstevel@tonic-gatecomplex_property_ptr_t
7337c478bdstevel@tonic-gatealloc_complex(void)
7347c478bdstevel@tonic-gate{
7357c478bdstevel@tonic-gate	return (calloc(1, sizeof (complex_property_t)));
7367c478bdstevel@tonic-gate}
7377c478bdstevel@tonic-gate
7387c478bdstevel@tonic-gatevoid
7397c478bdstevel@tonic-gatefree_complex(complex_property_ptr_t complex)
7407c478bdstevel@tonic-gate{
7417c478bdstevel@tonic-gate	if (complex == NULL)
7427c478bdstevel@tonic-gate		return;
7437c478bdstevel@tonic-gate	free_complex(complex->cp_next);
7447c478bdstevel@tonic-gate	if (complex->cp_value != NULL)
7457c478bdstevel@tonic-gate		free(complex->cp_value);
7467c478bdstevel@tonic-gate	free(complex);
7477c478bdstevel@tonic-gate}
7487c478bdstevel@tonic-gate
7497c478bdstevel@tonic-gatelist_property_ptr_t
7507c478bdstevel@tonic-gatealloc_list(void)
7517c478bdstevel@tonic-gate{
7527c478bdstevel@tonic-gate	return (calloc(1, sizeof (list_property_t)));
7537c478bdstevel@tonic-gate}
7547c478bdstevel@tonic-gate
7557c478bdstevel@tonic-gatevoid
7567c478bdstevel@tonic-gatefree_list(list_property_ptr_t list)
7577c478bdstevel@tonic-gate{
7587c478bdstevel@tonic-gate	if (list == NULL)
7597c478bdstevel@tonic-gate		return;
7607c478bdstevel@tonic-gate	if (list->lp_simple != NULL)
7617c478bdstevel@tonic-gate		free(list->lp_simple);
7627c478bdstevel@tonic-gate	free_complex(list->lp_complex);
7637c478bdstevel@tonic-gate	free_list(list->lp_next);
7647c478bdstevel@tonic-gate	free(list);
7657c478bdstevel@tonic-gate}
7667c478bdstevel@tonic-gate
7677c478bdstevel@tonic-gatevoid
7687c478bdstevel@tonic-gatefree_outer_list(list_property_ptr_t list)
7697c478bdstevel@tonic-gate{
7707c478bdstevel@tonic-gate	if (list == NULL)
7717c478bdstevel@tonic-gate		return;
7727c478bdstevel@tonic-gate	free_outer_list(list->lp_next);
7737c478bdstevel@tonic-gate	free(list);
7747c478bdstevel@tonic-gate}
7757c478bdstevel@tonic-gate
7767c478bdstevel@tonic-gatestatic struct zone_rctlvaltab *
7777c478bdstevel@tonic-gatealloc_rctlvaltab(void)
7787c478bdstevel@tonic-gate{
7797c478bdstevel@tonic-gate	return (calloc(1, sizeof (struct zone_rctlvaltab)));
7807c478bdstevel@tonic-gate}
7817c478bdstevel@tonic-gate
7827c478bdstevel@tonic-gatestatic char *
7837c478bdstevel@tonic-gatert_to_str(int res_type)
7847c478bdstevel@tonic-gate{
7857c478bdstevel@tonic-gate	assert(res_type >= RT_MIN && res_type <= RT_MAX);
7867c478bdstevel@tonic-gate	return (res_types[res_type]);
7877c478bdstevel@tonic-gate}
7887c478bdstevel@tonic-gate
7897c478bdstevel@tonic-gatestatic char *
7907c478bdstevel@tonic-gatept_to_str(int prop_type)
7917c478bdstevel@tonic-gate{
7927c478bdstevel@tonic-gate	assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
7937c478bdstevel@tonic-gate	return (prop_types[prop_type]);
7947c478bdstevel@tonic-gate}
7957c478bdstevel@tonic-gate
7967c478bdstevel@tonic-gatestatic char *
7977c478bdstevel@tonic-gatepvt_to_str(int pv_type)
7987c478bdstevel@tonic-gate{
7997c478bdstevel@tonic-gate	assert(pv_type >= PROP_VAL_MIN && pv_type <= PROP_VAL_MAX);
8007c478bdstevel@tonic-gate	return (prop_val_types[pv_type]);
8017c478bdstevel@tonic-gate}
8027c478bdstevel@tonic-gate
8037c478bdstevel@tonic-gatestatic char *
8047c478bdstevel@tonic-gatecmd_to_str(int cmd_num)
8057c478bdstevel@tonic-gate{
8067c478bdstevel@tonic-gate	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
8077c478bdstevel@tonic-gate	return (helptab[cmd_num].cmd_name);
8087c478bdstevel@tonic-gate}
8097c478bdstevel@tonic-gate
8103042b8bbatschul/* PRINTFLIKE1 */
8113042b8bbatschulstatic void
8123042b8bbatschulzerr(const char *fmt, ...)
8133042b8bbatschul{
8143042b8bbatschul	va_list alist;
8153042b8bbatschul	static int last_lineno;
8163042b8bbatschul
8173042b8bbatschul	/* lex_lineno has already been incremented in the lexer; compensate */
8183042b8bbatschul	if (cmd_file_mode && lex_lineno > last_lineno) {
8193042b8bbatschul		if (strcmp(cmd_file_name, "-") == 0)
8203042b8bbatschul			(void) fprintf(stderr, gettext("On line %d:\n"),
8213042b8bbatschul			    lex_lineno - 1);
8223042b8bbatschul		else
8233042b8bbatschul			(void) fprintf(stderr, gettext("On line %d of %s:\n"),
8243042b8bbatschul			    lex_lineno - 1, cmd_file_name);
8253042b8bbatschul		last_lineno = lex_lineno;
8263042b8bbatschul	}
8273042b8bbatschul	va_start(alist, fmt);
8283042b8bbatschul	(void) vfprintf(stderr, fmt, alist);
8293042b8bbatschul	(void) fprintf(stderr, "\n");
8303042b8bbatschul	va_end(alist);
8313042b8bbatschul}
8323042b8bbatschul
8337c478bdstevel@tonic-gate/*
8347c478bdstevel@tonic-gate * This is a separate function rather than a set of define's because of the
8357c478bdstevel@tonic-gate * gettext() wrapping.
8367c478bdstevel@tonic-gate */
8377c478bdstevel@tonic-gate
8387c478bdstevel@tonic-gate/*
8397c478bdstevel@tonic-gate * TRANSLATION_NOTE
8407c478bdstevel@tonic-gate * Each string below should have \t follow \n whenever needed; the
8417c478bdstevel@tonic-gate * initial \t and the terminal \n will be provided by the calling function.
8427c478bdstevel@tonic-gate */
8437c478bdstevel@tonic-gate
8447c478bdstevel@tonic-gatestatic char *
8457c478bdstevel@tonic-gatelong_help(int cmd_num)
8467c478bdstevel@tonic-gate{
8477c478bdstevel@tonic-gate	static char line[1024];	/* arbitrary large amount */
8487c478bdstevel@tonic-gate
8497c478bdstevel@tonic-gate	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
8507c478bdstevel@tonic-gate	switch (cmd_num) {
8517c478bdstevel@tonic-gate		case CMD_HELP:
8527c478bdstevel@tonic-gate			return (gettext("Prints help message."));
8537c478bdstevel@tonic-gate		case CMD_CREATE:
8547c478bdstevel@tonic-gate			(void) snprintf(line, sizeof (line),
8557c478bdstevel@tonic-gate			    gettext("Creates a configuration for the "
8567c478bdstevel@tonic-gate			    "specified zone.  %s should be\n\tused to "
8577c478bdstevel@tonic-gate			    "begin configuring a new zone.  If overwriting an "
8587c478bdstevel@tonic-gate			    "existing\n\tconfiguration, the -F flag can be "
8597c478bdstevel@tonic-gate			    "used to force the action.  If\n\t-t template is "
8607c478bdstevel@tonic-gate			    "given, creates a configuration identical to the\n"
8617c478bdstevel@tonic-gate			    "\tspecified template, except that the zone name "
8629e51865gjelinek			    "is changed from\n\ttemplate to zonename.  '%s -a' "
8639e51865gjelinek			    "creates a configuration from a\n\tdetached "
8649e51865gjelinek			    "zonepath.  '%s -b' results in a blank "
8659e51865gjelinek			    "configuration.\n\t'%s' with no arguments applies "
8669e51865gjelinek			    "the Sun default settings."),
8677c478bdstevel@tonic-gate			    cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE),
8689e51865gjelinek			    cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE));
8697c478bdstevel@tonic-gate			return (line);
8707c478bdstevel@tonic-gate		case CMD_EXIT:
8717c478bdstevel@tonic-gate			return (gettext("Exits the program.  The -F flag can "
8727c478bdstevel@tonic-gate			    "be used to force the action."));
8737c478bdstevel@tonic-gate		case CMD_EXPORT:
8747c478bdstevel@tonic-gate			return (gettext("Prints configuration to standard "
8757c478bdstevel@tonic-gate			    "output, or to output-file if\n\tspecified, in "
8767c478bdstevel@tonic-gate			    "a form suitable for use in a command-file."));
8777c478bdstevel@tonic-gate		case CMD_ADD:
8787c478bdstevel@tonic-gate			return (gettext("Add specified resource to "
8797c478bdstevel@tonic-gate			    "configuration."));
8807c478bdstevel@tonic-gate		case CMD_DELETE:
8817c478bdstevel@tonic-gate			return (gettext("Deletes the specified zone.  The -F "
8827c478bdstevel@tonic-gate			    "flag can be used to force the\n\taction."));
8837c478bdstevel@tonic-gate		case CMD_REMOVE:
8847c478bdstevel@tonic-gate			return (gettext("Remove specified resource from "
8850209230gjelinek			    "configuration.  The -F flag can be used\n\tto "
8860209230gjelinek			    "force the action."));
8877c478bdstevel@tonic-gate		case CMD_SELECT:
8887c478bdstevel@tonic-gate			(void) snprintf(line, sizeof (line),
8897c478bdstevel@tonic-gate			    gettext("Selects a resource to modify.  "
8907c478bdstevel@tonic-gate			    "Resource modification is completed\n\twith the "
8917c478bdstevel@tonic-gate			    "command \"%s\".  The property name/value pairs "
8927c478bdstevel@tonic-gate			    "must uniquely\n\tidentify a resource.  Note that "
8937c478bdstevel@tonic-gate			    "the curly braces ('{', '}') mean one\n\tor more "
8947c478bdstevel@tonic-gate			    "of whatever is between them."),
8957c478bdstevel@tonic-gate			    cmd_to_str(CMD_END));
8967c478bdstevel@tonic-gate			return (line);
8977c478bdstevel@tonic-gate		case CMD_SET:
8987c478bdstevel@tonic-gate			return (gettext("Sets property values."));
8990209230gjelinek		case CMD_CLEAR:
9000209230gjelinek			return (gettext("Clears property values."));
9017c478bdstevel@tonic-gate		case CMD_INFO:
9027c478bdstevel@tonic-gate			return (gettext("Displays information about the "
9037c478bdstevel@tonic-gate			    "current configuration.  If resource\n\ttype is "
9047c478bdstevel@tonic-gate			    "specified, displays only information about "
9057c478bdstevel@tonic-gate			    "resources of\n\tthe relevant type.  If resource "
9067c478bdstevel@tonic-gate			    "id is specified, displays only\n\tinformation "
9077c478bdstevel@tonic-gate			    "about that resource."));
9087c478bdstevel@tonic-gate		case CMD_VERIFY:
9097c478bdstevel@tonic-gate			return (gettext("Verifies current configuration "
9107c478bdstevel@tonic-gate			    "for correctness (some resource types\n\thave "
9117c478bdstevel@tonic-gate			    "required properties)."));
9127c478bdstevel@tonic-gate		case CMD_COMMIT:
9137c478bdstevel@tonic-gate			(void) snprintf(line, sizeof (line),
9147c478bdstevel@tonic-gate			    gettext("Commits current configuration.  "
9157c478bdstevel@tonic-gate			    "Configuration must be committed to\n\tbe used by "
9167c478bdstevel@tonic-gate			    "%s.  Until the configuration is committed, "
9177c478bdstevel@tonic-gate			    "changes \n\tcan be removed with the %s "
9187c478bdstevel@tonic-gate			    "command.  This operation is\n\tattempted "
9197c478bdstevel@tonic-gate			    "automatically upon completion of a %s "
9207c478bdstevel@tonic-gate			    "session."), "zoneadm", cmd_to_str(CMD_REVERT),
9217c478bdstevel@tonic-gate			    "zonecfg");
9227c478bdstevel@tonic-gate			return (line);
9237c478bdstevel@tonic-gate		case CMD_REVERT:
9247c478bdstevel@tonic-gate			return (gettext("Reverts configuration back to the "
9257c478bdstevel@tonic-gate			    "last committed state.  The -F flag\n\tcan be "
9267c478bdstevel@tonic-gate			    "used to force the action."));
9277c478bdstevel@tonic-gate		case CMD_CANCEL:
9287c478bdstevel@tonic-gate			return (gettext("Cancels resource/property "
9297c478bdstevel@tonic-gate			    "specification."));
9307c478bdstevel@tonic-gate		case CMD_END:
9317c478bdstevel@tonic-gate			return (gettext("Ends resource/property "
9327c478bdstevel@tonic-gate			    "specification."));
9337c478bdstevel@tonic-gate	}
9347c478bdstevel@tonic-gate	/* NOTREACHED */
9357e362f5comay	return (NULL);
9367c478bdstevel@tonic-gate}
9377c478bdstevel@tonic-gate
9387c478bdstevel@tonic-gate/*
939944b13eGary Mills * Return the input filename appended to each component of the path
940944b13eGary Mills * or the filename itself if it is absolute.
941944b13eGary Mills * Parameters: path string, file name, output string.
942944b13eGary Mills */
943944b13eGary Mills/* Copied almost verbatim from libtnfctl/prb_findexec.c */
944944b13eGary Millsstatic const char *
945944b13eGary Millsexec_cat(const char *s1, const char *s2, char *si)
946944b13eGary Mills{
947944b13eGary Mills	char		   *s;
948944b13eGary Mills	/* Number of remaining characters in s */
949944b13eGary Mills	int			 cnt = PATH_MAX + 1;
950944b13eGary Mills
951944b13eGary Mills	s = si;
952944b13eGary Mills	while (*s1 && *s1 != ':') { /* Copy first component of path to si */
953944b13eGary Mills		if (cnt > 0) {
954944b13eGary Mills			*s++ = *s1++;
955944b13eGary Mills			cnt--;
956944b13eGary Mills		} else {
957944b13eGary Mills			s1++;
958944b13eGary Mills		}
959944b13eGary Mills	}
960944b13eGary Mills	if (si != s && cnt > 0) { /* Add slash if s2 is not absolute */
961944b13eGary Mills		*s++ = '/';
962944b13eGary Mills		cnt--;
963944b13eGary Mills	}
964944b13eGary Mills	while (*s2 && cnt > 0) { /* Copy s2 to si */
965944b13eGary Mills		*s++ = *s2++;
966944b13eGary Mills		cnt--;
967944b13eGary Mills	}
968944b13eGary Mills	*s = '\0';  /* Terminate the output string */
969944b13eGary Mills	return (*s1 ? ++s1 : NULL);  /* Return next path component or NULL */
970944b13eGary Mills}
971944b13eGary Mills
972944b13eGary Mills/* Determine that a name exists in PATH */
973944b13eGary Mills/* Copied with changes from libtnfctl/prb_findexec.c */
974944b13eGary Millsstatic int
975944b13eGary Millspath_find(const char *name)
976944b13eGary Mills{
977944b13eGary Mills	const char	 *pathstr;
978944b13eGary Mills	char		fname[PATH_MAX + 2];
979944b13eGary Mills	const char	 *cp;
980944b13eGary Mills	struct stat	 stat_buf;
981944b13eGary Mills
982944b13eGary Mills	if ((pathstr = getenv("PATH")) == NULL) {
983944b13eGary Mills		if (geteuid() == 0 || getuid() == 0)
984944b13eGary Mills			pathstr = "/usr/sbin:/usr/bin";
985944b13eGary Mills		else
986944b13eGary Mills			pathstr = "/usr/bin:";
987944b13eGary Mills	}
988944b13eGary Mills	cp = strchr(name, '/') ? (const char *) "" : pathstr;
989944b13eGary Mills
990944b13eGary Mills	do {
991944b13eGary Mills		cp = exec_cat(cp, name, fname);
992944b13eGary Mills		if (stat(fname, &stat_buf) != -1) {
993944b13eGary Mills			/* successful find of the file */
994944b13eGary Mills			return (0);
995944b13eGary Mills		}
996944b13eGary Mills	} while (cp != NULL);
997944b13eGary Mills
998944b13eGary Mills	return (-1);
999944b13eGary Mills}
1000944b13eGary Mills
1001944b13eGary Millsstatic FILE *
1002d2a7078Richard Lowepager_open(void)
1003d2a7078Richard Lowe{
1004944b13eGary Mills	FILE *newfp;
1005944b13eGary Mills	char *pager, *space;
1006944b13eGary Mills
1007944b13eGary Mills	pager = getenv("PAGER");
1008944b13eGary Mills	if (pager == NULL || *pager == '\0')
1009944b13eGary Mills		pager = PAGER;
1010944b13eGary Mills
1011944b13eGary Mills	space = strchr(pager, ' ');
1012944b13eGary Mills	if (space)
1013944b13eGary Mills		*space = '\0';
1014944b13eGary Mills	if (path_find(pager) == 0) {
1015944b13eGary Mills		if (space)
1016944b13eGary Mills			*space = ' ';
1017944b13eGary Mills		if ((newfp = popen(pager, "w")) == NULL)
1018944b13eGary Mills			zerr(gettext("PAGER open failed (%s)."),
1019944b13eGary Mills			    strerror(errno));
1020944b13eGary Mills		return (newfp);
1021944b13eGary Mills	} else {
1022944b13eGary Mills		zerr(gettext("PAGER %s does not exist (%s)."),
1023944b13eGary Mills		    pager, strerror(errno));
1024944b13eGary Mills	}
1025944b13eGary Mills	return (NULL);
1026944b13eGary Mills}
1027944b13eGary Mills
1028944b13eGary Millsstatic void
1029d2a7078Richard Lowepager_close(FILE *fp)
1030d2a7078Richard Lowe{
1031944b13eGary Mills	int status;
1032944b13eGary Mills
1033944b13eGary Mills	status = pclose(fp);
1034944b13eGary Mills	if (status == -1)
1035944b13eGary Mills		zerr(gettext("PAGER close failed (%s)."),
1036944b13eGary Mills		    strerror(errno));
1037944b13eGary Mills}
1038944b13eGary Mills
1039944b13eGary Mills/*
10407c478bdstevel@tonic-gate * Called with verbose TRUE when help is explicitly requested, FALSE for
10417c478bdstevel@tonic-gate * unexpected errors.
10427c478bdstevel@tonic-gate */
10437c478bdstevel@tonic-gate
10447c478bdstevel@tonic-gatevoid
1045bbec428gjelinekusage(boolean_t verbose, uint_t flags)
10467c478bdstevel@tonic-gate{
10473042b8bbatschul	FILE *fp = verbose ? stdout : stderr;
10483042b8bbatschul	FILE *newfp;
1049bbec428gjelinek	boolean_t need_to_close = B_FALSE;
10507c478bdstevel@tonic-gate	int i;
10517c478bdstevel@tonic-gate
10527c478bdstevel@tonic-gate	/* don't page error output */
10537c478bdstevel@tonic-gate	if (verbose && interactive_mode) {
1054944b13eGary Mills		if ((newfp = pager_open()) != NULL) {
1055944b13eGary Mills			need_to_close = B_TRUE;
1056944b13eGary Mills			fp = newfp;
10577c478bdstevel@tonic-gate		}
10587c478bdstevel@tonic-gate	}
10593042b8bbatschul
10607c478bdstevel@tonic-gate	if (flags & HELP_META) {
10617c478bdstevel@tonic-gate		(void) fprintf(fp, gettext("More help is available for the "
10627c478bdstevel@tonic-gate		    "following:\n"));
10637c478bdstevel@tonic-gate		(void) fprintf(fp, "\n\tcommands ('%s commands')\n",
10647c478bdstevel@tonic-gate		    cmd_to_str(CMD_HELP));
10657c478bdstevel@tonic-gate		(void) fprintf(fp, "\tsyntax ('%s syntax')\n",
10667c478bdstevel@tonic-gate		    cmd_to_str(CMD_HELP));
10677c478bdstevel@tonic-gate		(void) fprintf(fp, "\tusage ('%s usage')\n\n",
10687c478bdstevel@tonic-gate		    cmd_to_str(CMD_HELP));
10697c478bdstevel@tonic-gate		(void) fprintf(fp, gettext("You may also obtain help on any "
10707c478bdstevel@tonic-gate		    "command by typing '%s <command-name>.'\n"),
10717c478bdstevel@tonic-gate		    cmd_to_str(CMD_HELP));
10727c478bdstevel@tonic-gate	}
10737c478bdstevel@tonic-gate	if (flags & HELP_RES_SCOPE) {
10747c478bdstevel@tonic-gate		switch (resource_scope) {
10757c478bdstevel@tonic-gate		case RT_FS:
10767c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("The '%s' resource scope is "
10777c478bdstevel@tonic-gate			    "used to configure a file-system.\n"),
10787c478bdstevel@tonic-gate			    rt_to_str(resource_scope));
10797c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("Valid commands:\n"));
10807c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10817c478bdstevel@tonic-gate			    pt_to_str(PT_DIR), gettext("<path>"));
10827c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10837c478bdstevel@tonic-gate			    pt_to_str(PT_SPECIAL), gettext("<path>"));
10847c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10857c478bdstevel@tonic-gate			    pt_to_str(PT_RAW), gettext("<raw-device>"));
10867c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10877c478bdstevel@tonic-gate			    pt_to_str(PT_TYPE), gettext("<file-system type>"));
10887c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s %s\n", cmd_to_str(CMD_ADD),
10897c478bdstevel@tonic-gate			    pt_to_str(PT_OPTIONS),
10907c478bdstevel@tonic-gate			    gettext("<file-system options>"));
1091ffbafc5comay			(void) fprintf(fp, "\t%s %s %s\n",
1092ffbafc5comay			    cmd_to_str(CMD_REMOVE), pt_to_str(PT_OPTIONS),
1093ffbafc5comay			    gettext("<file-system options>"));
10947c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("Consult the file-system "
10957c478bdstevel@tonic-gate			    "specific manual page, such as mount_ufs(1M), "
10967c478bdstevel@tonic-gate			    "for\ndetails about file-system options.  Note "
10977c478bdstevel@tonic-gate			    "that any file-system options with an\nembedded "
10987c478bdstevel@tonic-gate			    "'=' character must be enclosed in double quotes, "
10997c478bdstevel@tonic-gate			    /*CSTYLED*/
11007c478bdstevel@tonic-gate			    "such as \"%s=5\".\n"), MNTOPT_RETRY);
11017c478bdstevel@tonic-gate			break;
11027c478bdstevel@tonic-gate		case RT_NET:
11037c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("The '%s' resource scope is "
11047c478bdstevel@tonic-gate			    "used to configure a network interface.\n"),
11057c478bdstevel@tonic-gate			    rt_to_str(resource_scope));
11067c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("Valid commands:\n"));
11077c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11087c478bdstevel@tonic-gate			    pt_to_str(PT_ADDRESS), gettext("<IP-address>"));
11097c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1110550b6e4Sowmini Varadhan			    pt_to_str(PT_ALLOWED_ADDRESS),
1111550b6e4Sowmini Varadhan			    gettext("<IP-address>"));
1112550b6e4Sowmini Varadhan			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11137c478bdstevel@tonic-gate			    pt_to_str(PT_PHYSICAL), gettext("<interface>"));
11147c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("See ifconfig(1M) for "
11157c478bdstevel@tonic-gate			    "details of the <interface> string.\n"));
1116550b6e4Sowmini Varadhan			(void) fprintf(fp, gettext("%s %s is valid "
1117550b6e4Sowmini Varadhan			    "if the %s property is set to %s, otherwise it "
1118de860bdgfaden			    "must not be set.\n"),
1119f4b3ec6dh			    cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS),
1120550b6e4Sowmini Varadhan			    pt_to_str(PT_IPTYPE), gettext("shared"));
1121550b6e4Sowmini Varadhan			(void) fprintf(fp, gettext("%s %s is valid "
1122550b6e4Sowmini Varadhan			    "if the %s property is set to %s, otherwise it "
1123550b6e4Sowmini Varadhan			    "must not be set.\n"),
1124550b6e4Sowmini Varadhan			    cmd_to_str(CMD_SET), pt_to_str(PT_ALLOWED_ADDRESS),
1125550b6e4Sowmini Varadhan			    pt_to_str(PT_IPTYPE), gettext("exclusive"));
1126550b6e4Sowmini Varadhan			(void) fprintf(fp, gettext("\t%s %s=%s\n%s %s "
1127550b6e4Sowmini Varadhan			    "is valid if the %s or %s property is set, "
1128550b6e4Sowmini Varadhan			    "otherwise it must not be set\n"),
1129550b6e4Sowmini Varadhan			    cmd_to_str(CMD_SET),
1130550b6e4Sowmini Varadhan			    pt_to_str(PT_DEFROUTER), gettext("<IP-address>"),
1131de860bdgfaden			    cmd_to_str(CMD_SET), pt_to_str(PT_DEFROUTER),
1132550b6e4Sowmini Varadhan			    gettext(pt_to_str(PT_ADDRESS)),
1133550b6e4Sowmini Varadhan			    gettext(pt_to_str(PT_ALLOWED_ADDRESS)));
11347c478bdstevel@tonic-gate			break;
11357c478bdstevel@tonic-gate		case RT_DEVICE:
11367c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("The '%s' resource scope is "
11377c478bdstevel@tonic-gate			    "used to configure a device node.\n"),
11387c478bdstevel@tonic-gate			    rt_to_str(resource_scope));
11397c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("Valid commands:\n"));
11407c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11417c478bdstevel@tonic-gate			    pt_to_str(PT_MATCH), gettext("<device-path>"));
11427c478bdstevel@tonic-gate			break;
11437c478bdstevel@tonic-gate		case RT_RCTL:
11447c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("The '%s' resource scope is "
11457c478bdstevel@tonic-gate			    "used to configure a resource control.\n"),
11467c478bdstevel@tonic-gate			    rt_to_str(resource_scope));
11477c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("Valid commands:\n"));
11487c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11497c478bdstevel@tonic-gate			    pt_to_str(PT_NAME), gettext("<string>"));
11507c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
11517c478bdstevel@tonic-gate			    cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
11527c478bdstevel@tonic-gate			    pt_to_str(PT_PRIV), gettext("<priv-value>"),
11537c478bdstevel@tonic-gate			    pt_to_str(PT_LIMIT), gettext("<number>"),
11547c478bdstevel@tonic-gate			    pt_to_str(PT_ACTION), gettext("<action-value>"));
1155ffbafc5comay			(void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1156ffbafc5comay			    cmd_to_str(CMD_REMOVE), pt_to_str(PT_VALUE),
1157ffbafc5comay			    pt_to_str(PT_PRIV), gettext("<priv-value>"),
1158ffbafc5comay			    pt_to_str(PT_LIMIT), gettext("<number>"),
1159ffbafc5comay			    pt_to_str(PT_ACTION), gettext("<action-value>"));
11607c478bdstevel@tonic-gate			(void) fprintf(fp, "%s\n\t%s := privileged\n"
11617c478bdstevel@tonic-gate			    "\t%s := none | deny\n", gettext("Where"),
11627c478bdstevel@tonic-gate			    gettext("<priv-value>"), gettext("<action-value>"));
11637c478bdstevel@tonic-gate			break;
11647c478bdstevel@tonic-gate		case RT_ATTR:
11657c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("The '%s' resource scope is "
11667c478bdstevel@tonic-gate			    "used to configure a generic attribute.\n"),
11677c478bdstevel@tonic-gate			    rt_to_str(resource_scope));
11687c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("Valid commands:\n"));
11697c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11707c478bdstevel@tonic-gate			    pt_to_str(PT_NAME), gettext("<name>"));
11717c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=boolean\n",
11727c478bdstevel@tonic-gate			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
11737c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=true | false\n",
11747c478bdstevel@tonic-gate			    cmd_to_str(CMD_SET), pt_to_str(PT_VALUE));
11757c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("or\n"));
11767c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=int\n", cmd_to_str(CMD_SET),
11777c478bdstevel@tonic-gate			    pt_to_str(PT_TYPE));
11787c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11797c478bdstevel@tonic-gate			    pt_to_str(PT_VALUE), gettext("<integer>"));
11807c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("or\n"));
11817c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=string\n",
11827c478bdstevel@tonic-gate			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
11837c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11847c478bdstevel@tonic-gate			    pt_to_str(PT_VALUE), gettext("<string>"));
11857c478bdstevel@tonic-gate			(void) fprintf(fp, gettext("or\n"));
11867c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=uint\n",
11877c478bdstevel@tonic-gate			    cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
11887c478bdstevel@tonic-gate			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11897c478bdstevel@tonic-gate			    pt_to_str(PT_VALUE), gettext("<unsigned integer>"));
11907c478bdstevel@tonic-gate			break;
1191fa9e406ahrens		case RT_DATASET:
1192fa9e406ahrens			(void) fprintf(fp, gettext("The '%s' resource scope is "
1193fa9e406ahrens			    "used to export ZFS datasets.\n"),
1194fa9e406ahrens			    rt_to_str(resource_scope));
1195fa9e406ahrens			(void) fprintf(fp, gettext("Valid commands:\n"));
1196fa9e406ahrens			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1197fa9e406ahrens			    pt_to_str(PT_NAME), gettext("<name>"));
1198fa9e406ahrens			break;
11990209230gjelinek		case RT_DCPU:
12000209230gjelinek			(void) fprintf(fp, gettext("The '%s' resource scope "
12010209230gjelinek			    "configures the 'pools' facility to dedicate\na "
12020209230gjelinek			    "subset of the system's processors to this zone "
12030209230gjelinek			    "while it is running.\n"),
12040209230gjelinek			    rt_to_str(resource_scope));
12050209230gjelinek			(void) fprintf(fp, gettext("Valid commands:\n"));
12060209230gjelinek			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
12070209230gjelinek			    pt_to_str(PT_NCPUS),
12080209230gjelinek			    gettext("<unsigned integer | range>"));
12090209230gjelinek			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
12100209230gjelinek			    pt_to_str(PT_IMPORTANCE),
12110209230gjelinek			    gettext("<unsigned integer>"));
12120209230gjelinek			break;
1213c97ad5cakolb		case RT_PCAP:
1214c97ad5cakolb			(void) fprintf(fp, gettext("The '%s' resource scope is "
1215c97ad5cakolb			    "used to set an upper limit (a cap) on the\n"
1216c97ad5cakolb			    "percentage of CPU that can be used by this zone.  "
1217c97ad5cakolb			    "A '%s' value of 1\ncorresponds to one cpu.  The "
1218c97ad5cakolb			    "value can be set higher than 1, up to the total\n"
1219c97ad5cakolb			    "number of CPUs on the system.  The value can "
1220c97ad5cakolb			    "also be less than 1,\nrepresenting a fraction of "
1221c97ad5cakolb			    "a cpu.\n"),
1222c97ad5cakolb			    rt_to_str(resource_scope), pt_to_str(PT_NCPUS));
1223c97ad5cakolb			(void) fprintf(fp, gettext("Valid commands:\n"));
1224c97ad5cakolb			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1225c97ad5cakolb			    pt_to_str(PT_NCPUS), gettext("<unsigned decimal>"));
1226c97ad5cakolb			break;
12270209230gjelinek		case RT_MCAP:
12280209230gjelinek			(void) fprintf(fp, gettext("The '%s' resource scope is "
12290209230gjelinek			    "used to set an upper limit (a cap) on the\n"
12300209230gjelinek			    "amount of physical memory, swap space and locked "
12310209230gjelinek			    "memory that can be used by\nthis zone.\n"),
12320209230gjelinek			    rt_to_str(resource_scope));
12330209230gjelinek			(void) fprintf(fp, gettext("Valid commands:\n"));
12340209230gjelinek			(void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
12350209230gjelinek			    pt_to_str(PT_PHYSICAL),
12360209230gjelinek			    gettext("<qualified unsigned decimal>"));
1237