gh-85283: Build termios extension with the limited C API (#116928)

This commit is contained in:
Victor Stinner 2024-03-17 16:12:29 +01:00 committed by GitHub
parent 8e3c953b3a
commit 1cf0301086
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 42 additions and 32 deletions

View File

@ -1479,7 +1479,8 @@ Build Changes
* Building CPython now requires a compiler with support for the C11 atomic
library, GCC built-in atomic functions, or MSVC interlocked intrinsics.
* The ``errno``, ``fcntl``, ``grp``, ``md5``, ``pwd``, ``resource``, ``winsound``,
* The ``errno``, ``fcntl``, ``grp``, ``md5``, ``pwd``, ``resource``,
``termios``, ``winsound``,
``_ctypes_test``, ``_multiprocessing.posixshmem``, ``_scproxy``, ``_stat``,
``_testimportmultiple`` and ``_uuid`` C extensions are now built with the
:ref:`limited C API <limited-c-api>`.

View File

@ -1,2 +1,2 @@
The ``fcntl``, ``grp`` and ``pwd`` C extensions are now built with the :ref:`limited
C API <limited-c-api>`. (Contributed by Victor Stinner in :gh:`85283`.)
The ``fcntl``, ``grp``, ``pwd`` and ``termios`` C extensions are now
built with the :ref:`limited C API <limited-c-api>`. Patch by Victor Stinner.

View File

@ -2,8 +2,6 @@
preserve
[clinic start generated code]*/
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
PyDoc_STRVAR(termios_tcgetattr__doc__,
"tcgetattr($module, fd, /)\n"
"--\n"
@ -53,7 +51,7 @@ PyDoc_STRVAR(termios_tcsetattr__doc__,
"queued output and discarding all queued input.");
#define TERMIOS_TCSETATTR_METHODDEF \
{"tcsetattr", _PyCFunction_CAST(termios_tcsetattr), METH_FASTCALL, termios_tcsetattr__doc__},
{"tcsetattr", (PyCFunction)(void(*)(void))termios_tcsetattr, METH_FASTCALL, termios_tcsetattr__doc__},
static PyObject *
termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term);
@ -66,7 +64,8 @@ termios_tcsetattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
int when;
PyObject *term;
if (!_PyArg_CheckPositional("tcsetattr", nargs, 3, 3)) {
if (nargs != 3) {
PyErr_Format(PyExc_TypeError, "tcsetattr expected 3 arguments, got %zd", nargs);
goto exit;
}
fd = PyObject_AsFileDescriptor(args[0]);
@ -94,7 +93,7 @@ PyDoc_STRVAR(termios_tcsendbreak__doc__,
"has a system dependent meaning.");
#define TERMIOS_TCSENDBREAK_METHODDEF \
{"tcsendbreak", _PyCFunction_CAST(termios_tcsendbreak), METH_FASTCALL, termios_tcsendbreak__doc__},
{"tcsendbreak", (PyCFunction)(void(*)(void))termios_tcsendbreak, METH_FASTCALL, termios_tcsendbreak__doc__},
static PyObject *
termios_tcsendbreak_impl(PyObject *module, int fd, int duration);
@ -106,7 +105,8 @@ termios_tcsendbreak(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
int fd;
int duration;
if (!_PyArg_CheckPositional("tcsendbreak", nargs, 2, 2)) {
if (nargs != 2) {
PyErr_Format(PyExc_TypeError, "tcsendbreak expected 2 arguments, got %zd", nargs);
goto exit;
}
fd = PyObject_AsFileDescriptor(args[0]);
@ -162,7 +162,7 @@ PyDoc_STRVAR(termios_tcflush__doc__,
"both queues.");
#define TERMIOS_TCFLUSH_METHODDEF \
{"tcflush", _PyCFunction_CAST(termios_tcflush), METH_FASTCALL, termios_tcflush__doc__},
{"tcflush", (PyCFunction)(void(*)(void))termios_tcflush, METH_FASTCALL, termios_tcflush__doc__},
static PyObject *
termios_tcflush_impl(PyObject *module, int fd, int queue);
@ -174,7 +174,8 @@ termios_tcflush(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
int fd;
int queue;
if (!_PyArg_CheckPositional("tcflush", nargs, 2, 2)) {
if (nargs != 2) {
PyErr_Format(PyExc_TypeError, "tcflush expected 2 arguments, got %zd", nargs);
goto exit;
}
fd = PyObject_AsFileDescriptor(args[0]);
@ -202,7 +203,7 @@ PyDoc_STRVAR(termios_tcflow__doc__,
"or termios.TCION to restart input.");
#define TERMIOS_TCFLOW_METHODDEF \
{"tcflow", _PyCFunction_CAST(termios_tcflow), METH_FASTCALL, termios_tcflow__doc__},
{"tcflow", (PyCFunction)(void(*)(void))termios_tcflow, METH_FASTCALL, termios_tcflow__doc__},
static PyObject *
termios_tcflow_impl(PyObject *module, int fd, int action);
@ -214,7 +215,8 @@ termios_tcflow(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
int fd;
int action;
if (!_PyArg_CheckPositional("tcflow", nargs, 2, 2)) {
if (nargs != 2) {
PyErr_Format(PyExc_TypeError, "tcflow expected 2 arguments, got %zd", nargs);
goto exit;
}
fd = PyObject_AsFileDescriptor(args[0]);
@ -271,7 +273,7 @@ PyDoc_STRVAR(termios_tcsetwinsize__doc__,
"is a two-item tuple (ws_row, ws_col) like the one returned by tcgetwinsize().");
#define TERMIOS_TCSETWINSIZE_METHODDEF \
{"tcsetwinsize", _PyCFunction_CAST(termios_tcsetwinsize), METH_FASTCALL, termios_tcsetwinsize__doc__},
{"tcsetwinsize", (PyCFunction)(void(*)(void))termios_tcsetwinsize, METH_FASTCALL, termios_tcsetwinsize__doc__},
static PyObject *
termios_tcsetwinsize_impl(PyObject *module, int fd, PyObject *winsz);
@ -283,7 +285,8 @@ termios_tcsetwinsize(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
int fd;
PyObject *winsz;
if (!_PyArg_CheckPositional("tcsetwinsize", nargs, 2, 2)) {
if (nargs != 2) {
PyErr_Format(PyExc_TypeError, "tcsetwinsize expected 2 arguments, got %zd", nargs);
goto exit;
}
fd = PyObject_AsFileDescriptor(args[0]);
@ -296,4 +299,4 @@ termios_tcsetwinsize(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
exit:
return return_value;
}
/*[clinic end generated code: output=7327a2085972bf59 input=a9049054013a1b77]*/
/*[clinic end generated code: output=c6c6192583b0da36 input=a9049054013a1b77]*/

View File

@ -1,11 +1,19 @@
/* termios.c -- POSIX terminal I/O module implementation. */
#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
// Need limited C API version 3.13 for PyLong_AsInt()
// in code generated by Argument Clinic.
#include "pyconfig.h" // Py_GIL_DISABLED
#ifndef Py_GIL_DISABLED
# define Py_LIMITED_API 0x030d0000
#endif
#include "Python.h"
#include <string.h> // memset()
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h> // _POSIX_VDISABLE
// On QNX 6, struct termio must be declared by including sys/termio.h
// if TCGETA, TCSETA, TCSETAW, or TCSETAF are used. sys/termio.h must
// be included before termios.h or it will generate an error.
@ -19,28 +27,26 @@
# define CTRL(c) ((c)&037)
#endif
// We could do better. Check bpo-32660
#if defined(__sun)
/* We could do better. Check issue-32660 */
#include <sys/filio.h>
#include <sys/sockio.h>
# include <sys/filio.h>
# include <sys/sockio.h>
#endif
#include <termios.h>
#include <sys/ioctl.h>
#include <unistd.h> // _POSIX_VDISABLE
/* HP-UX requires that this be included to pick up MDCD, MCTS, MDSR,
* MDTR, MRI, and MRTS (apparently used internally by some things
* defined as macros; these are not used here directly).
*/
#ifdef HAVE_SYS_MODEM_H
#include <sys/modem.h>
# include <sys/modem.h>
#endif
/* HP-UX requires that this be included to pick up TIOCGPGRP and friends */
#ifdef HAVE_SYS_BSDTTY_H
#include <sys/bsdtty.h>
# include <sys/bsdtty.h>
#endif
/*[clinic input]
module termios
[clinic start generated code]*/
@ -120,7 +126,7 @@ termios_tcgetattr_impl(PyObject *module, int fd)
v = PyBytes_FromStringAndSize(&ch, 1);
if (v == NULL)
goto err;
PyList_SET_ITEM(cc, i, v);
PyList_SetItem(cc, i, v);
}
/* Convert the MIN and TIME slots to integer. On some systems, the
@ -154,7 +160,7 @@ termios_tcgetattr_impl(PyObject *module, int fd)
Py_DECREF(v); \
goto err; \
} \
PyList_SET_ITEM(v, index, l); \
PyList_SetItem(v, index, l); \
} while (0)
ADD_LONG_ITEM(0, mode.c_iflag);
@ -165,7 +171,7 @@ termios_tcgetattr_impl(PyObject *module, int fd)
ADD_LONG_ITEM(5, ospeed);
#undef ADD_LONG_ITEM
PyList_SET_ITEM(v, 6, cc);
PyList_SetItem(v, 6, cc);
return v;
err:
Py_DECREF(cc);
@ -214,7 +220,7 @@ termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term)
speed_t ispeed, ospeed;
#define SET_FROM_LIST(TYPE, VAR, LIST, N) do { \
PyObject *item = PyList_GET_ITEM(LIST, N); \
PyObject *item = PyList_GetItem(LIST, N); \
long num = PyLong_AsLong(item); \
if (num == -1 && PyErr_Occurred()) { \
return NULL; \
@ -230,7 +236,7 @@ termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term)
SET_FROM_LIST(speed_t, ospeed, term, 5);
#undef SET_FROM_LIST
PyObject *cc = PyList_GET_ITEM(term, 6);
PyObject *cc = PyList_GetItem(term, 6);
if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
PyErr_Format(PyExc_TypeError,
"tcsetattr: attributes[6] must be %d element list",