ยปCore Development>Code coverage>Modules/nismodule.c

Python code coverage for Modules/nismodule.c

#countcontent
1n/a/***********************************************************
2n/a Written by:
3n/a Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
4n/a B&O group,
5n/a Faculteit der Informatica,
6n/a Universiteit Twente,
7n/a Enschede,
8n/a the Netherlands.
9n/a******************************************************************/
10n/a
11n/a/* NIS module implementation */
12n/a
13n/a#include "Python.h"
14n/a
15n/a#include <sys/time.h>
16n/a#include <sys/types.h>
17n/a#include <rpc/rpc.h>
18n/a#include <rpcsvc/yp_prot.h>
19n/a#include <rpcsvc/ypclnt.h>
20n/a
21n/a#ifdef __sgi
22n/a/* This is missing from rpcsvc/ypclnt.h */
23n/aextern int yp_get_default_domain(char **);
24n/a#endif
25n/a
26n/aPyDoc_STRVAR(get_default_domain__doc__,
27n/a"get_default_domain() -> str\n\
28n/aCorresponds to the C library yp_get_default_domain() call, returning\n\
29n/athe default NIS domain.\n");
30n/a
31n/aPyDoc_STRVAR(match__doc__,
32n/a"match(key, map, domain = defaultdomain)\n\
33n/aCorresponds to the C library yp_match() call, returning the value of\n\
34n/akey in the given map. Optionally domain can be specified but it\n\
35n/adefaults to the system default domain.\n");
36n/a
37n/aPyDoc_STRVAR(cat__doc__,
38n/a"cat(map, domain = defaultdomain)\n\
39n/aReturns the entire map as a dictionary. Optionally domain can be\n\
40n/aspecified but it defaults to the system default domain.\n");
41n/a
42n/aPyDoc_STRVAR(maps__doc__,
43n/a"maps(domain = defaultdomain)\n\
44n/aReturns an array of all available NIS maps within a domain. If domain\n\
45n/ais not specified it defaults to the system default domain.\n");
46n/a
47n/astatic PyObject *NisError;
48n/a
49n/astatic PyObject *
50n/anis_error (int err)
51n/a{
52n/a PyErr_SetString(NisError, yperr_string(err));
53n/a return NULL;
54n/a}
55n/a
56n/astatic struct nis_map {
57n/a char *alias;
58n/a char *map;
59n/a int fix;
60n/a} aliases [] = {
61n/a {"passwd", "passwd.byname", 0},
62n/a {"group", "group.byname", 0},
63n/a {"networks", "networks.byaddr", 0},
64n/a {"hosts", "hosts.byname", 0},
65n/a {"protocols", "protocols.bynumber", 0},
66n/a {"services", "services.byname", 0},
67n/a {"aliases", "mail.aliases", 1}, /* created with 'makedbm -a' */
68n/a {"ethers", "ethers.byname", 0},
69n/a {0L, 0L, 0}
70n/a};
71n/a
72n/astatic char *
73n/anis_mapname (char *map, int *pfix)
74n/a{
75n/a int i;
76n/a
77n/a *pfix = 0;
78n/a for (i=0; aliases[i].alias != 0L; i++) {
79n/a if (!strcmp (aliases[i].alias, map) || !strcmp (aliases[i].map, map)) {
80n/a *pfix = aliases[i].fix;
81n/a return aliases[i].map;
82n/a }
83n/a }
84n/a
85n/a return map;
86n/a}
87n/a
88n/a#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
89n/atypedef int (*foreachfunc)(unsigned long, char *, int, char *, int, void *);
90n/a#else
91n/atypedef int (*foreachfunc)(int, char *, int, char *, int, char *);
92n/a#endif
93n/a
94n/astruct ypcallback_data {
95n/a PyObject *dict;
96n/a int fix;
97n/a PyThreadState *state;
98n/a};
99n/a
100n/astatic int
101n/anis_foreach (int instatus, char *inkey, int inkeylen, char *inval,
102n/a int invallen, struct ypcallback_data *indata)
103n/a{
104n/a if (instatus == YP_TRUE) {
105n/a PyObject *key;
106n/a PyObject *val;
107n/a int err;
108n/a
109n/a PyEval_RestoreThread(indata->state);
110n/a if (indata->fix) {
111n/a if (inkeylen > 0 && inkey[inkeylen-1] == '\0')
112n/a inkeylen--;
113n/a if (invallen > 0 && inval[invallen-1] == '\0')
114n/a invallen--;
115n/a }
116n/a key = PyUnicode_DecodeFSDefaultAndSize(inkey, inkeylen);
117n/a val = PyUnicode_DecodeFSDefaultAndSize(inval, invallen);
118n/a if (key == NULL || val == NULL) {
119n/a /* XXX error -- don't know how to handle */
120n/a PyErr_Clear();
121n/a Py_XDECREF(key);
122n/a Py_XDECREF(val);
123n/a indata->state = PyEval_SaveThread();
124n/a return 1;
125n/a }
126n/a err = PyDict_SetItem(indata->dict, key, val);
127n/a Py_DECREF(key);
128n/a Py_DECREF(val);
129n/a if (err != 0)
130n/a PyErr_Clear();
131n/a indata->state = PyEval_SaveThread();
132n/a if (err != 0)
133n/a return 1;
134n/a return 0;
135n/a }
136n/a return 1;
137n/a}
138n/a
139n/astatic PyObject *
140n/anis_get_default_domain (PyObject *self)
141n/a{
142n/a char *domain;
143n/a int err;
144n/a PyObject *res;
145n/a
146n/a if ((err = yp_get_default_domain(&domain)) != 0)
147n/a return nis_error(err);
148n/a
149n/a res = PyUnicode_FromStringAndSize (domain, strlen(domain));
150n/a return res;
151n/a}
152n/a
153n/astatic PyObject *
154n/anis_match (PyObject *self, PyObject *args, PyObject *kwdict)
155n/a{
156n/a char *match;
157n/a char *domain = NULL;
158n/a Py_ssize_t keylen;
159n/a int len;
160n/a char *key, *map;
161n/a int err;
162n/a PyObject *ukey, *bkey, *res;
163n/a int fix;
164n/a static char *kwlist[] = {"key", "map", "domain", NULL};
165n/a
166n/a if (!PyArg_ParseTupleAndKeywords(args, kwdict,
167n/a "Us|s:match", kwlist,
168n/a &ukey, &map, &domain))
169n/a return NULL;
170n/a if ((bkey = PyUnicode_EncodeFSDefault(ukey)) == NULL)
171n/a return NULL;
172n/a if (PyBytes_AsStringAndSize(bkey, &key, &keylen) == -1) {
173n/a Py_DECREF(bkey);
174n/a return NULL;
175n/a }
176n/a if (!domain && ((err = yp_get_default_domain(&domain)) != 0)) {
177n/a Py_DECREF(bkey);
178n/a return nis_error(err);
179n/a }
180n/a map = nis_mapname (map, &fix);
181n/a if (fix)
182n/a keylen++;
183n/a Py_BEGIN_ALLOW_THREADS
184n/a err = yp_match (domain, map, key, keylen, &match, &len);
185n/a Py_END_ALLOW_THREADS
186n/a Py_DECREF(bkey);
187n/a if (fix)
188n/a len--;
189n/a if (err != 0)
190n/a return nis_error(err);
191n/a res = PyUnicode_DecodeFSDefaultAndSize(match, len);
192n/a free (match);
193n/a return res;
194n/a}
195n/a
196n/astatic PyObject *
197n/anis_cat (PyObject *self, PyObject *args, PyObject *kwdict)
198n/a{
199n/a char *domain = NULL;
200n/a char *map;
201n/a struct ypall_callback cb;
202n/a struct ypcallback_data data;
203n/a PyObject *dict;
204n/a int err;
205n/a static char *kwlist[] = {"map", "domain", NULL};
206n/a
207n/a if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s|s:cat",
208n/a kwlist, &map, &domain))
209n/a return NULL;
210n/a if (!domain && ((err = yp_get_default_domain(&domain)) != 0))
211n/a return nis_error(err);
212n/a dict = PyDict_New ();
213n/a if (dict == NULL)
214n/a return NULL;
215n/a cb.foreach = (foreachfunc)nis_foreach;
216n/a data.dict = dict;
217n/a map = nis_mapname (map, &data.fix);
218n/a cb.data = (char *)&data;
219n/a data.state = PyEval_SaveThread();
220n/a err = yp_all (domain, map, &cb);
221n/a PyEval_RestoreThread(data.state);
222n/a if (err != 0) {
223n/a Py_DECREF(dict);
224n/a return nis_error(err);
225n/a }
226n/a return dict;
227n/a}
228n/a
229n/a/* These should be u_long on Sun h/w but not on 64-bit h/w.
230n/a This is not portable to machines with 16-bit ints and no prototypes */
231n/a#ifndef YPPROC_MAPLIST
232n/a#define YPPROC_MAPLIST 11
233n/a#endif
234n/a#ifndef YPPROG
235n/a#define YPPROG 100004
236n/a#endif
237n/a#ifndef YPVERS
238n/a#define YPVERS 2
239n/a#endif
240n/a
241n/atypedef char *domainname;
242n/atypedef char *mapname;
243n/a
244n/aenum nisstat {
245n/a NIS_TRUE = 1,
246n/a NIS_NOMORE = 2,
247n/a NIS_FALSE = 0,
248n/a NIS_NOMAP = -1,
249n/a NIS_NODOM = -2,
250n/a NIS_NOKEY = -3,
251n/a NIS_BADOP = -4,
252n/a NIS_BADDB = -5,
253n/a NIS_YPERR = -6,
254n/a NIS_BADARGS = -7,
255n/a NIS_VERS = -8
256n/a};
257n/atypedef enum nisstat nisstat;
258n/a
259n/astruct nismaplist {
260n/a mapname map;
261n/a struct nismaplist *next;
262n/a};
263n/atypedef struct nismaplist nismaplist;
264n/a
265n/astruct nisresp_maplist {
266n/a nisstat stat;
267n/a nismaplist *maps;
268n/a};
269n/atypedef struct nisresp_maplist nisresp_maplist;
270n/a
271n/astatic struct timeval TIMEOUT = { 25, 0 };
272n/a
273n/astatic
274n/abool_t
275n/anis_xdr_domainname(XDR *xdrs, domainname *objp)
276n/a{
277n/a if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
278n/a return (FALSE);
279n/a }
280n/a return (TRUE);
281n/a}
282n/a
283n/astatic
284n/abool_t
285n/anis_xdr_mapname(XDR *xdrs, mapname *objp)
286n/a{
287n/a if (!xdr_string(xdrs, objp, YPMAXMAP)) {
288n/a return (FALSE);
289n/a }
290n/a return (TRUE);
291n/a}
292n/a
293n/astatic
294n/abool_t
295n/anis_xdr_ypmaplist(XDR *xdrs, nismaplist *objp)
296n/a{
297n/a if (!nis_xdr_mapname(xdrs, &objp->map)) {
298n/a return (FALSE);
299n/a }
300n/a if (!xdr_pointer(xdrs, (char **)&objp->next,
301n/a sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
302n/a {
303n/a return (FALSE);
304n/a }
305n/a return (TRUE);
306n/a}
307n/a
308n/astatic
309n/abool_t
310n/anis_xdr_ypstat(XDR *xdrs, nisstat *objp)
311n/a{
312n/a if (!xdr_enum(xdrs, (enum_t *)objp)) {
313n/a return (FALSE);
314n/a }
315n/a return (TRUE);
316n/a}
317n/a
318n/a
319n/astatic
320n/abool_t
321n/anis_xdr_ypresp_maplist(XDR *xdrs, nisresp_maplist *objp)
322n/a{
323n/a if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
324n/a return (FALSE);
325n/a }
326n/a if (!xdr_pointer(xdrs, (char **)&objp->maps,
327n/a sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
328n/a {
329n/a return (FALSE);
330n/a }
331n/a return (TRUE);
332n/a}
333n/a
334n/a
335n/astatic
336n/anisresp_maplist *
337n/anisproc_maplist_2(domainname *argp, CLIENT *clnt)
338n/a{
339n/a static nisresp_maplist res;
340n/a
341n/a memset(&res, 0, sizeof(res));
342n/a if (clnt_call(clnt, YPPROC_MAPLIST,
343n/a (xdrproc_t)nis_xdr_domainname, (caddr_t)argp,
344n/a (xdrproc_t)nis_xdr_ypresp_maplist, (caddr_t)&res,
345n/a TIMEOUT) != RPC_SUCCESS)
346n/a {
347n/a return (NULL);
348n/a }
349n/a return (&res);
350n/a}
351n/a
352n/astatic
353n/anismaplist *
354n/anis_maplist (char *dom)
355n/a{
356n/a nisresp_maplist *list;
357n/a CLIENT *cl;
358n/a char *server = NULL;
359n/a int mapi = 0;
360n/a
361n/a while (!server && aliases[mapi].map != 0L) {
362n/a yp_master (dom, aliases[mapi].map, &server);
363n/a mapi++;
364n/a }
365n/a if (!server) {
366n/a PyErr_SetString(NisError, "No NIS master found for any map");
367n/a return NULL;
368n/a }
369n/a cl = clnt_create(server, YPPROG, YPVERS, "tcp");
370n/a if (cl == NULL) {
371n/a PyErr_SetString(NisError, clnt_spcreateerror(server));
372n/a goto finally;
373n/a }
374n/a list = nisproc_maplist_2 (&dom, cl);
375n/a clnt_destroy(cl);
376n/a if (list == NULL)
377n/a goto finally;
378n/a if (list->stat != NIS_TRUE)
379n/a goto finally;
380n/a
381n/a free(server);
382n/a return list->maps;
383n/a
384n/a finally:
385n/a free(server);
386n/a return NULL;
387n/a}
388n/a
389n/astatic PyObject *
390n/anis_maps (PyObject *self, PyObject *args, PyObject *kwdict)
391n/a{
392n/a char *domain = NULL;
393n/a nismaplist *maps;
394n/a PyObject *list;
395n/a int err;
396n/a static char *kwlist[] = {"domain", NULL};
397n/a
398n/a if (!PyArg_ParseTupleAndKeywords(args, kwdict,
399n/a "|s:maps", kwlist, &domain))
400n/a return NULL;
401n/a if (!domain && ((err = yp_get_default_domain (&domain)) != 0)) {
402n/a nis_error(err);
403n/a return NULL;
404n/a }
405n/a
406n/a if ((maps = nis_maplist (domain)) == NULL)
407n/a return NULL;
408n/a if ((list = PyList_New(0)) == NULL)
409n/a return NULL;
410n/a for (; maps; maps = maps->next) {
411n/a PyObject *str = PyUnicode_FromString(maps->map);
412n/a if (!str || PyList_Append(list, str) < 0)
413n/a {
414n/a Py_DECREF(list);
415n/a list = NULL;
416n/a break;
417n/a }
418n/a Py_DECREF(str);
419n/a }
420n/a /* XXX Shouldn't we free the list of maps now? */
421n/a return list;
422n/a}
423n/a
424n/astatic PyMethodDef nis_methods[] = {
425n/a {"match", (PyCFunction)nis_match,
426n/a METH_VARARGS | METH_KEYWORDS,
427n/a match__doc__},
428n/a {"cat", (PyCFunction)nis_cat,
429n/a METH_VARARGS | METH_KEYWORDS,
430n/a cat__doc__},
431n/a {"maps", (PyCFunction)nis_maps,
432n/a METH_VARARGS | METH_KEYWORDS,
433n/a maps__doc__},
434n/a {"get_default_domain", (PyCFunction)nis_get_default_domain,
435n/a METH_NOARGS,
436n/a get_default_domain__doc__},
437n/a {NULL, NULL} /* Sentinel */
438n/a};
439n/a
440n/aPyDoc_STRVAR(nis__doc__,
441n/a"This module contains functions for accessing NIS maps.\n");
442n/a
443n/astatic struct PyModuleDef nismodule = {
444n/a PyModuleDef_HEAD_INIT,
445n/a "nis",
446n/a nis__doc__,
447n/a -1,
448n/a nis_methods,
449n/a NULL,
450n/a NULL,
451n/a NULL,
452n/a NULL
453n/a};
454n/a
455n/aPyMODINIT_FUNC
456n/aPyInit_nis(void)
457n/a{
458n/a PyObject *m, *d;
459n/a m = PyModule_Create(&nismodule);
460n/a if (m == NULL)
461n/a return NULL;
462n/a d = PyModule_GetDict(m);
463n/a NisError = PyErr_NewException("nis.error", NULL, NULL);
464n/a if (NisError != NULL)
465n/a PyDict_SetItemString(d, "error", NisError);
466n/a return m;
467n/a}