#include "mt.h"
#include <stdlib.h>
#include <unistd.h>
#include <rpc/rpc.h>
#include <sys/types.h>
#include "yp_b.h"
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#include <string.h>
extern int __yp_dobind_cflookup(char *, struct dom_binding **, int);
static int dofirst(char *, char *, struct dom_binding *, struct timeval,
char **, int *, char **, int *);
static int donext(char *, char *, char *, int, struct dom_binding *,
struct timeval, char **, int *, char **val, int *);
int
__yp_first_cflookup(
char *domain,
char *map,
char **key,
int *keylen,
char **val,
int *vallen,
int hardlookup)
{
size_t domlen;
size_t maplen;
struct dom_binding *pdomb;
int reason;
if ((map == NULL) || (domain == NULL))
return (YPERR_BADARGS);
domlen = strlen(domain);
maplen = strlen(map);
if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
(maplen == 0) || (maplen > YPMAXMAP))
return (YPERR_BADARGS);
for (;;) {
if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup))
return (reason);
if (pdomb->dom_binding->ypbind_hi_vers == YPVERS) {
reason = dofirst(domain, map, pdomb, _ypserv_timeout,
key, keylen, val, vallen);
__yp_rel_binding(pdomb);
if (reason == YPERR_RPC || reason == YPERR_YPSERV ||
reason == YPERR_BUSY ) {
yp_unbind(domain);
if (hardlookup)
(void) sleep(_ypsleeptime);
else
return (reason);
} else
break;
} else {
__yp_rel_binding(pdomb);
return (YPERR_VERS);
}
}
return (reason);
}
int
yp_first(
char *domain,
char *map,
char **key,
int *keylen,
char **val,
int *vallen)
{
return (__yp_first_cflookup(domain, map, key, keylen, val, vallen, 1));
}
static int
dofirst(domain, map, pdomb, timeout, key, keylen, val, vallen)
char *domain;
char *map;
struct dom_binding *pdomb;
struct timeval timeout;
char **key;
int *keylen;
char **val;
int *vallen;
{
struct ypreq_nokey req;
struct ypresp_key_val resp;
unsigned int retval = 0;
req.domain = domain;
req.map = map;
resp.keydat.dptr = resp.valdat.dptr = NULL;
resp.keydat.dsize = resp.valdat.dsize = 0;
(void) memset((char *)&resp, 0, sizeof (struct ypresp_key_val));
switch (clnt_call(pdomb->dom_client, YPPROC_FIRST,
(xdrproc_t)xdr_ypreq_nokey,
(char *)&req, (xdrproc_t)xdr_ypresp_key_val,
(char *)&resp, timeout)) {
case RPC_SUCCESS:
break;
case RPC_TIMEDOUT:
return (YPERR_YPSERV);
default:
return (YPERR_RPC);
}
if (resp.status != YP_TRUE) {
retval = ypprot_err(resp.status);
}
if (!retval) {
if ((*key = malloc((size_t)resp.keydat.dsize + 2)) != NULL) {
if ((*val = malloc(
(size_t)resp.valdat.dsize + 2)) == NULL) {
free(*key);
retval = YPERR_RESRC;
}
} else {
retval = YPERR_RESRC;
}
}
if (!retval) {
*keylen = (int)resp.keydat.dsize;
(void) memcpy(*key, resp.keydat.dptr,
(size_t)resp.keydat.dsize);
(*key)[resp.keydat.dsize] = '\n';
(*key)[resp.keydat.dsize + 1] = '\0';
*vallen = (int)resp.valdat.dsize;
(void) memcpy(*val, resp.valdat.dptr,
(size_t)resp.valdat.dsize);
(*val)[resp.valdat.dsize] = '\n';
(*val)[resp.valdat.dsize + 1] = '\0';
}
CLNT_FREERES(pdomb->dom_client,
(xdrproc_t)xdr_ypresp_key_val, (char *)&resp);
return (retval);
}
int
__yp_next_cflookup(
char *domain,
char *map,
char *inkey,
int inkeylen,
char **outkey,
int *outkeylen,
char **val,
int *vallen,
int hardlookup)
{
size_t domlen;
size_t maplen;
struct dom_binding *pdomb;
int reason;
if ((map == NULL) || (domain == NULL) || (inkey == NULL))
return (YPERR_BADARGS);
domlen = strlen(domain);
maplen = strlen(map);
if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
(maplen == 0) || (maplen > YPMAXMAP))
return (YPERR_BADARGS);
for (;;) {
if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup))
return (reason);
if (pdomb->dom_binding->ypbind_hi_vers == YPVERS) {
reason = donext(domain, map, inkey, inkeylen, pdomb,
_ypserv_timeout, outkey, outkeylen, val, vallen);
__yp_rel_binding(pdomb);
if (reason == YPERR_RPC || reason == YPERR_YPSERV ||
reason == YPERR_BUSY ) {
yp_unbind(domain);
if (hardlookup)
(void) sleep(_ypsleeptime);
else
return (reason);
} else
break;
} else {
__yp_rel_binding(pdomb);
return (YPERR_VERS);
}
}
return (reason);
}
int
yp_next(
char *domain,
char *map,
char *inkey,
int inkeylen,
char **outkey,
int *outkeylen,
char **val,
int *vallen)
{
return (__yp_next_cflookup(domain, map, inkey, inkeylen, outkey,
outkeylen, val, vallen, 1));
}
static int
donext(domain, map, inkey, inkeylen, pdomb, timeout, outkey, outkeylen,
val, vallen)
char *domain;
char *map;
char *inkey;
int inkeylen;
struct dom_binding *pdomb;
struct timeval timeout;
char **outkey;
int *outkeylen;
char **val;
int *vallen;
{
struct ypreq_key req;
struct ypresp_key_val resp;
unsigned int retval = 0;
req.domain = domain;
req.map = map;
req.keydat.dptr = inkey;
req.keydat.dsize = inkeylen;
resp.keydat.dptr = resp.valdat.dptr = NULL;
resp.keydat.dsize = resp.valdat.dsize = 0;
switch (clnt_call(pdomb->dom_client,
YPPROC_NEXT, (xdrproc_t)xdr_ypreq_key, (char *)&req,
(xdrproc_t)xdr_ypresp_key_val, (char *)&resp,
timeout)) {
case RPC_SUCCESS:
break;
case RPC_TIMEDOUT:
return (YPERR_YPSERV);
default:
return (YPERR_RPC);
}
if (resp.status != YP_TRUE) {
retval = ypprot_err(resp.status);
}
if (!retval) {
if ((*outkey = malloc((size_t)
resp.keydat.dsize + 2)) != NULL) {
if ((*val = malloc((size_t)
resp.valdat.dsize + 2)) == NULL) {
free(*outkey);
retval = YPERR_RESRC;
}
} else {
retval = YPERR_RESRC;
}
}
if (!retval) {
*outkeylen = (int)resp.keydat.dsize;
(void) memcpy(*outkey, resp.keydat.dptr,
(size_t)resp.keydat.dsize);
(*outkey)[resp.keydat.dsize] = '\n';
(*outkey)[resp.keydat.dsize + 1] = '\0';
*vallen = (int)resp.valdat.dsize;
(void) memcpy(*val, resp.valdat.dptr,
(size_t)resp.valdat.dsize);
(*val)[resp.valdat.dsize] = '\n';
(*val)[resp.valdat.dsize + 1] = '\0';
}
CLNT_FREERES(pdomb->dom_client, (xdrproc_t)xdr_ypresp_key_val,
(char *)&resp);
return (retval);
}