Skip to content

Commit ddef3bd

Browse files
authored
bpo-40950: Port nis module to multiphase initialization (GH-20811)
1 parent 756180b commit ddef3bd

File tree

2 files changed

+105
-45
lines changed

2 files changed

+105
-45
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add a state to the :mod:`nis` module (:pep:`3121`) and apply
2+
the multiphase initialization. Patch by Dong-hee Na.

Modules/nismodule.c

Lines changed: 103 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,42 @@ PyDoc_STRVAR(maps__doc__,
4444
Returns an array of all available NIS maps within a domain. If domain\n\
4545
is not specified it defaults to the system default domain.\n");
4646

47-
static PyObject *NisError;
47+
typedef struct {
48+
PyObject *nis_error;
49+
} nis_state;
50+
51+
static inline nis_state*
52+
get_nis_state(PyObject *module)
53+
{
54+
void *state = PyModule_GetState(module);
55+
assert(state != NULL);
56+
return (nis_state *)state;
57+
}
58+
59+
static int
60+
nis_clear(PyObject *m)
61+
{
62+
Py_CLEAR(get_nis_state(m)->nis_error);
63+
return 0;
64+
}
65+
66+
static int
67+
nis_traverse(PyObject *m, visitproc visit, void *arg)
68+
{
69+
Py_VISIT(get_nis_state(m)->nis_error);
70+
return 0;
71+
}
72+
73+
static void
74+
nis_free(void *m)
75+
{
76+
nis_clear((PyObject *) m);
77+
}
4878

4979
static PyObject *
50-
nis_error (int err)
80+
nis_error(nis_state *state, int err)
5181
{
52-
PyErr_SetString(NisError, yperr_string(err));
82+
PyErr_SetString(state->nis_error, yperr_string(err));
5383
return NULL;
5484
}
5585

@@ -70,7 +100,7 @@ static struct nis_map {
70100
};
71101

72102
static char *
73-
nis_mapname (char *map, int *pfix)
103+
nis_mapname(char *map, int *pfix)
74104
{
75105
int i;
76106

@@ -98,7 +128,7 @@ struct ypcallback_data {
98128
};
99129

100130
static int
101-
nis_foreach (int instatus, char *inkey, int inkeylen, char *inval,
131+
nis_foreach(int instatus, char *inkey, int inkeylen, char *inval,
102132
int invallen, struct ypcallback_data *indata)
103133
{
104134
if (instatus == YP_TRUE) {
@@ -137,21 +167,22 @@ nis_foreach (int instatus, char *inkey, int inkeylen, char *inval,
137167
}
138168

139169
static PyObject *
140-
nis_get_default_domain (PyObject *self, PyObject *Py_UNUSED(ignored))
170+
nis_get_default_domain(PyObject *module, PyObject *Py_UNUSED(ignored))
141171
{
142172
char *domain;
143173
int err;
144174
PyObject *res;
145-
146-
if ((err = yp_get_default_domain(&domain)) != 0)
147-
return nis_error(err);
175+
nis_state *state = get_nis_state(module);
176+
if ((err = yp_get_default_domain(&domain)) != 0) {
177+
return nis_error(state, err);
178+
}
148179

149180
res = PyUnicode_FromStringAndSize (domain, strlen(domain));
150181
return res;
151182
}
152183

153184
static PyObject *
154-
nis_match (PyObject *self, PyObject *args, PyObject *kwdict)
185+
nis_match(PyObject *module, PyObject *args, PyObject *kwdict)
155186
{
156187
char *match;
157188
char *domain = NULL;
@@ -165,18 +196,22 @@ nis_match (PyObject *self, PyObject *args, PyObject *kwdict)
165196

166197
if (!PyArg_ParseTupleAndKeywords(args, kwdict,
167198
"Us|s:match", kwlist,
168-
&ukey, &map, &domain))
199+
&ukey, &map, &domain)) {
169200
return NULL;
170-
if ((bkey = PyUnicode_EncodeFSDefault(ukey)) == NULL)
201+
}
202+
if ((bkey = PyUnicode_EncodeFSDefault(ukey)) == NULL) {
171203
return NULL;
204+
}
172205
/* check for embedded null bytes */
173206
if (PyBytes_AsStringAndSize(bkey, &key, &keylen) == -1) {
174207
Py_DECREF(bkey);
175208
return NULL;
176209
}
210+
211+
nis_state *state = get_nis_state(module);
177212
if (!domain && ((err = yp_get_default_domain(&domain)) != 0)) {
178213
Py_DECREF(bkey);
179-
return nis_error(err);
214+
return nis_error(state, err);
180215
}
181216
map = nis_mapname (map, &fix);
182217
if (fix)
@@ -187,15 +222,16 @@ nis_match (PyObject *self, PyObject *args, PyObject *kwdict)
187222
Py_DECREF(bkey);
188223
if (fix)
189224
len--;
190-
if (err != 0)
191-
return nis_error(err);
225+
if (err != 0) {
226+
return nis_error(state, err);
227+
}
192228
res = PyUnicode_DecodeFSDefaultAndSize(match, len);
193229
free (match);
194230
return res;
195231
}
196232

197233
static PyObject *
198-
nis_cat (PyObject *self, PyObject *args, PyObject *kwdict)
234+
nis_cat(PyObject *module, PyObject *args, PyObject *kwdict)
199235
{
200236
char *domain = NULL;
201237
char *map;
@@ -206,10 +242,13 @@ nis_cat (PyObject *self, PyObject *args, PyObject *kwdict)
206242
static char *kwlist[] = {"map", "domain", NULL};
207243

208244
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s|s:cat",
209-
kwlist, &map, &domain))
245+
kwlist, &map, &domain)) {
210246
return NULL;
211-
if (!domain && ((err = yp_get_default_domain(&domain)) != 0))
212-
return nis_error(err);
247+
}
248+
nis_state *state = get_nis_state(module);
249+
if (!domain && ((err = yp_get_default_domain(&domain)) != 0)) {
250+
return nis_error(state, err);
251+
}
213252
dict = PyDict_New ();
214253
if (dict == NULL)
215254
return NULL;
@@ -222,7 +261,7 @@ nis_cat (PyObject *self, PyObject *args, PyObject *kwdict)
222261
PyEval_RestoreThread(data.state);
223262
if (err != 0) {
224263
Py_DECREF(dict);
225-
return nis_error(err);
264+
return nis_error(state, err);
226265
}
227266
return dict;
228267
}
@@ -352,7 +391,7 @@ nisproc_maplist_2(domainname *argp, CLIENT *clnt)
352391

353392
static
354393
nismaplist *
355-
nis_maplist (char *dom)
394+
nis_maplist(nis_state *state, char *dom)
356395
{
357396
nisresp_maplist *list;
358397
CLIENT *cl;
@@ -364,12 +403,12 @@ nis_maplist (char *dom)
364403
mapi++;
365404
}
366405
if (!server) {
367-
PyErr_SetString(NisError, "No NIS master found for any map");
406+
PyErr_SetString(state->nis_error, "No NIS master found for any map");
368407
return NULL;
369408
}
370409
cl = clnt_create(server, YPPROG, YPVERS, "tcp");
371410
if (cl == NULL) {
372-
PyErr_SetString(NisError, clnt_spcreateerror(server));
411+
PyErr_SetString(state->nis_error, clnt_spcreateerror(server));
373412
goto finally;
374413
}
375414
list = nisproc_maplist_2 (&dom, cl);
@@ -388,7 +427,7 @@ nis_maplist (char *dom)
388427
}
389428

390429
static PyObject *
391-
nis_maps (PyObject *self, PyObject *args, PyObject *kwdict)
430+
nis_maps (PyObject *module, PyObject *args, PyObject *kwdict)
392431
{
393432
char *domain = NULL;
394433
nismaplist *maps;
@@ -397,17 +436,22 @@ nis_maps (PyObject *self, PyObject *args, PyObject *kwdict)
397436
static char *kwlist[] = {"domain", NULL};
398437

399438
if (!PyArg_ParseTupleAndKeywords(args, kwdict,
400-
"|s:maps", kwlist, &domain))
439+
"|s:maps", kwlist, &domain)) {
401440
return NULL;
441+
}
442+
443+
nis_state *state = get_nis_state(module);
402444
if (!domain && ((err = yp_get_default_domain (&domain)) != 0)) {
403-
nis_error(err);
445+
nis_error(state, err);
404446
return NULL;
405447
}
406448

407-
if ((maps = nis_maplist (domain)) == NULL)
449+
if ((maps = nis_maplist(state, domain)) == NULL) {
408450
return NULL;
409-
if ((list = PyList_New(0)) == NULL)
451+
}
452+
if ((list = PyList_New(0)) == NULL) {
410453
return NULL;
454+
}
411455
for (; maps; maps = maps->next) {
412456
PyObject *str = PyUnicode_FromString(maps->map);
413457
if (!str || PyList_Append(list, str) < 0)
@@ -439,31 +483,45 @@ static PyMethodDef nis_methods[] = {
439483
{NULL, NULL} /* Sentinel */
440484
};
441485

486+
static int
487+
nis_exec(PyObject *module)
488+
{
489+
nis_state* state = get_nis_state(module);
490+
state->nis_error = PyErr_NewException("nis.error", NULL, NULL);
491+
if (state->nis_error == NULL) {
492+
return -1;
493+
}
494+
495+
Py_INCREF(state->nis_error);
496+
if (PyModule_AddObject(module, "error", state->nis_error) < 0) {
497+
Py_DECREF(state->nis_error);
498+
return -1;
499+
}
500+
return 0;
501+
}
502+
503+
static PyModuleDef_Slot nis_slots[] = {
504+
{Py_mod_exec, nis_exec},
505+
{0, NULL}
506+
};
507+
442508
PyDoc_STRVAR(nis__doc__,
443509
"This module contains functions for accessing NIS maps.\n");
444510

445511
static struct PyModuleDef nismodule = {
446512
PyModuleDef_HEAD_INIT,
447-
"nis",
448-
nis__doc__,
449-
-1,
450-
nis_methods,
451-
NULL,
452-
NULL,
453-
NULL,
454-
NULL
513+
.m_name = "nis",
514+
.m_doc = nis__doc__,
515+
.m_size = sizeof(nis_state),
516+
.m_methods = nis_methods,
517+
.m_traverse = nis_traverse,
518+
.m_clear = nis_clear,
519+
.m_free = nis_free,
520+
.m_slots = nis_slots,
455521
};
456522

457523
PyMODINIT_FUNC
458524
PyInit_nis(void)
459525
{
460-
PyObject *m, *d;
461-
m = PyModule_Create(&nismodule);
462-
if (m == NULL)
463-
return NULL;
464-
d = PyModule_GetDict(m);
465-
NisError = PyErr_NewException("nis.error", NULL, NULL);
466-
if (NisError != NULL)
467-
PyDict_SetItemString(d, "error", NisError);
468-
return m;
526+
return PyModuleDef_Init(&nismodule);
469527
}

0 commit comments

Comments
 (0)