Insert some missing semicolons. Bison didn't seem to care, but other
[become] / src / parser.y
1 /* -*-c-*-
2 *
3 * $Id: parser.y,v 1.7 1999/03/26 15:25:22 mdw Exp $
4 *
5 * Parser for `become.conf' files
6 *
7 * (c) 1998 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.7 1999/03/26 15:25:22 mdw
33 * Insert some missing semicolons. Bison didn't seem to care, but other
34 * programs like `yyextract' do, so it's worth fixing.
35 *
36 * Revision 1.6 1998/04/23 13:26:49 mdw
37 * New `parse' interface to configuration file parser; informs caller
38 * whether parsing encountered any errors. Also support no-network
39 * configuration.
40 *
41 * Revision 1.5 1998/01/12 16:46:22 mdw
42 * Fix copyright date.
43 *
44 * Revision 1.4 1997/09/17 10:26:52 mdw
45 * Use rewritten class handler. Makes the expression parsers considerably
46 * simpler.
47 *
48 * Revision 1.3 1997/09/09 18:17:06 mdw
49 * Allow default port to be given as a service name or port number.
50 *
51 * Revision 1.2 1997/08/04 10:24:24 mdw
52 * Sources placed under CVS control.
53 *
54 * Revision 1.1 1997/07/21 13:47:45 mdw
55 * Initial revision
56 *
57 */
58
59 /*----- Header files ------------------------------------------------------*/
60 %{
61
62 /* --- ANSI headers --- */
63
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67
68 /* --- Unix headers --- */
69
70 #include <sys/types.h>
71 #include <sys/socket.h>
72
73 #include <netinet/in.h>
74
75 #include <arpa/inet.h>
76
77 #include <netdb.h>
78 #include <pwd.h>
79 #include <unistd.h>
80
81 /* --- Local headers --- */
82
83 #include "class.h"
84 #include "daemon.h"
85 #include "lexer.h"
86 #include "name.h"
87 #include "rule.h"
88 #include "sym.h"
89 #include "userdb.h"
90 #include "utils.h"
91
92 %}
93 /*----- Stack type --------------------------------------------------------*/
94
95 %union {
96 long i;
97 char *s;
98 name *n;
99 class_node *c;
100 }
101
102 /*----- Token and rule declarations ---------------------------------------*/
103
104 /* --- Tokens --- */
105
106 %token BADTOKEN
107 %token USER
108 %token COMMAND
109 %token HOST
110 %token ALLOW
111 %token PORT
112 %token KEYFILE
113 %token <i> INT
114 %token <s> WORD
115 %token <s> STRING
116 %token ARROW
117
118 %left ','
119 %left '-'
120 %left '|'
121 %left '&'
122
123 /* --- Rules --- */
124
125 %type <c> user_class command_class host_class
126 %type <c> user_class_opt command_class_opt host_class_opt
127 %type <n> name
128
129 /*----- Error reporting ---------------------------------------------------*/
130 %{
131
132 #define YYDEBUG 1
133 #define YYERROR_VERBOSE
134
135 /* --- @yyprint@ --- *
136 *
137 * Arguments: @FILE *fp@ = pointer to stream to write on
138 * @int type@ = pointer to token type
139 * @YYSTYPE v@ = token value
140 *
141 * Returns: ---
142 *
143 * Use: Displays the semantic value of a token.
144 */
145
146 #define YYPRINT(fp, type, value) yyprint(fp, type, value)
147
148 static void yyprint(FILE *fp, int type, YYSTYPE v)
149 {
150 switch (type) {
151 case INT:
152 fprintf(fp, " %li", v.i);
153 break;
154 case WORD:
155 case STRING:
156 fprintf(fp, " `%s'", v.s);
157 break;
158 }
159 }
160
161 /* --- @yyerror@ --- *
162 *
163 * Arguments: @const char *msg@ = pointer to error message
164 *
165 * Returns: ---
166 *
167 * Use: Reports parse errors.
168 */
169
170 static void yyerror(const char *msg)
171 {
172 moan("%s at line %i", msg, lex_line);
173 }
174
175 %}
176 %%
177 /*----- The actual grammar ------------------------------------------------*/
178
179 /* --- Simple driver things --- */
180
181 file : /* empty */
182 | file statement
183 ;
184
185 statement : user_spec
186 | command_spec
187 | host_spec
188 | allow_spec
189 | port_spec
190 | key_spec
191 | error ';'
192 ;
193
194 /* --- Main statement types --- */
195
196 user_spec : USER name '=' user_class ';' {
197 if ($2->c)
198 class_dec($2->c);
199 $2->c = $4;
200 }
201 ;
202
203 command_spec : COMMAND name '=' command_class ';' {
204 if ($2->c)
205 class_dec($2->c);
206 $2->c = $4;
207 }
208 ;
209
210 host_spec : HOST name '=' host_class ';' {
211 if ($2->c)
212 class_dec($2->c);
213 $2->c = $4;
214 }
215 ;
216
217 port_spec : PORT STRING ';' {
218 #ifndef NONETWORK
219 struct servent *s = getservbyname($2, "udp");
220 if (!s) {
221 moan("unknown service `%s' at line %i",
222 $2, lex_line);
223 yynerrs++; YYERROR;
224 }
225 daemon_usePort(s->s_port);
226 #else
227 yyerror("`port' command unsupported");
228 yynerrs++; YYERROR;
229 #endif
230 }
231 | PORT INT ';' {
232 #ifndef NONETWORK
233 daemon_usePort(htons($2));
234 #else
235 yyerror("`port' command unsupported");
236 yynerrs++; YYERROR;
237 #endif
238 }
239 ;
240
241 key_spec : KEYFILE STRING ';' {
242 #ifndef NONETWORK
243 daemon_readKey($2);
244 #else
245 yyerror("`keyfile' command unsupported");
246 yynerrs++; YYERROR;
247 #endif
248 }
249 ;
250
251 /* --- Parsing allow specifications --- */
252
253 allow_spec : ALLOW host_class_opt user_class ARROW
254 user_class_opt command_class_opt ';' {
255 rule_add($2, $3, $5, $6);
256 }
257 ;
258
259 host_class_opt : /* empty */ { $$ = class_all; }
260 | '[' host_class ']' { $$ = $2; }
261 ;
262
263 user_class_opt : /* empty */ { $$ = class_all; }
264 | user_class { $$ = $1; }
265 ;
266
267 command_class_opt : /* empty */ { $$ = class_all; }
268 | ':' command_class { $$ = $2; }
269 ;
270
271 /* --- Names get translated into symbols quickly --- */
272
273 name : WORD {
274 unsigned f;
275 name *n = name_find($1, 1, &f);
276 if (!f)
277 n->c = 0;
278 $$ = n;
279 }
280 ;
281
282 /*----- Various class expression types ------------------------------------*
283 *
284 * Unfortunately, all these need to handle token types slightly differently
285 * and I can't be bothered to remember the current state.
286 */
287
288 /* --- User class expressions --- */
289
290 user_class : user_class ',' user_class {
291 if (($$ = class_union($1, $3)) == 0) {
292 yyerror("type mismatch");
293 yynerrs++; YYERROR;
294 }
295 }
296 | user_class '-' user_class {
297 if (($$ = class_diff($1, $3)) == 0) {
298 yyerror("type mismatch");
299 yynerrs++; YYERROR;
300 }
301 }
302 | user_class '&' user_class {
303 if (($$ = class_isect($1, $3)) == 0) {
304 yyerror("type mismatch");
305 yynerrs++; YYERROR;
306 }
307 }
308 | user_class '|' user_class {
309 if (($$ = class_union($1, $3)) == 0) {
310 yyerror("type mismatch");
311 yynerrs++; YYERROR;
312 }
313 }
314 | INT { $$ = class_fromUser(clType_user, $1); }
315 | STRING {
316 struct passwd *pw;
317 if ((pw = userdb_userByName($1)) == 0) {
318 moan("user `%s' not known at line %i",
319 $1, lex_line);
320 yynerrs++; YYERROR;
321 } else
322 $$ = class_fromUser(clType_user, pw->pw_uid);
323 }
324 | WORD {
325 name *n = name_find($1, 0, 0);
326 if (!n || !n->c) {
327 moan("class `%s' not found at line %i",
328 $1, lex_line);
329 yynerrs++; YYERROR;
330 } else if (~n->c->type & clType_user) {
331 yynerrs++; yyerror("type mismatch");
332 yynerrs++; YYERROR;
333 } else {
334 $$ = n->c;
335 class_inc(n->c);
336 }
337 }
338 | '(' user_class ')' { $$ = $2; }
339 ;
340
341 /* --- Command class expressions --- */
342
343 command_class : command_class ',' command_class {
344 if (($$ = class_union($1, $3)) == 0) {
345 yyerror("type mismatch");
346 yynerrs++; YYERROR;
347 }
348 }
349 | command_class '-' command_class {
350 if (($$ = class_diff($1, $3)) == 0) {
351 yyerror("type mismatch");
352 yynerrs++; YYERROR;
353 }
354 }
355 | command_class '&' command_class {
356 if (($$ = class_isect($1, $3)) == 0) {
357 yyerror("type mismatch");
358 yynerrs++; YYERROR;
359 }
360 }
361 | command_class '|' command_class {
362 if (($$ = class_union($1, $3)) == 0) {
363 yyerror("type mismatch");
364 yynerrs++; YYERROR;
365 }
366 }
367 | STRING { $$ = class_fromString(clType_command, $1); }
368 | WORD {
369 name *n = name_find($1, 0, 0);
370 if (!n || !n->c) {
371 moan("class `%s' not found at line %i",
372 $1, lex_line);
373 yynerrs++; YYERROR;
374 } else if (~n->c->type & clType_command) {
375 yyerror("type mismatch");
376 yynerrs++; YYERROR;
377 } else {
378 $$ = n->c;
379 class_inc(n->c);
380 }
381 }
382 | '(' command_class ')' { $$ = $2; }
383 ;
384
385 /* --- Host class expressions --- */
386
387 host_class : host_class ',' host_class {
388 if (($$ = class_union($1, $3)) == 0) {
389 yyerror("type mismatch");
390 yynerrs++; YYERROR;
391 }
392 }
393 | host_class '-' host_class {
394 if (($$ = class_diff($1, $3)) == 0) {
395 yyerror("type mismatch");
396 yynerrs++; YYERROR;
397 }
398 }
399 | host_class '&' host_class {
400 if (($$ = class_isect($1, $3)) == 0) {
401 yyerror("type mismatch");
402 yynerrs++; YYERROR;
403 }
404 }
405 | host_class '|' host_class {
406 if (($$ = class_union($1, $3)) == 0) {
407 yyerror("type mismatch");
408 yynerrs++; YYERROR;
409 }
410 }
411 | STRING { $$ = class_fromString(clType_host, $1); }
412 | WORD {
413 name *n = name_find($1, 0, 0);
414 if (!n || !n->c) {
415 moan("class `%s' not found at line %i",
416 $1, lex_line);
417 yynerrs++; YYERROR;
418 } else if (~n->c->type & clType_host) {
419 yyerror("type mismatch");
420 yynerrs++; YYERROR;
421 } else {
422 $$ = n->c;
423 class_inc(n->c);
424 }
425 }
426 | '(' host_class ')' { $$ = $2; }
427 ;
428
429 /*----- Helper functions --------------------------------------------------*/
430 %%
431 /* --- @parse@ --- *
432 *
433 * Arguments: ---
434 *
435 * Returns: Zero if it worked, nonzero if it didn't.
436 *
437 * Use: Parses configuration files.
438 */
439
440 int parse(void)
441 {
442 yynerrs = 0;
443 return (yyparse() || yynerrs);
444 }
445
446 /*----- That's all, folks -------------------------------------------------*/