diff --git a/src/usr.sbin/ntpd/parse.y b/src/usr.sbin/ntpd/parse.y index cbaaa3cd..f81341eb 100644 --- a/src/usr.sbin/ntpd/parse.y +++ b/src/usr.sbin/ntpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.36 2007/10/11 14:39:17 deraadt Exp $ */ +/* $OpenBSD: parse.y,v 1.37 2007/10/13 16:35:21 deraadt Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer @@ -36,20 +36,26 @@ #include "ntpd.h" -static struct ntpd_conf *conf; -static FILE *fin = NULL; -static int lineno = 1; -static int errors = 0; -const char *infile; - -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 popfile(void); +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); + +struct ntpd_conf *conf; struct opts { int weight; @@ -59,10 +65,10 @@ void opts_default(void); typedef struct { union { - int64_t number; + int64_t number; char *string; struct ntp_addr_wrap *addr; - struct opts opts; + struct opts opts; } v; int lineno; } YYSTYPE; @@ -83,11 +89,11 @@ typedef struct { grammar : /* empty */ | grammar '\n' - | grammar conf_main '\n' - | grammar error '\n' { errors++; } + | grammar main '\n' + | grammar error '\n' { file->errors++; } ; -conf_main : LISTEN ON address { +main : LISTEN ON address { struct listen_addr *la; struct ntp_addr *h, *next; @@ -279,9 +285,9 @@ yyerror(const char *fmt, ...) va_list ap; char *nfmt; - errors = 1; + file->errors++; va_start(ap, fmt); - if (asprintf(&nfmt, "%s:%d: %s", infile, yylval.lineno, fmt) == -1) + if (asprintf(&nfmt, "%s:%d: %s", file->name, yylval.lineno, fmt) == -1) fatalx("yyerror asprintf"); vlog(LOG_CRIT, nfmt, ap); va_end(ap); @@ -327,10 +333,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. */ @@ -346,29 +351,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); } @@ -400,7 +415,7 @@ findeol(void) while (1) { c = lgetc(0); if (c == '\n') { - lineno++; + file->lineno++; break; } if (c == EOF) @@ -414,14 +429,14 @@ yylex(void) { char buf[8096]; char *p; - int endc, next, c; + int quotec, next, c; int token; p = buf; while ((c = lgetc(0)) == ' ') ; /* nothing */ - yylval.lineno = lineno; + yylval.lineno = file->lineno; if (c == '#') while ((c = lgetc(0)) != '\n' && c != EOF) ; /* nothing */ @@ -429,21 +444,21 @@ yylex(void) 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; } @@ -517,33 +532,67 @@ nodigits: return (token); } if (c == '\n') { - yylval.lineno = lineno; - lineno++; + yylval.lineno = file->lineno; + file->lineno++; } if (c == EOF) return (0); return (c); } +struct file * +pushfile(const char *name) +{ + 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); + } + 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); +} + int parse_config(const char *filename, struct ntpd_conf *xconf) { + int errors = 0; + conf = xconf; - lineno = 1; - errors = 0; TAILQ_INIT(&conf->listen_addrs); TAILQ_INIT(&conf->ntp_peers); TAILQ_INIT(&conf->ntp_conf_sensors); - if ((fin = fopen(filename, "r")) == NULL) { + if ((file = pushfile(filename)) == NULL) { log_warn("%s", filename); return (-1); } - infile = filename; yyparse(); - - fclose(fin); + errors = file->errors; + popfile(); return (errors ? -1 : 0); }