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