#include #include #include #include <9pclient.h> #include "authlocal.h" static struct { char *verb; int val; } tab[] = { "ok", ARok, "done", ARdone, "error", ARerror, "needkey", ARneedkey, "badkey", ARbadkey, "phase", ARphase, "toosmall", ARtoosmall, "error", ARerror, }; static long rpcread(AuthRpc *rpc, void *buf, int buflen) { if (rpc->afd >= 0) return read(rpc->afd, buf, buflen); else return fsread(rpc->afid, buf, buflen); } static long rpcwrite(AuthRpc *rpc, void *buf, int buflen) { if (rpc->afd >= 0) return write(rpc->afd, buf, buflen); else return fswrite(rpc->afid, buf, buflen); } static int classify(char *buf, uint n, AuthRpc *rpc) { int i, len; for(i=0; i= len && memcmp(buf, tab[i].verb, len) == 0 && (n==len || buf[len]==' ')){ if(n==len){ rpc->narg = 0; rpc->arg = ""; }else{ rpc->narg = n - (len+1); rpc->arg = (char*)buf+len+1; } return tab[i].val; } } werrstr("malformed rpc response: %s", buf); return ARrpcfailure; } AuthRpc* auth_allocrpc(void) { AuthRpc *rpc; rpc = mallocz(sizeof(*rpc), 1); if(rpc == nil) return nil; rpc->afd = open("/mnt/factotum/rpc", ORDWR); if(rpc->afd < 0){ rpc->afid = nsopen("factotum", nil, "rpc", ORDWR); if(rpc->afid == nil){ free(rpc); return nil; } } return rpc; } void auth_freerpc(AuthRpc *rpc) { if(rpc == nil) return; if(rpc->afd >= 0) close(rpc->afd); if(rpc->afid != nil) fsclose(rpc->afid); free(rpc); } uint auth_rpc(AuthRpc *rpc, char *verb, void *a, int na) { int l, n, type; char *f[4]; l = strlen(verb); if(na+l+1 > AuthRpcMax){ werrstr("rpc too big"); return ARtoobig; } memmove(rpc->obuf, verb, l); rpc->obuf[l] = ' '; memmove(rpc->obuf+l+1, a, na); if((n=rpcwrite(rpc, rpc->obuf, l+1+na)) != l+1+na){ if(n >= 0) werrstr("auth_rpc short write"); return ARrpcfailure; } if((n=rpcread(rpc, rpc->ibuf, AuthRpcMax)) < 0) return ARrpcfailure; rpc->ibuf[n] = '\0'; /* * Set error string for good default behavior. */ switch(type = classify(rpc->ibuf, n, rpc)){ default: werrstr("unknown rpc type %d (bug in auth_rpc.c)", type); break; case ARok: break; case ARrpcfailure: break; case ARerror: if(rpc->narg == 0) werrstr("unspecified rpc error"); else werrstr("%s", rpc->arg); break; case ARneedkey: werrstr("needkey %s", rpc->arg); break; case ARbadkey: if(getfields(rpc->arg, f, nelem(f), 0, "\n") < 2) werrstr("badkey %s", rpc->arg); else werrstr("badkey %s", f[1]); break; case ARphase: werrstr("phase error %s", rpc->arg); break; } return type; }