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 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 * 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 * 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 * 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 if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1) 162 goto out; 163 if ((p = getpwnam(name)) == NULL) { 164 PyErr_Format(PyExc_KeyError, 165 "getpwnam(): name not found: %s", name); 166 goto out; 167 } 168 retval = mkpwent(p); 169 out: 170 Py_DECREF(bytes); 171 return retval; 172 } 173 174 #ifdef HAVE_GETPWENT 175 /*[clinic input] 176 pwd.getpwall 177 178 Return a list of all available password database entries, in arbitrary order. 179 180 See help(pwd) for more on password database entries. 181 [clinic start generated code]*/ 182 183 static PyObject * 184 pwd_getpwall_impl(PyObject *module) 185 /*[clinic end generated code: output=4853d2f5a0afac8a input=d7ecebfd90219b85]*/ 186 { 187 PyObject *d; 188 struct passwd *p; 189 if ((d = PyList_New(0)) == NULL) 190 return NULL; 191 setpwent(); 192 while ((p = getpwent()) != NULL) { 193 PyObject *v = mkpwent(p); 194 if (v == NULL || PyList_Append(d, v) != 0) { 195 Py_XDECREF(v); 196 Py_DECREF(d); 197 endpwent(); 198 return NULL; 199 } 200 Py_DECREF(v); 201 } 202 endpwent(); 203 return d; 204 } 205 #endif 206 207 static PyMethodDef pwd_methods[] = { 208 PWD_GETPWUID_METHODDEF 209 PWD_GETPWNAM_METHODDEF 210 #ifdef HAVE_GETPWENT 211 PWD_GETPWALL_METHODDEF 212 #endif 213 {NULL, NULL} /* sentinel */ 214 }; 215 216 static struct PyModuleDef pwdmodule = { 217 PyModuleDef_HEAD_INIT, 218 "pwd", 219 pwd__doc__, 220 -1, 221 pwd_methods, 222 NULL, 223 NULL, 224 NULL, 225 NULL 226 }; 227 228 229 PyMODINIT_FUNC 230 PyInit_pwd(void) 231 { 232 PyObject *m; 233 m = PyModule_Create(&pwdmodule); 234 if (m == NULL) 235 return NULL; 236 237 if (!initialized) { 238 if (PyStructSequence_InitType2(&StructPwdType, 239 &struct_pwd_type_desc) < 0) 240 return NULL; 241 initialized = 1; 242 } 243 Py_INCREF((PyObject *) &StructPwdType); 244 PyModule_AddObject(m, "struct_passwd", (PyObject *) &StructPwdType); 245 return m; 246 } 247