/* -*-c-*- * * $Id: parser.y,v 1.2 1997/08/04 10:24:24 mdw Exp $ * * Parser for `become.conf' files * * (c) 1997 EBI */ /*----- Licensing notice --------------------------------------------------* * * This file is part of `become' * * `Become' is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * `Become' is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with `become'; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*----- Revision history --------------------------------------------------* * * $Log: parser.y,v $ * Revision 1.2 1997/08/04 10:24:24 mdw * Sources placed under CVS control. * * Revision 1.1 1997/07/21 13:47:45 mdw * Initial revision * */ /*----- Header files ------------------------------------------------------*/ %{ /* --- ANSI headers --- */ #include #include #include /* --- Unix headers --- */ #include #include #include /* --- Local headers --- */ #include "class.h" #include "daemon.h" #include "lexer.h" #include "name.h" #include "rule.h" #include "set.h" #include "sym.h" #include "userdb.h" #include "utils.h" %} /*----- Stack type --------------------------------------------------------*/ %union { long i; char *s; name *n; classdef *c; } /*----- Token and rule declarations ---------------------------------------*/ /* --- Tokens --- */ %token BADTOKEN %token USER %token COMMAND %token HOST %token ALLOW %token PORT %token KEYFILE %token INT %token WORD %token STRING %token ARROW %left ',' %left '-' %left '|' %left '&' /* --- Rules --- */ %type user_class command_class host_class %type user_class_opt command_class_opt host_class_opt %type name /*----- Error reporting ---------------------------------------------------*/ %{ #define YYDEBUG 1 #define YYERROR_VERBOSE /* --- @yyprint@ --- * * * Arguments: @FILE *fp@ = pointer to stream to write on * @int type@ = pointer to token type * @YYSTYPE v@ = token value * * Returns: --- * * Use: Displays the semantic value of a token. */ #define YYPRINT(fp, type, value) yyprint(fp, type, value) static void yyprint(FILE *fp, int type, YYSTYPE v) { switch (type) { case INT: fprintf(fp, " %li", v.i); break; case WORD: case STRING: fprintf(fp, " `%s'", v.s); break; } } /* --- @yyerror@ --- * * * Arguments: @const char *msg@ = pointer to error message * * Returns: --- * * Use: Reports parse errors. */ static void yyerror(const char *msg) { moan("%s at line %i", msg, lex_line); } %} %% /*----- The actual grammar ------------------------------------------------*/ /* --- Simple driver things --- */ file : /* empty */ | file statement ; statement : user_spec | command_spec | host_spec | allow_spec | port_spec | key_spec | error ';' ; /* --- Main statement types --- */ user_spec : USER name '=' user_class ';' { if ($2->c) class_dec($2->c); $2->c = $4; } ; command_spec : COMMAND name '=' command_class ';' { if ($2->c) class_dec($2->c); $2->c = $4; } ; host_spec : HOST name '=' host_class ';' { if ($2->c) class_dec($2->c); $2->c = $4; } ; port_spec : PORT INT ';' { daemon_usePort($2); } ; key_spec : KEYFILE STRING ';' { daemon_readKey($2); } /* --- Parsing allow specifications --- */ allow_spec : ALLOW host_class_opt user_class ARROW user_class_opt command_class_opt ';' { rule_add($2, $3, $5, $6); } host_class_opt : /* empty */ { $$ = class_all; } | '[' host_class ']' { $$ = $2; } ; user_class_opt : /* empty */ { $$ = class_all; } | user_class { $$ = $1; } ; command_class_opt : /* empty */ { $$ = class_all; } | ':' command_class { $$ = $2; } ; /* --- Names get translated into symbols quickly --- */ name : WORD { unsigned f; name *n = name_find($1, 1, &f); if (!f) n->c = 0; $$ = n; } /*----- Various class expression types ------------------------------------* * * Unfortunately, all these need to handle token types slightly differently * and I can't be bothered to remember the current state. */ /* --- User class expressions --- */ user_class : user_class ',' user_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { if ($1 == class_all) $$ = class_all; else $$ = class_create($1->type, set_union($1->t, $3->t)); class_dec($1); class_dec($3); } } | user_class '-' user_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { $$ = class_create($1->type, set_subtract($1->t, $3->t)); class_dec($1); class_dec($3); } } | user_class '&' user_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { if ($1 == class_all) $$ = class_all; else $$ = class_create($1->type, set_intersect($1->t, $3->t)); class_dec($1); class_dec($3); } } | user_class '|' user_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { if ($1 == class_all) $$ = class_all; else $$ = class_create($1->type, set_union($1->t, $3->t)); class_dec($1); class_dec($3); } } | INT { sym_table *t = xmalloc(sizeof(*t)); int u = $1; sym_createTable(t); sym_find(t, (char *)&u, sizeof(u), sizeof(sym_base), 0); $$ = class_create(clType_user, t); } | STRING { struct passwd *pw; sym_table *t; int u; if ((pw = userdb_userByName($1)) == 0) { moan("user `%s' not known at line %i", $1, lex_line); YYERROR; } else { t = xmalloc(sizeof(*t)); u = pw->pw_uid; sym_createTable(t); sym_find(t, (char *)&u, sizeof(u), sizeof(sym_base), 0); $$ = class_create(clType_user, t); } } | WORD { name *n = name_find($1, 0, 0); if (!n || !n->c) { moan("class `%s' not found at line %i", $1, lex_line); YYERROR; } else if (~n->c->type & clType_user) { yyerror("type mismatch"); YYERROR; } else { $$ = n->c; class_inc(n->c); } } | '(' user_class ')' { $$ = $2; } ; /* --- Command class expressions --- */ command_class : command_class ',' command_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { if ($1 == class_all) $$ = class_all; else $$ = class_create($1->type, set_union($1->t, $3->t)); class_dec($1); class_dec($3); } } | command_class '-' command_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { $$ = class_create($1->type, set_subtract($1->t, $3->t)); class_dec($1); class_dec($3); } } | command_class '&' command_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { if ($1 == class_all) $$ = class_all; else $$ = class_create($1->type, set_intersect($1->t, $3->t)); class_dec($1); class_dec($3); } } | command_class '|' command_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { if ($1 == class_all) $$ = class_all; else $$ = class_create($1->type, set_union($1->t, $3->t)); class_dec($1); class_dec($3); } } | STRING { sym_table *t = xmalloc(sizeof(*t)); sym_createTable(t); sym_find(t, $1, -1, sizeof(sym_base), 0); $$ = class_create(clType_command, t); } | WORD { name *n = name_find($1, 0, 0); if (!n || !n->c) { moan("class `%s' not found at line %i", $1, lex_line); YYERROR; } else if (~n->c->type & clType_command) { yyerror("type mismatch"); YYERROR; } else { $$ = n->c; class_inc(n->c); } } | '(' command_class ')' { $$ = $2; } ; /* --- Host class expressions --- */ host_class : host_class ',' host_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { if ($1 == class_all) $$ = class_all; else $$ = class_create($1->type, set_union($1->t, $3->t)); class_dec($1); class_dec($3); } } | host_class '-' host_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { $$ = class_create($1->type, set_subtract($1->t, $3->t)); class_dec($1); class_dec($3); } } | host_class '&' host_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { if ($1 == class_all) $$ = class_all; else $$ = class_create($1->type, set_intersect($1->t, $3->t)); class_dec($1); class_dec($3); } } | host_class '|' host_class { if ($1->type != $3->type) { yyerror("type mismatch"); class_dec($1); class_dec($3); YYERROR; } else { if ($1 == class_all) $$ = class_all; else $$ = class_create($1->type, set_union($1->t, $3->t)); class_dec($1); class_dec($3); } } | STRING { sym_table *t = xmalloc(sizeof(*t)); sym_createTable(t); sym_find(t, $1, -1, sizeof(sym_base), 0); $$ = class_create(clType_host, t); } | WORD { name *n = name_find($1, 0, 0); if (!n || !n->c) { moan("class `%s' not found at line %i", $1, lex_line); YYERROR; } else if (~n->c->type & clType_host) { yyerror("type mismatch"); YYERROR; } else { $$ = n->c; class_inc(n->c); } } | '(' host_class ')' { $$ = $2; } ; /*----- That's all, folks -------------------------------------------------*/