• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
mkgrent(struct group * p)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 *
grp_getgrgid_impl(PyObject * module,PyObject * id)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 *
grp_getgrnam_impl(PyObject * module,PyObject * name)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 *
grp_getgrall_impl(PyObject * module)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
PyInit_grp(void)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