NIS interface by Fred Gansevles <Fred.Gansevles@cs.utwente.nl>.
diff --git a/Modules/nismodule.c b/Modules/nismodule.c
new file mode 100644
index 0000000..b5aeae2
--- /dev/null
+++ b/Modules/nismodule.c
@@ -0,0 +1,292 @@
+/***********************************************************
+ Written by:
+ Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
+ Vakgroep Spa,
+ Faculteit der Informatica,
+ Universiteit Twente,
+ Enschede,
+ the Netherlands.
+******************************************************************/
+
+/* NIS module implementation */
+
+#include "allobjects.h"
+#include "modsupport.h"
+#include "ceval.h"
+
+#include <rpcsvc/ypclnt.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+
+static struct nis_map {
+ char *alias;
+ char *map;
+} aliases [] = {
+{"passwd", "passwd.byname"},
+{"group", "group.byname"},
+{"networks", "networks.byaddr"},
+{"hosts", "hosts.byname"},
+{"protocols", "protocols.bynumber"},
+{"services", "services.byname"},
+{"aliases", "mail.aliases"},
+{"ethers", "ethers.byname"},
+{0L, 0L}
+};
+
+static char *
+nis_mapname (map)
+char *map;
+{
+int i;
+
+ for (i=0; aliases[i].alias != 0L; i++)
+ if (!strcmp (aliases[i].alias, map))
+ map = aliases[i].map;
+ return map;
+}
+
+static int
+nis_foreach (instatus, inkey, inkeylen, inval, invallen,indata)
+int instatus;
+char *inkey;
+int inkeylen;
+char *inval;
+int invallen;
+object *indata;
+{
+ if (instatus == YP_TRUE) {
+ inkey[inkeylen]=0;
+ inval[invallen]=0;
+ dictinsert (indata, inkey, newstringobject (inval));
+ return 0;
+ }
+ return 1;
+}
+
+static object *
+nis_match (self, args)
+object *self;
+object *args;
+{
+char *match;
+char *domain;
+int len;
+char *key, *map;
+
+ if (!getstrstrarg(args, &key, &map))
+ return NULL;
+ map = nis_mapname (map);
+ BGN_SAVE
+ yp_get_default_domain(&domain);
+ if (yp_match (domain, map, key, strlen (key), &match, &len) == 0)
+ match[len] = 0;
+ END_SAVE
+ return newstringobject (match);
+}
+
+static object *
+nis_cat (self, args)
+object *self;
+object *args;
+{
+char *domain;
+char *map;
+struct ypall_callback cb;
+object *cat;
+
+ if (!getstrarg(args, &map))
+ return NULL;
+ cat = newdictobject ();
+ if (cat == NULL)
+ return NULL;
+ map = nis_mapname (map);
+ cb.foreach = nis_foreach;
+ cb.data = (char *)cat;
+ yp_get_default_domain(&domain);
+ BGN_SAVE
+ yp_all (domain, map, &cb);
+ END_SAVE
+ return cat;
+}
+
+#define YPPROC_MAPLIST ((u_long)11)
+#define YPPROG ((u_long)100004)
+#define YPVERS ((u_long)2)
+
+typedef char *domainname;
+typedef char *mapname;
+
+enum nisstat {
+ NIS_TRUE = 1,
+ NIS_NOMORE = 2,
+ NIS_FALSE = 0,
+ NIS_NOMAP = -1,
+ NIS_NODOM = -2,
+ NIS_NOKEY = -3,
+ NIS_BADOP = -4,
+ NIS_BADDB = -5,
+ NIS_YPERR = -6,
+ NIS_BADARGS = -7,
+ NIS_VERS = -8
+};
+typedef enum nisstat nisstat;
+
+struct nismaplist {
+ mapname map;
+ struct nismaplist *next;
+};
+typedef struct nismaplist nismaplist;
+
+struct nisresp_maplist {
+ nisstat stat;
+ nismaplist *maps;
+};
+typedef struct nisresp_maplist nisresp_maplist;
+
+static struct timeval TIMEOUT = { 25, 0 };
+
+static
+bool_t
+nis_xdr_domainname(xdrs, objp)
+ XDR *xdrs;
+ domainname *objp;
+{
+ if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+static
+bool_t
+nis_xdr_mapname(xdrs, objp)
+ XDR *xdrs;
+ mapname *objp;
+{
+ if (!xdr_string(xdrs, objp, YPMAXMAP)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+static
+bool_t
+nis_xdr_ypmaplist(xdrs, objp)
+ XDR *xdrs;
+ nismaplist *objp;
+{
+ if (!nis_xdr_mapname(xdrs, &objp->map)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(nismaplist), nis_xdr_ypmaplist)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+static
+bool_t
+nis_xdr_ypstat(xdrs, objp)
+ XDR *xdrs;
+ nisstat *objp;
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+static
+bool_t
+nis_xdr_ypresp_maplist(xdrs, objp)
+ XDR *xdrs;
+ nisresp_maplist *objp;
+{
+ if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **)&objp->maps, sizeof(nismaplist), nis_xdr_ypmaplist)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+static
+nisresp_maplist *
+nisproc_maplist_2(argp, clnt)
+ domainname *argp;
+ CLIENT *clnt;
+{
+ static nisresp_maplist res;
+
+#ifdef hpux
+ memset(&res, 0, sizeof(res));
+#else hpux
+ memset(&res, sizeof(res));
+#endif hpux
+ if (clnt_call(clnt, YPPROC_MAPLIST, nis_xdr_domainname, argp, nis_xdr_ypresp_maplist
+, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+static
+nismaplist *
+nis_maplist ()
+{
+nisresp_maplist *list;
+char *dom;
+CLIENT *cl, *clnt_create();
+char *server;
+
+ yp_get_default_domain (&dom);
+ yp_master (dom, aliases[0].map, &server);
+ cl = clnt_create(server, YPPROG, YPVERS, "tcp");
+ if (cl == NULL) {
+ clnt_pcreateerror(server);
+ return NULL;
+ }
+ list = nisproc_maplist_2 (&dom, cl);
+ if (list == NULL)
+ return NULL;
+ if (list->stat != NIS_TRUE)
+ return NULL;
+ return list->maps;
+}
+
+static object *
+nis_maps (self, args)
+ object *self;
+ object *args;
+{
+nismaplist *maps;
+object *list;
+
+ if ((maps = nis_maplist ()) == NULL)
+ return NULL;
+ if ((list = newlistobject(0)) == NULL)
+ return NULL;
+ BGN_SAVE
+ for (maps = maps->next; maps; maps = maps->next)
+ addlistitem (list, newstringobject (maps->map));
+ END_SAVE
+ return list;
+}
+
+static struct methodlist nis_methods[] = {
+ {"match", nis_match},
+ {"cat", nis_cat},
+ {"maps", nis_maps},
+ {NULL, NULL} /* Sentinel */
+};
+
+void
+initnis ()
+{
+ (void) initmodule("nis", nis_methods);
+}