posixmodule.c revision bee325387b21b859054002a052149646399b52de
127a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt
227a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt/* POSIX module implementation */
327a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt
427a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt/* This file is also used for Windows NT/MS-Win and OS/2.  In that case the
527a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt   module actually calls itself 'nt' or 'os2', not 'posix', and a few
627a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt   functions are either unimplemented or implemented differently.  The source
727a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt   assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
827a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt   of the compiler used.  Different compilers define their own feature
927a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt   test macro, e.g. '__BORLANDC__' or '_MSC_VER'.  For OS/2, the compiler
1027a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt   independent macro PYOS_OS2 should be defined.  On OS/2 the default
115651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualitt   compiler is assumed to be IBM's VisualAge C++ (VACPP).  PYCC_GCC is used
12294870ff119b89fc902773643b054f14e5d1f554Robert Phillips   as the compiler specific macro for the EMX port of gcc to OS/2. */
13f7a7261b4ac23f97580a8ff6f0307b3c47399b9dRobert Phillips
14086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt/* See also ../Dos/dosmodule.c */
1527a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt
1627a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#ifdef __APPLE__
1718d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt   /*
1818d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt    * Step 1 of support for weak-linking a number of symbols existing on
1925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
2027a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt    * at the end of this file for more information.
2127a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt    */
2227a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#  pragma weak lchown
2327a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#  pragma weak statvfs
24c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#  pragma weak fstatvfs
25c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas
2663fd760a37905c45d26fc3d49cac261fad1b4808Ben Wagner#endif /* __APPLE__ */
27c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas
28c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#define PY_SSIZE_T_CLEAN
2927a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt
3027a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#include "Python.h"
3127a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#include "structseq.h"
3263fd760a37905c45d26fc3d49cac261fad1b4808Ben Wagner
33b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#if defined(__VMS)
34b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#    include <unixio.h>
3587a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt#endif /* defined(__VMS) */
36c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas
37c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#ifdef __cplusplus
38c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholasextern "C" {
39c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#endif
40c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas
41c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholasPyDoc_STRVAR(posix__doc__,
42c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas"This module provides access to operating system functionality that is\n\
43c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholasstandardized by the C Standard and the POSIX standard (a thinly\n\
44c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholasdisguised Unix interface).  Refer to the library manual and\n\
45c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholascorresponding Unix manual entries for more information on calls.");
46c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas
47c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas
48c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#if defined(PYOS_OS2)
49c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#define  INCL_DOS
50c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#define  INCL_DOSERRORS
51c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#define  INCL_DOSPROCESS
52c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#define  INCL_NOPMAPI
5342ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#include <os2.h>
5418d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#if defined(PYCC_GCC)
5542ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#include <ctype.h>
5642ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#include <io.h>
5718d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#include <stdio.h>
5842ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#include <process.h>
5918d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#endif
6018d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#include "osdefs.h"
6118d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#endif
6218d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt
6318d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#ifdef HAVE_SYS_TYPES_H
6418d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#include <sys/types.h>
6542ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#endif /* HAVE_SYS_TYPES_H */
66b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt
6742ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#ifdef HAVE_SYS_STAT_H
6842ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#include <sys/stat.h>
69b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#endif /* HAVE_SYS_STAT_H */
7087a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt
7187a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt#ifdef HAVE_SYS_WAIT_H
7242ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#include <sys/wait.h>		/* For WNOHANG */
7327a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#endif
74b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt
75b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#ifdef HAVE_SIGNAL_H
76b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#include <signal.h>
77b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#endif
7887a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt
79f55c3644850409c9410051c7a7f18af8d65bf990joshualitt#ifdef HAVE_FCNTL_H
80f55c3644850409c9410051c7a7f18af8d65bf990joshualitt#include <fcntl.h>
81f55c3644850409c9410051c7a7f18af8d65bf990joshualitt#endif /* HAVE_FCNTL_H */
82f55c3644850409c9410051c7a7f18af8d65bf990joshualitt
83f55c3644850409c9410051c7a7f18af8d65bf990joshualitt#ifdef HAVE_GRP_H
84318c419d3e373487a8bb28f56ea921ed850e61acRobert Phillips#include <grp.h>
85086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualitt#endif
8642ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon
8718d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#ifdef HAVE_SYSEXITS_H
8842ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#include <sysexits.h>
8942ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#endif /* HAVE_SYSEXITS_H */
9042ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon
9142ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#ifdef HAVE_SYS_LOADAVG_H
9242ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#include <sys/loadavg.h>
9342ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#endif
94b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt
95b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#ifdef HAVE_LANGINFO_H
9642ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#include <langinfo.h>
97b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#endif
9827a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt
99c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas/* Various compilers have only certain posix functions */
100c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas/* XXX Gosh I wish these were all moved into pyconfig.h */
101c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#if defined(PYCC_VACPP) && defined(PYOS_OS2)
102b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#include <process.h>
10318d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#else
10410d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt#if defined(__WATCOMC__) && !defined(__QNX__)		/* Watcom compiler */
10510d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt#define HAVE_GETCWD     1
10642ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#define HAVE_OPENDIR    1
10742ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#define HAVE_SYSTEM	1
108f7a7261b4ac23f97580a8ff6f0307b3c47399b9dRobert Phillips#if defined(__OS2__)
10910d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt#define HAVE_EXECV      1
11010d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt#define HAVE_WAIT       1
111f7a7261b4ac23f97580a8ff6f0307b3c47399b9dRobert Phillips#endif
112f7a7261b4ac23f97580a8ff6f0307b3c47399b9dRobert Phillips#include <process.h>
113f7a7261b4ac23f97580a8ff6f0307b3c47399b9dRobert Phillips#else
114f7a7261b4ac23f97580a8ff6f0307b3c47399b9dRobert Phillips#ifdef __BORLANDC__		/* Borland compiler */
11510d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt#define HAVE_EXECV      1
11610d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt#define HAVE_GETCWD     1
11742ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#define HAVE_OPENDIR    1
11842ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#define HAVE_PIPE       1
11910d8fc29bc1605c134e98f5b58c2efb73cef6073joshualitt#define HAVE_SYSTEM	1
120df3f2b0948507d20e72b16869f1b2bb1abdf4b40joshualitt#define HAVE_WAIT       1
12118d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#else
122b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#ifdef _MSC_VER		/* Microsoft compiler */
12327a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#define HAVE_GETCWD     1
12427a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#define HAVE_SPAWNV	1
12511fae87d39811882e3e99b4abc72c9713a38da55joshualitt#define HAVE_EXECV      1
12642ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#define HAVE_PIPE       1
127b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#define HAVE_SYSTEM	1
128b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#define HAVE_CWAIT	1
129f55c3644850409c9410051c7a7f18af8d65bf990joshualitt#define HAVE_FSYNC	1
130b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#define fsync _commit
131b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#else
13242ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS)
133b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt/* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */
13427a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#else			/* all other compilers */
13542ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon/* Unix functions that the configure script doesn't check for */
13627a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#define HAVE_EXECV      1
13742ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#define HAVE_FORK       1
13811fae87d39811882e3e99b4abc72c9713a38da55joshualitt#if defined(__USLC__) && defined(__SCO_VERSION__)	/* SCO UDK Compiler */
13942ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#define HAVE_FORK1      1
140318c419d3e373487a8bb28f56ea921ed850e61acRobert Phillips#endif
141b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt#define HAVE_GETCWD     1
142f7a7261b4ac23f97580a8ff6f0307b3c47399b9dRobert Phillips#define HAVE_GETEGID    1
143294870ff119b89fc902773643b054f14e5d1f554Robert Phillips#define HAVE_GETEUID    1
144f7a7261b4ac23f97580a8ff6f0307b3c47399b9dRobert Phillips#define HAVE_GETGID     1
145f7a7261b4ac23f97580a8ff6f0307b3c47399b9dRobert Phillips#define HAVE_GETPPID    1
14611fae87d39811882e3e99b4abc72c9713a38da55joshualitt#define HAVE_GETUID     1
14742ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#define HAVE_KILL       1
14811fae87d39811882e3e99b4abc72c9713a38da55joshualitt#define HAVE_OPENDIR    1
14942ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#define HAVE_PIPE       1
15046b301d2222b60dd5ab495b917dea163e8be94efjoshualitt#define HAVE_SYSTEM	1
15118d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#define HAVE_WAIT       1
15218d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#define HAVE_TTYNAME	1
153adab5a2a4b2ae4d7fa832093fe81a640e848746cjoshualitt#endif  /* PYOS_OS2 && PYCC_GCC && __VMS */
1546bd5284415bd983b0628c4941dff5def40018f5abungeman#endif  /* _MSC_VER */
15542ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#endif  /* __BORLANDC__ */
156b0666ad3a9e99ce1a6e6d9ea69ff9f1ddbe74594joshualitt#endif  /* ! __WATCOMC__ || __QNX__ */
15742ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#endif /* ! __IBMC__ */
15842ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon
159f55c3644850409c9410051c7a7f18af8d65bf990joshualitt#ifndef _MSC_VER
160b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt
16142ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#if defined(__sgi)&&_COMPILER_VERSION>=700
162b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
163b95c772d45efc98f0159fa65c7aa06314cecb9dejoshualitt   (default) */
16427a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualittextern char        *ctermid_r(char *);
16527a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualitt#endif
166c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas
167c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#ifndef HAVE_UNISTD_H
168c85d9fbc0adacc9acb9faa3fe107652f0d76760aethannicholas#if defined(PYCC_VACPP)
1695651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualittextern int mkdir(char *);
1705651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualitt#else
17187a721b2465c9ccfa191ce9f5012f92be7731fbcjoshualitt#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
172f55c3644850409c9410051c7a7f18af8d65bf990joshualittextern int mkdir(const char *);
1735651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualitt#else
1745651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualittextern int mkdir(const char *, mode_t);
175f55c3644850409c9410051c7a7f18af8d65bf990joshualitt#endif
1765651ee6376dc3271ea8f4fc91b037c8f361c3cfajoshualitt#endif
177318c419d3e373487a8bb28f56ea921ed850e61acRobert Phillips#if defined(__IBMC__) || defined(__IBMCPP__)
178318c419d3e373487a8bb28f56ea921ed850e61acRobert Phillipsextern int chdir(char *);
179086cee12deaf9a9f46bbd2e52173e0e4fc4df311joshualittextern int rmdir(char *);
18042ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#else
18142ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomonextern int chdir(const char *);
18218d6b75829ac5d90050ca4da4f99292c14ff06f0joshualittextern int rmdir(const char *);
18342ad83ac194c4c1848fef95e6cdcad83729e6ecfBrian Salomon#endif
18418d6b75829ac5d90050ca4da4f99292c14ff06f0joshualitt#ifdef __BORLANDC__
18527a48dc0cddad7f3531dcf0d39d290e7233e3e76joshualittextern int chmod(const char *, int);
186#else
187extern int chmod(const char *, mode_t);
188#endif
189/*#ifdef HAVE_FCHMOD
190extern int fchmod(int, mode_t);
191#endif*/
192/*#ifdef HAVE_LCHMOD
193extern int lchmod(const char *, mode_t);
194#endif*/
195extern int chown(const char *, uid_t, gid_t);
196extern char *getcwd(char *, int);
197extern char *strerror(int);
198extern int link(const char *, const char *);
199extern int rename(const char *, const char *);
200extern int stat(const char *, struct stat *);
201extern int unlink(const char *);
202#ifdef HAVE_SYMLINK
203extern int symlink(const char *, const char *);
204#endif /* HAVE_SYMLINK */
205#ifdef HAVE_LSTAT
206extern int lstat(const char *, struct stat *);
207#endif /* HAVE_LSTAT */
208#endif /* !HAVE_UNISTD_H */
209
210#endif /* !_MSC_VER */
211
212#ifdef HAVE_UTIME_H
213#include <utime.h>
214#endif /* HAVE_UTIME_H */
215
216#ifdef HAVE_SYS_UTIME_H
217#include <sys/utime.h>
218#define HAVE_UTIME_H /* pretend we do for the rest of this file */
219#endif /* HAVE_SYS_UTIME_H */
220
221#ifdef HAVE_SYS_TIMES_H
222#include <sys/times.h>
223#endif /* HAVE_SYS_TIMES_H */
224
225#ifdef HAVE_SYS_PARAM_H
226#include <sys/param.h>
227#endif /* HAVE_SYS_PARAM_H */
228
229#ifdef HAVE_SYS_UTSNAME_H
230#include <sys/utsname.h>
231#endif /* HAVE_SYS_UTSNAME_H */
232
233#ifdef HAVE_DIRENT_H
234#include <dirent.h>
235#define NAMLEN(dirent) strlen((dirent)->d_name)
236#else
237#if defined(__WATCOMC__) && !defined(__QNX__)
238#include <direct.h>
239#define NAMLEN(dirent) strlen((dirent)->d_name)
240#else
241#define dirent direct
242#define NAMLEN(dirent) (dirent)->d_namlen
243#endif
244#ifdef HAVE_SYS_NDIR_H
245#include <sys/ndir.h>
246#endif
247#ifdef HAVE_SYS_DIR_H
248#include <sys/dir.h>
249#endif
250#ifdef HAVE_NDIR_H
251#include <ndir.h>
252#endif
253#endif
254
255#ifdef _MSC_VER
256#ifdef HAVE_DIRECT_H
257#include <direct.h>
258#endif
259#ifdef HAVE_IO_H
260#include <io.h>
261#endif
262#ifdef HAVE_PROCESS_H
263#include <process.h>
264#endif
265#include "osdefs.h"
266#include <windows.h>
267#include <shellapi.h>	/* for ShellExecute() */
268#endif /* _MSC_VER */
269
270#if defined(PYCC_VACPP) && defined(PYOS_OS2)
271#include <io.h>
272#endif /* OS2 */
273
274#ifndef MAXPATHLEN
275#if defined(PATH_MAX) && PATH_MAX > 1024
276#define MAXPATHLEN PATH_MAX
277#else
278#define MAXPATHLEN 1024
279#endif
280#endif /* MAXPATHLEN */
281
282#ifdef UNION_WAIT
283/* Emulate some macros on systems that have a union instead of macros */
284
285#ifndef WIFEXITED
286#define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
287#endif
288
289#ifndef WEXITSTATUS
290#define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
291#endif
292
293#ifndef WTERMSIG
294#define WTERMSIG(u_wait) ((u_wait).w_termsig)
295#endif
296
297#define WAIT_TYPE union wait
298#define WAIT_STATUS_INT(s) (s.w_status)
299
300#else /* !UNION_WAIT */
301#define WAIT_TYPE int
302#define WAIT_STATUS_INT(s) (s)
303#endif /* UNION_WAIT */
304
305/* Don't use the "_r" form if we don't need it (also, won't have a
306   prototype for it, at least on Solaris -- maybe others as well?). */
307#if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
308#define USE_CTERMID_R
309#endif
310
311/* choose the appropriate stat and fstat functions and return structs */
312#undef STAT
313#if defined(MS_WIN64) || defined(MS_WINDOWS)
314#	define STAT win32_stat
315#	define FSTAT win32_fstat
316#	define STRUCT_STAT struct win32_stat
317#else
318#	define STAT stat
319#	define FSTAT fstat
320#	define STRUCT_STAT struct stat
321#endif
322
323#if defined(MAJOR_IN_MKDEV)
324#include <sys/mkdev.h>
325#else
326#if defined(MAJOR_IN_SYSMACROS)
327#include <sys/sysmacros.h>
328#endif
329#if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
330#include <sys/mkdev.h>
331#endif
332#endif
333
334/* Return a dictionary corresponding to the POSIX environment table */
335#ifdef WITH_NEXT_FRAMEWORK
336/* On Darwin/MacOSX a shared library or framework has no access to
337** environ directly, we must obtain it with _NSGetEnviron().
338*/
339#include <crt_externs.h>
340static char **environ;
341#elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
342extern char **environ;
343#endif /* !_MSC_VER */
344
345static PyObject *
346convertenviron(void)
347{
348	PyObject *d;
349#ifdef MS_WINDOWS
350	wchar_t **e;
351#else
352	char **e;
353#endif
354	d = PyDict_New();
355	if (d == NULL)
356		return NULL;
357#ifdef WITH_NEXT_FRAMEWORK
358	if (environ == NULL)
359		environ = *_NSGetEnviron();
360#endif
361#ifdef MS_WINDOWS
362	/* _wenviron must be initialized in this way if the program is started
363	   through main() instead of wmain(). */
364	_wgetenv(L"");
365	if (_wenviron == NULL)
366		return d;
367	/* This part ignores errors */
368	for (e = _wenviron; *e != NULL; e++) {
369		PyObject *k;
370		PyObject *v;
371		wchar_t *p = wcschr(*e, L'=');
372		if (p == NULL)
373			continue;
374		k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
375		if (k == NULL) {
376			PyErr_Clear();
377			continue;
378		}
379		v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
380		if (v == NULL) {
381			PyErr_Clear();
382			Py_DECREF(k);
383			continue;
384		}
385		if (PyDict_GetItem(d, k) == NULL) {
386			if (PyDict_SetItem(d, k, v) != 0)
387				PyErr_Clear();
388		}
389		Py_DECREF(k);
390		Py_DECREF(v);
391	}
392#else
393	if (environ == NULL)
394		return d;
395	/* This part ignores errors */
396	for (e = environ; *e != NULL; e++) {
397		PyObject *k;
398		PyObject *v;
399		char *p = strchr(*e, '=');
400		if (p == NULL)
401			continue;
402		k = PyUnicode_FromStringAndSize(*e, (int)(p-*e));
403		if (k == NULL) {
404			PyErr_Clear();
405			continue;
406		}
407		v = PyUnicode_FromString(p+1);
408		if (v == NULL) {
409			PyErr_Clear();
410			Py_DECREF(k);
411			continue;
412		}
413		if (PyDict_GetItem(d, k) == NULL) {
414			if (PyDict_SetItem(d, k, v) != 0)
415				PyErr_Clear();
416		}
417		Py_DECREF(k);
418		Py_DECREF(v);
419	}
420#endif
421#if defined(PYOS_OS2)
422    {
423        APIRET rc;
424        char   buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */
425
426        rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH);
427	if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */
428            PyObject *v = PyString_FromString(buffer);
429	    PyDict_SetItemString(d, "BEGINLIBPATH", v);
430            Py_DECREF(v);
431        }
432        rc = DosQueryExtLIBPATH(buffer, END_LIBPATH);
433        if (rc == NO_ERROR) { /* (not a typo, envname is NOT 'END_LIBPATH') */
434            PyObject *v = PyString_FromString(buffer);
435	    PyDict_SetItemString(d, "ENDLIBPATH", v);
436            Py_DECREF(v);
437        }
438    }
439#endif
440	return d;
441}
442
443
444/* Set a POSIX-specific error from errno, and return NULL */
445
446static PyObject *
447posix_error(void)
448{
449	return PyErr_SetFromErrno(PyExc_OSError);
450}
451static PyObject *
452posix_error_with_filename(char* name)
453{
454	return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
455}
456
457#ifdef Py_WIN_WIDE_FILENAMES
458static PyObject *
459posix_error_with_unicode_filename(Py_UNICODE* name)
460{
461	return PyErr_SetFromErrnoWithUnicodeFilename(PyExc_OSError, name);
462}
463#endif /* Py_WIN_WIDE_FILENAMES */
464
465
466static PyObject *
467posix_error_with_allocated_filename(char* name)
468{
469	PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
470	PyMem_Free(name);
471	return rc;
472}
473
474#ifdef MS_WINDOWS
475static PyObject *
476win32_error(char* function, char* filename)
477{
478	/* XXX We should pass the function name along in the future.
479	   (_winreg.c also wants to pass the function name.)
480	   This would however require an additional param to the
481	   Windows error object, which is non-trivial.
482	*/
483	errno = GetLastError();
484	if (filename)
485		return PyErr_SetFromWindowsErrWithFilename(errno, filename);
486	else
487		return PyErr_SetFromWindowsErr(errno);
488}
489
490#ifdef Py_WIN_WIDE_FILENAMES
491static PyObject *
492win32_error_unicode(char* function, Py_UNICODE* filename)
493{
494	/* XXX - see win32_error for comments on 'function' */
495	errno = GetLastError();
496	if (filename)
497		return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename);
498	else
499		return PyErr_SetFromWindowsErr(errno);
500}
501
502static PyObject *_PyUnicode_FromFileSystemEncodedObject(register PyObject *obj)
503{
504}
505
506/* Function suitable for O& conversion */
507static int
508convert_to_unicode(PyObject *arg, void* _param)
509{
510	PyObject **param = (PyObject**)_param;
511	if (PyUnicode_CheckExact(arg)) {
512		Py_INCREF(arg);
513		*param = arg;
514	}
515	else if (PyUnicode_Check(arg)) {
516		/* For a Unicode subtype that's not a Unicode object,
517		   return a true Unicode object with the same data. */
518		*param = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(arg),
519					       PyUnicode_GET_SIZE(arg));
520		return *param != NULL;
521	}
522	else
523		*param = PyUnicode_FromEncodedObject(arg,
524				                     Py_FileSystemDefaultEncoding,
525					             "strict");
526	return (*param) != NULL;
527}
528
529#endif /* Py_WIN_WIDE_FILENAMES */
530
531#endif
532
533#if defined(PYOS_OS2)
534/**********************************************************************
535 *         Helper Function to Trim and Format OS/2 Messages
536 **********************************************************************/
537    static void
538os2_formatmsg(char *msgbuf, int msglen, char *reason)
539{
540    msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */
541
542    if (strlen(msgbuf) > 0) { /* If Non-Empty Msg, Trim CRLF */
543        char *lastc = &msgbuf[ strlen(msgbuf)-1 ];
544
545        while (lastc > msgbuf && isspace(Py_CHARMASK(*lastc)))
546            *lastc-- = '\0'; /* Trim Trailing Whitespace (CRLF) */
547    }
548
549    /* Add Optional Reason Text */
550    if (reason) {
551        strcat(msgbuf, " : ");
552        strcat(msgbuf, reason);
553    }
554}
555
556/**********************************************************************
557 *             Decode an OS/2 Operating System Error Code
558 *
559 * A convenience function to lookup an OS/2 error code and return a
560 * text message we can use to raise a Python exception.
561 *
562 * Notes:
563 *   The messages for errors returned from the OS/2 kernel reside in
564 *   the file OSO001.MSG in the \OS2 directory hierarchy.
565 *
566 **********************************************************************/
567    static char *
568os2_strerror(char *msgbuf, int msgbuflen, int errorcode, char *reason)
569{
570    APIRET rc;
571    ULONG  msglen;
572
573    /* Retrieve Kernel-Related Error Message from OSO001.MSG File */
574    Py_BEGIN_ALLOW_THREADS
575    rc = DosGetMessage(NULL, 0, msgbuf, msgbuflen,
576                       errorcode, "oso001.msg", &msglen);
577    Py_END_ALLOW_THREADS
578
579    if (rc == NO_ERROR)
580        os2_formatmsg(msgbuf, msglen, reason);
581    else
582        PyOS_snprintf(msgbuf, msgbuflen,
583        	      "unknown OS error #%d", errorcode);
584
585    return msgbuf;
586}
587
588/* Set an OS/2-specific error and return NULL.  OS/2 kernel
589   errors are not in a global variable e.g. 'errno' nor are
590   they congruent with posix error numbers. */
591
592static PyObject * os2_error(int code)
593{
594    char text[1024];
595    PyObject *v;
596
597    os2_strerror(text, sizeof(text), code, "");
598
599    v = Py_BuildValue("(is)", code, text);
600    if (v != NULL) {
601        PyErr_SetObject(PyExc_OSError, v);
602        Py_DECREF(v);
603    }
604    return NULL; /* Signal to Python that an Exception is Pending */
605}
606
607#endif /* OS2 */
608
609/* POSIX generic methods */
610
611static PyObject *
612posix_fildes(PyObject *fdobj, int (*func)(int))
613{
614	int fd;
615	int res;
616	fd = PyObject_AsFileDescriptor(fdobj);
617	if (fd < 0)
618		return NULL;
619	Py_BEGIN_ALLOW_THREADS
620	res = (*func)(fd);
621	Py_END_ALLOW_THREADS
622	if (res < 0)
623		return posix_error();
624	Py_INCREF(Py_None);
625	return Py_None;
626}
627
628#ifdef Py_WIN_WIDE_FILENAMES
629static int
630unicode_file_names(void)
631{
632	static int canusewide = -1;
633	if (canusewide == -1) {
634		/* As per doc for ::GetVersion(), this is the correct test for
635		   the Windows NT family. */
636		canusewide = (GetVersion() < 0x80000000) ? 1 : 0;
637	}
638	return canusewide;
639}
640#endif
641
642static PyObject *
643posix_1str(PyObject *args, char *format, int (*func)(const char*))
644{
645	char *path1 = NULL;
646	int res;
647	if (!PyArg_ParseTuple(args, format,
648	                      Py_FileSystemDefaultEncoding, &path1))
649		return NULL;
650	Py_BEGIN_ALLOW_THREADS
651	res = (*func)(path1);
652	Py_END_ALLOW_THREADS
653	if (res < 0)
654		return posix_error_with_allocated_filename(path1);
655	PyMem_Free(path1);
656	Py_INCREF(Py_None);
657	return Py_None;
658}
659
660static PyObject *
661posix_2str(PyObject *args,
662	   char *format,
663	   int (*func)(const char *, const char *))
664{
665	char *path1 = NULL, *path2 = NULL;
666	int res;
667	if (!PyArg_ParseTuple(args, format,
668	                      Py_FileSystemDefaultEncoding, &path1,
669	                      Py_FileSystemDefaultEncoding, &path2))
670		return NULL;
671	Py_BEGIN_ALLOW_THREADS
672	res = (*func)(path1, path2);
673	Py_END_ALLOW_THREADS
674	PyMem_Free(path1);
675	PyMem_Free(path2);
676	if (res != 0)
677		/* XXX how to report both path1 and path2??? */
678		return posix_error();
679	Py_INCREF(Py_None);
680	return Py_None;
681}
682
683#ifdef Py_WIN_WIDE_FILENAMES
684static PyObject*
685win32_1str(PyObject* args, char* func,
686	   char* format, BOOL (__stdcall *funcA)(LPCSTR),
687	   char* wformat, BOOL (__stdcall *funcW)(LPWSTR))
688{
689	PyObject *uni;
690	char *ansi;
691	BOOL result;
692	if (unicode_file_names()) {
693		if (!PyArg_ParseTuple(args, wformat, &uni))
694			PyErr_Clear();
695		else {
696			Py_BEGIN_ALLOW_THREADS
697			result = funcW(PyUnicode_AsUnicode(uni));
698			Py_END_ALLOW_THREADS
699			if (!result)
700				return win32_error_unicode(func, PyUnicode_AsUnicode(uni));
701			Py_INCREF(Py_None);
702			return Py_None;
703		}
704	}
705	if (!PyArg_ParseTuple(args, format, &ansi))
706		return NULL;
707	Py_BEGIN_ALLOW_THREADS
708	result = funcA(ansi);
709	Py_END_ALLOW_THREADS
710	if (!result)
711		return win32_error(func, ansi);
712	Py_INCREF(Py_None);
713	return Py_None;
714
715}
716
717/* This is a reimplementation of the C library's chdir function,
718   but one that produces Win32 errors instead of DOS error codes.
719   chdir is essentially a wrapper around SetCurrentDirectory; however,
720   it also needs to set "magic" environment variables indicating
721   the per-drive current directory, which are of the form =<drive>: */
722BOOL __stdcall
723win32_chdir(LPCSTR path)
724{
725	char new_path[MAX_PATH+1];
726	int result;
727	char env[4] = "=x:";
728
729	if(!SetCurrentDirectoryA(path))
730		return FALSE;
731	result = GetCurrentDirectoryA(MAX_PATH+1, new_path);
732	if (!result)
733		return FALSE;
734	/* In the ANSI API, there should not be any paths longer
735	   than MAX_PATH. */
736	assert(result <= MAX_PATH+1);
737	if (strncmp(new_path, "\\\\", 2) == 0 ||
738	    strncmp(new_path, "//", 2) == 0)
739	    /* UNC path, nothing to do. */
740	    return TRUE;
741	env[1] = new_path[0];
742	return SetEnvironmentVariableA(env, new_path);
743}
744
745/* The Unicode version differs from the ANSI version
746   since the current directory might exceed MAX_PATH characters */
747BOOL __stdcall
748win32_wchdir(LPCWSTR path)
749{
750	wchar_t _new_path[MAX_PATH+1], *new_path = _new_path;
751	int result;
752	wchar_t env[4] = L"=x:";
753
754	if(!SetCurrentDirectoryW(path))
755		return FALSE;
756	result = GetCurrentDirectoryW(MAX_PATH+1, new_path);
757	if (!result)
758		return FALSE;
759	if (result > MAX_PATH+1) {
760		new_path = malloc(result);
761		if (!new_path) {
762			SetLastError(ERROR_OUTOFMEMORY);
763			return FALSE;
764		}
765	}
766	if (wcsncmp(new_path, L"\\\\", 2) == 0 ||
767	    wcsncmp(new_path, L"//", 2) == 0)
768	    /* UNC path, nothing to do. */
769	    return TRUE;
770	env[1] = new_path[0];
771	result = SetEnvironmentVariableW(env, new_path);
772	if (new_path != _new_path)
773		free(new_path);
774	return result;
775}
776#endif
777
778#ifdef MS_WINDOWS
779/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
780   - time stamps are restricted to second resolution
781   - file modification times suffer from forth-and-back conversions between
782     UTC and local time
783   Therefore, we implement our own stat, based on the Win32 API directly.
784*/
785#define HAVE_STAT_NSEC 1
786
787struct win32_stat{
788    int st_dev;
789    __int64 st_ino;
790    unsigned short st_mode;
791    int st_nlink;
792    int st_uid;
793    int st_gid;
794    int st_rdev;
795    __int64 st_size;
796    int st_atime;
797    int st_atime_nsec;
798    int st_mtime;
799    int st_mtime_nsec;
800    int st_ctime;
801    int st_ctime_nsec;
802};
803
804static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
805
806static void
807FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, int *time_out, int* nsec_out)
808{
809	/* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
810	/* Cannot simply cast and dereference in_ptr,
811	   since it might not be aligned properly */
812	__int64 in;
813	memcpy(&in, in_ptr, sizeof(in));
814	*nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
815	/* XXX Win32 supports time stamps past 2038; we currently don't */
816	*time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, int);
817}
818
819static void
820time_t_to_FILE_TIME(int time_in, int nsec_in, FILETIME *out_ptr)
821{
822	/* XXX endianness */
823	__int64 out;
824	out = time_in + secs_between_epochs;
825	out = out * 10000000 + nsec_in / 100;
826	memcpy(out_ptr, &out, sizeof(out));
827}
828
829/* Below, we *know* that ugo+r is 0444 */
830#if _S_IREAD != 0400
831#error Unsupported C library
832#endif
833static int
834attributes_to_mode(DWORD attr)
835{
836	int m = 0;
837	if (attr & FILE_ATTRIBUTE_DIRECTORY)
838		m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
839	else
840		m |= _S_IFREG;
841	if (attr & FILE_ATTRIBUTE_READONLY)
842		m |= 0444;
843	else
844		m |= 0666;
845	return m;
846}
847
848static int
849attribute_data_to_stat(WIN32_FILE_ATTRIBUTE_DATA *info, struct win32_stat *result)
850{
851	memset(result, 0, sizeof(*result));
852	result->st_mode = attributes_to_mode(info->dwFileAttributes);
853	result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
854	FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
855	FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
856	FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
857
858	return 0;
859}
860
861/* Emulate GetFileAttributesEx[AW] on Windows 95 */
862static int checked = 0;
863static BOOL (CALLBACK *gfaxa)(LPCSTR, GET_FILEEX_INFO_LEVELS, LPVOID);
864static BOOL (CALLBACK *gfaxw)(LPCWSTR, GET_FILEEX_INFO_LEVELS, LPVOID);
865static void
866check_gfax()
867{
868	HINSTANCE hKernel32;
869	if (checked)
870	    return;
871	checked = 1;
872	hKernel32 = GetModuleHandle("KERNEL32");
873	*(FARPROC*)&gfaxa = GetProcAddress(hKernel32, "GetFileAttributesExA");
874	*(FARPROC*)&gfaxw = GetProcAddress(hKernel32, "GetFileAttributesExW");
875}
876
877static BOOL
878attributes_from_dir(LPCSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad)
879{
880	HANDLE hFindFile;
881	WIN32_FIND_DATAA FileData;
882	hFindFile = FindFirstFileA(pszFile, &FileData);
883	if (hFindFile == INVALID_HANDLE_VALUE)
884		return FALSE;
885	FindClose(hFindFile);
886	pfad->dwFileAttributes = FileData.dwFileAttributes;
887	pfad->ftCreationTime   = FileData.ftCreationTime;
888	pfad->ftLastAccessTime = FileData.ftLastAccessTime;
889	pfad->ftLastWriteTime  = FileData.ftLastWriteTime;
890	pfad->nFileSizeHigh    = FileData.nFileSizeHigh;
891	pfad->nFileSizeLow     = FileData.nFileSizeLow;
892	return TRUE;
893}
894
895static BOOL
896attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad)
897{
898	HANDLE hFindFile;
899	WIN32_FIND_DATAW FileData;
900	hFindFile = FindFirstFileW(pszFile, &FileData);
901	if (hFindFile == INVALID_HANDLE_VALUE)
902		return FALSE;
903	FindClose(hFindFile);
904	pfad->dwFileAttributes = FileData.dwFileAttributes;
905	pfad->ftCreationTime   = FileData.ftCreationTime;
906	pfad->ftLastAccessTime = FileData.ftLastAccessTime;
907	pfad->ftLastWriteTime  = FileData.ftLastWriteTime;
908	pfad->nFileSizeHigh    = FileData.nFileSizeHigh;
909	pfad->nFileSizeLow     = FileData.nFileSizeLow;
910	return TRUE;
911}
912
913static BOOL WINAPI
914Py_GetFileAttributesExA(LPCSTR pszFile,
915		       GET_FILEEX_INFO_LEVELS level,
916                       LPVOID pv)
917{
918	BOOL result;
919	LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv;
920	/* First try to use the system's implementation, if that is
921	   available and either succeeds to gives an error other than
922	   that it isn't implemented. */
923	check_gfax();
924	if (gfaxa) {
925		result = gfaxa(pszFile, level, pv);
926		if (result || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
927			return result;
928	}
929	/* It's either not present, or not implemented.
930	   Emulate using FindFirstFile. */
931	if (level != GetFileExInfoStandard) {
932		SetLastError(ERROR_INVALID_PARAMETER);
933		return FALSE;
934	}
935	/* Use GetFileAttributes to validate that the file name
936	   does not contain wildcards (which FindFirstFile would
937	   accept). */
938	if (GetFileAttributesA(pszFile) == 0xFFFFFFFF)
939		return FALSE;
940	return attributes_from_dir(pszFile, pfad);
941}
942
943static BOOL WINAPI
944Py_GetFileAttributesExW(LPCWSTR pszFile,
945		       GET_FILEEX_INFO_LEVELS level,
946                       LPVOID pv)
947{
948	BOOL result;
949	LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv;
950	/* First try to use the system's implementation, if that is
951	   available and either succeeds to gives an error other than
952	   that it isn't implemented. */
953	check_gfax();
954	if (gfaxa) {
955		result = gfaxw(pszFile, level, pv);
956		if (result || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
957			return result;
958	}
959	/* It's either not present, or not implemented.
960	   Emulate using FindFirstFile. */
961	if (level != GetFileExInfoStandard) {
962		SetLastError(ERROR_INVALID_PARAMETER);
963		return FALSE;
964	}
965	/* Use GetFileAttributes to validate that the file name
966	   does not contain wildcards (which FindFirstFile would
967	   accept). */
968	if (GetFileAttributesW(pszFile) == 0xFFFFFFFF)
969		return FALSE;
970	return attributes_from_dir_w(pszFile, pfad);
971}
972
973static int
974win32_stat(const char* path, struct win32_stat *result)
975{
976	WIN32_FILE_ATTRIBUTE_DATA info;
977	int code;
978	char *dot;
979	/* XXX not supported on Win95 and NT 3.x */
980	if (!Py_GetFileAttributesExA(path, GetFileExInfoStandard, &info)) {
981		if (GetLastError() != ERROR_SHARING_VIOLATION) {
982			/* Protocol violation: we explicitly clear errno, instead of
983			   setting it to a POSIX error. Callers should use GetLastError. */
984			errno = 0;
985			return -1;
986		} else {
987			/* Could not get attributes on open file. Fall back to
988			   reading the directory. */
989			if (!attributes_from_dir(path, &info)) {
990				/* Very strange. This should not fail now */
991				errno = 0;
992				return -1;
993			}
994		}
995	}
996	code = attribute_data_to_stat(&info, result);
997	if (code != 0)
998		return code;
999	/* Set S_IFEXEC if it is an .exe, .bat, ... */
1000	dot = strrchr(path, '.');
1001	if (dot) {
1002		if (stricmp(dot, ".bat") == 0 ||
1003		stricmp(dot, ".cmd") == 0 ||
1004		stricmp(dot, ".exe") == 0 ||
1005		stricmp(dot, ".com") == 0)
1006		result->st_mode |= 0111;
1007	}
1008	return code;
1009}
1010
1011static int
1012win32_wstat(const wchar_t* path, struct win32_stat *result)
1013{
1014	int code;
1015	const wchar_t *dot;
1016	WIN32_FILE_ATTRIBUTE_DATA info;
1017	/* XXX not supported on Win95 and NT 3.x */
1018	if (!Py_GetFileAttributesExW(path, GetFileExInfoStandard, &info)) {
1019		if (GetLastError() != ERROR_SHARING_VIOLATION) {
1020			/* Protocol violation: we explicitly clear errno, instead of
1021			   setting it to a POSIX error. Callers should use GetLastError. */
1022			errno = 0;
1023			return -1;
1024		} else {
1025			/* Could not get attributes on open file. Fall back to
1026			   reading the directory. */
1027			if (!attributes_from_dir_w(path, &info)) {
1028				/* Very strange. This should not fail now */
1029				errno = 0;
1030				return -1;
1031			}
1032		}
1033	}
1034	code = attribute_data_to_stat(&info, result);
1035	if (code < 0)
1036		return code;
1037	/* Set IFEXEC if it is an .exe, .bat, ... */
1038	dot = wcsrchr(path, '.');
1039	if (dot) {
1040		if (_wcsicmp(dot, L".bat") == 0 ||
1041		    _wcsicmp(dot, L".cmd") == 0 ||
1042		    _wcsicmp(dot, L".exe") == 0 ||
1043		    _wcsicmp(dot, L".com") == 0)
1044			result->st_mode |= 0111;
1045	}
1046	return code;
1047}
1048
1049static int
1050win32_fstat(int file_number, struct win32_stat *result)
1051{
1052	BY_HANDLE_FILE_INFORMATION info;
1053	HANDLE h;
1054	int type;
1055
1056	h = (HANDLE)_get_osfhandle(file_number);
1057
1058	/* Protocol violation: we explicitly clear errno, instead of
1059	   setting it to a POSIX error. Callers should use GetLastError. */
1060	errno = 0;
1061
1062	if (h == INVALID_HANDLE_VALUE) {
1063    		/* This is really a C library error (invalid file handle).
1064		   We set the Win32 error to the closes one matching. */
1065		SetLastError(ERROR_INVALID_HANDLE);
1066		return -1;
1067	}
1068	memset(result, 0, sizeof(*result));
1069
1070	type = GetFileType(h);
1071	if (type == FILE_TYPE_UNKNOWN) {
1072	    DWORD error = GetLastError();
1073	    if (error != 0) {
1074		return -1;
1075	    }
1076	    /* else: valid but unknown file */
1077	}
1078
1079	if (type != FILE_TYPE_DISK) {
1080		if (type == FILE_TYPE_CHAR)
1081			result->st_mode = _S_IFCHR;
1082		else if (type == FILE_TYPE_PIPE)
1083			result->st_mode = _S_IFIFO;
1084		return 0;
1085	}
1086
1087	if (!GetFileInformationByHandle(h, &info)) {
1088		return -1;
1089	}
1090
1091	/* similar to stat() */
1092	result->st_mode = attributes_to_mode(info.dwFileAttributes);
1093	result->st_size = (((__int64)info.nFileSizeHigh)<<32) + info.nFileSizeLow;
1094	FILE_TIME_to_time_t_nsec(&info.ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
1095	FILE_TIME_to_time_t_nsec(&info.ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
1096	FILE_TIME_to_time_t_nsec(&info.ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
1097	/* specific to fstat() */
1098	result->st_nlink = info.nNumberOfLinks;
1099	result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
1100	return 0;
1101}
1102
1103#endif /* MS_WINDOWS */
1104
1105PyDoc_STRVAR(stat_result__doc__,
1106"stat_result: Result from stat or lstat.\n\n\
1107This object may be accessed either as a tuple of\n\
1108  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1109or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1110\n\
1111Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1112or st_flags, they are available as attributes only.\n\
1113\n\
1114See os.stat for more information.");
1115
1116static PyStructSequence_Field stat_result_fields[] = {
1117	{"st_mode",    "protection bits"},
1118	{"st_ino",     "inode"},
1119	{"st_dev",     "device"},
1120	{"st_nlink",   "number of hard links"},
1121	{"st_uid",     "user ID of owner"},
1122	{"st_gid",     "group ID of owner"},
1123	{"st_size",    "total size, in bytes"},
1124	/* The NULL is replaced with PyStructSequence_UnnamedField later. */
1125	{NULL,   "integer time of last access"},
1126	{NULL,   "integer time of last modification"},
1127	{NULL,   "integer time of last change"},
1128	{"st_atime",   "time of last access"},
1129	{"st_mtime",   "time of last modification"},
1130	{"st_ctime",   "time of last change"},
1131#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1132	{"st_blksize", "blocksize for filesystem I/O"},
1133#endif
1134#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1135	{"st_blocks",  "number of blocks allocated"},
1136#endif
1137#ifdef HAVE_STRUCT_STAT_ST_RDEV
1138	{"st_rdev",    "device type (if inode device)"},
1139#endif
1140#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1141	{"st_flags",   "user defined flags for file"},
1142#endif
1143#ifdef HAVE_STRUCT_STAT_ST_GEN
1144	{"st_gen",    "generation number"},
1145#endif
1146#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1147	{"st_birthtime",   "time of creation"},
1148#endif
1149	{0}
1150};
1151
1152#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1153#define ST_BLKSIZE_IDX 13
1154#else
1155#define ST_BLKSIZE_IDX 12
1156#endif
1157
1158#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1159#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
1160#else
1161#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
1162#endif
1163
1164#ifdef HAVE_STRUCT_STAT_ST_RDEV
1165#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
1166#else
1167#define ST_RDEV_IDX ST_BLOCKS_IDX
1168#endif
1169
1170#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1171#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
1172#else
1173#define ST_FLAGS_IDX ST_RDEV_IDX
1174#endif
1175
1176#ifdef HAVE_STRUCT_STAT_ST_GEN
1177#define ST_GEN_IDX (ST_FLAGS_IDX+1)
1178#else
1179#define ST_GEN_IDX ST_FLAGS_IDX
1180#endif
1181
1182#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1183#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
1184#else
1185#define ST_BIRTHTIME_IDX ST_GEN_IDX
1186#endif
1187
1188static PyStructSequence_Desc stat_result_desc = {
1189	"stat_result", /* name */
1190	stat_result__doc__, /* doc */
1191	stat_result_fields,
1192	10
1193};
1194
1195PyDoc_STRVAR(statvfs_result__doc__,
1196"statvfs_result: Result from statvfs or fstatvfs.\n\n\
1197This object may be accessed either as a tuple of\n\
1198  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
1199or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
1200\n\
1201See os.statvfs for more information.");
1202
1203static PyStructSequence_Field statvfs_result_fields[] = {
1204        {"f_bsize",  },
1205        {"f_frsize", },
1206        {"f_blocks", },
1207        {"f_bfree",  },
1208        {"f_bavail", },
1209        {"f_files",  },
1210        {"f_ffree",  },
1211        {"f_favail", },
1212        {"f_flag",   },
1213        {"f_namemax",},
1214        {0}
1215};
1216
1217static PyStructSequence_Desc statvfs_result_desc = {
1218	"statvfs_result", /* name */
1219	statvfs_result__doc__, /* doc */
1220	statvfs_result_fields,
1221	10
1222};
1223
1224static int initialized;
1225static PyTypeObject StatResultType;
1226static PyTypeObject StatVFSResultType;
1227static newfunc structseq_new;
1228
1229static PyObject *
1230statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1231{
1232	PyStructSequence *result;
1233	int i;
1234
1235	result = (PyStructSequence*)structseq_new(type, args, kwds);
1236	if (!result)
1237		return NULL;
1238	/* If we have been initialized from a tuple,
1239	   st_?time might be set to None. Initialize it
1240	   from the int slots.  */
1241	for (i = 7; i <= 9; i++) {
1242		if (result->ob_item[i+3] == Py_None) {
1243			Py_DECREF(Py_None);
1244			Py_INCREF(result->ob_item[i]);
1245			result->ob_item[i+3] = result->ob_item[i];
1246		}
1247	}
1248	return (PyObject*)result;
1249}
1250
1251
1252
1253/* If true, st_?time is float. */
1254static int _stat_float_times = 1;
1255
1256PyDoc_STRVAR(stat_float_times__doc__,
1257"stat_float_times([newval]) -> oldval\n\n\
1258Determine whether os.[lf]stat represents time stamps as float objects.\n\
1259If newval is True, future calls to stat() return floats, if it is False,\n\
1260future calls return ints. \n\
1261If newval is omitted, return the current setting.\n");
1262
1263static PyObject*
1264stat_float_times(PyObject* self, PyObject *args)
1265{
1266	int newval = -1;
1267	if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
1268		return NULL;
1269	if (newval == -1)
1270		/* Return old value */
1271		return PyBool_FromLong(_stat_float_times);
1272	_stat_float_times = newval;
1273	Py_INCREF(Py_None);
1274	return Py_None;
1275}
1276
1277static void
1278fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
1279{
1280	PyObject *fval,*ival;
1281#if SIZEOF_TIME_T > SIZEOF_LONG
1282	ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
1283#else
1284	ival = PyLong_FromLong((long)sec);
1285#endif
1286	if (!ival)
1287		return;
1288	if (_stat_float_times) {
1289		fval = PyFloat_FromDouble(sec + 1e-9*nsec);
1290	} else {
1291		fval = ival;
1292		Py_INCREF(fval);
1293	}
1294	PyStructSequence_SET_ITEM(v, index, ival);
1295	PyStructSequence_SET_ITEM(v, index+3, fval);
1296}
1297
1298/* pack a system stat C structure into the Python stat tuple
1299   (used by posix_stat() and posix_fstat()) */
1300static PyObject*
1301_pystat_fromstructstat(STRUCT_STAT *st)
1302{
1303	unsigned long ansec, mnsec, cnsec;
1304	PyObject *v = PyStructSequence_New(&StatResultType);
1305	if (v == NULL)
1306		return NULL;
1307
1308        PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
1309#ifdef HAVE_LARGEFILE_SUPPORT
1310        PyStructSequence_SET_ITEM(v, 1,
1311				  PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
1312#else
1313        PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long)st->st_ino));
1314#endif
1315#if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
1316        PyStructSequence_SET_ITEM(v, 2,
1317				  PyLong_FromLongLong((PY_LONG_LONG)st->st_dev));
1318#else
1319        PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long)st->st_dev));
1320#endif
1321        PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
1322        PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long)st->st_uid));
1323        PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long)st->st_gid));
1324#ifdef HAVE_LARGEFILE_SUPPORT
1325        PyStructSequence_SET_ITEM(v, 6,
1326				  PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
1327#else
1328        PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong(st->st_size));
1329#endif
1330
1331#if defined(HAVE_STAT_TV_NSEC)
1332	ansec = st->st_atim.tv_nsec;
1333	mnsec = st->st_mtim.tv_nsec;
1334	cnsec = st->st_ctim.tv_nsec;
1335#elif defined(HAVE_STAT_TV_NSEC2)
1336	ansec = st->st_atimespec.tv_nsec;
1337	mnsec = st->st_mtimespec.tv_nsec;
1338	cnsec = st->st_ctimespec.tv_nsec;
1339#elif defined(HAVE_STAT_NSEC)
1340	ansec = st->st_atime_nsec;
1341	mnsec = st->st_mtime_nsec;
1342	cnsec = st->st_ctime_nsec;
1343#else
1344	ansec = mnsec = cnsec = 0;
1345#endif
1346	fill_time(v, 7, st->st_atime, ansec);
1347	fill_time(v, 8, st->st_mtime, mnsec);
1348	fill_time(v, 9, st->st_ctime, cnsec);
1349
1350#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1351	PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
1352			 PyLong_FromLong((long)st->st_blksize));
1353#endif
1354#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1355	PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
1356			 PyLong_FromLong((long)st->st_blocks));
1357#endif
1358#ifdef HAVE_STRUCT_STAT_ST_RDEV
1359	PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
1360			 PyLong_FromLong((long)st->st_rdev));
1361#endif
1362#ifdef HAVE_STRUCT_STAT_ST_GEN
1363	PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
1364			 PyLong_FromLong((long)st->st_gen));
1365#endif
1366#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1367	{
1368	  PyObject *val;
1369	  unsigned long bsec,bnsec;
1370	  bsec = (long)st->st_birthtime;
1371#ifdef HAVE_STAT_TV_NSEC2
1372	  bnsec = st->st_birthtimespec.tv_nsec;
1373#else
1374	  bnsec = 0;
1375#endif
1376	  if (_stat_float_times) {
1377	    val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
1378	  } else {
1379	    val = PyLong_FromLong((long)bsec);
1380	  }
1381	  PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
1382				    val);
1383	}
1384#endif
1385#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1386	PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
1387			 PyLong_FromLong((long)st->st_flags));
1388#endif
1389
1390	if (PyErr_Occurred()) {
1391		Py_DECREF(v);
1392		return NULL;
1393	}
1394
1395	return v;
1396}
1397
1398#ifdef MS_WINDOWS
1399
1400/* IsUNCRoot -- test whether the supplied path is of the form \\SERVER\SHARE\,
1401   where / can be used in place of \ and the trailing slash is optional.
1402   Both SERVER and SHARE must have at least one character.
1403*/
1404
1405#define ISSLASHA(c) ((c) == '\\' || (c) == '/')
1406#define ISSLASHW(c) ((c) == L'\\' || (c) == L'/')
1407#ifndef ARRAYSIZE
1408#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
1409#endif
1410
1411static BOOL
1412IsUNCRootA(char *path, int pathlen)
1413{
1414	#define ISSLASH ISSLASHA
1415
1416	int i, share;
1417
1418	if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1]))
1419		/* minimum UNCRoot is \\x\y */
1420		return FALSE;
1421	for (i = 2; i < pathlen ; i++)
1422		if (ISSLASH(path[i])) break;
1423	if (i == 2 || i == pathlen)
1424		/* do not allow \\\SHARE or \\SERVER */
1425		return FALSE;
1426	share = i+1;
1427	for (i = share; i < pathlen; i++)
1428		if (ISSLASH(path[i])) break;
1429	return (i != share && (i == pathlen || i == pathlen-1));
1430
1431	#undef ISSLASH
1432}
1433
1434#ifdef Py_WIN_WIDE_FILENAMES
1435static BOOL
1436IsUNCRootW(Py_UNICODE *path, int pathlen)
1437{
1438	#define ISSLASH ISSLASHW
1439
1440	int i, share;
1441
1442	if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1]))
1443		/* minimum UNCRoot is \\x\y */
1444		return FALSE;
1445	for (i = 2; i < pathlen ; i++)
1446		if (ISSLASH(path[i])) break;
1447	if (i == 2 || i == pathlen)
1448		/* do not allow \\\SHARE or \\SERVER */
1449		return FALSE;
1450	share = i+1;
1451	for (i = share; i < pathlen; i++)
1452		if (ISSLASH(path[i])) break;
1453	return (i != share && (i == pathlen || i == pathlen-1));
1454
1455	#undef ISSLASH
1456}
1457#endif /* Py_WIN_WIDE_FILENAMES */
1458#endif /* MS_WINDOWS */
1459
1460static PyObject *
1461posix_do_stat(PyObject *self, PyObject *args,
1462	      char *format,
1463#ifdef __VMS
1464	      int (*statfunc)(const char *, STRUCT_STAT *, ...),
1465#else
1466	      int (*statfunc)(const char *, STRUCT_STAT *),
1467#endif
1468	      char *wformat,
1469	      int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *))
1470{
1471	STRUCT_STAT st;
1472	char *path = NULL;	/* pass this to stat; do not free() it */
1473	char *pathfree = NULL;  /* this memory must be free'd */
1474	int res;
1475	PyObject *result;
1476
1477#ifdef Py_WIN_WIDE_FILENAMES
1478	/* If on wide-character-capable OS see if argument
1479	   is Unicode and if so use wide API.  */
1480	if (unicode_file_names()) {
1481		PyUnicodeObject *po;
1482		if (PyArg_ParseTuple(args, wformat, &po)) {
1483			Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
1484
1485			Py_BEGIN_ALLOW_THREADS
1486				/* PyUnicode_AS_UNICODE result OK without
1487				   thread lock as it is a simple dereference. */
1488			res = wstatfunc(wpath, &st);
1489			Py_END_ALLOW_THREADS
1490
1491			if (res != 0)
1492				return win32_error_unicode("stat", wpath);
1493			return _pystat_fromstructstat(&st);
1494		}
1495		/* Drop the argument parsing error as narrow strings
1496		   are also valid. */
1497		PyErr_Clear();
1498	}
1499#endif
1500
1501	if (!PyArg_ParseTuple(args, format,
1502	                      Py_FileSystemDefaultEncoding, &path))
1503		return NULL;
1504	pathfree = path;
1505
1506	Py_BEGIN_ALLOW_THREADS
1507	res = (*statfunc)(path, &st);
1508	Py_END_ALLOW_THREADS
1509
1510	if (res != 0) {
1511#ifdef MS_WINDOWS
1512		result = win32_error("stat", pathfree);
1513#else
1514		result = posix_error_with_filename(pathfree);
1515#endif
1516	}
1517	else
1518		result = _pystat_fromstructstat(&st);
1519
1520	PyMem_Free(pathfree);
1521	return result;
1522}
1523
1524/* POSIX methods */
1525
1526PyDoc_STRVAR(posix_access__doc__,
1527"access(path, mode) -> True if granted, False otherwise\n\n\
1528Use the real uid/gid to test for access to a path.  Note that most\n\
1529operations will use the effective uid/gid, therefore this routine can\n\
1530be used in a suid/sgid environment to test if the invoking user has the\n\
1531specified access to the path.  The mode argument can be F_OK to test\n\
1532existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
1533
1534static PyObject *
1535posix_access(PyObject *self, PyObject *args)
1536{
1537	char *path;
1538	int mode;
1539
1540#ifdef Py_WIN_WIDE_FILENAMES
1541	DWORD attr;
1542	if (unicode_file_names()) {
1543		PyUnicodeObject *po;
1544		if (PyArg_ParseTuple(args, "Ui:access", &po, &mode)) {
1545			Py_BEGIN_ALLOW_THREADS
1546			/* PyUnicode_AS_UNICODE OK without thread lock as
1547			   it is a simple dereference. */
1548			attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
1549			Py_END_ALLOW_THREADS
1550			goto finish;
1551		}
1552		/* Drop the argument parsing error as narrow strings
1553		   are also valid. */
1554		PyErr_Clear();
1555	}
1556	if (!PyArg_ParseTuple(args, "eti:access",
1557			      Py_FileSystemDefaultEncoding, &path, &mode))
1558		return 0;
1559	Py_BEGIN_ALLOW_THREADS
1560	attr = GetFileAttributesA(path);
1561	Py_END_ALLOW_THREADS
1562	PyMem_Free(path);
1563finish:
1564	if (attr == 0xFFFFFFFF)
1565		/* File does not exist, or cannot read attributes */
1566		return PyBool_FromLong(0);
1567	/* Access is possible if either write access wasn't requested, or
1568	   the file isn't read-only, or if it's a directory, as there are
1569	   no read-only directories on Windows. */
1570	return PyBool_FromLong(!(mode & 2)
1571	                       || !(attr & FILE_ATTRIBUTE_READONLY)
1572			       || (attr & FILE_ATTRIBUTE_DIRECTORY));
1573#else
1574	int res;
1575	if (!PyArg_ParseTuple(args, "eti:access",
1576			      Py_FileSystemDefaultEncoding, &path, &mode))
1577		return NULL;
1578	Py_BEGIN_ALLOW_THREADS
1579	res = access(path, mode);
1580	Py_END_ALLOW_THREADS
1581	PyMem_Free(path);
1582	return PyBool_FromLong(res == 0);
1583#endif
1584}
1585
1586#ifndef F_OK
1587#define F_OK 0
1588#endif
1589#ifndef R_OK
1590#define R_OK 4
1591#endif
1592#ifndef W_OK
1593#define W_OK 2
1594#endif
1595#ifndef X_OK
1596#define X_OK 1
1597#endif
1598
1599#ifdef HAVE_TTYNAME
1600PyDoc_STRVAR(posix_ttyname__doc__,
1601"ttyname(fd) -> string\n\n\
1602Return the name of the terminal device connected to 'fd'.");
1603
1604static PyObject *
1605posix_ttyname(PyObject *self, PyObject *args)
1606{
1607	int id;
1608	char *ret;
1609
1610	if (!PyArg_ParseTuple(args, "i:ttyname", &id))
1611		return NULL;
1612
1613#if defined(__VMS)
1614        /* file descriptor 0 only, the default input device (stdin) */
1615	if (id == 0) {
1616		ret = ttyname();
1617	}
1618	else {
1619		ret = NULL;
1620	}
1621#else
1622	ret = ttyname(id);
1623#endif
1624	if (ret == NULL)
1625		return posix_error();
1626	return PyUnicode_FromString(ret);
1627}
1628#endif
1629
1630#ifdef HAVE_CTERMID
1631PyDoc_STRVAR(posix_ctermid__doc__,
1632"ctermid() -> string\n\n\
1633Return the name of the controlling terminal for this process.");
1634
1635static PyObject *
1636posix_ctermid(PyObject *self, PyObject *noargs)
1637{
1638        char *ret;
1639        char buffer[L_ctermid];
1640
1641#ifdef USE_CTERMID_R
1642	ret = ctermid_r(buffer);
1643#else
1644        ret = ctermid(buffer);
1645#endif
1646	if (ret == NULL)
1647		return posix_error();
1648	return PyUnicode_FromString(buffer);
1649}
1650#endif
1651
1652PyDoc_STRVAR(posix_chdir__doc__,
1653"chdir(path)\n\n\
1654Change the current working directory to the specified path.");
1655
1656static PyObject *
1657posix_chdir(PyObject *self, PyObject *args)
1658{
1659#ifdef MS_WINDOWS
1660	return win32_1str(args, "chdir", "s:chdir", win32_chdir, "U:chdir", win32_wchdir);
1661#elif defined(PYOS_OS2) && defined(PYCC_GCC)
1662	return posix_1str(args, "et:chdir", _chdir2);
1663#elif defined(__VMS)
1664	return posix_1str(args, "et:chdir", (int (*)(const char *))chdir);
1665#else
1666	return posix_1str(args, "et:chdir", chdir);
1667#endif
1668}
1669
1670#ifdef HAVE_FCHDIR
1671PyDoc_STRVAR(posix_fchdir__doc__,
1672"fchdir(fildes)\n\n\
1673Change to the directory of the given file descriptor.  fildes must be\n\
1674opened on a directory, not a file.");
1675
1676static PyObject *
1677posix_fchdir(PyObject *self, PyObject *fdobj)
1678{
1679	return posix_fildes(fdobj, fchdir);
1680}
1681#endif /* HAVE_FCHDIR */
1682
1683
1684PyDoc_STRVAR(posix_chmod__doc__,
1685"chmod(path, mode)\n\n\
1686Change the access permissions of a file.");
1687
1688static PyObject *
1689posix_chmod(PyObject *self, PyObject *args)
1690{
1691	char *path = NULL;
1692	int i;
1693	int res;
1694#ifdef Py_WIN_WIDE_FILENAMES
1695	DWORD attr;
1696	if (unicode_file_names()) {
1697		PyUnicodeObject *po;
1698		if (PyArg_ParseTuple(args, "Ui|:chmod", &po, &i)) {
1699			Py_BEGIN_ALLOW_THREADS
1700			attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
1701			if (attr != 0xFFFFFFFF) {
1702				if (i & _S_IWRITE)
1703					attr &= ~FILE_ATTRIBUTE_READONLY;
1704				else
1705					attr |= FILE_ATTRIBUTE_READONLY;
1706				res = SetFileAttributesW(PyUnicode_AS_UNICODE(po), attr);
1707			}
1708			else
1709				res = 0;
1710			Py_END_ALLOW_THREADS
1711			if (!res)
1712				return win32_error_unicode("chmod",
1713						PyUnicode_AS_UNICODE(po));
1714			Py_INCREF(Py_None);
1715			return Py_None;
1716		}
1717		/* Drop the argument parsing error as narrow strings
1718		   are also valid. */
1719		PyErr_Clear();
1720	}
1721	if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding,
1722	                      &path, &i))
1723		return NULL;
1724	Py_BEGIN_ALLOW_THREADS
1725	attr = GetFileAttributesA(path);
1726	if (attr != 0xFFFFFFFF) {
1727		if (i & _S_IWRITE)
1728			attr &= ~FILE_ATTRIBUTE_READONLY;
1729		else
1730			attr |= FILE_ATTRIBUTE_READONLY;
1731		res = SetFileAttributesA(path, attr);
1732	}
1733	else
1734		res = 0;
1735	Py_END_ALLOW_THREADS
1736	if (!res) {
1737		win32_error("chmod", path);
1738		PyMem_Free(path);
1739		return NULL;
1740	}
1741	PyMem_Free(path);
1742	Py_INCREF(Py_None);
1743	return Py_None;
1744#else /* Py_WIN_WIDE_FILENAMES */
1745	if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding,
1746	                      &path, &i))
1747		return NULL;
1748	Py_BEGIN_ALLOW_THREADS
1749	res = chmod(path, i);
1750	Py_END_ALLOW_THREADS
1751	if (res < 0)
1752		return posix_error_with_allocated_filename(path);
1753	PyMem_Free(path);
1754	Py_INCREF(Py_None);
1755	return Py_None;
1756#endif
1757}
1758
1759#ifdef HAVE_FCHMOD
1760PyDoc_STRVAR(posix_fchmod__doc__,
1761"fchmod(fd, mode)\n\n\
1762Change the access permissions of the file given by file\n\
1763descriptor fd.");
1764
1765static PyObject *
1766posix_fchmod(PyObject *self, PyObject *args)
1767{
1768	int fd, mode, res;
1769	if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
1770		return NULL;
1771	Py_BEGIN_ALLOW_THREADS
1772	res = fchmod(fd, mode);
1773	Py_END_ALLOW_THREADS
1774	if (res < 0)
1775		return posix_error();
1776	Py_RETURN_NONE;
1777}
1778#endif /* HAVE_FCHMOD */
1779
1780#ifdef HAVE_LCHMOD
1781PyDoc_STRVAR(posix_lchmod__doc__,
1782"lchmod(path, mode)\n\n\
1783Change the access permissions of a file. If path is a symlink, this\n\
1784affects the link itself rather than the target.");
1785
1786static PyObject *
1787posix_lchmod(PyObject *self, PyObject *args)
1788{
1789	char *path = NULL;
1790	int i;
1791	int res;
1792	if (!PyArg_ParseTuple(args, "eti:lchmod", Py_FileSystemDefaultEncoding,
1793	                      &path, &i))
1794		return NULL;
1795	Py_BEGIN_ALLOW_THREADS
1796	res = lchmod(path, i);
1797	Py_END_ALLOW_THREADS
1798	if (res < 0)
1799		return posix_error_with_allocated_filename(path);
1800	PyMem_Free(path);
1801	Py_RETURN_NONE;
1802}
1803#endif /* HAVE_LCHMOD */
1804
1805
1806#ifdef HAVE_CHFLAGS
1807PyDoc_STRVAR(posix_chflags__doc__,
1808"chflags(path, flags)\n\n\
1809Set file flags.");
1810
1811static PyObject *
1812posix_chflags(PyObject *self, PyObject *args)
1813{
1814	char *path;
1815	unsigned long flags;
1816	int res;
1817	if (!PyArg_ParseTuple(args, "etk:chflags",
1818			      Py_FileSystemDefaultEncoding, &path, &flags))
1819		return NULL;
1820	Py_BEGIN_ALLOW_THREADS
1821	res = chflags(path, flags);
1822	Py_END_ALLOW_THREADS
1823	if (res < 0)
1824		return posix_error_with_allocated_filename(path);
1825	PyMem_Free(path);
1826	Py_INCREF(Py_None);
1827	return Py_None;
1828}
1829#endif /* HAVE_CHFLAGS */
1830
1831#ifdef HAVE_LCHFLAGS
1832PyDoc_STRVAR(posix_lchflags__doc__,
1833"lchflags(path, flags)\n\n\
1834Set file flags.\n\
1835This function will not follow symbolic links.");
1836
1837static PyObject *
1838posix_lchflags(PyObject *self, PyObject *args)
1839{
1840	char *path;
1841	unsigned long flags;
1842	int res;
1843	if (!PyArg_ParseTuple(args, "etk:lchflags",
1844			      Py_FileSystemDefaultEncoding, &path, &flags))
1845		return NULL;
1846	Py_BEGIN_ALLOW_THREADS
1847	res = lchflags(path, flags);
1848	Py_END_ALLOW_THREADS
1849	if (res < 0)
1850		return posix_error_with_allocated_filename(path);
1851	PyMem_Free(path);
1852	Py_INCREF(Py_None);
1853	return Py_None;
1854}
1855#endif /* HAVE_LCHFLAGS */
1856
1857#ifdef HAVE_CHROOT
1858PyDoc_STRVAR(posix_chroot__doc__,
1859"chroot(path)\n\n\
1860Change root directory to path.");
1861
1862static PyObject *
1863posix_chroot(PyObject *self, PyObject *args)
1864{
1865	return posix_1str(args, "et:chroot", chroot);
1866}
1867#endif
1868
1869#ifdef HAVE_FSYNC
1870PyDoc_STRVAR(posix_fsync__doc__,
1871"fsync(fildes)\n\n\
1872force write of file with filedescriptor to disk.");
1873
1874static PyObject *
1875posix_fsync(PyObject *self, PyObject *fdobj)
1876{
1877       return posix_fildes(fdobj, fsync);
1878}
1879#endif /* HAVE_FSYNC */
1880
1881#ifdef HAVE_FDATASYNC
1882
1883#ifdef __hpux
1884extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
1885#endif
1886
1887PyDoc_STRVAR(posix_fdatasync__doc__,
1888"fdatasync(fildes)\n\n\
1889force write of file with filedescriptor to disk.\n\
1890 does not force update of metadata.");
1891
1892static PyObject *
1893posix_fdatasync(PyObject *self, PyObject *fdobj)
1894{
1895       return posix_fildes(fdobj, fdatasync);
1896}
1897#endif /* HAVE_FDATASYNC */
1898
1899
1900#ifdef HAVE_CHOWN
1901PyDoc_STRVAR(posix_chown__doc__,
1902"chown(path, uid, gid)\n\n\
1903Change the owner and group id of path to the numeric uid and gid.");
1904
1905static PyObject *
1906posix_chown(PyObject *self, PyObject *args)
1907{
1908	char *path = NULL;
1909	long uid, gid;
1910	int res;
1911	if (!PyArg_ParseTuple(args, "etll:chown",
1912	                      Py_FileSystemDefaultEncoding, &path,
1913	                      &uid, &gid))
1914		return NULL;
1915	Py_BEGIN_ALLOW_THREADS
1916	res = chown(path, (uid_t) uid, (gid_t) gid);
1917	Py_END_ALLOW_THREADS
1918	if (res < 0)
1919		return posix_error_with_allocated_filename(path);
1920	PyMem_Free(path);
1921	Py_INCREF(Py_None);
1922	return Py_None;
1923}
1924#endif /* HAVE_CHOWN */
1925
1926#ifdef HAVE_FCHOWN
1927PyDoc_STRVAR(posix_fchown__doc__,
1928"fchown(fd, uid, gid)\n\n\
1929Change the owner and group id of the file given by file descriptor\n\
1930fd to the numeric uid and gid.");
1931
1932static PyObject *
1933posix_fchown(PyObject *self, PyObject *args)
1934{
1935	int fd, uid, gid;
1936	int res;
1937	if (!PyArg_ParseTuple(args, "iii:chown", &fd, &uid, &gid))
1938		return NULL;
1939	Py_BEGIN_ALLOW_THREADS
1940	res = fchown(fd, (uid_t) uid, (gid_t) gid);
1941	Py_END_ALLOW_THREADS
1942	if (res < 0)
1943		return posix_error();
1944	Py_RETURN_NONE;
1945}
1946#endif /* HAVE_FCHOWN */
1947
1948#ifdef HAVE_LCHOWN
1949PyDoc_STRVAR(posix_lchown__doc__,
1950"lchown(path, uid, gid)\n\n\
1951Change the owner and group id of path to the numeric uid and gid.\n\
1952This function will not follow symbolic links.");
1953
1954static PyObject *
1955posix_lchown(PyObject *self, PyObject *args)
1956{
1957	char *path = NULL;
1958	int uid, gid;
1959	int res;
1960	if (!PyArg_ParseTuple(args, "etii:lchown",
1961	                      Py_FileSystemDefaultEncoding, &path,
1962	                      &uid, &gid))
1963		return NULL;
1964	Py_BEGIN_ALLOW_THREADS
1965	res = lchown(path, (uid_t) uid, (gid_t) gid);
1966	Py_END_ALLOW_THREADS
1967	if (res < 0)
1968		return posix_error_with_allocated_filename(path);
1969	PyMem_Free(path);
1970	Py_INCREF(Py_None);
1971	return Py_None;
1972}
1973#endif /* HAVE_LCHOWN */
1974
1975
1976#ifdef HAVE_GETCWD
1977PyDoc_STRVAR(posix_getcwd__doc__,
1978"getcwd() -> path\n\n\
1979Return a string representing the current working directory.");
1980
1981static PyObject *
1982posix_getcwd(PyObject *self, PyObject *noargs)
1983{
1984	char buf[1026];
1985	char *res;
1986
1987	Py_BEGIN_ALLOW_THREADS
1988#if defined(PYOS_OS2) && defined(PYCC_GCC)
1989	res = _getcwd2(buf, sizeof buf);
1990#else
1991	res = getcwd(buf, sizeof buf);
1992#endif
1993	Py_END_ALLOW_THREADS
1994	if (res == NULL)
1995		return posix_error();
1996	return PyUnicode_FromString(buf);
1997}
1998
1999PyDoc_STRVAR(posix_getcwdu__doc__,
2000"getcwdu() -> path\n\n\
2001Return a unicode string representing the current working directory.");
2002
2003static PyObject *
2004posix_getcwdu(PyObject *self, PyObject *noargs)
2005{
2006	char buf[1026];
2007	char *res;
2008
2009#ifdef Py_WIN_WIDE_FILENAMES
2010	DWORD len;
2011	if (unicode_file_names()) {
2012		wchar_t wbuf[1026];
2013		wchar_t *wbuf2 = wbuf;
2014		PyObject *resobj;
2015		Py_BEGIN_ALLOW_THREADS
2016		len = GetCurrentDirectoryW(sizeof wbuf/ sizeof wbuf[0], wbuf);
2017		/* If the buffer is large enough, len does not include the
2018		   terminating \0. If the buffer is too small, len includes
2019		   the space needed for the terminator. */
2020		if (len >= sizeof wbuf/ sizeof wbuf[0]) {
2021			wbuf2 = malloc(len * sizeof(wchar_t));
2022			if (wbuf2)
2023				len = GetCurrentDirectoryW(len, wbuf2);
2024		}
2025		Py_END_ALLOW_THREADS
2026		if (!wbuf2) {
2027			PyErr_NoMemory();
2028			return NULL;
2029		}
2030		if (!len) {
2031			if (wbuf2 != wbuf) free(wbuf2);
2032			return win32_error("getcwdu", NULL);
2033		}
2034		resobj = PyUnicode_FromWideChar(wbuf2, len);
2035		if (wbuf2 != wbuf) free(wbuf2);
2036		return resobj;
2037	}
2038#endif
2039
2040	Py_BEGIN_ALLOW_THREADS
2041#if defined(PYOS_OS2) && defined(PYCC_GCC)
2042	res = _getcwd2(buf, sizeof buf);
2043#else
2044	res = getcwd(buf, sizeof buf);
2045#endif
2046	Py_END_ALLOW_THREADS
2047	if (res == NULL)
2048		return posix_error();
2049	return PyUnicode_Decode(buf, strlen(buf), Py_FileSystemDefaultEncoding,"strict");
2050}
2051#endif
2052
2053
2054#ifdef HAVE_LINK
2055PyDoc_STRVAR(posix_link__doc__,
2056"link(src, dst)\n\n\
2057Create a hard link to a file.");
2058
2059static PyObject *
2060posix_link(PyObject *self, PyObject *args)
2061{
2062	return posix_2str(args, "etet:link", link);
2063}
2064#endif /* HAVE_LINK */
2065
2066
2067PyDoc_STRVAR(posix_listdir__doc__,
2068"listdir(path) -> list_of_strings\n\n\
2069Return a list containing the names of the entries in the directory.\n\
2070\n\
2071	path: path of directory to list\n\
2072\n\
2073The list is in arbitrary order.  It does not include the special\n\
2074entries '.' and '..' even if they are present in the directory.");
2075
2076static PyObject *
2077posix_listdir(PyObject *self, PyObject *args)
2078{
2079	/* XXX Should redo this putting the (now four) versions of opendir
2080	   in separate files instead of having them all here... */
2081#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
2082
2083	PyObject *d, *v;
2084	HANDLE hFindFile;
2085	BOOL result;
2086	WIN32_FIND_DATA FileData;
2087	char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
2088	char *bufptr = namebuf;
2089	Py_ssize_t len = sizeof(namebuf)-5; /* only claim to have space for MAX_PATH */
2090
2091#ifdef Py_WIN_WIDE_FILENAMES
2092	/* If on wide-character-capable OS see if argument
2093	   is Unicode and if so use wide API.  */
2094	if (unicode_file_names()) {
2095		PyObject *po;
2096		if (PyArg_ParseTuple(args, "U:listdir", &po)) {
2097			WIN32_FIND_DATAW wFileData;
2098			Py_UNICODE *wnamebuf;
2099			Py_UNICODE wch;
2100			/* Overallocate for \\*.*\0 */
2101			len = PyUnicode_GET_SIZE(po);
2102			wnamebuf = malloc((len + 5) * sizeof(wchar_t));
2103			if (!wnamebuf) {
2104				PyErr_NoMemory();
2105				return NULL;
2106			}
2107			wcscpy(wnamebuf, PyUnicode_AS_UNICODE(po));
2108			wch = len > 0 ? wnamebuf[len-1] : '\0';
2109			if (wch != L'/' && wch != L'\\' && wch != L':')
2110				wnamebuf[len++] = L'\\';
2111			wcscpy(wnamebuf + len, L"*.*");
2112			if ((d = PyList_New(0)) == NULL) {
2113				free(wnamebuf);
2114				return NULL;
2115			}
2116			hFindFile = FindFirstFileW(wnamebuf, &wFileData);
2117			if (hFindFile == INVALID_HANDLE_VALUE) {
2118				int error = GetLastError();
2119				if (error == ERROR_FILE_NOT_FOUND) {
2120					free(wnamebuf);
2121					return d;
2122				}
2123				Py_DECREF(d);
2124				win32_error_unicode("FindFirstFileW", wnamebuf);
2125				free(wnamebuf);
2126				return NULL;
2127			}
2128			do {
2129				/* Skip over . and .. */
2130				if (wcscmp(wFileData.cFileName, L".") != 0 &&
2131				    wcscmp(wFileData.cFileName, L"..") != 0) {
2132					v = PyUnicode_FromUnicode(wFileData.cFileName, wcslen(wFileData.cFileName));
2133					if (v == NULL) {
2134						Py_DECREF(d);
2135						d = NULL;
2136						break;
2137					}
2138					if (PyList_Append(d, v) != 0) {
2139						Py_DECREF(v);
2140						Py_DECREF(d);
2141						d = NULL;
2142						break;
2143					}
2144					Py_DECREF(v);
2145				}
2146				Py_BEGIN_ALLOW_THREADS
2147				result = FindNextFileW(hFindFile, &wFileData);
2148				Py_END_ALLOW_THREADS
2149				/* FindNextFile sets error to ERROR_NO_MORE_FILES if
2150				   it got to the end of the directory. */
2151				if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
2152				    Py_DECREF(d);
2153				    win32_error_unicode("FindNextFileW", wnamebuf);
2154				    FindClose(hFindFile);
2155				    free(wnamebuf);
2156				    return NULL;
2157				}
2158			} while (result == TRUE);
2159
2160			if (FindClose(hFindFile) == FALSE) {
2161				Py_DECREF(d);
2162				win32_error_unicode("FindClose", wnamebuf);
2163				free(wnamebuf);
2164				return NULL;
2165			}
2166			free(wnamebuf);
2167			return d;
2168		}
2169		/* Drop the argument parsing error as narrow strings
2170		   are also valid. */
2171		PyErr_Clear();
2172	}
2173#endif
2174
2175	if (!PyArg_ParseTuple(args, "et#:listdir",
2176	                      Py_FileSystemDefaultEncoding, &bufptr, &len))
2177		return NULL;
2178	if (len > 0) {
2179		char ch = namebuf[len-1];
2180		if (ch != SEP && ch != ALTSEP && ch != ':')
2181			namebuf[len++] = '/';
2182	}
2183	strcpy(namebuf + len, "*.*");
2184
2185	if ((d = PyList_New(0)) == NULL)
2186		return NULL;
2187
2188	hFindFile = FindFirstFile(namebuf, &FileData);
2189	if (hFindFile == INVALID_HANDLE_VALUE) {
2190		int error = GetLastError();
2191		if (error == ERROR_FILE_NOT_FOUND)
2192			return d;
2193		Py_DECREF(d);
2194		return win32_error("FindFirstFile", namebuf);
2195	}
2196	do {
2197		/* Skip over . and .. */
2198		if (strcmp(FileData.cFileName, ".") != 0 &&
2199		    strcmp(FileData.cFileName, "..") != 0) {
2200			v = PyString_FromString(FileData.cFileName);
2201			if (v == NULL) {
2202				Py_DECREF(d);
2203				d = NULL;
2204				break;
2205			}
2206			if (PyList_Append(d, v) != 0) {
2207				Py_DECREF(v);
2208				Py_DECREF(d);
2209				d = NULL;
2210				break;
2211			}
2212			Py_DECREF(v);
2213		}
2214		Py_BEGIN_ALLOW_THREADS
2215		result = FindNextFile(hFindFile, &FileData);
2216		Py_END_ALLOW_THREADS
2217		/* FindNextFile sets error to ERROR_NO_MORE_FILES if
2218		   it got to the end of the directory. */
2219		if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
2220		    Py_DECREF(d);
2221		    win32_error("FindNextFile", namebuf);
2222		    FindClose(hFindFile);
2223		    return NULL;
2224		}
2225	} while (result == TRUE);
2226
2227	if (FindClose(hFindFile) == FALSE) {
2228		Py_DECREF(d);
2229		return win32_error("FindClose", namebuf);
2230	}
2231
2232	return d;
2233
2234#elif defined(PYOS_OS2)
2235
2236#ifndef MAX_PATH
2237#define MAX_PATH    CCHMAXPATH
2238#endif
2239    char *name, *pt;
2240    Py_ssize_t len;
2241    PyObject *d, *v;
2242    char namebuf[MAX_PATH+5];
2243    HDIR  hdir = 1;
2244    ULONG srchcnt = 1;
2245    FILEFINDBUF3   ep;
2246    APIRET rc;
2247
2248    if (!PyArg_ParseTuple(args, "et#:listdir",
2249                          Py_FileSystemDefaultEncoding, &name, &len))
2250        return NULL;
2251    if (len >= MAX_PATH) {
2252        PyMem_Free(name);
2253        PyErr_SetString(PyExc_ValueError, "path too long");
2254        return NULL;
2255    }
2256    strcpy(namebuf, name);
2257    for (pt = namebuf; *pt; pt++)
2258        if (*pt == ALTSEP)
2259            *pt = SEP;
2260    if (namebuf[len-1] != SEP)
2261        namebuf[len++] = SEP;
2262    strcpy(namebuf + len, "*.*");
2263
2264    if ((d = PyList_New(0)) == NULL) {
2265        PyMem_Free(name);
2266        return NULL;
2267    }
2268
2269    rc = DosFindFirst(namebuf,         /* Wildcard Pattern to Match */
2270                      &hdir,           /* Handle to Use While Search Directory */
2271                      FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY,
2272                      &ep, sizeof(ep), /* Structure to Receive Directory Entry */
2273                      &srchcnt,        /* Max and Actual Count of Entries Per Iteration */
2274                      FIL_STANDARD);   /* Format of Entry (EAs or Not) */
2275
2276    if (rc != NO_ERROR) {
2277        errno = ENOENT;
2278        return posix_error_with_allocated_filename(name);
2279    }
2280
2281    if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */
2282        do {
2283            if (ep.achName[0] == '.'
2284            && (ep.achName[1] == '\0' || (ep.achName[1] == '.' && ep.achName[2] == '\0')))
2285                continue; /* Skip Over "." and ".." Names */
2286
2287            strcpy(namebuf, ep.achName);
2288
2289            /* Leave Case of Name Alone -- In Native Form */
2290            /* (Removed Forced Lowercasing Code) */
2291
2292            v = PyString_FromString(namebuf);
2293            if (v == NULL) {
2294                Py_DECREF(d);
2295                d = NULL;
2296                break;
2297            }
2298            if (PyList_Append(d, v) != 0) {
2299                Py_DECREF(v);
2300                Py_DECREF(d);
2301                d = NULL;
2302                break;
2303            }
2304            Py_DECREF(v);
2305        } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && srchcnt > 0);
2306    }
2307
2308    PyMem_Free(name);
2309    return d;
2310#else
2311
2312	char *name = NULL;
2313	PyObject *d, *v;
2314	DIR *dirp;
2315	struct dirent *ep;
2316	int arg_is_unicode = 1;
2317
2318	errno = 0;
2319	if (!PyArg_ParseTuple(args, "U:listdir", &v)) {
2320		arg_is_unicode = 0;
2321		PyErr_Clear();
2322	}
2323	if (!PyArg_ParseTuple(args, "et:listdir", Py_FileSystemDefaultEncoding, &name))
2324		return NULL;
2325	if ((dirp = opendir(name)) == NULL) {
2326		return posix_error_with_allocated_filename(name);
2327	}
2328	if ((d = PyList_New(0)) == NULL) {
2329		closedir(dirp);
2330		PyMem_Free(name);
2331		return NULL;
2332	}
2333	for (;;) {
2334		Py_BEGIN_ALLOW_THREADS
2335		ep = readdir(dirp);
2336		Py_END_ALLOW_THREADS
2337		if (ep == NULL)
2338			break;
2339		if (ep->d_name[0] == '.' &&
2340		    (NAMLEN(ep) == 1 ||
2341		     (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
2342			continue;
2343		v = PyString_FromStringAndSize(ep->d_name, NAMLEN(ep));
2344		if (v == NULL) {
2345			Py_DECREF(d);
2346			d = NULL;
2347			break;
2348		}
2349		if (arg_is_unicode) {
2350			PyObject *w;
2351
2352			w = PyUnicode_FromEncodedObject(v,
2353					Py_FileSystemDefaultEncoding,
2354					"strict");
2355			if (w != NULL) {
2356				Py_DECREF(v);
2357				v = w;
2358			}
2359			else {
2360				/* fall back to the original byte string, as
2361				   discussed in patch #683592 */
2362				PyErr_Clear();
2363			}
2364		}
2365		if (PyList_Append(d, v) != 0) {
2366			Py_DECREF(v);
2367			Py_DECREF(d);
2368			d = NULL;
2369			break;
2370		}
2371		Py_DECREF(v);
2372	}
2373	if (errno != 0 && d != NULL) {
2374		/* readdir() returned NULL and set errno */
2375		closedir(dirp);
2376		Py_DECREF(d);
2377		return posix_error_with_allocated_filename(name);
2378	}
2379	closedir(dirp);
2380	PyMem_Free(name);
2381
2382	return d;
2383
2384#endif /* which OS */
2385}  /* end of posix_listdir */
2386
2387#ifdef MS_WINDOWS
2388/* A helper function for abspath on win32 */
2389static PyObject *
2390posix__getfullpathname(PyObject *self, PyObject *args)
2391{
2392	/* assume encoded strings wont more than double no of chars */
2393	char inbuf[MAX_PATH*2];
2394	char *inbufp = inbuf;
2395	Py_ssize_t insize = sizeof(inbuf);
2396	char outbuf[MAX_PATH*2];
2397	char *temp;
2398#ifdef Py_WIN_WIDE_FILENAMES
2399	if (unicode_file_names()) {
2400		PyUnicodeObject *po;
2401		if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) {
2402			Py_UNICODE woutbuf[MAX_PATH*2];
2403			Py_UNICODE *wtemp;
2404			if (!GetFullPathNameW(PyUnicode_AS_UNICODE(po),
2405						sizeof(woutbuf)/sizeof(woutbuf[0]),
2406						 woutbuf, &wtemp))
2407				return win32_error("GetFullPathName", "");
2408			return PyUnicode_FromUnicode(woutbuf, wcslen(woutbuf));
2409		}
2410		/* Drop the argument parsing error as narrow strings
2411		   are also valid. */
2412		PyErr_Clear();
2413	}
2414#endif
2415	if (!PyArg_ParseTuple (args, "et#:_getfullpathname",
2416	                       Py_FileSystemDefaultEncoding, &inbufp,
2417	                       &insize))
2418		return NULL;
2419	if (!GetFullPathName(inbuf, sizeof(outbuf)/sizeof(outbuf[0]),
2420	                     outbuf, &temp))
2421		return win32_error("GetFullPathName", inbuf);
2422	if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
2423		return PyUnicode_Decode(outbuf, strlen(outbuf),
2424			Py_FileSystemDefaultEncoding, NULL);
2425	}
2426	return PyString_FromString(outbuf);
2427} /* end of posix__getfullpathname */
2428#endif /* MS_WINDOWS */
2429
2430PyDoc_STRVAR(posix_mkdir__doc__,
2431"mkdir(path [, mode=0777])\n\n\
2432Create a directory.");
2433
2434static PyObject *
2435posix_mkdir(PyObject *self, PyObject *args)
2436{
2437	int res;
2438	char *path = NULL;
2439	int mode = 0777;
2440
2441#ifdef Py_WIN_WIDE_FILENAMES
2442	if (unicode_file_names()) {
2443		PyUnicodeObject *po;
2444		if (PyArg_ParseTuple(args, "U|i:mkdir", &po, &mode)) {
2445			Py_BEGIN_ALLOW_THREADS
2446			/* PyUnicode_AS_UNICODE OK without thread lock as
2447			   it is a simple dereference. */
2448			res = CreateDirectoryW(PyUnicode_AS_UNICODE(po), NULL);
2449			Py_END_ALLOW_THREADS
2450			if (!res)
2451				return win32_error_unicode("mkdir", PyUnicode_AS_UNICODE(po));
2452			Py_INCREF(Py_None);
2453			return Py_None;
2454		}
2455		/* Drop the argument parsing error as narrow strings
2456		   are also valid. */
2457		PyErr_Clear();
2458	}
2459	if (!PyArg_ParseTuple(args, "et|i:mkdir",
2460	                      Py_FileSystemDefaultEncoding, &path, &mode))
2461		return NULL;
2462	Py_BEGIN_ALLOW_THREADS
2463	/* PyUnicode_AS_UNICODE OK without thread lock as
2464	   it is a simple dereference. */
2465	res = CreateDirectoryA(path, NULL);
2466	Py_END_ALLOW_THREADS
2467	if (!res) {
2468		win32_error("mkdir", path);
2469		PyMem_Free(path);
2470		return NULL;
2471	}
2472	PyMem_Free(path);
2473	Py_INCREF(Py_None);
2474	return Py_None;
2475#else
2476
2477	if (!PyArg_ParseTuple(args, "et|i:mkdir",
2478	                      Py_FileSystemDefaultEncoding, &path, &mode))
2479		return NULL;
2480	Py_BEGIN_ALLOW_THREADS
2481#if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
2482	res = mkdir(path);
2483#else
2484	res = mkdir(path, mode);
2485#endif
2486	Py_END_ALLOW_THREADS
2487	if (res < 0)
2488		return posix_error_with_allocated_filename(path);
2489	PyMem_Free(path);
2490	Py_INCREF(Py_None);
2491	return Py_None;
2492#endif
2493}
2494
2495
2496/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
2497#if defined(HAVE_SYS_RESOURCE_H)
2498#include <sys/resource.h>
2499#endif
2500
2501
2502#ifdef HAVE_NICE
2503PyDoc_STRVAR(posix_nice__doc__,
2504"nice(inc) -> new_priority\n\n\
2505Decrease the priority of process by inc and return the new priority.");
2506
2507static PyObject *
2508posix_nice(PyObject *self, PyObject *args)
2509{
2510	int increment, value;
2511
2512	if (!PyArg_ParseTuple(args, "i:nice", &increment))
2513		return NULL;
2514
2515	/* There are two flavours of 'nice': one that returns the new
2516	   priority (as required by almost all standards out there) and the
2517	   Linux/FreeBSD/BSDI one, which returns '0' on success and advices
2518	   the use of getpriority() to get the new priority.
2519
2520	   If we are of the nice family that returns the new priority, we
2521	   need to clear errno before the call, and check if errno is filled
2522	   before calling posix_error() on a returnvalue of -1, because the
2523	   -1 may be the actual new priority! */
2524
2525	errno = 0;
2526	value = nice(increment);
2527#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
2528	if (value == 0)
2529		value = getpriority(PRIO_PROCESS, 0);
2530#endif
2531	if (value == -1 && errno != 0)
2532		/* either nice() or getpriority() returned an error */
2533		return posix_error();
2534	return PyLong_FromLong((long) value);
2535}
2536#endif /* HAVE_NICE */
2537
2538PyDoc_STRVAR(posix_rename__doc__,
2539"rename(old, new)\n\n\
2540Rename a file or directory.");
2541
2542static PyObject *
2543posix_rename(PyObject *self, PyObject *args)
2544{
2545#ifdef MS_WINDOWS
2546	PyObject *o1, *o2;
2547	char *p1, *p2;
2548	BOOL result;
2549	if (unicode_file_names()) {
2550	    if (!PyArg_ParseTuple(args, "O&O&:rename",
2551		convert_to_unicode, &o1,
2552		convert_to_unicode, &o2))
2553		    PyErr_Clear();
2554	    else {
2555		    Py_BEGIN_ALLOW_THREADS
2556		    result = MoveFileW(PyUnicode_AsUnicode(o1),
2557				       PyUnicode_AsUnicode(o2));
2558		    Py_END_ALLOW_THREADS
2559		    Py_DECREF(o1);
2560		    Py_DECREF(o2);
2561		    if (!result)
2562			    return win32_error("rename", NULL);
2563		    Py_INCREF(Py_None);
2564		    return Py_None;
2565	    }
2566	}
2567	if (!PyArg_ParseTuple(args, "ss:rename", &p1, &p2))
2568		return NULL;
2569	Py_BEGIN_ALLOW_THREADS
2570	result = MoveFileA(p1, p2);
2571	Py_END_ALLOW_THREADS
2572	if (!result)
2573		return win32_error("rename", NULL);
2574	Py_INCREF(Py_None);
2575	return Py_None;
2576#else
2577	return posix_2str(args, "etet:rename", rename);
2578#endif
2579}
2580
2581
2582PyDoc_STRVAR(posix_rmdir__doc__,
2583"rmdir(path)\n\n\
2584Remove a directory.");
2585
2586static PyObject *
2587posix_rmdir(PyObject *self, PyObject *args)
2588{
2589#ifdef MS_WINDOWS
2590	return win32_1str(args, "rmdir", "s:rmdir", RemoveDirectoryA, "U:rmdir", RemoveDirectoryW);
2591#else
2592	return posix_1str(args, "et:rmdir", rmdir);
2593#endif
2594}
2595
2596
2597PyDoc_STRVAR(posix_stat__doc__,
2598"stat(path) -> stat result\n\n\
2599Perform a stat system call on the given path.");
2600
2601static PyObject *
2602posix_stat(PyObject *self, PyObject *args)
2603{
2604#ifdef MS_WINDOWS
2605	return posix_do_stat(self, args, "et:stat", STAT, "U:stat", win32_wstat);
2606#else
2607	return posix_do_stat(self, args, "et:stat", STAT, NULL, NULL);
2608#endif
2609}
2610
2611
2612#ifdef HAVE_SYSTEM
2613PyDoc_STRVAR(posix_system__doc__,
2614"system(command) -> exit_status\n\n\
2615Execute the command (a string) in a subshell.");
2616
2617static PyObject *
2618posix_system(PyObject *self, PyObject *args)
2619{
2620	long sts;
2621#ifdef MS_WINDOWS
2622	wchar_t *command;
2623	if (!PyArg_ParseTuple(args, "u:system", &command))
2624		return NULL;
2625#else
2626	char *command;
2627	if (!PyArg_ParseTuple(args, "s:system", &command))
2628		return NULL;
2629#endif
2630	Py_BEGIN_ALLOW_THREADS
2631#ifdef MS_WINDOWS
2632	sts = _wsystem(command);
2633#else
2634	sts = system(command);
2635#endif
2636	Py_END_ALLOW_THREADS
2637	return PyLong_FromLong(sts);
2638}
2639#endif
2640
2641
2642PyDoc_STRVAR(posix_umask__doc__,
2643"umask(new_mask) -> old_mask\n\n\
2644Set the current numeric umask and return the previous umask.");
2645
2646static PyObject *
2647posix_umask(PyObject *self, PyObject *args)
2648{
2649	int i;
2650	if (!PyArg_ParseTuple(args, "i:umask", &i))
2651		return NULL;
2652	i = (int)umask(i);
2653	if (i < 0)
2654		return posix_error();
2655	return PyLong_FromLong((long)i);
2656}
2657
2658
2659PyDoc_STRVAR(posix_unlink__doc__,
2660"unlink(path)\n\n\
2661Remove a file (same as remove(path)).");
2662
2663PyDoc_STRVAR(posix_remove__doc__,
2664"remove(path)\n\n\
2665Remove a file (same as unlink(path)).");
2666
2667static PyObject *
2668posix_unlink(PyObject *self, PyObject *args)
2669{
2670#ifdef MS_WINDOWS
2671	return win32_1str(args, "remove", "s:remove", DeleteFileA, "U:remove", DeleteFileW);
2672#else
2673	return posix_1str(args, "et:remove", unlink);
2674#endif
2675}
2676
2677
2678#ifdef HAVE_UNAME
2679PyDoc_STRVAR(posix_uname__doc__,
2680"uname() -> (sysname, nodename, release, version, machine)\n\n\
2681Return a tuple identifying the current operating system.");
2682
2683static PyObject *
2684posix_uname(PyObject *self, PyObject *noargs)
2685{
2686	struct utsname u;
2687	int res;
2688
2689	Py_BEGIN_ALLOW_THREADS
2690	res = uname(&u);
2691	Py_END_ALLOW_THREADS
2692	if (res < 0)
2693		return posix_error();
2694	return Py_BuildValue("(sssss)",
2695			     u.sysname,
2696			     u.nodename,
2697			     u.release,
2698			     u.version,
2699			     u.machine);
2700}
2701#endif /* HAVE_UNAME */
2702
2703static int
2704extract_time(PyObject *t, long* sec, long* usec)
2705{
2706	long intval;
2707	if (PyFloat_Check(t)) {
2708		double tval = PyFloat_AsDouble(t);
2709		PyObject *intobj = Py_TYPE(t)->tp_as_number->nb_int(t);
2710		if (!intobj)
2711			return -1;
2712		intval = PyLong_AsLong(intobj);
2713		Py_DECREF(intobj);
2714		if (intval == -1 && PyErr_Occurred())
2715			return -1;
2716		*sec = intval;
2717		*usec = (long)((tval - intval) * 1e6); /* can't exceed 1000000 */
2718		if (*usec < 0)
2719			/* If rounding gave us a negative number,
2720			   truncate.  */
2721			*usec = 0;
2722		return 0;
2723	}
2724	intval = PyLong_AsLong(t);
2725	if (intval == -1 && PyErr_Occurred())
2726		return -1;
2727	*sec = intval;
2728	*usec = 0;
2729        return 0;
2730}
2731
2732PyDoc_STRVAR(posix_utime__doc__,
2733"utime(path, (atime, mtime))\n\
2734utime(path, None)\n\n\
2735Set the access and modified time of the file to the given values.  If the\n\
2736second form is used, set the access and modified times to the current time.");
2737
2738static PyObject *
2739posix_utime(PyObject *self, PyObject *args)
2740{
2741#ifdef Py_WIN_WIDE_FILENAMES
2742	PyObject *arg;
2743	PyUnicodeObject *obwpath;
2744	wchar_t *wpath = NULL;
2745	char *apath = NULL;
2746	HANDLE hFile;
2747	long atimesec, mtimesec, ausec, musec;
2748	FILETIME atime, mtime;
2749	PyObject *result = NULL;
2750
2751	if (unicode_file_names()) {
2752		if (PyArg_ParseTuple(args, "UO|:utime", &obwpath, &arg)) {
2753			wpath = PyUnicode_AS_UNICODE(obwpath);
2754			Py_BEGIN_ALLOW_THREADS
2755			hFile = CreateFileW(wpath, FILE_WRITE_ATTRIBUTES, 0,
2756					    NULL, OPEN_EXISTING,
2757					    FILE_FLAG_BACKUP_SEMANTICS, NULL);
2758			Py_END_ALLOW_THREADS
2759			if (hFile == INVALID_HANDLE_VALUE)
2760				return win32_error_unicode("utime", wpath);
2761		} else
2762			/* Drop the argument parsing error as narrow strings
2763			   are also valid. */
2764			PyErr_Clear();
2765	}
2766	if (!wpath) {
2767		if (!PyArg_ParseTuple(args, "etO:utime",
2768				Py_FileSystemDefaultEncoding, &apath, &arg))
2769			return NULL;
2770		Py_BEGIN_ALLOW_THREADS
2771		hFile = CreateFileA(apath, FILE_WRITE_ATTRIBUTES, 0,
2772				    NULL, OPEN_EXISTING,
2773				    FILE_FLAG_BACKUP_SEMANTICS, NULL);
2774		Py_END_ALLOW_THREADS
2775		if (hFile == INVALID_HANDLE_VALUE) {
2776			win32_error("utime", apath);
2777			PyMem_Free(apath);
2778			return NULL;
2779		}
2780		PyMem_Free(apath);
2781	}
2782
2783	if (arg == Py_None) {
2784		SYSTEMTIME now;
2785		GetSystemTime(&now);
2786		if (!SystemTimeToFileTime(&now, &mtime) ||
2787		    !SystemTimeToFileTime(&now, &atime)) {
2788			win32_error("utime", NULL);
2789			goto done;
2790		    }
2791	}
2792	else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
2793		PyErr_SetString(PyExc_TypeError,
2794				"utime() arg 2 must be a tuple (atime, mtime)");
2795		goto done;
2796	}
2797	else {
2798		if (extract_time(PyTuple_GET_ITEM(arg, 0),
2799				 &atimesec, &ausec) == -1)
2800			goto done;
2801		time_t_to_FILE_TIME(atimesec, 1000*ausec, &atime);
2802		if (extract_time(PyTuple_GET_ITEM(arg, 1),
2803				 &mtimesec, &musec) == -1)
2804			goto done;
2805		time_t_to_FILE_TIME(mtimesec, 1000*musec, &mtime);
2806	}
2807	if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
2808		/* Avoid putting the file name into the error here,
2809		   as that may confuse the user into believing that
2810		   something is wrong with the file, when it also
2811		   could be the time stamp that gives a problem. */
2812		win32_error("utime", NULL);
2813	}
2814	Py_INCREF(Py_None);
2815	result = Py_None;
2816done:
2817	CloseHandle(hFile);
2818	return result;
2819#else /* Py_WIN_WIDE_FILENAMES */
2820
2821	char *path = NULL;
2822	long atime, mtime, ausec, musec;
2823	int res;
2824	PyObject* arg;
2825
2826#if defined(HAVE_UTIMES)
2827	struct timeval buf[2];
2828#define ATIME buf[0].tv_sec
2829#define MTIME buf[1].tv_sec
2830#elif defined(HAVE_UTIME_H)
2831/* XXX should define struct utimbuf instead, above */
2832	struct utimbuf buf;
2833#define ATIME buf.actime
2834#define MTIME buf.modtime
2835#define UTIME_ARG &buf
2836#else /* HAVE_UTIMES */
2837	time_t buf[2];
2838#define ATIME buf[0]
2839#define MTIME buf[1]
2840#define UTIME_ARG buf
2841#endif /* HAVE_UTIMES */
2842
2843
2844	if (!PyArg_ParseTuple(args, "etO:utime",
2845				  Py_FileSystemDefaultEncoding, &path, &arg))
2846		return NULL;
2847	if (arg == Py_None) {
2848		/* optional time values not given */
2849		Py_BEGIN_ALLOW_THREADS
2850		res = utime(path, NULL);
2851		Py_END_ALLOW_THREADS
2852	}
2853	else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
2854		PyErr_SetString(PyExc_TypeError,
2855				"utime() arg 2 must be a tuple (atime, mtime)");
2856		PyMem_Free(path);
2857		return NULL;
2858	}
2859	else {
2860		if (extract_time(PyTuple_GET_ITEM(arg, 0),
2861				 &atime, &ausec) == -1) {
2862			PyMem_Free(path);
2863			return NULL;
2864		}
2865		if (extract_time(PyTuple_GET_ITEM(arg, 1),
2866				 &mtime, &musec) == -1) {
2867			PyMem_Free(path);
2868			return NULL;
2869		}
2870		ATIME = atime;
2871		MTIME = mtime;
2872#ifdef HAVE_UTIMES
2873		buf[0].tv_usec = ausec;
2874		buf[1].tv_usec = musec;
2875		Py_BEGIN_ALLOW_THREADS
2876		res = utimes(path, buf);
2877		Py_END_ALLOW_THREADS
2878#else
2879		Py_BEGIN_ALLOW_THREADS
2880		res = utime(path, UTIME_ARG);
2881		Py_END_ALLOW_THREADS
2882#endif /* HAVE_UTIMES */
2883	}
2884	if (res < 0) {
2885		return posix_error_with_allocated_filename(path);
2886	}
2887	PyMem_Free(path);
2888	Py_INCREF(Py_None);
2889	return Py_None;
2890#undef UTIME_ARG
2891#undef ATIME
2892#undef MTIME
2893#endif /* Py_WIN_WIDE_FILENAMES */
2894}
2895
2896
2897/* Process operations */
2898
2899PyDoc_STRVAR(posix__exit__doc__,
2900"_exit(status)\n\n\
2901Exit to the system with specified status, without normal exit processing.");
2902
2903static PyObject *
2904posix__exit(PyObject *self, PyObject *args)
2905{
2906	int sts;
2907	if (!PyArg_ParseTuple(args, "i:_exit", &sts))
2908		return NULL;
2909	_exit(sts);
2910	return NULL; /* Make gcc -Wall happy */
2911}
2912
2913#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
2914static void
2915free_string_array(char **array, Py_ssize_t count)
2916{
2917	Py_ssize_t i;
2918	for (i = 0; i < count; i++)
2919		PyMem_Free(array[i]);
2920	PyMem_DEL(array);
2921}
2922#endif
2923
2924
2925#ifdef HAVE_EXECV
2926PyDoc_STRVAR(posix_execv__doc__,
2927"execv(path, args)\n\n\
2928Execute an executable path with arguments, replacing current process.\n\
2929\n\
2930	path: path of executable file\n\
2931	args: tuple or list of strings");
2932
2933static PyObject *
2934posix_execv(PyObject *self, PyObject *args)
2935{
2936	char *path;
2937	PyObject *argv;
2938	char **argvlist;
2939	Py_ssize_t i, argc;
2940	PyObject *(*getitem)(PyObject *, Py_ssize_t);
2941
2942	/* execv has two arguments: (path, argv), where
2943	   argv is a list or tuple of strings. */
2944
2945	if (!PyArg_ParseTuple(args, "etO:execv",
2946                              Py_FileSystemDefaultEncoding,
2947                              &path, &argv))
2948		return NULL;
2949	if (PyList_Check(argv)) {
2950		argc = PyList_Size(argv);
2951		getitem = PyList_GetItem;
2952	}
2953	else if (PyTuple_Check(argv)) {
2954		argc = PyTuple_Size(argv);
2955		getitem = PyTuple_GetItem;
2956	}
2957	else {
2958		PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list");
2959                PyMem_Free(path);
2960		return NULL;
2961	}
2962	if (argc < 1) {
2963		PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
2964                PyMem_Free(path);
2965		return NULL;
2966	}
2967
2968	argvlist = PyMem_NEW(char *, argc+1);
2969	if (argvlist == NULL) {
2970		PyMem_Free(path);
2971		return PyErr_NoMemory();
2972	}
2973	for (i = 0; i < argc; i++) {
2974		if (!PyArg_Parse((*getitem)(argv, i), "et",
2975				 Py_FileSystemDefaultEncoding,
2976				 &argvlist[i])) {
2977			free_string_array(argvlist, i);
2978			PyErr_SetString(PyExc_TypeError,
2979					"execv() arg 2 must contain only strings");
2980			PyMem_Free(path);
2981			return NULL;
2982
2983		}
2984	}
2985	argvlist[argc] = NULL;
2986
2987	execv(path, argvlist);
2988
2989	/* If we get here it's definitely an error */
2990
2991	free_string_array(argvlist, argc);
2992	PyMem_Free(path);
2993	return posix_error();
2994}
2995
2996
2997PyDoc_STRVAR(posix_execve__doc__,
2998"execve(path, args, env)\n\n\
2999Execute a path with arguments and environment, replacing current process.\n\
3000\n\
3001	path: path of executable file\n\
3002	args: tuple or list of arguments\n\
3003	env: dictionary of strings mapping to strings");
3004
3005static PyObject *
3006posix_execve(PyObject *self, PyObject *args)
3007{
3008	char *path;
3009	PyObject *argv, *env;
3010	char **argvlist;
3011	char **envlist;
3012	PyObject *key, *val, *keys=NULL, *vals=NULL;
3013	Py_ssize_t i, pos, argc, envc;
3014	PyObject *(*getitem)(PyObject *, Py_ssize_t);
3015	Py_ssize_t lastarg = 0;
3016
3017	/* execve has three arguments: (path, argv, env), where
3018	   argv is a list or tuple of strings and env is a dictionary
3019	   like posix.environ. */
3020
3021	if (!PyArg_ParseTuple(args, "etOO:execve",
3022			      Py_FileSystemDefaultEncoding,
3023			      &path, &argv, &env))
3024		return NULL;
3025	if (PyList_Check(argv)) {
3026		argc = PyList_Size(argv);
3027		getitem = PyList_GetItem;
3028	}
3029	else if (PyTuple_Check(argv)) {
3030		argc = PyTuple_Size(argv);
3031		getitem = PyTuple_GetItem;
3032	}
3033	else {
3034		PyErr_SetString(PyExc_TypeError,
3035				"execve() arg 2 must be a tuple or list");
3036		goto fail_0;
3037	}
3038	if (!PyMapping_Check(env)) {
3039		PyErr_SetString(PyExc_TypeError,
3040				"execve() arg 3 must be a mapping object");
3041		goto fail_0;
3042	}
3043
3044	argvlist = PyMem_NEW(char *, argc+1);
3045	if (argvlist == NULL) {
3046		PyErr_NoMemory();
3047		goto fail_0;
3048	}
3049	for (i = 0; i < argc; i++) {
3050		if (!PyArg_Parse((*getitem)(argv, i),
3051				 "et;execve() arg 2 must contain only strings",
3052				 Py_FileSystemDefaultEncoding,
3053				 &argvlist[i]))
3054		{
3055			lastarg = i;
3056			goto fail_1;
3057		}
3058	}
3059	lastarg = argc;
3060	argvlist[argc] = NULL;
3061
3062	i = PyMapping_Size(env);
3063	if (i < 0)
3064		goto fail_1;
3065	envlist = PyMem_NEW(char *, i + 1);
3066	if (envlist == NULL) {
3067		PyErr_NoMemory();
3068		goto fail_1;
3069	}
3070	envc = 0;
3071	keys = PyMapping_Keys(env);
3072	vals = PyMapping_Values(env);
3073	if (!keys || !vals)
3074		goto fail_2;
3075	if (!PyList_Check(keys) || !PyList_Check(vals)) {
3076		PyErr_SetString(PyExc_TypeError,
3077			"execve(): env.keys() or env.values() is not a list");
3078		goto fail_2;
3079	}
3080
3081	for (pos = 0; pos < i; pos++) {
3082		char *p, *k, *v;
3083		size_t len;
3084
3085		key = PyList_GetItem(keys, pos);
3086		val = PyList_GetItem(vals, pos);
3087		if (!key || !val)
3088			goto fail_2;
3089
3090		if (!PyArg_Parse(
3091			    key,
3092			    "s;execve() arg 3 contains a non-string key",
3093			    &k) ||
3094		    !PyArg_Parse(
3095			    val,
3096			    "s;execve() arg 3 contains a non-string value",
3097			    &v))
3098		{
3099			goto fail_2;
3100		}
3101
3102#if defined(PYOS_OS2)
3103        /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
3104        if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
3105#endif
3106		len = PyUnicode_GetSize(key) + PyUnicode_GetSize(val) + 2;
3107		p = PyMem_NEW(char, len);
3108		if (p == NULL) {
3109			PyErr_NoMemory();
3110			goto fail_2;
3111		}
3112		PyOS_snprintf(p, len, "%s=%s", k, v);
3113		envlist[envc++] = p;
3114#if defined(PYOS_OS2)
3115    }
3116#endif
3117	}
3118	envlist[envc] = 0;
3119
3120	execve(path, argvlist, envlist);
3121
3122	/* If we get here it's definitely an error */
3123
3124	(void) posix_error();
3125
3126  fail_2:
3127	while (--envc >= 0)
3128		PyMem_DEL(envlist[envc]);
3129	PyMem_DEL(envlist);
3130  fail_1:
3131	free_string_array(argvlist, lastarg);
3132	Py_XDECREF(vals);
3133	Py_XDECREF(keys);
3134  fail_0:
3135	PyMem_Free(path);
3136	return NULL;
3137}
3138#endif /* HAVE_EXECV */
3139
3140
3141#ifdef HAVE_SPAWNV
3142PyDoc_STRVAR(posix_spawnv__doc__,
3143"spawnv(mode, path, args)\n\n\
3144Execute the program 'path' in a new process.\n\
3145\n\
3146	mode: mode of process creation\n\
3147	path: path of executable file\n\
3148	args: tuple or list of strings");
3149
3150static PyObject *
3151posix_spawnv(PyObject *self, PyObject *args)
3152{
3153	char *path;
3154	PyObject *argv;
3155	char **argvlist;
3156	int mode, i;
3157	Py_ssize_t argc;
3158	Py_intptr_t spawnval;
3159	PyObject *(*getitem)(PyObject *, Py_ssize_t);
3160
3161	/* spawnv has three arguments: (mode, path, argv), where
3162	   argv is a list or tuple of strings. */
3163
3164	if (!PyArg_ParseTuple(args, "ietO:spawnv", &mode,
3165			      Py_FileSystemDefaultEncoding,
3166			      &path, &argv))
3167		return NULL;
3168	if (PyList_Check(argv)) {
3169		argc = PyList_Size(argv);
3170		getitem = PyList_GetItem;
3171	}
3172	else if (PyTuple_Check(argv)) {
3173		argc = PyTuple_Size(argv);
3174		getitem = PyTuple_GetItem;
3175	}
3176	else {
3177		PyErr_SetString(PyExc_TypeError,
3178				"spawnv() arg 2 must be a tuple or list");
3179		PyMem_Free(path);
3180		return NULL;
3181	}
3182
3183	argvlist = PyMem_NEW(char *, argc+1);
3184	if (argvlist == NULL) {
3185		PyMem_Free(path);
3186		return PyErr_NoMemory();
3187	}
3188	for (i = 0; i < argc; i++) {
3189		if (!PyArg_Parse((*getitem)(argv, i), "et",
3190				 Py_FileSystemDefaultEncoding,
3191				 &argvlist[i])) {
3192			free_string_array(argvlist, i);
3193			PyErr_SetString(
3194				PyExc_TypeError,
3195				"spawnv() arg 2 must contain only strings");
3196			PyMem_Free(path);
3197			return NULL;
3198		}
3199	}
3200	argvlist[argc] = NULL;
3201
3202#if defined(PYOS_OS2) && defined(PYCC_GCC)
3203	Py_BEGIN_ALLOW_THREADS
3204	spawnval = spawnv(mode, path, argvlist);
3205	Py_END_ALLOW_THREADS
3206#else
3207	if (mode == _OLD_P_OVERLAY)
3208		mode = _P_OVERLAY;
3209
3210	Py_BEGIN_ALLOW_THREADS
3211	spawnval = _spawnv(mode, path, argvlist);
3212	Py_END_ALLOW_THREADS
3213#endif
3214
3215	free_string_array(argvlist, argc);
3216	PyMem_Free(path);
3217
3218	if (spawnval == -1)
3219		return posix_error();
3220	else
3221#if SIZEOF_LONG == SIZEOF_VOID_P
3222		return Py_BuildValue("l", (long) spawnval);
3223#else
3224		return Py_BuildValue("L", (PY_LONG_LONG) spawnval);
3225#endif
3226}
3227
3228
3229PyDoc_STRVAR(posix_spawnve__doc__,
3230"spawnve(mode, path, args, env)\n\n\
3231Execute the program 'path' in a new process.\n\
3232\n\
3233	mode: mode of process creation\n\
3234	path: path of executable file\n\
3235	args: tuple or list of arguments\n\
3236	env: dictionary of strings mapping to strings");
3237
3238static PyObject *
3239posix_spawnve(PyObject *self, PyObject *args)
3240{
3241	char *path;
3242	PyObject *argv, *env;
3243	char **argvlist;
3244	char **envlist;
3245	PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
3246	int mode, pos, envc;
3247	Py_ssize_t argc, i;
3248	Py_intptr_t spawnval;
3249	PyObject *(*getitem)(PyObject *, Py_ssize_t);
3250	Py_ssize_t lastarg = 0;
3251
3252	/* spawnve has four arguments: (mode, path, argv, env), where
3253	   argv is a list or tuple of strings and env is a dictionary
3254	   like posix.environ. */
3255
3256	if (!PyArg_ParseTuple(args, "ietOO:spawnve", &mode,
3257			      Py_FileSystemDefaultEncoding,
3258			      &path, &argv, &env))
3259		return NULL;
3260	if (PyList_Check(argv)) {
3261		argc = PyList_Size(argv);
3262		getitem = PyList_GetItem;
3263	}
3264	else if (PyTuple_Check(argv)) {
3265		argc = PyTuple_Size(argv);
3266		getitem = PyTuple_GetItem;
3267	}
3268	else {
3269		PyErr_SetString(PyExc_TypeError,
3270				"spawnve() arg 2 must be a tuple or list");
3271		goto fail_0;
3272	}
3273	if (!PyMapping_Check(env)) {
3274		PyErr_SetString(PyExc_TypeError,
3275				"spawnve() arg 3 must be a mapping object");
3276		goto fail_0;
3277	}
3278
3279	argvlist = PyMem_NEW(char *, argc+1);
3280	if (argvlist == NULL) {
3281		PyErr_NoMemory();
3282		goto fail_0;
3283	}
3284	for (i = 0; i < argc; i++) {
3285		if (!PyArg_Parse((*getitem)(argv, i),
3286			     "et;spawnve() arg 2 must contain only strings",
3287				 Py_FileSystemDefaultEncoding,
3288				 &argvlist[i]))
3289		{
3290			lastarg = i;
3291			goto fail_1;
3292		}
3293	}
3294	lastarg = argc;
3295	argvlist[argc] = NULL;
3296
3297	i = PyMapping_Size(env);
3298	if (i < 0)
3299		goto fail_1;
3300	envlist = PyMem_NEW(char *, i + 1);
3301	if (envlist == NULL) {
3302		PyErr_NoMemory();
3303		goto fail_1;
3304	}
3305	envc = 0;
3306	keys = PyMapping_Keys(env);
3307	vals = PyMapping_Values(env);
3308	if (!keys || !vals)
3309		goto fail_2;
3310	if (!PyList_Check(keys) || !PyList_Check(vals)) {
3311		PyErr_SetString(PyExc_TypeError,
3312			"spawnve(): env.keys() or env.values() is not a list");
3313		goto fail_2;
3314	}
3315
3316	for (pos = 0; pos < i; pos++) {
3317		char *p, *k, *v;
3318		size_t len;
3319
3320		key = PyList_GetItem(keys, pos);
3321		val = PyList_GetItem(vals, pos);
3322		if (!key || !val)
3323			goto fail_2;
3324
3325		if (!PyArg_Parse(
3326			    key,
3327			    "s;spawnve() arg 3 contains a non-string key",
3328			    &k) ||
3329		    !PyArg_Parse(
3330			    val,
3331			    "s;spawnve() arg 3 contains a non-string value",
3332			    &v))
3333		{
3334			goto fail_2;
3335		}
3336		len = PyUnicode_GetSize(key) + PyUnicode_GetSize(val) + 2;
3337		p = PyMem_NEW(char, len);
3338		if (p == NULL) {
3339			PyErr_NoMemory();
3340			goto fail_2;
3341		}
3342		PyOS_snprintf(p, len, "%s=%s", k, v);
3343		envlist[envc++] = p;
3344	}
3345	envlist[envc] = 0;
3346
3347#if defined(PYOS_OS2) && defined(PYCC_GCC)
3348	Py_BEGIN_ALLOW_THREADS
3349	spawnval = spawnve(mode, path, argvlist, envlist);
3350	Py_END_ALLOW_THREADS
3351#else
3352	if (mode == _OLD_P_OVERLAY)
3353		mode = _P_OVERLAY;
3354
3355	Py_BEGIN_ALLOW_THREADS
3356	spawnval = _spawnve(mode, path, argvlist, envlist);
3357	Py_END_ALLOW_THREADS
3358#endif
3359
3360	if (spawnval == -1)
3361		(void) posix_error();
3362	else
3363#if SIZEOF_LONG == SIZEOF_VOID_P
3364		res = Py_BuildValue("l", (long) spawnval);
3365#else
3366		res = Py_BuildValue("L", (PY_LONG_LONG) spawnval);
3367#endif
3368
3369  fail_2:
3370	while (--envc >= 0)
3371		PyMem_DEL(envlist[envc]);
3372	PyMem_DEL(envlist);
3373  fail_1:
3374	free_string_array(argvlist, lastarg);
3375	Py_XDECREF(vals);
3376	Py_XDECREF(keys);
3377  fail_0:
3378	PyMem_Free(path);
3379	return res;
3380}
3381
3382/* OS/2 supports spawnvp & spawnvpe natively */
3383#if defined(PYOS_OS2)
3384PyDoc_STRVAR(posix_spawnvp__doc__,
3385"spawnvp(mode, file, args)\n\n\
3386Execute the program 'file' in a new process, using the environment\n\
3387search path to find the file.\n\
3388\n\
3389	mode: mode of process creation\n\
3390	file: executable file name\n\
3391	args: tuple or list of strings");
3392
3393static PyObject *
3394posix_spawnvp(PyObject *self, PyObject *args)
3395{
3396	char *path;
3397	PyObject *argv;
3398	char **argvlist;
3399	int mode, i, argc;
3400	Py_intptr_t spawnval;
3401	PyObject *(*getitem)(PyObject *, Py_ssize_t);
3402
3403	/* spawnvp has three arguments: (mode, path, argv), where
3404	   argv is a list or tuple of strings. */
3405
3406	if (!PyArg_ParseTuple(args, "ietO:spawnvp", &mode,
3407			      Py_FileSystemDefaultEncoding,
3408			      &path, &argv))
3409		return NULL;
3410	if (PyList_Check(argv)) {
3411		argc = PyList_Size(argv);
3412		getitem = PyList_GetItem;
3413	}
3414	else if (PyTuple_Check(argv)) {
3415		argc = PyTuple_Size(argv);
3416		getitem = PyTuple_GetItem;
3417	}
3418	else {
3419		PyErr_SetString(PyExc_TypeError,
3420				"spawnvp() arg 2 must be a tuple or list");
3421		PyMem_Free(path);
3422		return NULL;
3423	}
3424
3425	argvlist = PyMem_NEW(char *, argc+1);
3426	if (argvlist == NULL) {
3427		PyMem_Free(path);
3428		return PyErr_NoMemory();
3429	}
3430	for (i = 0; i < argc; i++) {
3431		if (!PyArg_Parse((*getitem)(argv, i), "et",
3432				 Py_FileSystemDefaultEncoding,
3433				 &argvlist[i])) {
3434			free_string_array(argvlist, i);
3435			PyErr_SetString(
3436				PyExc_TypeError,
3437				"spawnvp() arg 2 must contain only strings");
3438			PyMem_Free(path);
3439			return NULL;
3440		}
3441	}
3442	argvlist[argc] = NULL;
3443
3444	Py_BEGIN_ALLOW_THREADS
3445#if defined(PYCC_GCC)
3446	spawnval = spawnvp(mode, path, argvlist);
3447#else
3448	spawnval = _spawnvp(mode, path, argvlist);
3449#endif
3450	Py_END_ALLOW_THREADS
3451
3452	free_string_array(argvlist, argc);
3453	PyMem_Free(path);
3454
3455	if (spawnval == -1)
3456		return posix_error();
3457	else
3458		return Py_BuildValue("l", (long) spawnval);
3459}
3460
3461
3462PyDoc_STRVAR(posix_spawnvpe__doc__,
3463"spawnvpe(mode, file, args, env)\n\n\
3464Execute the program 'file' in a new process, using the environment\n\
3465search path to find the file.\n\
3466\n\
3467	mode: mode of process creation\n\
3468	file: executable file name\n\
3469	args: tuple or list of arguments\n\
3470	env: dictionary of strings mapping to strings");
3471
3472static PyObject *
3473posix_spawnvpe(PyObject *self, PyObject *args)
3474{
3475	char *path;
3476	PyObject *argv, *env;
3477	char **argvlist;
3478	char **envlist;
3479	PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
3480	int mode, i, pos, argc, envc;
3481	Py_intptr_t spawnval;
3482	PyObject *(*getitem)(PyObject *, Py_ssize_t);
3483	int lastarg = 0;
3484
3485	/* spawnvpe has four arguments: (mode, path, argv, env), where
3486	   argv is a list or tuple of strings and env is a dictionary
3487	   like posix.environ. */
3488
3489	if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode,
3490			      Py_FileSystemDefaultEncoding,
3491			      &path, &argv, &env))
3492		return NULL;
3493	if (PyList_Check(argv)) {
3494		argc = PyList_Size(argv);
3495		getitem = PyList_GetItem;
3496	}
3497	else if (PyTuple_Check(argv)) {
3498		argc = PyTuple_Size(argv);
3499		getitem = PyTuple_GetItem;
3500	}
3501	else {
3502		PyErr_SetString(PyExc_TypeError,
3503				"spawnvpe() arg 2 must be a tuple or list");
3504		goto fail_0;
3505	}
3506	if (!PyMapping_Check(env)) {
3507		PyErr_SetString(PyExc_TypeError,
3508				"spawnvpe() arg 3 must be a mapping object");
3509		goto fail_0;
3510	}
3511
3512	argvlist = PyMem_NEW(char *, argc+1);
3513	if (argvlist == NULL) {
3514		PyErr_NoMemory();
3515		goto fail_0;
3516	}
3517	for (i = 0; i < argc; i++) {
3518		if (!PyArg_Parse((*getitem)(argv, i),
3519			     "et;spawnvpe() arg 2 must contain only strings",
3520				 Py_FileSystemDefaultEncoding,
3521				 &argvlist[i]))
3522		{
3523			lastarg = i;
3524			goto fail_1;
3525		}
3526	}
3527	lastarg = argc;
3528	argvlist[argc] = NULL;
3529
3530	i = PyMapping_Size(env);
3531	if (i < 0)
3532		goto fail_1;
3533	envlist = PyMem_NEW(char *, i + 1);
3534	if (envlist == NULL) {
3535		PyErr_NoMemory();
3536		goto fail_1;
3537	}
3538	envc = 0;
3539	keys = PyMapping_Keys(env);
3540	vals = PyMapping_Values(env);
3541	if (!keys || !vals)
3542		goto fail_2;
3543	if (!PyList_Check(keys) || !PyList_Check(vals)) {
3544		PyErr_SetString(PyExc_TypeError,
3545			"spawnvpe(): env.keys() or env.values() is not a list");
3546		goto fail_2;
3547	}
3548
3549	for (pos = 0; pos < i; pos++) {
3550		char *p, *k, *v;
3551		size_t len;
3552
3553		key = PyList_GetItem(keys, pos);
3554		val = PyList_GetItem(vals, pos);
3555		if (!key || !val)
3556			goto fail_2;
3557
3558		if (!PyArg_Parse(
3559			    key,
3560			    "s;spawnvpe() arg 3 contains a non-string key",
3561			    &k) ||
3562		    !PyArg_Parse(
3563			    val,
3564			    "s;spawnvpe() arg 3 contains a non-string value",
3565			    &v))
3566		{
3567			goto fail_2;
3568		}
3569		len = PyUnicode_GetSize(key) + PyUnicode_GetSize(val) + 2;
3570		p = PyMem_NEW(char, len);
3571		if (p == NULL) {
3572			PyErr_NoMemory();
3573			goto fail_2;
3574		}
3575		PyOS_snprintf(p, len, "%s=%s", k, v);
3576		envlist[envc++] = p;
3577	}
3578	envlist[envc] = 0;
3579
3580	Py_BEGIN_ALLOW_THREADS
3581#if defined(PYCC_GCC)
3582	spawnval = spawnvpe(mode, path, argvlist, envlist);
3583#else
3584	spawnval = _spawnvpe(mode, path, argvlist, envlist);
3585#endif
3586	Py_END_ALLOW_THREADS
3587
3588	if (spawnval == -1)
3589		(void) posix_error();
3590	else
3591		res = Py_BuildValue("l", (long) spawnval);
3592
3593  fail_2:
3594	while (--envc >= 0)
3595		PyMem_DEL(envlist[envc]);
3596	PyMem_DEL(envlist);
3597  fail_1:
3598	free_string_array(argvlist, lastarg);
3599	Py_XDECREF(vals);
3600	Py_XDECREF(keys);
3601  fail_0:
3602	PyMem_Free(path);
3603	return res;
3604}
3605#endif /* PYOS_OS2 */
3606#endif /* HAVE_SPAWNV */
3607
3608
3609#ifdef HAVE_FORK1
3610PyDoc_STRVAR(posix_fork1__doc__,
3611"fork1() -> pid\n\n\
3612Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
3613\n\
3614Return 0 to child process and PID of child to parent process.");
3615
3616static PyObject *
3617posix_fork1(PyObject *self, PyObject *noargs)
3618{
3619	pid_t pid = fork1();
3620	if (pid == -1)
3621		return posix_error();
3622	PyOS_AfterFork();
3623	return PyLong_FromLong(pid);
3624}
3625#endif
3626
3627
3628#ifdef HAVE_FORK
3629PyDoc_STRVAR(posix_fork__doc__,
3630"fork() -> pid\n\n\
3631Fork a child process.\n\
3632Return 0 to child process and PID of child to parent process.");
3633
3634static PyObject *
3635posix_fork(PyObject *self, PyObject *noargs)
3636{
3637	pid_t pid = fork();
3638	if (pid == -1)
3639		return posix_error();
3640	if (pid == 0)
3641		PyOS_AfterFork();
3642	return PyLong_FromLong(pid);
3643}
3644#endif
3645
3646/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
3647/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
3648#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
3649#define DEV_PTY_FILE "/dev/ptc"
3650#define HAVE_DEV_PTMX
3651#else
3652#define DEV_PTY_FILE "/dev/ptmx"
3653#endif
3654
3655#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
3656#ifdef HAVE_PTY_H
3657#include <pty.h>
3658#else
3659#ifdef HAVE_LIBUTIL_H
3660#include <libutil.h>
3661#endif /* HAVE_LIBUTIL_H */
3662#endif /* HAVE_PTY_H */
3663#ifdef HAVE_STROPTS_H
3664#include <stropts.h>
3665#endif
3666#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
3667
3668#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
3669PyDoc_STRVAR(posix_openpty__doc__,
3670"openpty() -> (master_fd, slave_fd)\n\n\
3671Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
3672
3673static PyObject *
3674posix_openpty(PyObject *self, PyObject *noargs)
3675{
3676	int master_fd, slave_fd;
3677#ifndef HAVE_OPENPTY
3678	char * slave_name;
3679#endif
3680#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
3681	PyOS_sighandler_t sig_saved;
3682#ifdef sun
3683	extern char *ptsname(int fildes);
3684#endif
3685#endif
3686
3687#ifdef HAVE_OPENPTY
3688	if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
3689		return posix_error();
3690#elif defined(HAVE__GETPTY)
3691	slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
3692	if (slave_name == NULL)
3693		return posix_error();
3694
3695	slave_fd = open(slave_name, O_RDWR);
3696	if (slave_fd < 0)
3697		return posix_error();
3698#else
3699	master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
3700	if (master_fd < 0)
3701		return posix_error();
3702	sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
3703	/* change permission of slave */
3704	if (grantpt(master_fd) < 0) {
3705		PyOS_setsig(SIGCHLD, sig_saved);
3706		return posix_error();
3707	}
3708	/* unlock slave */
3709	if (unlockpt(master_fd) < 0) {
3710		PyOS_setsig(SIGCHLD, sig_saved);
3711		return posix_error();
3712	}
3713	PyOS_setsig(SIGCHLD, sig_saved);
3714	slave_name = ptsname(master_fd); /* get name of slave */
3715	if (slave_name == NULL)
3716		return posix_error();
3717	slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
3718	if (slave_fd < 0)
3719		return posix_error();
3720#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
3721	ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
3722	ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
3723#ifndef __hpux
3724	ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
3725#endif /* __hpux */
3726#endif /* HAVE_CYGWIN */
3727#endif /* HAVE_OPENPTY */
3728
3729	return Py_BuildValue("(ii)", master_fd, slave_fd);
3730
3731}
3732#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
3733
3734#ifdef HAVE_FORKPTY
3735PyDoc_STRVAR(posix_forkpty__doc__,
3736"forkpty() -> (pid, master_fd)\n\n\
3737Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
3738Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
3739To both, return fd of newly opened pseudo-terminal.\n");
3740
3741static PyObject *
3742posix_forkpty(PyObject *self, PyObject *noargs)
3743{
3744	int master_fd = -1;
3745	pid_t pid;
3746
3747	pid = forkpty(&master_fd, NULL, NULL, NULL);
3748	if (pid == -1)
3749		return posix_error();
3750	if (pid == 0)
3751		PyOS_AfterFork();
3752	return Py_BuildValue("(li)", pid, master_fd);
3753}
3754#endif
3755
3756#ifdef HAVE_GETEGID
3757PyDoc_STRVAR(posix_getegid__doc__,
3758"getegid() -> egid\n\n\
3759Return the current process's effective group id.");
3760
3761static PyObject *
3762posix_getegid(PyObject *self, PyObject *noargs)
3763{
3764	return PyLong_FromLong((long)getegid());
3765}
3766#endif
3767
3768
3769#ifdef HAVE_GETEUID
3770PyDoc_STRVAR(posix_geteuid__doc__,
3771"geteuid() -> euid\n\n\
3772Return the current process's effective user id.");
3773
3774static PyObject *
3775posix_geteuid(PyObject *self, PyObject *noargs)
3776{
3777	return PyLong_FromLong((long)geteuid());
3778}
3779#endif
3780
3781
3782#ifdef HAVE_GETGID
3783PyDoc_STRVAR(posix_getgid__doc__,
3784"getgid() -> gid\n\n\
3785Return the current process's group id.");
3786
3787static PyObject *
3788posix_getgid(PyObject *self, PyObject *noargs)
3789{
3790	return PyLong_FromLong((long)getgid());
3791}
3792#endif
3793
3794
3795PyDoc_STRVAR(posix_getpid__doc__,
3796"getpid() -> pid\n\n\
3797Return the current process id");
3798
3799static PyObject *
3800posix_getpid(PyObject *self, PyObject *noargs)
3801{
3802	return PyLong_FromLong((long)getpid());
3803}
3804
3805
3806#ifdef HAVE_GETGROUPS
3807PyDoc_STRVAR(posix_getgroups__doc__,
3808"getgroups() -> list of group IDs\n\n\
3809Return list of supplemental group IDs for the process.");
3810
3811static PyObject *
3812posix_getgroups(PyObject *self, PyObject *noargs)
3813{
3814    PyObject *result = NULL;
3815
3816#ifdef NGROUPS_MAX
3817#define MAX_GROUPS NGROUPS_MAX
3818#else
3819        /* defined to be 16 on Solaris7, so this should be a small number */
3820#define MAX_GROUPS 64
3821#endif
3822        gid_t grouplist[MAX_GROUPS];
3823        int n;
3824
3825        n = getgroups(MAX_GROUPS, grouplist);
3826        if (n < 0)
3827            posix_error();
3828        else {
3829            result = PyList_New(n);
3830            if (result != NULL) {
3831                int i;
3832                for (i = 0; i < n; ++i) {
3833                    PyObject *o = PyLong_FromLong((long)grouplist[i]);
3834                    if (o == NULL) {
3835                        Py_DECREF(result);
3836                        result = NULL;
3837                        break;
3838                    }
3839                    PyList_SET_ITEM(result, i, o);
3840                }
3841            }
3842        }
3843
3844    return result;
3845}
3846#endif
3847
3848#ifdef HAVE_GETPGID
3849PyDoc_STRVAR(posix_getpgid__doc__,
3850"getpgid(pid) -> pgid\n\n\
3851Call the system call getpgid().");
3852
3853static PyObject *
3854posix_getpgid(PyObject *self, PyObject *args)
3855{
3856	int pid, pgid;
3857	if (!PyArg_ParseTuple(args, "i:getpgid", &pid))
3858		return NULL;
3859	pgid = getpgid(pid);
3860	if (pgid < 0)
3861		return posix_error();
3862	return PyLong_FromLong((long)pgid);
3863}
3864#endif /* HAVE_GETPGID */
3865
3866
3867#ifdef HAVE_GETPGRP
3868PyDoc_STRVAR(posix_getpgrp__doc__,
3869"getpgrp() -> pgrp\n\n\
3870Return the current process group id.");
3871
3872static PyObject *
3873posix_getpgrp(PyObject *self, PyObject *noargs)
3874{
3875#ifdef GETPGRP_HAVE_ARG
3876	return PyLong_FromLong((long)getpgrp(0));
3877#else /* GETPGRP_HAVE_ARG */
3878	return PyLong_FromLong((long)getpgrp());
3879#endif /* GETPGRP_HAVE_ARG */
3880}
3881#endif /* HAVE_GETPGRP */
3882
3883
3884#ifdef HAVE_SETPGRP
3885PyDoc_STRVAR(posix_setpgrp__doc__,
3886"setpgrp()\n\n\
3887Make this process a session leader.");
3888
3889static PyObject *
3890posix_setpgrp(PyObject *self, PyObject *noargs)
3891{
3892#ifdef SETPGRP_HAVE_ARG
3893	if (setpgrp(0, 0) < 0)
3894#else /* SETPGRP_HAVE_ARG */
3895	if (setpgrp() < 0)
3896#endif /* SETPGRP_HAVE_ARG */
3897		return posix_error();
3898	Py_INCREF(Py_None);
3899	return Py_None;
3900}
3901
3902#endif /* HAVE_SETPGRP */
3903
3904#ifdef HAVE_GETPPID
3905PyDoc_STRVAR(posix_getppid__doc__,
3906"getppid() -> ppid\n\n\
3907Return the parent's process id.");
3908
3909static PyObject *
3910posix_getppid(PyObject *self, PyObject *noargs)
3911{
3912	return PyLong_FromLong((long)getppid());
3913}
3914#endif
3915
3916
3917#ifdef HAVE_GETLOGIN
3918PyDoc_STRVAR(posix_getlogin__doc__,
3919"getlogin() -> string\n\n\
3920Return the actual login name.");
3921
3922static PyObject *
3923posix_getlogin(PyObject *self, PyObject *noargs)
3924{
3925        PyObject *result = NULL;
3926        char *name;
3927        int old_errno = errno;
3928
3929        errno = 0;
3930        name = getlogin();
3931        if (name == NULL) {
3932            if (errno)
3933                posix_error();
3934            else
3935                PyErr_SetString(PyExc_OSError,
3936                                "unable to determine login name");
3937        }
3938        else
3939            result = PyUnicode_FromString(name);
3940        errno = old_errno;
3941
3942    return result;
3943}
3944#endif
3945
3946#ifdef HAVE_GETUID
3947PyDoc_STRVAR(posix_getuid__doc__,
3948"getuid() -> uid\n\n\
3949Return the current process's user id.");
3950
3951static PyObject *
3952posix_getuid(PyObject *self, PyObject *noargs)
3953{
3954	return PyLong_FromLong((long)getuid());
3955}
3956#endif
3957
3958
3959#ifdef HAVE_KILL
3960PyDoc_STRVAR(posix_kill__doc__,
3961"kill(pid, sig)\n\n\
3962Kill a process with a signal.");
3963
3964static PyObject *
3965posix_kill(PyObject *self, PyObject *args)
3966{
3967	pid_t pid;
3968	int sig;
3969	if (!PyArg_ParseTuple(args, "ii:kill", &pid, &sig))
3970		return NULL;
3971#if defined(PYOS_OS2) && !defined(PYCC_GCC)
3972    if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
3973        APIRET rc;
3974        if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
3975            return os2_error(rc);
3976
3977    } else if (sig == XCPT_SIGNAL_KILLPROC) {
3978        APIRET rc;
3979        if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
3980            return os2_error(rc);
3981
3982    } else
3983        return NULL; /* Unrecognized Signal Requested */
3984#else
3985	if (kill(pid, sig) == -1)
3986		return posix_error();
3987#endif
3988	Py_INCREF(Py_None);
3989	return Py_None;
3990}
3991#endif
3992
3993#ifdef HAVE_KILLPG
3994PyDoc_STRVAR(posix_killpg__doc__,
3995"killpg(pgid, sig)\n\n\
3996Kill a process group with a signal.");
3997
3998static PyObject *
3999posix_killpg(PyObject *self, PyObject *args)
4000{
4001	int pgid, sig;
4002	if (!PyArg_ParseTuple(args, "ii:killpg", &pgid, &sig))
4003		return NULL;
4004	if (killpg(pgid, sig) == -1)
4005		return posix_error();
4006	Py_INCREF(Py_None);
4007	return Py_None;
4008}
4009#endif
4010
4011#ifdef HAVE_PLOCK
4012
4013#ifdef HAVE_SYS_LOCK_H
4014#include <sys/lock.h>
4015#endif
4016
4017PyDoc_STRVAR(posix_plock__doc__,
4018"plock(op)\n\n\
4019Lock program segments into memory.");
4020
4021static PyObject *
4022posix_plock(PyObject *self, PyObject *args)
4023{
4024	int op;
4025	if (!PyArg_ParseTuple(args, "i:plock", &op))
4026		return NULL;
4027	if (plock(op) == -1)
4028		return posix_error();
4029	Py_INCREF(Py_None);
4030	return Py_None;
4031}
4032#endif
4033
4034
4035
4036
4037#ifdef HAVE_SETUID
4038PyDoc_STRVAR(posix_setuid__doc__,
4039"setuid(uid)\n\n\
4040Set the current process's user id.");
4041
4042static PyObject *
4043posix_setuid(PyObject *self, PyObject *args)
4044{
4045	int uid;
4046	if (!PyArg_ParseTuple(args, "i:setuid", &uid))
4047		return NULL;
4048	if (setuid(uid) < 0)
4049		return posix_error();
4050	Py_INCREF(Py_None);
4051	return Py_None;
4052}
4053#endif /* HAVE_SETUID */
4054
4055
4056#ifdef HAVE_SETEUID
4057PyDoc_STRVAR(posix_seteuid__doc__,
4058"seteuid(uid)\n\n\
4059Set the current process's effective user id.");
4060
4061static PyObject *
4062posix_seteuid (PyObject *self, PyObject *args)
4063{
4064	int euid;
4065	if (!PyArg_ParseTuple(args, "i", &euid)) {
4066		return NULL;
4067	} else if (seteuid(euid) < 0) {
4068		return posix_error();
4069	} else {
4070		Py_INCREF(Py_None);
4071		return Py_None;
4072	}
4073}
4074#endif /* HAVE_SETEUID */
4075
4076#ifdef HAVE_SETEGID
4077PyDoc_STRVAR(posix_setegid__doc__,
4078"setegid(gid)\n\n\
4079Set the current process's effective group id.");
4080
4081static PyObject *
4082posix_setegid (PyObject *self, PyObject *args)
4083{
4084	int egid;
4085	if (!PyArg_ParseTuple(args, "i", &egid)) {
4086		return NULL;
4087	} else if (setegid(egid) < 0) {
4088		return posix_error();
4089	} else {
4090		Py_INCREF(Py_None);
4091		return Py_None;
4092	}
4093}
4094#endif /* HAVE_SETEGID */
4095
4096#ifdef HAVE_SETREUID
4097PyDoc_STRVAR(posix_setreuid__doc__,
4098"setreuid(ruid, euid)\n\n\
4099Set the current process's real and effective user ids.");
4100
4101static PyObject *
4102posix_setreuid (PyObject *self, PyObject *args)
4103{
4104	int ruid, euid;
4105	if (!PyArg_ParseTuple(args, "ii", &ruid, &euid)) {
4106		return NULL;
4107	} else if (setreuid(ruid, euid) < 0) {
4108		return posix_error();
4109	} else {
4110		Py_INCREF(Py_None);
4111		return Py_None;
4112	}
4113}
4114#endif /* HAVE_SETREUID */
4115
4116#ifdef HAVE_SETREGID
4117PyDoc_STRVAR(posix_setregid__doc__,
4118"setregid(rgid, egid)\n\n\
4119Set the current process's real and effective group ids.");
4120
4121static PyObject *
4122posix_setregid (PyObject *self, PyObject *args)
4123{
4124	int rgid, egid;
4125	if (!PyArg_ParseTuple(args, "ii", &rgid, &egid)) {
4126		return NULL;
4127	} else if (setregid(rgid, egid) < 0) {
4128		return posix_error();
4129	} else {
4130		Py_INCREF(Py_None);
4131		return Py_None;
4132	}
4133}
4134#endif /* HAVE_SETREGID */
4135
4136#ifdef HAVE_SETGID
4137PyDoc_STRVAR(posix_setgid__doc__,
4138"setgid(gid)\n\n\
4139Set the current process's group id.");
4140
4141static PyObject *
4142posix_setgid(PyObject *self, PyObject *args)
4143{
4144	int gid;
4145	if (!PyArg_ParseTuple(args, "i:setgid", &gid))
4146		return NULL;
4147	if (setgid(gid) < 0)
4148		return posix_error();
4149	Py_INCREF(Py_None);
4150	return Py_None;
4151}
4152#endif /* HAVE_SETGID */
4153
4154#ifdef HAVE_SETGROUPS
4155PyDoc_STRVAR(posix_setgroups__doc__,
4156"setgroups(list)\n\n\
4157Set the groups of the current process to list.");
4158
4159static PyObject *
4160posix_setgroups(PyObject *self, PyObject *groups)
4161{
4162	int i, len;
4163        gid_t grouplist[MAX_GROUPS];
4164
4165	if (!PySequence_Check(groups)) {
4166		PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
4167		return NULL;
4168	}
4169	len = PySequence_Size(groups);
4170	if (len > MAX_GROUPS) {
4171		PyErr_SetString(PyExc_ValueError, "too many groups");
4172		return NULL;
4173	}
4174	for(i = 0; i < len; i++) {
4175		PyObject *elem;
4176		elem = PySequence_GetItem(groups, i);
4177		if (!elem)
4178			return NULL;
4179		if (!PyLong_Check(elem)) {
4180			PyErr_SetString(PyExc_TypeError,
4181					"groups must be integers");
4182			Py_DECREF(elem);
4183			return NULL;
4184		} else {
4185			unsigned long x = PyLong_AsUnsignedLong(elem);
4186			if (PyErr_Occurred()) {
4187				PyErr_SetString(PyExc_TypeError,
4188						"group id too big");
4189				Py_DECREF(elem);
4190				return NULL;
4191			}
4192			grouplist[i] = x;
4193			/* read back the value to see if it fitted in gid_t */
4194			if (grouplist[i] != x) {
4195				PyErr_SetString(PyExc_TypeError,
4196						"group id too big");
4197				Py_DECREF(elem);
4198				return NULL;
4199			}
4200		}
4201		Py_DECREF(elem);
4202	}
4203
4204	if (setgroups(len, grouplist) < 0)
4205		return posix_error();
4206	Py_INCREF(Py_None);
4207	return Py_None;
4208}
4209#endif /* HAVE_SETGROUPS */
4210
4211#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
4212static PyObject *
4213wait_helper(pid_t pid, int status, struct rusage *ru)
4214{
4215	PyObject *result;
4216   	static PyObject *struct_rusage;
4217
4218	if (pid == -1)
4219		return posix_error();
4220
4221	if (struct_rusage == NULL) {
4222		PyObject *m = PyImport_ImportModuleNoBlock("resource");
4223		if (m == NULL)
4224			return NULL;
4225		struct_rusage = PyObject_GetAttrString(m, "struct_rusage");
4226		Py_DECREF(m);
4227		if (struct_rusage == NULL)
4228			return NULL;
4229	}
4230
4231	/* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
4232	result = PyStructSequence_New((PyTypeObject*) struct_rusage);
4233	if (!result)
4234		return NULL;
4235
4236#ifndef doubletime
4237#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
4238#endif
4239
4240	PyStructSequence_SET_ITEM(result, 0,
4241			PyFloat_FromDouble(doubletime(ru->ru_utime)));
4242	PyStructSequence_SET_ITEM(result, 1,
4243			PyFloat_FromDouble(doubletime(ru->ru_stime)));
4244#define SET_INT(result, index, value)\
4245		PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
4246	SET_INT(result, 2, ru->ru_maxrss);
4247	SET_INT(result, 3, ru->ru_ixrss);
4248	SET_INT(result, 4, ru->ru_idrss);
4249	SET_INT(result, 5, ru->ru_isrss);
4250	SET_INT(result, 6, ru->ru_minflt);
4251	SET_INT(result, 7, ru->ru_majflt);
4252	SET_INT(result, 8, ru->ru_nswap);
4253	SET_INT(result, 9, ru->ru_inblock);
4254	SET_INT(result, 10, ru->ru_oublock);
4255	SET_INT(result, 11, ru->ru_msgsnd);
4256	SET_INT(result, 12, ru->ru_msgrcv);
4257	SET_INT(result, 13, ru->ru_nsignals);
4258	SET_INT(result, 14, ru->ru_nvcsw);
4259	SET_INT(result, 15, ru->ru_nivcsw);
4260#undef SET_INT
4261
4262	if (PyErr_Occurred()) {
4263		Py_DECREF(result);
4264		return NULL;
4265	}
4266
4267	return Py_BuildValue("iiN", pid, status, result);
4268}
4269#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
4270
4271#ifdef HAVE_WAIT3
4272PyDoc_STRVAR(posix_wait3__doc__,
4273"wait3(options) -> (pid, status, rusage)\n\n\
4274Wait for completion of a child process.");
4275
4276static PyObject *
4277posix_wait3(PyObject *self, PyObject *args)
4278{
4279	pid_t pid;
4280	int options;
4281	struct rusage ru;
4282	WAIT_TYPE status;
4283	WAIT_STATUS_INT(status) = 0;
4284
4285	if (!PyArg_ParseTuple(args, "i:wait3", &options))
4286		return NULL;
4287
4288	Py_BEGIN_ALLOW_THREADS
4289	pid = wait3(&status, options, &ru);
4290	Py_END_ALLOW_THREADS
4291
4292	return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
4293}
4294#endif /* HAVE_WAIT3 */
4295
4296#ifdef HAVE_WAIT4
4297PyDoc_STRVAR(posix_wait4__doc__,
4298"wait4(pid, options) -> (pid, status, rusage)\n\n\
4299Wait for completion of a given child process.");
4300
4301static PyObject *
4302posix_wait4(PyObject *self, PyObject *args)
4303{
4304	pid_t pid;
4305	int options;
4306	struct rusage ru;
4307	WAIT_TYPE status;
4308	WAIT_STATUS_INT(status) = 0;
4309
4310	if (!PyArg_ParseTuple(args, "ii:wait4", &pid, &options))
4311		return NULL;
4312
4313	Py_BEGIN_ALLOW_THREADS
4314	pid = wait4(pid, &status, options, &ru);
4315	Py_END_ALLOW_THREADS
4316
4317	return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
4318}
4319#endif /* HAVE_WAIT4 */
4320
4321#ifdef HAVE_WAITPID
4322PyDoc_STRVAR(posix_waitpid__doc__,
4323"waitpid(pid, options) -> (pid, status)\n\n\
4324Wait for completion of a given child process.");
4325
4326static PyObject *
4327posix_waitpid(PyObject *self, PyObject *args)
4328{
4329	pid_t pid;
4330	int options;
4331	WAIT_TYPE status;
4332	WAIT_STATUS_INT(status) = 0;
4333
4334	if (!PyArg_ParseTuple(args, "ii:waitpid", &pid, &options))
4335		return NULL;
4336	Py_BEGIN_ALLOW_THREADS
4337	pid = waitpid(pid, &status, options);
4338	Py_END_ALLOW_THREADS
4339	if (pid == -1)
4340		return posix_error();
4341
4342	return Py_BuildValue("ii", pid, WAIT_STATUS_INT(status));
4343}
4344
4345#elif defined(HAVE_CWAIT)
4346
4347/* MS C has a variant of waitpid() that's usable for most purposes. */
4348PyDoc_STRVAR(posix_waitpid__doc__,
4349"waitpid(pid, options) -> (pid, status << 8)\n\n"
4350"Wait for completion of a given process.  options is ignored on Windows.");
4351
4352static PyObject *
4353posix_waitpid(PyObject *self, PyObject *args)
4354{
4355	Py_intptr_t pid;
4356	int status, options;
4357
4358	if (!PyArg_ParseTuple(args, "ii:waitpid", &pid, &options))
4359		return NULL;
4360	Py_BEGIN_ALLOW_THREADS
4361	pid = _cwait(&status, pid, options);
4362	Py_END_ALLOW_THREADS
4363	if (pid == -1)
4364		return posix_error();
4365
4366	/* shift the status left a byte so this is more like the POSIX waitpid */
4367	return Py_BuildValue("ii", pid, status << 8);
4368}
4369#endif /* HAVE_WAITPID || HAVE_CWAIT */
4370
4371#ifdef HAVE_WAIT
4372PyDoc_STRVAR(posix_wait__doc__,
4373"wait() -> (pid, status)\n\n\
4374Wait for completion of a child process.");
4375
4376static PyObject *
4377posix_wait(PyObject *self, PyObject *noargs)
4378{
4379	pid_t pid;
4380	WAIT_TYPE status;
4381	WAIT_STATUS_INT(status) = 0;
4382
4383	Py_BEGIN_ALLOW_THREADS
4384	pid = wait(&status);
4385	Py_END_ALLOW_THREADS
4386	if (pid == -1)
4387		return posix_error();
4388
4389	return Py_BuildValue("ii", pid, WAIT_STATUS_INT(status));
4390}
4391#endif
4392
4393
4394PyDoc_STRVAR(posix_lstat__doc__,
4395"lstat(path) -> stat result\n\n\
4396Like stat(path), but do not follow symbolic links.");
4397
4398static PyObject *
4399posix_lstat(PyObject *self, PyObject *args)
4400{
4401#ifdef HAVE_LSTAT
4402	return posix_do_stat(self, args, "et:lstat", lstat, NULL, NULL);
4403#else /* !HAVE_LSTAT */
4404#ifdef MS_WINDOWS
4405	return posix_do_stat(self, args, "et:lstat", STAT, "U:lstat", win32_wstat);
4406#else
4407	return posix_do_stat(self, args, "et:lstat", STAT, NULL, NULL);
4408#endif
4409#endif /* !HAVE_LSTAT */
4410}
4411
4412
4413#ifdef HAVE_READLINK
4414PyDoc_STRVAR(posix_readlink__doc__,
4415"readlink(path) -> path\n\n\
4416Return a string representing the path to which the symbolic link points.");
4417
4418static PyObject *
4419posix_readlink(PyObject *self, PyObject *args)
4420{
4421	PyObject* v;
4422	char buf[MAXPATHLEN];
4423	char *path;
4424	int n;
4425	int arg_is_unicode = 0;
4426
4427	if (!PyArg_ParseTuple(args, "et:readlink",
4428				Py_FileSystemDefaultEncoding, &path))
4429		return NULL;
4430	v = PySequence_GetItem(args, 0);
4431	if (v == NULL) {
4432		PyMem_Free(path);
4433		return NULL;
4434	}
4435
4436	if (PyUnicode_Check(v)) {
4437		arg_is_unicode = 1;
4438	}
4439	Py_DECREF(v);
4440
4441	Py_BEGIN_ALLOW_THREADS
4442	n = readlink(path, buf, (int) sizeof buf);
4443	Py_END_ALLOW_THREADS
4444	if (n < 0)
4445		return posix_error_with_allocated_filename(path);
4446
4447	PyMem_Free(path);
4448	v = PyString_FromStringAndSize(buf, n);
4449	if (arg_is_unicode) {
4450		PyObject *w;
4451
4452		w = PyUnicode_FromEncodedObject(v,
4453				Py_FileSystemDefaultEncoding,
4454				"strict");
4455		if (w != NULL) {
4456			Py_DECREF(v);
4457			v = w;
4458		}
4459		else {
4460			/* fall back to the original byte string, as
4461			   discussed in patch #683592 */
4462			PyErr_Clear();
4463		}
4464	}
4465	return v;
4466}
4467#endif /* HAVE_READLINK */
4468
4469
4470#ifdef HAVE_SYMLINK
4471PyDoc_STRVAR(posix_symlink__doc__,
4472"symlink(src, dst)\n\n\
4473Create a symbolic link pointing to src named dst.");
4474
4475static PyObject *
4476posix_symlink(PyObject *self, PyObject *args)
4477{
4478	return posix_2str(args, "etet:symlink", symlink);
4479}
4480#endif /* HAVE_SYMLINK */
4481
4482
4483#ifdef HAVE_TIMES
4484#ifndef HZ
4485#define HZ 60 /* Universal constant :-) */
4486#endif /* HZ */
4487
4488#if defined(PYCC_VACPP) && defined(PYOS_OS2)
4489static long
4490system_uptime(void)
4491{
4492    ULONG     value = 0;
4493
4494    Py_BEGIN_ALLOW_THREADS
4495    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value));
4496    Py_END_ALLOW_THREADS
4497
4498    return value;
4499}
4500
4501static PyObject *
4502posix_times(PyObject *self, PyObject *noargs)
4503{
4504    /* Currently Only Uptime is Provided -- Others Later */
4505	return Py_BuildValue("ddddd",
4506			     (double)0 /* t.tms_utime / HZ */,
4507			     (double)0 /* t.tms_stime / HZ */,
4508			     (double)0 /* t.tms_cutime / HZ */,
4509			     (double)0 /* t.tms_cstime / HZ */,
4510			     (double)system_uptime() / 1000);
4511}
4512#else /* not OS2 */
4513static PyObject *
4514posix_times(PyObject *self, PyObject *noargs)
4515{
4516	struct tms t;
4517	clock_t c;
4518	errno = 0;
4519	c = times(&t);
4520	if (c == (clock_t) -1)
4521		return posix_error();
4522	return Py_BuildValue("ddddd",
4523			     (double)t.tms_utime / HZ,
4524			     (double)t.tms_stime / HZ,
4525			     (double)t.tms_cutime / HZ,
4526			     (double)t.tms_cstime / HZ,
4527			     (double)c / HZ);
4528}
4529#endif /* not OS2 */
4530#endif /* HAVE_TIMES */
4531
4532
4533#ifdef MS_WINDOWS
4534#define HAVE_TIMES	/* so the method table will pick it up */
4535static PyObject *
4536posix_times(PyObject *self, PyObject *noargs)
4537{
4538	FILETIME create, exit, kernel, user;
4539	HANDLE hProc;
4540	hProc = GetCurrentProcess();
4541	GetProcessTimes(hProc, &create, &exit, &kernel, &user);
4542	/* The fields of a FILETIME structure are the hi and lo part
4543	   of a 64-bit value expressed in 100 nanosecond units.
4544	   1e7 is one second in such units; 1e-7 the inverse.
4545	   429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
4546	*/
4547	return Py_BuildValue(
4548		"ddddd",
4549		(double)(user.dwHighDateTime*429.4967296 +
4550		         user.dwLowDateTime*1e-7),
4551		(double)(kernel.dwHighDateTime*429.4967296 +
4552		         kernel.dwLowDateTime*1e-7),
4553		(double)0,
4554		(double)0,
4555		(double)0);
4556}
4557#endif /* MS_WINDOWS */
4558
4559#ifdef HAVE_TIMES
4560PyDoc_STRVAR(posix_times__doc__,
4561"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
4562Return a tuple of floating point numbers indicating process times.");
4563#endif
4564
4565
4566#ifdef HAVE_GETSID
4567PyDoc_STRVAR(posix_getsid__doc__,
4568"getsid(pid) -> sid\n\n\
4569Call the system call getsid().");
4570
4571static PyObject *
4572posix_getsid(PyObject *self, PyObject *args)
4573{
4574	pid_t pid;
4575	int sid;
4576	if (!PyArg_ParseTuple(args, "i:getsid", &pid))
4577		return NULL;
4578	sid = getsid(pid);
4579	if (sid < 0)
4580		return posix_error();
4581	return PyLong_FromLong((long)sid);
4582}
4583#endif /* HAVE_GETSID */
4584
4585
4586#ifdef HAVE_SETSID
4587PyDoc_STRVAR(posix_setsid__doc__,
4588"setsid()\n\n\
4589Call the system call setsid().");
4590
4591static PyObject *
4592posix_setsid(PyObject *self, PyObject *noargs)
4593{
4594	if (setsid() < 0)
4595		return posix_error();
4596	Py_INCREF(Py_None);
4597	return Py_None;
4598}
4599#endif /* HAVE_SETSID */
4600
4601#ifdef HAVE_SETPGID
4602PyDoc_STRVAR(posix_setpgid__doc__,
4603"setpgid(pid, pgrp)\n\n\
4604Call the system call setpgid().");
4605
4606static PyObject *
4607posix_setpgid(PyObject *self, PyObject *args)
4608{
4609	pid_t pid;
4610	int pgrp;
4611	if (!PyArg_ParseTuple(args, "ii:setpgid", &pid, &pgrp))
4612		return NULL;
4613	if (setpgid(pid, pgrp) < 0)
4614		return posix_error();
4615	Py_INCREF(Py_None);
4616	return Py_None;
4617}
4618#endif /* HAVE_SETPGID */
4619
4620
4621#ifdef HAVE_TCGETPGRP
4622PyDoc_STRVAR(posix_tcgetpgrp__doc__,
4623"tcgetpgrp(fd) -> pgid\n\n\
4624Return the process group associated with the terminal given by a fd.");
4625
4626static PyObject *
4627posix_tcgetpgrp(PyObject *self, PyObject *args)
4628{
4629	int fd;
4630	pid_t pgid;
4631	if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
4632		return NULL;
4633	pgid = tcgetpgrp(fd);
4634	if (pgid < 0)
4635		return posix_error();
4636	return PyLong_FromLong((long)pgid);
4637}
4638#endif /* HAVE_TCGETPGRP */
4639
4640
4641#ifdef HAVE_TCSETPGRP
4642PyDoc_STRVAR(posix_tcsetpgrp__doc__,
4643"tcsetpgrp(fd, pgid)\n\n\
4644Set the process group associated with the terminal given by a fd.");
4645
4646static PyObject *
4647posix_tcsetpgrp(PyObject *self, PyObject *args)
4648{
4649	int fd, pgid;
4650	if (!PyArg_ParseTuple(args, "ii:tcsetpgrp", &fd, &pgid))
4651		return NULL;
4652	if (tcsetpgrp(fd, pgid) < 0)
4653		return posix_error();
4654	Py_INCREF(Py_None);
4655	return Py_None;
4656}
4657#endif /* HAVE_TCSETPGRP */
4658
4659/* Functions acting on file descriptors */
4660
4661PyDoc_STRVAR(posix_open__doc__,
4662"open(filename, flag [, mode=0777]) -> fd\n\n\
4663Open a file (for low level IO).");
4664
4665static PyObject *
4666posix_open(PyObject *self, PyObject *args)
4667{
4668	char *file = NULL;
4669	int flag;
4670	int mode = 0777;
4671	int fd;
4672
4673#ifdef MS_WINDOWS
4674	if (unicode_file_names()) {
4675		PyUnicodeObject *po;
4676		if (PyArg_ParseTuple(args, "Ui|i:mkdir", &po, &flag, &mode)) {
4677			Py_BEGIN_ALLOW_THREADS
4678			/* PyUnicode_AS_UNICODE OK without thread
4679			   lock as it is a simple dereference. */
4680			fd = _wopen(PyUnicode_AS_UNICODE(po), flag, mode);
4681			Py_END_ALLOW_THREADS
4682			if (fd < 0)
4683				return posix_error();
4684			return PyLong_FromLong((long)fd);
4685		}
4686		/* Drop the argument parsing error as narrow strings
4687		   are also valid. */
4688		PyErr_Clear();
4689	}
4690#endif
4691
4692	if (!PyArg_ParseTuple(args, "eti|i",
4693	                      Py_FileSystemDefaultEncoding, &file,
4694	                      &flag, &mode))
4695		return NULL;
4696
4697	Py_BEGIN_ALLOW_THREADS
4698	fd = open(file, flag, mode);
4699	Py_END_ALLOW_THREADS
4700	if (fd < 0)
4701		return posix_error_with_allocated_filename(file);
4702	PyMem_Free(file);
4703	return PyLong_FromLong((long)fd);
4704}
4705
4706
4707PyDoc_STRVAR(posix_close__doc__,
4708"close(fd)\n\n\
4709Close a file descriptor (for low level IO).");
4710
4711static PyObject *
4712posix_close(PyObject *self, PyObject *args)
4713{
4714	int fd, res;
4715	if (!PyArg_ParseTuple(args, "i:close", &fd))
4716		return NULL;
4717	Py_BEGIN_ALLOW_THREADS
4718	res = close(fd);
4719	Py_END_ALLOW_THREADS
4720	if (res < 0)
4721		return posix_error();
4722	Py_INCREF(Py_None);
4723	return Py_None;
4724}
4725
4726
4727PyDoc_STRVAR(posix_closerange__doc__,
4728"closerange(fd_low, fd_high)\n\n\
4729Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
4730
4731static PyObject *
4732posix_closerange(PyObject *self, PyObject *args)
4733{
4734	int fd_from, fd_to, i;
4735	if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
4736		return NULL;
4737	Py_BEGIN_ALLOW_THREADS
4738	for (i = fd_from; i < fd_to; i++)
4739		close(i);
4740	Py_END_ALLOW_THREADS
4741	Py_RETURN_NONE;
4742}
4743
4744
4745PyDoc_STRVAR(posix_dup__doc__,
4746"dup(fd) -> fd2\n\n\
4747Return a duplicate of a file descriptor.");
4748
4749static PyObject *
4750posix_dup(PyObject *self, PyObject *args)
4751{
4752	int fd;
4753	if (!PyArg_ParseTuple(args, "i:dup", &fd))
4754		return NULL;
4755	Py_BEGIN_ALLOW_THREADS
4756	fd = dup(fd);
4757	Py_END_ALLOW_THREADS
4758	if (fd < 0)
4759		return posix_error();
4760	return PyLong_FromLong((long)fd);
4761}
4762
4763
4764PyDoc_STRVAR(posix_dup2__doc__,
4765"dup2(old_fd, new_fd)\n\n\
4766Duplicate file descriptor.");
4767
4768static PyObject *
4769posix_dup2(PyObject *self, PyObject *args)
4770{
4771	int fd, fd2, res;
4772	if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
4773		return NULL;
4774	Py_BEGIN_ALLOW_THREADS
4775	res = dup2(fd, fd2);
4776	Py_END_ALLOW_THREADS
4777	if (res < 0)
4778		return posix_error();
4779	Py_INCREF(Py_None);
4780	return Py_None;
4781}
4782
4783
4784PyDoc_STRVAR(posix_lseek__doc__,
4785"lseek(fd, pos, how) -> newpos\n\n\
4786Set the current position of a file descriptor.");
4787
4788static PyObject *
4789posix_lseek(PyObject *self, PyObject *args)
4790{
4791	int fd, how;
4792#if defined(MS_WIN64) || defined(MS_WINDOWS)
4793	PY_LONG_LONG pos, res;
4794#else
4795	off_t pos, res;
4796#endif
4797	PyObject *posobj;
4798	if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
4799		return NULL;
4800#ifdef SEEK_SET
4801	/* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
4802	switch (how) {
4803	case 0: how = SEEK_SET; break;
4804	case 1: how = SEEK_CUR; break;
4805	case 2: how = SEEK_END; break;
4806	}
4807#endif /* SEEK_END */
4808
4809#if !defined(HAVE_LARGEFILE_SUPPORT)
4810	pos = PyLong_AsLong(posobj);
4811#else
4812	pos = PyLong_Check(posobj) ?
4813		PyLong_AsLongLong(posobj) : PyLong_AsLong(posobj);
4814#endif
4815	if (PyErr_Occurred())
4816		return NULL;
4817
4818	Py_BEGIN_ALLOW_THREADS
4819#if defined(MS_WIN64) || defined(MS_WINDOWS)
4820	res = _lseeki64(fd, pos, how);
4821#else
4822	res = lseek(fd, pos, how);
4823#endif
4824	Py_END_ALLOW_THREADS
4825	if (res < 0)
4826		return posix_error();
4827
4828#if !defined(HAVE_LARGEFILE_SUPPORT)
4829	return PyLong_FromLong(res);
4830#else
4831	return PyLong_FromLongLong(res);
4832#endif
4833}
4834
4835
4836PyDoc_STRVAR(posix_read__doc__,
4837"read(fd, buffersize) -> string\n\n\
4838Read a file descriptor.");
4839
4840static PyObject *
4841posix_read(PyObject *self, PyObject *args)
4842{
4843	int fd, size;
4844        Py_ssize_t n;
4845	PyObject *buffer;
4846	if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
4847		return NULL;
4848	if (size < 0) {
4849		errno = EINVAL;
4850		return posix_error();
4851	}
4852	buffer = PyString_FromStringAndSize((char *)NULL, size);
4853	if (buffer == NULL)
4854		return NULL;
4855	Py_BEGIN_ALLOW_THREADS
4856	n = read(fd, PyString_AS_STRING(buffer), size);
4857	Py_END_ALLOW_THREADS
4858	if (n < 0) {
4859		Py_DECREF(buffer);
4860		return posix_error();
4861	}
4862	if (n != size)
4863		_PyString_Resize(&buffer, n);
4864	return buffer;
4865}
4866
4867
4868PyDoc_STRVAR(posix_write__doc__,
4869"write(fd, string) -> byteswritten\n\n\
4870Write a string to a file descriptor.");
4871
4872static PyObject *
4873posix_write(PyObject *self, PyObject *args)
4874{
4875	int fd;
4876	Py_ssize_t size;
4877	char *buffer;
4878
4879	if (!PyArg_ParseTuple(args, "is#:write", &fd, &buffer, &size))
4880		return NULL;
4881	Py_BEGIN_ALLOW_THREADS
4882	size = write(fd, buffer, (size_t)size);
4883	Py_END_ALLOW_THREADS
4884	if (size < 0)
4885		return posix_error();
4886	return PyLong_FromSsize_t(size);
4887}
4888
4889
4890PyDoc_STRVAR(posix_fstat__doc__,
4891"fstat(fd) -> stat result\n\n\
4892Like stat(), but for an open file descriptor.");
4893
4894static PyObject *
4895posix_fstat(PyObject *self, PyObject *args)
4896{
4897	int fd;
4898	STRUCT_STAT st;
4899	int res;
4900	if (!PyArg_ParseTuple(args, "i:fstat", &fd))
4901		return NULL;
4902#ifdef __VMS
4903        /* on OpenVMS we must ensure that all bytes are written to the file */
4904        fsync(fd);
4905#endif
4906	Py_BEGIN_ALLOW_THREADS
4907	res = FSTAT(fd, &st);
4908	Py_END_ALLOW_THREADS
4909	if (res != 0) {
4910#ifdef MS_WINDOWS
4911		return win32_error("fstat", NULL);
4912#else
4913		return posix_error();
4914#endif
4915	}
4916
4917	return _pystat_fromstructstat(&st);
4918}
4919
4920PyDoc_STRVAR(posix_isatty__doc__,
4921"isatty(fd) -> bool\n\n\
4922Return True if the file descriptor 'fd' is an open file descriptor\n\
4923connected to the slave end of a terminal.");
4924
4925static PyObject *
4926posix_isatty(PyObject *self, PyObject *args)
4927{
4928	int fd;
4929	if (!PyArg_ParseTuple(args, "i:isatty", &fd))
4930		return NULL;
4931	return PyBool_FromLong(isatty(fd));
4932}
4933
4934#ifdef HAVE_PIPE
4935PyDoc_STRVAR(posix_pipe__doc__,
4936"pipe() -> (read_end, write_end)\n\n\
4937Create a pipe.");
4938
4939static PyObject *
4940posix_pipe(PyObject *self, PyObject *noargs)
4941{
4942#if defined(PYOS_OS2)
4943    HFILE read, write;
4944    APIRET rc;
4945
4946	Py_BEGIN_ALLOW_THREADS
4947    rc = DosCreatePipe( &read, &write, 4096);
4948	Py_END_ALLOW_THREADS
4949    if (rc != NO_ERROR)
4950        return os2_error(rc);
4951
4952    return Py_BuildValue("(ii)", read, write);
4953#else
4954#if !defined(MS_WINDOWS)
4955	int fds[2];
4956	int res;
4957	Py_BEGIN_ALLOW_THREADS
4958	res = pipe(fds);
4959	Py_END_ALLOW_THREADS
4960	if (res != 0)
4961		return posix_error();
4962	return Py_BuildValue("(ii)", fds[0], fds[1]);
4963#else /* MS_WINDOWS */
4964	HANDLE read, write;
4965	int read_fd, write_fd;
4966	BOOL ok;
4967	Py_BEGIN_ALLOW_THREADS
4968	ok = CreatePipe(&read, &write, NULL, 0);
4969	Py_END_ALLOW_THREADS
4970	if (!ok)
4971		return win32_error("CreatePipe", NULL);
4972	read_fd = _open_osfhandle((Py_intptr_t)read, 0);
4973	write_fd = _open_osfhandle((Py_intptr_t)write, 1);
4974	return Py_BuildValue("(ii)", read_fd, write_fd);
4975#endif /* MS_WINDOWS */
4976#endif
4977}
4978#endif  /* HAVE_PIPE */
4979
4980
4981#ifdef HAVE_MKFIFO
4982PyDoc_STRVAR(posix_mkfifo__doc__,
4983"mkfifo(filename [, mode=0666])\n\n\
4984Create a FIFO (a POSIX named pipe).");
4985
4986static PyObject *
4987posix_mkfifo(PyObject *self, PyObject *args)
4988{
4989	char *filename;
4990	int mode = 0666;
4991	int res;
4992	if (!PyArg_ParseTuple(args, "s|i:mkfifo", &filename, &mode))
4993		return NULL;
4994	Py_BEGIN_ALLOW_THREADS
4995	res = mkfifo(filename, mode);
4996	Py_END_ALLOW_THREADS
4997	if (res < 0)
4998		return posix_error();
4999	Py_INCREF(Py_None);
5000	return Py_None;
5001}
5002#endif
5003
5004
5005#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
5006PyDoc_STRVAR(posix_mknod__doc__,
5007"mknod(filename [, mode=0600, device])\n\n\
5008Create a filesystem node (file, device special file or named pipe)\n\
5009named filename. mode specifies both the permissions to use and the\n\
5010type of node to be created, being combined (bitwise OR) with one of\n\
5011S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
5012device defines the newly created device special file (probably using\n\
5013os.makedev()), otherwise it is ignored.");
5014
5015
5016static PyObject *
5017posix_mknod(PyObject *self, PyObject *args)
5018{
5019	char *filename;
5020	int mode = 0600;
5021	int device = 0;
5022	int res;
5023	if (!PyArg_ParseTuple(args, "s|ii:mknod", &filename, &mode, &device))
5024		return NULL;
5025	Py_BEGIN_ALLOW_THREADS
5026	res = mknod(filename, mode, device);
5027	Py_END_ALLOW_THREADS
5028	if (res < 0)
5029		return posix_error();
5030	Py_INCREF(Py_None);
5031	return Py_None;
5032}
5033#endif
5034
5035#ifdef HAVE_DEVICE_MACROS
5036PyDoc_STRVAR(posix_major__doc__,
5037"major(device) -> major number\n\
5038Extracts a device major number from a raw device number.");
5039
5040static PyObject *
5041posix_major(PyObject *self, PyObject *args)
5042{
5043	int device;
5044	if (!PyArg_ParseTuple(args, "i:major", &device))
5045		return NULL;
5046	return PyLong_FromLong((long)major(device));
5047}
5048
5049PyDoc_STRVAR(posix_minor__doc__,
5050"minor(device) -> minor number\n\
5051Extracts a device minor number from a raw device number.");
5052
5053static PyObject *
5054posix_minor(PyObject *self, PyObject *args)
5055{
5056	int device;
5057	if (!PyArg_ParseTuple(args, "i:minor", &device))
5058		return NULL;
5059	return PyLong_FromLong((long)minor(device));
5060}
5061
5062PyDoc_STRVAR(posix_makedev__doc__,
5063"makedev(major, minor) -> device number\n\
5064Composes a raw device number from the major and minor device numbers.");
5065
5066static PyObject *
5067posix_makedev(PyObject *self, PyObject *args)
5068{
5069	int major, minor;
5070	if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
5071		return NULL;
5072	return PyLong_FromLong((long)makedev(major, minor));
5073}
5074#endif /* device macros */
5075
5076
5077#ifdef HAVE_FTRUNCATE
5078PyDoc_STRVAR(posix_ftruncate__doc__,
5079"ftruncate(fd, length)\n\n\
5080Truncate a file to a specified length.");
5081
5082static PyObject *
5083posix_ftruncate(PyObject *self, PyObject *args)
5084{
5085	int fd;
5086	off_t length;
5087	int res;
5088	PyObject *lenobj;
5089
5090	if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj))
5091		return NULL;
5092
5093#if !defined(HAVE_LARGEFILE_SUPPORT)
5094	length = PyLong_AsLong(lenobj);
5095#else
5096	length = PyLong_Check(lenobj) ?
5097		PyLong_AsLongLong(lenobj) : PyLong_AsLong(lenobj);
5098#endif
5099	if (PyErr_Occurred())
5100		return NULL;
5101
5102	Py_BEGIN_ALLOW_THREADS
5103	res = ftruncate(fd, length);
5104	Py_END_ALLOW_THREADS
5105	if (res < 0) {
5106		PyErr_SetFromErrno(PyExc_IOError);
5107		return NULL;
5108	}
5109	Py_INCREF(Py_None);
5110	return Py_None;
5111}
5112#endif
5113
5114#ifdef HAVE_PUTENV
5115PyDoc_STRVAR(posix_putenv__doc__,
5116"putenv(key, value)\n\n\
5117Change or add an environment variable.");
5118
5119/* Save putenv() parameters as values here, so we can collect them when they
5120 * get re-set with another call for the same key. */
5121static PyObject *posix_putenv_garbage;
5122
5123static PyObject *
5124posix_putenv(PyObject *self, PyObject *args)
5125{
5126#ifdef MS_WINDOWS
5127        wchar_t *s1, *s2;
5128        wchar_t *newenv;
5129#else
5130        char *s1, *s2;
5131        char *newenv;
5132#endif
5133	PyObject *newstr;
5134	size_t len;
5135
5136	if (!PyArg_ParseTuple(args,
5137#ifdef MS_WINDOWS
5138			      "uu:putenv",
5139#else
5140			      "ss:putenv",
5141#endif
5142			      &s1, &s2))
5143		return NULL;
5144
5145#if defined(PYOS_OS2)
5146    if (stricmp(s1, "BEGINLIBPATH") == 0) {
5147        APIRET rc;
5148
5149        rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH);
5150        if (rc != NO_ERROR)
5151            return os2_error(rc);
5152
5153    } else if (stricmp(s1, "ENDLIBPATH") == 0) {
5154        APIRET rc;
5155
5156        rc = DosSetExtLIBPATH(s2, END_LIBPATH);
5157        if (rc != NO_ERROR)
5158            return os2_error(rc);
5159    } else {
5160#endif
5161	/* XXX This can leak memory -- not easy to fix :-( */
5162	/* len includes space for a trailing \0; the size arg to
5163	   PyString_FromStringAndSize does not count that */
5164#ifdef MS_WINDOWS
5165	len = wcslen(s1) + wcslen(s2) + 2;
5166	newstr = PyUnicode_FromUnicode(NULL, (int)len - 1);
5167#else
5168	len = strlen(s1) + strlen(s2) + 2;
5169	newstr = PyString_FromStringAndSize(NULL, (int)len - 1);
5170#endif
5171	if (newstr == NULL)
5172		return PyErr_NoMemory();
5173#ifdef MS_WINDOWS
5174	newenv = PyUnicode_AsUnicode(newstr);
5175	_snwprintf(newenv, len, L"%s=%s", s1, s2);
5176	if (_wputenv(newenv)) {
5177                Py_DECREF(newstr);
5178                posix_error();
5179                return NULL;
5180	}
5181#else
5182	newenv = PyString_AS_STRING(newstr);
5183	PyOS_snprintf(newenv, len, "%s=%s", s1, s2);
5184	if (putenv(newenv)) {
5185                Py_DECREF(newstr);
5186                posix_error();
5187                return NULL;
5188	}
5189#endif
5190	/* Install the first arg and newstr in posix_putenv_garbage;
5191	 * this will cause previous value to be collected.  This has to
5192	 * happen after the real putenv() call because the old value
5193	 * was still accessible until then. */
5194	if (PyDict_SetItem(posix_putenv_garbage,
5195			   PyTuple_GET_ITEM(args, 0), newstr)) {
5196		/* really not much we can do; just leak */
5197		PyErr_Clear();
5198	}
5199	else {
5200		Py_DECREF(newstr);
5201	}
5202
5203#if defined(PYOS_OS2)
5204    }
5205#endif
5206	Py_INCREF(Py_None);
5207        return Py_None;
5208}
5209#endif /* putenv */
5210
5211#ifdef HAVE_UNSETENV
5212PyDoc_STRVAR(posix_unsetenv__doc__,
5213"unsetenv(key)\n\n\
5214Delete an environment variable.");
5215
5216static PyObject *
5217posix_unsetenv(PyObject *self, PyObject *args)
5218{
5219        char *s1;
5220
5221	if (!PyArg_ParseTuple(args, "s:unsetenv", &s1))
5222		return NULL;
5223
5224	unsetenv(s1);
5225
5226	/* Remove the key from posix_putenv_garbage;
5227	 * this will cause it to be collected.  This has to
5228	 * happen after the real unsetenv() call because the
5229	 * old value was still accessible until then.
5230	 */
5231	if (PyDict_DelItem(posix_putenv_garbage,
5232		PyTuple_GET_ITEM(args, 0))) {
5233		/* really not much we can do; just leak */
5234		PyErr_Clear();
5235	}
5236
5237	Py_INCREF(Py_None);
5238	return Py_None;
5239}
5240#endif /* unsetenv */
5241
5242PyDoc_STRVAR(posix_strerror__doc__,
5243"strerror(code) -> string\n\n\
5244Translate an error code to a message string.");
5245
5246static PyObject *
5247posix_strerror(PyObject *self, PyObject *args)
5248{
5249	int code;
5250	char *message;
5251	if (!PyArg_ParseTuple(args, "i:strerror", &code))
5252		return NULL;
5253	message = strerror(code);
5254	if (message == NULL) {
5255		PyErr_SetString(PyExc_ValueError,
5256				"strerror() argument out of range");
5257		return NULL;
5258	}
5259	return PyUnicode_FromString(message);
5260}
5261
5262
5263#ifdef HAVE_SYS_WAIT_H
5264
5265#ifdef WCOREDUMP
5266PyDoc_STRVAR(posix_WCOREDUMP__doc__,
5267"WCOREDUMP(status) -> bool\n\n\
5268Return True if the process returning 'status' was dumped to a core file.");
5269
5270static PyObject *
5271posix_WCOREDUMP(PyObject *self, PyObject *args)
5272{
5273	WAIT_TYPE status;
5274	WAIT_STATUS_INT(status) = 0;
5275
5276	if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
5277		return NULL;
5278
5279	return PyBool_FromLong(WCOREDUMP(status));
5280}
5281#endif /* WCOREDUMP */
5282
5283#ifdef WIFCONTINUED
5284PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
5285"WIFCONTINUED(status) -> bool\n\n\
5286Return True if the process returning 'status' was continued from a\n\
5287job control stop.");
5288
5289static PyObject *
5290posix_WIFCONTINUED(PyObject *self, PyObject *args)
5291{
5292	WAIT_TYPE status;
5293	WAIT_STATUS_INT(status) = 0;
5294
5295	if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
5296		return NULL;
5297
5298	return PyBool_FromLong(WIFCONTINUED(status));
5299}
5300#endif /* WIFCONTINUED */
5301
5302#ifdef WIFSTOPPED
5303PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
5304"WIFSTOPPED(status) -> bool\n\n\
5305Return True if the process returning 'status' was stopped.");
5306
5307static PyObject *
5308posix_WIFSTOPPED(PyObject *self, PyObject *args)
5309{
5310	WAIT_TYPE status;
5311	WAIT_STATUS_INT(status) = 0;
5312
5313	if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
5314		return NULL;
5315
5316	return PyBool_FromLong(WIFSTOPPED(status));
5317}
5318#endif /* WIFSTOPPED */
5319
5320#ifdef WIFSIGNALED
5321PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
5322"WIFSIGNALED(status) -> bool\n\n\
5323Return True if the process returning 'status' was terminated by a signal.");
5324
5325static PyObject *
5326posix_WIFSIGNALED(PyObject *self, PyObject *args)
5327{
5328	WAIT_TYPE status;
5329	WAIT_STATUS_INT(status) = 0;
5330
5331	if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
5332		return NULL;
5333
5334	return PyBool_FromLong(WIFSIGNALED(status));
5335}
5336#endif /* WIFSIGNALED */
5337
5338#ifdef WIFEXITED
5339PyDoc_STRVAR(posix_WIFEXITED__doc__,
5340"WIFEXITED(status) -> bool\n\n\
5341Return true if the process returning 'status' exited using the exit()\n\
5342system call.");
5343
5344static PyObject *
5345posix_WIFEXITED(PyObject *self, PyObject *args)
5346{
5347	WAIT_TYPE status;
5348	WAIT_STATUS_INT(status) = 0;
5349
5350	if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
5351		return NULL;
5352
5353	return PyBool_FromLong(WIFEXITED(status));
5354}
5355#endif /* WIFEXITED */
5356
5357#ifdef WEXITSTATUS
5358PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
5359"WEXITSTATUS(status) -> integer\n\n\
5360Return the process return code from 'status'.");
5361
5362static PyObject *
5363posix_WEXITSTATUS(PyObject *self, PyObject *args)
5364{
5365	WAIT_TYPE status;
5366	WAIT_STATUS_INT(status) = 0;
5367
5368	if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
5369		return NULL;
5370
5371	return Py_BuildValue("i", WEXITSTATUS(status));
5372}
5373#endif /* WEXITSTATUS */
5374
5375#ifdef WTERMSIG
5376PyDoc_STRVAR(posix_WTERMSIG__doc__,
5377"WTERMSIG(status) -> integer\n\n\
5378Return the signal that terminated the process that provided the 'status'\n\
5379value.");
5380
5381static PyObject *
5382posix_WTERMSIG(PyObject *self, PyObject *args)
5383{
5384	WAIT_TYPE status;
5385	WAIT_STATUS_INT(status) = 0;
5386
5387	if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
5388		return NULL;
5389
5390	return Py_BuildValue("i", WTERMSIG(status));
5391}
5392#endif /* WTERMSIG */
5393
5394#ifdef WSTOPSIG
5395PyDoc_STRVAR(posix_WSTOPSIG__doc__,
5396"WSTOPSIG(status) -> integer\n\n\
5397Return the signal that stopped the process that provided\n\
5398the 'status' value.");
5399
5400static PyObject *
5401posix_WSTOPSIG(PyObject *self, PyObject *args)
5402{
5403	WAIT_TYPE status;
5404	WAIT_STATUS_INT(status) = 0;
5405
5406	if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
5407		return NULL;
5408
5409	return Py_BuildValue("i", WSTOPSIG(status));
5410}
5411#endif /* WSTOPSIG */
5412
5413#endif /* HAVE_SYS_WAIT_H */
5414
5415
5416#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
5417#ifdef _SCO_DS
5418/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
5419   needed definitions in sys/statvfs.h */
5420#define _SVID3
5421#endif
5422#include <sys/statvfs.h>
5423
5424static PyObject*
5425_pystatvfs_fromstructstatvfs(struct statvfs st) {
5426        PyObject *v = PyStructSequence_New(&StatVFSResultType);
5427	if (v == NULL)
5428		return NULL;
5429
5430#if !defined(HAVE_LARGEFILE_SUPPORT)
5431        PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
5432        PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
5433        PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
5434        PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
5435        PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
5436        PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
5437        PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
5438        PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
5439        PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
5440        PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
5441#else
5442        PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
5443        PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
5444        PyStructSequence_SET_ITEM(v, 2,
5445			       PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
5446        PyStructSequence_SET_ITEM(v, 3,
5447			       PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
5448        PyStructSequence_SET_ITEM(v, 4,
5449			       PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
5450        PyStructSequence_SET_ITEM(v, 5,
5451			       PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
5452        PyStructSequence_SET_ITEM(v, 6,
5453			       PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
5454        PyStructSequence_SET_ITEM(v, 7,
5455			       PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
5456        PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
5457        PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
5458#endif
5459
5460        return v;
5461}
5462
5463PyDoc_STRVAR(posix_fstatvfs__doc__,
5464"fstatvfs(fd) -> statvfs result\n\n\
5465Perform an fstatvfs system call on the given fd.");
5466
5467static PyObject *
5468posix_fstatvfs(PyObject *self, PyObject *args)
5469{
5470	int fd, res;
5471	struct statvfs st;
5472
5473	if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
5474		return NULL;
5475	Py_BEGIN_ALLOW_THREADS
5476	res = fstatvfs(fd, &st);
5477	Py_END_ALLOW_THREADS
5478	if (res != 0)
5479		return posix_error();
5480
5481        return _pystatvfs_fromstructstatvfs(st);
5482}
5483#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
5484
5485
5486#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
5487#include <sys/statvfs.h>
5488
5489PyDoc_STRVAR(posix_statvfs__doc__,
5490"statvfs(path) -> statvfs result\n\n\
5491Perform a statvfs system call on the given path.");
5492
5493static PyObject *
5494posix_statvfs(PyObject *self, PyObject *args)
5495{
5496	char *path;
5497	int res;
5498	struct statvfs st;
5499	if (!PyArg_ParseTuple(args, "s:statvfs", &path))
5500		return NULL;
5501	Py_BEGIN_ALLOW_THREADS
5502	res = statvfs(path, &st);
5503	Py_END_ALLOW_THREADS
5504	if (res != 0)
5505		return posix_error_with_filename(path);
5506
5507        return _pystatvfs_fromstructstatvfs(st);
5508}
5509#endif /* HAVE_STATVFS */
5510
5511/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
5512 * It maps strings representing configuration variable names to
5513 * integer values, allowing those functions to be called with the
5514 * magic names instead of polluting the module's namespace with tons of
5515 * rarely-used constants.  There are three separate tables that use
5516 * these definitions.
5517 *
5518 * This code is always included, even if none of the interfaces that
5519 * need it are included.  The #if hackery needed to avoid it would be
5520 * sufficiently pervasive that it's not worth the loss of readability.
5521 */
5522struct constdef {
5523    char *name;
5524    long value;
5525};
5526
5527static int
5528conv_confname(PyObject *arg, int *valuep, struct constdef *table,
5529              size_t tablesize)
5530{
5531    if (PyLong_Check(arg)) {
5532        *valuep = PyLong_AS_LONG(arg);
5533        return 1;
5534    }
5535    else {
5536        /* look up the value in the table using a binary search */
5537        size_t lo = 0;
5538        size_t mid;
5539        size_t hi = tablesize;
5540        int cmp;
5541        const char *confname;
5542        if (!PyUnicode_Check(arg)) {
5543            PyErr_SetString(PyExc_TypeError,
5544                            "configuration names must be strings or integers");
5545            return 0;
5546        }
5547        confname = PyUnicode_AsString(arg);
5548        if (confname == NULL)
5549            return 0;
5550        while (lo < hi) {
5551            mid = (lo + hi) / 2;
5552            cmp = strcmp(confname, table[mid].name);
5553            if (cmp < 0)
5554                hi = mid;
5555            else if (cmp > 0)
5556                lo = mid + 1;
5557            else {
5558                *valuep = table[mid].value;
5559                return 1;
5560            }
5561        }
5562        PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
5563        return 0;
5564    }
5565}
5566
5567
5568#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
5569static struct constdef  posix_constants_pathconf[] = {
5570#ifdef _PC_ABI_AIO_XFER_MAX
5571    {"PC_ABI_AIO_XFER_MAX",	_PC_ABI_AIO_XFER_MAX},
5572#endif
5573#ifdef _PC_ABI_ASYNC_IO
5574    {"PC_ABI_ASYNC_IO",	_PC_ABI_ASYNC_IO},
5575#endif
5576#ifdef _PC_ASYNC_IO
5577    {"PC_ASYNC_IO",	_PC_ASYNC_IO},
5578#endif
5579#ifdef _PC_CHOWN_RESTRICTED
5580    {"PC_CHOWN_RESTRICTED",	_PC_CHOWN_RESTRICTED},
5581#endif
5582#ifdef _PC_FILESIZEBITS
5583    {"PC_FILESIZEBITS",	_PC_FILESIZEBITS},
5584#endif
5585#ifdef _PC_LAST
5586    {"PC_LAST",	_PC_LAST},
5587#endif
5588#ifdef _PC_LINK_MAX
5589    {"PC_LINK_MAX",	_PC_LINK_MAX},
5590#endif
5591#ifdef _PC_MAX_CANON
5592    {"PC_MAX_CANON",	_PC_MAX_CANON},
5593#endif
5594#ifdef _PC_MAX_INPUT
5595    {"PC_MAX_INPUT",	_PC_MAX_INPUT},
5596#endif
5597#ifdef _PC_NAME_MAX
5598    {"PC_NAME_MAX",	_PC_NAME_MAX},
5599#endif
5600#ifdef _PC_NO_TRUNC
5601    {"PC_NO_TRUNC",	_PC_NO_TRUNC},
5602#endif
5603#ifdef _PC_PATH_MAX
5604    {"PC_PATH_MAX",	_PC_PATH_MAX},
5605#endif
5606#ifdef _PC_PIPE_BUF
5607    {"PC_PIPE_BUF",	_PC_PIPE_BUF},
5608#endif
5609#ifdef _PC_PRIO_IO
5610    {"PC_PRIO_IO",	_PC_PRIO_IO},
5611#endif
5612#ifdef _PC_SOCK_MAXBUF
5613    {"PC_SOCK_MAXBUF",	_PC_SOCK_MAXBUF},
5614#endif
5615#ifdef _PC_SYNC_IO
5616    {"PC_SYNC_IO",	_PC_SYNC_IO},
5617#endif
5618#ifdef _PC_VDISABLE
5619    {"PC_VDISABLE",	_PC_VDISABLE},
5620#endif
5621};
5622
5623static int
5624conv_path_confname(PyObject *arg, int *valuep)
5625{
5626    return conv_confname(arg, valuep, posix_constants_pathconf,
5627                         sizeof(posix_constants_pathconf)
5628                           / sizeof(struct constdef));
5629}
5630#endif
5631
5632#ifdef HAVE_FPATHCONF
5633PyDoc_STRVAR(posix_fpathconf__doc__,
5634"fpathconf(fd, name) -> integer\n\n\
5635Return the configuration limit name for the file descriptor fd.\n\
5636If there is no limit, return -1.");
5637
5638static PyObject *
5639posix_fpathconf(PyObject *self, PyObject *args)
5640{
5641    PyObject *result = NULL;
5642    int name, fd;
5643
5644    if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
5645                         conv_path_confname, &name)) {
5646        long limit;
5647
5648        errno = 0;
5649        limit = fpathconf(fd, name);
5650        if (limit == -1 && errno != 0)
5651            posix_error();
5652        else
5653            result = PyLong_FromLong(limit);
5654    }
5655    return result;
5656}
5657#endif
5658
5659
5660#ifdef HAVE_PATHCONF
5661PyDoc_STRVAR(posix_pathconf__doc__,
5662"pathconf(path, name) -> integer\n\n\
5663Return the configuration limit name for the file or directory path.\n\
5664If there is no limit, return -1.");
5665
5666static PyObject *
5667posix_pathconf(PyObject *self, PyObject *args)
5668{
5669    PyObject *result = NULL;
5670    int name;
5671    char *path;
5672
5673    if (PyArg_ParseTuple(args, "sO&:pathconf", &path,
5674                         conv_path_confname, &name)) {
5675        long limit;
5676
5677        errno = 0;
5678        limit = pathconf(path, name);
5679        if (limit == -1 && errno != 0) {
5680            if (errno == EINVAL)
5681                /* could be a path or name problem */
5682                posix_error();
5683            else
5684                posix_error_with_filename(path);
5685        }
5686        else
5687            result = PyLong_FromLong(limit);
5688    }
5689    return result;
5690}
5691#endif
5692
5693#ifdef HAVE_CONFSTR
5694static struct constdef posix_constants_confstr[] = {
5695#ifdef _CS_ARCHITECTURE
5696    {"CS_ARCHITECTURE",	_CS_ARCHITECTURE},
5697#endif
5698#ifdef _CS_HOSTNAME
5699    {"CS_HOSTNAME",	_CS_HOSTNAME},
5700#endif
5701#ifdef _CS_HW_PROVIDER
5702    {"CS_HW_PROVIDER",	_CS_HW_PROVIDER},
5703#endif
5704#ifdef _CS_HW_SERIAL
5705    {"CS_HW_SERIAL",	_CS_HW_SERIAL},
5706#endif
5707#ifdef _CS_INITTAB_NAME
5708    {"CS_INITTAB_NAME",	_CS_INITTAB_NAME},
5709#endif
5710#ifdef _CS_LFS64_CFLAGS
5711    {"CS_LFS64_CFLAGS",	_CS_LFS64_CFLAGS},
5712#endif
5713#ifdef _CS_LFS64_LDFLAGS
5714    {"CS_LFS64_LDFLAGS",	_CS_LFS64_LDFLAGS},
5715#endif
5716#ifdef _CS_LFS64_LIBS
5717    {"CS_LFS64_LIBS",	_CS_LFS64_LIBS},
5718#endif
5719#ifdef _CS_LFS64_LINTFLAGS
5720    {"CS_LFS64_LINTFLAGS",	_CS_LFS64_LINTFLAGS},
5721#endif
5722#ifdef _CS_LFS_CFLAGS
5723    {"CS_LFS_CFLAGS",	_CS_LFS_CFLAGS},
5724#endif
5725#ifdef _CS_LFS_LDFLAGS
5726    {"CS_LFS_LDFLAGS",	_CS_LFS_LDFLAGS},
5727#endif
5728#ifdef _CS_LFS_LIBS
5729    {"CS_LFS_LIBS",	_CS_LFS_LIBS},
5730#endif
5731#ifdef _CS_LFS_LINTFLAGS
5732    {"CS_LFS_LINTFLAGS",	_CS_LFS_LINTFLAGS},
5733#endif
5734#ifdef _CS_MACHINE
5735    {"CS_MACHINE",	_CS_MACHINE},
5736#endif
5737#ifdef _CS_PATH
5738    {"CS_PATH",	_CS_PATH},
5739#endif
5740#ifdef _CS_RELEASE
5741    {"CS_RELEASE",	_CS_RELEASE},
5742#endif
5743#ifdef _CS_SRPC_DOMAIN
5744    {"CS_SRPC_DOMAIN",	_CS_SRPC_DOMAIN},
5745#endif
5746#ifdef _CS_SYSNAME
5747    {"CS_SYSNAME",	_CS_SYSNAME},
5748#endif
5749#ifdef _CS_VERSION
5750    {"CS_VERSION",	_CS_VERSION},
5751#endif
5752#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
5753    {"CS_XBS5_ILP32_OFF32_CFLAGS",	_CS_XBS5_ILP32_OFF32_CFLAGS},
5754#endif
5755#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
5756    {"CS_XBS5_ILP32_OFF32_LDFLAGS",	_CS_XBS5_ILP32_OFF32_LDFLAGS},
5757#endif
5758#ifdef _CS_XBS5_ILP32_OFF32_LIBS
5759    {"CS_XBS5_ILP32_OFF32_LIBS",	_CS_XBS5_ILP32_OFF32_LIBS},
5760#endif
5761#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
5762    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",	_CS_XBS5_ILP32_OFF32_LINTFLAGS},
5763#endif
5764#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
5765    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",	_CS_XBS5_ILP32_OFFBIG_CFLAGS},
5766#endif
5767#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
5768    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",	_CS_XBS5_ILP32_OFFBIG_LDFLAGS},
5769#endif
5770#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
5771    {"CS_XBS5_ILP32_OFFBIG_LIBS",	_CS_XBS5_ILP32_OFFBIG_LIBS},
5772#endif
5773#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
5774    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",	_CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
5775#endif
5776#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
5777    {"CS_XBS5_LP64_OFF64_CFLAGS",	_CS_XBS5_LP64_OFF64_CFLAGS},
5778#endif
5779#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
5780    {"CS_XBS5_LP64_OFF64_LDFLAGS",	_CS_XBS5_LP64_OFF64_LDFLAGS},
5781#endif
5782#ifdef _CS_XBS5_LP64_OFF64_LIBS
5783    {"CS_XBS5_LP64_OFF64_LIBS",	_CS_XBS5_LP64_OFF64_LIBS},
5784#endif
5785#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
5786    {"CS_XBS5_LP64_OFF64_LINTFLAGS",	_CS_XBS5_LP64_OFF64_LINTFLAGS},
5787#endif
5788#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
5789    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",	_CS_XBS5_LPBIG_OFFBIG_CFLAGS},
5790#endif
5791#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
5792    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",	_CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
5793#endif
5794#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
5795    {"CS_XBS5_LPBIG_OFFBIG_LIBS",	_CS_XBS5_LPBIG_OFFBIG_LIBS},
5796#endif
5797#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
5798    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",	_CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
5799#endif
5800#ifdef _MIPS_CS_AVAIL_PROCESSORS
5801    {"MIPS_CS_AVAIL_PROCESSORS",	_MIPS_CS_AVAIL_PROCESSORS},
5802#endif
5803#ifdef _MIPS_CS_BASE
5804    {"MIPS_CS_BASE",	_MIPS_CS_BASE},
5805#endif
5806#ifdef _MIPS_CS_HOSTID
5807    {"MIPS_CS_HOSTID",	_MIPS_CS_HOSTID},
5808#endif
5809#ifdef _MIPS_CS_HW_NAME
5810    {"MIPS_CS_HW_NAME",	_MIPS_CS_HW_NAME},
5811#endif
5812#ifdef _MIPS_CS_NUM_PROCESSORS
5813    {"MIPS_CS_NUM_PROCESSORS",	_MIPS_CS_NUM_PROCESSORS},
5814#endif
5815#ifdef _MIPS_CS_OSREL_MAJ
5816    {"MIPS_CS_OSREL_MAJ",	_MIPS_CS_OSREL_MAJ},
5817#endif
5818#ifdef _MIPS_CS_OSREL_MIN
5819    {"MIPS_CS_OSREL_MIN",	_MIPS_CS_OSREL_MIN},
5820#endif
5821#ifdef _MIPS_CS_OSREL_PATCH
5822    {"MIPS_CS_OSREL_PATCH",	_MIPS_CS_OSREL_PATCH},
5823#endif
5824#ifdef _MIPS_CS_OS_NAME
5825    {"MIPS_CS_OS_NAME",	_MIPS_CS_OS_NAME},
5826#endif
5827#ifdef _MIPS_CS_OS_PROVIDER
5828    {"MIPS_CS_OS_PROVIDER",	_MIPS_CS_OS_PROVIDER},
5829#endif
5830#ifdef _MIPS_CS_PROCESSORS
5831    {"MIPS_CS_PROCESSORS",	_MIPS_CS_PROCESSORS},
5832#endif
5833#ifdef _MIPS_CS_SERIAL
5834    {"MIPS_CS_SERIAL",	_MIPS_CS_SERIAL},
5835#endif
5836#ifdef _MIPS_CS_VENDOR
5837    {"MIPS_CS_VENDOR",	_MIPS_CS_VENDOR},
5838#endif
5839};
5840
5841static int
5842conv_confstr_confname(PyObject *arg, int *valuep)
5843{
5844    return conv_confname(arg, valuep, posix_constants_confstr,
5845                         sizeof(posix_constants_confstr)
5846                           / sizeof(struct constdef));
5847}
5848
5849PyDoc_STRVAR(posix_confstr__doc__,
5850"confstr(name) -> string\n\n\
5851Return a string-valued system configuration variable.");
5852
5853static PyObject *
5854posix_confstr(PyObject *self, PyObject *args)
5855{
5856    PyObject *result = NULL;
5857    int name;
5858    char buffer[256];
5859
5860    if (PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) {
5861	int len;
5862
5863        errno = 0;
5864	len = confstr(name, buffer, sizeof(buffer));
5865	if (len == 0) {
5866	    if (errno) {
5867		posix_error();
5868	    }
5869	    else {
5870		result = Py_None;
5871		Py_INCREF(Py_None);
5872	    }
5873        }
5874        else {
5875	    if ((unsigned int)len >= sizeof(buffer)) {
5876                result = PyUnicode_FromStringAndSize(NULL, len-1);
5877                if (result != NULL)
5878                    confstr(name, PyUnicode_AsString(result), len);
5879            }
5880            else
5881                result = PyUnicode_FromStringAndSize(buffer, len-1);
5882        }
5883    }
5884    return result;
5885}
5886#endif
5887
5888
5889#ifdef HAVE_SYSCONF
5890static struct constdef posix_constants_sysconf[] = {
5891#ifdef _SC_2_CHAR_TERM
5892    {"SC_2_CHAR_TERM",	_SC_2_CHAR_TERM},
5893#endif
5894#ifdef _SC_2_C_BIND
5895    {"SC_2_C_BIND",	_SC_2_C_BIND},
5896#endif
5897#ifdef _SC_2_C_DEV
5898    {"SC_2_C_DEV",	_SC_2_C_DEV},
5899#endif
5900#ifdef _SC_2_C_VERSION
5901    {"SC_2_C_VERSION",	_SC_2_C_VERSION},
5902#endif
5903#ifdef _SC_2_FORT_DEV
5904    {"SC_2_FORT_DEV",	_SC_2_FORT_DEV},
5905#endif
5906#ifdef _SC_2_FORT_RUN
5907    {"SC_2_FORT_RUN",	_SC_2_FORT_RUN},
5908#endif
5909#ifdef _SC_2_LOCALEDEF
5910    {"SC_2_LOCALEDEF",	_SC_2_LOCALEDEF},
5911#endif
5912#ifdef _SC_2_SW_DEV
5913    {"SC_2_SW_DEV",	_SC_2_SW_DEV},
5914#endif
5915#ifdef _SC_2_UPE
5916    {"SC_2_UPE",	_SC_2_UPE},
5917#endif
5918#ifdef _SC_2_VERSION
5919    {"SC_2_VERSION",	_SC_2_VERSION},
5920#endif
5921#ifdef _SC_ABI_ASYNCHRONOUS_IO
5922    {"SC_ABI_ASYNCHRONOUS_IO",	_SC_ABI_ASYNCHRONOUS_IO},
5923#endif
5924#ifdef _SC_ACL
5925    {"SC_ACL",	_SC_ACL},
5926#endif
5927#ifdef _SC_AIO_LISTIO_MAX
5928    {"SC_AIO_LISTIO_MAX",	_SC_AIO_LISTIO_MAX},
5929#endif
5930#ifdef _SC_AIO_MAX
5931    {"SC_AIO_MAX",	_SC_AIO_MAX},
5932#endif
5933#ifdef _SC_AIO_PRIO_DELTA_MAX
5934    {"SC_AIO_PRIO_DELTA_MAX",	_SC_AIO_PRIO_DELTA_MAX},
5935#endif
5936#ifdef _SC_ARG_MAX
5937    {"SC_ARG_MAX",	_SC_ARG_MAX},
5938#endif
5939#ifdef _SC_ASYNCHRONOUS_IO
5940    {"SC_ASYNCHRONOUS_IO",	_SC_ASYNCHRONOUS_IO},
5941#endif
5942#ifdef _SC_ATEXIT_MAX
5943    {"SC_ATEXIT_MAX",	_SC_ATEXIT_MAX},
5944#endif
5945#ifdef _SC_AUDIT
5946    {"SC_AUDIT",	_SC_AUDIT},
5947#endif
5948#ifdef _SC_AVPHYS_PAGES
5949    {"SC_AVPHYS_PAGES",	_SC_AVPHYS_PAGES},
5950#endif
5951#ifdef _SC_BC_BASE_MAX
5952    {"SC_BC_BASE_MAX",	_SC_BC_BASE_MAX},
5953#endif
5954#ifdef _SC_BC_DIM_MAX
5955    {"SC_BC_DIM_MAX",	_SC_BC_DIM_MAX},
5956#endif
5957#ifdef _SC_BC_SCALE_MAX
5958    {"SC_BC_SCALE_MAX",	_SC_BC_SCALE_MAX},
5959#endif
5960#ifdef _SC_BC_STRING_MAX
5961    {"SC_BC_STRING_MAX",	_SC_BC_STRING_MAX},
5962#endif
5963#ifdef _SC_CAP
5964    {"SC_CAP",	_SC_CAP},
5965#endif
5966#ifdef _SC_CHARCLASS_NAME_MAX
5967    {"SC_CHARCLASS_NAME_MAX",	_SC_CHARCLASS_NAME_MAX},
5968#endif
5969#ifdef _SC_CHAR_BIT
5970    {"SC_CHAR_BIT",	_SC_CHAR_BIT},
5971#endif
5972#ifdef _SC_CHAR_MAX
5973    {"SC_CHAR_MAX",	_SC_CHAR_MAX},
5974#endif
5975#ifdef _SC_CHAR_MIN
5976    {"SC_CHAR_MIN",	_SC_CHAR_MIN},
5977#endif
5978#ifdef _SC_CHILD_MAX
5979    {"SC_CHILD_MAX",	_SC_CHILD_MAX},
5980#endif
5981#ifdef _SC_CLK_TCK
5982    {"SC_CLK_TCK",	_SC_CLK_TCK},
5983#endif
5984#ifdef _SC_COHER_BLKSZ
5985    {"SC_COHER_BLKSZ",	_SC_COHER_BLKSZ},
5986#endif
5987#ifdef _SC_COLL_WEIGHTS_MAX
5988    {"SC_COLL_WEIGHTS_MAX",	_SC_COLL_WEIGHTS_MAX},
5989#endif
5990#ifdef _SC_DCACHE_ASSOC
5991    {"SC_DCACHE_ASSOC",	_SC_DCACHE_ASSOC},
5992#endif
5993#ifdef _SC_DCACHE_BLKSZ
5994    {"SC_DCACHE_BLKSZ",	_SC_DCACHE_BLKSZ},
5995#endif
5996#ifdef _SC_DCACHE_LINESZ
5997    {"SC_DCACHE_LINESZ",	_SC_DCACHE_LINESZ},
5998#endif
5999#ifdef _SC_DCACHE_SZ
6000    {"SC_DCACHE_SZ",	_SC_DCACHE_SZ},
6001#endif
6002#ifdef _SC_DCACHE_TBLKSZ
6003    {"SC_DCACHE_TBLKSZ",	_SC_DCACHE_TBLKSZ},
6004#endif
6005#ifdef _SC_DELAYTIMER_MAX
6006    {"SC_DELAYTIMER_MAX",	_SC_DELAYTIMER_MAX},
6007#endif
6008#ifdef _SC_EQUIV_CLASS_MAX
6009    {"SC_EQUIV_CLASS_MAX",	_SC_EQUIV_CLASS_MAX},
6010#endif
6011#ifdef _SC_EXPR_NEST_MAX
6012    {"SC_EXPR_NEST_MAX",	_SC_EXPR_NEST_MAX},
6013#endif
6014#ifdef _SC_FSYNC
6015    {"SC_FSYNC",	_SC_FSYNC},
6016#endif
6017#ifdef _SC_GETGR_R_SIZE_MAX
6018    {"SC_GETGR_R_SIZE_MAX",	_SC_GETGR_R_SIZE_MAX},
6019#endif
6020#ifdef _SC_GETPW_R_SIZE_MAX
6021    {"SC_GETPW_R_SIZE_MAX",	_SC_GETPW_R_SIZE_MAX},
6022#endif
6023#ifdef _SC_ICACHE_ASSOC
6024    {"SC_ICACHE_ASSOC",	_SC_ICACHE_ASSOC},
6025#endif
6026#ifdef _SC_ICACHE_BLKSZ
6027    {"SC_ICACHE_BLKSZ",	_SC_ICACHE_BLKSZ},
6028#endif
6029#ifdef _SC_ICACHE_LINESZ
6030    {"SC_ICACHE_LINESZ",	_SC_ICACHE_LINESZ},
6031#endif
6032#ifdef _SC_ICACHE_SZ
6033    {"SC_ICACHE_SZ",	_SC_ICACHE_SZ},
6034#endif
6035#ifdef _SC_INF
6036    {"SC_INF",	_SC_INF},
6037#endif
6038#ifdef _SC_INT_MAX
6039    {"SC_INT_MAX",	_SC_INT_MAX},
6040#endif
6041#ifdef _SC_INT_MIN
6042    {"SC_INT_MIN",	_SC_INT_MIN},
6043#endif
6044#ifdef _SC_IOV_MAX
6045    {"SC_IOV_MAX",	_SC_IOV_MAX},
6046#endif
6047#ifdef _SC_IP_SECOPTS
6048    {"SC_IP_SECOPTS",	_SC_IP_SECOPTS},
6049#endif
6050#ifdef _SC_JOB_CONTROL
6051    {"SC_JOB_CONTROL",	_SC_JOB_CONTROL},
6052#endif
6053#ifdef _SC_KERN_POINTERS
6054    {"SC_KERN_POINTERS",	_SC_KERN_POINTERS},
6055#endif
6056#ifdef _SC_KERN_SIM
6057    {"SC_KERN_SIM",	_SC_KERN_SIM},
6058#endif
6059#ifdef _SC_LINE_MAX
6060    {"SC_LINE_MAX",	_SC_LINE_MAX},
6061#endif
6062#ifdef _SC_LOGIN_NAME_MAX
6063    {"SC_LOGIN_NAME_MAX",	_SC_LOGIN_NAME_MAX},
6064#endif
6065#ifdef _SC_LOGNAME_MAX
6066    {"SC_LOGNAME_MAX",	_SC_LOGNAME_MAX},
6067#endif
6068#ifdef _SC_LONG_BIT
6069    {"SC_LONG_BIT",	_SC_LONG_BIT},
6070#endif
6071#ifdef _SC_MAC
6072    {"SC_MAC",	_SC_MAC},
6073#endif
6074#ifdef _SC_MAPPED_FILES
6075    {"SC_MAPPED_FILES",	_SC_MAPPED_FILES},
6076#endif
6077#ifdef _SC_MAXPID
6078    {"SC_MAXPID",	_SC_MAXPID},
6079#endif
6080#ifdef _SC_MB_LEN_MAX
6081    {"SC_MB_LEN_MAX",	_SC_MB_LEN_MAX},
6082#endif
6083#ifdef _SC_MEMLOCK
6084    {"SC_MEMLOCK",	_SC_MEMLOCK},
6085#endif
6086#ifdef _SC_MEMLOCK_RANGE
6087    {"SC_MEMLOCK_RANGE",	_SC_MEMLOCK_RANGE},
6088#endif
6089#ifdef _SC_MEMORY_PROTECTION
6090    {"SC_MEMORY_PROTECTION",	_SC_MEMORY_PROTECTION},
6091#endif
6092#ifdef _SC_MESSAGE_PASSING
6093    {"SC_MESSAGE_PASSING",	_SC_MESSAGE_PASSING},
6094#endif
6095#ifdef _SC_MMAP_FIXED_ALIGNMENT
6096    {"SC_MMAP_FIXED_ALIGNMENT",	_SC_MMAP_FIXED_ALIGNMENT},
6097#endif
6098#ifdef _SC_MQ_OPEN_MAX
6099    {"SC_MQ_OPEN_MAX",	_SC_MQ_OPEN_MAX},
6100#endif
6101#ifdef _SC_MQ_PRIO_MAX
6102    {"SC_MQ_PRIO_MAX",	_SC_MQ_PRIO_MAX},
6103#endif
6104#ifdef _SC_NACLS_MAX
6105    {"SC_NACLS_MAX",	_SC_NACLS_MAX},
6106#endif
6107#ifdef _SC_NGROUPS_MAX
6108    {"SC_NGROUPS_MAX",	_SC_NGROUPS_MAX},
6109#endif
6110#ifdef _SC_NL_ARGMAX
6111    {"SC_NL_ARGMAX",	_SC_NL_ARGMAX},
6112#endif
6113#ifdef _SC_NL_LANGMAX
6114    {"SC_NL_LANGMAX",	_SC_NL_LANGMAX},
6115#endif
6116#ifdef _SC_NL_MSGMAX
6117    {"SC_NL_MSGMAX",	_SC_NL_MSGMAX},
6118#endif
6119#ifdef _SC_NL_NMAX
6120    {"SC_NL_NMAX",	_SC_NL_NMAX},
6121#endif
6122#ifdef _SC_NL_SETMAX
6123    {"SC_NL_SETMAX",	_SC_NL_SETMAX},
6124#endif
6125#ifdef _SC_NL_TEXTMAX
6126    {"SC_NL_TEXTMAX",	_SC_NL_TEXTMAX},
6127#endif
6128#ifdef _SC_NPROCESSORS_CONF
6129    {"SC_NPROCESSORS_CONF",	_SC_NPROCESSORS_CONF},
6130#endif
6131#ifdef _SC_NPROCESSORS_ONLN
6132    {"SC_NPROCESSORS_ONLN",	_SC_NPROCESSORS_ONLN},
6133#endif
6134#ifdef _SC_NPROC_CONF
6135    {"SC_NPROC_CONF",	_SC_NPROC_CONF},
6136#endif
6137#ifdef _SC_NPROC_ONLN
6138    {"SC_NPROC_ONLN",	_SC_NPROC_ONLN},
6139#endif
6140#ifdef _SC_NZERO
6141    {"SC_NZERO",	_SC_NZERO},
6142#endif
6143#ifdef _SC_OPEN_MAX
6144    {"SC_OPEN_MAX",	_SC_OPEN_MAX},
6145#endif
6146#ifdef _SC_PAGESIZE
6147    {"SC_PAGESIZE",	_SC_PAGESIZE},
6148#endif
6149#ifdef _SC_PAGE_SIZE
6150    {"SC_PAGE_SIZE",	_SC_PAGE_SIZE},
6151#endif
6152#ifdef _SC_PASS_MAX
6153    {"SC_PASS_MAX",	_SC_PASS_MAX},
6154#endif
6155#ifdef _SC_PHYS_PAGES
6156    {"SC_PHYS_PAGES",	_SC_PHYS_PAGES},
6157#endif
6158#ifdef _SC_PII
6159    {"SC_PII",	_SC_PII},
6160#endif
6161#ifdef _SC_PII_INTERNET
6162    {"SC_PII_INTERNET",	_SC_PII_INTERNET},
6163#endif
6164#ifdef _SC_PII_INTERNET_DGRAM
6165    {"SC_PII_INTERNET_DGRAM",	_SC_PII_INTERNET_DGRAM},
6166#endif
6167#ifdef _SC_PII_INTERNET_STREAM
6168    {"SC_PII_INTERNET_STREAM",	_SC_PII_INTERNET_STREAM},
6169#endif
6170#ifdef _SC_PII_OSI
6171    {"SC_PII_OSI",	_SC_PII_OSI},
6172#endif
6173#ifdef _SC_PII_OSI_CLTS
6174    {"SC_PII_OSI_CLTS",	_SC_PII_OSI_CLTS},
6175#endif
6176#ifdef _SC_PII_OSI_COTS
6177    {"SC_PII_OSI_COTS",	_SC_PII_OSI_COTS},
6178#endif
6179#ifdef _SC_PII_OSI_M
6180    {"SC_PII_OSI_M",	_SC_PII_OSI_M},
6181#endif
6182#ifdef _SC_PII_SOCKET
6183    {"SC_PII_SOCKET",	_SC_PII_SOCKET},
6184#endif
6185#ifdef _SC_PII_XTI
6186    {"SC_PII_XTI",	_SC_PII_XTI},
6187#endif
6188#ifdef _SC_POLL
6189    {"SC_POLL",	_SC_POLL},
6190#endif
6191#ifdef _SC_PRIORITIZED_IO
6192    {"SC_PRIORITIZED_IO",	_SC_PRIORITIZED_IO},
6193#endif
6194#ifdef _SC_PRIORITY_SCHEDULING
6195    {"SC_PRIORITY_SCHEDULING",	_SC_PRIORITY_SCHEDULING},
6196#endif
6197#ifdef _SC_REALTIME_SIGNALS
6198    {"SC_REALTIME_SIGNALS",	_SC_REALTIME_SIGNALS},
6199#endif
6200#ifdef _SC_RE_DUP_MAX
6201    {"SC_RE_DUP_MAX",	_SC_RE_DUP_MAX},
6202#endif
6203#ifdef _SC_RTSIG_MAX
6204    {"SC_RTSIG_MAX",	_SC_RTSIG_MAX},
6205#endif
6206#ifdef _SC_SAVED_IDS
6207    {"SC_SAVED_IDS",	_SC_SAVED_IDS},
6208#endif
6209#ifdef _SC_SCHAR_MAX
6210    {"SC_SCHAR_MAX",	_SC_SCHAR_MAX},
6211#endif
6212#ifdef _SC_SCHAR_MIN
6213    {"SC_SCHAR_MIN",	_SC_SCHAR_MIN},
6214#endif
6215#ifdef _SC_SELECT
6216    {"SC_SELECT",	_SC_SELECT},
6217#endif
6218#ifdef _SC_SEMAPHORES
6219    {"SC_SEMAPHORES",	_SC_SEMAPHORES},
6220#endif
6221#ifdef _SC_SEM_NSEMS_MAX
6222    {"SC_SEM_NSEMS_MAX",	_SC_SEM_NSEMS_MAX},
6223#endif
6224#ifdef _SC_SEM_VALUE_MAX
6225    {"SC_SEM_VALUE_MAX",	_SC_SEM_VALUE_MAX},
6226#endif
6227#ifdef _SC_SHARED_MEMORY_OBJECTS
6228    {"SC_SHARED_MEMORY_OBJECTS",	_SC_SHARED_MEMORY_OBJECTS},
6229#endif
6230#ifdef _SC_SHRT_MAX
6231    {"SC_SHRT_MAX",	_SC_SHRT_MAX},
6232#endif
6233#ifdef _SC_SHRT_MIN
6234    {"SC_SHRT_MIN",	_SC_SHRT_MIN},
6235#endif
6236#ifdef _SC_SIGQUEUE_MAX
6237    {"SC_SIGQUEUE_MAX",	_SC_SIGQUEUE_MAX},
6238#endif
6239#ifdef _SC_SIGRT_MAX
6240    {"SC_SIGRT_MAX",	_SC_SIGRT_MAX},
6241#endif
6242#ifdef _SC_SIGRT_MIN
6243    {"SC_SIGRT_MIN",	_SC_SIGRT_MIN},
6244#endif
6245#ifdef _SC_SOFTPOWER
6246    {"SC_SOFTPOWER",	_SC_SOFTPOWER},
6247#endif
6248#ifdef _SC_SPLIT_CACHE
6249    {"SC_SPLIT_CACHE",	_SC_SPLIT_CACHE},
6250#endif
6251#ifdef _SC_SSIZE_MAX
6252    {"SC_SSIZE_MAX",	_SC_SSIZE_MAX},
6253#endif
6254#ifdef _SC_STACK_PROT
6255    {"SC_STACK_PROT",	_SC_STACK_PROT},
6256#endif
6257#ifdef _SC_STREAM_MAX
6258    {"SC_STREAM_MAX",	_SC_STREAM_MAX},
6259#endif
6260#ifdef _SC_SYNCHRONIZED_IO
6261    {"SC_SYNCHRONIZED_IO",	_SC_SYNCHRONIZED_IO},
6262#endif
6263#ifdef _SC_THREADS
6264    {"SC_THREADS",	_SC_THREADS},
6265#endif
6266#ifdef _SC_THREAD_ATTR_STACKADDR
6267    {"SC_THREAD_ATTR_STACKADDR",	_SC_THREAD_ATTR_STACKADDR},
6268#endif
6269#ifdef _SC_THREAD_ATTR_STACKSIZE
6270    {"SC_THREAD_ATTR_STACKSIZE",	_SC_THREAD_ATTR_STACKSIZE},
6271#endif
6272#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
6273    {"SC_THREAD_DESTRUCTOR_ITERATIONS",	_SC_THREAD_DESTRUCTOR_ITERATIONS},
6274#endif
6275#ifdef _SC_THREAD_KEYS_MAX
6276    {"SC_THREAD_KEYS_MAX",	_SC_THREAD_KEYS_MAX},
6277#endif
6278#ifdef _SC_THREAD_PRIORITY_SCHEDULING
6279    {"SC_THREAD_PRIORITY_SCHEDULING",	_SC_THREAD_PRIORITY_SCHEDULING},
6280#endif
6281#ifdef _SC_THREAD_PRIO_INHERIT
6282    {"SC_THREAD_PRIO_INHERIT",	_SC_THREAD_PRIO_INHERIT},
6283#endif
6284#ifdef _SC_THREAD_PRIO_PROTECT
6285    {"SC_THREAD_PRIO_PROTECT",	_SC_THREAD_PRIO_PROTECT},
6286#endif
6287#ifdef _SC_THREAD_PROCESS_SHARED
6288    {"SC_THREAD_PROCESS_SHARED",	_SC_THREAD_PROCESS_SHARED},
6289#endif
6290#ifdef _SC_THREAD_SAFE_FUNCTIONS
6291    {"SC_THREAD_SAFE_FUNCTIONS",	_SC_THREAD_SAFE_FUNCTIONS},
6292#endif
6293#ifdef _SC_THREAD_STACK_MIN
6294    {"SC_THREAD_STACK_MIN",	_SC_THREAD_STACK_MIN},
6295#endif
6296#ifdef _SC_THREAD_THREADS_MAX
6297    {"SC_THREAD_THREADS_MAX",	_SC_THREAD_THREADS_MAX},
6298#endif
6299#ifdef _SC_TIMERS
6300    {"SC_TIMERS",	_SC_TIMERS},
6301#endif
6302#ifdef _SC_TIMER_MAX
6303    {"SC_TIMER_MAX",	_SC_TIMER_MAX},
6304#endif
6305#ifdef _SC_TTY_NAME_MAX
6306    {"SC_TTY_NAME_MAX",	_SC_TTY_NAME_MAX},
6307#endif
6308#ifdef _SC_TZNAME_MAX
6309    {"SC_TZNAME_MAX",	_SC_TZNAME_MAX},
6310#endif
6311#ifdef _SC_T_IOV_MAX
6312    {"SC_T_IOV_MAX",	_SC_T_IOV_MAX},
6313#endif
6314#ifdef _SC_UCHAR_MAX
6315    {"SC_UCHAR_MAX",	_SC_UCHAR_MAX},
6316#endif
6317#ifdef _SC_UINT_MAX
6318    {"SC_UINT_MAX",	_SC_UINT_MAX},
6319#endif
6320#ifdef _SC_UIO_MAXIOV
6321    {"SC_UIO_MAXIOV",	_SC_UIO_MAXIOV},
6322#endif
6323#ifdef _SC_ULONG_MAX
6324    {"SC_ULONG_MAX",	_SC_ULONG_MAX},
6325#endif
6326#ifdef _SC_USHRT_MAX
6327    {"SC_USHRT_MAX",	_SC_USHRT_MAX},
6328#endif
6329#ifdef _SC_VERSION
6330    {"SC_VERSION",	_SC_VERSION},
6331#endif
6332#ifdef _SC_WORD_BIT
6333    {"SC_WORD_BIT",	_SC_WORD_BIT},
6334#endif
6335#ifdef _SC_XBS5_ILP32_OFF32
6336    {"SC_XBS5_ILP32_OFF32",	_SC_XBS5_ILP32_OFF32},
6337#endif
6338#ifdef _SC_XBS5_ILP32_OFFBIG
6339    {"SC_XBS5_ILP32_OFFBIG",	_SC_XBS5_ILP32_OFFBIG},
6340#endif
6341#ifdef _SC_XBS5_LP64_OFF64
6342    {"SC_XBS5_LP64_OFF64",	_SC_XBS5_LP64_OFF64},
6343#endif
6344#ifdef _SC_XBS5_LPBIG_OFFBIG
6345    {"SC_XBS5_LPBIG_OFFBIG",	_SC_XBS5_LPBIG_OFFBIG},
6346#endif
6347#ifdef _SC_XOPEN_CRYPT
6348    {"SC_XOPEN_CRYPT",	_SC_XOPEN_CRYPT},
6349#endif
6350#ifdef _SC_XOPEN_ENH_I18N
6351    {"SC_XOPEN_ENH_I18N",	_SC_XOPEN_ENH_I18N},
6352#endif
6353#ifdef _SC_XOPEN_LEGACY
6354    {"SC_XOPEN_LEGACY",	_SC_XOPEN_LEGACY},
6355#endif
6356#ifdef _SC_XOPEN_REALTIME
6357    {"SC_XOPEN_REALTIME",	_SC_XOPEN_REALTIME},
6358#endif
6359#ifdef _SC_XOPEN_REALTIME_THREADS
6360    {"SC_XOPEN_REALTIME_THREADS",	_SC_XOPEN_REALTIME_THREADS},
6361#endif
6362#ifdef _SC_XOPEN_SHM
6363    {"SC_XOPEN_SHM",	_SC_XOPEN_SHM},
6364#endif
6365#ifdef _SC_XOPEN_UNIX
6366    {"SC_XOPEN_UNIX",	_SC_XOPEN_UNIX},
6367#endif
6368#ifdef _SC_XOPEN_VERSION
6369    {"SC_XOPEN_VERSION",	_SC_XOPEN_VERSION},
6370#endif
6371#ifdef _SC_XOPEN_XCU_VERSION
6372    {"SC_XOPEN_XCU_VERSION",	_SC_XOPEN_XCU_VERSION},
6373#endif
6374#ifdef _SC_XOPEN_XPG2
6375    {"SC_XOPEN_XPG2",	_SC_XOPEN_XPG2},
6376#endif
6377#ifdef _SC_XOPEN_XPG3
6378    {"SC_XOPEN_XPG3",	_SC_XOPEN_XPG3},
6379#endif
6380#ifdef _SC_XOPEN_XPG4
6381    {"SC_XOPEN_XPG4",	_SC_XOPEN_XPG4},
6382#endif
6383};
6384
6385static int
6386conv_sysconf_confname(PyObject *arg, int *valuep)
6387{
6388    return conv_confname(arg, valuep, posix_constants_sysconf,
6389                         sizeof(posix_constants_sysconf)
6390                           / sizeof(struct constdef));
6391}
6392
6393PyDoc_STRVAR(posix_sysconf__doc__,
6394"sysconf(name) -> integer\n\n\
6395Return an integer-valued system configuration variable.");
6396
6397static PyObject *
6398posix_sysconf(PyObject *self, PyObject *args)
6399{
6400    PyObject *result = NULL;
6401    int name;
6402
6403    if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
6404        int value;
6405
6406        errno = 0;
6407        value = sysconf(name);
6408        if (value == -1 && errno != 0)
6409            posix_error();
6410        else
6411            result = PyLong_FromLong(value);
6412    }
6413    return result;
6414}
6415#endif
6416
6417
6418/* This code is used to ensure that the tables of configuration value names
6419 * are in sorted order as required by conv_confname(), and also to build the
6420 * the exported dictionaries that are used to publish information about the
6421 * names available on the host platform.
6422 *
6423 * Sorting the table at runtime ensures that the table is properly ordered
6424 * when used, even for platforms we're not able to test on.  It also makes
6425 * it easier to add additional entries to the tables.
6426 */
6427
6428static int
6429cmp_constdefs(const void *v1,  const void *v2)
6430{
6431    const struct constdef *c1 =
6432        (const struct constdef *) v1;
6433    const struct constdef *c2 =
6434        (const struct constdef *) v2;
6435
6436    return strcmp(c1->name, c2->name);
6437}
6438
6439static int
6440setup_confname_table(struct constdef *table, size_t tablesize,
6441		     char *tablename, PyObject *module)
6442{
6443    PyObject *d = NULL;
6444    size_t i;
6445
6446    qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
6447    d = PyDict_New();
6448    if (d == NULL)
6449	    return -1;
6450
6451    for (i=0; i < tablesize; ++i) {
6452            PyObject *o = PyLong_FromLong(table[i].value);
6453            if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
6454		    Py_XDECREF(o);
6455		    Py_DECREF(d);
6456		    return -1;
6457            }
6458	    Py_DECREF(o);
6459    }
6460    return PyModule_AddObject(module, tablename, d);
6461}
6462
6463/* Return -1 on failure, 0 on success. */
6464static int
6465setup_confname_tables(PyObject *module)
6466{
6467#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
6468    if (setup_confname_table(posix_constants_pathconf,
6469                             sizeof(posix_constants_pathconf)
6470                               / sizeof(struct constdef),
6471                             "pathconf_names", module))
6472        return -1;
6473#endif
6474#ifdef HAVE_CONFSTR
6475    if (setup_confname_table(posix_constants_confstr,
6476                             sizeof(posix_constants_confstr)
6477                               / sizeof(struct constdef),
6478                             "confstr_names", module))
6479        return -1;
6480#endif
6481#ifdef HAVE_SYSCONF
6482    if (setup_confname_table(posix_constants_sysconf,
6483                             sizeof(posix_constants_sysconf)
6484                               / sizeof(struct constdef),
6485                             "sysconf_names", module))
6486        return -1;
6487#endif
6488    return 0;
6489}
6490
6491
6492PyDoc_STRVAR(posix_abort__doc__,
6493"abort() -> does not return!\n\n\
6494Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
6495in the hardest way possible on the hosting operating system.");
6496
6497static PyObject *
6498posix_abort(PyObject *self, PyObject *noargs)
6499{
6500    abort();
6501    /*NOTREACHED*/
6502    Py_FatalError("abort() called from Python code didn't abort!");
6503    return NULL;
6504}
6505
6506#ifdef MS_WINDOWS
6507PyDoc_STRVAR(win32_startfile__doc__,
6508"startfile(filepath [, operation]) - Start a file with its associated\n\
6509application.\n\
6510\n\
6511When \"operation\" is not specified or \"open\", this acts like\n\
6512double-clicking the file in Explorer, or giving the file name as an\n\
6513argument to the DOS \"start\" command: the file is opened with whatever\n\
6514application (if any) its extension is associated.\n\
6515When another \"operation\" is given, it specifies what should be done with\n\
6516the file.  A typical operation is \"print\".\n\
6517\n\
6518startfile returns as soon as the associated application is launched.\n\
6519There is no option to wait for the application to close, and no way\n\
6520to retrieve the application's exit status.\n\
6521\n\
6522The filepath is relative to the current directory.  If you want to use\n\
6523an absolute path, make sure the first character is not a slash (\"/\");\n\
6524the underlying Win32 ShellExecute function doesn't work if it is.");
6525
6526static PyObject *
6527win32_startfile(PyObject *self, PyObject *args)
6528{
6529	char *filepath;
6530	char *operation = NULL;
6531	HINSTANCE rc;
6532#ifdef Py_WIN_WIDE_FILENAMES
6533	if (unicode_file_names()) {
6534		PyObject *unipath, *woperation = NULL;
6535		if (!PyArg_ParseTuple(args, "U|s:startfile",
6536				      &unipath, &operation)) {
6537			PyErr_Clear();
6538			goto normal;
6539		}
6540
6541
6542		if (operation) {
6543		    woperation = PyUnicode_DecodeASCII(operation,
6544						       strlen(operation), NULL);
6545		    if (!woperation) {
6546			    PyErr_Clear();
6547			    operation = NULL;
6548			    goto normal;
6549		    }
6550		}
6551
6552		Py_BEGIN_ALLOW_THREADS
6553		rc = ShellExecuteW((HWND)0, woperation ? PyUnicode_AS_UNICODE(woperation) : 0,
6554			PyUnicode_AS_UNICODE(unipath),
6555			NULL, NULL, SW_SHOWNORMAL);
6556		Py_END_ALLOW_THREADS
6557
6558		Py_XDECREF(woperation);
6559		if (rc <= (HINSTANCE)32) {
6560			PyObject *errval = win32_error_unicode("startfile",
6561						PyUnicode_AS_UNICODE(unipath));
6562			return errval;
6563		}
6564		Py_INCREF(Py_None);
6565		return Py_None;
6566	}
6567#endif
6568
6569normal:
6570	if (!PyArg_ParseTuple(args, "et|s:startfile",
6571			      Py_FileSystemDefaultEncoding, &filepath,
6572			      &operation))
6573		return NULL;
6574	Py_BEGIN_ALLOW_THREADS
6575	rc = ShellExecute((HWND)0, operation, filepath,
6576			  NULL, NULL, SW_SHOWNORMAL);
6577	Py_END_ALLOW_THREADS
6578	if (rc <= (HINSTANCE)32) {
6579		PyObject *errval = win32_error("startfile", filepath);
6580		PyMem_Free(filepath);
6581		return errval;
6582	}
6583	PyMem_Free(filepath);
6584	Py_INCREF(Py_None);
6585	return Py_None;
6586}
6587#endif
6588
6589#ifdef HAVE_GETLOADAVG
6590PyDoc_STRVAR(posix_getloadavg__doc__,
6591"getloadavg() -> (float, float, float)\n\n\
6592Return the number of processes in the system run queue averaged over\n\
6593the last 1, 5, and 15 minutes or raises OSError if the load average\n\
6594was unobtainable");
6595
6596static PyObject *
6597posix_getloadavg(PyObject *self, PyObject *noargs)
6598{
6599    double loadavg[3];
6600    if (getloadavg(loadavg, 3)!=3) {
6601        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
6602        return NULL;
6603    } else
6604        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
6605}
6606#endif
6607
6608#ifdef MS_WINDOWS
6609
6610PyDoc_STRVAR(win32_urandom__doc__,
6611"urandom(n) -> str\n\n\
6612Return n random bytes suitable for cryptographic use.");
6613
6614typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv,\
6615              LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType,\
6616              DWORD dwFlags );
6617typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,\
6618              BYTE *pbBuffer );
6619
6620static CRYPTGENRANDOM pCryptGenRandom = NULL;
6621/* This handle is never explicitly released. Instead, the operating
6622   system will release it when the process terminates. */
6623static HCRYPTPROV hCryptProv = 0;
6624
6625static PyObject*
6626win32_urandom(PyObject *self, PyObject *args)
6627{
6628	int howMany;
6629	PyObject* result;
6630
6631	/* Read arguments */
6632	if (! PyArg_ParseTuple(args, "i:urandom", &howMany))
6633		return NULL;
6634	if (howMany < 0)
6635		return PyErr_Format(PyExc_ValueError,
6636				    "negative argument not allowed");
6637
6638	if (hCryptProv == 0) {
6639		HINSTANCE hAdvAPI32 = NULL;
6640		CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL;
6641
6642		/* Obtain handle to the DLL containing CryptoAPI
6643		   This should not fail	*/
6644		hAdvAPI32 = GetModuleHandle("advapi32.dll");
6645		if(hAdvAPI32 == NULL)
6646			return win32_error("GetModuleHandle", NULL);
6647
6648		/* Obtain pointers to the CryptoAPI functions
6649		   This will fail on some early versions of Win95 */
6650		pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress(
6651						hAdvAPI32,
6652						"CryptAcquireContextA");
6653		if (pCryptAcquireContext == NULL)
6654			return PyErr_Format(PyExc_NotImplementedError,
6655					    "CryptAcquireContextA not found");
6656
6657		pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(
6658						hAdvAPI32, "CryptGenRandom");
6659		if (pCryptGenRandom == NULL)
6660			return PyErr_Format(PyExc_NotImplementedError,
6661					    "CryptGenRandom not found");
6662
6663		/* Acquire context */
6664		if (! pCryptAcquireContext(&hCryptProv, NULL, NULL,
6665					   PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
6666			return win32_error("CryptAcquireContext", NULL);
6667	}
6668
6669	/* Allocate bytes */
6670	result = PyString_FromStringAndSize(NULL, howMany);
6671	if (result != NULL) {
6672		/* Get random data */
6673		if (! pCryptGenRandom(hCryptProv, howMany, (unsigned char*)
6674				      PyString_AS_STRING(result))) {
6675			Py_DECREF(result);
6676			return win32_error("CryptGenRandom", NULL);
6677		}
6678	}
6679	return result;
6680}
6681#endif
6682
6683PyDoc_STRVAR(device_encoding__doc__,
6684"device_encoding(fd) -> str\n\n\
6685Return a string describing the encoding of the device\n\
6686if the output is a terminal; else return None.");
6687
6688static PyObject *
6689device_encoding(PyObject *self, PyObject *args)
6690{
6691	int fd;
6692	if (!PyArg_ParseTuple(args, "i:device_encoding", &fd))
6693		return NULL;
6694	if (!isatty(fd)) {
6695		Py_INCREF(Py_None);
6696		return Py_None;
6697	}
6698#if defined(MS_WINDOWS) || defined(MS_WIN64)
6699	if (fd == 0) {
6700		char buf[100];
6701		sprintf(buf, "cp%d", GetConsoleCP());
6702		return PyUnicode_FromString(buf);
6703	}
6704	if (fd == 1 || fd == 2) {
6705		char buf[100];
6706		sprintf(buf, "cp%d", GetConsoleOutputCP());
6707		return PyUnicode_FromString(buf);
6708	}
6709#elif defined(CODESET)
6710	{
6711		char *codeset = nl_langinfo(CODESET);
6712		if (codeset)
6713			return PyUnicode_FromString(codeset);
6714	}
6715#endif
6716	Py_INCREF(Py_None);
6717	return Py_None;
6718}
6719
6720#ifdef __VMS
6721/* Use openssl random routine */
6722#include <openssl/rand.h>
6723PyDoc_STRVAR(vms_urandom__doc__,
6724"urandom(n) -> str\n\n\
6725Return n random bytes suitable for cryptographic use.");
6726
6727static PyObject*
6728vms_urandom(PyObject *self, PyObject *args)
6729{
6730	int howMany;
6731	PyObject* result;
6732
6733	/* Read arguments */
6734	if (! PyArg_ParseTuple(args, "i:urandom", &howMany))
6735		return NULL;
6736	if (howMany < 0)
6737		return PyErr_Format(PyExc_ValueError,
6738				    "negative argument not allowed");
6739
6740	/* Allocate bytes */
6741	result = PyString_FromStringAndSize(NULL, howMany);
6742	if (result != NULL) {
6743		/* Get random data */
6744		if (RAND_pseudo_bytes((unsigned char*)
6745				      PyString_AS_STRING(result),
6746				      howMany) < 0) {
6747			Py_DECREF(result);
6748			return PyErr_Format(PyExc_ValueError,
6749					    "RAND_pseudo_bytes");
6750		}
6751	}
6752	return result;
6753}
6754#endif
6755
6756static PyMethodDef posix_methods[] = {
6757	{"access",	posix_access, METH_VARARGS, posix_access__doc__},
6758#ifdef HAVE_TTYNAME
6759	{"ttyname",	posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
6760#endif
6761	{"chdir",	posix_chdir, METH_VARARGS, posix_chdir__doc__},
6762#ifdef HAVE_CHFLAGS
6763	{"chflags",	posix_chflags, METH_VARARGS, posix_chflags__doc__},
6764#endif /* HAVE_CHFLAGS */
6765	{"chmod",	posix_chmod, METH_VARARGS, posix_chmod__doc__},
6766#ifdef HAVE_FCHMOD
6767	{"fchmod",	posix_fchmod, METH_VARARGS, posix_fchmod__doc__},
6768#endif /* HAVE_FCHMOD */
6769#ifdef HAVE_CHOWN
6770	{"chown",	posix_chown, METH_VARARGS, posix_chown__doc__},
6771#endif /* HAVE_CHOWN */
6772#ifdef HAVE_LCHMOD
6773	{"lchmod",	posix_lchmod, METH_VARARGS, posix_lchmod__doc__},
6774#endif /* HAVE_LCHMOD */
6775#ifdef HAVE_FCHOWN
6776	{"fchown",	posix_fchown, METH_VARARGS, posix_fchown__doc__},
6777#endif /* HAVE_FCHOWN */
6778#ifdef HAVE_LCHFLAGS
6779	{"lchflags",	posix_lchflags, METH_VARARGS, posix_lchflags__doc__},
6780#endif /* HAVE_LCHFLAGS */
6781#ifdef HAVE_LCHOWN
6782	{"lchown",	posix_lchown, METH_VARARGS, posix_lchown__doc__},
6783#endif /* HAVE_LCHOWN */
6784#ifdef HAVE_CHROOT
6785	{"chroot",	posix_chroot, METH_VARARGS, posix_chroot__doc__},
6786#endif
6787#ifdef HAVE_CTERMID
6788	{"ctermid",	posix_ctermid, METH_NOARGS, posix_ctermid__doc__},
6789#endif
6790#ifdef HAVE_GETCWD
6791	{"getcwd",	posix_getcwd, METH_NOARGS, posix_getcwd__doc__},
6792	{"getcwdu",	posix_getcwdu, METH_NOARGS, posix_getcwdu__doc__},
6793#endif
6794#ifdef HAVE_LINK
6795	{"link",	posix_link, METH_VARARGS, posix_link__doc__},
6796#endif /* HAVE_LINK */
6797	{"listdir",	posix_listdir, METH_VARARGS, posix_listdir__doc__},
6798	{"lstat",	posix_lstat, METH_VARARGS, posix_lstat__doc__},
6799	{"mkdir",	posix_mkdir, METH_VARARGS, posix_mkdir__doc__},
6800#ifdef HAVE_NICE
6801	{"nice",	posix_nice, METH_VARARGS, posix_nice__doc__},
6802#endif /* HAVE_NICE */
6803#ifdef HAVE_READLINK
6804	{"readlink",	posix_readlink, METH_VARARGS, posix_readlink__doc__},
6805#endif /* HAVE_READLINK */
6806	{"rename",	posix_rename, METH_VARARGS, posix_rename__doc__},
6807	{"rmdir",	posix_rmdir, METH_VARARGS, posix_rmdir__doc__},
6808	{"stat",	posix_stat, METH_VARARGS, posix_stat__doc__},
6809	{"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
6810#ifdef HAVE_SYMLINK
6811	{"symlink",	posix_symlink, METH_VARARGS, posix_symlink__doc__},
6812#endif /* HAVE_SYMLINK */
6813#ifdef HAVE_SYSTEM
6814	{"system",	posix_system, METH_VARARGS, posix_system__doc__},
6815#endif
6816	{"umask",	posix_umask, METH_VARARGS, posix_umask__doc__},
6817#ifdef HAVE_UNAME
6818	{"uname",	posix_uname, METH_NOARGS, posix_uname__doc__},
6819#endif /* HAVE_UNAME */
6820	{"unlink",	posix_unlink, METH_VARARGS, posix_unlink__doc__},
6821	{"remove",	posix_unlink, METH_VARARGS, posix_remove__doc__},
6822	{"utime",	posix_utime, METH_VARARGS, posix_utime__doc__},
6823#ifdef HAVE_TIMES
6824	{"times",	posix_times, METH_NOARGS, posix_times__doc__},
6825#endif /* HAVE_TIMES */
6826	{"_exit",	posix__exit, METH_VARARGS, posix__exit__doc__},
6827#ifdef HAVE_EXECV
6828	{"execv",	posix_execv, METH_VARARGS, posix_execv__doc__},
6829	{"execve",	posix_execve, METH_VARARGS, posix_execve__doc__},
6830#endif /* HAVE_EXECV */
6831#ifdef HAVE_SPAWNV
6832	{"spawnv",	posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
6833	{"spawnve",	posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
6834#if defined(PYOS_OS2)
6835	{"spawnvp",	posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__},
6836	{"spawnvpe",	posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__},
6837#endif /* PYOS_OS2 */
6838#endif /* HAVE_SPAWNV */
6839#ifdef HAVE_FORK1
6840	{"fork1",       posix_fork1, METH_NOARGS, posix_fork1__doc__},
6841#endif /* HAVE_FORK1 */
6842#ifdef HAVE_FORK
6843	{"fork",	posix_fork, METH_NOARGS, posix_fork__doc__},
6844#endif /* HAVE_FORK */
6845#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
6846	{"openpty",	posix_openpty, METH_NOARGS, posix_openpty__doc__},
6847#endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
6848#ifdef HAVE_FORKPTY
6849	{"forkpty",	posix_forkpty, METH_NOARGS, posix_forkpty__doc__},
6850#endif /* HAVE_FORKPTY */
6851#ifdef HAVE_GETEGID
6852	{"getegid",	posix_getegid, METH_NOARGS, posix_getegid__doc__},
6853#endif /* HAVE_GETEGID */
6854#ifdef HAVE_GETEUID
6855	{"geteuid",	posix_geteuid, METH_NOARGS, posix_geteuid__doc__},
6856#endif /* HAVE_GETEUID */
6857#ifdef HAVE_GETGID
6858	{"getgid",	posix_getgid, METH_NOARGS, posix_getgid__doc__},
6859#endif /* HAVE_GETGID */
6860#ifdef HAVE_GETGROUPS
6861	{"getgroups",	posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
6862#endif
6863	{"getpid",	posix_getpid, METH_NOARGS, posix_getpid__doc__},
6864#ifdef HAVE_GETPGRP
6865	{"getpgrp",	posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__},
6866#endif /* HAVE_GETPGRP */
6867#ifdef HAVE_GETPPID
6868	{"getppid",	posix_getppid, METH_NOARGS, posix_getppid__doc__},
6869#endif /* HAVE_GETPPID */
6870#ifdef HAVE_GETUID
6871	{"getuid",	posix_getuid, METH_NOARGS, posix_getuid__doc__},
6872#endif /* HAVE_GETUID */
6873#ifdef HAVE_GETLOGIN
6874	{"getlogin",	posix_getlogin, METH_NOARGS, posix_getlogin__doc__},
6875#endif
6876#ifdef HAVE_KILL
6877	{"kill",	posix_kill, METH_VARARGS, posix_kill__doc__},
6878#endif /* HAVE_KILL */
6879#ifdef HAVE_KILLPG
6880	{"killpg",	posix_killpg, METH_VARARGS, posix_killpg__doc__},
6881#endif /* HAVE_KILLPG */
6882#ifdef HAVE_PLOCK
6883	{"plock",	posix_plock, METH_VARARGS, posix_plock__doc__},
6884#endif /* HAVE_PLOCK */
6885#ifdef MS_WINDOWS
6886	{"startfile",	win32_startfile, METH_VARARGS, win32_startfile__doc__},
6887#endif
6888#ifdef HAVE_SETUID
6889	{"setuid",	posix_setuid, METH_VARARGS, posix_setuid__doc__},
6890#endif /* HAVE_SETUID */
6891#ifdef HAVE_SETEUID
6892	{"seteuid",	posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
6893#endif /* HAVE_SETEUID */
6894#ifdef HAVE_SETEGID
6895	{"setegid",	posix_setegid, METH_VARARGS, posix_setegid__doc__},
6896#endif /* HAVE_SETEGID */
6897#ifdef HAVE_SETREUID
6898	{"setreuid",	posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
6899#endif /* HAVE_SETREUID */
6900#ifdef HAVE_SETREGID
6901	{"setregid",	posix_setregid,	METH_VARARGS, posix_setregid__doc__},
6902#endif /* HAVE_SETREGID */
6903#ifdef HAVE_SETGID
6904	{"setgid",	posix_setgid, METH_VARARGS, posix_setgid__doc__},
6905#endif /* HAVE_SETGID */
6906#ifdef HAVE_SETGROUPS
6907	{"setgroups",	posix_setgroups, METH_O, posix_setgroups__doc__},
6908#endif /* HAVE_SETGROUPS */
6909#ifdef HAVE_GETPGID
6910	{"getpgid",	posix_getpgid, METH_VARARGS, posix_getpgid__doc__},
6911#endif /* HAVE_GETPGID */
6912#ifdef HAVE_SETPGRP
6913	{"setpgrp",	posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__},
6914#endif /* HAVE_SETPGRP */
6915#ifdef HAVE_WAIT
6916	{"wait",	posix_wait, METH_NOARGS, posix_wait__doc__},
6917#endif /* HAVE_WAIT */
6918#ifdef HAVE_WAIT3
6919        {"wait3",	posix_wait3, METH_VARARGS, posix_wait3__doc__},
6920#endif /* HAVE_WAIT3 */
6921#ifdef HAVE_WAIT4
6922        {"wait4",	posix_wait4, METH_VARARGS, posix_wait4__doc__},
6923#endif /* HAVE_WAIT4 */
6924#if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
6925	{"waitpid",	posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
6926#endif /* HAVE_WAITPID */
6927#ifdef HAVE_GETSID
6928	{"getsid",	posix_getsid, METH_VARARGS, posix_getsid__doc__},
6929#endif /* HAVE_GETSID */
6930#ifdef HAVE_SETSID
6931	{"setsid",	posix_setsid, METH_NOARGS, posix_setsid__doc__},
6932#endif /* HAVE_SETSID */
6933#ifdef HAVE_SETPGID
6934	{"setpgid",	posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
6935#endif /* HAVE_SETPGID */
6936#ifdef HAVE_TCGETPGRP
6937	{"tcgetpgrp",	posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
6938#endif /* HAVE_TCGETPGRP */
6939#ifdef HAVE_TCSETPGRP
6940	{"tcsetpgrp",	posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
6941#endif /* HAVE_TCSETPGRP */
6942	{"open",	posix_open, METH_VARARGS, posix_open__doc__},
6943	{"close",	posix_close, METH_VARARGS, posix_close__doc__},
6944	{"closerange",	posix_closerange, METH_VARARGS, posix_closerange__doc__},
6945	{"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__},
6946	{"dup",		posix_dup, METH_VARARGS, posix_dup__doc__},
6947	{"dup2",	posix_dup2, METH_VARARGS, posix_dup2__doc__},
6948	{"lseek",	posix_lseek, METH_VARARGS, posix_lseek__doc__},
6949	{"read",	posix_read, METH_VARARGS, posix_read__doc__},
6950	{"write",	posix_write, METH_VARARGS, posix_write__doc__},
6951	{"fstat",	posix_fstat, METH_VARARGS, posix_fstat__doc__},
6952	{"isatty",	posix_isatty, METH_VARARGS, posix_isatty__doc__},
6953#ifdef HAVE_PIPE
6954	{"pipe",	posix_pipe, METH_NOARGS, posix_pipe__doc__},
6955#endif
6956#ifdef HAVE_MKFIFO
6957	{"mkfifo",	posix_mkfifo, METH_VARARGS, posix_mkfifo__doc__},
6958#endif
6959#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
6960	{"mknod",	posix_mknod, METH_VARARGS, posix_mknod__doc__},
6961#endif
6962#ifdef HAVE_DEVICE_MACROS
6963	{"major",	posix_major, METH_VARARGS, posix_major__doc__},
6964	{"minor",	posix_minor, METH_VARARGS, posix_minor__doc__},
6965	{"makedev",	posix_makedev, METH_VARARGS, posix_makedev__doc__},
6966#endif
6967#ifdef HAVE_FTRUNCATE
6968	{"ftruncate",	posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
6969#endif
6970#ifdef HAVE_PUTENV
6971	{"putenv",	posix_putenv, METH_VARARGS, posix_putenv__doc__},
6972#endif
6973#ifdef HAVE_UNSETENV
6974	{"unsetenv",	posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__},
6975#endif
6976	{"strerror",	posix_strerror, METH_VARARGS, posix_strerror__doc__},
6977#ifdef HAVE_FCHDIR
6978	{"fchdir",	posix_fchdir, METH_O, posix_fchdir__doc__},
6979#endif
6980#ifdef HAVE_FSYNC
6981	{"fsync",       posix_fsync, METH_O, posix_fsync__doc__},
6982#endif
6983#ifdef HAVE_FDATASYNC
6984	{"fdatasync",   posix_fdatasync,  METH_O, posix_fdatasync__doc__},
6985#endif
6986#ifdef HAVE_SYS_WAIT_H
6987#ifdef WCOREDUMP
6988        {"WCOREDUMP",	posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__},
6989#endif /* WCOREDUMP */
6990#ifdef WIFCONTINUED
6991        {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__},
6992#endif /* WIFCONTINUED */
6993#ifdef WIFSTOPPED
6994        {"WIFSTOPPED",	posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
6995#endif /* WIFSTOPPED */
6996#ifdef WIFSIGNALED
6997        {"WIFSIGNALED",	posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
6998#endif /* WIFSIGNALED */
6999#ifdef WIFEXITED
7000        {"WIFEXITED",	posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
7001#endif /* WIFEXITED */
7002#ifdef WEXITSTATUS
7003        {"WEXITSTATUS",	posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
7004#endif /* WEXITSTATUS */
7005#ifdef WTERMSIG
7006        {"WTERMSIG",	posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
7007#endif /* WTERMSIG */
7008#ifdef WSTOPSIG
7009        {"WSTOPSIG",	posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
7010#endif /* WSTOPSIG */
7011#endif /* HAVE_SYS_WAIT_H */
7012#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
7013	{"fstatvfs",	posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
7014#endif
7015#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
7016	{"statvfs",	posix_statvfs, METH_VARARGS, posix_statvfs__doc__},
7017#endif
7018#ifdef HAVE_CONFSTR
7019	{"confstr",	posix_confstr, METH_VARARGS, posix_confstr__doc__},
7020#endif
7021#ifdef HAVE_SYSCONF
7022	{"sysconf",	posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
7023#endif
7024#ifdef HAVE_FPATHCONF
7025	{"fpathconf",	posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
7026#endif
7027#ifdef HAVE_PATHCONF
7028	{"pathconf",	posix_pathconf, METH_VARARGS, posix_pathconf__doc__},
7029#endif
7030	{"abort",	posix_abort, METH_NOARGS, posix_abort__doc__},
7031#ifdef MS_WINDOWS
7032	{"_getfullpathname",	posix__getfullpathname, METH_VARARGS, NULL},
7033#endif
7034#ifdef HAVE_GETLOADAVG
7035	{"getloadavg",	posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__},
7036#endif
7037 #ifdef MS_WINDOWS
7038 	{"urandom", win32_urandom, METH_VARARGS, win32_urandom__doc__},
7039 #endif
7040 #ifdef __VMS
7041 	{"urandom", vms_urandom, METH_VARARGS, vms_urandom__doc__},
7042 #endif
7043	{NULL,		NULL}		 /* Sentinel */
7044};
7045
7046
7047static int
7048ins(PyObject *module, char *symbol, long value)
7049{
7050        return PyModule_AddIntConstant(module, symbol, value);
7051}
7052
7053#if defined(PYOS_OS2)
7054/* Insert Platform-Specific Constant Values (Strings & Numbers) of Common Use */
7055static int insertvalues(PyObject *module)
7056{
7057    APIRET    rc;
7058    ULONG     values[QSV_MAX+1];
7059    PyObject *v;
7060    char     *ver, tmp[50];
7061
7062    Py_BEGIN_ALLOW_THREADS
7063    rc = DosQuerySysInfo(1L, QSV_MAX, &values[1], sizeof(ULONG) * QSV_MAX);
7064    Py_END_ALLOW_THREADS
7065
7066    if (rc != NO_ERROR) {
7067        os2_error(rc);
7068        return -1;
7069    }
7070
7071    if (ins(module, "meminstalled", values[QSV_TOTPHYSMEM])) return -1;
7072    if (ins(module, "memkernel",    values[QSV_TOTRESMEM])) return -1;
7073    if (ins(module, "memvirtual",   values[QSV_TOTAVAILMEM])) return -1;
7074    if (ins(module, "maxpathlen",   values[QSV_MAX_PATH_LENGTH])) return -1;
7075    if (ins(module, "maxnamelen",   values[QSV_MAX_COMP_LENGTH])) return -1;
7076    if (ins(module, "revision",     values[QSV_VERSION_REVISION])) return -1;
7077    if (ins(module, "timeslice",    values[QSV_MIN_SLICE])) return -1;
7078
7079    switch (values[QSV_VERSION_MINOR]) {
7080    case 0:  ver = "2.00"; break;
7081    case 10: ver = "2.10"; break;
7082    case 11: ver = "2.11"; break;
7083    case 30: ver = "3.00"; break;
7084    case 40: ver = "4.00"; break;
7085    case 50: ver = "5.00"; break;
7086    default:
7087        PyOS_snprintf(tmp, sizeof(tmp),
7088        	      "%d-%d", values[QSV_VERSION_MAJOR],
7089                      values[QSV_VERSION_MINOR]);
7090        ver = &tmp[0];
7091    }
7092
7093    /* Add Indicator of the Version of the Operating System */
7094    if (PyModule_AddStringConstant(module, "version", tmp) < 0)
7095        return -1;
7096
7097    /* Add Indicator of Which Drive was Used to Boot the System */
7098    tmp[0] = 'A' + values[QSV_BOOT_DRIVE] - 1;
7099    tmp[1] = ':';
7100    tmp[2] = '\0';
7101
7102    return PyModule_AddStringConstant(module, "bootdrive", tmp);
7103}
7104#endif
7105
7106static int
7107all_ins(PyObject *d)
7108{
7109#ifdef F_OK
7110        if (ins(d, "F_OK", (long)F_OK)) return -1;
7111#endif
7112#ifdef R_OK
7113        if (ins(d, "R_OK", (long)R_OK)) return -1;
7114#endif
7115#ifdef W_OK
7116        if (ins(d, "W_OK", (long)W_OK)) return -1;
7117#endif
7118#ifdef X_OK
7119        if (ins(d, "X_OK", (long)X_OK)) return -1;
7120#endif
7121#ifdef NGROUPS_MAX
7122        if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
7123#endif
7124#ifdef TMP_MAX
7125        if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
7126#endif
7127#ifdef WCONTINUED
7128        if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
7129#endif
7130#ifdef WNOHANG
7131        if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
7132#endif
7133#ifdef WUNTRACED
7134        if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
7135#endif
7136#ifdef O_RDONLY
7137        if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
7138#endif
7139#ifdef O_WRONLY
7140        if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
7141#endif
7142#ifdef O_RDWR
7143        if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
7144#endif
7145#ifdef O_NDELAY
7146        if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
7147#endif
7148#ifdef O_NONBLOCK
7149        if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
7150#endif
7151#ifdef O_APPEND
7152        if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
7153#endif
7154#ifdef O_DSYNC
7155        if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
7156#endif
7157#ifdef O_RSYNC
7158        if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
7159#endif
7160#ifdef O_SYNC
7161        if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
7162#endif
7163#ifdef O_NOCTTY
7164        if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
7165#endif
7166#ifdef O_CREAT
7167        if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
7168#endif
7169#ifdef O_EXCL
7170        if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
7171#endif
7172#ifdef O_TRUNC
7173        if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
7174#endif
7175#ifdef O_BINARY
7176        if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
7177#endif
7178#ifdef O_TEXT
7179        if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
7180#endif
7181#ifdef O_LARGEFILE
7182        if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
7183#endif
7184#ifdef O_SHLOCK
7185        if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
7186#endif
7187#ifdef O_EXLOCK
7188        if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
7189#endif
7190
7191/* MS Windows */
7192#ifdef O_NOINHERIT
7193	/* Don't inherit in child processes. */
7194        if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
7195#endif
7196#ifdef _O_SHORT_LIVED
7197	/* Optimize for short life (keep in memory). */
7198	/* MS forgot to define this one with a non-underscore form too. */
7199        if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
7200#endif
7201#ifdef O_TEMPORARY
7202	/* Automatically delete when last handle is closed. */
7203        if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
7204#endif
7205#ifdef O_RANDOM
7206	/* Optimize for random access. */
7207        if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
7208#endif
7209#ifdef O_SEQUENTIAL
7210	/* Optimize for sequential access. */
7211        if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
7212#endif
7213
7214/* GNU extensions. */
7215#ifdef O_ASYNC
7216        /* Send a SIGIO signal whenever input or output
7217           becomes available on file descriptor */
7218        if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1;
7219#endif
7220#ifdef O_DIRECT
7221        /* Direct disk access. */
7222        if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
7223#endif
7224#ifdef O_DIRECTORY
7225        /* Must be a directory.	 */
7226        if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
7227#endif
7228#ifdef O_NOFOLLOW
7229        /* Do not follow links.	 */
7230        if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
7231#endif
7232#ifdef O_NOATIME
7233	/* Do not update the access time. */
7234	if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1;
7235#endif
7236
7237	/* These come from sysexits.h */
7238#ifdef EX_OK
7239	if (ins(d, "EX_OK", (long)EX_OK)) return -1;
7240#endif /* EX_OK */
7241#ifdef EX_USAGE
7242	if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
7243#endif /* EX_USAGE */
7244#ifdef EX_DATAERR
7245	if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
7246#endif /* EX_DATAERR */
7247#ifdef EX_NOINPUT
7248	if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
7249#endif /* EX_NOINPUT */
7250#ifdef EX_NOUSER
7251	if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
7252#endif /* EX_NOUSER */
7253#ifdef EX_NOHOST
7254	if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
7255#endif /* EX_NOHOST */
7256#ifdef EX_UNAVAILABLE
7257	if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
7258#endif /* EX_UNAVAILABLE */
7259#ifdef EX_SOFTWARE
7260	if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
7261#endif /* EX_SOFTWARE */
7262#ifdef EX_OSERR
7263	if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
7264#endif /* EX_OSERR */
7265#ifdef EX_OSFILE
7266	if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
7267#endif /* EX_OSFILE */
7268#ifdef EX_CANTCREAT
7269	if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
7270#endif /* EX_CANTCREAT */
7271#ifdef EX_IOERR
7272	if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
7273#endif /* EX_IOERR */
7274#ifdef EX_TEMPFAIL
7275	if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
7276#endif /* EX_TEMPFAIL */
7277#ifdef EX_PROTOCOL
7278	if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
7279#endif /* EX_PROTOCOL */
7280#ifdef EX_NOPERM
7281	if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
7282#endif /* EX_NOPERM */
7283#ifdef EX_CONFIG
7284	if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
7285#endif /* EX_CONFIG */
7286#ifdef EX_NOTFOUND
7287	if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
7288#endif /* EX_NOTFOUND */
7289
7290#ifdef HAVE_SPAWNV
7291#if defined(PYOS_OS2) && defined(PYCC_GCC)
7292	if (ins(d, "P_WAIT", (long)P_WAIT)) return -1;
7293	if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1;
7294	if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1;
7295	if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1;
7296	if (ins(d, "P_SESSION", (long)P_SESSION)) return -1;
7297	if (ins(d, "P_DETACH", (long)P_DETACH)) return -1;
7298	if (ins(d, "P_PM", (long)P_PM)) return -1;
7299	if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1;
7300	if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1;
7301	if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1;
7302	if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1;
7303	if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1;
7304	if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1;
7305	if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1;
7306	if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1;
7307	if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1;
7308	if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1;
7309	if (ins(d, "P_TILDE", (long)P_TILDE)) return -1;
7310	if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1;
7311	if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1;
7312#else
7313        if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
7314        if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
7315        if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
7316        if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
7317        if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
7318#endif
7319#endif
7320
7321#if defined(PYOS_OS2)
7322        if (insertvalues(d)) return -1;
7323#endif
7324        return 0;
7325}
7326
7327
7328#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__)) && !defined(__QNX__)
7329#define INITFUNC initnt
7330#define MODNAME "nt"
7331
7332#elif defined(PYOS_OS2)
7333#define INITFUNC initos2
7334#define MODNAME "os2"
7335
7336#else
7337#define INITFUNC initposix
7338#define MODNAME "posix"
7339#endif
7340
7341PyMODINIT_FUNC
7342INITFUNC(void)
7343{
7344	PyObject *m, *v;
7345
7346	m = Py_InitModule3(MODNAME,
7347			   posix_methods,
7348			   posix__doc__);
7349	if (m == NULL)
7350    		return;
7351
7352	/* Initialize environ dictionary */
7353	v = convertenviron();
7354	Py_XINCREF(v);
7355	if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
7356		return;
7357	Py_DECREF(v);
7358
7359        if (all_ins(m))
7360                return;
7361
7362        if (setup_confname_tables(m))
7363                return;
7364
7365	Py_INCREF(PyExc_OSError);
7366	PyModule_AddObject(m, "error", PyExc_OSError);
7367
7368#ifdef HAVE_PUTENV
7369	if (posix_putenv_garbage == NULL)
7370		posix_putenv_garbage = PyDict_New();
7371#endif
7372
7373	if (!initialized) {
7374		stat_result_desc.name = MODNAME ".stat_result";
7375		stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
7376		stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
7377		stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
7378		PyStructSequence_InitType(&StatResultType, &stat_result_desc);
7379		structseq_new = StatResultType.tp_new;
7380		StatResultType.tp_new = statresult_new;
7381
7382		statvfs_result_desc.name = MODNAME ".statvfs_result";
7383		PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
7384	}
7385	Py_INCREF((PyObject*) &StatResultType);
7386	PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
7387	Py_INCREF((PyObject*) &StatVFSResultType);
7388	PyModule_AddObject(m, "statvfs_result",
7389			   (PyObject*) &StatVFSResultType);
7390	initialized = 1;
7391
7392#ifdef __APPLE__
7393	/*
7394	 * Step 2 of weak-linking support on Mac OS X.
7395	 *
7396	 * The code below removes functions that are not available on the
7397	 * currently active platform.
7398	 *
7399	 * This block allow one to use a python binary that was build on
7400	 * OSX 10.4 on OSX 10.3, without loosing access to new APIs on
7401	 * OSX 10.4.
7402	 */
7403#ifdef HAVE_FSTATVFS
7404	if (fstatvfs == NULL) {
7405		if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
7406			return;
7407		}
7408	}
7409#endif /* HAVE_FSTATVFS */
7410
7411#ifdef HAVE_STATVFS
7412	if (statvfs == NULL) {
7413		if (PyObject_DelAttrString(m, "statvfs") == -1) {
7414			return;
7415		}
7416	}
7417#endif /* HAVE_STATVFS */
7418
7419# ifdef HAVE_LCHOWN
7420	if (lchown == NULL) {
7421		if (PyObject_DelAttrString(m, "lchown") == -1) {
7422			return;
7423		}
7424	}
7425#endif /* HAVE_LCHOWN */
7426
7427
7428#endif /* __APPLE__ */
7429
7430}
7431
7432#ifdef __cplusplus
7433}
7434#endif
7435