1 /* $OpenBSD: parse.y,v 1.10 2015/07/24 06:36:42 zhuk Exp $ */
3 * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
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.
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.
19 #include <sys/types.h>
47 #define YYSTYPE yystype
55 void yyerror(const char *, ...);
61 %token TPERMIT TDENY TAS TCMD TARGS
62 %token TNOPASS TKEEPENV
73 rule: action ident target cmd {
75 r = calloc(1, sizeof(*r));
77 errx(1, "can't allocate rule");
78 r->action = $1.action;
79 r->options = $1.options;
80 r->envlist = $1.envlist;
84 r->cmdargs = $4.cmdargs;
85 if (nrules == maxrules) {
90 if (!(rules = reallocarray(rules, maxrules,
92 errx(1, "can't allocate rules");
97 action: TPERMIT options {
99 $$.options = $2.options;
100 $$.envlist = $2.envlist;
105 options: /* none */ {
109 $$.options = $1.options | $2.options;
110 $$.envlist = $1.envlist;
113 yyerror("can't have two keepenv sections");
116 $$.envlist = $2.envlist;
123 $$.options = KEEPENV;
125 } | TKEEPENV '{' envlist '}' {
126 $$.options = KEEPENV;
127 $$.envlist = $3.envlist;
130 envlist: /* empty */ {
132 } | envlist TSTRING {
133 int nenv = arraylen($1.envlist);
134 if (!($$.envlist = reallocarray($1.envlist, nenv + 2,
136 errx(1, "can't allocate envlist");
137 $$.envlist[nenv] = $2.str;
138 $$.envlist[nenv + 1] = NULL;
146 target: /* optional */ {
152 cmd: /* optional */ {
155 } | TCMD TSTRING args {
157 $$.cmdargs = $3.cmdargs;
163 $$.cmdargs = $2.cmdargs;
166 argslist: /* empty */ {
168 } | argslist TSTRING {
169 int nargs = arraylen($1.cmdargs);
170 if (!($$.cmdargs = reallocarray($1.cmdargs, nargs + 2,
172 errx(1, "can't allocate args");
173 $$.cmdargs[nargs] = $2.str;
174 $$.cmdargs[nargs + 1] = NULL;
180 yyerror(const char *fmt, ...)
185 vfprintf(stderr, fmt, va);
187 fprintf(stderr, " at line %d\n", yylval.lineno + 1);
196 { "permit", TPERMIT },
200 { "nopass", TNOPASS },
201 { "keepenv", TKEEPENV },
207 char buf[1024], *ebuf, *p, *str;
208 int c, quotes = 0, escape = 0, qpos = -1, nonkw = 0;
211 ebuf = buf + sizeof(buf);
214 /* skip whitespace first */
215 for (c = getc(yyfp); c == ' ' || c == '\t'; c = getc(yyfp))
218 /* check for special one-character constructions */
228 /* skip comments; NUL is allowed; no continuation */
229 while ((c = getc(yyfp)) != '\n')
239 /* parsing next word */
240 for (;; c = getc(yyfp), yylval.colno++) {
243 yyerror("unallowed character NUL in column %d",
254 yyerror("unterminated quotes in column %d",
264 yyerror("unterminated escape in column %d",
267 yyerror("unterminated quotes in column %d",
276 if (!escape && !quotes)
291 yyerror("too long line");
301 * There could be a number of reasons for empty buffer,
302 * and we handle all of them here, to avoid cluttering
307 else if (qpos == -1) /* accept, e.g., empty args: cmd foo args "" */
312 for (i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
313 if (strcmp(buf, keywords[i].word) == 0)
314 return keywords[i].token;
317 if ((str = strdup(buf)) == NULL)