|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <auth.h> | 
|  | #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<nelem(tab); i++){ | 
|  | len = strlen(tab[i].verb); | 
|  | if(n >= 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; | 
|  | } |