bpo-41818: Add os.login_tty() for *nix. (#29658)

* Add `os.login_tty(fd)` for Unix.

Reviewed-by: Christian Heimes <christian@python.org>
Signed-off-by: Gregory P. Smith [Google LLC] <greg@krypto.org>
This commit is contained in:
Soumendra Ganguly 2022-05-05 11:04:44 -05:00 committed by GitHub
parent 42fee931d0
commit ae553b3561
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 184 additions and 14 deletions

View file

@ -3106,6 +3106,41 @@ os_openpty(PyObject *module, PyObject *Py_UNUSED(ignored))
#endif /* (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)) */
#if (defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY))
PyDoc_STRVAR(os_login_tty__doc__,
"login_tty($module, fd, /)\n"
"--\n"
"\n"
"Prepare the tty of which fd is a file descriptor for a new login session.\n"
"\n"
"Make the calling process a session leader; make the tty the\n"
"controlling tty, the stdin, the stdout, and the stderr of the\n"
"calling process; close fd.");
#define OS_LOGIN_TTY_METHODDEF \
{"login_tty", (PyCFunction)os_login_tty, METH_O, os_login_tty__doc__},
static PyObject *
os_login_tty_impl(PyObject *module, int fd);
static PyObject *
os_login_tty(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
int fd;
if (!_PyLong_FileDescriptor_Converter(arg, &fd)) {
goto exit;
}
return_value = os_login_tty_impl(module, fd);
exit:
return return_value;
}
#endif /* (defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)) */
#if defined(HAVE_FORKPTY)
PyDoc_STRVAR(os_forkpty__doc__,
@ -8932,6 +8967,10 @@ exit:
#define OS_OPENPTY_METHODDEF
#endif /* !defined(OS_OPENPTY_METHODDEF) */
#ifndef OS_LOGIN_TTY_METHODDEF
#define OS_LOGIN_TTY_METHODDEF
#endif /* !defined(OS_LOGIN_TTY_METHODDEF) */
#ifndef OS_FORKPTY_METHODDEF
#define OS_FORKPTY_METHODDEF
#endif /* !defined(OS_FORKPTY_METHODDEF) */
@ -9331,4 +9370,4 @@ exit:
#ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF
#define OS_WAITSTATUS_TO_EXITCODE_METHODDEF
#endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */
/*[clinic end generated code: output=3b5a56add047ee1d input=a9049054013a1b77]*/
/*[clinic end generated code: output=6150bcc25f5e4bc7 input=a9049054013a1b77]*/

View file

@ -7274,22 +7274,21 @@ error:
# define DEV_PTY_FILE "/dev/ptmx"
#endif
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
#ifdef HAVE_PTY_H
#include <pty.h>
#else
#ifdef HAVE_LIBUTIL_H
#ifdef HAVE_UTMP_H
#include <utmp.h>
#endif /* HAVE_UTMP_H */
#elif defined(HAVE_LIBUTIL_H)
#include <libutil.h>
#else
#ifdef HAVE_UTIL_H
#elif defined(HAVE_UTIL_H)
#include <util.h>
#endif /* HAVE_UTIL_H */
#endif /* HAVE_LIBUTIL_H */
#endif /* HAVE_PTY_H */
#ifdef HAVE_STROPTS_H
#include <stropts.h>
#endif
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
@ -7392,6 +7391,56 @@ error:
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
#define HAVE_FALLBACK_LOGIN_TTY 1
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
/*[clinic input]
os.login_tty
fd: fildes
/
Prepare the tty of which fd is a file descriptor for a new login session.
Make the calling process a session leader; make the tty the
controlling tty, the stdin, the stdout, and the stderr of the
calling process; close fd.
[clinic start generated code]*/
static PyObject *
os_login_tty_impl(PyObject *module, int fd)
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
{
#ifdef HAVE_LOGIN_TTY
if (login_tty(fd) == -1) {
return posix_error();
}
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
/* Establish a new session. */
if (setsid() == -1) {
return posix_error();
}
/* The tty becomes the controlling terminal. */
if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
return posix_error();
}
/* The tty becomes stdin/stdout/stderr */
if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
return posix_error();
}
if (fd > 2) {
close(fd);
}
#endif /* HAVE_LOGIN_TTY */
Py_RETURN_NONE;
}
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
#ifdef HAVE_FORKPTY
/*[clinic input]
os.forkpty
@ -7427,8 +7476,9 @@ os_forkpty_impl(PyObject *module)
/* parent: release the import lock. */
PyOS_AfterFork_Parent();
}
if (pid == -1)
if (pid == -1) {
return posix_error();
}
return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
}
#endif /* HAVE_FORKPTY */
@ -14797,6 +14847,7 @@ static PyMethodDef posix_methods[] = {
OS_SCHED_SETAFFINITY_METHODDEF
OS_SCHED_GETAFFINITY_METHODDEF
OS_OPENPTY_METHODDEF
OS_LOGIN_TTY_METHODDEF
OS_FORKPTY_METHODDEF
OS_GETEGID_METHODDEF
OS_GETEUID_METHODDEF