#include <9pm/u.h>
#include <9pm/libc.h>
#include <9pm/auth.h>
#include "authlocal.h"

enum {
	ARgiveup = 100,
};

static int
dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
{
	int ret;

	for(;;){
		if((ret = _auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
			return ret;
		if(getkey == nil)
			return ARgiveup;	/* don't know how */
		if((*getkey)(rpc->arg) < 0)
			return ARgiveup;	/* user punted */
	}
}

int
auth_respond(void *chal, uint nchal, void *resp, uint nresp, AuthGetkey *getkey, char *fmt, ...)
{
	char buf[256];
	va_list arg;
	int afd;
	AuthRpc *rpc;

	if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
		return -1;
	
	if((rpc = _auth_allocrpc(afd)) == nil){
		close(afd);
		return -1;
	}

	quotefmtinstall();	/* just in case */
	va_start(arg, fmt);
	doprint(buf, buf+sizeof buf, fmt, arg);
	va_end(arg);

	if(dorpc(rpc, "start", buf, strlen(buf), getkey) != ARok
	|| dorpc(rpc, "write", chal, nchal, getkey) != ARok
	|| dorpc(rpc, "read", nil, 0, getkey) != ARok){
		close(afd);
		_auth_freerpc(rpc);
		return -1;
	}

	if(rpc->narg < nresp)
		nresp = rpc->narg;
	memmove(resp, rpc->arg, nresp);
	close(afd);
	_auth_freerpc(rpc);
	return nresp;	
}
