5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 */
26
27 /*
28 * zonecfg is a lex/yacc based command interpreter used to manage zone
29 * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which
30 * the grammar (see zonecfg_grammar.y) builds up into commands, some of
31 * which takes resources and/or properties as arguments. See the block
32 * comments near the end of zonecfg_grammar.y for how the data structures
33 * which keep track of these resources and properties are built up.
34 *
35 * The resource/property data structures are inserted into a command
36 * structure (see zonecfg.h), which also keeps track of command names,
37 * miscellaneous arguments, and function handlers. The grammar selects
38 * the appropriate function handler, each of which takes a pointer to a
39 * command structure as its sole argument, and invokes it. The grammar
40 * itself is "entered" (a la the Matrix) by yyparse(), which is called
41 * from read_input(), our main driving function. That in turn is called
42 * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
43 * of which is called from main() depending on how the program was invoked.
44 *
914 */
915
916 void
917 usage(boolean_t verbose, uint_t flags)
918 {
919 FILE *fp = verbose ? stdout : stderr;
920 FILE *newfp;
921 boolean_t need_to_close = B_FALSE;
922 char *pager, *space;
923 int i;
924 struct stat statbuf;
925
926 /* don't page error output */
927 if (verbose && interactive_mode) {
928 if ((pager = getenv("PAGER")) == NULL)
929 pager = PAGER;
930
931 space = strchr(pager, ' ');
932 if (space)
933 *space = '\0';
934 if (stat(pager, &statbuf) == 0) {
935 if (space)
936 *space = ' ';
937 if ((newfp = popen(pager, "w")) != NULL) {
938 need_to_close = B_TRUE;
939 fp = newfp;
940 }
941 } else {
942 zerr(gettext("PAGER %s does not exist (%s)."),
943 pager, strerror(errno));
944 }
945 }
946
947 if (flags & HELP_META) {
948 (void) fprintf(fp, gettext("More help is available for the "
949 "following:\n"));
950 (void) fprintf(fp, "\n\tcommands ('%s commands')\n",
951 cmd_to_str(CMD_HELP));
952 (void) fprintf(fp, "\tsyntax ('%s syntax')\n",
953 cmd_to_str(CMD_HELP));
954 (void) fprintf(fp, "\tusage ('%s usage')\n\n",
955 cmd_to_str(CMD_HELP));
956 (void) fprintf(fp, gettext("You may also obtain help on any "
957 "command by typing '%s <command-name>.'\n"),
958 cmd_to_str(CMD_HELP));
959 }
960 if (flags & HELP_RES_SCOPE) {
961 switch (resource_scope) {
962 case RT_FS:
963 (void) fprintf(fp, gettext("The '%s' resource scope is "
1256 pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
1257 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
1258 pt_to_str(PT_MATCH));
1259 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1260 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1261 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1262 pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1263 pt_to_str(PT_VALUE));
1264 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1265 pt_to_str(PT_NAME));
1266 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
1267 pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
1268 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
1269 pt_to_str(PT_NCPUS));
1270 (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
1271 pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
1272 pt_to_str(PT_LOCKED));
1273 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
1274 pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
1275 }
1276 if (need_to_close)
1277 (void) pclose(fp);
1278 }
1279
1280 static void
1281 zone_perror(char *prefix, int err, boolean_t set_saw)
1282 {
1283 zerr("%s: %s", prefix, zonecfg_strerror(err));
1284 if (set_saw)
1285 saw_error = B_TRUE;
1286 }
1287
1288 /*
1289 * zone_perror() expects a single string, but for remove and select
1290 * we have both the command and the resource type, so this wrapper
1291 * function serves the same purpose in a slightly different way.
1292 */
1293
1294 static void
1295 z_cmd_rt_perror(int cmd_num, int res_num, int err, boolean_t set_saw)
1296 {
1297 zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num),
5345 boolean_t need_to_close = B_FALSE;
5346 char *pager, *space;
5347 int type;
5348 int res1, res2;
5349 uint64_t swap_limit;
5350 uint64_t locked_limit;
5351 struct stat statbuf;
5352
5353 assert(cmd != NULL);
5354
5355 if (initialize(B_TRUE) != Z_OK)
5356 return;
5357
5358 /* don't page error output */
5359 if (interactive_mode) {
5360 if ((pager = getenv("PAGER")) == NULL)
5361 pager = PAGER;
5362 space = strchr(pager, ' ');
5363 if (space)
5364 *space = '\0';
5365 if (stat(pager, &statbuf) == 0) {
5366 if (space)
5367 *space = ' ';
5368 if ((fp = popen(pager, "w")) != NULL)
5369 need_to_close = B_TRUE;
5370 else
5371 fp = stdout;
5372 } else {
5373 zerr(gettext("PAGER %s does not exist (%s)."),
5374 pager, strerror(errno));
5375 }
5376
5377 setbuf(fp, NULL);
5378 }
5379
5380 if (!global_scope) {
5381 switch (resource_scope) {
5382 case RT_FS:
5383 output_fs(fp, &in_progress_fstab);
5384 break;
5385 case RT_NET:
5386 output_net(fp, &in_progress_nwiftab);
5387 break;
5388 case RT_DEVICE:
5389 output_dev(fp, &in_progress_devtab);
5390 break;
5391 case RT_RCTL:
5392 output_rctl(fp, &in_progress_rctltab);
5393 break;
5394 case RT_ATTR:
5395 output_attr(fp, &in_progress_attrtab);
5544 info_pcap(fp);
5545 break;
5546 case RT_MCAP:
5547 info_mcap(handle, fp);
5548 break;
5549 case RT_HOSTID:
5550 info_hostid(handle, fp);
5551 break;
5552 case RT_ADMIN:
5553 info_auth(handle, fp, cmd);
5554 break;
5555 case RT_FS_ALLOWED:
5556 info_fs_allowed(handle, fp);
5557 break;
5558 default:
5559 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
5560 B_TRUE);
5561 }
5562
5563 cleanup:
5564 if (need_to_close)
5565 (void) pclose(fp);
5566 }
5567
5568 /*
5569 * Helper function for verify-- checks that a required string property
5570 * exists.
5571 */
5572 static void
5573 check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
5574 {
5575 if (strlen(attr) == 0) {
5576 zerr(gettext("%s: %s not specified"), rt_to_str(rt),
5577 pt_to_str(pt));
5578 saw_error = B_TRUE;
5579 if (*ret_val == Z_OK)
5580 *ret_val = Z_REQD_PROPERTY_MISSING;
5581 }
5582 }
5583
5584 static int
5585 do_subproc(char *cmdbuf)
|
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 * Copyright 2014 Gary Mills
26 */
27
28 /*
29 * zonecfg is a lex/yacc based command interpreter used to manage zone
30 * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which
31 * the grammar (see zonecfg_grammar.y) builds up into commands, some of
32 * which takes resources and/or properties as arguments. See the block
33 * comments near the end of zonecfg_grammar.y for how the data structures
34 * which keep track of these resources and properties are built up.
35 *
36 * The resource/property data structures are inserted into a command
37 * structure (see zonecfg.h), which also keeps track of command names,
38 * miscellaneous arguments, and function handlers. The grammar selects
39 * the appropriate function handler, each of which takes a pointer to a
40 * command structure as its sole argument, and invokes it. The grammar
41 * itself is "entered" (a la the Matrix) by yyparse(), which is called
42 * from read_input(), our main driving function. That in turn is called
43 * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
44 * of which is called from main() depending on how the program was invoked.
45 *
915 */
916
917 void
918 usage(boolean_t verbose, uint_t flags)
919 {
920 FILE *fp = verbose ? stdout : stderr;
921 FILE *newfp;
922 boolean_t need_to_close = B_FALSE;
923 char *pager, *space;
924 int i;
925 struct stat statbuf;
926
927 /* don't page error output */
928 if (verbose && interactive_mode) {
929 if ((pager = getenv("PAGER")) == NULL)
930 pager = PAGER;
931
932 space = strchr(pager, ' ');
933 if (space)
934 *space = '\0';
935 if (*pager == '/' && stat(pager, &statbuf) != 0) {
936 zerr(gettext("PAGER %s does not exist (%s)."),
937 pager, strerror(errno));
938 } else {
939 if (space)
940 *space = ' ';
941 if ((newfp = popen(pager, "w")) == NULL) {
942 zerr(gettext("PAGER %s open failed (%s)."),
943 pager, strerror(errno));
944 } else {
945 need_to_close = B_TRUE;
946 fp = newfp;
947 }
948 }
949 }
950
951 if (flags & HELP_META) {
952 (void) fprintf(fp, gettext("More help is available for the "
953 "following:\n"));
954 (void) fprintf(fp, "\n\tcommands ('%s commands')\n",
955 cmd_to_str(CMD_HELP));
956 (void) fprintf(fp, "\tsyntax ('%s syntax')\n",
957 cmd_to_str(CMD_HELP));
958 (void) fprintf(fp, "\tusage ('%s usage')\n\n",
959 cmd_to_str(CMD_HELP));
960 (void) fprintf(fp, gettext("You may also obtain help on any "
961 "command by typing '%s <command-name>.'\n"),
962 cmd_to_str(CMD_HELP));
963 }
964 if (flags & HELP_RES_SCOPE) {
965 switch (resource_scope) {
966 case RT_FS:
967 (void) fprintf(fp, gettext("The '%s' resource scope is "
1260 pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
1261 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
1262 pt_to_str(PT_MATCH));
1263 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1264 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1265 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1266 pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1267 pt_to_str(PT_VALUE));
1268 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1269 pt_to_str(PT_NAME));
1270 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
1271 pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
1272 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
1273 pt_to_str(PT_NCPUS));
1274 (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
1275 pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
1276 pt_to_str(PT_LOCKED));
1277 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
1278 pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
1279 }
1280 if (need_to_close) {
1281 int status;
1282
1283 status = pclose(fp);
1284 if (status == -1)
1285 zerr(gettext("PAGER %s close failed (%s)."),
1286 pager, strerror(errno));
1287 else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
1288 zerr(gettext("PAGER %s exit code: %d."),
1289 pager, WEXITSTATUS(status));
1290 }
1291 }
1292
1293 static void
1294 zone_perror(char *prefix, int err, boolean_t set_saw)
1295 {
1296 zerr("%s: %s", prefix, zonecfg_strerror(err));
1297 if (set_saw)
1298 saw_error = B_TRUE;
1299 }
1300
1301 /*
1302 * zone_perror() expects a single string, but for remove and select
1303 * we have both the command and the resource type, so this wrapper
1304 * function serves the same purpose in a slightly different way.
1305 */
1306
1307 static void
1308 z_cmd_rt_perror(int cmd_num, int res_num, int err, boolean_t set_saw)
1309 {
1310 zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num),
5358 boolean_t need_to_close = B_FALSE;
5359 char *pager, *space;
5360 int type;
5361 int res1, res2;
5362 uint64_t swap_limit;
5363 uint64_t locked_limit;
5364 struct stat statbuf;
5365
5366 assert(cmd != NULL);
5367
5368 if (initialize(B_TRUE) != Z_OK)
5369 return;
5370
5371 /* don't page error output */
5372 if (interactive_mode) {
5373 if ((pager = getenv("PAGER")) == NULL)
5374 pager = PAGER;
5375 space = strchr(pager, ' ');
5376 if (space)
5377 *space = '\0';
5378 if (*pager == '/' && stat(pager, &statbuf) != 0) {
5379 zerr(gettext("PAGER %s does not exist (%s)."),
5380 pager, strerror(errno));
5381 } else {
5382 if (space)
5383 *space = ' ';
5384 if ((fp = popen(pager, "w")) == NULL) {
5385 fp = stdout;
5386 zerr(gettext("PAGER %s open failed (%s)."),
5387 pager, strerror(errno));
5388 } else {
5389 need_to_close = B_TRUE;
5390 }
5391 }
5392
5393 setbuf(fp, NULL);
5394 }
5395
5396 if (!global_scope) {
5397 switch (resource_scope) {
5398 case RT_FS:
5399 output_fs(fp, &in_progress_fstab);
5400 break;
5401 case RT_NET:
5402 output_net(fp, &in_progress_nwiftab);
5403 break;
5404 case RT_DEVICE:
5405 output_dev(fp, &in_progress_devtab);
5406 break;
5407 case RT_RCTL:
5408 output_rctl(fp, &in_progress_rctltab);
5409 break;
5410 case RT_ATTR:
5411 output_attr(fp, &in_progress_attrtab);
5560 info_pcap(fp);
5561 break;
5562 case RT_MCAP:
5563 info_mcap(handle, fp);
5564 break;
5565 case RT_HOSTID:
5566 info_hostid(handle, fp);
5567 break;
5568 case RT_ADMIN:
5569 info_auth(handle, fp, cmd);
5570 break;
5571 case RT_FS_ALLOWED:
5572 info_fs_allowed(handle, fp);
5573 break;
5574 default:
5575 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
5576 B_TRUE);
5577 }
5578
5579 cleanup:
5580 if (need_to_close) {
5581 int status;
5582
5583 status = pclose(fp);
5584 if (status == -1)
5585 zerr(gettext("PAGER %s close failed (%s)."),
5586 pager, strerror(errno));
5587 else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
5588 zerr(gettext("PAGER %s exit code: %d."),
5589 pager, WEXITSTATUS(status));
5590 }
5591 }
5592
5593 /*
5594 * Helper function for verify-- checks that a required string property
5595 * exists.
5596 */
5597 static void
5598 check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
5599 {
5600 if (strlen(attr) == 0) {
5601 zerr(gettext("%s: %s not specified"), rt_to_str(rt),
5602 pt_to_str(pt));
5603 saw_error = B_TRUE;
5604 if (*ret_val == Z_OK)
5605 *ret_val = Z_REQD_PROPERTY_MISSING;
5606 }
5607 }
5608
5609 static int
5610 do_subproc(char *cmdbuf)
|