Annotation of src/usr.bin/doas/parse.y, Revision 1.6
1.6 ! benno 1: /* $OpenBSD: parse.y,v 1.5 2015/07/19 22:09:08 benno Exp $ */
1.1 tedu 2: /*
3: * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: %{
19: #include <sys/types.h>
20: #include <ctype.h>
21: #include <unistd.h>
22: #include <stdint.h>
23: #include <stdarg.h>
24: #include <stdio.h>
25: #include <string.h>
26: #include <err.h>
27:
28: #include "doas.h"
29:
30: typedef struct {
31: union {
32: struct {
33: int action;
34: int options;
35: const char **envlist;
36: };
37: const char *str;
38: };
39: } yystype;
40: #define YYSTYPE yystype
41:
42: FILE *yyfp;
43:
44: struct rule **rules;
45: int nrules, maxrules;
46:
1.4 nicm 47: void yyerror(const char *, ...);
48: int yylex(void);
49: int yyparse(void);
50:
1.1 tedu 51: %}
52:
53: %token TPERMIT TDENY TAS TCMD
54: %token TNOPASS TKEEPENV
55: %token TSTRING
56:
57: %%
58:
59: grammar: /* empty */
60: | grammar '\n'
61: | grammar rule '\n'
62: ;
63:
64: rule: action ident target cmd {
65: struct rule *r;
66: r = calloc(1, sizeof(*r));
1.2 nicm 67: if (!r)
68: errx(1, "can't allocate rule");
1.1 tedu 69: r->action = $1.action;
70: r->options = $1.options;
71: r->envlist = $1.envlist;
72: r->ident = $2.str;
73: r->target = $3.str;
74: r->cmd = $4.str;
75: if (nrules == maxrules) {
76: if (maxrules == 0)
77: maxrules = 63;
78: else
79: maxrules *= 2;
1.6 ! benno 80: if (!(rules = reallocarray(rules, maxrules,
! 81: sizeof(*rules))))
1.1 tedu 82: errx(1, "can't allocate rules");
83: }
84: rules[nrules++] = r;
85: } ;
86:
87: action: TPERMIT options {
88: $$.action = PERMIT;
89: $$.options = $2.options;
90: $$.envlist = $2.envlist;
91: } | TDENY {
92: $$.action = DENY;
93: } ;
94:
95: options: /* none */
96: | options option {
97: $$.options = $1.options | $2.options;
98: $$.envlist = $1.envlist;
99: if ($2.envlist) {
100: if ($$.envlist)
101: errx(1, "can't have two keepenv sections");
102: else
103: $$.envlist = $2.envlist;
104: }
105: } ;
106: option: TNOPASS {
107: $$.options = NOPASS;
108: } | TKEEPENV {
109: $$.options = KEEPENV;
110: } | TKEEPENV '{' envlist '}' {
111: $$.options = KEEPENV;
112: $$.envlist = $3.envlist;
113: } ;
114:
115: envlist: /* empty */ {
116: if (!($$.envlist = calloc(1, sizeof(char *))))
117: errx(1, "can't allocate envlist");
118: } | envlist TSTRING {
119: int nenv = arraylen($1.envlist);
1.6 ! benno 120: if (!($$.envlist = reallocarray($1.envlist, nenv + 2,
! 121: sizeof(char *))))
1.1 tedu 122: errx(1, "can't allocate envlist");
123: $$.envlist[nenv] = $2.str;
124: $$.envlist[nenv + 1] = NULL;
125: }
126:
127:
128: ident: TSTRING {
129: $$.str = $1.str;
130: } ;
131:
132: target: /* optional */ {
133: $$.str = NULL;
134: } | TAS TSTRING {
135: $$.str = $2.str;
136: } ;
137:
138: cmd: /* optional */ {
139: $$.str = NULL;
140: } | TCMD TSTRING {
141: $$.str = $2.str;
142: } ;
143:
144: %%
145:
146: void
147: yyerror(const char *fmt, ...)
148: {
149: va_list va;
150:
151: va_start(va, fmt);
1.4 nicm 152: verrx(1, fmt, va);
1.1 tedu 153: }
154:
155: struct keyword {
156: const char *word;
157: int token;
158: } keywords[] = {
159: { "deny", TDENY },
160: { "permit", TPERMIT },
161: { "as", TAS },
162: { "cmd", TCMD },
163: { "nopass", TNOPASS },
164: { "keepenv", TKEEPENV },
165: };
166:
167: int
168: yylex(void)
169: {
170: char buf[1024], *ebuf, *p, *str;
1.5 benno 171: int i, c, next;
1.1 tedu 172:
173: p = buf;
174: ebuf = buf + sizeof(buf);
1.5 benno 175: repeat:
176: c = getc(yyfp);
1.1 tedu 177: switch (c) {
1.5 benno 178: case ' ':
179: case '\t':
180: goto repeat; /* skip spaces */
181: case '\\':
182: next = getc(yyfp);
183: if (next == '\n')
184: goto repeat;
1.6 ! benno 185: else
1.5 benno 186: c = next;
1.1 tedu 187: case '\n':
188: case '{':
189: case '}':
190: return c;
191: case '#':
192: while ((c = getc(yyfp)) != '\n' && c != EOF)
193: ; /* skip comments */
194: if (c == EOF)
195: return 0;
196: return c;
197: case EOF:
198: return 0;
199: }
1.3 zhuk 200: while (1) {
201: switch (c) {
202: case '\n':
203: case '{':
204: case '}':
205: case '#':
206: case ' ':
207: case '\t':
208: case EOF:
209: goto eow;
210: }
1.1 tedu 211: *p++ = c;
212: if (p == ebuf)
213: yyerror("too much stuff");
214: c = getc(yyfp);
215: }
1.3 zhuk 216: eow:
1.1 tedu 217: *p = 0;
218: if (c != EOF)
219: ungetc(c, yyfp);
220: for (i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
221: if (strcmp(buf, keywords[i].word) == 0)
222: return keywords[i].token;
223: }
224: if ((str = strdup(buf)) == NULL)
225: err(1, "strdup");
226: yylval.str = str;
227: return TSTRING;
228: }