#include #include #include #include #include #include #include extern const char *__progname; #include "vars.h" #include "util.h" #include "repo.h" #include "listen.h" #include "structs.h" #include "linereader.h" #include "config.h" extern SECT_OPS sectops_repo; extern SECT_OPS sectops_listen; static SECT_OPS *sects[] = { §ops_repo, §ops_listen }; void config_warn(CONFIG *cfg, const char *fmt, ...) { va_list ap; if (! cfg->pt) abort(); va_start(ap,fmt); vfprintf(cfg->pt->errf,fmt,ap); va_end(ap); putc('\n',cfg->pt->errf); } void config_err(CONFIG *cfg, const char *fmt, ...) { va_list ap; if (! cfg->pt) abort(); va_start(ap,fmt); vfprintf(cfg->pt->errf,fmt,ap); va_end(ap); putc('\n',cfg->pt->errf); (*cfg->pt->err_throw)(); } void config_err_post(void (*post)(void), CONFIG *cfg, const char *fmt, ...) { va_list ap; if (! cfg->pt) abort(); va_start(ap,fmt); vfprintf(cfg->pt->errf,fmt,ap); va_end(ap); putc('\n',cfg->pt->errf); (*post)(); (*cfg->pt->err_throw)(); } static void config_err_wrap(FILE *f, void *ptv, const char *buf, int len) { CONFIG_PARSE_TEMP *pt; pt = ptv; for (;len>0;buf++,len--) { if (pt->elb) fprintf(f,"%s: line %d: ",pt->filename,lr_lineno(pt->lr)); putc(*buf,f); pt->elb = (*buf == '\n'); } } static int config_process(CONFIG *cfg, const char *line) { int i; if (cfg->pt->ops) { switch ((*cfg->pt->ops->parse)(cfg->pt->sectpriv,line)) { case SPRV_GOOD: return(0); break; case SPRV_UNKNOWN: break; case SPRV_ERROR: return(1); break; default: abort(); break; } } for (i=(sizeof(sects)/sizeof(sects[0]))-1;i>=0;i--) { void *pp; pp = (*sects[i]->start)(line,cfg); if (pp) { int throwing; throwing = 0; if (cfg->pt->ops) { __label__ errjmp; FILE *fsave; void (*saved_err_throw)(void); void err_throw(void) { throwing = 1; goto errjmp; } void err_wrap(FILE *f, void *ptv, const char *buf, int len) { CONFIG_PARSE_TEMP *pt; pt = ptv; for (;len>0;buf++,len--) { if (pt->elb) fprintf(f,"ending previous section: "); putc(*buf,f); pt->elb = (*buf == '\n'); } } saved_err_throw = cfg->pt->err_throw; cfg->pt->err_throw = &err_throw; fsave = cfg->pt->errf; cfg->pt->errf = stdio_wrap_w(fsave,cfg->pt,&err_wrap,0); throwing = 0; (*cfg->pt->ops->done)(cfg->pt->sectpriv); errjmp:; fclose(cfg->pt->errf); cfg->pt->errf = fsave; cfg->pt->err_throw = saved_err_throw; } cfg->pt->ops = sects[i]; cfg->pt->sectpriv = pp; if (throwing) (*cfg->pt->err_throw)(); } } if (cfg->pt->ops) { config_err(cfg,"not valid in this section and not a valid section start line"); } else { config_err(cfg,"not a valid section start line"); } } static void config_free(CONFIG *cfg) { if (cfg->pt) abort(); repo_free_chain(cfg->repos); listen_free_chain(cfg->listens); free(cfg); } static void config_replace(CONFIG *old, CONFIG *new) { old=old; new=new; /* XXX XXX XXX */ } static void config_parse_done(CONFIG *cfg) { lr_done(cfg->pt->lr); fclose(cfg->pt->errf); free(cfg->pt); cfg->pt = 0; } int reload_config(void) { __label__ errjmp; CONFIG *cfg; int fd; int err; int errs; void err_throw(void) { goto errjmp; } fd = open(configfile,O_RDONLY,0); if (fd < 0) { fprintf(stderr,"%s: %s: open: %s\n",__progname,configfile,strerror(errno)); return(-1); } cfg = malloc(sizeof(CONFIG)); cfg->repos = 0; cfg->listens = 0; cfg->pt = malloc(sizeof(CONFIG_PARSE_TEMP)); cfg->pt->ops = 0; cfg->pt->sectpriv = 0; cfg->pt->filename = configfile; cfg->pt->lr = lr_setup(fd); cfg->pt->errf = stdio_wrap_w(stderr,cfg->pt,&config_err_wrap,0); cfg->pt->elb = 1; cfg->pt->err_throw = 0; if (fstat(fd,&cfg->confstat) < 0) { fprintf(stderr,"%s: %s: fstat %s\n",__progname,configfile,strerror(errno)); config_parse_done(cfg); free(cfg); close(fd); return(-1); } errs = 0; while <"lines"> (1) { switch (lr_getline(cfg->pt->lr)) { case LRGL_ERROR: errs = 1; break <"lines">; case LRGL_EOF: break <"lines">; case LRGL_LINE: break; default: abort(); break; } cfg->pt->err_throw = &err_throw; err = config_process(cfg,lr_ptr(cfg->pt->lr)); if (0) { errjmp:; err = 1; } cfg->pt->err_throw = 0; if (err) errs = 1; if (err < 0) break; } config_parse_done(cfg); if (errs) { config_free(cfg); return(-1); } else { config_replace(conf,cfg); conf = cfg; return(0); } }