#include "am.h"
#include <unistd.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#include <time.h>
static int has_yp_order = FALSE;
static int
determine_nis_domain(void)
{
static int nis_not_running = 0;
char default_domain[YPMAXDOMAIN];
if (nis_not_running)
return ENOENT;
if (getdomainname(default_domain, sizeof(default_domain)) < 0) {
nis_not_running = 1;
plog(XLOG_ERROR, "getdomainname: %m");
return EIO;
}
if (!*default_domain) {
nis_not_running = 1;
plog(XLOG_INFO, "NIS domain name is not set. NIS ignored.");
return ENOENT;
}
domain = strdup(default_domain);
return 0;
}
struct nis_callback_data {
mnt_map *ncd_m;
char *ncd_map;
void (*ncd_fn)(mnt_map *, char *, char *);
};
static int
callback(unsigned long status, char *key, int kl, char *val, int vl, void *arg)
{
struct nis_callback_data *data = arg;
if (status == YP_TRUE) {
char *kp = strnsave(key, kl);
char *vp = strnsave(val, vl);
(*data->ncd_fn)(data->ncd_m, kp, vp);
return FALSE;
} else {
if (status != YP_NOMORE) {
int e = ypprot_err(status);
#ifdef DEBUG
plog(XLOG_ERROR, "yp enumeration of %s: %s, status=%d, e=%d",
data->ncd_map, yperr_string(e), status, e);
#else
plog(XLOG_ERROR, "yp enumeration of %s: %s",
data->ncd_map, yperr_string(e));
#endif
}
return TRUE;
}
}
int
nis_reload(mnt_map *m, char *map, void (*fn)(mnt_map *, char *, char *))
{
struct ypall_callback cbinfo;
int error;
struct nis_callback_data data;
if (!domain) {
error = determine_nis_domain();
if (error)
return error;
}
data.ncd_m = m;
data.ncd_map = map;
data.ncd_fn = fn;
cbinfo.data = (void *)&data;
cbinfo.foreach = &callback;
error = yp_all(domain, map, &cbinfo);
if (error)
plog(XLOG_ERROR, "error grabbing nis map of %s: %s",
map, yperr_string(ypprot_err(error)));
return error;
}
int
nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
{
int outlen;
int order;
int res;
if (has_yp_order) {
if (yp_order(domain, map, &order))
return EIO;
if ((time_t) order > *tp) {
*tp = (time_t) order;
return -1;
}
} else {
order = time(NULL);
if ((time_t)order - *tp > am_timeo) {
*tp = (time_t)order;
return(-1);
}
}
if (has_yp_order) {
if (yp_order(domain, map, &order))
return EIO;
if ((time_t) order > *tp) {
*tp = (time_t) order;
return -1;
}
} else {
order = time(NULL);
if ((time_t)order - *tp > am_timeo) {
*tp = (time_t)order;
return(-1);
}
}
res = yp_match(domain, map, key, strlen(key), val, &outlen);
switch (res) {
case 0:
return 0;
case YPERR_KEY:
return ENOENT;
default:
plog(XLOG_ERROR, "%s: %s", map, yperr_string(res));
return EIO;
}
}
int
nis_init(char *map, time_t *tp)
{
int order;
int yp_order_result;
char *master;
if (!domain) {
int error = determine_nis_domain();
if (error)
return error;
}
yp_order_result = yp_order(domain, map, &order);
switch (yp_order_result) {
case 0:
has_yp_order = TRUE;
*tp = (time_t)order;
#ifdef DEBUG
dlog("NIS master for %s@%s has order %d", map, domain, order);
#endif
break;
case YPERR_YPERR:
plog(XLOG_ERROR, "%s: %s", map, "NIS+ server");
has_yp_order = FALSE;
if (yp_master(domain, map, &master))
return ENOENT;
else
*tp = time(NULL);
break;
default:
return ENOENT;
}
return 0;
}