blob: 74286ab3974dea8b862776e95941e795f4ed09aa [file] [log] [blame]
Guido van Rossum20882d51994-06-23 11:15:44 +00001
2/* UNIX group file access module */
3
Roger E. Masseb2b44e51996-12-18 19:37:32 +00004#include "Python.h"
Serhiy Storchaka7cf55992013-02-10 21:56:49 +02005#include "posixmodule.h"
Guido van Rossum20882d51994-06-23 11:15:44 +00006
Guido van Rossum20882d51994-06-23 11:15:44 +00007#include <grp.h>
8
Brett Cannon8fb7bb22014-08-22 11:52:46 -04009#include "clinic/grpmodule.c.h"
10/*[clinic input]
Brett Cannon8fb7bb22014-08-22 11:52:46 -040011module grp
12[clinic start generated code]*/
Serhiy Storchaka1009bf12015-04-03 23:53:51 +030013/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cade63f2ed1bd9f8]*/
Brett Cannon8fb7bb22014-08-22 11:52:46 -040014
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000015static PyStructSequence_Field struct_group_type_fields[] = {
16 {"gr_name", "group name"},
17 {"gr_passwd", "password"},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000018 {"gr_gid", "group id"},
Mark Dickinsonfb29a162013-08-05 17:57:01 +010019 {"gr_mem", "group members"},
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000020 {0}
21};
22
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000023PyDoc_STRVAR(struct_group__doc__,
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000024"grp.struct_group: Results from getgr*() routines.\n\n\
25This object may be accessed either as a tuple of\n\
26 (gr_name,gr_passwd,gr_gid,gr_mem)\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000027or via the object attributes as named in the above tuple.\n");
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000028
29static PyStructSequence_Desc struct_group_type_desc = {
30 "grp.struct_group",
31 struct_group__doc__,
32 struct_group_type_fields,
33 4,
34};
35
36
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000037static int initialized;
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000038static PyTypeObject StructGrpType;
Fred Drake51b6bc52000-07-08 16:56:26 +000039
William Grzybowski23e65b22018-09-07 09:06:15 -030040#define DEFAULT_BUFFER_SIZE 1024
41
Fred Drake51b6bc52000-07-08 16:56:26 +000042static PyObject *
43mkgrent(struct group *p)
Guido van Rossum20882d51994-06-23 11:15:44 +000044{
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000045 int setIndex = 0;
46 PyObject *v = PyStructSequence_New(&StructGrpType), *w;
Fred Drake51b6bc52000-07-08 16:56:26 +000047 char **member;
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000048
49 if (v == NULL)
50 return NULL;
51
Fred Drake51b6bc52000-07-08 16:56:26 +000052 if ((w = PyList_New(0)) == NULL) {
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000053 Py_DECREF(v);
Fred Drake51b6bc52000-07-08 16:56:26 +000054 return NULL;
55 }
56 for (member = p->gr_mem; *member != NULL; member++) {
Victor Stinner97c18ab2010-05-07 16:34:53 +000057 PyObject *x = PyUnicode_DecodeFSDefault(*member);
Fred Drake51b6bc52000-07-08 16:56:26 +000058 if (x == NULL || PyList_Append(w, x) != 0) {
59 Py_XDECREF(x);
60 Py_DECREF(w);
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000061 Py_DECREF(v);
Fred Drake51b6bc52000-07-08 16:56:26 +000062 return NULL;
63 }
64 Py_DECREF(x);
65 }
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000066
67#define SET(i,val) PyStructSequence_SET_ITEM(v, i, val)
Victor Stinner97c18ab2010-05-07 16:34:53 +000068 SET(setIndex++, PyUnicode_DecodeFSDefault(p->gr_name));
Martin v. Löwisceb7c182002-09-17 07:05:25 +000069 if (p->gr_passwd)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000070 SET(setIndex++, PyUnicode_DecodeFSDefault(p->gr_passwd));
Martin v. Löwisceb7c182002-09-17 07:05:25 +000071 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000072 SET(setIndex++, Py_None);
73 Py_INCREF(Py_None);
Martin v. Löwisceb7c182002-09-17 07:05:25 +000074 }
Serhiy Storchaka7cf55992013-02-10 21:56:49 +020075 SET(setIndex++, _PyLong_FromGid(p->gr_gid));
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000076 SET(setIndex++, w);
77#undef SET
78
79 if (PyErr_Occurred()) {
80 Py_DECREF(v);
Martin v. Löwisdbd55b32002-03-01 10:38:44 +000081 return NULL;
82 }
83
Fred Drake51b6bc52000-07-08 16:56:26 +000084 return v;
Guido van Rossum20882d51994-06-23 11:15:44 +000085}
86
Brett Cannon8fb7bb22014-08-22 11:52:46 -040087/*[clinic input]
88grp.getgrgid
89
90 id: object
91
92Return the group database entry for the given numeric group ID.
93
94If id is not valid, raise KeyError.
95[clinic start generated code]*/
96
Fred Drake51b6bc52000-07-08 16:56:26 +000097static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +030098grp_getgrgid_impl(PyObject *module, PyObject *id)
99/*[clinic end generated code: output=30797c289504a1ba input=15fa0e2ccf5cda25]*/
Guido van Rossum20882d51994-06-23 11:15:44 +0000100{
William Grzybowski23e65b22018-09-07 09:06:15 -0300101 PyObject *py_int_id, *retval = NULL;
102 int nomem = 0;
103 char *buf = NULL, *buf2 = NULL;
Serhiy Storchaka7cf55992013-02-10 21:56:49 +0200104 gid_t gid;
Fred Drake51b6bc52000-07-08 16:56:26 +0000105 struct group *p;
Thomas Wouters477c8d52006-05-27 19:21:47 +0000106
Serhiy Storchaka9cc4ed52016-01-18 18:49:57 +0200107 if (!_Py_Gid_Converter(id, &gid)) {
108 if (!PyErr_ExceptionMatches(PyExc_TypeError)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 return NULL;
Serhiy Storchaka9cc4ed52016-01-18 18:49:57 +0200110 }
111 PyErr_Clear();
112 if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
113 "group id must be int, not %.200",
114 id->ob_type->tp_name) < 0) {
115 return NULL;
116 }
117 py_int_id = PyNumber_Long(id);
118 if (!py_int_id)
119 return NULL;
120 if (!_Py_Gid_Converter(py_int_id, &gid)) {
121 Py_DECREF(py_int_id);
122 return NULL;
123 }
Serhiy Storchaka7cf55992013-02-10 21:56:49 +0200124 Py_DECREF(py_int_id);
Serhiy Storchaka7cf55992013-02-10 21:56:49 +0200125 }
William Grzybowski23e65b22018-09-07 09:06:15 -0300126#ifdef HAVE_GETGRGID_R
127 Py_BEGIN_ALLOW_THREADS
128 int status;
129 Py_ssize_t bufsize;
130 struct group grp;
Thomas Wouters477c8d52006-05-27 19:21:47 +0000131
William Grzybowski23e65b22018-09-07 09:06:15 -0300132 bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
133 if (bufsize == -1) {
134 bufsize = DEFAULT_BUFFER_SIZE;
135 }
136
137 while (1) {
138 buf2 = PyMem_RawRealloc(buf, bufsize);
139 if (buf2 == NULL) {
140 p = NULL;
141 nomem = 1;
142 break;
143 }
144 buf = buf2;
145 status = getgrgid_r(gid, &grp, buf, bufsize, &p);
146 if (status != 0) {
147 p = NULL;
148 }
149 if (p != NULL || status != ERANGE) {
150 break;
151 }
152 if (bufsize > (PY_SSIZE_T_MAX >> 1)) {
153 nomem = 1;
154 break;
155 }
156 bufsize <<= 1;
157 }
158
159 Py_END_ALLOW_THREADS
160#else
161 p = getgrgid(gid);
162#endif
163 if (p == NULL) {
164 PyMem_RawFree(buf);
165 if (nomem == 1) {
166 return PyErr_NoMemory();
167 }
Serhiy Storchaka7cf55992013-02-10 21:56:49 +0200168 PyObject *gid_obj = _PyLong_FromGid(gid);
169 if (gid_obj == NULL)
170 return NULL;
171 PyErr_Format(PyExc_KeyError, "getgrgid(): gid not found: %S", gid_obj);
172 Py_DECREF(gid_obj);
Fred Drake51b6bc52000-07-08 16:56:26 +0000173 return NULL;
174 }
William Grzybowski23e65b22018-09-07 09:06:15 -0300175 retval = mkgrent(p);
176#ifdef HAVE_GETGRGID_R
177 PyMem_RawFree(buf);
178#endif
179 return retval;
Guido van Rossum20882d51994-06-23 11:15:44 +0000180}
181
Brett Cannon8fb7bb22014-08-22 11:52:46 -0400182/*[clinic input]
183grp.getgrnam
Thomas Wouters477c8d52006-05-27 19:21:47 +0000184
Brett Cannon8fb7bb22014-08-22 11:52:46 -0400185 name: unicode
186
187Return the group database entry for the given group name.
188
189If name is not valid, raise KeyError.
190[clinic start generated code]*/
191
192static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300193grp_getgrnam_impl(PyObject *module, PyObject *name)
194/*[clinic end generated code: output=67905086f403c21c input=08ded29affa3c863]*/
Brett Cannon8fb7bb22014-08-22 11:52:46 -0400195{
William Grzybowski23e65b22018-09-07 09:06:15 -0300196 char *buf = NULL, *buf2 = NULL, *name_chars;
197 int nomem = 0;
Brett Cannon8fb7bb22014-08-22 11:52:46 -0400198 struct group *p;
199 PyObject *bytes, *retval = NULL;
200
201 if ((bytes = PyUnicode_EncodeFSDefault(name)) == NULL)
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000202 return NULL;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300203 /* check for embedded null bytes */
Brett Cannon8fb7bb22014-08-22 11:52:46 -0400204 if (PyBytes_AsStringAndSize(bytes, &name_chars, NULL) == -1)
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000205 goto out;
William Grzybowski23e65b22018-09-07 09:06:15 -0300206#ifdef HAVE_GETGRNAM_R
207 Py_BEGIN_ALLOW_THREADS
208 int status;
209 Py_ssize_t bufsize;
210 struct group grp;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000211
William Grzybowski23e65b22018-09-07 09:06:15 -0300212 bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
213 if (bufsize == -1) {
214 bufsize = DEFAULT_BUFFER_SIZE;
215 }
216
217 while(1) {
218 buf2 = PyMem_RawRealloc(buf, bufsize);
219 if (buf2 == NULL) {
220 p = NULL;
221 nomem = 1;
222 break;
223 }
224 buf = buf2;
225 status = getgrnam_r(name_chars, &grp, buf, bufsize, &p);
226 if (status != 0) {
227 p = NULL;
228 }
229 if (p != NULL || status != ERANGE) {
230 break;
231 }
232 if (bufsize > (PY_SSIZE_T_MAX >> 1)) {
233 nomem = 1;
234 break;
235 }
236 bufsize <<= 1;
237 }
238
239 Py_END_ALLOW_THREADS
240#else
241 p = getgrnam(name_chars);
242#endif
243 if (p == NULL) {
244 if (nomem == 1) {
245 PyErr_NoMemory();
246 }
247 else {
William Grzybowski28658482018-09-07 14:10:39 -0300248 PyErr_Format(PyExc_KeyError, "getgrnam(): name not found: %S", name);
William Grzybowski23e65b22018-09-07 09:06:15 -0300249 }
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000250 goto out;
Fred Drake51b6bc52000-07-08 16:56:26 +0000251 }
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000252 retval = mkgrent(p);
253out:
William Grzybowski23e65b22018-09-07 09:06:15 -0300254 PyMem_RawFree(buf);
Martin v. Löwisb6a748b2009-05-29 15:23:17 +0000255 Py_DECREF(bytes);
256 return retval;
Guido van Rossum20882d51994-06-23 11:15:44 +0000257}
258
Brett Cannon8fb7bb22014-08-22 11:52:46 -0400259/*[clinic input]
260grp.getgrall
261
262Return a list of all available group entries, in arbitrary order.
263
264An entry whose name starts with '+' or '-' represents an instruction
265to use YP/NIS and may not be accessible via getgrnam or getgrgid.
266[clinic start generated code]*/
267
Fred Drake51b6bc52000-07-08 16:56:26 +0000268static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300269grp_getgrall_impl(PyObject *module)
270/*[clinic end generated code: output=585dad35e2e763d7 input=d7df76c825c367df]*/
Guido van Rossum20882d51994-06-23 11:15:44 +0000271{
Fred Drake51b6bc52000-07-08 16:56:26 +0000272 PyObject *d;
273 struct group *p;
274
Fred Drake51b6bc52000-07-08 16:56:26 +0000275 if ((d = PyList_New(0)) == NULL)
276 return NULL;
277 setgrent();
278 while ((p = getgrent()) != NULL) {
279 PyObject *v = mkgrent(p);
280 if (v == NULL || PyList_Append(d, v) != 0) {
281 Py_XDECREF(v);
282 Py_DECREF(d);
Martin v. Löwise23c8682009-05-29 16:01:34 +0000283 endgrent();
Fred Drake51b6bc52000-07-08 16:56:26 +0000284 return NULL;
285 }
286 Py_DECREF(v);
287 }
Fred Drake8e68eb62001-03-11 03:03:07 +0000288 endgrent();
Fred Drake51b6bc52000-07-08 16:56:26 +0000289 return d;
Guido van Rossum20882d51994-06-23 11:15:44 +0000290}
291
Roger E. Masseb2b44e51996-12-18 19:37:32 +0000292static PyMethodDef grp_methods[] = {
Brett Cannon8fb7bb22014-08-22 11:52:46 -0400293 GRP_GETGRGID_METHODDEF
294 GRP_GETGRNAM_METHODDEF
295 GRP_GETGRALL_METHODDEF
296 {NULL, NULL}
Guido van Rossum20882d51994-06-23 11:15:44 +0000297};
298
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000299PyDoc_STRVAR(grp__doc__,
Fred Drake51b6bc52000-07-08 16:56:26 +0000300"Access to the Unix group database.\n\
301\n\
302Group entries are reported as 4-tuples containing the following fields\n\
303from the group database, in order:\n\
304\n\
Georg Brandl41ea1f42014-10-02 08:34:41 +0200305 gr_name - name of the group\n\
306 gr_passwd - group password (encrypted); often empty\n\
307 gr_gid - numeric ID of the group\n\
308 gr_mem - list of members\n\
Fred Drake51b6bc52000-07-08 16:56:26 +0000309\n\
310The gid is an integer, name and password are strings. (Note that most\n\
311users are not explicitly listed as members of the groups they are in\n\
312according to the password database. Check both databases to get\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000313complete membership information.)");
Fred Drake51b6bc52000-07-08 16:56:26 +0000314
315
Martin v. Löwis1a214512008-06-11 05:26:20 +0000316
317static struct PyModuleDef grpmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000318 PyModuleDef_HEAD_INIT,
319 "grp",
320 grp__doc__,
321 -1,
322 grp_methods,
323 NULL,
324 NULL,
325 NULL,
326 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000327};
328
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000329PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000330PyInit_grp(void)
Guido van Rossum20882d51994-06-23 11:15:44 +0000331{
Martin v. Löwisdbd55b32002-03-01 10:38:44 +0000332 PyObject *m, *d;
Martin v. Löwis1a214512008-06-11 05:26:20 +0000333 m = PyModule_Create(&grpmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000334 if (m == NULL)
Martin v. Löwis1a214512008-06-11 05:26:20 +0000335 return NULL;
Martin v. Löwisdbd55b32002-03-01 10:38:44 +0000336 d = PyModule_GetDict(m);
Victor Stinner1c8f0592013-07-22 22:24:54 +0200337 if (!initialized) {
338 if (PyStructSequence_InitType2(&StructGrpType,
339 &struct_group_type_desc) < 0)
340 return NULL;
341 }
342 if (PyDict_SetItemString(d, "struct_group",
343 (PyObject *)&StructGrpType) < 0)
344 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000345 initialized = 1;
Martin v. Löwis1a214512008-06-11 05:26:20 +0000346 return m;
Guido van Rossum20882d51994-06-23 11:15:44 +0000347}