Home | History | Annotate | Download | only in Modules
      1 
      2 /* UNIX group file access module */
      3 
      4 #include "Python.h"
      5 #include "posixmodule.h"
      6 
      7 #include <grp.h>
      8 
      9 #include "clinic/grpmodule.c.h"
     10 /*[clinic input]
     11 module grp
     12 [clinic start generated code]*/
     13 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=cade63f2ed1bd9f8]*/
     14 
     15 static PyStructSequence_Field struct_group_type_fields[] = {
     16    {"gr_name", "group name"},
     17    {"gr_passwd", "password"},
     18    {"gr_gid", "group id"},
     19    {"gr_mem", "group members"},
     20    {0}
     21 };
     22 
     23 PyDoc_STRVAR(struct_group__doc__,
     24 "grp.struct_group: Results from getgr*() routines.\n\n\
     25 This object may be accessed either as a tuple of\n\
     26   (gr_name,gr_passwd,gr_gid,gr_mem)\n\
     27 or via the object attributes as named in the above tuple.\n");
     28 
     29 static PyStructSequence_Desc struct_group_type_desc = {
     30    "grp.struct_group",
     31    struct_group__doc__,
     32    struct_group_type_fields,
     33    4,
     34 };
     35 
     36 
     37 static int initialized;
     38 static PyTypeObject StructGrpType;
     39 
     40 static PyObject *
     41 mkgrent(struct group *p)
     42 {
     43     int setIndex = 0;
     44     PyObject *v = PyStructSequence_New(&StructGrpType), *w;
     45     char **member;
     46 
     47     if (v == NULL)
     48         return NULL;
     49 
     50     if ((w = PyList_New(0)) == NULL) {
     51         Py_DECREF(v);
     52         return NULL;
     53     }
     54     for (member = p->gr_mem; *member != NULL; member++) {
     55         PyObject *x = PyUnicode_DecodeFSDefault(*member);
     56         if (x == NULL || PyList_Append(w, x) != 0) {
     57             Py_XDECREF(x);
     58             Py_DECREF(w);
     59             Py_DECREF(v);
     60             return NULL;
     61         }
     62         Py_DECREF(x);
     63     }
     64 
     65 #define SET(i,val) PyStructSequence_SET_ITEM(v, i, val)
     66     SET(setIndex++, PyUnicode_DecodeFSDefault(p->gr_name));
     67     if (p->gr_passwd)
     68             SET(setIndex++, PyUnicode_DecodeFSDefault(p->gr_passwd));
     69     else {
     70             SET(setIndex++, Py_None);
     71             Py_INCREF(Py_None);
     72     }
     73     SET(setIndex++, _PyLong_FromGid(p->gr_gid));
     74     SET(setIndex++, w);
     75 #undef SET
     76 
     77     if (PyErr_Occurred()) {
     78         Py_DECREF(v);
     79         return NULL;
     80     }
     81 
     82     return v;
     83 }
     84 
     85 /*[clinic input]
     86 grp.getgrgid
     87 
     88     id: object
     89 
     90 Return the group database entry for the given numeric group ID.
     91 
     92 If id is not valid, raise KeyError.
     93 [clinic start generated code]*/
     94 
     95 static PyObject *
     96 grp_getgrgid_impl(PyObject *module, PyObject *id)
     97 /*[clinic end generated code: output=30797c289504a1ba input=15fa0e2ccf5cda25]*/
     98 {
     99     PyObject *py_int_id;
    100     gid_t gid;
    101     struct group *p;
    102 
    103     if (!_Py_Gid_Converter(id, &gid)) {
    104         if (!PyErr_ExceptionMatches(PyExc_TypeError)) {
    105             return NULL;
    106         }
    107         PyErr_Clear();
    108         if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
    109                              "group id must be int, not %.200",
    110                              id->ob_type->tp_name) < 0) {
    111             return NULL;
    112         }
    113         py_int_id = PyNumber_Long(id);
    114         if (!py_int_id)
    115             return NULL;
    116         if (!_Py_Gid_Converter(py_int_id, &gid)) {
    117             Py_DECREF(py_int_id);
    118             return NULL;
    119         }
    120         Py_DECREF(py_int_id);
    121     }
    122 
    123     if ((p = getgrgid(gid)) == NULL) {
    124         PyObject *gid_obj = _PyLong_FromGid(gid);
    125         if (gid_obj == NULL)
    126             return NULL;
    127         PyErr_Format(PyExc_KeyError, "getgrgid(): gid not found: %S", gid_obj);
    128         Py_DECREF(gid_obj);
    129         return NULL;
    130     }
    131     return mkgrent(p);
    132 }
    133 
    134 /*[clinic input]
    135 grp.getgrnam
    136 
    137     name: unicode
    138 
    139 Return the group database entry for the given group name.
    140 
    141 If name is not valid, raise KeyError.
    142 [clinic start generated code]*/
    143 
    144 static PyObject *
    145 grp_getgrnam_impl(PyObject *module, PyObject *name)
    146 /*[clinic end generated code: output=67905086f403c21c input=08ded29affa3c863]*/
    147 {
    148     char *name_chars;
    149     struct group *p;
    150     PyObject *bytes, *retval = NULL;
    151 
    152     if ((bytes = PyUnicode_EncodeFSDefault(name)) == NULL)
    153         return NULL;
    154     /* check for embedded null bytes */
    155     if (PyBytes_AsStringAndSize(bytes, &name_chars, NULL) == -1)
    156         goto out;
    157 
    158     if ((p = getgrnam(name_chars)) == NULL) {
    159         PyErr_Format(PyExc_KeyError, "getgrnam(): name not found: %R", name);
    160         goto out;
    161     }
    162     retval = mkgrent(p);
    163 out:
    164     Py_DECREF(bytes);
    165     return retval;
    166 }
    167 
    168 /*[clinic input]
    169 grp.getgrall
    170 
    171 Return a list of all available group entries, in arbitrary order.
    172 
    173 An entry whose name starts with '+' or '-' represents an instruction
    174 to use YP/NIS and may not be accessible via getgrnam or getgrgid.
    175 [clinic start generated code]*/
    176 
    177 static PyObject *
    178 grp_getgrall_impl(PyObject *module)
    179 /*[clinic end generated code: output=585dad35e2e763d7 input=d7df76c825c367df]*/
    180 {
    181     PyObject *d;
    182     struct group *p;
    183 
    184     if ((d = PyList_New(0)) == NULL)
    185         return NULL;
    186     setgrent();
    187     while ((p = getgrent()) != NULL) {
    188         PyObject *v = mkgrent(p);
    189         if (v == NULL || PyList_Append(d, v) != 0) {
    190             Py_XDECREF(v);
    191             Py_DECREF(d);
    192             endgrent();
    193             return NULL;
    194         }
    195         Py_DECREF(v);
    196     }
    197     endgrent();
    198     return d;
    199 }
    200 
    201 static PyMethodDef grp_methods[] = {
    202     GRP_GETGRGID_METHODDEF
    203     GRP_GETGRNAM_METHODDEF
    204     GRP_GETGRALL_METHODDEF
    205     {NULL, NULL}
    206 };
    207 
    208 PyDoc_STRVAR(grp__doc__,
    209 "Access to the Unix group database.\n\
    210 \n\
    211 Group entries are reported as 4-tuples containing the following fields\n\
    212 from the group database, in order:\n\
    213 \n\
    214   gr_name   - name of the group\n\
    215   gr_passwd - group password (encrypted); often empty\n\
    216   gr_gid    - numeric ID of the group\n\
    217   gr_mem    - list of members\n\
    218 \n\
    219 The gid is an integer, name and password are strings.  (Note that most\n\
    220 users are not explicitly listed as members of the groups they are in\n\
    221 according to the password database.  Check both databases to get\n\
    222 complete membership information.)");
    223 
    224 
    225 
    226 static struct PyModuleDef grpmodule = {
    227         PyModuleDef_HEAD_INIT,
    228         "grp",
    229         grp__doc__,
    230         -1,
    231         grp_methods,
    232         NULL,
    233         NULL,
    234         NULL,
    235         NULL
    236 };
    237 
    238 PyMODINIT_FUNC
    239 PyInit_grp(void)
    240 {
    241     PyObject *m, *d;
    242     m = PyModule_Create(&grpmodule);
    243     if (m == NULL)
    244         return NULL;
    245     d = PyModule_GetDict(m);
    246     if (!initialized) {
    247         if (PyStructSequence_InitType2(&StructGrpType,
    248                                        &struct_group_type_desc) < 0)
    249             return NULL;
    250     }
    251     if (PyDict_SetItemString(d, "struct_group",
    252                              (PyObject *)&StructGrpType) < 0)
    253         return NULL;
    254     initialized = 1;
    255     return m;
    256 }
    257