1 /***********************************************************
3 Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
5 Faculteit der Informatica,
9 ******************************************************************/
11 /* NIS module implementation */
16 #include <sys/types.h>
18 #include <rpcsvc/yp_prot.h>
19 #include <rpcsvc/ypclnt.h>
22 /* This is missing from rpcsvc/ypclnt.h */
23 extern int yp_get_default_domain(char **);
26 PyDoc_STRVAR(get_default_domain__doc__
,
27 "get_default_domain() -> str\n\
28 Corresponds to the C library yp_get_default_domain() call, returning\n\
29 the default NIS domain.\n");
31 PyDoc_STRVAR(match__doc__
,
32 "match(key, map, domain = defaultdomain)\n\
33 Corresponds to the C library yp_match() call, returning the value of\n\
34 key in the given map. Optionally domain can be specified but it\n\
35 defaults to the system default domain.\n");
37 PyDoc_STRVAR(cat__doc__
,
38 "cat(map, domain = defaultdomain)\n\
39 Returns the entire map as a dictionary. Optionally domain can be\n\
40 specified but it defaults to the system default domain.\n");
42 PyDoc_STRVAR(maps__doc__
,
43 "maps(domain = defaultdomain)\n\
44 Returns an array of all available NIS maps within a domain. If domain\n\
45 is not specified it defaults to the system default domain.\n");
47 static PyObject
*NisError
;
52 PyErr_SetString(NisError
, yperr_string(err
));
56 static struct nis_map
{
61 {"passwd", "passwd.byname", 0},
62 {"group", "group.byname", 0},
63 {"networks", "networks.byaddr", 0},
64 {"hosts", "hosts.byname", 0},
65 {"protocols", "protocols.bynumber", 0},
66 {"services", "services.byname", 0},
67 {"aliases", "mail.aliases", 1}, /* created with 'makedbm -a' */
68 {"ethers", "ethers.byname", 0},
73 nis_mapname (char *map
, int *pfix
)
78 for (i
=0; aliases
[i
].alias
!= 0L; i
++) {
79 if (!strcmp (aliases
[i
].alias
, map
)) {
80 *pfix
= aliases
[i
].fix
;
81 return aliases
[i
].map
;
83 if (!strcmp (aliases
[i
].map
, map
)) {
84 *pfix
= aliases
[i
].fix
;
85 return aliases
[i
].map
;
92 #if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
93 typedef int (*foreachfunc
)(unsigned long, char *, int, char *, int, void *);
95 typedef int (*foreachfunc
)(int, char *, int, char *, int, char *);
98 struct ypcallback_data
{
101 PyThreadState
*state
;
105 nis_foreach (int instatus
, char *inkey
, int inkeylen
, char *inval
,
106 int invallen
, struct ypcallback_data
*indata
)
108 if (instatus
== YP_TRUE
) {
113 PyEval_RestoreThread(indata
->state
);
115 if (inkeylen
> 0 && inkey
[inkeylen
-1] == '\0')
117 if (invallen
> 0 && inval
[invallen
-1] == '\0')
120 key
= PyString_FromStringAndSize(inkey
, inkeylen
);
121 val
= PyString_FromStringAndSize(inval
, invallen
);
122 if (key
== NULL
|| val
== NULL
) {
123 /* XXX error -- don't know how to handle */
129 err
= PyDict_SetItem(indata
->dict
, key
, val
);
134 indata
->state
= PyEval_SaveThread();
143 nis_get_default_domain (PyObject
*self
)
149 if ((err
= yp_get_default_domain(&domain
)) != 0)
150 return nis_error(err
);
152 res
= PyString_FromStringAndSize (domain
, strlen(domain
));
157 nis_match (PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
166 static char *kwlist
[] = {"key", "map", "domain", NULL
};
168 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
,
169 "t#s|s:match", kwlist
,
170 &key
, &keylen
, &map
, &domain
))
172 if (!domain
&& ((err
= yp_get_default_domain(&domain
)) != 0))
173 return nis_error(err
);
174 map
= nis_mapname (map
, &fix
);
177 Py_BEGIN_ALLOW_THREADS
178 err
= yp_match (domain
, map
, key
, keylen
, &match
, &len
);
183 return nis_error(err
);
184 res
= PyString_FromStringAndSize (match
, len
);
190 nis_cat (PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
194 struct ypall_callback cb
;
195 struct ypcallback_data data
;
198 static char *kwlist
[] = {"map", "domain", NULL
};
200 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
, "s|s:cat",
201 kwlist
, &map
, &domain
))
203 if (!domain
&& ((err
= yp_get_default_domain(&domain
)) != 0))
204 return nis_error(err
);
205 dict
= PyDict_New ();
208 cb
.foreach
= (foreachfunc
)nis_foreach
;
210 map
= nis_mapname (map
, &data
.fix
);
211 cb
.data
= (char *)&data
;
212 data
.state
= PyEval_SaveThread();
213 err
= yp_all (domain
, map
, &cb
);
214 PyEval_RestoreThread(data
.state
);
217 return nis_error(err
);
222 /* These should be u_long on Sun h/w but not on 64-bit h/w.
223 This is not portable to machines with 16-bit ints and no prototypes */
224 #ifndef YPPROC_MAPLIST
225 #define YPPROC_MAPLIST 11
228 #define YPPROG 100004
234 typedef char *domainname
;
235 typedef char *mapname
;
250 typedef enum nisstat nisstat
;
254 struct nismaplist
*next
;
256 typedef struct nismaplist nismaplist
;
258 struct nisresp_maplist
{
262 typedef struct nisresp_maplist nisresp_maplist
;
264 static struct timeval TIMEOUT
= { 25, 0 };
268 nis_xdr_domainname(XDR
*xdrs
, domainname
*objp
)
270 if (!xdr_string(xdrs
, objp
, YPMAXDOMAIN
)) {
278 nis_xdr_mapname(XDR
*xdrs
, mapname
*objp
)
280 if (!xdr_string(xdrs
, objp
, YPMAXMAP
)) {
288 nis_xdr_ypmaplist(XDR
*xdrs
, nismaplist
*objp
)
290 if (!nis_xdr_mapname(xdrs
, &objp
->map
)) {
293 if (!xdr_pointer(xdrs
, (char **)&objp
->next
,
294 sizeof(nismaplist
), (xdrproc_t
)nis_xdr_ypmaplist
))
303 nis_xdr_ypstat(XDR
*xdrs
, nisstat
*objp
)
305 if (!xdr_enum(xdrs
, (enum_t
*)objp
)) {
314 nis_xdr_ypresp_maplist(XDR
*xdrs
, nisresp_maplist
*objp
)
316 if (!nis_xdr_ypstat(xdrs
, &objp
->stat
)) {
319 if (!xdr_pointer(xdrs
, (char **)&objp
->maps
,
320 sizeof(nismaplist
), (xdrproc_t
)nis_xdr_ypmaplist
))
330 nisproc_maplist_2(domainname
*argp
, CLIENT
*clnt
)
332 static nisresp_maplist res
;
334 memset(&res
, 0, sizeof(res
));
335 if (clnt_call(clnt
, YPPROC_MAPLIST
,
336 (xdrproc_t
)nis_xdr_domainname
, (caddr_t
)argp
,
337 (xdrproc_t
)nis_xdr_ypresp_maplist
, (caddr_t
)&res
,
338 TIMEOUT
) != RPC_SUCCESS
)
347 nis_maplist (char *dom
)
349 nisresp_maplist
*list
;
354 while (!server
&& aliases
[mapi
].map
!= 0L) {
355 yp_master (dom
, aliases
[mapi
].map
, &server
);
359 PyErr_SetString(NisError
, "No NIS master found for any map");
362 cl
= clnt_create(server
, YPPROG
, YPVERS
, "tcp");
364 PyErr_SetString(NisError
, clnt_spcreateerror(server
));
367 list
= nisproc_maplist_2 (&dom
, cl
);
371 if (list
->stat
!= NIS_TRUE
)
383 nis_maps (PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
389 static char *kwlist
[] = {"domain", NULL
};
391 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
,
392 "|s:maps", kwlist
, &domain
))
394 if (!domain
&& ((err
= yp_get_default_domain (&domain
)) != 0)) {
399 if ((maps
= nis_maplist (domain
)) == NULL
)
401 if ((list
= PyList_New(0)) == NULL
)
403 for (maps
= maps
; maps
; maps
= maps
->next
) {
404 PyObject
*str
= PyString_FromString(maps
->map
);
405 if (!str
|| PyList_Append(list
, str
) < 0)
413 /* XXX Shouldn't we free the list of maps now? */
417 static PyMethodDef nis_methods
[] = {
418 {"match", (PyCFunction
)nis_match
,
419 METH_VARARGS
| METH_KEYWORDS
,
421 {"cat", (PyCFunction
)nis_cat
,
422 METH_VARARGS
| METH_KEYWORDS
,
424 {"maps", (PyCFunction
)nis_maps
,
425 METH_VARARGS
| METH_KEYWORDS
,
427 {"get_default_domain", (PyCFunction
)nis_get_default_domain
,
429 get_default_domain__doc__
},
430 {NULL
, NULL
} /* Sentinel */
433 PyDoc_STRVAR(nis__doc__
,
434 "This module contains functions for accessing NIS maps.\n");
440 m
= Py_InitModule3("nis", nis_methods
, nis__doc__
);
443 d
= PyModule_GetDict(m
);
444 NisError
= PyErr_NewException("nis.error", NULL
, NULL
);
445 if (NisError
!= NULL
)
446 PyDict_SetItemString(d
, "error", NisError
);