17db96d56Sopenharmony_ci 27db96d56Sopenharmony_ci/* UNIX group file access module */ 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci#include "Python.h" 57db96d56Sopenharmony_ci#include "posixmodule.h" 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci#include <grp.h> 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci#include "clinic/grpmodule.c.h" 107db96d56Sopenharmony_ci/*[clinic input] 117db96d56Sopenharmony_cimodule grp 127db96d56Sopenharmony_ci[clinic start generated code]*/ 137db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cade63f2ed1bd9f8]*/ 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_cistatic PyStructSequence_Field struct_group_type_fields[] = { 167db96d56Sopenharmony_ci {"gr_name", "group name"}, 177db96d56Sopenharmony_ci {"gr_passwd", "password"}, 187db96d56Sopenharmony_ci {"gr_gid", "group id"}, 197db96d56Sopenharmony_ci {"gr_mem", "group members"}, 207db96d56Sopenharmony_ci {0} 217db96d56Sopenharmony_ci}; 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_ciPyDoc_STRVAR(struct_group__doc__, 247db96d56Sopenharmony_ci"grp.struct_group: Results from getgr*() routines.\n\n\ 257db96d56Sopenharmony_ciThis object may be accessed either as a tuple of\n\ 267db96d56Sopenharmony_ci (gr_name,gr_passwd,gr_gid,gr_mem)\n\ 277db96d56Sopenharmony_cior via the object attributes as named in the above tuple.\n"); 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_cistatic PyStructSequence_Desc struct_group_type_desc = { 307db96d56Sopenharmony_ci "grp.struct_group", 317db96d56Sopenharmony_ci struct_group__doc__, 327db96d56Sopenharmony_ci struct_group_type_fields, 337db96d56Sopenharmony_ci 4, 347db96d56Sopenharmony_ci}; 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_citypedef struct { 387db96d56Sopenharmony_ci PyTypeObject *StructGrpType; 397db96d56Sopenharmony_ci} grpmodulestate; 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_cistatic inline grpmodulestate* 427db96d56Sopenharmony_ciget_grp_state(PyObject *module) 437db96d56Sopenharmony_ci{ 447db96d56Sopenharmony_ci void *state = PyModule_GetState(module); 457db96d56Sopenharmony_ci assert(state != NULL); 467db96d56Sopenharmony_ci return (grpmodulestate *)state; 477db96d56Sopenharmony_ci} 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_cistatic struct PyModuleDef grpmodule; 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci#define DEFAULT_BUFFER_SIZE 1024 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_cistatic PyObject * 547db96d56Sopenharmony_cimkgrent(PyObject *module, struct group *p) 557db96d56Sopenharmony_ci{ 567db96d56Sopenharmony_ci int setIndex = 0; 577db96d56Sopenharmony_ci PyObject *v, *w; 587db96d56Sopenharmony_ci char **member; 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci v = PyStructSequence_New(get_grp_state(module)->StructGrpType); 617db96d56Sopenharmony_ci if (v == NULL) 627db96d56Sopenharmony_ci return NULL; 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci if ((w = PyList_New(0)) == NULL) { 657db96d56Sopenharmony_ci Py_DECREF(v); 667db96d56Sopenharmony_ci return NULL; 677db96d56Sopenharmony_ci } 687db96d56Sopenharmony_ci for (member = p->gr_mem; *member != NULL; member++) { 697db96d56Sopenharmony_ci PyObject *x = PyUnicode_DecodeFSDefault(*member); 707db96d56Sopenharmony_ci if (x == NULL || PyList_Append(w, x) != 0) { 717db96d56Sopenharmony_ci Py_XDECREF(x); 727db96d56Sopenharmony_ci Py_DECREF(w); 737db96d56Sopenharmony_ci Py_DECREF(v); 747db96d56Sopenharmony_ci return NULL; 757db96d56Sopenharmony_ci } 767db96d56Sopenharmony_ci Py_DECREF(x); 777db96d56Sopenharmony_ci } 787db96d56Sopenharmony_ci 797db96d56Sopenharmony_ci#define SET(i,val) PyStructSequence_SET_ITEM(v, i, val) 807db96d56Sopenharmony_ci SET(setIndex++, PyUnicode_DecodeFSDefault(p->gr_name)); 817db96d56Sopenharmony_ci if (p->gr_passwd) 827db96d56Sopenharmony_ci SET(setIndex++, PyUnicode_DecodeFSDefault(p->gr_passwd)); 837db96d56Sopenharmony_ci else { 847db96d56Sopenharmony_ci SET(setIndex++, Py_None); 857db96d56Sopenharmony_ci Py_INCREF(Py_None); 867db96d56Sopenharmony_ci } 877db96d56Sopenharmony_ci SET(setIndex++, _PyLong_FromGid(p->gr_gid)); 887db96d56Sopenharmony_ci SET(setIndex++, w); 897db96d56Sopenharmony_ci#undef SET 907db96d56Sopenharmony_ci 917db96d56Sopenharmony_ci if (PyErr_Occurred()) { 927db96d56Sopenharmony_ci Py_DECREF(v); 937db96d56Sopenharmony_ci return NULL; 947db96d56Sopenharmony_ci } 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci return v; 977db96d56Sopenharmony_ci} 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci/*[clinic input] 1007db96d56Sopenharmony_cigrp.getgrgid 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci id: object 1037db96d56Sopenharmony_ci 1047db96d56Sopenharmony_ciReturn the group database entry for the given numeric group ID. 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ciIf id is not valid, raise KeyError. 1077db96d56Sopenharmony_ci[clinic start generated code]*/ 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_cistatic PyObject * 1107db96d56Sopenharmony_cigrp_getgrgid_impl(PyObject *module, PyObject *id) 1117db96d56Sopenharmony_ci/*[clinic end generated code: output=30797c289504a1ba input=15fa0e2ccf5cda25]*/ 1127db96d56Sopenharmony_ci{ 1137db96d56Sopenharmony_ci PyObject *retval = NULL; 1147db96d56Sopenharmony_ci int nomem = 0; 1157db96d56Sopenharmony_ci char *buf = NULL, *buf2 = NULL; 1167db96d56Sopenharmony_ci gid_t gid; 1177db96d56Sopenharmony_ci struct group *p; 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci if (!_Py_Gid_Converter(id, &gid)) { 1207db96d56Sopenharmony_ci return NULL; 1217db96d56Sopenharmony_ci } 1227db96d56Sopenharmony_ci#ifdef HAVE_GETGRGID_R 1237db96d56Sopenharmony_ci int status; 1247db96d56Sopenharmony_ci Py_ssize_t bufsize; 1257db96d56Sopenharmony_ci /* Note: 'grp' will be used via pointer 'p' on getgrgid_r success. */ 1267db96d56Sopenharmony_ci struct group grp; 1277db96d56Sopenharmony_ci 1287db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 1297db96d56Sopenharmony_ci bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); 1307db96d56Sopenharmony_ci if (bufsize == -1) { 1317db96d56Sopenharmony_ci bufsize = DEFAULT_BUFFER_SIZE; 1327db96d56Sopenharmony_ci } 1337db96d56Sopenharmony_ci 1347db96d56Sopenharmony_ci while (1) { 1357db96d56Sopenharmony_ci buf2 = PyMem_RawRealloc(buf, bufsize); 1367db96d56Sopenharmony_ci if (buf2 == NULL) { 1377db96d56Sopenharmony_ci p = NULL; 1387db96d56Sopenharmony_ci nomem = 1; 1397db96d56Sopenharmony_ci break; 1407db96d56Sopenharmony_ci } 1417db96d56Sopenharmony_ci buf = buf2; 1427db96d56Sopenharmony_ci status = getgrgid_r(gid, &grp, buf, bufsize, &p); 1437db96d56Sopenharmony_ci if (status != 0) { 1447db96d56Sopenharmony_ci p = NULL; 1457db96d56Sopenharmony_ci } 1467db96d56Sopenharmony_ci if (p != NULL || status != ERANGE) { 1477db96d56Sopenharmony_ci break; 1487db96d56Sopenharmony_ci } 1497db96d56Sopenharmony_ci if (bufsize > (PY_SSIZE_T_MAX >> 1)) { 1507db96d56Sopenharmony_ci nomem = 1; 1517db96d56Sopenharmony_ci break; 1527db96d56Sopenharmony_ci } 1537db96d56Sopenharmony_ci bufsize <<= 1; 1547db96d56Sopenharmony_ci } 1557db96d56Sopenharmony_ci 1567db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 1577db96d56Sopenharmony_ci#else 1587db96d56Sopenharmony_ci p = getgrgid(gid); 1597db96d56Sopenharmony_ci#endif 1607db96d56Sopenharmony_ci if (p == NULL) { 1617db96d56Sopenharmony_ci PyMem_RawFree(buf); 1627db96d56Sopenharmony_ci if (nomem == 1) { 1637db96d56Sopenharmony_ci return PyErr_NoMemory(); 1647db96d56Sopenharmony_ci } 1657db96d56Sopenharmony_ci PyObject *gid_obj = _PyLong_FromGid(gid); 1667db96d56Sopenharmony_ci if (gid_obj == NULL) 1677db96d56Sopenharmony_ci return NULL; 1687db96d56Sopenharmony_ci PyErr_Format(PyExc_KeyError, "getgrgid(): gid not found: %S", gid_obj); 1697db96d56Sopenharmony_ci Py_DECREF(gid_obj); 1707db96d56Sopenharmony_ci return NULL; 1717db96d56Sopenharmony_ci } 1727db96d56Sopenharmony_ci retval = mkgrent(module, p); 1737db96d56Sopenharmony_ci#ifdef HAVE_GETGRGID_R 1747db96d56Sopenharmony_ci PyMem_RawFree(buf); 1757db96d56Sopenharmony_ci#endif 1767db96d56Sopenharmony_ci return retval; 1777db96d56Sopenharmony_ci} 1787db96d56Sopenharmony_ci 1797db96d56Sopenharmony_ci/*[clinic input] 1807db96d56Sopenharmony_cigrp.getgrnam 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ci name: unicode 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ciReturn the group database entry for the given group name. 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_ciIf name is not valid, raise KeyError. 1877db96d56Sopenharmony_ci[clinic start generated code]*/ 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_cistatic PyObject * 1907db96d56Sopenharmony_cigrp_getgrnam_impl(PyObject *module, PyObject *name) 1917db96d56Sopenharmony_ci/*[clinic end generated code: output=67905086f403c21c input=08ded29affa3c863]*/ 1927db96d56Sopenharmony_ci{ 1937db96d56Sopenharmony_ci char *buf = NULL, *buf2 = NULL, *name_chars; 1947db96d56Sopenharmony_ci int nomem = 0; 1957db96d56Sopenharmony_ci struct group *p; 1967db96d56Sopenharmony_ci PyObject *bytes, *retval = NULL; 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_ci if ((bytes = PyUnicode_EncodeFSDefault(name)) == NULL) 1997db96d56Sopenharmony_ci return NULL; 2007db96d56Sopenharmony_ci /* check for embedded null bytes */ 2017db96d56Sopenharmony_ci if (PyBytes_AsStringAndSize(bytes, &name_chars, NULL) == -1) 2027db96d56Sopenharmony_ci goto out; 2037db96d56Sopenharmony_ci#ifdef HAVE_GETGRNAM_R 2047db96d56Sopenharmony_ci int status; 2057db96d56Sopenharmony_ci Py_ssize_t bufsize; 2067db96d56Sopenharmony_ci /* Note: 'grp' will be used via pointer 'p' on getgrnam_r success. */ 2077db96d56Sopenharmony_ci struct group grp; 2087db96d56Sopenharmony_ci 2097db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 2107db96d56Sopenharmony_ci bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); 2117db96d56Sopenharmony_ci if (bufsize == -1) { 2127db96d56Sopenharmony_ci bufsize = DEFAULT_BUFFER_SIZE; 2137db96d56Sopenharmony_ci } 2147db96d56Sopenharmony_ci 2157db96d56Sopenharmony_ci while(1) { 2167db96d56Sopenharmony_ci buf2 = PyMem_RawRealloc(buf, bufsize); 2177db96d56Sopenharmony_ci if (buf2 == NULL) { 2187db96d56Sopenharmony_ci p = NULL; 2197db96d56Sopenharmony_ci nomem = 1; 2207db96d56Sopenharmony_ci break; 2217db96d56Sopenharmony_ci } 2227db96d56Sopenharmony_ci buf = buf2; 2237db96d56Sopenharmony_ci status = getgrnam_r(name_chars, &grp, buf, bufsize, &p); 2247db96d56Sopenharmony_ci if (status != 0) { 2257db96d56Sopenharmony_ci p = NULL; 2267db96d56Sopenharmony_ci } 2277db96d56Sopenharmony_ci if (p != NULL || status != ERANGE) { 2287db96d56Sopenharmony_ci break; 2297db96d56Sopenharmony_ci } 2307db96d56Sopenharmony_ci if (bufsize > (PY_SSIZE_T_MAX >> 1)) { 2317db96d56Sopenharmony_ci nomem = 1; 2327db96d56Sopenharmony_ci break; 2337db96d56Sopenharmony_ci } 2347db96d56Sopenharmony_ci bufsize <<= 1; 2357db96d56Sopenharmony_ci } 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 2387db96d56Sopenharmony_ci#else 2397db96d56Sopenharmony_ci p = getgrnam(name_chars); 2407db96d56Sopenharmony_ci#endif 2417db96d56Sopenharmony_ci if (p == NULL) { 2427db96d56Sopenharmony_ci if (nomem == 1) { 2437db96d56Sopenharmony_ci PyErr_NoMemory(); 2447db96d56Sopenharmony_ci } 2457db96d56Sopenharmony_ci else { 2467db96d56Sopenharmony_ci PyErr_Format(PyExc_KeyError, "getgrnam(): name not found: %R", name); 2477db96d56Sopenharmony_ci } 2487db96d56Sopenharmony_ci goto out; 2497db96d56Sopenharmony_ci } 2507db96d56Sopenharmony_ci retval = mkgrent(module, p); 2517db96d56Sopenharmony_ciout: 2527db96d56Sopenharmony_ci PyMem_RawFree(buf); 2537db96d56Sopenharmony_ci Py_DECREF(bytes); 2547db96d56Sopenharmony_ci return retval; 2557db96d56Sopenharmony_ci} 2567db96d56Sopenharmony_ci 2577db96d56Sopenharmony_ci/*[clinic input] 2587db96d56Sopenharmony_cigrp.getgrall 2597db96d56Sopenharmony_ci 2607db96d56Sopenharmony_ciReturn a list of all available group entries, in arbitrary order. 2617db96d56Sopenharmony_ci 2627db96d56Sopenharmony_ciAn entry whose name starts with '+' or '-' represents an instruction 2637db96d56Sopenharmony_cito use YP/NIS and may not be accessible via getgrnam or getgrgid. 2647db96d56Sopenharmony_ci[clinic start generated code]*/ 2657db96d56Sopenharmony_ci 2667db96d56Sopenharmony_cistatic PyObject * 2677db96d56Sopenharmony_cigrp_getgrall_impl(PyObject *module) 2687db96d56Sopenharmony_ci/*[clinic end generated code: output=585dad35e2e763d7 input=d7df76c825c367df]*/ 2697db96d56Sopenharmony_ci{ 2707db96d56Sopenharmony_ci PyObject *d; 2717db96d56Sopenharmony_ci struct group *p; 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_ci if ((d = PyList_New(0)) == NULL) 2747db96d56Sopenharmony_ci return NULL; 2757db96d56Sopenharmony_ci setgrent(); 2767db96d56Sopenharmony_ci while ((p = getgrent()) != NULL) { 2777db96d56Sopenharmony_ci PyObject *v = mkgrent(module, p); 2787db96d56Sopenharmony_ci if (v == NULL || PyList_Append(d, v) != 0) { 2797db96d56Sopenharmony_ci Py_XDECREF(v); 2807db96d56Sopenharmony_ci Py_DECREF(d); 2817db96d56Sopenharmony_ci endgrent(); 2827db96d56Sopenharmony_ci return NULL; 2837db96d56Sopenharmony_ci } 2847db96d56Sopenharmony_ci Py_DECREF(v); 2857db96d56Sopenharmony_ci } 2867db96d56Sopenharmony_ci endgrent(); 2877db96d56Sopenharmony_ci return d; 2887db96d56Sopenharmony_ci} 2897db96d56Sopenharmony_ci 2907db96d56Sopenharmony_cistatic PyMethodDef grp_methods[] = { 2917db96d56Sopenharmony_ci GRP_GETGRGID_METHODDEF 2927db96d56Sopenharmony_ci GRP_GETGRNAM_METHODDEF 2937db96d56Sopenharmony_ci GRP_GETGRALL_METHODDEF 2947db96d56Sopenharmony_ci {NULL, NULL} 2957db96d56Sopenharmony_ci}; 2967db96d56Sopenharmony_ci 2977db96d56Sopenharmony_ciPyDoc_STRVAR(grp__doc__, 2987db96d56Sopenharmony_ci"Access to the Unix group database.\n\ 2997db96d56Sopenharmony_ci\n\ 3007db96d56Sopenharmony_ciGroup entries are reported as 4-tuples containing the following fields\n\ 3017db96d56Sopenharmony_cifrom the group database, in order:\n\ 3027db96d56Sopenharmony_ci\n\ 3037db96d56Sopenharmony_ci gr_name - name of the group\n\ 3047db96d56Sopenharmony_ci gr_passwd - group password (encrypted); often empty\n\ 3057db96d56Sopenharmony_ci gr_gid - numeric ID of the group\n\ 3067db96d56Sopenharmony_ci gr_mem - list of members\n\ 3077db96d56Sopenharmony_ci\n\ 3087db96d56Sopenharmony_ciThe gid is an integer, name and password are strings. (Note that most\n\ 3097db96d56Sopenharmony_ciusers are not explicitly listed as members of the groups they are in\n\ 3107db96d56Sopenharmony_ciaccording to the password database. Check both databases to get\n\ 3117db96d56Sopenharmony_cicomplete membership information.)"); 3127db96d56Sopenharmony_ci 3137db96d56Sopenharmony_cistatic int 3147db96d56Sopenharmony_cigrpmodule_exec(PyObject *module) 3157db96d56Sopenharmony_ci{ 3167db96d56Sopenharmony_ci grpmodulestate *state = get_grp_state(module); 3177db96d56Sopenharmony_ci 3187db96d56Sopenharmony_ci state->StructGrpType = PyStructSequence_NewType(&struct_group_type_desc); 3197db96d56Sopenharmony_ci if (state->StructGrpType == NULL) { 3207db96d56Sopenharmony_ci return -1; 3217db96d56Sopenharmony_ci } 3227db96d56Sopenharmony_ci if (PyModule_AddType(module, state->StructGrpType) < 0) { 3237db96d56Sopenharmony_ci return -1; 3247db96d56Sopenharmony_ci } 3257db96d56Sopenharmony_ci return 0; 3267db96d56Sopenharmony_ci} 3277db96d56Sopenharmony_ci 3287db96d56Sopenharmony_cistatic PyModuleDef_Slot grpmodule_slots[] = { 3297db96d56Sopenharmony_ci {Py_mod_exec, grpmodule_exec}, 3307db96d56Sopenharmony_ci {0, NULL} 3317db96d56Sopenharmony_ci}; 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_cistatic int grpmodule_traverse(PyObject *m, visitproc visit, void *arg) { 3347db96d56Sopenharmony_ci Py_VISIT(get_grp_state(m)->StructGrpType); 3357db96d56Sopenharmony_ci return 0; 3367db96d56Sopenharmony_ci} 3377db96d56Sopenharmony_ci 3387db96d56Sopenharmony_cistatic int grpmodule_clear(PyObject *m) { 3397db96d56Sopenharmony_ci Py_CLEAR(get_grp_state(m)->StructGrpType); 3407db96d56Sopenharmony_ci return 0; 3417db96d56Sopenharmony_ci} 3427db96d56Sopenharmony_ci 3437db96d56Sopenharmony_cistatic void grpmodule_free(void *m) { 3447db96d56Sopenharmony_ci grpmodule_clear((PyObject *)m); 3457db96d56Sopenharmony_ci} 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_cistatic struct PyModuleDef grpmodule = { 3487db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 3497db96d56Sopenharmony_ci .m_name = "grp", 3507db96d56Sopenharmony_ci .m_doc = grp__doc__, 3517db96d56Sopenharmony_ci .m_size = sizeof(grpmodulestate), 3527db96d56Sopenharmony_ci .m_methods = grp_methods, 3537db96d56Sopenharmony_ci .m_slots = grpmodule_slots, 3547db96d56Sopenharmony_ci .m_traverse = grpmodule_traverse, 3557db96d56Sopenharmony_ci .m_clear = grpmodule_clear, 3567db96d56Sopenharmony_ci .m_free = grpmodule_free, 3577db96d56Sopenharmony_ci}; 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ciPyMODINIT_FUNC 3607db96d56Sopenharmony_ciPyInit_grp(void) 3617db96d56Sopenharmony_ci{ 3627db96d56Sopenharmony_ci return PyModuleDef_Init(&grpmodule); 3637db96d56Sopenharmony_ci} 364