Make it build\!
[become] / src / parser.y
CommitLineData
c4f2d992 1/* -*-c-*-
2 *
9285878d 3 * $Id: parser.y,v 1.7 1999/03/26 15:25:22 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
29/*----- Revision history --------------------------------------------------*
30 *
31 * $Log: parser.y,v $
9285878d 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 *
082ddb26 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 *
c758e654 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
c327f3bc 45 * Use rewritten class handler. Makes the expression parsers considerably
46 * simpler.
47 *
f3debbd8 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 *
03f996bd 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
c4f2d992 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>
f3debbd8 71#include <sys/socket.h>
72
73#include <netinet/in.h>
c4f2d992 74
f3debbd8 75#include <arpa/inet.h>
76
77#include <netdb.h>
c4f2d992 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"
c4f2d992 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;
c327f3bc 99 class_node *c;
c4f2d992 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
148static 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
170static 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
181file : /* empty */
182 | file statement
183 ;
184
185statement : 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
196user_spec : USER name '=' user_class ';' {
197 if ($2->c)
198 class_dec($2->c);
199 $2->c = $4;
200 }
201 ;
202
203command_spec : COMMAND name '=' command_class ';' {
204 if ($2->c)
205 class_dec($2->c);
206 $2->c = $4;
207 }
208 ;
209
210host_spec : HOST name '=' host_class ';' {
211 if ($2->c)
212 class_dec($2->c);
213 $2->c = $4;
214 }
215 ;
216
f3debbd8 217port_spec : PORT STRING ';' {
082ddb26 218#ifndef NONETWORK
f3debbd8 219 struct servent *s = getservbyname($2, "udp");
220 if (!s) {
221 moan("unknown service `%s' at line %i",
222 $2, lex_line);
082ddb26 223 yynerrs++; YYERROR;
f3debbd8 224 }
225 daemon_usePort(s->s_port);
082ddb26 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
f3debbd8 238 }
c4f2d992 239 ;
240
082ddb26 241key_spec : KEYFILE STRING ';' {
242#ifndef NONETWORK
243 daemon_readKey($2);
244#else
245 yyerror("`keyfile' command unsupported");
246 yynerrs++; YYERROR;
247#endif
248 }
9285878d 249 ;
c4f2d992 250
251/* --- Parsing allow specifications --- */
252
253allow_spec : ALLOW host_class_opt user_class ARROW
254 user_class_opt command_class_opt ';' {
255 rule_add($2, $3, $5, $6);
256 }
9285878d 257 ;
c4f2d992 258
259host_class_opt : /* empty */ { $$ = class_all; }
260 | '[' host_class ']' { $$ = $2; }
261 ;
262
263user_class_opt : /* empty */ { $$ = class_all; }
264 | user_class { $$ = $1; }
265 ;
266
267command_class_opt : /* empty */ { $$ = class_all; }
268 | ':' command_class { $$ = $2; }
269 ;
270
271/* --- Names get translated into symbols quickly --- */
272
273name : WORD {
274 unsigned f;
275 name *n = name_find($1, 1, &f);
276 if (!f)
277 n->c = 0;
278 $$ = n;
279 }
9285878d 280 ;
c4f2d992 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
290user_class : user_class ',' user_class {
c327f3bc 291 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 292 yyerror("type mismatch");
082ddb26 293 yynerrs++; YYERROR;
c4f2d992 294 }
295 }
296 | user_class '-' user_class {
c327f3bc 297 if (($$ = class_diff($1, $3)) == 0) {
c4f2d992 298 yyerror("type mismatch");
082ddb26 299 yynerrs++; YYERROR;
c4f2d992 300 }
301 }
302 | user_class '&' user_class {
c327f3bc 303 if (($$ = class_isect($1, $3)) == 0) {
c4f2d992 304 yyerror("type mismatch");
082ddb26 305 yynerrs++; YYERROR;
c4f2d992 306 }
307 }
308 | user_class '|' user_class {
c327f3bc 309 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 310 yyerror("type mismatch");
082ddb26 311 yynerrs++; YYERROR;
c4f2d992 312 }
313 }
c327f3bc 314 | INT { $$ = class_fromUser(clType_user, $1); }
c4f2d992 315 | STRING {
316 struct passwd *pw;
c4f2d992 317 if ((pw = userdb_userByName($1)) == 0) {
318 moan("user `%s' not known at line %i",
319 $1, lex_line);
082ddb26 320 yynerrs++; YYERROR;
c327f3bc 321 } else
322 $$ = class_fromUser(clType_user, pw->pw_uid);
c4f2d992 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);
082ddb26 329 yynerrs++; YYERROR;
c4f2d992 330 } else if (~n->c->type & clType_user) {
082ddb26 331 yynerrs++; yyerror("type mismatch");
332 yynerrs++; YYERROR;
c4f2d992 333 } else {
334 $$ = n->c;
335 class_inc(n->c);
336 }
337 }
338 | '(' user_class ')' { $$ = $2; }
339 ;
340
341/* --- Command class expressions --- */
342
343command_class : command_class ',' command_class {
c327f3bc 344 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 345 yyerror("type mismatch");
082ddb26 346 yynerrs++; YYERROR;
c4f2d992 347 }
348 }
349 | command_class '-' command_class {
c327f3bc 350 if (($$ = class_diff($1, $3)) == 0) {
c4f2d992 351 yyerror("type mismatch");
082ddb26 352 yynerrs++; YYERROR;
c4f2d992 353 }
354 }
355 | command_class '&' command_class {
c327f3bc 356 if (($$ = class_isect($1, $3)) == 0) {
c4f2d992 357 yyerror("type mismatch");
082ddb26 358 yynerrs++; YYERROR;
c4f2d992 359 }
360 }
361 | command_class '|' command_class {
c327f3bc 362 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 363 yyerror("type mismatch");
082ddb26 364 yynerrs++; YYERROR;
c4f2d992 365 }
366 }
c327f3bc 367 | STRING { $$ = class_fromString(clType_command, $1); }
c4f2d992 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);
082ddb26 373 yynerrs++; YYERROR;
c4f2d992 374 } else if (~n->c->type & clType_command) {
375 yyerror("type mismatch");
082ddb26 376 yynerrs++; YYERROR;
c4f2d992 377 } else {
378 $$ = n->c;
379 class_inc(n->c);
380 }
381 }
382 | '(' command_class ')' { $$ = $2; }
383 ;
384
385/* --- Host class expressions --- */
386
c327f3bc 387host_class : host_class ',' host_class {
388 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 389 yyerror("type mismatch");
082ddb26 390 yynerrs++; YYERROR;
c4f2d992 391 }
392 }
393 | host_class '-' host_class {
c327f3bc 394 if (($$ = class_diff($1, $3)) == 0) {
c4f2d992 395 yyerror("type mismatch");
082ddb26 396 yynerrs++; YYERROR;
c4f2d992 397 }
398 }
399 | host_class '&' host_class {
c327f3bc 400 if (($$ = class_isect($1, $3)) == 0) {
c4f2d992 401 yyerror("type mismatch");
082ddb26 402 yynerrs++; YYERROR;
c4f2d992 403 }
404 }
405 | host_class '|' host_class {
c327f3bc 406 if (($$ = class_union($1, $3)) == 0) {
c4f2d992 407 yyerror("type mismatch");
082ddb26 408 yynerrs++; YYERROR;
c4f2d992 409 }
410 }
c327f3bc 411 | STRING { $$ = class_fromString(clType_host, $1); }
c4f2d992 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);
082ddb26 417 yynerrs++; YYERROR;
c4f2d992 418 } else if (~n->c->type & clType_host) {
419 yyerror("type mismatch");
082ddb26 420 yynerrs++; YYERROR;
c4f2d992 421 } else {
422 $$ = n->c;
423 class_inc(n->c);
424 }
425 }
426 | '(' host_class ')' { $$ = $2; }
427 ;
428
082ddb26 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
440int parse(void)
441{
442 yynerrs = 0;
443 return (yyparse() || yynerrs);
444}
445
c4f2d992 446/*----- That's all, folks -------------------------------------------------*/