Home | History | Annotate | Download | only in Modules
      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