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
;
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
{
104 nis_foreach (int instatus
, char *inkey
, int inkeylen
, char *inval
,
105 int invallen
, struct ypcallback_data
*indata
)
107 if (instatus
== YP_TRUE
) {
113 if (inkeylen
> 0 && inkey
[inkeylen
-1] == '\0')
115 if (invallen
> 0 && inval
[invallen
-1] == '\0')
118 key
= PyString_FromStringAndSize(inkey
, inkeylen
);
119 val
= PyString_FromStringAndSize(inval
, invallen
);
120 if (key
== NULL
|| val
== NULL
) {
121 /* XXX error -- don't know how to handle */
127 err
= PyDict_SetItem(indata
->dict
, key
, val
);
140 nis_get_default_domain (PyObject
*self
)
146 if ((err
= yp_get_default_domain(&domain
)) != 0)
147 return nis_error(err
);
149 res
= PyString_FromStringAndSize (domain
, strlen(domain
));
154 nis_match (PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
163 static char *kwlist
[] = {"key", "map", "domain", NULL
};
165 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
,
166 "t#s|s:match", kwlist
,
167 &key
, &keylen
, &map
, &domain
))
169 if (!domain
&& ((err
= yp_get_default_domain(&domain
)) != 0))
170 return nis_error(err
);
171 map
= nis_mapname (map
, &fix
);
174 Py_BEGIN_ALLOW_THREADS
175 err
= yp_match (domain
, map
, key
, keylen
, &match
, &len
);
180 return nis_error(err
);
181 res
= PyString_FromStringAndSize (match
, len
);
187 nis_cat (PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
191 struct ypall_callback cb
;
192 struct ypcallback_data data
;
195 static char *kwlist
[] = {"map", "domain", NULL
};
197 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
, "s|s:cat",
198 kwlist
, &map
, &domain
))
200 if (!domain
&& ((err
= yp_get_default_domain(&domain
)) != 0))
201 return nis_error(err
);
202 dict
= PyDict_New ();
205 cb
.foreach
= (foreachfunc
)nis_foreach
;
207 map
= nis_mapname (map
, &data
.fix
);
208 cb
.data
= (char *)&data
;
209 Py_BEGIN_ALLOW_THREADS
210 err
= yp_all (domain
, map
, &cb
);
214 return nis_error(err
);
219 /* These should be u_long on Sun h/w but not on 64-bit h/w.
220 This is not portable to machines with 16-bit ints and no prototypes */
221 #ifndef YPPROC_MAPLIST
222 #define YPPROC_MAPLIST 11
225 #define YPPROG 100004
231 typedef char *domainname
;
232 typedef char *mapname
;
247 typedef enum nisstat nisstat
;
251 struct nismaplist
*next
;
253 typedef struct nismaplist nismaplist
;
255 struct nisresp_maplist
{
259 typedef struct nisresp_maplist nisresp_maplist
;
261 static struct timeval TIMEOUT
= { 25, 0 };
265 nis_xdr_domainname(XDR
*xdrs
, domainname
*objp
)
267 if (!xdr_string(xdrs
, objp
, YPMAXDOMAIN
)) {
275 nis_xdr_mapname(XDR
*xdrs
, mapname
*objp
)
277 if (!xdr_string(xdrs
, objp
, YPMAXMAP
)) {
285 nis_xdr_ypmaplist(XDR
*xdrs
, nismaplist
*objp
)
287 if (!nis_xdr_mapname(xdrs
, &objp
->map
)) {
290 if (!xdr_pointer(xdrs
, (char **)&objp
->next
,
291 sizeof(nismaplist
), (xdrproc_t
)nis_xdr_ypmaplist
))
300 nis_xdr_ypstat(XDR
*xdrs
, nisstat
*objp
)
302 if (!xdr_enum(xdrs
, (enum_t
*)objp
)) {
311 nis_xdr_ypresp_maplist(XDR
*xdrs
, nisresp_maplist
*objp
)
313 if (!nis_xdr_ypstat(xdrs
, &objp
->stat
)) {
316 if (!xdr_pointer(xdrs
, (char **)&objp
->maps
,
317 sizeof(nismaplist
), (xdrproc_t
)nis_xdr_ypmaplist
))
327 nisproc_maplist_2(domainname
*argp
, CLIENT
*clnt
)
329 static nisresp_maplist res
;
331 memset(&res
, 0, sizeof(res
));
332 if (clnt_call(clnt
, YPPROC_MAPLIST
,
333 (xdrproc_t
)nis_xdr_domainname
, (caddr_t
)argp
,
334 (xdrproc_t
)nis_xdr_ypresp_maplist
, (caddr_t
)&res
,
335 TIMEOUT
) != RPC_SUCCESS
)
344 nis_maplist (char *dom
)
346 nisresp_maplist
*list
;
351 while (!server
&& aliases
[mapi
].map
!= 0L) {
352 yp_master (dom
, aliases
[mapi
].map
, &server
);
356 PyErr_SetString(NisError
, "No NIS master found for any map");
359 cl
= clnt_create(server
, YPPROG
, YPVERS
, "tcp");
361 PyErr_SetString(NisError
, clnt_spcreateerror(server
));
364 list
= nisproc_maplist_2 (&dom
, cl
);
368 if (list
->stat
!= NIS_TRUE
)
380 nis_maps (PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
386 static char *kwlist
[] = {"domain", NULL
};
388 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
,
389 "|s:maps", kwlist
, &domain
))
391 if (!domain
&& ((err
= yp_get_default_domain (&domain
)) != 0)) {
396 if ((maps
= nis_maplist (domain
)) == NULL
)
398 if ((list
= PyList_New(0)) == NULL
)
400 for (maps
= maps
; maps
; maps
= maps
->next
) {
401 PyObject
*str
= PyString_FromString(maps
->map
);
402 if (!str
|| PyList_Append(list
, str
) < 0)
410 /* XXX Shouldn't we free the list of maps now? */
414 static PyMethodDef nis_methods
[] = {
415 {"match", (PyCFunction
)nis_match
,
416 METH_VARARGS
| METH_KEYWORDS
,
418 {"cat", (PyCFunction
)nis_cat
,
419 METH_VARARGS
| METH_KEYWORDS
,
421 {"maps", (PyCFunction
)nis_maps
,
422 METH_VARARGS
| METH_KEYWORDS
,
424 {"get_default_domain", (PyCFunction
)nis_get_default_domain
,
426 get_default_domain__doc__
},
427 {NULL
, NULL
} /* Sentinel */
430 PyDoc_STRVAR(nis__doc__
,
431 "This module contains functions for accessing NIS maps.\n");
437 m
= Py_InitModule3("nis", nis_methods
, nis__doc__
);
440 d
= PyModule_GetDict(m
);
441 NisError
= PyErr_NewException("nis.error", NULL
, NULL
);
442 if (NisError
!= NULL
)
443 PyDict_SetItemString(d
, "error", NisError
);