X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=blobdiff_plain;f=conffile.c;h=b17517b58092d800da561c44f28420dbcdd54f30;hp=e9c84d3cb4aa82fc9a49eeaea73d6f1eb8f0827b;hb=fe5e9cc422cd72526ccfceffbc7e5af8ac83b407;hpb=7138d0c54cd2212439434d27cb2d6ea775c3039b diff --git a/conffile.c b/conffile.c index e9c84d3..b17517b 100644 --- a/conffile.c +++ b/conffile.c @@ -1,7 +1,3 @@ -/* - * $Log$ - */ - /* conffile.c - process the configuration file */ /* #define DUMP_PARSE_TREE */ @@ -76,10 +72,8 @@ static list_t *dict_ilookup(dict_t *dict, atom_t key) static void dict_iadd(dict_t *dict, atom_t key, list_t *val) { struct entry *e; - /* XXX May want to permit redefinition of keys in the future */ - /* (although it could be very confusing) */ if (dict_ilookup_primitive(dict, key)) { - fatal("duplicate key \"%s\" in dictionary\n",key); + fatal("duplicate key \"%s\" in dictionary",key); } e=safe_malloc(sizeof(*e),"dict_add"); e->next=dict->entries; @@ -134,25 +128,25 @@ static void ptree_mangle(struct p_node *t) ptree_mangle(t->r); switch (t->type) { case T_DICT: - /* ASSERT !t->l || t->l->type==T_ALIST */ - /* ASSERT !t->r || t->r->type==T_LISTITEM */ + ASSERT(!t->l || t->l->type==T_ALIST); + ASSERT(!t->r || t->r->type==T_LISTITEM); t->l=list_reverse(t->l); t->r=list_reverse(t->r); break; case T_ASSIGNMENT: - /* ASSERT t->l->type==T_KEY */ - /* ASSERT t->r->type==T_LISTITEM */ + ASSERT(t->l->type==T_KEY); + ASSERT(t->r->type==T_LISTITEM); t->r=list_reverse(t->r); break; case T_ABSPATH: case T_RELPATH: - /* ASSERT t->l==NULL */ - /* ASSERT t->r->type==T_PATHELEM */ + ASSERT(t->l==NULL); + ASSERT(t->r->type==T_PATHELEM); t->r=list_reverse(t->r); break; case T_EXEC: - /* ASSERT t->l */ - /* ASSERT t->r->type==T_LISTITEM */ + ASSERT(t->l); + ASSERT(t->r==NULL || t->r->type==T_LISTITEM); t->r=list_reverse(t->r); break; } @@ -226,8 +220,8 @@ static list_t *dict_lookup_path(dict_t *context, struct p_node *p) dict_t *i; list_t *l; - /* ASSERT p->type==T_PATHELEM */ - /* ASSERT p->l->type==T_KEY */ + ASSERT(p->type==T_PATHELEM); + ASSERT(p->l->type==T_KEY); l=dict_ilookup(context, p->l->data.key); if (!l) { cfgfatal(p->loc,"conffile","can't find key %s\n", @@ -294,7 +288,7 @@ static list_t *process_item(dict_t *context, struct p_node *i) default: #ifdef DUMP_PARSE_TREE ptree_dump(i,0); - fatal("process_item: invalid node type for a list item (%s)\n", + fatal("process_item: invalid node type for a list item (%s)", ntype(i->type)); #else fatal("process_item: list item has invalid node type %d - recompile " @@ -311,7 +305,7 @@ static list_t *process_ilist(dict_t *context, struct p_node *l) struct p_node *i; list_t *r; - /* ASSERT l->type==T_LISTITEM */ + ASSERT(!l || l->type==T_LISTITEM); r=list_new(); @@ -327,14 +321,16 @@ static list_t *process_invocation(dict_t *context, struct p_node *i) item_t *cl; list_t *args; - /* ASSERT i->type==T_EXEC */ - /* ASSERT i->r->type==T_LISTITEM */ - /* XXX it might be null too */ + ASSERT(i->type==T_EXEC); + ASSERT(i->r==NULL || i->r->type==T_LISTITEM); cll=process_item(context,i->l); cl=cll->item; if (cl->type != t_closure) { cfgfatal(i->l->loc,"conffile","only closures can be invoked\n"); } + if (!cl->data.closure->apply) { + cfgfatal(i->l->loc,"conffile","this closure cannot be invoked\n"); + } args=process_ilist(context, i->r); return cl->data.closure->apply(cl->data.closure, i->loc, context, args); } @@ -347,15 +343,15 @@ static void process_alist(dict_t *context, struct p_node *c) if (!c) return; /* NULL assignment lists are valid (empty dictionary) */ - /* ASSERT c->type==T_ALIST */ + ASSERT(c->type==T_ALIST); if (c->type!=T_ALIST) { - fatal("invalid node type in assignment list\n"); + fatal("invalid node type in assignment list"); } for (i=c; i; i=i->r) { - /* ASSERT i->l && i->l->type==T_ASSIGNMENT */ - /* ASSERT i->l->l->type==T_KEY */ - /* ASSERT i->l->r->type==T_LISTITEM */ + ASSERT(i->l && i->l->type==T_ASSIGNMENT); + ASSERT(i->l->l->type==T_KEY); + ASSERT(i->l->r->type==T_LISTITEM); k=i->l->l->data.key; l=process_ilist(context, i->l->r); dict_iadd(context, k, l); @@ -447,8 +443,9 @@ static list_t *readfile(closure_t *self, struct cloc loc, r=new_item(t_string,loc); r->data.string=safe_malloc(length+1,"readfile"); if (fread(r->data.string,length,1,f)!=1) { - fatal("readfile (%s:%d): fread: could not read all of file\n", - loc.file,loc.line); + (ferror(f) ? fatal_perror : fatal) + ("readfile (%s:%d): fread: could not read all of file", + loc.file,loc.line); } r->data.string[length]=0; if (fclose(f)!=0) { @@ -501,7 +498,7 @@ static dict_t *process_config(struct p_node *c) /***** Externally accessible functions */ -atom_t intern(string_t s) +atom_t intern(cstring_t s) { struct atomlist *i; @@ -519,22 +516,22 @@ atom_t intern(string_t s) return i->a; } -list_t *dict_lookup(dict_t *dict, string_t key) +list_t *dict_lookup(dict_t *dict, cstring_t key) { return dict_ilookup(dict, intern(key)); } -list_t *dict_lookup_primitive(dict_t *dict, string_t key) +list_t *dict_lookup_primitive(dict_t *dict, cstring_t key) { return dict_ilookup_primitive(dict, intern(key)); } -void dict_add(dict_t *dict, string_t key, list_t *val) +void dict_add(dict_t *dict, cstring_t key, list_t *val) { dict_iadd(dict,intern(key),val); } -string_t *dict_keys(dict_t *dict) +cstring_t *dict_keys(dict_t *dict) { atom_t *r, *j; struct entry *i; @@ -617,7 +614,7 @@ list_t *new_closure(closure_t *cl) return list_append(NULL,i); } -void add_closure(dict_t *dict, string_t name, apply_fn apply) +void add_closure(dict_t *dict, cstring_t name, apply_fn apply) { closure_t *c; c=safe_malloc(sizeof(*c),"add_closure"); @@ -628,8 +625,8 @@ void add_closure(dict_t *dict, string_t name, apply_fn apply) dict_add(dict,name,new_closure(c)); } -void *find_cl_if(dict_t *dict, string_t name, uint32_t type, - bool_t fail_if_invalid, string_t desc, struct cloc loc) +void *find_cl_if(dict_t *dict, cstring_t name, uint32_t type, + bool_t fail_if_invalid, cstring_t desc, struct cloc loc) { list_t *l; item_t *i; @@ -654,8 +651,8 @@ void *find_cl_if(dict_t *dict, string_t name, uint32_t type, } /* Convenience functions for modules reading configuration dictionaries */ -item_t *dict_find_item(dict_t *dict, string_t key, bool_t required, - string_t desc, struct cloc loc) +item_t *dict_find_item(dict_t *dict, cstring_t key, bool_t required, + cstring_t desc, struct cloc loc) { list_t *l; item_t *i; @@ -669,8 +666,8 @@ item_t *dict_find_item(dict_t *dict, string_t key, bool_t required, return i; } -string_t dict_read_string(dict_t *dict, string_t key, bool_t required, - string_t desc, struct cloc loc) +string_t dict_read_string(dict_t *dict, cstring_t key, bool_t required, + cstring_t desc, struct cloc loc) { item_t *i; string_t r; @@ -684,8 +681,8 @@ string_t dict_read_string(dict_t *dict, string_t key, bool_t required, return r; } -uint32_t dict_read_number(dict_t *dict, string_t key, bool_t required, - string_t desc, struct cloc loc, uint32_t def) +uint32_t dict_read_number(dict_t *dict, cstring_t key, bool_t required, + cstring_t desc, struct cloc loc, uint32_t def) { item_t *i; uint32_t r; @@ -699,8 +696,8 @@ uint32_t dict_read_number(dict_t *dict, string_t key, bool_t required, return r; } -bool_t dict_read_bool(dict_t *dict, string_t key, bool_t required, - string_t desc, struct cloc loc, bool_t def) +bool_t dict_read_bool(dict_t *dict, cstring_t key, bool_t required, + cstring_t desc, struct cloc loc, bool_t def) { item_t *i; bool_t r; @@ -714,96 +711,8 @@ bool_t dict_read_bool(dict_t *dict, string_t key, bool_t required, return r; } -static struct subnet string_to_subnet(item_t *i, string_t desc) -{ - struct subnet s; - uint32_t a, b, c, d, n; - uint32_t match; - - /* i is not guaranteed to be a string */ - if (i->type!=t_string) { - cfgfatal(i->loc,desc,"expecting a string (subnet specification)\n"); - } - - /* We expect strings of the form "a.b.c.d[/n]", i.e. the dots are - NOT optional. The subnet mask is optional; if missing it is assumed - to be /32. */ - match=sscanf(i->data.string,"%u.%u.%u.%u/%u", &a, &b, &c, &d, &n); - if (match<4) { - cfgfatal(i->loc,desc,"\"%s\" is not a valid " - "subnet specification\n",i->data.string); - } - if (match<5) { - n=32; - } - if (a>255 || b>255 || c>255 || d>255 || n>32) { - cfgfatal(i->loc,desc,"\"%s\": range error\n",i->data.string); - } - s.prefix=(a<<24)|(b<<16)|(c<<8)|(d); - s.mask=(~0UL << (32-n)); - s.len=n; - if (s.prefix & ~s.mask) { - cfgfatal(i->loc,desc,"\"%s\": prefix not fully contained " - "in mask\n",i->data.string); - } - return s; -} - -uint32_t string_to_ipaddr(item_t *i, string_t desc) -{ - uint32_t a, b, c, d; - uint32_t match; - - /* i is not guaranteed to be a string */ - if (i->type!=t_string) { - cfgfatal(i->loc,desc,"expecting a string (IP address)\n"); - } - - match=sscanf(i->data.string,"%u.%u.%u.%u", &a, &b, &c, &d); - if (match<4) { - cfgfatal(i->loc,desc,"\"%s\" is not a valid " - "IP address\n",i->data.string); - } - if (a>255 || b>255 || c>255 || d>255) { - cfgfatal(i->loc,desc,"\"%s\": range error\n",i->data.string); - } - return (a<<24)|(b<<16)|(c<<8)|(d); -} - -void dict_read_subnet_list(dict_t *dict, string_t key, bool_t required, - string_t desc, struct cloc loc, - struct subnet_list *sl) -{ - list_t *l, *li; - item_t *i; - uint32_t e=0; - - sl->entries=0; - sl->list=NULL; - l=dict_lookup(dict, key); - if (!l) { - if (!required) return; - cfgfatal(loc,desc,"required parameter \"%s\" not found\n",key); - } - /* Count the items in the list */ - e=list_length(l); - if (e==0) return; - sl->entries=e; - sl->list=safe_malloc(sizeof(struct subnet)*e, "dict_read_subnet_list"); - e=0; - /* Fill in the list */ - for (li=l; li; li=li->next) { - i=li->item; - if (i->type!=t_string) { - cfgfatal(loc,desc,"parameter \"%s\": all elements must " - "be strings\n",key); - } - sl->list[e++]=string_to_subnet(i,desc); - } -} - -uint32_t string_to_word(string_t s, struct cloc loc, - struct flagstr *f, string_t desc) +uint32_t string_to_word(cstring_t s, struct cloc loc, + struct flagstr *f, cstring_t desc) { struct flagstr *j; for (j=f; j->name; j++) @@ -813,7 +722,7 @@ uint32_t string_to_word(string_t s, struct cloc loc, return 0; } -uint32_t string_list_to_word(list_t *l, struct flagstr *f, string_t desc) +uint32_t string_list_to_word(list_t *l, struct flagstr *f, cstring_t desc) { list_t *i; uint32_t r=0; @@ -830,7 +739,7 @@ uint32_t string_list_to_word(list_t *l, struct flagstr *f, string_t desc) return r; } -dict_t *read_conffile(char *name) +dict_t *read_conffile(const char *name) { FILE *conffile; struct p_node *config;