/home/mdboom/Work/builds/cpython/Modules/pwdmodule.c
Line | Count | Source (jump to first uncovered line) |
1 | |
2 | /* UNIX password file access module */ |
3 | |
4 | #include "Python.h" |
5 | #include "posixmodule.h" |
6 | |
7 | #include <pwd.h> |
8 | |
9 | #include "clinic/pwdmodule.c.h" |
10 | /*[clinic input] |
11 | module pwd |
12 | [clinic start generated code]*/ |
13 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=60f628ef356b97b6]*/ |
14 | |
15 | static PyStructSequence_Field struct_pwd_type_fields[] = { |
16 | {"pw_name", "user name"}, |
17 | {"pw_passwd", "password"}, |
18 | {"pw_uid", "user id"}, |
19 | {"pw_gid", "group id"}, |
20 | {"pw_gecos", "real name"}, |
21 | {"pw_dir", "home directory"}, |
22 | {"pw_shell", "shell program"}, |
23 | {0} |
24 | }; |
25 | |
26 | PyDoc_STRVAR(struct_passwd__doc__, |
27 | "pwd.struct_passwd: Results from getpw*() routines.\n\n\ |
28 | This object may be accessed either as a tuple of\n\ |
29 | (pw_name,pw_passwd,pw_uid,pw_gid,pw_gecos,pw_dir,pw_shell)\n\ |
30 | or via the object attributes as named in the above tuple."); |
31 | |
32 | static PyStructSequence_Desc struct_pwd_type_desc = { |
33 | "pwd.struct_passwd", |
34 | struct_passwd__doc__, |
35 | struct_pwd_type_fields, |
36 | 7, |
37 | }; |
38 | |
39 | PyDoc_STRVAR(pwd__doc__, |
40 | "This module provides access to the Unix password database.\n\ |
41 | It is available on all Unix versions.\n\ |
42 | \n\ |
43 | Password database entries are reported as 7-tuples containing the following\n\ |
44 | items from the password database (see `<pwd.h>'), in order:\n\ |
45 | pw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir, pw_shell.\n\ |
46 | The uid and gid items are integers, all others are strings. An\n\ |
47 | exception is raised if the entry asked for cannot be found."); |
48 | |
49 | |
50 | typedef struct { |
51 | PyTypeObject *StructPwdType; |
52 | } pwdmodulestate; |
53 | |
54 | static inline pwdmodulestate* |
55 | get_pwd_state(PyObject *module) |
56 | { |
57 | void *state = PyModule_GetState(module); |
58 | assert(state != NULL); |
59 | return (pwdmodulestate *)state; |
60 | } |
61 | |
62 | static struct PyModuleDef pwdmodule; |
63 | |
64 | #define DEFAULT_BUFFER_SIZE 1024 |
65 | |
66 | static void |
67 | sets(PyObject *v, int i, const char* val) |
68 | { |
69 | if (val) { Branch (69:7): [True: 3.92k, False: 0]
|
70 | PyObject *o = PyUnicode_DecodeFSDefault(val); |
71 | PyStructSequence_SET_ITEM(v, i, o); |
72 | } |
73 | else { |
74 | PyStructSequence_SET_ITEM(v, i, Py_None); |
75 | Py_INCREF(Py_None); |
76 | } |
77 | } |
78 | |
79 | static PyObject * |
80 | mkpwent(PyObject *module, struct passwd *p) |
81 | { |
82 | int setIndex = 0; |
83 | PyObject *v = PyStructSequence_New(get_pwd_state(module)->StructPwdType); |
84 | if (v == NULL) Branch (84:9): [True: 0, False: 785]
|
85 | return NULL; |
86 | |
87 | #define SETS(i,val) sets(v, i, val) |
88 | |
89 | SETS(setIndex++, p->pw_name); |
90 | #if defined(HAVE_STRUCT_PASSWD_PW_PASSWD) && !defined(__ANDROID__) |
91 | SETS(setIndex++, p->pw_passwd); |
92 | #else |
93 | SETS(setIndex++, ""); |
94 | #endif |
95 | PyStructSequence_SET_ITEM(v, setIndex++, _PyLong_FromUid(p->pw_uid)); |
96 | PyStructSequence_SET_ITEM(v, setIndex++, _PyLong_FromGid(p->pw_gid)); |
97 | #if defined(HAVE_STRUCT_PASSWD_PW_GECOS) |
98 | SETS(setIndex++, p->pw_gecos); |
99 | #else |
100 | SETS(setIndex++, ""); |
101 | #endif |
102 | SETS(setIndex++, p->pw_dir); |
103 | SETS(setIndex++, p->pw_shell); |
104 | |
105 | #undef SETS |
106 | |
107 | if (PyErr_Occurred()) { Branch (107:9): [True: 0, False: 785]
|
108 | Py_XDECREF(v); |
109 | return NULL; |
110 | } |
111 | |
112 | return v; |
113 | } |
114 | |
115 | /*[clinic input] |
116 | pwd.getpwuid |
117 | |
118 | uidobj: object |
119 | / |
120 | |
121 | Return the password database entry for the given numeric user ID. |
122 | |
123 | See `help(pwd)` for more on password database entries. |
124 | [clinic start generated code]*/ |
125 | |
126 | static PyObject * |
127 | pwd_getpwuid(PyObject *module, PyObject *uidobj) |
128 | /*[clinic end generated code: output=c4ee1d4d429b86c4 input=ae64d507a1c6d3e8]*/ |
129 | { |
130 | PyObject *retval = NULL; |
131 | uid_t uid; |
132 | int nomem = 0; |
133 | struct passwd *p; |
134 | char *buf = NULL, *buf2 = NULL; |
135 | |
136 | if (!_Py_Uid_Converter(uidobj, &uid)) { Branch (136:9): [True: 4, False: 586]
|
137 | if (PyErr_ExceptionMatches(PyExc_OverflowError)) Branch (137:13): [True: 3, False: 1]
|
138 | PyErr_Format(PyExc_KeyError, |
139 | "getpwuid(): uid not found"); |
140 | return NULL; |
141 | } |
142 | #ifdef HAVE_GETPWUID_R |
143 | int status; |
144 | Py_ssize_t bufsize; |
145 | /* Note: 'pwd' will be used via pointer 'p' on getpwuid_r success. */ |
146 | struct passwd pwd; |
147 | |
148 | Py_BEGIN_ALLOW_THREADS |
149 | bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); |
150 | if (bufsize == -1) { Branch (150:9): [True: 0, False: 586]
|
151 | bufsize = DEFAULT_BUFFER_SIZE; |
152 | } |
153 | |
154 | while(1) { Branch (154:11): [Folded - Ignored]
|
155 | buf2 = PyMem_RawRealloc(buf, bufsize); |
156 | if (buf2 == NULL) { Branch (156:13): [True: 0, False: 586]
|
157 | p = NULL; |
158 | nomem = 1; |
159 | break; |
160 | } |
161 | buf = buf2; |
162 | status = getpwuid_r(uid, &pwd, buf, bufsize, &p); |
163 | if (status != 0) { Branch (163:13): [True: 0, False: 586]
|
164 | p = NULL; |
165 | } |
166 | if (p != NULL || status != ERANGE1 ) { Branch (166:13): [True: 585, False: 1]
Branch (166:26): [True: 1, False: 0]
|
167 | break; |
168 | } |
169 | if (bufsize > (PY_SSIZE_T_MAX >> 1)) { Branch (169:13): [True: 0, False: 0]
|
170 | nomem = 1; |
171 | break; |
172 | } |
173 | bufsize <<= 1; |
174 | } |
175 | |
176 | Py_END_ALLOW_THREADS |
177 | #else |
178 | p = getpwuid(uid); |
179 | #endif |
180 | if (p == NULL) { Branch (180:9): [True: 1, False: 585]
|
181 | PyMem_RawFree(buf); |
182 | if (nomem == 1) { Branch (182:13): [True: 0, False: 1]
|
183 | return PyErr_NoMemory(); |
184 | } |
185 | PyObject *uid_obj = _PyLong_FromUid(uid); |
186 | if (uid_obj == NULL) Branch (186:13): [True: 0, False: 1]
|
187 | return NULL; |
188 | PyErr_Format(PyExc_KeyError, |
189 | "getpwuid(): uid not found: %S", uid_obj); |
190 | Py_DECREF(uid_obj); |
191 | return NULL; |
192 | } |
193 | retval = mkpwent(module, p); |
194 | #ifdef HAVE_GETPWUID_R |
195 | PyMem_RawFree(buf); |
196 | #endif |
197 | return retval; |
198 | } |
199 | |
200 | /*[clinic input] |
201 | pwd.getpwnam |
202 | |
203 | name: unicode |
204 | / |
205 | |
206 | Return the password database entry for the given user name. |
207 | |
208 | See `help(pwd)` for more on password database entries. |
209 | [clinic start generated code]*/ |
210 | |
211 | static PyObject * |
212 | pwd_getpwnam_impl(PyObject *module, PyObject *name) |
213 | /*[clinic end generated code: output=359ce1ddeb7a824f input=a6aeb5e3447fb9e0]*/ |
214 | { |
215 | char *buf = NULL, *buf2 = NULL, *name_chars; |
216 | int nomem = 0; |
217 | struct passwd *p; |
218 | PyObject *bytes, *retval = NULL; |
219 | |
220 | if ((bytes = PyUnicode_EncodeFSDefault(name)) == NULL) Branch (220:9): [True: 0, False: 53]
|
221 | return NULL; |
222 | /* check for embedded null bytes */ |
223 | if (PyBytes_AsStringAndSize(bytes, &name_chars, NULL) == -1) Branch (223:9): [True: 0, False: 53]
|
224 | goto out; |
225 | #ifdef HAVE_GETPWNAM_R |
226 | int status; |
227 | Py_ssize_t bufsize; |
228 | /* Note: 'pwd' will be used via pointer 'p' on getpwnam_r success. */ |
229 | struct passwd pwd; |
230 | |
231 | Py_BEGIN_ALLOW_THREADS |
232 | bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); |
233 | if (bufsize == -1) { Branch (233:9): [True: 0, False: 53]
|
234 | bufsize = DEFAULT_BUFFER_SIZE; |
235 | } |
236 | |
237 | while(1) { Branch (237:11): [Folded - Ignored]
|
238 | buf2 = PyMem_RawRealloc(buf, bufsize); |
239 | if (buf2 == NULL) { Branch (239:13): [True: 0, False: 53]
|
240 | p = NULL; |
241 | nomem = 1; |
242 | break; |
243 | } |
244 | buf = buf2; |
245 | status = getpwnam_r(name_chars, &pwd, buf, bufsize, &p); |
246 | if (status != 0) { Branch (246:13): [True: 0, False: 53]
|
247 | p = NULL; |
248 | } |
249 | if (p != NULL || status != ERANGE9 ) { Branch (249:13): [True: 44, False: 9]
Branch (249:26): [True: 9, False: 0]
|
250 | break; |
251 | } |
252 | if (bufsize > (PY_SSIZE_T_MAX >> 1)) { Branch (252:13): [True: 0, False: 0]
|
253 | nomem = 1; |
254 | break; |
255 | } |
256 | bufsize <<= 1; |
257 | } |
258 | |
259 | Py_END_ALLOW_THREADS |
260 | #else |
261 | p = getpwnam(name_chars); |
262 | #endif |
263 | if (p == NULL) { Branch (263:9): [True: 9, False: 44]
|
264 | if (nomem == 1) { Branch (264:13): [True: 0, False: 9]
|
265 | PyErr_NoMemory(); |
266 | } |
267 | else { |
268 | PyErr_Format(PyExc_KeyError, |
269 | "getpwnam(): name not found: %R", name); |
270 | } |
271 | goto out; |
272 | } |
273 | retval = mkpwent(module, p); |
274 | out: |
275 | PyMem_RawFree(buf); |
276 | Py_DECREF(bytes); |
277 | return retval; |
278 | } |
279 | |
280 | #ifdef HAVE_GETPWENT |
281 | /*[clinic input] |
282 | pwd.getpwall |
283 | |
284 | Return a list of all available password database entries, in arbitrary order. |
285 | |
286 | See help(pwd) for more on password database entries. |
287 | [clinic start generated code]*/ |
288 | |
289 | static PyObject * |
290 | pwd_getpwall_impl(PyObject *module) |
291 | /*[clinic end generated code: output=4853d2f5a0afac8a input=d7ecebfd90219b85]*/ |
292 | { |
293 | PyObject *d; |
294 | struct passwd *p; |
295 | if ((d = PyList_New(0)) == NULL) Branch (295:9): [True: 0, False: 6]
|
296 | return NULL; |
297 | setpwent(); |
298 | while ((p = getpwent()) != NULL) { Branch (298:12): [True: 156, False: 6]
|
299 | PyObject *v = mkpwent(module, p); |
300 | if (v == NULL || PyList_Append(d, v) != 0) { Branch (300:13): [True: 0, False: 156]
Branch (300:26): [True: 0, False: 156]
|
301 | Py_XDECREF(v); |
302 | Py_DECREF(d); |
303 | endpwent(); |
304 | return NULL; |
305 | } |
306 | Py_DECREF(v); |
307 | } |
308 | endpwent(); |
309 | return d; |
310 | } |
311 | #endif |
312 | |
313 | static PyMethodDef pwd_methods[] = { |
314 | PWD_GETPWUID_METHODDEF |
315 | PWD_GETPWNAM_METHODDEF |
316 | #ifdef HAVE_GETPWENT |
317 | PWD_GETPWALL_METHODDEF |
318 | #endif |
319 | {NULL, NULL} /* sentinel */ |
320 | }; |
321 | |
322 | static int |
323 | pwdmodule_exec(PyObject *module) |
324 | { |
325 | pwdmodulestate *state = get_pwd_state(module); |
326 | |
327 | state->StructPwdType = PyStructSequence_NewType(&struct_pwd_type_desc); |
328 | if (state->StructPwdType == NULL) { Branch (328:9): [True: 0, False: 1]
|
329 | return -1; |
330 | } |
331 | if (PyModule_AddType(module, state->StructPwdType) < 0) { Branch (331:9): [True: 0, False: 1]
|
332 | return -1; |
333 | } |
334 | return 0; |
335 | } |
336 | |
337 | static PyModuleDef_Slot pwdmodule_slots[] = { |
338 | {Py_mod_exec, pwdmodule_exec}, |
339 | {0, NULL} |
340 | }; |
341 | |
342 | static int pwdmodule_traverse(PyObject *m, visitproc visit, void *arg) { |
343 | Py_VISIT(get_pwd_state(m)->StructPwdType); |
344 | return 0; |
345 | } |
346 | static int pwdmodule_clear(PyObject *m) { |
347 | Py_CLEAR(get_pwd_state(m)->StructPwdType); |
348 | return 0; |
349 | } |
350 | static void pwdmodule_free(void *m) { |
351 | pwdmodule_clear((PyObject *)m); |
352 | } |
353 | |
354 | static struct PyModuleDef pwdmodule = { |
355 | PyModuleDef_HEAD_INIT, |
356 | .m_name = "pwd", |
357 | .m_doc = pwd__doc__, |
358 | .m_size = sizeof(pwdmodulestate), |
359 | .m_methods = pwd_methods, |
360 | .m_slots = pwdmodule_slots, |
361 | .m_traverse = pwdmodule_traverse, |
362 | .m_clear = pwdmodule_clear, |
363 | .m_free = pwdmodule_free, |
364 | }; |
365 | |
366 | |
367 | PyMODINIT_FUNC |
368 | PyInit_pwd(void) |
369 | { |
370 | return PyModuleDef_Init(&pwdmodule); |
371 | } |