#include <netgr.h>
#include <mach/mach.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include "_lu_types.h"
#include "lookup.h"
#include "lu_utils.h"
#include "lu_overrides.h"
#define FIX(x) ((x == NULL) ? NULL : &(x))
static struct netgrent global_netgr;
static int global_free = 1;
static char *netgr_data = NULL;
static unsigned netgr_datalen;
static int netgr_nentries = 0;
static int netgr_start = 1;
static XDR netgr_xdr;
static void
freeold(void)
{
if (global_free == 1) return;
free(global_netgr.ng_host);
free(global_netgr.ng_user);
free(global_netgr.ng_domain);
global_free = 1;
}
static void
convert_netgr(_lu_netgrent *lu_netgr)
{
freeold();
global_netgr.ng_host = strdup(lu_netgr->ng_host);
global_netgr.ng_user = strdup(lu_netgr->ng_user);
global_netgr.ng_domain = strdup(lu_netgr->ng_domain);
global_free = 0;
}
static int
lu_innetgr(const char *group, const char *host, const char *user,
const char *domain)
{
unsigned datalen;
XDR xdr;
char namebuf[4*_LU_MAXLUSTRLEN + 3*BYTES_PER_XDR_UNIT];
static int proc = -1;
int size;
int res;
_lu_innetgr_args args;
unit lookup_buf[MAX_INLINE_UNITS];
if (proc < 0)
{
if (_lookup_link(_lu_port, "innetgr", &proc) != KERN_SUCCESS)
{
return (0);
}
}
args.group = (char *)group;
args.host = FIX(host);
args.user = FIX(user);
args.domain = FIX(domain);
xdrmem_create(&xdr, namebuf, sizeof(namebuf), XDR_ENCODE);
if (!xdr__lu_innetgr_args(&xdr, &args))
{
xdr_destroy(&xdr);
return (0);
}
size = xdr_getpos(&xdr) / BYTES_PER_XDR_UNIT;
xdr_destroy(&xdr);
datalen = MAX_INLINE_UNITS;
if (_lookup_one(_lu_port, proc, (unit *)namebuf, size, lookup_buf,
&datalen) != KERN_SUCCESS)
{
return (0);
}
datalen *= BYTES_PER_XDR_UNIT;
xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
if (!xdr_int(&xdr, &res))
{
xdr_destroy(&xdr);
return (0);
}
xdr_destroy(&xdr);
return (res);
}
static void
lu_endnetgrent(void)
{
netgr_nentries = 0;
if (netgr_data != NULL)
{
freeold();
vm_deallocate(mach_task_self(), (vm_address_t)netgr_data, netgr_datalen);
netgr_data = NULL;
}
}
static void
lu_setnetgrent(const char *group)
{
unsigned datalen;
char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
XDR outxdr;
static int proc = -1;
lu_endnetgrent();
if (proc < 0)
{
if (_lookup_link(_lu_port, "getnetgrent", &proc) != KERN_SUCCESS)
{
lu_endnetgrent();
return;
}
}
xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
if (!xdr__lu_string(&outxdr, &group))
{
xdr_destroy(&outxdr);
lu_endnetgrent();
return;
}
datalen = MAX_INLINE_UNITS;
if (_lookup_all(_lu_port, proc, (unit *)namebuf,
xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT,
&netgr_data, &netgr_datalen) != KERN_SUCCESS)
{
xdr_destroy(&outxdr);
lu_endnetgrent();
return;
}
xdr_destroy(&outxdr);
#ifdef NOTDEF
netgr_datalen *= BYTES_PER_XDR_UNIT;
#endif
xdrmem_create(&netgr_xdr, netgr_data,
netgr_datalen, XDR_DECODE);
if (!xdr_int(&netgr_xdr, &netgr_nentries))
{
xdr_destroy(&netgr_xdr);
lu_endnetgrent();
}
}
struct netgrent *
lu_getnetgrent(void)
{
_lu_netgrent lu_netgr;
if (netgr_nentries == 0)
{
xdr_destroy(&netgr_xdr);
lu_endnetgrent();
return (NULL);
}
bzero(&lu_netgr, sizeof(lu_netgr));
if (!xdr__lu_netgrent(&netgr_xdr, &lu_netgr))
{
xdr_destroy(&netgr_xdr);
lu_endnetgrent();
return (NULL);
}
netgr_nentries--;
convert_netgr(&lu_netgr);
xdr_free(xdr__lu_netgrent, &lu_netgr);
return (&global_netgr);
}
int
innetgr(const char *group, const char *host, const char *user,
const char *domain)
{
if (_lu_running()) return (lu_innetgr(group, host, user, domain));
return (0);
}
struct netgrent *
getnetgrent(void)
{
if (_lu_running()) return (lu_getnetgrent());
return (NULL);
}
void
setnetgrent(const char *group)
{
if (_lu_running()) lu_setnetgrent(group);
}
void
endnetgrent(void)
{
if (_lu_running()) lu_endnetgrent();
}