summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorSoumendra Ganguly <67527439+8vasu@users.noreply.github.com>2024-01-29 16:10:28 (GMT)
committerGitHub <noreply@github.com>2024-01-29 16:10:28 (GMT)
commite351ca3c205860e94cad5da25c74bd76933f5f11 (patch)
tree81531a49ba50989ad202ce1afe73b8ef3cb01da7 /Modules
parent0f54ee4c6cdba74492183eb2dd142393c7dba403 (diff)
downloadcpython-e351ca3c205860e94cad5da25c74bd76933f5f11.zip
cpython-e351ca3c205860e94cad5da25c74bd76933f5f11.tar.gz
cpython-e351ca3c205860e94cad5da25c74bd76933f5f11.tar.bz2
gh-85984: Add POSIX pseudo-terminal functions. (GH-102413)
Signed-off-by: Soumendra Ganguly <soumendraganguly@gmail.com> Co-authored-by: Gregory P. Smith <greg@krypto.org> Co-authored-by: Petr Viktorin <encukou@gmail.com>
Diffstat (limited to 'Modules')
-rw-r--r--Modules/clinic/posixmodule.c.h168
-rw-r--r--Modules/posixmodule.c147
2 files changed, 314 insertions, 1 deletions
diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h
index ba3e1cf..1373bde 100644
--- a/Modules/clinic/posixmodule.c.h
+++ b/Modules/clinic/posixmodule.c.h
@@ -4465,6 +4465,156 @@ exit:
#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) */
+#if defined(HAVE_POSIX_OPENPT)
+
+PyDoc_STRVAR(os_posix_openpt__doc__,
+"posix_openpt($module, oflag, /)\n"
+"--\n"
+"\n"
+"Open and return a file descriptor for a master pseudo-terminal device.\n"
+"\n"
+"Performs a posix_openpt() C function call. The oflag argument is used to\n"
+"set file status flags and file access modes as specified in the manual page\n"
+"of posix_openpt() of your system.");
+
+#define OS_POSIX_OPENPT_METHODDEF \
+ {"posix_openpt", (PyCFunction)os_posix_openpt, METH_O, os_posix_openpt__doc__},
+
+static int
+os_posix_openpt_impl(PyObject *module, int oflag);
+
+static PyObject *
+os_posix_openpt(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ int oflag;
+ int _return_value;
+
+ oflag = PyLong_AsInt(arg);
+ if (oflag == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ _return_value = os_posix_openpt_impl(module, oflag);
+ if ((_return_value == -1) && PyErr_Occurred()) {
+ goto exit;
+ }
+ return_value = PyLong_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+#endif /* defined(HAVE_POSIX_OPENPT) */
+
+#if defined(HAVE_GRANTPT)
+
+PyDoc_STRVAR(os_grantpt__doc__,
+"grantpt($module, fd, /)\n"
+"--\n"
+"\n"
+"Grant access to the slave pseudo-terminal device.\n"
+"\n"
+" fd\n"
+" File descriptor of a master pseudo-terminal device.\n"
+"\n"
+"Performs a grantpt() C function call.");
+
+#define OS_GRANTPT_METHODDEF \
+ {"grantpt", (PyCFunction)os_grantpt, METH_O, os_grantpt__doc__},
+
+static PyObject *
+os_grantpt_impl(PyObject *module, int fd);
+
+static PyObject *
+os_grantpt(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ int fd;
+
+ if (!_PyLong_FileDescriptor_Converter(arg, &fd)) {
+ goto exit;
+ }
+ return_value = os_grantpt_impl(module, fd);
+
+exit:
+ return return_value;
+}
+
+#endif /* defined(HAVE_GRANTPT) */
+
+#if defined(HAVE_UNLOCKPT)
+
+PyDoc_STRVAR(os_unlockpt__doc__,
+"unlockpt($module, fd, /)\n"
+"--\n"
+"\n"
+"Unlock a pseudo-terminal master/slave pair.\n"
+"\n"
+" fd\n"
+" File descriptor of a master pseudo-terminal device.\n"
+"\n"
+"Performs an unlockpt() C function call.");
+
+#define OS_UNLOCKPT_METHODDEF \
+ {"unlockpt", (PyCFunction)os_unlockpt, METH_O, os_unlockpt__doc__},
+
+static PyObject *
+os_unlockpt_impl(PyObject *module, int fd);
+
+static PyObject *
+os_unlockpt(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ int fd;
+
+ if (!_PyLong_FileDescriptor_Converter(arg, &fd)) {
+ goto exit;
+ }
+ return_value = os_unlockpt_impl(module, fd);
+
+exit:
+ return return_value;
+}
+
+#endif /* defined(HAVE_UNLOCKPT) */
+
+#if (defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R))
+
+PyDoc_STRVAR(os_ptsname__doc__,
+"ptsname($module, fd, /)\n"
+"--\n"
+"\n"
+"Return the name of the slave pseudo-terminal device.\n"
+"\n"
+" fd\n"
+" File descriptor of a master pseudo-terminal device.\n"
+"\n"
+"If the ptsname_r() C function is available, it is called;\n"
+"otherwise, performs a ptsname() C function call.");
+
+#define OS_PTSNAME_METHODDEF \
+ {"ptsname", (PyCFunction)os_ptsname, METH_O, os_ptsname__doc__},
+
+static PyObject *
+os_ptsname_impl(PyObject *module, int fd);
+
+static PyObject *
+os_ptsname(PyObject *module, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ int fd;
+
+ if (!_PyLong_FileDescriptor_Converter(arg, &fd)) {
+ goto exit;
+ }
+ return_value = os_ptsname_impl(module, fd);
+
+exit:
+ return return_value;
+}
+
+#endif /* (defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)) */
+
#if (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX))
PyDoc_STRVAR(os_openpty__doc__,
@@ -11991,6 +12141,22 @@ os__supports_virtual_terminal(PyObject *module, PyObject *Py_UNUSED(ignored))
#define OS_SCHED_GETAFFINITY_METHODDEF
#endif /* !defined(OS_SCHED_GETAFFINITY_METHODDEF) */
+#ifndef OS_POSIX_OPENPT_METHODDEF
+ #define OS_POSIX_OPENPT_METHODDEF
+#endif /* !defined(OS_POSIX_OPENPT_METHODDEF) */
+
+#ifndef OS_GRANTPT_METHODDEF
+ #define OS_GRANTPT_METHODDEF
+#endif /* !defined(OS_GRANTPT_METHODDEF) */
+
+#ifndef OS_UNLOCKPT_METHODDEF
+ #define OS_UNLOCKPT_METHODDEF
+#endif /* !defined(OS_UNLOCKPT_METHODDEF) */
+
+#ifndef OS_PTSNAME_METHODDEF
+ #define OS_PTSNAME_METHODDEF
+#endif /* !defined(OS_PTSNAME_METHODDEF) */
+
#ifndef OS_OPENPTY_METHODDEF
#define OS_OPENPTY_METHODDEF
#endif /* !defined(OS_OPENPTY_METHODDEF) */
@@ -12422,4 +12588,4 @@ os__supports_virtual_terminal(PyObject *module, PyObject *Py_UNUSED(ignored))
#ifndef OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
#define OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
#endif /* !defined(OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF) */
-/*[clinic end generated code: output=18c128534c355d84 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=43e4e557c771358a input=a9049054013a1b77]*/
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 007fc1c..40ff131 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -8358,6 +8358,149 @@ error:
#endif /* HAVE_SCHED_H */
+#ifdef HAVE_POSIX_OPENPT
+/*[clinic input]
+os.posix_openpt -> int
+
+ oflag: int
+ /
+
+Open and return a file descriptor for a master pseudo-terminal device.
+
+Performs a posix_openpt() C function call. The oflag argument is used to
+set file status flags and file access modes as specified in the manual page
+of posix_openpt() of your system.
+[clinic start generated code]*/
+
+static int
+os_posix_openpt_impl(PyObject *module, int oflag)
+/*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
+{
+ int fd;
+
+#if defined(O_CLOEXEC)
+ oflag |= O_CLOEXEC;
+#endif
+
+ fd = posix_openpt(oflag);
+ if (fd == -1) {
+ posix_error();
+ return -1;
+ }
+
+ // Just in case, likely a no-op given O_CLOEXEC above.
+ if (_Py_set_inheritable(fd, 0, NULL) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+#endif /* HAVE_POSIX_OPENPT */
+
+#ifdef HAVE_GRANTPT
+/*[clinic input]
+os.grantpt
+
+ fd: fildes
+ File descriptor of a master pseudo-terminal device.
+ /
+
+Grant access to the slave pseudo-terminal device.
+
+Performs a grantpt() C function call.
+[clinic start generated code]*/
+
+static PyObject *
+os_grantpt_impl(PyObject *module, int fd)
+/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
+{
+ int ret;
+ int saved_errno;
+ PyOS_sighandler_t sig_saved;
+
+ sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
+
+ ret = grantpt(fd);
+ if (ret == -1)
+ saved_errno = errno;
+
+ PyOS_setsig(SIGCHLD, sig_saved);
+
+ if (ret == -1) {
+ errno = saved_errno;
+ return posix_error();
+ }
+
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_GRANTPT */
+
+#ifdef HAVE_UNLOCKPT
+/*[clinic input]
+os.unlockpt
+
+ fd: fildes
+ File descriptor of a master pseudo-terminal device.
+ /
+
+Unlock a pseudo-terminal master/slave pair.
+
+Performs an unlockpt() C function call.
+[clinic start generated code]*/
+
+static PyObject *
+os_unlockpt_impl(PyObject *module, int fd)
+/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
+{
+ if (unlockpt(fd) == -1)
+ return posix_error();
+
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_UNLOCKPT */
+
+#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
+/*[clinic input]
+os.ptsname
+
+ fd: fildes
+ File descriptor of a master pseudo-terminal device.
+ /
+
+Return the name of the slave pseudo-terminal device.
+
+If the ptsname_r() C function is available, it is called;
+otherwise, performs a ptsname() C function call.
+[clinic start generated code]*/
+
+static PyObject *
+os_ptsname_impl(PyObject *module, int fd)
+/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
+{
+#ifdef HAVE_PTSNAME_R
+ int ret;
+ char name[MAXPATHLEN+1];
+
+ ret = ptsname_r(fd, name, sizeof(name));
+ if (ret != 0) {
+ errno = ret;
+ return posix_error();
+ }
+#else
+ char *name;
+
+ name = ptsname(fd);
+ /* POSIX manpage: Upon failure, ptsname() shall return a null pointer and may set errno.
+ *MAY* set errno? Hmm... */
+ if (name == NULL)
+ return posix_error();
+#endif /* HAVE_PTSNAME_R */
+
+ return PyUnicode_DecodeFSDefault(name);
+}
+#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
+
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
# define DEV_PTY_FILE "/dev/ptc"
@@ -16275,6 +16418,10 @@ static PyMethodDef posix_methods[] = {
OS_SCHED_YIELD_METHODDEF
OS_SCHED_SETAFFINITY_METHODDEF
OS_SCHED_GETAFFINITY_METHODDEF
+ OS_POSIX_OPENPT_METHODDEF
+ OS_GRANTPT_METHODDEF
+ OS_UNLOCKPT_METHODDEF
+ OS_PTSNAME_METHODDEF
OS_OPENPTY_METHODDEF
OS_LOGIN_TTY_METHODDEF
OS_FORKPTY_METHODDEF