chiark / gitweb /
Use rewritten class handler. Makes the expression parsers considerably
[become] / src / parser.y
1 /* -*-c-*-
2  *
3  * $Id: parser.y,v 1.4 1997/09/17 10:26:52 mdw Exp $
4  *
5  * Parser for `become.conf' files
6  *
7  * (c) 1997 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.4  1997/09/17 10:26:52  mdw
33  * Use rewritten class handler.  Makes the expression parsers considerably
34  * simpler.
35  *
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  *
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
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>
59 #include <sys/socket.h>
60
61 #include <netinet/in.h>
62
63 #include <arpa/inet.h>
64
65 #include <netdb.h>
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"
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;
87   class_node *c;
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
136 static 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
158 static 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
169 file            : /* empty */
170                 | file statement
171                 ;
172
173 statement       : 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
184 user_spec       : USER name '=' user_class ';' {
185                           if ($2->c)
186                             class_dec($2->c);
187                           $2->c = $4;
188                         }
189                 ;
190
191 command_spec    : COMMAND name '=' command_class ';' {
192                           if ($2->c)
193                             class_dec($2->c);
194                           $2->c = $4;
195                         }
196                 ;
197
198 host_spec       : HOST name '=' host_class ';' {
199                           if ($2->c)
200                             class_dec($2->c);
201                           $2->c = $4;
202                         }
203                 ;
204
205 port_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)); }
215                 ;
216
217 key_spec        : KEYFILE STRING ';' { daemon_readKey($2); }
218
219 /* --- Parsing allow specifications --- */
220
221 allow_spec      : ALLOW host_class_opt user_class ARROW
222                    user_class_opt command_class_opt ';' {
223                           rule_add($2, $3, $5, $6);
224                         }
225
226 host_class_opt  : /* empty */ { $$ = class_all; }
227                 | '[' host_class ']' { $$ = $2; }
228                 ;
229
230 user_class_opt  : /* empty */ { $$ = class_all; }
231                 | user_class { $$ = $1; }
232                 ;
233
234 command_class_opt : /* empty */ { $$ = class_all; }
235                 | ':' command_class { $$ = $2; }
236                 ;
237
238 /* --- Names get translated into symbols quickly --- */
239
240 name            : 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
256 user_class      : user_class ',' user_class {
257                           if (($$ = class_union($1, $3)) == 0) {
258                             yyerror("type mismatch");
259                             YYERROR;
260                           }
261                         }
262                 | user_class '-' user_class {
263                           if (($$ = class_diff($1, $3)) == 0) {
264                             yyerror("type mismatch");
265                             YYERROR;
266                           }
267                         }
268                 | user_class '&' user_class {
269                           if (($$ = class_isect($1, $3)) == 0) {
270                             yyerror("type mismatch");
271                             YYERROR;
272                           }
273                         }
274                 | user_class '|' user_class {
275                           if (($$ = class_union($1, $3)) == 0) {
276                             yyerror("type mismatch");
277                             YYERROR;
278                           }
279                         }
280                 | INT   { $$ = class_fromUser(clType_user, $1); }
281                 | STRING {
282                           struct passwd *pw;
283                           if ((pw = userdb_userByName($1)) == 0) {
284                             moan("user `%s' not known at line %i",
285                                  $1, lex_line);
286                             YYERROR;
287                           } else
288                             $$ = class_fromUser(clType_user, pw->pw_uid);
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
309 command_class   : command_class ',' command_class {
310                           if (($$ = class_union($1, $3)) == 0) {
311                             yyerror("type mismatch");
312                             YYERROR;
313                           }
314                         }
315                 | command_class '-' command_class {
316                           if (($$ = class_diff($1, $3)) == 0) {
317                             yyerror("type mismatch");
318                             YYERROR;
319                           }
320                         }
321                 | command_class '&' command_class {
322                           if (($$ = class_isect($1, $3)) == 0) {
323                             yyerror("type mismatch");
324                             YYERROR;
325                           }
326                         }
327                 | command_class '|' command_class {
328                           if (($$ = class_union($1, $3)) == 0) {
329                             yyerror("type mismatch");
330                             YYERROR;
331                           }
332                         }
333                 | STRING { $$ = class_fromString(clType_command, $1); }
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
353 host_class      : host_class ',' host_class {
354                           if (($$ = class_union($1, $3)) == 0) {
355                             yyerror("type mismatch");
356                             YYERROR;
357                           }
358                         }
359                 | host_class '-' host_class {
360                           if (($$ = class_diff($1, $3)) == 0) {
361                             yyerror("type mismatch");
362                             YYERROR;
363                           }
364                         }
365                 | host_class '&' host_class {
366                           if (($$ = class_isect($1, $3)) == 0) {
367                             yyerror("type mismatch");
368                             YYERROR;
369                           }
370                         }
371                 | host_class '|' host_class {
372                           if (($$ = class_union($1, $3)) == 0) {
373                             yyerror("type mismatch");
374                             YYERROR;
375                           }
376                         }
377                 | STRING { $$ = class_fromString(clType_host, $1); }
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 -------------------------------------------------*/