Index: configure.in =================================================================== --- configure.in (revision 76162) +++ configure.in (working copy) @@ -2546,13 +2546,15 @@ AC_CHECK_FUNCS(alarm setitimer getitimer bind_textdomain_codeset chown \ clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \ gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ - getpriority getpwent getspnam getspent getsid getwd \ + getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ kill killpg lchmod lchown lstat mkfifo mknod mktime \ mremap nice pathconf pause plock poll pthread_init \ putenv readlink realpath \ select sem_open sem_timedwait sem_getvalue sem_unlink setegid seteuid \ setgid \ setlocale setregid setreuid setsid setpgid setpgrp setuid setvbuf snprintf \ + setlocale setregid setreuid setresuid setresgid \ + setsid setpgid setpgrp setuid setvbuf snprintf \ sigaction siginterrupt sigrelse strftime \ sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ truncate uname unsetenv utimes waitpid wait3 wait4 wcscoll _getpty) Index: Lib/test/test_posix.py =================================================================== --- Lib/test/test_posix.py (revision 76162) +++ Lib/test/test_posix.py (working copy) @@ -41,6 +41,48 @@ posix_func() self.assertRaises(TypeError, posix_func, 1) + if hasattr(posix, 'getresuid'): + def test_getresuid(self): + user_ids = posix.getresuid() + self.assertEqual(len(user_ids), 3) + for val in user_ids: + self.assertGreaterEqual(val, 0) + + if hasattr(posix, 'getresgid'): + def test_getresgid(self): + group_ids = posix.getresgid() + self.assertEqual(len(group_ids), 3) + for val in group_ids: + self.assertGreaterEqual(val, 0) + + if hasattr(posix, 'setresuid'): + def test_setresuid(self): + current_user_ids = posix.getresuid() + self.assertIsNone(posix.setresuid(*current_user_ids)) + # -1 means don't change that value. + self.assertIsNone(posix.setresuid(-1, -1, -1)) + + def test_setresuid_exception(self): + # Don't do this test if someone is silly enough to run us as root. + current_user_ids = posix.getresuid() + if 0 not in current_user_ids: + new_user_ids = (current_user_ids[0]+1, -1, -1) + self.assertRaises(OSError, posix.setresuid, *new_user_ids) + + if hasattr(posix, 'setresgid'): + def test_setresgid(self): + current_group_ids = posix.getresgid() + self.assertIsNone(posix.setresgid(*current_group_ids)) + # -1 means don't change that value. + self.assertIsNone(posix.setresgid(-1, -1, -1)) + + def test_setresgid_exception(self): + # Don't do this test if someone is silly enough to run us as root. + current_group_ids = posix.getresgid() + if 0 not in current_group_ids: + new_group_ids = (current_group_ids[0]+1, -1, -1) + self.assertRaises(OSError, posix.setresgid, *new_group_ids) + def test_statvfs(self): if hasattr(posix, 'statvfs'): self.assertTrue(posix.statvfs(os.curdir)) Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 76162) +++ Modules/posixmodule.c (working copy) @@ -8386,6 +8386,82 @@ } #endif +#ifdef HAVE_SETRESUID +PyDoc_STRVAR(posix_setresuid__doc__, +"setresuid(ruid, euid, suid)\n\n\ +Set the current process's real, effective, and saved user ids."); + +static PyObject* +posix_setresuid (PyObject *self, PyObject *args) +{ + /* We assume uid_t is no larger than a long. */ + long ruid, euid, suid; + if (!PyArg_ParseTuple(args, "lll", &ruid, &euid, &suid)) + return NULL; + if (setresuid(ruid, euid, suid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + +#ifdef HAVE_SETRESGID +PyDoc_STRVAR(posix_setresgid__doc__, +"setresgid(rgid, egid, sgid)\n\n\ +Set the current process's real, effective, and saved group ids."); + +static PyObject* +posix_setresgid (PyObject *self, PyObject *args) +{ + /* We assume uid_t is no larger than a long. */ + long rgid, egid, sgid; + if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid)) + return NULL; + if (setresgid(rgid, egid, sgid) < 0) + return posix_error(); + Py_RETURN_NONE; +} +#endif + +#ifdef HAVE_GETRESUID +PyDoc_STRVAR(posix_getresuid__doc__, +"getresuid() -> (ruid, euid, sgid)\n\n\ +Get tuple of the current process's real, effective, and saved user ids."); + +static PyObject* +posix_getresuid (PyObject *self, PyObject *noargs) +{ + uid_t ruid, euid, suid; + long l_ruid, l_euid, l_suid; + if (getresuid(&ruid, &euid, &suid) < 0) + return posix_error(); + /* Force the values into long's as we don't know the size of uid_t. */ + l_ruid = ruid; + l_euid = euid; + l_suid = suid; + return Py_BuildValue("(lll)", l_ruid, l_euid, l_suid); +} +#endif + +#ifdef HAVE_GETRESGID +PyDoc_STRVAR(posix_getresgid__doc__, +"getresgid() -> (rgid, egid, sgid)\n\n\ +Get tuple of the current process's real, effective, and saved user ids."); + +static PyObject* +posix_getresgid (PyObject *self, PyObject *noargs) +{ + uid_t rgid, egid, sgid; + long l_rgid, l_egid, l_sgid; + if (getresgid(&rgid, &egid, &sgid) < 0) + return posix_error(); + /* Force the values into long's as we don't know the size of uid_t. */ + l_rgid = rgid; + l_egid = egid; + l_sgid = sgid; + return Py_BuildValue("(lll)", l_rgid, l_egid, l_sgid); +} +#endif + static PyMethodDef posix_methods[] = { {"access", posix_access, METH_VARARGS, posix_access__doc__}, #ifdef HAVE_TTYNAME @@ -8696,6 +8772,19 @@ #ifdef __VMS {"urandom", vms_urandom, METH_VARARGS, vms_urandom__doc__}, #endif +#ifdef HAVE_SETRESUID + {"setresuid", posix_setresuid, METH_VARARGS, posix_setresuid__doc__}, +#endif +#ifdef HAVE_SETRESGID + {"setresgid", posix_setresgid, METH_VARARGS, posix_setresgid__doc__}, +#endif +#ifdef HAVE_GETRESUID + {"getresuid", posix_getresuid, METH_NOARGS, posix_getresuid__doc__}, +#endif +#ifdef HAVE_GETRESGID + {"getresgid", posix_getresgid, METH_NOARGS, posix_getresgid__doc__}, +#endif + {NULL, NULL} /* Sentinel */ }; Index: pyconfig.h.in =================================================================== --- pyconfig.h.in (revision 76162) +++ pyconfig.h.in (working copy) @@ -316,6 +316,12 @@ /* Define to 1 if you have the `getpwent' function. */ #undef HAVE_GETPWENT +/* Define to 1 if you have the `getresgid' function. */ +#undef HAVE_GETRESGID + +/* Define to 1 if you have the `getresuid' function. */ +#undef HAVE_GETRESUID + /* Define to 1 if you have the `getsid' function. */ #undef HAVE_GETSID @@ -580,6 +586,12 @@ /* Define to 1 if you have the `setregid' function. */ #undef HAVE_SETREGID +/* Define to 1 if you have the `setresgid' function. */ +#undef HAVE_SETRESGID + +/* Define to 1 if you have the `setresuid' function. */ +#undef HAVE_SETRESUID + /* Define to 1 if you have the `setreuid' function. */ #undef HAVE_SETREUID