#include <rpc/rpc.h>
#include <netdb.h>
#include <stdlib.h>
#include <mach/mach.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <netinet/in.h>
#include <pthread.h>
#include "lu_utils.h"
#include "lu_overrides.h"
static pthread_mutex_t _rpc_lock = PTHREAD_MUTEX_INITIALIZER;
#define RPC_GET_NAME 1
#define RPC_GET_NUM 2
#define RPC_GET_ENT 3
#define ENTRY_SIZE sizeof(struct rpcent)
#define ENTRY_KEY _li_data_key_rpc
static struct rpcent *
copy_rpc(struct rpcent *in)
{
if (in == NULL) return NULL;
return (struct rpcent *)LI_ils_create("s*4", in->r_name, in->r_aliases, in->r_number);
}
static void *
extract_rpc(kvarray_t *in)
{
struct rpcent tmp;
uint32_t d, k, kcount;
char *empty[1];
if (in == NULL) return NULL;
d = in->curr;
in->curr++;
if (d >= in->count) return NULL;
empty[0] = NULL;
memset(&tmp, 0, ENTRY_SIZE);
kcount = in->dict[d].kcount;
for (k = 0; k < kcount; k++)
{
if (!strcmp(in->dict[d].key[k], "r_name"))
{
if (tmp.r_name != NULL) continue;
if (in->dict[d].vcount[k] == 0) continue;
tmp.r_name = (char *)in->dict[d].val[k][0];
}
else if (!strcmp(in->dict[d].key[k], "r_number"))
{
if (in->dict[d].vcount[k] == 0) continue;
tmp.r_number = atoi(in->dict[d].val[k][0]);
}
else if (!strcmp(in->dict[d].key[k], "r_aliases"))
{
if (tmp.r_aliases != NULL) continue;
if (in->dict[d].vcount[k] == 0) continue;
tmp.r_aliases = (char **)in->dict[d].val[k];
}
}
if (tmp.r_name == NULL) tmp.r_name = "";
if (tmp.r_aliases == NULL) tmp.r_aliases = empty;
return copy_rpc(&tmp);
}
static struct rpcent *
ds_getrpcbynumber(uint32_t number)
{
static int proc = -1;
char val[16];
snprintf(val, sizeof(val), "%u", number);
return (struct rpcent *)LI_getone("getrpcbynumber", &proc, extract_rpc, "number", val);
}
static struct rpcent *
ds_getrpcbyname(const char *name)
{
static int proc = -1;
return (struct rpcent *)LI_getone("getrpcbyname", &proc, extract_rpc, "name", name);
}
static void
ds_endrpcent(void)
{
LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY));
}
static void
ds_setrpcent(void)
{
ds_endrpcent();
}
static struct rpcent *
ds_getrpcent(void)
{
static int proc = -1;
return (struct rpcent *)LI_getent("getrpcent", &proc, extract_rpc, ENTRY_KEY, ENTRY_SIZE);
}
static struct rpcent *
getrpc(const char *name, uint32_t number, int source)
{
struct rpcent *res = NULL;
struct li_thread_info *tdata;
tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE);
if (tdata == NULL) return NULL;
if (_ds_running())
{
switch (source)
{
case RPC_GET_NAME:
res = ds_getrpcbyname(name);
break;
case RPC_GET_NUM:
res = ds_getrpcbynumber(number);
break;
case RPC_GET_ENT:
res = ds_getrpcent();
break;
default: res = NULL;
}
}
else
{
pthread_mutex_lock(&_rpc_lock);
switch (source)
{
case RPC_GET_NAME:
res = copy_rpc(_old_getrpcbyname(name));
break;
case RPC_GET_NUM:
res = copy_rpc(_old_getrpcbynumber(number));
break;
case RPC_GET_ENT:
res = copy_rpc(_old_getrpcent());
break;
default: res = NULL;
}
pthread_mutex_unlock(&_rpc_lock);
}
LI_data_recycle(tdata, res, ENTRY_SIZE);
return (struct rpcent *)tdata->li_entry;
}
struct rpcent *
getrpcbyname(const char *name)
{
return getrpc(name, -2, RPC_GET_NAME);
}
struct rpcent *
#ifdef __LP64__
getrpcbynumber(int number)
#else
getrpcbynumber(long number)
#endif
{
uint32_t n;
n = number;
return getrpc(NULL, n, RPC_GET_NUM);
}
struct rpcent *
getrpcent(void)
{
return getrpc(NULL, -2, RPC_GET_ENT);
}
void
setrpcent(int stayopen)
{
if (_ds_running()) ds_setrpcent();
else _old_setrpcent(stayopen);
}
void
endrpcent(void)
{
if (_ds_running()) ds_endrpcent();
else _old_endrpcent();
}