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     if (PyBytes_AsStringAndSize(bytes, &name_chars, NULL) == -1)
    155         goto out;
    156 
    157     if ((p = getgrnam(name_chars)) == NULL) {
    158         PyErr_Format(PyExc_KeyError, "getgrnam(): name not found: %s", name_chars);
    159         goto out;
    160     }
    161     retval = mkgrent(p);
    162 out:
    163     Py_DECREF(bytes);
    164     return retval;
    165 }
    166 
    167 /*[clinic input]
    168 grp.getgrall
    169 
    170 Return a list of all available group entries, in arbitrary order.
    171 
    172 An entry whose name starts with '+' or '-' represents an instruction
    173 to use YP/NIS and may not be accessible via getgrnam or getgrgid.
    174 [clinic start generated code]*/
    175 
    176 static PyObject *
    177 grp_getgrall_impl(PyObject *module)
    178 /*[clinic end generated code: output=585dad35e2e763d7 input=d7df76c825c367df]*/
    179 {
    180     PyObject *d;
    181     struct group *p;
    182 
    183     if ((d = PyList_New(0)) == NULL)
    184         return NULL;
    185     setgrent();
    186     while ((p = getgrent()) != NULL) {
    187         PyObject *v = mkgrent(p);
    188         if (v == NULL || PyList_Append(d, v) != 0) {
    189             Py_XDECREF(v);
    190             Py_DECREF(d);
    191             endgrent();
    192             return NULL;
    193         }
    194         Py_DECREF(v);
    195     }
    196     endgrent();
    197     return d;
    198 }
    199 
    200 static PyMethodDef grp_methods[] = {
    201     GRP_GETGRGID_METHODDEF
    202     GRP_GETGRNAM_METHODDEF
    203     GRP_GETGRALL_METHODDEF
    204     {NULL, NULL}
    205 };
    206 
    207 PyDoc_STRVAR(grp__doc__,
    208 "Access to the Unix group database.\n\
    209 \n\
    210 Group entries are reported as 4-tuples containing the following fields\n\
    211 from the group database, in order:\n\
    212 \n\
    213   gr_name   - name of the group\n\
    214   gr_passwd - group password (encrypted); often empty\n\
    215   gr_gid    - numeric ID of the group\n\
    216   gr_mem    - list of members\n\
    217 \n\
    218 The gid is an integer, name and password are strings.  (Note that most\n\
    219 users are not explicitly listed as members of the groups they are in\n\
    220 according to the password database.  Check both databases to get\n\
    221 complete membership information.)");
    222 
    223 
    224 
    225 static struct PyModuleDef grpmodule = {
    226         PyModuleDef_HEAD_INIT,
    227         "grp",
    228         grp__doc__,
    229         -1,
    230         grp_methods,
    231         NULL,
    232         NULL,
    233         NULL,
    234         NULL
    235 };
    236 
    237 PyMODINIT_FUNC
    238 PyInit_grp(void)
    239 {
    240     PyObject *m, *d;
    241     m = PyModule_Create(&grpmodule);
    242     if (m == NULL)
    243         return NULL;
    244     d = PyModule_GetDict(m);
    245     if (!initialized) {
    246         if (PyStructSequence_InitType2(&StructGrpType,
    247                                        &struct_group_type_desc) < 0)
    248             return NULL;
    249     }
    250     if (PyDict_SetItemString(d, "struct_group",
    251                              (PyObject *)&StructGrpType) < 0)
    252         return NULL;
    253     initialized = 1;
    254     return m;
    255 }
    256