Annotation of src/usr.bin/doas/parse.y, Revision 1.8
1.8 ! tedu 1: /* $OpenBSD: parse.y,v 1.7 2015/07/21 11:04:06 zhuk 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;
1.7 zhuk 35: const char *cmd;
36: const char **cmdargs;
1.1 tedu 37: const char **envlist;
38: };
39: const char *str;
40: };
41: } yystype;
42: #define YYSTYPE yystype
43:
44: FILE *yyfp;
45:
46: struct rule **rules;
47: int nrules, maxrules;
48:
1.4 nicm 49: void yyerror(const char *, ...);
50: int yylex(void);
51: int yyparse(void);
52:
1.1 tedu 53: %}
54:
1.7 zhuk 55: %token TPERMIT TDENY TAS TCMD TARGS
1.1 tedu 56: %token TNOPASS TKEEPENV
57: %token TSTRING
58:
59: %%
60:
61: grammar: /* empty */
62: | grammar '\n'
63: | grammar rule '\n'
64: ;
65:
66: rule: action ident target cmd {
67: struct rule *r;
68: r = calloc(1, sizeof(*r));
1.2 nicm 69: if (!r)
70: errx(1, "can't allocate rule");
1.1 tedu 71: r->action = $1.action;
72: r->options = $1.options;
73: r->envlist = $1.envlist;
74: r->ident = $2.str;
75: r->target = $3.str;
1.7 zhuk 76: r->cmd = $4.cmd;
77: r->cmdargs = $4.cmdargs;
1.1 tedu 78: if (nrules == maxrules) {
79: if (maxrules == 0)
80: maxrules = 63;
81: else
82: maxrules *= 2;
1.6 benno 83: if (!(rules = reallocarray(rules, maxrules,
84: sizeof(*rules))))
1.1 tedu 85: errx(1, "can't allocate rules");
86: }
87: rules[nrules++] = r;
88: } ;
89:
90: action: TPERMIT options {
91: $$.action = PERMIT;
92: $$.options = $2.options;
93: $$.envlist = $2.envlist;
94: } | TDENY {
95: $$.action = DENY;
96: } ;
97:
98: options: /* none */
99: | options option {
100: $$.options = $1.options | $2.options;
101: $$.envlist = $1.envlist;
102: if ($2.envlist) {
103: if ($$.envlist)
104: errx(1, "can't have two keepenv sections");
105: else
106: $$.envlist = $2.envlist;
107: }
108: } ;
109: option: TNOPASS {
110: $$.options = NOPASS;
111: } | TKEEPENV {
112: $$.options = KEEPENV;
113: } | TKEEPENV '{' envlist '}' {
114: $$.options = KEEPENV;
115: $$.envlist = $3.envlist;
116: } ;
117:
118: envlist: /* empty */ {
119: if (!($$.envlist = calloc(1, sizeof(char *))))
120: errx(1, "can't allocate envlist");
121: } | envlist TSTRING {
122: int nenv = arraylen($1.envlist);
1.6 benno 123: if (!($$.envlist = reallocarray($1.envlist, nenv + 2,
124: sizeof(char *))))
1.1 tedu 125: errx(1, "can't allocate envlist");
126: $$.envlist[nenv] = $2.str;
127: $$.envlist[nenv + 1] = NULL;
128: }
129:
130:
131: ident: TSTRING {
132: $$.str = $1.str;
133: } ;
134:
135: target: /* optional */ {
136: $$.str = NULL;
137: } | TAS TSTRING {
138: $$.str = $2.str;
139: } ;
140:
141: cmd: /* optional */ {
1.7 zhuk 142: $$.cmd = NULL;
143: $$.cmdargs = NULL;
144: } | TCMD TSTRING args {
145: $$.cmd = $2.str;
146: $$.cmdargs = $3.cmdargs;
147: } ;
148:
149: args: /* empty */ {
150: $$.cmdargs = NULL;
151: } | TARGS argslist {
152: $$.cmdargs = $2.cmdargs;
153: } ;
154:
155: argslist: /* empty */ {
156: if (!($$.cmdargs = calloc(1, sizeof(char *))))
157: errx(1, "can't allocate args");
158: } | argslist TSTRING {
159: int nargs = arraylen($1.cmdargs);
160: if (!($$.cmdargs = reallocarray($1.cmdargs, nargs + 2, sizeof(char *))))
161: errx(1, "can't allocate args");
162: $$.cmdargs[nargs] = $2.str;
163: $$.cmdargs[nargs + 1] = NULL;
1.1 tedu 164: } ;
165:
166: %%
167:
168: void
169: yyerror(const char *fmt, ...)
170: {
171: va_list va;
172:
173: va_start(va, fmt);
1.4 nicm 174: verrx(1, fmt, va);
1.1 tedu 175: }
176:
177: struct keyword {
178: const char *word;
179: int token;
180: } keywords[] = {
181: { "deny", TDENY },
182: { "permit", TPERMIT },
183: { "as", TAS },
184: { "cmd", TCMD },
1.7 zhuk 185: { "args", TARGS },
1.1 tedu 186: { "nopass", TNOPASS },
187: { "keepenv", TKEEPENV },
188: };
189:
190: int
191: yylex(void)
192: {
193: char buf[1024], *ebuf, *p, *str;
1.5 benno 194: int i, c, next;
1.1 tedu 195:
196: p = buf;
197: ebuf = buf + sizeof(buf);
1.5 benno 198: repeat:
199: c = getc(yyfp);
1.1 tedu 200: switch (c) {
1.8 ! tedu 201: case ' ':
! 202: case '\t':
! 203: goto repeat; /* skip spaces */
! 204: case '\\':
! 205: next = getc(yyfp);
! 206: if (next == '\n')
! 207: goto repeat;
! 208: else
! 209: c = next;
! 210: case '\n':
! 211: case '{':
! 212: case '}':
! 213: return c;
! 214: case '#':
! 215: while ((c = getc(yyfp)) != '\n' && c != EOF)
! 216: ; /* skip comments */
! 217: if (c == EOF)
1.1 tedu 218: return 0;
1.8 ! tedu 219: return c;
! 220: case EOF:
! 221: return 0;
1.1 tedu 222: }
1.3 zhuk 223: while (1) {
224: switch (c) {
225: case '\n':
226: case '{':
227: case '}':
228: case '#':
229: case ' ':
230: case '\t':
231: case EOF:
232: goto eow;
233: }
1.1 tedu 234: *p++ = c;
235: if (p == ebuf)
236: yyerror("too much stuff");
237: c = getc(yyfp);
238: }
1.3 zhuk 239: eow:
1.1 tedu 240: *p = 0;
241: if (c != EOF)
242: ungetc(c, yyfp);
243: for (i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
244: if (strcmp(buf, keywords[i].word) == 0)
245: return keywords[i].token;
246: }
247: if ((str = strdup(buf)) == NULL)
248: err(1, "strdup");
249: yylval.str = str;
250: return TSTRING;
251: }