X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=conffile.c;h=e9c84d3cb4aa82fc9a49eeaea73d6f1eb8f0827b;hb=042a8da9053c205ea74ec1785c93ca4bcf4ea5e0;hp=45889ba93de36d6c27699ee96bbde39393264e09;hpb=8689b3a94c043f04e334a7b181a7250ad5940616;p=secnet.git diff --git a/conffile.c b/conffile.c index 45889ba..e9c84d3 100644 --- a/conffile.c +++ b/conffile.c @@ -12,7 +12,10 @@ #include "conffile.h" #include "conffile_internal.h" #include "util.h" -#include "modules.h" +#include "ipaddr.h" + +/* from modules.c */ +extern void init_builtin_modules(dict_t *dict); static struct cloc no_loc={"none",0}; @@ -379,6 +382,36 @@ static list_t *makelist(closure_t *self, struct cloc loc, return r; } +/* Take a list consisting of a closure and some other things. Apply the + closure to the other things, and return the resulting list */ +static list_t *map(closure_t *self, struct cloc loc, dict_t *context, + list_t *args) +{ + list_t *r=NULL, *al; + item_t *ci; + closure_t *cl; + list_t se; + + ci=list_elem(args,0); + if (ci && ci->type==t_closure) { + cl=ci->data.closure; + if (!cl->apply) { + cfgfatal(loc,"map","closure cannot be applied\n"); + } + for (al=args->next; al; al=al->next) { + /* Construct a single-element list */ + se.next=NULL; + se.item=al->item; + /* Invoke the closure, append its result to the output */ + r=list_append_list(r,cl->apply(cl,loc,context,&se)); + } + } else { + cfgfatal(loc,"map","you must supply a closure as the " + "first argument\n"); + } + return r; +} + /* Read a file and turn it into a string */ static list_t *readfile(closure_t *self, struct cloc loc, dict_t *context, list_t *args) @@ -457,6 +490,7 @@ static dict_t *process_config(struct p_node *c) add_closure(root,"makelist",makelist); add_closure(root,"readfile",readfile); + add_closure(root,"map",map); init_builtin_modules(root); @@ -520,10 +554,36 @@ list_t *list_new(void) return NULL; } +uint32_t list_length(list_t *a) +{ + uint32_t l=0; + list_t *i; + for (i=a; i; i=i->next) l++; + return l; +} + +list_t *list_copy(list_t *a) +{ + list_t *r, *i, *b, *l; + + if (!a) return NULL; + l=NULL; + r=NULL; + for (i=a; i; i=i->next) { + b=safe_malloc(sizeof(*b),"list_copy"); + if (l) l->next=b; else r=b; + l=b; + b->item=i->item; + b->next=NULL; + } + return r; +} + list_t *list_append_list(list_t *a, list_t *b) { list_t *i; + b=list_copy(b); if (!a) return b; for (i=a; i->next; i=i->next); i->next=b; @@ -681,6 +741,7 @@ static struct subnet string_to_subnet(item_t *i, string_t desc) } 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); @@ -725,7 +786,7 @@ void dict_read_subnet_list(dict_t *dict, string_t key, bool_t required, cfgfatal(loc,desc,"required parameter \"%s\" not found\n",key); } /* Count the items in the list */ - for (li=l; li; li=li->next) e++; + e=list_length(l); if (e==0) return; sl->entries=e; sl->list=safe_malloc(sizeof(struct subnet)*e, "dict_read_subnet_list"); @@ -741,6 +802,34 @@ void dict_read_subnet_list(dict_t *dict, string_t key, bool_t required, } } +uint32_t string_to_word(string_t s, struct cloc loc, + struct flagstr *f, string_t desc) +{ + struct flagstr *j; + for (j=f; j->name; j++) + if (strcmp(s,j->name)==0) + return j->value; + cfgfatal(loc,desc,"option \"%s\" not known\n",s); + return 0; +} + +uint32_t string_list_to_word(list_t *l, struct flagstr *f, string_t desc) +{ + list_t *i; + uint32_t r=0; + struct flagstr *j; + + for (i=l; i; i=i->next) { + if (i->item->type!=t_string) { + cfgfatal(i->item->loc,desc,"all elements of list must be " + "strings\n"); + } + for (j=f; j->name; j++) + r|=string_to_word(i->item->data.string,i->item->loc,f,desc); + } + return r; +} + dict_t *read_conffile(char *name) { FILE *conffile;