218 lines
3.3 KiB
C
218 lines
3.3 KiB
C
|
|
#include "std.h"
|
||
|
|
#include "dat.h"
|
||
|
|
|
||
|
|
Ring ring;
|
||
|
|
|
||
|
|
Key*
|
||
|
|
keyiterate(int skip, char *fmt, ...)
|
||
|
|
{
|
||
|
|
int i;
|
||
|
|
Attr *a;
|
||
|
|
Key *k;
|
||
|
|
va_list arg;
|
||
|
|
|
||
|
|
va_start(arg, fmt);
|
||
|
|
a = parseattrfmtv(fmt, arg);
|
||
|
|
va_end(arg);
|
||
|
|
|
||
|
|
for(i=0; i<ring.nkey; i++){
|
||
|
|
k = ring.key[i];
|
||
|
|
if(matchattr(a, k->attr, k->privattr)){
|
||
|
|
if(skip-- > 0)
|
||
|
|
continue;
|
||
|
|
k->ref++;
|
||
|
|
freeattr(a);
|
||
|
|
return k;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
freeattr(a);
|
||
|
|
werrstr("no key found");
|
||
|
|
return nil;
|
||
|
|
}
|
||
|
|
|
||
|
|
Key*
|
||
|
|
keylookup(char *fmt, ...)
|
||
|
|
{
|
||
|
|
int i;
|
||
|
|
Attr *a;
|
||
|
|
Key *k;
|
||
|
|
va_list arg;
|
||
|
|
|
||
|
|
va_start(arg, fmt);
|
||
|
|
a = parseattrfmtv(fmt, arg);
|
||
|
|
va_end(arg);
|
||
|
|
|
||
|
|
for(i=0; i<ring.nkey; i++){
|
||
|
|
k = ring.key[i];
|
||
|
|
if(matchattr(a, k->attr, k->privattr)){
|
||
|
|
k->ref++;
|
||
|
|
freeattr(a);
|
||
|
|
return k;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
freeattr(a);
|
||
|
|
werrstr("no key found");
|
||
|
|
return nil;
|
||
|
|
}
|
||
|
|
|
||
|
|
Key*
|
||
|
|
keyfetch(Conv *c, char *fmt, ...)
|
||
|
|
{
|
||
|
|
int i, tag;
|
||
|
|
Attr *a;
|
||
|
|
Key *k;
|
||
|
|
va_list arg;
|
||
|
|
|
||
|
|
va_start(arg, fmt);
|
||
|
|
a = parseattrfmtv(fmt, arg);
|
||
|
|
va_end(arg);
|
||
|
|
|
||
|
|
tag = 0;
|
||
|
|
|
||
|
|
for(i=0; i<ring.nkey; i++){
|
||
|
|
k = ring.key[i];
|
||
|
|
if(tag < k->tag)
|
||
|
|
tag = k->tag;
|
||
|
|
if(matchattr(a, k->attr, k->privattr)){
|
||
|
|
k->ref++;
|
||
|
|
if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){
|
||
|
|
k->ref--;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
freeattr(a);
|
||
|
|
return k;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if(needkey(c, a) < 0)
|
||
|
|
convneedkey(c, a);
|
||
|
|
|
||
|
|
for(i=0; i<ring.nkey; i++){
|
||
|
|
k = ring.key[i];
|
||
|
|
if(k->tag <= tag)
|
||
|
|
continue;
|
||
|
|
if(matchattr(a, k->attr, k->privattr)){
|
||
|
|
k->ref++;
|
||
|
|
if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){
|
||
|
|
k->ref--;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
freeattr(a);
|
||
|
|
return k;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
freeattr(a);
|
||
|
|
werrstr("no key found");
|
||
|
|
return nil;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int taggen;
|
||
|
|
|
||
|
|
void
|
||
|
|
keyadd(Key *k)
|
||
|
|
{
|
||
|
|
int i;
|
||
|
|
|
||
|
|
k->ref++;
|
||
|
|
k->tag = ++taggen;
|
||
|
|
for(i=0; i<ring.nkey; i++){
|
||
|
|
if(matchattr(k->attr, ring.key[i]->attr, nil)
|
||
|
|
&& matchattr(ring.key[i]->attr, k->attr, nil)){
|
||
|
|
keyclose(ring.key[i]);
|
||
|
|
ring.key[i] = k;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
ring.key = erealloc(ring.key, (ring.nkey+1)*sizeof(ring.key[0]));
|
||
|
|
ring.key[ring.nkey++] = k;
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
keyclose(Key *k)
|
||
|
|
{
|
||
|
|
if(k == nil)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if(--k->ref > 0)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if(k->proto->closekey)
|
||
|
|
(*k->proto->closekey)(k);
|
||
|
|
|
||
|
|
freeattr(k->attr);
|
||
|
|
freeattr(k->privattr);
|
||
|
|
free(k);
|
||
|
|
}
|
||
|
|
|
||
|
|
Key*
|
||
|
|
keyreplace(Conv *c, Key *k, char *fmt, ...)
|
||
|
|
{
|
||
|
|
Key *kk;
|
||
|
|
char *msg;
|
||
|
|
Attr *a, *b, *bp;
|
||
|
|
va_list arg;
|
||
|
|
|
||
|
|
va_start(arg, fmt);
|
||
|
|
msg = vsmprint(fmt, arg);
|
||
|
|
if(msg == nil)
|
||
|
|
sysfatal("out of memory");
|
||
|
|
va_end(arg);
|
||
|
|
|
||
|
|
/* replace prompted values with prompts */
|
||
|
|
a = copyattr(k->attr);
|
||
|
|
bp = parseattr(k->proto->keyprompt);
|
||
|
|
for(b=bp; b; b=b->next){
|
||
|
|
a = delattr(a, b->name);
|
||
|
|
a = addattr(a, "%q?", b->name);
|
||
|
|
}
|
||
|
|
freeattr(bp);
|
||
|
|
|
||
|
|
if(badkey(c, k, msg, a) < 0)
|
||
|
|
convbadkey(c, k, msg, a);
|
||
|
|
kk = keylookup("%A", a);
|
||
|
|
freeattr(a);
|
||
|
|
keyclose(k);
|
||
|
|
if(kk == k){
|
||
|
|
keyclose(kk);
|
||
|
|
werrstr("%s", msg);
|
||
|
|
return nil;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(strfindattr(kk->attr, "confirm")){
|
||
|
|
if(confirmkey(c, kk) != 1){
|
||
|
|
werrstr("key use not confirmed");
|
||
|
|
keyclose(kk);
|
||
|
|
return nil;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return kk;
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
keyevict(Conv *c, Key *k, char *fmt, ...)
|
||
|
|
{
|
||
|
|
char *msg;
|
||
|
|
Attr *a, *b, *bp;
|
||
|
|
va_list arg;
|
||
|
|
|
||
|
|
va_start(arg, fmt);
|
||
|
|
msg = vsmprint(fmt, arg);
|
||
|
|
if(msg == nil)
|
||
|
|
sysfatal("out of memory");
|
||
|
|
va_end(arg);
|
||
|
|
|
||
|
|
/* replace prompted values with prompts */
|
||
|
|
a = copyattr(k->attr);
|
||
|
|
bp = parseattr(k->proto->keyprompt);
|
||
|
|
for(b=bp; b; b=b->next){
|
||
|
|
a = delattr(a, b->name);
|
||
|
|
a = addattr(a, "%q?", b->name);
|
||
|
|
}
|
||
|
|
freeattr(bp);
|
||
|
|
|
||
|
|
if(badkey(c, k, msg, nil) < 0)
|
||
|
|
convbadkey(c, k, msg, nil);
|
||
|
|
keyclose(k);
|
||
|
|
}
|