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