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 /* 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 *
grp_getgrall_impl(PyObject * module)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
PyInit_grp(void)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