Skip to content

Commit ddc3219

Browse files
committed
Soumendra Ganguly: add os.login_tty() for *nix.
Signed-off-by: Soumendra Ganguly <[email protected]>
1 parent 67b769f commit ddc3219

File tree

5 files changed

+241
-14
lines changed

5 files changed

+241
-14
lines changed

Doc/library/os.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,17 @@ as internal buffering of data.
990990
.. versionadded:: 3.3
991991

992992

993+
.. function:: login_tty(fd)
994+
995+
Prepare the tty of which fd is a file descriptor for a new login session.
996+
Make the calling process a session leader; make the tty the controlling tty,
997+
the stdin, the stdout, and the stderr of the calling process; close fd.
998+
999+
.. availability:: Unix.
1000+
1001+
.. versionadded:: 3.10
1002+
1003+
9931004
.. function:: lseek(fd, pos, how)
9941005

9951006
Set the current position of file descriptor *fd* to position *pos*, modified
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Soumendra Ganguly: New function os.login_tty() for Unix.

Modules/clinic/posixmodule.c.h

Lines changed: 40 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/posixmodule.c

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7118,22 +7118,21 @@ os_sched_getaffinity_impl(PyObject *module, pid_t pid)
71187118
# define DEV_PTY_FILE "/dev/ptmx"
71197119
#endif
71207120

7121-
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
7122-
#ifdef HAVE_PTY_H
7121+
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
7122+
#if defined(HAVE_PTY_H)
71237123
#include <pty.h>
7124-
#else
7125-
#ifdef HAVE_LIBUTIL_H
7124+
#if defined(HAVE_UTMP_H)
7125+
#include <utmp.h>
7126+
#endif /* HAVE_UTMP_H */
7127+
#elif defined(HAVE_LIBUTIL_H)
71267128
#include <libutil.h>
7127-
#else
7128-
#ifdef HAVE_UTIL_H
7129+
#elif defined(HAVE_UTIL_H)
71297130
#include <util.h>
7130-
#endif /* HAVE_UTIL_H */
7131-
#endif /* HAVE_LIBUTIL_H */
71327131
#endif /* HAVE_PTY_H */
71337132
#ifdef HAVE_STROPTS_H
71347133
#include <stropts.h>
71357134
#endif
7136-
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
7135+
#endif /* if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
71377136

71387137

71397138
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
@@ -7235,6 +7234,84 @@ os_openpty_impl(PyObject *module)
72357234
}
72367235
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
72377236

7237+
#if defined(HAVE_SETSID)
7238+
#if defined(TIOCSCTTY) || defined(HAVE_TTYNAME)
7239+
#define HAVE_FALLBACK_LOGIN_TTY 1
7240+
#endif /* defined(TIOCSCTTY) || defined(HAVE_TTYNAME) */
7241+
#endif /* HAVE_SETSID */
7242+
7243+
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
7244+
/*[clinic input]
7245+
os.login_tty
7246+
7247+
fd: fildes
7248+
/
7249+
7250+
Prepare the tty of which fd is a file descriptor for a new login session.
7251+
7252+
Make the calling process a session leader; make the tty the
7253+
controlling tty, the stdin, the stdout, and the stderr of the
7254+
calling process; close fd.
7255+
[clinic start generated code]*/
7256+
7257+
static PyObject *
7258+
os_login_tty_impl(PyObject *module, int fd)
7259+
/*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
7260+
{
7261+
#if defined(HAVE_LOGIN_TTY)
7262+
if (login_tty(fd) == -1) {
7263+
return posix_error();
7264+
}
7265+
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
7266+
/* Establish a new session. */
7267+
if (setsid() == -1) {
7268+
return posix_error();
7269+
}
7270+
7271+
/* The tty becomes the controlling terminal. */
7272+
#if defined(TIOCSCTTY)
7273+
if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
7274+
return posix_error();
7275+
}
7276+
#else /* defined(HAVE_TTYNAME) */
7277+
/* Fallback method (archaic); from Advanced Programming in the UNIX(R)
7278+
* Environment, Third edition, 2013, Section 9.6 - Controlling Terminal:
7279+
* "Systems derived from UNIX System V allocate the controlling
7280+
* terminal for a session when the session leader opens the first
7281+
* terminal device that is not already associated with a session, as
7282+
* long as the call to open does not specify the O_NOCTTY flag." */
7283+
char *tmppath = ttyname(fd);
7284+
if (tmppath == NULL) {
7285+
return posix_error();
7286+
}
7287+
7288+
#define CLOSE_IF_NOT_FD(otherfd) \
7289+
if (fd != otherfd) { \
7290+
close(otherfd); \
7291+
} \
7292+
7293+
CLOSE_IF_NOT_FD(0);
7294+
CLOSE_IF_NOT_FD(1);
7295+
CLOSE_IF_NOT_FD(2);
7296+
7297+
int tmpfd = open(tmppath, O_RDWR);
7298+
if (tmpfd == -1) {
7299+
return posix_error();
7300+
}
7301+
close(tmpfd);
7302+
#endif /* defined(TIOCSCTTY) */
7303+
7304+
/* The tty becomes stdin/stdout/stderr */
7305+
if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
7306+
return posix_error();
7307+
}
7308+
if (fd > 2) {
7309+
close(fd);
7310+
}
7311+
#endif /* defined(HAVE_LOGIN_TTY) */
7312+
Py_RETURN_NONE;
7313+
}
7314+
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
72387315

72397316
#ifdef HAVE_FORKPTY
72407317
/*[clinic input]
@@ -7271,8 +7348,9 @@ os_forkpty_impl(PyObject *module)
72717348
/* parent: release the import lock. */
72727349
PyOS_AfterFork_Parent();
72737350
}
7274-
if (pid == -1)
7351+
if (pid == -1) {
72757352
return posix_error();
7353+
}
72767354
return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
72777355
}
72787356
#endif /* HAVE_FORKPTY */
@@ -7613,7 +7691,7 @@ os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
76137691
const char *username = PyBytes_AS_STRING(oname);
76147692

76157693
if (initgroups(username, gid) == -1)
7616-
return PyErr_SetFromErrno(PyExc_OSError);
7694+
return posix_error();
76177695

76187696
Py_RETURN_NONE;
76197697
}
@@ -14652,6 +14730,7 @@ static PyMethodDef posix_methods[] = {
1465214730
OS_SCHED_GETAFFINITY_METHODDEF
1465314731
OS_OPENPTY_METHODDEF
1465414732
OS_FORKPTY_METHODDEF
14733+
OS_LOGIN_TTY_METHODDEF
1465514734
OS_GETEGID_METHODDEF
1465614735
OS_GETEUID_METHODDEF
1465714736
OS_GETGID_METHODDEF

configure

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8041,7 +8041,7 @@ sys/audioio.h sys/xattr.h sys/bsdtty.h sys/event.h sys/file.h sys/ioctl.h \
80418041
sys/kern_control.h sys/loadavg.h sys/lock.h sys/mkdev.h sys/modem.h \
80428042
sys/param.h sys/random.h sys/select.h sys/sendfile.h sys/socket.h sys/statvfs.h \
80438043
sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
8044-
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
8044+
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h utmp.h \
80458045
libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
80468046
linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
80478047
sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h \
@@ -12735,7 +12735,7 @@ $as_echo "no" >&6; }
1273512735
fi
1273612736
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
1273712737

12738-
# check for openpty and forkpty
12738+
# check for openpty, login_tty, and forkpty
1273912739

1274012740
for ac_func in openpty
1274112741
do :
@@ -12831,6 +12831,103 @@ fi
1283112831
fi
1283212832

1283312833

12834+
fi
12835+
done
12836+
12837+
for ac_func in login_tty
12838+
do :
12839+
ac_fn_c_check_func "$LINENO" "login_tty" "ac_cv_func_login_tty"
12840+
if test "x$ac_cv_func_login_tty" = xyes; then :
12841+
cat >>confdefs.h <<_ACEOF
12842+
#define HAVE_LOGIN_TTY 1
12843+
_ACEOF
12844+
12845+
else
12846+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for login_tty in -lutil" >&5
12847+
$as_echo_n "checking for login_tty in -lutil... " >&6; }
12848+
if ${ac_cv_lib_util_login_tty+:} false; then :
12849+
$as_echo_n "(cached) " >&6
12850+
else
12851+
ac_check_lib_save_LIBS=$LIBS
12852+
LIBS="-lutil $LIBS"
12853+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
12854+
/* end confdefs.h. */
12855+
12856+
/* Override any GCC internal prototype to avoid an error.
12857+
Use char because int might match the return type of a GCC
12858+
builtin and then its argument prototype would still apply. */
12859+
#ifdef __cplusplus
12860+
extern "C"
12861+
#endif
12862+
char login_tty ();
12863+
int
12864+
main ()
12865+
{
12866+
return login_tty ();
12867+
;
12868+
return 0;
12869+
}
12870+
_ACEOF
12871+
if ac_fn_c_try_link "$LINENO"; then :
12872+
ac_cv_lib_util_login_tty=yes
12873+
else
12874+
ac_cv_lib_util_login_tty=no
12875+
fi
12876+
rm -f core conftest.err conftest.$ac_objext \
12877+
conftest$ac_exeext conftest.$ac_ext
12878+
LIBS=$ac_check_lib_save_LIBS
12879+
fi
12880+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_util_login_tty" >&5
12881+
$as_echo "$ac_cv_lib_util_login_tty" >&6; }
12882+
if test "x$ac_cv_lib_util_login_tty" = xyes; then :
12883+
$as_echo "#define HAVE_LOGIN_TTY 1" >>confdefs.h
12884+
LIBS="$LIBS -lutil"
12885+
else
12886+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for login_tty in -lbsd" >&5
12887+
$as_echo_n "checking for login_tty in -lbsd... " >&6; }
12888+
if ${ac_cv_lib_bsd_login_tty+:} false; then :
12889+
$as_echo_n "(cached) " >&6
12890+
else
12891+
ac_check_lib_save_LIBS=$LIBS
12892+
LIBS="-lbsd $LIBS"
12893+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
12894+
/* end confdefs.h. */
12895+
12896+
/* Override any GCC internal prototype to avoid an error.
12897+
Use char because int might match the return type of a GCC
12898+
builtin and then its argument prototype would still apply. */
12899+
#ifdef __cplusplus
12900+
extern "C"
12901+
#endif
12902+
char login_tty ();
12903+
int
12904+
main ()
12905+
{
12906+
return login_tty ();
12907+
;
12908+
return 0;
12909+
}
12910+
_ACEOF
12911+
if ac_fn_c_try_link "$LINENO"; then :
12912+
ac_cv_lib_bsd_login_tty=yes
12913+
else
12914+
ac_cv_lib_bsd_login_tty=no
12915+
fi
12916+
rm -f core conftest.err conftest.$ac_objext \
12917+
conftest$ac_exeext conftest.$ac_ext
12918+
LIBS=$ac_check_lib_save_LIBS
12919+
fi
12920+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_login_tty" >&5
12921+
$as_echo "$ac_cv_lib_bsd_login_tty" >&6; }
12922+
if test "x$ac_cv_lib_bsd_login_tty" = xyes; then :
12923+
$as_echo "#define HAVE_LOGIN_TTY 1" >>confdefs.h
12924+
LIBS="$LIBS -lbsd"
12925+
fi
12926+
12927+
12928+
fi
12929+
12930+
1283412931
fi
1283512932
done
1283612933

0 commit comments

Comments
 (0)