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