blob: 55da9b8aa2860e174ec0c40849ebedc368b10090 [file] [log] [blame]
Andrew Hsieh9a7616f2013-05-21 20:32:42 +08001
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
10static PyStructSequence_Field struct_group_type_fields[] = {
11 {"gr_name", "group name"},
12 {"gr_passwd", "password"},
13 {"gr_gid", "group id"},
14 {"gr_mem", "group memebers"},
15 {0}
16};
17
18PyDoc_STRVAR(struct_group__doc__,
19"grp.struct_group: Results from getgr*() routines.\n\n\
20This object may be accessed either as a tuple of\n\
21 (gr_name,gr_passwd,gr_gid,gr_mem)\n\
22or via the object attributes as named in the above tuple.\n");
23
24static PyStructSequence_Desc struct_group_type_desc = {
25 "grp.struct_group",
26 struct_group__doc__,
27 struct_group_type_fields,
28 4,
29};
30
31
32static int initialized;
33static PyTypeObject StructGrpType;
34
35static PyObject *
36mkgrent(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
85static PyObject *
86grp_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
113static PyObject *
114grp_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
135static PyObject *
136grp_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
158static PyMethodDef grp_methods[] = {
159 {"getgrgid", grp_getgrgid, METH_O,
160 "getgrgid(id) -> tuple\n\
161Return the group database entry for the given numeric group ID. If\n\
162id is not valid, raise KeyError."},
163 {"getgrnam", grp_getgrnam, METH_O,
164 "getgrnam(name) -> tuple\n\
165Return the group database entry for the given group name. If\n\
166name is not valid, raise KeyError."},
167 {"getgrall", grp_getgrall, METH_NOARGS,
168 "getgrall() -> list of tuples\n\
169Return a list of all available group entries, in arbitrary order.\n\
170An entry whose name starts with '+' or '-' represents an instruction\n\
171to use YP/NIS and may not be accessible via getgrnam or getgrgid."},
172 {NULL, NULL} /* sentinel */
173};
174
175PyDoc_STRVAR(grp__doc__,
176"Access to the Unix group database.\n\
177\n\
178Group entries are reported as 4-tuples containing the following fields\n\
179from the group database, in order:\n\
180\n\
181 name - name of the group\n\
182 passwd - group password (encrypted); often empty\n\
183 gid - numeric ID of the group\n\
184 mem - list of members\n\
185\n\
186The gid is an integer, name and password are strings. (Note that most\n\
187users are not explicitly listed as members of the groups they are in\n\
188according to the password database. Check both databases to get\n\
189complete membership information.)");
190
191
192PyMODINIT_FUNC
193initgrp(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}