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