/* This file is in the public domain. */ #include #include #include #include "ctype.h" #include "config.h" #include "structs.h" /* * Implementation of `listen' config-file sections. * * These are comparatively complex, with lists of LEPs and MAPs and * suchlike. */ /* * All the LEP types we support. */ extern const LEP_OPS lep_ops_local; extern const LEP_OPS lep_ops_ip; static const LEP_OPS * const leps[] = { &lep_ops_local, &lep_ops_ip }; /* * All the MAP types we support. */ extern const MAP_OPS map_ops_trivial; extern const MAP_OPS map_ops_error; extern const MAP_OPS map_ops_simple; extern const MAP_OPS map_ops_regex; static const MAP_OPS * const maps[] = { &map_ops_trivial, &map_ops_error, &map_ops_simple, &map_ops_regex }; /* * Our section-private data. All we keep here is the LISTEN we're * building and the CONFIG we're planning on adding it to. */ typedef struct sect_listen_priv SECT_LISTEN_PRIV; struct sect_listen_priv { LISTEN *l; CONFIG *cfg; } ; /* * Our start method. Just check to see if the line is a `listen' line; * if so, set up a new LISTEN to build, and a SECT_LISTEN_PRIV to hold * it while we're building it. */ static void *sect_listen_start(const char *line, CONFIG *cfg) { int i; SECT_LISTEN_PRIV *p; i = 0; while (line[i] && UCisspace(line[i])) i ++; if (strncmp(line+i,"listen",6) || (line[i+6] && !UCisspace(line[i+6]))) return(0); i += 6; while (line[i] && UCisspace(line[i])) i ++; if (line[i]) config_err(cfg,"junk on listen line"); p = malloc(sizeof(SECT_LISTEN_PRIV)); p->l = malloc(sizeof(LISTEN)); p->l->conf = cfg; p->l->refs = 1; p->l->permit = 0; p->l->endpoints = 0; p->l->mappings = 0; p->cfg = cfg; return(p); } /* * Our parse method. We handle `permit' lines directly. For `map' * lines, we pick out the priority and then the type keyword, then * call on the MAP types to do the real work. Everything else must be * an endpoint line, for which we call on the LEP types. */ static SPRV sect_listen_parse(void *pv, const char *line) { int i; int j; int k; SECT_LISTEN_PRIV *p; int x; p = pv; i = 0; while (line[i] && UCisspace(line[i])) i ++; j = i; while (line[i] && !UCisspace(line[i])) i ++; k = i; while (line[i] && UCisspace(line[i])) i ++; if ((k-j == 6) && !bcmp(line+j,"permit",6)) { while (line[i]) { j = i; while (line[i] && !UCisspace(line[i])) i ++; k = i; while (line[i] && UCisspace(line[i])) i ++; if ((k-j == 8) && !bcmp(line+j,"new-data",8)) { p->l->permit |= OP_NEW; } else if ((k-j == 5) && !bcmp(line+j,"fetch",5)) { p->l->permit |= OP_FETCH; } else if ((k-j == 1) && (line[j] == '*')) { p->l->permit |= OP_NEW | OP_FETCH; } else { config_err(p->cfg,"invalid operation `%.*s' on `permit' line",k-j,line+j); } } return(SPRV_GOOD); } else if ((k-j == 3) && !bcmp(line+j,"map",3)) { char *ne; unsigned long int nvl; int nv; j = i; while (line[i] && !UCisspace(line[i])) i ++; k = i; nvl = strtoul(line+j,&ne,10); nv = nvl; if ((ne != line+k) || (nv < 0) || (nv != nvl)) config_err(p->cfg,"bad priority value `%.*s' on `map' line",k-j,line+j); while (line[i] && UCisspace(line[i])) i ++; j = i; while (line[i] && !UCisspace(line[i])) i ++; k = i; while (line[i] && UCisspace(line[i])) i ++; for (x=(sizeof(maps)/sizeof(maps[0]))-1;x>=0;x--) { if ((*maps[x]->add)(p->cfg,p->l,nv,line+j,k-j,line+i)) { return(SPRV_GOOD); } } } else { for (x=(sizeof(leps)/sizeof(leps[0]))-1;x>=0;x--) { if ((*leps[x]->add)(p->cfg,p->l,line+j,k-j,line+i)) { return(SPRV_GOOD); } } } return(SPRV_UNKNOWN); } /* * Our done method. We never error, but we do warn about certain * conditions which make the section useless. Besides that checking, * all we do is hook the LISTEN into the CONFIG. */ static void sect_listen_done(void *pv) { SECT_LISTEN_PRIV *p; p = pv; if (p->l->permit == 0) config_warn(p->cfg,"`listen' section does not permit any operations"); if (p->l->endpoints == 0) config_warn(p->cfg,"`listen' section has no listening endpoints"); if (p->l->mappings == 0) config_warn(p->cfg,"`listen' section has no mappings"); p->l->link = p->cfg->listens; p->cfg->listens = p->l; free(p); } /* * Our SECT_OPS. */ const SECT_OPS sectops_listen = SECT_OPS_INIT(listen);