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 static int initialized;
51 static PyTypeObject StructPwdType;
52
53 static void
sets(PyObject * v,int i,const char * val)54 sets(PyObject *v, int i, const char* val)
55 {
56 if (val) {
57 PyObject *o = PyUnicode_DecodeFSDefault(val);
58 PyStructSequence_SET_ITEM(v, i, o);
59 }
60 else {
61 PyStructSequence_SET_ITEM(v, i, Py_None);
62 Py_INCREF(Py_None);
63 }
64 }
65
66 static PyObject *
mkpwent(struct passwd * p)67 mkpwent(struct passwd *p)
68 {
69 int setIndex = 0;
70 PyObject *v = PyStructSequence_New(&StructPwdType);
71 if (v == NULL)
72 return NULL;
73
74 #define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val))
75 #define SETS(i,val) sets(v, i, val)
76
77 SETS(setIndex++, p->pw_name);
78 #if defined(HAVE_STRUCT_PASSWD_PW_PASSWD) && !defined(__ANDROID__)
79 SETS(setIndex++, p->pw_passwd);
80 #else
81 SETS(setIndex++, "");
82 #endif
83 PyStructSequence_SET_ITEM(v, setIndex++, _PyLong_FromUid(p->pw_uid));
84 PyStructSequence_SET_ITEM(v, setIndex++, _PyLong_FromGid(p->pw_gid));
85 #if defined(HAVE_STRUCT_PASSWD_PW_GECOS)
86 SETS(setIndex++, p->pw_gecos);
87 #else
88 SETS(setIndex++, "");
89 #endif
90 SETS(setIndex++, p->pw_dir);
91 SETS(setIndex++, p->pw_shell);
92
93 #undef SETS
94 #undef SETI
95
96 if (PyErr_Occurred()) {
97 Py_XDECREF(v);
98 return NULL;
99 }
100
101 return v;
102 }
103
104 /*[clinic input]
105 pwd.getpwuid
106
107 uidobj: object
108 /
109
110 Return the password database entry for the given numeric user ID.
111
112 See `help(pwd)` for more on password database entries.
113 [clinic start generated code]*/
114
115 static PyObject *
pwd_getpwuid(PyObject * module,PyObject * uidobj)116 pwd_getpwuid(PyObject *module, PyObject *uidobj)
117 /*[clinic end generated code: output=c4ee1d4d429b86c4 input=ae64d507a1c6d3e8]*/
118 {
119 uid_t uid;
120 struct passwd *p;
121
122 if (!_Py_Uid_Converter(uidobj, &uid)) {
123 if (PyErr_ExceptionMatches(PyExc_OverflowError))
124 PyErr_Format(PyExc_KeyError,
125 "getpwuid(): uid not found");
126 return NULL;
127 }
128 if ((p = getpwuid(uid)) == NULL) {
129 PyObject *uid_obj = _PyLong_FromUid(uid);
130 if (uid_obj == NULL)
131 return NULL;
132 PyErr_Format(PyExc_KeyError,
133 "getpwuid(): uid not found: %S", uid_obj);
134 Py_DECREF(uid_obj);
135 return NULL;
136 }
137 return mkpwent(p);
138 }
139
140 /*[clinic input]
141 pwd.getpwnam
142
143 arg: unicode
144 /
145
146 Return the password database entry for the given user name.
147
148 See `help(pwd)` for more on password database entries.
149 [clinic start generated code]*/
150
151 static PyObject *
pwd_getpwnam_impl(PyObject * module,PyObject * arg)152 pwd_getpwnam_impl(PyObject *module, PyObject *arg)
153 /*[clinic end generated code: output=6abeee92430e43d2 input=d5f7e700919b02d3]*/
154 {
155 char *name;
156 struct passwd *p;
157 PyObject *bytes, *retval = NULL;
158
159 if ((bytes = PyUnicode_EncodeFSDefault(arg)) == NULL)
160 return NULL;
161 /* check for embedded null bytes */
162 if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
163 goto out;
164 if ((p = getpwnam(name)) == NULL) {
165 PyErr_Format(PyExc_KeyError,
166 "getpwnam(): name not found: %R", arg);
167 goto out;
168 }
169 retval = mkpwent(p);
170 out:
171 Py_DECREF(bytes);
172 return retval;
173 }
174
175 #ifdef HAVE_GETPWENT
176 /*[clinic input]
177 pwd.getpwall
178
179 Return a list of all available password database entries, in arbitrary order.
180
181 See help(pwd) for more on password database entries.
182 [clinic start generated code]*/
183
184 static PyObject *
pwd_getpwall_impl(PyObject * module)185 pwd_getpwall_impl(PyObject *module)
186 /*[clinic end generated code: output=4853d2f5a0afac8a input=d7ecebfd90219b85]*/
187 {
188 PyObject *d;
189 struct passwd *p;
190 if ((d = PyList_New(0)) == NULL)
191 return NULL;
192 setpwent();
193 while ((p = getpwent()) != NULL) {
194 PyObject *v = mkpwent(p);
195 if (v == NULL || PyList_Append(d, v) != 0) {
196 Py_XDECREF(v);
197 Py_DECREF(d);
198 endpwent();
199 return NULL;
200 }
201 Py_DECREF(v);
202 }
203 endpwent();
204 return d;
205 }
206 #endif
207
208 static PyMethodDef pwd_methods[] = {
209 PWD_GETPWUID_METHODDEF
210 PWD_GETPWNAM_METHODDEF
211 #ifdef HAVE_GETPWENT
212 PWD_GETPWALL_METHODDEF
213 #endif
214 {NULL, NULL} /* sentinel */
215 };
216
217 static struct PyModuleDef pwdmodule = {
218 PyModuleDef_HEAD_INIT,
219 "pwd",
220 pwd__doc__,
221 -1,
222 pwd_methods,
223 NULL,
224 NULL,
225 NULL,
226 NULL
227 };
228
229
230 PyMODINIT_FUNC
PyInit_pwd(void)231 PyInit_pwd(void)
232 {
233 PyObject *m;
234 m = PyModule_Create(&pwdmodule);
235 if (m == NULL)
236 return NULL;
237
238 if (!initialized) {
239 if (PyStructSequence_InitType2(&StructPwdType,
240 &struct_pwd_type_desc) < 0)
241 return NULL;
242 initialized = 1;
243 }
244 Py_INCREF((PyObject *) &StructPwdType);
245 PyModule_AddObject(m, "struct_passwd", (PyObject *) &StructPwdType);
246 return m;
247 }
248