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, **l, **lpriv, **lprotos, *pa, *priv, *protos;
40 Key *k;
41 Proto *proto;
43 if(a[0] == '#' || a[0] == '\0')
44 return 0;
46 /*
47 * it would be nice to emit a warning of some sort here.
48 * we ignore all but the first line of the write. this helps
49 * both with things like "echo delkey >/mnt/factotum/ctl"
50 * and writes that (incorrectly) contain multiple key lines.
51 */
52 if(p = strchr(a, '\n')){
53 if(p[1] != '\0'){
54 werrstr("multiline write not allowed");
55 return -1;
56 }
57 *p = '\0';
58 }
60 if((p = strchr(a, ' ')) == nil)
61 p = "";
62 else
63 *p++ = '\0';
64 switch(classify(a)){
65 default:
66 werrstr("unknown verb");
67 return -1;
68 case 0: /* key */
69 attr = parseattr(p);
70 /* separate out proto= attributes */
71 lprotos = &protos;
72 for(l=&attr; (*l); ){
73 if(strcmp((*l)->name, "proto") == 0){
74 *lprotos = *l;
75 lprotos = &(*l)->next;
76 *l = (*l)->next;
77 }else
78 l = &(*l)->next;
79 }
80 *lprotos = nil;
81 if(protos == nil){
82 werrstr("key without protos");
83 freeattr(attr);
84 return -1;
85 }
87 /* separate out private attributes */
88 lpriv = &priv;
89 for(l=&attr; (*l); ){
90 if((*l)->name[0] == '!'){
91 *lpriv = *l;
92 lpriv = &(*l)->next;
93 *l = (*l)->next;
94 }else
95 l = &(*l)->next;
96 }
97 *lpriv = nil;
99 /* add keys */
100 ret = 0;
101 for(pa=protos; pa; pa=pa->next){
102 if((proto = protolookup(pa->val)) == nil){
103 werrstr("unknown proto %s", pa->val);
104 ret = -1;
105 continue;
107 if(proto->checkkey == nil){
108 werrstr("proto %s does not accept keys", proto->name);
109 ret = -1;
110 continue;
112 k = emalloc(sizeof(Key));
113 k->attr = mkattr(AttrNameval, "proto", proto->name, copyattr(attr));
114 k->privattr = copyattr(priv);
115 k->ref = 1;
116 k->proto = proto;
117 if((*proto->checkkey)(k) < 0){
118 ret = -1;
119 keyclose(k);
120 continue;
122 keyadd(k);
123 keyclose(k);
125 freeattr(attr);
126 freeattr(priv);
127 freeattr(protos);
128 return ret;
129 case 1: /* delkey */
130 nmatch = 0;
131 attr = parseattr(p);
132 for(pa=attr; pa; pa=pa->next){
133 if(pa->type != AttrQuery && pa->name[0]=='!'){
134 werrstr("only !private? patterns are allowed for private fields");
135 freeattr(attr);
136 return -1;
139 for(i=0; i<ring.nkey; ){
140 if(matchattr(attr, ring.key[i]->attr, ring.key[i]->privattr)){
141 nmatch++;
142 keyclose(ring.key[i]);
143 ring.nkey--;
144 memmove(&ring.key[i], &ring.key[i+1], (ring.nkey-i)*sizeof(ring.key[0]));
145 }else
146 i++;
148 freeattr(attr);
149 if(nmatch == 0){
150 werrstr("found no keys to delete");
151 return -1;
153 return 0;
154 case 2: /* debug */
155 debug ^= 1;
156 return 0;