#include "std.h" #include "dat.h" /* * key attr=val... - add a key * the attr=val pairs are protocol-specific. * for example, both of these are valid: * key p9sk1 gre cs.bell-labs.com mysecret * key p9sk1 gre cs.bell-labs.com 11223344556677 fmt=des7hex * delkey ... - delete a key * if given, the attr=val pairs are used to narrow the search * [maybe should require a password?] * * debug - toggle debugging */ static char *msg[] = { "key", "delkey", "debug" }; static int classify(char *s) { int i; for(i=0; i/mnt/factotum/ctl" * and writes that (incorrectly) contain multiple key lines. */ if(p = strchr(a, '\n')){ if(p[1] != '\0'){ werrstr("multiline write not allowed"); return -1; } *p = '\0'; } if((p = strchr(a, ' ')) == nil) p = ""; else *p++ = '\0'; switch(classify(a)){ default: werrstr("unknown verb %s", a); return -1; case 0: /* key */ attr = parseattr(p); /* separate out proto= attributes */ lprotos = &protos; for(l=&attr; (*l); ){ if(strcmp((*l)->name, "proto") == 0){ *lprotos = *l; lprotos = &(*l)->next; *l = (*l)->next; }else l = &(*l)->next; } *lprotos = nil; if(protos == nil){ werrstr("key without protos"); freeattr(attr); return -1; } /* separate out private attributes */ lpriv = &priv; for(l=&attr; (*l); ){ if((*l)->name[0] == '!'){ *lpriv = *l; lpriv = &(*l)->next; *l = (*l)->next; }else l = &(*l)->next; } *lpriv = nil; flog("addkey %A %A %N", protos, attr, priv); /* add keys */ ret = 0; for(pa=protos; pa; pa=pa->next){ if((proto = protolookup(pa->val)) == nil){ werrstr("unknown proto %s", pa->val); flog("addkey: %r"); ret = -1; continue; } if(proto->keyprompt){ kpa = parseattr(proto->keyprompt); if(!matchattr(kpa, attr, priv)){ freeattr(kpa); werrstr("missing attributes -- want %s", proto->keyprompt); flog("addkey %s: %r", proto->name); ret = -1; continue; } freeattr(kpa); } k = emalloc(sizeof(Key)); k->attr = mkattr(AttrNameval, "proto", proto->name, copyattr(attr)); k->privattr = copyattr(priv); k->ref = 1; k->proto = proto; if(proto->checkkey && (*proto->checkkey)(k) < 0){ flog("addkey %s: %r", proto->name); ret = -1; keyclose(k); continue; } flog("adding key: %A %N", k->attr, k->privattr); keyadd(k); keyclose(k); } freeattr(attr); freeattr(priv); freeattr(protos); return ret; case 1: /* delkey */ nmatch = 0; attr = parseattr(p); flog("delkey %A", attr); for(pa=attr; pa; pa=pa->next){ if(pa->type != AttrQuery && pa->name[0]=='!'){ werrstr("only !private? patterns are allowed for private fields"); freeattr(attr); return -1; } } for(i=0; iattr, ring.key[i]->privattr)){ nmatch++; flog("deleting %A %N", ring.key[i]->attr, ring.key[i]->privattr); keyclose(ring.key[i]); ring.nkey--; memmove(&ring.key[i], &ring.key[i+1], (ring.nkey-i)*sizeof(ring.key[0])); }else i++; } freeattr(attr); if(nmatch == 0){ werrstr("found no keys to delete"); return -1; } return 0; case 2: /* debug */ debug ^= 1; flog("debug = %d", debug); return 0; } }