| /*********************************************************** |
| 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 <sys/time.h> |
| #include <sys/types.h> |
| #include <rpc/rpc.h> |
| #include <rpcsvc/yp_prot.h> |
| #include <rpcsvc/ypclnt.h> |
| |
| static object *NisError; |
| |
| static object * |
| nis_error (err) |
| int err; |
| { |
| err_setstr(NisError, yperr_string(err)); |
| return NULL; |
| } |
| |
| 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; |
| } |
| |
| typedef int (*foreachfunc) PROTO((int, char *, int, char *, int, char *)); |
| |
| 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) { |
| object *key = newsizedstringobject(inkey, inkeylen); |
| object *val = newsizedstringobject(inval, invallen); |
| int err; |
| if (key == NULL || val == NULL) { |
| /* XXX error -- don't know how to handle */ |
| err_clear(); |
| XDECREF(key); |
| XDECREF(val); |
| return 1; |
| } |
| err = mappinginsert(indata, key, val); |
| DECREF(key); |
| DECREF(val); |
| if (err != 0) { |
| err_clear(); |
| return 1; |
| } |
| return 0; |
| } |
| return 1; |
| } |
| |
| static object * |
| nis_match (self, args) |
| object *self; |
| object *args; |
| { |
| char *match; |
| char *domain; |
| int keylen, len; |
| char *key, *map; |
| int err; |
| object *res; |
| |
| if (!getargs(args, "(s#s)", &key, &keylen, &map)) |
| return NULL; |
| if ((err = yp_get_default_domain(&domain)) != 0) |
| return nis_error(err); |
| BGN_SAVE |
| map = nis_mapname (map); |
| err = yp_match (domain, map, key, keylen, &match, &len); |
| END_SAVE |
| if (err != 0) |
| return nis_error(err); |
| res = newsizedstringobject (match, len); |
| free (match); |
| return res; |
| } |
| |
| static object * |
| nis_cat (self, args) |
| object *self; |
| object *args; |
| { |
| char *domain; |
| char *map; |
| struct ypall_callback cb; |
| object *cat; |
| int err; |
| |
| if (!getstrarg(args, &map)) |
| return NULL; |
| if ((err = yp_get_default_domain(&domain)) != 0) |
| return nis_error(err); |
| cat = newdictobject (); |
| if (cat == NULL) |
| return NULL; |
| cb.foreach = (foreachfunc)nis_foreach; |
| cb.data = (char *)cat; |
| BGN_SAVE |
| map = nis_mapname (map); |
| err = yp_all (domain, map, &cb); |
| END_SAVE |
| if (err != 0) { |
| DECREF(cat); |
| return nis_error(err); |
| } |
| return cat; |
| } |
| |
| /* These should be u_long on Sun h/w but not on 64-bit h/w. |
| This is not portable to machines with 16-bit ints and no prototypes */ |
| #ifndef YPPROC_MAPLIST |
| #define YPPROC_MAPLIST 11 |
| #endif |
| #ifndef YPPROG |
| #define YPPROG 100004 |
| #endif |
| #ifndef YPVERS |
| #define YPVERS 2 |
| #endif |
| |
| 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; |
| |
| memset(&res, 0, sizeof(res)); |
| if (clnt_call(clnt, YPPROC_MAPLIST, nis_xdr_domainname, (caddr_t)argp, |
| nis_xdr_ypresp_maplist, (caddr_t)&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; |
| for (maps = maps->next; maps; maps = maps->next) { |
| if (addlistitem (list, newstringobject (maps->map)) < 0) { |
| DECREF(list); |
| list = NULL; |
| break; |
| } |
| } |
| /* XXX Shouldn't we free the list of maps now? */ |
| return list; |
| } |
| |
| static struct methodlist nis_methods[] = { |
| {"match", nis_match}, |
| {"cat", nis_cat}, |
| {"maps", nis_maps}, |
| {NULL, NULL} /* Sentinel */ |
| }; |
| |
| void |
| initnis () |
| { |
| object *m, *d; |
| m = initmodule("nis", nis_methods); |
| d = getmoduledict(m); |
| NisError = newstringobject("nis.error"); |
| if (NisError == NULL || dictinsert(d, "error", NisError) != 0) |
| fatal("Cannot define nis.error"); |
| } |