posixmodule.c revision b37a3734960b0d4c06665e41b0451b6f814f1cb6
1/***********************************************************
2Copyright (c) 2000, BeOpen.com.
3Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5All rights reserved.
6
7See the file "Misc/COPYRIGHT" for information on usage and
8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
9******************************************************************/
10
11/* POSIX module implementation */
12
13/* This file is also used for Windows NT and MS-Win.  In that case the module
14   actually calls itself 'nt', not 'posix', and a few functions are
15   either unimplemented or implemented differently.  The source
16   assumes that for Windows NT, the macro 'MS_WIN32' is defined independent
17   of the compiler used.  Different compilers define their own feature
18   test macro, e.g. '__BORLANDC__' or '_MSC_VER'. */
19
20/* See also ../Dos/dosmodule.c */
21
22static char posix__doc__ [] =
23"This module provides access to operating system functionality that is\n\
24standardized by the C Standard and the POSIX standard (a thinly\n\
25disguised Unix interface).  Refer to the library manual and\n\
26corresponding Unix manual entries for more information on calls.";
27
28#include "Python.h"
29
30#if defined(PYOS_OS2)
31#define  INCL_DOS
32#define  INCL_DOSERRORS
33#define  INCL_DOSPROCESS
34#define  INCL_NOPMAPI
35#include <os2.h>
36#endif
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#ifdef HAVE_SYS_WAIT_H
41#include <sys/wait.h>		/* For WNOHANG */
42#endif
43
44#ifdef HAVE_SIGNAL_H
45#include <signal.h>
46#endif
47
48#ifdef HAVE_FCNTL_H
49#include <fcntl.h>
50#endif /* HAVE_FCNTL_H */
51
52/* Various compilers have only certain posix functions */
53/* XXX Gosh I wish these were all moved into config.h */
54#if defined(PYCC_VACPP) && defined(PYOS_OS2)
55#include <process.h>
56#else
57#if defined(__WATCOMC__) && !defined(__QNX__)		/* Watcom compiler */
58#define HAVE_GETCWD     1
59#define HAVE_OPENDIR    1
60#define HAVE_SYSTEM	1
61#if defined(__OS2__)
62#define HAVE_EXECV      1
63#define HAVE_WAIT       1
64#endif
65#include <process.h>
66#else
67#ifdef __BORLANDC__		/* Borland compiler */
68#define HAVE_EXECV      1
69#define HAVE_GETCWD     1
70#define HAVE_GETEGID    1
71#define HAVE_GETEUID    1
72#define HAVE_GETGID     1
73#define HAVE_GETPPID    1
74#define HAVE_GETUID     1
75#define HAVE_KILL       1
76#define HAVE_OPENDIR    1
77#define HAVE_PIPE       1
78#define HAVE_POPEN      1
79#define HAVE_SYSTEM	1
80#define HAVE_WAIT       1
81#else
82#ifdef _MSC_VER		/* Microsoft compiler */
83#define HAVE_GETCWD     1
84#ifdef MS_WIN32
85#define HAVE_SPAWNV	1
86#define HAVE_EXECV      1
87#define HAVE_PIPE       1
88#define HAVE_POPEN      1
89#define HAVE_SYSTEM	1
90#else /* 16-bit Windows */
91#endif /* !MS_WIN32 */
92#else			/* all other compilers */
93/* Unix functions that the configure script doesn't check for */
94#define HAVE_EXECV      1
95#define HAVE_FORK       1
96#define HAVE_GETCWD     1
97#define HAVE_GETEGID    1
98#define HAVE_GETEUID    1
99#define HAVE_GETGID     1
100#define HAVE_GETPPID    1
101#define HAVE_GETUID     1
102#define HAVE_KILL       1
103#define HAVE_OPENDIR    1
104#define HAVE_PIPE       1
105#define HAVE_POPEN      1
106#define HAVE_SYSTEM	1
107#define HAVE_WAIT       1
108#define HAVE_TTYNAME	1
109#endif  /* _MSC_VER */
110#endif  /* __BORLANDC__ */
111#endif  /* ! __WATCOMC__ || __QNX__ */
112#endif /* ! __IBMC__ */
113
114#ifndef _MSC_VER
115
116#ifdef HAVE_UNISTD_H
117#include <unistd.h>
118#endif
119
120#ifdef NeXT
121/* NeXT's <unistd.h> and <utime.h> aren't worth much */
122#undef HAVE_UNISTD_H
123#undef HAVE_UTIME_H
124#define HAVE_WAITPID
125/* #undef HAVE_GETCWD */
126#define UNION_WAIT /* This should really be checked for by autoconf */
127#endif
128
129#ifndef HAVE_UNISTD_H
130#if defined(PYCC_VACPP)
131extern int mkdir(char *);
132#else
133#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
134extern int mkdir(const char *);
135#else
136extern int mkdir(const char *, mode_t);
137#endif
138#endif
139#if defined(__IBMC__) || defined(__IBMCPP__)
140extern int chdir(char *);
141extern int rmdir(char *);
142#else
143extern int chdir(const char *);
144extern int rmdir(const char *);
145#endif
146extern int chmod(const char *, mode_t);
147extern int chown(const char *, uid_t, gid_t);
148extern char *getcwd(char *, int);
149extern char *strerror(int);
150extern int link(const char *, const char *);
151extern int rename(const char *, const char *);
152extern int stat(const char *, struct stat *);
153extern int unlink(const char *);
154extern int pclose(FILE *);
155#ifdef HAVE_SYMLINK
156extern int symlink(const char *, const char *);
157#endif /* HAVE_SYMLINK */
158#ifdef HAVE_LSTAT
159extern int lstat(const char *, struct stat *);
160#endif /* HAVE_LSTAT */
161#endif /* !HAVE_UNISTD_H */
162
163#endif /* !_MSC_VER */
164
165#ifdef HAVE_UTIME_H
166#include <utime.h>
167#endif /* HAVE_UTIME_H */
168
169#ifdef HAVE_SYS_UTIME_H
170#include <sys/utime.h>
171#define HAVE_UTIME_H /* pretend we do for the rest of this file */
172#endif /* HAVE_SYS_UTIME_H */
173
174#ifdef HAVE_SYS_TIMES_H
175#include <sys/times.h>
176#endif /* HAVE_SYS_TIMES_H */
177
178#ifdef HAVE_SYS_PARAM_H
179#include <sys/param.h>
180#endif /* HAVE_SYS_PARAM_H */
181
182#ifdef HAVE_SYS_UTSNAME_H
183#include <sys/utsname.h>
184#endif /* HAVE_SYS_UTSNAME_H */
185
186#ifndef MAXPATHLEN
187#define MAXPATHLEN 1024
188#endif /* MAXPATHLEN */
189
190#ifdef HAVE_DIRENT_H
191#include <dirent.h>
192#define NAMLEN(dirent) strlen((dirent)->d_name)
193#else
194#if defined(__WATCOMC__) && !defined(__QNX__)
195#include <direct.h>
196#define NAMLEN(dirent) strlen((dirent)->d_name)
197#else
198#define dirent direct
199#define NAMLEN(dirent) (dirent)->d_namlen
200#endif
201#ifdef HAVE_SYS_NDIR_H
202#include <sys/ndir.h>
203#endif
204#ifdef HAVE_SYS_DIR_H
205#include <sys/dir.h>
206#endif
207#ifdef HAVE_NDIR_H
208#include <ndir.h>
209#endif
210#endif
211
212#ifdef _MSC_VER
213#include <direct.h>
214#include <io.h>
215#include <process.h>
216#define WINDOWS_LEAN_AND_MEAN
217#include <windows.h>
218#ifdef MS_WIN32
219#define popen	_popen
220#define pclose	_pclose
221#else /* 16-bit Windows */
222#include <dos.h>
223#include <ctype.h>
224#endif /* MS_WIN32 */
225#endif /* _MSC_VER */
226
227#if defined(PYCC_VACPP) && defined(PYOS_OS2)
228#include <io.h>
229#endif /* OS2 */
230
231#ifdef UNION_WAIT
232/* Emulate some macros on systems that have a union instead of macros */
233
234#ifndef WIFEXITED
235#define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
236#endif
237
238#ifndef WEXITSTATUS
239#define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
240#endif
241
242#ifndef WTERMSIG
243#define WTERMSIG(u_wait) ((u_wait).w_termsig)
244#endif
245
246#endif /* UNION_WAIT */
247
248/* Don't use the "_r" form if we don't need it (also, won't have a
249   prototype for it, at least on Solaris -- maybe others as well?). */
250#if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
251#define USE_CTERMID_R
252#endif
253
254#if defined(HAVE_TMPNAM_R) && defined(WITH_THREAD)
255#define USE_TMPNAM_R
256#endif
257
258/* choose the appropriate stat and fstat functions and return structs */
259#undef STAT
260#ifdef MS_WIN64
261#	define STAT _stati64
262#	define FSTAT _fstati64
263#	define STRUCT_STAT struct _stati64
264#else
265#	define STAT stat
266#	define FSTAT fstat
267#	define STRUCT_STAT struct stat
268#endif
269
270
271/* Return a dictionary corresponding to the POSIX environment table */
272
273#if !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
274extern char **environ;
275#endif /* !_MSC_VER */
276
277static PyObject *
278convertenviron(void)
279{
280	PyObject *d;
281	char **e;
282	d = PyDict_New();
283	if (d == NULL)
284		return NULL;
285	if (environ == NULL)
286		return d;
287	/* This part ignores errors */
288	for (e = environ; *e != NULL; e++) {
289		PyObject *k;
290		PyObject *v;
291		char *p = strchr(*e, '=');
292		if (p == NULL)
293			continue;
294		k = PyString_FromStringAndSize(*e, (int)(p-*e));
295		if (k == NULL) {
296			PyErr_Clear();
297			continue;
298		}
299		v = PyString_FromString(p+1);
300		if (v == NULL) {
301			PyErr_Clear();
302			Py_DECREF(k);
303			continue;
304		}
305		if (PyDict_GetItem(d, k) == NULL) {
306			if (PyDict_SetItem(d, k, v) != 0)
307				PyErr_Clear();
308		}
309		Py_DECREF(k);
310		Py_DECREF(v);
311	}
312#if defined(PYOS_OS2)
313    {
314        APIRET rc;
315        char   buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */
316
317        rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH);
318	if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */
319            PyObject *v = PyString_FromString(buffer);
320		    PyDict_SetItemString(d, "BEGINLIBPATH", v);
321            Py_DECREF(v);
322        }
323        rc = DosQueryExtLIBPATH(buffer, END_LIBPATH);
324        if (rc == NO_ERROR) { /* (not a typo, envname is NOT 'END_LIBPATH') */
325            PyObject *v = PyString_FromString(buffer);
326		    PyDict_SetItemString(d, "ENDLIBPATH", v);
327            Py_DECREF(v);
328        }
329    }
330#endif
331	return d;
332}
333
334
335/* Set a POSIX-specific error from errno, and return NULL */
336
337static PyObject *
338posix_error(void)
339{
340	return PyErr_SetFromErrno(PyExc_OSError);
341}
342static PyObject *
343posix_error_with_filename(char* name)
344{
345	return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
346}
347
348#ifdef MS_WIN32
349static PyObject *
350win32_error(char* function, char* filename)
351{
352	/* XXX this could be improved */
353	errno = GetLastError();
354	if (filename)
355		return PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
356	else
357		return PyErr_SetFromErrno(PyExc_OSError);
358}
359#endif
360
361#if defined(PYOS_OS2)
362/**********************************************************************
363 *         Helper Function to Trim and Format OS/2 Messages
364 **********************************************************************/
365    static void
366os2_formatmsg(char *msgbuf, int msglen, char *reason)
367{
368    msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */
369
370    if (strlen(msgbuf) > 0) { /* If Non-Empty Msg, Trim CRLF */
371        char *lastc = &msgbuf[ strlen(msgbuf)-1 ];
372
373        while (lastc > msgbuf && isspace(*lastc))
374            *lastc-- = '\0'; /* Trim Trailing Whitespace (CRLF) */
375    }
376
377    /* Add Optional Reason Text */
378    if (reason) {
379        strcat(msgbuf, " : ");
380        strcat(msgbuf, reason);
381    }
382}
383
384/**********************************************************************
385 *             Decode an OS/2 Operating System Error Code
386 *
387 * A convenience function to lookup an OS/2 error code and return a
388 * text message we can use to raise a Python exception.
389 *
390 * Notes:
391 *   The messages for errors returned from the OS/2 kernel reside in
392 *   the file OSO001.MSG in the \OS2 directory hierarchy.
393 *
394 **********************************************************************/
395    static char *
396os2_strerror(char *msgbuf, int msgbuflen, int errorcode, char *reason)
397{
398    APIRET rc;
399    ULONG  msglen;
400
401    /* Retrieve Kernel-Related Error Message from OSO001.MSG File */
402    Py_BEGIN_ALLOW_THREADS
403    rc = DosGetMessage(NULL, 0, msgbuf, msgbuflen,
404                       errorcode, "oso001.msg", &msglen);
405    Py_END_ALLOW_THREADS
406
407    if (rc == NO_ERROR)
408        os2_formatmsg(msgbuf, msglen, reason);
409    else
410        sprintf(msgbuf, "unknown OS error #%d", errorcode);
411
412    return msgbuf;
413}
414
415/* Set an OS/2-specific error and return NULL.  OS/2 kernel
416   errors are not in a global variable e.g. 'errno' nor are
417   they congruent with posix error numbers. */
418
419static PyObject * os2_error(int code)
420{
421    char text[1024];
422    PyObject *v;
423
424    os2_strerror(text, sizeof(text), code, "");
425
426    v = Py_BuildValue("(is)", code, text);
427    if (v != NULL) {
428        PyErr_SetObject(PyExc_OSError, v);
429        Py_DECREF(v);
430    }
431    return NULL; /* Signal to Python that an Exception is Pending */
432}
433
434#endif /* OS2 */
435
436/* POSIX generic methods */
437
438static PyObject *
439posix_int(PyObject *args, char *format, int (*func)(int))
440{
441	int fd;
442	int res;
443	if (!PyArg_ParseTuple(args,  format, &fd))
444		return NULL;
445	Py_BEGIN_ALLOW_THREADS
446	res = (*func)(fd);
447	Py_END_ALLOW_THREADS
448	if (res < 0)
449		return posix_error();
450	Py_INCREF(Py_None);
451	return Py_None;
452}
453
454
455static PyObject *
456posix_1str(PyObject *args, char *format, int (*func)(const char*))
457{
458	char *path1;
459	int res;
460	if (!PyArg_ParseTuple(args, format, &path1))
461		return NULL;
462	Py_BEGIN_ALLOW_THREADS
463	res = (*func)(path1);
464	Py_END_ALLOW_THREADS
465	if (res < 0)
466		return posix_error_with_filename(path1);
467	Py_INCREF(Py_None);
468	return Py_None;
469}
470
471static PyObject *
472posix_2str(PyObject *args, char *format,
473	   int (*func)(const char *, const char *))
474{
475	char *path1, *path2;
476	int res;
477	if (!PyArg_ParseTuple(args, format, &path1, &path2))
478		return NULL;
479	Py_BEGIN_ALLOW_THREADS
480	res = (*func)(path1, path2);
481	Py_END_ALLOW_THREADS
482	if (res != 0)
483		/* XXX how to report both path1 and path2??? */
484		return posix_error();
485	Py_INCREF(Py_None);
486	return Py_None;
487}
488
489/* pack a system stat C structure into the Python stat tuple
490   (used by posix_stat() and posix_fstat()) */
491static PyObject*
492_pystat_fromstructstat(STRUCT_STAT st)
493{
494	PyObject *v = PyTuple_New(10);
495	if (v == NULL)
496		return NULL;
497
498	PyTuple_SetItem(v, 0, PyInt_FromLong((long)st.st_mode));
499#ifdef HAVE_LARGEFILE_SUPPORT
500	PyTuple_SetItem(v, 1, PyLong_FromLongLong((LONG_LONG)st.st_ino));
501#else
502	PyTuple_SetItem(v, 1, PyInt_FromLong((long)st.st_ino));
503#endif
504#if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
505	PyTuple_SetItem(v, 2, PyLong_FromLongLong((LONG_LONG)st.st_dev));
506#else
507	PyTuple_SetItem(v, 2, PyInt_FromLong((long)st.st_dev));
508#endif
509	PyTuple_SetItem(v, 3, PyInt_FromLong((long)st.st_nlink));
510	PyTuple_SetItem(v, 4, PyInt_FromLong((long)st.st_uid));
511	PyTuple_SetItem(v, 5, PyInt_FromLong((long)st.st_gid));
512#ifdef HAVE_LARGEFILE_SUPPORT
513	PyTuple_SetItem(v, 6, PyLong_FromLongLong((LONG_LONG)st.st_size));
514#else
515	PyTuple_SetItem(v, 6, PyInt_FromLong(st.st_size));
516#endif
517#if SIZEOF_TIME_T > SIZEOF_LONG
518	PyTuple_SetItem(v, 7, PyLong_FromLongLong((LONG_LONG)st.st_atime));
519	PyTuple_SetItem(v, 8, PyLong_FromLongLong((LONG_LONG)st.st_mtime));
520	PyTuple_SetItem(v, 9, PyLong_FromLongLong((LONG_LONG)st.st_ctime));
521#else
522	PyTuple_SetItem(v, 7, PyInt_FromLong((long)st.st_atime));
523	PyTuple_SetItem(v, 8, PyInt_FromLong((long)st.st_mtime));
524	PyTuple_SetItem(v, 9, PyInt_FromLong((long)st.st_ctime));
525#endif
526
527	if (PyErr_Occurred()) {
528		Py_DECREF(v);
529		return NULL;
530	}
531
532	return v;
533}
534
535
536static PyObject *
537posix_do_stat(PyObject *self, PyObject *args, char *format,
538	      int (*statfunc)(const char *, STRUCT_STAT *))
539{
540	STRUCT_STAT st;
541	char *path;
542	int res;
543
544#ifdef MS_WIN32
545      int pathlen;
546      char pathcopy[MAX_PATH];
547#endif /* MS_WIN32 */
548
549	if (!PyArg_ParseTuple(args, format, &path))
550		return NULL;
551
552#ifdef MS_WIN32
553	pathlen = strlen(path);
554	/* the library call can blow up if the file name is too long! */
555	if (pathlen > MAX_PATH) {
556		errno = ENAMETOOLONG;
557		return posix_error();
558	}
559
560	if ((pathlen > 0) && (path[pathlen-1] == '\\' || path[pathlen-1] == '/')) {
561		/* exception for specific or current drive root */
562		if (!((pathlen == 1) ||
563		      ((pathlen == 3) &&
564		      (path[1] == ':') &&
565		      (path[2] == '\\' || path[2] == '/'))))
566		{
567			strncpy(pathcopy, path, pathlen);
568			pathcopy[pathlen-1] = '\0'; /* nuke the trailing backslash */
569			path = pathcopy;
570		}
571	}
572#endif /* MS_WIN32 */
573
574	Py_BEGIN_ALLOW_THREADS
575	res = (*statfunc)(path, &st);
576	Py_END_ALLOW_THREADS
577	if (res != 0)
578		return posix_error_with_filename(path);
579
580	return _pystat_fromstructstat(st);
581}
582
583
584/* POSIX methods */
585
586static char posix_access__doc__[] =
587"access(path, mode) -> 1 if granted, 0 otherwise\n\
588Test for access to a file.";
589
590static PyObject *
591posix_access(PyObject *self, PyObject *args)
592{
593	char *path;
594	int mode;
595	int res;
596
597	if (!PyArg_ParseTuple(args, "si:access", &path, &mode))
598		return NULL;
599	Py_BEGIN_ALLOW_THREADS
600	res = access(path, mode);
601	Py_END_ALLOW_THREADS
602	return(PyInt_FromLong(res == 0 ? 1L : 0L));
603}
604
605#ifndef F_OK
606#define F_OK 0
607#endif
608#ifndef R_OK
609#define R_OK 4
610#endif
611#ifndef W_OK
612#define W_OK 2
613#endif
614#ifndef X_OK
615#define X_OK 1
616#endif
617
618#ifdef HAVE_TTYNAME
619static char posix_ttyname__doc__[] =
620"ttyname(fd) -> String\n\
621Return the name of the terminal device connected to 'fd'.";
622
623static PyObject *
624posix_ttyname(PyObject *self, PyObject *args)
625{
626	int id;
627	char *ret;
628
629	if (!PyArg_ParseTuple(args, "i:ttyname", &id))
630		return NULL;
631
632	ret = ttyname(id);
633	if (ret == NULL)
634		return(posix_error());
635	return(PyString_FromString(ret));
636}
637#endif
638
639#ifdef HAVE_CTERMID
640static char posix_ctermid__doc__[] =
641"ctermid() -> String\n\
642Return the name of the controlling terminal for this process.";
643
644static PyObject *
645posix_ctermid(PyObject *self, PyObject *args)
646{
647        char *ret;
648        char buffer[L_ctermid];
649
650	if (!PyArg_ParseTuple(args, ":ctermid"))
651		return NULL;
652
653#ifdef USE_CTERMID_R
654	ret = ctermid_r(buffer);
655#else
656        ret = ctermid(buffer);
657#endif
658	if (ret == NULL)
659		return(posix_error());
660	return(PyString_FromString(buffer));
661}
662#endif
663
664static char posix_chdir__doc__[] =
665"chdir(path) -> None\n\
666Change the current working directory to the specified path.";
667
668static PyObject *
669posix_chdir(PyObject *self, PyObject *args)
670{
671	return posix_1str(args, "s:chdir", chdir);
672}
673
674
675static char posix_chmod__doc__[] =
676"chmod(path, mode) -> None\n\
677Change the access permissions of a file.";
678
679static PyObject *
680posix_chmod(PyObject *self, PyObject *args)
681{
682	char *path;
683	int i;
684	int res;
685	if (!PyArg_ParseTuple(args, "si", &path, &i))
686		return NULL;
687	Py_BEGIN_ALLOW_THREADS
688	res = chmod(path, i);
689	Py_END_ALLOW_THREADS
690	if (res < 0)
691		return posix_error_with_filename(path);
692	Py_INCREF(Py_None);
693	return Py_None;
694}
695
696
697#ifdef HAVE_FSYNC
698static char posix_fsync__doc__[] =
699"fsync(fildes) -> None\n\
700force write of file with filedescriptor to disk.";
701
702static PyObject *
703posix_fsync(PyObject *self, PyObject *args)
704{
705       return posix_int(args, "i:fsync", fsync);
706}
707#endif /* HAVE_FSYNC */
708
709#ifdef HAVE_FDATASYNC
710static char posix_fdatasync__doc__[] =
711"fdatasync(fildes) -> None\n\
712force write of file with filedescriptor to disk.\n\
713 does not force update of metadata.";
714
715static PyObject *
716posix_fdatasync(PyObject *self, PyObject *args)
717{
718       return posix_int(args, "i:fdatasync", fdatasync);
719}
720#endif /* HAVE_FDATASYNC */
721
722
723#ifdef HAVE_CHOWN
724static char posix_chown__doc__[] =
725"chown(path, uid, gid) -> None\n\
726Change the owner and group id of path to the numeric uid and gid.";
727
728static PyObject *
729posix_chown(PyObject *self, PyObject *args)
730{
731	char *path;
732	int uid, gid;
733	int res;
734	if (!PyArg_ParseTuple(args, "sii:chown", &path, &uid, &gid))
735		return NULL;
736	Py_BEGIN_ALLOW_THREADS
737	res = chown(path, (uid_t) uid, (gid_t) gid);
738	Py_END_ALLOW_THREADS
739	if (res < 0)
740		return posix_error_with_filename(path);
741	Py_INCREF(Py_None);
742	return Py_None;
743}
744#endif /* HAVE_CHOWN */
745
746
747#ifdef HAVE_GETCWD
748static char posix_getcwd__doc__[] =
749"getcwd() -> path\n\
750Return a string representing the current working directory.";
751
752static PyObject *
753posix_getcwd(PyObject *self, PyObject *args)
754{
755	char buf[1026];
756	char *res;
757	if (!PyArg_ParseTuple(args, ":getcwd"))
758		return NULL;
759	Py_BEGIN_ALLOW_THREADS
760	res = getcwd(buf, sizeof buf);
761	Py_END_ALLOW_THREADS
762	if (res == NULL)
763		return posix_error();
764	return PyString_FromString(buf);
765}
766#endif
767
768
769#ifdef HAVE_LINK
770static char posix_link__doc__[] =
771"link(src, dst) -> None\n\
772Create a hard link to a file.";
773
774static PyObject *
775posix_link(PyObject *self, PyObject *args)
776{
777	return posix_2str(args, "ss:link", link);
778}
779#endif /* HAVE_LINK */
780
781
782static char posix_listdir__doc__[] =
783"listdir(path) -> list_of_strings\n\
784Return a list containing the names of the entries in the directory.\n\
785\n\
786	path: path of directory to list\n\
787\n\
788The list is in arbitrary order.  It does not include the special\n\
789entries '.' and '..' even if they are present in the directory.";
790
791static PyObject *
792posix_listdir(PyObject *self, PyObject *args)
793{
794	/* XXX Should redo this putting the (now four) versions of opendir
795	   in separate files instead of having them all here... */
796#if defined(MS_WIN32) && !defined(HAVE_OPENDIR)
797
798	char *name;
799	int len;
800	PyObject *d, *v;
801	HANDLE hFindFile;
802	WIN32_FIND_DATA FileData;
803	char namebuf[MAX_PATH+5];
804
805	if (!PyArg_ParseTuple(args, "t#:listdir", &name, &len))
806		return NULL;
807	if (len >= MAX_PATH) {
808		PyErr_SetString(PyExc_ValueError, "path too long");
809		return NULL;
810	}
811	strcpy(namebuf, name);
812	if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
813		namebuf[len++] = '/';
814	strcpy(namebuf + len, "*.*");
815
816	if ((d = PyList_New(0)) == NULL)
817		return NULL;
818
819	hFindFile = FindFirstFile(namebuf, &FileData);
820	if (hFindFile == INVALID_HANDLE_VALUE) {
821		errno = GetLastError();
822		if (errno == ERROR_FILE_NOT_FOUND)
823			return PyList_New(0);
824		return win32_error("FindFirstFile", name);
825	}
826	do {
827		if (FileData.cFileName[0] == '.' &&
828		    (FileData.cFileName[1] == '\0' ||
829		     FileData.cFileName[1] == '.' &&
830		     FileData.cFileName[2] == '\0'))
831			continue;
832		v = PyString_FromString(FileData.cFileName);
833		if (v == NULL) {
834			Py_DECREF(d);
835			d = NULL;
836			break;
837		}
838		if (PyList_Append(d, v) != 0) {
839			Py_DECREF(v);
840			Py_DECREF(d);
841			d = NULL;
842			break;
843		}
844		Py_DECREF(v);
845	} while (FindNextFile(hFindFile, &FileData) == TRUE);
846
847	if (FindClose(hFindFile) == FALSE)
848		return win32_error("FindClose", name);
849
850	return d;
851
852#else /* !MS_WIN32 */
853#ifdef _MSC_VER /* 16-bit Windows */
854
855#ifndef MAX_PATH
856#define MAX_PATH	250
857#endif
858	char *name, *pt;
859	int len;
860	PyObject *d, *v;
861	char namebuf[MAX_PATH+5];
862	struct _find_t ep;
863
864	if (!PyArg_ParseTuple(args, "t#:listdir", &name, &len))
865		return NULL;
866	if (len >= MAX_PATH) {
867		PyErr_SetString(PyExc_ValueError, "path too long");
868		return NULL;
869	}
870	strcpy(namebuf, name);
871	for (pt = namebuf; *pt; pt++)
872		if (*pt == '/')
873			*pt = '\\';
874	if (namebuf[len-1] != '\\')
875		namebuf[len++] = '\\';
876	strcpy(namebuf + len, "*.*");
877
878	if ((d = PyList_New(0)) == NULL)
879		return NULL;
880
881	if (_dos_findfirst(namebuf, _A_RDONLY |
882			   _A_HIDDEN | _A_SYSTEM | _A_SUBDIR, &ep) != 0)
883        {
884		errno = ENOENT;
885		return posix_error_with_filename(name);
886	}
887	do {
888		if (ep.name[0] == '.' &&
889		    (ep.name[1] == '\0' ||
890		     ep.name[1] == '.' &&
891		     ep.name[2] == '\0'))
892			continue;
893		strcpy(namebuf, ep.name);
894		for (pt = namebuf; *pt; pt++)
895			if (isupper(*pt))
896				*pt = tolower(*pt);
897		v = PyString_FromString(namebuf);
898		if (v == NULL) {
899			Py_DECREF(d);
900			d = NULL;
901			break;
902		}
903		if (PyList_Append(d, v) != 0) {
904			Py_DECREF(v);
905			Py_DECREF(d);
906			d = NULL;
907			break;
908		}
909		Py_DECREF(v);
910	} while (_dos_findnext(&ep) == 0);
911
912	return d;
913
914#else
915#if defined(PYOS_OS2)
916
917#ifndef MAX_PATH
918#define MAX_PATH    CCHMAXPATH
919#endif
920    char *name, *pt;
921    int len;
922    PyObject *d, *v;
923    char namebuf[MAX_PATH+5];
924    HDIR  hdir = 1;
925    ULONG srchcnt = 1;
926    FILEFINDBUF3   ep;
927    APIRET rc;
928
929    if (!PyArg_ParseTuple(args, "t#:listdir", &name, &len))
930        return NULL;
931    if (len >= MAX_PATH) {
932		PyErr_SetString(PyExc_ValueError, "path too long");
933        return NULL;
934    }
935    strcpy(namebuf, name);
936    for (pt = namebuf; *pt; pt++)
937        if (*pt == '/')
938            *pt = '\\';
939    if (namebuf[len-1] != '\\')
940        namebuf[len++] = '\\';
941    strcpy(namebuf + len, "*.*");
942
943	if ((d = PyList_New(0)) == NULL)
944        return NULL;
945
946    rc = DosFindFirst(namebuf,         /* Wildcard Pattern to Match */
947                      &hdir,           /* Handle to Use While Search Directory */
948                      FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY,
949                      &ep, sizeof(ep), /* Structure to Receive Directory Entry */
950                      &srchcnt,        /* Max and Actual Count of Entries Per Iteration */
951                      FIL_STANDARD);   /* Format of Entry (EAs or Not) */
952
953    if (rc != NO_ERROR) {
954        errno = ENOENT;
955        return posix_error_with_filename(name);
956    }
957
958    if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */
959        do {
960            if (ep.achName[0] == '.'
961            && (ep.achName[1] == '\0' || ep.achName[1] == '.' && ep.achName[2] == '\0'))
962                continue; /* Skip Over "." and ".." Names */
963
964            strcpy(namebuf, ep.achName);
965
966            /* Leave Case of Name Alone -- In Native Form */
967            /* (Removed Forced Lowercasing Code) */
968
969            v = PyString_FromString(namebuf);
970            if (v == NULL) {
971                Py_DECREF(d);
972                d = NULL;
973                break;
974            }
975            if (PyList_Append(d, v) != 0) {
976                Py_DECREF(v);
977                Py_DECREF(d);
978                d = NULL;
979                break;
980            }
981            Py_DECREF(v);
982        } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && srchcnt > 0);
983    }
984
985    return d;
986#else
987
988	char *name;
989	PyObject *d, *v;
990	DIR *dirp;
991	struct dirent *ep;
992	if (!PyArg_ParseTuple(args, "s:listdir", &name))
993		return NULL;
994	if ((dirp = opendir(name)) == NULL) {
995		return posix_error_with_filename(name);
996	}
997	if ((d = PyList_New(0)) == NULL) {
998		closedir(dirp);
999		return NULL;
1000	}
1001	while ((ep = readdir(dirp)) != NULL) {
1002		if (ep->d_name[0] == '.' &&
1003		    (NAMLEN(ep) == 1 ||
1004		     (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
1005			continue;
1006		v = PyString_FromStringAndSize(ep->d_name, NAMLEN(ep));
1007		if (v == NULL) {
1008			Py_DECREF(d);
1009			d = NULL;
1010			break;
1011		}
1012		if (PyList_Append(d, v) != 0) {
1013			Py_DECREF(v);
1014			Py_DECREF(d);
1015			d = NULL;
1016			break;
1017		}
1018		Py_DECREF(v);
1019	}
1020	closedir(dirp);
1021
1022	return d;
1023
1024#endif /* !PYOS_OS2 */
1025#endif /* !_MSC_VER */
1026#endif /* !MS_WIN32 */
1027}
1028
1029static char posix_mkdir__doc__[] =
1030"mkdir(path [, mode=0777]) -> None\n\
1031Create a directory.";
1032
1033static PyObject *
1034posix_mkdir(PyObject *self, PyObject *args)
1035{
1036	int res;
1037	char *path;
1038	int mode = 0777;
1039	if (!PyArg_ParseTuple(args, "s|i:mkdir", &path, &mode))
1040		return NULL;
1041	Py_BEGIN_ALLOW_THREADS
1042#if ( defined(__WATCOMC__) || defined(_MSC_VER) || defined(PYCC_VACPP) ) && !defined(__QNX__)
1043	res = mkdir(path);
1044#else
1045	res = mkdir(path, mode);
1046#endif
1047	Py_END_ALLOW_THREADS
1048	if (res < 0)
1049		return posix_error_with_filename(path);
1050	Py_INCREF(Py_None);
1051	return Py_None;
1052}
1053
1054
1055#ifdef HAVE_NICE
1056static char posix_nice__doc__[] =
1057"nice(inc) -> new_priority\n\
1058Decrease the priority of process and return new priority.";
1059
1060static PyObject *
1061posix_nice(PyObject *self, PyObject *args)
1062{
1063	int increment, value;
1064
1065	if (!PyArg_ParseTuple(args, "i:nice", &increment))
1066		return NULL;
1067	value = nice(increment);
1068	if (value == -1)
1069		return posix_error();
1070	return PyInt_FromLong((long) value);
1071}
1072#endif /* HAVE_NICE */
1073
1074
1075static char posix_rename__doc__[] =
1076"rename(old, new) -> None\n\
1077Rename a file or directory.";
1078
1079static PyObject *
1080posix_rename(PyObject *self, PyObject *args)
1081{
1082	return posix_2str(args, "ss:rename", rename);
1083}
1084
1085
1086static char posix_rmdir__doc__[] =
1087"rmdir(path) -> None\n\
1088Remove a directory.";
1089
1090static PyObject *
1091posix_rmdir(PyObject *self, PyObject *args)
1092{
1093	return posix_1str(args, "s:rmdir", rmdir);
1094}
1095
1096
1097static char posix_stat__doc__[] =
1098"stat(path) -> (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\
1099Perform a stat system call on the given path.";
1100
1101static PyObject *
1102posix_stat(PyObject *self, PyObject *args)
1103{
1104	return posix_do_stat(self, args, "s:stat", STAT);
1105}
1106
1107
1108#ifdef HAVE_SYSTEM
1109static char posix_system__doc__[] =
1110"system(command) -> exit_status\n\
1111Execute the command (a string) in a subshell.";
1112
1113static PyObject *
1114posix_system(PyObject *self, PyObject *args)
1115{
1116	char *command;
1117	long sts;
1118	if (!PyArg_ParseTuple(args, "s:system", &command))
1119		return NULL;
1120	Py_BEGIN_ALLOW_THREADS
1121	sts = system(command);
1122	Py_END_ALLOW_THREADS
1123	return PyInt_FromLong(sts);
1124}
1125#endif
1126
1127
1128static char posix_umask__doc__[] =
1129"umask(new_mask) -> old_mask\n\
1130Set the current numeric umask and return the previous umask.";
1131
1132static PyObject *
1133posix_umask(PyObject *self, PyObject *args)
1134{
1135	int i;
1136	if (!PyArg_ParseTuple(args, "i:umask", &i))
1137		return NULL;
1138	i = umask(i);
1139	if (i < 0)
1140		return posix_error();
1141	return PyInt_FromLong((long)i);
1142}
1143
1144
1145static char posix_unlink__doc__[] =
1146"unlink(path) -> None\n\
1147Remove a file (same as remove(path)).";
1148
1149static char posix_remove__doc__[] =
1150"remove(path) -> None\n\
1151Remove a file (same as unlink(path)).";
1152
1153static PyObject *
1154posix_unlink(PyObject *self, PyObject *args)
1155{
1156	return posix_1str(args, "s:remove", unlink);
1157}
1158
1159
1160#ifdef HAVE_UNAME
1161static char posix_uname__doc__[] =
1162"uname() -> (sysname, nodename, release, version, machine)\n\
1163Return a tuple identifying the current operating system.";
1164
1165static PyObject *
1166posix_uname(PyObject *self, PyObject *args)
1167{
1168	struct utsname u;
1169	int res;
1170	if (!PyArg_ParseTuple(args, ":uname"))
1171		return NULL;
1172	Py_BEGIN_ALLOW_THREADS
1173	res = uname(&u);
1174	Py_END_ALLOW_THREADS
1175	if (res < 0)
1176		return posix_error();
1177	return Py_BuildValue("(sssss)",
1178			     u.sysname,
1179			     u.nodename,
1180			     u.release,
1181			     u.version,
1182			     u.machine);
1183}
1184#endif /* HAVE_UNAME */
1185
1186
1187static char posix_utime__doc__[] =
1188"utime(path, (atime, utime)) -> None\n\
1189utime(path, None) -> None\n\
1190Set the access and modified time of the file to the given values.  If the\n\
1191second form is used, set the access and modified times to the current time.";
1192
1193static PyObject *
1194posix_utime(PyObject *self, PyObject *args)
1195{
1196	char *path;
1197	long atime, mtime;
1198	int res;
1199	PyObject* arg;
1200
1201/* XXX should define struct utimbuf instead, above */
1202#ifdef HAVE_UTIME_H
1203	struct utimbuf buf;
1204#define ATIME buf.actime
1205#define MTIME buf.modtime
1206#define UTIME_ARG &buf
1207#else /* HAVE_UTIME_H */
1208	time_t buf[2];
1209#define ATIME buf[0]
1210#define MTIME buf[1]
1211#define UTIME_ARG buf
1212#endif /* HAVE_UTIME_H */
1213
1214	if (!PyArg_ParseTuple(args, "sO:utime", &path, &arg))
1215		return NULL;
1216	if (arg == Py_None) {
1217		/* optional time values not given */
1218		Py_BEGIN_ALLOW_THREADS
1219		res = utime(path, NULL);
1220		Py_END_ALLOW_THREADS
1221	}
1222	else if (!PyArg_Parse(arg, "(ll)", &atime, &mtime)) {
1223		PyErr_SetString(PyExc_TypeError,
1224			      "Second argument must be a 2-tuple of numbers.");
1225		return NULL;
1226	}
1227	else {
1228		ATIME = atime;
1229		MTIME = mtime;
1230		Py_BEGIN_ALLOW_THREADS
1231		res = utime(path, UTIME_ARG);
1232		Py_END_ALLOW_THREADS
1233	}
1234	if (res < 0)
1235		return posix_error_with_filename(path);
1236	Py_INCREF(Py_None);
1237	return Py_None;
1238#undef UTIME_ARG
1239#undef ATIME
1240#undef MTIME
1241}
1242
1243
1244/* Process operations */
1245
1246static char posix__exit__doc__[] =
1247"_exit(status)\n\
1248Exit to the system with specified status, without normal exit processing.";
1249
1250static PyObject *
1251posix__exit(PyObject *self, PyObject *args)
1252{
1253	int sts;
1254	if (!PyArg_ParseTuple(args, "i:_exit", &sts))
1255		return NULL;
1256	_exit(sts);
1257	return NULL; /* Make gcc -Wall happy */
1258}
1259
1260
1261#ifdef HAVE_EXECV
1262static char posix_execv__doc__[] =
1263"execv(path, args)\n\
1264Execute an executable path with arguments, replacing current process.\n\
1265\n\
1266	path: path of executable file\n\
1267	args: tuple or list of strings";
1268
1269static PyObject *
1270posix_execv(PyObject *self, PyObject *args)
1271{
1272	char *path;
1273	PyObject *argv;
1274	char **argvlist;
1275	int i, argc;
1276	PyObject *(*getitem)(PyObject *, int);
1277
1278	/* execv has two arguments: (path, argv), where
1279	   argv is a list or tuple of strings. */
1280
1281	if (!PyArg_ParseTuple(args, "sO:execv", &path, &argv))
1282		return NULL;
1283	if (PyList_Check(argv)) {
1284		argc = PyList_Size(argv);
1285		getitem = PyList_GetItem;
1286	}
1287	else if (PyTuple_Check(argv)) {
1288		argc = PyTuple_Size(argv);
1289		getitem = PyTuple_GetItem;
1290	}
1291	else {
1292		PyErr_SetString(PyExc_TypeError, "argv must be tuple or list");
1293		return NULL;
1294	}
1295
1296	if (argc == 0) {
1297		PyErr_SetString(PyExc_ValueError, "empty argument list");
1298		return NULL;
1299	}
1300
1301	argvlist = PyMem_NEW(char *, argc+1);
1302	if (argvlist == NULL)
1303		return NULL;
1304	for (i = 0; i < argc; i++) {
1305		if (!PyArg_Parse((*getitem)(argv, i), "s", &argvlist[i])) {
1306			PyMem_DEL(argvlist);
1307			PyErr_SetString(PyExc_TypeError,
1308					"all arguments must be strings");
1309			return NULL;
1310
1311		}
1312	}
1313	argvlist[argc] = NULL;
1314
1315#ifdef BAD_EXEC_PROTOTYPES
1316	execv(path, (const char **) argvlist);
1317#else /* BAD_EXEC_PROTOTYPES */
1318	execv(path, argvlist);
1319#endif /* BAD_EXEC_PROTOTYPES */
1320
1321	/* If we get here it's definitely an error */
1322
1323	PyMem_DEL(argvlist);
1324	return posix_error();
1325}
1326
1327
1328static char posix_execve__doc__[] =
1329"execve(path, args, env)\n\
1330Execute a path with arguments and environment, replacing current process.\n\
1331\n\
1332	path: path of executable file\n\
1333	args: tuple or list of arguments\n\
1334	env: dictionary of strings mapping to strings";
1335
1336static PyObject *
1337posix_execve(PyObject *self, PyObject *args)
1338{
1339	char *path;
1340	PyObject *argv, *env;
1341	char **argvlist;
1342	char **envlist;
1343	PyObject *key, *val, *keys=NULL, *vals=NULL;
1344	int i, pos, argc, envc;
1345	PyObject *(*getitem)(PyObject *, int);
1346
1347	/* execve has three arguments: (path, argv, env), where
1348	   argv is a list or tuple of strings and env is a dictionary
1349	   like posix.environ. */
1350
1351	if (!PyArg_ParseTuple(args, "sOO:execve", &path, &argv, &env))
1352		return NULL;
1353	if (PyList_Check(argv)) {
1354		argc = PyList_Size(argv);
1355		getitem = PyList_GetItem;
1356	}
1357	else if (PyTuple_Check(argv)) {
1358		argc = PyTuple_Size(argv);
1359		getitem = PyTuple_GetItem;
1360	}
1361	else {
1362		PyErr_SetString(PyExc_TypeError, "argv must be tuple or list");
1363		return NULL;
1364	}
1365	if (!PyMapping_Check(env)) {
1366		PyErr_SetString(PyExc_TypeError, "env must be mapping object");
1367		return NULL;
1368	}
1369
1370	if (argc == 0) {
1371		PyErr_SetString(PyExc_ValueError,
1372				"empty argument list");
1373		return NULL;
1374	}
1375
1376	argvlist = PyMem_NEW(char *, argc+1);
1377	if (argvlist == NULL) {
1378		PyErr_NoMemory();
1379		return NULL;
1380	}
1381	for (i = 0; i < argc; i++) {
1382		if (!PyArg_Parse((*getitem)(argv, i),
1383				 "s;argv must be list of strings",
1384				 &argvlist[i]))
1385		{
1386			goto fail_1;
1387		}
1388	}
1389	argvlist[argc] = NULL;
1390
1391	i = PyMapping_Size(env);
1392	envlist = PyMem_NEW(char *, i + 1);
1393	if (envlist == NULL) {
1394		PyErr_NoMemory();
1395		goto fail_1;
1396	}
1397	envc = 0;
1398	keys = PyMapping_Keys(env);
1399	vals = PyMapping_Values(env);
1400	if (!keys || !vals)
1401		goto fail_2;
1402
1403	for (pos = 0; pos < i; pos++) {
1404		char *p, *k, *v;
1405
1406		key = PyList_GetItem(keys, pos);
1407		val = PyList_GetItem(vals, pos);
1408		if (!key || !val)
1409			goto fail_2;
1410
1411		if (!PyArg_Parse(key, "s;non-string key in env", &k) ||
1412		    !PyArg_Parse(val, "s;non-string value in env", &v))
1413		{
1414			goto fail_2;
1415		}
1416
1417#if defined(PYOS_OS2)
1418        /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
1419        if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
1420#endif
1421		p = PyMem_NEW(char, PyString_Size(key)+PyString_Size(val) + 2);
1422		if (p == NULL) {
1423			PyErr_NoMemory();
1424			goto fail_2;
1425		}
1426		sprintf(p, "%s=%s", k, v);
1427		envlist[envc++] = p;
1428#if defined(PYOS_OS2)
1429    }
1430#endif
1431	}
1432	envlist[envc] = 0;
1433
1434
1435#ifdef BAD_EXEC_PROTOTYPES
1436	execve(path, (const char **)argvlist, envlist);
1437#else /* BAD_EXEC_PROTOTYPES */
1438	execve(path, argvlist, envlist);
1439#endif /* BAD_EXEC_PROTOTYPES */
1440
1441	/* If we get here it's definitely an error */
1442
1443	(void) posix_error();
1444
1445 fail_2:
1446	while (--envc >= 0)
1447		PyMem_DEL(envlist[envc]);
1448	PyMem_DEL(envlist);
1449 fail_1:
1450	PyMem_DEL(argvlist);
1451	Py_XDECREF(vals);
1452	Py_XDECREF(keys);
1453	return NULL;
1454}
1455#endif /* HAVE_EXECV */
1456
1457
1458#ifdef HAVE_SPAWNV
1459static char posix_spawnv__doc__[] =
1460"spawnv(mode, path, args)\n\
1461Execute an executable path with arguments, replacing current process.\n\
1462\n\
1463	mode: mode of process creation\n\
1464	path: path of executable file\n\
1465	args: tuple or list of strings";
1466
1467static PyObject *
1468posix_spawnv(PyObject *self, PyObject *args)
1469{
1470	char *path;
1471	PyObject *argv;
1472	char **argvlist;
1473	int mode, i, argc;
1474	intptr_t spawnval;
1475	PyObject *(*getitem)(PyObject *, int);
1476
1477	/* spawnv has three arguments: (mode, path, argv), where
1478	   argv is a list or tuple of strings. */
1479
1480	if (!PyArg_ParseTuple(args, "isO:spawnv", &mode, &path, &argv))
1481		return NULL;
1482	if (PyList_Check(argv)) {
1483		argc = PyList_Size(argv);
1484		getitem = PyList_GetItem;
1485	}
1486	else if (PyTuple_Check(argv)) {
1487		argc = PyTuple_Size(argv);
1488		getitem = PyTuple_GetItem;
1489	}
1490	else {
1491		PyErr_SetString(PyExc_TypeError, "argv must be tuple or list");
1492		return NULL;
1493	}
1494
1495	argvlist = PyMem_NEW(char *, argc+1);
1496	if (argvlist == NULL)
1497		return NULL;
1498	for (i = 0; i < argc; i++) {
1499		if (!PyArg_Parse((*getitem)(argv, i), "s", &argvlist[i])) {
1500			PyMem_DEL(argvlist);
1501			PyErr_SetString(PyExc_TypeError,
1502					"all arguments must be strings");
1503			return NULL;
1504		}
1505	}
1506	argvlist[argc] = NULL;
1507
1508	if (mode == _OLD_P_OVERLAY)
1509		mode = _P_OVERLAY;
1510	spawnval = _spawnv(mode, path, argvlist);
1511
1512	PyMem_DEL(argvlist);
1513
1514	if (spawnval == -1)
1515		return posix_error();
1516	else
1517#if SIZEOF_LONG == SIZEOF_VOID_P
1518		return Py_BuildValue("l", (long) spawnval);
1519#else
1520		return Py_BuildValue("L", (LONG_LONG) spawnval);
1521#endif
1522}
1523
1524
1525static char posix_spawnve__doc__[] =
1526"spawnve(mode, path, args, env)\n\
1527Execute a path with arguments and environment, replacing current process.\n\
1528\n\
1529	mode: mode of process creation\n\
1530	path: path of executable file\n\
1531	args: tuple or list of arguments\n\
1532	env: dictionary of strings mapping to strings";
1533
1534static PyObject *
1535posix_spawnve(PyObject *self, PyObject *args)
1536{
1537	char *path;
1538	PyObject *argv, *env;
1539	char **argvlist;
1540	char **envlist;
1541	PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
1542	int mode, i, pos, argc, envc;
1543	intptr_t spawnval;
1544	PyObject *(*getitem)(PyObject *, int);
1545
1546	/* spawnve has four arguments: (mode, path, argv, env), where
1547	   argv is a list or tuple of strings and env is a dictionary
1548	   like posix.environ. */
1549
1550	if (!PyArg_ParseTuple(args, "isOO:spawnve", &mode, &path, &argv, &env))
1551		return NULL;
1552	if (PyList_Check(argv)) {
1553		argc = PyList_Size(argv);
1554		getitem = PyList_GetItem;
1555	}
1556	else if (PyTuple_Check(argv)) {
1557		argc = PyTuple_Size(argv);
1558		getitem = PyTuple_GetItem;
1559	}
1560	else {
1561		PyErr_SetString(PyExc_TypeError, "argv must be tuple or list");
1562		return NULL;
1563	}
1564	if (!PyMapping_Check(env)) {
1565		PyErr_SetString(PyExc_TypeError, "env must be mapping object");
1566		return NULL;
1567	}
1568
1569	argvlist = PyMem_NEW(char *, argc+1);
1570	if (argvlist == NULL) {
1571		PyErr_NoMemory();
1572		return NULL;
1573	}
1574	for (i = 0; i < argc; i++) {
1575		if (!PyArg_Parse((*getitem)(argv, i),
1576				 "s;argv must be list of strings",
1577				 &argvlist[i]))
1578		{
1579			goto fail_1;
1580		}
1581	}
1582	argvlist[argc] = NULL;
1583
1584	i = PyMapping_Size(env);
1585	envlist = PyMem_NEW(char *, i + 1);
1586	if (envlist == NULL) {
1587		PyErr_NoMemory();
1588		goto fail_1;
1589	}
1590	envc = 0;
1591	keys = PyMapping_Keys(env);
1592	vals = PyMapping_Values(env);
1593	if (!keys || !vals)
1594		goto fail_2;
1595
1596	for (pos = 0; pos < i; pos++) {
1597		char *p, *k, *v;
1598
1599		key = PyList_GetItem(keys, pos);
1600		val = PyList_GetItem(vals, pos);
1601		if (!key || !val)
1602			goto fail_2;
1603
1604		if (!PyArg_Parse(key, "s;non-string key in env", &k) ||
1605		    !PyArg_Parse(val, "s;non-string value in env", &v))
1606		{
1607			goto fail_2;
1608		}
1609		p = PyMem_NEW(char, PyString_Size(key)+PyString_Size(val) + 2);
1610		if (p == NULL) {
1611			PyErr_NoMemory();
1612			goto fail_2;
1613		}
1614		sprintf(p, "%s=%s", k, v);
1615		envlist[envc++] = p;
1616	}
1617	envlist[envc] = 0;
1618
1619	if (mode == _OLD_P_OVERLAY)
1620		mode = _P_OVERLAY;
1621	spawnval = _spawnve(mode, path, argvlist, envlist);
1622	if (spawnval == -1)
1623		(void) posix_error();
1624	else
1625#if SIZEOF_LONG == SIZEOF_VOID_P
1626		res = Py_BuildValue("l", (long) spawnval);
1627#else
1628		res = Py_BuildValue("L", (LONG_LONG) spawnval);
1629#endif
1630
1631 fail_2:
1632	while (--envc >= 0)
1633		PyMem_DEL(envlist[envc]);
1634	PyMem_DEL(envlist);
1635 fail_1:
1636	PyMem_DEL(argvlist);
1637	Py_XDECREF(vals);
1638	Py_XDECREF(keys);
1639	return res;
1640}
1641#endif /* HAVE_SPAWNV */
1642
1643
1644#ifdef HAVE_FORK
1645static char posix_fork__doc__[] =
1646"fork() -> pid\n\
1647Fork a child process.\n\
1648\n\
1649Return 0 to child process and PID of child to parent process.";
1650
1651static PyObject *
1652posix_fork(PyObject *self, PyObject *args)
1653{
1654	int pid;
1655	if (!PyArg_ParseTuple(args, ":fork"))
1656		return NULL;
1657	pid = fork();
1658	if (pid == -1)
1659		return posix_error();
1660	if (pid == 0)
1661		PyOS_AfterFork();
1662	return PyInt_FromLong((long)pid);
1663}
1664#endif
1665
1666#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY)
1667#ifdef HAVE_PTY_H
1668#include <pty.h>
1669#else
1670#ifdef HAVE_LIBUTIL_H
1671#include <libutil.h>
1672#endif /* HAVE_LIBUTIL_H */
1673#endif /* HAVE_PTY_H */
1674#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) */
1675
1676#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY)
1677static char posix_openpty__doc__[] =
1678"openpty() -> (master_fd, slave_fd)\n\
1679Open a pseudo-terminal, returning open fd's for both master and slave end.\n";
1680
1681static PyObject *
1682posix_openpty(PyObject *self, PyObject *args)
1683{
1684	int master_fd, slave_fd;
1685#ifndef HAVE_OPENPTY
1686	char * slave_name;
1687#endif
1688
1689	if (!PyArg_ParseTuple(args, ":openpty"))
1690		return NULL;
1691
1692#ifdef HAVE_OPENPTY
1693	if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
1694		return posix_error();
1695#else
1696	slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
1697	if (slave_name == NULL)
1698		return posix_error();
1699
1700	slave_fd = open(slave_name, O_RDWR);
1701	if (slave_fd < 0)
1702		return posix_error();
1703#endif /* HAVE_OPENPTY */
1704
1705	return Py_BuildValue("(ii)", master_fd, slave_fd);
1706
1707}
1708#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) */
1709
1710#ifdef HAVE_FORKPTY
1711static char posix_forkpty__doc__[] =
1712"forkpty() -> (pid, master_fd)\n\
1713Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
1714Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
1715To both, return fd of newly opened pseudo-terminal.\n";
1716
1717static PyObject *
1718posix_forkpty(PyObject *self, PyObject *args)
1719{
1720	int master_fd, pid;
1721
1722	if (!PyArg_ParseTuple(args, ":forkpty"))
1723		return NULL;
1724	pid = forkpty(&master_fd, NULL, NULL, NULL);
1725	if (pid == -1)
1726		return posix_error();
1727	if (pid == 0)
1728		PyOS_AfterFork();
1729	return Py_BuildValue("(ii)", pid, master_fd);
1730}
1731#endif
1732
1733#ifdef HAVE_GETEGID
1734static char posix_getegid__doc__[] =
1735"getegid() -> egid\n\
1736Return the current process's effective group id.";
1737
1738static PyObject *
1739posix_getegid(PyObject *self, PyObject *args)
1740{
1741	if (!PyArg_ParseTuple(args, ":getegid"))
1742		return NULL;
1743	return PyInt_FromLong((long)getegid());
1744}
1745#endif
1746
1747
1748#ifdef HAVE_GETEUID
1749static char posix_geteuid__doc__[] =
1750"geteuid() -> euid\n\
1751Return the current process's effective user id.";
1752
1753static PyObject *
1754posix_geteuid(PyObject *self, PyObject *args)
1755{
1756	if (!PyArg_ParseTuple(args, ":geteuid"))
1757		return NULL;
1758	return PyInt_FromLong((long)geteuid());
1759}
1760#endif
1761
1762
1763#ifdef HAVE_GETGID
1764static char posix_getgid__doc__[] =
1765"getgid() -> gid\n\
1766Return the current process's group id.";
1767
1768static PyObject *
1769posix_getgid(PyObject *self, PyObject *args)
1770{
1771	if (!PyArg_ParseTuple(args, ":getgid"))
1772		return NULL;
1773	return PyInt_FromLong((long)getgid());
1774}
1775#endif
1776
1777
1778static char posix_getpid__doc__[] =
1779"getpid() -> pid\n\
1780Return the current process id";
1781
1782static PyObject *
1783posix_getpid(PyObject *self, PyObject *args)
1784{
1785	if (!PyArg_ParseTuple(args, ":getpid"))
1786		return NULL;
1787	return PyInt_FromLong((long)getpid());
1788}
1789
1790
1791#ifdef HAVE_GETGROUPS
1792static char posix_getgroups__doc__[] = "\
1793getgroups() -> list of group IDs\n\
1794Return list of supplemental group IDs for the process.";
1795
1796static PyObject *
1797posix_getgroups(PyObject *self, PyObject *args)
1798{
1799    PyObject *result = NULL;
1800
1801    if (PyArg_ParseTuple(args, ":getgroups")) {
1802#ifdef NGROUPS_MAX
1803#define MAX_GROUPS NGROUPS_MAX
1804#else
1805        /* defined to be 16 on Solaris7, so this should be a small number */
1806#define MAX_GROUPS 64
1807#endif
1808        gid_t grouplist[MAX_GROUPS];
1809        int n;
1810
1811        n = getgroups(MAX_GROUPS, grouplist);
1812        if (n < 0)
1813            posix_error();
1814        else {
1815            result = PyList_New(n);
1816            if (result != NULL) {
1817                PyObject *o;
1818                int i;
1819                for (i = 0; i < n; ++i) {
1820                    o = PyInt_FromLong((long)grouplist[i]);
1821                    if (o == NULL) {
1822                        Py_DECREF(result);
1823                        result = NULL;
1824                        break;
1825                    }
1826                    PyList_SET_ITEM(result, i, o);
1827                }
1828            }
1829        }
1830    }
1831    return result;
1832}
1833#endif
1834
1835#ifdef HAVE_GETPGRP
1836static char posix_getpgrp__doc__[] =
1837"getpgrp() -> pgrp\n\
1838Return the current process group id.";
1839
1840static PyObject *
1841posix_getpgrp(PyObject *self, PyObject *args)
1842{
1843	if (!PyArg_ParseTuple(args, ":getpgrp"))
1844		return NULL;
1845#ifdef GETPGRP_HAVE_ARG
1846	return PyInt_FromLong((long)getpgrp(0));
1847#else /* GETPGRP_HAVE_ARG */
1848	return PyInt_FromLong((long)getpgrp());
1849#endif /* GETPGRP_HAVE_ARG */
1850}
1851#endif /* HAVE_GETPGRP */
1852
1853
1854#ifdef HAVE_SETPGRP
1855static char posix_setpgrp__doc__[] =
1856"setpgrp() -> None\n\
1857Make this process a session leader.";
1858
1859static PyObject *
1860posix_setpgrp(PyObject *self, PyObject *args)
1861{
1862	if (!PyArg_ParseTuple(args, ":setpgrp"))
1863		return NULL;
1864#ifdef SETPGRP_HAVE_ARG
1865	if (setpgrp(0, 0) < 0)
1866#else /* SETPGRP_HAVE_ARG */
1867	if (setpgrp() < 0)
1868#endif /* SETPGRP_HAVE_ARG */
1869		return posix_error();
1870	Py_INCREF(Py_None);
1871	return Py_None;
1872}
1873
1874#endif /* HAVE_SETPGRP */
1875
1876#ifdef HAVE_GETPPID
1877static char posix_getppid__doc__[] =
1878"getppid() -> ppid\n\
1879Return the parent's process id.";
1880
1881static PyObject *
1882posix_getppid(PyObject *self, PyObject *args)
1883{
1884	if (!PyArg_ParseTuple(args, ":getppid"))
1885		return NULL;
1886	return PyInt_FromLong((long)getppid());
1887}
1888#endif
1889
1890
1891#ifdef HAVE_GETLOGIN
1892static char posix_getlogin__doc__[] = "\
1893getlogin() -> string\n\
1894Return the actual login name.";
1895
1896static PyObject *
1897posix_getlogin(PyObject *self, PyObject *args)
1898{
1899    PyObject *result = NULL;
1900
1901    if (PyArg_ParseTuple(args, ":getlogin")) {
1902        char *name = getlogin();
1903
1904        if (name == NULL)
1905            posix_error();
1906        else
1907            result = PyString_FromString(name);
1908    }
1909    return result;
1910}
1911#endif
1912
1913#ifdef HAVE_GETUID
1914static char posix_getuid__doc__[] =
1915"getuid() -> uid\n\
1916Return the current process's user id.";
1917
1918static PyObject *
1919posix_getuid(PyObject *self, PyObject *args)
1920{
1921	if (!PyArg_ParseTuple(args, ":getuid"))
1922		return NULL;
1923	return PyInt_FromLong((long)getuid());
1924}
1925#endif
1926
1927
1928#ifdef HAVE_KILL
1929static char posix_kill__doc__[] =
1930"kill(pid, sig) -> None\n\
1931Kill a process with a signal.";
1932
1933static PyObject *
1934posix_kill(PyObject *self, PyObject *args)
1935{
1936	int pid, sig;
1937	if (!PyArg_ParseTuple(args, "ii:kill", &pid, &sig))
1938		return NULL;
1939#if defined(PYOS_OS2)
1940    if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
1941        APIRET rc;
1942        if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
1943            return os2_error(rc);
1944
1945    } else if (sig == XCPT_SIGNAL_KILLPROC) {
1946        APIRET rc;
1947        if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
1948            return os2_error(rc);
1949
1950    } else
1951        return NULL; /* Unrecognized Signal Requested */
1952#else
1953	if (kill(pid, sig) == -1)
1954		return posix_error();
1955#endif
1956	Py_INCREF(Py_None);
1957	return Py_None;
1958}
1959#endif
1960
1961#ifdef HAVE_PLOCK
1962
1963#ifdef HAVE_SYS_LOCK_H
1964#include <sys/lock.h>
1965#endif
1966
1967static char posix_plock__doc__[] =
1968"plock(op) -> None\n\
1969Lock program segments into memory.";
1970
1971static PyObject *
1972posix_plock(PyObject *self, PyObject *args)
1973{
1974	int op;
1975	if (!PyArg_ParseTuple(args, "i:plock", &op))
1976		return NULL;
1977	if (plock(op) == -1)
1978		return posix_error();
1979	Py_INCREF(Py_None);
1980	return Py_None;
1981}
1982#endif
1983
1984
1985#ifdef HAVE_POPEN
1986static char posix_popen__doc__[] =
1987"popen(command [, mode='r' [, bufsize]]) -> pipe\n\
1988Open a pipe to/from a command returning a file object.";
1989
1990#if defined(PYOS_OS2)
1991static int
1992async_system(const char *command)
1993{
1994    char        *p, errormsg[256], args[1024];
1995    RESULTCODES  rcodes;
1996    APIRET       rc;
1997    char        *shell = getenv("COMSPEC");
1998    if (!shell)
1999        shell = "cmd";
2000
2001    strcpy(args, shell);
2002    p = &args[ strlen(args)+1 ];
2003    strcpy(p, "/c ");
2004    strcat(p, command);
2005    p += strlen(p) + 1;
2006    *p = '\0';
2007
2008    rc = DosExecPgm(errormsg, sizeof(errormsg),
2009                    EXEC_ASYNC, /* Execute Async w/o Wait for Results */
2010                    args,
2011                    NULL,       /* Inherit Parent's Environment */
2012                    &rcodes, shell);
2013    return rc;
2014}
2015
2016static FILE *
2017popen(const char *command, const char *mode, int pipesize, int *err)
2018{
2019    HFILE    rhan, whan;
2020    FILE    *retfd = NULL;
2021    APIRET   rc = DosCreatePipe(&rhan, &whan, pipesize);
2022
2023    if (rc != NO_ERROR) {
2024	*err = rc;
2025        return NULL; /* ERROR - Unable to Create Anon Pipe */
2026    }
2027
2028    if (strchr(mode, 'r') != NULL) { /* Treat Command as a Data Source */
2029        int oldfd = dup(1);      /* Save STDOUT Handle in Another Handle */
2030
2031        DosEnterCritSec();      /* Stop Other Threads While Changing Handles */
2032        close(1);                /* Make STDOUT Available for Reallocation */
2033
2034        if (dup2(whan, 1) == 0) {      /* Connect STDOUT to Pipe Write Side */
2035            DosClose(whan);            /* Close Now-Unused Pipe Write Handle */
2036
2037            if (async_system(command) == NO_ERROR)
2038                retfd = fdopen(rhan, mode); /* And Return Pipe Read Handle */
2039        }
2040
2041        dup2(oldfd, 1);          /* Reconnect STDOUT to Original Handle */
2042        DosExitCritSec();        /* Now Allow Other Threads to Run */
2043
2044        close(oldfd);            /* And Close Saved STDOUT Handle */
2045        return retfd;            /* Return fd of Pipe or NULL if Error */
2046
2047    } else if (strchr(mode, 'w')) { /* Treat Command as a Data Sink */
2048        int oldfd = dup(0);      /* Save STDIN Handle in Another Handle */
2049
2050        DosEnterCritSec();      /* Stop Other Threads While Changing Handles */
2051        close(0);                /* Make STDIN Available for Reallocation */
2052
2053        if (dup2(rhan, 0) == 0)     { /* Connect STDIN to Pipe Read Side */
2054            DosClose(rhan);           /* Close Now-Unused Pipe Read Handle */
2055
2056            if (async_system(command) == NO_ERROR)
2057                retfd = fdopen(whan, mode); /* And Return Pipe Write Handle */
2058        }
2059
2060        dup2(oldfd, 0);          /* Reconnect STDIN to Original Handle */
2061        DosExitCritSec();        /* Now Allow Other Threads to Run */
2062
2063        close(oldfd);            /* And Close Saved STDIN Handle */
2064        return retfd;            /* Return fd of Pipe or NULL if Error */
2065
2066    } else {
2067	*err = ERROR_INVALID_ACCESS;
2068        return NULL; /* ERROR - Invalid Mode (Neither Read nor Write) */
2069    }
2070}
2071
2072static PyObject *
2073posix_popen(PyObject *self, PyObject *args)
2074{
2075	char *name;
2076	char *mode = "r";
2077	int   err, bufsize = -1;
2078	FILE *fp;
2079	PyObject *f;
2080	if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
2081		return NULL;
2082	Py_BEGIN_ALLOW_THREADS
2083	fp = popen(name, mode, (bufsize > 0) ? bufsize : 4096, &err);
2084	Py_END_ALLOW_THREADS
2085	if (fp == NULL)
2086		return os2_error(err);
2087
2088	f = PyFile_FromFile(fp, name, mode, fclose);
2089	if (f != NULL)
2090		PyFile_SetBufSize(f, bufsize);
2091	return f;
2092}
2093
2094#elif defined(MS_WIN32)
2095
2096/*
2097 * Portable 'popen' replacement for Win32.
2098 *
2099 * Written by Bill Tutt <billtut@microsoft.com>.  Minor tweaks
2100 * and 2.0 integration by Fredrik Lundh <fredrik@pythonware.com>
2101 * Return code handling by David Bolen <db3l@fitlinxx.com>.
2102 */
2103
2104#include <malloc.h>
2105#include <io.h>
2106#include <fcntl.h>
2107
2108/* These tell _PyPopen() wether to return 1, 2, or 3 file objects. */
2109#define POPEN_1 1
2110#define POPEN_2 2
2111#define POPEN_3 3
2112#define POPEN_4 4
2113
2114static PyObject *_PyPopen(char *, int, int);
2115static int _PyPclose(FILE *file);
2116
2117/*
2118 * Internal dictionary mapping popen* file pointers to process handles,
2119 * for use when retrieving the process exit code.  See _PyPclose() below
2120 * for more information on this dictionary's use.
2121 */
2122static PyObject *_PyPopenProcs = NULL;
2123
2124
2125/* popen that works from a GUI.
2126 *
2127 * The result of this function is a pipe (file) connected to the
2128 * processes stdin or stdout, depending on the requested mode.
2129 */
2130
2131static PyObject *
2132posix_popen(PyObject *self, PyObject *args)
2133{
2134	PyObject *f, *s;
2135	int tm = 0;
2136
2137	char *cmdstring;
2138	char *mode = "r";
2139	int bufsize = -1;
2140	if (!PyArg_ParseTuple(args, "s|si:popen", &cmdstring, &mode, &bufsize))
2141		return NULL;
2142
2143	s = PyTuple_New(0);
2144
2145	if (*mode == 'r')
2146		tm = _O_RDONLY;
2147	else if (*mode != 'w') {
2148		PyErr_SetString(PyExc_ValueError, "mode must be 'r' or 'w'");
2149		return NULL;
2150	} else
2151		tm = _O_WRONLY;
2152
2153	if (bufsize != -1) {
2154		PyErr_SetString(PyExc_ValueError, "bufsize must be -1");
2155		return NULL;
2156	}
2157
2158	if (*(mode+1) == 't')
2159		f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1);
2160	else if (*(mode+1) == 'b')
2161		f = _PyPopen(cmdstring, tm | _O_BINARY, POPEN_1);
2162	else
2163		f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1);
2164
2165	return f;
2166}
2167
2168/* Variation on win32pipe.popen
2169 *
2170 * The result of this function is a pipe (file) connected to the
2171 * process's stdin, and a pipe connected to the process's stdout.
2172 */
2173
2174static PyObject *
2175win32_popen2(PyObject *self, PyObject  *args)
2176{
2177	PyObject *f;
2178	int tm=0;
2179
2180	char *cmdstring;
2181	char *mode = "t";
2182	int bufsize = -1;
2183	if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize))
2184		return NULL;
2185
2186	if (*mode == 't')
2187		tm = _O_TEXT;
2188	else if (*mode != 'b') {
2189		PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
2190		return NULL;
2191	} else
2192		tm = _O_BINARY;
2193
2194	if (bufsize != -1) {
2195		PyErr_SetString(PyExc_ValueError, "bufsize must be -1");
2196		return NULL;
2197	}
2198
2199	f = _PyPopen(cmdstring, tm, POPEN_2);
2200
2201	return f;
2202}
2203
2204/*
2205 * Variation on <om win32pipe.popen>
2206 *
2207 * The result of this function is 3 pipes - the process's stdin,
2208 * stdout and stderr
2209 */
2210
2211static PyObject *
2212win32_popen3(PyObject *self, PyObject *args)
2213{
2214	PyObject *f;
2215	int tm = 0;
2216
2217	char *cmdstring;
2218	char *mode = "t";
2219	int bufsize = -1;
2220	if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize))
2221		return NULL;
2222
2223	if (*mode == 't')
2224		tm = _O_TEXT;
2225	else if (*mode != 'b') {
2226		PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
2227		return NULL;
2228	} else
2229		tm = _O_BINARY;
2230
2231	if (bufsize != -1) {
2232		PyErr_SetString(PyExc_ValueError, "bufsize must be -1");
2233		return NULL;
2234	}
2235
2236	f = _PyPopen(cmdstring, tm, POPEN_3);
2237
2238	return f;
2239}
2240
2241/*
2242 * Variation on win32pipe.popen
2243 *
2244 * The result of this function is 2 pipes - the processes stdin,
2245 * and stdout+stderr combined as a single pipe.
2246 */
2247
2248static PyObject *
2249win32_popen4(PyObject *self, PyObject  *args)
2250{
2251	PyObject *f;
2252	int tm = 0;
2253
2254	char *cmdstring;
2255	char *mode = "t";
2256	int bufsize = -1;
2257	if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize))
2258		return NULL;
2259
2260	if (*mode == 't')
2261		tm = _O_TEXT;
2262	else if (*mode != 'b') {
2263		PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
2264		return NULL;
2265	} else
2266		tm = _O_BINARY;
2267
2268	if (bufsize != -1) {
2269		PyErr_SetString(PyExc_ValueError, "bufsize must be -1");
2270		return NULL;
2271	}
2272
2273	f = _PyPopen(cmdstring, tm, POPEN_4);
2274
2275	return f;
2276}
2277
2278static int
2279_PyPopenCreateProcess(char *cmdstring,
2280		      HANDLE hStdin,
2281		      HANDLE hStdout,
2282		      HANDLE hStderr,
2283		      HANDLE *hProcess)
2284{
2285	PROCESS_INFORMATION piProcInfo;
2286	STARTUPINFO siStartInfo;
2287	char *s1,*s2, *s3 = " /c ";
2288	const char *szConsoleSpawn = "w9xpopen.exe \"";
2289	int i;
2290	int x;
2291
2292	if (i = GetEnvironmentVariable("COMSPEC",NULL,0)) {
2293		s1 = (char *)_alloca(i);
2294		if (!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
2295			return x;
2296		if (GetVersion() < 0x80000000) {
2297			/*
2298			 * NT/2000
2299			 */
2300			x = i + strlen(s3) + strlen(cmdstring) + 1;
2301			s2 = (char *)_alloca(x);
2302			ZeroMemory(s2, x);
2303			sprintf(s2, "%s%s%s", s1, s3, cmdstring);
2304		}
2305		else {
2306			/*
2307			 * Oh gag, we're on Win9x. Use the workaround listed in
2308			 * KB: Q150956
2309			 */
2310			char modulepath[256];
2311			GetModuleFileName(NULL, modulepath, sizeof(modulepath));
2312			for (i = x = 0; modulepath[i]; i++)
2313				if (modulepath[i] == '\\')
2314					x = i+1;
2315			modulepath[x] = '\0';
2316			x = i + strlen(s3) + strlen(cmdstring) + 1 +
2317				strlen(modulepath) +
2318				strlen(szConsoleSpawn) + 1;
2319			s2 = (char *)_alloca(x);
2320			ZeroMemory(s2, x);
2321			sprintf(
2322				s2,
2323				"%s%s%s%s%s\"",
2324				modulepath,
2325				szConsoleSpawn,
2326				s1,
2327				s3,
2328				cmdstring);
2329		}
2330	}
2331
2332	/* Could be an else here to try cmd.exe / command.com in the path
2333	   Now we'll just error out.. */
2334	else
2335		return -1;
2336
2337	ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
2338	siStartInfo.cb = sizeof(STARTUPINFO);
2339	siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
2340	siStartInfo.hStdInput = hStdin;
2341	siStartInfo.hStdOutput = hStdout;
2342	siStartInfo.hStdError = hStderr;
2343	siStartInfo.wShowWindow = SW_HIDE;
2344
2345	if (CreateProcess(NULL,
2346			  s2,
2347			  NULL,
2348			  NULL,
2349			  TRUE,
2350			  CREATE_NEW_CONSOLE,
2351			  NULL,
2352			  NULL,
2353			  &siStartInfo,
2354			  &piProcInfo) ) {
2355		/* Close the handles now so anyone waiting is woken. */
2356		CloseHandle(piProcInfo.hThread);
2357
2358		/* Return process handle */
2359		*hProcess = piProcInfo.hProcess;
2360		return TRUE;
2361	}
2362	return FALSE;
2363}
2364
2365/* The following code is based off of KB: Q190351 */
2366
2367static PyObject *
2368_PyPopen(char *cmdstring, int mode, int n)
2369{
2370	HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr,
2371		hChildStderrRd, hChildStderrWr, hChildStdinWrDup, hChildStdoutRdDup,
2372		hChildStderrRdDup, hProcess; /* hChildStdoutWrDup; */
2373
2374	SECURITY_ATTRIBUTES saAttr;
2375	BOOL fSuccess;
2376	int fd1, fd2, fd3;
2377	FILE *f1, *f2, *f3;
2378	long file_count;
2379	PyObject *f;
2380
2381	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
2382	saAttr.bInheritHandle = TRUE;
2383	saAttr.lpSecurityDescriptor = NULL;
2384
2385	if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
2386		return win32_error("CreatePipe", NULL);
2387
2388	/* Create new output read handle and the input write handle. Set
2389	 * the inheritance properties to FALSE. Otherwise, the child inherits
2390	 * the these handles; resulting in non-closeable handles to the pipes
2391	 * being created. */
2392	 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
2393				    GetCurrentProcess(), &hChildStdinWrDup, 0,
2394				    FALSE,
2395				    DUPLICATE_SAME_ACCESS);
2396	 if (!fSuccess)
2397		 return win32_error("DuplicateHandle", NULL);
2398
2399	 /* Close the inheritable version of ChildStdin
2400	that we're using. */
2401	 CloseHandle(hChildStdinWr);
2402
2403	 if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
2404		 return win32_error("CreatePipe", NULL);
2405
2406	 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
2407				    GetCurrentProcess(), &hChildStdoutRdDup, 0,
2408				    FALSE, DUPLICATE_SAME_ACCESS);
2409	 if (!fSuccess)
2410		 return win32_error("DuplicateHandle", NULL);
2411
2412	 /* Close the inheritable version of ChildStdout
2413		that we're using. */
2414	 CloseHandle(hChildStdoutRd);
2415
2416	 if (n != POPEN_4) {
2417		 if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
2418			 return win32_error("CreatePipe", NULL);
2419		 fSuccess = DuplicateHandle(GetCurrentProcess(),
2420					    hChildStderrRd,
2421					    GetCurrentProcess(),
2422					    &hChildStderrRdDup, 0,
2423					    FALSE, DUPLICATE_SAME_ACCESS);
2424		 if (!fSuccess)
2425			 return win32_error("DuplicateHandle", NULL);
2426		 /* Close the inheritable version of ChildStdErr that we're using. */
2427		 CloseHandle(hChildStderrRd);
2428	 }
2429
2430	 switch (n) {
2431	 case POPEN_1:
2432		 switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY)) {
2433		 case _O_WRONLY | _O_TEXT:
2434			 /* Case for writing to child Stdin in text mode. */
2435			 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
2436			 f1 = _fdopen(fd1, "w");
2437			 f = PyFile_FromFile(f1, cmdstring, "w", _PyPclose);
2438			 PyFile_SetBufSize(f, 0);
2439			 /* We don't care about these pipes anymore, so close them. */
2440			 CloseHandle(hChildStdoutRdDup);
2441			 CloseHandle(hChildStderrRdDup);
2442			 break;
2443
2444		 case _O_RDONLY | _O_TEXT:
2445			 /* Case for reading from child Stdout in text mode. */
2446			 fd1 = _open_osfhandle((long)hChildStdoutRdDup, mode);
2447			 f1 = _fdopen(fd1, "r");
2448			 f = PyFile_FromFile(f1, cmdstring, "r", _PyPclose);
2449			 PyFile_SetBufSize(f, 0);
2450			 /* We don't care about these pipes anymore, so close them. */
2451			 CloseHandle(hChildStdinWrDup);
2452			 CloseHandle(hChildStderrRdDup);
2453			 break;
2454
2455		 case _O_RDONLY | _O_BINARY:
2456			 /* Case for readinig from child Stdout in binary mode. */
2457			 fd1 = _open_osfhandle((long)hChildStdoutRdDup, mode);
2458			 f1 = _fdopen(fd1, "rb");
2459			 f = PyFile_FromFile(f1, cmdstring, "rb", _PyPclose);
2460			 PyFile_SetBufSize(f, 0);
2461			 /* We don't care about these pipes anymore, so close them. */
2462			 CloseHandle(hChildStdinWrDup);
2463			 CloseHandle(hChildStderrRdDup);
2464			 break;
2465
2466		 case _O_WRONLY | _O_BINARY:
2467			 /* Case for writing to child Stdin in binary mode. */
2468			 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
2469			 f1 = _fdopen(fd1, "wb");
2470			 f = PyFile_FromFile(f1, cmdstring, "wb", _PyPclose);
2471			 PyFile_SetBufSize(f, 0);
2472			 /* We don't care about these pipes anymore, so close them. */
2473			 CloseHandle(hChildStdoutRdDup);
2474			 CloseHandle(hChildStderrRdDup);
2475			 break;
2476		 }
2477		 file_count = 1;
2478		 break;
2479
2480	 case POPEN_2:
2481	 case POPEN_4:
2482	 {
2483		 char *m1, *m2;
2484		 PyObject *p1, *p2;
2485
2486		 if (mode && _O_TEXT) {
2487			 m1 = "r";
2488			 m2 = "w";
2489		 } else {
2490			 m1 = "rb";
2491			 m2 = "wb";
2492		 }
2493
2494		 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
2495		 f1 = _fdopen(fd1, m2);
2496		 fd2 = _open_osfhandle((long)hChildStdoutRdDup, mode);
2497		 f2 = _fdopen(fd2, m1);
2498		 p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
2499		 PyFile_SetBufSize(p1, 0);
2500		 p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose);
2501		 PyFile_SetBufSize(p2, 0);
2502
2503		 if (n != 4)
2504			 CloseHandle(hChildStderrRdDup);
2505
2506		 f = Py_BuildValue("OO",p1,p2);
2507		 file_count = 2;
2508		 break;
2509	 }
2510
2511	 case POPEN_3:
2512	 {
2513		 char *m1, *m2;
2514		 PyObject *p1, *p2, *p3;
2515
2516		 if (mode && _O_TEXT) {
2517			 m1 = "r";
2518			 m2 = "w";
2519		 } else {
2520			 m1 = "rb";
2521			 m2 = "wb";
2522		 }
2523
2524		 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
2525		 f1 = _fdopen(fd1, m2);
2526		 fd2 = _open_osfhandle((long)hChildStdoutRdDup, mode);
2527		 f2 = _fdopen(fd2, m1);
2528		 fd3 = _open_osfhandle((long)hChildStderrRdDup, mode);
2529		 f3 = _fdopen(fd3, m1);
2530		 p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
2531		 p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose);
2532		 p3 = PyFile_FromFile(f3, cmdstring, m1, _PyPclose);
2533		 PyFile_SetBufSize(p1, 0);
2534		 PyFile_SetBufSize(p2, 0);
2535		 PyFile_SetBufSize(p3, 0);
2536		 f = Py_BuildValue("OOO",p1,p2,p3);
2537		 file_count = 3;
2538		 break;
2539	 }
2540	 }
2541
2542	 if (n == POPEN_4) {
2543		 if (!_PyPopenCreateProcess(cmdstring,
2544					    hChildStdinRd,
2545					    hChildStdoutWr,
2546					    hChildStdoutWr,
2547					    &hProcess))
2548			 return win32_error("CreateProcess", NULL);
2549	 }
2550	 else {
2551		 if (!_PyPopenCreateProcess(cmdstring,
2552					    hChildStdinRd,
2553					    hChildStdoutWr,
2554					    hChildStderrWr,
2555					    &hProcess))
2556			 return win32_error("CreateProcess", NULL);
2557	 }
2558
2559	 /*
2560	  * Insert the files we've created into the process dictionary
2561	  * all referencing the list with the process handle and the
2562	  * initial number of files (see description below in _PyPclose).
2563	  * Since if _PyPclose later tried to wait on a process when all
2564	  * handles weren't closed, it could create a deadlock with the
2565	  * child, we spend some energy here to try to ensure that we
2566	  * either insert all file handles into the dictionary or none
2567	  * at all.  It's a little clumsy with the various popen modes
2568	  * and variable number of files involved.
2569	  */
2570	 if (!_PyPopenProcs) {
2571		 _PyPopenProcs = PyDict_New();
2572	 }
2573
2574	 if (_PyPopenProcs) {
2575		 PyObject *procObj, *hProcessObj, *intObj, *fileObj[3];
2576		 int ins_rc[3];
2577
2578		 fileObj[0] = fileObj[1] = fileObj[2] = NULL;
2579		 ins_rc[0]  = ins_rc[1]  = ins_rc[2]  = 0;
2580
2581		 procObj = PyList_New(2);
2582		 hProcessObj = PyLong_FromVoidPtr(hProcess);
2583		 intObj = PyInt_FromLong(file_count);
2584
2585		 if (procObj && hProcessObj && intObj) {
2586			 PyList_SetItem(procObj,0,hProcessObj);
2587			 PyList_SetItem(procObj,1,intObj);
2588
2589			 fileObj[0] = PyLong_FromVoidPtr(f1);
2590			 if (fileObj[0]) {
2591			    ins_rc[0] = PyDict_SetItem(_PyPopenProcs,
2592						       fileObj[0],
2593						       procObj);
2594			 }
2595			 if (file_count >= 2) {
2596				 fileObj[1] = PyLong_FromVoidPtr(f2);
2597				 if (fileObj[1]) {
2598				    ins_rc[1] = PyDict_SetItem(_PyPopenProcs,
2599							       fileObj[1],
2600							       procObj);
2601				 }
2602			 }
2603			 if (file_count >= 3) {
2604				 fileObj[2] = PyLong_FromVoidPtr(f3);
2605				 if (fileObj[2]) {
2606				    ins_rc[2] = PyDict_SetItem(_PyPopenProcs,
2607							       fileObj[2],
2608							       procObj);
2609				 }
2610			 }
2611
2612			 if (ins_rc[0] < 0 || !fileObj[0] ||
2613			     ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) ||
2614			     ins_rc[2] < 0 || (file_count > 2 && !fileObj[2])) {
2615				 /* Something failed - remove any dictionary
2616				  * entries that did make it.
2617				  */
2618				 if (!ins_rc[0] && fileObj[0]) {
2619					 PyDict_DelItem(_PyPopenProcs,
2620							fileObj[0]);
2621				 }
2622				 if (!ins_rc[1] && fileObj[1]) {
2623					 PyDict_DelItem(_PyPopenProcs,
2624							fileObj[1]);
2625				 }
2626				 if (!ins_rc[2] && fileObj[2]) {
2627					 PyDict_DelItem(_PyPopenProcs,
2628							fileObj[2]);
2629				 }
2630			 }
2631		 }
2632
2633		 /*
2634		  * Clean up our localized references for the dictionary keys
2635		  * and value since PyDict_SetItem will Py_INCREF any copies
2636		  * that got placed in the dictionary.
2637		  */
2638		 Py_XDECREF(procObj);
2639		 Py_XDECREF(fileObj[0]);
2640		 Py_XDECREF(fileObj[1]);
2641		 Py_XDECREF(fileObj[2]);
2642	 }
2643
2644	 /* Child is launched. Close the parents copy of those pipe
2645	  * handles that only the child should have open.  You need to
2646	  * make sure that no handles to the write end of the output pipe
2647	  * are maintained in this process or else the pipe will not close
2648	  * when the child process exits and the ReadFile will hang. */
2649
2650	 if (!CloseHandle(hChildStdinRd))
2651		 return win32_error("CloseHandle", NULL);
2652
2653	 if (!CloseHandle(hChildStdoutWr))
2654		 return win32_error("CloseHandle", NULL);
2655
2656	 if ((n != 4) && (!CloseHandle(hChildStderrWr)))
2657		 return win32_error("CloseHandle", NULL);
2658
2659	 return f;
2660}
2661
2662/*
2663 * Wrapper for fclose() to use for popen* files, so we can retrieve the
2664 * exit code for the child process and return as a result of the close.
2665 *
2666 * This function uses the _PyPopenProcs dictionary in order to map the
2667 * input file pointer to information about the process that was
2668 * originally created by the popen* call that created the file pointer.
2669 * The dictionary uses the file pointer as a key (with one entry
2670 * inserted for each file returned by the original popen* call) and a
2671 * single list object as the value for all files from a single call.
2672 * The list object contains the Win32 process handle at [0], and a file
2673 * count at [1], which is initialized to the total number of file
2674 * handles using that list.
2675 *
2676 * This function closes whichever handle it is passed, and decrements
2677 * the file count in the dictionary for the process handle pointed to
2678 * by this file.  On the last close (when the file count reaches zero),
2679 * this function will wait for the child process and then return its
2680 * exit code as the result of the close() operation.  This permits the
2681 * files to be closed in any order - it is always the close() of the
2682 * final handle that will return the exit code.
2683 */
2684static int _PyPclose(FILE *file)
2685{
2686	int result;
2687	DWORD exit_code;
2688	HANDLE hProcess;
2689	PyObject *procObj, *hProcessObj, *intObj, *fileObj;
2690	long file_count;
2691
2692	/* Close the file handle first, to ensure it can't block the
2693	 * child from exiting if it's the last handle.
2694	 */
2695	result = fclose(file);
2696
2697	if (_PyPopenProcs) {
2698		if ((fileObj = PyLong_FromVoidPtr(file)) != NULL &&
2699		    (procObj = PyDict_GetItem(_PyPopenProcs,
2700					      fileObj)) != NULL &&
2701		    (hProcessObj = PyList_GetItem(procObj,0)) != NULL &&
2702		    (intObj = PyList_GetItem(procObj,1)) != NULL) {
2703
2704			hProcess = PyLong_AsVoidPtr(hProcessObj);
2705			file_count = PyInt_AsLong(intObj);
2706
2707			if (file_count > 1) {
2708				/* Still other files referencing process */
2709				file_count--;
2710				PyList_SetItem(procObj,1,
2711					       PyInt_FromLong(file_count));
2712			} else {
2713				/* Last file for this process */
2714				if (result != EOF &&
2715				    WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED &&
2716				    GetExitCodeProcess(hProcess, &exit_code)) {
2717					/* Possible truncation here in 16-bit environments, but
2718					 * real exit codes are just the lower byte in any event.
2719					 */
2720					result = exit_code;
2721				} else {
2722					/* Indicate failure - this will cause the file object
2723					 * to raise an I/O error and translate the last Win32
2724					 * error code from errno.  We do have a problem with
2725					 * last errors that overlap the normal errno table,
2726					 * but that's a consistent problem with the file object.
2727					 */
2728					if (result != EOF) {
2729						/* If the error wasn't from the fclose(), then
2730						 * set errno for the file object error handling.
2731						 */
2732						errno = GetLastError();
2733					}
2734					result = -1;
2735				}
2736
2737				/* Free up the native handle at this point */
2738				CloseHandle(hProcess);
2739			}
2740
2741			/* Remove this file pointer from dictionary */
2742			PyDict_DelItem(_PyPopenProcs, fileObj);
2743
2744			if (PyDict_Size(_PyPopenProcs) == 0) {
2745				Py_DECREF(_PyPopenProcs);
2746				_PyPopenProcs = NULL;
2747			}
2748
2749		} /* if object retrieval ok */
2750
2751		Py_XDECREF(fileObj);
2752	} /* if _PyPopenProcs */
2753
2754	return result;
2755}
2756#else
2757static PyObject *
2758posix_popen(PyObject *self, PyObject *args)
2759{
2760	char *name;
2761	char *mode = "r";
2762	int bufsize = -1;
2763	FILE *fp;
2764	PyObject *f;
2765	if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
2766		return NULL;
2767	Py_BEGIN_ALLOW_THREADS
2768	fp = popen(name, mode);
2769	Py_END_ALLOW_THREADS
2770	if (fp == NULL)
2771		return posix_error();
2772	f = PyFile_FromFile(fp, name, mode, pclose);
2773	if (f != NULL)
2774		PyFile_SetBufSize(f, bufsize);
2775	return f;
2776}
2777#endif
2778
2779#endif /* HAVE_POPEN */
2780
2781
2782#ifdef HAVE_SETUID
2783static char posix_setuid__doc__[] =
2784"setuid(uid) -> None\n\
2785Set the current process's user id.";
2786static PyObject *
2787posix_setuid(PyObject *self, PyObject *args)
2788{
2789	int uid;
2790	if (!PyArg_ParseTuple(args, "i:setuid", &uid))
2791		return NULL;
2792	if (setuid(uid) < 0)
2793		return posix_error();
2794	Py_INCREF(Py_None);
2795	return Py_None;
2796}
2797#endif /* HAVE_SETUID */
2798
2799
2800#ifdef HAVE_SETEUID
2801static char posix_seteuid__doc__[] =
2802"seteuid(uid) -> None\n\
2803Set the current process's effective user id.";
2804static PyObject *
2805posix_seteuid (PyObject *self, PyObject *args)
2806{
2807	int euid;
2808	if (!PyArg_ParseTuple(args, "i", &euid)) {
2809		return NULL;
2810	} else if (seteuid(euid) < 0) {
2811		return posix_error();
2812	} else {
2813		Py_INCREF(Py_None);
2814		return Py_None;
2815	}
2816}
2817#endif /* HAVE_SETEUID */
2818
2819#ifdef HAVE_SETEGID
2820static char posix_setegid__doc__[] =
2821"setegid(gid) -> None\n\
2822Set the current process's effective group id.";
2823static PyObject *
2824posix_setegid (PyObject *self, PyObject *args)
2825{
2826	int egid;
2827	if (!PyArg_ParseTuple(args, "i", &egid)) {
2828		return NULL;
2829	} else if (setegid(egid) < 0) {
2830		return posix_error();
2831	} else {
2832		Py_INCREF(Py_None);
2833		return Py_None;
2834	}
2835}
2836#endif /* HAVE_SETEGID */
2837
2838#ifdef HAVE_SETREUID
2839static char posix_setreuid__doc__[] =
2840"seteuid(ruid, euid) -> None\n\
2841Set the current process's real and effective user ids.";
2842static PyObject *
2843posix_setreuid (PyObject *self, PyObject *args)
2844{
2845	int ruid, euid;
2846	if (!PyArg_ParseTuple(args, "ii", &ruid, &euid)) {
2847		return NULL;
2848	} else if (setreuid(ruid, euid) < 0) {
2849		return posix_error();
2850	} else {
2851		Py_INCREF(Py_None);
2852		return Py_None;
2853	}
2854}
2855#endif /* HAVE_SETREUID */
2856
2857#ifdef HAVE_SETREGID
2858static char posix_setregid__doc__[] =
2859"setegid(rgid, egid) -> None\n\
2860Set the current process's real and effective group ids.";
2861static PyObject *
2862posix_setregid (PyObject *self, PyObject *args)
2863{
2864	int rgid, egid;
2865	if (!PyArg_ParseTuple(args, "ii", &rgid, &egid)) {
2866		return NULL;
2867	} else if (setregid(rgid, egid) < 0) {
2868		return posix_error();
2869	} else {
2870		Py_INCREF(Py_None);
2871		return Py_None;
2872	}
2873}
2874#endif /* HAVE_SETREGID */
2875
2876#ifdef HAVE_SETGID
2877static char posix_setgid__doc__[] =
2878"setgid(gid) -> None\n\
2879Set the current process's group id.";
2880
2881static PyObject *
2882posix_setgid(PyObject *self, PyObject *args)
2883{
2884	int gid;
2885	if (!PyArg_ParseTuple(args, "i:setgid", &gid))
2886		return NULL;
2887	if (setgid(gid) < 0)
2888		return posix_error();
2889	Py_INCREF(Py_None);
2890	return Py_None;
2891}
2892#endif /* HAVE_SETGID */
2893
2894
2895#ifdef HAVE_WAITPID
2896static char posix_waitpid__doc__[] =
2897"waitpid(pid, options) -> (pid, status)\n\
2898Wait for completion of a give child process.";
2899
2900static PyObject *
2901posix_waitpid(PyObject *self, PyObject *args)
2902{
2903	int pid, options;
2904#ifdef UNION_WAIT
2905	union wait status;
2906#define status_i (status.w_status)
2907#else
2908	int status;
2909#define status_i status
2910#endif
2911	status_i = 0;
2912
2913	if (!PyArg_ParseTuple(args, "ii:waitpid", &pid, &options))
2914		return NULL;
2915	Py_BEGIN_ALLOW_THREADS
2916#ifdef NeXT
2917	pid = wait4(pid, &status, options, NULL);
2918#else
2919	pid = waitpid(pid, &status, options);
2920#endif
2921	Py_END_ALLOW_THREADS
2922	if (pid == -1)
2923		return posix_error();
2924	else
2925		return Py_BuildValue("ii", pid, status_i);
2926}
2927#endif /* HAVE_WAITPID */
2928
2929
2930#ifdef HAVE_WAIT
2931static char posix_wait__doc__[] =
2932"wait() -> (pid, status)\n\
2933Wait for completion of a child process.";
2934
2935static PyObject *
2936posix_wait(PyObject *self, PyObject *args)
2937{
2938	int pid;
2939#ifdef UNION_WAIT
2940	union wait status;
2941#define status_i (status.w_status)
2942#else
2943	int status;
2944#define status_i status
2945#endif
2946        if (!PyArg_ParseTuple(args, ":wait"))
2947                return NULL;
2948	status_i = 0;
2949	Py_BEGIN_ALLOW_THREADS
2950	pid = wait(&status);
2951	Py_END_ALLOW_THREADS
2952	if (pid == -1)
2953		return posix_error();
2954	else
2955		return Py_BuildValue("ii", pid, status_i);
2956#undef status_i
2957}
2958#endif
2959
2960
2961static char posix_lstat__doc__[] =
2962"lstat(path) -> (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\
2963Like stat(path), but do not follow symbolic links.";
2964
2965static PyObject *
2966posix_lstat(PyObject *self, PyObject *args)
2967{
2968#ifdef HAVE_LSTAT
2969	return posix_do_stat(self, args, "s:lstat", lstat);
2970#else /* !HAVE_LSTAT */
2971	return posix_do_stat(self, args, "s:lstat", STAT);
2972#endif /* !HAVE_LSTAT */
2973}
2974
2975
2976#ifdef HAVE_READLINK
2977static char posix_readlink__doc__[] =
2978"readlink(path) -> path\n\
2979Return a string representing the path to which the symbolic link points.";
2980
2981static PyObject *
2982posix_readlink(PyObject *self, PyObject *args)
2983{
2984	char buf[MAXPATHLEN];
2985	char *path;
2986	int n;
2987	if (!PyArg_ParseTuple(args, "s:readlink", &path))
2988		return NULL;
2989	Py_BEGIN_ALLOW_THREADS
2990	n = readlink(path, buf, (int) sizeof buf);
2991	Py_END_ALLOW_THREADS
2992	if (n < 0)
2993		return posix_error_with_filename(path);
2994	return PyString_FromStringAndSize(buf, n);
2995}
2996#endif /* HAVE_READLINK */
2997
2998
2999#ifdef HAVE_SYMLINK
3000static char posix_symlink__doc__[] =
3001"symlink(src, dst) -> None\n\
3002Create a symbolic link.";
3003
3004static PyObject *
3005posix_symlink(PyObject *self, PyObject *args)
3006{
3007	return posix_2str(args, "ss:symlink", symlink);
3008}
3009#endif /* HAVE_SYMLINK */
3010
3011
3012#ifdef HAVE_TIMES
3013#ifndef HZ
3014#define HZ 60 /* Universal constant :-) */
3015#endif /* HZ */
3016
3017#if defined(PYCC_VACPP) && defined(PYOS_OS2)
3018static long
3019system_uptime(void)
3020{
3021    ULONG     value = 0;
3022
3023    Py_BEGIN_ALLOW_THREADS
3024    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value));
3025    Py_END_ALLOW_THREADS
3026
3027    return value;
3028}
3029
3030static PyObject *
3031posix_times(PyObject *self, PyObject *args)
3032{
3033	if (!PyArg_ParseTuple(args, ":times"))
3034		return NULL;
3035
3036    /* Currently Only Uptime is Provided -- Others Later */
3037	return Py_BuildValue("ddddd",
3038			     (double)0 /* t.tms_utime / HZ */,
3039			     (double)0 /* t.tms_stime / HZ */,
3040			     (double)0 /* t.tms_cutime / HZ */,
3041			     (double)0 /* t.tms_cstime / HZ */,
3042			     (double)system_uptime() / 1000);
3043}
3044#else /* not OS2 */
3045static PyObject *
3046posix_times(PyObject *self, PyObject *args)
3047{
3048	struct tms t;
3049	clock_t c;
3050	if (!PyArg_ParseTuple(args, ":times"))
3051		return NULL;
3052	errno = 0;
3053	c = times(&t);
3054	if (c == (clock_t) -1)
3055		return posix_error();
3056	return Py_BuildValue("ddddd",
3057			     (double)t.tms_utime / HZ,
3058			     (double)t.tms_stime / HZ,
3059			     (double)t.tms_cutime / HZ,
3060			     (double)t.tms_cstime / HZ,
3061			     (double)c / HZ);
3062}
3063#endif /* not OS2 */
3064#endif /* HAVE_TIMES */
3065
3066
3067#ifdef MS_WIN32
3068#define HAVE_TIMES	/* so the method table will pick it up */
3069static PyObject *
3070posix_times(PyObject *self, PyObject *args)
3071{
3072	FILETIME create, exit, kernel, user;
3073	HANDLE hProc;
3074	if (!PyArg_ParseTuple(args, ":times"))
3075		return NULL;
3076	hProc = GetCurrentProcess();
3077	GetProcessTimes(hProc, &create, &exit, &kernel, &user);
3078	/* The fields of a FILETIME structure are the hi and lo part
3079	   of a 64-bit value expressed in 100 nanosecond units.
3080	   1e7 is one second in such units; 1e-7 the inverse.
3081	   429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
3082	*/
3083	return Py_BuildValue(
3084		"ddddd",
3085		(double)(kernel.dwHighDateTime*429.4967296 +
3086		         kernel.dwLowDateTime*1e-7),
3087		(double)(user.dwHighDateTime*429.4967296 +
3088		         user.dwLowDateTime*1e-7),
3089		(double)0,
3090		(double)0,
3091		(double)0);
3092}
3093#endif /* MS_WIN32 */
3094
3095#ifdef HAVE_TIMES
3096static char posix_times__doc__[] =
3097"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\
3098Return a tuple of floating point numbers indicating process times.";
3099#endif
3100
3101
3102#ifdef HAVE_SETSID
3103static char posix_setsid__doc__[] =
3104"setsid() -> None\n\
3105Call the system call setsid().";
3106
3107static PyObject *
3108posix_setsid(PyObject *self, PyObject *args)
3109{
3110	if (!PyArg_ParseTuple(args, ":setsid"))
3111		return NULL;
3112	if (setsid() < 0)
3113		return posix_error();
3114	Py_INCREF(Py_None);
3115	return Py_None;
3116}
3117#endif /* HAVE_SETSID */
3118
3119#ifdef HAVE_SETPGID
3120static char posix_setpgid__doc__[] =
3121"setpgid(pid, pgrp) -> None\n\
3122Call the system call setpgid().";
3123
3124static PyObject *
3125posix_setpgid(PyObject *self, PyObject *args)
3126{
3127	int pid, pgrp;
3128	if (!PyArg_ParseTuple(args, "ii:setpgid", &pid, &pgrp))
3129		return NULL;
3130	if (setpgid(pid, pgrp) < 0)
3131		return posix_error();
3132	Py_INCREF(Py_None);
3133	return Py_None;
3134}
3135#endif /* HAVE_SETPGID */
3136
3137
3138#ifdef HAVE_TCGETPGRP
3139static char posix_tcgetpgrp__doc__[] =
3140"tcgetpgrp(fd) -> pgid\n\
3141Return the process group associated with the terminal given by a fd.";
3142
3143static PyObject *
3144posix_tcgetpgrp(PyObject *self, PyObject *args)
3145{
3146	int fd, pgid;
3147	if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
3148		return NULL;
3149	pgid = tcgetpgrp(fd);
3150	if (pgid < 0)
3151		return posix_error();
3152	return PyInt_FromLong((long)pgid);
3153}
3154#endif /* HAVE_TCGETPGRP */
3155
3156
3157#ifdef HAVE_TCSETPGRP
3158static char posix_tcsetpgrp__doc__[] =
3159"tcsetpgrp(fd, pgid) -> None\n\
3160Set the process group associated with the terminal given by a fd.";
3161
3162static PyObject *
3163posix_tcsetpgrp(PyObject *self, PyObject *args)
3164{
3165	int fd, pgid;
3166	if (!PyArg_ParseTuple(args, "ii:tcsetpgrp", &fd, &pgid))
3167		return NULL;
3168	if (tcsetpgrp(fd, pgid) < 0)
3169		return posix_error();
3170	Py_INCREF(Py_None);
3171	return Py_None;
3172}
3173#endif /* HAVE_TCSETPGRP */
3174
3175/* Functions acting on file descriptors */
3176
3177static char posix_open__doc__[] =
3178"open(filename, flag [, mode=0777]) -> fd\n\
3179Open a file (for low level IO).";
3180
3181static PyObject *
3182posix_open(PyObject *self, PyObject *args)
3183{
3184	char *file;
3185	int flag;
3186	int mode = 0777;
3187	int fd;
3188	if (!PyArg_ParseTuple(args, "si|i", &file, &flag, &mode))
3189		return NULL;
3190
3191	Py_BEGIN_ALLOW_THREADS
3192	fd = open(file, flag, mode);
3193	Py_END_ALLOW_THREADS
3194	if (fd < 0)
3195		return posix_error_with_filename(file);
3196	return PyInt_FromLong((long)fd);
3197}
3198
3199
3200static char posix_close__doc__[] =
3201"close(fd) -> None\n\
3202Close a file descriptor (for low level IO).";
3203
3204static PyObject *
3205posix_close(PyObject *self, PyObject *args)
3206{
3207	int fd, res;
3208	if (!PyArg_ParseTuple(args, "i:close", &fd))
3209		return NULL;
3210	Py_BEGIN_ALLOW_THREADS
3211	res = close(fd);
3212	Py_END_ALLOW_THREADS
3213	if (res < 0)
3214		return posix_error();
3215	Py_INCREF(Py_None);
3216	return Py_None;
3217}
3218
3219
3220static char posix_dup__doc__[] =
3221"dup(fd) -> fd2\n\
3222Return a duplicate of a file descriptor.";
3223
3224static PyObject *
3225posix_dup(PyObject *self, PyObject *args)
3226{
3227	int fd;
3228	if (!PyArg_ParseTuple(args, "i:dup", &fd))
3229		return NULL;
3230	Py_BEGIN_ALLOW_THREADS
3231	fd = dup(fd);
3232	Py_END_ALLOW_THREADS
3233	if (fd < 0)
3234		return posix_error();
3235	return PyInt_FromLong((long)fd);
3236}
3237
3238
3239static char posix_dup2__doc__[] =
3240"dup2(fd, fd2) -> None\n\
3241Duplicate file descriptor.";
3242
3243static PyObject *
3244posix_dup2(PyObject *self, PyObject *args)
3245{
3246	int fd, fd2, res;
3247	if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
3248		return NULL;
3249	Py_BEGIN_ALLOW_THREADS
3250	res = dup2(fd, fd2);
3251	Py_END_ALLOW_THREADS
3252	if (res < 0)
3253		return posix_error();
3254	Py_INCREF(Py_None);
3255	return Py_None;
3256}
3257
3258
3259static char posix_lseek__doc__[] =
3260"lseek(fd, pos, how) -> newpos\n\
3261Set the current position of a file descriptor.";
3262
3263static PyObject *
3264posix_lseek(PyObject *self, PyObject *args)
3265{
3266	int fd, how;
3267#ifdef MS_WIN64
3268	LONG_LONG pos, res;
3269#else
3270	off_t pos, res;
3271#endif
3272	PyObject *posobj;
3273	if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
3274		return NULL;
3275#ifdef SEEK_SET
3276	/* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
3277	switch (how) {
3278	case 0: how = SEEK_SET; break;
3279	case 1: how = SEEK_CUR; break;
3280	case 2: how = SEEK_END; break;
3281	}
3282#endif /* SEEK_END */
3283
3284#if !defined(HAVE_LARGEFILE_SUPPORT)
3285	pos = PyInt_AsLong(posobj);
3286#else
3287	pos = PyLong_Check(posobj) ?
3288		PyLong_AsLongLong(posobj) : PyInt_AsLong(posobj);
3289#endif
3290	if (PyErr_Occurred())
3291		return NULL;
3292
3293	Py_BEGIN_ALLOW_THREADS
3294#ifdef MS_WIN64
3295	res = _lseeki64(fd, pos, how);
3296#else
3297	res = lseek(fd, pos, how);
3298#endif
3299	Py_END_ALLOW_THREADS
3300	if (res < 0)
3301		return posix_error();
3302
3303#if !defined(HAVE_LARGEFILE_SUPPORT)
3304	return PyInt_FromLong(res);
3305#else
3306	return PyLong_FromLongLong(res);
3307#endif
3308}
3309
3310
3311static char posix_read__doc__[] =
3312"read(fd, buffersize) -> string\n\
3313Read a file descriptor.";
3314
3315static PyObject *
3316posix_read(PyObject *self, PyObject *args)
3317{
3318	int fd, size, n;
3319	PyObject *buffer;
3320	if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
3321		return NULL;
3322	buffer = PyString_FromStringAndSize((char *)NULL, size);
3323	if (buffer == NULL)
3324		return NULL;
3325	Py_BEGIN_ALLOW_THREADS
3326	n = read(fd, PyString_AsString(buffer), size);
3327	Py_END_ALLOW_THREADS
3328	if (n < 0) {
3329		Py_DECREF(buffer);
3330		return posix_error();
3331	}
3332	if (n != size)
3333		_PyString_Resize(&buffer, n);
3334	return buffer;
3335}
3336
3337
3338static char posix_write__doc__[] =
3339"write(fd, string) -> byteswritten\n\
3340Write a string to a file descriptor.";
3341
3342static PyObject *
3343posix_write(PyObject *self, PyObject *args)
3344{
3345	int fd, size;
3346	char *buffer;
3347	if (!PyArg_ParseTuple(args, "is#:write", &fd, &buffer, &size))
3348		return NULL;
3349	Py_BEGIN_ALLOW_THREADS
3350	size = write(fd, buffer, size);
3351	Py_END_ALLOW_THREADS
3352	if (size < 0)
3353		return posix_error();
3354	return PyInt_FromLong((long)size);
3355}
3356
3357
3358static char posix_fstat__doc__[]=
3359"fstat(fd) -> (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
3360Like stat(), but for an open file descriptor.";
3361
3362static PyObject *
3363posix_fstat(PyObject *self, PyObject *args)
3364{
3365	int fd;
3366	STRUCT_STAT st;
3367	int res;
3368	if (!PyArg_ParseTuple(args, "i:fstat", &fd))
3369		return NULL;
3370	Py_BEGIN_ALLOW_THREADS
3371	res = FSTAT(fd, &st);
3372	Py_END_ALLOW_THREADS
3373	if (res != 0)
3374		return posix_error();
3375
3376	return _pystat_fromstructstat(st);
3377}
3378
3379
3380static char posix_fdopen__doc__[] =
3381"fdopen(fd, [, mode='r' [, bufsize]]) -> file_object\n\
3382Return an open file object connected to a file descriptor.";
3383
3384static PyObject *
3385posix_fdopen(PyObject *self, PyObject *args)
3386{
3387	int fd;
3388	char *mode = "r";
3389	int bufsize = -1;
3390	FILE *fp;
3391	PyObject *f;
3392	if (!PyArg_ParseTuple(args, "i|si", &fd, &mode, &bufsize))
3393		return NULL;
3394
3395	Py_BEGIN_ALLOW_THREADS
3396	fp = fdopen(fd, mode);
3397	Py_END_ALLOW_THREADS
3398	if (fp == NULL)
3399		return posix_error();
3400	f = PyFile_FromFile(fp, "(fdopen)", mode, fclose);
3401	if (f != NULL)
3402		PyFile_SetBufSize(f, bufsize);
3403	return f;
3404}
3405
3406static char posix_isatty__doc__[] =
3407"isatty(fd) -> Boolean\n\
3408Return true if the file descriptor 'fd' is an open file descriptor\n\
3409connected to a terminal.";
3410
3411static PyObject *
3412posix_isatty(PyObject *self, PyObject *args)
3413{
3414	int fd;
3415	if (!PyArg_ParseTuple(args, "i:isatty", &fd))
3416		return NULL;
3417	return Py_BuildValue("i", isatty(fd));
3418}
3419
3420#ifdef HAVE_PIPE
3421static char posix_pipe__doc__[] =
3422"pipe() -> (read_end, write_end)\n\
3423Create a pipe.";
3424
3425static PyObject *
3426posix_pipe(PyObject *self, PyObject *args)
3427{
3428#if defined(PYOS_OS2)
3429    HFILE read, write;
3430    APIRET rc;
3431
3432    if (!PyArg_ParseTuple(args, ":pipe"))
3433        return NULL;
3434
3435	Py_BEGIN_ALLOW_THREADS
3436    rc = DosCreatePipe( &read, &write, 4096);
3437	Py_END_ALLOW_THREADS
3438    if (rc != NO_ERROR)
3439        return os2_error(rc);
3440
3441    return Py_BuildValue("(ii)", read, write);
3442#else
3443#if !defined(MS_WIN32)
3444	int fds[2];
3445	int res;
3446	if (!PyArg_ParseTuple(args, ":pipe"))
3447		return NULL;
3448	Py_BEGIN_ALLOW_THREADS
3449	res = pipe(fds);
3450	Py_END_ALLOW_THREADS
3451	if (res != 0)
3452		return posix_error();
3453	return Py_BuildValue("(ii)", fds[0], fds[1]);
3454#else /* MS_WIN32 */
3455	HANDLE read, write;
3456	int read_fd, write_fd;
3457	BOOL ok;
3458	if (!PyArg_ParseTuple(args, ":pipe"))
3459		return NULL;
3460	Py_BEGIN_ALLOW_THREADS
3461	ok = CreatePipe(&read, &write, NULL, 0);
3462	Py_END_ALLOW_THREADS
3463	if (!ok)
3464		return win32_error("CreatePipe", NULL);
3465	read_fd = _open_osfhandle((intptr_t)read, 0);
3466	write_fd = _open_osfhandle((intptr_t)write, 1);
3467	return Py_BuildValue("(ii)", read_fd, write_fd);
3468#endif /* MS_WIN32 */
3469#endif
3470}
3471#endif  /* HAVE_PIPE */
3472
3473
3474#ifdef HAVE_MKFIFO
3475static char posix_mkfifo__doc__[] =
3476"mkfifo(file, [, mode=0666]) -> None\n\
3477Create a FIFO (a POSIX named pipe).";
3478
3479static PyObject *
3480posix_mkfifo(PyObject *self, PyObject *args)
3481{
3482	char *file;
3483	int mode = 0666;
3484	int res;
3485	if (!PyArg_ParseTuple(args, "s|i:mkfifo", &file, &mode))
3486		return NULL;
3487	Py_BEGIN_ALLOW_THREADS
3488	res = mkfifo(file, mode);
3489	Py_END_ALLOW_THREADS
3490	if (res < 0)
3491		return posix_error();
3492	Py_INCREF(Py_None);
3493	return Py_None;
3494}
3495#endif
3496
3497
3498#ifdef HAVE_FTRUNCATE
3499static char posix_ftruncate__doc__[] =
3500"ftruncate(fd, length) -> None\n\
3501Truncate a file to a specified length.";
3502
3503static PyObject *
3504posix_ftruncate(PyObject *self, PyObject *args)
3505{
3506	int fd;
3507	off_t length;
3508	int res;
3509	PyObject *lenobj;
3510
3511	if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj))
3512		return NULL;
3513
3514#if !defined(HAVE_LARGEFILE_SUPPORT)
3515	length = PyInt_AsLong(lenobj);
3516#else
3517	length = PyLong_Check(lenobj) ?
3518		PyLong_AsLongLong(lenobj) : PyInt_AsLong(lenobj);
3519#endif
3520	if (PyErr_Occurred())
3521		return NULL;
3522
3523	Py_BEGIN_ALLOW_THREADS
3524	res = ftruncate(fd, length);
3525	Py_END_ALLOW_THREADS
3526	if (res < 0) {
3527		PyErr_SetFromErrno(PyExc_IOError);
3528		return NULL;
3529	}
3530	Py_INCREF(Py_None);
3531	return Py_None;
3532}
3533#endif
3534
3535#ifdef NeXT
3536#define HAVE_PUTENV
3537/* Steve Spicklemire got this putenv from NeXTAnswers */
3538static int
3539putenv(char *newval)
3540{
3541	extern char **environ;
3542
3543	static int firstTime = 1;
3544	char **ep;
3545	char *cp;
3546	int esiz;
3547	char *np;
3548
3549	if (!(np = strchr(newval, '=')))
3550		return 1;
3551	*np = '\0';
3552
3553	/* look it up */
3554	for (ep=environ ; *ep ; ep++)
3555	{
3556		/* this should always be true... */
3557		if (cp = strchr(*ep, '='))
3558		{
3559			*cp = '\0';
3560			if (!strcmp(*ep, newval))
3561			{
3562				/* got it! */
3563				*cp = '=';
3564				break;
3565			}
3566			*cp = '=';
3567		}
3568		else
3569		{
3570			*np = '=';
3571			return 1;
3572		}
3573	}
3574
3575	*np = '=';
3576	if (*ep)
3577	{
3578		/* the string was already there:
3579		   just replace it with the new one */
3580		*ep = newval;
3581		return 0;
3582	}
3583
3584	/* expand environ by one */
3585	for (esiz=2, ep=environ ; *ep ; ep++)
3586		esiz++;
3587	if (firstTime)
3588	{
3589		char **epp;
3590		char **newenv;
3591		if (!(newenv = malloc(esiz * sizeof(char *))))
3592			return 1;
3593
3594		for (ep=environ, epp=newenv ; *ep ;)
3595			*epp++ = *ep++;
3596		*epp++ = newval;
3597		*epp = (char *) 0;
3598		environ = newenv;
3599	}
3600	else
3601	{
3602		if (!(environ = realloc(environ, esiz * sizeof(char *))))
3603			return 1;
3604		environ[esiz - 2] = newval;
3605		environ[esiz - 1] = (char *) 0;
3606		firstTime = 0;
3607	}
3608
3609	return 0;
3610}
3611#endif /* NeXT */
3612
3613
3614#ifdef HAVE_PUTENV
3615static char posix_putenv__doc__[] =
3616"putenv(key, value) -> None\n\
3617Change or add an environment variable.";
3618
3619#ifdef __BEOS__
3620/* We have putenv(), but not in the headers (as of PR2). - [cjh] */
3621int putenv( const char *str );
3622#endif
3623
3624/* Save putenv() parameters as values here, so we can collect them when they
3625 * get re-set with another call for the same key. */
3626static PyObject *posix_putenv_garbage;
3627
3628static PyObject *
3629posix_putenv(PyObject *self, PyObject *args)
3630{
3631        char *s1, *s2;
3632        char *new;
3633	PyObject *newstr;
3634
3635	if (!PyArg_ParseTuple(args, "ss:putenv", &s1, &s2))
3636		return NULL;
3637
3638#if defined(PYOS_OS2)
3639    if (stricmp(s1, "BEGINLIBPATH") == 0) {
3640        APIRET rc;
3641
3642        if (strlen(s2) == 0)  /* If New Value is an Empty String */
3643            s2 = NULL;        /* Then OS/2 API Wants a NULL to Undefine It */
3644
3645        rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH);
3646        if (rc != NO_ERROR)
3647            return os2_error(rc);
3648
3649    } else if (stricmp(s1, "ENDLIBPATH") == 0) {
3650        APIRET rc;
3651
3652        if (strlen(s2) == 0)  /* If New Value is an Empty String */
3653            s2 = NULL;        /* Then OS/2 API Wants a NULL to Undefine It */
3654
3655        rc = DosSetExtLIBPATH(s2, END_LIBPATH);
3656        if (rc != NO_ERROR)
3657            return os2_error(rc);
3658    } else {
3659#endif
3660
3661	/* XXX This can leak memory -- not easy to fix :-( */
3662	newstr = PyString_FromStringAndSize(NULL, strlen(s1) + strlen(s2) + 2);
3663	if (newstr == NULL)
3664		return PyErr_NoMemory();
3665	new = PyString_AS_STRING(newstr);
3666	(void) sprintf(new, "%s=%s", s1, s2);
3667	if (putenv(new)) {
3668                posix_error();
3669                return NULL;
3670	}
3671	/* Install the first arg and newstr in posix_putenv_garbage;
3672	 * this will cause previous value to be collected.  This has to
3673	 * happen after the real putenv() call because the old value
3674	 * was still accessible until then. */
3675	if (PyDict_SetItem(posix_putenv_garbage,
3676			   PyTuple_GET_ITEM(args, 0), newstr)) {
3677		/* really not much we can do; just leak */
3678		PyErr_Clear();
3679	}
3680	else {
3681		Py_DECREF(newstr);
3682	}
3683
3684#if defined(PYOS_OS2)
3685    }
3686#endif
3687	Py_INCREF(Py_None);
3688        return Py_None;
3689}
3690#endif /* putenv */
3691
3692#ifdef HAVE_STRERROR
3693static char posix_strerror__doc__[] =
3694"strerror(code) -> string\n\
3695Translate an error code to a message string.";
3696
3697PyObject *
3698posix_strerror(PyObject *self, PyObject *args)
3699{
3700	int code;
3701	char *message;
3702	if (!PyArg_ParseTuple(args, "i:strerror", &code))
3703		return NULL;
3704	message = strerror(code);
3705	if (message == NULL) {
3706		PyErr_SetString(PyExc_ValueError,
3707				"strerror code out of range");
3708		return NULL;
3709	}
3710	return PyString_FromString(message);
3711}
3712#endif /* strerror */
3713
3714
3715#ifdef HAVE_SYS_WAIT_H
3716
3717#ifdef WIFSTOPPED
3718static char posix_WIFSTOPPED__doc__[] =
3719"WIFSTOPPED(status) -> Boolean\n\
3720Return true if the process returning 'status' was stopped.";
3721
3722static PyObject *
3723posix_WIFSTOPPED(PyObject *self, PyObject *args)
3724{
3725#ifdef UNION_WAIT
3726	union wait status;
3727#define status_i (status.w_status)
3728#else
3729	int status;
3730#define status_i status
3731#endif
3732	status_i = 0;
3733
3734	if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &status_i))
3735	{
3736		return NULL;
3737	}
3738
3739	return Py_BuildValue("i", WIFSTOPPED(status));
3740#undef status_i
3741}
3742#endif /* WIFSTOPPED */
3743
3744#ifdef WIFSIGNALED
3745static char posix_WIFSIGNALED__doc__[] =
3746"WIFSIGNALED(status) -> Boolean\n\
3747Return true if the process returning 'status' was terminated by a signal.";
3748
3749static PyObject *
3750posix_WIFSIGNALED(PyObject *self, PyObject *args)
3751{
3752#ifdef UNION_WAIT
3753	union wait status;
3754#define status_i (status.w_status)
3755#else
3756	int status;
3757#define status_i status
3758#endif
3759	status_i = 0;
3760
3761	if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &status_i))
3762	{
3763		return NULL;
3764	}
3765
3766	return Py_BuildValue("i", WIFSIGNALED(status));
3767#undef status_i
3768}
3769#endif /* WIFSIGNALED */
3770
3771#ifdef WIFEXITED
3772static char posix_WIFEXITED__doc__[] =
3773"WIFEXITED(status) -> Boolean\n\
3774Return true if the process returning 'status' exited using the exit()\n\
3775system call.";
3776
3777static PyObject *
3778posix_WIFEXITED(PyObject *self, PyObject *args)
3779{
3780#ifdef UNION_WAIT
3781	union wait status;
3782#define status_i (status.w_status)
3783#else
3784	int status;
3785#define status_i status
3786#endif
3787	status_i = 0;
3788
3789	if (!PyArg_ParseTuple(args, "i:WIFEXITED", &status_i))
3790	{
3791		return NULL;
3792	}
3793
3794	return Py_BuildValue("i", WIFEXITED(status));
3795#undef status_i
3796}
3797#endif /* WIFEXITED */
3798
3799#ifdef WEXITSTATUS
3800static char posix_WEXITSTATUS__doc__[] =
3801"WEXITSTATUS(status) -> integer\n\
3802Return the process return code from 'status'.";
3803
3804static PyObject *
3805posix_WEXITSTATUS(PyObject *self, PyObject *args)
3806{
3807#ifdef UNION_WAIT
3808	union wait status;
3809#define status_i (status.w_status)
3810#else
3811	int status;
3812#define status_i status
3813#endif
3814	status_i = 0;
3815
3816	if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &status_i))
3817	{
3818		return NULL;
3819	}
3820
3821	return Py_BuildValue("i", WEXITSTATUS(status));
3822#undef status_i
3823}
3824#endif /* WEXITSTATUS */
3825
3826#ifdef WTERMSIG
3827static char posix_WTERMSIG__doc__[] =
3828"WTERMSIG(status) -> integer\n\
3829Return the signal that terminated the process that provided the 'status'\n\
3830value.";
3831
3832static PyObject *
3833posix_WTERMSIG(PyObject *self, PyObject *args)
3834{
3835#ifdef UNION_WAIT
3836	union wait status;
3837#define status_i (status.w_status)
3838#else
3839	int status;
3840#define status_i status
3841#endif
3842	status_i = 0;
3843
3844	if (!PyArg_ParseTuple(args, "i:WTERMSIG", &status_i))
3845	{
3846		return NULL;
3847	}
3848
3849	return Py_BuildValue("i", WTERMSIG(status));
3850#undef status_i
3851}
3852#endif /* WTERMSIG */
3853
3854#ifdef WSTOPSIG
3855static char posix_WSTOPSIG__doc__[] =
3856"WSTOPSIG(status) -> integer\n\
3857Return the signal that stopped the process that provided the 'status' value.";
3858
3859static PyObject *
3860posix_WSTOPSIG(PyObject *self, PyObject *args)
3861{
3862#ifdef UNION_WAIT
3863	union wait status;
3864#define status_i (status.w_status)
3865#else
3866	int status;
3867#define status_i status
3868#endif
3869	status_i = 0;
3870
3871	if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &status_i))
3872	{
3873		return NULL;
3874	}
3875
3876	return Py_BuildValue("i", WSTOPSIG(status));
3877#undef status_i
3878}
3879#endif /* WSTOPSIG */
3880
3881#endif /* HAVE_SYS_WAIT_H */
3882
3883
3884#if defined(HAVE_FSTATVFS)
3885#ifdef _SCO_DS
3886/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
3887   needed definitions in sys/statvfs.h */
3888#define _SVID3
3889#endif
3890#include <sys/statvfs.h>
3891
3892static char posix_fstatvfs__doc__[] =
3893"fstatvfs(fd) -> \n\
3894 (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax)\n\
3895Perform an fstatvfs system call on the given fd.";
3896
3897static PyObject *
3898posix_fstatvfs(PyObject *self, PyObject *args)
3899{
3900	int fd, res;
3901	struct statvfs st;
3902	if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
3903		return NULL;
3904	Py_BEGIN_ALLOW_THREADS
3905	res = fstatvfs(fd, &st);
3906	Py_END_ALLOW_THREADS
3907	if (res != 0)
3908		return posix_error();
3909#if !defined(HAVE_LARGEFILE_SUPPORT)
3910	return Py_BuildValue("(llllllllll)",
3911		    (long) st.f_bsize,
3912		    (long) st.f_frsize,
3913		    (long) st.f_blocks,
3914		    (long) st.f_bfree,
3915		    (long) st.f_bavail,
3916		    (long) st.f_files,
3917		    (long) st.f_ffree,
3918		    (long) st.f_favail,
3919		    (long) st.f_flag,
3920		    (long) st.f_namemax);
3921#else
3922	return Py_BuildValue("(llLLLLLLll)",
3923		    (long) st.f_bsize,
3924		    (long) st.f_frsize,
3925		    (LONG_LONG) st.f_blocks,
3926		    (LONG_LONG) st.f_bfree,
3927		    (LONG_LONG) st.f_bavail,
3928		    (LONG_LONG) st.f_files,
3929		    (LONG_LONG) st.f_ffree,
3930		    (LONG_LONG) st.f_favail,
3931		    (long) st.f_flag,
3932		    (long) st.f_namemax);
3933#endif
3934}
3935#endif /* HAVE_FSTATVFS */
3936
3937
3938#if defined(HAVE_STATVFS)
3939#include <sys/statvfs.h>
3940
3941static char posix_statvfs__doc__[] =
3942"statvfs(path) -> \n\
3943 (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax)\n\
3944Perform a statvfs system call on the given path.";
3945
3946static PyObject *
3947posix_statvfs(PyObject *self, PyObject *args)
3948{
3949	char *path;
3950	int res;
3951	struct statvfs st;
3952	if (!PyArg_ParseTuple(args, "s:statvfs", &path))
3953		return NULL;
3954	Py_BEGIN_ALLOW_THREADS
3955	res = statvfs(path, &st);
3956	Py_END_ALLOW_THREADS
3957	if (res != 0)
3958		return posix_error_with_filename(path);
3959#if !defined(HAVE_LARGEFILE_SUPPORT)
3960	return Py_BuildValue("(llllllllll)",
3961		    (long) st.f_bsize,
3962		    (long) st.f_frsize,
3963		    (long) st.f_blocks,
3964		    (long) st.f_bfree,
3965		    (long) st.f_bavail,
3966		    (long) st.f_files,
3967		    (long) st.f_ffree,
3968		    (long) st.f_favail,
3969		    (long) st.f_flag,
3970		    (long) st.f_namemax);
3971#else	/* HAVE_LARGEFILE_SUPPORT */
3972	return Py_BuildValue("(llLLLLLLll)",
3973		    (long) st.f_bsize,
3974		    (long) st.f_frsize,
3975		    (LONG_LONG) st.f_blocks,
3976		    (LONG_LONG) st.f_bfree,
3977		    (LONG_LONG) st.f_bavail,
3978		    (LONG_LONG) st.f_files,
3979		    (LONG_LONG) st.f_ffree,
3980		    (LONG_LONG) st.f_favail,
3981		    (long) st.f_flag,
3982		    (long) st.f_namemax);
3983#endif
3984}
3985#endif /* HAVE_STATVFS */
3986
3987
3988#ifdef HAVE_TEMPNAM
3989static char posix_tempnam__doc__[] = "\
3990tempnam([dir[, prefix]]) -> string\n\
3991Return a unique name for a temporary file.\n\
3992The directory and a short may be specified as strings; they may be omitted\n\
3993or None if not needed.";
3994
3995static PyObject *
3996posix_tempnam(PyObject *self, PyObject *args)
3997{
3998    PyObject *result = NULL;
3999    char *dir = NULL;
4000    char *pfx = NULL;
4001    char *name;
4002
4003    if (!PyArg_ParseTuple(args, "|zz:tempnam", &dir, &pfx))
4004        return NULL;
4005    name = tempnam(dir, pfx);
4006    if (name == NULL)
4007        return PyErr_NoMemory();
4008    result = PyString_FromString(name);
4009    free(name);
4010    return result;
4011}
4012#endif
4013
4014
4015#ifdef HAVE_TMPFILE
4016static char posix_tmpfile__doc__[] = "\
4017tmpfile() -> file object\n\
4018Create a temporary file with no directory entries.";
4019
4020static PyObject *
4021posix_tmpfile(PyObject *self, PyObject *args)
4022{
4023    FILE *fp;
4024
4025    if (!PyArg_ParseTuple(args, ":tmpfile"))
4026        return NULL;
4027    fp = tmpfile();
4028    if (fp == NULL)
4029        return posix_error();
4030    return PyFile_FromFile(fp, "<tmpfile>", "w+", fclose);
4031}
4032#endif
4033
4034
4035#ifdef HAVE_TMPNAM
4036static char posix_tmpnam__doc__[] = "\
4037tmpnam() -> string\n\
4038Return a unique name for a temporary file.";
4039
4040static PyObject *
4041posix_tmpnam(PyObject *self, PyObject *args)
4042{
4043    char buffer[L_tmpnam];
4044    char *name;
4045
4046    if (!PyArg_ParseTuple(args, ":tmpnam"))
4047        return NULL;
4048#ifdef USE_TMPNAM_R
4049    name = tmpnam_r(buffer);
4050#else
4051    name = tmpnam(buffer);
4052#endif
4053    if (name == NULL) {
4054        PyErr_SetObject(PyExc_OSError,
4055                        Py_BuildValue("is", 0,
4056#ifdef USE_TMPNAM_R
4057                                      "unexpected NULL from tmpnam_r"
4058#else
4059                                      "unexpected NULL from tmpnam"
4060#endif
4061                                      ));
4062        return NULL;
4063    }
4064    return PyString_FromString(buffer);
4065}
4066#endif
4067
4068
4069/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
4070 * It maps strings representing configuration variable names to
4071 * integer values, allowing those functions to be called with the
4072 * magic names instead of polluting the module's namespace with tons of
4073 * rarely-used constants.  There are three separate tables that use
4074 * these definitions.
4075 *
4076 * This code is always included, even if none of the interfaces that
4077 * need it are included.  The #if hackery needed to avoid it would be
4078 * sufficiently pervasive that it's not worth the loss of readability.
4079 */
4080struct constdef {
4081    char *name;
4082    long value;
4083};
4084
4085static int
4086conv_confname(PyObject *arg, int *valuep, struct constdef *table,
4087	      size_t tablesize)
4088{
4089    if (PyInt_Check(arg)) {
4090        *valuep = PyInt_AS_LONG(arg);
4091        return 1;
4092    }
4093    if (PyString_Check(arg)) {
4094        /* look up the value in the table using a binary search */
4095        size_t lo = 0;
4096		size_t mid;
4097        size_t hi = tablesize;
4098        int cmp;
4099        char *confname = PyString_AS_STRING(arg);
4100        while (lo < hi) {
4101            mid = (lo + hi) / 2;
4102            cmp = strcmp(confname, table[mid].name);
4103            if (cmp < 0)
4104                hi = mid;
4105            else if (cmp > 0)
4106                lo = mid + 1;
4107            else {
4108                *valuep = table[mid].value;
4109                return 1;
4110            }
4111        }
4112        PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
4113    }
4114    else
4115        PyErr_SetString(PyExc_TypeError,
4116                        "configuration names must be strings or integers");
4117    return 0;
4118}
4119
4120
4121#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
4122static struct constdef  posix_constants_pathconf[] = {
4123#ifdef _PC_ABI_AIO_XFER_MAX
4124    {"PC_ABI_AIO_XFER_MAX",	_PC_ABI_AIO_XFER_MAX},
4125#endif
4126#ifdef _PC_ABI_ASYNC_IO
4127    {"PC_ABI_ASYNC_IO",	_PC_ABI_ASYNC_IO},
4128#endif
4129#ifdef _PC_ASYNC_IO
4130    {"PC_ASYNC_IO",	_PC_ASYNC_IO},
4131#endif
4132#ifdef _PC_CHOWN_RESTRICTED
4133    {"PC_CHOWN_RESTRICTED",	_PC_CHOWN_RESTRICTED},
4134#endif
4135#ifdef _PC_FILESIZEBITS
4136    {"PC_FILESIZEBITS",	_PC_FILESIZEBITS},
4137#endif
4138#ifdef _PC_LAST
4139    {"PC_LAST",	_PC_LAST},
4140#endif
4141#ifdef _PC_LINK_MAX
4142    {"PC_LINK_MAX",	_PC_LINK_MAX},
4143#endif
4144#ifdef _PC_MAX_CANON
4145    {"PC_MAX_CANON",	_PC_MAX_CANON},
4146#endif
4147#ifdef _PC_MAX_INPUT
4148    {"PC_MAX_INPUT",	_PC_MAX_INPUT},
4149#endif
4150#ifdef _PC_NAME_MAX
4151    {"PC_NAME_MAX",	_PC_NAME_MAX},
4152#endif
4153#ifdef _PC_NO_TRUNC
4154    {"PC_NO_TRUNC",	_PC_NO_TRUNC},
4155#endif
4156#ifdef _PC_PATH_MAX
4157    {"PC_PATH_MAX",	_PC_PATH_MAX},
4158#endif
4159#ifdef _PC_PIPE_BUF
4160    {"PC_PIPE_BUF",	_PC_PIPE_BUF},
4161#endif
4162#ifdef _PC_PRIO_IO
4163    {"PC_PRIO_IO",	_PC_PRIO_IO},
4164#endif
4165#ifdef _PC_SOCK_MAXBUF
4166    {"PC_SOCK_MAXBUF",	_PC_SOCK_MAXBUF},
4167#endif
4168#ifdef _PC_SYNC_IO
4169    {"PC_SYNC_IO",	_PC_SYNC_IO},
4170#endif
4171#ifdef _PC_VDISABLE
4172    {"PC_VDISABLE",	_PC_VDISABLE},
4173#endif
4174};
4175
4176static int
4177conv_path_confname(PyObject *arg, int *valuep)
4178{
4179    return conv_confname(arg, valuep, posix_constants_pathconf,
4180                         sizeof(posix_constants_pathconf)
4181                           / sizeof(struct constdef));
4182}
4183#endif
4184
4185#ifdef HAVE_FPATHCONF
4186static char posix_fpathconf__doc__[] = "\
4187fpathconf(fd, name) -> integer\n\
4188Return the configuration limit name for the file descriptor fd.\n\
4189If there is no limit, return -1.";
4190
4191static PyObject *
4192posix_fpathconf(PyObject *self, PyObject *args)
4193{
4194    PyObject *result = NULL;
4195    int name, fd;
4196
4197    if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
4198                         conv_path_confname, &name)) {
4199        long limit;
4200
4201        errno = 0;
4202        limit = fpathconf(fd, name);
4203        if (limit == -1 && errno != 0)
4204            posix_error();
4205        else
4206            result = PyInt_FromLong(limit);
4207    }
4208    return result;
4209}
4210#endif
4211
4212
4213#ifdef HAVE_PATHCONF
4214static char posix_pathconf__doc__[] = "\
4215pathconf(path, name) -> integer\n\
4216Return the configuration limit name for the file or directory path.\n\
4217If there is no limit, return -1.";
4218
4219static PyObject *
4220posix_pathconf(PyObject *self, PyObject *args)
4221{
4222    PyObject *result = NULL;
4223    int name;
4224    char *path;
4225
4226    if (PyArg_ParseTuple(args, "sO&:pathconf", &path,
4227                         conv_path_confname, &name)) {
4228        long limit;
4229
4230        errno = 0;
4231        limit = pathconf(path, name);
4232        if (limit == -1 && errno != 0) {
4233            if (errno == EINVAL)
4234                /* could be a path or name problem */
4235                posix_error();
4236            else
4237                posix_error_with_filename(path);
4238        }
4239        else
4240            result = PyInt_FromLong(limit);
4241    }
4242    return result;
4243}
4244#endif
4245
4246#ifdef HAVE_CONFSTR
4247static struct constdef posix_constants_confstr[] = {
4248#ifdef _CS_ARCHITECTURE
4249    {"CS_ARCHITECTURE",	_CS_ARCHITECTURE},
4250#endif
4251#ifdef _CS_HOSTNAME
4252    {"CS_HOSTNAME",	_CS_HOSTNAME},
4253#endif
4254#ifdef _CS_HW_PROVIDER
4255    {"CS_HW_PROVIDER",	_CS_HW_PROVIDER},
4256#endif
4257#ifdef _CS_HW_SERIAL
4258    {"CS_HW_SERIAL",	_CS_HW_SERIAL},
4259#endif
4260#ifdef _CS_INITTAB_NAME
4261    {"CS_INITTAB_NAME",	_CS_INITTAB_NAME},
4262#endif
4263#ifdef _CS_LFS64_CFLAGS
4264    {"CS_LFS64_CFLAGS",	_CS_LFS64_CFLAGS},
4265#endif
4266#ifdef _CS_LFS64_LDFLAGS
4267    {"CS_LFS64_LDFLAGS",	_CS_LFS64_LDFLAGS},
4268#endif
4269#ifdef _CS_LFS64_LIBS
4270    {"CS_LFS64_LIBS",	_CS_LFS64_LIBS},
4271#endif
4272#ifdef _CS_LFS64_LINTFLAGS
4273    {"CS_LFS64_LINTFLAGS",	_CS_LFS64_LINTFLAGS},
4274#endif
4275#ifdef _CS_LFS_CFLAGS
4276    {"CS_LFS_CFLAGS",	_CS_LFS_CFLAGS},
4277#endif
4278#ifdef _CS_LFS_LDFLAGS
4279    {"CS_LFS_LDFLAGS",	_CS_LFS_LDFLAGS},
4280#endif
4281#ifdef _CS_LFS_LIBS
4282    {"CS_LFS_LIBS",	_CS_LFS_LIBS},
4283#endif
4284#ifdef _CS_LFS_LINTFLAGS
4285    {"CS_LFS_LINTFLAGS",	_CS_LFS_LINTFLAGS},
4286#endif
4287#ifdef _CS_MACHINE
4288    {"CS_MACHINE",	_CS_MACHINE},
4289#endif
4290#ifdef _CS_PATH
4291    {"CS_PATH",	_CS_PATH},
4292#endif
4293#ifdef _CS_RELEASE
4294    {"CS_RELEASE",	_CS_RELEASE},
4295#endif
4296#ifdef _CS_SRPC_DOMAIN
4297    {"CS_SRPC_DOMAIN",	_CS_SRPC_DOMAIN},
4298#endif
4299#ifdef _CS_SYSNAME
4300    {"CS_SYSNAME",	_CS_SYSNAME},
4301#endif
4302#ifdef _CS_VERSION
4303    {"CS_VERSION",	_CS_VERSION},
4304#endif
4305#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
4306    {"CS_XBS5_ILP32_OFF32_CFLAGS",	_CS_XBS5_ILP32_OFF32_CFLAGS},
4307#endif
4308#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
4309    {"CS_XBS5_ILP32_OFF32_LDFLAGS",	_CS_XBS5_ILP32_OFF32_LDFLAGS},
4310#endif
4311#ifdef _CS_XBS5_ILP32_OFF32_LIBS
4312    {"CS_XBS5_ILP32_OFF32_LIBS",	_CS_XBS5_ILP32_OFF32_LIBS},
4313#endif
4314#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
4315    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",	_CS_XBS5_ILP32_OFF32_LINTFLAGS},
4316#endif
4317#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
4318    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",	_CS_XBS5_ILP32_OFFBIG_CFLAGS},
4319#endif
4320#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
4321    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",	_CS_XBS5_ILP32_OFFBIG_LDFLAGS},
4322#endif
4323#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
4324    {"CS_XBS5_ILP32_OFFBIG_LIBS",	_CS_XBS5_ILP32_OFFBIG_LIBS},
4325#endif
4326#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
4327    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",	_CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
4328#endif
4329#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
4330    {"CS_XBS5_LP64_OFF64_CFLAGS",	_CS_XBS5_LP64_OFF64_CFLAGS},
4331#endif
4332#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
4333    {"CS_XBS5_LP64_OFF64_LDFLAGS",	_CS_XBS5_LP64_OFF64_LDFLAGS},
4334#endif
4335#ifdef _CS_XBS5_LP64_OFF64_LIBS
4336    {"CS_XBS5_LP64_OFF64_LIBS",	_CS_XBS5_LP64_OFF64_LIBS},
4337#endif
4338#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
4339    {"CS_XBS5_LP64_OFF64_LINTFLAGS",	_CS_XBS5_LP64_OFF64_LINTFLAGS},
4340#endif
4341#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
4342    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",	_CS_XBS5_LPBIG_OFFBIG_CFLAGS},
4343#endif
4344#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
4345    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",	_CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
4346#endif
4347#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
4348    {"CS_XBS5_LPBIG_OFFBIG_LIBS",	_CS_XBS5_LPBIG_OFFBIG_LIBS},
4349#endif
4350#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
4351    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",	_CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
4352#endif
4353#ifdef _MIPS_CS_AVAIL_PROCESSORS
4354    {"MIPS_CS_AVAIL_PROCESSORS",	_MIPS_CS_AVAIL_PROCESSORS},
4355#endif
4356#ifdef _MIPS_CS_BASE
4357    {"MIPS_CS_BASE",	_MIPS_CS_BASE},
4358#endif
4359#ifdef _MIPS_CS_HOSTID
4360    {"MIPS_CS_HOSTID",	_MIPS_CS_HOSTID},
4361#endif
4362#ifdef _MIPS_CS_HW_NAME
4363    {"MIPS_CS_HW_NAME",	_MIPS_CS_HW_NAME},
4364#endif
4365#ifdef _MIPS_CS_NUM_PROCESSORS
4366    {"MIPS_CS_NUM_PROCESSORS",	_MIPS_CS_NUM_PROCESSORS},
4367#endif
4368#ifdef _MIPS_CS_OSREL_MAJ
4369    {"MIPS_CS_OSREL_MAJ",	_MIPS_CS_OSREL_MAJ},
4370#endif
4371#ifdef _MIPS_CS_OSREL_MIN
4372    {"MIPS_CS_OSREL_MIN",	_MIPS_CS_OSREL_MIN},
4373#endif
4374#ifdef _MIPS_CS_OSREL_PATCH
4375    {"MIPS_CS_OSREL_PATCH",	_MIPS_CS_OSREL_PATCH},
4376#endif
4377#ifdef _MIPS_CS_OS_NAME
4378    {"MIPS_CS_OS_NAME",	_MIPS_CS_OS_NAME},
4379#endif
4380#ifdef _MIPS_CS_OS_PROVIDER
4381    {"MIPS_CS_OS_PROVIDER",	_MIPS_CS_OS_PROVIDER},
4382#endif
4383#ifdef _MIPS_CS_PROCESSORS
4384    {"MIPS_CS_PROCESSORS",	_MIPS_CS_PROCESSORS},
4385#endif
4386#ifdef _MIPS_CS_SERIAL
4387    {"MIPS_CS_SERIAL",	_MIPS_CS_SERIAL},
4388#endif
4389#ifdef _MIPS_CS_VENDOR
4390    {"MIPS_CS_VENDOR",	_MIPS_CS_VENDOR},
4391#endif
4392};
4393
4394static int
4395conv_confstr_confname(PyObject *arg, int *valuep)
4396{
4397    return conv_confname(arg, valuep, posix_constants_confstr,
4398                         sizeof(posix_constants_confstr)
4399                           / sizeof(struct constdef));
4400}
4401
4402static char posix_confstr__doc__[] = "\
4403confstr(name) -> string\n\
4404Return a string-valued system configuration variable.";
4405
4406static PyObject *
4407posix_confstr(PyObject *self, PyObject *args)
4408{
4409    PyObject *result = NULL;
4410    int name;
4411    char buffer[64];
4412
4413    if (PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) {
4414        int len = confstr(name, buffer, sizeof(buffer));
4415
4416        errno = 0;
4417        if (len == 0) {
4418            if (errno != 0)
4419                posix_error();
4420            else
4421                result = PyString_FromString("");
4422        }
4423        else {
4424            if (len >= sizeof(buffer)) {
4425                result = PyString_FromStringAndSize(NULL, len);
4426                if (result != NULL)
4427                    confstr(name, PyString_AS_STRING(result), len+1);
4428            }
4429            else
4430                result = PyString_FromString(buffer);
4431        }
4432    }
4433    return result;
4434}
4435#endif
4436
4437
4438#ifdef HAVE_SYSCONF
4439static struct constdef posix_constants_sysconf[] = {
4440#ifdef _SC_2_CHAR_TERM
4441    {"SC_2_CHAR_TERM",	_SC_2_CHAR_TERM},
4442#endif
4443#ifdef _SC_2_C_BIND
4444    {"SC_2_C_BIND",	_SC_2_C_BIND},
4445#endif
4446#ifdef _SC_2_C_DEV
4447    {"SC_2_C_DEV",	_SC_2_C_DEV},
4448#endif
4449#ifdef _SC_2_C_VERSION
4450    {"SC_2_C_VERSION",	_SC_2_C_VERSION},
4451#endif
4452#ifdef _SC_2_FORT_DEV
4453    {"SC_2_FORT_DEV",	_SC_2_FORT_DEV},
4454#endif
4455#ifdef _SC_2_FORT_RUN
4456    {"SC_2_FORT_RUN",	_SC_2_FORT_RUN},
4457#endif
4458#ifdef _SC_2_LOCALEDEF
4459    {"SC_2_LOCALEDEF",	_SC_2_LOCALEDEF},
4460#endif
4461#ifdef _SC_2_SW_DEV
4462    {"SC_2_SW_DEV",	_SC_2_SW_DEV},
4463#endif
4464#ifdef _SC_2_UPE
4465    {"SC_2_UPE",	_SC_2_UPE},
4466#endif
4467#ifdef _SC_2_VERSION
4468    {"SC_2_VERSION",	_SC_2_VERSION},
4469#endif
4470#ifdef _SC_ABI_ASYNCHRONOUS_IO
4471    {"SC_ABI_ASYNCHRONOUS_IO",	_SC_ABI_ASYNCHRONOUS_IO},
4472#endif
4473#ifdef _SC_ACL
4474    {"SC_ACL",	_SC_ACL},
4475#endif
4476#ifdef _SC_AIO_LISTIO_MAX
4477    {"SC_AIO_LISTIO_MAX",	_SC_AIO_LISTIO_MAX},
4478#endif
4479#ifdef _SC_AIO_MAX
4480    {"SC_AIO_MAX",	_SC_AIO_MAX},
4481#endif
4482#ifdef _SC_AIO_PRIO_DELTA_MAX
4483    {"SC_AIO_PRIO_DELTA_MAX",	_SC_AIO_PRIO_DELTA_MAX},
4484#endif
4485#ifdef _SC_ARG_MAX
4486    {"SC_ARG_MAX",	_SC_ARG_MAX},
4487#endif
4488#ifdef _SC_ASYNCHRONOUS_IO
4489    {"SC_ASYNCHRONOUS_IO",	_SC_ASYNCHRONOUS_IO},
4490#endif
4491#ifdef _SC_ATEXIT_MAX
4492    {"SC_ATEXIT_MAX",	_SC_ATEXIT_MAX},
4493#endif
4494#ifdef _SC_AUDIT
4495    {"SC_AUDIT",	_SC_AUDIT},
4496#endif
4497#ifdef _SC_AVPHYS_PAGES
4498    {"SC_AVPHYS_PAGES",	_SC_AVPHYS_PAGES},
4499#endif
4500#ifdef _SC_BC_BASE_MAX
4501    {"SC_BC_BASE_MAX",	_SC_BC_BASE_MAX},
4502#endif
4503#ifdef _SC_BC_DIM_MAX
4504    {"SC_BC_DIM_MAX",	_SC_BC_DIM_MAX},
4505#endif
4506#ifdef _SC_BC_SCALE_MAX
4507    {"SC_BC_SCALE_MAX",	_SC_BC_SCALE_MAX},
4508#endif
4509#ifdef _SC_BC_STRING_MAX
4510    {"SC_BC_STRING_MAX",	_SC_BC_STRING_MAX},
4511#endif
4512#ifdef _SC_CAP
4513    {"SC_CAP",	_SC_CAP},
4514#endif
4515#ifdef _SC_CHARCLASS_NAME_MAX
4516    {"SC_CHARCLASS_NAME_MAX",	_SC_CHARCLASS_NAME_MAX},
4517#endif
4518#ifdef _SC_CHAR_BIT
4519    {"SC_CHAR_BIT",	_SC_CHAR_BIT},
4520#endif
4521#ifdef _SC_CHAR_MAX
4522    {"SC_CHAR_MAX",	_SC_CHAR_MAX},
4523#endif
4524#ifdef _SC_CHAR_MIN
4525    {"SC_CHAR_MIN",	_SC_CHAR_MIN},
4526#endif
4527#ifdef _SC_CHILD_MAX
4528    {"SC_CHILD_MAX",	_SC_CHILD_MAX},
4529#endif
4530#ifdef _SC_CLK_TCK
4531    {"SC_CLK_TCK",	_SC_CLK_TCK},
4532#endif
4533#ifdef _SC_COHER_BLKSZ
4534    {"SC_COHER_BLKSZ",	_SC_COHER_BLKSZ},
4535#endif
4536#ifdef _SC_COLL_WEIGHTS_MAX
4537    {"SC_COLL_WEIGHTS_MAX",	_SC_COLL_WEIGHTS_MAX},
4538#endif
4539#ifdef _SC_DCACHE_ASSOC
4540    {"SC_DCACHE_ASSOC",	_SC_DCACHE_ASSOC},
4541#endif
4542#ifdef _SC_DCACHE_BLKSZ
4543    {"SC_DCACHE_BLKSZ",	_SC_DCACHE_BLKSZ},
4544#endif
4545#ifdef _SC_DCACHE_LINESZ
4546    {"SC_DCACHE_LINESZ",	_SC_DCACHE_LINESZ},
4547#endif
4548#ifdef _SC_DCACHE_SZ
4549    {"SC_DCACHE_SZ",	_SC_DCACHE_SZ},
4550#endif
4551#ifdef _SC_DCACHE_TBLKSZ
4552    {"SC_DCACHE_TBLKSZ",	_SC_DCACHE_TBLKSZ},
4553#endif
4554#ifdef _SC_DELAYTIMER_MAX
4555    {"SC_DELAYTIMER_MAX",	_SC_DELAYTIMER_MAX},
4556#endif
4557#ifdef _SC_EQUIV_CLASS_MAX
4558    {"SC_EQUIV_CLASS_MAX",	_SC_EQUIV_CLASS_MAX},
4559#endif
4560#ifdef _SC_EXPR_NEST_MAX
4561    {"SC_EXPR_NEST_MAX",	_SC_EXPR_NEST_MAX},
4562#endif
4563#ifdef _SC_FSYNC
4564    {"SC_FSYNC",	_SC_FSYNC},
4565#endif
4566#ifdef _SC_GETGR_R_SIZE_MAX
4567    {"SC_GETGR_R_SIZE_MAX",	_SC_GETGR_R_SIZE_MAX},
4568#endif
4569#ifdef _SC_GETPW_R_SIZE_MAX
4570    {"SC_GETPW_R_SIZE_MAX",	_SC_GETPW_R_SIZE_MAX},
4571#endif
4572#ifdef _SC_ICACHE_ASSOC
4573    {"SC_ICACHE_ASSOC",	_SC_ICACHE_ASSOC},
4574#endif
4575#ifdef _SC_ICACHE_BLKSZ
4576    {"SC_ICACHE_BLKSZ",	_SC_ICACHE_BLKSZ},
4577#endif
4578#ifdef _SC_ICACHE_LINESZ
4579    {"SC_ICACHE_LINESZ",	_SC_ICACHE_LINESZ},
4580#endif
4581#ifdef _SC_ICACHE_SZ
4582    {"SC_ICACHE_SZ",	_SC_ICACHE_SZ},
4583#endif
4584#ifdef _SC_INF
4585    {"SC_INF",	_SC_INF},
4586#endif
4587#ifdef _SC_INT_MAX
4588    {"SC_INT_MAX",	_SC_INT_MAX},
4589#endif
4590#ifdef _SC_INT_MIN
4591    {"SC_INT_MIN",	_SC_INT_MIN},
4592#endif
4593#ifdef _SC_IOV_MAX
4594    {"SC_IOV_MAX",	_SC_IOV_MAX},
4595#endif
4596#ifdef _SC_IP_SECOPTS
4597    {"SC_IP_SECOPTS",	_SC_IP_SECOPTS},
4598#endif
4599#ifdef _SC_JOB_CONTROL
4600    {"SC_JOB_CONTROL",	_SC_JOB_CONTROL},
4601#endif
4602#ifdef _SC_KERN_POINTERS
4603    {"SC_KERN_POINTERS",	_SC_KERN_POINTERS},
4604#endif
4605#ifdef _SC_KERN_SIM
4606    {"SC_KERN_SIM",	_SC_KERN_SIM},
4607#endif
4608#ifdef _SC_LINE_MAX
4609    {"SC_LINE_MAX",	_SC_LINE_MAX},
4610#endif
4611#ifdef _SC_LOGIN_NAME_MAX
4612    {"SC_LOGIN_NAME_MAX",	_SC_LOGIN_NAME_MAX},
4613#endif
4614#ifdef _SC_LOGNAME_MAX
4615    {"SC_LOGNAME_MAX",	_SC_LOGNAME_MAX},
4616#endif
4617#ifdef _SC_LONG_BIT
4618    {"SC_LONG_BIT",	_SC_LONG_BIT},
4619#endif
4620#ifdef _SC_MAC
4621    {"SC_MAC",	_SC_MAC},
4622#endif
4623#ifdef _SC_MAPPED_FILES
4624    {"SC_MAPPED_FILES",	_SC_MAPPED_FILES},
4625#endif
4626#ifdef _SC_MAXPID
4627    {"SC_MAXPID",	_SC_MAXPID},
4628#endif
4629#ifdef _SC_MB_LEN_MAX
4630    {"SC_MB_LEN_MAX",	_SC_MB_LEN_MAX},
4631#endif
4632#ifdef _SC_MEMLOCK
4633    {"SC_MEMLOCK",	_SC_MEMLOCK},
4634#endif
4635#ifdef _SC_MEMLOCK_RANGE
4636    {"SC_MEMLOCK_RANGE",	_SC_MEMLOCK_RANGE},
4637#endif
4638#ifdef _SC_MEMORY_PROTECTION
4639    {"SC_MEMORY_PROTECTION",	_SC_MEMORY_PROTECTION},
4640#endif
4641#ifdef _SC_MESSAGE_PASSING
4642    {"SC_MESSAGE_PASSING",	_SC_MESSAGE_PASSING},
4643#endif
4644#ifdef _SC_MMAP_FIXED_ALIGNMENT
4645    {"SC_MMAP_FIXED_ALIGNMENT",	_SC_MMAP_FIXED_ALIGNMENT},
4646#endif
4647#ifdef _SC_MQ_OPEN_MAX
4648    {"SC_MQ_OPEN_MAX",	_SC_MQ_OPEN_MAX},
4649#endif
4650#ifdef _SC_MQ_PRIO_MAX
4651    {"SC_MQ_PRIO_MAX",	_SC_MQ_PRIO_MAX},
4652#endif
4653#ifdef _SC_NACLS_MAX
4654    {"SC_NACLS_MAX",	_SC_NACLS_MAX},
4655#endif
4656#ifdef _SC_NGROUPS_MAX
4657    {"SC_NGROUPS_MAX",	_SC_NGROUPS_MAX},
4658#endif
4659#ifdef _SC_NL_ARGMAX
4660    {"SC_NL_ARGMAX",	_SC_NL_ARGMAX},
4661#endif
4662#ifdef _SC_NL_LANGMAX
4663    {"SC_NL_LANGMAX",	_SC_NL_LANGMAX},
4664#endif
4665#ifdef _SC_NL_MSGMAX
4666    {"SC_NL_MSGMAX",	_SC_NL_MSGMAX},
4667#endif
4668#ifdef _SC_NL_NMAX
4669    {"SC_NL_NMAX",	_SC_NL_NMAX},
4670#endif
4671#ifdef _SC_NL_SETMAX
4672    {"SC_NL_SETMAX",	_SC_NL_SETMAX},
4673#endif
4674#ifdef _SC_NL_TEXTMAX
4675    {"SC_NL_TEXTMAX",	_SC_NL_TEXTMAX},
4676#endif
4677#ifdef _SC_NPROCESSORS_CONF
4678    {"SC_NPROCESSORS_CONF",	_SC_NPROCESSORS_CONF},
4679#endif
4680#ifdef _SC_NPROCESSORS_ONLN
4681    {"SC_NPROCESSORS_ONLN",	_SC_NPROCESSORS_ONLN},
4682#endif
4683#ifdef _SC_NPROC_CONF
4684    {"SC_NPROC_CONF",	_SC_NPROC_CONF},
4685#endif
4686#ifdef _SC_NPROC_ONLN
4687    {"SC_NPROC_ONLN",	_SC_NPROC_ONLN},
4688#endif
4689#ifdef _SC_NZERO
4690    {"SC_NZERO",	_SC_NZERO},
4691#endif
4692#ifdef _SC_OPEN_MAX
4693    {"SC_OPEN_MAX",	_SC_OPEN_MAX},
4694#endif
4695#ifdef _SC_PAGESIZE
4696    {"SC_PAGESIZE",	_SC_PAGESIZE},
4697#endif
4698#ifdef _SC_PAGE_SIZE
4699    {"SC_PAGE_SIZE",	_SC_PAGE_SIZE},
4700#endif
4701#ifdef _SC_PASS_MAX
4702    {"SC_PASS_MAX",	_SC_PASS_MAX},
4703#endif
4704#ifdef _SC_PHYS_PAGES
4705    {"SC_PHYS_PAGES",	_SC_PHYS_PAGES},
4706#endif
4707#ifdef _SC_PII
4708    {"SC_PII",	_SC_PII},
4709#endif
4710#ifdef _SC_PII_INTERNET
4711    {"SC_PII_INTERNET",	_SC_PII_INTERNET},
4712#endif
4713#ifdef _SC_PII_INTERNET_DGRAM
4714    {"SC_PII_INTERNET_DGRAM",	_SC_PII_INTERNET_DGRAM},
4715#endif
4716#ifdef _SC_PII_INTERNET_STREAM
4717    {"SC_PII_INTERNET_STREAM",	_SC_PII_INTERNET_STREAM},
4718#endif
4719#ifdef _SC_PII_OSI
4720    {"SC_PII_OSI",	_SC_PII_OSI},
4721#endif
4722#ifdef _SC_PII_OSI_CLTS
4723    {"SC_PII_OSI_CLTS",	_SC_PII_OSI_CLTS},
4724#endif
4725#ifdef _SC_PII_OSI_COTS
4726    {"SC_PII_OSI_COTS",	_SC_PII_OSI_COTS},
4727#endif
4728#ifdef _SC_PII_OSI_M
4729    {"SC_PII_OSI_M",	_SC_PII_OSI_M},
4730#endif
4731#ifdef _SC_PII_SOCKET
4732    {"SC_PII_SOCKET",	_SC_PII_SOCKET},
4733#endif
4734#ifdef _SC_PII_XTI
4735    {"SC_PII_XTI",	_SC_PII_XTI},
4736#endif
4737#ifdef _SC_POLL
4738    {"SC_POLL",	_SC_POLL},
4739#endif
4740#ifdef _SC_PRIORITIZED_IO
4741    {"SC_PRIORITIZED_IO",	_SC_PRIORITIZED_IO},
4742#endif
4743#ifdef _SC_PRIORITY_SCHEDULING
4744    {"SC_PRIORITY_SCHEDULING",	_SC_PRIORITY_SCHEDULING},
4745#endif
4746#ifdef _SC_REALTIME_SIGNALS
4747    {"SC_REALTIME_SIGNALS",	_SC_REALTIME_SIGNALS},
4748#endif
4749#ifdef _SC_RE_DUP_MAX
4750    {"SC_RE_DUP_MAX",	_SC_RE_DUP_MAX},
4751#endif
4752#ifdef _SC_RTSIG_MAX
4753    {"SC_RTSIG_MAX",	_SC_RTSIG_MAX},
4754#endif
4755#ifdef _SC_SAVED_IDS
4756    {"SC_SAVED_IDS",	_SC_SAVED_IDS},
4757#endif
4758#ifdef _SC_SCHAR_MAX
4759    {"SC_SCHAR_MAX",	_SC_SCHAR_MAX},
4760#endif
4761#ifdef _SC_SCHAR_MIN
4762    {"SC_SCHAR_MIN",	_SC_SCHAR_MIN},
4763#endif
4764#ifdef _SC_SELECT
4765    {"SC_SELECT",	_SC_SELECT},
4766#endif
4767#ifdef _SC_SEMAPHORES
4768    {"SC_SEMAPHORES",	_SC_SEMAPHORES},
4769#endif
4770#ifdef _SC_SEM_NSEMS_MAX
4771    {"SC_SEM_NSEMS_MAX",	_SC_SEM_NSEMS_MAX},
4772#endif
4773#ifdef _SC_SEM_VALUE_MAX
4774    {"SC_SEM_VALUE_MAX",	_SC_SEM_VALUE_MAX},
4775#endif
4776#ifdef _SC_SHARED_MEMORY_OBJECTS
4777    {"SC_SHARED_MEMORY_OBJECTS",	_SC_SHARED_MEMORY_OBJECTS},
4778#endif
4779#ifdef _SC_SHRT_MAX
4780    {"SC_SHRT_MAX",	_SC_SHRT_MAX},
4781#endif
4782#ifdef _SC_SHRT_MIN
4783    {"SC_SHRT_MIN",	_SC_SHRT_MIN},
4784#endif
4785#ifdef _SC_SIGQUEUE_MAX
4786    {"SC_SIGQUEUE_MAX",	_SC_SIGQUEUE_MAX},
4787#endif
4788#ifdef _SC_SIGRT_MAX
4789    {"SC_SIGRT_MAX",	_SC_SIGRT_MAX},
4790#endif
4791#ifdef _SC_SIGRT_MIN
4792    {"SC_SIGRT_MIN",	_SC_SIGRT_MIN},
4793#endif
4794#ifdef _SC_SOFTPOWER
4795    {"SC_SOFTPOWER",	_SC_SOFTPOWER},
4796#endif
4797#ifdef _SC_SPLIT_CACHE
4798    {"SC_SPLIT_CACHE",	_SC_SPLIT_CACHE},
4799#endif
4800#ifdef _SC_SSIZE_MAX
4801    {"SC_SSIZE_MAX",	_SC_SSIZE_MAX},
4802#endif
4803#ifdef _SC_STACK_PROT
4804    {"SC_STACK_PROT",	_SC_STACK_PROT},
4805#endif
4806#ifdef _SC_STREAM_MAX
4807    {"SC_STREAM_MAX",	_SC_STREAM_MAX},
4808#endif
4809#ifdef _SC_SYNCHRONIZED_IO
4810    {"SC_SYNCHRONIZED_IO",	_SC_SYNCHRONIZED_IO},
4811#endif
4812#ifdef _SC_THREADS
4813    {"SC_THREADS",	_SC_THREADS},
4814#endif
4815#ifdef _SC_THREAD_ATTR_STACKADDR
4816    {"SC_THREAD_ATTR_STACKADDR",	_SC_THREAD_ATTR_STACKADDR},
4817#endif
4818#ifdef _SC_THREAD_ATTR_STACKSIZE
4819    {"SC_THREAD_ATTR_STACKSIZE",	_SC_THREAD_ATTR_STACKSIZE},
4820#endif
4821#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
4822    {"SC_THREAD_DESTRUCTOR_ITERATIONS",	_SC_THREAD_DESTRUCTOR_ITERATIONS},
4823#endif
4824#ifdef _SC_THREAD_KEYS_MAX
4825    {"SC_THREAD_KEYS_MAX",	_SC_THREAD_KEYS_MAX},
4826#endif
4827#ifdef _SC_THREAD_PRIORITY_SCHEDULING
4828    {"SC_THREAD_PRIORITY_SCHEDULING",	_SC_THREAD_PRIORITY_SCHEDULING},
4829#endif
4830#ifdef _SC_THREAD_PRIO_INHERIT
4831    {"SC_THREAD_PRIO_INHERIT",	_SC_THREAD_PRIO_INHERIT},
4832#endif
4833#ifdef _SC_THREAD_PRIO_PROTECT
4834    {"SC_THREAD_PRIO_PROTECT",	_SC_THREAD_PRIO_PROTECT},
4835#endif
4836#ifdef _SC_THREAD_PROCESS_SHARED
4837    {"SC_THREAD_PROCESS_SHARED",	_SC_THREAD_PROCESS_SHARED},
4838#endif
4839#ifdef _SC_THREAD_SAFE_FUNCTIONS
4840    {"SC_THREAD_SAFE_FUNCTIONS",	_SC_THREAD_SAFE_FUNCTIONS},
4841#endif
4842#ifdef _SC_THREAD_STACK_MIN
4843    {"SC_THREAD_STACK_MIN",	_SC_THREAD_STACK_MIN},
4844#endif
4845#ifdef _SC_THREAD_THREADS_MAX
4846    {"SC_THREAD_THREADS_MAX",	_SC_THREAD_THREADS_MAX},
4847#endif
4848#ifdef _SC_TIMERS
4849    {"SC_TIMERS",	_SC_TIMERS},
4850#endif
4851#ifdef _SC_TIMER_MAX
4852    {"SC_TIMER_MAX",	_SC_TIMER_MAX},
4853#endif
4854#ifdef _SC_TTY_NAME_MAX
4855    {"SC_TTY_NAME_MAX",	_SC_TTY_NAME_MAX},
4856#endif
4857#ifdef _SC_TZNAME_MAX
4858    {"SC_TZNAME_MAX",	_SC_TZNAME_MAX},
4859#endif
4860#ifdef _SC_T_IOV_MAX
4861    {"SC_T_IOV_MAX",	_SC_T_IOV_MAX},
4862#endif
4863#ifdef _SC_UCHAR_MAX
4864    {"SC_UCHAR_MAX",	_SC_UCHAR_MAX},
4865#endif
4866#ifdef _SC_UINT_MAX
4867    {"SC_UINT_MAX",	_SC_UINT_MAX},
4868#endif
4869#ifdef _SC_UIO_MAXIOV
4870    {"SC_UIO_MAXIOV",	_SC_UIO_MAXIOV},
4871#endif
4872#ifdef _SC_ULONG_MAX
4873    {"SC_ULONG_MAX",	_SC_ULONG_MAX},
4874#endif
4875#ifdef _SC_USHRT_MAX
4876    {"SC_USHRT_MAX",	_SC_USHRT_MAX},
4877#endif
4878#ifdef _SC_VERSION
4879    {"SC_VERSION",	_SC_VERSION},
4880#endif
4881#ifdef _SC_WORD_BIT
4882    {"SC_WORD_BIT",	_SC_WORD_BIT},
4883#endif
4884#ifdef _SC_XBS5_ILP32_OFF32
4885    {"SC_XBS5_ILP32_OFF32",	_SC_XBS5_ILP32_OFF32},
4886#endif
4887#ifdef _SC_XBS5_ILP32_OFFBIG
4888    {"SC_XBS5_ILP32_OFFBIG",	_SC_XBS5_ILP32_OFFBIG},
4889#endif
4890#ifdef _SC_XBS5_LP64_OFF64
4891    {"SC_XBS5_LP64_OFF64",	_SC_XBS5_LP64_OFF64},
4892#endif
4893#ifdef _SC_XBS5_LPBIG_OFFBIG
4894    {"SC_XBS5_LPBIG_OFFBIG",	_SC_XBS5_LPBIG_OFFBIG},
4895#endif
4896#ifdef _SC_XOPEN_CRYPT
4897    {"SC_XOPEN_CRYPT",	_SC_XOPEN_CRYPT},
4898#endif
4899#ifdef _SC_XOPEN_ENH_I18N
4900    {"SC_XOPEN_ENH_I18N",	_SC_XOPEN_ENH_I18N},
4901#endif
4902#ifdef _SC_XOPEN_LEGACY
4903    {"SC_XOPEN_LEGACY",	_SC_XOPEN_LEGACY},
4904#endif
4905#ifdef _SC_XOPEN_REALTIME
4906    {"SC_XOPEN_REALTIME",	_SC_XOPEN_REALTIME},
4907#endif
4908#ifdef _SC_XOPEN_REALTIME_THREADS
4909    {"SC_XOPEN_REALTIME_THREADS",	_SC_XOPEN_REALTIME_THREADS},
4910#endif
4911#ifdef _SC_XOPEN_SHM
4912    {"SC_XOPEN_SHM",	_SC_XOPEN_SHM},
4913#endif
4914#ifdef _SC_XOPEN_UNIX
4915    {"SC_XOPEN_UNIX",	_SC_XOPEN_UNIX},
4916#endif
4917#ifdef _SC_XOPEN_VERSION
4918    {"SC_XOPEN_VERSION",	_SC_XOPEN_VERSION},
4919#endif
4920#ifdef _SC_XOPEN_XCU_VERSION
4921    {"SC_XOPEN_XCU_VERSION",	_SC_XOPEN_XCU_VERSION},
4922#endif
4923#ifdef _SC_XOPEN_XPG2
4924    {"SC_XOPEN_XPG2",	_SC_XOPEN_XPG2},
4925#endif
4926#ifdef _SC_XOPEN_XPG3
4927    {"SC_XOPEN_XPG3",	_SC_XOPEN_XPG3},
4928#endif
4929#ifdef _SC_XOPEN_XPG4
4930    {"SC_XOPEN_XPG4",	_SC_XOPEN_XPG4},
4931#endif
4932};
4933
4934static int
4935conv_sysconf_confname(PyObject *arg, int *valuep)
4936{
4937    return conv_confname(arg, valuep, posix_constants_sysconf,
4938                         sizeof(posix_constants_sysconf)
4939                           / sizeof(struct constdef));
4940}
4941
4942static char posix_sysconf__doc__[] = "\
4943sysconf(name) -> integer\n\
4944Return an integer-valued system configuration variable.";
4945
4946static PyObject *
4947posix_sysconf(PyObject *self, PyObject *args)
4948{
4949    PyObject *result = NULL;
4950    int name;
4951
4952    if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
4953        int value;
4954
4955        errno = 0;
4956        value = sysconf(name);
4957        if (value == -1 && errno != 0)
4958            posix_error();
4959        else
4960            result = PyInt_FromLong(value);
4961    }
4962    return result;
4963}
4964#endif
4965
4966
4967/* This code is used to ensure that the tables of configuration value names
4968 * are in sorted order as required by conv_confname(), and also to build the
4969 * the exported dictionaries that are used to publish information about the
4970 * names available on the host platform.
4971 *
4972 * Sorting the table at runtime ensures that the table is properly ordered
4973 * when used, even for platforms we're not able to test on.  It also makes
4974 * it easier to add additional entries to the tables.
4975 */
4976
4977static int
4978cmp_constdefs(const void *v1,  const void *v2)
4979{
4980    const struct constdef *c1 =
4981        (const struct constdef *) v1;
4982    const struct constdef *c2 =
4983        (const struct constdef *) v2;
4984
4985    return strcmp(c1->name, c2->name);
4986}
4987
4988static int
4989setup_confname_table(struct constdef *table, size_t tablesize,
4990		     char *tablename, PyObject *moddict)
4991{
4992    PyObject *d = NULL;
4993    size_t i;
4994    int status;
4995
4996    qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
4997    d = PyDict_New();
4998    if (d == NULL)
4999	    return -1;
5000
5001    for (i=0; i < tablesize; ++i) {
5002            PyObject *o = PyInt_FromLong(table[i].value);
5003            if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
5004		    Py_XDECREF(o);
5005		    Py_DECREF(d);
5006		    return -1;
5007            }
5008	    Py_DECREF(o);
5009    }
5010    status = PyDict_SetItemString(moddict, tablename, d);
5011    Py_DECREF(d);
5012    return status;
5013}
5014
5015/* Return -1 on failure, 0 on success. */
5016static int
5017setup_confname_tables(PyObject *moddict)
5018{
5019#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
5020    if (setup_confname_table(posix_constants_pathconf,
5021                             sizeof(posix_constants_pathconf)
5022                               / sizeof(struct constdef),
5023                             "pathconf_names", moddict))
5024        return -1;
5025#endif
5026#ifdef HAVE_CONFSTR
5027    if (setup_confname_table(posix_constants_confstr,
5028                             sizeof(posix_constants_confstr)
5029                               / sizeof(struct constdef),
5030                             "confstr_names", moddict))
5031        return -1;
5032#endif
5033#ifdef HAVE_SYSCONF
5034    if (setup_confname_table(posix_constants_sysconf,
5035                             sizeof(posix_constants_sysconf)
5036                               / sizeof(struct constdef),
5037                             "sysconf_names", moddict))
5038        return -1;
5039#endif
5040    return 0;
5041}
5042
5043
5044static char posix_abort__doc__[] = "\
5045abort() -> does not return!\n\
5046Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
5047in the hardest way possible on the hosting operating system.";
5048
5049static PyObject *
5050posix_abort(PyObject *self, PyObject *args)
5051{
5052    if (!PyArg_ParseTuple(args, ":abort"))
5053        return NULL;
5054    abort();
5055    /*NOTREACHED*/
5056    Py_FatalError("abort() called from Python code didn't abort!");
5057    return NULL;
5058}
5059
5060
5061static PyMethodDef posix_methods[] = {
5062	{"access",	posix_access, METH_VARARGS, posix_access__doc__},
5063#ifdef HAVE_TTYNAME
5064	{"ttyname",	posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
5065#endif
5066	{"chdir",	posix_chdir, METH_VARARGS, posix_chdir__doc__},
5067	{"chmod",	posix_chmod, METH_VARARGS, posix_chmod__doc__},
5068#ifdef HAVE_CHOWN
5069	{"chown",	posix_chown, METH_VARARGS, posix_chown__doc__},
5070#endif /* HAVE_CHOWN */
5071#ifdef HAVE_CTERMID
5072	{"ctermid",	posix_ctermid, METH_VARARGS, posix_ctermid__doc__},
5073#endif
5074#ifdef HAVE_GETCWD
5075	{"getcwd",	posix_getcwd, METH_VARARGS, posix_getcwd__doc__},
5076#endif
5077#ifdef HAVE_LINK
5078	{"link",	posix_link, METH_VARARGS, posix_link__doc__},
5079#endif /* HAVE_LINK */
5080	{"listdir",	posix_listdir, METH_VARARGS, posix_listdir__doc__},
5081	{"lstat",	posix_lstat, METH_VARARGS, posix_lstat__doc__},
5082	{"mkdir",	posix_mkdir, METH_VARARGS, posix_mkdir__doc__},
5083#ifdef HAVE_NICE
5084	{"nice",	posix_nice, METH_VARARGS, posix_nice__doc__},
5085#endif /* HAVE_NICE */
5086#ifdef HAVE_READLINK
5087	{"readlink",	posix_readlink, METH_VARARGS, posix_readlink__doc__},
5088#endif /* HAVE_READLINK */
5089	{"rename",	posix_rename, METH_VARARGS, posix_rename__doc__},
5090	{"rmdir",	posix_rmdir, METH_VARARGS, posix_rmdir__doc__},
5091	{"stat",	posix_stat, METH_VARARGS, posix_stat__doc__},
5092#ifdef HAVE_SYMLINK
5093	{"symlink",	posix_symlink, METH_VARARGS, posix_symlink__doc__},
5094#endif /* HAVE_SYMLINK */
5095#ifdef HAVE_SYSTEM
5096	{"system",	posix_system, METH_VARARGS, posix_system__doc__},
5097#endif
5098	{"umask",	posix_umask, METH_VARARGS, posix_umask__doc__},
5099#ifdef HAVE_UNAME
5100	{"uname",	posix_uname, METH_VARARGS, posix_uname__doc__},
5101#endif /* HAVE_UNAME */
5102	{"unlink",	posix_unlink, METH_VARARGS, posix_unlink__doc__},
5103	{"remove",	posix_unlink, METH_VARARGS, posix_remove__doc__},
5104	{"utime",	posix_utime, METH_VARARGS, posix_utime__doc__},
5105#ifdef HAVE_TIMES
5106	{"times",	posix_times, METH_VARARGS, posix_times__doc__},
5107#endif /* HAVE_TIMES */
5108	{"_exit",	posix__exit, METH_VARARGS, posix__exit__doc__},
5109#ifdef HAVE_EXECV
5110	{"execv",	posix_execv, METH_VARARGS, posix_execv__doc__},
5111	{"execve",	posix_execve, METH_VARARGS, posix_execve__doc__},
5112#endif /* HAVE_EXECV */
5113#ifdef HAVE_SPAWNV
5114	{"spawnv",	posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
5115	{"spawnve",	posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
5116#endif /* HAVE_SPAWNV */
5117#ifdef HAVE_FORK
5118	{"fork",	posix_fork, METH_VARARGS, posix_fork__doc__},
5119#endif /* HAVE_FORK */
5120#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY)
5121	{"openpty",	posix_openpty, METH_VARARGS, posix_openpty__doc__},
5122#endif /* HAVE_OPENPTY || HAVE__GETPTY */
5123#ifdef HAVE_FORKPTY
5124	{"forkpty",	posix_forkpty, METH_VARARGS, posix_forkpty__doc__},
5125#endif /* HAVE_FORKPTY */
5126#ifdef HAVE_GETEGID
5127	{"getegid",	posix_getegid, METH_VARARGS, posix_getegid__doc__},
5128#endif /* HAVE_GETEGID */
5129#ifdef HAVE_GETEUID
5130	{"geteuid",	posix_geteuid, METH_VARARGS, posix_geteuid__doc__},
5131#endif /* HAVE_GETEUID */
5132#ifdef HAVE_GETGID
5133	{"getgid",	posix_getgid, METH_VARARGS, posix_getgid__doc__},
5134#endif /* HAVE_GETGID */
5135#ifdef HAVE_GETGROUPS
5136	{"getgroups",	posix_getgroups, METH_VARARGS, posix_getgroups__doc__},
5137#endif
5138	{"getpid",	posix_getpid, METH_VARARGS, posix_getpid__doc__},
5139#ifdef HAVE_GETPGRP
5140	{"getpgrp",	posix_getpgrp, METH_VARARGS, posix_getpgrp__doc__},
5141#endif /* HAVE_GETPGRP */
5142#ifdef HAVE_GETPPID
5143	{"getppid",	posix_getppid, METH_VARARGS, posix_getppid__doc__},
5144#endif /* HAVE_GETPPID */
5145#ifdef HAVE_GETUID
5146	{"getuid",	posix_getuid, METH_VARARGS, posix_getuid__doc__},
5147#endif /* HAVE_GETUID */
5148#ifdef HAVE_GETLOGIN
5149	{"getlogin",	posix_getlogin, METH_VARARGS, posix_getlogin__doc__},
5150#endif
5151#ifdef HAVE_KILL
5152	{"kill",	posix_kill, METH_VARARGS, posix_kill__doc__},
5153#endif /* HAVE_KILL */
5154#ifdef HAVE_PLOCK
5155	{"plock",	posix_plock, METH_VARARGS, posix_plock__doc__},
5156#endif /* HAVE_PLOCK */
5157#ifdef HAVE_POPEN
5158	{"popen",	posix_popen, METH_VARARGS, posix_popen__doc__},
5159#ifdef MS_WIN32
5160	{"popen2",	win32_popen2, METH_VARARGS},
5161	{"popen3",	win32_popen3, METH_VARARGS},
5162	{"popen4",	win32_popen4, METH_VARARGS},
5163#endif
5164#endif /* HAVE_POPEN */
5165#ifdef HAVE_SETUID
5166	{"setuid",	posix_setuid, METH_VARARGS, posix_setuid__doc__},
5167#endif /* HAVE_SETUID */
5168#ifdef HAVE_SETEUID
5169	{"seteuid",	posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
5170#endif /* HAVE_SETEUID */
5171#ifdef HAVE_SETEGID
5172	{"setegid",	posix_setegid, METH_VARARGS, posix_setegid__doc__},
5173#endif /* HAVE_SETEGID */
5174#ifdef HAVE_SETREUID
5175	{"setreuid",	posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
5176#endif /* HAVE_SETREUID */
5177#ifdef HAVE_SETREGID
5178	{"setregid",	posix_setregid,	METH_VARARGS, posix_setregid__doc__},
5179#endif /* HAVE_SETREGID */
5180#ifdef HAVE_SETGID
5181	{"setgid",	posix_setgid, METH_VARARGS, posix_setgid__doc__},
5182#endif /* HAVE_SETGID */
5183#ifdef HAVE_SETPGRP
5184	{"setpgrp",	posix_setpgrp, METH_VARARGS, posix_setpgrp__doc__},
5185#endif /* HAVE_SETPGRP */
5186#ifdef HAVE_WAIT
5187	{"wait",	posix_wait, METH_VARARGS, posix_wait__doc__},
5188#endif /* HAVE_WAIT */
5189#ifdef HAVE_WAITPID
5190	{"waitpid",	posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
5191#endif /* HAVE_WAITPID */
5192#ifdef HAVE_SETSID
5193	{"setsid",	posix_setsid, METH_VARARGS, posix_setsid__doc__},
5194#endif /* HAVE_SETSID */
5195#ifdef HAVE_SETPGID
5196	{"setpgid",	posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
5197#endif /* HAVE_SETPGID */
5198#ifdef HAVE_TCGETPGRP
5199	{"tcgetpgrp",	posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
5200#endif /* HAVE_TCGETPGRP */
5201#ifdef HAVE_TCSETPGRP
5202	{"tcsetpgrp",	posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
5203#endif /* HAVE_TCSETPGRP */
5204	{"open",	posix_open, METH_VARARGS, posix_open__doc__},
5205	{"close",	posix_close, METH_VARARGS, posix_close__doc__},
5206	{"dup",		posix_dup, METH_VARARGS, posix_dup__doc__},
5207	{"dup2",	posix_dup2, METH_VARARGS, posix_dup2__doc__},
5208	{"lseek",	posix_lseek, METH_VARARGS, posix_lseek__doc__},
5209	{"read",	posix_read, METH_VARARGS, posix_read__doc__},
5210	{"write",	posix_write, METH_VARARGS, posix_write__doc__},
5211	{"fstat",	posix_fstat, METH_VARARGS, posix_fstat__doc__},
5212	{"fdopen",	posix_fdopen, METH_VARARGS, posix_fdopen__doc__},
5213	{"isatty",	posix_isatty, METH_VARARGS, posix_isatty__doc__},
5214#ifdef HAVE_PIPE
5215	{"pipe",	posix_pipe, METH_VARARGS, posix_pipe__doc__},
5216#endif
5217#ifdef HAVE_MKFIFO
5218	{"mkfifo",	posix_mkfifo, METH_VARARGS, posix_mkfifo__doc__},
5219#endif
5220#ifdef HAVE_FTRUNCATE
5221	{"ftruncate",	posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
5222#endif
5223#ifdef HAVE_PUTENV
5224	{"putenv",	posix_putenv, METH_VARARGS, posix_putenv__doc__},
5225#endif
5226#ifdef HAVE_STRERROR
5227	{"strerror",	posix_strerror, METH_VARARGS, posix_strerror__doc__},
5228#endif
5229#ifdef HAVE_FSYNC
5230	{"fsync",       posix_fsync, METH_VARARGS, posix_fsync__doc__},
5231#endif
5232#ifdef HAVE_FDATASYNC
5233	{"fdatasync",   posix_fdatasync,  METH_VARARGS, posix_fdatasync__doc__},
5234#endif
5235#ifdef HAVE_SYS_WAIT_H
5236#ifdef WIFSTOPPED
5237        {"WIFSTOPPED",	posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
5238#endif /* WIFSTOPPED */
5239#ifdef WIFSIGNALED
5240        {"WIFSIGNALED",	posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
5241#endif /* WIFSIGNALED */
5242#ifdef WIFEXITED
5243        {"WIFEXITED",	posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
5244#endif /* WIFEXITED */
5245#ifdef WEXITSTATUS
5246        {"WEXITSTATUS",	posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
5247#endif /* WEXITSTATUS */
5248#ifdef WTERMSIG
5249        {"WTERMSIG",	posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
5250#endif /* WTERMSIG */
5251#ifdef WSTOPSIG
5252        {"WSTOPSIG",	posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
5253#endif /* WSTOPSIG */
5254#endif /* HAVE_SYS_WAIT_H */
5255#ifdef HAVE_FSTATVFS
5256	{"fstatvfs",	posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
5257#endif
5258#ifdef HAVE_STATVFS
5259	{"statvfs",	posix_statvfs, METH_VARARGS, posix_statvfs__doc__},
5260#endif
5261#ifdef HAVE_TMPNAM
5262	{"tmpfile",	posix_tmpfile, METH_VARARGS, posix_tmpfile__doc__},
5263#endif
5264#ifdef HAVE_TEMPNAM
5265	{"tempnam",	posix_tempnam, METH_VARARGS, posix_tempnam__doc__},
5266#endif
5267#ifdef HAVE_TMPNAM
5268	{"tmpnam",	posix_tmpnam, METH_VARARGS, posix_tmpnam__doc__},
5269#endif
5270#ifdef HAVE_CONFSTR
5271	{"confstr",	posix_confstr, METH_VARARGS, posix_confstr__doc__},
5272#endif
5273#ifdef HAVE_SYSCONF
5274	{"sysconf",	posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
5275#endif
5276#ifdef HAVE_FPATHCONF
5277	{"fpathconf",	posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
5278#endif
5279#ifdef HAVE_PATHCONF
5280	{"pathconf",	posix_pathconf, METH_VARARGS, posix_pathconf__doc__},
5281#endif
5282	{"abort",	posix_abort, METH_VARARGS, posix_abort__doc__},
5283	{NULL,		NULL}		 /* Sentinel */
5284};
5285
5286
5287static int
5288ins(PyObject *d, char *symbol, long value)
5289{
5290        PyObject* v = PyInt_FromLong(value);
5291        if (!v || PyDict_SetItemString(d, symbol, v) < 0)
5292                return -1;                   /* triggers fatal error */
5293
5294        Py_DECREF(v);
5295        return 0;
5296}
5297
5298#if defined(PYOS_OS2)
5299/* Insert Platform-Specific Constant Values (Strings & Numbers) of Common Use */
5300static int insertvalues(PyObject *d)
5301{
5302    APIRET    rc;
5303    ULONG     values[QSV_MAX+1];
5304    PyObject *v;
5305    char     *ver, tmp[10];
5306
5307    Py_BEGIN_ALLOW_THREADS
5308    rc = DosQuerySysInfo(1, QSV_MAX, &values[1], sizeof(values));
5309    Py_END_ALLOW_THREADS
5310
5311    if (rc != NO_ERROR) {
5312        os2_error(rc);
5313        return -1;
5314    }
5315
5316    if (ins(d, "meminstalled", values[QSV_TOTPHYSMEM])) return -1;
5317    if (ins(d, "memkernel",    values[QSV_TOTRESMEM])) return -1;
5318    if (ins(d, "memvirtual",   values[QSV_TOTAVAILMEM])) return -1;
5319    if (ins(d, "maxpathlen",   values[QSV_MAX_PATH_LENGTH])) return -1;
5320    if (ins(d, "maxnamelen",   values[QSV_MAX_COMP_LENGTH])) return -1;
5321    if (ins(d, "revision",     values[QSV_VERSION_REVISION])) return -1;
5322    if (ins(d, "timeslice",    values[QSV_MIN_SLICE])) return -1;
5323
5324    switch (values[QSV_VERSION_MINOR]) {
5325    case 0:  ver = "2.00"; break;
5326    case 10: ver = "2.10"; break;
5327    case 11: ver = "2.11"; break;
5328    case 30: ver = "3.00"; break;
5329    case 40: ver = "4.00"; break;
5330    case 50: ver = "5.00"; break;
5331    default:
5332        sprintf(tmp, "%d-%d", values[QSV_VERSION_MAJOR],
5333                              values[QSV_VERSION_MINOR]);
5334        ver = &tmp[0];
5335    }
5336
5337    /* Add Indicator of the Version of the Operating System */
5338    v = PyString_FromString(ver);
5339    if (!v || PyDict_SetItemString(d, "version", v) < 0)
5340        return -1;
5341    Py_DECREF(v);
5342
5343    /* Add Indicator of Which Drive was Used to Boot the System */
5344    tmp[0] = 'A' + values[QSV_BOOT_DRIVE] - 1;
5345    tmp[1] = ':';
5346    tmp[2] = '\0';
5347
5348    v = PyString_FromString(tmp);
5349    if (!v || PyDict_SetItemString(d, "bootdrive", v) < 0)
5350        return -1;
5351    Py_DECREF(v);
5352
5353    return 0;
5354}
5355#endif
5356
5357static int
5358all_ins(PyObject *d)
5359{
5360#ifdef F_OK
5361        if (ins(d, "F_OK", (long)F_OK)) return -1;
5362#endif
5363#ifdef R_OK
5364        if (ins(d, "R_OK", (long)R_OK)) return -1;
5365#endif
5366#ifdef W_OK
5367        if (ins(d, "W_OK", (long)W_OK)) return -1;
5368#endif
5369#ifdef X_OK
5370        if (ins(d, "X_OK", (long)X_OK)) return -1;
5371#endif
5372#ifdef NGROUPS_MAX
5373        if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
5374#endif
5375#ifdef TMP_MAX
5376        if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
5377#endif
5378#ifdef WNOHANG
5379        if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
5380#endif
5381#ifdef O_RDONLY
5382        if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
5383#endif
5384#ifdef O_WRONLY
5385        if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
5386#endif
5387#ifdef O_RDWR
5388        if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
5389#endif
5390#ifdef O_NDELAY
5391        if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
5392#endif
5393#ifdef O_NONBLOCK
5394        if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
5395#endif
5396#ifdef O_APPEND
5397        if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
5398#endif
5399#ifdef O_DSYNC
5400        if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
5401#endif
5402#ifdef O_RSYNC
5403        if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
5404#endif
5405#ifdef O_SYNC
5406        if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
5407#endif
5408#ifdef O_NOCTTY
5409        if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
5410#endif
5411#ifdef O_CREAT
5412        if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
5413#endif
5414#ifdef O_EXCL
5415        if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
5416#endif
5417#ifdef O_TRUNC
5418        if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
5419#endif
5420#ifdef O_BINARY
5421        if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
5422#endif
5423#ifdef O_TEXT
5424        if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
5425#endif
5426
5427#ifdef HAVE_SPAWNV
5428        if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
5429        if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
5430        if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
5431        if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
5432        if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
5433#endif
5434
5435#if defined(PYOS_OS2)
5436        if (insertvalues(d)) return -1;
5437#endif
5438        return 0;
5439}
5440
5441
5442#if ( defined(_MSC_VER) || defined(__WATCOMC__) ) && !defined(__QNX__)
5443#define INITFUNC initnt
5444#define MODNAME "nt"
5445#else
5446#if defined(PYOS_OS2)
5447#define INITFUNC initos2
5448#define MODNAME "os2"
5449#else
5450#define INITFUNC initposix
5451#define MODNAME "posix"
5452#endif
5453#endif
5454
5455DL_EXPORT(void)
5456INITFUNC(void)
5457{
5458	PyObject *m, *d, *v;
5459
5460	m = Py_InitModule4(MODNAME,
5461			   posix_methods,
5462			   posix__doc__,
5463			   (PyObject *)NULL,
5464			   PYTHON_API_VERSION);
5465	d = PyModule_GetDict(m);
5466
5467	/* Initialize environ dictionary */
5468	v = convertenviron();
5469	if (v == NULL || PyDict_SetItemString(d, "environ", v) != 0)
5470		return;
5471	Py_DECREF(v);
5472
5473        if (all_ins(d))
5474                return;
5475
5476        if (setup_confname_tables(d))
5477                return;
5478
5479	PyDict_SetItemString(d, "error", PyExc_OSError);
5480
5481#ifdef HAVE_PUTENV
5482	posix_putenv_garbage = PyDict_New();
5483#endif
5484}
5485