[BACK]Return to parse.y CVS log [TXT][DIR] Up to [local] / src / usr.bin / doas

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: }