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