@ -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 <henning@openbsd.org>
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -36,20 +36,26 @@
#include "ntpd.h"
#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 {
struct opts {
int weight;
int weight;
@ -59,10 +65,10 @@ void opts_default(void);
typedef struct {
typedef struct {
union {
union {
int64_t number;
int64_t number;
char *string;
char *string;
struct ntp_addr_wrap *addr;
struct ntp_addr_wrap *addr;
struct opts opts;
struct opts opts;
} v;
} v;
int lineno;
int lineno;
} YYSTYPE;
} YYSTYPE;
@ -83,11 +89,11 @@ typedef struct {
grammar : /* empty */
grammar : /* empty */
| grammar '\n'
| 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 listen_addr *la;
struct ntp_addr *h, *next;
struct ntp_addr *h, *next;
@ -279,9 +285,9 @@ yyerror(const char *fmt, ...)
va_list ap;
va_list ap;
char *nfmt;
char *nfmt;
errors = 1 ;
file->errors++ ;
va_start(ap, fmt);
va_start(ap, fmt);
if (asprintf(&nfmt, "%s:%d: %s", in file, yylval.lineno, fmt) == -1)
if (asprintf(&nfmt, "%s:%d: %s", file->nam e, yylval.lineno, fmt) == -1)
fatalx("yyerror asprintf");
fatalx("yyerror asprintf");
vlog(LOG_CRIT, nfmt, ap);
vlog(LOG_CRIT, nfmt, ap);
va_end(ap);
va_end(ap);
@ -327,10 +333,9 @@ char pushback_buffer[MAXPUSHBACK];
int pushback_index = 0;
int pushback_index = 0;
int
int
lgetc(int in quot)
lgetc(int quotec )
{
{
int c, next;
FILE *f = fin;
int c, next;
if (parsebuf) {
if (parsebuf) {
/* Read character from the parsebuffer instead of input. */
/* Read character from the parsebuffer instead of input. */
@ -346,29 +351,39 @@ lgetc(int inquot)
if (pushback_index)
if (pushback_index)
return (pushback_buffer[--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);
return (c);
}
}
while ((c = getc(f)) == '\\') {
next = getc(f);
while ((c = getc(file->stream )) == '\\') {
next = getc(file->stream );
if (next != '\n') {
if (next != '\n') {
c = next;
c = next;
break;
break;
}
}
yylval.lineno = lineno;
lineno++;
yylval.lineno = file-> lineno;
file-> lineno++;
}
}
if (c == '\t' || c == ' ') {
if (c == '\t' || c == ' ') {
/* Compress blanks to a single space. */
/* Compress blanks to a single space. */
do {
do {
c = getc(f);
c = getc(file->stream );
} while (c == '\t' || c == ' ');
} while (c == '\t' || c == ' ');
ungetc(c, f);
ungetc(c, file->stream );
c = ' ';
c = ' ';
}
}
while (c == EOF) {
if (popfile() == EOF)
return (EOF);
c = getc(file->stream);
}
return (c);
return (c);
}
}
@ -400,7 +415,7 @@ findeol(void)
while (1) {
while (1) {
c = lgetc(0);
c = lgetc(0);
if (c == '\n') {
if (c == '\n') {
lineno++;
file-> lineno++;
break;
break;
}
}
if (c == EOF)
if (c == EOF)
@ -414,14 +429,14 @@ yylex(void)
{
{
char buf[8096];
char buf[8096];
char *p;
char *p;
int end c, next, c;
int quot ec, next, c;
int token;
int token;
p = buf;
p = buf;
while ((c = lgetc(0)) == ' ')
while ((c = lgetc(0)) == ' ')
; /* nothing */
; /* nothing */
yylval.lineno = lineno;
yylval.lineno = file-> lineno;
if (c == '#')
if (c == '#')
while ((c = lgetc(0)) != '\n' && c != EOF)
while ((c = lgetc(0)) != '\n' && c != EOF)
; /* nothing */
; /* nothing */
@ -429,21 +444,21 @@ yylex(void)
switch (c) {
switch (c) {
case '\'':
case '\'':
case '"':
case '"':
end c = c;
quot ec = c;
while (1) {
while (1) {
if ((c = lgetc(1 )) == EOF)
if ((c = lgetc(quotec )) == EOF)
return (0);
return (0);
if (c == '\n') {
if (c == '\n') {
lineno++;
file-> lineno++;
continue;
continue;
} else if (c == '\\') {
} else if (c == '\\') {
if ((next = lgetc(1 )) == EOF)
if ((next = lgetc(quotec )) == EOF)
return (0);
return (0);
if (next == end c)
if (next == quot ec)
c = next;
c = next;
else
else
lungetc(next);
lungetc(next);
} else if (c == end c) {
} else if (c == quot ec) {
*p = '\0';
*p = '\0';
break;
break;
}
}
@ -517,33 +532,67 @@ nodigits:
return (token);
return (token);
}
}
if (c == '\n') {
if (c == '\n') {
yylval.lineno = lineno;
lineno++;
yylval.lineno = file-> lineno;
file-> lineno++;
}
}
if (c == EOF)
if (c == EOF)
return (0);
return (0);
return (c);
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
int
parse_config(const char *filename, struct ntpd_conf *xconf)
parse_config(const char *filename, struct ntpd_conf *xconf)
{
{
int errors = 0;
conf = xconf;
conf = xconf;
lineno = 1;
errors = 0;
TAILQ_INIT(&conf->listen_addrs);
TAILQ_INIT(&conf->listen_addrs);
TAILQ_INIT(&conf->ntp_peers);
TAILQ_INIT(&conf->ntp_peers);
TAILQ_INIT(&conf->ntp_conf_sensors);
TAILQ_INIT(&conf->ntp_conf_sensors);
if ((fin = fopen(filename, "r")) == NULL) {
if ((file = pushfile(filename )) == NULL) {
log_warn("%s", filename);
log_warn("%s", filename);
return (-1);
return (-1);
}
}
infile = filename;
yyparse();
yyparse();
fclose(fin);
errors = file->errors;
popfile( );
return (errors ? -1 : 0);
return (errors ? -1 : 0);
}
}