version 1.14, 2022/03/29 22:16:46 |
version 1.19, 2022/04/17 21:23:34 |
|
|
#include "config.h" |
#include "config.h" |
#include "log.h" |
#include "log.h" |
|
|
static struct file { |
#define EXPAND_ON 1 |
FILE *stream; |
#define EXPAND_OFF 2 |
char *name; |
|
size_t ungetpos; |
|
size_t ungetsize; |
|
u_char *ungetbuf; |
|
int eof_reached; |
|
int lineno; |
|
} *f; |
|
|
|
int lookup(char *); |
int lookup(char *); |
int igetc(void); |
int igetc(void); |
Line 47 int yyerror(const char *, ...) |
|
Line 40 int yyerror(const char *, ...) |
|
__attribute__((__format__ (printf, 1, 2))) |
__attribute__((__format__ (printf, 1, 2))) |
__attribute__((__nonnull__ (1))); |
__attribute__((__nonnull__ (1))); |
|
|
|
int symset(const char *, const char *, int); |
|
char *symget(const char *); |
|
|
int config_load(struct blind *); |
int config_load(struct blind *); |
struct file *config_push(const char *); |
int config_close(void); |
int config_pop(void); |
|
|
|
TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); |
static int expanding; |
|
static int errors = 0; |
|
struct blind *env = NULL; |
|
static struct file *f = NULL; |
|
|
|
TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); |
struct sym { |
struct sym { |
TAILQ_ENTRY(sym) entry; |
TAILQ_ENTRY(sym) entry; |
int used; |
int used; |
int persist; |
int persist; |
char *nam; |
char *nam; |
char *val; |
char *val; |
}; |
}; |
char *symget(const char *); |
|
|
|
struct blind *env = NULL; |
|
static int errors = 0; |
|
|
|
typedef struct { |
typedef struct { |
union { |
union { |
int64_t number; |
int64_t number; |
char *string; |
char *string; |
} v; |
} v; |
int lineno; |
int lineno; |
} YYSTYPE; |
} YYSTYPE; |
|
|
|
|
grammar : |
grammar : |
| grammar '\n' |
| grammar '\n' |
| grammar set '\n' |
| grammar varset '\n' |
| grammar error '\n' { errors++; } |
| grammar set '\n' |
; |
| grammar error '\n' { errors++; } |
|
; |
|
|
|
varset : STRING '=' STRING { |
|
char *s = $1; |
|
while (*s++) { |
|
if (isspace((unsigned char)*s)) { |
|
yyerror("macro contain whitespace"); |
|
free($1); |
|
free($3); |
|
YYERROR; |
|
} |
|
} |
|
if (symset($1, $3, 0) == -1) |
|
log_fatal("cannot store variable"); |
|
free($1); |
|
free($3); |
|
} |
|
; |
|
|
set : SET EXPIRE NUMBER { |
set : SET EXPIRE NUMBER { |
env->bl_ttl = $3; |
env->bl_ttl = $3; |
} |
} |
| SET ACTION ENABLE { |
| SET ACTION ENABLE { |
env->bl_opt |= BL_OPT_ACTION; |
env->bl_opt |= BL_OPT_ACTION; |
} |
} |
| SET ACTION DISABLE { |
| SET ACTION DISABLE { |
env->bl_opt |= !BL_OPT_ACTION; |
env->bl_opt |= !BL_OPT_ACTION; |
} |
} |
; |
; |
|
|
%% |
%% |
|
|
struct keywords { |
struct keywords { |
const char *k_name; |
const char *k_name; |
int k_val; |
int k_val; |
}; |
}; |
|
|
int |
int |
Line 115 yyerror(const char *fmt, ...) |
|
Line 129 yyerror(const char *fmt, ...) |
|
if (vasprintf(&msg, fmt, ap) == -1) |
if (vasprintf(&msg, fmt, ap) == -1) |
log_fatal("yyerror vasprintf"); |
log_fatal("yyerror vasprintf"); |
va_end(ap); |
va_end(ap); |
log_info("%s:%d: %s", f->name, yylval.lineno, msg); |
log_info("%s:%d: %s", f->name, yylval.lineno, msg); |
free(msg); |
free(msg); |
return (0); |
return (0); |
} |
} |
|
|
return (STRING); |
return (STRING); |
} |
} |
|
|
#define START_EXPAND 1 |
int |
#define DONE_EXPAND 2 |
symset(const char *nam, const char *val, int persist) |
|
{ |
|
struct sym *sym; |
|
|
static int expanding; |
TAILQ_FOREACH(sym, &symhead, entry) { |
|
if (strcmp(nam, sym->nam) == 0) |
|
break; |
|
} |
|
|
|
if (sym != NULL) { |
|
if (sym->persist == 1) |
|
return (0); |
|
else { |
|
free(sym->nam); |
|
free(sym->val); |
|
TAILQ_REMOVE(&symhead, sym, entry); |
|
free(sym); |
|
} |
|
} |
|
if ((sym = calloc(1, sizeof(*sym))) == NULL) |
|
return (-1); |
|
|
|
sym->nam = strdup(nam); |
|
if (sym->nam == NULL) { |
|
free(sym); |
|
return (-1); |
|
} |
|
sym->val = strdup(val); |
|
if (sym->val == NULL) { |
|
free(sym->nam); |
|
free(sym); |
|
return (-1); |
|
} |
|
sym->used = 0; |
|
sym->persist = persist; |
|
TAILQ_INSERT_TAIL(&symhead, sym, entry); |
|
return (0); |
|
} |
|
|
char * |
char * |
symget(const char *nam) |
symget(const char *nam) |
{ |
{ |
|
|
int c; |
int c; |
|
|
while (1) { |
while (1) { |
if (f->ungetpos > 0) |
if (f->unpos > 0) |
c = f->ungetbuf[--f->ungetpos]; |
c = f->unbuf[--f->unpos]; |
else |
else |
c = getc(f->stream); |
c = getc(f->stream); |
|
|
if (c == START_EXPAND) |
if (c == EXPAND_ON) |
expanding = 1; |
expanding = 1; |
else if (c == DONE_EXPAND) |
else if (c == EXPAND_OFF) |
expanding = 0; |
expanding = 0; |
else |
else |
break; |
break; |
Line 197 lgetc(int quotec) |
|
Line 246 lgetc(int quotec) |
|
if ((c = igetc()) == EOF) { |
if ((c = igetc()) == EOF) { |
yyerror("reached end of file while parsing " |
yyerror("reached end of file while parsing " |
"quoted string"); |
"quoted string"); |
if (config_pop() == EOF) |
if (config_close() == EOF) |
return (EOF); |
return (EOF); |
return (quotec); |
return (quotec); |
} |
} |
Line 220 lgetc(int quotec) |
|
Line 269 lgetc(int quotec) |
|
* count right if last line in included file is syntactically |
* count right if last line in included file is syntactically |
* invalid and has no newline. |
* invalid and has no newline. |
*/ |
*/ |
if (f->eof_reached == 0) { |
if (f->eof == 0) { |
f->eof_reached = 1; |
f->eof = 1; |
return ('\n'); |
return ('\n'); |
} |
} |
while (c == EOF) { |
while (c == EOF) { |
if (config_pop() == EOF) |
if (config_close() == EOF) |
return (EOF); |
return (EOF); |
c = igetc(); |
c = igetc(); |
} |
} |
|
|
if (c == EOF) |
if (c == EOF) |
return; |
return; |
|
|
if (f->ungetpos >= f->ungetsize) { |
if (f->unpos >= f->unsize) { |
void *p = reallocarray(f->ungetbuf, f->ungetsize, 2); |
void *p = reallocarray(f->unbuf, f->unsize, 2); |
if (p == NULL) |
if (p == NULL) |
log_fatal("cannot reallocate memory"); |
log_fatal("cannot reallocate memory"); |
f->ungetbuf = p; |
f->unbuf = p; |
f->ungetsize *= 2; |
f->unsize *= 2; |
} |
} |
f->ungetbuf[f->ungetpos++] = c; |
f->unbuf[f->unpos++] = c; |
} |
} |
|
|
int |
int |
|
|
return (findeol()); |
return (findeol()); |
} |
} |
p = val + strlen(val) - 1; |
p = val + strlen(val) - 1; |
lungetc(DONE_EXPAND); |
lungetc(EXPAND_OFF); |
while (p >= val) { |
while (p >= val) { |
lungetc((unsigned char)*p); |
lungetc((unsigned char)*p); |
p--; |
p--; |
} |
} |
lungetc(START_EXPAND); |
lungetc(EXPAND_ON); |
goto top; |
goto top; |
} |
} |
|
|
|
|
if (c == '-' || isdigit(c)) { |
if (c == '-' || isdigit(c)) { |
do { |
do { |
*p++ = c; |
*p++ = c; |
if ((size_t)(p-buf) >= sizeof(buf)) { |
if ((size_t)(p-buf) >= sizeof(buf)) { |
yyerror("string too long"); |
yyerror("string too long"); |
return (findeol()); |
return (findeol()); |
} |
} |
|
|
int |
int |
config_load(struct blind *temp) |
config_load(struct blind *temp) |
{ |
{ |
env = temp; |
env = temp; |
errors = 0; |
errors = 0; |
|
|
if ((f = config_push(env->bl_conf)) == NULL) { |
if ((f = calloc(1, sizeof(struct file))) == NULL) { |
// config_purge(PURGE_ALL); |
log_debug("cannot allocate memory"); |
return (-1); |
return (-1); |
|
} |
|
if ((f->name = strdup(env->bl_conf)) == NULL) { |
|
log_debug("cannot duplicate name"); |
|
free(f); |
|
return (-1); |
} |
} |
|
if ((f->stream = fopen(f->name, "r")) == NULL) { |
|
log_debug("cannot open config file"); |
|
free(f->name); |
|
free(f); |
|
return (-1); |
|
} |
|
if (config_perm(fileno(f->stream), f->name)) { |
|
fclose(f->stream); |
|
free(f->name); |
|
free(f); |
|
return (-1); |
|
} |
|
f->lineno = 1; |
|
f->unsize = 16; |
|
if ((f->unbuf = malloc(f->unsize)) == NULL) { |
|
log_debug("cannot allocate buffer"); |
|
fclose(f->stream); |
|
free(f->name); |
|
free(f); |
|
return (-1); |
|
} |
|
|
yyparse(); |
yyparse(); |
|
// setup |
|
|
// setup |
if (errors) |
|
return (-1); |
|
|
if (errors) { |
return (0); |
// config_purge(PURGE_ALL); |
|
return (-1); |
|
} |
|
|
|
return (0); |
|
} |
} |
|
|
struct file * |
|
config_push(const char *name) |
|
{ |
|
struct file *nf; |
|
|
|
if ((nf = calloc(1, sizeof(struct file))) == NULL) { |
|
log_debug("cannot allocate memory"); |
|
return (NULL); |
|
} |
|
if ((nf->name = strdup(name)) == NULL) { |
|
log_debug("cannot duplicate name"); |
|
free(nf); |
|
return (NULL); |
|
} |
|
if ((nf->stream = fopen(nf->name, "r")) == NULL) { |
|
log_debug("cannot open config file"); |
|
free(nf->name); |
|
free(nf); |
|
return (NULL); |
|
} |
|
if (config_perm(fileno(nf->stream), nf->name)) { |
|
fclose(nf->stream); |
|
free(nf->name); |
|
free(nf); |
|
return (NULL); |
|
} |
|
nf->lineno = 1; |
|
nf->ungetsize = 16; |
|
nf->ungetbuf = malloc(nf->ungetsize); |
|
if (nf->ungetbuf == NULL) { |
|
log_debug("cannot allocate buffer"); |
|
fclose(nf->stream); |
|
free(nf->name); |
|
free(nf); |
|
return (NULL); |
|
} |
|
|
|
return (nf); |
|
} |
|
|
|
int |
int |
config_pop(void) |
config_close(void) |
{ |
{ |
fclose(f->stream); |
fclose(f->stream); |
free(f->name); |
free(f->name); |
free(f->ungetbuf); |
free(f->unbuf); |
free(f); |
free(f); |
|
|
return (EOF); |
return (EOF); |
} |
} |