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