chiark / gitweb /
Added. No idea why this wasn't done before.
[become] / src / parser.y
1 /* -*-c-*-
2  *
3  * $Id: parser.y,v 1.2 1997/08/04 10:24:24 mdw Exp $
4  *
5  * Parser for `become.conf' files
6  *
7  * (c) 1997 EBI
8  */
9
10 /*----- Licensing notice --------------------------------------------------*
11  *
12  * This file is part of `become'
13  *
14  * `Become' is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * `Become' is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with `become'; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /*----- Revision history --------------------------------------------------*
30  *
31  * $Log: parser.y,v $
32  * Revision 1.2  1997/08/04 10:24:24  mdw
33  * Sources placed under CVS control.
34  *
35  * Revision 1.1  1997/07/21  13:47:45  mdw
36  * Initial revision
37  *
38  */
39
40 /*----- Header files ------------------------------------------------------*/
41 %{
42
43 /* --- ANSI headers --- */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48
49 /* --- Unix headers --- */
50
51 #include <sys/types.h>
52
53 #include <pwd.h>
54 #include <unistd.h>
55
56 /* --- Local headers --- */
57
58 #include "class.h"
59 #include "daemon.h"
60 #include "lexer.h"
61 #include "name.h"
62 #include "rule.h"
63 #include "set.h"
64 #include "sym.h"
65 #include "userdb.h"
66 #include "utils.h"
67
68 %}
69 /*----- Stack type --------------------------------------------------------*/
70
71 %union {
72   long i;
73   char *s;
74   name *n;
75   classdef *c;
76 }
77
78 /*----- Token and rule declarations ---------------------------------------*/
79
80 /* --- Tokens --- */
81
82 %token BADTOKEN
83 %token USER
84 %token COMMAND
85 %token HOST
86 %token ALLOW
87 %token PORT
88 %token KEYFILE
89 %token <i> INT
90 %token <s> WORD
91 %token <s> STRING
92 %token ARROW
93
94 %left ','
95 %left '-'
96 %left '|'
97 %left '&'
98
99 /* --- Rules --- */
100
101 %type <c> user_class command_class host_class
102 %type <c> user_class_opt command_class_opt host_class_opt
103 %type <n> name
104
105 /*----- Error reporting ---------------------------------------------------*/
106 %{
107
108 #define YYDEBUG 1
109 #define YYERROR_VERBOSE
110
111 /* --- @yyprint@ --- *
112  *
113  * Arguments:   @FILE *fp@ = pointer to stream to write on
114  *              @int type@ = pointer to token type
115  *              @YYSTYPE v@ = token value
116  *
117  * Returns:     ---
118  *
119  * Use:         Displays the semantic value of a token.
120  */
121
122 #define YYPRINT(fp, type, value) yyprint(fp, type, value)
123
124 static void yyprint(FILE *fp, int type, YYSTYPE v)
125 {
126   switch (type) {
127     case INT:
128       fprintf(fp, " %li", v.i);
129       break;
130     case WORD:
131     case STRING:
132       fprintf(fp, " `%s'", v.s);
133       break;
134   }
135 }
136
137 /* --- @yyerror@ --- *
138  *
139  * Arguments:   @const char *msg@ = pointer to error message
140  *
141  * Returns:     ---
142  *
143  * Use:         Reports parse errors.
144  */
145
146 static void yyerror(const char *msg)
147 {
148   moan("%s at line %i", msg, lex_line);
149 }
150
151 %}
152 %%
153 /*----- The actual grammar ------------------------------------------------*/
154
155 /* --- Simple driver things --- */
156
157 file            : /* empty */
158                 | file statement
159                 ;
160
161 statement       : user_spec
162                 | command_spec
163                 | host_spec
164                 | allow_spec
165                 | port_spec
166                 | key_spec
167                 | error ';'
168                 ;
169
170 /* --- Main statement types --- */
171
172 user_spec       : USER name '=' user_class ';' {
173                           if ($2->c)
174                             class_dec($2->c);
175                           $2->c = $4;
176                         }
177                 ;
178
179 command_spec    : COMMAND name '=' command_class ';' {
180                           if ($2->c)
181                             class_dec($2->c);
182                           $2->c = $4;
183                         }
184                 ;
185
186 host_spec       : HOST name '=' host_class ';' {
187                           if ($2->c)
188                             class_dec($2->c);
189                           $2->c = $4;
190                         }
191                 ;
192
193 port_spec       : PORT INT ';' { daemon_usePort($2); }
194                 ;
195
196 key_spec        : KEYFILE STRING ';' { daemon_readKey($2); }
197
198 /* --- Parsing allow specifications --- */
199
200 allow_spec      : ALLOW host_class_opt user_class ARROW
201                    user_class_opt command_class_opt ';' {
202                           rule_add($2, $3, $5, $6);
203                         }
204
205 host_class_opt  : /* empty */ { $$ = class_all; }
206                 | '[' host_class ']' { $$ = $2; }
207                 ;
208
209 user_class_opt  : /* empty */ { $$ = class_all; }
210                 | user_class { $$ = $1; }
211                 ;
212
213 command_class_opt : /* empty */ { $$ = class_all; }
214                 | ':' command_class { $$ = $2; }
215                 ;
216
217 /* --- Names get translated into symbols quickly --- */
218
219 name            : WORD  {
220                           unsigned f;
221                           name *n = name_find($1, 1, &f);
222                           if (!f)
223                             n->c = 0;
224                           $$ = n;
225                         }
226
227 /*----- Various class expression types ------------------------------------*
228  *
229  * Unfortunately, all these need to handle token types slightly differently
230  * and I can't be bothered to remember the current state.
231  */
232
233 /* --- User class expressions --- */
234
235 user_class      : user_class ',' user_class {
236                           if ($1->type != $3->type) {
237                             yyerror("type mismatch");
238                             class_dec($1);
239                             class_dec($3);
240                             YYERROR;
241                           } else {
242                             if ($1 == class_all)
243                               $$ = class_all;
244                             else
245                               $$ = class_create($1->type,
246                                                 set_union($1->t, $3->t));
247                             class_dec($1);
248                             class_dec($3);
249                           }
250                         }
251                 | user_class '-' user_class {
252                           if ($1->type != $3->type) {
253                             yyerror("type mismatch");
254                             class_dec($1);
255                             class_dec($3);
256                             YYERROR;
257                           } else {
258                             $$ = class_create($1->type,
259                                               set_subtract($1->t, $3->t));
260                             class_dec($1);
261                             class_dec($3);
262                           }
263                         }
264                 | user_class '&' user_class {
265                           if ($1->type != $3->type) {
266                             yyerror("type mismatch");
267                             class_dec($1);
268                             class_dec($3);
269                             YYERROR;
270                           } else {
271                             if ($1 == class_all)
272                               $$ = class_all;
273                             else
274                               $$ = class_create($1->type,
275                                                 set_intersect($1->t, $3->t));
276                             class_dec($1);
277                             class_dec($3);
278                           }
279                         }
280                 | user_class '|' user_class {
281                           if ($1->type != $3->type) {
282                             yyerror("type mismatch");
283                             class_dec($1);
284                             class_dec($3);
285                             YYERROR;
286                           } else {
287                             if ($1 == class_all)
288                               $$ = class_all;
289                             else
290                               $$ = class_create($1->type,
291                                                 set_union($1->t, $3->t));
292                             class_dec($1);
293                             class_dec($3);
294                           }
295                         }
296                 | INT   {
297                           sym_table *t = xmalloc(sizeof(*t));
298                           int u = $1;
299                           sym_createTable(t);
300                           sym_find(t, (char *)&u, sizeof(u),
301                                    sizeof(sym_base), 0);
302                           $$ = class_create(clType_user, t);
303                         }
304                 | STRING {
305                           struct passwd *pw;
306                           sym_table *t;
307                           int u;
308                           if ((pw = userdb_userByName($1)) == 0) {
309                             moan("user `%s' not known at line %i",
310                                  $1, lex_line);
311                             YYERROR;
312                           } else {
313                             t = xmalloc(sizeof(*t));
314                             u = pw->pw_uid;
315                             sym_createTable(t);
316                             sym_find(t, (char *)&u, sizeof(u),
317                                      sizeof(sym_base), 0);
318                             $$ = class_create(clType_user, t);
319                           }
320                         }
321                 | WORD  {
322                           name *n = name_find($1, 0, 0);
323                           if (!n || !n->c) {
324                             moan("class `%s' not found at line %i",
325                                  $1, lex_line);
326                             YYERROR;
327                           } else if (~n->c->type & clType_user) {
328                             yyerror("type mismatch");
329                             YYERROR;
330                           } else {
331                             $$ = n->c;
332                             class_inc(n->c);
333                           }
334                         }
335                 | '(' user_class ')' { $$ = $2; }
336                 ;
337
338 /* --- Command class expressions --- */
339
340 command_class   : command_class ',' command_class {
341                           if ($1->type != $3->type) {
342                             yyerror("type mismatch");
343                             class_dec($1);
344                             class_dec($3);
345                             YYERROR;
346                           } else {
347                             if ($1 == class_all)
348                               $$ = class_all;
349                             else
350                               $$ = class_create($1->type,
351                                                 set_union($1->t, $3->t));
352                             class_dec($1);
353                             class_dec($3);
354                           }
355                         }
356                 | command_class '-' command_class {
357                           if ($1->type != $3->type) {
358                             yyerror("type mismatch");
359                             class_dec($1);
360                             class_dec($3);
361                             YYERROR;
362                           } else {
363                             $$ = class_create($1->type,
364                                               set_subtract($1->t, $3->t));
365                             class_dec($1);
366                             class_dec($3);
367                           }
368                         }
369                 | command_class '&' command_class {
370                           if ($1->type != $3->type) {
371                             yyerror("type mismatch");
372                             class_dec($1);
373                             class_dec($3);
374                             YYERROR;
375                           } else {
376                             if ($1 == class_all)
377                               $$ = class_all;
378                             else
379                               $$ = class_create($1->type,
380                                                 set_intersect($1->t, $3->t));
381                             class_dec($1);
382                             class_dec($3);
383                           }
384                         }
385                 | command_class '|' command_class {
386                           if ($1->type != $3->type) {
387                             yyerror("type mismatch");
388                             class_dec($1);
389                             class_dec($3);
390                             YYERROR;
391                           } else {
392                             if ($1 == class_all)
393                               $$ = class_all;
394                             else
395                               $$ = class_create($1->type,
396                                                 set_union($1->t, $3->t));
397                             class_dec($1);
398                             class_dec($3);
399                           }
400                         }
401                 | STRING {
402                           sym_table *t = xmalloc(sizeof(*t));
403                           sym_createTable(t);
404                           sym_find(t, $1, -1, sizeof(sym_base), 0);
405                           $$ = class_create(clType_command, t);
406                         }
407                 | WORD  {
408                           name *n = name_find($1, 0, 0);
409                           if (!n || !n->c) {
410                             moan("class `%s' not found at line %i",
411                                  $1, lex_line);
412                             YYERROR;
413                           } else if (~n->c->type & clType_command) {
414                             yyerror("type mismatch");
415                             YYERROR;
416                           } else {
417                             $$ = n->c;
418                             class_inc(n->c);
419                           }
420                         }
421                 | '(' command_class ')' { $$ = $2; }
422                 ;
423
424 /* --- Host class expressions --- */
425
426 host_class : host_class ',' host_class {
427                           if ($1->type != $3->type) {
428                             yyerror("type mismatch");
429                             class_dec($1);
430                             class_dec($3);
431                             YYERROR;
432                           } else {
433                             if ($1 == class_all)
434                               $$ = class_all;
435                             else
436                               $$ = class_create($1->type,
437                                                 set_union($1->t, $3->t));
438                             class_dec($1);
439                             class_dec($3);
440                           }
441                         }
442                 | host_class '-' host_class {
443                           if ($1->type != $3->type) {
444                             yyerror("type mismatch");
445                             class_dec($1);
446                             class_dec($3);
447                             YYERROR;
448                           } else {
449                             $$ = class_create($1->type,
450                                               set_subtract($1->t, $3->t));
451                             class_dec($1);
452                             class_dec($3);
453                           }
454                         }
455                 | host_class '&' host_class {
456                           if ($1->type != $3->type) {
457                             yyerror("type mismatch");
458                             class_dec($1);
459                             class_dec($3);
460                             YYERROR;
461                           } else {
462                             if ($1 == class_all)
463                               $$ = class_all;
464                             else
465                               $$ = class_create($1->type,
466                                                 set_intersect($1->t, $3->t));
467                             class_dec($1);
468                             class_dec($3);
469                           }
470                         }
471                 | host_class '|' host_class {
472                           if ($1->type != $3->type) {
473                             yyerror("type mismatch");
474                             class_dec($1);
475                             class_dec($3);
476                             YYERROR;
477                           } else {
478                             if ($1 == class_all)
479                               $$ = class_all;
480                             else
481                               $$ = class_create($1->type,
482                                                 set_union($1->t, $3->t));
483                             class_dec($1);
484                             class_dec($3);
485                           }
486                         }
487                 | STRING {
488                           sym_table *t = xmalloc(sizeof(*t));
489                           sym_createTable(t);
490                           sym_find(t, $1, -1, sizeof(sym_base), 0);
491                           $$ = class_create(clType_host, t);
492                         }
493                 | WORD  {
494                           name *n = name_find($1, 0, 0);
495                           if (!n || !n->c) {
496                             moan("class `%s' not found at line %i",
497                                  $1, lex_line);
498                             YYERROR;
499                           } else if (~n->c->type & clType_host) {
500                             yyerror("type mismatch");
501                             YYERROR;
502                           } else {
503                             $$ = n->c;
504                             class_inc(n->c);
505                           }
506                         }
507                 | '(' host_class ')' { $$ = $2; }
508                 ;
509
510 /*----- That's all, folks -------------------------------------------------*/