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