Blob


1 #include "std.h"
2 #include "dat.h"
4 /*
5 * key attr=val... - add a key
6 * the attr=val pairs are protocol-specific.
7 * for example, both of these are valid:
8 * key p9sk1 gre cs.bell-labs.com mysecret
9 * key p9sk1 gre cs.bell-labs.com 11223344556677 fmt=des7hex
10 * delkey ... - delete a key
11 * if given, the attr=val pairs are used to narrow the search
12 * [maybe should require a password?]
13 *
14 * debug - toggle debugging
15 */
17 static char *msg[] = {
18 "key",
19 "delkey",
20 "debug"
21 };
23 static int
24 classify(char *s)
25 {
26 int i;
28 for(i=0; i<nelem(msg); i++)
29 if(strcmp(msg[i], s) == 0)
30 return i;
31 return -1;
32 }
34 int
35 ctlwrite(char *a)
36 {
37 char *p;
38 int i, nmatch, ret;
39 Attr *attr, *kpa, **l, **lpriv, **lprotos, *pa, *priv, *protos;
40 Key *k;
41 Proto *proto;
43 while(*a == ' ' || *a == '\t' || *a == '\n')
44 a++;
46 if(a[0] == '#' || a[0] == '\0')
47 return 0;
49 /*
50 * it would be nice to emit a warning of some sort here.
51 * we ignore all but the first line of the write. this helps
52 * both with things like "echo delkey >/mnt/factotum/ctl"
53 * and writes that (incorrectly) contain multiple key lines.
54 */
55 if(p = strchr(a, '\n')){
56 if(p[1] != '\0'){
57 werrstr("multiline write not allowed");
58 return -1;
59 }
60 *p = '\0';
61 }
63 if((p = strchr(a, ' ')) == nil)
64 p = "";
65 else
66 *p++ = '\0';
67 switch(classify(a)){
68 default:
69 werrstr("unknown verb %s", a);
70 return -1;
71 case 0: /* key */
72 attr = parseattr(p);
73 /* separate out proto= attributes */
74 lprotos = &protos;
75 for(l=&attr; (*l); ){
76 if(strcmp((*l)->name, "proto") == 0){
77 *lprotos = *l;
78 lprotos = &(*l)->next;
79 *l = (*l)->next;
80 }else
81 l = &(*l)->next;
82 }
83 *lprotos = nil;
84 if(protos == nil){
85 werrstr("key without protos");
86 freeattr(attr);
87 return -1;
88 }
90 /* separate out private attributes */
91 lpriv = &priv;
92 for(l=&attr; (*l); ){
93 if((*l)->name[0] == '!'){
94 *lpriv = *l;
95 lpriv = &(*l)->next;
96 *l = (*l)->next;
97 }else
98 l = &(*l)->next;
99 }
100 *lpriv = nil;
101 flog("addkey %A %A %N", protos, attr, priv);
103 /* add keys */
104 ret = 0;
105 for(pa=protos; pa; pa=pa->next){
106 if((proto = protolookup(pa->val)) == nil){
107 werrstr("unknown proto %s", pa->val);
108 flog("addkey: %r");
109 ret = -1;
110 continue;
112 if(proto->keyprompt){
113 kpa = parseattr(proto->keyprompt);
114 if(!matchattr(kpa, attr, priv)){
115 freeattr(kpa);
116 werrstr("missing attributes -- want %s", proto->keyprompt);
117 flog("addkey %s: %r", proto->name);
118 ret = -1;
119 continue;
121 freeattr(kpa);
123 k = emalloc(sizeof(Key));
124 k->attr = mkattr(AttrNameval, "proto", proto->name, copyattr(attr));
125 k->privattr = copyattr(priv);
126 k->ref = 1;
127 k->proto = proto;
128 if(proto->checkkey && (*proto->checkkey)(k) < 0){
129 flog("addkey %s: %r", proto->name);
130 ret = -1;
131 keyclose(k);
132 continue;
134 flog("adding key: %A %N", k->attr, k->privattr);
135 keyadd(k);
136 keyclose(k);
138 freeattr(attr);
139 freeattr(priv);
140 freeattr(protos);
141 return ret;
142 case 1: /* delkey */
143 nmatch = 0;
144 attr = parseattr(p);
145 flog("delkey %A", attr);
146 for(pa=attr; pa; pa=pa->next){
147 if(pa->type != AttrQuery && pa->name[0]=='!'){
148 werrstr("only !private? patterns are allowed for private fields");
149 freeattr(attr);
150 return -1;
153 for(i=0; i<ring.nkey; ){
154 if(matchattr(attr, ring.key[i]->attr, ring.key[i]->privattr)){
155 nmatch++;
156 flog("deleting %A %N", ring.key[i]->attr, ring.key[i]->privattr);
157 keyclose(ring.key[i]);
158 ring.nkey--;
159 memmove(&ring.key[i], &ring.key[i+1], (ring.nkey-i)*sizeof(ring.key[0]));
160 }else
161 i++;
163 freeattr(attr);
164 if(nmatch == 0){
165 werrstr("found no keys to delete");
166 return -1;
168 return 0;
169 case 2: /* debug */
170 debug ^= 1;
171 flog("debug = %d", debug);
172 return 0;