plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

ctl.c (3781B)


      1 #include "std.h"
      2 #include "dat.h"
      3 
      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  */
     16 
     17 static char *msg[] = {
     18 	"key",
     19 	"delkey",
     20 	"debug"
     21 };
     22 
     23 static int
     24 classify(char *s)
     25 {
     26 	int i;
     27 
     28 	for(i=0; i<nelem(msg); i++)
     29 		if(strcmp(msg[i], s) == 0)
     30 			return i;
     31 	return -1;
     32 }
     33 
     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;
     42 
     43 	while(*a == ' ' || *a == '\t' || *a == '\n')
     44 		a++;
     45 
     46 	if(a[0] == '#' || a[0] == '\0')
     47 		return 0;
     48 
     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 	}
     62 
     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 		}
     89 
     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);
    102 
    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;
    111 			}
    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;
    120 				}
    121 				freeattr(kpa);
    122 			}
    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;
    133 			}
    134 			flog("adding key: %A %N", k->attr, k->privattr);
    135 			keyadd(k);
    136 			keyclose(k);
    137 		}
    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;
    151 			}
    152 		}
    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++;
    162 		}
    163 		freeattr(attr);
    164 		if(nmatch == 0){
    165 			werrstr("found no keys to delete");
    166 			return -1;
    167 		}
    168 		return 0;
    169 	case 2:	/* debug */
    170 		debug ^= 1;
    171 		flog("debug = %d", debug);
    172 		return 0;
    173 	}
    174 }