blob: a9028bbfe54c6c71d764c76e2de7d2ab9741c4f8 [file] [log] [blame]
Guido van Rossum9de7a011992-08-12 14:57:12 +00001/***********************************************************
2 Written by:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003 Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
4 B&O group,
5 Faculteit der Informatica,
6 Universiteit Twente,
7 Enschede,
8 the Netherlands.
Guido van Rossum9de7a011992-08-12 14:57:12 +00009******************************************************************/
10
11/* NIS module implementation */
12
Barry Warsawadbf4e61996-12-11 00:15:58 +000013#include "Python.h"
Guido van Rossum9de7a011992-08-12 14:57:12 +000014
Guido van Rossum9de7a011992-08-12 14:57:12 +000015#include <sys/time.h>
16#include <sys/types.h>
17#include <rpc/rpc.h>
18#include <rpcsvc/yp_prot.h>
Guido van Rossum8a170cb1996-08-08 19:11:41 +000019#include <rpcsvc/ypclnt.h>
Guido van Rossum9de7a011992-08-12 14:57:12 +000020
Guido van Rossum259552d1996-12-09 18:46:28 +000021#ifdef __sgi
22/* This is missing from rpcsvc/ypclnt.h */
Thomas Woutersbd4bc4e2000-07-22 23:57:55 +000023extern int yp_get_default_domain(char **);
Guido van Rossum259552d1996-12-09 18:46:28 +000024#endif
25
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000026PyDoc_STRVAR(get_default_domain__doc__,
Martin v. Löwis57a34e82006-02-04 19:12:37 +000027"get_default_domain() -> str\n\
28Corresponds to the C library yp_get_default_domain() call, returning\n\
29the default NIS domain.\n");
30
31PyDoc_STRVAR(match__doc__,
32"match(key, map, domain = defaultdomain)\n\
33Corresponds to the C library yp_match() call, returning the value of\n\
34key in the given map. Optionally domain can be specified but it\n\
35defaults to the system default domain.\n");
36
37PyDoc_STRVAR(cat__doc__,
38"cat(map, domain = defaultdomain)\n\
39Returns the entire map as a dictionary. Optionally domain can be\n\
40specified but it defaults to the system default domain.\n");
41
42PyDoc_STRVAR(maps__doc__,
43"maps(domain = defaultdomain)\n\
44Returns an array of all available NIS maps within a domain. If domain\n\
45is not specified it defaults to the system default domain.\n");
46
Barry Warsawadbf4e61996-12-11 00:15:58 +000047static PyObject *NisError;
Guido van Rossum3562d521992-08-12 15:26:16 +000048
Barry Warsawadbf4e61996-12-11 00:15:58 +000049static PyObject *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +000050nis_error (int err)
Guido van Rossum3562d521992-08-12 15:26:16 +000051{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000052 PyErr_SetString(NisError, yperr_string(err));
53 return NULL;
Guido van Rossum3562d521992-08-12 15:26:16 +000054}
55
Guido van Rossum9de7a011992-08-12 14:57:12 +000056static struct nis_map {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000057 char *alias;
58 char *map;
59 int fix;
Guido van Rossum9de7a011992-08-12 14:57:12 +000060} aliases [] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000061 {"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},
69 {0L, 0L, 0}
Guido van Rossum9de7a011992-08-12 14:57:12 +000070};
71
72static char *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +000073nis_mapname (char *map, int *pfix)
Guido van Rossum9de7a011992-08-12 14:57:12 +000074{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000075 int i;
Guido van Rossum9de7a011992-08-12 14:57:12 +000076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000077 *pfix = 0;
78 for (i=0; aliases[i].alias != 0L; i++) {
Raymond Hettinger9f4b8602015-07-24 00:43:44 -040079 if (!strcmp (aliases[i].alias, map) || !strcmp (aliases[i].map, map)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000080 *pfix = aliases[i].fix;
81 return aliases[i].map;
82 }
83 }
Guido van Rossum61b705a2000-02-29 15:52:40 +000084
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000085 return map;
Guido van Rossum9de7a011992-08-12 14:57:12 +000086}
87
Amaury Forgeot d'Arc783f86e2009-07-07 06:51:26 +000088#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
Brett Cannonf6067ec2004-07-10 00:57:37 +000089typedef int (*foreachfunc)(unsigned long, char *, int, char *, int, void *);
90#else
Tim Petersdbd9ba62000-07-09 03:09:57 +000091typedef int (*foreachfunc)(int, char *, int, char *, int, char *);
Brett Cannonf6067ec2004-07-10 00:57:37 +000092#endif
Guido van Rossumb6775db1994-08-01 11:34:53 +000093
Guido van Rossum61b705a2000-02-29 15:52:40 +000094struct ypcallback_data {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000095 PyObject *dict;
96 int fix;
97 PyThreadState *state;
Guido van Rossum61b705a2000-02-29 15:52:40 +000098};
99
Guido van Rossum9de7a011992-08-12 14:57:12 +0000100static int
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000101nis_foreach (int instatus, char *inkey, int inkeylen, char *inval,
102 int invallen, struct ypcallback_data *indata)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000103{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 if (instatus == YP_TRUE) {
105 PyObject *key;
106 PyObject *val;
107 int err;
Guido van Rossum61b705a2000-02-29 15:52:40 +0000108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 PyEval_RestoreThread(indata->state);
110 if (indata->fix) {
111 if (inkeylen > 0 && inkey[inkeylen-1] == '\0')
112 inkeylen--;
113 if (invallen > 0 && inval[invallen-1] == '\0')
114 invallen--;
115 }
Martin v. Löwis5ea823c2010-08-19 09:11:51 +0000116 key = PyUnicode_DecodeFSDefaultAndSize(inkey, inkeylen);
117 val = PyUnicode_DecodeFSDefaultAndSize(inval, invallen);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 if (key == NULL || val == NULL) {
119 /* XXX error -- don't know how to handle */
120 PyErr_Clear();
121 Py_XDECREF(key);
122 Py_XDECREF(val);
Martin v. Löwisdfaf9ec2010-08-18 16:12:23 +0000123 indata->state = PyEval_SaveThread();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000124 return 1;
125 }
126 err = PyDict_SetItem(indata->dict, key, val);
127 Py_DECREF(key);
128 Py_DECREF(val);
129 if (err != 0)
130 PyErr_Clear();
131 indata->state = PyEval_SaveThread();
132 if (err != 0)
133 return 1;
134 return 0;
135 }
136 return 1;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000137}
138
Barry Warsawadbf4e61996-12-11 00:15:58 +0000139static PyObject *
Martin v. Löwis57a34e82006-02-04 19:12:37 +0000140nis_get_default_domain (PyObject *self)
141{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000142 char *domain;
143 int err;
144 PyObject *res;
Martin v. Löwis57a34e82006-02-04 19:12:37 +0000145
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000146 if ((err = yp_get_default_domain(&domain)) != 0)
147 return nis_error(err);
Martin v. Löwis57a34e82006-02-04 19:12:37 +0000148
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000149 res = PyUnicode_FromStringAndSize (domain, strlen(domain));
150 return res;
Martin v. Löwis57a34e82006-02-04 19:12:37 +0000151}
152
153static PyObject *
154nis_match (PyObject *self, PyObject *args, PyObject *kwdict)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000155{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000156 char *match;
157 char *domain = NULL;
Martin v. Löwis5ea823c2010-08-19 09:11:51 +0000158 Py_ssize_t keylen;
159 int len;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000160 char *key, *map;
161 int err;
Martin v. Löwis5ea823c2010-08-19 09:11:51 +0000162 PyObject *ukey, *bkey, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000163 int fix;
164 static char *kwlist[] = {"key", "map", "domain", NULL};
Guido van Rossum9de7a011992-08-12 14:57:12 +0000165
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000166 if (!PyArg_ParseTupleAndKeywords(args, kwdict,
Martin v. Löwis5ea823c2010-08-19 09:11:51 +0000167 "Us|s:match", kwlist,
168 &ukey, &map, &domain))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000169 return NULL;
Martin v. Löwis5ea823c2010-08-19 09:11:51 +0000170 if ((bkey = PyUnicode_EncodeFSDefault(ukey)) == NULL)
171 return NULL;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300172 /* check for embedded null bytes */
Martin v. Löwis5ea823c2010-08-19 09:11:51 +0000173 if (PyBytes_AsStringAndSize(bkey, &key, &keylen) == -1) {
174 Py_DECREF(bkey);
175 return NULL;
176 }
177 if (!domain && ((err = yp_get_default_domain(&domain)) != 0)) {
178 Py_DECREF(bkey);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000179 return nis_error(err);
Martin v. Löwis5ea823c2010-08-19 09:11:51 +0000180 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 map = nis_mapname (map, &fix);
182 if (fix)
183 keylen++;
184 Py_BEGIN_ALLOW_THREADS
185 err = yp_match (domain, map, key, keylen, &match, &len);
186 Py_END_ALLOW_THREADS
Martin v. Löwis5ea823c2010-08-19 09:11:51 +0000187 Py_DECREF(bkey);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000188 if (fix)
189 len--;
190 if (err != 0)
191 return nis_error(err);
Martin v. Löwis5ea823c2010-08-19 09:11:51 +0000192 res = PyUnicode_DecodeFSDefaultAndSize(match, len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000193 free (match);
194 return res;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000195}
196
Barry Warsawadbf4e61996-12-11 00:15:58 +0000197static PyObject *
Martin v. Löwis57a34e82006-02-04 19:12:37 +0000198nis_cat (PyObject *self, PyObject *args, PyObject *kwdict)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000199{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 char *domain = NULL;
201 char *map;
202 struct ypall_callback cb;
203 struct ypcallback_data data;
204 PyObject *dict;
205 int err;
206 static char *kwlist[] = {"map", "domain", NULL};
Guido van Rossum9de7a011992-08-12 14:57:12 +0000207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s|s:cat",
209 kwlist, &map, &domain))
210 return NULL;
211 if (!domain && ((err = yp_get_default_domain(&domain)) != 0))
212 return nis_error(err);
213 dict = PyDict_New ();
214 if (dict == NULL)
215 return NULL;
216 cb.foreach = (foreachfunc)nis_foreach;
217 data.dict = dict;
218 map = nis_mapname (map, &data.fix);
219 cb.data = (char *)&data;
220 data.state = PyEval_SaveThread();
221 err = yp_all (domain, map, &cb);
222 PyEval_RestoreThread(data.state);
223 if (err != 0) {
224 Py_DECREF(dict);
225 return nis_error(err);
226 }
227 return dict;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000228}
229
Guido van Rossumb6775db1994-08-01 11:34:53 +0000230/* These should be u_long on Sun h/w but not on 64-bit h/w.
231 This is not portable to machines with 16-bit ints and no prototypes */
232#ifndef YPPROC_MAPLIST
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000233#define YPPROC_MAPLIST 11
Guido van Rossumb6775db1994-08-01 11:34:53 +0000234#endif
235#ifndef YPPROG
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236#define YPPROG 100004
Guido van Rossumb6775db1994-08-01 11:34:53 +0000237#endif
238#ifndef YPVERS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000239#define YPVERS 2
Guido van Rossumb6775db1994-08-01 11:34:53 +0000240#endif
Guido van Rossum9de7a011992-08-12 14:57:12 +0000241
242typedef char *domainname;
243typedef char *mapname;
244
245enum nisstat {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000246 NIS_TRUE = 1,
247 NIS_NOMORE = 2,
248 NIS_FALSE = 0,
249 NIS_NOMAP = -1,
250 NIS_NODOM = -2,
251 NIS_NOKEY = -3,
252 NIS_BADOP = -4,
253 NIS_BADDB = -5,
254 NIS_YPERR = -6,
255 NIS_BADARGS = -7,
256 NIS_VERS = -8
Guido van Rossum9de7a011992-08-12 14:57:12 +0000257};
258typedef enum nisstat nisstat;
259
260struct nismaplist {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261 mapname map;
262 struct nismaplist *next;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000263};
264typedef struct nismaplist nismaplist;
265
266struct nisresp_maplist {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000267 nisstat stat;
268 nismaplist *maps;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000269};
270typedef struct nisresp_maplist nisresp_maplist;
271
272static struct timeval TIMEOUT = { 25, 0 };
273
274static
275bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000276nis_xdr_domainname(XDR *xdrs, domainname *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000277{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000278 if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
279 return (FALSE);
280 }
281 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000282}
283
284static
285bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000286nis_xdr_mapname(XDR *xdrs, mapname *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000287{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000288 if (!xdr_string(xdrs, objp, YPMAXMAP)) {
289 return (FALSE);
290 }
291 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000292}
293
294static
295bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000296nis_xdr_ypmaplist(XDR *xdrs, nismaplist *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000297{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000298 if (!nis_xdr_mapname(xdrs, &objp->map)) {
299 return (FALSE);
300 }
301 if (!xdr_pointer(xdrs, (char **)&objp->next,
302 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
303 {
304 return (FALSE);
305 }
306 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000307}
308
309static
310bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000311nis_xdr_ypstat(XDR *xdrs, nisstat *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000312{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313 if (!xdr_enum(xdrs, (enum_t *)objp)) {
314 return (FALSE);
315 }
316 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000317}
318
319
320static
321bool_t
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000322nis_xdr_ypresp_maplist(XDR *xdrs, nisresp_maplist *objp)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000323{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000324 if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
325 return (FALSE);
326 }
327 if (!xdr_pointer(xdrs, (char **)&objp->maps,
328 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
329 {
330 return (FALSE);
331 }
332 return (TRUE);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000333}
334
335
336static
337nisresp_maplist *
Peter Schneider-Kamp39e0e5a2000-07-10 13:12:27 +0000338nisproc_maplist_2(domainname *argp, CLIENT *clnt)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000339{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000340 static nisresp_maplist res;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000342 memset(&res, 0, sizeof(res));
343 if (clnt_call(clnt, YPPROC_MAPLIST,
344 (xdrproc_t)nis_xdr_domainname, (caddr_t)argp,
345 (xdrproc_t)nis_xdr_ypresp_maplist, (caddr_t)&res,
346 TIMEOUT) != RPC_SUCCESS)
347 {
348 return (NULL);
349 }
350 return (&res);
Guido van Rossum9de7a011992-08-12 14:57:12 +0000351}
352
353static
354nismaplist *
Martin v. Löwis57a34e82006-02-04 19:12:37 +0000355nis_maplist (char *dom)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000356{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000357 nisresp_maplist *list;
358 CLIENT *cl;
359 char *server = NULL;
360 int mapi = 0;
Barry Warsaw3696c521996-12-11 00:29:14 +0000361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362 while (!server && aliases[mapi].map != 0L) {
363 yp_master (dom, aliases[mapi].map, &server);
364 mapi++;
365 }
366 if (!server) {
367 PyErr_SetString(NisError, "No NIS master found for any map");
368 return NULL;
369 }
370 cl = clnt_create(server, YPPROG, YPVERS, "tcp");
371 if (cl == NULL) {
372 PyErr_SetString(NisError, clnt_spcreateerror(server));
373 goto finally;
374 }
375 list = nisproc_maplist_2 (&dom, cl);
376 clnt_destroy(cl);
377 if (list == NULL)
378 goto finally;
379 if (list->stat != NIS_TRUE)
380 goto finally;
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382 free(server);
383 return list->maps;
Barry Warsaw4bc9d391997-01-09 22:22:05 +0000384
385 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000386 free(server);
387 return NULL;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000388}
389
Barry Warsawadbf4e61996-12-11 00:15:58 +0000390static PyObject *
Martin v. Löwis57a34e82006-02-04 19:12:37 +0000391nis_maps (PyObject *self, PyObject *args, PyObject *kwdict)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000392{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000393 char *domain = NULL;
394 nismaplist *maps;
395 PyObject *list;
396 int err;
397 static char *kwlist[] = {"domain", NULL};
Guido van Rossum9de7a011992-08-12 14:57:12 +0000398
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000399 if (!PyArg_ParseTupleAndKeywords(args, kwdict,
400 "|s:maps", kwlist, &domain))
401 return NULL;
402 if (!domain && ((err = yp_get_default_domain (&domain)) != 0)) {
403 nis_error(err);
404 return NULL;
405 }
Martin v. Löwis57a34e82006-02-04 19:12:37 +0000406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000407 if ((maps = nis_maplist (domain)) == NULL)
408 return NULL;
409 if ((list = PyList_New(0)) == NULL)
410 return NULL;
Brett Cannoneb175c42011-06-06 20:24:11 -0700411 for (; maps; maps = maps->next) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000412 PyObject *str = PyUnicode_FromString(maps->map);
413 if (!str || PyList_Append(list, str) < 0)
414 {
415 Py_DECREF(list);
416 list = NULL;
417 break;
418 }
419 Py_DECREF(str);
420 }
421 /* XXX Shouldn't we free the list of maps now? */
422 return list;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000423}
424
Barry Warsawadbf4e61996-12-11 00:15:58 +0000425static PyMethodDef nis_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000426 {"match", (PyCFunction)nis_match,
427 METH_VARARGS | METH_KEYWORDS,
428 match__doc__},
429 {"cat", (PyCFunction)nis_cat,
430 METH_VARARGS | METH_KEYWORDS,
431 cat__doc__},
432 {"maps", (PyCFunction)nis_maps,
433 METH_VARARGS | METH_KEYWORDS,
434 maps__doc__},
435 {"get_default_domain", (PyCFunction)nis_get_default_domain,
436 METH_NOARGS,
437 get_default_domain__doc__},
438 {NULL, NULL} /* Sentinel */
Guido van Rossum9de7a011992-08-12 14:57:12 +0000439};
440
Martin v. Löwis57a34e82006-02-04 19:12:37 +0000441PyDoc_STRVAR(nis__doc__,
442"This module contains functions for accessing NIS maps.\n");
443
Martin v. Löwis1a214512008-06-11 05:26:20 +0000444static struct PyModuleDef nismodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000445 PyModuleDef_HEAD_INIT,
446 "nis",
447 nis__doc__,
448 -1,
449 nis_methods,
450 NULL,
451 NULL,
452 NULL,
453 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000454};
455
Victor Stinnerf024d262015-03-17 17:48:27 +0100456PyMODINIT_FUNC
457PyInit_nis(void)
Guido van Rossum9de7a011992-08-12 14:57:12 +0000458{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000459 PyObject *m, *d;
460 m = PyModule_Create(&nismodule);
461 if (m == NULL)
462 return NULL;
463 d = PyModule_GetDict(m);
464 NisError = PyErr_NewException("nis.error", NULL, NULL);
465 if (NisError != NULL)
466 PyDict_SetItemString(d, "error", NisError);
467 return m;
Guido van Rossum9de7a011992-08-12 14:57:12 +0000468}