diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-10-13 16:35:23 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-10-13 16:35:23 +0000 |
commit | 3bc6f4c74e1cc60c05a1ab152805af447144952a (patch) | |
tree | 4a68ea922315ee6f6d1396cafc87ae97f4d0d06f /usr.sbin/ifstated/parse.y | |
parent | 3270c1ab5c203bfd16890aaf55afd4c31904e523 (diff) |
in all these programs using the same pfctl-derived parse.y, re-unify the
yylex implementation and the code which interacts with yylex. this also
brings the future potential for include support to all of the parsers.
in the future please do not silly modifications to one of these files
without checking if you are de-unifying the code.
checked by developers in all these areas.
Diffstat (limited to 'usr.sbin/ifstated/parse.y')
-rw-r--r-- | usr.sbin/ifstated/parse.y | 200 |
1 files changed, 139 insertions, 61 deletions
diff --git a/usr.sbin/ifstated/parse.y b/usr.sbin/ifstated/parse.y index 6b80338df66..af32be14a49 100644 --- a/usr.sbin/ifstated/parse.y +++ b/usr.sbin/ifstated/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.19 2007/10/11 14:39:17 deraadt Exp $ */ +/* $OpenBSD: parse.y,v 1.20 2007/10/13 16:35:21 deraadt Exp $ */ /* * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org> @@ -24,54 +24,62 @@ #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> +#include <sys/stat.h> #include <netinet/in.h> #include <arpa/inet.h> #include <net/if.h> #include <ctype.h> +#include <unistd.h> #include <err.h> #include <errno.h> +#include <limits.h> #include <stdarg.h> #include <stdio.h> #include <string.h> #include <syslog.h> #include <event.h> -#include <limits.h> #include "ifstated.h" -static struct ifsd_config *conf; -static FILE *fin = NULL; -static int lineno = 1; -static int errors = 0; -char *infile; -char *start_state; - -struct ifsd_action *curaction; -struct ifsd_state *curstate = NULL; - -int yyerror(const char *, ...); -int yyparse(void); -int kw_cmp(const void *, const void *); -int lookup(char *); -int lgetc(int); -int lungetc(int); -int findeol(void); -int yylex(void); - +TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); +static struct file { + TAILQ_ENTRY(file) entry; + FILE *stream; + char *name; + int lineno; + int errors; +} *file; +struct file *pushfile(const char *, int); +int popfile(void); +int check_file_secrecy(int, const char *); +int yyparse(void); +int yylex(void); +int yyerror(const char *, ...); +int kw_cmp(const void *, const void *); +int lookup(char *); +int lgetc(int); +int lungetc(int); +int findeol(void); TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); struct sym { - TAILQ_ENTRY(sym) entries; + TAILQ_ENTRY(sym) entry; int used; int persist; char *nam; char *val; }; +int symset(const char *, const char *, int); +char *symget(const char *); + +static struct ifsd_config *conf; +char *start_state; + +struct ifsd_action *curaction; +struct ifsd_state *curstate = NULL; void link_states(struct ifsd_action *); -int symset(const char *, const char *, int); -char *symget(const char *); void set_expression_depth(struct ifsd_expression *, int); void init_state(struct ifsd_state *); struct ifsd_ifstate *new_ifstate(u_short, int); @@ -115,7 +123,7 @@ grammar : /* empty */ | grammar varset '\n' | grammar action '\n' | grammar state '\n' - | grammar error '\n' { errors++; } + | grammar error '\n' { file->errors++; } ; string : string STRING { @@ -359,11 +367,11 @@ struct keywords { int yyerror(const char *fmt, ...) { - va_list ap; + va_list ap; - errors = 1; + file->errors++; va_start(ap, fmt); - fprintf(stderr, "%s:%d: ", infile, yylval.lineno); + fprintf(stderr, "%s:%d: ", file->name, yylval.lineno); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); @@ -417,10 +425,9 @@ char pushback_buffer[MAXPUSHBACK]; int pushback_index = 0; int -lgetc(int inquot) +lgetc(int quotec) { - int c, next; - FILE *f = fin; + int c, next; if (parsebuf) { /* Read character from the parsebuffer instead of input. */ @@ -436,29 +443,39 @@ lgetc(int inquot) if (pushback_index) return (pushback_buffer[--pushback_index]); - if (inquot) { - c = getc(f); + if (quotec) { + if ((c = getc(file->stream)) == EOF) { + yyerror("reached end of file while parsing quoted string"); + if (popfile() == EOF) + return (EOF); + return (quotec); + } return (c); } - while ((c = getc(f)) == '\\') { - next = getc(f); + while ((c = getc(file->stream)) == '\\') { + next = getc(file->stream); if (next != '\n') { c = next; break; } - yylval.lineno = lineno; - lineno++; + yylval.lineno = file->lineno; + file->lineno++; } if (c == '\t' || c == ' ') { /* Compress blanks to a single space. */ do { - c = getc(f); + c = getc(file->stream); } while (c == '\t' || c == ' '); - ungetc(c, f); + ungetc(c, file->stream); c = ' '; } + while (c == EOF) { + if (popfile() == EOF) + return (EOF); + c = getc(file->stream); + } return (c); } @@ -490,7 +507,7 @@ findeol(void) while (1) { c = lgetc(0); if (c == '\n') { - lineno++; + file->lineno++; break; } if (c == EOF) @@ -504,7 +521,7 @@ yylex(void) { char buf[8096]; char *p, *val; - int endc, next, c; + int quotec, next, c; int token; top: @@ -512,7 +529,7 @@ top: while ((c = lgetc(0)) == ' ') ; /* nothing */ - yylval.lineno = lineno; + yylval.lineno = file->lineno; if (c == '#') while ((c = lgetc(0)) != '\n' && c != EOF) ; /* nothing */ @@ -546,21 +563,21 @@ top: switch (c) { case '\'': case '"': - endc = c; + quotec = c; while (1) { - if ((c = lgetc(1)) == EOF) + if ((c = lgetc(quotec)) == EOF) return (0); if (c == '\n') { - lineno++; + file->lineno++; continue; } else if (c == '\\') { - if ((next = lgetc(1)) == EOF) + if ((next = lgetc(quotec)) == EOF) return (0); - if (next == endc) + if (next == quotec) c = next; else lungetc(next); - } else if (c == endc) { + } else if (c == quotec) { *p = '\0'; break; } @@ -634,17 +651,79 @@ nodigits: return (token); } if (c == '\n') { - yylval.lineno = lineno; - lineno++; + yylval.lineno = file->lineno; + file->lineno++; } if (c == EOF) return (0); return (c); } +int +check_file_secrecy(int fd, const char *fname) +{ + struct stat st; + + if (fstat(fd, &st)) { + warn("cannot stat %s", fname); + return (-1); + } + if (st.st_uid != 0 && st.st_uid != getuid()) { + warnx("%s: owner not root or current user", fname); + return (-1); + } + if (st.st_mode & (S_IRWXG | S_IRWXO)) { + warnx("%s: group/world readable/writeable", fname); + return (-1); + } + return (0); +} + +struct file * +pushfile(const char *name, int secret) +{ + struct file *nfile; + + if ((nfile = calloc(1, sizeof(struct file))) == NULL || + (nfile->name = strdup(name)) == NULL) + return (NULL); + if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { + free(nfile->name); + free(nfile); + return (NULL); + } else if (secret && + check_file_secrecy(fileno(nfile->stream), nfile->name)) { + fclose(nfile->stream); + free(nfile->name); + free(nfile); + return (NULL); + } + nfile->lineno = 1; + TAILQ_INSERT_TAIL(&files, nfile, entry); + return (nfile); +} + +int +popfile(void) +{ + struct file *prev; + + if ((prev = TAILQ_PREV(file, files, entry)) != NULL) { + prev->errors += file->errors; + TAILQ_REMOVE(&files, file, entry); + fclose(file->stream); + free(file->name); + free(file); + file = prev; + return (0); + } + return (EOF); +} + struct ifsd_config * parse_config(char *filename, int opts) { + int errors = 0; struct sym *sym, *next; struct ifsd_state *state; @@ -653,12 +732,11 @@ parse_config(char *filename, int opts) return (NULL); } - if ((fin = fopen(filename, "r")) == NULL) { + if ((file = pushfile(filename, 0)) == NULL) { warn("%s", filename); free(conf); return (NULL); } - infile = filename; TAILQ_INIT(&conf->states); @@ -668,8 +746,8 @@ parse_config(char *filename, int opts) conf->opts = opts; yyparse(); - - fclose(fin); + errors = file->errors; + popfile(); /* Link states */ TAILQ_FOREACH(state, &conf->states, entries) { @@ -692,14 +770,14 @@ parse_config(char *filename, int opts) /* Free macros and check which have not been used. */ for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) { - next = TAILQ_NEXT(sym, entries); + next = TAILQ_NEXT(sym, entry); if ((conf->opts & IFSD_OPT_VERBOSE2) && !sym->used) fprintf(stderr, "warning: macro '%s' not " "used\n", sym->nam); if (!sym->persist) { free(sym->nam); free(sym->val); - TAILQ_REMOVE(&symhead, sym, entries); + TAILQ_REMOVE(&symhead, sym, entry); free(sym); } } @@ -735,7 +813,7 @@ link_states(struct ifsd_action *action) if (state == NULL) { fprintf(stderr, "error: state '%s' not declared\n", action->act.statename); - errors++; + file->errors++; } break; } @@ -752,7 +830,7 @@ symset(const char *nam, const char *val, int persist) struct sym *sym; for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); - sym = TAILQ_NEXT(sym, entries)) + sym = TAILQ_NEXT(sym, entry)) ; /* nothing */ if (sym != NULL) { @@ -761,7 +839,7 @@ symset(const char *nam, const char *val, int persist) else { free(sym->nam); free(sym->val); - TAILQ_REMOVE(&symhead, sym, entries); + TAILQ_REMOVE(&symhead, sym, entry); free(sym); } } @@ -781,7 +859,7 @@ symset(const char *nam, const char *val, int persist) } sym->used = 0; sym->persist = persist; - TAILQ_INSERT_TAIL(&symhead, sym, entries); + TAILQ_INSERT_TAIL(&symhead, sym, entry); return (0); } @@ -812,7 +890,7 @@ symget(const char *nam) { struct sym *sym; - TAILQ_FOREACH(sym, &symhead, entries) + TAILQ_FOREACH(sym, &symhead, entry) if (strcmp(nam, sym->nam) == 0) { sym->used = 1; return (sym->val); |