#include "std.h"
#include "dat.h"

/*
 *	key attr=val... - add a key
 *		the attr=val pairs are protocol-specific.
 *		for example, both of these are valid:
 *			key p9sk1 gre cs.bell-labs.com mysecret
 *			key p9sk1 gre cs.bell-labs.com 11223344556677 fmt=des7hex
 *	delkey ... - delete a key
 *		if given, the attr=val pairs are used to narrow the search
 *		[maybe should require a password?]
 *
 *	debug - toggle debugging
 */

static char *msg[] = {
	"key",
	"delkey",
	"debug",
};

static int
classify(char *s)
{
	int i;

	for(i=0; i<nelem(msg); i++)
		if(strcmp(msg[i], s) == 0)
			return i;
	return -1;
}

int
ctlwrite(char *a)
{
	char *p;
	int i, nmatch, ret;
	Attr *attr, **l, **lpriv, **lprotos, *pa, *priv, *protos;
	Key *k;
	Proto *proto;

	if(a[0] == '#' || a[0] == '\0')
		return 0;

	/*
	 * it would be nice to emit a warning of some sort here.
	 * we ignore all but the first line of the write.  this helps
	 * both with things like "echo delkey >/mnt/factotum/ctl"
	 * and writes that (incorrectly) contain multiple key lines.
	 */
	if(p = strchr(a, '\n')){
		if(p[1] != '\0'){
			werrstr("multiline write not allowed");
			return -1;
		}
		*p = '\0';
	}

	if((p = strchr(a, ' ')) == nil)
		p = "";
	else
		*p++ = '\0';
	switch(classify(a)){
	default:
		werrstr("unknown verb");
		return -1;
	case 0:	/* key */
		attr = parseattr(p);
		/* separate out proto= attributes */
		lprotos = &protos;
		for(l=&attr; (*l); ){
			if(strcmp((*l)->name, "proto") == 0){
				*lprotos = *l;
				lprotos = &(*l)->next;
				*l = (*l)->next;
			}else
				l = &(*l)->next;
		}
		*lprotos = nil;
		if(protos == nil){
			werrstr("key without protos");
			freeattr(attr);
			return -1;
		}

		/* separate out private attributes */
		lpriv = &priv;
		for(l=&attr; (*l); ){
			if((*l)->name[0] == '!'){
				*lpriv = *l;
				lpriv = &(*l)->next;
				*l = (*l)->next;
			}else
				l = &(*l)->next;
		}
		*lpriv = nil;

		/* add keys */
		ret = 0;
		for(pa=protos; pa; pa=pa->next){
			if((proto = protolookup(pa->val)) == nil){
				werrstr("unknown proto %s", pa->val);
				ret = -1;
				continue;
			}
			if(proto->checkkey == nil){
				werrstr("proto %s does not accept keys", proto->name);
				ret = -1;
				continue;
			}
			k = emalloc(sizeof(Key));
			k->attr = mkattr(AttrNameval, "proto", proto->name, copyattr(attr));
			k->privattr = copyattr(priv);
			k->ref = 1;
			k->proto = proto;
			if((*proto->checkkey)(k) < 0){
				ret = -1;
				keyclose(k);
				continue;
			}
			keyadd(k);
			keyclose(k);
		}
		freeattr(attr);
		freeattr(priv);
		freeattr(protos);
		return ret;
	case 1:	/* delkey */
		nmatch = 0;
		attr = parseattr(p);
		for(pa=attr; pa; pa=pa->next){
			if(pa->type != AttrQuery && pa->name[0]=='!'){
				werrstr("only !private? patterns are allowed for private fields");
				freeattr(attr);
				return -1;
			}
		}
		for(i=0; i<ring.nkey; ){
			if(matchattr(attr, ring.key[i]->attr, ring.key[i]->privattr)){
				nmatch++;
				keyclose(ring.key[i]);
				ring.nkey--;
				memmove(&ring.key[i], &ring.key[i+1], (ring.nkey-i)*sizeof(ring.key[0]));
			}else
				i++;
		}
		freeattr(attr);
		if(nmatch == 0){
			werrstr("found no keys to delete");
			return -1;
		}
		return 0;
	case 2:	/* debug */
		debug ^= 1;
		return 0;
	}
}
