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