Annotation of src/usr.bin/doas/parse.y, Revision 1.1
1.1 ! tedu 1: /* $OpenBSD$ */
! 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:
! 47: %}
! 48:
! 49: %token TPERMIT TDENY TAS TCMD
! 50: %token TNOPASS TKEEPENV
! 51: %token TSTRING
! 52:
! 53: %%
! 54:
! 55: grammar: /* empty */
! 56: | grammar '\n'
! 57: | grammar rule '\n'
! 58: ;
! 59:
! 60: rule: action ident target cmd {
! 61: struct rule *r;
! 62: r = calloc(1, sizeof(*r));
! 63: r->action = $1.action;
! 64: r->options = $1.options;
! 65: r->envlist = $1.envlist;
! 66: r->ident = $2.str;
! 67: r->target = $3.str;
! 68: r->cmd = $4.str;
! 69: if (nrules == maxrules) {
! 70: if (maxrules == 0)
! 71: maxrules = 63;
! 72: else
! 73: maxrules *= 2;
! 74: if (!(rules = reallocarray(rules, maxrules, sizeof(*rules))))
! 75: errx(1, "can't allocate rules");
! 76: }
! 77: rules[nrules++] = r;
! 78: } ;
! 79:
! 80: action: TPERMIT options {
! 81: $$.action = PERMIT;
! 82: $$.options = $2.options;
! 83: $$.envlist = $2.envlist;
! 84: } | TDENY {
! 85: $$.action = DENY;
! 86: } ;
! 87:
! 88: options: /* none */
! 89: | options option {
! 90: $$.options = $1.options | $2.options;
! 91: $$.envlist = $1.envlist;
! 92: if ($2.envlist) {
! 93: if ($$.envlist)
! 94: errx(1, "can't have two keepenv sections");
! 95: else
! 96: $$.envlist = $2.envlist;
! 97: }
! 98: } ;
! 99: option: TNOPASS {
! 100: $$.options = NOPASS;
! 101: } | TKEEPENV {
! 102: $$.options = KEEPENV;
! 103: } | TKEEPENV '{' envlist '}' {
! 104: $$.options = KEEPENV;
! 105: $$.envlist = $3.envlist;
! 106: } ;
! 107:
! 108: envlist: /* empty */ {
! 109: if (!($$.envlist = calloc(1, sizeof(char *))))
! 110: errx(1, "can't allocate envlist");
! 111: } | envlist TSTRING {
! 112: int nenv = arraylen($1.envlist);
! 113: if (!($$.envlist = reallocarray($1.envlist, nenv + 2, sizeof(char *))))
! 114: errx(1, "can't allocate envlist");
! 115: $$.envlist[nenv] = $2.str;
! 116: $$.envlist[nenv + 1] = NULL;
! 117: }
! 118:
! 119:
! 120: ident: TSTRING {
! 121: $$.str = $1.str;
! 122: } ;
! 123:
! 124: target: /* optional */ {
! 125: $$.str = NULL;
! 126: } | TAS TSTRING {
! 127: $$.str = $2.str;
! 128: } ;
! 129:
! 130: cmd: /* optional */ {
! 131: $$.str = NULL;
! 132: } | TCMD TSTRING {
! 133: $$.str = $2.str;
! 134: } ;
! 135:
! 136: %%
! 137:
! 138: void
! 139: yyerror(const char *fmt, ...)
! 140: {
! 141: va_list va;
! 142:
! 143: va_start(va, fmt);
! 144: fprintf(stderr, "doas: ");
! 145: vfprintf(stderr, fmt, va);
! 146: fprintf(stderr, "\n");
! 147: va_end(va);
! 148: exit(1);
! 149: }
! 150:
! 151: struct keyword {
! 152: const char *word;
! 153: int token;
! 154: } keywords[] = {
! 155: { "deny", TDENY },
! 156: { "permit", TPERMIT },
! 157: { "as", TAS },
! 158: { "cmd", TCMD },
! 159: { "nopass", TNOPASS },
! 160: { "keepenv", TKEEPENV },
! 161: };
! 162:
! 163: int
! 164: yylex(void)
! 165: {
! 166: char buf[1024], *ebuf, *p, *str;
! 167: int i, c;
! 168:
! 169: p = buf;
! 170: ebuf = buf + sizeof(buf);
! 171: while ((c = getc(yyfp)) == ' ' || c == '\t')
! 172: ; /* skip spaces */
! 173: switch (c) {
! 174: case '\n':
! 175: case '{':
! 176: case '}':
! 177: return c;
! 178: case '#':
! 179: while ((c = getc(yyfp)) != '\n' && c != EOF)
! 180: ; /* skip comments */
! 181: if (c == EOF)
! 182: return 0;
! 183: return c;
! 184: case EOF:
! 185: return 0;
! 186: case ':':
! 187: *p++ = c;
! 188: c = getc(yyfp);
! 189: break;
! 190: default:
! 191: break;
! 192: }
! 193: while (isalnum(c)) {
! 194: *p++ = c;
! 195: if (p == ebuf)
! 196: yyerror("too much stuff");
! 197: c = getc(yyfp);
! 198: }
! 199: *p = 0;
! 200: if (c != EOF)
! 201: ungetc(c, yyfp);
! 202: for (i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
! 203: if (strcmp(buf, keywords[i].word) == 0)
! 204: return keywords[i].token;
! 205: }
! 206: if ((str = strdup(buf)) == NULL)
! 207: err(1, "strdup");
! 208: yylval.str = str;
! 209: return TSTRING;
! 210: }