1
2 /* UNIX group file access module */
3
4 #include "Python.h"
5 #include "structseq.h"
6 #include "posixmodule.h"
7
8 #include <grp.h>
9
10 static PyStructSequence_Field struct_group_type_fields[] = {
11 {"gr_name", "group name"},
12 {"gr_passwd", "password"},
13 {"gr_gid", "group id"},
14 {"gr_mem", "group members"},
15 {0}
16 };
17
18 PyDoc_STRVAR(struct_group__doc__,
19 "grp.struct_group: Results from getgr*() routines.\n\n\
20 This object may be accessed either as a tuple of\n\
21 (gr_name,gr_passwd,gr_gid,gr_mem)\n\
22 or via the object attributes as named in the above tuple.\n");
23
24 static PyStructSequence_Desc struct_group_type_desc = {
25 "grp.struct_group",
26 struct_group__doc__,
27 struct_group_type_fields,
28 4,
29 };
30
31
32 static int initialized;
33 static PyTypeObject StructGrpType;
34
35 static PyObject *
mkgrent(struct group * p)36 mkgrent(struct group *p)
37 {
38 int setIndex = 0;
39 PyObject *v = PyStructSequence_New(&StructGrpType), *w;
40 char **member;
41
42 if (v == NULL)
43 return NULL;
44
45 if ((w = PyList_New(0)) == NULL) {
46 Py_DECREF(v);
47 return NULL;
48 }
49 for (member = p->gr_mem; *member != NULL; member++) {
50 PyObject *x = PyString_FromString(*member);
51 if (x == NULL || PyList_Append(w, x) != 0) {
52 Py_XDECREF(x);
53 Py_DECREF(w);
54 Py_DECREF(v);
55 return NULL;
56 }
57 Py_DECREF(x);
58 }
59
60 #define SET(i,val) PyStructSequence_SET_ITEM(v, i, val)
61 SET(setIndex++, PyString_FromString(p->gr_name));
62 #ifdef __VMS
63 SET(setIndex++, Py_None);
64 Py_INCREF(Py_None);
65 #else
66 if (p->gr_passwd)
67 SET(setIndex++, PyString_FromString(p->gr_passwd));
68 else {
69 SET(setIndex++, Py_None);
70 Py_INCREF(Py_None);
71 }
72 #endif
73 SET(setIndex++, _PyInt_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 static PyObject *
grp_getgrgid(PyObject * self,PyObject * pyo_id)86 grp_getgrgid(PyObject *self, PyObject *pyo_id)
87 {
88 PyObject *py_int_id;
89 gid_t gid;
90 struct group *p;
91
92 py_int_id = PyNumber_Int(pyo_id);
93 if (!py_int_id)
94 return NULL;
95 if (!_Py_Gid_Converter(py_int_id, &gid)) {
96 Py_DECREF(py_int_id);
97 return NULL;
98 }
99 Py_DECREF(py_int_id);
100
101 if ((p = getgrgid(gid)) == NULL) {
102 if (gid < 0)
103 PyErr_Format(PyExc_KeyError,
104 "getgrgid(): gid not found: %ld", (long)gid);
105 else
106 PyErr_Format(PyExc_KeyError,
107 "getgrgid(): gid not found: %lu", (unsigned long)gid);
108 return NULL;
109 }
110 return mkgrent(p);
111 }
112
113 static PyObject *
grp_getgrnam(PyObject * self,PyObject * pyo_name)114 grp_getgrnam(PyObject *self, PyObject *pyo_name)
115 {
116 PyObject *py_str_name;
117 char *name;
118 struct group *p;
119
120 py_str_name = PyObject_Str(pyo_name);
121 if (!py_str_name)
122 return NULL;
123 name = PyString_AS_STRING(py_str_name);
124
125 if ((p = getgrnam(name)) == NULL) {
126 PyErr_Format(PyExc_KeyError, "getgrnam(): name not found: %s", name);
127 Py_DECREF(py_str_name);
128 return NULL;
129 }
130
131 Py_DECREF(py_str_name);
132 return mkgrent(p);
133 }
134
135 static PyObject *
grp_getgrall(PyObject * self,PyObject * ignore)136 grp_getgrall(PyObject *self, PyObject *ignore)
137 {
138 PyObject *d;
139 struct group *p;
140
141 if ((d = PyList_New(0)) == NULL)
142 return NULL;
143 setgrent();
144 while ((p = getgrent()) != NULL) {
145 PyObject *v = mkgrent(p);
146 if (v == NULL || PyList_Append(d, v) != 0) {
147 Py_XDECREF(v);
148 Py_DECREF(d);
149 endgrent();
150 return NULL;
151 }
152 Py_DECREF(v);
153 }
154 endgrent();
155 return d;
156 }
157
158 static PyMethodDef grp_methods[] = {
159 {"getgrgid", grp_getgrgid, METH_O,
160 "getgrgid(id) -> (gr_name,gr_passwd,gr_gid,gr_mem)\n\
161 Return the group database entry for the given numeric group ID. If\n\
162 id is not valid, raise KeyError."},
163 {"getgrnam", grp_getgrnam, METH_O,
164 "getgrnam(name) -> (gr_name,gr_passwd,gr_gid,gr_mem)\n\
165 Return the group database entry for the given group name. If\n\
166 name is not valid, raise KeyError."},
167 {"getgrall", grp_getgrall, METH_NOARGS,
168 "getgrall() -> list of tuples\n\
169 Return a list of all available group entries, in arbitrary order.\n\
170 An entry whose name starts with '+' or '-' represents an instruction\n\
171 to use YP/NIS and may not be accessible via getgrnam or getgrgid."},
172 {NULL, NULL} /* sentinel */
173 };
174
175 PyDoc_STRVAR(grp__doc__,
176 "Access to the Unix group database.\n\
177 \n\
178 Group entries are reported as 4-tuples containing the following fields\n\
179 from the group database, in order:\n\
180 \n\
181 gr_name - name of the group\n\
182 gr_passwd - group password (encrypted); often empty\n\
183 gr_gid - numeric ID of the group\n\
184 gr_mem - list of members\n\
185 \n\
186 The gid is an integer, name and password are strings. (Note that most\n\
187 users are not explicitly listed as members of the groups they are in\n\
188 according to the password database. Check both databases to get\n\
189 complete membership information.)");
190
191
192 PyMODINIT_FUNC
initgrp(void)193 initgrp(void)
194 {
195 PyObject *m, *d;
196 m = Py_InitModule3("grp", grp_methods, grp__doc__);
197 if (m == NULL)
198 return;
199 d = PyModule_GetDict(m);
200 if (!initialized)
201 PyStructSequence_InitType(&StructGrpType, &struct_group_type_desc);
202 PyDict_SetItemString(d, "struct_group", (PyObject *) &StructGrpType);
203 initialized = 1;
204 }
205