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