Index: configure =================================================================== --- configure (revision 87178) +++ configure (working copy) @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision. +# From configure.in Revision: 86731 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.67 for python 3.2. # @@ -9241,7 +9241,7 @@ # checks for library functions for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \ - gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ + gai_strerror getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ initgroups kill killpg lchmod lchown lstat mbrtowc mkfifo mknod mktime \ mremap nice pathconf pause plock poll pthread_init \ Index: configure.in =================================================================== --- configure.in (revision 87178) +++ configure.in (working copy) @@ -2526,7 +2526,7 @@ # checks for library functions AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \ - gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ + gai_strerror getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ initgroups kill killpg lchmod lchown lstat mbrtowc mkfifo mknod mktime \ mremap nice pathconf pause plock poll pthread_init \ Index: Misc/NEWS =================================================================== --- Misc/NEWS (revision 87178) +++ Misc/NEWS (working copy) @@ -11,6 +11,8 @@ Library ------- +* Issue #9344: Add posix.getgrouplist function. + * Issue #10107: Warn about unsaved files in IDLE on OSX. Index: Misc/ACKS =================================================================== --- Misc/ACKS (revision 87178) +++ Misc/ACKS (working copy) @@ -474,6 +474,7 @@ Ivan Krstić Andrew Kuchling Vladimir Kushnir +Ross Lagerwall Cameron Laird Jean-Baptiste "Jiba" Lamy Torsten Landschoff Index: Lib/test/test_posix.py =================================================================== --- Lib/test/test_posix.py (revision 87178) +++ Lib/test/test_posix.py (working copy) @@ -373,6 +373,18 @@ os.chdir(curdir) support.rmtree(base_path) + if hasattr(posix, 'getgrouplist'): + def test_getgrouplist(self): + with os.popen('id -G') as idg: + groups = idg.read().strip() + + if not groups: + raise unittest.SkipTest("need working 'id -G'") + + self.assertEqual( + set([int(x) for x in groups.split()]), + set(posix.getgrouplist(pwd.getpwuid(os.getuid())[0], pwd.getpwuid(os.getuid())[3]))) + def test_getgroups(self): with os.popen('id -G') as idg: groups = idg.read().strip() Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 87178) +++ Modules/posixmodule.c (working copy) @@ -1181,7 +1181,7 @@ HANDLE hFile; BY_HANDLE_FILE_INFORMATION info; ULONG reparse_tag = 0; - wchar_t *target_path; + wchar_t *target_path; const wchar_t *dot; if (depth > SYMLOOP_MAX) { @@ -4230,7 +4230,69 @@ return PyLong_FromPid(getpid()); } +#ifdef HAVE_GETGROUPLIST +PyDoc_STRVAR(posix_getgrouplist__doc__, +"getgrouplist(user, group) -> list of groups to which a user belongs\n\n\ +Returns a list of groups to which a user belongs.\n\n\ + user: username to lookup\n\ + group: base group id of the user"); + +static PyObject * +posix_getgrouplist(PyObject *self, PyObject *args) +{ +#ifdef NGROUPS_MAX +#define MAX_GROUPS NGROUPS_MAX +#else + /* defined to be 16 on Solaris7, so this should be a small number */ +#define MAX_GROUPS 64 +#endif + + const char *user; + int i, ngroups; + PyObject *list; +#ifdef __APPLE__ + int *groups, basegid; +#else + gid_t *groups, basegid; +#endif + ngroups = MAX_GROUPS; + + if (!PyArg_ParseTuple(args, "si", &user, &basegid)) + return NULL; + +#ifdef __APPLE__ + groups = PyMem_Malloc(ngroups * sizeof (int)); +#else + groups = PyMem_Malloc(ngroups * sizeof (gid_t)); +#endif + if (groups == NULL) + return PyErr_NoMemory(); + + if (getgrouplist(user, basegid, groups, &ngroups) == -1) { + PyMem_Del(groups); + return posix_error(); + } + + list = PyList_New(ngroups); + + for (i = 0; i < ngroups; i++) { + PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]); + if (o == NULL) { + Py_DECREF(list); + PyMem_Del(groups); + return NULL; + } + PyList_SET_ITEM(list, i, o); + } + + PyMem_Del(groups); + + return list; +} + +#endif + #ifdef HAVE_GETGROUPS PyDoc_STRVAR(posix_getgroups__doc__, "getgroups() -> list of group IDs\n\n\ @@ -7852,6 +7914,9 @@ {"getgid", posix_getgid, METH_NOARGS, posix_getgid__doc__}, #endif /* HAVE_GETGID */ #ifdef HAVE_GETGROUPS + {"getgrouplist", posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__}, +#endif +#ifdef HAVE_GETGROUPS {"getgroups", posix_getgroups, METH_NOARGS, posix_getgroups__doc__}, #endif {"getpid", posix_getpid, METH_NOARGS, posix_getpid__doc__}, Index: pyconfig.h.in =================================================================== --- pyconfig.h.in (revision 87178) +++ pyconfig.h.in (working copy) @@ -278,6 +278,9 @@ /* Define this if you have flockfile(), getc_unlocked(), and funlockfile() */ #undef HAVE_GETC_UNLOCKED +/* Define to 1 if you have the `getgrouplist' function. */ +#undef HAVE_GETGROUPLIST + /* Define to 1 if you have the `getgroups' function. */ #undef HAVE_GETGROUPS