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