#include "sys_defs.h"
#include <string.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
#ifdef HAS_NIS
#include <rpcsvc/ypclnt.h>
#ifndef YPERR_BUSY
#define YPERR_BUSY 16
#endif
#ifndef YPERR_ACCESS
#define YPERR_ACCESS 15
#endif
#endif
#include "msg.h"
#include "mymalloc.h"
#include "vstring.h"
#include "dict.h"
#include "dict_nis.h"
#ifdef HAS_NIS
typedef struct {
DICT dict;
} DICT_NIS;
static char dict_nis_disabled[1];
static char *dict_nis_domain;
static void dict_nis_init(void)
{
char *myname = "dict_nis_init";
if (yp_get_default_domain(&dict_nis_domain) != 0
|| dict_nis_domain == 0 || *dict_nis_domain == 0
|| strcasecmp(dict_nis_domain, "(none)") == 0) {
dict_nis_domain = dict_nis_disabled;
msg_warn("%s: NIS domain name not set - NIS lookups disabled", myname);
}
if (msg_verbose)
msg_info("%s: NIS domain %s", myname, dict_nis_domain);
}
static char *dict_nis_strerror(int err)
{
switch (err) {
case YPERR_BADARGS:
return ("args to function are bad");
case YPERR_RPC:
return ("RPC failure - domain has been unbound");
case YPERR_DOMAIN:
return ("can't bind to server on this domain");
case YPERR_MAP:
return ("no such map in server's domain");
case YPERR_KEY:
return ("no such key in map");
case YPERR_YPERR:
return ("internal yp server or client error");
case YPERR_RESRC:
return ("resource allocation failure");
case YPERR_NOMORE:
return ("no more records in map database");
case YPERR_PMAP:
return ("can't communicate with portmapper");
case YPERR_YPBIND:
return ("can't communicate with ypbind");
case YPERR_YPSERV:
return ("can't communicate with ypserv");
case YPERR_NODOM:
return ("local domain name not set");
case YPERR_BADDB:
return ("yp database is bad");
case YPERR_VERS:
return ("yp version mismatch");
case YPERR_ACCESS:
return ("access violation");
case YPERR_BUSY:
return ("database busy");
default:
return ("unknown NIS lookup error");
}
}
static const char *dict_nis_lookup(DICT *dict, const char *key)
{
DICT_NIS *dict_nis = (DICT_NIS *) dict;
static char *result;
int result_len;
int err;
static VSTRING *buf;
dict_errno = 0;
if (dict_nis_domain == dict_nis_disabled)
return (0);
if (dict->flags & DICT_FLAG_TRY1NULL) {
err = yp_match(dict_nis_domain, dict_nis->dict.name,
(void *) key, strlen(key) + 1,
&result, &result_len);
if (err == 0) {
dict->flags &= ~DICT_FLAG_TRY0NULL;
return (result);
}
}
if (dict->flags & DICT_FLAG_TRY0NULL) {
err = yp_match(dict_nis_domain, dict_nis->dict.name,
(void *) key, strlen(key),
&result, &result_len);
if (err == 0) {
dict->flags &= ~DICT_FLAG_TRY1NULL;
if (buf == 0)
buf = vstring_alloc(10);
vstring_strncpy(buf, result, result_len);
return (vstring_str(buf));
}
}
if (err != YPERR_KEY) {
msg_warn("lookup %s, NIS domain %s, map %s: %s",
key, dict_nis_domain, dict_nis->dict.name,
dict_nis_strerror(err));
dict_errno = DICT_ERR_RETRY;
}
return (0);
}
static void dict_nis_close(DICT *dict)
{
dict_free(dict);
}
DICT *dict_nis_open(const char *map, int open_flags, int dict_flags)
{
DICT_NIS *dict_nis;
if (open_flags != O_RDONLY)
msg_fatal("%s:%s map requires O_RDONLY access mode",
DICT_TYPE_NIS, map);
dict_nis = (DICT_NIS *) dict_alloc(DICT_TYPE_NIS, map, sizeof(*dict_nis));
dict_nis->dict.lookup = dict_nis_lookup;
dict_nis->dict.close = dict_nis_close;
dict_nis->dict.flags = dict_flags | DICT_FLAG_FIXED;
if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
dict_nis->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL);
if (dict_nis_domain == 0)
dict_nis_init();
return (DICT_DEBUG (&dict_nis->dict));
}
#endif