Exceptions raised during renaming in rotating file handlers are now passed to handleE...
[python.git] / Modules / nismodule.c
blob2494adbbedad622d2ca7c5f96fc1cbfa553c8025
1 /***********************************************************
2 Written by:
3 Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
4 B&O group,
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(char **);
24 #endif
26 static PyObject *NisError;
28 static PyObject *
29 nis_error (int err)
31 PyErr_SetString(NisError, yperr_string(err));
32 return NULL;
35 static struct nis_map {
36 char *alias;
37 char *map;
38 int fix;
39 } aliases [] = {
40 {"passwd", "passwd.byname", 0},
41 {"group", "group.byname", 0},
42 {"networks", "networks.byaddr", 0},
43 {"hosts", "hosts.byname", 0},
44 {"protocols", "protocols.bynumber", 0},
45 {"services", "services.byname", 0},
46 {"aliases", "mail.aliases", 1}, /* created with 'makedbm -a' */
47 {"ethers", "ethers.byname", 0},
48 {0L, 0L, 0}
51 static char *
52 nis_mapname (char *map, int *pfix)
54 int i;
56 *pfix = 0;
57 for (i=0; aliases[i].alias != 0L; i++) {
58 if (!strcmp (aliases[i].alias, map)) {
59 *pfix = aliases[i].fix;
60 return aliases[i].map;
62 if (!strcmp (aliases[i].map, map)) {
63 *pfix = aliases[i].fix;
64 return aliases[i].map;
68 return map;
71 #ifdef __APPLE__
72 typedef int (*foreachfunc)(unsigned long, char *, int, char *, int, void *);
73 #else
74 typedef int (*foreachfunc)(int, char *, int, char *, int, char *);
75 #endif
77 struct ypcallback_data {
78 PyObject *dict;
79 int fix;
82 static int
83 nis_foreach (int instatus, char *inkey, int inkeylen, char *inval,
84 int invallen, struct ypcallback_data *indata)
86 if (instatus == YP_TRUE) {
87 PyObject *key;
88 PyObject *val;
89 int err;
91 if (indata->fix) {
92 if (inkeylen > 0 && inkey[inkeylen-1] == '\0')
93 inkeylen--;
94 if (invallen > 0 && inval[invallen-1] == '\0')
95 invallen--;
97 key = PyString_FromStringAndSize(inkey, inkeylen);
98 val = PyString_FromStringAndSize(inval, invallen);
99 if (key == NULL || val == NULL) {
100 /* XXX error -- don't know how to handle */
101 PyErr_Clear();
102 Py_XDECREF(key);
103 Py_XDECREF(val);
104 return 1;
106 err = PyDict_SetItem(indata->dict, key, val);
107 Py_DECREF(key);
108 Py_DECREF(val);
109 if (err != 0) {
110 PyErr_Clear();
111 return 1;
113 return 0;
115 return 1;
118 static PyObject *
119 nis_match (PyObject *self, PyObject *args)
121 char *match;
122 char *domain;
123 int keylen, len;
124 char *key, *map;
125 int err;
126 PyObject *res;
127 int fix;
129 if (!PyArg_ParseTuple(args, "t#s:match", &key, &keylen, &map))
130 return NULL;
131 if ((err = yp_get_default_domain(&domain)) != 0)
132 return nis_error(err);
133 map = nis_mapname (map, &fix);
134 if (fix)
135 keylen++;
136 Py_BEGIN_ALLOW_THREADS
137 err = yp_match (domain, map, key, keylen, &match, &len);
138 Py_END_ALLOW_THREADS
139 if (fix)
140 len--;
141 if (err != 0)
142 return nis_error(err);
143 res = PyString_FromStringAndSize (match, len);
144 free (match);
145 return res;
148 static PyObject *
149 nis_cat (PyObject *self, PyObject *args)
151 char *domain;
152 char *map;
153 struct ypall_callback cb;
154 struct ypcallback_data data;
155 PyObject *dict;
156 int err;
158 if (!PyArg_ParseTuple(args, "s:cat", &map))
159 return NULL;
160 if ((err = yp_get_default_domain(&domain)) != 0)
161 return nis_error(err);
162 dict = PyDict_New ();
163 if (dict == NULL)
164 return NULL;
165 cb.foreach = (foreachfunc)nis_foreach;
166 data.dict = dict;
167 map = nis_mapname (map, &data.fix);
168 cb.data = (char *)&data;
169 Py_BEGIN_ALLOW_THREADS
170 err = yp_all (domain, map, &cb);
171 Py_END_ALLOW_THREADS
172 if (err != 0) {
173 Py_DECREF(dict);
174 return nis_error(err);
176 return dict;
179 /* These should be u_long on Sun h/w but not on 64-bit h/w.
180 This is not portable to machines with 16-bit ints and no prototypes */
181 #ifndef YPPROC_MAPLIST
182 #define YPPROC_MAPLIST 11
183 #endif
184 #ifndef YPPROG
185 #define YPPROG 100004
186 #endif
187 #ifndef YPVERS
188 #define YPVERS 2
189 #endif
191 typedef char *domainname;
192 typedef char *mapname;
194 enum nisstat {
195 NIS_TRUE = 1,
196 NIS_NOMORE = 2,
197 NIS_FALSE = 0,
198 NIS_NOMAP = -1,
199 NIS_NODOM = -2,
200 NIS_NOKEY = -3,
201 NIS_BADOP = -4,
202 NIS_BADDB = -5,
203 NIS_YPERR = -6,
204 NIS_BADARGS = -7,
205 NIS_VERS = -8
207 typedef enum nisstat nisstat;
209 struct nismaplist {
210 mapname map;
211 struct nismaplist *next;
213 typedef struct nismaplist nismaplist;
215 struct nisresp_maplist {
216 nisstat stat;
217 nismaplist *maps;
219 typedef struct nisresp_maplist nisresp_maplist;
221 static struct timeval TIMEOUT = { 25, 0 };
223 static
224 bool_t
225 nis_xdr_domainname(XDR *xdrs, domainname *objp)
227 if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
228 return (FALSE);
230 return (TRUE);
233 static
234 bool_t
235 nis_xdr_mapname(XDR *xdrs, mapname *objp)
237 if (!xdr_string(xdrs, objp, YPMAXMAP)) {
238 return (FALSE);
240 return (TRUE);
243 static
244 bool_t
245 nis_xdr_ypmaplist(XDR *xdrs, nismaplist *objp)
247 if (!nis_xdr_mapname(xdrs, &objp->map)) {
248 return (FALSE);
250 if (!xdr_pointer(xdrs, (char **)&objp->next,
251 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
253 return (FALSE);
255 return (TRUE);
258 static
259 bool_t
260 nis_xdr_ypstat(XDR *xdrs, nisstat *objp)
262 if (!xdr_enum(xdrs, (enum_t *)objp)) {
263 return (FALSE);
265 return (TRUE);
269 static
270 bool_t
271 nis_xdr_ypresp_maplist(XDR *xdrs, nisresp_maplist *objp)
273 if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
274 return (FALSE);
276 if (!xdr_pointer(xdrs, (char **)&objp->maps,
277 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
279 return (FALSE);
281 return (TRUE);
285 static
286 nisresp_maplist *
287 nisproc_maplist_2(domainname *argp, CLIENT *clnt)
289 static nisresp_maplist res;
291 memset(&res, 0, sizeof(res));
292 if (clnt_call(clnt, YPPROC_MAPLIST,
293 (xdrproc_t)nis_xdr_domainname, (caddr_t)argp,
294 (xdrproc_t)nis_xdr_ypresp_maplist, (caddr_t)&res,
295 TIMEOUT) != RPC_SUCCESS)
297 return (NULL);
299 return (&res);
302 static
303 nismaplist *
304 nis_maplist (void)
306 nisresp_maplist *list;
307 char *dom;
308 CLIENT *cl;
309 char *server = NULL;
310 int mapi = 0;
311 int err;
313 if ((err = yp_get_default_domain (&dom)) != 0) {
314 nis_error(err);
315 return NULL;
318 while (!server && aliases[mapi].map != 0L) {
319 yp_master (dom, aliases[mapi].map, &server);
320 mapi++;
322 if (!server) {
323 PyErr_SetString(NisError, "No NIS master found for any map");
324 return NULL;
326 cl = clnt_create(server, YPPROG, YPVERS, "tcp");
327 if (cl == NULL) {
328 PyErr_SetString(NisError, clnt_spcreateerror(server));
329 goto finally;
331 list = nisproc_maplist_2 (&dom, cl);
332 clnt_destroy(cl);
333 if (list == NULL)
334 goto finally;
335 if (list->stat != NIS_TRUE)
336 goto finally;
338 free(server);
339 return list->maps;
341 finally:
342 free(server);
343 return NULL;
346 static PyObject *
347 nis_maps (PyObject *self)
349 nismaplist *maps;
350 PyObject *list;
352 if ((maps = nis_maplist ()) == NULL)
353 return NULL;
354 if ((list = PyList_New(0)) == NULL)
355 return NULL;
356 for (maps = maps; maps; maps = maps->next) {
357 PyObject *str = PyString_FromString(maps->map);
358 if (!str || PyList_Append(list, str) < 0)
360 Py_DECREF(list);
361 list = NULL;
362 break;
364 Py_DECREF(str);
366 /* XXX Shouldn't we free the list of maps now? */
367 return list;
370 static PyMethodDef nis_methods[] = {
371 {"match", nis_match, METH_VARARGS},
372 {"cat", nis_cat, METH_VARARGS},
373 {"maps", (PyCFunction)nis_maps, METH_NOARGS},
374 {NULL, NULL} /* Sentinel */
377 void
378 initnis (void)
380 PyObject *m, *d;
381 m = Py_InitModule("nis", nis_methods);
382 d = PyModule_GetDict(m);
383 NisError = PyErr_NewException("nis.error", NULL, NULL);
384 if (NisError != NULL)
385 PyDict_SetItemString(d, "error", NisError);