#include "namespace.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpc/types.h>
#include <rpc/auth.h>
#include <rpc/clnt.h>
#include "un-namespace.h"
static char *buf;
static char *_buf(void);
static char *auth_errmsg(enum auth_stat);
#define CLNT_PERROR_BUFLEN 256
static char *
_buf(void)
{
if (buf == NULL)
buf = malloc(CLNT_PERROR_BUFLEN);
return (buf);
}
char *
clnt_sperror(CLIENT *rpch, const char *s)
{
struct rpc_err e;
char *err;
char *str;
char *strstart;
size_t len, i;
assert(rpch != NULL);
assert(s != NULL);
str = _buf();
if (str == NULL)
return (0);
len = CLNT_PERROR_BUFLEN;
strstart = str;
CLNT_GETERR(rpch, &e);
if ((i = snprintf(str, len, "%s: ", s)) > 0) {
str += i;
len -= i;
}
(void)strncpy(str, clnt_sperrno(e.re_status), len - 1);
i = strlen(str);
str += i;
len -= i;
switch (e.re_status) {
case RPC_SUCCESS:
case RPC_CANTENCODEARGS:
case RPC_CANTDECODERES:
case RPC_TIMEDOUT:
case RPC_PROGUNAVAIL:
case RPC_PROCUNAVAIL:
case RPC_CANTDECODEARGS:
case RPC_SYSTEMERROR:
case RPC_UNKNOWNHOST:
case RPC_UNKNOWNPROTO:
case RPC_PMAPFAILURE:
case RPC_PROGNOTREGISTERED:
case RPC_FAILED:
break;
case RPC_CANTSEND:
case RPC_CANTRECV:
i = snprintf(str, len, "; errno = %s", strerror(e.re_errno));
if (i > 0) {
str += i;
len -= i;
}
break;
case RPC_VERSMISMATCH:
i = snprintf(str, len, "; low version = %u, high version = %u",
e.re_vers.low, e.re_vers.high);
if (i > 0) {
str += i;
len -= i;
}
break;
case RPC_AUTHERROR:
err = auth_errmsg(e.re_why);
i = snprintf(str, len, "; why = ");
if (i > 0) {
str += i;
len -= i;
}
if (err != NULL) {
i = snprintf(str, len, "%s",err);
} else {
i = snprintf(str, len,
"(unknown authentication error - %d)",
(int) e.re_why);
}
if (i > 0) {
str += i;
len -= i;
}
break;
case RPC_PROGVERSMISMATCH:
i = snprintf(str, len, "; low version = %u, high version = %u",
e.re_vers.low, e.re_vers.high);
if (i > 0) {
str += i;
len -= i;
}
break;
default:
i = snprintf(str, len, "; s1 = %u, s2 = %u",
e.re_lb.s1, e.re_lb.s2);
if (i > 0) {
str += i;
len -= i;
}
break;
}
strstart[CLNT_PERROR_BUFLEN-1] = '\0';
return(strstart) ;
}
void
clnt_perror(CLIENT *rpch, const char *s)
{
assert(rpch != NULL);
assert(s != NULL);
(void) fprintf(stderr, "%s\n", clnt_sperror(rpch,s));
}
static const char *const rpc_errlist[] = {
"RPC: Success",
"RPC: Can't encode arguments",
"RPC: Can't decode result",
"RPC: Unable to send",
"RPC: Unable to receive",
"RPC: Timed out",
"RPC: Incompatible versions of RPC",
"RPC: Authentication error",
"RPC: Program unavailable",
"RPC: Program/version mismatch",
"RPC: Procedure unavailable",
"RPC: Server can't decode arguments",
"RPC: Remote system error",
"RPC: Unknown host",
"RPC: Port mapper failure",
"RPC: Program not registered",
"RPC: Failed (unspecified error)",
"RPC: Unknown protocol"
};
char *
clnt_sperrno(enum clnt_stat stat)
{
unsigned int errnum = stat;
if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0])))
return (char *)rpc_errlist[errnum];
return ("RPC: (unknown error code)");
}
void
clnt_perrno(enum clnt_stat num)
{
(void) fprintf(stderr, "%s\n", clnt_sperrno(num));
}
char *
clnt_spcreateerror(const char *s)
{
char *str;
size_t len, i;
assert(s != NULL);
str = _buf();
if (str == NULL)
return(0);
len = CLNT_PERROR_BUFLEN;
i = snprintf(str, len, "%s: ", s);
if (i > 0)
len -= i;
(void)strncat(str, clnt_sperrno(rpc_createerr.cf_stat), len - 1);
switch (rpc_createerr.cf_stat) {
case RPC_PMAPFAILURE:
(void) strncat(str, " - ", len - 1);
(void) strncat(str,
clnt_sperrno(rpc_createerr.cf_error.re_status), len - 4);
break;
case RPC_SYSTEMERROR:
(void)strncat(str, " - ", len - 1);
(void)strncat(str, strerror(rpc_createerr.cf_error.re_errno),
len - 4);
break;
case RPC_CANTSEND:
case RPC_CANTDECODERES:
case RPC_CANTENCODEARGS:
case RPC_SUCCESS:
case RPC_UNKNOWNPROTO:
case RPC_PROGNOTREGISTERED:
case RPC_FAILED:
case RPC_UNKNOWNHOST:
case RPC_CANTDECODEARGS:
case RPC_PROCUNAVAIL:
case RPC_PROGVERSMISMATCH:
case RPC_PROGUNAVAIL:
case RPC_AUTHERROR:
case RPC_VERSMISMATCH:
case RPC_TIMEDOUT:
case RPC_CANTRECV:
default:
break;
}
str[CLNT_PERROR_BUFLEN-1] = '\0';
return (str);
}
void
clnt_pcreateerror(const char *s)
{
assert(s != NULL);
(void) fprintf(stderr, "%s\n", clnt_spcreateerror(s));
}
static const char *const auth_errlist[] = {
"Authentication OK",
"Invalid client credential",
"Server rejected credential",
"Invalid client verifier",
"Server rejected verifier",
"Client credential too weak",
"Invalid server verifier",
"Failed (unspecified error)",
"Kerberos generic error",
"Kerberos credential expired",
"Bad kerberos ticket file",
"Can't decode kerberos authenticator",
"Address wrong in kerberos ticket",
"GSS-API crediential problem",
"GSS-API context problem"
};
static char *
auth_errmsg(enum auth_stat stat)
{
unsigned int errnum = stat;
if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0])))
return (char *)auth_errlist[errnum];
return(NULL);
}