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