plan9port

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

key.c (3469B)


      1 #include "std.h"
      2 #include "dat.h"
      3 
      4 Ring ring;
      5 
      6 Key*
      7 keyiterate(int skip, char *fmt, ...)
      8 {
      9 	int i;
     10 	Attr *a;
     11 	Key *k;
     12 	va_list arg;
     13 
     14 	va_start(arg, fmt);
     15 	a = parseattrfmtv(fmt, arg);
     16 	va_end(arg);
     17 
     18 	for(i=0; i<ring.nkey; i++){
     19 		k = ring.key[i];
     20 		if(matchattr(a, k->attr, k->privattr)){
     21 			if(skip-- > 0)
     22 				continue;
     23 			k->ref++;
     24 			freeattr(a);
     25 			return k;
     26 		}
     27 	}
     28 	freeattr(a);
     29 	werrstr("no key found");
     30 	return nil;
     31 }
     32 
     33 Key*
     34 keylookup(char *fmt, ...)
     35 {
     36 	int i;
     37 	Attr *a;
     38 	Key *k;
     39 	va_list arg;
     40 
     41 	va_start(arg, fmt);
     42 	a = parseattrfmtv(fmt, arg);
     43 	va_end(arg);
     44 
     45 	for(i=0; i<ring.nkey; i++){
     46 		k = ring.key[i];
     47 		if(matchattr(a, k->attr, k->privattr)){
     48 			k->ref++;
     49 			freeattr(a);
     50 			return k;
     51 		}
     52 	}
     53 	freeattr(a);
     54 	werrstr("no key found");
     55 	return nil;
     56 }
     57 
     58 Key*
     59 keyfetch(Conv *c, char *fmt, ...)
     60 {
     61 	int i, tag;
     62 	Attr *a;
     63 	Key *k;
     64 	va_list arg;
     65 
     66 	va_start(arg, fmt);
     67 	a = parseattrfmtv(fmt, arg);
     68 	va_end(arg);
     69 
     70 	flog("keyfetch %A", a);
     71 	tag = 0;
     72 
     73 	for(i=0; i<ring.nkey; i++){
     74 		k = ring.key[i];
     75 		if(tag < k->tag)
     76 			tag = k->tag;
     77 		if(matchattr(a, k->attr, k->privattr)){
     78 			k->ref++;
     79 			if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){
     80 				k->ref--;
     81 				continue;
     82 			}
     83 			freeattr(a);
     84 			flog("using key %A %N", k->attr, k->privattr);
     85 			return k;
     86 		}
     87 	}
     88 
     89 	if(needkey(c, a) < 0)
     90 		convneedkey(c, a);
     91 
     92 	for(i=0; i<ring.nkey; i++){
     93 		k = ring.key[i];
     94 		if(k->tag <= tag)
     95 			continue;
     96 		if(matchattr(a, k->attr, k->privattr)){
     97 			k->ref++;
     98 			if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){
     99 				k->ref--;
    100 				continue;
    101 			}
    102 			freeattr(a);
    103 			return k;
    104 		}
    105 	}
    106 	freeattr(a);
    107 	werrstr("no key found");
    108 	return nil;
    109 }
    110 
    111 static int taggen;
    112 
    113 void
    114 keyadd(Key *k)
    115 {
    116 	int i;
    117 
    118 	k->ref++;
    119 	k->tag = ++taggen;
    120 	for(i=0; i<ring.nkey; i++){
    121 		if(matchattr(k->attr, ring.key[i]->attr, nil)
    122 		&& matchattr(ring.key[i]->attr, k->attr, nil)){
    123 			keyclose(ring.key[i]);
    124 			ring.key[i] = k;
    125 			return;
    126 		}
    127 	}
    128 
    129 	ring.key = erealloc(ring.key, (ring.nkey+1)*sizeof(ring.key[0]));
    130 	ring.key[ring.nkey++] = k;
    131 }
    132 
    133 void
    134 keyclose(Key *k)
    135 {
    136 	if(k == nil)
    137 		return;
    138 
    139 	if(--k->ref > 0)
    140 		return;
    141 
    142 	if(k->proto->closekey)
    143 		(*k->proto->closekey)(k);
    144 
    145 	freeattr(k->attr);
    146 	freeattr(k->privattr);
    147 	free(k);
    148 }
    149 
    150 Key*
    151 keyreplace(Conv *c, Key *k, char *fmt, ...)
    152 {
    153 	Key *kk;
    154 	char *msg;
    155 	Attr *a, *b, *bp;
    156 	va_list arg;
    157 
    158 	va_start(arg, fmt);
    159 	msg = vsmprint(fmt, arg);
    160 	if(msg == nil)
    161 		sysfatal("out of memory");
    162 	va_end(arg);
    163 
    164 	/* replace prompted values with prompts */
    165 	a = copyattr(k->attr);
    166 	bp = parseattr(k->proto->keyprompt);
    167 	for(b=bp; b; b=b->next){
    168 		a = delattr(a, b->name);
    169 		a = addattr(a, "%q?", b->name);
    170 	}
    171 	freeattr(bp);
    172 
    173 	if(badkey(c, k, msg, a) < 0)
    174 		convbadkey(c, k, msg, a);
    175 	kk = keylookup("%A", a);
    176 	freeattr(a);
    177 	keyclose(k);
    178 	if(kk == k){
    179 		keyclose(kk);
    180 		werrstr("%s", msg);
    181 		return nil;
    182 	}
    183 
    184 	if(strfindattr(kk->attr, "confirm")){
    185 		if(confirmkey(c, kk) != 1){
    186 			werrstr("key use not confirmed");
    187 			keyclose(kk);
    188 			return nil;
    189 		}
    190 	}
    191 	return kk;
    192 }
    193 
    194 void
    195 keyevict(Conv *c, Key *k, char *fmt, ...)
    196 {
    197 	char *msg;
    198 	Attr *a, *b, *bp;
    199 	va_list arg;
    200 
    201 	va_start(arg, fmt);
    202 	msg = vsmprint(fmt, arg);
    203 	if(msg == nil)
    204 		sysfatal("out of memory");
    205 	va_end(arg);
    206 
    207 	/* replace prompted values with prompts */
    208 	a = copyattr(k->attr);
    209 	bp = parseattr(k->proto->keyprompt);
    210 	for(b=bp; b; b=b->next){
    211 		a = delattr(a, b->name);
    212 		a = addattr(a, "%q?", b->name);
    213 	}
    214 	freeattr(bp);
    215 
    216 	if(badkey(c, k, msg, nil) < 0)
    217 		convbadkey(c, k, msg, nil);
    218 	keyclose(k);
    219 }