/* This file is in the public domain. */ #include #include #include #include #include #include #include extern const char *__progname; typedef enum { DT_INT = 1, DT_FLOAT, } DATATYPE; typedef unsigned long long int TIMEINTVL; typedef struct config CONFIG; typedef struct repo REPO; typedef struct listen LISTEN; typedef struct lep LEP; typedef struct lep_ops LEP_OPS; typedef struct map MAP; typedef struct map_ops MAP_OPS; typedef struct linereader LINEREADER; struct linereader { unsigned int flags; #define LRF_EOF 0x00000001 #define LRF_ERROR 0x00000002 int fd; unsigned char ibuf[8192]; int ibfill; int ibptr; unsigned char *lb; int ll; int la; } ; struct config { REPO *repos; LISTEN *listens; struct stat confstat; } ; struct listen { LISTEN *link; unsigned int permit; #define OP_NEW 0x00000001 #define OP_FETCH 0x00000002 LEP *endpoints; MAP *mappings; } ; struct lep { LEP *link; LEP_OPS *ops; void *priv; } ; struct map { MAP *link; MAP_OPS *ops; void *priv; } ; struct repo { REPO *link; char *name; char *filename; DATATYPE type; TIMEINTVL maxgap; } ; struct lep_ops { void *(*match)(const char *); } ; struct map_ops { void *(*match)(const char *); } ; static const char *configfile = "scd.conf"; static CONFIG *conf; static void handleargs(int ac, char **av) { int skip; int errs; skip = 0; errs = 0; for (ac--,av++;ac;ac--,av++) { if (skip > 0) { skip --; continue; } if (**av != '-') { fprintf(stderr,"%s: extra argument `%s'\n",__progname,*av); errs = 1; continue; } if (0) { needarg:; fprintf(stderr,"%s: %s needs a following argument\n",__progname,*av); errs = 1; continue; } #define WANTARG() do { if (++skip >= ac) goto needarg; } while (0) if (!strcmp(*av,"-config")) { WANTARG(); configfile = av[skip]; continue; } #undef WANTARG fprintf(stderr,"%s: unrecognized option `%s'\n",__progname,*av); errs = 1; } if (errs) exit(1); } static void init(void) { conf = 0; } static void config_init(CONFIG *cfg) { cfg->repos = 0; cfg->listens = 0; } static LINEREADER *lr_setup(int fd) { LINEREADER *lr; lr = malloc(sizeof(LINEREADER)); lr->flags = 0; lr->fd = fd; lr->ibfill = 0; lr->ibptr = 0; lr->lb = 0; lr->ll = 0; lr->la = 0; return(lr); } static void lr_done(LINEREADER *lr) { free(lr->lb); free(lr); } typedef enum { LRGL_LINE = 1, LRGL_EOF, LRGL_ERROR, } LRGLSTAT; static LRGLSTAT lr_getline(LINEREADER *lr) { int c; void save(char ch) { if (lr->ll >= lr->la) lr->lb = realloc(lr->lb,lr->la=lr->ll+8); lr->lb[lr->ll++] = ch; } if (lr->flags & LRF_EOF) return(LRGL_EOF); if (lr->flags & LRF_ERROR) return(LRGL_ERROR); lr->ll = 0; while (1) { if (lr->ibptr >= lr->ibfill) { lr->ibptr = 0; lr->ibfill = read(lr->fd,&lr->ibuf[0],sizeof(lr->ibuf)); if (lr->ibfill < 0) { lr->flags |= LRF_ERROR; return(LRGL_ERROR); } if (lr->ibfill == 0) { lr->flags |= LRF_EOF; if (lr->ll > 0) { save('\0'); lr->ll --; return(LRGL_LINE); } return(LRGL_EOF); } } c = lr->ibuf[lr->ibptr++]; if (c == '\n') { save('\0'); lr->ll --; return(LRGL_LINE); } save(c); } } static const char *lr_ptr(LINEREADER *lr) { return(lr->lb); } static int lr_len(LINEREADER *lr) { return(lr->ll); } static int reload_config(void) { CONFIG *cfg; int fd; LINEREADER *lr; int err; int errs; fd = open(configfile,O_RDONLY,0); if (fd < 0) { fprintf(stderr,"%s: %s: open: %s\n",__progname,configfile,strerror(errno)); return(-1); } lr = lr_setup(fd); cfg = malloc(sizeof(CONFIG)); config_init(cfg); if (fstat(fd,&cfg->confstat) < 0) { fprintf(stderr,"%s: %s: fstat %s\n",__progname,configfile,strerror(errno)); lr_done(lr); free(cfg); close(fd); return(-1); } errs = 0; while <"lines"> (1) { switch (lr_getline(lr)) { case LRGL_ERROR: errs = 1; break <"lines">; case LRGL_EOF: break <"lines">; case LRGL_LINE: break; default: abort(); break; } err = config_process(cfg,lr_ptr(lr),lr_len(lr)); if (err) errs = 1; if (err < 0) break; } lr_done(lr); if (errs) { config_free(cfg); } else { config_replace(conf,cfg); conf = cfg; } } int main(int, char **); int main(int ac, char **av) { handleargs(ac,av); init(); reload_config(); return(0); }