]> granicus.if.org Git - python/commitdiff
Issue #23446: Use PyMem_New instead of PyMem_Malloc to avoid possible integer
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 16 Feb 2015 11:33:32 +0000 (13:33 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Mon, 16 Feb 2015 11:33:32 +0000 (13:33 +0200)
overflows.  Added few missed PyErr_NoMemory().

1  2 
Modules/_ssl.c
Modules/_testbuffer.c
Modules/_testcapimodule.c
Modules/getpath.c
Modules/posixmodule.c
Modules/pyexpat.c
Modules/socketmodule.c
Objects/unicodeobject.c

diff --cc Modules/_ssl.c
Simple merge
Simple merge
Simple merge
Simple merge
index 118a380e715152abd185f75f4534b020081a6736,d45f59e5f1b6763eb71d14df31b5c488ca61a119..c019b1609b182a08bda64d976a79145dcc08dc7e
@@@ -4414,133 -4310,101 +4414,133 @@@ os_link_impl(PyModuleDef *module, path_
  
  #ifdef MS_WINDOWS
      Py_BEGIN_ALLOW_THREADS
 -    if (src.wide)
 -        result = MoveFileExW(src.wide, dst.wide, flags);
 +    if (src->wide)
 +        result = CreateHardLinkW(dst->wide, src->wide, NULL);
      else
 -        result = MoveFileExA(src.narrow, dst.narrow, flags);
 +        result = CreateHardLinkA(dst->narrow, src->narrow, NULL);
      Py_END_ALLOW_THREADS
  
 -    if (!result) {
 -        return_value = path_error2(&src, &dst);
 -        goto exit;
 -    }
 -
 +    if (!result)
 +        return path_error2(src, dst);
  #else
      Py_BEGIN_ALLOW_THREADS
 -#ifdef HAVE_RENAMEAT
 -    if (dir_fd_specified)
 -        result = renameat(src_dir_fd, src.narrow, dst_dir_fd, dst.narrow);
 +#ifdef HAVE_LINKAT
 +    if ((src_dir_fd != DEFAULT_DIR_FD) ||
 +        (dst_dir_fd != DEFAULT_DIR_FD) ||
 +        (!follow_symlinks))
 +        result = linkat(src_dir_fd, src->narrow,
 +            dst_dir_fd, dst->narrow,
 +            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
      else
  #endif
 -        result = rename(src.narrow, dst.narrow);
 +        result = link(src->narrow, dst->narrow);
      Py_END_ALLOW_THREADS
  
 -    if (result) {
 -        return_value = path_error2(&src, &dst);
 -        goto exit;
 -    }
 +    if (result)
 +        return path_error2(src, dst);
  #endif
  
 -    Py_INCREF(Py_None);
 -    return_value = Py_None;
 -exit:
 -    path_cleanup(&src);
 -    path_cleanup(&dst);
 -    return return_value;
 +    Py_RETURN_NONE;
  }
 +#endif
  
 -PyDoc_STRVAR(posix_rename__doc__,
 -"rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\
 -Rename a file or directory.\n\
 -\n\
 -If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
 -  descriptor open to a directory, and the respective path string (src or dst)\n\
 -  should be relative; the path will then be relative to that directory.\n\
 -src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\
 -  If they are unavailable, using them will raise a NotImplementedError.");
  
 +#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
  static PyObject *
 -posix_rename(PyObject *self, PyObject *args, PyObject *kwargs)
 +_listdir_windows_no_opendir(path_t *path, PyObject *list)
  {
 -    return internal_rename(args, kwargs, 0);
 -}
 -
 -PyDoc_STRVAR(posix_replace__doc__,
 -"replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\
 -Rename a file or directory, overwriting the destination.\n\
 -\n\
 -If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
 -  descriptor open to a directory, and the respective path string (src or dst)\n\
 -  should be relative; the path will then be relative to that directory.\n\
 -src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\
 -  If they are unavailable, using them will raise a NotImplementedError.");
 +    PyObject *v;
 +    HANDLE hFindFile = INVALID_HANDLE_VALUE;
 +    BOOL result;
 +    WIN32_FIND_DATA FileData;
 +    char namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
 +    char *bufptr = namebuf;
 +    /* only claim to have space for MAX_PATH */
 +    Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
 +    PyObject *po = NULL;
 +    wchar_t *wnamebuf = NULL;
  
 -static PyObject *
 -posix_replace(PyObject *self, PyObject *args, PyObject *kwargs)
 -{
 -    return internal_rename(args, kwargs, 1);
 -}
 +    if (!path->narrow) {
 +        WIN32_FIND_DATAW wFileData;
 +        wchar_t *po_wchars;
  
 -PyDoc_STRVAR(posix_rmdir__doc__,
 -"rmdir(path, *, dir_fd=None)\n\n\
 -Remove a directory.\n\
 -\n\
 -If dir_fd is not None, it should be a file descriptor open to a directory,\n\
 -  and path should be relative; path will then be relative to that directory.\n\
 -dir_fd may not be implemented on your platform.\n\
 -  If it is unavailable, using it will raise a NotImplementedError.");
 +        if (!path->wide) { /* Default arg: "." */
 +            po_wchars = L".";
 +            len = 1;
 +        } else {
 +            po_wchars = path->wide;
 +            len = wcslen(path->wide);
 +        }
 +        /* The +5 is so we can append "\\*.*\0" */
-         wnamebuf = PyMem_Malloc((len + 5) * sizeof(wchar_t));
++        wnamebuf = PyMem_New(wchar_t, len + 5);
 +        if (!wnamebuf) {
 +            PyErr_NoMemory();
 +            goto exit;
 +        }
 +        wcscpy(wnamebuf, po_wchars);
 +        if (len > 0) {
 +            wchar_t wch = wnamebuf[len-1];
 +            if (wch != SEP && wch != ALTSEP && wch != L':')
 +                wnamebuf[len++] = SEP;
 +            wcscpy(wnamebuf + len, L"*.*");
 +        }
 +        if ((list = PyList_New(0)) == NULL) {
 +            goto exit;
 +        }
 +        Py_BEGIN_ALLOW_THREADS
 +        hFindFile = FindFirstFileW(wnamebuf, &wFileData);
 +        Py_END_ALLOW_THREADS
 +        if (hFindFile == INVALID_HANDLE_VALUE) {
 +            int error = GetLastError();
 +            if (error == ERROR_FILE_NOT_FOUND)
 +                goto exit;
 +            Py_DECREF(list);
 +            list = path_error(path);
 +            goto exit;
 +        }
 +        do {
 +            /* Skip over . and .. */
 +            if (wcscmp(wFileData.cFileName, L".") != 0 &&
 +                wcscmp(wFileData.cFileName, L"..") != 0) {
 +                v = PyUnicode_FromWideChar(wFileData.cFileName,
 +                                           wcslen(wFileData.cFileName));
 +                if (v == NULL) {
 +                    Py_DECREF(list);
 +                    list = NULL;
 +                    break;
 +                }
 +                if (PyList_Append(list, v) != 0) {
 +                    Py_DECREF(v);
 +                    Py_DECREF(list);
 +                    list = NULL;
 +                    break;
 +                }
 +                Py_DECREF(v);
 +            }
 +            Py_BEGIN_ALLOW_THREADS
 +            result = FindNextFileW(hFindFile, &wFileData);
 +            Py_END_ALLOW_THREADS
 +            /* FindNextFile sets error to ERROR_NO_MORE_FILES if
 +               it got to the end of the directory. */
 +            if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
 +                Py_DECREF(list);
 +                list = path_error(path);
 +                goto exit;
 +            }
 +        } while (result == TRUE);
  
 -static PyObject *
 -posix_rmdir(PyObject *self, PyObject *args, PyObject *kwargs)
 -{
 -    path_t path;
 -    int dir_fd = DEFAULT_DIR_FD;
 -    static char *keywords[] = {"path", "dir_fd", NULL};
 -    int result;
 -    PyObject *return_value = NULL;
 +        goto exit;
 +    }
 +    strcpy(namebuf, path->narrow);
 +    len = path->length;
 +    if (len > 0) {
 +        char ch = namebuf[len-1];
 +        if (ch != '\\' && ch != '/' && ch != ':')
 +            namebuf[len++] = '\\';
 +        strcpy(namebuf + len, "*.*");
 +    }
  
 -    memset(&path, 0, sizeof(path));
 -    path.function_name = "rmdir";
 -    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:rmdir", keywords,
 -            path_converter, &path,
 -#ifdef HAVE_UNLINKAT
 -            dir_fd_converter, &dir_fd
 -#else
 -            dir_fd_unavailable, &dir_fd
 -#endif
 -            ))
 +    if ((list = PyList_New(0)) == NULL)
          return NULL;
  
      Py_BEGIN_ALLOW_THREADS
      return return_value;
  }
  
 +static PyObject *
 +os_listdir_impl(PyModuleDef *module, path_t *path)
 +/*[clinic end generated code: output=e159bd9be6909018 input=09e300416e3cd729]*/
 +{
 +#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
 +    return _listdir_windows_no_opendir(path, NULL);
 +#else
 +    return _posix_listdir(path, NULL);
 +#endif
 +}
  
 -PyDoc_STRVAR(posix_uname__doc__,
 -"uname() -> uname_result\n\n\
 -Return an object identifying the current operating system.\n\
 -The object behaves like a named tuple with the following fields:\n\
 -  (sysname, nodename, release, version, machine)");
 -
 -static PyStructSequence_Field uname_result_fields[] = {
 -    {"sysname",    "operating system name"},
 -    {"nodename",   "name of machine on network (implementation-defined)"},
 -    {"release",    "operating system release"},
 -    {"version",    "operating system version"},
 -    {"machine",    "hardware identifier"},
 -    {NULL}
 -};
 -
 -PyDoc_STRVAR(uname_result__doc__,
 -"uname_result: Result from os.uname().\n\n\
 -This object may be accessed either as a tuple of\n\
 -  (sysname, nodename, release, version, machine),\n\
 -or via the attributes sysname, nodename, release, version, and machine.\n\
 -\n\
 -See os.uname for more information.");
 -
 -static PyStructSequence_Desc uname_result_desc = {
 -    "uname_result", /* name */
 -    uname_result__doc__, /* doc */
 -    uname_result_fields,
 -    5
 -};
 -
 -static PyTypeObject UnameResultType;
 -
 -
 -#ifdef HAVE_UNAME
 +#ifdef MS_WINDOWS
 +/* A helper function for abspath on win32 */
 +/* AC 3.5: probably just convert to using path converter */
  static PyObject *
 -posix_uname(PyObject *self, PyObject *noargs)
 +posix__getfullpathname(PyObject *self, PyObject *args)
  {
 -    struct utsname u;
 -    int res;
 -    PyObject *value;
 +    const char *path;
 +    char outbuf[MAX_PATH];
 +    char *temp;
 +    PyObject *po;
  
 -    Py_BEGIN_ALLOW_THREADS
 -    res = uname(&u);
 -    Py_END_ALLOW_THREADS
 -    if (res < 0)
 -        return posix_error();
 +    if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po))
 +    {
 +        wchar_t *wpath;
 +        wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
 +        wchar_t *wtemp;
 +        DWORD result;
 +        PyObject *v;
  
 -    value = PyStructSequence_New(&UnameResultType);
 -    if (value == NULL)
 +        wpath = PyUnicode_AsUnicode(po);
 +        if (wpath == NULL)
 +            return NULL;
 +        result = GetFullPathNameW(wpath,
 +                                  Py_ARRAY_LENGTH(woutbuf),
 +                                  woutbuf, &wtemp);
 +        if (result > Py_ARRAY_LENGTH(woutbuf)) {
-             woutbufp = PyMem_Malloc(result * sizeof(wchar_t));
++            woutbufp = PyMem_New(wchar_t, result);
 +            if (!woutbufp)
 +                return PyErr_NoMemory();
 +            result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
 +        }
 +        if (result)
 +            v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
 +        else
 +            v = win32_error_object("GetFullPathNameW", po);
 +        if (woutbufp != woutbuf)
 +            PyMem_Free(woutbufp);
 +        return v;
 +    }
 +    /* Drop the argument parsing error as narrow strings
 +       are also valid. */
 +    PyErr_Clear();
 +
 +    if (!PyArg_ParseTuple (args, "y:_getfullpathname",
 +                           &path))
 +        return NULL;
 +    if (win32_warn_bytes_api())
 +        return NULL;
 +    if (!GetFullPathName(path, Py_ARRAY_LENGTH(outbuf),
 +                         outbuf, &temp)) {
 +        win32_error("GetFullPathName", path);
          return NULL;
 +    }
 +    if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
 +        return PyUnicode_Decode(outbuf, strlen(outbuf),
 +                                Py_FileSystemDefaultEncoding, NULL);
 +    }
 +    return PyBytes_FromString(outbuf);
 +}
  
 -#define SET(i, field) \
 -    { \
 -    PyObject *o = PyUnicode_DecodeFSDefault(field); \
 -    if (!o) { \
 -        Py_DECREF(value); \
 -        return NULL; \
 -    } \
 -    PyStructSequence_SET_ITEM(value, i, o); \
 -    } \
  
 -    SET(0, u.sysname);
 -    SET(1, u.nodename);
 -    SET(2, u.release);
 -    SET(3, u.version);
 -    SET(4, u.machine);
 +/*[clinic input]
 +os._getfinalpathname
  
 -#undef SET
 +    path: unicode
 +    /
  
 -    return value;
 -}
 -#endif /* HAVE_UNAME */
 +A helper function for samepath on windows.
 +[clinic start generated code]*/
  
 +PyDoc_STRVAR(os__getfinalpathname__doc__,
 +"_getfinalpathname($module, path, /)\n"
 +"--\n"
 +"\n"
 +"A helper function for samepath on windows.");
  
 -PyDoc_STRVAR(posix_utime__doc__,
 -"utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True)\n\
 -Set the access and modified time of path.\n\
 -\n\
 -path may always be specified as a string.\n\
 -On some platforms, path may also be specified as an open file descriptor.\n\
 -  If this functionality is unavailable, using it raises an exception.\n\
 -\n\
 -If times is not None, it must be a tuple (atime, mtime);\n\
 -    atime and mtime should be expressed as float seconds since the epoch.\n\
 -If ns is not None, it must be a tuple (atime_ns, mtime_ns);\n\
 -    atime_ns and mtime_ns should be expressed as integer nanoseconds\n\
 -    since the epoch.\n\
 -If both times and ns are None, utime uses the current time.\n\
 -Specifying tuples for both times and ns is an error.\n\
 -\n\
 -If dir_fd is not None, it should be a file descriptor open to a directory,\n\
 -  and path should be relative; path will then be relative to that directory.\n\
 -If follow_symlinks is False, and the last element of the path is a symbolic\n\
 -  link, utime will modify the symbolic link itself instead of the file the\n\
 -  link points to.\n\
 -It is an error to use dir_fd or follow_symlinks when specifying path\n\
 -  as an open file descriptor.\n\
 -dir_fd and follow_symlinks may not be available on your platform.\n\
 -  If they are unavailable, using them will raise a NotImplementedError.");
 +#define OS__GETFINALPATHNAME_METHODDEF    \
 +    {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_VARARGS, os__getfinalpathname__doc__},
  
 -typedef struct {
 -    int    now;
 -    time_t atime_s;
 -    long   atime_ns;
 -    time_t mtime_s;
 -    long   mtime_ns;
 -} utime_t;
 +static PyObject *
 +os__getfinalpathname_impl(PyModuleDef *module, PyObject *path);
  
 -/*
 - * these macros assume that "ut" is a pointer to a utime_t
 - * they also intentionally leak the declaration of a pointer named "time"
 - */
 -#define UTIME_TO_TIMESPEC \
 -    struct timespec ts[2]; \
 -    struct timespec *time; \
 -    if (ut->now) \
 -        time = NULL; \
 -    else { \
 -        ts[0].tv_sec = ut->atime_s; \
 -        ts[0].tv_nsec = ut->atime_ns; \
 -        ts[1].tv_sec = ut->mtime_s; \
 -        ts[1].tv_nsec = ut->mtime_ns; \
 -        time = ts; \
 -    } \
 +static PyObject *
 +os__getfinalpathname(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    PyObject *path;
  
 -#define UTIME_TO_TIMEVAL \
 -    struct timeval tv[2]; \
 -    struct timeval *time; \
 -    if (ut->now) \
 -        time = NULL; \
 -    else { \
 -        tv[0].tv_sec = ut->atime_s; \
 -        tv[0].tv_usec = ut->atime_ns / 1000; \
 -        tv[1].tv_sec = ut->mtime_s; \
 -        tv[1].tv_usec = ut->mtime_ns / 1000; \
 -        time = tv; \
 -    } \
 +    if (!PyArg_ParseTuple(args,
 +        "U:_getfinalpathname",
 +        &path))
 +        goto exit;
 +    return_value = os__getfinalpathname_impl(module, path);
  
 -#define UTIME_TO_UTIMBUF \
 -    struct utimbuf u; \
 -    struct utimbuf *time; \
 -    if (ut->now) \
 -        time = NULL; \
 -    else { \
 -        u.actime = ut->atime_s; \
 -        u.modtime = ut->mtime_s; \
 -        time = &u; \
 -    }
 +exit:
 +    return return_value;
 +}
  
 -#define UTIME_TO_TIME_T \
 -    time_t timet[2]; \
 -    time_t *time; \
 -    if (ut->now) \
 -        time = NULL; \
 -    else { \
 -        timet[0] = ut->atime_s; \
 -        timet[1] = ut->mtime_s; \
 -        time = timet; \
 -    } \
 +static PyObject *
 +os__getfinalpathname_impl(PyModuleDef *module, PyObject *path)
 +/*[clinic end generated code: output=4563c6eacf1b0881 input=71d5e89334891bf4]*/
 +{
 +    HANDLE hFile;
 +    int buf_size;
 +    wchar_t *target_path;
 +    int result_length;
 +    PyObject *result;
 +    wchar_t *path_wchar;
  
 +    path_wchar = PyUnicode_AsUnicode(path);
 +    if (path_wchar == NULL)
 +        return NULL;
  
 -#define UTIME_HAVE_DIR_FD (defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT))
 +    if(!check_GetFinalPathNameByHandle()) {
 +        /* If the OS doesn't have GetFinalPathNameByHandle, return a
 +           NotImplementedError. */
 +        return PyErr_Format(PyExc_NotImplementedError,
 +            "GetFinalPathNameByHandle not available on this platform");
 +    }
  
 -#if UTIME_HAVE_DIR_FD
 +    hFile = CreateFileW(
 +        path_wchar,
 +        0, /* desired access */
 +        0, /* share mode */
 +        NULL, /* security attributes */
 +        OPEN_EXISTING,
 +        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
 +        FILE_FLAG_BACKUP_SEMANTICS,
 +        NULL);
  
 -static int
 -utime_dir_fd(utime_t *ut, int dir_fd, char *path, int follow_symlinks)
 -{
 -#ifdef HAVE_UTIMENSAT
 -    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
 -    UTIME_TO_TIMESPEC;
 -    return utimensat(dir_fd, path, time, flags);
 -#elif defined(HAVE_FUTIMESAT)
 -    UTIME_TO_TIMEVAL;
 -    /*
 -     * follow_symlinks will never be false here;
 -     * we only allow !follow_symlinks and dir_fd together
 -     * if we have utimensat()
 -     */
 -    assert(follow_symlinks);
 -    return futimesat(dir_fd, path, time);
 -#endif
 -}
 +    if(hFile == INVALID_HANDLE_VALUE)
 +        return win32_error_object("CreateFileW", path);
  
 -#endif
 +    /* We have a good handle to the target, use it to determine the
 +       target path name. */
 +    buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT);
  
 -#define UTIME_HAVE_FD (defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS))
 +    if(!buf_size)
 +        return win32_error_object("GetFinalPathNameByHandle", path);
  
-     target_path = (wchar_t *)PyMem_Malloc((buf_size+1)*sizeof(wchar_t));
 -#if UTIME_HAVE_FD
++    target_path = PyMem_New(wchar_t, buf_size+1);
 +    if(!target_path)
 +        return PyErr_NoMemory();
  
 -static int
 -utime_fd(utime_t *ut, int fd)
 -{
 -#ifdef HAVE_FUTIMENS
 -    UTIME_TO_TIMESPEC;
 -    return futimens(fd, time);
 -#else
 -    UTIME_TO_TIMEVAL;
 -    return futimes(fd, time);
 -#endif
 +    result_length = Py_GetFinalPathNameByHandleW(hFile, target_path,
 +                                                 buf_size, VOLUME_NAME_DOS);
 +    if(!result_length)
 +        return win32_error_object("GetFinalPathNamyByHandle", path);
 +
 +    if(!CloseHandle(hFile))
 +        return win32_error_object("CloseHandle", path);
 +
 +    target_path[result_length] = 0;
 +    result = PyUnicode_FromWideChar(target_path, result_length);
 +    PyMem_Free(target_path);
 +    return result;
  }
  
 -#endif
 +PyDoc_STRVAR(posix__isdir__doc__,
 +"Return true if the pathname refers to an existing directory.");
  
 +/* AC 3.5: convert using path converter */
 +static PyObject *
 +posix__isdir(PyObject *self, PyObject *args)
 +{
 +    const char *path;
 +    PyObject *po;
 +    DWORD attributes;
  
 -#define UTIME_HAVE_NOFOLLOW_SYMLINKS \
 -        (defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES))
 +    if (PyArg_ParseTuple(args, "U|:_isdir", &po)) {
 +        wchar_t *wpath = PyUnicode_AsUnicode(po);
 +        if (wpath == NULL)
 +            return NULL;
  
 -#if UTIME_HAVE_NOFOLLOW_SYMLINKS
 +        attributes = GetFileAttributesW(wpath);
 +        if (attributes == INVALID_FILE_ATTRIBUTES)
 +            Py_RETURN_FALSE;
 +        goto check;
 +    }
 +    /* Drop the argument parsing error as narrow strings
 +       are also valid. */
 +    PyErr_Clear();
  
 -static int
 -utime_nofollow_symlinks(utime_t *ut, char *path)
 -{
 -#ifdef HAVE_UTIMENSAT
 -    UTIME_TO_TIMESPEC;
 -    return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
 -#else
 -    UTIME_TO_TIMEVAL;
 -    return lutimes(path, time);
 -#endif
 +    if (!PyArg_ParseTuple(args, "y:_isdir", &path))
 +        return NULL;
 +    if (win32_warn_bytes_api())
 +        return NULL;
 +    attributes = GetFileAttributesA(path);
 +    if (attributes == INVALID_FILE_ATTRIBUTES)
 +        Py_RETURN_FALSE;
 +
 +check:
 +    if (attributes & FILE_ATTRIBUTE_DIRECTORY)
 +        Py_RETURN_TRUE;
 +    else
 +        Py_RETURN_FALSE;
  }
  
 -#endif
  
 -#ifndef MS_WINDOWS
 +/*[clinic input]
 +os._getvolumepathname
  
 -static int
 -utime_default(utime_t *ut, char *path)
 -{
 -#ifdef HAVE_UTIMENSAT
 -    UTIME_TO_TIMESPEC;
 -    return utimensat(DEFAULT_DIR_FD, path, time, 0);
 -#elif defined(HAVE_UTIMES)
 -    UTIME_TO_TIMEVAL;
 -    return utimes(path, time);
 -#elif defined(HAVE_UTIME_H)
 -    UTIME_TO_UTIMBUF;
 -    return utime(path, time);
 -#else
 -    UTIME_TO_TIME_T;
 -    return utime(path, time);
 -#endif
 -}
 +    path: unicode
  
 -#endif
 +A helper function for ismount on Win32.
 +[clinic start generated code]*/
  
 -static int
 -split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)
 +PyDoc_STRVAR(os__getvolumepathname__doc__,
 +"_getvolumepathname($module, /, path)\n"
 +"--\n"
 +"\n"
 +"A helper function for ismount on Win32.");
 +
 +#define OS__GETVOLUMEPATHNAME_METHODDEF    \
 +    {"_getvolumepathname", (PyCFunction)os__getvolumepathname, METH_VARARGS|METH_KEYWORDS, os__getvolumepathname__doc__},
 +
 +static PyObject *
 +os__getvolumepathname_impl(PyModuleDef *module, PyObject *path);
 +
 +static PyObject *
 +os__getvolumepathname(PyModuleDef *module, PyObject *args, PyObject *kwargs)
  {
 -    int result = 0;
 -    PyObject *divmod;
 -    divmod = PyNumber_Divmod(py_long, billion);
 -    if (!divmod)
 -        goto exit;
 -    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
 -    if ((*s == -1) && PyErr_Occurred())
 -        goto exit;
 -    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
 -    if ((*ns == -1) && PyErr_Occurred())
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"path", NULL};
 +    PyObject *path;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "U:_getvolumepathname", _keywords,
 +        &path))
          goto exit;
 +    return_value = os__getvolumepathname_impl(module, path);
  
 -    result = 1;
  exit:
 -    Py_XDECREF(divmod);
 -    return result;
 +    return return_value;
  }
  
  static PyObject *
 -posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
 +os__getvolumepathname_impl(PyModuleDef *module, PyObject *path)
 +/*[clinic end generated code: output=ac0833b6d6da7657 input=7eacadc40acbda6b]*/
  {
 -    path_t path;
 -    PyObject *times = NULL;
 -    PyObject *ns = NULL;
 -    int dir_fd = DEFAULT_DIR_FD;
 -    int follow_symlinks = 1;
 -    char *keywords[] = {"path", "times", "ns", "dir_fd",
 -                        "follow_symlinks", NULL};
 -
 -    utime_t utime;
 +    PyObject *result;
 +    wchar_t *path_wchar, *mountpath=NULL;
 +    size_t buflen;
 +    BOOL ret;
  
 -#ifdef MS_WINDOWS
 -    HANDLE hFile;
 -    FILETIME atime, mtime;
 -#else
 -    int result;
 -#endif
 +    path_wchar = PyUnicode_AsUnicodeAndSize(path, &buflen);
 +    if (path_wchar == NULL)
 +        return NULL;
 +    buflen += 1;
  
 -    PyObject *return_value = NULL;
 +    /* Volume path should be shorter than entire path */
 +    buflen = Py_MAX(buflen, MAX_PATH);
  
 -    memset(&path, 0, sizeof(path));
 -    path.function_name = "utime";
 -    memset(&utime, 0, sizeof(utime_t));
 -#if UTIME_HAVE_FD
 -    path.allow_fd = 1;
 -#endif
 -    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 -            "O&|O$OO&p:utime", keywords,
 -            path_converter, &path,
 -            &times, &ns,
 -#if UTIME_HAVE_DIR_FD
 -            dir_fd_converter, &dir_fd,
 -#else
 -            dir_fd_unavailable, &dir_fd,
 -#endif
 -            &follow_symlinks
 -            ))
 +    if (buflen > DWORD_MAX) {
 +        PyErr_SetString(PyExc_OverflowError, "path too long");
          return NULL;
 +    }
  
-     mountpath = (wchar_t *)PyMem_Malloc(buflen * sizeof(wchar_t));
 -    if (times && (times != Py_None) && ns) {
 -        PyErr_SetString(PyExc_ValueError,
 -                     "utime: you may specify either 'times'"
 -                     " or 'ns' but not both");
++    mountpath = PyMem_New(wchar_t, buflen);
 +    if (mountpath == NULL)
 +        return PyErr_NoMemory();
 +
 +    Py_BEGIN_ALLOW_THREADS
 +    ret = GetVolumePathNameW(path_wchar, mountpath,
 +                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
 +    Py_END_ALLOW_THREADS
 +
 +    if (!ret) {
 +        result = win32_error_object("_getvolumepathname", path);
          goto exit;
      }
 +    result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
  
 -    if (times && (times != Py_None)) {
 -        time_t a_sec, m_sec;
 -        long a_nsec, m_nsec;
 -        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
 -            PyErr_SetString(PyExc_TypeError,
 -                         "utime: 'times' must be either"
 -                         " a tuple of two ints or None");
 -            goto exit;
 -        }
 -        utime.now = 0;
 -        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
 -                                     &a_sec, &a_nsec, _PyTime_ROUND_DOWN) == -1 ||
 -            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
 -                                     &m_sec, &m_nsec, _PyTime_ROUND_DOWN) == -1) {
 -            goto exit;
 -        }
 -        utime.atime_s = a_sec;
 -        utime.atime_ns = a_nsec;
 -        utime.mtime_s = m_sec;
 -        utime.mtime_ns = m_nsec;
 -    }
 -    else if (ns) {
 -        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
 -            PyErr_SetString(PyExc_TypeError,
 -                         "utime: 'ns' must be a tuple of two ints");
 -            goto exit;
 -        }
 -        utime.now = 0;
 -        if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
 -                                      &utime.atime_s, &utime.atime_ns) ||
 -            !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
 -                                       &utime.mtime_s, &utime.mtime_ns)) {
 -            goto exit;
 -        }
 -    }
 -    else {
 -        /* times and ns are both None/unspecified. use "now". */
 -        utime.now = 1;
 -    }
 +exit:
 +    PyMem_Free(mountpath);
 +    return result;
 +}
  
 -#if !UTIME_HAVE_NOFOLLOW_SYMLINKS
 -    if (follow_symlinks_specified("utime", follow_symlinks))
 -        goto exit;
 -#endif
 +#endif /* MS_WINDOWS */
  
 -    if (path_and_dir_fd_invalid("utime", &path, dir_fd) ||
 -        dir_fd_and_fd_invalid("utime", dir_fd, path.fd) ||
 -        fd_and_follow_symlinks_invalid("utime", path.fd, follow_symlinks))
 -        goto exit;
  
 -#if !defined(HAVE_UTIMENSAT)
 -    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
 -        PyErr_SetString(PyExc_ValueError,
 -                     "utime: cannot use dir_fd and follow_symlinks "
 -                     "together on this platform");
 +/*[clinic input]
 +os.mkdir
 +
 +    path : path_t
 +
 +    mode: int = 0o777
 +
 +    *
 +
 +    dir_fd : dir_fd(requires='mkdirat') = None
 +
 +# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
 +
 +Create a directory.
 +
 +If dir_fd is not None, it should be a file descriptor open to a directory,
 +  and path should be relative; path will then be relative to that directory.
 +dir_fd may not be implemented on your platform.
 +  If it is unavailable, using it will raise a NotImplementedError.
 +
 +The mode argument is ignored on Windows.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_mkdir__doc__,
 +"mkdir($module, /, path, mode=511, *, dir_fd=None)\n"
 +"--\n"
 +"\n"
 +"Create a directory.\n"
 +"\n"
 +"If dir_fd is not None, it should be a file descriptor open to a directory,\n"
 +"  and path should be relative; path will then be relative to that directory.\n"
 +"dir_fd may not be implemented on your platform.\n"
 +"  If it is unavailable, using it will raise a NotImplementedError.\n"
 +"\n"
 +"The mode argument is ignored on Windows.");
 +
 +#define OS_MKDIR_METHODDEF    \
 +    {"mkdir", (PyCFunction)os_mkdir, METH_VARARGS|METH_KEYWORDS, os_mkdir__doc__},
 +
 +static PyObject *
 +os_mkdir_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd);
 +
 +static PyObject *
 +os_mkdir(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"path", "mode", "dir_fd", NULL};
 +    path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0);
 +    int mode = 511;
 +    int dir_fd = DEFAULT_DIR_FD;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "O&|i$O&:mkdir", _keywords,
 +        path_converter, &path, &mode, MKDIRAT_DIR_FD_CONVERTER, &dir_fd))
          goto exit;
 -    }
 -#endif
 +    return_value = os_mkdir_impl(module, &path, mode, dir_fd);
 +
 +exit:
 +    /* Cleanup for path */
 +    path_cleanup(&path);
 +
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_mkdir_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd)
 +/*[clinic end generated code: output=55c6ef2bc1b207e6 input=e965f68377e9b1ce]*/
 +{
 +    int result;
  
  #ifdef MS_WINDOWS
      Py_BEGIN_ALLOW_THREADS
@@@ -7617,7135 -7844,2152 +7617,7135 @@@ os_sched_getparam_impl(PyModuleDef *mod
  }
  
  
 -PyDoc_STRVAR(posix_dup2__doc__,
 -"dup2(old_fd, new_fd)\n\n\
 -Duplicate file descriptor.");
 +/*[clinic input]
 +os.sched_setparam
 +    pid: pid_t
 +    param: sched_param
 +    /
  
 -static PyObject *
 -posix_dup2(PyObject *self, PyObject *args, PyObject *kwargs)
 -{
 -    static char *keywords[] = {"fd", "fd2", "inheritable", NULL};
 -    int fd, fd2;
 -    int inheritable = 1;
 -    int res;
 -#if defined(HAVE_DUP3) && \
 -    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
 -    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
 -    int dup3_works = -1;
 -#endif
 -
 -    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i:dup2", keywords,
 -                                     &fd, &fd2, &inheritable))
 -        return NULL;
 -
 -    if (!_PyVerify_fd_dup2(fd, fd2))
 -        return posix_error();
 -
 -#ifdef MS_WINDOWS
 -    Py_BEGIN_ALLOW_THREADS
 -    res = dup2(fd, fd2);
 -    Py_END_ALLOW_THREADS
 -    if (res < 0)
 -        return posix_error();
 -
 -    /* Character files like console cannot be make non-inheritable */
 -    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
 -        close(fd2);
 -        return NULL;
 -    }
 +Set scheduling parameters for the process identified by pid.
  
 -#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
 -    Py_BEGIN_ALLOW_THREADS
 -    if (!inheritable)
 -        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
 -    else
 -        res = dup2(fd, fd2);
 -    Py_END_ALLOW_THREADS
 -    if (res < 0)
 -        return posix_error();
 +If pid is 0, sets parameters for the calling process.
 +param should be an instance of sched_param.
 +[clinic start generated code]*/
  
 -#else
 +PyDoc_STRVAR(os_sched_setparam__doc__,
 +"sched_setparam($module, pid, param, /)\n"
 +"--\n"
 +"\n"
 +"Set scheduling parameters for the process identified by pid.\n"
 +"\n"
 +"If pid is 0, sets parameters for the calling process.\n"
 +"param should be an instance of sched_param.");
  
 -#ifdef HAVE_DUP3
 -    if (!inheritable && dup3_works != 0) {
 -        Py_BEGIN_ALLOW_THREADS
 -        res = dup3(fd, fd2, O_CLOEXEC);
 -        Py_END_ALLOW_THREADS
 -        if (res < 0) {
 -            if (dup3_works == -1)
 -                dup3_works = (errno != ENOSYS);
 -            if (dup3_works)
 -                return posix_error();
 -        }
 -    }
 +#define OS_SCHED_SETPARAM_METHODDEF    \
 +    {"sched_setparam", (PyCFunction)os_sched_setparam, METH_VARARGS, os_sched_setparam__doc__},
  
 -    if (inheritable || dup3_works == 0)
 -    {
 -#endif
 -        Py_BEGIN_ALLOW_THREADS
 -        res = dup2(fd, fd2);
 -        Py_END_ALLOW_THREADS
 -        if (res < 0)
 -            return posix_error();
 +static PyObject *
 +os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param);
  
 -        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
 -            close(fd2);
 -            return NULL;
 -        }
 -#ifdef HAVE_DUP3
 -    }
 -#endif
 +static PyObject *
 +os_sched_setparam(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    pid_t pid;
 +    struct sched_param param;
  
 -#endif
 +    if (!PyArg_ParseTuple(args,
 +        "" _Py_PARSE_PID "O&:sched_setparam",
 +        &pid, convert_sched_param, &param))
 +        goto exit;
 +    return_value = os_sched_setparam_impl(module, pid, &param);
  
 -    Py_INCREF(Py_None);
 -    return Py_None;
 +exit:
 +    return return_value;
  }
  
 -#ifdef HAVE_LOCKF
 -PyDoc_STRVAR(posix_lockf__doc__,
 -"lockf(fd, cmd, len)\n\n\
 -Apply, test or remove a POSIX lock on an open file descriptor.\n\n\
 -fd is an open file descriptor.\n\
 -cmd specifies the command to use - one of F_LOCK, F_TLOCK, F_ULOCK or\n\
 -F_TEST.\n\
 -len specifies the section of the file to lock.");
 -
  static PyObject *
 -posix_lockf(PyObject *self, PyObject *args)
 +os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param)
 +/*[clinic end generated code: output=488bdf5bcbe0d4e8 input=6b8d6dfcecdc21bd]*/
  {
 -    int fd, cmd, res;
 -    off_t len;
 -    if (!PyArg_ParseTuple(args, "iiO&:lockf",
 -            &fd, &cmd, _parse_off_t, &len))
 -        return NULL;
 -
 -    Py_BEGIN_ALLOW_THREADS
 -    res = lockf(fd, cmd, len);
 -    Py_END_ALLOW_THREADS
 -
 -    if (res < 0)
 +    if (sched_setparam(pid, param))
          return posix_error();
 -
      Py_RETURN_NONE;
  }
 -#endif
 -
 +#endif /* HAVE_SCHED_SETPARAM */
  
 -PyDoc_STRVAR(posix_lseek__doc__,
 -"lseek(fd, pos, how) -> newpos\n\n\
 -Set the current position of a file descriptor.\n\
 -Return the new cursor position in bytes, starting from the beginning.");
  
 -static PyObject *
 -posix_lseek(PyObject *self, PyObject *args)
 -{
 -    int fd, how;
 -#ifdef MS_WINDOWS
 -    PY_LONG_LONG pos, res;
 -#else
 -    off_t pos, res;
 -#endif
 -    PyObject *posobj;
 -    if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
 -        return NULL;
 -#ifdef SEEK_SET
 -    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
 -    switch (how) {
 -    case 0: how = SEEK_SET; break;
 -    case 1: how = SEEK_CUR; break;
 -    case 2: how = SEEK_END; break;
 -    }
 -#endif /* SEEK_END */
 +#ifdef HAVE_SCHED_RR_GET_INTERVAL
 +/*[clinic input]
 +os.sched_rr_get_interval -> double
 +    pid: pid_t
 +    /
  
 -#if !defined(HAVE_LARGEFILE_SUPPORT)
 -    pos = PyLong_AsLong(posobj);
 -#else
 -    pos = PyLong_AsLongLong(posobj);
 -#endif
 -    if (PyErr_Occurred())
 -        return NULL;
 +Return the round-robin quantum for the process identified by pid, in seconds.
  
 -    if (!_PyVerify_fd(fd))
 -        return posix_error();
 -    Py_BEGIN_ALLOW_THREADS
 -#ifdef MS_WINDOWS
 -    res = _lseeki64(fd, pos, how);
 -#else
 -    res = lseek(fd, pos, how);
 -#endif
 -    Py_END_ALLOW_THREADS
 -    if (res < 0)
 -        return posix_error();
 +Value returned is a float.
 +[clinic start generated code]*/
  
 -#if !defined(HAVE_LARGEFILE_SUPPORT)
 -    return PyLong_FromLong(res);
 -#else
 -    return PyLong_FromLongLong(res);
 -#endif
 -}
 +PyDoc_STRVAR(os_sched_rr_get_interval__doc__,
 +"sched_rr_get_interval($module, pid, /)\n"
 +"--\n"
 +"\n"
 +"Return the round-robin quantum for the process identified by pid, in seconds.\n"
 +"\n"
 +"Value returned is a float.");
  
 +#define OS_SCHED_RR_GET_INTERVAL_METHODDEF    \
 +    {"sched_rr_get_interval", (PyCFunction)os_sched_rr_get_interval, METH_VARARGS, os_sched_rr_get_interval__doc__},
  
 -PyDoc_STRVAR(posix_read__doc__,
 -"read(fd, buffersize) -> bytes\n\n\
 -Read a file descriptor.");
 +static double
 +os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid);
  
  static PyObject *
 -posix_read(PyObject *self, PyObject *args)
 +os_sched_rr_get_interval(PyModuleDef *module, PyObject *args)
  {
 -    int fd, size;
 -    Py_ssize_t n;
 -    PyObject *buffer;
 -    if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
 -        return NULL;
 -    if (size < 0) {
 -        errno = EINVAL;
 -        return posix_error();
 -    }
 -    buffer = PyBytes_FromStringAndSize((char *)NULL, size);
 -    if (buffer == NULL)
 -        return NULL;
 -    if (!_PyVerify_fd(fd)) {
 -        Py_DECREF(buffer);
 -        return posix_error();
 -    }
 -    Py_BEGIN_ALLOW_THREADS
 -    n = read(fd, PyBytes_AS_STRING(buffer), size);
 -    Py_END_ALLOW_THREADS
 -    if (n < 0) {
 -        Py_DECREF(buffer);
 -        return posix_error();
 -    }
 -    if (n != size)
 -        _PyBytes_Resize(&buffer, n);
 -    return buffer;
 +    PyObject *return_value = NULL;
 +    pid_t pid;
 +    double _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "" _Py_PARSE_PID ":sched_rr_get_interval",
 +        &pid))
 +        goto exit;
 +    _return_value = os_sched_rr_get_interval_impl(module, pid);
 +    if ((_return_value == -1.0) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyFloat_FromDouble(_return_value);
 +
 +exit:
 +    return return_value;
  }
  
 -#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
 -    || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV)
 -static Py_ssize_t
 -iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
 +static double
 +os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid)
 +/*[clinic end generated code: output=5b3b8d1f27fb2c0a input=2a973da15cca6fae]*/
  {
 -    int i, j;
 -    Py_ssize_t blen, total = 0;
 -
 -    *iov = PyMem_New(struct iovec, cnt);
 -    if (*iov == NULL) {
 -        PyErr_NoMemory();
 -        return -1;
 +    struct timespec interval;
 +    if (sched_rr_get_interval(pid, &interval)) {
 +        posix_error();
 +        return -1.0;
      }
 +    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
 +}
 +#endif /* HAVE_SCHED_RR_GET_INTERVAL */
  
 -    *buf = PyMem_New(Py_buffer, cnt);
 -    if (*buf == NULL) {
 -        PyMem_Del(*iov);
 -        PyErr_NoMemory();
 -        return -1;
 -    }
  
 -    for (i = 0; i < cnt; i++) {
 -        PyObject *item = PySequence_GetItem(seq, i);
 -        if (item == NULL)
 -            goto fail;
 -        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
 -            Py_DECREF(item);
 -            goto fail;
 -        }
 -        Py_DECREF(item);
 -        (*iov)[i].iov_base = (*buf)[i].buf;
 -        blen = (*buf)[i].len;
 -        (*iov)[i].iov_len = blen;
 -        total += blen;
 -    }
 -    return total;
 +/*[clinic input]
 +os.sched_yield
  
 -fail:
 -    PyMem_Del(*iov);
 -    for (j = 0; j < i; j++) {
 -        PyBuffer_Release(&(*buf)[j]);
 -    }
 -    PyMem_Del(*buf);
 -    return -1;
 -}
 +Voluntarily relinquish the CPU.
 +[clinic start generated code]*/
  
 -static void
 -iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
 +PyDoc_STRVAR(os_sched_yield__doc__,
 +"sched_yield($module, /)\n"
 +"--\n"
 +"\n"
 +"Voluntarily relinquish the CPU.");
 +
 +#define OS_SCHED_YIELD_METHODDEF    \
 +    {"sched_yield", (PyCFunction)os_sched_yield, METH_NOARGS, os_sched_yield__doc__},
 +
 +static PyObject *
 +os_sched_yield_impl(PyModuleDef *module);
 +
 +static PyObject *
 +os_sched_yield(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
  {
 -    int i;
 -    PyMem_Del(iov);
 -    for (i = 0; i < cnt; i++) {
 -        PyBuffer_Release(&buf[i]);
 -    }
 -    PyMem_Del(buf);
 +    return os_sched_yield_impl(module);
  }
 -#endif
 -
 -#ifdef HAVE_READV
 -PyDoc_STRVAR(posix_readv__doc__,
 -"readv(fd, buffers) -> bytesread\n\n\
 -Read from a file descriptor fd into a number of mutable, bytes-like\n\
 -objects (\"buffers\").  readv will transfer data into each buffer\n\
 -until it is full and then move on to the next buffer in the sequence\n\
 -to hold the rest of the data.\n\n\
 -readv returns the total number of bytes read (which may be less than\n\
 -the total capacity of all the buffers.");
  
  static PyObject *
 -posix_readv(PyObject *self, PyObject *args)
 +os_sched_yield_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=9d2e5f29f1370324 input=e54d6f98189391d4]*/
  {
 -    int fd, cnt;
 -    Py_ssize_t n;
 -    PyObject *seq;
 -    struct iovec *iov;
 -    Py_buffer *buf;
 +    if (sched_yield())
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
  
 -    if (!PyArg_ParseTuple(args, "iO:readv", &fd, &seq))
 -        return NULL;
 -    if (!PySequence_Check(seq)) {
 -        PyErr_SetString(PyExc_TypeError,
 -            "readv() arg 2 must be a sequence");
 -        return NULL;
 -    }
 -    cnt = PySequence_Size(seq);
 +#ifdef HAVE_SCHED_SETAFFINITY
 +/* The minimum number of CPUs allocated in a cpu_set_t */
 +static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
  
 -    if (iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE) < 0)
 -        return NULL;
 +/*[clinic input]
 +os.sched_setaffinity
 +    pid: pid_t
 +    mask : object
 +    /
  
 -    Py_BEGIN_ALLOW_THREADS
 -    n = readv(fd, iov, cnt);
 -    Py_END_ALLOW_THREADS
 +Set the CPU affinity of the process identified by pid to mask.
  
 -    iov_cleanup(iov, buf, cnt);
 -    if (n < 0)
 -        return posix_error();
 +mask should be an iterable of integers identifying CPUs.
 +[clinic start generated code]*/
  
 -    return PyLong_FromSsize_t(n);
 -}
 -#endif
 +PyDoc_STRVAR(os_sched_setaffinity__doc__,
 +"sched_setaffinity($module, pid, mask, /)\n"
 +"--\n"
 +"\n"
 +"Set the CPU affinity of the process identified by pid to mask.\n"
 +"\n"
 +"mask should be an iterable of integers identifying CPUs.");
  
 -#ifdef HAVE_PREAD
 -PyDoc_STRVAR(posix_pread__doc__,
 -"pread(fd, buffersize, offset) -> string\n\n\
 -Read from a file descriptor, fd, at a position of offset. It will read up\n\
 -to buffersize number of bytes. The file offset remains unchanged.");
 +#define OS_SCHED_SETAFFINITY_METHODDEF    \
 +    {"sched_setaffinity", (PyCFunction)os_sched_setaffinity, METH_VARARGS, os_sched_setaffinity__doc__},
  
  static PyObject *
 -posix_pread(PyObject *self, PyObject *args)
 -{
 -    int fd, size;
 -    off_t offset;
 -    Py_ssize_t n;
 -    PyObject *buffer;
 -    if (!PyArg_ParseTuple(args, "iiO&:pread", &fd, &size, _parse_off_t, &offset))
 -        return NULL;
 -
 -    if (size < 0) {
 -        errno = EINVAL;
 -        return posix_error();
 -    }
 -    buffer = PyBytes_FromStringAndSize((char *)NULL, size);
 -    if (buffer == NULL)
 -        return NULL;
 -    if (!_PyVerify_fd(fd)) {
 -        Py_DECREF(buffer);
 -        return posix_error();
 -    }
 -    Py_BEGIN_ALLOW_THREADS
 -    n = pread(fd, PyBytes_AS_STRING(buffer), size, offset);
 -    Py_END_ALLOW_THREADS
 -    if (n < 0) {
 -        Py_DECREF(buffer);
 -        return posix_error();
 -    }
 -    if (n != size)
 -        _PyBytes_Resize(&buffer, n);
 -    return buffer;
 -}
 -#endif
 -
 -PyDoc_STRVAR(posix_write__doc__,
 -"write(fd, data) -> byteswritten\n\n\
 -Write bytes to a file descriptor.");
 +os_sched_setaffinity_impl(PyModuleDef *module, pid_t pid, PyObject *mask);
  
  static PyObject *
 -posix_write(PyObject *self, PyObject *args)
 +os_sched_setaffinity(PyModuleDef *module, PyObject *args)
  {
 -    Py_buffer pbuf;
 -    int fd;
 -    Py_ssize_t size, len;
 +    PyObject *return_value = NULL;
 +    pid_t pid;
 +    PyObject *mask;
  
 -    if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf))
 -        return NULL;
 -    if (!_PyVerify_fd(fd)) {
 -        PyBuffer_Release(&pbuf);
 -        return posix_error();
 -    }
 -    len = pbuf.len;
 -    Py_BEGIN_ALLOW_THREADS
 -#ifdef MS_WINDOWS
 -    if (len > INT_MAX)
 -        len = INT_MAX;
 -    size = write(fd, pbuf.buf, (int)len);
 -#else
 -    size = write(fd, pbuf.buf, len);
 -#endif
 -    Py_END_ALLOW_THREADS
 -    PyBuffer_Release(&pbuf);
 -    if (size < 0)
 -        return posix_error();
 -    return PyLong_FromSsize_t(size);
 -}
 +    if (!PyArg_ParseTuple(args,
 +        "" _Py_PARSE_PID "O:sched_setaffinity",
 +        &pid, &mask))
 +        goto exit;
 +    return_value = os_sched_setaffinity_impl(module, pid, mask);
  
 -#ifdef HAVE_SENDFILE
 -PyDoc_STRVAR(posix_sendfile__doc__,
 -"sendfile(out, in, offset, nbytes) -> byteswritten\n\
 -sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\
 -            -> byteswritten\n\
 -Copy nbytes bytes from file descriptor in to file descriptor out.");
 +exit:
 +    return return_value;
 +}
  
  static PyObject *
 -posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
 +os_sched_setaffinity_impl(PyModuleDef *module, pid_t pid, PyObject *mask)
 +/*[clinic end generated code: output=5199929738130196 input=a0791a597c7085ba]*/
  {
 -    int in, out;
 -    Py_ssize_t ret;
 -    off_t offset;
 +    int ncpus;
 +    size_t setsize;
 +    cpu_set_t *cpu_set = NULL;
 +    PyObject *iterator = NULL, *item;
  
 -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
 -#ifndef __APPLE__
 -    Py_ssize_t len;
 -#endif
 -    PyObject *headers = NULL, *trailers = NULL;
 -    Py_buffer *hbuf, *tbuf;
 -    off_t sbytes;
 -    struct sf_hdtr sf;
 -    int flags = 0;
 -    static char *keywords[] = {"out", "in",
 -                                "offset", "count",
 -                                "headers", "trailers", "flags", NULL};
 +    iterator = PyObject_GetIter(mask);
 +    if (iterator == NULL)
 +        return NULL;
  
 -    sf.headers = NULL;
 -    sf.trailers = NULL;
 +    ncpus = NCPUS_START;
 +    setsize = CPU_ALLOC_SIZE(ncpus);
 +    cpu_set = CPU_ALLOC(ncpus);
 +    if (cpu_set == NULL) {
 +        PyErr_NoMemory();
 +        goto error;
 +    }
 +    CPU_ZERO_S(setsize, cpu_set);
  
 -#ifdef __APPLE__
 -    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
 -        keywords, &out, &in, _parse_off_t, &offset, _parse_off_t, &sbytes,
 -#else
 -    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
 -        keywords, &out, &in, _parse_off_t, &offset, &len,
 -#endif
 -                &headers, &trailers, &flags))
 -            return NULL;
 -    if (headers != NULL) {
 -        if (!PySequence_Check(headers)) {
 -            PyErr_SetString(PyExc_TypeError,
 -                "sendfile() headers must be a sequence or None");
 -            return NULL;
 -        } else {
 -            Py_ssize_t i = 0; /* Avoid uninitialized warning */
 -            sf.hdr_cnt = PySequence_Size(headers);
 -            if (sf.hdr_cnt > 0 &&
 -                (i = iov_setup(&(sf.headers), &hbuf,
 -                                headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0)
 -                return NULL;
 -#ifdef __APPLE__
 -            sbytes += i;
 -#endif
 +    while ((item = PyIter_Next(iterator))) {
 +        long cpu;
 +        if (!PyLong_Check(item)) {
 +            PyErr_Format(PyExc_TypeError,
 +                        "expected an iterator of ints, "
 +                        "but iterator yielded %R",
 +                        Py_TYPE(item));
 +            Py_DECREF(item);
 +            goto error;
          }
 -    }
 -    if (trailers != NULL) {
 -        if (!PySequence_Check(trailers)) {
 -            PyErr_SetString(PyExc_TypeError,
 -                "sendfile() trailers must be a sequence or None");
 -            return NULL;
 -        } else {
 -            Py_ssize_t i = 0; /* Avoid uninitialized warning */
 -            sf.trl_cnt = PySequence_Size(trailers);
 -            if (sf.trl_cnt > 0 &&
 -                (i = iov_setup(&(sf.trailers), &tbuf,
 -                                trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0)
 -                return NULL;
 -#ifdef __APPLE__
 -            sbytes += i;
 -#endif
 +        cpu = PyLong_AsLong(item);
 +        Py_DECREF(item);
 +        if (cpu < 0) {
 +            if (!PyErr_Occurred())
 +                PyErr_SetString(PyExc_ValueError, "negative CPU number");
 +            goto error;
          }
 -    }
 -
 -    Py_BEGIN_ALLOW_THREADS
 -#ifdef __APPLE__
 -    ret = sendfile(in, out, offset, &sbytes, &sf, flags);
 -#else
 -    ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
 -#endif
 -    Py_END_ALLOW_THREADS
 -
 -    if (sf.headers != NULL)
 -        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
 -    if (sf.trailers != NULL)
 -        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
 -
 -    if (ret < 0) {
 -        if ((errno == EAGAIN) || (errno == EBUSY)) {
 -            if (sbytes != 0) {
 -                // some data has been sent
 -                goto done;
 +        if (cpu > INT_MAX - 1) {
 +            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
 +            goto error;
 +        }
 +        if (cpu >= ncpus) {
 +            /* Grow CPU mask to fit the CPU number */
 +            int newncpus = ncpus;
 +            cpu_set_t *newmask;
 +            size_t newsetsize;
 +            while (newncpus <= cpu) {
 +                if (newncpus > INT_MAX / 2)
 +                    newncpus = cpu + 1;
 +                else
 +                    newncpus = newncpus * 2;
              }
 -            else {
 -                // no data has been sent; upper application is supposed
 -                // to retry on EAGAIN or EBUSY
 -                return posix_error();
 +            newmask = CPU_ALLOC(newncpus);
 +            if (newmask == NULL) {
 +                PyErr_NoMemory();
 +                goto error;
              }
 +            newsetsize = CPU_ALLOC_SIZE(newncpus);
 +            CPU_ZERO_S(newsetsize, newmask);
 +            memcpy(newmask, cpu_set, setsize);
 +            CPU_FREE(cpu_set);
 +            setsize = newsetsize;
 +            cpu_set = newmask;
 +            ncpus = newncpus;
          }
 -        return posix_error();
 +        CPU_SET_S(cpu, setsize, cpu_set);
      }
 -    goto done;
 -
 -done:
 -    #if !defined(HAVE_LARGEFILE_SUPPORT)
 -        return Py_BuildValue("l", sbytes);
 -    #else
 -        return Py_BuildValue("L", sbytes);
 -    #endif
 +    Py_CLEAR(iterator);
  
 -#else
 -    Py_ssize_t count;
 -    PyObject *offobj;
 -    static char *keywords[] = {"out", "in",
 -                                "offset", "count", NULL};
 -    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
 -            keywords, &out, &in, &offobj, &count))
 -        return NULL;
 -#ifdef linux
 -    if (offobj == Py_None) {
 -        Py_BEGIN_ALLOW_THREADS
 -        ret = sendfile(out, in, NULL, count);
 -        Py_END_ALLOW_THREADS
 -        if (ret < 0)
 -            return posix_error();
 -        return Py_BuildValue("n", ret);
 +    if (sched_setaffinity(pid, setsize, cpu_set)) {
 +        posix_error();
 +        goto error;
      }
 -#endif
 -    if (!_parse_off_t(offobj, &offset))
 -        return NULL;
 -    Py_BEGIN_ALLOW_THREADS
 -    ret = sendfile(out, in, &offset, count);
 -    Py_END_ALLOW_THREADS
 -    if (ret < 0)
 -        return posix_error();
 -    return Py_BuildValue("n", ret);
 -#endif
 +    CPU_FREE(cpu_set);
 +    Py_RETURN_NONE;
 +
 +error:
 +    if (cpu_set)
 +        CPU_FREE(cpu_set);
 +    Py_XDECREF(iterator);
 +    return NULL;
  }
 -#endif
  
 -PyDoc_STRVAR(posix_fstat__doc__,
 -"fstat(fd) -> stat result\n\n\
 -Like stat(), but for an open file descriptor.\n\
 -Equivalent to stat(fd=fd).");
  
 -static PyObject *
 -posix_fstat(PyObject *self, PyObject *args)
 -{
 -    int fd;
 -    STRUCT_STAT st;
 -    int res;
 -    if (!PyArg_ParseTuple(args, "i:fstat", &fd))
 -        return NULL;
 -    Py_BEGIN_ALLOW_THREADS
 -    res = FSTAT(fd, &st);
 -    Py_END_ALLOW_THREADS
 -    if (res != 0) {
 -#ifdef MS_WINDOWS
 -        return PyErr_SetFromWindowsErr(0);
 -#else
 -        return posix_error();
 -#endif
 -    }
 +/*[clinic input]
 +os.sched_getaffinity
 +    pid: pid_t
 +    /
  
 -    return _pystat_fromstructstat(&st);
 -}
 +Return the affinity of the process identified by pid.
 +
 +The affinity is returned as a set of CPU identifiers.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_sched_getaffinity__doc__,
 +"sched_getaffinity($module, pid, /)\n"
 +"--\n"
 +"\n"
 +"Return the affinity of the process identified by pid.\n"
 +"\n"
 +"The affinity is returned as a set of CPU identifiers.");
 +
 +#define OS_SCHED_GETAFFINITY_METHODDEF    \
 +    {"sched_getaffinity", (PyCFunction)os_sched_getaffinity, METH_VARARGS, os_sched_getaffinity__doc__},
  
 -PyDoc_STRVAR(posix_isatty__doc__,
 -"isatty(fd) -> bool\n\n\
 -Return True if the file descriptor 'fd' is an open file descriptor\n\
 -connected to the slave end of a terminal.");
 +static PyObject *
 +os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid);
  
  static PyObject *
 -posix_isatty(PyObject *self, PyObject *args)
 +os_sched_getaffinity(PyModuleDef *module, PyObject *args)
  {
 -    int fd;
 -    if (!PyArg_ParseTuple(args, "i:isatty", &fd))
 -        return NULL;
 -    if (!_PyVerify_fd(fd))
 -        return PyBool_FromLong(0);
 -    return PyBool_FromLong(isatty(fd));
 -}
 +    PyObject *return_value = NULL;
 +    pid_t pid;
  
 -#ifdef HAVE_PIPE
 -PyDoc_STRVAR(posix_pipe__doc__,
 -"pipe() -> (read_end, write_end)\n\n\
 -Create a pipe.");
 +    if (!PyArg_ParseTuple(args,
 +        "" _Py_PARSE_PID ":sched_getaffinity",
 +        &pid))
 +        goto exit;
 +    return_value = os_sched_getaffinity_impl(module, pid);
 +
 +exit:
 +    return return_value;
 +}
  
  static PyObject *
 -posix_pipe(PyObject *self, PyObject *noargs)
 +os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid)
 +/*[clinic end generated code: output=7b273b0fca9830f0 input=eaf161936874b8a1]*/
  {
 -    int fds[2];
 -#ifdef MS_WINDOWS
 -    HANDLE read, write;
 -    SECURITY_ATTRIBUTES attr;
 -    BOOL ok;
 -#else
 -    int res;
 -#endif
 -
 -#ifdef MS_WINDOWS
 -    attr.nLength = sizeof(attr);
 -    attr.lpSecurityDescriptor = NULL;
 -    attr.bInheritHandle = FALSE;
 +    int cpu, ncpus, count;
 +    size_t setsize;
 +    cpu_set_t *mask = NULL;
 +    PyObject *res = NULL;
  
 -    Py_BEGIN_ALLOW_THREADS
 -    ok = CreatePipe(&read, &write, &attr, 0);
 -    if (ok) {
 -        fds[0] = _open_osfhandle((Py_intptr_t)read, _O_RDONLY);
 -        fds[1] = _open_osfhandle((Py_intptr_t)write, _O_WRONLY);
 -        if (fds[0] == -1 || fds[1] == -1) {
 -            CloseHandle(read);
 -            CloseHandle(write);
 -            ok = 0;
 +    ncpus = NCPUS_START;
 +    while (1) {
 +        setsize = CPU_ALLOC_SIZE(ncpus);
 +        mask = CPU_ALLOC(ncpus);
 +        if (mask == NULL)
 +            return PyErr_NoMemory();
 +        if (sched_getaffinity(pid, setsize, mask) == 0)
 +            break;
 +        CPU_FREE(mask);
 +        if (errno != EINVAL)
 +            return posix_error();
 +        if (ncpus > INT_MAX / 2) {
 +            PyErr_SetString(PyExc_OverflowError, "could not allocate "
 +                            "a large enough CPU set");
 +            return NULL;
          }
 +        ncpus = ncpus * 2;
      }
 -    Py_END_ALLOW_THREADS
 -
 -    if (!ok)
 -        return PyErr_SetFromWindowsErr(0);
 -#else
 -
 -#ifdef HAVE_PIPE2
 -    Py_BEGIN_ALLOW_THREADS
 -    res = pipe2(fds, O_CLOEXEC);
 -    Py_END_ALLOW_THREADS
  
 -    if (res != 0 && errno == ENOSYS)
 -    {
 -#endif
 -        Py_BEGIN_ALLOW_THREADS
 -        res = pipe(fds);
 -        Py_END_ALLOW_THREADS
 -
 -        if (res == 0) {
 -            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
 -                close(fds[0]);
 -                close(fds[1]);
 -                return NULL;
 -            }
 -            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
 -                close(fds[0]);
 -                close(fds[1]);
 -                return NULL;
 +    res = PySet_New(NULL);
 +    if (res == NULL)
 +        goto error;
 +    for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
 +        if (CPU_ISSET_S(cpu, setsize, mask)) {
 +            PyObject *cpu_num = PyLong_FromLong(cpu);
 +            --count;
 +            if (cpu_num == NULL)
 +                goto error;
 +            if (PySet_Add(res, cpu_num)) {
 +                Py_DECREF(cpu_num);
 +                goto error;
              }
 +            Py_DECREF(cpu_num);
          }
 -#ifdef HAVE_PIPE2
      }
 -#endif
 +    CPU_FREE(mask);
 +    return res;
  
 -    if (res != 0)
 -        return PyErr_SetFromErrno(PyExc_OSError);
 -#endif /* !MS_WINDOWS */
 -    return Py_BuildValue("(ii)", fds[0], fds[1]);
 +error:
 +    if (mask)
 +        CPU_FREE(mask);
 +    Py_XDECREF(res);
 +    return NULL;
  }
 -#endif  /* HAVE_PIPE */
 -
 -#ifdef HAVE_PIPE2
 -PyDoc_STRVAR(posix_pipe2__doc__,
 -"pipe2(flags) -> (read_end, write_end)\n\n\
 -Create a pipe with flags set atomically.\n\
 -flags can be constructed by ORing together one or more of these values:\n\
 -O_NONBLOCK, O_CLOEXEC.\n\
 -");
 -
 -static PyObject *
 -posix_pipe2(PyObject *self, PyObject *arg)
 -{
 -    int flags;
 -    int fds[2];
 -    int res;
  
 -    flags = _PyLong_AsInt(arg);
 -    if (flags == -1 && PyErr_Occurred())
 -        return NULL;
 -
 -    res = pipe2(fds, flags);
 -    if (res != 0)
 -        return posix_error();
 -    return Py_BuildValue("(ii)", fds[0], fds[1]);
 -}
 -#endif /* HAVE_PIPE2 */
 +#endif /* HAVE_SCHED_SETAFFINITY */
  
 -#ifdef HAVE_WRITEV
 -PyDoc_STRVAR(posix_writev__doc__,
 -"writev(fd, buffers) -> byteswritten\n\n\
 -Write the contents of *buffers* to file descriptor *fd*. *buffers*\n\
 -must be a sequence of bytes-like objects.\n\n\
 -writev writes the contents of each object to the file descriptor\n\
 -and returns the total number of bytes written.");
 +#endif /* HAVE_SCHED_H */
  
 -static PyObject *
 -posix_writev(PyObject *self, PyObject *args)
 -{
 -    int fd, cnt;
 -    Py_ssize_t res;
 -    PyObject *seq;
 -    struct iovec *iov;
 -    Py_buffer *buf;
 -    if (!PyArg_ParseTuple(args, "iO:writev", &fd, &seq))
 -        return NULL;
 -    if (!PySequence_Check(seq)) {
 -        PyErr_SetString(PyExc_TypeError,
 -            "writev() arg 2 must be a sequence");
 -        return NULL;
 -    }
 -    cnt = PySequence_Size(seq);
 +#ifndef OS_SCHED_GET_PRIORITY_MAX_METHODDEF
 +#define OS_SCHED_GET_PRIORITY_MAX_METHODDEF
 +#endif  /* OS_SCHED_GET_PRIORITY_MAX_METHODDEF */
  
 -    if (iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE) < 0) {
 -        return NULL;
 -    }
 +#ifndef OS_SCHED_GET_PRIORITY_MIN_METHODDEF
 +#define OS_SCHED_GET_PRIORITY_MIN_METHODDEF
 +#endif  /* OS_SCHED_GET_PRIORITY_MIN_METHODDEF */
  
 -    Py_BEGIN_ALLOW_THREADS
 -    res = writev(fd, iov, cnt);
 -    Py_END_ALLOW_THREADS
 +#ifndef OS_SCHED_GETSCHEDULER_METHODDEF
 +#define OS_SCHED_GETSCHEDULER_METHODDEF
 +#endif  /* OS_SCHED_GETSCHEDULER_METHODDEF */
  
 -    iov_cleanup(iov, buf, cnt);
 -    if (res < 0)
 -        return posix_error();
 +#ifndef OS_SCHED_SETSCHEDULER_METHODDEF
 +#define OS_SCHED_SETSCHEDULER_METHODDEF
 +#endif  /* OS_SCHED_SETSCHEDULER_METHODDEF */
  
 -    return PyLong_FromSsize_t(res);
 -}
 -#endif
 +#ifndef OS_SCHED_GETPARAM_METHODDEF
 +#define OS_SCHED_GETPARAM_METHODDEF
 +#endif  /* OS_SCHED_GETPARAM_METHODDEF */
  
 -#ifdef HAVE_PWRITE
 -PyDoc_STRVAR(posix_pwrite__doc__,
 -"pwrite(fd, string, offset) -> byteswritten\n\n\
 -Write string to a file descriptor, fd, from offset, leaving the file\n\
 -offset unchanged.");
 +#ifndef OS_SCHED_SETPARAM_METHODDEF
 +#define OS_SCHED_SETPARAM_METHODDEF
 +#endif  /* OS_SCHED_SETPARAM_METHODDEF */
  
 -static PyObject *
 -posix_pwrite(PyObject *self, PyObject *args)
 -{
 -    Py_buffer pbuf;
 -    int fd;
 -    off_t offset;
 -    Py_ssize_t size;
 +#ifndef OS_SCHED_RR_GET_INTERVAL_METHODDEF
 +#define OS_SCHED_RR_GET_INTERVAL_METHODDEF
 +#endif  /* OS_SCHED_RR_GET_INTERVAL_METHODDEF */
  
 -    if (!PyArg_ParseTuple(args, "iy*O&:pwrite", &fd, &pbuf, _parse_off_t, &offset))
 -        return NULL;
 +#ifndef OS_SCHED_YIELD_METHODDEF
 +#define OS_SCHED_YIELD_METHODDEF
 +#endif  /* OS_SCHED_YIELD_METHODDEF */
  
 -    if (!_PyVerify_fd(fd)) {
 -        PyBuffer_Release(&pbuf);
 -        return posix_error();
 -    }
 -    Py_BEGIN_ALLOW_THREADS
 -    size = pwrite(fd, pbuf.buf, (size_t)pbuf.len, offset);
 -    Py_END_ALLOW_THREADS
 -    PyBuffer_Release(&pbuf);
 -    if (size < 0)
 -        return posix_error();
 -    return PyLong_FromSsize_t(size);
 -}
 -#endif
 +#ifndef OS_SCHED_SETAFFINITY_METHODDEF
 +#define OS_SCHED_SETAFFINITY_METHODDEF
 +#endif  /* OS_SCHED_SETAFFINITY_METHODDEF */
  
 -#ifdef HAVE_MKFIFO
 -PyDoc_STRVAR(posix_mkfifo__doc__,
 -"mkfifo(path, mode=0o666, *, dir_fd=None)\n\n\
 -Create a FIFO (a POSIX named pipe).\n\
 -\n\
 -If dir_fd is not None, it should be a file descriptor open to a directory,\n\
 -  and path should be relative; path will then be relative to that directory.\n\
 -dir_fd may not be implemented on your platform.\n\
 -  If it is unavailable, using it will raise a NotImplementedError.");
 +#ifndef OS_SCHED_GETAFFINITY_METHODDEF
 +#define OS_SCHED_GETAFFINITY_METHODDEF
 +#endif  /* OS_SCHED_GETAFFINITY_METHODDEF */
  
 -static PyObject *
 -posix_mkfifo(PyObject *self, PyObject *args, PyObject *kwargs)
 -{
 -    path_t path;
 -    int mode = 0666;
 -    int dir_fd = DEFAULT_DIR_FD;
 -    int result;
 -    PyObject *return_value = NULL;
 -    static char *keywords[] = {"path", "mode", "dir_fd", NULL};
  
 -    memset(&path, 0, sizeof(path));
 -    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkfifo", keywords,
 -        path_converter, &path,
 -        &mode,
 -#ifdef HAVE_MKFIFOAT
 -        dir_fd_converter, &dir_fd
 +/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
 +/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
 +#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
 +#define DEV_PTY_FILE "/dev/ptc"
 +#define HAVE_DEV_PTMX
  #else
 -        dir_fd_unavailable, &dir_fd
 -#endif
 -        ))
 -        return NULL;
 -
 -    Py_BEGIN_ALLOW_THREADS
 -#ifdef HAVE_MKFIFOAT
 -    if (dir_fd != DEFAULT_DIR_FD)
 -        result = mkfifoat(dir_fd, path.narrow, mode);
 -    else
 -#endif
 -        result = mkfifo(path.narrow, mode);
 -    Py_END_ALLOW_THREADS
 -
 -    if (result < 0) {
 -        return_value = posix_error();
 -        goto exit;
 -    }
 -
 -    return_value = Py_None;
 -    Py_INCREF(Py_None);
 -
 -exit:
 -    path_cleanup(&path);
 -    return return_value;
 -}
 +#define DEV_PTY_FILE "/dev/ptmx"
  #endif
  
 -#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
 -PyDoc_STRVAR(posix_mknod__doc__,
 -"mknod(filename, mode=0o600, device=0, *, dir_fd=None)\n\n\
 -Create a filesystem node (file, device special file or named pipe)\n\
 -named filename. mode specifies both the permissions to use and the\n\
 -type of node to be created, being combined (bitwise OR) with one of\n\
 -S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
 -device defines the newly created device special file (probably using\n\
 -os.makedev()), otherwise it is ignored.\n\
 -\n\
 -If dir_fd is not None, it should be a file descriptor open to a directory,\n\
 -  and path should be relative; path will then be relative to that directory.\n\
 -dir_fd may not be implemented on your platform.\n\
 -  If it is unavailable, using it will raise a NotImplementedError.");
 -
 -
 -static PyObject *
 -posix_mknod(PyObject *self, PyObject *args, PyObject *kwargs)
 -{
 -    path_t path;
 -    int mode = 0666;
 -    dev_t device = 0;
 -    int dir_fd = DEFAULT_DIR_FD;
 -    int result;
 -    PyObject *return_value = NULL;
 -    static char *keywords[] = {"path", "mode", "device", "dir_fd", NULL};
 -
 -    memset(&path, 0, sizeof(path));
 -    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|iO&$O&:mknod", keywords,
 -        path_converter, &path,
 -        &mode, _Py_Dev_Converter, &device,
 -#ifdef HAVE_MKNODAT
 -        dir_fd_converter, &dir_fd
 +#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
 +#ifdef HAVE_PTY_H
 +#include <pty.h>
  #else
 -        dir_fd_unavailable, &dir_fd
 +#ifdef HAVE_LIBUTIL_H
 +#include <libutil.h>
 +#else
 +#ifdef 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
 -        ))
 -        return NULL;
 +#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
  
 -    Py_BEGIN_ALLOW_THREADS
 -#ifdef HAVE_MKNODAT
 -    if (dir_fd != DEFAULT_DIR_FD)
 -        result = mknodat(dir_fd, path.narrow, mode, device);
 -    else
 -#endif
 -        result = mknod(path.narrow, mode, device);
 -    Py_END_ALLOW_THREADS
  
 -    if (result < 0) {
 -        return_value = posix_error();
 -        goto exit;
 -    }
 +#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
 +/*[clinic input]
 +os.openpty
  
 -    return_value = Py_None;
 -    Py_INCREF(Py_None);
 +Open a pseudo-terminal.
  
 -exit:
 -    path_cleanup(&path);
 -    return return_value;
 -}
 -#endif
 +Return a tuple of (master_fd, slave_fd) containing open file descriptors
 +for both the master and slave ends.
 +[clinic start generated code]*/
  
 -#ifdef HAVE_DEVICE_MACROS
 -PyDoc_STRVAR(posix_major__doc__,
 -"major(device) -> major number\n\
 -Extracts a device major number from a raw device number.");
 +PyDoc_STRVAR(os_openpty__doc__,
 +"openpty($module, /)\n"
 +"--\n"
 +"\n"
 +"Open a pseudo-terminal.\n"
 +"\n"
 +"Return a tuple of (master_fd, slave_fd) containing open file descriptors\n"
 +"for both the master and slave ends.");
  
 -static PyObject *
 -posix_major(PyObject *self, PyObject *args)
 -{
 -    dev_t device;
 -    if (!PyArg_ParseTuple(args, "O&:major", _Py_Dev_Converter, &device))
 -        return NULL;
 -    return PyLong_FromLong((long)major(device));
 -}
 +#define OS_OPENPTY_METHODDEF    \
 +    {"openpty", (PyCFunction)os_openpty, METH_NOARGS, os_openpty__doc__},
  
 -PyDoc_STRVAR(posix_minor__doc__,
 -"minor(device) -> minor number\n\
 -Extracts a device minor number from a raw device number.");
 +static PyObject *
 +os_openpty_impl(PyModuleDef *module);
  
  static PyObject *
 -posix_minor(PyObject *self, PyObject *args)
 +os_openpty(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
  {
 -    dev_t device;
 -    if (!PyArg_ParseTuple(args, "O&:minor", _Py_Dev_Converter, &device))
 -        return NULL;
 -    return PyLong_FromLong((long)minor(device));
 +    return os_openpty_impl(module);
  }
  
 -PyDoc_STRVAR(posix_makedev__doc__,
 -"makedev(major, minor) -> device number\n\
 -Composes a raw device number from the major and minor device numbers.");
 -
  static PyObject *
 -posix_makedev(PyObject *self, PyObject *args)
 +os_openpty_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=b12d3c1735468464 input=f3d99fd99e762907]*/
  {
 -    int major, minor;
 -    if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
 -        return NULL;
 -    return _PyLong_FromDev(makedev(major, minor));
 -}
 -#endif /* device macros */
 -
 +    int master_fd = -1, slave_fd = -1;
 +#ifndef HAVE_OPENPTY
 +    char * slave_name;
 +#endif
 +#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
 +    PyOS_sighandler_t sig_saved;
 +#ifdef sun
 +    extern char *ptsname(int fildes);
 +#endif
 +#endif
  
 -#ifdef HAVE_FTRUNCATE
 -PyDoc_STRVAR(posix_ftruncate__doc__,
 -"ftruncate(fd, length)\n\n\
 -Truncate a file to a specified length.");
 +#ifdef HAVE_OPENPTY
 +    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
 +        goto posix_error;
  
 -static PyObject *
 -posix_ftruncate(PyObject *self, PyObject *args)
 -{
 -    int fd;
 -    off_t length;
 -    int res;
 +    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
 +        goto error;
 +    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
 +        goto error;
  
 -    if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, _parse_off_t, &length))
 -        return NULL;
 +#elif defined(HAVE__GETPTY)
 +    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
 +    if (slave_name == NULL)
 +        goto posix_error;
 +    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
 +        goto error;
  
 -    Py_BEGIN_ALLOW_THREADS
 -    res = ftruncate(fd, length);
 -    Py_END_ALLOW_THREADS
 -    if (res < 0)
 -        return posix_error();
 -    Py_INCREF(Py_None);
 -    return Py_None;
 -}
 -#endif
 +    slave_fd = _Py_open(slave_name, O_RDWR);
 +    if (slave_fd < 0)
 +        goto posix_error;
  
 -#ifdef HAVE_TRUNCATE
 -PyDoc_STRVAR(posix_truncate__doc__,
 -"truncate(path, length)\n\n\
 -Truncate the file given by path to length bytes.\n\
 -On some platforms, path may also be specified as an open file descriptor.\n\
 -  If this functionality is unavailable, using it raises an exception.");
 +#else
 +    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
 +    if (master_fd < 0)
 +        goto posix_error;
  
 -static PyObject *
 -posix_truncate(PyObject *self, PyObject *args, PyObject *kwargs)
 -{
 -    path_t path;
 -    off_t length;
 -    int res;
 -    PyObject *result = NULL;
 -    static char *keywords[] = {"path", "length", NULL};
 +    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
  
 -    memset(&path, 0, sizeof(path));
 -    path.function_name = "truncate";
 -#ifdef HAVE_FTRUNCATE
 -    path.allow_fd = 1;
 -#endif
 -    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:truncate", keywords,
 -                                     path_converter, &path,
 -                                     _parse_off_t, &length))
 -        return NULL;
 +    /* change permission of slave */
 +    if (grantpt(master_fd) < 0) {
 +        PyOS_setsig(SIGCHLD, sig_saved);
 +        goto posix_error;
 +    }
  
 -    Py_BEGIN_ALLOW_THREADS
 -#ifdef HAVE_FTRUNCATE
 -    if (path.fd != -1)
 -        res = ftruncate(path.fd, length);
 -    else
 -#endif
 -        res = truncate(path.narrow, length);
 -    Py_END_ALLOW_THREADS
 -    if (res < 0)
 -        result = path_error(&path);
 -    else {
 -        Py_INCREF(Py_None);
 -        result = Py_None;
 +    /* unlock slave */
 +    if (unlockpt(master_fd) < 0) {
 +        PyOS_setsig(SIGCHLD, sig_saved);
 +        goto posix_error;
      }
 -    path_cleanup(&path);
 -    return result;
 -}
 -#endif
  
 -/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
 -   and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
 -   defined, which is the case in Python on AIX. AIX bug report:
 -   http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
 -#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
 -#  define POSIX_FADVISE_AIX_BUG
 -#endif
 +    PyOS_setsig(SIGCHLD, sig_saved);
  
 -#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
 -PyDoc_STRVAR(posix_posix_fallocate__doc__,
 -"posix_fallocate(fd, offset, len)\n\n\
 -Ensures that enough disk space is allocated for the file specified by fd\n\
 -starting from offset and continuing for len bytes.");
 +    slave_name = ptsname(master_fd); /* get name of slave */
 +    if (slave_name == NULL)
 +        goto posix_error;
  
 -static PyObject *
 -posix_posix_fallocate(PyObject *self, PyObject *args)
 -{
 -    off_t len, offset;
 -    int res, fd;
 +    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
 +    if (slave_fd < 0)
 +        goto posix_error;
  
 -    if (!PyArg_ParseTuple(args, "iO&O&:posix_fallocate",
 -            &fd, _parse_off_t, &offset, _parse_off_t, &len))
 -        return NULL;
 +    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
 +        goto posix_error;
  
 -    Py_BEGIN_ALLOW_THREADS
 -    res = posix_fallocate(fd, offset, len);
 -    Py_END_ALLOW_THREADS
 -    if (res != 0) {
 -        errno = res;
 -        return posix_error();
 -    }
 -    Py_RETURN_NONE;
 -}
 +#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
 +    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
 +    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
 +#ifndef __hpux
 +    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
 +#endif /* __hpux */
 +#endif /* HAVE_CYGWIN */
 +#endif /* HAVE_OPENPTY */
 +
 +    return Py_BuildValue("(ii)", master_fd, slave_fd);
 +
 +posix_error:
 +    posix_error();
 +#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY)
 +error:
  #endif
 +    if (master_fd != -1)
 +        close(master_fd);
 +    if (slave_fd != -1)
 +        close(slave_fd);
 +    return NULL;
 +}
 +#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
  
 -#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
 -PyDoc_STRVAR(posix_posix_fadvise__doc__,
 -"posix_fadvise(fd, offset, len, advice)\n\n\
 -Announces an intention to access data in a specific pattern thus allowing\n\
 -the kernel to make optimizations.\n\
 -The advice applies to the region of the file specified by fd starting at\n\
 -offset and continuing for len bytes.\n\
 -advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n\
 -POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED or\n\
 -POSIX_FADV_DONTNEED.");
  
 -static PyObject *
 -posix_posix_fadvise(PyObject *self, PyObject *args)
 -{
 -    off_t len, offset;
 -    int res, fd, advice;
 +#ifdef HAVE_FORKPTY
 +/*[clinic input]
 +os.forkpty
  
 -    if (!PyArg_ParseTuple(args, "iO&O&i:posix_fadvise",
 -            &fd, _parse_off_t, &offset, _parse_off_t, &len, &advice))
 -        return NULL;
 +Fork a new process with a new pseudo-terminal as controlling tty.
  
 -    Py_BEGIN_ALLOW_THREADS
 -    res = posix_fadvise(fd, offset, len, advice);
 -    Py_END_ALLOW_THREADS
 -    if (res != 0) {
 -        errno = res;
 -        return posix_error();
 -    }
 -    Py_RETURN_NONE;
 -}
 -#endif
 +Returns a tuple of (pid, master_fd).
 +Like fork(), return pid of 0 to the child process,
 +and pid of child to the parent process.
 +To both, return fd of newly opened pseudo-terminal.
 +[clinic start generated code]*/
  
 -#ifdef HAVE_PUTENV
 -PyDoc_STRVAR(posix_putenv__doc__,
 -"putenv(key, value)\n\n\
 -Change or add an environment variable.");
 +PyDoc_STRVAR(os_forkpty__doc__,
 +"forkpty($module, /)\n"
 +"--\n"
 +"\n"
 +"Fork a new process with a new pseudo-terminal as controlling tty.\n"
 +"\n"
 +"Returns a tuple of (pid, master_fd).\n"
 +"Like fork(), return pid of 0 to the child process,\n"
 +"and pid of child to the parent process.\n"
 +"To both, return fd of newly opened pseudo-terminal.");
  
 -/* Save putenv() parameters as values here, so we can collect them when they
 - * get re-set with another call for the same key. */
 -static PyObject *posix_putenv_garbage;
 +#define OS_FORKPTY_METHODDEF    \
 +    {"forkpty", (PyCFunction)os_forkpty, METH_NOARGS, os_forkpty__doc__},
  
  static PyObject *
 -posix_putenv(PyObject *self, PyObject *args)
 +os_forkpty_impl(PyModuleDef *module);
 +
 +static PyObject *
 +os_forkpty(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
  {
 -    PyObject *newstr = NULL;
 -#ifdef MS_WINDOWS
 -    PyObject *os1, *os2;
 -    wchar_t *newenv;
 +    return os_forkpty_impl(module);
 +}
  
 -    if (!PyArg_ParseTuple(args,
 -                          "UU:putenv",
 -                          &os1, &os2))
 -        return NULL;
 +static PyObject *
 +os_forkpty_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=d4f82958d2ed5cad input=f1f7f4bae3966010]*/
 +{
 +    int master_fd = -1, result = 0;
 +    pid_t pid;
  
 -    newstr = PyUnicode_FromFormat("%U=%U", os1, os2);
 -    if (newstr == NULL) {
 -        PyErr_NoMemory();
 -        goto error;
 +    _PyImport_AcquireLock();
 +    pid = forkpty(&master_fd, NULL, NULL, NULL);
 +    if (pid == 0) {
 +        /* child: this clobbers and resets the import lock. */
 +        PyOS_AfterFork();
 +    } else {
 +        /* parent: release the import lock. */
 +        result = _PyImport_ReleaseLock();
      }
 -    if (_MAX_ENV < PyUnicode_GET_LENGTH(newstr)) {
 -        PyErr_Format(PyExc_ValueError,
 -                     "the environment variable is longer than %u characters",
 -                     _MAX_ENV);
 -        goto error;
 +    if (pid == -1)
 +        return posix_error();
 +    if (result < 0) {
 +        /* Don't clobber the OSError if the fork failed. */
 +        PyErr_SetString(PyExc_RuntimeError,
 +                        "not holding the import lock");
 +        return NULL;
      }
 +    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
 +}
 +#endif /* HAVE_FORKPTY */
  
 -    newenv = PyUnicode_AsUnicode(newstr);
 -    if (newenv == NULL)
 -        goto error;
 -    if (_wputenv(newenv)) {
 -        posix_error();
 -        goto error;
 -    }
 -#else
 -    PyObject *os1, *os2;
 -    char *s1, *s2;
 -    char *newenv;
  
 -    if (!PyArg_ParseTuple(args,
 -                          "O&O&:putenv",
 -                          PyUnicode_FSConverter, &os1,
 -                          PyUnicode_FSConverter, &os2))
 -        return NULL;
 -    s1 = PyBytes_AsString(os1);
 -    s2 = PyBytes_AsString(os2);
 +#ifdef HAVE_GETEGID
 +/*[clinic input]
 +os.getegid
  
 -    newstr = PyBytes_FromFormat("%s=%s", s1, s2);
 -    if (newstr == NULL) {
 -        PyErr_NoMemory();
 -        goto error;
 -    }
 +Return the current process's effective group id.
 +[clinic start generated code]*/
  
 -    newenv = PyBytes_AS_STRING(newstr);
 -    if (putenv(newenv)) {
 -        posix_error();
 -        goto error;
 -    }
 -#endif
 +PyDoc_STRVAR(os_getegid__doc__,
 +"getegid($module, /)\n"
 +"--\n"
 +"\n"
 +"Return the current process\'s effective group id.");
  
 -    /* Install the first arg and newstr in posix_putenv_garbage;
 -     * this will cause previous value to be collected.  This has to
 -     * happen after the real putenv() call because the old value
 -     * was still accessible until then. */
 -    if (PyDict_SetItem(posix_putenv_garbage, os1, newstr)) {
 -        /* really not much we can do; just leak */
 -        PyErr_Clear();
 -    }
 -    else {
 -        Py_DECREF(newstr);
 -    }
 +#define OS_GETEGID_METHODDEF    \
 +    {"getegid", (PyCFunction)os_getegid, METH_NOARGS, os_getegid__doc__},
  
 -#ifndef MS_WINDOWS
 -    Py_DECREF(os1);
 -    Py_DECREF(os2);
 -#endif
 -    Py_RETURN_NONE;
 +static PyObject *
 +os_getegid_impl(PyModuleDef *module);
  
 -error:
 -#ifndef MS_WINDOWS
 -    Py_DECREF(os1);
 -    Py_DECREF(os2);
 -#endif
 -    Py_XDECREF(newstr);
 -    return NULL;
 +static PyObject *
 +os_getegid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_getegid_impl(module);
  }
 -#endif /* putenv */
 -
 -#ifdef HAVE_UNSETENV
 -PyDoc_STRVAR(posix_unsetenv__doc__,
 -"unsetenv(key)\n\n\
 -Delete an environment variable.");
  
  static PyObject *
 -posix_unsetenv(PyObject *self, PyObject *args)
 +os_getegid_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=fd12c346fa41cccb input=1596f79ad1107d5d]*/
  {
 -    PyObject *name;
 -#ifndef HAVE_BROKEN_UNSETENV
 -    int err;
 -#endif
 +    return _PyLong_FromGid(getegid());
 +}
 +#endif /* HAVE_GETEGID */
  
 -    if (!PyArg_ParseTuple(args, "O&:unsetenv",
  
 -                          PyUnicode_FSConverter, &name))
 -        return NULL;
 +#ifdef HAVE_GETEUID
 +/*[clinic input]
 +os.geteuid
  
 -#ifdef HAVE_BROKEN_UNSETENV
 -    unsetenv(PyBytes_AS_STRING(name));
 -#else
 -    err = unsetenv(PyBytes_AS_STRING(name));
 -    if (err) {
 -        Py_DECREF(name);
 -        return posix_error();
 -    }
 -#endif
 +Return the current process's effective user id.
 +[clinic start generated code]*/
  
 -    /* Remove the key from posix_putenv_garbage;
 -     * this will cause it to be collected.  This has to
 -     * happen after the real unsetenv() call because the
 -     * old value was still accessible until then.
 -     */
 -    if (PyDict_DelItem(posix_putenv_garbage, name)) {
 -        /* really not much we can do; just leak */
 -        PyErr_Clear();
 -    }
 -    Py_DECREF(name);
 -    Py_RETURN_NONE;
 -}
 -#endif /* unsetenv */
 +PyDoc_STRVAR(os_geteuid__doc__,
 +"geteuid($module, /)\n"
 +"--\n"
 +"\n"
 +"Return the current process\'s effective user id.");
 +
 +#define OS_GETEUID_METHODDEF    \
 +    {"geteuid", (PyCFunction)os_geteuid, METH_NOARGS, os_geteuid__doc__},
  
 -PyDoc_STRVAR(posix_strerror__doc__,
 -"strerror(code) -> string\n\n\
 -Translate an error code to a message string.");
 +static PyObject *
 +os_geteuid_impl(PyModuleDef *module);
  
  static PyObject *
 -posix_strerror(PyObject *self, PyObject *args)
 +os_geteuid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
  {
 -    int code;
 -    char *message;
 -    if (!PyArg_ParseTuple(args, "i:strerror", &code))
 -        return NULL;
 -    message = strerror(code);
 -    if (message == NULL) {
 -        PyErr_SetString(PyExc_ValueError,
 -                        "strerror() argument out of range");
 -        return NULL;
 -    }
 -    return PyUnicode_DecodeLocale(message, "surrogateescape");
 +    return os_geteuid_impl(module);
  }
  
 -
 -#ifdef HAVE_SYS_WAIT_H
 -
 -#ifdef WCOREDUMP
 -PyDoc_STRVAR(posix_WCOREDUMP__doc__,
 -"WCOREDUMP(status) -> bool\n\n\
 -Return True if the process returning 'status' was dumped to a core file.");
 -
  static PyObject *
 -posix_WCOREDUMP(PyObject *self, PyObject *args)
 +os_geteuid_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=03d98e07f4bc03d4 input=4644c662d3bd9f19]*/
  {
 -    WAIT_TYPE status;
 -    WAIT_STATUS_INT(status) = 0;
 -
 -    if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
 -        return NULL;
 -
 -    return PyBool_FromLong(WCOREDUMP(status));
 +    return _PyLong_FromUid(geteuid());
  }
 -#endif /* WCOREDUMP */
 +#endif /* HAVE_GETEUID */
  
 -#ifdef WIFCONTINUED
 -PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
 -"WIFCONTINUED(status) -> bool\n\n\
 -Return True if the process returning 'status' was continued from a\n\
 -job control stop.");
  
 -static PyObject *
 -posix_WIFCONTINUED(PyObject *self, PyObject *args)
 -{
 -    WAIT_TYPE status;
 -    WAIT_STATUS_INT(status) = 0;
 +#ifdef HAVE_GETGID
 +/*[clinic input]
 +os.getgid
  
 -    if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
 -        return NULL;
 +Return the current process's group id.
 +[clinic start generated code]*/
  
 -    return PyBool_FromLong(WIFCONTINUED(status));
 -}
 -#endif /* WIFCONTINUED */
 +PyDoc_STRVAR(os_getgid__doc__,
 +"getgid($module, /)\n"
 +"--\n"
 +"\n"
 +"Return the current process\'s group id.");
  
 -#ifdef WIFSTOPPED
 -PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
 -"WIFSTOPPED(status) -> bool\n\n\
 -Return True if the process returning 'status' was stopped.");
 +#define OS_GETGID_METHODDEF    \
 +    {"getgid", (PyCFunction)os_getgid, METH_NOARGS, os_getgid__doc__},
  
  static PyObject *
 -posix_WIFSTOPPED(PyObject *self, PyObject *args)
 -{
 -    WAIT_TYPE status;
 -    WAIT_STATUS_INT(status) = 0;
 -
 -    if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
 -        return NULL;
 +os_getgid_impl(PyModuleDef *module);
  
 -    return PyBool_FromLong(WIFSTOPPED(status));
 +static PyObject *
 +os_getgid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_getgid_impl(module);
  }
 -#endif /* WIFSTOPPED */
 -
 -#ifdef WIFSIGNALED
 -PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
 -"WIFSIGNALED(status) -> bool\n\n\
 -Return True if the process returning 'status' was terminated by a signal.");
  
  static PyObject *
 -posix_WIFSIGNALED(PyObject *self, PyObject *args)
 +os_getgid_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=07b0356121b8098d input=58796344cd87c0f6]*/
  {
 -    WAIT_TYPE status;
 -    WAIT_STATUS_INT(status) = 0;
 -
 -    if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
 -        return NULL;
 -
 -    return PyBool_FromLong(WIFSIGNALED(status));
 +    return _PyLong_FromGid(getgid());
  }
 -#endif /* WIFSIGNALED */
 +#endif /* HAVE_GETGID */
  
 -#ifdef WIFEXITED
 -PyDoc_STRVAR(posix_WIFEXITED__doc__,
 -"WIFEXITED(status) -> bool\n\n\
 -Return true if the process returning 'status' exited using the exit()\n\
 -system call.");
  
 -static PyObject *
 -posix_WIFEXITED(PyObject *self, PyObject *args)
 -{
 -    WAIT_TYPE status;
 -    WAIT_STATUS_INT(status) = 0;
 +/*[clinic input]
 +os.getpid
  
 -    if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
 -        return NULL;
 +Return the current process id.
 +[clinic start generated code]*/
  
 -    return PyBool_FromLong(WIFEXITED(status));
 -}
 -#endif /* WIFEXITED */
 +PyDoc_STRVAR(os_getpid__doc__,
 +"getpid($module, /)\n"
 +"--\n"
 +"\n"
 +"Return the current process id.");
  
 -#ifdef WEXITSTATUS
 -PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
 -"WEXITSTATUS(status) -> integer\n\n\
 -Return the process return code from 'status'.");
 +#define OS_GETPID_METHODDEF    \
 +    {"getpid", (PyCFunction)os_getpid, METH_NOARGS, os_getpid__doc__},
  
  static PyObject *
 -posix_WEXITSTATUS(PyObject *self, PyObject *args)
 -{
 -    WAIT_TYPE status;
 -    WAIT_STATUS_INT(status) = 0;
 +os_getpid_impl(PyModuleDef *module);
  
 -    if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
 -        return NULL;
 -
 -    return Py_BuildValue("i", WEXITSTATUS(status));
 +static PyObject *
 +os_getpid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_getpid_impl(module);
  }
 -#endif /* WEXITSTATUS */
 -
 -#ifdef WTERMSIG
 -PyDoc_STRVAR(posix_WTERMSIG__doc__,
 -"WTERMSIG(status) -> integer\n\n\
 -Return the signal that terminated the process that provided the 'status'\n\
 -value.");
  
  static PyObject *
 -posix_WTERMSIG(PyObject *self, PyObject *args)
 +os_getpid_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=d63a01a3cebc573d input=5a9a00f0ab68aa00]*/
  {
 -    WAIT_TYPE status;
 -    WAIT_STATUS_INT(status) = 0;
 -
 -    if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
 -        return NULL;
 -
 -    return Py_BuildValue("i", WTERMSIG(status));
 +    return PyLong_FromPid(getpid());
  }
 -#endif /* WTERMSIG */
  
 -#ifdef WSTOPSIG
 -PyDoc_STRVAR(posix_WSTOPSIG__doc__,
 -"WSTOPSIG(status) -> integer\n\n\
 -Return the signal that stopped the process that provided\n\
 -the 'status' value.");
 +#ifdef HAVE_GETGROUPLIST
 +
 +/* AC 3.5: funny apple logic below */
 +PyDoc_STRVAR(posix_getgrouplist__doc__,
 +"getgrouplist(user, group) -> list of groups to which a user belongs\n\n\
 +Returns a list of groups to which a user belongs.\n\n\
 +    user: username to lookup\n\
 +    group: base group id of the user");
  
  static PyObject *
 -posix_WSTOPSIG(PyObject *self, PyObject *args)
 +posix_getgrouplist(PyObject *self, PyObject *args)
  {
 -    WAIT_TYPE status;
 -    WAIT_STATUS_INT(status) = 0;
 -
 -    if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
 -        return NULL;
 -
 -    return Py_BuildValue("i", WSTOPSIG(status));
 -}
 -#endif /* WSTOPSIG */
 +#ifdef NGROUPS_MAX
 +#define MAX_GROUPS NGROUPS_MAX
 +#else
 +    /* defined to be 16 on Solaris7, so this should be a small number */
 +#define MAX_GROUPS 64
 +#endif
  
 -#endif /* HAVE_SYS_WAIT_H */
 +    const char *user;
 +    int i, ngroups;
 +    PyObject *list;
 +#ifdef __APPLE__
 +    int *groups, basegid;
 +#else
 +    gid_t *groups, basegid;
 +#endif
 +    ngroups = MAX_GROUPS;
  
 +#ifdef __APPLE__
 +    if (!PyArg_ParseTuple(args, "si:getgrouplist", &user, &basegid))
 +        return NULL;
 +#else
 +    if (!PyArg_ParseTuple(args, "sO&:getgrouplist", &user,
 +                          _Py_Gid_Converter, &basegid))
 +        return NULL;
 +#endif
  
 -#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
 -#ifdef _SCO_DS
 -/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
 -   needed definitions in sys/statvfs.h */
 -#define _SVID3
 +#ifdef __APPLE__
-     groups = PyMem_Malloc(ngroups * sizeof(int));
++    groups = PyMem_New(int, ngroups);
 +#else
-     groups = PyMem_Malloc(ngroups * sizeof(gid_t));
++    groups = PyMem_New(gid_t, ngroups);
  #endif
 -#include <sys/statvfs.h>
 +    if (groups == NULL)
 +        return PyErr_NoMemory();
  
 -static PyObject*
 -_pystatvfs_fromstructstatvfs(struct statvfs st) {
 -    PyObject *v = PyStructSequence_New(&StatVFSResultType);
 -    if (v == NULL)
 +    if (getgrouplist(user, basegid, groups, &ngroups) == -1) {
 +        PyMem_Del(groups);
 +        return posix_error();
 +    }
 +
 +    list = PyList_New(ngroups);
 +    if (list == NULL) {
 +        PyMem_Del(groups);
          return NULL;
 +    }
  
 -#if !defined(HAVE_LARGEFILE_SUPPORT)
 -    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
 -    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
 -    PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
 -    PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
 -    PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
 -    PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
 -    PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
 -    PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
 -    PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
 -    PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
 +    for (i = 0; i < ngroups; i++) {
 +#ifdef __APPLE__
 +        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
  #else
 -    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
 -    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
 -    PyStructSequence_SET_ITEM(v, 2,
 -                              PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
 -    PyStructSequence_SET_ITEM(v, 3,
 -                              PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
 -    PyStructSequence_SET_ITEM(v, 4,
 -                              PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
 -    PyStructSequence_SET_ITEM(v, 5,
 -                              PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
 -    PyStructSequence_SET_ITEM(v, 6,
 -                              PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
 -    PyStructSequence_SET_ITEM(v, 7,
 -                              PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
 -    PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
 -    PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
 +        PyObject *o = _PyLong_FromGid(groups[i]);
  #endif
 -    if (PyErr_Occurred()) {
 -        Py_DECREF(v);
 -        return NULL;
 +        if (o == NULL) {
 +            Py_DECREF(list);
 +            PyMem_Del(groups);
 +            return NULL;
 +        }
 +        PyList_SET_ITEM(list, i, o);
      }
  
 -    return v;
 -}
 +    PyMem_Del(groups);
  
 -PyDoc_STRVAR(posix_fstatvfs__doc__,
 -"fstatvfs(fd) -> statvfs result\n\n\
 -Perform an fstatvfs system call on the given fd.\n\
 -Equivalent to statvfs(fd).");
 +    return list;
 +}
 +#endif /* HAVE_GETGROUPLIST */
  
 -static PyObject *
 -posix_fstatvfs(PyObject *self, PyObject *args)
 -{
 -    int fd, res;
 -    struct statvfs st;
  
 -    if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
 -        return NULL;
 -    Py_BEGIN_ALLOW_THREADS
 -    res = fstatvfs(fd, &st);
 -    Py_END_ALLOW_THREADS
 -    if (res != 0)
 -        return posix_error();
 +#ifdef HAVE_GETGROUPS
 +/*[clinic input]
 +os.getgroups
  
 -    return _pystatvfs_fromstructstatvfs(st);
 -}
 -#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
 +Return list of supplemental group IDs for the process.
 +[clinic start generated code]*/
  
 +PyDoc_STRVAR(os_getgroups__doc__,
 +"getgroups($module, /)\n"
 +"--\n"
 +"\n"
 +"Return list of supplemental group IDs for the process.");
  
 -#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
 -#include <sys/statvfs.h>
 +#define OS_GETGROUPS_METHODDEF    \
 +    {"getgroups", (PyCFunction)os_getgroups, METH_NOARGS, os_getgroups__doc__},
  
 -PyDoc_STRVAR(posix_statvfs__doc__,
 -"statvfs(path)\n\n\
 -Perform a statvfs system call on the given path.\n\
 -\n\
 -path may always be specified as a string.\n\
 -On some platforms, path may also be specified as an open file descriptor.\n\
 -  If this functionality is unavailable, using it raises an exception.");
 +static PyObject *
 +os_getgroups_impl(PyModuleDef *module);
  
  static PyObject *
 -posix_statvfs(PyObject *self, PyObject *args, PyObject *kwargs)
 +os_getgroups(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
  {
 -    static char *keywords[] = {"path", NULL};
 -    path_t path;
 -    int result;
 -    PyObject *return_value = NULL;
 -    struct statvfs st;
 -
 -    memset(&path, 0, sizeof(path));
 -    path.function_name = "statvfs";
 -#ifdef HAVE_FSTATVFS
 -    path.allow_fd = 1;
 -#endif
 -    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:statvfs", keywords,
 -        path_converter, &path
 -        ))
 -        return NULL;
 -
 -    Py_BEGIN_ALLOW_THREADS
 -#ifdef HAVE_FSTATVFS
 -    if (path.fd != -1) {
 -#ifdef __APPLE__
 -        /* handle weak-linking on Mac OS X 10.3 */
 -        if (fstatvfs == NULL) {
 -            fd_specified("statvfs", path.fd);
 -            goto exit;
 -        }
 -#endif
 -        result = fstatvfs(path.fd, &st);
 -    }
 -    else
 -#endif
 -        result = statvfs(path.narrow, &st);
 -    Py_END_ALLOW_THREADS
 -
 -    if (result) {
 -        return_value = path_error(&path);
 -        goto exit;
 -    }
 -
 -    return_value = _pystatvfs_fromstructstatvfs(st);
 -
 -exit:
 -    path_cleanup(&path);
 -    return return_value;
 +    return os_getgroups_impl(module);
  }
 -#endif /* HAVE_STATVFS */
 -
 -#ifdef MS_WINDOWS
 -PyDoc_STRVAR(win32__getdiskusage__doc__,
 -"_getdiskusage(path) -> (total, free)\n\n\
 -Return disk usage statistics about the given path as (total, free) tuple.");
  
  static PyObject *
 -win32__getdiskusage(PyObject *self, PyObject *args)
 +os_getgroups_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=d9a3559b2e6f4ab8 input=d3f109412e6a155c]*/
  {
 -    BOOL retval;
 -    ULARGE_INTEGER _, total, free;
 -    const wchar_t *path;
 +    PyObject *result = NULL;
  
 -    if (! PyArg_ParseTuple(args, "u", &path))
 -        return NULL;
 +#ifdef NGROUPS_MAX
 +#define MAX_GROUPS NGROUPS_MAX
 +#else
 +    /* defined to be 16 on Solaris7, so this should be a small number */
 +#define MAX_GROUPS 64
 +#endif
 +    gid_t grouplist[MAX_GROUPS];
  
 -    Py_BEGIN_ALLOW_THREADS
 -    retval = GetDiskFreeSpaceExW(path, &_, &total, &free);
 -    Py_END_ALLOW_THREADS
 -    if (retval == 0)
 -        return PyErr_SetFromWindowsErr(0);
 -
 -    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
 -}
 -#endif
 -
 -
 -/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
 - * It maps strings representing configuration variable names to
 - * integer values, allowing those functions to be called with the
 - * magic names instead of polluting the module's namespace with tons of
 - * rarely-used constants.  There are three separate tables that use
 - * these definitions.
 - *
 - * This code is always included, even if none of the interfaces that
 - * need it are included.  The #if hackery needed to avoid it would be
 - * sufficiently pervasive that it's not worth the loss of readability.
 - */
 -struct constdef {
 -    char *name;
 -    long value;
 -};
 +    /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
 +     * This is a helper variable to store the intermediate result when
 +     * that happens.
 +     *
 +     * To keep the code readable the OSX behaviour is unconditional,
 +     * according to the POSIX spec this should be safe on all unix-y
 +     * systems.
 +     */
 +    gid_t* alt_grouplist = grouplist;
 +    int n;
  
 -static int
 -conv_confname(PyObject *arg, int *valuep, struct constdef *table,
 -              size_t tablesize)
 -{
 -    if (PyLong_Check(arg)) {
 -        *valuep = PyLong_AS_LONG(arg);
 -        return 1;
 +#ifdef __APPLE__
 +    /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
 +     * there are more groups than can fit in grouplist.  Therefore, on OS X
 +     * always first call getgroups with length 0 to get the actual number
 +     * of groups.
 +     */
 +    n = getgroups(0, NULL);
 +    if (n < 0) {
 +        return posix_error();
 +    } else if (n <= MAX_GROUPS) {
 +        /* groups will fit in existing array */
 +        alt_grouplist = grouplist;
 +    } else {
-         alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
++        alt_grouplist = PyMem_New(gid_t, n);
 +        if (alt_grouplist == NULL) {
 +            errno = EINVAL;
 +            return posix_error();
 +        }
      }
 -    else {
 -        /* look up the value in the table using a binary search */
 -        size_t lo = 0;
 -        size_t mid;
 -        size_t hi = tablesize;
 -        int cmp;
 -        const char *confname;
 -        if (!PyUnicode_Check(arg)) {
 -            PyErr_SetString(PyExc_TypeError,
 -                "configuration names must be strings or integers");
 -            return 0;
 +
 +    n = getgroups(n, alt_grouplist);
 +    if (n == -1) {
 +        if (alt_grouplist != grouplist) {
 +            PyMem_Free(alt_grouplist);
          }
 -        confname = _PyUnicode_AsString(arg);
 -        if (confname == NULL)
 -            return 0;
 -        while (lo < hi) {
 -            mid = (lo + hi) / 2;
 -            cmp = strcmp(confname, table[mid].name);
 -            if (cmp < 0)
 -                hi = mid;
 -            else if (cmp > 0)
 -                lo = mid + 1;
 -            else {
 -                *valuep = table[mid].value;
 -                return 1;
 +        return posix_error();
 +    }
 +#else
 +    n = getgroups(MAX_GROUPS, grouplist);
 +    if (n < 0) {
 +        if (errno == EINVAL) {
 +            n = getgroups(0, NULL);
 +            if (n == -1) {
 +                return posix_error();
 +            }
 +            if (n == 0) {
 +                /* Avoid malloc(0) */
 +                alt_grouplist = grouplist;
 +            } else {
-                 alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
++                alt_grouplist = PyMem_New(gid_t, n);
 +                if (alt_grouplist == NULL) {
 +                    errno = EINVAL;
 +                    return posix_error();
 +                }
 +                n = getgroups(n, alt_grouplist);
 +                if (n == -1) {
 +                    PyMem_Free(alt_grouplist);
 +                    return posix_error();
 +                }
              }
 +        } else {
 +            return posix_error();
          }
 -        PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
 -        return 0;
      }
 -}
 -
 -
 -#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
 -static struct constdef  posix_constants_pathconf[] = {
 -#ifdef _PC_ABI_AIO_XFER_MAX
 -    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
 -#endif
 -#ifdef _PC_ABI_ASYNC_IO
 -    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
 -#endif
 -#ifdef _PC_ASYNC_IO
 -    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
 -#endif
 -#ifdef _PC_CHOWN_RESTRICTED
 -    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
 -#endif
 -#ifdef _PC_FILESIZEBITS
 -    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
 -#endif
 -#ifdef _PC_LAST
 -    {"PC_LAST", _PC_LAST},
 -#endif
 -#ifdef _PC_LINK_MAX
 -    {"PC_LINK_MAX",     _PC_LINK_MAX},
 -#endif
 -#ifdef _PC_MAX_CANON
 -    {"PC_MAX_CANON",    _PC_MAX_CANON},
 -#endif
 -#ifdef _PC_MAX_INPUT
 -    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
 -#endif
 -#ifdef _PC_NAME_MAX
 -    {"PC_NAME_MAX",     _PC_NAME_MAX},
 -#endif
 -#ifdef _PC_NO_TRUNC
 -    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
 -#endif
 -#ifdef _PC_PATH_MAX
 -    {"PC_PATH_MAX",     _PC_PATH_MAX},
 -#endif
 -#ifdef _PC_PIPE_BUF
 -    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
 -#endif
 -#ifdef _PC_PRIO_IO
 -    {"PC_PRIO_IO",      _PC_PRIO_IO},
 -#endif
 -#ifdef _PC_SOCK_MAXBUF
 -    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
 -#endif
 -#ifdef _PC_SYNC_IO
 -    {"PC_SYNC_IO",      _PC_SYNC_IO},
 -#endif
 -#ifdef _PC_VDISABLE
 -    {"PC_VDISABLE",     _PC_VDISABLE},
 -#endif
 -#ifdef _PC_ACL_ENABLED
 -    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
 -#endif
 -#ifdef _PC_MIN_HOLE_SIZE
 -    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
 -#endif
 -#ifdef _PC_ALLOC_SIZE_MIN
 -    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
 -#endif
 -#ifdef _PC_REC_INCR_XFER_SIZE
 -    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
 -#endif
 -#ifdef _PC_REC_MAX_XFER_SIZE
 -    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
 -#endif
 -#ifdef _PC_REC_MIN_XFER_SIZE
 -    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
 -#endif
 -#ifdef _PC_REC_XFER_ALIGN
 -    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
 -#endif
 -#ifdef _PC_SYMLINK_MAX
 -    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
 -#endif
 -#ifdef _PC_XATTR_ENABLED
 -    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
 -#endif
 -#ifdef _PC_XATTR_EXISTS
 -    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
 -#endif
 -#ifdef _PC_TIMESTAMP_RESOLUTION
 -    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
 -#endif
 -};
 -
 -static int
 -conv_path_confname(PyObject *arg, int *valuep)
 -{
 -    return conv_confname(arg, valuep, posix_constants_pathconf,
 -                         sizeof(posix_constants_pathconf)
 -                           / sizeof(struct constdef));
 -}
  #endif
  
 -#ifdef HAVE_FPATHCONF
 -PyDoc_STRVAR(posix_fpathconf__doc__,
 -"fpathconf(fd, name) -> integer\n\n\
 -Return the configuration limit name for the file descriptor fd.\n\
 -If there is no limit, return -1.");
 -
 -static PyObject *
 -posix_fpathconf(PyObject *self, PyObject *args)
 -{
 -    PyObject *result = NULL;
 -    int name, fd;
 -
 -    if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
 -                         conv_path_confname, &name)) {
 -        long limit;
 +    result = PyList_New(n);
 +    if (result != NULL) {
 +        int i;
 +        for (i = 0; i < n; ++i) {
 +            PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
 +            if (o == NULL) {
 +                Py_DECREF(result);
 +                result = NULL;
 +                break;
 +            }
 +            PyList_SET_ITEM(result, i, o);
 +        }
 +    }
  
 -        errno = 0;
 -        limit = fpathconf(fd, name);
 -        if (limit == -1 && errno != 0)
 -            posix_error();
 -        else
 -            result = PyLong_FromLong(limit);
 +    if (alt_grouplist != grouplist) {
 +        PyMem_Free(alt_grouplist);
      }
 +
      return result;
  }
 -#endif
 +#endif /* HAVE_GETGROUPS */
  
 +#ifdef HAVE_INITGROUPS
 +PyDoc_STRVAR(posix_initgroups__doc__,
 +"initgroups(username, gid) -> None\n\n\
 +Call the system initgroups() to initialize the group access list with all of\n\
 +the groups of which the specified username is a member, plus the specified\n\
 +group id.");
  
 -#ifdef HAVE_PATHCONF
 -PyDoc_STRVAR(posix_pathconf__doc__,
 -"pathconf(path, name) -> integer\n\n\
 -Return the configuration limit name for the file or directory path.\n\
 -If there is no limit, return -1.\n\
 -On some platforms, path may also be specified as an open file descriptor.\n\
 -  If this functionality is unavailable, using it raises an exception.");
 -
 +/* AC 3.5: funny apple logic */
  static PyObject *
 -posix_pathconf(PyObject *self, PyObject *args, PyObject *kwargs)
 +posix_initgroups(PyObject *self, PyObject *args)
  {
 -    path_t path;
 -    PyObject *result = NULL;
 -    int name;
 -    static char *keywords[] = {"path", "name", NULL};
 -
 -    memset(&path, 0, sizeof(path));
 -    path.function_name = "pathconf";
 -#ifdef HAVE_FPATHCONF
 -    path.allow_fd = 1;
 +    PyObject *oname;
 +    char *username;
 +    int res;
 +#ifdef __APPLE__
 +    int gid;
 +#else
 +    gid_t gid;
  #endif
 -    if (PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:pathconf", keywords,
 -                                    path_converter, &path,
 -                                    conv_path_confname, &name)) {
 -    long limit;
  
 -    errno = 0;
 -#ifdef HAVE_FPATHCONF
 -    if (path.fd != -1)
 -        limit = fpathconf(path.fd, name);
 -    else
 -#endif
 -        limit = pathconf(path.narrow, name);
 -    if (limit == -1 && errno != 0) {
 -        if (errno == EINVAL)
 -            /* could be a path or name problem */
 -            posix_error();
 -        else
 -            result = path_error(&path);
 -    }
 -    else
 -        result = PyLong_FromLong(limit);
 -    }
 -    path_cleanup(&path);
 -    return result;
 -}
 +#ifdef __APPLE__
 +    if (!PyArg_ParseTuple(args, "O&i:initgroups",
 +                          PyUnicode_FSConverter, &oname,
 +                          &gid))
 +#else
 +    if (!PyArg_ParseTuple(args, "O&O&:initgroups",
 +                          PyUnicode_FSConverter, &oname,
 +                          _Py_Gid_Converter, &gid))
  #endif
 +        return NULL;
 +    username = PyBytes_AS_STRING(oname);
  
 -#ifdef HAVE_CONFSTR
 -static struct constdef posix_constants_confstr[] = {
 -#ifdef _CS_ARCHITECTURE
 -    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
 -#endif
 -#ifdef _CS_GNU_LIBC_VERSION
 -    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
 -#endif
 -#ifdef _CS_GNU_LIBPTHREAD_VERSION
 -    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
 -#endif
 -#ifdef _CS_HOSTNAME
 -    {"CS_HOSTNAME",     _CS_HOSTNAME},
 -#endif
 -#ifdef _CS_HW_PROVIDER
 -    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
 -#endif
 -#ifdef _CS_HW_SERIAL
 -    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
 -#endif
 -#ifdef _CS_INITTAB_NAME
 -    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
 -#endif
 -#ifdef _CS_LFS64_CFLAGS
 -    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
 -#endif
 -#ifdef _CS_LFS64_LDFLAGS
 -    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
 -#endif
 -#ifdef _CS_LFS64_LIBS
 -    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
 -#endif
 -#ifdef _CS_LFS64_LINTFLAGS
 -    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
 -#endif
 -#ifdef _CS_LFS_CFLAGS
 -    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
 -#endif
 -#ifdef _CS_LFS_LDFLAGS
 -    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
 -#endif
 -#ifdef _CS_LFS_LIBS
 -    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
 -#endif
 -#ifdef _CS_LFS_LINTFLAGS
 -    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
 -#endif
 -#ifdef _CS_MACHINE
 -    {"CS_MACHINE",      _CS_MACHINE},
 -#endif
 -#ifdef _CS_PATH
 -    {"CS_PATH", _CS_PATH},
 -#endif
 -#ifdef _CS_RELEASE
 -    {"CS_RELEASE",      _CS_RELEASE},
 -#endif
 -#ifdef _CS_SRPC_DOMAIN
 -    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
 -#endif
 -#ifdef _CS_SYSNAME
 -    {"CS_SYSNAME",      _CS_SYSNAME},
 -#endif
 -#ifdef _CS_VERSION
 -    {"CS_VERSION",      _CS_VERSION},
 -#endif
 -#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
 -    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
 -#endif
 -#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
 -    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
 -#endif
 -#ifdef _CS_XBS5_ILP32_OFF32_LIBS
 -    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
 -#endif
 -#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
 -    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
 -#endif
 -#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
 -    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
 -#endif
 -#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
 -    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
 -#endif
 -#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
 -    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
 -#endif
 -#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
 -    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
 -#endif
 -#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
 -    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
 -#endif
 -#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
 -    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
 -#endif
 -#ifdef _CS_XBS5_LP64_OFF64_LIBS
 -    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
 -#endif
 -#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
 -    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
 -#endif
 -#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
 -    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
 -#endif
 -#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
 -    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
 -#endif
 -#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
 -    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
 -#endif
 -#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
 -    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
 -#endif
 -#ifdef _MIPS_CS_AVAIL_PROCESSORS
 -    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
 -#endif
 -#ifdef _MIPS_CS_BASE
 -    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
 -#endif
 -#ifdef _MIPS_CS_HOSTID
 -    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
 -#endif
 -#ifdef _MIPS_CS_HW_NAME
 -    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
 -#endif
 -#ifdef _MIPS_CS_NUM_PROCESSORS
 -    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
 -#endif
 -#ifdef _MIPS_CS_OSREL_MAJ
 -    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
 -#endif
 -#ifdef _MIPS_CS_OSREL_MIN
 -    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
 -#endif
 -#ifdef _MIPS_CS_OSREL_PATCH
 -    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
 -#endif
 -#ifdef _MIPS_CS_OS_NAME
 -    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
 -#endif
 -#ifdef _MIPS_CS_OS_PROVIDER
 -    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
 -#endif
 -#ifdef _MIPS_CS_PROCESSORS
 -    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
 -#endif
 -#ifdef _MIPS_CS_SERIAL
 -    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
 -#endif
 -#ifdef _MIPS_CS_VENDOR
 -    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
 -#endif
 -};
 +    res = initgroups(username, gid);
 +    Py_DECREF(oname);
 +    if (res == -1)
 +        return PyErr_SetFromErrno(PyExc_OSError);
  
 -static int
 -conv_confstr_confname(PyObject *arg, int *valuep)
 -{
 -    return conv_confname(arg, valuep, posix_constants_confstr,
 -                         sizeof(posix_constants_confstr)
 -                           / sizeof(struct constdef));
 +    Py_INCREF(Py_None);
 +    return Py_None;
  }
 +#endif /* HAVE_INITGROUPS */
 +
 +
 +#ifdef HAVE_GETPGID
 +/*[clinic input]
 +os.getpgid
 +
 +    pid: pid_t
 +
 +Call the system call getpgid(), and return the result.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_getpgid__doc__,
 +"getpgid($module, /, pid)\n"
 +"--\n"
 +"\n"
 +"Call the system call getpgid(), and return the result.");
  
 -PyDoc_STRVAR(posix_confstr__doc__,
 -"confstr(name) -> string\n\n\
 -Return a string-valued system configuration variable.");
 +#define OS_GETPGID_METHODDEF    \
 +    {"getpgid", (PyCFunction)os_getpgid, METH_VARARGS|METH_KEYWORDS, os_getpgid__doc__},
 +
 +static PyObject *
 +os_getpgid_impl(PyModuleDef *module, pid_t pid);
  
  static PyObject *
 -posix_confstr(PyObject *self, PyObject *args)
 +os_getpgid(PyModuleDef *module, PyObject *args, PyObject *kwargs)
  {
 -    PyObject *result = NULL;
 -    int name;
 -    char buffer[255];
 -    size_t len;
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"pid", NULL};
 +    pid_t pid;
  
 -    if (!PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name))
 -        return NULL;
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "" _Py_PARSE_PID ":getpgid", _keywords,
 +        &pid))
 +        goto exit;
 +    return_value = os_getpgid_impl(module, pid);
  
 -    errno = 0;
 -    len = confstr(name, buffer, sizeof(buffer));
 -    if (len == 0) {
 -        if (errno) {
 -            posix_error();
 -            return NULL;
 -        }
 -        else {
 -            Py_RETURN_NONE;
 -        }
 -    }
 +exit:
 +    return return_value;
 +}
  
 -    if (len >= sizeof(buffer)) {
 -        char *buf = PyMem_Malloc(len);
 -        if (buf == NULL)
 -            return PyErr_NoMemory();
 -        confstr(name, buf, len);
 -        result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1);
 -        PyMem_Free(buf);
 -    }
 -    else
 -        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
 -    return result;
 +static PyObject *
 +os_getpgid_impl(PyModuleDef *module, pid_t pid)
 +/*[clinic end generated code: output=3db4ed686179160d input=39d710ae3baaf1c7]*/
 +{
 +    pid_t pgid = getpgid(pid);
 +    if (pgid < 0)
 +        return posix_error();
 +    return PyLong_FromPid(pgid);
  }
 -#endif
 +#endif /* HAVE_GETPGID */
  
  
 -#ifdef HAVE_SYSCONF
 -static struct constdef posix_constants_sysconf[] = {
 -#ifdef _SC_2_CHAR_TERM
 -    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
 -#endif
 -#ifdef _SC_2_C_BIND
 -    {"SC_2_C_BIND",     _SC_2_C_BIND},
 -#endif
 -#ifdef _SC_2_C_DEV
 -    {"SC_2_C_DEV",      _SC_2_C_DEV},
 -#endif
 -#ifdef _SC_2_C_VERSION
 -    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
 -#endif
 -#ifdef _SC_2_FORT_DEV
 -    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
 -#endif
 -#ifdef _SC_2_FORT_RUN
 -    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
 -#endif
 -#ifdef _SC_2_LOCALEDEF
 -    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
 -#endif
 -#ifdef _SC_2_SW_DEV
 -    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
 -#endif
 -#ifdef _SC_2_UPE
 -    {"SC_2_UPE",        _SC_2_UPE},
 -#endif
 -#ifdef _SC_2_VERSION
 -    {"SC_2_VERSION",    _SC_2_VERSION},
 -#endif
 -#ifdef _SC_ABI_ASYNCHRONOUS_IO
 -    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
 -#endif
 -#ifdef _SC_ACL
 -    {"SC_ACL",  _SC_ACL},
 -#endif
 -#ifdef _SC_AIO_LISTIO_MAX
 -    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
 -#endif
 -#ifdef _SC_AIO_MAX
 -    {"SC_AIO_MAX",      _SC_AIO_MAX},
 -#endif
 -#ifdef _SC_AIO_PRIO_DELTA_MAX
 -    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
 -#endif
 -#ifdef _SC_ARG_MAX
 -    {"SC_ARG_MAX",      _SC_ARG_MAX},
 -#endif
 -#ifdef _SC_ASYNCHRONOUS_IO
 -    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
 -#endif
 -#ifdef _SC_ATEXIT_MAX
 -    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
 -#endif
 -#ifdef _SC_AUDIT
 -    {"SC_AUDIT",        _SC_AUDIT},
 -#endif
 -#ifdef _SC_AVPHYS_PAGES
 -    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
 -#endif
 -#ifdef _SC_BC_BASE_MAX
 -    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
 -#endif
 -#ifdef _SC_BC_DIM_MAX
 -    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
 -#endif
 -#ifdef _SC_BC_SCALE_MAX
 -    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
 -#endif
 -#ifdef _SC_BC_STRING_MAX
 -    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
 -#endif
 -#ifdef _SC_CAP
 -    {"SC_CAP",  _SC_CAP},
 -#endif
 -#ifdef _SC_CHARCLASS_NAME_MAX
 -    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
 -#endif
 -#ifdef _SC_CHAR_BIT
 -    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
 -#endif
 -#ifdef _SC_CHAR_MAX
 -    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
 -#endif
 -#ifdef _SC_CHAR_MIN
 -    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
 +#ifdef HAVE_GETPGRP
 +/*[clinic input]
 +os.getpgrp
 +
 +Return the current process group id.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_getpgrp__doc__,
 +"getpgrp($module, /)\n"
 +"--\n"
 +"\n"
 +"Return the current process group id.");
 +
 +#define OS_GETPGRP_METHODDEF    \
 +    {"getpgrp", (PyCFunction)os_getpgrp, METH_NOARGS, os_getpgrp__doc__},
 +
 +static PyObject *
 +os_getpgrp_impl(PyModuleDef *module);
 +
 +static PyObject *
 +os_getpgrp(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_getpgrp_impl(module);
 +}
 +
 +static PyObject *
 +os_getpgrp_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=3b0d3663ea054277 input=6846fb2bb9a3705e]*/
 +{
 +#ifdef GETPGRP_HAVE_ARG
 +    return PyLong_FromPid(getpgrp(0));
 +#else /* GETPGRP_HAVE_ARG */
 +    return PyLong_FromPid(getpgrp());
 +#endif /* GETPGRP_HAVE_ARG */
 +}
 +#endif /* HAVE_GETPGRP */
 +
 +
 +#ifdef HAVE_SETPGRP
 +/*[clinic input]
 +os.setpgrp
 +
 +Make the current process the leader of its process group.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_setpgrp__doc__,
 +"setpgrp($module, /)\n"
 +"--\n"
 +"\n"
 +"Make the current process the leader of its process group.");
 +
 +#define OS_SETPGRP_METHODDEF    \
 +    {"setpgrp", (PyCFunction)os_setpgrp, METH_NOARGS, os_setpgrp__doc__},
 +
 +static PyObject *
 +os_setpgrp_impl(PyModuleDef *module);
 +
 +static PyObject *
 +os_setpgrp(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_setpgrp_impl(module);
 +}
 +
 +static PyObject *
 +os_setpgrp_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=8fbb0ee29ef6fb2d input=1f0619fcb5731e7e]*/
 +{
 +#ifdef SETPGRP_HAVE_ARG
 +    if (setpgrp(0, 0) < 0)
 +#else /* SETPGRP_HAVE_ARG */
 +    if (setpgrp() < 0)
 +#endif /* SETPGRP_HAVE_ARG */
 +        return posix_error();
 +    Py_INCREF(Py_None);
 +    return Py_None;
 +}
 +#endif /* HAVE_SETPGRP */
 +
 +#ifdef HAVE_GETPPID
 +
 +#ifdef MS_WINDOWS
 +#include <tlhelp32.h>
 +
 +static PyObject*
 +win32_getppid()
 +{
 +    HANDLE snapshot;
 +    pid_t mypid;
 +    PyObject* result = NULL;
 +    BOOL have_record;
 +    PROCESSENTRY32 pe;
 +
 +    mypid = getpid(); /* This function never fails */
 +
 +    snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 +    if (snapshot == INVALID_HANDLE_VALUE)
 +        return PyErr_SetFromWindowsErr(GetLastError());
 +
 +    pe.dwSize = sizeof(pe);
 +    have_record = Process32First(snapshot, &pe);
 +    while (have_record) {
 +        if (mypid == (pid_t)pe.th32ProcessID) {
 +            /* We could cache the ulong value in a static variable. */
 +            result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
 +            break;
 +        }
 +
 +        have_record = Process32Next(snapshot, &pe);
 +    }
 +
 +    /* If our loop exits and our pid was not found (result will be NULL)
 +     * then GetLastError will return ERROR_NO_MORE_FILES. This is an
 +     * error anyway, so let's raise it. */
 +    if (!result)
 +        result = PyErr_SetFromWindowsErr(GetLastError());
 +
 +    CloseHandle(snapshot);
 +
 +    return result;
 +}
 +#endif /*MS_WINDOWS*/
 +
 +
 +/*[clinic input]
 +os.getppid
 +
 +Return the parent's process id.
 +
 +If the parent process has already exited, Windows machines will still
 +return its id; others systems will return the id of the 'init' process (1).
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_getppid__doc__,
 +"getppid($module, /)\n"
 +"--\n"
 +"\n"
 +"Return the parent\'s process id.\n"
 +"\n"
 +"If the parent process has already exited, Windows machines will still\n"
 +"return its id; others systems will return the id of the \'init\' process (1).");
 +
 +#define OS_GETPPID_METHODDEF    \
 +    {"getppid", (PyCFunction)os_getppid, METH_NOARGS, os_getppid__doc__},
 +
 +static PyObject *
 +os_getppid_impl(PyModuleDef *module);
 +
 +static PyObject *
 +os_getppid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_getppid_impl(module);
 +}
 +
 +static PyObject *
 +os_getppid_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=9ff3b387781edf3a input=e637cb87539c030e]*/
 +{
 +#ifdef MS_WINDOWS
 +    return win32_getppid();
 +#else
 +    return PyLong_FromPid(getppid());
  #endif
 -#ifdef _SC_CHILD_MAX
 -    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
 +}
 +#endif /* HAVE_GETPPID */
 +
 +
 +#ifdef HAVE_GETLOGIN
 +/*[clinic input]
 +os.getlogin
 +
 +Return the actual login name.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_getlogin__doc__,
 +"getlogin($module, /)\n"
 +"--\n"
 +"\n"
 +"Return the actual login name.");
 +
 +#define OS_GETLOGIN_METHODDEF    \
 +    {"getlogin", (PyCFunction)os_getlogin, METH_NOARGS, os_getlogin__doc__},
 +
 +static PyObject *
 +os_getlogin_impl(PyModuleDef *module);
 +
 +static PyObject *
 +os_getlogin(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_getlogin_impl(module);
 +}
 +
 +static PyObject *
 +os_getlogin_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=ab6211dab104cbb2 input=2a21ab1e917163df]*/
 +{
 +    PyObject *result = NULL;
 +#ifdef MS_WINDOWS
 +    wchar_t user_name[UNLEN + 1];
 +    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
 +
 +    if (GetUserNameW(user_name, &num_chars)) {
 +        /* num_chars is the number of unicode chars plus null terminator */
 +        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
 +    }
 +    else
 +        result = PyErr_SetFromWindowsErr(GetLastError());
 +#else
 +    char *name;
 +    int old_errno = errno;
 +
 +    errno = 0;
 +    name = getlogin();
 +    if (name == NULL) {
 +        if (errno)
 +            posix_error();
 +        else
 +            PyErr_SetString(PyExc_OSError, "unable to determine login name");
 +    }
 +    else
 +        result = PyUnicode_DecodeFSDefault(name);
 +    errno = old_errno;
  #endif
 -#ifdef _SC_CLK_TCK
 -    {"SC_CLK_TCK",      _SC_CLK_TCK},
 -#endif
 -#ifdef _SC_COHER_BLKSZ
 -    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
 -#endif
 -#ifdef _SC_COLL_WEIGHTS_MAX
 -    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
 -#endif
 -#ifdef _SC_DCACHE_ASSOC
 -    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
 -#endif
 -#ifdef _SC_DCACHE_BLKSZ
 -    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
 -#endif
 -#ifdef _SC_DCACHE_LINESZ
 -    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
 -#endif
 -#ifdef _SC_DCACHE_SZ
 -    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
 -#endif
 -#ifdef _SC_DCACHE_TBLKSZ
 -    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
 -#endif
 -#ifdef _SC_DELAYTIMER_MAX
 -    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
 -#endif
 -#ifdef _SC_EQUIV_CLASS_MAX
 -    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
 -#endif
 -#ifdef _SC_EXPR_NEST_MAX
 -    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
 -#endif
 -#ifdef _SC_FSYNC
 -    {"SC_FSYNC",        _SC_FSYNC},
 -#endif
 -#ifdef _SC_GETGR_R_SIZE_MAX
 -    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
 -#endif
 -#ifdef _SC_GETPW_R_SIZE_MAX
 -    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
 -#endif
 -#ifdef _SC_ICACHE_ASSOC
 -    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
 -#endif
 -#ifdef _SC_ICACHE_BLKSZ
 -    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
 -#endif
 -#ifdef _SC_ICACHE_LINESZ
 -    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
 -#endif
 -#ifdef _SC_ICACHE_SZ
 -    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
 -#endif
 -#ifdef _SC_INF
 -    {"SC_INF",  _SC_INF},
 -#endif
 -#ifdef _SC_INT_MAX
 -    {"SC_INT_MAX",      _SC_INT_MAX},
 -#endif
 -#ifdef _SC_INT_MIN
 -    {"SC_INT_MIN",      _SC_INT_MIN},
 -#endif
 -#ifdef _SC_IOV_MAX
 -    {"SC_IOV_MAX",      _SC_IOV_MAX},
 -#endif
 -#ifdef _SC_IP_SECOPTS
 -    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
 -#endif
 -#ifdef _SC_JOB_CONTROL
 -    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
 -#endif
 -#ifdef _SC_KERN_POINTERS
 -    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
 -#endif
 -#ifdef _SC_KERN_SIM
 -    {"SC_KERN_SIM",     _SC_KERN_SIM},
 -#endif
 -#ifdef _SC_LINE_MAX
 -    {"SC_LINE_MAX",     _SC_LINE_MAX},
 -#endif
 -#ifdef _SC_LOGIN_NAME_MAX
 -    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
 -#endif
 -#ifdef _SC_LOGNAME_MAX
 -    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
 -#endif
 -#ifdef _SC_LONG_BIT
 -    {"SC_LONG_BIT",     _SC_LONG_BIT},
 -#endif
 -#ifdef _SC_MAC
 -    {"SC_MAC",  _SC_MAC},
 -#endif
 -#ifdef _SC_MAPPED_FILES
 -    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
 -#endif
 -#ifdef _SC_MAXPID
 -    {"SC_MAXPID",       _SC_MAXPID},
 -#endif
 -#ifdef _SC_MB_LEN_MAX
 -    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
 -#endif
 -#ifdef _SC_MEMLOCK
 -    {"SC_MEMLOCK",      _SC_MEMLOCK},
 -#endif
 -#ifdef _SC_MEMLOCK_RANGE
 -    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
 -#endif
 -#ifdef _SC_MEMORY_PROTECTION
 -    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
 -#endif
 -#ifdef _SC_MESSAGE_PASSING
 -    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
 -#endif
 -#ifdef _SC_MMAP_FIXED_ALIGNMENT
 -    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
 -#endif
 -#ifdef _SC_MQ_OPEN_MAX
 -    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
 +    return result;
 +}
 +#endif /* HAVE_GETLOGIN */
 +
 +
 +#ifdef HAVE_GETUID
 +/*[clinic input]
 +os.getuid
 +
 +Return the current process's user id.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_getuid__doc__,
 +"getuid($module, /)\n"
 +"--\n"
 +"\n"
 +"Return the current process\'s user id.");
 +
 +#define OS_GETUID_METHODDEF    \
 +    {"getuid", (PyCFunction)os_getuid, METH_NOARGS, os_getuid__doc__},
 +
 +static PyObject *
 +os_getuid_impl(PyModuleDef *module);
 +
 +static PyObject *
 +os_getuid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_getuid_impl(module);
 +}
 +
 +static PyObject *
 +os_getuid_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=77e0dcf2e37d1e89 input=b53c8b35f110a516]*/
 +{
 +    return _PyLong_FromUid(getuid());
 +}
 +#endif /* HAVE_GETUID */
 +
 +
 +#ifdef MS_WINDOWS
 +#define HAVE_KILL
 +#endif /* MS_WINDOWS */
 +
 +#ifdef HAVE_KILL
 +/*[clinic input]
 +os.kill
 +
 +    pid: pid_t
 +    signal: Py_ssize_t
 +    /
 +
 +Kill a process with a signal.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_kill__doc__,
 +"kill($module, pid, signal, /)\n"
 +"--\n"
 +"\n"
 +"Kill a process with a signal.");
 +
 +#define OS_KILL_METHODDEF    \
 +    {"kill", (PyCFunction)os_kill, METH_VARARGS, os_kill__doc__},
 +
 +static PyObject *
 +os_kill_impl(PyModuleDef *module, pid_t pid, Py_ssize_t signal);
 +
 +static PyObject *
 +os_kill(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    pid_t pid;
 +    Py_ssize_t signal;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "" _Py_PARSE_PID "n:kill",
 +        &pid, &signal))
 +        goto exit;
 +    return_value = os_kill_impl(module, pid, signal);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_kill_impl(PyModuleDef *module, pid_t pid, Py_ssize_t signal)
 +/*[clinic end generated code: output=2f5c77920ed575e6 input=61a36b86ca275ab9]*/
 +#ifndef MS_WINDOWS
 +{
 +    if (kill(pid, (int)signal) == -1)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +#else /* !MS_WINDOWS */
 +{
 +    PyObject *result;
 +    DWORD sig = (DWORD)signal;
 +    DWORD err;
 +    HANDLE handle;
 +
 +    /* Console processes which share a common console can be sent CTRL+C or
 +       CTRL+BREAK events, provided they handle said events. */
 +    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
 +        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
 +            err = GetLastError();
 +            PyErr_SetFromWindowsErr(err);
 +        }
 +        else
 +            Py_RETURN_NONE;
 +    }
 +
 +    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
 +       attempt to open and terminate the process. */
 +    handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
 +    if (handle == NULL) {
 +        err = GetLastError();
 +        return PyErr_SetFromWindowsErr(err);
 +    }
 +
 +    if (TerminateProcess(handle, sig) == 0) {
 +        err = GetLastError();
 +        result = PyErr_SetFromWindowsErr(err);
 +    } else {
 +        Py_INCREF(Py_None);
 +        result = Py_None;
 +    }
 +
 +    CloseHandle(handle);
 +    return result;
 +}
 +#endif /* !MS_WINDOWS */
 +#endif /* HAVE_KILL */
 +
 +
 +#ifdef HAVE_KILLPG
 +/*[clinic input]
 +os.killpg
 +
 +    pgid: pid_t
 +    signal: int
 +    /
 +
 +Kill a process group with a signal.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_killpg__doc__,
 +"killpg($module, pgid, signal, /)\n"
 +"--\n"
 +"\n"
 +"Kill a process group with a signal.");
 +
 +#define OS_KILLPG_METHODDEF    \
 +    {"killpg", (PyCFunction)os_killpg, METH_VARARGS, os_killpg__doc__},
 +
 +static PyObject *
 +os_killpg_impl(PyModuleDef *module, pid_t pgid, int signal);
 +
 +static PyObject *
 +os_killpg(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    pid_t pgid;
 +    int signal;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "" _Py_PARSE_PID "i:killpg",
 +        &pgid, &signal))
 +        goto exit;
 +    return_value = os_killpg_impl(module, pgid, signal);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_killpg_impl(PyModuleDef *module, pid_t pgid, int signal)
 +/*[clinic end generated code: output=0e05215d1c007e01 input=38b5449eb8faec19]*/
 +{
 +    /* XXX some man pages make the `pgid` parameter an int, others
 +       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
 +       take the same type. Moreover, pid_t is always at least as wide as
 +       int (else compilation of this module fails), which is safe. */
 +    if (killpg(pgid, signal) == -1)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_KILLPG */
 +
 +
 +#ifdef HAVE_PLOCK
 +#ifdef HAVE_SYS_LOCK_H
 +#include <sys/lock.h>
 +#endif
 +
 +/*[clinic input]
 +os.plock
 +    op: int
 +    /
 +
 +Lock program segments into memory.");
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_plock__doc__,
 +"plock($module, op, /)\n"
 +"--\n"
 +"\n"
 +"Lock program segments into memory.\");");
 +
 +#define OS_PLOCK_METHODDEF    \
 +    {"plock", (PyCFunction)os_plock, METH_VARARGS, os_plock__doc__},
 +
 +static PyObject *
 +os_plock_impl(PyModuleDef *module, int op);
 +
 +static PyObject *
 +os_plock(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int op;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "i:plock",
 +        &op))
 +        goto exit;
 +    return_value = os_plock_impl(module, op);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_plock_impl(PyModuleDef *module, int op)
 +/*[clinic end generated code: output=2744fe4b6e5f4dbc input=e6e5e348e1525f60]*/
 +{
 +    if (plock(op) == -1)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_PLOCK */
 +
 +
 +#ifdef HAVE_SETUID
 +/*[clinic input]
 +os.setuid
 +
 +    uid: uid_t
 +    /
 +
 +Set the current process's user id.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_setuid__doc__,
 +"setuid($module, uid, /)\n"
 +"--\n"
 +"\n"
 +"Set the current process\'s user id.");
 +
 +#define OS_SETUID_METHODDEF    \
 +    {"setuid", (PyCFunction)os_setuid, METH_VARARGS, os_setuid__doc__},
 +
 +static PyObject *
 +os_setuid_impl(PyModuleDef *module, uid_t uid);
 +
 +static PyObject *
 +os_setuid(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    uid_t uid;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "O&:setuid",
 +        _Py_Uid_Converter, &uid))
 +        goto exit;
 +    return_value = os_setuid_impl(module, uid);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_setuid_impl(PyModuleDef *module, uid_t uid)
 +/*[clinic end generated code: output=aea344bc22ccf400 input=c921a3285aa22256]*/
 +{
 +    if (setuid(uid) < 0)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_SETUID */
 +
 +
 +#ifdef HAVE_SETEUID
 +/*[clinic input]
 +os.seteuid
 +
 +    euid: uid_t
 +    /
 +
 +Set the current process's effective user id.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_seteuid__doc__,
 +"seteuid($module, euid, /)\n"
 +"--\n"
 +"\n"
 +"Set the current process\'s effective user id.");
 +
 +#define OS_SETEUID_METHODDEF    \
 +    {"seteuid", (PyCFunction)os_seteuid, METH_VARARGS, os_seteuid__doc__},
 +
 +static PyObject *
 +os_seteuid_impl(PyModuleDef *module, uid_t euid);
 +
 +static PyObject *
 +os_seteuid(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    uid_t euid;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "O&:seteuid",
 +        _Py_Uid_Converter, &euid))
 +        goto exit;
 +    return_value = os_seteuid_impl(module, euid);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_seteuid_impl(PyModuleDef *module, uid_t euid)
 +/*[clinic end generated code: output=6e824cce4f3b8a5d input=ba93d927e4781aa9]*/
 +{
 +    if (seteuid(euid) < 0)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_SETEUID */
 +
 +
 +#ifdef HAVE_SETEGID
 +/*[clinic input]
 +os.setegid
 +
 +    egid: gid_t
 +    /
 +
 +Set the current process's effective group id.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_setegid__doc__,
 +"setegid($module, egid, /)\n"
 +"--\n"
 +"\n"
 +"Set the current process\'s effective group id.");
 +
 +#define OS_SETEGID_METHODDEF    \
 +    {"setegid", (PyCFunction)os_setegid, METH_VARARGS, os_setegid__doc__},
 +
 +static PyObject *
 +os_setegid_impl(PyModuleDef *module, gid_t egid);
 +
 +static PyObject *
 +os_setegid(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    gid_t egid;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "O&:setegid",
 +        _Py_Gid_Converter, &egid))
 +        goto exit;
 +    return_value = os_setegid_impl(module, egid);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_setegid_impl(PyModuleDef *module, gid_t egid)
 +/*[clinic end generated code: output=80a32263a4d56a9c input=4080526d0ccd6ce3]*/
 +{
 +    if (setegid(egid) < 0)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_SETEGID */
 +
 +
 +#ifdef HAVE_SETREUID
 +/*[clinic input]
 +os.setreuid
 +
 +    ruid: uid_t
 +    euid: uid_t
 +    /
 +
 +Set the current process's real and effective user ids.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_setreuid__doc__,
 +"setreuid($module, ruid, euid, /)\n"
 +"--\n"
 +"\n"
 +"Set the current process\'s real and effective user ids.");
 +
 +#define OS_SETREUID_METHODDEF    \
 +    {"setreuid", (PyCFunction)os_setreuid, METH_VARARGS, os_setreuid__doc__},
 +
 +static PyObject *
 +os_setreuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid);
 +
 +static PyObject *
 +os_setreuid(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    uid_t ruid;
 +    uid_t euid;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "O&O&:setreuid",
 +        _Py_Uid_Converter, &ruid, _Py_Uid_Converter, &euid))
 +        goto exit;
 +    return_value = os_setreuid_impl(module, ruid, euid);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_setreuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid)
 +/*[clinic end generated code: output=d7f226f943dad739 input=0ca8978de663880c]*/
 +{
 +    if (setreuid(ruid, euid) < 0) {
 +        return posix_error();
 +    } else {
 +        Py_INCREF(Py_None);
 +        return Py_None;
 +    }
 +}
 +#endif /* HAVE_SETREUID */
 +
 +
 +#ifdef HAVE_SETREGID
 +/*[clinic input]
 +os.setregid
 +
 +    rgid: gid_t
 +    egid: gid_t
 +    /
 +
 +Set the current process's real and effective group ids.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_setregid__doc__,
 +"setregid($module, rgid, egid, /)\n"
 +"--\n"
 +"\n"
 +"Set the current process\'s real and effective group ids.");
 +
 +#define OS_SETREGID_METHODDEF    \
 +    {"setregid", (PyCFunction)os_setregid, METH_VARARGS, os_setregid__doc__},
 +
 +static PyObject *
 +os_setregid_impl(PyModuleDef *module, gid_t rgid, gid_t egid);
 +
 +static PyObject *
 +os_setregid(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    gid_t rgid;
 +    gid_t egid;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "O&O&:setregid",
 +        _Py_Gid_Converter, &rgid, _Py_Gid_Converter, &egid))
 +        goto exit;
 +    return_value = os_setregid_impl(module, rgid, egid);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_setregid_impl(PyModuleDef *module, gid_t rgid, gid_t egid)
 +/*[clinic end generated code: output=a82d9ab70f8e6562 input=c59499f72846db78]*/
 +{
 +    if (setregid(rgid, egid) < 0)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_SETREGID */
 +
 +
 +#ifdef HAVE_SETGID
 +/*[clinic input]
 +os.setgid
 +    gid: gid_t
 +    /
 +
 +Set the current process's group id.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_setgid__doc__,
 +"setgid($module, gid, /)\n"
 +"--\n"
 +"\n"
 +"Set the current process\'s group id.");
 +
 +#define OS_SETGID_METHODDEF    \
 +    {"setgid", (PyCFunction)os_setgid, METH_VARARGS, os_setgid__doc__},
 +
 +static PyObject *
 +os_setgid_impl(PyModuleDef *module, gid_t gid);
 +
 +static PyObject *
 +os_setgid(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    gid_t gid;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "O&:setgid",
 +        _Py_Gid_Converter, &gid))
 +        goto exit;
 +    return_value = os_setgid_impl(module, gid);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_setgid_impl(PyModuleDef *module, gid_t gid)
 +/*[clinic end generated code: output=08287886db435f23 input=27d30c4059045dc6]*/
 +{
 +    if (setgid(gid) < 0)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_SETGID */
 +
 +
 +#ifdef HAVE_SETGROUPS
 +/*[clinic input]
 +os.setgroups
 +
 +    groups: object
 +    /
 +
 +Set the groups of the current process to list.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_setgroups__doc__,
 +"setgroups($module, groups, /)\n"
 +"--\n"
 +"\n"
 +"Set the groups of the current process to list.");
 +
 +#define OS_SETGROUPS_METHODDEF    \
 +    {"setgroups", (PyCFunction)os_setgroups, METH_O, os_setgroups__doc__},
 +
 +static PyObject *
 +os_setgroups(PyModuleDef *module, PyObject *groups)
 +/*[clinic end generated code: output=0b8de65d5b3cda94 input=fa742ca3daf85a7e]*/
 +{
 +    int i, len;
 +    gid_t grouplist[MAX_GROUPS];
 +
 +    if (!PySequence_Check(groups)) {
 +        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
 +        return NULL;
 +    }
 +    len = PySequence_Size(groups);
 +    if (len > MAX_GROUPS) {
 +        PyErr_SetString(PyExc_ValueError, "too many groups");
 +        return NULL;
 +    }
 +    for(i = 0; i < len; i++) {
 +        PyObject *elem;
 +        elem = PySequence_GetItem(groups, i);
 +        if (!elem)
 +            return NULL;
 +        if (!PyLong_Check(elem)) {
 +            PyErr_SetString(PyExc_TypeError,
 +                            "groups must be integers");
 +            Py_DECREF(elem);
 +            return NULL;
 +        } else {
 +            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
 +                Py_DECREF(elem);
 +                return NULL;
 +            }
 +        }
 +        Py_DECREF(elem);
 +    }
 +
 +    if (setgroups(len, grouplist) < 0)
 +        return posix_error();
 +    Py_INCREF(Py_None);
 +    return Py_None;
 +}
 +#endif /* HAVE_SETGROUPS */
 +
 +#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
 +static PyObject *
 +wait_helper(pid_t pid, int status, struct rusage *ru)
 +{
 +    PyObject *result;
 +    static PyObject *struct_rusage;
 +    _Py_IDENTIFIER(struct_rusage);
 +
 +    if (pid == -1)
 +        return posix_error();
 +
 +    if (struct_rusage == NULL) {
 +        PyObject *m = PyImport_ImportModuleNoBlock("resource");
 +        if (m == NULL)
 +            return NULL;
 +        struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage);
 +        Py_DECREF(m);
 +        if (struct_rusage == NULL)
 +            return NULL;
 +    }
 +
 +    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
 +    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
 +    if (!result)
 +        return NULL;
 +
 +#ifndef doubletime
 +#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
 +#endif
 +
 +    PyStructSequence_SET_ITEM(result, 0,
 +                              PyFloat_FromDouble(doubletime(ru->ru_utime)));
 +    PyStructSequence_SET_ITEM(result, 1,
 +                              PyFloat_FromDouble(doubletime(ru->ru_stime)));
 +#define SET_INT(result, index, value)\
 +        PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
 +    SET_INT(result, 2, ru->ru_maxrss);
 +    SET_INT(result, 3, ru->ru_ixrss);
 +    SET_INT(result, 4, ru->ru_idrss);
 +    SET_INT(result, 5, ru->ru_isrss);
 +    SET_INT(result, 6, ru->ru_minflt);
 +    SET_INT(result, 7, ru->ru_majflt);
 +    SET_INT(result, 8, ru->ru_nswap);
 +    SET_INT(result, 9, ru->ru_inblock);
 +    SET_INT(result, 10, ru->ru_oublock);
 +    SET_INT(result, 11, ru->ru_msgsnd);
 +    SET_INT(result, 12, ru->ru_msgrcv);
 +    SET_INT(result, 13, ru->ru_nsignals);
 +    SET_INT(result, 14, ru->ru_nvcsw);
 +    SET_INT(result, 15, ru->ru_nivcsw);
 +#undef SET_INT
 +
 +    if (PyErr_Occurred()) {
 +        Py_DECREF(result);
 +        return NULL;
 +    }
 +
 +    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
 +}
 +#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
 +
 +
 +#ifdef HAVE_WAIT3
 +/*[clinic input]
 +os.wait3
 +
 +    options: int
 +Wait for completion of a child process.
 +
 +Returns a tuple of information about the child process:
 +  (pid, status, rusage)
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_wait3__doc__,
 +"wait3($module, /, options)\n"
 +"--\n"
 +"\n"
 +"Wait for completion of a child process.\n"
 +"\n"
 +"Returns a tuple of information about the child process:\n"
 +"  (pid, status, rusage)");
 +
 +#define OS_WAIT3_METHODDEF    \
 +    {"wait3", (PyCFunction)os_wait3, METH_VARARGS|METH_KEYWORDS, os_wait3__doc__},
 +
 +static PyObject *
 +os_wait3_impl(PyModuleDef *module, int options);
 +
 +static PyObject *
 +os_wait3(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"options", NULL};
 +    int options;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "i:wait3", _keywords,
 +        &options))
 +        goto exit;
 +    return_value = os_wait3_impl(module, options);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_wait3_impl(PyModuleDef *module, int options)
 +/*[clinic end generated code: output=1f2a63b6a93cbb57 input=8ac4c56956b61710]*/
 +{
 +    pid_t pid;
 +    struct rusage ru;
 +    int async_err = 0;
 +    WAIT_TYPE status;
 +    WAIT_STATUS_INT(status) = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        pid = wait3(&status, options, &ru);
 +        Py_END_ALLOW_THREADS
 +    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +    if (pid < 0)
 +        return (!async_err) ? posix_error() : NULL;
 +
 +    return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
 +}
 +#endif /* HAVE_WAIT3 */
 +
 +
 +#ifdef HAVE_WAIT4
 +/*[clinic input]
 +
 +os.wait4
 +
 +    pid: pid_t
 +    options: int
 +
 +Wait for completion of a specific child process.
 +
 +Returns a tuple of information about the child process:
 +  (pid, status, rusage)
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_wait4__doc__,
 +"wait4($module, /, pid, options)\n"
 +"--\n"
 +"\n"
 +"Wait for completion of a specific child process.\n"
 +"\n"
 +"Returns a tuple of information about the child process:\n"
 +"  (pid, status, rusage)");
 +
 +#define OS_WAIT4_METHODDEF    \
 +    {"wait4", (PyCFunction)os_wait4, METH_VARARGS|METH_KEYWORDS, os_wait4__doc__},
 +
 +static PyObject *
 +os_wait4_impl(PyModuleDef *module, pid_t pid, int options);
 +
 +static PyObject *
 +os_wait4(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"pid", "options", NULL};
 +    pid_t pid;
 +    int options;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "" _Py_PARSE_PID "i:wait4", _keywords,
 +        &pid, &options))
 +        goto exit;
 +    return_value = os_wait4_impl(module, pid, options);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_wait4_impl(PyModuleDef *module, pid_t pid, int options)
 +/*[clinic end generated code: output=20dfb05289d37dc6 input=d11deed0750600ba]*/
 +{
 +    pid_t res;
 +    struct rusage ru;
 +    int async_err = 0;
 +    WAIT_TYPE status;
 +    WAIT_STATUS_INT(status) = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        res = wait4(pid, &status, options, &ru);
 +        Py_END_ALLOW_THREADS
 +    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +    if (res < 0)
 +        return (!async_err) ? posix_error() : NULL;
 +
 +    return wait_helper(res, WAIT_STATUS_INT(status), &ru);
 +}
 +#endif /* HAVE_WAIT4 */
 +
 +
 +#if defined(HAVE_WAITID) && !defined(__APPLE__)
 +/*[clinic input]
 +os.waitid
 +
 +    idtype: idtype_t
 +        Must be one of be P_PID, P_PGID or P_ALL.
 +    id: id_t
 +        The id to wait on.
 +    options: int
 +        Constructed from the ORing of one or more of WEXITED, WSTOPPED
 +        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
 +    /
 +
 +Returns the result of waiting for a process or processes.
 +
 +Returns either waitid_result or None if WNOHANG is specified and there are
 +no children in a waitable state.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_waitid__doc__,
 +"waitid($module, idtype, id, options, /)\n"
 +"--\n"
 +"\n"
 +"Returns the result of waiting for a process or processes.\n"
 +"\n"
 +"  idtype\n"
 +"    Must be one of be P_PID, P_PGID or P_ALL.\n"
 +"  id\n"
 +"    The id to wait on.\n"
 +"  options\n"
 +"    Constructed from the ORing of one or more of WEXITED, WSTOPPED\n"
 +"    or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n"
 +"\n"
 +"Returns either waitid_result or None if WNOHANG is specified and there are\n"
 +"no children in a waitable state.");
 +
 +#define OS_WAITID_METHODDEF    \
 +    {"waitid", (PyCFunction)os_waitid, METH_VARARGS, os_waitid__doc__},
 +
 +static PyObject *
 +os_waitid_impl(PyModuleDef *module, idtype_t idtype, id_t id, int options);
 +
 +static PyObject *
 +os_waitid(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    idtype_t idtype;
 +    id_t id;
 +    int options;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "i" _Py_PARSE_PID "i:waitid",
 +        &idtype, &id, &options))
 +        goto exit;
 +    return_value = os_waitid_impl(module, idtype, id, options);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_waitid_impl(PyModuleDef *module, idtype_t idtype, id_t id, int options)
 +/*[clinic end generated code: output=fb44bf97f01021b2 input=d8e7f76e052b7920]*/
 +{
 +    PyObject *result;
 +    int res;
 +    int async_err = 0;
 +    siginfo_t si;
 +    si.si_pid = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        res = waitid(idtype, id, &si, options);
 +        Py_END_ALLOW_THREADS
 +    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +    if (res < 0)
 +        return (!async_err) ? posix_error() : NULL;
 +
 +    if (si.si_pid == 0)
 +        Py_RETURN_NONE;
 +
 +    result = PyStructSequence_New(&WaitidResultType);
 +    if (!result)
 +        return NULL;
 +
 +    PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
 +    PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
 +    PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
 +    PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
 +    PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
 +    if (PyErr_Occurred()) {
 +        Py_DECREF(result);
 +        return NULL;
 +    }
 +
 +    return result;
 +}
 +#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
 +
 +
 +#if defined(HAVE_WAITPID)
 +/*[clinic input]
 +os.waitpid
 +    pid: pid_t
 +    options: int
 +    /
 +
 +Wait for completion of a given child process.
 +
 +Returns a tuple of information regarding the child process:
 +    (pid, status)
 +
 +The options argument is ignored on Windows.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_waitpid__doc__,
 +"waitpid($module, pid, options, /)\n"
 +"--\n"
 +"\n"
 +"Wait for completion of a given child process.\n"
 +"\n"
 +"Returns a tuple of information regarding the child process:\n"
 +"    (pid, status)\n"
 +"\n"
 +"The options argument is ignored on Windows.");
 +
 +#define OS_WAITPID_METHODDEF    \
 +    {"waitpid", (PyCFunction)os_waitpid, METH_VARARGS, os_waitpid__doc__},
 +
 +static PyObject *
 +os_waitpid_impl(PyModuleDef *module, pid_t pid, int options);
 +
 +static PyObject *
 +os_waitpid(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    pid_t pid;
 +    int options;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "" _Py_PARSE_PID "i:waitpid",
 +        &pid, &options))
 +        goto exit;
 +    return_value = os_waitpid_impl(module, pid, options);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_waitpid_impl(PyModuleDef *module, pid_t pid, int options)
 +/*[clinic end generated code: output=095a6b00af70b7ac input=0bf1666b8758fda3]*/
 +{
 +    pid_t res;
 +    int async_err = 0;
 +    WAIT_TYPE status;
 +    WAIT_STATUS_INT(status) = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        res = waitpid(pid, &status, options);
 +        Py_END_ALLOW_THREADS
 +    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +    if (res < 0)
 +        return (!async_err) ? posix_error() : NULL;
 +
 +    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
 +}
 +#elif defined(HAVE_CWAIT)
 +/* MS C has a variant of waitpid() that's usable for most purposes. */
 +/*[clinic input]
 +os.waitpid
 +    pid: Py_intptr_t
 +    options: int
 +    /
 +
 +Wait for completion of a given process.
 +
 +Returns a tuple of information regarding the process:
 +    (pid, status << 8)
 +
 +The options argument is ignored on Windows.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_waitpid__doc__,
 +"waitpid($module, pid, options, /)\n"
 +"--\n"
 +"\n"
 +"Wait for completion of a given process.\n"
 +"\n"
 +"Returns a tuple of information regarding the process:\n"
 +"    (pid, status << 8)\n"
 +"\n"
 +"The options argument is ignored on Windows.");
 +
 +#define OS_WAITPID_METHODDEF    \
 +    {"waitpid", (PyCFunction)os_waitpid, METH_VARARGS, os_waitpid__doc__},
 +
 +static PyObject *
 +os_waitpid_impl(PyModuleDef *module, Py_intptr_t pid, int options);
 +
 +static PyObject *
 +os_waitpid(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    Py_intptr_t pid;
 +    int options;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "" _Py_PARSE_INTPTR "i:waitpid",
 +        &pid, &options))
 +        goto exit;
 +    return_value = os_waitpid_impl(module, pid, options);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_waitpid_impl(PyModuleDef *module, Py_intptr_t pid, int options)
 +/*[clinic end generated code: output=c20b95b15ad44a3a input=444c8f51cca5b862]*/
 +{
 +    int status;
 +    Py_intptr_t res;
 +    int async_err = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        res = _cwait(&status, pid, options);
 +        Py_END_ALLOW_THREADS
 +    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +    if (res != 0)
 +        return (!async_err) ? posix_error() : NULL;
 +
 +    /* shift the status left a byte so this is more like the POSIX waitpid */
 +    return Py_BuildValue(_Py_PARSE_INTPTR "i", res, status << 8);
 +}
 +#endif
 +
 +
 +#ifdef HAVE_WAIT
 +/*[clinic input]
 +os.wait
 +
 +Wait for completion of a child process.
 +
 +Returns a tuple of information about the child process:
 +    (pid, status)
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_wait__doc__,
 +"wait($module, /)\n"
 +"--\n"
 +"\n"
 +"Wait for completion of a child process.\n"
 +"\n"
 +"Returns a tuple of information about the child process:\n"
 +"    (pid, status)");
 +
 +#define OS_WAIT_METHODDEF    \
 +    {"wait", (PyCFunction)os_wait, METH_NOARGS, os_wait__doc__},
 +
 +static PyObject *
 +os_wait_impl(PyModuleDef *module);
 +
 +static PyObject *
 +os_wait(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_wait_impl(module);
 +}
 +
 +static PyObject *
 +os_wait_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=2a83a9d164e7e6a8 input=03b0182d4a4700ce]*/
 +{
 +    pid_t pid;
 +    int async_err = 0;
 +    WAIT_TYPE status;
 +    WAIT_STATUS_INT(status) = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        pid = wait(&status);
 +        Py_END_ALLOW_THREADS
 +    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +    if (pid < 0)
 +        return (!async_err) ? posix_error() : NULL;
 +
 +    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
 +}
 +#endif /* HAVE_WAIT */
 +
 +
 +#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
 +PyDoc_STRVAR(readlink__doc__,
 +"readlink(path, *, dir_fd=None) -> path\n\n\
 +Return a string representing the path to which the symbolic link points.\n\
 +\n\
 +If dir_fd is not None, it should be a file descriptor open to a directory,\n\
 +  and path should be relative; path will then be relative to that directory.\n\
 +dir_fd may not be implemented on your platform.\n\
 +  If it is unavailable, using it will raise a NotImplementedError.");
 +#endif
 +
 +#ifdef HAVE_READLINK
 +
 +/* AC 3.5: merge win32 and not together */
 +static PyObject *
 +posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
 +{
 +    path_t path;
 +    int dir_fd = DEFAULT_DIR_FD;
 +    char buffer[MAXPATHLEN];
 +    ssize_t length;
 +    PyObject *return_value = NULL;
 +    static char *keywords[] = {"path", "dir_fd", NULL};
 +
 +    memset(&path, 0, sizeof(path));
 +    path.function_name = "readlink";
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords,
 +                          path_converter, &path,
 +                          READLINKAT_DIR_FD_CONVERTER, &dir_fd))
 +        return NULL;
 +
 +    Py_BEGIN_ALLOW_THREADS
 +#ifdef HAVE_READLINKAT
 +    if (dir_fd != DEFAULT_DIR_FD)
 +        length = readlinkat(dir_fd, path.narrow, buffer, sizeof(buffer));
 +    else
 +#endif
 +        length = readlink(path.narrow, buffer, sizeof(buffer));
 +    Py_END_ALLOW_THREADS
 +
 +    if (length < 0) {
 +        return_value = path_error(&path);
 +        goto exit;
 +    }
 +
 +    if (PyUnicode_Check(path.object))
 +        return_value = PyUnicode_DecodeFSDefaultAndSize(buffer, length);
 +    else
 +        return_value = PyBytes_FromStringAndSize(buffer, length);
 +exit:
 +    path_cleanup(&path);
 +    return return_value;
 +}
 +
 +#endif /* HAVE_READLINK */
 +
 +#if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
 +
 +static PyObject *
 +win_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
 +{
 +    wchar_t *path;
 +    DWORD n_bytes_returned;
 +    DWORD io_result;
 +    PyObject *po, *result;
 +        int dir_fd;
 +    HANDLE reparse_point_handle;
 +
 +    char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
 +    REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
 +    wchar_t *print_name;
 +
 +    static char *keywords[] = {"path", "dir_fd", NULL};
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|$O&:readlink", keywords,
 +                          &po,
 +                          dir_fd_unavailable, &dir_fd
 +                          ))
 +        return NULL;
 +
 +    path = PyUnicode_AsUnicode(po);
 +    if (path == NULL)
 +        return NULL;
 +
 +    /* First get a handle to the reparse point */
 +    Py_BEGIN_ALLOW_THREADS
 +    reparse_point_handle = CreateFileW(
 +        path,
 +        0,
 +        0,
 +        0,
 +        OPEN_EXISTING,
 +        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
 +        0);
 +    Py_END_ALLOW_THREADS
 +
 +    if (reparse_point_handle==INVALID_HANDLE_VALUE)
 +        return win32_error_object("readlink", po);
 +
 +    Py_BEGIN_ALLOW_THREADS
 +    /* New call DeviceIoControl to read the reparse point */
 +    io_result = DeviceIoControl(
 +        reparse_point_handle,
 +        FSCTL_GET_REPARSE_POINT,
 +        0, 0, /* in buffer */
 +        target_buffer, sizeof(target_buffer),
 +        &n_bytes_returned,
 +        0 /* we're not using OVERLAPPED_IO */
 +        );
 +    CloseHandle(reparse_point_handle);
 +    Py_END_ALLOW_THREADS
 +
 +    if (io_result==0)
 +        return win32_error_object("readlink", po);
 +
 +    if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK)
 +    {
 +        PyErr_SetString(PyExc_ValueError,
 +                "not a symbolic link");
 +        return NULL;
 +    }
 +    print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer +
 +                 rdb->SymbolicLinkReparseBuffer.PrintNameOffset;
 +
 +    result = PyUnicode_FromWideChar(print_name,
 +                    rdb->SymbolicLinkReparseBuffer.PrintNameLength/2);
 +    return result;
 +}
 +
 +#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
 +
 +
 +
 +#ifdef HAVE_SYMLINK
 +
 +#if defined(MS_WINDOWS)
 +
 +/* Grab CreateSymbolicLinkW dynamically from kernel32 */
 +static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD) = NULL;
 +static DWORD (CALLBACK *Py_CreateSymbolicLinkA)(LPSTR, LPSTR, DWORD) = NULL;
 +
 +static int
 +check_CreateSymbolicLink(void)
 +{
 +    HINSTANCE hKernel32;
 +    /* only recheck */
 +    if (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA)
 +        return 1;
 +    hKernel32 = GetModuleHandleW(L"KERNEL32");
 +    *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32,
 +                                                        "CreateSymbolicLinkW");
 +    *(FARPROC*)&Py_CreateSymbolicLinkA = GetProcAddress(hKernel32,
 +                                                        "CreateSymbolicLinkA");
 +    return (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA);
 +}
 +
 +/* Remove the last portion of the path */
 +static void
 +_dirnameW(WCHAR *path)
 +{
 +    WCHAR *ptr;
 +
 +    /* walk the path from the end until a backslash is encountered */
 +    for(ptr = path + wcslen(path); ptr != path; ptr--) {
 +        if (*ptr == L'\\' || *ptr == L'/')
 +            break;
 +    }
 +    *ptr = 0;
 +}
 +
 +/* Remove the last portion of the path */
 +static void
 +_dirnameA(char *path)
 +{
 +    char *ptr;
 +
 +    /* walk the path from the end until a backslash is encountered */
 +    for(ptr = path + strlen(path); ptr != path; ptr--) {
 +        if (*ptr == '\\' || *ptr == '/')
 +            break;
 +    }
 +    *ptr = 0;
 +}
 +
 +/* Is this path absolute? */
 +static int
 +_is_absW(const WCHAR *path)
 +{
 +    return path[0] == L'\\' || path[0] == L'/' || path[1] == L':';
 +
 +}
 +
 +/* Is this path absolute? */
 +static int
 +_is_absA(const char *path)
 +{
 +    return path[0] == '\\' || path[0] == '/' || path[1] == ':';
 +
 +}
 +
 +/* join root and rest with a backslash */
 +static void
 +_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
 +{
 +    size_t root_len;
 +
 +    if (_is_absW(rest)) {
 +        wcscpy(dest_path, rest);
 +        return;
 +    }
 +
 +    root_len = wcslen(root);
 +
 +    wcscpy(dest_path, root);
 +    if(root_len) {
 +        dest_path[root_len] = L'\\';
 +        root_len++;
 +    }
 +    wcscpy(dest_path+root_len, rest);
 +}
 +
 +/* join root and rest with a backslash */
 +static void
 +_joinA(char *dest_path, const char *root, const char *rest)
 +{
 +    size_t root_len;
 +
 +    if (_is_absA(rest)) {
 +        strcpy(dest_path, rest);
 +        return;
 +    }
 +
 +    root_len = strlen(root);
 +
 +    strcpy(dest_path, root);
 +    if(root_len) {
 +        dest_path[root_len] = '\\';
 +        root_len++;
 +    }
 +    strcpy(dest_path+root_len, rest);
 +}
 +
 +/* Return True if the path at src relative to dest is a directory */
 +static int
 +_check_dirW(WCHAR *src, WCHAR *dest)
 +{
 +    WIN32_FILE_ATTRIBUTE_DATA src_info;
 +    WCHAR dest_parent[MAX_PATH];
 +    WCHAR src_resolved[MAX_PATH] = L"";
 +
 +    /* dest_parent = os.path.dirname(dest) */
 +    wcscpy(dest_parent, dest);
 +    _dirnameW(dest_parent);
 +    /* src_resolved = os.path.join(dest_parent, src) */
 +    _joinW(src_resolved, dest_parent, src);
 +    return (
 +        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
 +        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
 +    );
 +}
 +
 +/* Return True if the path at src relative to dest is a directory */
 +static int
 +_check_dirA(char *src, char *dest)
 +{
 +    WIN32_FILE_ATTRIBUTE_DATA src_info;
 +    char dest_parent[MAX_PATH];
 +    char src_resolved[MAX_PATH] = "";
 +
 +    /* dest_parent = os.path.dirname(dest) */
 +    strcpy(dest_parent, dest);
 +    _dirnameA(dest_parent);
 +    /* src_resolved = os.path.join(dest_parent, src) */
 +    _joinA(src_resolved, dest_parent, src);
 +    return (
 +        GetFileAttributesExA(src_resolved, GetFileExInfoStandard, &src_info)
 +        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
 +    );
 +}
 +#endif
 +
 +
 +/*[clinic input]
 +os.symlink
 +    src: path_t
 +    dst: path_t
 +    target_is_directory: bool = False
 +    *
 +    dir_fd: dir_fd(requires='symlinkat')=None
 +
 +# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
 +
 +Create a symbolic link pointing to src named dst.
 +
 +target_is_directory is required on Windows if the target is to be
 +  interpreted as a directory.  (On Windows, symlink requires
 +  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
 +  target_is_directory is ignored on non-Windows platforms.
 +
 +If dir_fd is not None, it should be a file descriptor open to a directory,
 +  and path should be relative; path will then be relative to that directory.
 +dir_fd may not be implemented on your platform.
 +  If it is unavailable, using it will raise a NotImplementedError.
 +
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_symlink__doc__,
 +"symlink($module, /, src, dst, target_is_directory=False, *, dir_fd=None)\n"
 +"--\n"
 +"\n"
 +"Create a symbolic link pointing to src named dst.\n"
 +"\n"
 +"target_is_directory is required on Windows if the target is to be\n"
 +"  interpreted as a directory.  (On Windows, symlink requires\n"
 +"  Windows 6.0 or greater, and raises a NotImplementedError otherwise.)\n"
 +"  target_is_directory is ignored on non-Windows platforms.\n"
 +"\n"
 +"If dir_fd is not None, it should be a file descriptor open to a directory,\n"
 +"  and path should be relative; path will then be relative to that directory.\n"
 +"dir_fd may not be implemented on your platform.\n"
 +"  If it is unavailable, using it will raise a NotImplementedError.");
 +
 +#define OS_SYMLINK_METHODDEF    \
 +    {"symlink", (PyCFunction)os_symlink, METH_VARARGS|METH_KEYWORDS, os_symlink__doc__},
 +
 +static PyObject *
 +os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd);
 +
 +static PyObject *
 +os_symlink(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"src", "dst", "target_is_directory", "dir_fd", NULL};
 +    path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0);
 +    path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0);
 +    int target_is_directory = 0;
 +    int dir_fd = DEFAULT_DIR_FD;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "O&O&|p$O&:symlink", _keywords,
 +        path_converter, &src, path_converter, &dst, &target_is_directory, SYMLINKAT_DIR_FD_CONVERTER, &dir_fd))
 +        goto exit;
 +    return_value = os_symlink_impl(module, &src, &dst, target_is_directory, dir_fd);
 +
 +exit:
 +    /* Cleanup for src */
 +    path_cleanup(&src);
 +    /* Cleanup for dst */
 +    path_cleanup(&dst);
 +
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd)
 +/*[clinic end generated code: output=1a31e6d88aafe9b6 input=e820ec4472547bc3]*/
 +{
 +#ifdef MS_WINDOWS
 +    DWORD result;
 +#else
 +    int result;
 +#endif
 +
 +#ifdef MS_WINDOWS
 +    if (!check_CreateSymbolicLink()) {
 +        PyErr_SetString(PyExc_NotImplementedError,
 +            "CreateSymbolicLink functions not found");
 +        return NULL;
 +        }
 +    if (!win32_can_symlink) {
 +        PyErr_SetString(PyExc_OSError, "symbolic link privilege not held");
 +        return NULL;
 +        }
 +#endif
 +
 +    if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
 +        PyErr_SetString(PyExc_ValueError,
 +            "symlink: src and dst must be the same type");
 +        return NULL;
 +    }
 +
 +#ifdef MS_WINDOWS
 +
 +    Py_BEGIN_ALLOW_THREADS
 +    if (dst->wide) {
 +        /* if src is a directory, ensure target_is_directory==1 */
 +        target_is_directory |= _check_dirW(src->wide, dst->wide);
 +        result = Py_CreateSymbolicLinkW(dst->wide, src->wide,
 +                                        target_is_directory);
 +    }
 +    else {
 +        /* if src is a directory, ensure target_is_directory==1 */
 +        target_is_directory |= _check_dirA(src->narrow, dst->narrow);
 +        result = Py_CreateSymbolicLinkA(dst->narrow, src->narrow,
 +                                        target_is_directory);
 +    }
 +    Py_END_ALLOW_THREADS
 +
 +    if (!result)
 +        return path_error2(src, dst);
 +
 +#else
 +
 +    Py_BEGIN_ALLOW_THREADS
 +#if HAVE_SYMLINKAT
 +    if (dir_fd != DEFAULT_DIR_FD)
 +        result = symlinkat(src->narrow, dir_fd, dst->narrow);
 +    else
 +#endif
 +        result = symlink(src->narrow, dst->narrow);
 +    Py_END_ALLOW_THREADS
 +
 +    if (result)
 +        return path_error2(src, dst);
 +#endif
 +
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_SYMLINK */
 +
 +
 +
 +
 +static PyStructSequence_Field times_result_fields[] = {
 +    {"user",    "user time"},
 +    {"system",   "system time"},
 +    {"children_user",    "user time of children"},
 +    {"children_system",    "system time of children"},
 +    {"elapsed",    "elapsed time since an arbitrary point in the past"},
 +    {NULL}
 +};
 +
 +PyDoc_STRVAR(times_result__doc__,
 +"times_result: Result from os.times().\n\n\
 +This object may be accessed either as a tuple of\n\
 +  (user, system, children_user, children_system, elapsed),\n\
 +or via the attributes user, system, children_user, children_system,\n\
 +and elapsed.\n\
 +\n\
 +See os.times for more information.");
 +
 +static PyStructSequence_Desc times_result_desc = {
 +    "times_result", /* name */
 +    times_result__doc__, /* doc */
 +    times_result_fields,
 +    5
 +};
 +
 +static PyTypeObject TimesResultType;
 +
 +#ifdef MS_WINDOWS
 +#define HAVE_TIMES  /* mandatory, for the method table */
 +#endif
 +
 +#ifdef HAVE_TIMES
 +
 +static PyObject *
 +build_times_result(double user, double system,
 +    double children_user, double children_system,
 +    double elapsed)
 +{
 +    PyObject *value = PyStructSequence_New(&TimesResultType);
 +    if (value == NULL)
 +        return NULL;
 +
 +#define SET(i, field) \
 +    { \
 +    PyObject *o = PyFloat_FromDouble(field); \
 +    if (!o) { \
 +        Py_DECREF(value); \
 +        return NULL; \
 +    } \
 +    PyStructSequence_SET_ITEM(value, i, o); \
 +    } \
 +
 +    SET(0, user);
 +    SET(1, system);
 +    SET(2, children_user);
 +    SET(3, children_system);
 +    SET(4, elapsed);
 +
 +#undef SET
 +
 +    return value;
 +}
 +
 +
 +#ifndef MS_WINDOWS
 +#define NEED_TICKS_PER_SECOND
 +static long ticks_per_second = -1;
 +#endif /* MS_WINDOWS */
 +
 +/*[clinic input]
 +os.times
 +
 +Return a collection containing process timing information.
 +
 +The object returned behaves like a named tuple with these fields:
 +  (utime, stime, cutime, cstime, elapsed_time)
 +All fields are floating point numbers.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_times__doc__,
 +"times($module, /)\n"
 +"--\n"
 +"\n"
 +"Return a collection containing process timing information.\n"
 +"\n"
 +"The object returned behaves like a named tuple with these fields:\n"
 +"  (utime, stime, cutime, cstime, elapsed_time)\n"
 +"All fields are floating point numbers.");
 +
 +#define OS_TIMES_METHODDEF    \
 +    {"times", (PyCFunction)os_times, METH_NOARGS, os_times__doc__},
 +
 +static PyObject *
 +os_times_impl(PyModuleDef *module);
 +
 +static PyObject *
 +os_times(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_times_impl(module);
 +}
 +
 +static PyObject *
 +os_times_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=b86896d031a9b768 input=2bf9df3d6ab2e48b]*/
 +#ifdef MS_WINDOWS
 +{
 +    FILETIME create, exit, kernel, user;
 +    HANDLE hProc;
 +    hProc = GetCurrentProcess();
 +    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
 +    /* The fields of a FILETIME structure are the hi and lo part
 +       of a 64-bit value expressed in 100 nanosecond units.
 +       1e7 is one second in such units; 1e-7 the inverse.
 +       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
 +    */
 +    return build_times_result(
 +        (double)(user.dwHighDateTime*429.4967296 +
 +                 user.dwLowDateTime*1e-7),
 +        (double)(kernel.dwHighDateTime*429.4967296 +
 +                 kernel.dwLowDateTime*1e-7),
 +        (double)0,
 +        (double)0,
 +        (double)0);
 +}
 +#else /* MS_WINDOWS */
 +{
 +
 +
 +    struct tms t;
 +    clock_t c;
 +    errno = 0;
 +    c = times(&t);
 +    if (c == (clock_t) -1)
 +        return posix_error();
 +    return build_times_result(
 +                         (double)t.tms_utime / ticks_per_second,
 +                         (double)t.tms_stime / ticks_per_second,
 +                         (double)t.tms_cutime / ticks_per_second,
 +                         (double)t.tms_cstime / ticks_per_second,
 +                         (double)c / ticks_per_second);
 +}
 +#endif /* MS_WINDOWS */
 +#endif /* HAVE_TIMES */
 +
 +
 +#ifdef HAVE_GETSID
 +/*[clinic input]
 +os.getsid
 +
 +    pid: pid_t
 +    /
 +
 +Call the system call getsid(pid) and return the result.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_getsid__doc__,
 +"getsid($module, pid, /)\n"
 +"--\n"
 +"\n"
 +"Call the system call getsid(pid) and return the result.");
 +
 +#define OS_GETSID_METHODDEF    \
 +    {"getsid", (PyCFunction)os_getsid, METH_VARARGS, os_getsid__doc__},
 +
 +static PyObject *
 +os_getsid_impl(PyModuleDef *module, pid_t pid);
 +
 +static PyObject *
 +os_getsid(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    pid_t pid;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "" _Py_PARSE_PID ":getsid",
 +        &pid))
 +        goto exit;
 +    return_value = os_getsid_impl(module, pid);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_getsid_impl(PyModuleDef *module, pid_t pid)
 +/*[clinic end generated code: output=ea8390f395f4e0e1 input=eeb2b923a30ce04e]*/
 +{
 +    int sid;
 +    sid = getsid(pid);
 +    if (sid < 0)
 +        return posix_error();
 +    return PyLong_FromLong((long)sid);
 +}
 +#endif /* HAVE_GETSID */
 +
 +
 +#ifdef HAVE_SETSID
 +/*[clinic input]
 +os.setsid
 +
 +Call the system call setsid().
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_setsid__doc__,
 +"setsid($module, /)\n"
 +"--\n"
 +"\n"
 +"Call the system call setsid().");
 +
 +#define OS_SETSID_METHODDEF    \
 +    {"setsid", (PyCFunction)os_setsid, METH_NOARGS, os_setsid__doc__},
 +
 +static PyObject *
 +os_setsid_impl(PyModuleDef *module);
 +
 +static PyObject *
 +os_setsid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_setsid_impl(module);
 +}
 +
 +static PyObject *
 +os_setsid_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=2a9a1435d8d764d5 input=5fff45858e2f0776]*/
 +{
 +    if (setsid() < 0)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_SETSID */
 +
 +
 +#ifdef HAVE_SETPGID
 +/*[clinic input]
 +os.setpgid
 +
 +    pid: pid_t
 +    pgrp: pid_t
 +    /
 +
 +Call the system call setpgid(pid, pgrp).
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_setpgid__doc__,
 +"setpgid($module, pid, pgrp, /)\n"
 +"--\n"
 +"\n"
 +"Call the system call setpgid(pid, pgrp).");
 +
 +#define OS_SETPGID_METHODDEF    \
 +    {"setpgid", (PyCFunction)os_setpgid, METH_VARARGS, os_setpgid__doc__},
 +
 +static PyObject *
 +os_setpgid_impl(PyModuleDef *module, pid_t pid, pid_t pgrp);
 +
 +static PyObject *
 +os_setpgid(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    pid_t pid;
 +    pid_t pgrp;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "" _Py_PARSE_PID "" _Py_PARSE_PID ":setpgid",
 +        &pid, &pgrp))
 +        goto exit;
 +    return_value = os_setpgid_impl(module, pid, pgrp);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_setpgid_impl(PyModuleDef *module, pid_t pid, pid_t pgrp)
 +/*[clinic end generated code: output=7ad79b725f890e1f input=fceb395eca572e1a]*/
 +{
 +    if (setpgid(pid, pgrp) < 0)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_SETPGID */
 +
 +
 +#ifdef HAVE_TCGETPGRP
 +/*[clinic input]
 +os.tcgetpgrp
 +
 +    fd: int
 +    /
 +
 +Return the process group associated with the terminal specified by fd.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_tcgetpgrp__doc__,
 +"tcgetpgrp($module, fd, /)\n"
 +"--\n"
 +"\n"
 +"Return the process group associated with the terminal specified by fd.");
 +
 +#define OS_TCGETPGRP_METHODDEF    \
 +    {"tcgetpgrp", (PyCFunction)os_tcgetpgrp, METH_VARARGS, os_tcgetpgrp__doc__},
 +
 +static PyObject *
 +os_tcgetpgrp_impl(PyModuleDef *module, int fd);
 +
 +static PyObject *
 +os_tcgetpgrp(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "i:tcgetpgrp",
 +        &fd))
 +        goto exit;
 +    return_value = os_tcgetpgrp_impl(module, fd);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_tcgetpgrp_impl(PyModuleDef *module, int fd)
 +/*[clinic end generated code: output=abcf52ed4c8d22cb input=7f6c18eac10ada86]*/
 +{
 +    pid_t pgid = tcgetpgrp(fd);
 +    if (pgid < 0)
 +        return posix_error();
 +    return PyLong_FromPid(pgid);
 +}
 +#endif /* HAVE_TCGETPGRP */
 +
 +
 +#ifdef HAVE_TCSETPGRP
 +/*[clinic input]
 +os.tcsetpgrp
 +
 +    fd: int
 +    pgid: pid_t
 +    /
 +
 +Set the process group associated with the terminal specified by fd.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_tcsetpgrp__doc__,
 +"tcsetpgrp($module, fd, pgid, /)\n"
 +"--\n"
 +"\n"
 +"Set the process group associated with the terminal specified by fd.");
 +
 +#define OS_TCSETPGRP_METHODDEF    \
 +    {"tcsetpgrp", (PyCFunction)os_tcsetpgrp, METH_VARARGS, os_tcsetpgrp__doc__},
 +
 +static PyObject *
 +os_tcsetpgrp_impl(PyModuleDef *module, int fd, pid_t pgid);
 +
 +static PyObject *
 +os_tcsetpgrp(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    pid_t pgid;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "i" _Py_PARSE_PID ":tcsetpgrp",
 +        &fd, &pgid))
 +        goto exit;
 +    return_value = os_tcsetpgrp_impl(module, fd, pgid);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_tcsetpgrp_impl(PyModuleDef *module, int fd, pid_t pgid)
 +/*[clinic end generated code: output=76f9bb8fd00f20f5 input=5bdc997c6a619020]*/
 +{
 +    if (tcsetpgrp(fd, pgid) < 0)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_TCSETPGRP */
 +
 +/* Functions acting on file descriptors */
 +
 +#ifdef O_CLOEXEC
 +extern int _Py_open_cloexec_works;
 +#endif
 +
 +
 +/*[clinic input]
 +os.open -> int
 +    path: path_t
 +    flags: int
 +    mode: int = 0o777
 +    *
 +    dir_fd: dir_fd(requires='openat') = None
 +
 +# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
 +
 +Open a file for low level IO.  Returns a file descriptor (integer).
 +
 +If dir_fd is not None, it should be a file descriptor open to a directory,
 +  and path should be relative; path will then be relative to that directory.
 +dir_fd may not be implemented on your platform.
 +  If it is unavailable, using it will raise a NotImplementedError.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_open__doc__,
 +"open($module, /, path, flags, mode=511, *, dir_fd=None)\n"
 +"--\n"
 +"\n"
 +"Open a file for low level IO.  Returns a file descriptor (integer).\n"
 +"\n"
 +"If dir_fd is not None, it should be a file descriptor open to a directory,\n"
 +"  and path should be relative; path will then be relative to that directory.\n"
 +"dir_fd may not be implemented on your platform.\n"
 +"  If it is unavailable, using it will raise a NotImplementedError.");
 +
 +#define OS_OPEN_METHODDEF    \
 +    {"open", (PyCFunction)os_open, METH_VARARGS|METH_KEYWORDS, os_open__doc__},
 +
 +static int
 +os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd);
 +
 +static PyObject *
 +os_open(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"path", "flags", "mode", "dir_fd", NULL};
 +    path_t path = PATH_T_INITIALIZE("open", "path", 0, 0);
 +    int flags;
 +    int mode = 511;
 +    int dir_fd = DEFAULT_DIR_FD;
 +    int _return_value;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "O&i|i$O&:open", _keywords,
 +        path_converter, &path, &flags, &mode, OPENAT_DIR_FD_CONVERTER, &dir_fd))
 +        goto exit;
 +    _return_value = os_open_impl(module, &path, flags, mode, dir_fd);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromLong((long)_return_value);
 +
 +exit:
 +    /* Cleanup for path */
 +    path_cleanup(&path);
 +
 +    return return_value;
 +}
 +
 +static int
 +os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd)
 +/*[clinic end generated code: output=05b68fc4ed5e29c9 input=ad8623b29acd2934]*/
 +{
 +    int fd;
 +    int async_err = 0;
 +
 +#ifdef O_CLOEXEC
 +    int *atomic_flag_works = &_Py_open_cloexec_works;
 +#elif !defined(MS_WINDOWS)
 +    int *atomic_flag_works = NULL;
 +#endif
 +
 +#ifdef MS_WINDOWS
 +    flags |= O_NOINHERIT;
 +#elif defined(O_CLOEXEC)
 +    flags |= O_CLOEXEC;
 +#endif
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +#ifdef MS_WINDOWS
 +        if (path->wide)
 +            fd = _wopen(path->wide, flags, mode);
 +        else
 +#endif
 +#ifdef HAVE_OPENAT
 +        if (dir_fd != DEFAULT_DIR_FD)
 +            fd = openat(dir_fd, path->narrow, flags, mode);
 +        else
 +#endif
 +            fd = open(path->narrow, flags, mode);
 +        Py_END_ALLOW_THREADS
 +    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +
 +    if (fd == -1) {
 +        if (!async_err)
 +            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
 +        return -1;
 +    }
 +
 +#ifndef MS_WINDOWS
 +    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
 +        close(fd);
 +        return -1;
 +    }
 +#endif
 +
 +    return fd;
 +}
 +
 +
 +/*[clinic input]
 +os.close
 +
 +    fd: int
 +
 +Close a file descriptor.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_close__doc__,
 +"close($module, /, fd)\n"
 +"--\n"
 +"\n"
 +"Close a file descriptor.");
 +
 +#define OS_CLOSE_METHODDEF    \
 +    {"close", (PyCFunction)os_close, METH_VARARGS|METH_KEYWORDS, os_close__doc__},
 +
 +static PyObject *
 +os_close_impl(PyModuleDef *module, int fd);
 +
 +static PyObject *
 +os_close(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"fd", NULL};
 +    int fd;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "i:close", _keywords,
 +        &fd))
 +        goto exit;
 +    return_value = os_close_impl(module, fd);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_close_impl(PyModuleDef *module, int fd)
 +/*[clinic end generated code: output=927004e29ad55808 input=2bc42451ca5c3223]*/
 +{
 +    int res;
 +    if (!_PyVerify_fd(fd))
 +        return posix_error();
 +    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
 +     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
 +     * for more details.
 +     */
 +    Py_BEGIN_ALLOW_THREADS
 +    res = close(fd);
 +    Py_END_ALLOW_THREADS
 +    if (res < 0)
 +        return posix_error();
 +    Py_RETURN_NONE;
 +}
 +
 +
 +/*[clinic input]
 +os.closerange
 +
 +    fd_low: int
 +    fd_high: int
 +    /
 +
 +Closes all file descriptors in [fd_low, fd_high), ignoring errors.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_closerange__doc__,
 +"closerange($module, fd_low, fd_high, /)\n"
 +"--\n"
 +"\n"
 +"Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
 +
 +#define OS_CLOSERANGE_METHODDEF    \
 +    {"closerange", (PyCFunction)os_closerange, METH_VARARGS, os_closerange__doc__},
 +
 +static PyObject *
 +os_closerange_impl(PyModuleDef *module, int fd_low, int fd_high);
 +
 +static PyObject *
 +os_closerange(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd_low;
 +    int fd_high;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "ii:closerange",
 +        &fd_low, &fd_high))
 +        goto exit;
 +    return_value = os_closerange_impl(module, fd_low, fd_high);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_closerange_impl(PyModuleDef *module, int fd_low, int fd_high)
 +/*[clinic end generated code: output=0a929ece386811c3 input=5855a3d053ebd4ec]*/
 +{
 +    int i;
 +    Py_BEGIN_ALLOW_THREADS
 +    for (i = fd_low; i < fd_high; i++)
 +        if (_PyVerify_fd(i))
 +            close(i);
 +    Py_END_ALLOW_THREADS
 +    Py_RETURN_NONE;
 +}
 +
 +
 +/*[clinic input]
 +os.dup -> int
 +
 +    fd: int
 +    /
 +
 +Return a duplicate of a file descriptor.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_dup__doc__,
 +"dup($module, fd, /)\n"
 +"--\n"
 +"\n"
 +"Return a duplicate of a file descriptor.");
 +
 +#define OS_DUP_METHODDEF    \
 +    {"dup", (PyCFunction)os_dup, METH_VARARGS, os_dup__doc__},
 +
 +static int
 +os_dup_impl(PyModuleDef *module, int fd);
 +
 +static PyObject *
 +os_dup(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    int _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "i:dup",
 +        &fd))
 +        goto exit;
 +    _return_value = os_dup_impl(module, fd);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromLong((long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static int
 +os_dup_impl(PyModuleDef *module, int fd)
 +/*[clinic end generated code: output=75943e057b25e1bd input=6f10f7ea97f7852a]*/
 +{
 +    return _Py_dup(fd);
 +}
 +
 +
 +/*[clinic input]
 +os.dup2
 +    fd: int
 +    fd2: int
 +    inheritable: bool=True
 +
 +Duplicate file descriptor.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_dup2__doc__,
 +"dup2($module, /, fd, fd2, inheritable=True)\n"
 +"--\n"
 +"\n"
 +"Duplicate file descriptor.");
 +
 +#define OS_DUP2_METHODDEF    \
 +    {"dup2", (PyCFunction)os_dup2, METH_VARARGS|METH_KEYWORDS, os_dup2__doc__},
 +
 +static PyObject *
 +os_dup2_impl(PyModuleDef *module, int fd, int fd2, int inheritable);
 +
 +static PyObject *
 +os_dup2(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"fd", "fd2", "inheritable", NULL};
 +    int fd;
 +    int fd2;
 +    int inheritable = 1;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "ii|p:dup2", _keywords,
 +        &fd, &fd2, &inheritable))
 +        goto exit;
 +    return_value = os_dup2_impl(module, fd, fd2, inheritable);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_dup2_impl(PyModuleDef *module, int fd, int fd2, int inheritable)
 +/*[clinic end generated code: output=531e482dd11a99a0 input=76e96f511be0352f]*/
 +{
 +    int res;
 +#if defined(HAVE_DUP3) && \
 +    !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
 +    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
 +    int dup3_works = -1;
 +#endif
 +
 +    if (!_PyVerify_fd_dup2(fd, fd2))
 +        return posix_error();
 +
 +    /* dup2() can fail with EINTR if the target FD is already open, because it
 +     * then has to be closed. See os_close_impl() for why we don't handle EINTR
 +     * upon close(), and therefore below.
 +     */
 +#ifdef MS_WINDOWS
 +    Py_BEGIN_ALLOW_THREADS
 +    res = dup2(fd, fd2);
 +    Py_END_ALLOW_THREADS
 +    if (res < 0)
 +        return posix_error();
 +
 +    /* Character files like console cannot be make non-inheritable */
 +    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
 +        close(fd2);
 +        return NULL;
 +    }
 +
 +#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
 +    Py_BEGIN_ALLOW_THREADS
 +    if (!inheritable)
 +        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
 +    else
 +        res = dup2(fd, fd2);
 +    Py_END_ALLOW_THREADS
 +    if (res < 0)
 +        return posix_error();
 +
 +#else
 +
 +#ifdef HAVE_DUP3
 +    if (!inheritable && dup3_works != 0) {
 +        Py_BEGIN_ALLOW_THREADS
 +        res = dup3(fd, fd2, O_CLOEXEC);
 +        Py_END_ALLOW_THREADS
 +        if (res < 0) {
 +            if (dup3_works == -1)
 +                dup3_works = (errno != ENOSYS);
 +            if (dup3_works)
 +                return posix_error();
 +        }
 +    }
 +
 +    if (inheritable || dup3_works == 0)
 +    {
 +#endif
 +        Py_BEGIN_ALLOW_THREADS
 +        res = dup2(fd, fd2);
 +        Py_END_ALLOW_THREADS
 +        if (res < 0)
 +            return posix_error();
 +
 +        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
 +            close(fd2);
 +            return NULL;
 +        }
 +#ifdef HAVE_DUP3
 +    }
 +#endif
 +
 +#endif
 +
 +    Py_RETURN_NONE;
 +}
 +
 +
 +#ifdef HAVE_LOCKF
 +/*[clinic input]
 +os.lockf
 +
 +    fd: int
 +        An open file descriptor.
 +    command: int
 +        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
 +    length: Py_off_t
 +        The number of bytes to lock, starting at the current position.
 +    /
 +
 +Apply, test or remove a POSIX lock on an open file descriptor.
 +
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_lockf__doc__,
 +"lockf($module, fd, command, length, /)\n"
 +"--\n"
 +"\n"
 +"Apply, test or remove a POSIX lock on an open file descriptor.\n"
 +"\n"
 +"  fd\n"
 +"    An open file descriptor.\n"
 +"  command\n"
 +"    One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.\n"
 +"  length\n"
 +"    The number of bytes to lock, starting at the current position.");
 +
 +#define OS_LOCKF_METHODDEF    \
 +    {"lockf", (PyCFunction)os_lockf, METH_VARARGS, os_lockf__doc__},
 +
 +static PyObject *
 +os_lockf_impl(PyModuleDef *module, int fd, int command, Py_off_t length);
 +
 +static PyObject *
 +os_lockf(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    int command;
 +    Py_off_t length;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "iiO&:lockf",
 +        &fd, &command, Py_off_t_converter, &length))
 +        goto exit;
 +    return_value = os_lockf_impl(module, fd, command, length);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_lockf_impl(PyModuleDef *module, int fd, int command, Py_off_t length)
 +/*[clinic end generated code: output=1b28346ac7335c0f input=65da41d2106e9b79]*/
 +{
 +    int res;
 +
 +    Py_BEGIN_ALLOW_THREADS
 +    res = lockf(fd, command, length);
 +    Py_END_ALLOW_THREADS
 +
 +    if (res < 0)
 +        return posix_error();
 +
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_LOCKF */
 +
 +
 +/*[clinic input]
 +os.lseek -> Py_off_t
 +
 +    fd: int
 +    position: Py_off_t
 +    how: int
 +    /
 +
 +Set the position of a file descriptor.  Return the new position.
 +
 +Return the new cursor position in number of bytes
 +relative to the beginning of the file.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_lseek__doc__,
 +"lseek($module, fd, position, how, /)\n"
 +"--\n"
 +"\n"
 +"Set the position of a file descriptor.  Return the new position.\n"
 +"\n"
 +"Return the new cursor position in number of bytes\n"
 +"relative to the beginning of the file.");
 +
 +#define OS_LSEEK_METHODDEF    \
 +    {"lseek", (PyCFunction)os_lseek, METH_VARARGS, os_lseek__doc__},
 +
 +static Py_off_t
 +os_lseek_impl(PyModuleDef *module, int fd, Py_off_t position, int how);
 +
 +static PyObject *
 +os_lseek(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    Py_off_t position;
 +    int how;
 +    Py_off_t _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "iO&i:lseek",
 +        &fd, Py_off_t_converter, &position, &how))
 +        goto exit;
 +    _return_value = os_lseek_impl(module, fd, position, how);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromPy_off_t(_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static Py_off_t
 +os_lseek_impl(PyModuleDef *module, int fd, Py_off_t position, int how)
 +/*[clinic end generated code: output=88cfc146f55667af input=902654ad3f96a6d3]*/
 +{
 +    Py_off_t result;
 +
 +    if (!_PyVerify_fd(fd)) {
 +        posix_error();
 +        return -1;
 +    }
 +#ifdef SEEK_SET
 +    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
 +    switch (how) {
 +        case 0: how = SEEK_SET; break;
 +        case 1: how = SEEK_CUR; break;
 +        case 2: how = SEEK_END; break;
 +    }
 +#endif /* SEEK_END */
 +
 +    if (PyErr_Occurred())
 +        return -1;
 +
 +    if (!_PyVerify_fd(fd)) {
 +        posix_error();
 +        return -1;
 +    }
 +    Py_BEGIN_ALLOW_THREADS
 +#ifdef MS_WINDOWS
 +    result = _lseeki64(fd, position, how);
 +#else
 +    result = lseek(fd, position, how);
 +#endif
 +    Py_END_ALLOW_THREADS
 +    if (result < 0)
 +        posix_error();
 +
 +    return result;
 +}
 +
 +
 +/*[clinic input]
 +os.read
 +    fd: int
 +    length: Py_ssize_t
 +    /
 +
 +Read from a file descriptor.  Returns a bytes object.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_read__doc__,
 +"read($module, fd, length, /)\n"
 +"--\n"
 +"\n"
 +"Read from a file descriptor.  Returns a bytes object.");
 +
 +#define OS_READ_METHODDEF    \
 +    {"read", (PyCFunction)os_read, METH_VARARGS, os_read__doc__},
 +
 +static PyObject *
 +os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length);
 +
 +static PyObject *
 +os_read(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    Py_ssize_t length;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "in:read",
 +        &fd, &length))
 +        goto exit;
 +    return_value = os_read_impl(module, fd, length);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length)
 +/*[clinic end generated code: output=1f3bc27260a24968 input=1df2eaa27c0bf1d3]*/
 +{
 +    Py_ssize_t n;
 +    int async_err = 0;
 +    PyObject *buffer;
 +
 +    if (length < 0) {
 +        errno = EINVAL;
 +        return posix_error();
 +    }
 +    if (!_PyVerify_fd(fd))
 +        return posix_error();
 +
 +#ifdef MS_WINDOWS
 +    #define READ_CAST (int)
 +    if (length > INT_MAX)
 +        length = INT_MAX;
 +#else
 +    #define READ_CAST
 +#endif
 +
 +    buffer = PyBytes_FromStringAndSize((char *)NULL, length);
 +    if (buffer == NULL)
 +        return NULL;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        n = read(fd, PyBytes_AS_STRING(buffer), READ_CAST length);
 +        Py_END_ALLOW_THREADS
 +    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +
 +    if (n < 0) {
 +        Py_DECREF(buffer);
 +        return (!async_err) ? posix_error() : NULL;
 +    }
 +
 +    if (n != length)
 +        _PyBytes_Resize(&buffer, n);
 +
 +    return buffer;
 +}
 +
 +#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
 +    || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV)
 +static Py_ssize_t
 +iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
 +{
 +    int i, j;
 +    Py_ssize_t blen, total = 0;
 +
 +    *iov = PyMem_New(struct iovec, cnt);
 +    if (*iov == NULL) {
 +        PyErr_NoMemory();
 +        return -1;
 +    }
 +
 +    *buf = PyMem_New(Py_buffer, cnt);
 +    if (*buf == NULL) {
 +        PyMem_Del(*iov);
 +        PyErr_NoMemory();
 +        return -1;
 +    }
 +
 +    for (i = 0; i < cnt; i++) {
 +        PyObject *item = PySequence_GetItem(seq, i);
 +        if (item == NULL)
 +            goto fail;
 +        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
 +            Py_DECREF(item);
 +            goto fail;
 +        }
 +        Py_DECREF(item);
 +        (*iov)[i].iov_base = (*buf)[i].buf;
 +        blen = (*buf)[i].len;
 +        (*iov)[i].iov_len = blen;
 +        total += blen;
 +    }
 +    return total;
 +
 +fail:
 +    PyMem_Del(*iov);
 +    for (j = 0; j < i; j++) {
 +        PyBuffer_Release(&(*buf)[j]);
 +    }
 +    PyMem_Del(*buf);
 +    return -1;
 +}
 +
 +static void
 +iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
 +{
 +    int i;
 +    PyMem_Del(iov);
 +    for (i = 0; i < cnt; i++) {
 +        PyBuffer_Release(&buf[i]);
 +    }
 +    PyMem_Del(buf);
 +}
 +#endif
 +
 +
 +#ifdef HAVE_READV
 +/*[clinic input]
 +os.readv -> Py_ssize_t
 +
 +    fd: int
 +    buffers: object
 +    /
 +
 +Read from a file descriptor fd into an iterable of buffers.
 +
 +The buffers should be mutable buffers accepting bytes.
 +readv will transfer data into each buffer until it is full
 +and then move on to the next buffer in the sequence to hold
 +the rest of the data.
 +
 +readv returns the total number of bytes read,
 +which may be less than the total capacity of all the buffers.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_readv__doc__,
 +"readv($module, fd, buffers, /)\n"
 +"--\n"
 +"\n"
 +"Read from a file descriptor fd into an iterable of buffers.\n"
 +"\n"
 +"The buffers should be mutable buffers accepting bytes.\n"
 +"readv will transfer data into each buffer until it is full\n"
 +"and then move on to the next buffer in the sequence to hold\n"
 +"the rest of the data.\n"
 +"\n"
 +"readv returns the total number of bytes read,\n"
 +"which may be less than the total capacity of all the buffers.");
 +
 +#define OS_READV_METHODDEF    \
 +    {"readv", (PyCFunction)os_readv, METH_VARARGS, os_readv__doc__},
 +
 +static Py_ssize_t
 +os_readv_impl(PyModuleDef *module, int fd, PyObject *buffers);
 +
 +static PyObject *
 +os_readv(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    PyObject *buffers;
 +    Py_ssize_t _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "iO:readv",
 +        &fd, &buffers))
 +        goto exit;
 +    _return_value = os_readv_impl(module, fd, buffers);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromSsize_t(_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static Py_ssize_t
 +os_readv_impl(PyModuleDef *module, int fd, PyObject *buffers)
 +/*[clinic end generated code: output=72748b1c32a6e2a1 input=e679eb5dbfa0357d]*/
 +{
 +    int cnt;
 +    Py_ssize_t n;
 +    int async_err = 0;
 +    struct iovec *iov;
 +    Py_buffer *buf;
 +
 +    if (!PySequence_Check(buffers)) {
 +        PyErr_SetString(PyExc_TypeError,
 +            "readv() arg 2 must be a sequence");
 +        return -1;
 +    }
 +
 +    cnt = PySequence_Size(buffers);
 +
 +    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
 +        return -1;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        n = readv(fd, iov, cnt);
 +        Py_END_ALLOW_THREADS
 +    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +
 +    iov_cleanup(iov, buf, cnt);
 +    if (n < 0) {
 +        if (!async_err)
 +            posix_error();
 +        return -1;
 +    }
 +
 +    return n;
 +}
 +#endif /* HAVE_READV */
 +
 +
 +#ifdef HAVE_PREAD
 +/*[clinic input]
 +# TODO length should be size_t!  but Python doesn't support parsing size_t yet.
 +os.pread
 +
 +    fd: int
 +    length: int
 +    offset: Py_off_t
 +    /
 +
 +Read a number of bytes from a file descriptor starting at a particular offset.
 +
 +Read length bytes from file descriptor fd, starting at offset bytes from
 +the beginning of the file.  The file offset remains unchanged.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_pread__doc__,
 +"pread($module, fd, length, offset, /)\n"
 +"--\n"
 +"\n"
 +"Read a number of bytes from a file descriptor starting at a particular offset.\n"
 +"\n"
 +"Read length bytes from file descriptor fd, starting at offset bytes from\n"
 +"the beginning of the file.  The file offset remains unchanged.");
 +
 +#define OS_PREAD_METHODDEF    \
 +    {"pread", (PyCFunction)os_pread, METH_VARARGS, os_pread__doc__},
 +
 +static PyObject *
 +os_pread_impl(PyModuleDef *module, int fd, int length, Py_off_t offset);
 +
 +static PyObject *
 +os_pread(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    int length;
 +    Py_off_t offset;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "iiO&:pread",
 +        &fd, &length, Py_off_t_converter, &offset))
 +        goto exit;
 +    return_value = os_pread_impl(module, fd, length, offset);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_pread_impl(PyModuleDef *module, int fd, int length, Py_off_t offset)
 +/*[clinic end generated code: output=7b62bf6c06e20ae8 input=084948dcbaa35d4c]*/
 +{
 +    Py_ssize_t n;
 +    int async_err = 0;
 +    PyObject *buffer;
 +
 +    if (length < 0) {
 +        errno = EINVAL;
 +        return posix_error();
 +    }
 +    buffer = PyBytes_FromStringAndSize((char *)NULL, length);
 +    if (buffer == NULL)
 +        return NULL;
 +    if (!_PyVerify_fd(fd)) {
 +        Py_DECREF(buffer);
 +        return posix_error();
 +    }
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
 +        Py_END_ALLOW_THREADS
 +    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +
 +    if (n < 0) {
 +        Py_DECREF(buffer);
 +        return (!async_err) ? posix_error() : NULL;
 +    }
 +    if (n != length)
 +        _PyBytes_Resize(&buffer, n);
 +    return buffer;
 +}
 +#endif /* HAVE_PREAD */
 +
 +
 +/*[clinic input]
 +os.write -> Py_ssize_t
 +
 +    fd: int
 +    data: Py_buffer
 +    /
 +
 +Write a bytes object to a file descriptor.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_write__doc__,
 +"write($module, fd, data, /)\n"
 +"--\n"
 +"\n"
 +"Write a bytes object to a file descriptor.");
 +
 +#define OS_WRITE_METHODDEF    \
 +    {"write", (PyCFunction)os_write, METH_VARARGS, os_write__doc__},
 +
 +static Py_ssize_t
 +os_write_impl(PyModuleDef *module, int fd, Py_buffer *data);
 +
 +static PyObject *
 +os_write(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    Py_buffer data = {NULL, NULL};
 +    Py_ssize_t _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "iy*:write",
 +        &fd, &data))
 +        goto exit;
 +    _return_value = os_write_impl(module, fd, &data);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromSsize_t(_return_value);
 +
 +exit:
 +    /* Cleanup for data */
 +    if (data.obj)
 +       PyBuffer_Release(&data);
 +
 +    return return_value;
 +}
 +
 +static Py_ssize_t
 +os_write_impl(PyModuleDef *module, int fd, Py_buffer *data)
 +/*[clinic end generated code: output=aeb96acfdd4d5112 input=3207e28963234f3c]*/
 +{
 +    Py_ssize_t size;
 +    int async_err = 0;
 +    Py_ssize_t len = data->len;
 +
 +    if (!_PyVerify_fd(fd)) {
 +        posix_error();
 +        return -1;
 +    }
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +#ifdef MS_WINDOWS
 +        if (len > INT_MAX)
 +            len = INT_MAX;
 +        size = write(fd, data->buf, (int)len);
 +#else
 +        size = write(fd, data->buf, len);
 +#endif
 +        Py_END_ALLOW_THREADS
 +    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +
 +    if (size < 0) {
 +        if (!async_err)
 +            posix_error();
 +        return -1;
 +    }
 +    return size;
 +}
 +
 +#ifdef HAVE_SENDFILE
 +PyDoc_STRVAR(posix_sendfile__doc__,
 +"sendfile(out, in, offset, nbytes) -> byteswritten\n\
 +sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\
 +            -> byteswritten\n\
 +Copy nbytes bytes from file descriptor in to file descriptor out.");
 +
 +/* AC 3.5: don't bother converting, has optional group*/
 +static PyObject *
 +posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
 +{
 +    int in, out;
 +    Py_ssize_t ret;
 +    int async_err = 0;
 +    off_t offset;
 +
 +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
 +#ifndef __APPLE__
 +    Py_ssize_t len;
 +#endif
 +    PyObject *headers = NULL, *trailers = NULL;
 +    Py_buffer *hbuf, *tbuf;
 +    off_t sbytes;
 +    struct sf_hdtr sf;
 +    int flags = 0;
 +    static char *keywords[] = {"out", "in",
 +                                "offset", "count",
 +                                "headers", "trailers", "flags", NULL};
 +
 +    sf.headers = NULL;
 +    sf.trailers = NULL;
 +
 +#ifdef __APPLE__
 +    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
 +        keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes,
 +#else
 +    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
 +        keywords, &out, &in, Py_off_t_converter, &offset, &len,
 +#endif
 +                &headers, &trailers, &flags))
 +            return NULL;
 +    if (headers != NULL) {
 +        if (!PySequence_Check(headers)) {
 +            PyErr_SetString(PyExc_TypeError,
 +                "sendfile() headers must be a sequence or None");
 +            return NULL;
 +        } else {
 +            Py_ssize_t i = 0; /* Avoid uninitialized warning */
 +            sf.hdr_cnt = PySequence_Size(headers);
 +            if (sf.hdr_cnt > 0 &&
 +                (i = iov_setup(&(sf.headers), &hbuf,
 +                                headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0)
 +                return NULL;
 +#ifdef __APPLE__
 +            sbytes += i;
 +#endif
 +        }
 +    }
 +    if (trailers != NULL) {
 +        if (!PySequence_Check(trailers)) {
 +            PyErr_SetString(PyExc_TypeError,
 +                "sendfile() trailers must be a sequence or None");
 +            return NULL;
 +        } else {
 +            Py_ssize_t i = 0; /* Avoid uninitialized warning */
 +            sf.trl_cnt = PySequence_Size(trailers);
 +            if (sf.trl_cnt > 0 &&
 +                (i = iov_setup(&(sf.trailers), &tbuf,
 +                                trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0)
 +                return NULL;
 +#ifdef __APPLE__
 +            sbytes += i;
 +#endif
 +        }
 +    }
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +#ifdef __APPLE__
 +        ret = sendfile(in, out, offset, &sbytes, &sf, flags);
 +#else
 +        ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
 +#endif
 +        Py_END_ALLOW_THREADS
 +    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +
 +    if (sf.headers != NULL)
 +        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
 +    if (sf.trailers != NULL)
 +        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
 +
 +    if (ret < 0) {
 +        if ((errno == EAGAIN) || (errno == EBUSY)) {
 +            if (sbytes != 0) {
 +                // some data has been sent
 +                goto done;
 +            }
 +            else {
 +                // no data has been sent; upper application is supposed
 +                // to retry on EAGAIN or EBUSY
 +                return posix_error();
 +            }
 +        }
 +        return (!async_err) ? posix_error() : NULL;
 +    }
 +    goto done;
 +
 +done:
 +    #if !defined(HAVE_LARGEFILE_SUPPORT)
 +        return Py_BuildValue("l", sbytes);
 +    #else
 +        return Py_BuildValue("L", sbytes);
 +    #endif
 +
 +#else
 +    Py_ssize_t count;
 +    PyObject *offobj;
 +    static char *keywords[] = {"out", "in",
 +                                "offset", "count", NULL};
 +    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
 +            keywords, &out, &in, &offobj, &count))
 +        return NULL;
 +#ifdef linux
 +    if (offobj == Py_None) {
 +        do {
 +            Py_BEGIN_ALLOW_THREADS
 +            ret = sendfile(out, in, NULL, count);
 +            Py_END_ALLOW_THREADS
 +        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +        if (ret < 0)
 +            return (!async_err) ? posix_error() : NULL;
 +        return Py_BuildValue("n", ret);
 +    }
 +#endif
 +    if (!Py_off_t_converter(offobj, &offset))
 +        return NULL;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        ret = sendfile(out, in, &offset, count);
 +        Py_END_ALLOW_THREADS
 +    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +    if (ret < 0)
 +        return (!async_err) ? posix_error() : NULL;
 +    return Py_BuildValue("n", ret);
 +#endif
 +}
 +#endif /* HAVE_SENDFILE */
 +
 +
 +/*[clinic input]
 +os.fstat
 +
 +    fd : int
 +
 +Perform a stat system call on the given file descriptor.
 +
 +Like stat(), but for an open file descriptor.
 +Equivalent to os.stat(fd).
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_fstat__doc__,
 +"fstat($module, /, fd)\n"
 +"--\n"
 +"\n"
 +"Perform a stat system call on the given file descriptor.\n"
 +"\n"
 +"Like stat(), but for an open file descriptor.\n"
 +"Equivalent to os.stat(fd).");
 +
 +#define OS_FSTAT_METHODDEF    \
 +    {"fstat", (PyCFunction)os_fstat, METH_VARARGS|METH_KEYWORDS, os_fstat__doc__},
 +
 +static PyObject *
 +os_fstat_impl(PyModuleDef *module, int fd);
 +
 +static PyObject *
 +os_fstat(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"fd", NULL};
 +    int fd;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "i:fstat", _keywords,
 +        &fd))
 +        goto exit;
 +    return_value = os_fstat_impl(module, fd);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_fstat_impl(PyModuleDef *module, int fd)
 +/*[clinic end generated code: output=dae4a9678c7bd881 input=27e0e0ebbe5600c9]*/
 +{
 +    STRUCT_STAT st;
 +    int res;
 +    int async_err = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        res = FSTAT(fd, &st);
 +        Py_END_ALLOW_THREADS
 +    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +    if (res != 0) {
 +#ifdef MS_WINDOWS
 +        return PyErr_SetFromWindowsErr(0);
 +#else
 +        return (!async_err) ? posix_error() : NULL;
 +#endif
 +    }
 +
 +    return _pystat_fromstructstat(&st);
 +}
 +
 +
 +/*[clinic input]
 +os.isatty -> bool
 +    fd: int
 +    /
 +
 +Return True if the fd is connected to a terminal.
 +
 +Return True if the file descriptor is an open file descriptor
 +connected to the slave end of a terminal.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_isatty__doc__,
 +"isatty($module, fd, /)\n"
 +"--\n"
 +"\n"
 +"Return True if the fd is connected to a terminal.\n"
 +"\n"
 +"Return True if the file descriptor is an open file descriptor\n"
 +"connected to the slave end of a terminal.");
 +
 +#define OS_ISATTY_METHODDEF    \
 +    {"isatty", (PyCFunction)os_isatty, METH_VARARGS, os_isatty__doc__},
 +
 +static int
 +os_isatty_impl(PyModuleDef *module, int fd);
 +
 +static PyObject *
 +os_isatty(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    int _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "i:isatty",
 +        &fd))
 +        goto exit;
 +    _return_value = os_isatty_impl(module, fd);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyBool_FromLong((long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static int
 +os_isatty_impl(PyModuleDef *module, int fd)
 +/*[clinic end generated code: output=4bfadbfe22715097 input=08ce94aa1eaf7b5e]*/
 +{
 +    if (!_PyVerify_fd(fd))
 +        return 0;
 +    return isatty(fd);
 +}
 +
 +
 +#ifdef HAVE_PIPE
 +/*[clinic input]
 +os.pipe
 +
 +Create a pipe.
 +
 +Returns a tuple of two file descriptors:
 +  (read_fd, write_fd)
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_pipe__doc__,
 +"pipe($module, /)\n"
 +"--\n"
 +"\n"
 +"Create a pipe.\n"
 +"\n"
 +"Returns a tuple of two file descriptors:\n"
 +"  (read_fd, write_fd)");
 +
 +#define OS_PIPE_METHODDEF    \
 +    {"pipe", (PyCFunction)os_pipe, METH_NOARGS, os_pipe__doc__},
 +
 +static PyObject *
 +os_pipe_impl(PyModuleDef *module);
 +
 +static PyObject *
 +os_pipe(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
 +{
 +    return os_pipe_impl(module);
 +}
 +
 +static PyObject *
 +os_pipe_impl(PyModuleDef *module)
 +/*[clinic end generated code: output=0da2479f2266e774 input=02535e8c8fa6c4d4]*/
 +{
 +    int fds[2];
 +#ifdef MS_WINDOWS
 +    HANDLE read, write;
 +    SECURITY_ATTRIBUTES attr;
 +    BOOL ok;
 +#else
 +    int res;
 +#endif
 +
 +#ifdef MS_WINDOWS
 +    attr.nLength = sizeof(attr);
 +    attr.lpSecurityDescriptor = NULL;
 +    attr.bInheritHandle = FALSE;
 +
 +    Py_BEGIN_ALLOW_THREADS
 +    ok = CreatePipe(&read, &write, &attr, 0);
 +    if (ok) {
 +        fds[0] = _open_osfhandle((Py_intptr_t)read, _O_RDONLY);
 +        fds[1] = _open_osfhandle((Py_intptr_t)write, _O_WRONLY);
 +        if (fds[0] == -1 || fds[1] == -1) {
 +            CloseHandle(read);
 +            CloseHandle(write);
 +            ok = 0;
 +        }
 +    }
 +    Py_END_ALLOW_THREADS
 +
 +    if (!ok)
 +        return PyErr_SetFromWindowsErr(0);
 +#else
 +
 +#ifdef HAVE_PIPE2
 +    Py_BEGIN_ALLOW_THREADS
 +    res = pipe2(fds, O_CLOEXEC);
 +    Py_END_ALLOW_THREADS
 +
 +    if (res != 0 && errno == ENOSYS)
 +    {
 +#endif
 +        Py_BEGIN_ALLOW_THREADS
 +        res = pipe(fds);
 +        Py_END_ALLOW_THREADS
 +
 +        if (res == 0) {
 +            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
 +                close(fds[0]);
 +                close(fds[1]);
 +                return NULL;
 +            }
 +            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
 +                close(fds[0]);
 +                close(fds[1]);
 +                return NULL;
 +            }
 +        }
 +#ifdef HAVE_PIPE2
 +    }
 +#endif
 +
 +    if (res != 0)
 +        return PyErr_SetFromErrno(PyExc_OSError);
 +#endif /* !MS_WINDOWS */
 +    return Py_BuildValue("(ii)", fds[0], fds[1]);
 +}
 +#endif  /* HAVE_PIPE */
 +
 +
 +#ifdef HAVE_PIPE2
 +/*[clinic input]
 +os.pipe2
 +
 +    flags: int
 +    /
 +
 +Create a pipe with flags set atomically.
 +
 +Returns a tuple of two file descriptors:
 +  (read_fd, write_fd)
 +
 +flags can be constructed by ORing together one or more of these values:
 +O_NONBLOCK, O_CLOEXEC.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_pipe2__doc__,
 +"pipe2($module, flags, /)\n"
 +"--\n"
 +"\n"
 +"Create a pipe with flags set atomically.\n"
 +"\n"
 +"Returns a tuple of two file descriptors:\n"
 +"  (read_fd, write_fd)\n"
 +"\n"
 +"flags can be constructed by ORing together one or more of these values:\n"
 +"O_NONBLOCK, O_CLOEXEC.");
 +
 +#define OS_PIPE2_METHODDEF    \
 +    {"pipe2", (PyCFunction)os_pipe2, METH_VARARGS, os_pipe2__doc__},
 +
 +static PyObject *
 +os_pipe2_impl(PyModuleDef *module, int flags);
 +
 +static PyObject *
 +os_pipe2(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int flags;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "i:pipe2",
 +        &flags))
 +        goto exit;
 +    return_value = os_pipe2_impl(module, flags);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_pipe2_impl(PyModuleDef *module, int flags)
 +/*[clinic end generated code: output=9e27c799ce19220b input=f261b6e7e63c6817]*/
 +{
 +    int fds[2];
 +    int res;
 +
 +    res = pipe2(fds, flags);
 +    if (res != 0)
 +        return posix_error();
 +    return Py_BuildValue("(ii)", fds[0], fds[1]);
 +}
 +#endif /* HAVE_PIPE2 */
 +
 +
 +#ifdef HAVE_WRITEV
 +/*[clinic input]
 +os.writev -> Py_ssize_t
 +    fd: int
 +    buffers: object
 +    /
 +
 +Iterate over buffers, and write the contents of each to a file descriptor.
 +
 +Returns the total number of bytes written.
 +buffers must be a sequence of bytes-like objects.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_writev__doc__,
 +"writev($module, fd, buffers, /)\n"
 +"--\n"
 +"\n"
 +"Iterate over buffers, and write the contents of each to a file descriptor.\n"
 +"\n"
 +"Returns the total number of bytes written.\n"
 +"buffers must be a sequence of bytes-like objects.");
 +
 +#define OS_WRITEV_METHODDEF    \
 +    {"writev", (PyCFunction)os_writev, METH_VARARGS, os_writev__doc__},
 +
 +static Py_ssize_t
 +os_writev_impl(PyModuleDef *module, int fd, PyObject *buffers);
 +
 +static PyObject *
 +os_writev(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    PyObject *buffers;
 +    Py_ssize_t _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "iO:writev",
 +        &fd, &buffers))
 +        goto exit;
 +    _return_value = os_writev_impl(module, fd, buffers);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromSsize_t(_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static Py_ssize_t
 +os_writev_impl(PyModuleDef *module, int fd, PyObject *buffers)
 +/*[clinic end generated code: output=591c662dccbe4951 input=5b8d17fe4189d2fe]*/
 +{
 +    int cnt;
 +    Py_ssize_t result;
 +    int async_err = 0;
 +    struct iovec *iov;
 +    Py_buffer *buf;
 +
 +    if (!PySequence_Check(buffers)) {
 +        PyErr_SetString(PyExc_TypeError,
 +            "writev() arg 2 must be a sequence");
 +        return -1;
 +    }
 +    cnt = PySequence_Size(buffers);
 +
 +    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
 +        return -1;
 +    }
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        result = writev(fd, iov, cnt);
 +        Py_END_ALLOW_THREADS
 +    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +
 +    iov_cleanup(iov, buf, cnt);
 +    if (result < 0 && !async_err)
 +        posix_error();
 +
 +    return result;
 +}
 +#endif /* HAVE_WRITEV */
 +
 +
 +#ifdef HAVE_PWRITE
 +/*[clinic input]
 +os.pwrite -> Py_ssize_t
 +
 +    fd: int
 +    buffer: Py_buffer
 +    offset: Py_off_t
 +    /
 +
 +Write bytes to a file descriptor starting at a particular offset.
 +
 +Write buffer to fd, starting at offset bytes from the beginning of
 +the file.  Returns the number of bytes writte.  Does not change the
 +current file offset.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_pwrite__doc__,
 +"pwrite($module, fd, buffer, offset, /)\n"
 +"--\n"
 +"\n"
 +"Write bytes to a file descriptor starting at a particular offset.\n"
 +"\n"
 +"Write buffer to fd, starting at offset bytes from the beginning of\n"
 +"the file.  Returns the number of bytes writte.  Does not change the\n"
 +"current file offset.");
 +
 +#define OS_PWRITE_METHODDEF    \
 +    {"pwrite", (PyCFunction)os_pwrite, METH_VARARGS, os_pwrite__doc__},
 +
 +static Py_ssize_t
 +os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset);
 +
 +static PyObject *
 +os_pwrite(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    Py_buffer buffer = {NULL, NULL};
 +    Py_off_t offset;
 +    Py_ssize_t _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "iy*O&:pwrite",
 +        &fd, &buffer, Py_off_t_converter, &offset))
 +        goto exit;
 +    _return_value = os_pwrite_impl(module, fd, &buffer, offset);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromSsize_t(_return_value);
 +
 +exit:
 +    /* Cleanup for buffer */
 +    if (buffer.obj)
 +       PyBuffer_Release(&buffer);
 +
 +    return return_value;
 +}
 +
 +static Py_ssize_t
 +os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset)
 +/*[clinic end generated code: output=ec9cc5b2238e96a7 input=19903f1b3dd26377]*/
 +{
 +    Py_ssize_t size;
 +    int async_err = 0;
 +
 +    if (!_PyVerify_fd(fd)) {
 +        posix_error();
 +        return -1;
 +    }
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
 +        Py_END_ALLOW_THREADS
 +    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
 +
 +    if (size < 0 && !async_err)
 +        posix_error();
 +    return size;
 +}
 +#endif /* HAVE_PWRITE */
 +
 +
 +#ifdef HAVE_MKFIFO
 +/*[clinic input]
 +os.mkfifo
 +
 +    path: path_t
 +    mode: int=0o666
 +    *
 +    dir_fd: dir_fd(requires='mkfifoat')=None
 +
 +Create a "fifo" (a POSIX named pipe).
 +
 +If dir_fd is not None, it should be a file descriptor open to a directory,
 +  and path should be relative; path will then be relative to that directory.
 +dir_fd may not be implemented on your platform.
 +  If it is unavailable, using it will raise a NotImplementedError.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_mkfifo__doc__,
 +"mkfifo($module, /, path, mode=438, *, dir_fd=None)\n"
 +"--\n"
 +"\n"
 +"Create a \"fifo\" (a POSIX named pipe).\n"
 +"\n"
 +"If dir_fd is not None, it should be a file descriptor open to a directory,\n"
 +"  and path should be relative; path will then be relative to that directory.\n"
 +"dir_fd may not be implemented on your platform.\n"
 +"  If it is unavailable, using it will raise a NotImplementedError.");
 +
 +#define OS_MKFIFO_METHODDEF    \
 +    {"mkfifo", (PyCFunction)os_mkfifo, METH_VARARGS|METH_KEYWORDS, os_mkfifo__doc__},
 +
 +static PyObject *
 +os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd);
 +
 +static PyObject *
 +os_mkfifo(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"path", "mode", "dir_fd", NULL};
 +    path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0);
 +    int mode = 438;
 +    int dir_fd = DEFAULT_DIR_FD;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "O&|i$O&:mkfifo", _keywords,
 +        path_converter, &path, &mode, MKFIFOAT_DIR_FD_CONVERTER, &dir_fd))
 +        goto exit;
 +    return_value = os_mkfifo_impl(module, &path, mode, dir_fd);
 +
 +exit:
 +    /* Cleanup for path */
 +    path_cleanup(&path);
 +
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd)
 +/*[clinic end generated code: output=b3321927546893d0 input=73032e98a36e0e19]*/
 +{
 +    int result;
 +    int async_err = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +#ifdef HAVE_MKFIFOAT
 +        if (dir_fd != DEFAULT_DIR_FD)
 +            result = mkfifoat(dir_fd, path->narrow, mode);
 +        else
 +#endif
 +            result = mkfifo(path->narrow, mode);
 +        Py_END_ALLOW_THREADS
 +    } while (result != 0 && errno == EINTR &&
 +             !(async_err = PyErr_CheckSignals()));
 +    if (result != 0)
 +        return (!async_err) ? posix_error() : NULL;
 +
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_MKFIFO */
 +
 +
 +#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
 +/*[clinic input]
 +os.mknod
 +
 +    path: path_t
 +    mode: int=0o600
 +    device: dev_t=0
 +    *
 +    dir_fd: dir_fd(requires='mknodat')=None
 +
 +Create a node in the file system.
 +
 +Create a node in the file system (file, device special file or named pipe)
 +at path.  mode specifies both the permissions to use and the
 +type of node to be created, being combined (bitwise OR) with one of
 +S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
 +device defines the newly created device special file (probably using
 +os.makedev()).  Otherwise device is ignored.
 +
 +If dir_fd is not None, it should be a file descriptor open to a directory,
 +  and path should be relative; path will then be relative to that directory.
 +dir_fd may not be implemented on your platform.
 +  If it is unavailable, using it will raise a NotImplementedError.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_mknod__doc__,
 +"mknod($module, /, path, mode=384, device=0, *, dir_fd=None)\n"
 +"--\n"
 +"\n"
 +"Create a node in the file system.\n"
 +"\n"
 +"Create a node in the file system (file, device special file or named pipe)\n"
 +"at path.  mode specifies both the permissions to use and the\n"
 +"type of node to be created, being combined (bitwise OR) with one of\n"
 +"S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,\n"
 +"device defines the newly created device special file (probably using\n"
 +"os.makedev()).  Otherwise device is ignored.\n"
 +"\n"
 +"If dir_fd is not None, it should be a file descriptor open to a directory,\n"
 +"  and path should be relative; path will then be relative to that directory.\n"
 +"dir_fd may not be implemented on your platform.\n"
 +"  If it is unavailable, using it will raise a NotImplementedError.");
 +
 +#define OS_MKNOD_METHODDEF    \
 +    {"mknod", (PyCFunction)os_mknod, METH_VARARGS|METH_KEYWORDS, os_mknod__doc__},
 +
 +static PyObject *
 +os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd);
 +
 +static PyObject *
 +os_mknod(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"path", "mode", "device", "dir_fd", NULL};
 +    path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0);
 +    int mode = 384;
 +    dev_t device = 0;
 +    int dir_fd = DEFAULT_DIR_FD;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "O&|iO&$O&:mknod", _keywords,
 +        path_converter, &path, &mode, _Py_Dev_Converter, &device, MKNODAT_DIR_FD_CONVERTER, &dir_fd))
 +        goto exit;
 +    return_value = os_mknod_impl(module, &path, mode, device, dir_fd);
 +
 +exit:
 +    /* Cleanup for path */
 +    path_cleanup(&path);
 +
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd)
 +/*[clinic end generated code: output=f71d54eaf9bb6f1a input=ee44531551a4d83b]*/
 +{
 +    int result;
 +    int async_err = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +#ifdef HAVE_MKNODAT
 +        if (dir_fd != DEFAULT_DIR_FD)
 +            result = mknodat(dir_fd, path->narrow, mode, device);
 +        else
 +#endif
 +            result = mknod(path->narrow, mode, device);
 +        Py_END_ALLOW_THREADS
 +    } while (result != 0 && errno == EINTR &&
 +             !(async_err = PyErr_CheckSignals()));
 +    if (result != 0)
 +        return (!async_err) ? posix_error() : NULL;
 +
 +    Py_RETURN_NONE;
 +}
 +#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
 +
 +
 +#ifdef HAVE_DEVICE_MACROS
 +/*[clinic input]
 +os.major -> unsigned_int
 +
 +    device: dev_t
 +    /
 +
 +Extracts a device major number from a raw device number.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_major__doc__,
 +"major($module, device, /)\n"
 +"--\n"
 +"\n"
 +"Extracts a device major number from a raw device number.");
 +
 +#define OS_MAJOR_METHODDEF    \
 +    {"major", (PyCFunction)os_major, METH_VARARGS, os_major__doc__},
 +
 +static unsigned int
 +os_major_impl(PyModuleDef *module, dev_t device);
 +
 +static PyObject *
 +os_major(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    dev_t device;
 +    unsigned int _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "O&:major",
 +        _Py_Dev_Converter, &device))
 +        goto exit;
 +    _return_value = os_major_impl(module, device);
 +    if ((_return_value == (unsigned int)-1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromUnsignedLong((unsigned long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static unsigned int
 +os_major_impl(PyModuleDef *module, dev_t device)
 +/*[clinic end generated code: output=a2d06e908ebf95b5 input=1e16a4d30c4d4462]*/
 +{
 +    return major(device);
 +}
 +
 +
 +/*[clinic input]
 +os.minor -> unsigned_int
 +
 +    device: dev_t
 +    /
 +
 +Extracts a device minor number from a raw device number.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_minor__doc__,
 +"minor($module, device, /)\n"
 +"--\n"
 +"\n"
 +"Extracts a device minor number from a raw device number.");
 +
 +#define OS_MINOR_METHODDEF    \
 +    {"minor", (PyCFunction)os_minor, METH_VARARGS, os_minor__doc__},
 +
 +static unsigned int
 +os_minor_impl(PyModuleDef *module, dev_t device);
 +
 +static PyObject *
 +os_minor(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    dev_t device;
 +    unsigned int _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "O&:minor",
 +        _Py_Dev_Converter, &device))
 +        goto exit;
 +    _return_value = os_minor_impl(module, device);
 +    if ((_return_value == (unsigned int)-1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromUnsignedLong((unsigned long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static unsigned int
 +os_minor_impl(PyModuleDef *module, dev_t device)
 +/*[clinic end generated code: output=6332287ee3f006e2 input=0842c6d23f24c65e]*/
 +{
 +    return minor(device);
 +}
 +
 +
 +/*[clinic input]
 +os.makedev -> dev_t
 +
 +    major: int
 +    minor: int
 +    /
 +
 +Composes a raw device number from the major and minor device numbers.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_makedev__doc__,
 +"makedev($module, major, minor, /)\n"
 +"--\n"
 +"\n"
 +"Composes a raw device number from the major and minor device numbers.");
 +
 +#define OS_MAKEDEV_METHODDEF    \
 +    {"makedev", (PyCFunction)os_makedev, METH_VARARGS, os_makedev__doc__},
 +
 +static dev_t
 +os_makedev_impl(PyModuleDef *module, int major, int minor);
 +
 +static PyObject *
 +os_makedev(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int major;
 +    int minor;
 +    dev_t _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "ii:makedev",
 +        &major, &minor))
 +        goto exit;
 +    _return_value = os_makedev_impl(module, major, minor);
 +    if ((_return_value == (dev_t)-1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = _PyLong_FromDev(_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static dev_t
 +os_makedev_impl(PyModuleDef *module, int major, int minor)
 +/*[clinic end generated code: output=38e9a9774c96511a input=4b9fd8fc73cbe48f]*/
 +{
 +    return makedev(major, minor);
 +}
 +#endif /* HAVE_DEVICE_MACROS */
 +
 +
 +#ifdef HAVE_FTRUNCATE
 +/*[clinic input]
 +os.ftruncate
 +
 +    fd: int
 +    length: Py_off_t
 +    /
 +
 +Truncate a file, specified by file descriptor, to a specific length.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_ftruncate__doc__,
 +"ftruncate($module, fd, length, /)\n"
 +"--\n"
 +"\n"
 +"Truncate a file, specified by file descriptor, to a specific length.");
 +
 +#define OS_FTRUNCATE_METHODDEF    \
 +    {"ftruncate", (PyCFunction)os_ftruncate, METH_VARARGS, os_ftruncate__doc__},
 +
 +static PyObject *
 +os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length);
 +
 +static PyObject *
 +os_ftruncate(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    Py_off_t length;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "iO&:ftruncate",
 +        &fd, Py_off_t_converter, &length))
 +        goto exit;
 +    return_value = os_ftruncate_impl(module, fd, length);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length)
 +/*[clinic end generated code: output=62326766cb9b76bf input=63b43641e52818f2]*/
 +{
 +    int result;
 +    int async_err = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        result = ftruncate(fd, length);
 +        Py_END_ALLOW_THREADS
 +    } while (result != 0 && errno == EINTR &&
 +             !(async_err = PyErr_CheckSignals()));
 +    if (result != 0)
 +        return (!async_err) ? posix_error() : NULL;
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_FTRUNCATE */
 +
 +
 +#ifdef HAVE_TRUNCATE
 +/*[clinic input]
 +os.truncate
 +    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
 +    length: Py_off_t
 +
 +Truncate a file, specified by path, to a specific length.
 +
 +On some platforms, path may also be specified as an open file descriptor.
 +  If this functionality is unavailable, using it raises an exception.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_truncate__doc__,
 +"truncate($module, /, path, length)\n"
 +"--\n"
 +"\n"
 +"Truncate a file, specified by path, to a specific length.\n"
 +"\n"
 +"On some platforms, path may also be specified as an open file descriptor.\n"
 +"  If this functionality is unavailable, using it raises an exception.");
 +
 +#define OS_TRUNCATE_METHODDEF    \
 +    {"truncate", (PyCFunction)os_truncate, METH_VARARGS|METH_KEYWORDS, os_truncate__doc__},
 +
 +static PyObject *
 +os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length);
 +
 +static PyObject *
 +os_truncate(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"path", "length", NULL};
 +    path_t path = PATH_T_INITIALIZE("truncate", "path", 0, PATH_HAVE_FTRUNCATE);
 +    Py_off_t length;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "O&O&:truncate", _keywords,
 +        path_converter, &path, Py_off_t_converter, &length))
 +        goto exit;
 +    return_value = os_truncate_impl(module, &path, length);
 +
 +exit:
 +    /* Cleanup for path */
 +    path_cleanup(&path);
 +
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length)
 +/*[clinic end generated code: output=6bd76262d2e027c6 input=77229cf0b50a9b77]*/
 +{
 +    int result;
 +
 +    Py_BEGIN_ALLOW_THREADS
 +#ifdef HAVE_FTRUNCATE
 +    if (path->fd != -1)
 +        result = ftruncate(path->fd, length);
 +    else
 +#endif
 +        result = truncate(path->narrow, length);
 +    Py_END_ALLOW_THREADS
 +    if (result < 0)
 +        return path_error(path);
 +
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_TRUNCATE */
 +
 +
 +/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
 +   and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
 +   defined, which is the case in Python on AIX. AIX bug report:
 +   http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
 +#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
 +#  define POSIX_FADVISE_AIX_BUG
 +#endif
 +
 +
 +#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
 +/*[clinic input]
 +os.posix_fallocate
 +
 +    fd: int
 +    offset: Py_off_t
 +    length: Py_off_t
 +    /
 +
 +Ensure a file has allocated at least a particular number of bytes on disk.
 +
 +Ensure that the file specified by fd encompasses a range of bytes
 +starting at offset bytes from the beginning and continuing for length bytes.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_posix_fallocate__doc__,
 +"posix_fallocate($module, fd, offset, length, /)\n"
 +"--\n"
 +"\n"
 +"Ensure a file has allocated at least a particular number of bytes on disk.\n"
 +"\n"
 +"Ensure that the file specified by fd encompasses a range of bytes\n"
 +"starting at offset bytes from the beginning and continuing for length bytes.");
 +
 +#define OS_POSIX_FALLOCATE_METHODDEF    \
 +    {"posix_fallocate", (PyCFunction)os_posix_fallocate, METH_VARARGS, os_posix_fallocate__doc__},
 +
 +static PyObject *
 +os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length);
 +
 +static PyObject *
 +os_posix_fallocate(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    Py_off_t offset;
 +    Py_off_t length;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "iO&O&:posix_fallocate",
 +        &fd, Py_off_t_converter, &offset, Py_off_t_converter, &length))
 +        goto exit;
 +    return_value = os_posix_fallocate_impl(module, fd, offset, length);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length)
 +/*[clinic end generated code: output=0cd702d2065c79db input=d7a2ef0ab2ca52fb]*/
 +{
 +    int result;
 +    int async_err = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        result = posix_fallocate(fd, offset, length);
 +        Py_END_ALLOW_THREADS
 +    } while (result != 0 && errno == EINTR &&
 +             !(async_err = PyErr_CheckSignals()));
 +    if (result != 0)
 +        return (!async_err) ? posix_error() : NULL;
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
 +
 +
 +#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
 +/*[clinic input]
 +os.posix_fadvise
 +
 +    fd: int
 +    offset: Py_off_t
 +    length: Py_off_t
 +    advice: int
 +    /
 +
 +Announce an intention to access data in a specific pattern.
 +
 +Announce an intention to access data in a specific pattern, thus allowing
 +the kernel to make optimizations.
 +The advice applies to the region of the file specified by fd starting at
 +offset and continuing for length bytes.
 +advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
 +POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
 +POSIX_FADV_DONTNEED.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_posix_fadvise__doc__,
 +"posix_fadvise($module, fd, offset, length, advice, /)\n"
 +"--\n"
 +"\n"
 +"Announce an intention to access data in a specific pattern.\n"
 +"\n"
 +"Announce an intention to access data in a specific pattern, thus allowing\n"
 +"the kernel to make optimizations.\n"
 +"The advice applies to the region of the file specified by fd starting at\n"
 +"offset and continuing for length bytes.\n"
 +"advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n"
 +"POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or\n"
 +"POSIX_FADV_DONTNEED.");
 +
 +#define OS_POSIX_FADVISE_METHODDEF    \
 +    {"posix_fadvise", (PyCFunction)os_posix_fadvise, METH_VARARGS, os_posix_fadvise__doc__},
 +
 +static PyObject *
 +os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice);
 +
 +static PyObject *
 +os_posix_fadvise(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    Py_off_t offset;
 +    Py_off_t length;
 +    int advice;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "iO&O&i:posix_fadvise",
 +        &fd, Py_off_t_converter, &offset, Py_off_t_converter, &length, &advice))
 +        goto exit;
 +    return_value = os_posix_fadvise_impl(module, fd, offset, length, advice);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice)
 +/*[clinic end generated code: output=dad93f32c04dd4f7 input=0fbe554edc2f04b5]*/
 +{
 +    int result;
 +    int async_err = 0;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        result = posix_fadvise(fd, offset, length, advice);
 +        Py_END_ALLOW_THREADS
 +    } while (result != 0 && errno == EINTR &&
 +             !(async_err = PyErr_CheckSignals()));
 +    if (result != 0)
 +        return (!async_err) ? posix_error() : NULL;
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
 +
 +#ifdef HAVE_PUTENV
 +
 +/* Save putenv() parameters as values here, so we can collect them when they
 + * get re-set with another call for the same key. */
 +static PyObject *posix_putenv_garbage;
 +
 +static void
 +posix_putenv_garbage_setitem(PyObject *name, PyObject *value)
 +{
 +    /* Install the first arg and newstr in posix_putenv_garbage;
 +     * this will cause previous value to be collected.  This has to
 +     * happen after the real putenv() call because the old value
 +     * was still accessible until then. */
 +    if (PyDict_SetItem(posix_putenv_garbage, name, value))
 +        /* really not much we can do; just leak */
 +        PyErr_Clear();
 +    else
 +        Py_DECREF(value);
 +}
 +
 +
 +#ifdef MS_WINDOWS
 +/*[clinic input]
 +os.putenv
 +
 +    name: unicode
 +    value: unicode
 +    /
 +
 +Change or add an environment variable.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_putenv__doc__,
 +"putenv($module, name, value, /)\n"
 +"--\n"
 +"\n"
 +"Change or add an environment variable.");
 +
 +#define OS_PUTENV_METHODDEF    \
 +    {"putenv", (PyCFunction)os_putenv, METH_VARARGS, os_putenv__doc__},
 +
 +static PyObject *
 +os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value);
 +
 +static PyObject *
 +os_putenv(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    PyObject *name;
 +    PyObject *value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "UU:putenv",
 +        &name, &value))
 +        goto exit;
 +    return_value = os_putenv_impl(module, name, value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value)
 +/*[clinic end generated code: output=5ce9ef9b15606e7e input=ba586581c2e6105f]*/
 +{
 +    wchar_t *env;
 +
 +    PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value);
 +    if (unicode == NULL) {
 +        PyErr_NoMemory();
 +        return NULL;
 +    }
 +    if (_MAX_ENV < PyUnicode_GET_LENGTH(unicode)) {
 +        PyErr_Format(PyExc_ValueError,
 +                     "the environment variable is longer than %u characters",
 +                     _MAX_ENV);
 +        goto error;
 +    }
 +
 +    env = PyUnicode_AsUnicode(unicode);
 +    if (env == NULL)
 +        goto error;
 +    if (_wputenv(env)) {
 +        posix_error();
 +        goto error;
 +    }
 +
 +    posix_putenv_garbage_setitem(name, unicode);
 +    Py_RETURN_NONE;
 +
 +error:
 +    Py_DECREF(unicode);
 +    return NULL;
 +}
 +#else /* MS_WINDOWS */
 +/*[clinic input]
 +os.putenv
 +
 +    name: FSConverter
 +    value: FSConverter
 +    /
 +
 +Change or add an environment variable.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_putenv__doc__,
 +"putenv($module, name, value, /)\n"
 +"--\n"
 +"\n"
 +"Change or add an environment variable.");
 +
 +#define OS_PUTENV_METHODDEF    \
 +    {"putenv", (PyCFunction)os_putenv, METH_VARARGS, os_putenv__doc__},
 +
 +static PyObject *
 +os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value);
 +
 +static PyObject *
 +os_putenv(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    PyObject *name = NULL;
 +    PyObject *value = NULL;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "O&O&:putenv",
 +        PyUnicode_FSConverter, &name, PyUnicode_FSConverter, &value))
 +        goto exit;
 +    return_value = os_putenv_impl(module, name, value);
 +
 +exit:
 +    /* Cleanup for name */
 +    Py_XDECREF(name);
 +    /* Cleanup for value */
 +    Py_XDECREF(value);
 +
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value)
 +/*[clinic end generated code: output=85ab223393dc7afd input=a97bc6152f688d31]*/
 +{
 +    PyObject *bytes = NULL;
 +    char *env;
 +    char *name_string = PyBytes_AsString(name);
 +    char *value_string = PyBytes_AsString(value);
 +
 +    bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
 +    if (bytes == NULL) {
 +        PyErr_NoMemory();
 +        return NULL;
 +    }
 +
 +    env = PyBytes_AS_STRING(bytes);
 +    if (putenv(env)) {
 +        Py_DECREF(bytes);
 +        return posix_error();
 +    }
 +
 +    posix_putenv_garbage_setitem(name, bytes);
 +    Py_RETURN_NONE;
 +}
 +#endif /* MS_WINDOWS */
 +#endif /* HAVE_PUTENV */
 +
 +
 +#ifdef HAVE_UNSETENV
 +/*[clinic input]
 +os.unsetenv
 +    name: FSConverter
 +    /
 +
 +Delete an environment variable.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_unsetenv__doc__,
 +"unsetenv($module, name, /)\n"
 +"--\n"
 +"\n"
 +"Delete an environment variable.");
 +
 +#define OS_UNSETENV_METHODDEF    \
 +    {"unsetenv", (PyCFunction)os_unsetenv, METH_VARARGS, os_unsetenv__doc__},
 +
 +static PyObject *
 +os_unsetenv_impl(PyModuleDef *module, PyObject *name);
 +
 +static PyObject *
 +os_unsetenv(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    PyObject *name = NULL;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "O&:unsetenv",
 +        PyUnicode_FSConverter, &name))
 +        goto exit;
 +    return_value = os_unsetenv_impl(module, name);
 +
 +exit:
 +    /* Cleanup for name */
 +    Py_XDECREF(name);
 +
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_unsetenv_impl(PyModuleDef *module, PyObject *name)
 +/*[clinic end generated code: output=91318c995f9a0767 input=2bb5288a599c7107]*/
 +{
 +#ifndef HAVE_BROKEN_UNSETENV
 +    int err;
 +#endif
 +
 +#ifdef HAVE_BROKEN_UNSETENV
 +    unsetenv(PyBytes_AS_STRING(name));
 +#else
 +    err = unsetenv(PyBytes_AS_STRING(name));
 +    if (err)
 +        return posix_error();
 +#endif
 +
 +    /* Remove the key from posix_putenv_garbage;
 +     * this will cause it to be collected.  This has to
 +     * happen after the real unsetenv() call because the
 +     * old value was still accessible until then.
 +     */
 +    if (PyDict_DelItem(posix_putenv_garbage, name)) {
 +        /* really not much we can do; just leak */
 +        PyErr_Clear();
 +    }
 +    Py_RETURN_NONE;
 +}
 +#endif /* HAVE_UNSETENV */
 +
 +
 +/*[clinic input]
 +os.strerror
 +
 +    code: int
 +    /
 +
 +Translate an error code to a message string.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_strerror__doc__,
 +"strerror($module, code, /)\n"
 +"--\n"
 +"\n"
 +"Translate an error code to a message string.");
 +
 +#define OS_STRERROR_METHODDEF    \
 +    {"strerror", (PyCFunction)os_strerror, METH_VARARGS, os_strerror__doc__},
 +
 +static PyObject *
 +os_strerror_impl(PyModuleDef *module, int code);
 +
 +static PyObject *
 +os_strerror(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int code;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "i:strerror",
 +        &code))
 +        goto exit;
 +    return_value = os_strerror_impl(module, code);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_strerror_impl(PyModuleDef *module, int code)
 +/*[clinic end generated code: output=8665c70bb2ca4720 input=75a8673d97915a91]*/
 +{
 +    char *message = strerror(code);
 +    if (message == NULL) {
 +        PyErr_SetString(PyExc_ValueError,
 +                        "strerror() argument out of range");
 +        return NULL;
 +    }
 +    return PyUnicode_DecodeLocale(message, "surrogateescape");
 +}
 +
 +
 +#ifdef HAVE_SYS_WAIT_H
 +#ifdef WCOREDUMP
 +/*[clinic input]
 +os.WCOREDUMP -> bool
 +
 +    status: int
 +    /
 +
 +Return True if the process returning status was dumped to a core file.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_WCOREDUMP__doc__,
 +"WCOREDUMP($module, status, /)\n"
 +"--\n"
 +"\n"
 +"Return True if the process returning status was dumped to a core file.");
 +
 +#define OS_WCOREDUMP_METHODDEF    \
 +    {"WCOREDUMP", (PyCFunction)os_WCOREDUMP, METH_VARARGS, os_WCOREDUMP__doc__},
 +
 +static int
 +os_WCOREDUMP_impl(PyModuleDef *module, int status);
 +
 +static PyObject *
 +os_WCOREDUMP(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int status;
 +    int _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "i:WCOREDUMP",
 +        &status))
 +        goto exit;
 +    _return_value = os_WCOREDUMP_impl(module, status);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyBool_FromLong((long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static int
 +os_WCOREDUMP_impl(PyModuleDef *module, int status)
 +/*[clinic end generated code: output=e04d55c09c299828 input=8b05e7ab38528d04]*/
 +{
 +    WAIT_TYPE wait_status;
 +    WAIT_STATUS_INT(wait_status) = status;
 +    return WCOREDUMP(wait_status);
 +}
 +#endif /* WCOREDUMP */
 +
 +
 +#ifdef WIFCONTINUED
 +/*[clinic input]
 +os.WIFCONTINUED -> bool
 +
 +    status: int
 +
 +Return True if a particular process was continued from a job control stop.
 +
 +Return True if the process returning status was continued from a
 +job control stop.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_WIFCONTINUED__doc__,
 +"WIFCONTINUED($module, /, status)\n"
 +"--\n"
 +"\n"
 +"Return True if a particular process was continued from a job control stop.\n"
 +"\n"
 +"Return True if the process returning status was continued from a\n"
 +"job control stop.");
 +
 +#define OS_WIFCONTINUED_METHODDEF    \
 +    {"WIFCONTINUED", (PyCFunction)os_WIFCONTINUED, METH_VARARGS|METH_KEYWORDS, os_WIFCONTINUED__doc__},
 +
 +static int
 +os_WIFCONTINUED_impl(PyModuleDef *module, int status);
 +
 +static PyObject *
 +os_WIFCONTINUED(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"status", NULL};
 +    int status;
 +    int _return_value;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "i:WIFCONTINUED", _keywords,
 +        &status))
 +        goto exit;
 +    _return_value = os_WIFCONTINUED_impl(module, status);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyBool_FromLong((long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static int
 +os_WIFCONTINUED_impl(PyModuleDef *module, int status)
 +/*[clinic end generated code: output=9c4e6105a4520ab5 input=e777e7d38eb25bd9]*/
 +{
 +    WAIT_TYPE wait_status;
 +    WAIT_STATUS_INT(wait_status) = status;
 +    return WIFCONTINUED(wait_status);
 +}
 +#endif /* WIFCONTINUED */
 +
 +
 +#ifdef WIFSTOPPED
 +/*[clinic input]
 +os.WIFSTOPPED -> bool
 +
 +    status: int
 +
 +Return True if the process returning status was stopped.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_WIFSTOPPED__doc__,
 +"WIFSTOPPED($module, /, status)\n"
 +"--\n"
 +"\n"
 +"Return True if the process returning status was stopped.");
 +
 +#define OS_WIFSTOPPED_METHODDEF    \
 +    {"WIFSTOPPED", (PyCFunction)os_WIFSTOPPED, METH_VARARGS|METH_KEYWORDS, os_WIFSTOPPED__doc__},
 +
 +static int
 +os_WIFSTOPPED_impl(PyModuleDef *module, int status);
 +
 +static PyObject *
 +os_WIFSTOPPED(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"status", NULL};
 +    int status;
 +    int _return_value;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "i:WIFSTOPPED", _keywords,
 +        &status))
 +        goto exit;
 +    _return_value = os_WIFSTOPPED_impl(module, status);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyBool_FromLong((long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static int
 +os_WIFSTOPPED_impl(PyModuleDef *module, int status)
 +/*[clinic end generated code: output=e0de2da8ec9593ff input=043cb7f1289ef904]*/
 +{
 +    WAIT_TYPE wait_status;
 +    WAIT_STATUS_INT(wait_status) = status;
 +    return WIFSTOPPED(wait_status);
 +}
 +#endif /* WIFSTOPPED */
 +
 +
 +#ifdef WIFSIGNALED
 +/*[clinic input]
 +os.WIFSIGNALED -> bool
 +
 +    status: int
 +
 +Return True if the process returning status was terminated by a signal.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_WIFSIGNALED__doc__,
 +"WIFSIGNALED($module, /, status)\n"
 +"--\n"
 +"\n"
 +"Return True if the process returning status was terminated by a signal.");
 +
 +#define OS_WIFSIGNALED_METHODDEF    \
 +    {"WIFSIGNALED", (PyCFunction)os_WIFSIGNALED, METH_VARARGS|METH_KEYWORDS, os_WIFSIGNALED__doc__},
 +
 +static int
 +os_WIFSIGNALED_impl(PyModuleDef *module, int status);
 +
 +static PyObject *
 +os_WIFSIGNALED(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"status", NULL};
 +    int status;
 +    int _return_value;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "i:WIFSIGNALED", _keywords,
 +        &status))
 +        goto exit;
 +    _return_value = os_WIFSIGNALED_impl(module, status);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyBool_FromLong((long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static int
 +os_WIFSIGNALED_impl(PyModuleDef *module, int status)
 +/*[clinic end generated code: output=f14d106558f406be input=d55ba7cc9ce5dc43]*/
 +{
 +    WAIT_TYPE wait_status;
 +    WAIT_STATUS_INT(wait_status) = status;
 +    return WIFSIGNALED(wait_status);
 +}
 +#endif /* WIFSIGNALED */
 +
 +
 +#ifdef WIFEXITED
 +/*[clinic input]
 +os.WIFEXITED -> bool
 +
 +    status: int
 +
 +Return True if the process returning status exited via the exit() system call.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_WIFEXITED__doc__,
 +"WIFEXITED($module, /, status)\n"
 +"--\n"
 +"\n"
 +"Return True if the process returning status exited via the exit() system call.");
 +
 +#define OS_WIFEXITED_METHODDEF    \
 +    {"WIFEXITED", (PyCFunction)os_WIFEXITED, METH_VARARGS|METH_KEYWORDS, os_WIFEXITED__doc__},
 +
 +static int
 +os_WIFEXITED_impl(PyModuleDef *module, int status);
 +
 +static PyObject *
 +os_WIFEXITED(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"status", NULL};
 +    int status;
 +    int _return_value;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "i:WIFEXITED", _keywords,
 +        &status))
 +        goto exit;
 +    _return_value = os_WIFEXITED_impl(module, status);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyBool_FromLong((long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static int
 +os_WIFEXITED_impl(PyModuleDef *module, int status)
 +/*[clinic end generated code: output=2f76087d53721255 input=d63775a6791586c0]*/
 +{
 +    WAIT_TYPE wait_status;
 +    WAIT_STATUS_INT(wait_status) = status;
 +    return WIFEXITED(wait_status);
 +}
 +#endif /* WIFEXITED */
 +
 +
 +#ifdef WEXITSTATUS
 +/*[clinic input]
 +os.WEXITSTATUS -> int
 +
 +    status: int
 +
 +Return the process return code from status.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_WEXITSTATUS__doc__,
 +"WEXITSTATUS($module, /, status)\n"
 +"--\n"
 +"\n"
 +"Return the process return code from status.");
 +
 +#define OS_WEXITSTATUS_METHODDEF    \
 +    {"WEXITSTATUS", (PyCFunction)os_WEXITSTATUS, METH_VARARGS|METH_KEYWORDS, os_WEXITSTATUS__doc__},
 +
 +static int
 +os_WEXITSTATUS_impl(PyModuleDef *module, int status);
 +
 +static PyObject *
 +os_WEXITSTATUS(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"status", NULL};
 +    int status;
 +    int _return_value;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "i:WEXITSTATUS", _keywords,
 +        &status))
 +        goto exit;
 +    _return_value = os_WEXITSTATUS_impl(module, status);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromLong((long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static int
 +os_WEXITSTATUS_impl(PyModuleDef *module, int status)
 +/*[clinic end generated code: output=13b6c270e2a326b1 input=e1fb4944e377585b]*/
 +{
 +    WAIT_TYPE wait_status;
 +    WAIT_STATUS_INT(wait_status) = status;
 +    return WEXITSTATUS(wait_status);
 +}
 +#endif /* WEXITSTATUS */
 +
 +
 +#ifdef WTERMSIG
 +/*[clinic input]
 +os.WTERMSIG -> int
 +
 +    status: int
 +
 +Return the signal that terminated the process that provided the status value.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_WTERMSIG__doc__,
 +"WTERMSIG($module, /, status)\n"
 +"--\n"
 +"\n"
 +"Return the signal that terminated the process that provided the status value.");
 +
 +#define OS_WTERMSIG_METHODDEF    \
 +    {"WTERMSIG", (PyCFunction)os_WTERMSIG, METH_VARARGS|METH_KEYWORDS, os_WTERMSIG__doc__},
 +
 +static int
 +os_WTERMSIG_impl(PyModuleDef *module, int status);
 +
 +static PyObject *
 +os_WTERMSIG(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"status", NULL};
 +    int status;
 +    int _return_value;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "i:WTERMSIG", _keywords,
 +        &status))
 +        goto exit;
 +    _return_value = os_WTERMSIG_impl(module, status);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromLong((long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static int
 +os_WTERMSIG_impl(PyModuleDef *module, int status)
 +/*[clinic end generated code: output=bf1fd4b002d0a9ed input=727fd7f84ec3f243]*/
 +{
 +    WAIT_TYPE wait_status;
 +    WAIT_STATUS_INT(wait_status) = status;
 +    return WTERMSIG(wait_status);
 +}
 +#endif /* WTERMSIG */
 +
 +
 +#ifdef WSTOPSIG
 +/*[clinic input]
 +os.WSTOPSIG -> int
 +
 +    status: int
 +
 +Return the signal that stopped the process that provided the status value.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_WSTOPSIG__doc__,
 +"WSTOPSIG($module, /, status)\n"
 +"--\n"
 +"\n"
 +"Return the signal that stopped the process that provided the status value.");
 +
 +#define OS_WSTOPSIG_METHODDEF    \
 +    {"WSTOPSIG", (PyCFunction)os_WSTOPSIG, METH_VARARGS|METH_KEYWORDS, os_WSTOPSIG__doc__},
 +
 +static int
 +os_WSTOPSIG_impl(PyModuleDef *module, int status);
 +
 +static PyObject *
 +os_WSTOPSIG(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"status", NULL};
 +    int status;
 +    int _return_value;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "i:WSTOPSIG", _keywords,
 +        &status))
 +        goto exit;
 +    _return_value = os_WSTOPSIG_impl(module, status);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromLong((long)_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static int
 +os_WSTOPSIG_impl(PyModuleDef *module, int status)
 +/*[clinic end generated code: output=92e1647d29ee0549 input=46ebf1d1b293c5c1]*/
 +{
 +    WAIT_TYPE wait_status;
 +    WAIT_STATUS_INT(wait_status) = status;
 +    return WSTOPSIG(wait_status);
 +}
 +#endif /* WSTOPSIG */
 +#endif /* HAVE_SYS_WAIT_H */
 +
 +
 +#ifndef OS_WCOREDUMP_METHODDEF
 +#define OS_WCOREDUMP_METHODDEF
 +#endif /* OS_WCOREDUMP_METHODDEF */
 +
 +#ifndef OS_WIFCONTINUED_METHODDEF
 +#define OS_WIFCONTINUED_METHODDEF
 +#endif /* OS_WIFCONTINUED_METHODDEF */
 +
 +#ifndef OS_WIFSTOPPED_METHODDEF
 +#define OS_WIFSTOPPED_METHODDEF
 +#endif /* OS_WIFSTOPPED_METHODDEF */
 +
 +#ifndef OS_WIFSIGNALED_METHODDEF
 +#define OS_WIFSIGNALED_METHODDEF
 +#endif /* OS_WIFSIGNALED_METHODDEF */
 +
 +#ifndef OS_WIFEXITED_METHODDEF
 +#define OS_WIFEXITED_METHODDEF
 +#endif /* OS_WIFEXITED_METHODDEF */
 +
 +#ifndef OS_WEXITSTATUS_METHODDEF
 +#define OS_WEXITSTATUS_METHODDEF
 +#endif /* OS_WEXITSTATUS_METHODDEF */
 +
 +#ifndef OS_WTERMSIG_METHODDEF
 +#define OS_WTERMSIG_METHODDEF
 +#endif /* OS_WTERMSIG_METHODDEF */
 +
 +#ifndef OS_WSTOPSIG_METHODDEF
 +#define OS_WSTOPSIG_METHODDEF
 +#endif /* OS_WSTOPSIG_METHODDEF */
 +
 +
 +#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
 +#ifdef _SCO_DS
 +/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
 +   needed definitions in sys/statvfs.h */
 +#define _SVID3
 +#endif
 +#include <sys/statvfs.h>
 +
 +static PyObject*
 +_pystatvfs_fromstructstatvfs(struct statvfs st) {
 +    PyObject *v = PyStructSequence_New(&StatVFSResultType);
 +    if (v == NULL)
 +        return NULL;
 +
 +#if !defined(HAVE_LARGEFILE_SUPPORT)
 +    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
 +    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
 +    PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
 +    PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
 +    PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
 +    PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
 +    PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
 +    PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
 +    PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
 +    PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
 +#else
 +    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
 +    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
 +    PyStructSequence_SET_ITEM(v, 2,
 +                              PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
 +    PyStructSequence_SET_ITEM(v, 3,
 +                              PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
 +    PyStructSequence_SET_ITEM(v, 4,
 +                              PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
 +    PyStructSequence_SET_ITEM(v, 5,
 +                              PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
 +    PyStructSequence_SET_ITEM(v, 6,
 +                              PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
 +    PyStructSequence_SET_ITEM(v, 7,
 +                              PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
 +    PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
 +    PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
 +#endif
 +    if (PyErr_Occurred()) {
 +        Py_DECREF(v);
 +        return NULL;
 +    }
 +
 +    return v;
 +}
 +
 +
 +/*[clinic input]
 +os.fstatvfs
 +    fd: int
 +    /
 +
 +Perform an fstatvfs system call on the given fd.
 +
 +Equivalent to statvfs(fd).
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_fstatvfs__doc__,
 +"fstatvfs($module, fd, /)\n"
 +"--\n"
 +"\n"
 +"Perform an fstatvfs system call on the given fd.\n"
 +"\n"
 +"Equivalent to statvfs(fd).");
 +
 +#define OS_FSTATVFS_METHODDEF    \
 +    {"fstatvfs", (PyCFunction)os_fstatvfs, METH_VARARGS, os_fstatvfs__doc__},
 +
 +static PyObject *
 +os_fstatvfs_impl(PyModuleDef *module, int fd);
 +
 +static PyObject *
 +os_fstatvfs(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "i:fstatvfs",
 +        &fd))
 +        goto exit;
 +    return_value = os_fstatvfs_impl(module, fd);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_fstatvfs_impl(PyModuleDef *module, int fd)
 +/*[clinic end generated code: output=0e32bf07f946ec0d input=d8122243ac50975e]*/
 +{
 +    int result;
 +    int async_err = 0;
 +    struct statvfs st;
 +
 +    do {
 +        Py_BEGIN_ALLOW_THREADS
 +        result = fstatvfs(fd, &st);
 +        Py_END_ALLOW_THREADS
 +    } while (result != 0 && errno == EINTR &&
 +             !(async_err = PyErr_CheckSignals()));
 +    if (result != 0)
 +        return (!async_err) ? posix_error() : NULL;
 +
 +    return _pystatvfs_fromstructstatvfs(st);
 +}
 +#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
 +
 +
 +#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
 +#include <sys/statvfs.h>
 +/*[clinic input]
 +os.statvfs
 +
 +    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
 +
 +Perform a statvfs system call on the given path.
 +
 +path may always be specified as a string.
 +On some platforms, path may also be specified as an open file descriptor.
 +  If this functionality is unavailable, using it raises an exception.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_statvfs__doc__,
 +"statvfs($module, /, path)\n"
 +"--\n"
 +"\n"
 +"Perform a statvfs system call on the given path.\n"
 +"\n"
 +"path may always be specified as a string.\n"
 +"On some platforms, path may also be specified as an open file descriptor.\n"
 +"  If this functionality is unavailable, using it raises an exception.");
 +
 +#define OS_STATVFS_METHODDEF    \
 +    {"statvfs", (PyCFunction)os_statvfs, METH_VARARGS|METH_KEYWORDS, os_statvfs__doc__},
 +
 +static PyObject *
 +os_statvfs_impl(PyModuleDef *module, path_t *path);
 +
 +static PyObject *
 +os_statvfs(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"path", NULL};
 +    path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, PATH_HAVE_FSTATVFS);
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "O&:statvfs", _keywords,
 +        path_converter, &path))
 +        goto exit;
 +    return_value = os_statvfs_impl(module, &path);
 +
 +exit:
 +    /* Cleanup for path */
 +    path_cleanup(&path);
 +
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_statvfs_impl(PyModuleDef *module, path_t *path)
 +/*[clinic end generated code: output=00ff54983360b446 input=3f5c35791c669bd9]*/
 +{
 +    int result;
 +    struct statvfs st;
 +
 +    Py_BEGIN_ALLOW_THREADS
 +#ifdef HAVE_FSTATVFS
 +    if (path->fd != -1) {
 +#ifdef __APPLE__
 +        /* handle weak-linking on Mac OS X 10.3 */
 +        if (fstatvfs == NULL) {
 +            fd_specified("statvfs", path->fd);
 +            return NULL;
 +        }
 +#endif
 +        result = fstatvfs(path->fd, &st);
 +    }
 +    else
 +#endif
 +        result = statvfs(path->narrow, &st);
 +    Py_END_ALLOW_THREADS
 +
 +    if (result) {
 +        return path_error(path);
 +    }
 +
 +    return _pystatvfs_fromstructstatvfs(st);
 +}
 +#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
 +
 +
 +#ifdef MS_WINDOWS
 +/*[clinic input]
 +os._getdiskusage
 +
 +    path: Py_UNICODE
 +
 +Return disk usage statistics about the given path as a (total, free) tuple.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os__getdiskusage__doc__,
 +"_getdiskusage($module, /, path)\n"
 +"--\n"
 +"\n"
 +"Return disk usage statistics about the given path as a (total, free) tuple.");
 +
 +#define OS__GETDISKUSAGE_METHODDEF    \
 +    {"_getdiskusage", (PyCFunction)os__getdiskusage, METH_VARARGS|METH_KEYWORDS, os__getdiskusage__doc__},
 +
 +static PyObject *
 +os__getdiskusage_impl(PyModuleDef *module, Py_UNICODE *path);
 +
 +static PyObject *
 +os__getdiskusage(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"path", NULL};
 +    Py_UNICODE *path;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "u:_getdiskusage", _keywords,
 +        &path))
 +        goto exit;
 +    return_value = os__getdiskusage_impl(module, path);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os__getdiskusage_impl(PyModuleDef *module, Py_UNICODE *path)
 +/*[clinic end generated code: output=054c972179b13708 input=6458133aed893c78]*/
 +{
 +    BOOL retval;
 +    ULARGE_INTEGER _, total, free;
 +
 +    Py_BEGIN_ALLOW_THREADS
 +    retval = GetDiskFreeSpaceExW(path, &_, &total, &free);
 +    Py_END_ALLOW_THREADS
 +    if (retval == 0)
 +        return PyErr_SetFromWindowsErr(0);
 +
 +    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
 +}
 +#endif /* MS_WINDOWS */
 +
 +
 +/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
 + * It maps strings representing configuration variable names to
 + * integer values, allowing those functions to be called with the
 + * magic names instead of polluting the module's namespace with tons of
 + * rarely-used constants.  There are three separate tables that use
 + * these definitions.
 + *
 + * This code is always included, even if none of the interfaces that
 + * need it are included.  The #if hackery needed to avoid it would be
 + * sufficiently pervasive that it's not worth the loss of readability.
 + */
 +struct constdef {
 +    char *name;
 +    long value;
 +};
 +
 +static int
 +conv_confname(PyObject *arg, int *valuep, struct constdef *table,
 +              size_t tablesize)
 +{
 +    if (PyLong_Check(arg)) {
 +        *valuep = PyLong_AS_LONG(arg);
 +        return 1;
 +    }
 +    else {
 +        /* look up the value in the table using a binary search */
 +        size_t lo = 0;
 +        size_t mid;
 +        size_t hi = tablesize;
 +        int cmp;
 +        const char *confname;
 +        if (!PyUnicode_Check(arg)) {
 +            PyErr_SetString(PyExc_TypeError,
 +                "configuration names must be strings or integers");
 +            return 0;
 +        }
 +        confname = _PyUnicode_AsString(arg);
 +        if (confname == NULL)
 +            return 0;
 +        while (lo < hi) {
 +            mid = (lo + hi) / 2;
 +            cmp = strcmp(confname, table[mid].name);
 +            if (cmp < 0)
 +                hi = mid;
 +            else if (cmp > 0)
 +                lo = mid + 1;
 +            else {
 +                *valuep = table[mid].value;
 +                return 1;
 +            }
 +        }
 +        PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
 +        return 0;
 +    }
 +}
 +
 +
 +#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
 +static struct constdef  posix_constants_pathconf[] = {
 +#ifdef _PC_ABI_AIO_XFER_MAX
 +    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
 +#endif
 +#ifdef _PC_ABI_ASYNC_IO
 +    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
 +#endif
 +#ifdef _PC_ASYNC_IO
 +    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
 +#endif
 +#ifdef _PC_CHOWN_RESTRICTED
 +    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
 +#endif
 +#ifdef _PC_FILESIZEBITS
 +    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
 +#endif
 +#ifdef _PC_LAST
 +    {"PC_LAST", _PC_LAST},
 +#endif
 +#ifdef _PC_LINK_MAX
 +    {"PC_LINK_MAX",     _PC_LINK_MAX},
 +#endif
 +#ifdef _PC_MAX_CANON
 +    {"PC_MAX_CANON",    _PC_MAX_CANON},
 +#endif
 +#ifdef _PC_MAX_INPUT
 +    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
 +#endif
 +#ifdef _PC_NAME_MAX
 +    {"PC_NAME_MAX",     _PC_NAME_MAX},
 +#endif
 +#ifdef _PC_NO_TRUNC
 +    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
 +#endif
 +#ifdef _PC_PATH_MAX
 +    {"PC_PATH_MAX",     _PC_PATH_MAX},
 +#endif
 +#ifdef _PC_PIPE_BUF
 +    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
 +#endif
 +#ifdef _PC_PRIO_IO
 +    {"PC_PRIO_IO",      _PC_PRIO_IO},
 +#endif
 +#ifdef _PC_SOCK_MAXBUF
 +    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
 +#endif
 +#ifdef _PC_SYNC_IO
 +    {"PC_SYNC_IO",      _PC_SYNC_IO},
 +#endif
 +#ifdef _PC_VDISABLE
 +    {"PC_VDISABLE",     _PC_VDISABLE},
 +#endif
 +#ifdef _PC_ACL_ENABLED
 +    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
 +#endif
 +#ifdef _PC_MIN_HOLE_SIZE
 +    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
 +#endif
 +#ifdef _PC_ALLOC_SIZE_MIN
 +    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
 +#endif
 +#ifdef _PC_REC_INCR_XFER_SIZE
 +    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
 +#endif
 +#ifdef _PC_REC_MAX_XFER_SIZE
 +    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
 +#endif
 +#ifdef _PC_REC_MIN_XFER_SIZE
 +    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
 +#endif
 +#ifdef _PC_REC_XFER_ALIGN
 +    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
 +#endif
 +#ifdef _PC_SYMLINK_MAX
 +    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
 +#endif
 +#ifdef _PC_XATTR_ENABLED
 +    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
 +#endif
 +#ifdef _PC_XATTR_EXISTS
 +    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
 +#endif
 +#ifdef _PC_TIMESTAMP_RESOLUTION
 +    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
 +#endif
 +};
 +
 +static int
 +conv_path_confname(PyObject *arg, int *valuep)
 +{
 +    return conv_confname(arg, valuep, posix_constants_pathconf,
 +                         sizeof(posix_constants_pathconf)
 +                           / sizeof(struct constdef));
 +}
 +#endif
 +
 +
 +#ifdef HAVE_FPATHCONF
 +/*[clinic input]
 +os.fpathconf -> long
 +
 +    fd: int
 +    name: path_confname
 +    /
 +
 +Return the configuration limit name for the file descriptor fd.
 +
 +If there is no limit, return -1.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_fpathconf__doc__,
 +"fpathconf($module, fd, name, /)\n"
 +"--\n"
 +"\n"
 +"Return the configuration limit name for the file descriptor fd.\n"
 +"\n"
 +"If there is no limit, return -1.");
 +
 +#define OS_FPATHCONF_METHODDEF    \
 +    {"fpathconf", (PyCFunction)os_fpathconf, METH_VARARGS, os_fpathconf__doc__},
 +
 +static long
 +os_fpathconf_impl(PyModuleDef *module, int fd, int name);
 +
 +static PyObject *
 +os_fpathconf(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int fd;
 +    int name;
 +    long _return_value;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "iO&:fpathconf",
 +        &fd, conv_path_confname, &name))
 +        goto exit;
 +    _return_value = os_fpathconf_impl(module, fd, name);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromLong(_return_value);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static long
 +os_fpathconf_impl(PyModuleDef *module, int fd, int name)
 +/*[clinic end generated code: output=3bf04b40e0523a8c input=5942a024d3777810]*/
 +{
 +    long limit;
 +
 +    errno = 0;
 +    limit = fpathconf(fd, name);
 +    if (limit == -1 && errno != 0)
 +        posix_error();
 +
 +    return limit;
 +}
 +#endif /* HAVE_FPATHCONF */
 +
 +
 +#ifdef HAVE_PATHCONF
 +/*[clinic input]
 +os.pathconf -> long
 +    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
 +    name: path_confname
 +
 +Return the configuration limit name for the file or directory path.
 +
 +If there is no limit, return -1.
 +On some platforms, path may also be specified as an open file descriptor.
 +  If this functionality is unavailable, using it raises an exception.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_pathconf__doc__,
 +"pathconf($module, /, path, name)\n"
 +"--\n"
 +"\n"
 +"Return the configuration limit name for the file or directory path.\n"
 +"\n"
 +"If there is no limit, return -1.\n"
 +"On some platforms, path may also be specified as an open file descriptor.\n"
 +"  If this functionality is unavailable, using it raises an exception.");
 +
 +#define OS_PATHCONF_METHODDEF    \
 +    {"pathconf", (PyCFunction)os_pathconf, METH_VARARGS|METH_KEYWORDS, os_pathconf__doc__},
 +
 +static long
 +os_pathconf_impl(PyModuleDef *module, path_t *path, int name);
 +
 +static PyObject *
 +os_pathconf(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 +{
 +    PyObject *return_value = NULL;
 +    static char *_keywords[] = {"path", "name", NULL};
 +    path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, PATH_HAVE_FPATHCONF);
 +    int name;
 +    long _return_value;
 +
 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 +        "O&O&:pathconf", _keywords,
 +        path_converter, &path, conv_path_confname, &name))
 +        goto exit;
 +    _return_value = os_pathconf_impl(module, &path, name);
 +    if ((_return_value == -1) && PyErr_Occurred())
 +        goto exit;
 +    return_value = PyLong_FromLong(_return_value);
 +
 +exit:
 +    /* Cleanup for path */
 +    path_cleanup(&path);
 +
 +    return return_value;
 +}
 +
 +static long
 +os_pathconf_impl(PyModuleDef *module, path_t *path, int name)
 +/*[clinic end generated code: output=1a53e125b6cf63e4 input=bc3e2a985af27e5e]*/
 +{
 +    long limit;
 +
 +    errno = 0;
 +#ifdef HAVE_FPATHCONF
 +    if (path->fd != -1)
 +        limit = fpathconf(path->fd, name);
 +    else
 +#endif
 +        limit = pathconf(path->narrow, name);
 +    if (limit == -1 && errno != 0) {
 +        if (errno == EINVAL)
 +            /* could be a path or name problem */
 +            posix_error();
 +        else
 +            path_error(path);
 +    }
 +
 +    return limit;
 +}
 +#endif /* HAVE_PATHCONF */
 +
 +#ifdef HAVE_CONFSTR
 +static struct constdef posix_constants_confstr[] = {
 +#ifdef _CS_ARCHITECTURE
 +    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
 +#endif
 +#ifdef _CS_GNU_LIBC_VERSION
 +    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
 +#endif
 +#ifdef _CS_GNU_LIBPTHREAD_VERSION
 +    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
 +#endif
 +#ifdef _CS_HOSTNAME
 +    {"CS_HOSTNAME",     _CS_HOSTNAME},
 +#endif
 +#ifdef _CS_HW_PROVIDER
 +    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
 +#endif
 +#ifdef _CS_HW_SERIAL
 +    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
 +#endif
 +#ifdef _CS_INITTAB_NAME
 +    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
 +#endif
 +#ifdef _CS_LFS64_CFLAGS
 +    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
 +#endif
 +#ifdef _CS_LFS64_LDFLAGS
 +    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
 +#endif
 +#ifdef _CS_LFS64_LIBS
 +    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
 +#endif
 +#ifdef _CS_LFS64_LINTFLAGS
 +    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
 +#endif
 +#ifdef _CS_LFS_CFLAGS
 +    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
 +#endif
 +#ifdef _CS_LFS_LDFLAGS
 +    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
 +#endif
 +#ifdef _CS_LFS_LIBS
 +    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
 +#endif
 +#ifdef _CS_LFS_LINTFLAGS
 +    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
 +#endif
 +#ifdef _CS_MACHINE
 +    {"CS_MACHINE",      _CS_MACHINE},
 +#endif
 +#ifdef _CS_PATH
 +    {"CS_PATH", _CS_PATH},
 +#endif
 +#ifdef _CS_RELEASE
 +    {"CS_RELEASE",      _CS_RELEASE},
 +#endif
 +#ifdef _CS_SRPC_DOMAIN
 +    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
 +#endif
 +#ifdef _CS_SYSNAME
 +    {"CS_SYSNAME",      _CS_SYSNAME},
 +#endif
 +#ifdef _CS_VERSION
 +    {"CS_VERSION",      _CS_VERSION},
 +#endif
 +#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
 +    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
 +#endif
 +#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
 +    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
 +#endif
 +#ifdef _CS_XBS5_ILP32_OFF32_LIBS
 +    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
 +#endif
 +#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
 +    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
 +#endif
 +#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
 +    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
 +#endif
 +#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
 +    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
 +#endif
 +#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
 +    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
 +#endif
 +#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
 +    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
 +#endif
 +#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
 +    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
 +#endif
 +#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
 +    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
 +#endif
 +#ifdef _CS_XBS5_LP64_OFF64_LIBS
 +    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
 +#endif
 +#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
 +    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
 +#endif
 +#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
 +    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
 +#endif
 +#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
 +    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
 +#endif
 +#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
 +    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
 +#endif
 +#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
 +    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
 +#endif
 +#ifdef _MIPS_CS_AVAIL_PROCESSORS
 +    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
 +#endif
 +#ifdef _MIPS_CS_BASE
 +    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
 +#endif
 +#ifdef _MIPS_CS_HOSTID
 +    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
 +#endif
 +#ifdef _MIPS_CS_HW_NAME
 +    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
 +#endif
 +#ifdef _MIPS_CS_NUM_PROCESSORS
 +    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
 +#endif
 +#ifdef _MIPS_CS_OSREL_MAJ
 +    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
 +#endif
 +#ifdef _MIPS_CS_OSREL_MIN
 +    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
 +#endif
 +#ifdef _MIPS_CS_OSREL_PATCH
 +    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
 +#endif
 +#ifdef _MIPS_CS_OS_NAME
 +    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
 +#endif
 +#ifdef _MIPS_CS_OS_PROVIDER
 +    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
 +#endif
 +#ifdef _MIPS_CS_PROCESSORS
 +    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
 +#endif
 +#ifdef _MIPS_CS_SERIAL
 +    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
 +#endif
 +#ifdef _MIPS_CS_VENDOR
 +    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
 +#endif
 +};
 +
 +static int
 +conv_confstr_confname(PyObject *arg, int *valuep)
 +{
 +    return conv_confname(arg, valuep, posix_constants_confstr,
 +                         sizeof(posix_constants_confstr)
 +                           / sizeof(struct constdef));
 +}
 +
 +
 +/*[clinic input]
 +os.confstr
 +
 +    name: confstr_confname
 +    /
 +
 +Return a string-valued system configuration variable.
 +[clinic start generated code]*/
 +
 +PyDoc_STRVAR(os_confstr__doc__,
 +"confstr($module, name, /)\n"
 +"--\n"
 +"\n"
 +"Return a string-valued system configuration variable.");
 +
 +#define OS_CONFSTR_METHODDEF    \
 +    {"confstr", (PyCFunction)os_confstr, METH_VARARGS, os_confstr__doc__},
 +
 +static PyObject *
 +os_confstr_impl(PyModuleDef *module, int name);
 +
 +static PyObject *
 +os_confstr(PyModuleDef *module, PyObject *args)
 +{
 +    PyObject *return_value = NULL;
 +    int name;
 +
 +    if (!PyArg_ParseTuple(args,
 +        "O&:confstr",
 +        conv_confstr_confname, &name))
 +        goto exit;
 +    return_value = os_confstr_impl(module, name);
 +
 +exit:
 +    return return_value;
 +}
 +
 +static PyObject *
 +os_confstr_impl(PyModuleDef *module, int name)
 +/*[clinic end generated code: output=3f5e8aba9f8e3174 input=18fb4d0567242e65]*/
 +{
 +    PyObject *result = NULL;
 +    char buffer[255];
 +    size_t len;
 +
 +    errno = 0;
 +    len = confstr(name, buffer, sizeof(buffer));
 +    if (len == 0) {
 +        if (errno) {
 +            posix_error();
 +            return NULL;
 +        }
 +        else {
 +            Py_RETURN_NONE;
 +        }
 +    }
 +
 +    if (len >= sizeof(buffer)) {
 +        size_t len2;
 +        char *buf = PyMem_Malloc(len);
 +        if (buf == NULL)
 +            return PyErr_NoMemory();
 +        len2 = confstr(name, buf, len);
 +        assert(len == len2);
 +        result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1);
 +        PyMem_Free(buf);
 +    }
 +    else
 +        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
 +    return result;
 +}
 +#endif /* HAVE_CONFSTR */
 +
 +
 +#ifdef HAVE_SYSCONF
 +static struct constdef posix_constants_sysconf[] = {
 +#ifdef _SC_2_CHAR_TERM
 +    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
 +#endif
 +#ifdef _SC_2_C_BIND
 +    {"SC_2_C_BIND",     _SC_2_C_BIND},
 +#endif
 +#ifdef _SC_2_C_DEV
 +    {"SC_2_C_DEV",      _SC_2_C_DEV},
 +#endif
 +#ifdef _SC_2_C_VERSION
 +    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
 +#endif
 +#ifdef _SC_2_FORT_DEV
 +    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
 +#endif
 +#ifdef _SC_2_FORT_RUN
 +    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
 +#endif
 +#ifdef _SC_2_LOCALEDEF
 +    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
 +#endif
 +#ifdef _SC_2_SW_DEV
 +    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
 +#endif
 +#ifdef _SC_2_UPE
 +    {"SC_2_UPE",        _SC_2_UPE},
 +#endif
 +#ifdef _SC_2_VERSION
 +    {"SC_2_VERSION",    _SC_2_VERSION},
 +#endif
 +#ifdef _SC_ABI_ASYNCHRONOUS_IO
 +    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
 +#endif
 +#ifdef _SC_ACL
 +    {"SC_ACL",  _SC_ACL},
 +#endif
 +#ifdef _SC_AIO_LISTIO_MAX
 +    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
 +#endif
 +#ifdef _SC_AIO_MAX
 +    {"SC_AIO_MAX",      _SC_AIO_MAX},
 +#endif
 +#ifdef _SC_AIO_PRIO_DELTA_MAX
 +    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
 +#endif
 +#ifdef _SC_ARG_MAX
 +    {"SC_ARG_MAX",      _SC_ARG_MAX},
 +#endif
 +#ifdef _SC_ASYNCHRONOUS_IO
 +    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
 +#endif
 +#ifdef _SC_ATEXIT_MAX
 +    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
 +#endif
 +#ifdef _SC_AUDIT
 +    {"SC_AUDIT",        _SC_AUDIT},
 +#endif
 +#ifdef _SC_AVPHYS_PAGES
 +    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
 +#endif
 +#ifdef _SC_BC_BASE_MAX
 +    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
 +#endif
 +#ifdef _SC_BC_DIM_MAX
 +    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
 +#endif
 +#ifdef _SC_BC_SCALE_MAX
 +    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
 +#endif
 +#ifdef _SC_BC_STRING_MAX
 +    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
 +#endif
 +#ifdef _SC_CAP
 +    {"SC_CAP",  _SC_CAP},
 +#endif
 +#ifdef _SC_CHARCLASS_NAME_MAX
 +    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
 +#endif
 +#ifdef _SC_CHAR_BIT
 +    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
 +#endif
 +#ifdef _SC_CHAR_MAX
 +    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
 +#endif
 +#ifdef _SC_CHAR_MIN
 +    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
 +#endif
 +#ifdef _SC_CHILD_MAX
 +    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
 +#endif
 +#ifdef _SC_CLK_TCK
 +    {"SC_CLK_TCK",      _SC_CLK_TCK},
 +#endif
 +#ifdef _SC_COHER_BLKSZ
 +    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
 +#endif
 +#ifdef _SC_COLL_WEIGHTS_MAX
 +    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
 +#endif
 +#ifdef _SC_DCACHE_ASSOC
 +    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
 +#endif
 +#ifdef _SC_DCACHE_BLKSZ
 +    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
 +#endif
 +#ifdef _SC_DCACHE_LINESZ
 +    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
 +#endif
 +#ifdef _SC_DCACHE_SZ
 +    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
 +#endif
 +#ifdef _SC_DCACHE_TBLKSZ
 +    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
 +#endif
 +#ifdef _SC_DELAYTIMER_MAX
 +    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
 +#endif
 +#ifdef _SC_EQUIV_CLASS_MAX
 +    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
 +#endif
 +#ifdef _SC_EXPR_NEST_MAX
 +    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
 +#endif
 +#ifdef _SC_FSYNC
 +    {"SC_FSYNC",        _SC_FSYNC},
 +#endif
 +#ifdef _SC_GETGR_R_SIZE_MAX
 +    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
 +#endif
 +#ifdef _SC_GETPW_R_SIZE_MAX
 +    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
 +#endif
 +#ifdef _SC_ICACHE_ASSOC
 +    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
 +#endif
 +#ifdef _SC_ICACHE_BLKSZ
 +    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
 +#endif
 +#ifdef _SC_ICACHE_LINESZ
 +    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
 +#endif
 +#ifdef _SC_ICACHE_SZ
 +    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
 +#endif
 +#ifdef _SC_INF
 +    {"SC_INF",  _SC_INF},
 +#endif
 +#ifdef _SC_INT_MAX
 +    {"SC_INT_MAX",      _SC_INT_MAX},
 +#endif
 +#ifdef _SC_INT_MIN
 +    {"SC_INT_MIN",      _SC_INT_MIN},
 +#endif
 +#ifdef _SC_IOV_MAX
 +    {"SC_IOV_MAX",      _SC_IOV_MAX},
 +#endif
 +#ifdef _SC_IP_SECOPTS
 +    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
 +#endif
 +#ifdef _SC_JOB_CONTROL
 +    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
 +#endif
 +#ifdef _SC_KERN_POINTERS
 +    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
 +#endif
 +#ifdef _SC_KERN_SIM
 +    {"SC_KERN_SIM",     _SC_KERN_SIM},
 +#endif
 +#ifdef _SC_LINE_MAX
 +    {"SC_LINE_MAX",     _SC_LINE_MAX},
 +#endif
 +#ifdef _SC_LOGIN_NAME_MAX
 +    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
 +#endif
 +#ifdef _SC_LOGNAME_MAX
 +    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
 +#endif
 +#ifdef _SC_LONG_BIT
 +    {"SC_LONG_BIT",     _SC_LONG_BIT},
 +#endif
 +#ifdef _SC_MAC
 +    {"SC_MAC",  _SC_MAC},
 +#endif
 +#ifdef _SC_MAPPED_FILES
 +    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
 +#endif
 +#ifdef _SC_MAXPID
 +    {"SC_MAXPID",       _SC_MAXPID},
 +#endif
 +#ifdef _SC_MB_LEN_MAX
 +    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
 +#endif
 +#ifdef _SC_MEMLOCK
 +    {"SC_MEMLOCK",      _SC_MEMLOCK},
 +#endif
 +#ifdef _SC_MEMLOCK_RANGE
 +    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
 +#endif
 +#ifdef _SC_MEMORY_PROTECTION
 +    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
 +#endif
 +#ifdef _SC_MESSAGE_PASSING
 +    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
 +#endif
 +#ifdef _SC_MMAP_FIXED_ALIGNMENT
 +    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
 +#endif
 +#ifdef _SC_MQ_OPEN_MAX
 +    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
  #endif
  #ifdef _SC_MQ_PRIO_MAX
      {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
Simple merge
Simple merge
Simple merge