688ffc41b37b34b9281a8327d975ee7c3dbe497c
[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 -------------------------------------------------*/