Clarify portability and main program.
[python/dscho.git] / Modules / nismodule.c
blobfcd64ffe318c42baf6d82e7acbaab4960499f2f7
1 /***********************************************************
2 Written by:
3 Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
4 Vakgroep Spa,
5 Faculteit der Informatica,
6 Universiteit Twente,
7 Enschede,
8 the Netherlands.
9 ******************************************************************/
11 /* NIS module implementation */
13 #include "Python.h"
15 #include <sys/time.h>
16 #include <sys/types.h>
17 #include <rpc/rpc.h>
18 #include <rpcsvc/yp_prot.h>
19 #include <rpcsvc/ypclnt.h>
21 #ifdef __sgi
22 /* This is missing from rpcsvc/ypclnt.h */
23 extern int yp_get_default_domain();
24 #endif
26 static PyObject *NisError;
28 static PyObject *
29 nis_error (err)
30 int err;
32 PyErr_SetString(NisError, yperr_string(err));
33 return NULL;
36 static struct nis_map {
37 char *alias;
38 char *map;
39 } aliases [] = {
40 {"passwd", "passwd.byname"},
41 {"group", "group.byname"},
42 {"networks", "networks.byaddr"},
43 {"hosts", "hosts.byname"},
44 {"protocols", "protocols.bynumber"},
45 {"services", "services.byname"},
46 {"aliases", "mail.aliases"},
47 {"ethers", "ethers.byname"},
48 {0L, 0L}
51 static char *
52 nis_mapname (map)
53 char *map;
55 int i;
57 for (i=0; aliases[i].alias != 0L; i++)
58 if (!strcmp (aliases[i].alias, map))
59 map = aliases[i].map;
60 return map;
63 typedef int (*foreachfunc) Py_PROTO((int, char *, int, char *, int, char *));
65 static int
66 nis_foreach (instatus, inkey, inkeylen, inval, invallen, indata)
67 int instatus;
68 char *inkey;
69 int inkeylen;
70 char *inval;
71 int invallen;
72 PyObject *indata;
74 if (instatus == YP_TRUE) {
75 PyObject *key = PyString_FromStringAndSize(inkey, inkeylen);
76 PyObject *val = PyString_FromStringAndSize(inval, invallen);
77 int err;
78 if (key == NULL || val == NULL) {
79 /* XXX error -- don't know how to handle */
80 PyErr_Clear();
81 Py_XDECREF(key);
82 Py_XDECREF(val);
83 return 1;
85 err = PyDict_SetItem(indata, key, val);
86 Py_DECREF(key);
87 Py_DECREF(val);
88 if (err != 0) {
89 PyErr_Clear();
90 return 1;
92 return 0;
94 return 1;
97 static PyObject *
98 nis_match (self, args)
99 PyObject *self;
100 PyObject *args;
102 char *match;
103 char *domain;
104 int keylen, len;
105 char *key, *map;
106 int err;
107 PyObject *res;
109 if (!PyArg_Parse(args, "(t#s)", &key, &keylen, &map))
110 return NULL;
111 if ((err = yp_get_default_domain(&domain)) != 0)
112 return nis_error(err);
113 Py_BEGIN_ALLOW_THREADS
114 map = nis_mapname (map);
115 err = yp_match (domain, map, key, keylen, &match, &len);
116 Py_END_ALLOW_THREADS
117 if (err != 0)
118 return nis_error(err);
119 res = PyString_FromStringAndSize (match, len);
120 free (match);
121 return res;
124 static PyObject *
125 nis_cat (self, args)
126 PyObject *self;
127 PyObject *args;
129 char *domain;
130 char *map;
131 struct ypall_callback cb;
132 PyObject *cat;
133 int err;
135 if (!PyArg_Parse(args, "s", &map))
136 return NULL;
137 if ((err = yp_get_default_domain(&domain)) != 0)
138 return nis_error(err);
139 cat = PyDict_New ();
140 if (cat == NULL)
141 return NULL;
142 cb.foreach = (foreachfunc)nis_foreach;
143 cb.data = (char *)cat;
144 Py_BEGIN_ALLOW_THREADS
145 map = nis_mapname (map);
146 err = yp_all (domain, map, &cb);
147 Py_END_ALLOW_THREADS
148 if (err != 0) {
149 Py_DECREF(cat);
150 return nis_error(err);
152 return cat;
155 /* These should be u_long on Sun h/w but not on 64-bit h/w.
156 This is not portable to machines with 16-bit ints and no prototypes */
157 #ifndef YPPROC_MAPLIST
158 #define YPPROC_MAPLIST 11
159 #endif
160 #ifndef YPPROG
161 #define YPPROG 100004
162 #endif
163 #ifndef YPVERS
164 #define YPVERS 2
165 #endif
167 typedef char *domainname;
168 typedef char *mapname;
170 enum nisstat {
171 NIS_TRUE = 1,
172 NIS_NOMORE = 2,
173 NIS_FALSE = 0,
174 NIS_NOMAP = -1,
175 NIS_NODOM = -2,
176 NIS_NOKEY = -3,
177 NIS_BADOP = -4,
178 NIS_BADDB = -5,
179 NIS_YPERR = -6,
180 NIS_BADARGS = -7,
181 NIS_VERS = -8
183 typedef enum nisstat nisstat;
185 struct nismaplist {
186 mapname map;
187 struct nismaplist *next;
189 typedef struct nismaplist nismaplist;
191 struct nisresp_maplist {
192 nisstat stat;
193 nismaplist *maps;
195 typedef struct nisresp_maplist nisresp_maplist;
197 static struct timeval TIMEOUT = { 25, 0 };
199 static
200 bool_t
201 nis_xdr_domainname(xdrs, objp)
202 XDR *xdrs;
203 domainname *objp;
205 if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
206 return (FALSE);
208 return (TRUE);
211 static
212 bool_t
213 nis_xdr_mapname(xdrs, objp)
214 XDR *xdrs;
215 mapname *objp;
217 if (!xdr_string(xdrs, objp, YPMAXMAP)) {
218 return (FALSE);
220 return (TRUE);
223 static
224 bool_t
225 nis_xdr_ypmaplist(xdrs, objp)
226 XDR *xdrs;
227 nismaplist *objp;
229 if (!nis_xdr_mapname(xdrs, &objp->map)) {
230 return (FALSE);
232 if (!xdr_pointer(xdrs, (char **)&objp->next,
233 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
235 return (FALSE);
237 return (TRUE);
240 static
241 bool_t
242 nis_xdr_ypstat(xdrs, objp)
243 XDR *xdrs;
244 nisstat *objp;
246 if (!xdr_enum(xdrs, (enum_t *)objp)) {
247 return (FALSE);
249 return (TRUE);
253 static
254 bool_t
255 nis_xdr_ypresp_maplist(xdrs, objp)
256 XDR *xdrs;
257 nisresp_maplist *objp;
259 if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
260 return (FALSE);
262 if (!xdr_pointer(xdrs, (char **)&objp->maps,
263 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
265 return (FALSE);
267 return (TRUE);
271 static
272 nisresp_maplist *
273 nisproc_maplist_2(argp, clnt)
274 domainname *argp;
275 CLIENT *clnt;
277 static nisresp_maplist res;
279 memset(&res, 0, sizeof(res));
280 if (clnt_call(clnt, YPPROC_MAPLIST,
281 (xdrproc_t)nis_xdr_domainname, (caddr_t)argp,
282 (xdrproc_t)nis_xdr_ypresp_maplist, (caddr_t)&res,
283 TIMEOUT) != RPC_SUCCESS)
285 return (NULL);
287 return (&res);
290 static
291 nismaplist *
292 nis_maplist ()
294 nisresp_maplist *list;
295 char *dom;
296 CLIENT *cl, *clnt_create();
297 char *server = NULL;
298 int mapi = 0;
299 int err;
301 if ((err = yp_get_default_domain (&dom)) != 0) {
302 nis_error(err);
303 return NULL;
306 while (!server && aliases[mapi].map != 0L) {
307 yp_master (dom, aliases[mapi].map, &server);
308 mapi++;
310 if (!server) {
311 PyErr_SetString(NisError, "No NIS master found for any map");
312 return NULL;
314 cl = clnt_create(server, YPPROG, YPVERS, "tcp");
315 if (cl == NULL) {
316 PyErr_SetString(NisError, clnt_spcreateerror(server));
317 goto finally;
319 list = nisproc_maplist_2 (&dom, cl);
320 clnt_destroy(cl);
321 if (list == NULL)
322 goto finally;
323 if (list->stat != NIS_TRUE)
324 goto finally;
326 PyMem_DEL(server);
327 return list->maps;
329 finally:
330 PyMem_DEL(server);
331 return NULL;
334 static PyObject *
335 nis_maps (self, args)
336 PyObject *self;
337 PyObject *args;
339 nismaplist *maps;
340 PyObject *list;
342 if (!PyArg_NoArgs(args))
343 return NULL;
344 if ((maps = nis_maplist ()) == NULL)
345 return NULL;
346 if ((list = PyList_New(0)) == NULL)
347 return NULL;
348 for (maps = maps->next; maps; maps = maps->next) {
349 PyObject *str = PyString_FromString(maps->map);
350 if (!str || PyList_Append(list, str) < 0)
352 Py_DECREF(list);
353 list = NULL;
354 break;
356 Py_DECREF(str);
358 /* XXX Shouldn't we free the list of maps now? */
359 return list;
362 static PyMethodDef nis_methods[] = {
363 {"match", nis_match},
364 {"cat", nis_cat},
365 {"maps", nis_maps},
366 {NULL, NULL} /* Sentinel */
369 void
370 initnis ()
372 PyObject *m, *d;
373 m = Py_InitModule("nis", nis_methods);
374 d = PyModule_GetDict(m);
375 NisError = PyErr_NewException("nis.error", NULL, NULL);
376 if (NisError != NULL)
377 PyDict_SetItemString(d, "error", NisError);