Home | History | Annotate | Download | only in zonecfg
      1 %{
      2 /*
      3  * CDDL HEADER START
      4  *
      5  * The contents of this file are subject to the terms of the
      6  * Common Development and Distribution License (the "License").
      7  * You may not use this file except in compliance with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 
     23 /*
     24  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     25  * Use is subject to license terms.
     26  */
     27 
     28 #include <stdio.h>
     29 #include <strings.h>
     30 
     31 #include "zonecfg.h"
     32 
     33 static cmd_t *cmd = NULL;		/* Command being processed */
     34 static complex_property_ptr_t complex = NULL;
     35 static list_property_ptr_t new_list = NULL, tmp_list, last,
     36     list[MAX_EQ_PROP_PAIRS];
     37 static property_value_t property[MAX_EQ_PROP_PAIRS];
     38 
     39 extern boolean_t newline_terminated;
     40 extern int num_prop_vals;		/* # of property values */
     41 
     42 /* yacc externals */
     43 extern int yydebug;
     44 extern void yyerror(char *s);
     45 
     46 /*
     47  * This function is used by the simple_prop_val reduction rules to set up
     48  * a list_property_ptr_t and adjust the above global variables appropriately.
     49  * Note that this function duplicates the specified string and makes
     50  * the new list's lp_simple field point to the duplicate.  This function does
     51  * not free the original string.
     52  *
     53  * This function returns a pointer to the duplicated string or NULL if an error
     54  * occurred.  The simple_prop_val reduction rules that invoke this function
     55  * should set $$ to the returned pointer.
     56  */
     57 static char *
     58 simple_prop_val_func(const char *str)
     59 {
     60 	char *retstr;
     61 
     62 	if ((new_list = alloc_list()) == NULL)
     63 		return (NULL);
     64 	if ((retstr = strdup(str)) == NULL) {
     65 		free_list(new_list);
     66 		return (NULL);
     67 	}
     68 	new_list->lp_simple = retstr;
     69 	new_list->lp_complex = NULL;
     70 	new_list->lp_next = NULL;
     71 	if (list[num_prop_vals] == NULL) {
     72 		list[num_prop_vals] = new_list;
     73 	} else {
     74 		for (tmp_list = list[num_prop_vals]; tmp_list != NULL;
     75 		    tmp_list = tmp_list->lp_next)
     76 			last = tmp_list;
     77 		last->lp_next = new_list;
     78 	}
     79 	return (retstr);
     80 }
     81 
     82 /*
     83  * This function is used by the complex_piece reduction rules to set up a
     84  * complex_property_prt_t and adjust the above global variables appropriately.
     85  * Note that this function duplicates the specified string and makes the new
     86  * complex_property_ptr_t's cp_value field point to the duplicate.  It also sets
     87  * the complex_property_ptr_t's cp_type field to cp_type and its cp_next field
     88  * to cp_next.  This function does not free the original string.
     89  *
     90  * This function returns a pointer to the complex_property_t created for the
     91  * complex_piece or NULL if an error occurred.  The complex_piece reduction
     92  * rules that invoke this function should set $$ to the returned pointer.
     93  */
     94 static complex_property_ptr_t
     95 complex_piece_func(int cp_type, const char *str, complex_property_ptr_t cp_next)
     96 {
     97 	complex_property_ptr_t retval;
     98 
     99 	if ((retval = alloc_complex()) == NULL)
    100 		return (NULL);
    101 	if ((retval->cp_value = strdup(str)) == NULL) {
    102 		free_complex(retval);
    103 		return (NULL);
    104 	}
    105 	retval->cp_type = cp_type;
    106 	retval->cp_next = cp_next;
    107 	complex = retval;
    108 	return (retval);
    109 }
    110 
    111 
    112 %}
    113 
    114 %union {
    115 	int ival;
    116 	char *strval;
    117 	cmd_t *cmd;
    118 	complex_property_ptr_t complex;
    119 	list_property_ptr_t list;
    120 }
    121 
    122 %start commands
    123 
    124 %token HELP CREATE EXPORT ADD DELETE REMOVE SELECT SET INFO CANCEL END VERIFY
    125 %token COMMIT REVERT EXIT SEMICOLON TOKEN ZONENAME ZONEPATH AUTOBOOT POOL NET
    126 %token FS IPD ATTR DEVICE RCTL SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL
    127 %token IPTYPE HOSTID
    128 %token NAME MATCH PRIV LIMIT ACTION VALUE EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
    129 %token OPEN_PAREN CLOSE_PAREN COMMA DATASET LIMITPRIV BOOTARGS BRAND PSET PCAP
    130 %token MCAP NCPUS IMPORTANCE SHARES MAXLWPS MAXSHMMEM MAXSHMIDS MAXMSGIDS
    131 %token MAXSEMIDS LOCKED SWAP SCHED CLEAR DEFROUTER
    132 
    133 %type <strval> TOKEN EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
    134     property_value OPEN_PAREN CLOSE_PAREN COMMA simple_prop_val
    135 %type <complex> complex_piece complex_prop_val
    136 %type <ival> resource_type NET FS IPD DEVICE RCTL ATTR DATASET PSET PCAP MCAP
    137 %type <ival> property_name SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL NAME
    138     MATCH ZONENAME ZONEPATH AUTOBOOT POOL LIMITPRIV BOOTARGS VALUE PRIV LIMIT
    139     ACTION BRAND SCHED IPTYPE DEFROUTER HOSTID
    140 %type <cmd> command
    141 %type <cmd> add_command ADD
    142 %type <cmd> cancel_command CANCEL
    143 %type <cmd> commit_command COMMIT
    144 %type <cmd> create_command CREATE
    145 %type <cmd> delete_command DELETE
    146 %type <cmd> end_command END
    147 %type <cmd> exit_command EXIT
    148 %type <cmd> export_command EXPORT
    149 %type <cmd> help_command HELP
    150 %type <cmd> info_command INFO
    151 %type <cmd> remove_command REMOVE
    152 %type <cmd> revert_command REVERT
    153 %type <cmd> select_command SELECT
    154 %type <cmd> set_command SET
    155 %type <cmd> clear_command CLEAR
    156 %type <cmd> verify_command VERIFY
    157 %type <cmd> terminator
    158 
    159 %%
    160 
    161 commands: command terminator
    162 	{
    163 		if ($1 != NULL) {
    164 			if ($1->cmd_handler != NULL)
    165 				$1->cmd_handler($1);
    166 			free_cmd($1);
    167 			bzero(list, sizeof (list_property_t));
    168 			num_prop_vals = 0;
    169 		}
    170 		return (0);
    171 	}
    172 	| command error terminator
    173 	{
    174 		if ($1 != NULL) {
    175 			free_cmd($1);
    176 			bzero(list, sizeof (list_property_t));
    177 			num_prop_vals = 0;
    178 		}
    179 		if (YYRECOVERING())
    180 			YYABORT;
    181 		yyclearin;
    182 		yyerrok;
    183 	}
    184 	| error terminator
    185 	{
    186 		if (YYRECOVERING())
    187 			YYABORT;
    188 		yyclearin;
    189 		yyerrok;
    190 	}
    191 	| terminator
    192 	{
    193 		return (0);
    194 	}
    195 
    196 command: add_command
    197 	| cancel_command
    198 	| clear_command
    199 	| create_command
    200 	| commit_command
    201 	| delete_command
    202 	| end_command
    203 	| exit_command
    204 	| export_command
    205 	| help_command
    206 	| info_command
    207 	| remove_command
    208 	| revert_command
    209 	| select_command
    210 	| set_command
    211 	| verify_command
    212 
    213 terminator:	'\n'	{ newline_terminated = B_TRUE; }
    214 	|	';'	{ newline_terminated = B_FALSE; }
    215 
    216 add_command: ADD
    217 	{
    218 		short_usage(CMD_ADD);
    219 		(void) fputs("\n", stderr);
    220 		usage(B_FALSE, HELP_RES_PROPS);
    221 		YYERROR;
    222 	}
    223 	| ADD TOKEN
    224 	{
    225 		if (($$ = alloc_cmd()) == NULL)
    226 			YYERROR;
    227 		cmd = $$;
    228 		$$->cmd_handler = &add_func;
    229 		$$->cmd_argc = 1;
    230 		$$->cmd_argv[0] = $2;
    231 		$$->cmd_argv[1] = NULL;
    232 	}
    233 	| ADD resource_type
    234 	{
    235 		if (($$ = alloc_cmd()) == NULL)
    236 			YYERROR;
    237 		cmd = $$;
    238 		$$->cmd_handler = &add_func;
    239 		$$->cmd_argc = 0;
    240 		$$->cmd_res_type = $2;
    241 		$$->cmd_prop_nv_pairs = 0;
    242 	}
    243 	| ADD property_name property_value
    244 	{
    245 		if (($$ = alloc_cmd()) == NULL)
    246 			YYERROR;
    247 		cmd = $$;
    248 		$$->cmd_handler = &add_func;
    249 		$$->cmd_argc = 0;
    250 		$$->cmd_prop_nv_pairs = 1;
    251 		$$->cmd_prop_name[0] = $2;
    252 		$$->cmd_property_ptr[0] = &property[0];
    253 	}
    254 
    255 cancel_command: CANCEL
    256 	{
    257 		if (($$ = alloc_cmd()) == NULL)
    258 			YYERROR;
    259 		cmd = $$;
    260 		$$->cmd_handler = &cancel_func;
    261 		$$->cmd_argc = 0;
    262 		$$->cmd_argv[0] = NULL;
    263 	}
    264 	| CANCEL TOKEN
    265 	{
    266 		if (($$ = alloc_cmd()) == NULL)
    267 			YYERROR;
    268 		cmd = $$;
    269 		$$->cmd_handler = &cancel_func;
    270 		$$->cmd_argc = 1;
    271 		$$->cmd_argv[0] = $2;
    272 		$$->cmd_argv[1] = NULL;
    273 	}
    274 
    275 create_command: CREATE
    276 	{
    277 		if (($$ = alloc_cmd()) == NULL)
    278 			YYERROR;
    279 		cmd = $$;
    280 		$$->cmd_handler = &create_func;
    281 		$$->cmd_argc = 0;
    282 		$$->cmd_argv[0] = NULL;
    283 	}
    284 	| CREATE TOKEN
    285 	{
    286 		if (($$ = alloc_cmd()) == NULL)
    287 			YYERROR;
    288 		cmd = $$;
    289 		$$->cmd_handler = &create_func;
    290 		$$->cmd_argc = 1;
    291 		$$->cmd_argv[0] = $2;
    292 		$$->cmd_argv[1] = NULL;
    293 	}
    294 	| CREATE TOKEN TOKEN
    295 	{
    296 		if (($$ = alloc_cmd()) == NULL)
    297 			YYERROR;
    298 		cmd = $$;
    299 		$$->cmd_handler = &create_func;
    300 		$$->cmd_argc = 2;
    301 		$$->cmd_argv[0] = $2;
    302 		$$->cmd_argv[1] = $3;
    303 		$$->cmd_argv[2] = NULL;
    304 	}
    305 	| CREATE TOKEN TOKEN TOKEN
    306 	{
    307 		if (($$ = alloc_cmd()) == NULL)
    308 			YYERROR;
    309 		cmd = $$;
    310 		$$->cmd_handler = &create_func;
    311 		$$->cmd_argc = 3;
    312 		$$->cmd_argv[0] = $2;
    313 		$$->cmd_argv[1] = $3;
    314 		$$->cmd_argv[2] = $4;
    315 		$$->cmd_argv[3] = NULL;
    316 	}
    317 
    318 commit_command: COMMIT
    319 	{
    320 		if (($$ = alloc_cmd()) == NULL)
    321 			YYERROR;
    322 		cmd = $$;
    323 		$$->cmd_handler = &commit_func;
    324 		$$->cmd_argc = 0;
    325 		$$->cmd_argv[0] = NULL;
    326 	}
    327 	| COMMIT TOKEN
    328 	{
    329 		if (($$ = alloc_cmd()) == NULL)
    330 			YYERROR;
    331 		cmd = $$;
    332 		$$->cmd_handler = &commit_func;
    333 		$$->cmd_argc = 1;
    334 		$$->cmd_argv[0] = $2;
    335 		$$->cmd_argv[1] = NULL;
    336 	}
    337 
    338 delete_command: DELETE
    339 	{
    340 		if (($$ = alloc_cmd()) == NULL)
    341 			YYERROR;
    342 		cmd = $$;
    343 		$$->cmd_handler = &delete_func;
    344 		$$->cmd_argc = 0;
    345 		$$->cmd_argv[0] = NULL;
    346 	}
    347 	|	DELETE TOKEN
    348 	{
    349 		if (($$ = alloc_cmd()) == NULL)
    350 			YYERROR;
    351 		cmd = $$;
    352 		$$->cmd_handler = &delete_func;
    353 		$$->cmd_argc = 1;
    354 		$$->cmd_argv[0] = $2;
    355 		$$->cmd_argv[1] = NULL;
    356 	}
    357 
    358 end_command: END
    359 	{
    360 		if (($$ = alloc_cmd()) == NULL)
    361 			YYERROR;
    362 		cmd = $$;
    363 		$$->cmd_handler = &end_func;
    364 		$$->cmd_argc = 0;
    365 		$$->cmd_argv[0] = NULL;
    366 	}
    367 	| END TOKEN
    368 	{
    369 		if (($$ = alloc_cmd()) == NULL)
    370 			YYERROR;
    371 		cmd = $$;
    372 		$$->cmd_handler = &end_func;
    373 		$$->cmd_argc = 1;
    374 		$$->cmd_argv[0] = $2;
    375 		$$->cmd_argv[1] = NULL;
    376 	}
    377 
    378 exit_command: EXIT
    379 	{
    380 		if (($$ = alloc_cmd()) == NULL)
    381 			YYERROR;
    382 		cmd = $$;
    383 		$$->cmd_handler = &exit_func;
    384 		$$->cmd_argc = 0;
    385 		$$->cmd_argv[0] = NULL;
    386 	}
    387 	| EXIT TOKEN
    388 	{
    389 		if (($$ = alloc_cmd()) == NULL)
    390 			YYERROR;
    391 		cmd = $$;
    392 		$$->cmd_handler = &exit_func;
    393 		$$->cmd_argc = 1;
    394 		$$->cmd_argv[0] = $2;
    395 		$$->cmd_argv[1] = NULL;
    396 	}
    397 
    398 export_command: EXPORT
    399 	{
    400 		if (($$ = alloc_cmd()) == NULL)
    401 			YYERROR;
    402 		cmd = $$;
    403 		$$->cmd_handler = &export_func;
    404 		$$->cmd_argc = 0;
    405 		$$->cmd_argv[0] = NULL;
    406 	}
    407 	| EXPORT TOKEN
    408 	{
    409 		if (($$ = alloc_cmd()) == NULL)
    410 			YYERROR;
    411 		cmd = $$;
    412 		$$->cmd_handler = &export_func;
    413 		$$->cmd_argc = 1;
    414 		$$->cmd_argv[0] = $2;
    415 		$$->cmd_argv[1] = NULL;
    416 	}
    417 	| EXPORT TOKEN TOKEN
    418 	{
    419 		if (($$ = alloc_cmd()) == NULL)
    420 			YYERROR;
    421 		cmd = $$;
    422 		$$->cmd_handler = &export_func;
    423 		$$->cmd_argc = 2;
    424 		$$->cmd_argv[0] = $2;
    425 		$$->cmd_argv[1] = $3;
    426 		$$->cmd_argv[2] = NULL;
    427 	}
    428 
    429 help_command:	HELP
    430 	{
    431 		if (($$ = alloc_cmd()) == NULL)
    432 			YYERROR;
    433 		cmd = $$;
    434 		$$->cmd_handler = &help_func;
    435 		$$->cmd_argc = 0;
    436 		$$->cmd_argv[0] = NULL;
    437 	}
    438 	|	HELP TOKEN
    439 	{
    440 		if (($$ = alloc_cmd()) == NULL)
    441 			YYERROR;
    442 		cmd = $$;
    443 		$$->cmd_handler = &help_func;
    444 		$$->cmd_argc = 1;
    445 		$$->cmd_argv[0] = $2;
    446 		$$->cmd_argv[1] = NULL;
    447 	}
    448 
    449 info_command:	INFO
    450 	{
    451 		if (($$ = alloc_cmd()) == NULL)
    452 			YYERROR;
    453 		cmd = $$;
    454 		$$->cmd_handler = &info_func;
    455 		$$->cmd_res_type = RT_UNKNOWN;
    456 		$$->cmd_prop_nv_pairs = 0;
    457 	}
    458 	|	INFO TOKEN
    459 	{
    460 		short_usage(CMD_INFO);
    461 		(void) fputs("\n", stderr);
    462 		usage(B_FALSE, HELP_RES_PROPS);
    463 		free($2);
    464 		YYERROR;
    465 	}
    466 	|	INFO resource_type
    467 	{
    468 		if (($$ = alloc_cmd()) == NULL)
    469 			YYERROR;
    470 		cmd = $$;
    471 		$$->cmd_handler = &info_func;
    472 		$$->cmd_res_type = $2;
    473 		$$->cmd_prop_nv_pairs = 0;
    474 	}
    475 	|	INFO ZONENAME
    476 	{
    477 		if (($$ = alloc_cmd()) == NULL)
    478 			YYERROR;
    479 		cmd = $$;
    480 		$$->cmd_handler = &info_func;
    481 		$$->cmd_res_type = RT_ZONENAME;
    482 		$$->cmd_prop_nv_pairs = 0;
    483 	}
    484 	|	INFO ZONEPATH
    485 	{
    486 		if (($$ = alloc_cmd()) == NULL)
    487 			YYERROR;
    488 		cmd = $$;
    489 		$$->cmd_handler = &info_func;
    490 		$$->cmd_res_type = RT_ZONEPATH;
    491 		$$->cmd_prop_nv_pairs = 0;
    492 	}
    493 	|	INFO BRAND
    494 	{
    495 		if (($$ = alloc_cmd()) == NULL)
    496 			YYERROR;
    497 		cmd = $$;
    498 		$$->cmd_handler = &info_func;
    499 		$$->cmd_res_type = RT_BRAND;
    500 		$$->cmd_prop_nv_pairs = 0;
    501 	}
    502 	|	INFO AUTOBOOT
    503 	{
    504 		if (($$ = alloc_cmd()) == NULL)
    505 			YYERROR;
    506 		cmd = $$;
    507 		$$->cmd_handler = &info_func;
    508 		$$->cmd_res_type = RT_AUTOBOOT;
    509 		$$->cmd_prop_nv_pairs = 0;
    510 	}
    511 	|	INFO IPTYPE
    512 	{
    513 		if (($$ = alloc_cmd()) == NULL)
    514 			YYERROR;
    515 		cmd = $$;
    516 		$$->cmd_handler = &info_func;
    517 		$$->cmd_res_type = RT_IPTYPE;
    518 		$$->cmd_prop_nv_pairs = 0;
    519 	}
    520 	|	INFO POOL
    521 	{
    522 		if (($$ = alloc_cmd()) == NULL)
    523 			YYERROR;
    524 		cmd = $$;
    525 		$$->cmd_handler = &info_func;
    526 		$$->cmd_res_type = RT_POOL;
    527 		$$->cmd_prop_nv_pairs = 0;
    528 	}
    529 	|	INFO LIMITPRIV
    530 	{
    531 		if (($$ = alloc_cmd()) == NULL)
    532 			YYERROR;
    533 		cmd = $$;
    534 		$$->cmd_handler = &info_func;
    535 		$$->cmd_res_type = RT_LIMITPRIV;
    536 		$$->cmd_prop_nv_pairs = 0;
    537 	}
    538 	|	INFO BOOTARGS
    539 	{
    540 		if (($$ = alloc_cmd()) == NULL)
    541 			YYERROR;
    542 		cmd = $$;
    543 		$$->cmd_handler = &info_func;
    544 		$$->cmd_res_type = RT_BOOTARGS;
    545 		$$->cmd_prop_nv_pairs = 0;
    546 	}
    547 	|	INFO SCHED
    548 	{
    549 		if (($$ = alloc_cmd()) == NULL)
    550 			YYERROR;
    551 		cmd = $$;
    552 		$$->cmd_handler = &info_func;
    553 		$$->cmd_res_type = RT_SCHED;
    554 		$$->cmd_prop_nv_pairs = 0;
    555 	}
    556 	|	INFO SHARES
    557 	{
    558 		if (($$ = alloc_cmd()) == NULL)
    559 			YYERROR;
    560 		cmd = $$;
    561 		$$->cmd_handler = &info_func;
    562 		$$->cmd_res_type = RT_SHARES;
    563 		$$->cmd_prop_nv_pairs = 0;
    564 	}
    565 	|	INFO MAXLWPS
    566 	{
    567 		if (($$ = alloc_cmd()) == NULL)
    568 			YYERROR;
    569 		cmd = $$;
    570 		$$->cmd_handler = &info_func;
    571 		$$->cmd_res_type = RT_MAXLWPS;
    572 		$$->cmd_prop_nv_pairs = 0;
    573 	}
    574 	|	INFO MAXSHMMEM
    575 	{
    576 		if (($$ = alloc_cmd()) == NULL)
    577 			YYERROR;
    578 		cmd = $$;
    579 		$$->cmd_handler = &info_func;
    580 		$$->cmd_res_type = RT_MAXSHMMEM;
    581 		$$->cmd_prop_nv_pairs = 0;
    582 	}
    583 	|	INFO MAXSHMIDS
    584 	{
    585 		if (($$ = alloc_cmd()) == NULL)
    586 			YYERROR;
    587 		cmd = $$;
    588 		$$->cmd_handler = &info_func;
    589 		$$->cmd_res_type = RT_MAXSHMIDS;
    590 		$$->cmd_prop_nv_pairs = 0;
    591 	}
    592 	|	INFO MAXMSGIDS
    593 	{
    594 		if (($$ = alloc_cmd()) == NULL)
    595 			YYERROR;
    596 		cmd = $$;
    597 		$$->cmd_handler = &info_func;
    598 		$$->cmd_res_type = RT_MAXMSGIDS;
    599 		$$->cmd_prop_nv_pairs = 0;
    600 	}
    601 	|	INFO MAXSEMIDS
    602 	{
    603 		if (($$ = alloc_cmd()) == NULL)
    604 			YYERROR;
    605 		cmd = $$;
    606 		$$->cmd_handler = &info_func;
    607 		$$->cmd_res_type = RT_MAXSEMIDS;
    608 		$$->cmd_prop_nv_pairs = 0;
    609 	}
    610 	|	INFO HOSTID
    611 	{
    612 		if (($$ = alloc_cmd()) == NULL)
    613 			YYERROR;
    614 		cmd = $$;
    615 		$$->cmd_handler = &info_func;
    616 		$$->cmd_res_type = RT_HOSTID;
    617 		$$->cmd_prop_nv_pairs = 0;
    618 	}
    619 	|	INFO resource_type property_name EQUAL property_value
    620 	{
    621 		if (($$ = alloc_cmd()) == NULL)
    622 			YYERROR;
    623 		cmd = $$;
    624 		$$->cmd_handler = &info_func;
    625 		$$->cmd_res_type = $2;
    626 		$$->cmd_prop_nv_pairs = 1;
    627 		$$->cmd_prop_name[0] = $3;
    628 		$$->cmd_property_ptr[0] = &property[0];
    629 	}
    630 	|	INFO resource_type property_name EQUAL property_value property_name EQUAL property_value
    631 	{
    632 		if (($$ = alloc_cmd()) == NULL)
    633 			YYERROR;
    634 		cmd = $$;
    635 		$$->cmd_handler = &info_func;
    636 		$$->cmd_res_type = $2;
    637 		$$->cmd_prop_nv_pairs = 2;
    638 		$$->cmd_prop_name[0] = $3;
    639 		$$->cmd_property_ptr[0] = &property[0];
    640 		$$->cmd_prop_name[1] = $6;
    641 		$$->cmd_property_ptr[1] = &property[1];
    642 	}
    643 	|	INFO resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value
    644 	{
    645 		if (($$ = alloc_cmd()) == NULL)
    646 			YYERROR;
    647 		cmd = $$;
    648 		$$->cmd_handler = &info_func;
    649 		$$->cmd_res_type = $2;
    650 		$$->cmd_prop_nv_pairs = 3;
    651 		$$->cmd_prop_name[0] = $3;
    652 		$$->cmd_property_ptr[0] = &property[0];
    653 		$$->cmd_prop_name[1] = $6;
    654 		$$->cmd_property_ptr[1] = &property[1];
    655 		$$->cmd_prop_name[2] = $9;
    656 		$$->cmd_property_ptr[2] = &property[2];
    657 	}
    658 
    659 remove_command: REMOVE
    660 	{
    661 		short_usage(CMD_REMOVE);
    662 		(void) fputs("\n", stderr);
    663 		usage(B_FALSE, HELP_RES_PROPS);
    664 		YYERROR;
    665 	}
    666 	| REMOVE TOKEN
    667 	{
    668 		short_usage(CMD_REMOVE);
    669 		(void) fputs("\n", stderr);
    670 		usage(B_FALSE, HELP_RES_PROPS);
    671 		YYERROR;
    672 	}
    673 	| REMOVE resource_type
    674 	{
    675 		if (($$ = alloc_cmd()) == NULL)
    676 			YYERROR;
    677 		cmd = $$;
    678 		$$->cmd_handler = &remove_func;
    679 		$$->cmd_res_type = $2;
    680 	}
    681 	| REMOVE TOKEN resource_type
    682 	{
    683 		if (($$ = alloc_cmd()) == NULL)
    684 			YYERROR;
    685 		cmd = $$;
    686 		$$->cmd_handler = &remove_func;
    687 		$$->cmd_res_type = $3;
    688 		$$->cmd_argc = 1;
    689 		$$->cmd_argv[0] = $2;
    690 		$$->cmd_argv[1] = NULL;
    691 	}
    692 	| REMOVE property_name property_value
    693 	{
    694 		if (($$ = alloc_cmd()) == NULL)
    695 			YYERROR;
    696 		cmd = $$;
    697 		$$->cmd_handler = &remove_func;
    698 		$$->cmd_prop_nv_pairs = 1;
    699 		$$->cmd_prop_name[0] = $2;
    700 		$$->cmd_property_ptr[0] = &property[0];
    701 	}
    702 	| REMOVE resource_type property_name EQUAL property_value
    703 	{
    704 		if (($$ = alloc_cmd()) == NULL)
    705 			YYERROR;
    706 		cmd = $$;
    707 		$$->cmd_handler = &remove_func;
    708 		$$->cmd_res_type = $2;
    709 		$$->cmd_prop_nv_pairs = 1;
    710 		$$->cmd_prop_name[0] = $3;
    711 		$$->cmd_property_ptr[0] = &property[0];
    712 	}
    713 	| REMOVE resource_type property_name EQUAL property_value property_name EQUAL property_value
    714 	{
    715 		if (($$ = alloc_cmd()) == NULL)
    716 			YYERROR;
    717 		cmd = $$;
    718 		$$->cmd_handler = &remove_func;
    719 		$$->cmd_res_type = $2;
    720 		$$->cmd_prop_nv_pairs = 2;
    721 		$$->cmd_prop_name[0] = $3;
    722 		$$->cmd_property_ptr[0] = &property[0];
    723 		$$->cmd_prop_name[1] = $6;
    724 		$$->cmd_property_ptr[1] = &property[1];
    725 	}
    726 	| REMOVE resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value
    727 	{
    728 		if (($$ = alloc_cmd()) == NULL)
    729 			YYERROR;
    730 		cmd = $$;
    731 		$$->cmd_handler = &remove_func;
    732 		$$->cmd_res_type = $2;
    733 		$$->cmd_prop_nv_pairs = 3;
    734 		$$->cmd_prop_name[0] = $3;
    735 		$$->cmd_property_ptr[0] = &property[0];
    736 		$$->cmd_prop_name[1] = $6;
    737 		$$->cmd_property_ptr[1] = &property[1];
    738 		$$->cmd_prop_name[2] = $9;
    739 		$$->cmd_property_ptr[2] = &property[2];
    740 	}
    741 
    742 revert_command: REVERT
    743 	{
    744 		if (($$ = alloc_cmd()) == NULL)
    745 			YYERROR;
    746 		cmd = $$;
    747 		$$->cmd_handler = &revert_func;
    748 		$$->cmd_argc = 0;
    749 		$$->cmd_argv[0] = NULL;
    750 	}
    751 	| REVERT TOKEN
    752 	{
    753 		if (($$ = alloc_cmd()) == NULL)
    754 			YYERROR;
    755 		cmd = $$;
    756 		$$->cmd_handler = &revert_func;
    757 		$$->cmd_argc = 1;
    758 		$$->cmd_argv[0] = $2;
    759 		$$->cmd_argv[1] = NULL;
    760 	}
    761 
    762 select_command: SELECT
    763 	{
    764 		short_usage(CMD_SELECT);
    765 		(void) fputs("\n", stderr);
    766 		usage(B_FALSE, HELP_RES_PROPS);
    767 		YYERROR;
    768 	}
    769 	| SELECT PSET
    770 	{
    771 		if (($$ = alloc_cmd()) == NULL)
    772 			YYERROR;
    773 		cmd = $$;
    774 		$$->cmd_handler = &select_func;
    775 		$$->cmd_res_type = RT_DCPU;
    776 	}
    777 	| SELECT PCAP
    778 	{
    779 		if (($$ = alloc_cmd()) == NULL)
    780 			YYERROR;
    781 		cmd = $$;
    782 		$$->cmd_handler = &select_func;
    783 		$$->cmd_res_type = RT_PCAP;
    784 	}
    785 	| SELECT MCAP
    786 	{
    787 		if (($$ = alloc_cmd()) == NULL)
    788 			YYERROR;
    789 		cmd = $$;
    790 		$$->cmd_handler = &select_func;
    791 		$$->cmd_res_type = RT_MCAP;
    792 	}
    793 	| SELECT resource_type
    794 	{
    795 		short_usage(CMD_SELECT);
    796 		YYERROR;
    797 	}
    798 	| SELECT resource_type property_name EQUAL property_value
    799 	{
    800 		if (($$ = alloc_cmd()) == NULL)
    801 			YYERROR;
    802 		cmd = $$;
    803 		$$->cmd_handler = &select_func;
    804 		$$->cmd_res_type = $2;
    805 		$$->cmd_prop_nv_pairs = 1;
    806 		$$->cmd_prop_name[0] = $3;
    807 		$$->cmd_property_ptr[0] = &property[0];
    808 	}
    809 	| SELECT resource_type property_name EQUAL property_value property_name EQUAL property_value
    810 	{
    811 		if (($$ = alloc_cmd()) == NULL)
    812 			YYERROR;
    813 		cmd = $$;
    814 		$$->cmd_handler = &select_func;
    815 		$$->cmd_res_type = $2;
    816 		$$->cmd_prop_nv_pairs = 2;
    817 		$$->cmd_prop_name[0] = $3;
    818 		$$->cmd_property_ptr[0] = &property[0];
    819 		$$->cmd_prop_name[1] = $6;
    820 		$$->cmd_property_ptr[1] = &property[1];
    821 	}
    822 	| SELECT resource_type property_name EQUAL property_value property_name EQUAL property_value property_name EQUAL property_value
    823 	{
    824 		if (($$ = alloc_cmd()) == NULL)
    825 			YYERROR;
    826 		cmd = $$;
    827 		$$->cmd_handler = &select_func;
    828 		$$->cmd_res_type = $2;
    829 		$$->cmd_prop_nv_pairs = 3;
    830 		$$->cmd_prop_name[0] = $3;
    831 		$$->cmd_property_ptr[0] = &property[0];
    832 		$$->cmd_prop_name[1] = $6;
    833 		$$->cmd_property_ptr[1] = &property[1];
    834 		$$->cmd_prop_name[2] = $9;
    835 		$$->cmd_property_ptr[2] = &property[2];
    836 	}
    837 
    838 set_command: SET
    839 	{
    840 		short_usage(CMD_SET);
    841 		(void) fputs("\n", stderr);
    842 		usage(B_FALSE, HELP_PROPS);
    843 		YYERROR;
    844 	}
    845 	| SET property_name EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
    846 	{
    847 		if (($$ = alloc_cmd()) == NULL)
    848 			YYERROR;
    849 		cmd = $$;
    850 		$$->cmd_handler = &set_func;
    851 		$$->cmd_prop_nv_pairs = 0;
    852 		$$->cmd_prop_name[0] = $2;
    853 		property[0].pv_type = PROP_VAL_LIST;
    854 		property[0].pv_list = NULL;
    855 		$$->cmd_property_ptr[0] = &property[0];
    856 	}
    857 	| SET property_name EQUAL property_value
    858 	{
    859 		if (($$ = alloc_cmd()) == NULL)
    860 			YYERROR;
    861 		cmd = $$;
    862 		$$->cmd_handler = &set_func;
    863 		$$->cmd_prop_nv_pairs = 1;
    864 		$$->cmd_prop_name[0] = $2;
    865 		$$->cmd_property_ptr[0] = &property[0];
    866 	}
    867 	| SET TOKEN ZONEPATH EQUAL property_value
    868 	{
    869 		if (($$ = alloc_cmd()) == NULL)
    870 			YYERROR;
    871 		cmd = $$;
    872 		$$->cmd_argc = 1;
    873 		$$->cmd_argv[0] = $2;
    874 		$$->cmd_argv[1] = NULL;
    875 		$$->cmd_handler = &set_func;
    876 		$$->cmd_prop_nv_pairs = 1;
    877 		$$->cmd_prop_name[0] = PT_ZONEPATH;
    878 		$$->cmd_property_ptr[0] = &property[0];
    879 	}
    880 
    881 clear_command: CLEAR
    882 	{
    883 		short_usage(CMD_CLEAR);
    884 		(void) fputs("\n", stderr);
    885 		usage(B_FALSE, HELP_PROPS);
    886 		YYERROR;
    887 	}
    888 	| CLEAR property_name
    889 	{
    890 		if (($$ = alloc_cmd()) == NULL)
    891 			YYERROR;
    892 		cmd = $$;
    893 		$$->cmd_handler = &clear_func;
    894 		$$->cmd_res_type = $2;
    895 	}
    896 
    897 verify_command: VERIFY
    898 	{
    899 		if (($$ = alloc_cmd()) == NULL)
    900 			YYERROR;
    901 		cmd = $$;
    902 		$$->cmd_handler = &verify_func;
    903 		$$->cmd_argc = 0;
    904 		$$->cmd_argv[0] = NULL;
    905 	}
    906 	| VERIFY TOKEN
    907 	{
    908 		if (($$ = alloc_cmd()) == NULL)
    909 			YYERROR;
    910 		cmd = $$;
    911 		$$->cmd_handler = &verify_func;
    912 		$$->cmd_argc = 1;
    913 		$$->cmd_argv[0] = $2;
    914 		$$->cmd_argv[1] = NULL;
    915 	}
    916 
    917 resource_type: NET	{ $$ = RT_NET; }
    918 	| FS		{ $$ = RT_FS; }
    919 	| IPD		{ $$ = RT_IPD; }
    920 	| DEVICE	{ $$ = RT_DEVICE; }
    921 	| RCTL		{ $$ = RT_RCTL; }
    922 	| ATTR		{ $$ = RT_ATTR; }
    923 	| DATASET	{ $$ = RT_DATASET; }
    924 	| PSET		{ $$ = RT_DCPU; }
    925 	| PCAP		{ $$ = RT_PCAP; }
    926 	| MCAP		{ $$ = RT_MCAP; }
    927 
    928 property_name: SPECIAL	{ $$ = PT_SPECIAL; }
    929 	| RAW		{ $$ = PT_RAW; }
    930 	| DIR		{ $$ = PT_DIR; }
    931 	| TYPE		{ $$ = PT_TYPE; }
    932 	| OPTIONS	{ $$ = PT_OPTIONS; }
    933 	| ZONENAME	{ $$ = PT_ZONENAME; }
    934 	| ZONEPATH	{ $$ = PT_ZONEPATH; }
    935 	| AUTOBOOT	{ $$ = PT_AUTOBOOT; }
    936 	| IPTYPE	{ $$ = PT_IPTYPE; }
    937 	| POOL		{ $$ = PT_POOL; }
    938 	| LIMITPRIV	{ $$ = PT_LIMITPRIV; }
    939 	| BOOTARGS	{ $$ = PT_BOOTARGS; }
    940 	| ADDRESS	{ $$ = PT_ADDRESS; }
    941 	| PHYSICAL	{ $$ = PT_PHYSICAL; }
    942 	| DEFROUTER	{ $$ = PT_DEFROUTER; }
    943 	| NAME		{ $$ = PT_NAME; }
    944 	| VALUE		{ $$ = PT_VALUE; }
    945 	| MATCH		{ $$ = PT_MATCH; }
    946 	| PRIV		{ $$ = PT_PRIV; }
    947 	| LIMIT		{ $$ = PT_LIMIT; }
    948 	| ACTION	{ $$ = PT_ACTION; }
    949 	| BRAND		{ $$ = PT_BRAND; }
    950 	| NCPUS		{ $$ = PT_NCPUS; }
    951 	| LOCKED	{ $$ = PT_LOCKED; }
    952 	| SWAP		{ $$ = PT_SWAP; }
    953 	| IMPORTANCE	{ $$ = PT_IMPORTANCE; }
    954 	| SHARES	{ $$ = PT_SHARES; }
    955 	| MAXLWPS	{ $$ = PT_MAXLWPS; }
    956 	| MAXSHMMEM	{ $$ = PT_MAXSHMMEM; }
    957 	| MAXSHMIDS	{ $$ = PT_MAXSHMIDS; }
    958 	| MAXMSGIDS	{ $$ = PT_MAXMSGIDS; }
    959 	| MAXSEMIDS	{ $$ = PT_MAXSEMIDS; }
    960 	| SCHED		{ $$ = PT_SCHED; }
    961 	| HOSTID	{ $$ = PT_HOSTID; }
    962 
    963 /*
    964  * The grammar builds data structures from the bottom up.  Thus various
    965  * strings are lexed into TOKENs or commands or resource or property values.
    966  * Below is where the resource and property values are built up into more
    967  * complex data structures.
    968  *
    969  * There are three kinds of properties: simple (single valued), complex
    970  * (one or more name=value pairs) and list (concatenation of one or more
    971  * simple or complex properties).
    972  *
    973  * So the property structure has a type which is one of these, and the
    974  * corresponding _simple, _complex or _list is set to the corresponding
    975  * lower-level data structure.
    976  */
    977 
    978 property_value: simple_prop_val
    979 	{
    980 		property[num_prop_vals].pv_type = PROP_VAL_SIMPLE;
    981 		property[num_prop_vals].pv_simple = $1;
    982 		if (list[num_prop_vals] != NULL) {
    983 			free_outer_list(list[num_prop_vals]);
    984 			list[num_prop_vals] = NULL;
    985 		}
    986 		num_prop_vals++;
    987 	}
    988 	| complex_prop_val
    989 	{
    990 		property[num_prop_vals].pv_type = PROP_VAL_COMPLEX;
    991 		property[num_prop_vals].pv_complex = complex;
    992 		if (list[num_prop_vals] != NULL) {
    993 			free_outer_list(list[num_prop_vals]);
    994 			list[num_prop_vals] = NULL;
    995 		}
    996 		num_prop_vals++;
    997 	}
    998 	| list_prop_val
    999 	{
   1000 		property[num_prop_vals].pv_type = PROP_VAL_LIST;
   1001 		property[num_prop_vals].pv_list = list[num_prop_vals];
   1002 		num_prop_vals++;
   1003 	}
   1004 
   1005 /*
   1006  * One level lower, lists are made up of simple or complex values, so
   1007  * simple_prop_val and complex_prop_val fill in a list structure and
   1008  * insert it into the linked list which is built up.  And because
   1009  * complex properties can have multiple name=value pairs, we keep
   1010  * track of them in another linked list.
   1011  *
   1012  * The complex and list structures for the linked lists are allocated
   1013  * below, and freed by recursive functions which are ultimately called
   1014  * by free_cmd(), which is called from the top-most "commands" part of
   1015  * the grammar.
   1016  *
   1017  * NOTE: simple_prop_val and complex_piece need reduction rules for
   1018  * property_name and resource_type so that the parser will accept property names
   1019  * and resource type names as property values.
   1020  */
   1021 
   1022 simple_prop_val: TOKEN
   1023 	{
   1024 		$$ = simple_prop_val_func($1);
   1025 		free($1);
   1026 		if ($$ == NULL)
   1027 			YYERROR;
   1028 	}
   1029 	| resource_type
   1030 	{
   1031 		if (($$ = simple_prop_val_func(res_types[$1])) == NULL)
   1032 			YYERROR;
   1033 	}
   1034 	| property_name
   1035 	{
   1036 		if (($$ = simple_prop_val_func(prop_types[$1])) == NULL)
   1037 			YYERROR;
   1038 	}
   1039 
   1040 complex_prop_val: OPEN_PAREN complex_piece CLOSE_PAREN
   1041 	{
   1042 		if ((new_list = alloc_list()) == NULL)
   1043 			YYERROR;
   1044 		new_list->lp_simple = NULL;
   1045 		new_list->lp_complex = complex;
   1046 		new_list->lp_next = NULL;
   1047 		if (list[num_prop_vals] == NULL) {
   1048 			list[num_prop_vals] = new_list;
   1049 		} else {
   1050 			for (tmp_list = list[num_prop_vals]; tmp_list != NULL;
   1051 			    tmp_list = tmp_list->lp_next)
   1052 				last = tmp_list;
   1053 			last->lp_next = new_list;
   1054 		}
   1055 	}
   1056 
   1057 complex_piece: property_name EQUAL TOKEN
   1058 	{
   1059 		$$ = complex_piece_func($1, $3, NULL);
   1060 		free($3);
   1061 		if ($$ == NULL)
   1062 			YYERROR;
   1063 	}
   1064 	| property_name EQUAL resource_type
   1065 	{
   1066 		if (($$ = complex_piece_func($1, res_types[$3], NULL)) == NULL)
   1067 			YYERROR;
   1068 	}
   1069 	| property_name EQUAL property_name
   1070 	{
   1071 		if (($$ = complex_piece_func($1, prop_types[$3], NULL)) == NULL)
   1072 			YYERROR;
   1073 	}
   1074 	| property_name EQUAL TOKEN COMMA complex_piece
   1075 	{
   1076 		$$ = complex_piece_func($1, $3, complex);
   1077 		free($3);
   1078 		if ($$ == NULL)
   1079 			YYERROR;
   1080 	}
   1081 	| property_name EQUAL resource_type COMMA complex_piece
   1082 	{
   1083 		if (($$ = complex_piece_func($1, res_types[$3], complex)) ==
   1084 		    NULL)
   1085 			YYERROR;
   1086 	}
   1087 	| property_name EQUAL property_name COMMA complex_piece
   1088 	{
   1089 		if (($$ = complex_piece_func($1, prop_types[$3], complex)) ==
   1090 		    NULL)
   1091 			YYERROR;
   1092 	}
   1093 
   1094 list_piece: simple_prop_val
   1095 	| complex_prop_val
   1096 	| simple_prop_val COMMA list_piece
   1097 	| complex_prop_val COMMA list_piece
   1098 
   1099 list_prop_val: OPEN_SQ_BRACKET list_piece CLOSE_SQ_BRACKET
   1100 %%
   1101