diff options
Diffstat (limited to 'src/cmd/auth/factotum/attr.c')
-rw-r--r-- | src/cmd/auth/factotum/attr.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/src/cmd/auth/factotum/attr.c b/src/cmd/auth/factotum/attr.c new file mode 100644 index 00000000..2f2511b9 --- /dev/null +++ b/src/cmd/auth/factotum/attr.c @@ -0,0 +1,231 @@ +#include "std.h" +#include "dat.h" + +Attr* +addattr(Attr *a, char *fmt, ...) +{ + char buf[8192]; + va_list arg; + Attr *b; + + va_start(arg, fmt); + vseprint(buf, buf+sizeof buf, fmt, arg); + va_end(arg); + b = _parseattr(buf); + a = addattrs(a, b); + setmalloctag(a, getcallerpc(&a)); + _freeattr(b); + return a; +} + +/* + * add attributes in list b to list a. If any attributes are in + * both lists, replace those in a by those in b. + */ +Attr* +addattrs(Attr *a, Attr *b) +{ + int found; + Attr **l, *aa; + + for(; b; b=b->next){ + switch(b->type){ + case AttrNameval: + for(l=&a; *l; ){ + if(strcmp((*l)->name, b->name) != 0){ + l=&(*l)->next; + continue; + } + aa = *l; + *l = aa->next; + aa->next = nil; + freeattr(aa); + } + *l = mkattr(AttrNameval, b->name, b->val, nil); + break; + case AttrQuery: + found = 0; + for(l=&a; *l; l=&(*l)->next) + if((*l)->type==AttrNameval && strcmp((*l)->name, b->name) == 0) + found++; + if(!found) + *l = mkattr(AttrQuery, b->name, b->val, nil); + break; + } + } + return a; +} + +void +setmalloctaghere(void *v) +{ + setmalloctag(v, getcallerpc(&v)); +} + +Attr* +sortattr(Attr *a) +{ + int i; + Attr *anext, *a0, *a1, **l; + + if(a == nil || a->next == nil) + return a; + + /* cut list in halves */ + a0 = nil; + a1 = nil; + i = 0; + for(; a; a=anext){ + anext = a->next; + if(i++%2){ + a->next = a0; + a0 = a; + }else{ + a->next = a1; + a1 = a; + } + } + + /* sort */ + a0 = sortattr(a0); + a1 = sortattr(a1); + + /* merge */ + l = &a; + while(a0 || a1){ + if(a1==nil){ + anext = a0; + a0 = a0->next; + }else if(a0==nil){ + anext = a1; + a1 = a1->next; + }else if(strcmp(a0->name, a1->name) < 0){ + anext = a0; + a0 = a0->next; + }else{ + anext = a1; + a1 = a1->next; + } + *l = anext; + l = &(*l)->next; + } + *l = nil; + return a; +} + +int +attrnamefmt(Fmt *fmt) +{ + char *b, buf[8192], *ebuf; + Attr *a; + + ebuf = buf+sizeof buf; + b = buf; + strcpy(buf, " "); + for(a=va_arg(fmt->args, Attr*); a; a=a->next){ + if(a->name == nil) + continue; + b = seprint(b, ebuf, " %q?", a->name); + } + return fmtstrcpy(fmt, buf+1); +} + +/* +static int +hasqueries(Attr *a) +{ + for(; a; a=a->next) + if(a->type == AttrQuery) + return 1; + return 0; +} +*/ + +char *ignored[] = { + "role", + "disabled", +}; + +static int +ignoreattr(char *s) +{ + int i; + + for(i=0; i<nelem(ignored); i++) + if(strcmp(ignored[i], s)==0) + return 1; + return 0; +} + +static int +hasname(Attr *a0, Attr *a1, char *name) +{ + return _findattr(a0, name) || _findattr(a1, name); +} + +static int +hasnameval(Attr *a0, Attr *a1, char *name, char *val) +{ + Attr *a; + + for(a=_findattr(a0, name); a; a=_findattr(a->next, name)) + if(strcmp(a->val, val) == 0) + return 1; + for(a=_findattr(a1, name); a; a=_findattr(a->next, name)) + if(strcmp(a->val, val) == 0) + return 1; + return 0; +} + +int +matchattr(Attr *pat, Attr *a0, Attr *a1) +{ + int type; + + for(; pat; pat=pat->next){ + type = pat->type; + if(ignoreattr(pat->name)) + type = AttrDefault; + switch(type){ + case AttrQuery: /* name=something be present */ + if(!hasname(a0, a1, pat->name)) + return 0; + break; + case AttrNameval: /* name=val must be present */ + if(!hasnameval(a0, a1, pat->name, pat->val)) + return 0; + break; + case AttrDefault: /* name=val must be present if name=anything is present */ + if(hasname(a0, a1, pat->name) && !hasnameval(a0, a1, pat->name, pat->val)) + return 0; + break; + } + } + return 1; +} + +Attr* +parseattrfmtv(char *fmt, va_list arg) +{ + char *s; + Attr *a; + + s = vsmprint(fmt, arg); + if(s == nil) + sysfatal("vsmprint: out of memory"); + a = parseattr(s); + free(s); + return a; +} + +Attr* +parseattrfmt(char *fmt, ...) +{ + va_list arg; + Attr *a; + + va_start(arg, fmt); + a = parseattrfmtv(fmt, arg); + va_end(arg); + return a; +} |