X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=secnet.git;a=blobdiff_plain;f=conffile.c;h=7f0202ca7f9c034b64bc466eb58a024f01f902d1;hp=8f2d0fd48498946eca58cce1d3beb92d2179d910;hb=1fc8a4acb3ef658696038c9c4bd3c155fbc27ac3;hpb=4f5e39ecfaa49376b0a5c3a4c384e91a828c1105 diff --git a/conffile.c b/conffile.c index 8f2d0fd..7f0202c 100644 --- a/conffile.c +++ b/conffile.c @@ -1,18 +1,36 @@ /* conffile.c - process the configuration file */ +/* + * This file is part of secnet. + * See README for full list of copyright holders. + * + * secnet is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version d of the License, or + * (at your option) any later version. + * + * secnet is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with secnet; if not, see + * https://www.gnu.org/licenses/gpl.html. + */ /* #define DUMP_PARSE_TREE */ #include "secnet.h" +#include +#include #include #include #include "conffile.h" #include "conffile_internal.h" +#include "conffile.yy.h" #include "util.h" #include "ipaddr.h" -/* from modules.c */ -extern void init_builtin_modules(dict_t *dict); - static struct cloc no_loc={"none",0}; struct atomlist { @@ -35,7 +53,7 @@ struct dict { struct dict *parent; struct searchlist *search; struct entry *entries; - uint32_t size; + int32_t size; }; static struct atomlist *atoms=NULL; @@ -75,7 +93,7 @@ static void dict_iadd(dict_t *dict, atom_t key, list_t *val) if (dict_ilookup_primitive(dict, key)) { fatal("duplicate key \"%s\" in dictionary",key); } - e=safe_malloc(sizeof(*e),"dict_add"); + NEW(e); e->next=dict->entries; e->key=key; e->val=val; @@ -89,7 +107,7 @@ static dict_t *dict_new(dict_t *parent) { dict_t *d; - d=safe_malloc(sizeof(*d),"dict_new"); + NEW(d); d->parent=parent; d->search=NULL; d->entries=NULL; @@ -100,7 +118,7 @@ static dict_t *dict_new(dict_t *parent) static struct p_node *node_copy(struct p_node *n) { struct p_node *r; - r=safe_malloc(sizeof(*r),"node_copy"); + NEW(r); *r=*n; return r; } @@ -154,7 +172,7 @@ static void ptree_mangle(struct p_node *t) #ifdef DUMP_PARSE_TREE /* Convert a node type to a string, for parse tree dump */ -static string_t ntype(uint32_t type) +static const char *ntype(uint32_t type) { switch(type) { case T_STRING: return "T_STRING"; @@ -173,20 +191,20 @@ static string_t ntype(uint32_t type) return "**unknown**"; } -static void ptree_indent(uint32_t amount) +static void ptree_indent(int amount) { - uint32_t i; + int i; for (i=0; itype<10) { + if (T_IS_PRIMITIVE(n->type)) { switch(n->type) { case T_STRING: printf("T_STRING: \"%s\" (%s line %d)\n", n->data.string,n->loc.file,n->loc.line); break; @@ -197,6 +215,7 @@ static void ptree_dump(struct p_node *n, uint32_t d) default: printf("**unknown primitive type**\n"); break; } } else { + assert(d<10000); printf("%s: (%s line %d)\n",ntype(n->type),n->loc.file,n->loc.line); ptree_indent(d); printf(" |-"); ptree_dump(n->l, d+1); @@ -249,7 +268,7 @@ static item_t *new_item(enum types type, struct cloc loc) { item_t *i; - i=safe_malloc(sizeof(*i),"new_item"); + NEW(i); i->type=type; i->loc=loc; return i; @@ -466,6 +485,9 @@ static dict_t *process_config(struct p_node *c) context=root; /* Predefined keys for boolean values */ + /* "nowise" and "verily" have the advantage of being the same + length, so they line up nicely... thanks VKC and SGT (who also + point out that "mayhap" is a good "maybe" value as well) */ i=new_item(t_bool,no_loc); i->data.bool=False; false=list_append(NULL,i); @@ -478,12 +500,18 @@ static dict_t *process_config(struct p_node *c) dict_add(root,"no",false); dict_add(root,"No",false); dict_add(root,"NO",false); + dict_add(root,"nowise",false); + dict_add(root,"Nowise",false); + dict_add(root,"NOWISE",false); dict_add(root,"true",true); dict_add(root,"True",true); dict_add(root,"TRUE",true); dict_add(root,"yes",true); dict_add(root,"Yes",true); dict_add(root,"YES",true); + dict_add(root,"verily",true); + dict_add(root,"Verily",true); + dict_add(root,"VERILY",true); add_closure(root,"makelist",makelist); add_closure(root,"readfile",readfile); @@ -498,7 +526,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; @@ -508,7 +536,7 @@ atom_t intern(string_t s) if (!i) { /* Did't find it; create a new one */ - i=safe_malloc(sizeof(*i),"intern: alloc list entry"); + NEW(i); i->a=safe_strdup(s,"intern: alloc string"); i->next=atoms; atoms=i; @@ -516,26 +544,26 @@ 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; - r=safe_malloc(sizeof(*r)*(dict->size+1),"dict_keys"); + NEW_ARY(r,dict->size+1); for (i=dict->entries, j=r; i; i=i->next, j++) { *j=i->key; } @@ -551,15 +579,15 @@ list_t *list_new(void) return NULL; } -uint32_t list_length(list_t *a) +int32_t list_length(const list_t *a) { - uint32_t l=0; - list_t *i; - for (i=a; i; i=i->next) l++; + int32_t l=0; + const list_t *i; + for (i=a; i; i=i->next) { assert(l < INT_MAX); l++; } return l; } -list_t *list_copy(list_t *a) +static list_t *list_copy(list_t *a) { list_t *r, *i, *b, *l; @@ -567,7 +595,7 @@ list_t *list_copy(list_t *a) l=NULL; r=NULL; for (i=a; i; i=i->next) { - b=safe_malloc(sizeof(*b),"list_copy"); + NEW(b); if (l) l->next=b; else r=b; l=b; b->item=i->item; @@ -591,14 +619,14 @@ list_t *list_append(list_t *list, item_t *item) { list_t *l; - l=safe_malloc(sizeof(*l),"list_append"); + NEW(l); l->item=item; l->next=NULL; return list_append_list(list,l); } -item_t *list_elem(list_t *l, uint32_t index) +item_t *list_elem(list_t *l, int32_t index) { if (!l) return NULL; if (index==0) return l->item; @@ -614,30 +642,25 @@ 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"); + NEW(c); c->description=name; + c->type=CL_PURE; c->apply=apply; c->interface=NULL; 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; closure_t *cl; - l=dict_lookup(dict,name); - if (!l) { - if (!fail_if_invalid) return NULL; - cfgfatal(loc,desc,"closure \"%s\" not found\n",name); - } - i=list_elem(l,0); + i = dict_find_item(dict,name,fail_if_invalid,desc,loc); if (i->type!=t_closure) { if (!fail_if_invalid) return NULL; cfgfatal(loc,desc,"\"%s\" must be a closure\n",name); @@ -651,8 +674,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; @@ -662,12 +685,14 @@ item_t *dict_find_item(dict_t *dict, string_t key, bool_t required, if (!required) return NULL; cfgfatal(loc,desc,"required parameter \"%s\" not found\n",key); } + if(list_length(l) != 1) + cfgfatal(loc,desc,"parameter \"%s\" has wrong number of values",key); i=list_elem(l,0); 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; @@ -677,12 +702,40 @@ string_t dict_read_string(dict_t *dict, string_t key, bool_t required, if (i->type!=t_string) { cfgfatal(loc,desc,"\"%s\" must be a string\n",key); } + if (strlen(i->data.string) > INT_MAX/10) { + cfgfatal(loc,desc,"\"%s\" is unreasonably long\n",key); + } r=i->data.string; 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) +const char **dict_read_string_array(dict_t *dict, cstring_t key, + bool_t required, cstring_t desc, + struct cloc loc, const char *const *def) +{ + list_t *l; + const char **ra, **rap; + + l=dict_lookup(dict,key); + if (!l) { + if (!required) return (const char**)def; + cfgfatal(loc,desc,"required string list \"%s\" not found\n",key); + } + + int32_t ll=list_length(l); + NEW_ARY(ra, ll+1); + for (rap=ra; l; l=l->next,rap++) { + item_t *it=l->item; + if (it->type!=t_string) + cfgfatal(it->loc,desc,"\"%s\" entry must be a string\n",key); + *rap=it->data.string; + } + *rap=0; + return ra; +} + +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; @@ -692,12 +745,15 @@ uint32_t dict_read_number(dict_t *dict, string_t key, bool_t required, if (i->type!=t_number) { cfgfatal(loc,desc,"\"%s\" must be a number\n",key); } + if (i->data.number >= 0x80000000) { + cfgfatal(loc,desc,"\"%s\" must fit into a 32-bit signed integer\n",key); + } r=i->data.number; 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; @@ -711,8 +767,23 @@ bool_t dict_read_bool(dict_t *dict, string_t key, bool_t required, return r; } -uint32_t string_to_word(string_t s, struct cloc loc, - struct flagstr *f, string_t desc) +dict_t *dict_read_dict(dict_t *dict, cstring_t key, bool_t required, + cstring_t desc, struct cloc loc) +{ + item_t *i; + dict_t *r; + + i=dict_find_item(dict,key,required,desc,loc); + if (!i) return NULL; + if (i->type!=t_dict) { + cfgfatal(loc,desc,"\"%s\" must be a dictionary\n",key); + } + r=i->data.dict; + return r; +} + +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++) @@ -722,7 +793,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; @@ -739,7 +810,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;