17db96d56Sopenharmony_ci/***********************************************************
27db96d56Sopenharmony_ci    Written by:
37db96d56Sopenharmony_ci    Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
47db96d56Sopenharmony_ci    B&O group,
57db96d56Sopenharmony_ci    Faculteit der Informatica,
67db96d56Sopenharmony_ci    Universiteit Twente,
77db96d56Sopenharmony_ci    Enschede,
87db96d56Sopenharmony_ci    the Netherlands.
97db96d56Sopenharmony_ci******************************************************************/
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ci/* NIS module implementation */
127db96d56Sopenharmony_ci
137db96d56Sopenharmony_ci#include "Python.h"
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ci#include <stdlib.h>               // free()
167db96d56Sopenharmony_ci#include <sys/time.h>
177db96d56Sopenharmony_ci#include <sys/types.h>
187db96d56Sopenharmony_ci#include <rpc/rpc.h>
197db96d56Sopenharmony_ci#include <rpcsvc/yp_prot.h>
207db96d56Sopenharmony_ci#include <rpcsvc/ypclnt.h>
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_ci#ifdef __sgi
237db96d56Sopenharmony_ci/* This is missing from rpcsvc/ypclnt.h */
247db96d56Sopenharmony_ciextern int yp_get_default_domain(char **);
257db96d56Sopenharmony_ci#endif
267db96d56Sopenharmony_ci
277db96d56Sopenharmony_ciPyDoc_STRVAR(get_default_domain__doc__,
287db96d56Sopenharmony_ci"get_default_domain() -> str\n\
297db96d56Sopenharmony_ciCorresponds to the C library yp_get_default_domain() call, returning\n\
307db96d56Sopenharmony_cithe default NIS domain.\n");
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_ciPyDoc_STRVAR(match__doc__,
337db96d56Sopenharmony_ci"match(key, map, domain = defaultdomain)\n\
347db96d56Sopenharmony_ciCorresponds to the C library yp_match() call, returning the value of\n\
357db96d56Sopenharmony_cikey in the given map. Optionally domain can be specified but it\n\
367db96d56Sopenharmony_cidefaults to the system default domain.\n");
377db96d56Sopenharmony_ci
387db96d56Sopenharmony_ciPyDoc_STRVAR(cat__doc__,
397db96d56Sopenharmony_ci"cat(map, domain = defaultdomain)\n\
407db96d56Sopenharmony_ciReturns the entire map as a dictionary. Optionally domain can be\n\
417db96d56Sopenharmony_cispecified but it defaults to the system default domain.\n");
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_ciPyDoc_STRVAR(maps__doc__,
447db96d56Sopenharmony_ci"maps(domain = defaultdomain)\n\
457db96d56Sopenharmony_ciReturns an array of all available NIS maps within a domain. If domain\n\
467db96d56Sopenharmony_ciis not specified it defaults to the system default domain.\n");
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_citypedef struct {
497db96d56Sopenharmony_ci    PyObject *nis_error;
507db96d56Sopenharmony_ci} nis_state;
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_cistatic inline nis_state*
537db96d56Sopenharmony_ciget_nis_state(PyObject *module)
547db96d56Sopenharmony_ci{
557db96d56Sopenharmony_ci    void *state = PyModule_GetState(module);
567db96d56Sopenharmony_ci    assert(state != NULL);
577db96d56Sopenharmony_ci    return (nis_state *)state;
587db96d56Sopenharmony_ci}
597db96d56Sopenharmony_ci
607db96d56Sopenharmony_cistatic int
617db96d56Sopenharmony_cinis_clear(PyObject *m)
627db96d56Sopenharmony_ci{
637db96d56Sopenharmony_ci    Py_CLEAR(get_nis_state(m)->nis_error);
647db96d56Sopenharmony_ci    return 0;
657db96d56Sopenharmony_ci}
667db96d56Sopenharmony_ci
677db96d56Sopenharmony_cistatic int
687db96d56Sopenharmony_cinis_traverse(PyObject *m, visitproc visit, void *arg)
697db96d56Sopenharmony_ci{
707db96d56Sopenharmony_ci    Py_VISIT(get_nis_state(m)->nis_error);
717db96d56Sopenharmony_ci    return 0;
727db96d56Sopenharmony_ci}
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_cistatic void
757db96d56Sopenharmony_cinis_free(void *m)
767db96d56Sopenharmony_ci{
777db96d56Sopenharmony_ci    nis_clear((PyObject *) m);
787db96d56Sopenharmony_ci}
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_cistatic PyObject *
817db96d56Sopenharmony_cinis_error(nis_state *state, int err)
827db96d56Sopenharmony_ci{
837db96d56Sopenharmony_ci    PyErr_SetString(state->nis_error, yperr_string(err));
847db96d56Sopenharmony_ci    return NULL;
857db96d56Sopenharmony_ci}
867db96d56Sopenharmony_ci
877db96d56Sopenharmony_cistatic struct nis_map {
887db96d56Sopenharmony_ci    char *alias;
897db96d56Sopenharmony_ci    char *map;
907db96d56Sopenharmony_ci    int  fix;
917db96d56Sopenharmony_ci} aliases [] = {
927db96d56Sopenharmony_ci    {"passwd",          "passwd.byname",        0},
937db96d56Sopenharmony_ci    {"group",           "group.byname",         0},
947db96d56Sopenharmony_ci    {"networks",        "networks.byaddr",      0},
957db96d56Sopenharmony_ci    {"hosts",           "hosts.byname",         0},
967db96d56Sopenharmony_ci    {"protocols",       "protocols.bynumber",   0},
977db96d56Sopenharmony_ci    {"services",        "services.byname",      0},
987db96d56Sopenharmony_ci    {"aliases",         "mail.aliases",         1}, /* created with 'makedbm -a' */
997db96d56Sopenharmony_ci    {"ethers",          "ethers.byname",        0},
1007db96d56Sopenharmony_ci    {0L,                0L,                     0}
1017db96d56Sopenharmony_ci};
1027db96d56Sopenharmony_ci
1037db96d56Sopenharmony_cistatic char *
1047db96d56Sopenharmony_cinis_mapname(char *map, int *pfix)
1057db96d56Sopenharmony_ci{
1067db96d56Sopenharmony_ci    int i;
1077db96d56Sopenharmony_ci
1087db96d56Sopenharmony_ci    *pfix = 0;
1097db96d56Sopenharmony_ci    for (i=0; aliases[i].alias != 0L; i++) {
1107db96d56Sopenharmony_ci        if (!strcmp (aliases[i].alias, map) || !strcmp (aliases[i].map, map)) {
1117db96d56Sopenharmony_ci            *pfix = aliases[i].fix;
1127db96d56Sopenharmony_ci            return aliases[i].map;
1137db96d56Sopenharmony_ci        }
1147db96d56Sopenharmony_ci    }
1157db96d56Sopenharmony_ci
1167db96d56Sopenharmony_ci    return map;
1177db96d56Sopenharmony_ci}
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_ci#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
1207db96d56Sopenharmony_citypedef int (*foreachfunc)(unsigned long, char *, int, char *, int, void *);
1217db96d56Sopenharmony_ci#else
1227db96d56Sopenharmony_citypedef int (*foreachfunc)(int, char *, int, char *, int, char *);
1237db96d56Sopenharmony_ci#endif
1247db96d56Sopenharmony_ci
1257db96d56Sopenharmony_cistruct ypcallback_data {
1267db96d56Sopenharmony_ci    PyObject            *dict;
1277db96d56Sopenharmony_ci    int                         fix;
1287db96d56Sopenharmony_ci    PyThreadState *state;
1297db96d56Sopenharmony_ci};
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_cistatic int
1327db96d56Sopenharmony_cinis_foreach(int instatus, char *inkey, int inkeylen, char *inval,
1337db96d56Sopenharmony_ci             int invallen, struct ypcallback_data *indata)
1347db96d56Sopenharmony_ci{
1357db96d56Sopenharmony_ci    if (instatus == YP_TRUE) {
1367db96d56Sopenharmony_ci        PyObject *key;
1377db96d56Sopenharmony_ci        PyObject *val;
1387db96d56Sopenharmony_ci        int err;
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ci        PyEval_RestoreThread(indata->state);
1417db96d56Sopenharmony_ci        if (indata->fix) {
1427db96d56Sopenharmony_ci            if (inkeylen > 0 && inkey[inkeylen-1] == '\0')
1437db96d56Sopenharmony_ci            inkeylen--;
1447db96d56Sopenharmony_ci            if (invallen > 0 && inval[invallen-1] == '\0')
1457db96d56Sopenharmony_ci            invallen--;
1467db96d56Sopenharmony_ci        }
1477db96d56Sopenharmony_ci        key = PyUnicode_DecodeFSDefaultAndSize(inkey, inkeylen);
1487db96d56Sopenharmony_ci        val = PyUnicode_DecodeFSDefaultAndSize(inval, invallen);
1497db96d56Sopenharmony_ci        if (key == NULL || val == NULL) {
1507db96d56Sopenharmony_ci            /* XXX error -- don't know how to handle */
1517db96d56Sopenharmony_ci            PyErr_Clear();
1527db96d56Sopenharmony_ci            Py_XDECREF(key);
1537db96d56Sopenharmony_ci            Py_XDECREF(val);
1547db96d56Sopenharmony_ci            indata->state = PyEval_SaveThread();
1557db96d56Sopenharmony_ci            return 1;
1567db96d56Sopenharmony_ci        }
1577db96d56Sopenharmony_ci        err = PyDict_SetItem(indata->dict, key, val);
1587db96d56Sopenharmony_ci        Py_DECREF(key);
1597db96d56Sopenharmony_ci        Py_DECREF(val);
1607db96d56Sopenharmony_ci        if (err != 0)
1617db96d56Sopenharmony_ci            PyErr_Clear();
1627db96d56Sopenharmony_ci        indata->state = PyEval_SaveThread();
1637db96d56Sopenharmony_ci        if (err != 0)
1647db96d56Sopenharmony_ci            return 1;
1657db96d56Sopenharmony_ci        return 0;
1667db96d56Sopenharmony_ci    }
1677db96d56Sopenharmony_ci    return 1;
1687db96d56Sopenharmony_ci}
1697db96d56Sopenharmony_ci
1707db96d56Sopenharmony_cistatic PyObject *
1717db96d56Sopenharmony_cinis_get_default_domain(PyObject *module, PyObject *Py_UNUSED(ignored))
1727db96d56Sopenharmony_ci{
1737db96d56Sopenharmony_ci    char *domain;
1747db96d56Sopenharmony_ci    int err;
1757db96d56Sopenharmony_ci    PyObject *res;
1767db96d56Sopenharmony_ci    nis_state *state = get_nis_state(module);
1777db96d56Sopenharmony_ci    if ((err = yp_get_default_domain(&domain)) != 0) {
1787db96d56Sopenharmony_ci        return nis_error(state, err);
1797db96d56Sopenharmony_ci    }
1807db96d56Sopenharmony_ci
1817db96d56Sopenharmony_ci    res = PyUnicode_FromStringAndSize (domain, strlen(domain));
1827db96d56Sopenharmony_ci    return res;
1837db96d56Sopenharmony_ci}
1847db96d56Sopenharmony_ci
1857db96d56Sopenharmony_cistatic PyObject *
1867db96d56Sopenharmony_cinis_match(PyObject *module, PyObject *args, PyObject *kwdict)
1877db96d56Sopenharmony_ci{
1887db96d56Sopenharmony_ci    char *match;
1897db96d56Sopenharmony_ci    char *domain = NULL;
1907db96d56Sopenharmony_ci    Py_ssize_t keylen;
1917db96d56Sopenharmony_ci    int len;
1927db96d56Sopenharmony_ci    char *key, *map;
1937db96d56Sopenharmony_ci    int err;
1947db96d56Sopenharmony_ci    PyObject *ukey, *bkey, *res;
1957db96d56Sopenharmony_ci    int fix;
1967db96d56Sopenharmony_ci    static char *kwlist[] = {"key", "map", "domain", NULL};
1977db96d56Sopenharmony_ci
1987db96d56Sopenharmony_ci    if (!PyArg_ParseTupleAndKeywords(args, kwdict,
1997db96d56Sopenharmony_ci                                     "Us|s:match", kwlist,
2007db96d56Sopenharmony_ci                                     &ukey, &map, &domain)) {
2017db96d56Sopenharmony_ci        return NULL;
2027db96d56Sopenharmony_ci    }
2037db96d56Sopenharmony_ci    if ((bkey = PyUnicode_EncodeFSDefault(ukey)) == NULL) {
2047db96d56Sopenharmony_ci        return NULL;
2057db96d56Sopenharmony_ci    }
2067db96d56Sopenharmony_ci    /* check for embedded null bytes */
2077db96d56Sopenharmony_ci    if (PyBytes_AsStringAndSize(bkey, &key, &keylen) == -1) {
2087db96d56Sopenharmony_ci        Py_DECREF(bkey);
2097db96d56Sopenharmony_ci        return NULL;
2107db96d56Sopenharmony_ci    }
2117db96d56Sopenharmony_ci
2127db96d56Sopenharmony_ci    nis_state *state = get_nis_state(module);
2137db96d56Sopenharmony_ci    if (!domain && ((err = yp_get_default_domain(&domain)) != 0)) {
2147db96d56Sopenharmony_ci        Py_DECREF(bkey);
2157db96d56Sopenharmony_ci        return nis_error(state, err);
2167db96d56Sopenharmony_ci    }
2177db96d56Sopenharmony_ci    map = nis_mapname (map, &fix);
2187db96d56Sopenharmony_ci    if (fix)
2197db96d56Sopenharmony_ci        keylen++;
2207db96d56Sopenharmony_ci    Py_BEGIN_ALLOW_THREADS
2217db96d56Sopenharmony_ci    err = yp_match (domain, map, key, keylen, &match, &len);
2227db96d56Sopenharmony_ci    Py_END_ALLOW_THREADS
2237db96d56Sopenharmony_ci    Py_DECREF(bkey);
2247db96d56Sopenharmony_ci    if (fix)
2257db96d56Sopenharmony_ci        len--;
2267db96d56Sopenharmony_ci    if (err != 0) {
2277db96d56Sopenharmony_ci        return nis_error(state, err);
2287db96d56Sopenharmony_ci    }
2297db96d56Sopenharmony_ci    res = PyUnicode_DecodeFSDefaultAndSize(match, len);
2307db96d56Sopenharmony_ci    free (match);
2317db96d56Sopenharmony_ci    return res;
2327db96d56Sopenharmony_ci}
2337db96d56Sopenharmony_ci
2347db96d56Sopenharmony_cistatic PyObject *
2357db96d56Sopenharmony_cinis_cat(PyObject *module, PyObject *args, PyObject *kwdict)
2367db96d56Sopenharmony_ci{
2377db96d56Sopenharmony_ci    char *domain = NULL;
2387db96d56Sopenharmony_ci    char *map;
2397db96d56Sopenharmony_ci    struct ypall_callback cb;
2407db96d56Sopenharmony_ci    struct ypcallback_data data;
2417db96d56Sopenharmony_ci    PyObject *dict;
2427db96d56Sopenharmony_ci    int err;
2437db96d56Sopenharmony_ci    static char *kwlist[] = {"map", "domain", NULL};
2447db96d56Sopenharmony_ci
2457db96d56Sopenharmony_ci    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s|s:cat",
2467db96d56Sopenharmony_ci                                     kwlist, &map, &domain)) {
2477db96d56Sopenharmony_ci        return NULL;
2487db96d56Sopenharmony_ci    }
2497db96d56Sopenharmony_ci    nis_state *state = get_nis_state(module);
2507db96d56Sopenharmony_ci    if (!domain && ((err = yp_get_default_domain(&domain)) != 0)) {
2517db96d56Sopenharmony_ci        return nis_error(state, err);
2527db96d56Sopenharmony_ci    }
2537db96d56Sopenharmony_ci    dict = PyDict_New ();
2547db96d56Sopenharmony_ci    if (dict == NULL)
2557db96d56Sopenharmony_ci        return NULL;
2567db96d56Sopenharmony_ci    cb.foreach = (foreachfunc)nis_foreach;
2577db96d56Sopenharmony_ci    data.dict = dict;
2587db96d56Sopenharmony_ci    map = nis_mapname (map, &data.fix);
2597db96d56Sopenharmony_ci    cb.data = (char *)&data;
2607db96d56Sopenharmony_ci    data.state = PyEval_SaveThread();
2617db96d56Sopenharmony_ci    err = yp_all (domain, map, &cb);
2627db96d56Sopenharmony_ci    PyEval_RestoreThread(data.state);
2637db96d56Sopenharmony_ci    if (err != 0) {
2647db96d56Sopenharmony_ci        Py_DECREF(dict);
2657db96d56Sopenharmony_ci        return nis_error(state, err);
2667db96d56Sopenharmony_ci    }
2677db96d56Sopenharmony_ci    return dict;
2687db96d56Sopenharmony_ci}
2697db96d56Sopenharmony_ci
2707db96d56Sopenharmony_ci/* These should be u_long on Sun h/w but not on 64-bit h/w.
2717db96d56Sopenharmony_ci   This is not portable to machines with 16-bit ints and no prototypes */
2727db96d56Sopenharmony_ci#ifndef YPPROC_MAPLIST
2737db96d56Sopenharmony_ci#define YPPROC_MAPLIST  11
2747db96d56Sopenharmony_ci#endif
2757db96d56Sopenharmony_ci#ifndef YPPROG
2767db96d56Sopenharmony_ci#define YPPROG          100004
2777db96d56Sopenharmony_ci#endif
2787db96d56Sopenharmony_ci#ifndef YPVERS
2797db96d56Sopenharmony_ci#define YPVERS          2
2807db96d56Sopenharmony_ci#endif
2817db96d56Sopenharmony_ci
2827db96d56Sopenharmony_citypedef char *domainname;
2837db96d56Sopenharmony_citypedef char *mapname;
2847db96d56Sopenharmony_ci
2857db96d56Sopenharmony_cienum nisstat {
2867db96d56Sopenharmony_ci    NIS_TRUE = 1,
2877db96d56Sopenharmony_ci    NIS_NOMORE = 2,
2887db96d56Sopenharmony_ci    NIS_FALSE = 0,
2897db96d56Sopenharmony_ci    NIS_NOMAP = -1,
2907db96d56Sopenharmony_ci    NIS_NODOM = -2,
2917db96d56Sopenharmony_ci    NIS_NOKEY = -3,
2927db96d56Sopenharmony_ci    NIS_BADOP = -4,
2937db96d56Sopenharmony_ci    NIS_BADDB = -5,
2947db96d56Sopenharmony_ci    NIS_YPERR = -6,
2957db96d56Sopenharmony_ci    NIS_BADARGS = -7,
2967db96d56Sopenharmony_ci    NIS_VERS = -8
2977db96d56Sopenharmony_ci};
2987db96d56Sopenharmony_citypedef enum nisstat nisstat;
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_cistruct nismaplist {
3017db96d56Sopenharmony_ci    mapname map;
3027db96d56Sopenharmony_ci    struct nismaplist *next;
3037db96d56Sopenharmony_ci};
3047db96d56Sopenharmony_citypedef struct nismaplist nismaplist;
3057db96d56Sopenharmony_ci
3067db96d56Sopenharmony_cistruct nisresp_maplist {
3077db96d56Sopenharmony_ci    nisstat stat;
3087db96d56Sopenharmony_ci    nismaplist *maps;
3097db96d56Sopenharmony_ci};
3107db96d56Sopenharmony_citypedef struct nisresp_maplist nisresp_maplist;
3117db96d56Sopenharmony_ci
3127db96d56Sopenharmony_cistatic struct timeval TIMEOUT = { 25, 0 };
3137db96d56Sopenharmony_ci
3147db96d56Sopenharmony_cistatic
3157db96d56Sopenharmony_cibool_t
3167db96d56Sopenharmony_cinis_xdr_domainname(XDR *xdrs, domainname *objp)
3177db96d56Sopenharmony_ci{
3187db96d56Sopenharmony_ci    if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
3197db96d56Sopenharmony_ci        return (FALSE);
3207db96d56Sopenharmony_ci    }
3217db96d56Sopenharmony_ci    return (TRUE);
3227db96d56Sopenharmony_ci}
3237db96d56Sopenharmony_ci
3247db96d56Sopenharmony_cistatic
3257db96d56Sopenharmony_cibool_t
3267db96d56Sopenharmony_cinis_xdr_mapname(XDR *xdrs, mapname *objp)
3277db96d56Sopenharmony_ci{
3287db96d56Sopenharmony_ci    if (!xdr_string(xdrs, objp, YPMAXMAP)) {
3297db96d56Sopenharmony_ci        return (FALSE);
3307db96d56Sopenharmony_ci    }
3317db96d56Sopenharmony_ci    return (TRUE);
3327db96d56Sopenharmony_ci}
3337db96d56Sopenharmony_ci
3347db96d56Sopenharmony_cistatic
3357db96d56Sopenharmony_cibool_t
3367db96d56Sopenharmony_cinis_xdr_ypmaplist(XDR *xdrs, nismaplist *objp)
3377db96d56Sopenharmony_ci{
3387db96d56Sopenharmony_ci    if (!nis_xdr_mapname(xdrs, &objp->map)) {
3397db96d56Sopenharmony_ci        return (FALSE);
3407db96d56Sopenharmony_ci    }
3417db96d56Sopenharmony_ci    if (!xdr_pointer(xdrs, (char **)&objp->next,
3427db96d56Sopenharmony_ci                     sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
3437db96d56Sopenharmony_ci    {
3447db96d56Sopenharmony_ci        return (FALSE);
3457db96d56Sopenharmony_ci    }
3467db96d56Sopenharmony_ci    return (TRUE);
3477db96d56Sopenharmony_ci}
3487db96d56Sopenharmony_ci
3497db96d56Sopenharmony_cistatic
3507db96d56Sopenharmony_cibool_t
3517db96d56Sopenharmony_cinis_xdr_ypstat(XDR *xdrs, nisstat *objp)
3527db96d56Sopenharmony_ci{
3537db96d56Sopenharmony_ci    if (!xdr_enum(xdrs, (enum_t *)objp)) {
3547db96d56Sopenharmony_ci        return (FALSE);
3557db96d56Sopenharmony_ci    }
3567db96d56Sopenharmony_ci    return (TRUE);
3577db96d56Sopenharmony_ci}
3587db96d56Sopenharmony_ci
3597db96d56Sopenharmony_ci
3607db96d56Sopenharmony_cistatic
3617db96d56Sopenharmony_cibool_t
3627db96d56Sopenharmony_cinis_xdr_ypresp_maplist(XDR *xdrs, nisresp_maplist *objp)
3637db96d56Sopenharmony_ci{
3647db96d56Sopenharmony_ci    if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
3657db96d56Sopenharmony_ci        return (FALSE);
3667db96d56Sopenharmony_ci    }
3677db96d56Sopenharmony_ci    if (!xdr_pointer(xdrs, (char **)&objp->maps,
3687db96d56Sopenharmony_ci                     sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
3697db96d56Sopenharmony_ci    {
3707db96d56Sopenharmony_ci        return (FALSE);
3717db96d56Sopenharmony_ci    }
3727db96d56Sopenharmony_ci    return (TRUE);
3737db96d56Sopenharmony_ci}
3747db96d56Sopenharmony_ci
3757db96d56Sopenharmony_ci
3767db96d56Sopenharmony_cistatic
3777db96d56Sopenharmony_cinisresp_maplist *
3787db96d56Sopenharmony_cinisproc_maplist_2(domainname *argp, CLIENT *clnt)
3797db96d56Sopenharmony_ci{
3807db96d56Sopenharmony_ci    static nisresp_maplist res;
3817db96d56Sopenharmony_ci
3827db96d56Sopenharmony_ci    memset(&res, 0, sizeof(res));
3837db96d56Sopenharmony_ci    if (clnt_call(clnt, YPPROC_MAPLIST,
3847db96d56Sopenharmony_ci                  (xdrproc_t)nis_xdr_domainname, (caddr_t)argp,
3857db96d56Sopenharmony_ci                  (xdrproc_t)nis_xdr_ypresp_maplist, (caddr_t)&res,
3867db96d56Sopenharmony_ci                  TIMEOUT) != RPC_SUCCESS)
3877db96d56Sopenharmony_ci    {
3887db96d56Sopenharmony_ci        return (NULL);
3897db96d56Sopenharmony_ci    }
3907db96d56Sopenharmony_ci    return (&res);
3917db96d56Sopenharmony_ci}
3927db96d56Sopenharmony_ci
3937db96d56Sopenharmony_cistatic
3947db96d56Sopenharmony_cinismaplist *
3957db96d56Sopenharmony_cinis_maplist(nis_state *state, char *dom)
3967db96d56Sopenharmony_ci{
3977db96d56Sopenharmony_ci    nisresp_maplist *list;
3987db96d56Sopenharmony_ci    CLIENT *cl;
3997db96d56Sopenharmony_ci    char *server = NULL;
4007db96d56Sopenharmony_ci    int mapi = 0;
4017db96d56Sopenharmony_ci
4027db96d56Sopenharmony_ci    while (!server && aliases[mapi].map != 0L) {
4037db96d56Sopenharmony_ci        yp_master (dom, aliases[mapi].map, &server);
4047db96d56Sopenharmony_ci        mapi++;
4057db96d56Sopenharmony_ci    }
4067db96d56Sopenharmony_ci    if (!server) {
4077db96d56Sopenharmony_ci        PyErr_SetString(state->nis_error, "No NIS master found for any map");
4087db96d56Sopenharmony_ci        return NULL;
4097db96d56Sopenharmony_ci    }
4107db96d56Sopenharmony_ci    cl = clnt_create(server, YPPROG, YPVERS, "tcp");
4117db96d56Sopenharmony_ci    if (cl == NULL) {
4127db96d56Sopenharmony_ci        PyErr_SetString(state->nis_error, clnt_spcreateerror(server));
4137db96d56Sopenharmony_ci        goto finally;
4147db96d56Sopenharmony_ci    }
4157db96d56Sopenharmony_ci    list = nisproc_maplist_2 (&dom, cl);
4167db96d56Sopenharmony_ci    clnt_destroy(cl);
4177db96d56Sopenharmony_ci    if (list == NULL)
4187db96d56Sopenharmony_ci        goto finally;
4197db96d56Sopenharmony_ci    if (list->stat != NIS_TRUE)
4207db96d56Sopenharmony_ci        goto finally;
4217db96d56Sopenharmony_ci
4227db96d56Sopenharmony_ci    free(server);
4237db96d56Sopenharmony_ci    return list->maps;
4247db96d56Sopenharmony_ci
4257db96d56Sopenharmony_ci  finally:
4267db96d56Sopenharmony_ci    free(server);
4277db96d56Sopenharmony_ci    return NULL;
4287db96d56Sopenharmony_ci}
4297db96d56Sopenharmony_ci
4307db96d56Sopenharmony_cistatic PyObject *
4317db96d56Sopenharmony_cinis_maps (PyObject *module, PyObject *args, PyObject *kwdict)
4327db96d56Sopenharmony_ci{
4337db96d56Sopenharmony_ci    char *domain = NULL;
4347db96d56Sopenharmony_ci    nismaplist *maps;
4357db96d56Sopenharmony_ci    PyObject *list;
4367db96d56Sopenharmony_ci    int err;
4377db96d56Sopenharmony_ci    static char *kwlist[] = {"domain", NULL};
4387db96d56Sopenharmony_ci
4397db96d56Sopenharmony_ci    if (!PyArg_ParseTupleAndKeywords(args, kwdict,
4407db96d56Sopenharmony_ci                                     "|s:maps", kwlist, &domain)) {
4417db96d56Sopenharmony_ci        return NULL;
4427db96d56Sopenharmony_ci    }
4437db96d56Sopenharmony_ci
4447db96d56Sopenharmony_ci    nis_state *state = get_nis_state(module);
4457db96d56Sopenharmony_ci    if (!domain && ((err = yp_get_default_domain (&domain)) != 0)) {
4467db96d56Sopenharmony_ci        nis_error(state, err);
4477db96d56Sopenharmony_ci        return NULL;
4487db96d56Sopenharmony_ci    }
4497db96d56Sopenharmony_ci
4507db96d56Sopenharmony_ci    if ((maps = nis_maplist(state, domain)) == NULL) {
4517db96d56Sopenharmony_ci        return NULL;
4527db96d56Sopenharmony_ci    }
4537db96d56Sopenharmony_ci    if ((list = PyList_New(0)) == NULL) {
4547db96d56Sopenharmony_ci        return NULL;
4557db96d56Sopenharmony_ci    }
4567db96d56Sopenharmony_ci    for (; maps; maps = maps->next) {
4577db96d56Sopenharmony_ci        PyObject *str = PyUnicode_FromString(maps->map);
4587db96d56Sopenharmony_ci        if (!str || PyList_Append(list, str) < 0)
4597db96d56Sopenharmony_ci        {
4607db96d56Sopenharmony_ci            Py_XDECREF(str);
4617db96d56Sopenharmony_ci            Py_DECREF(list);
4627db96d56Sopenharmony_ci            list = NULL;
4637db96d56Sopenharmony_ci            break;
4647db96d56Sopenharmony_ci        }
4657db96d56Sopenharmony_ci        Py_DECREF(str);
4667db96d56Sopenharmony_ci    }
4677db96d56Sopenharmony_ci    /* XXX Shouldn't we free the list of maps now? */
4687db96d56Sopenharmony_ci    return list;
4697db96d56Sopenharmony_ci}
4707db96d56Sopenharmony_ci
4717db96d56Sopenharmony_cistatic PyMethodDef nis_methods[] = {
4727db96d56Sopenharmony_ci    {"match",                   _PyCFunction_CAST(nis_match),
4737db96d56Sopenharmony_ci                                    METH_VARARGS | METH_KEYWORDS,
4747db96d56Sopenharmony_ci                                    match__doc__},
4757db96d56Sopenharmony_ci    {"cat",                     _PyCFunction_CAST(nis_cat),
4767db96d56Sopenharmony_ci                                    METH_VARARGS | METH_KEYWORDS,
4777db96d56Sopenharmony_ci                                    cat__doc__},
4787db96d56Sopenharmony_ci    {"maps",                    _PyCFunction_CAST(nis_maps),
4797db96d56Sopenharmony_ci                                    METH_VARARGS | METH_KEYWORDS,
4807db96d56Sopenharmony_ci                                    maps__doc__},
4817db96d56Sopenharmony_ci    {"get_default_domain",      nis_get_default_domain,
4827db96d56Sopenharmony_ci                                    METH_NOARGS,
4837db96d56Sopenharmony_ci                                    get_default_domain__doc__},
4847db96d56Sopenharmony_ci    {NULL,                      NULL}            /* Sentinel */
4857db96d56Sopenharmony_ci};
4867db96d56Sopenharmony_ci
4877db96d56Sopenharmony_cistatic int
4887db96d56Sopenharmony_cinis_exec(PyObject *module)
4897db96d56Sopenharmony_ci{
4907db96d56Sopenharmony_ci    nis_state* state = get_nis_state(module);
4917db96d56Sopenharmony_ci    state->nis_error = PyErr_NewException("nis.error", NULL, NULL);
4927db96d56Sopenharmony_ci    if (state->nis_error == NULL) {
4937db96d56Sopenharmony_ci        return -1;
4947db96d56Sopenharmony_ci    }
4957db96d56Sopenharmony_ci
4967db96d56Sopenharmony_ci    Py_INCREF(state->nis_error);
4977db96d56Sopenharmony_ci    if (PyModule_AddObject(module, "error", state->nis_error) < 0) {
4987db96d56Sopenharmony_ci        Py_DECREF(state->nis_error);
4997db96d56Sopenharmony_ci        return -1;
5007db96d56Sopenharmony_ci    }
5017db96d56Sopenharmony_ci    return 0;
5027db96d56Sopenharmony_ci}
5037db96d56Sopenharmony_ci
5047db96d56Sopenharmony_cistatic PyModuleDef_Slot nis_slots[] = {
5057db96d56Sopenharmony_ci    {Py_mod_exec, nis_exec},
5067db96d56Sopenharmony_ci    {0, NULL}
5077db96d56Sopenharmony_ci};
5087db96d56Sopenharmony_ci
5097db96d56Sopenharmony_ciPyDoc_STRVAR(nis__doc__,
5107db96d56Sopenharmony_ci"This module contains functions for accessing NIS maps.\n");
5117db96d56Sopenharmony_ci
5127db96d56Sopenharmony_cistatic struct PyModuleDef nismodule = {
5137db96d56Sopenharmony_ci    PyModuleDef_HEAD_INIT,
5147db96d56Sopenharmony_ci    .m_name = "nis",
5157db96d56Sopenharmony_ci    .m_doc = nis__doc__,
5167db96d56Sopenharmony_ci    .m_size = sizeof(nis_state),
5177db96d56Sopenharmony_ci    .m_methods = nis_methods,
5187db96d56Sopenharmony_ci    .m_traverse = nis_traverse,
5197db96d56Sopenharmony_ci    .m_clear = nis_clear,
5207db96d56Sopenharmony_ci    .m_free = nis_free,
5217db96d56Sopenharmony_ci    .m_slots = nis_slots,
5227db96d56Sopenharmony_ci};
5237db96d56Sopenharmony_ci
5247db96d56Sopenharmony_ciPyMODINIT_FUNC
5257db96d56Sopenharmony_ciPyInit_nis(void)
5267db96d56Sopenharmony_ci{
5277db96d56Sopenharmony_ci    if (PyErr_WarnEx(PyExc_DeprecationWarning,
5287db96d56Sopenharmony_ci                     "'nis' is deprecated and slated for removal in "
5297db96d56Sopenharmony_ci                     "Python 3.13",
5307db96d56Sopenharmony_ci                     7)) {
5317db96d56Sopenharmony_ci        return NULL;
5327db96d56Sopenharmony_ci    }
5337db96d56Sopenharmony_ci    return PyModuleDef_Init(&nismodule);
5347db96d56Sopenharmony_ci}
535