posixmodule.c revision 246bc17a8b680fd08af7aeb405e8d0feed3fb9f5
1/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5                        All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
32/* POSIX module implementation */
33
34/* This file is also used for Windows NT and MS-Win.  In that case the module
35   actually calls itself 'nt', not 'posix', and a few functions are
36   either unimplemented or implemented differently.  The source
37   assumes that for Windows NT, the macro 'MS_WIN32' is defined independent
38   of the compiler used.  Different compilers define their own feature
39   test macro, e.g. '__BORLANDC__' or '_MSC_VER'. */
40
41/* See also ../Dos/dosmodule.c */
42
43static char posix__doc__ [] =
44"This module provides access to operating system functionality that is\n\
45standardized by the C Standard and the POSIX standard (a thinly\n\
46disguised Unix interface).  Refer to the library manual and\n\
47corresponding Unix manual entries for more information on calls.";
48
49#include "Python.h"
50
51#if defined(PYOS_OS2)
52#define  INCL_DOS
53#define  INCL_DOSERRORS
54#define  INCL_DOSPROCESS
55#define  INCL_NOPMAPI
56#include <os2.h>
57#endif
58
59#include <sys/types.h>
60#include <sys/stat.h>
61#ifdef HAVE_SYS_WAIT_H
62#include <sys/wait.h>		/* For WNOHANG */
63#endif
64
65#ifdef HAVE_SIGNAL_H
66#include <signal.h>
67#endif
68
69#include "mytime.h"		/* For clock_t on some systems */
70
71#ifdef HAVE_FCNTL_H
72#include <fcntl.h>
73#endif /* HAVE_FCNTL_H */
74
75/* Various compilers have only certain posix functions */
76/* XXX Gosh I wish these were all moved into config.h */
77#if defined(PYCC_VACPP) && defined(PYOS_OS2)
78#include <process.h>
79#else
80#if defined(__WATCOMC__) && !defined(__QNX__)		/* Watcom compiler */
81#define HAVE_GETCWD     1
82#define HAVE_OPENDIR    1
83#define HAVE_SYSTEM	1
84#if defined(__OS2__)
85#define HAVE_EXECV      1
86#define HAVE_WAIT       1
87#endif
88#include <process.h>
89#else
90#ifdef __BORLANDC__		/* Borland compiler */
91#define HAVE_EXECV      1
92#define HAVE_GETCWD     1
93#define HAVE_GETEGID    1
94#define HAVE_GETEUID    1
95#define HAVE_GETGID     1
96#define HAVE_GETPPID    1
97#define HAVE_GETUID     1
98#define HAVE_KILL       1
99#define HAVE_OPENDIR    1
100#define HAVE_PIPE       1
101#define HAVE_POPEN      1
102#define HAVE_SYSTEM	1
103#define HAVE_WAIT       1
104#else
105#ifdef _MSC_VER		/* Microsoft compiler */
106#define HAVE_GETCWD     1
107#ifdef MS_WIN32
108#define HAVE_SPAWNV	1
109#define HAVE_EXECV      1
110#define HAVE_PIPE       1
111#define HAVE_POPEN      1
112#define HAVE_SYSTEM	1
113#else /* 16-bit Windows */
114#endif /* !MS_WIN32 */
115#else			/* all other compilers */
116/* Unix functions that the configure script doesn't check for */
117#define HAVE_EXECV      1
118#define HAVE_FORK       1
119#define HAVE_GETCWD     1
120#define HAVE_GETEGID    1
121#define HAVE_GETEUID    1
122#define HAVE_GETGID     1
123#define HAVE_GETPPID    1
124#define HAVE_GETUID     1
125#define HAVE_KILL       1
126#define HAVE_OPENDIR    1
127#define HAVE_PIPE       1
128#define HAVE_POPEN      1
129#define HAVE_SYSTEM	1
130#define HAVE_WAIT       1
131#define HAVE_TTYNAME	1
132#endif  /* _MSC_VER */
133#endif  /* __BORLANDC__ */
134#endif  /* ! __WATCOMC__ || __QNX__ */
135#endif /* ! __IBMC__ */
136
137#ifndef _MSC_VER
138
139#ifdef HAVE_UNISTD_H
140#include <unistd.h>
141#endif
142
143#ifdef NeXT
144/* NeXT's <unistd.h> and <utime.h> aren't worth much */
145#undef HAVE_UNISTD_H
146#undef HAVE_UTIME_H
147#define HAVE_WAITPID
148/* #undef HAVE_GETCWD */
149#define UNION_WAIT /* This should really be checked for by autoconf */
150#endif
151
152#ifdef HAVE_UNISTD_H
153/* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */
154extern int rename();
155extern int pclose();
156extern int lstat();
157extern int symlink();
158#else /* !HAVE_UNISTD_H */
159#if defined(PYCC_VACPP)
160extern int mkdir Py_PROTO((char *));
161#else
162#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
163extern int mkdir Py_PROTO((const char *));
164#else
165extern int mkdir Py_PROTO((const char *, mode_t));
166#endif
167#endif
168#if defined(__IBMC__) || defined(__IBMCPP__)
169extern int chdir Py_PROTO((char *));
170extern int rmdir Py_PROTO((char *));
171#else
172extern int chdir Py_PROTO((const char *));
173extern int rmdir Py_PROTO((const char *));
174#endif
175extern int chmod Py_PROTO((const char *, mode_t));
176extern int chown Py_PROTO((const char *, uid_t, gid_t));
177extern char *getcwd Py_PROTO((char *, int));
178extern char *strerror Py_PROTO((int));
179extern int link Py_PROTO((const char *, const char *));
180extern int rename Py_PROTO((const char *, const char *));
181extern int stat Py_PROTO((const char *, struct stat *));
182extern int unlink Py_PROTO((const char *));
183extern int pclose Py_PROTO((FILE *));
184#ifdef HAVE_SYMLINK
185extern int symlink Py_PROTO((const char *, const char *));
186#endif /* HAVE_SYMLINK */
187#ifdef HAVE_LSTAT
188extern int lstat Py_PROTO((const char *, struct stat *));
189#endif /* HAVE_LSTAT */
190#endif /* !HAVE_UNISTD_H */
191
192#endif /* !_MSC_VER */
193
194#ifdef HAVE_UTIME_H
195#include <utime.h>
196#endif /* HAVE_UTIME_H */
197
198#ifdef HAVE_SYS_UTIME_H
199#include <sys/utime.h>
200#define HAVE_UTIME_H /* pretend we do for the rest of this file */
201#endif /* HAVE_SYS_UTIME_H */
202
203#ifdef HAVE_SYS_TIMES_H
204#include <sys/times.h>
205#endif /* HAVE_SYS_TIMES_H */
206
207#ifdef HAVE_SYS_PARAM_H
208#include <sys/param.h>
209#endif /* HAVE_SYS_PARAM_H */
210
211#ifdef HAVE_SYS_UTSNAME_H
212#include <sys/utsname.h>
213#endif /* HAVE_SYS_UTSNAME_H */
214
215#ifndef MAXPATHLEN
216#define MAXPATHLEN 1024
217#endif /* MAXPATHLEN */
218
219#ifdef HAVE_DIRENT_H
220#include <dirent.h>
221#define NAMLEN(dirent) strlen((dirent)->d_name)
222#else
223#if defined(__WATCOMC__) && !defined(__QNX__)
224#include <direct.h>
225#define NAMLEN(dirent) strlen((dirent)->d_name)
226#else
227#define dirent direct
228#define NAMLEN(dirent) (dirent)->d_namlen
229#endif
230#ifdef HAVE_SYS_NDIR_H
231#include <sys/ndir.h>
232#endif
233#ifdef HAVE_SYS_DIR_H
234#include <sys/dir.h>
235#endif
236#ifdef HAVE_NDIR_H
237#include <ndir.h>
238#endif
239#endif
240
241#ifdef _MSC_VER
242#include <direct.h>
243#include <io.h>
244#include <process.h>
245#include <windows.h>
246#ifdef MS_WIN32
247#define popen	_popen
248#define pclose	_pclose
249#else /* 16-bit Windows */
250#include <dos.h>
251#include <ctype.h>
252#endif /* MS_WIN32 */
253#endif /* _MSC_VER */
254
255#if defined(PYCC_VACPP) && defined(PYOS_OS2)
256#include <io.h>
257#endif /* OS2 */
258
259#ifdef UNION_WAIT
260/* Emulate some macros on systems that have a union instead of macros */
261
262#ifndef WIFEXITED
263#define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
264#endif
265
266#ifndef WEXITSTATUS
267#define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
268#endif
269
270#ifndef WTERMSIG
271#define WTERMSIG(u_wait) ((u_wait).w_termsig)
272#endif
273
274#endif /* UNION_WAIT */
275
276/* Return a dictionary corresponding to the POSIX environment table */
277
278#if !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
279extern char **environ;
280#endif /* !_MSC_VER */
281
282static PyObject *
283convertenviron()
284{
285	PyObject *d;
286	char **e;
287	d = PyDict_New();
288	if (d == NULL)
289		return NULL;
290	if (environ == NULL)
291		return d;
292	/* XXX This part ignores errors */
293	for (e = environ; *e != NULL; e++) {
294		PyObject *v;
295		char *p = strchr(*e, '=');
296		if (p == NULL)
297			continue;
298		v = PyString_FromString(p+1);
299		if (v == NULL)
300			continue;
301		*p = '\0';
302		(void) PyDict_SetItemString(d, *e, v);
303		*p = '=';
304		Py_DECREF(v);
305	}
306#if defined(PYOS_OS2)
307    {
308        APIRET rc;
309        char   buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */
310
311        rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH);
312        if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */
313            PyObject *v = PyString_FromString(buffer);
314		    PyDict_SetItemString(d, "BEGINLIBPATH", v);
315            Py_DECREF(v);
316        }
317        rc = DosQueryExtLIBPATH(buffer, END_LIBPATH);
318        if (rc == NO_ERROR) { /* (not a typo, envname is NOT 'END_LIBPATH') */
319            PyObject *v = PyString_FromString(buffer);
320		    PyDict_SetItemString(d, "ENDLIBPATH", v);
321            Py_DECREF(v);
322        }
323    }
324#endif
325	return d;
326}
327
328
329static PyObject *PosixError; /* Exception posix.error */
330
331/* Set a POSIX-specific error from errno, and return NULL */
332
333static PyObject *
334posix_error()
335{
336	return PyErr_SetFromErrno(PosixError);
337}
338static PyObject *
339posix_error_with_filename(name)
340	char* name;
341{
342	return PyErr_SetFromErrnoWithFilename(PosixError, name);
343}
344
345
346#if defined(PYOS_OS2)
347/**********************************************************************
348 *         Helper Function to Trim and Format OS/2 Messages
349 **********************************************************************/
350    static void
351os2_formatmsg(char *msgbuf, int msglen, char *reason)
352{
353    msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */
354
355    if (strlen(msgbuf) > 0) { /* If Non-Empty Msg, Trim CRLF */
356        char *lastc = &msgbuf[ strlen(msgbuf)-1 ];
357
358        while (lastc > msgbuf && isspace(*lastc))
359            *lastc-- = '\0'; /* Trim Trailing Whitespace (CRLF) */
360    }
361
362    /* Add Optional Reason Text */
363    if (reason) {
364        strcat(msgbuf, " : ");
365        strcat(msgbuf, reason);
366    }
367}
368
369/**********************************************************************
370 *             Decode an OS/2 Operating System Error Code
371 *
372 * A convenience function to lookup an OS/2 error code and return a
373 * text message we can use to raise a Python exception.
374 *
375 * Notes:
376 *   The messages for errors returned from the OS/2 kernel reside in
377 *   the file OSO001.MSG in the \OS2 directory hierarchy.
378 *
379 **********************************************************************/
380    static char *
381os2_strerror(char *msgbuf, int msgbuflen, int errorcode, char *reason)
382{
383    APIRET rc;
384    ULONG  msglen;
385
386    /* Retrieve Kernel-Related Error Message from OSO001.MSG File */
387    Py_BEGIN_ALLOW_THREADS
388    rc = DosGetMessage(NULL, 0, msgbuf, msgbuflen,
389                       errorcode, "oso001.msg", &msglen);
390    Py_END_ALLOW_THREADS
391
392    if (rc == NO_ERROR)
393        os2_formatmsg(msgbuf, msglen, reason);
394    else
395        sprintf(msgbuf, "unknown OS error #%d", errorcode);
396
397    return msgbuf;
398}
399
400/* Set an OS/2-specific error and return NULL.  OS/2 kernel
401   errors are not in a global variable e.g. 'errno' nor are
402   they congruent with posix error numbers. */
403
404static PyObject * os2_error(int code)
405{
406    char text[1024];
407    PyObject *v;
408
409    os2_strerror(text, sizeof(text), code, "");
410
411    v = Py_BuildValue("(is)", code, text);
412    if (v != NULL) {
413        PyErr_SetObject(PosixError, v);
414        Py_DECREF(v);
415    }
416    return NULL; /* Signal to Python that an Exception is Pending */
417}
418
419#endif /* OS2 */
420
421/* POSIX generic methods */
422
423static PyObject *
424posix_int(args, func)
425        PyObject *args;
426	int (*func) Py_FPROTO((int));
427{
428	int fd;
429	int res;
430	if (!PyArg_Parse(args,  "i", &fd))
431		return NULL;
432	Py_BEGIN_ALLOW_THREADS
433	res = (*func)(fd);
434	Py_END_ALLOW_THREADS
435	if (res < 0)
436		return posix_error();
437	Py_INCREF(Py_None);
438	return Py_None;
439}
440
441
442static PyObject *
443posix_1str(args, func)
444	PyObject *args;
445	int (*func) Py_FPROTO((const char *));
446{
447	char *path1;
448	int res;
449	if (!PyArg_Parse(args, "s", &path1))
450		return NULL;
451	Py_BEGIN_ALLOW_THREADS
452	res = (*func)(path1);
453	Py_END_ALLOW_THREADS
454	if (res < 0)
455		return posix_error_with_filename(path1);
456	Py_INCREF(Py_None);
457	return Py_None;
458}
459
460static PyObject *
461posix_2str(args, func)
462	PyObject *args;
463	int (*func) Py_FPROTO((const char *, const char *));
464{
465	char *path1, *path2;
466	int res;
467	if (!PyArg_Parse(args, "(ss)", &path1, &path2))
468		return NULL;
469	Py_BEGIN_ALLOW_THREADS
470	res = (*func)(path1, path2);
471	Py_END_ALLOW_THREADS
472	if (res != 0)
473		/* XXX how to report both path1 and path2??? */
474		return posix_error();
475	Py_INCREF(Py_None);
476	return Py_None;
477}
478
479static PyObject *
480posix_strint(args, func)
481	PyObject *args;
482	int (*func) Py_FPROTO((const char *, int));
483{
484	char *path;
485	int i;
486	int res;
487	if (!PyArg_Parse(args, "(si)", &path, &i))
488		return NULL;
489	Py_BEGIN_ALLOW_THREADS
490	res = (*func)(path, i);
491	Py_END_ALLOW_THREADS
492	if (res < 0)
493		return posix_error_with_filename(path);
494	Py_INCREF(Py_None);
495	return Py_None;
496}
497
498static PyObject *
499posix_strintint(args, func)
500	PyObject *args;
501	int (*func) Py_FPROTO((const char *, int, int));
502{
503	char *path;
504	int i,i2;
505	int res;
506	if (!PyArg_Parse(args, "(sii)", &path, &i, &i2))
507		return NULL;
508	Py_BEGIN_ALLOW_THREADS
509	res = (*func)(path, i, i2);
510	Py_END_ALLOW_THREADS
511	if (res < 0)
512		return posix_error_with_filename(path);
513	Py_INCREF(Py_None);
514	return Py_None;
515}
516
517static PyObject *
518posix_do_stat(self, args, statfunc)
519	PyObject *self;
520	PyObject *args;
521	int (*statfunc) Py_FPROTO((const char *, struct stat *));
522{
523	struct stat st;
524	char *path;
525	int res;
526	if (!PyArg_Parse(args, "s", &path))
527		return NULL;
528	Py_BEGIN_ALLOW_THREADS
529	res = (*statfunc)(path, &st);
530	Py_END_ALLOW_THREADS
531	if (res != 0)
532		return posix_error_with_filename(path);
533#if !defined(HAVE_LARGEFILE_SUPPORT)
534	return Py_BuildValue("(llllllllll)",
535			     (long)st.st_mode,
536			     (long)st.st_ino,
537			     (long)st.st_dev,
538			     (long)st.st_nlink,
539			     (long)st.st_uid,
540			     (long)st.st_gid,
541			     (long)st.st_size,
542			     (long)st.st_atime,
543			     (long)st.st_mtime,
544			     (long)st.st_ctime);
545#else
546	return Py_BuildValue("(lLllllLlll)",
547			     (long)st.st_mode,
548			     (LONG_LONG)st.st_ino,
549			     (long)st.st_dev,
550			     (long)st.st_nlink,
551			     (long)st.st_uid,
552			     (long)st.st_gid,
553			     (LONG_LONG)st.st_size,
554			     (long)st.st_atime,
555			     (long)st.st_mtime,
556			     (long)st.st_ctime);
557#endif
558}
559
560
561/* POSIX methods */
562
563static char posix_access__doc__[] =
564"access(path, mode) -> 1 if granted, 0 otherwise\n\
565Test for access to a file.";
566
567static PyObject *
568posix_access(self, args)
569	PyObject *self;
570	PyObject *args;
571{
572	char *path;
573	int mode;
574	int res;
575
576	if (!PyArg_Parse(args, "(si)", &path, &mode))
577		return NULL;
578	Py_BEGIN_ALLOW_THREADS
579	res = access(path, mode);
580	Py_END_ALLOW_THREADS
581	return(PyInt_FromLong(res == 0 ? 1L : 0L));
582}
583
584#ifndef F_OK
585#define F_OK 0
586#endif
587#ifndef R_OK
588#define R_OK 4
589#endif
590#ifndef W_OK
591#define W_OK 2
592#endif
593#ifndef X_OK
594#define X_OK 1
595#endif
596
597#ifdef HAVE_TTYNAME
598static char posix_ttyname__doc__[] =
599"ttyname(fd, mode) -> String\n\
600Return the name of the terminal device connected to 'fd'.";
601
602static PyObject *
603posix_ttyname(self, args)
604	PyObject *self;
605	PyObject *args;
606{
607	PyObject *file;
608	int id;
609	char *ret;
610
611	if (!PyArg_Parse(args, "i", &id))
612		return NULL;
613
614	ret = ttyname(id);
615	if (ret == NULL)
616		return(posix_error());
617	return(PyString_FromString(ret));
618}
619#endif
620
621static char posix_chdir__doc__[] =
622"chdir(path) -> None\n\
623Change the current working directory to the specified path.";
624
625static PyObject *
626posix_chdir(self, args)
627	PyObject *self;
628	PyObject *args;
629{
630	return posix_1str(args, chdir);
631}
632
633
634static char posix_chmod__doc__[] =
635"chmod(path, mode) -> None\n\
636Change the access permissions of a file.";
637
638static PyObject *
639posix_chmod(self, args)
640	PyObject *self;
641	PyObject *args;
642{
643	return posix_strint(args, chmod);
644}
645
646
647#ifdef HAVE_FSYNC
648static char posix_fsync__doc__[] =
649"fsync(fildes) -> None\n\
650force write of file with filedescriptor to disk.";
651
652static PyObject *
653posix_fsync(self, args)
654       PyObject *self;
655       PyObject *args;
656{
657       return posix_int(args, fsync);
658}
659#endif /* HAVE_FSYNC */
660
661#ifdef HAVE_FDATASYNC
662static char posix_fdatasync__doc__[] =
663"fdatasync(fildes) -> None\n\
664force write of file with filedescriptor to disk.\n\
665 does not force update of metadata.";
666
667extern int fdatasync(int); /* Prototype just in case */
668
669static PyObject *
670posix_fdatasync(self, args)
671       PyObject *self;
672       PyObject *args;
673{
674       return posix_int(args, fdatasync);
675}
676#endif /* HAVE_FDATASYNC */
677
678
679#ifdef HAVE_CHOWN
680static char posix_chown__doc__[] =
681"chown(path, uid, gid) -> None\n\
682Change the owner and group id of path to the numeric uid and gid.";
683
684static PyObject *
685posix_chown(self, args)
686	PyObject *self;
687	PyObject *args;
688{
689	return posix_strintint(args, chown);
690}
691#endif /* HAVE_CHOWN */
692
693
694#ifdef HAVE_GETCWD
695static char posix_getcwd__doc__[] =
696"getcwd() -> path\n\
697Return a string representing the current working directory.";
698
699static PyObject *
700posix_getcwd(self, args)
701	PyObject *self;
702	PyObject *args;
703{
704	char buf[1026];
705	char *res;
706	if (!PyArg_NoArgs(args))
707		return NULL;
708	Py_BEGIN_ALLOW_THREADS
709	res = getcwd(buf, sizeof buf);
710	Py_END_ALLOW_THREADS
711	if (res == NULL)
712		return posix_error();
713	return PyString_FromString(buf);
714}
715#endif
716
717
718#ifdef HAVE_LINK
719static char posix_link__doc__[] =
720"link(src, dst) -> None\n\
721Create a hard link to a file.";
722
723static PyObject *
724posix_link(self, args)
725	PyObject *self;
726	PyObject *args;
727{
728	return posix_2str(args, link);
729}
730#endif /* HAVE_LINK */
731
732
733static char posix_listdir__doc__[] =
734"listdir(path) -> list_of_strings\n\
735Return a list containing the names of the entries in the directory.\n\
736\n\
737	path: path of directory to list\n\
738\n\
739The list is in arbitrary order.  It does not include the special\n\
740entries '.' and '..' even if they are present in the directory.";
741
742static PyObject *
743posix_listdir(self, args)
744	PyObject *self;
745	PyObject *args;
746{
747	/* XXX Should redo this putting the (now four) versions of opendir
748	   in separate files instead of having them all here... */
749#if defined(MS_WIN32) && !defined(HAVE_OPENDIR)
750
751	char *name;
752	int len;
753	PyObject *d, *v;
754	HANDLE hFindFile;
755	WIN32_FIND_DATA FileData;
756	char namebuf[MAX_PATH+5];
757
758	if (!PyArg_Parse(args, "t#", &name, &len))
759		return NULL;
760	if (len >= MAX_PATH) {
761		PyErr_SetString(PyExc_ValueError, "path too long");
762		return NULL;
763	}
764	strcpy(namebuf, name);
765	if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
766		namebuf[len++] = '/';
767	strcpy(namebuf + len, "*.*");
768
769	if ((d = PyList_New(0)) == NULL)
770		return NULL;
771
772	hFindFile = FindFirstFile(namebuf, &FileData);
773	if (hFindFile == INVALID_HANDLE_VALUE) {
774		errno = GetLastError();
775		if (errno == ERROR_FILE_NOT_FOUND)
776			return PyList_New(0);
777		return posix_error();
778	}
779	do {
780		if (FileData.cFileName[0] == '.' &&
781		    (FileData.cFileName[1] == '\0' ||
782		     FileData.cFileName[1] == '.' &&
783		     FileData.cFileName[2] == '\0'))
784			continue;
785		v = PyString_FromString(FileData.cFileName);
786		if (v == NULL) {
787			Py_DECREF(d);
788			d = NULL;
789			break;
790		}
791		if (PyList_Append(d, v) != 0) {
792			Py_DECREF(v);
793			Py_DECREF(d);
794			d = NULL;
795			break;
796		}
797		Py_DECREF(v);
798	} while (FindNextFile(hFindFile, &FileData) == TRUE);
799
800	if (FindClose(hFindFile) == FALSE) {
801		errno = GetLastError();
802		return posix_error();
803	}
804
805	return d;
806
807#else /* !MS_WIN32 */
808#ifdef _MSC_VER /* 16-bit Windows */
809
810#ifndef MAX_PATH
811#define MAX_PATH	250
812#endif
813	char *name, *pt;
814	int len;
815	PyObject *d, *v;
816	char namebuf[MAX_PATH+5];
817	struct _find_t ep;
818
819	if (!PyArg_Parse(args, "t#", &name, &len))
820		return NULL;
821	if (len >= MAX_PATH) {
822		PyErr_SetString(PyExc_ValueError, "path too long");
823		return NULL;
824	}
825	strcpy(namebuf, name);
826	for (pt = namebuf; *pt; pt++)
827		if (*pt == '/')
828			*pt = '\\';
829	if (namebuf[len-1] != '\\')
830		namebuf[len++] = '\\';
831	strcpy(namebuf + len, "*.*");
832
833	if ((d = PyList_New(0)) == NULL)
834		return NULL;
835
836	if (_dos_findfirst(namebuf, _A_RDONLY |
837			   _A_HIDDEN | _A_SYSTEM | _A_SUBDIR, &ep) != 0)
838        {
839		errno = ENOENT;
840		return posix_error();
841	}
842	do {
843		if (ep.name[0] == '.' &&
844		    (ep.name[1] == '\0' ||
845		     ep.name[1] == '.' &&
846		     ep.name[2] == '\0'))
847			continue;
848		strcpy(namebuf, ep.name);
849		for (pt = namebuf; *pt; pt++)
850			if (isupper(*pt))
851				*pt = tolower(*pt);
852		v = PyString_FromString(namebuf);
853		if (v == NULL) {
854			Py_DECREF(d);
855			d = NULL;
856			break;
857		}
858		if (PyList_Append(d, v) != 0) {
859			Py_DECREF(v);
860			Py_DECREF(d);
861			d = NULL;
862			break;
863		}
864		Py_DECREF(v);
865	} while (_dos_findnext(&ep) == 0);
866
867	return d;
868
869#else
870#if defined(PYOS_OS2)
871
872#ifndef MAX_PATH
873#define MAX_PATH    CCHMAXPATH
874#endif
875    char *name, *pt;
876    int len;
877    PyObject *d, *v;
878    char namebuf[MAX_PATH+5];
879    HDIR  hdir = 1;
880    ULONG srchcnt = 1;
881    FILEFINDBUF3   ep;
882    APIRET rc;
883
884	if (!PyArg_Parse(args, "t#", &name, &len))
885        return NULL;
886    if (len >= MAX_PATH) {
887		PyErr_SetString(PyExc_ValueError, "path too long");
888        return NULL;
889    }
890    strcpy(namebuf, name);
891    for (pt = namebuf; *pt; pt++)
892        if (*pt == '/')
893            *pt = '\\';
894    if (namebuf[len-1] != '\\')
895        namebuf[len++] = '\\';
896    strcpy(namebuf + len, "*.*");
897
898	if ((d = PyList_New(0)) == NULL)
899        return NULL;
900
901    rc = DosFindFirst(namebuf,         /* Wildcard Pattern to Match */
902                      &hdir,           /* Handle to Use While Search Directory */
903                      FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY,
904                      &ep, sizeof(ep), /* Structure to Receive Directory Entry */
905                      &srchcnt,        /* Max and Actual Count of Entries Per Iteration */
906                      FIL_STANDARD);   /* Format of Entry (EAs or Not) */
907
908    if (rc != NO_ERROR) {
909        errno = ENOENT;
910        return posix_error();
911    }
912
913    if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */
914        do {
915            if (ep.achName[0] == '.'
916            && (ep.achName[1] == '\0' || ep.achName[1] == '.' && ep.achName[2] == '\0'))
917                continue; /* Skip Over "." and ".." Names */
918
919            strcpy(namebuf, ep.achName);
920
921            /* Leave Case of Name Alone -- In Native Form */
922            /* (Removed Forced Lowercasing Code) */
923
924            v = PyString_FromString(namebuf);
925            if (v == NULL) {
926                Py_DECREF(d);
927                d = NULL;
928                break;
929            }
930            if (PyList_Append(d, v) != 0) {
931                Py_DECREF(v);
932                Py_DECREF(d);
933                d = NULL;
934                break;
935            }
936            Py_DECREF(v);
937        } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && srchcnt > 0);
938    }
939
940    return d;
941#else
942
943	char *name;
944	PyObject *d, *v;
945	DIR *dirp;
946	struct dirent *ep;
947	if (!PyArg_Parse(args, "s", &name))
948		return NULL;
949	Py_BEGIN_ALLOW_THREADS
950	if ((dirp = opendir(name)) == NULL) {
951		Py_BLOCK_THREADS
952		return posix_error();
953	}
954	if ((d = PyList_New(0)) == NULL) {
955		closedir(dirp);
956		Py_BLOCK_THREADS
957		return NULL;
958	}
959	while ((ep = readdir(dirp)) != NULL) {
960		if (ep->d_name[0] == '.' &&
961		    (NAMLEN(ep) == 1 ||
962		     (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
963			continue;
964		v = PyString_FromStringAndSize(ep->d_name, NAMLEN(ep));
965		if (v == NULL) {
966			Py_DECREF(d);
967			d = NULL;
968			break;
969		}
970		if (PyList_Append(d, v) != 0) {
971			Py_DECREF(v);
972			Py_DECREF(d);
973			d = NULL;
974			break;
975		}
976		Py_DECREF(v);
977	}
978	closedir(dirp);
979	Py_END_ALLOW_THREADS
980
981	return d;
982
983#endif /* !PYOS_OS2 */
984#endif /* !_MSC_VER */
985#endif /* !MS_WIN32 */
986}
987
988static char posix_mkdir__doc__[] =
989"mkdir(path [, mode=0777]) -> None\n\
990Create a directory.";
991
992static PyObject *
993posix_mkdir(self, args)
994	PyObject *self;
995	PyObject *args;
996{
997	int res;
998	char *path;
999	int mode = 0777;
1000	if (!PyArg_ParseTuple(args, "s|i", &path, &mode))
1001		return NULL;
1002	Py_BEGIN_ALLOW_THREADS
1003#if ( defined(__WATCOMC__) || defined(_MSC_VER) || defined(PYCC_VACPP) ) && !defined(__QNX__)
1004	res = mkdir(path);
1005#else
1006	res = mkdir(path, mode);
1007#endif
1008	Py_END_ALLOW_THREADS
1009	if (res < 0)
1010		return posix_error_with_filename(path);
1011	Py_INCREF(Py_None);
1012	return Py_None;
1013}
1014
1015
1016#ifdef HAVE_NICE
1017static char posix_nice__doc__[] =
1018"nice(inc) -> new_priority\n\
1019Decrease the priority of process and return new priority.";
1020
1021static PyObject *
1022posix_nice(self, args)
1023	PyObject *self;
1024	PyObject *args;
1025{
1026	int increment, value;
1027
1028	if (!PyArg_Parse(args, "i", &increment))
1029		return NULL;
1030	value = nice(increment);
1031	if (value == -1)
1032		return posix_error();
1033	return PyInt_FromLong((long) value);
1034}
1035#endif /* HAVE_NICE */
1036
1037
1038static char posix_rename__doc__[] =
1039"rename(old, new) -> None\n\
1040Rename a file or directory.";
1041
1042static PyObject *
1043posix_rename(self, args)
1044	PyObject *self;
1045	PyObject *args;
1046{
1047	return posix_2str(args, rename);
1048}
1049
1050
1051static char posix_rmdir__doc__[] =
1052"rmdir(path) -> None\n\
1053Remove a directory.";
1054
1055static PyObject *
1056posix_rmdir(self, args)
1057	PyObject *self;
1058	PyObject *args;
1059{
1060	return posix_1str(args, rmdir);
1061}
1062
1063
1064static char posix_stat__doc__[] =
1065"stat(path) -> (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\
1066Perform a stat system call on the given path.";
1067
1068static PyObject *
1069posix_stat(self, args)
1070	PyObject *self;
1071	PyObject *args;
1072{
1073	return posix_do_stat(self, args, stat);
1074}
1075
1076
1077#ifdef HAVE_SYSTEM
1078static char posix_system__doc__[] =
1079"system(command) -> exit_status\n\
1080Execute the command (a string) in a subshell.";
1081
1082static PyObject *
1083posix_system(self, args)
1084	PyObject *self;
1085	PyObject *args;
1086{
1087	char *command;
1088	long sts;
1089	if (!PyArg_Parse(args, "s", &command))
1090		return NULL;
1091	Py_BEGIN_ALLOW_THREADS
1092	sts = system(command);
1093	Py_END_ALLOW_THREADS
1094	return PyInt_FromLong(sts);
1095}
1096#endif
1097
1098
1099static char posix_umask__doc__[] =
1100"umask(new_mask) -> old_mask\n\
1101Set the current numeric umask and return the previous umask.";
1102
1103static PyObject *
1104posix_umask(self, args)
1105	PyObject *self;
1106	PyObject *args;
1107{
1108	int i;
1109	if (!PyArg_Parse(args, "i", &i))
1110		return NULL;
1111	i = umask(i);
1112	if (i < 0)
1113		return posix_error();
1114	return PyInt_FromLong((long)i);
1115}
1116
1117
1118static char posix_unlink__doc__[] =
1119"unlink(path) -> None\n\
1120Remove a file (same as remove(path)).";
1121
1122static char posix_remove__doc__[] =
1123"remove(path) -> None\n\
1124Remove a file (same as unlink(path)).";
1125
1126static PyObject *
1127posix_unlink(self, args)
1128	PyObject *self;
1129	PyObject *args;
1130{
1131	return posix_1str(args, unlink);
1132}
1133
1134
1135#ifdef HAVE_UNAME
1136static char posix_uname__doc__[] =
1137"uname() -> (sysname, nodename, release, version, machine)\n\
1138Return a tuple identifying the current operating system.";
1139
1140static PyObject *
1141posix_uname(self, args)
1142	PyObject *self;
1143	PyObject *args;
1144{
1145	struct utsname u;
1146	int res;
1147	if (!PyArg_NoArgs(args))
1148		return NULL;
1149	Py_BEGIN_ALLOW_THREADS
1150	res = uname(&u);
1151	Py_END_ALLOW_THREADS
1152	if (res < 0)
1153		return posix_error();
1154	return Py_BuildValue("(sssss)",
1155			     u.sysname,
1156			     u.nodename,
1157			     u.release,
1158			     u.version,
1159			     u.machine);
1160}
1161#endif /* HAVE_UNAME */
1162
1163
1164static char posix_utime__doc__[] =
1165"utime(path, (atime, utime)) -> None\n\
1166Set the access and modified time of the file to the given values.";
1167
1168static PyObject *
1169posix_utime(self, args)
1170	PyObject *self;
1171	PyObject *args;
1172{
1173	char *path;
1174	long atime, mtime;
1175	int res;
1176
1177/* XXX should define struct utimbuf instead, above */
1178#ifdef HAVE_UTIME_H
1179	struct utimbuf buf;
1180#define ATIME buf.actime
1181#define MTIME buf.modtime
1182#define UTIME_ARG &buf
1183#else /* HAVE_UTIME_H */
1184	time_t buf[2];
1185#define ATIME buf[0]
1186#define MTIME buf[1]
1187#define UTIME_ARG buf
1188#endif /* HAVE_UTIME_H */
1189
1190	if (!PyArg_Parse(args, "(s(ll))", &path, &atime, &mtime))
1191		return NULL;
1192	ATIME = atime;
1193	MTIME = mtime;
1194	Py_BEGIN_ALLOW_THREADS
1195	res = utime(path, UTIME_ARG);
1196	Py_END_ALLOW_THREADS
1197	if (res < 0)
1198		return posix_error_with_filename(path);
1199	Py_INCREF(Py_None);
1200	return Py_None;
1201#undef UTIME_ARG
1202#undef ATIME
1203#undef MTIME
1204}
1205
1206
1207/* Process operations */
1208
1209static char posix__exit__doc__[] =
1210"_exit(status)\n\
1211Exit to the system with specified status, without normal exit processing.";
1212
1213static PyObject *
1214posix__exit(self, args)
1215	PyObject *self;
1216	PyObject *args;
1217{
1218	int sts;
1219	if (!PyArg_Parse(args, "i", &sts))
1220		return NULL;
1221	_exit(sts);
1222	return NULL; /* Make gcc -Wall happy */
1223}
1224
1225
1226#ifdef HAVE_EXECV
1227static char posix_execv__doc__[] =
1228"execv(path, args)\n\
1229Execute an executable path with arguments, replacing current process.\n\
1230\n\
1231	path: path of executable file\n\
1232	args: tuple or list of strings";
1233
1234static PyObject *
1235posix_execv(self, args)
1236	PyObject *self;
1237	PyObject *args;
1238{
1239	char *path;
1240	PyObject *argv;
1241	char **argvlist;
1242	int i, argc;
1243	PyObject *(*getitem) Py_PROTO((PyObject *, int));
1244
1245	/* execv has two arguments: (path, argv), where
1246	   argv is a list or tuple of strings. */
1247
1248	if (!PyArg_Parse(args, "(sO)", &path, &argv))
1249		return NULL;
1250	if (PyList_Check(argv)) {
1251		argc = PyList_Size(argv);
1252		getitem = PyList_GetItem;
1253	}
1254	else if (PyTuple_Check(argv)) {
1255		argc = PyTuple_Size(argv);
1256		getitem = PyTuple_GetItem;
1257	}
1258	else {
1259 badarg:
1260		PyErr_BadArgument();
1261		return NULL;
1262	}
1263
1264	argvlist = PyMem_NEW(char *, argc+1);
1265	if (argvlist == NULL)
1266		return NULL;
1267	for (i = 0; i < argc; i++) {
1268		if (!PyArg_Parse((*getitem)(argv, i), "s", &argvlist[i])) {
1269			PyMem_DEL(argvlist);
1270			goto badarg;
1271		}
1272	}
1273	argvlist[argc] = NULL;
1274
1275#ifdef BAD_EXEC_PROTOTYPES
1276	execv(path, (const char **) argvlist);
1277#else /* BAD_EXEC_PROTOTYPES */
1278	execv(path, argvlist);
1279#endif /* BAD_EXEC_PROTOTYPES */
1280
1281	/* If we get here it's definitely an error */
1282
1283	PyMem_DEL(argvlist);
1284	return posix_error();
1285}
1286
1287
1288static char posix_execve__doc__[] =
1289"execve(path, args, env)\n\
1290Execute a path with arguments and environment, replacing current process.\n\
1291\n\
1292	path: path of executable file\n\
1293	args: tuple or list of arguments\n\
1294	env: dictonary of strings mapping to strings";
1295
1296static PyObject *
1297posix_execve(self, args)
1298	PyObject *self;
1299	PyObject *args;
1300{
1301	char *path;
1302	PyObject *argv, *env;
1303	char **argvlist;
1304	char **envlist;
1305	PyObject *key, *val, *keys=NULL, *vals=NULL;
1306	int i, pos, argc, envc;
1307	PyObject *(*getitem) Py_PROTO((PyObject *, int));
1308
1309	/* execve has three arguments: (path, argv, env), where
1310	   argv is a list or tuple of strings and env is a dictionary
1311	   like posix.environ. */
1312
1313	if (!PyArg_Parse(args, "(sOO)", &path, &argv, &env))
1314		return NULL;
1315	if (PyList_Check(argv)) {
1316		argc = PyList_Size(argv);
1317		getitem = PyList_GetItem;
1318	}
1319	else if (PyTuple_Check(argv)) {
1320		argc = PyTuple_Size(argv);
1321		getitem = PyTuple_GetItem;
1322	}
1323	else {
1324		PyErr_SetString(PyExc_TypeError, "argv must be tuple or list");
1325		return NULL;
1326	}
1327	if (!PyMapping_Check(env)) {
1328		PyErr_SetString(PyExc_TypeError, "env must be mapping object");
1329		return NULL;
1330	}
1331
1332	argvlist = PyMem_NEW(char *, argc+1);
1333	if (argvlist == NULL) {
1334		PyErr_NoMemory();
1335		return NULL;
1336	}
1337	for (i = 0; i < argc; i++) {
1338		if (!PyArg_Parse((*getitem)(argv, i),
1339				 "s;argv must be list of strings",
1340				 &argvlist[i]))
1341		{
1342			goto fail_1;
1343		}
1344	}
1345	argvlist[argc] = NULL;
1346
1347	i = PyMapping_Length(env);
1348	envlist = PyMem_NEW(char *, i + 1);
1349	if (envlist == NULL) {
1350		PyErr_NoMemory();
1351		goto fail_1;
1352	}
1353	envc = 0;
1354	keys = PyMapping_Keys(env);
1355	vals = PyMapping_Values(env);
1356	if (!keys || !vals)
1357		goto fail_2;
1358
1359	for (pos = 0; pos < i; pos++) {
1360		char *p, *k, *v;
1361
1362		key = PyList_GetItem(keys, pos);
1363		val = PyList_GetItem(vals, pos);
1364		if (!key || !val)
1365			goto fail_2;
1366
1367		if (!PyArg_Parse(key, "s;non-string key in env", &k) ||
1368		    !PyArg_Parse(val, "s;non-string value in env", &v))
1369		{
1370			goto fail_2;
1371		}
1372
1373#if defined(PYOS_OS2)
1374        /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
1375        if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
1376#endif
1377		p = PyMem_NEW(char, PyString_Size(key)+PyString_Size(val) + 2);
1378		if (p == NULL) {
1379			PyErr_NoMemory();
1380			goto fail_2;
1381		}
1382		sprintf(p, "%s=%s", k, v);
1383		envlist[envc++] = p;
1384#if defined(PYOS_OS2)
1385    }
1386#endif
1387	}
1388	envlist[envc] = 0;
1389
1390
1391#ifdef BAD_EXEC_PROTOTYPES
1392	execve(path, (const char **)argvlist, envlist);
1393#else /* BAD_EXEC_PROTOTYPES */
1394	execve(path, argvlist, envlist);
1395#endif /* BAD_EXEC_PROTOTYPES */
1396
1397	/* If we get here it's definitely an error */
1398
1399	(void) posix_error();
1400
1401 fail_2:
1402	while (--envc >= 0)
1403		PyMem_DEL(envlist[envc]);
1404	PyMem_DEL(envlist);
1405 fail_1:
1406	PyMem_DEL(argvlist);
1407	Py_XDECREF(vals);
1408	Py_XDECREF(keys);
1409	return NULL;
1410}
1411#endif /* HAVE_EXECV */
1412
1413
1414#ifdef HAVE_SPAWNV
1415static char posix_spawnv__doc__[] =
1416"spawnv(mode, path, args)\n\
1417Execute an executable path with arguments, replacing current process.\n\
1418\n\
1419	mode: mode of process creation\n\
1420	path: path of executable file\n\
1421	args: tuple or list of strings";
1422
1423static PyObject *
1424posix_spawnv(self, args)
1425	PyObject *self;
1426	PyObject *args;
1427{
1428	char *path;
1429	PyObject *argv;
1430	char **argvlist;
1431	int mode, i, argc;
1432	PyObject *(*getitem) Py_PROTO((PyObject *, int));
1433
1434	/* spawnv has three arguments: (mode, path, argv), where
1435	   argv is a list or tuple of strings. */
1436
1437	if (!PyArg_Parse(args, "(isO)", &mode, &path, &argv))
1438		return NULL;
1439	if (PyList_Check(argv)) {
1440		argc = PyList_Size(argv);
1441		getitem = PyList_GetItem;
1442	}
1443	else if (PyTuple_Check(argv)) {
1444		argc = PyTuple_Size(argv);
1445		getitem = PyTuple_GetItem;
1446	}
1447	else {
1448 badarg:
1449		PyErr_BadArgument();
1450		return NULL;
1451	}
1452
1453	argvlist = PyMem_NEW(char *, argc+1);
1454	if (argvlist == NULL)
1455		return NULL;
1456	for (i = 0; i < argc; i++) {
1457		if (!PyArg_Parse((*getitem)(argv, i), "s", &argvlist[i])) {
1458			PyMem_DEL(argvlist);
1459			goto badarg;
1460		}
1461	}
1462	argvlist[argc] = NULL;
1463
1464	if (mode == _OLD_P_OVERLAY)
1465		mode = _P_OVERLAY;
1466	i = _spawnv(mode, path, argvlist);
1467
1468	PyMem_DEL(argvlist);
1469
1470	if (i == -1)
1471		return posix_error();
1472	else
1473		return Py_BuildValue("i", i);
1474}
1475
1476
1477static char posix_spawnve__doc__[] =
1478"spawnve(mode, path, args, env)\n\
1479Execute a path with arguments and environment, replacing current process.\n\
1480\n\
1481	mode: mode of process creation\n\
1482	path: path of executable file\n\
1483	args: tuple or list of arguments\n\
1484	env: dictonary of strings mapping to strings";
1485
1486static PyObject *
1487posix_spawnve(self, args)
1488	PyObject *self;
1489	PyObject *args;
1490{
1491	char *path;
1492	PyObject *argv, *env;
1493	char **argvlist;
1494	char **envlist;
1495	PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
1496	int mode, i, pos, argc, envc;
1497	PyObject *(*getitem) Py_PROTO((PyObject *, int));
1498
1499	/* spawnve has four arguments: (mode, path, argv, env), where
1500	   argv is a list or tuple of strings and env is a dictionary
1501	   like posix.environ. */
1502
1503	if (!PyArg_Parse(args, "(isOO)", &mode, &path, &argv, &env))
1504		return NULL;
1505	if (PyList_Check(argv)) {
1506		argc = PyList_Size(argv);
1507		getitem = PyList_GetItem;
1508	}
1509	else if (PyTuple_Check(argv)) {
1510		argc = PyTuple_Size(argv);
1511		getitem = PyTuple_GetItem;
1512	}
1513	else {
1514		PyErr_SetString(PyExc_TypeError, "argv must be tuple or list");
1515		return NULL;
1516	}
1517	if (!PyMapping_Check(env)) {
1518		PyErr_SetString(PyExc_TypeError, "env must be mapping object");
1519		return NULL;
1520	}
1521
1522	argvlist = PyMem_NEW(char *, argc+1);
1523	if (argvlist == NULL) {
1524		PyErr_NoMemory();
1525		return NULL;
1526	}
1527	for (i = 0; i < argc; i++) {
1528		if (!PyArg_Parse((*getitem)(argv, i),
1529				 "s;argv must be list of strings",
1530				 &argvlist[i]))
1531		{
1532			goto fail_1;
1533		}
1534	}
1535	argvlist[argc] = NULL;
1536
1537	i = PyMapping_Length(env);
1538	envlist = PyMem_NEW(char *, i + 1);
1539	if (envlist == NULL) {
1540		PyErr_NoMemory();
1541		goto fail_1;
1542	}
1543	envc = 0;
1544	keys = PyMapping_Keys(env);
1545	vals = PyMapping_Values(env);
1546	if (!keys || !vals)
1547		goto fail_2;
1548
1549	for (pos = 0; pos < i; pos++) {
1550		char *p, *k, *v;
1551
1552		key = PyList_GetItem(keys, pos);
1553		val = PyList_GetItem(vals, pos);
1554		if (!key || !val)
1555			goto fail_2;
1556
1557		if (!PyArg_Parse(key, "s;non-string key in env", &k) ||
1558		    !PyArg_Parse(val, "s;non-string value in env", &v))
1559		{
1560			goto fail_2;
1561		}
1562		p = PyMem_NEW(char, PyString_Size(key)+PyString_Size(val) + 2);
1563		if (p == NULL) {
1564			PyErr_NoMemory();
1565			goto fail_2;
1566		}
1567		sprintf(p, "%s=%s", k, v);
1568		envlist[envc++] = p;
1569	}
1570	envlist[envc] = 0;
1571
1572	if (mode == _OLD_P_OVERLAY)
1573		mode = _P_OVERLAY;
1574	i = _spawnve(mode, path, argvlist, envlist);
1575	if (i == -1)
1576		(void) posix_error();
1577	else
1578		res = Py_BuildValue("i", i);
1579
1580 fail_2:
1581	while (--envc >= 0)
1582		PyMem_DEL(envlist[envc]);
1583	PyMem_DEL(envlist);
1584 fail_1:
1585	PyMem_DEL(argvlist);
1586	Py_XDECREF(vals);
1587	Py_XDECREF(keys);
1588	return res;
1589}
1590#endif /* HAVE_SPAWNV */
1591
1592
1593#ifdef HAVE_FORK
1594static char posix_fork__doc__[] =
1595"fork() -> pid\n\
1596Fork a child process.\n\
1597\n\
1598Return 0 to child process and PID of child to parent process.";
1599
1600static PyObject *
1601posix_fork(self, args)
1602	PyObject *self;
1603	PyObject *args;
1604{
1605	int pid;
1606	if (!PyArg_NoArgs(args))
1607		return NULL;
1608	pid = fork();
1609	if (pid == -1)
1610		return posix_error();
1611	PyOS_AfterFork();
1612	return PyInt_FromLong((long)pid);
1613}
1614#endif
1615
1616
1617#ifdef HAVE_GETEGID
1618static char posix_getegid__doc__[] =
1619"getegid() -> egid\n\
1620Return the current process's effective group id.";
1621
1622static PyObject *
1623posix_getegid(self, args)
1624	PyObject *self;
1625	PyObject *args;
1626{
1627	if (!PyArg_NoArgs(args))
1628		return NULL;
1629	return PyInt_FromLong((long)getegid());
1630}
1631#endif
1632
1633
1634#ifdef HAVE_GETEUID
1635static char posix_geteuid__doc__[] =
1636"geteuid() -> euid\n\
1637Return the current process's effective user id.";
1638
1639static PyObject *
1640posix_geteuid(self, args)
1641	PyObject *self;
1642	PyObject *args;
1643{
1644	if (!PyArg_NoArgs(args))
1645		return NULL;
1646	return PyInt_FromLong((long)geteuid());
1647}
1648#endif
1649
1650
1651#ifdef HAVE_GETGID
1652static char posix_getgid__doc__[] =
1653"getgid() -> gid\n\
1654Return the current process's group id.";
1655
1656static PyObject *
1657posix_getgid(self, args)
1658	PyObject *self;
1659	PyObject *args;
1660{
1661	if (!PyArg_NoArgs(args))
1662		return NULL;
1663	return PyInt_FromLong((long)getgid());
1664}
1665#endif
1666
1667
1668static char posix_getpid__doc__[] =
1669"getpid() -> pid\n\
1670Return the current process id";
1671
1672static PyObject *
1673posix_getpid(self, args)
1674	PyObject *self;
1675	PyObject *args;
1676{
1677	if (!PyArg_NoArgs(args))
1678		return NULL;
1679	return PyInt_FromLong((long)getpid());
1680}
1681
1682
1683#ifdef HAVE_GETPGRP
1684static char posix_getpgrp__doc__[] =
1685"getpgrp() -> pgrp\n\
1686Return the current process group id.";
1687
1688static PyObject *
1689posix_getpgrp(self, args)
1690	PyObject *self;
1691	PyObject *args;
1692{
1693	if (!PyArg_NoArgs(args))
1694		return NULL;
1695#ifdef GETPGRP_HAVE_ARG
1696	return PyInt_FromLong((long)getpgrp(0));
1697#else /* GETPGRP_HAVE_ARG */
1698	return PyInt_FromLong((long)getpgrp());
1699#endif /* GETPGRP_HAVE_ARG */
1700}
1701#endif /* HAVE_GETPGRP */
1702
1703
1704#ifdef HAVE_SETPGRP
1705static char posix_setpgrp__doc__[] =
1706"setpgrp() -> None\n\
1707Make this process a session leader.";
1708
1709static PyObject *
1710posix_setpgrp(self, args)
1711	PyObject *self;
1712	PyObject *args;
1713{
1714	if (!PyArg_NoArgs(args))
1715		return NULL;
1716#ifdef SETPGRP_HAVE_ARG
1717	if (setpgrp(0, 0) < 0)
1718#else /* SETPGRP_HAVE_ARG */
1719	if (setpgrp() < 0)
1720#endif /* SETPGRP_HAVE_ARG */
1721		return posix_error();
1722	Py_INCREF(Py_None);
1723	return Py_None;
1724}
1725
1726#endif /* HAVE_SETPGRP */
1727
1728#ifdef HAVE_GETPPID
1729static char posix_getppid__doc__[] =
1730"getppid() -> ppid\n\
1731Return the parent's process id.";
1732
1733static PyObject *
1734posix_getppid(self, args)
1735	PyObject *self;
1736	PyObject *args;
1737{
1738	if (!PyArg_NoArgs(args))
1739		return NULL;
1740	return PyInt_FromLong((long)getppid());
1741}
1742#endif
1743
1744
1745#ifdef HAVE_GETUID
1746static char posix_getuid__doc__[] =
1747"getuid() -> uid\n\
1748Return the current process's user id.";
1749
1750static PyObject *
1751posix_getuid(self, args)
1752	PyObject *self;
1753	PyObject *args;
1754{
1755	if (!PyArg_NoArgs(args))
1756		return NULL;
1757	return PyInt_FromLong((long)getuid());
1758}
1759#endif
1760
1761
1762#ifdef HAVE_KILL
1763static char posix_kill__doc__[] =
1764"kill(pid, sig) -> None\n\
1765Kill a process with a signal.";
1766
1767static PyObject *
1768posix_kill(self, args)
1769	PyObject *self;
1770	PyObject *args;
1771{
1772	int pid, sig;
1773	if (!PyArg_Parse(args, "(ii)", &pid, &sig))
1774		return NULL;
1775#if defined(PYOS_OS2)
1776    if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
1777        APIRET rc;
1778        if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
1779            return os2_error(rc);
1780
1781    } else if (sig == XCPT_SIGNAL_KILLPROC) {
1782        APIRET rc;
1783        if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
1784            return os2_error(rc);
1785
1786    } else
1787        return NULL; /* Unrecognized Signal Requested */
1788#else
1789	if (kill(pid, sig) == -1)
1790		return posix_error();
1791#endif
1792	Py_INCREF(Py_None);
1793	return Py_None;
1794}
1795#endif
1796
1797#ifdef HAVE_PLOCK
1798
1799#ifdef HAVE_SYS_LOCK_H
1800#include <sys/lock.h>
1801#endif
1802
1803static char posix_plock__doc__[] =
1804"plock(op) -> None\n\
1805Lock program segments into memory.";
1806
1807static PyObject *
1808posix_plock(self, args)
1809	PyObject *self;
1810	PyObject *args;
1811{
1812	int op;
1813	if (!PyArg_Parse(args, "i", &op))
1814		return NULL;
1815	if (plock(op) == -1)
1816		return posix_error();
1817	Py_INCREF(Py_None);
1818	return Py_None;
1819}
1820#endif
1821
1822
1823#ifdef HAVE_POPEN
1824static char posix_popen__doc__[] =
1825"popen(command [, mode='r' [, bufsize]]) -> pipe\n\
1826Open a pipe to/from a command returning a file object.";
1827
1828#if defined(PYOS_OS2)
1829static int
1830async_system(const char *command)
1831{
1832    char        *p, errormsg[256], args[1024];
1833    RESULTCODES  rcodes;
1834    APIRET       rc;
1835    char        *shell = getenv("COMSPEC");
1836    if (!shell)
1837        shell = "cmd";
1838
1839    strcpy(args, shell);
1840    p = &args[ strlen(args)+1 ];
1841    strcpy(p, "/c ");
1842    strcat(p, command);
1843    p += strlen(p) + 1;
1844    *p = '\0';
1845
1846    rc = DosExecPgm(errormsg, sizeof(errormsg),
1847                    EXEC_ASYNC, /* Execute Async w/o Wait for Results */
1848                    args,
1849                    NULL,       /* Inherit Parent's Environment */
1850                    &rcodes, shell);
1851    return rc;
1852}
1853
1854static FILE *
1855popen(const char *command, const char *mode, int pipesize, int *err)
1856{
1857    HFILE    rhan, whan;
1858    FILE    *retfd = NULL;
1859    APIRET   rc = DosCreatePipe(&rhan, &whan, pipesize);
1860
1861    if (rc != NO_ERROR) {
1862	*err = rc;
1863        return NULL; /* ERROR - Unable to Create Anon Pipe */
1864    }
1865
1866    if (strchr(mode, 'r') != NULL) { /* Treat Command as a Data Source */
1867        int oldfd = dup(1);      /* Save STDOUT Handle in Another Handle */
1868
1869        DosEnterCritSec();      /* Stop Other Threads While Changing Handles */
1870        close(1);                /* Make STDOUT Available for Reallocation */
1871
1872        if (dup2(whan, 1) == 0) {      /* Connect STDOUT to Pipe Write Side */
1873            DosClose(whan);            /* Close Now-Unused Pipe Write Handle */
1874
1875            if (async_system(command) == NO_ERROR)
1876                retfd = fdopen(rhan, mode); /* And Return Pipe Read Handle */
1877        }
1878
1879        dup2(oldfd, 1);          /* Reconnect STDOUT to Original Handle */
1880        DosExitCritSec();        /* Now Allow Other Threads to Run */
1881
1882        close(oldfd);            /* And Close Saved STDOUT Handle */
1883        return retfd;            /* Return fd of Pipe or NULL if Error */
1884
1885    } else if (strchr(mode, 'w')) { /* Treat Command as a Data Sink */
1886        int oldfd = dup(0);      /* Save STDIN Handle in Another Handle */
1887
1888        DosEnterCritSec();      /* Stop Other Threads While Changing Handles */
1889        close(0);                /* Make STDIN Available for Reallocation */
1890
1891        if (dup2(rhan, 0) == 0)     { /* Connect STDIN to Pipe Read Side */
1892            DosClose(rhan);           /* Close Now-Unused Pipe Read Handle */
1893
1894            if (async_system(command) == NO_ERROR)
1895                retfd = fdopen(whan, mode); /* And Return Pipe Write Handle */
1896        }
1897
1898        dup2(oldfd, 0);          /* Reconnect STDIN to Original Handle */
1899        DosExitCritSec();        /* Now Allow Other Threads to Run */
1900
1901        close(oldfd);            /* And Close Saved STDIN Handle */
1902        return retfd;            /* Return fd of Pipe or NULL if Error */
1903
1904    } else {
1905	*err = ERROR_INVALID_ACCESS;
1906        return NULL; /* ERROR - Invalid Mode (Neither Read nor Write) */
1907    }
1908}
1909
1910static PyObject *
1911posix_popen(self, args)
1912	PyObject *self;
1913	PyObject *args;
1914{
1915	char *name;
1916	char *mode = "r";
1917	int   err, bufsize = -1;
1918	FILE *fp;
1919	PyObject *f;
1920	if (!PyArg_ParseTuple(args, "s|si", &name, &mode, &bufsize))
1921		return NULL;
1922	Py_BEGIN_ALLOW_THREADS
1923	fp = popen(name, mode, (bufsize > 0) ? bufsize : 4096, &err);
1924	Py_END_ALLOW_THREADS
1925	if (fp == NULL)
1926		return os2_error(err);
1927
1928	f = PyFile_FromFile(fp, name, mode, fclose);
1929	if (f != NULL)
1930		PyFile_SetBufSize(f, bufsize);
1931	return f;
1932}
1933
1934#else
1935static PyObject *
1936posix_popen(self, args)
1937	PyObject *self;
1938	PyObject *args;
1939{
1940	char *name;
1941	char *mode = "r";
1942	int bufsize = -1;
1943	FILE *fp;
1944	PyObject *f;
1945	if (!PyArg_ParseTuple(args, "s|si", &name, &mode, &bufsize))
1946		return NULL;
1947	Py_BEGIN_ALLOW_THREADS
1948	fp = popen(name, mode);
1949	Py_END_ALLOW_THREADS
1950	if (fp == NULL)
1951		return posix_error();
1952	f = PyFile_FromFile(fp, name, mode, pclose);
1953	if (f != NULL)
1954		PyFile_SetBufSize(f, bufsize);
1955	return f;
1956}
1957#endif
1958
1959#endif /* HAVE_POPEN */
1960
1961
1962#ifdef HAVE_SETUID
1963static char posix_setuid__doc__[] =
1964"setuid(uid) -> None\n\
1965Set the current process's user id.";
1966static PyObject *
1967posix_setuid(self, args)
1968	PyObject *self;
1969	PyObject *args;
1970{
1971	int uid;
1972	if (!PyArg_Parse(args, "i", &uid))
1973		return NULL;
1974	if (setuid(uid) < 0)
1975		return posix_error();
1976	Py_INCREF(Py_None);
1977	return Py_None;
1978}
1979#endif /* HAVE_SETUID */
1980
1981
1982#ifdef HAVE_SETGID
1983static char posix_setgid__doc__[] =
1984"setgid(gid) -> None\n\
1985Set the current process's group id.";
1986
1987static PyObject *
1988posix_setgid(self, args)
1989	PyObject *self;
1990	PyObject *args;
1991{
1992	int gid;
1993	if (!PyArg_Parse(args, "i", &gid))
1994		return NULL;
1995	if (setgid(gid) < 0)
1996		return posix_error();
1997	Py_INCREF(Py_None);
1998	return Py_None;
1999}
2000#endif /* HAVE_SETGID */
2001
2002
2003#ifdef HAVE_WAITPID
2004static char posix_waitpid__doc__[] =
2005"waitpid(pid, options) -> (pid, status)\n\
2006Wait for completion of a give child process.";
2007
2008static PyObject *
2009posix_waitpid(self, args)
2010	PyObject *self;
2011	PyObject *args;
2012{
2013	int pid, options;
2014#ifdef UNION_WAIT
2015	union wait status;
2016#define status_i (status.w_status)
2017#else
2018	int status;
2019#define status_i status
2020#endif
2021	status_i = 0;
2022
2023	if (!PyArg_Parse(args, "(ii)", &pid, &options))
2024		return NULL;
2025	Py_BEGIN_ALLOW_THREADS
2026#ifdef NeXT
2027	pid = wait4(pid, &status, options, NULL);
2028#else
2029	pid = waitpid(pid, &status, options);
2030#endif
2031	Py_END_ALLOW_THREADS
2032	if (pid == -1)
2033		return posix_error();
2034	else
2035		return Py_BuildValue("ii", pid, status_i);
2036}
2037#endif /* HAVE_WAITPID */
2038
2039
2040#ifdef HAVE_WAIT
2041static char posix_wait__doc__[] =
2042"wait() -> (pid, status)\n\
2043Wait for completion of a child process.";
2044
2045static PyObject *
2046posix_wait(self, args)
2047	PyObject *self;
2048	PyObject *args;
2049{
2050	int pid, sts;
2051#ifdef UNION_WAIT
2052	union wait status;
2053#define status_i (status.w_status)
2054#else
2055	int status;
2056#define status_i status
2057#endif
2058	status_i = 0;
2059	Py_BEGIN_ALLOW_THREADS
2060	pid = wait(&status);
2061	Py_END_ALLOW_THREADS
2062	if (pid == -1)
2063		return posix_error();
2064	else
2065		return Py_BuildValue("ii", pid, status_i);
2066}
2067#endif
2068
2069
2070static char posix_lstat__doc__[] =
2071"lstat(path) -> (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\
2072Like stat(path), but do not follow symbolic links.";
2073
2074static PyObject *
2075posix_lstat(self, args)
2076	PyObject *self;
2077	PyObject *args;
2078{
2079#ifdef HAVE_LSTAT
2080	return posix_do_stat(self, args, lstat);
2081#else /* !HAVE_LSTAT */
2082	return posix_do_stat(self, args, stat);
2083#endif /* !HAVE_LSTAT */
2084}
2085
2086
2087#ifdef HAVE_READLINK
2088static char posix_readlink__doc__[] =
2089"readlink(path) -> path\n\
2090Return a string representing the path to which the symbolic link points.";
2091
2092static PyObject *
2093posix_readlink(self, args)
2094	PyObject *self;
2095	PyObject *args;
2096{
2097	char buf[MAXPATHLEN];
2098	char *path;
2099	int n;
2100	if (!PyArg_Parse(args, "s", &path))
2101		return NULL;
2102	Py_BEGIN_ALLOW_THREADS
2103	n = readlink(path, buf, (int) sizeof buf);
2104	Py_END_ALLOW_THREADS
2105	if (n < 0)
2106		return posix_error_with_filename(path);
2107	return PyString_FromStringAndSize(buf, n);
2108}
2109#endif /* HAVE_READLINK */
2110
2111
2112#ifdef HAVE_SYMLINK
2113static char posix_symlink__doc__[] =
2114"symlink(src, dst) -> None\n\
2115Create a symbolic link.";
2116
2117static PyObject *
2118posix_symlink(self, args)
2119	PyObject *self;
2120	PyObject *args;
2121{
2122	return posix_2str(args, symlink);
2123}
2124#endif /* HAVE_SYMLINK */
2125
2126
2127#ifdef HAVE_TIMES
2128#ifndef HZ
2129#define HZ 60 /* Universal constant :-) */
2130#endif /* HZ */
2131
2132#if defined(PYCC_VACPP) && defined(PYOS_OS2)
2133static long
2134system_uptime()
2135{
2136    ULONG     value = 0;
2137
2138    Py_BEGIN_ALLOW_THREADS
2139    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value));
2140    Py_END_ALLOW_THREADS
2141
2142    return value;
2143}
2144
2145static PyObject *
2146posix_times(self, args)
2147	PyObject *self;
2148	PyObject *args;
2149{
2150	if (!PyArg_NoArgs(args))
2151		return NULL;
2152
2153    /* Currently Only Uptime is Provided -- Others Later */
2154	return Py_BuildValue("ddddd",
2155			     (double)0 /* t.tms_utime / HZ */,
2156			     (double)0 /* t.tms_stime / HZ */,
2157			     (double)0 /* t.tms_cutime / HZ */,
2158			     (double)0 /* t.tms_cstime / HZ */,
2159			     (double)system_uptime() / 1000);
2160}
2161#else /* not OS2 */
2162static PyObject *
2163posix_times(self, args)
2164	PyObject *self;
2165	PyObject *args;
2166{
2167	struct tms t;
2168	clock_t c;
2169	if (!PyArg_NoArgs(args))
2170		return NULL;
2171	errno = 0;
2172	c = times(&t);
2173	if (c == (clock_t) -1)
2174		return posix_error();
2175	return Py_BuildValue("ddddd",
2176			     (double)t.tms_utime / HZ,
2177			     (double)t.tms_stime / HZ,
2178			     (double)t.tms_cutime / HZ,
2179			     (double)t.tms_cstime / HZ,
2180			     (double)c / HZ);
2181}
2182#endif /* not OS2 */
2183#endif /* HAVE_TIMES */
2184
2185
2186#ifdef MS_WIN32
2187#define HAVE_TIMES	/* so the method table will pick it up */
2188static PyObject *
2189posix_times(self, args)
2190	PyObject *self;
2191	PyObject *args;
2192{
2193	FILETIME create, exit, kernel, user;
2194	HANDLE hProc;
2195	if (!PyArg_NoArgs(args))
2196		return NULL;
2197	hProc = GetCurrentProcess();
2198	GetProcessTimes(hProc,&create, &exit, &kernel, &user);
2199	return Py_BuildValue(
2200		"ddddd",
2201		(double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime)/2E6,
2202		(double)(user.dwHighDateTime*2E32+user.dwLowDateTime) / 2E6,
2203		(double)0,
2204		(double)0,
2205		(double)0);
2206}
2207#endif /* MS_WIN32 */
2208
2209#ifdef HAVE_TIMES
2210static char posix_times__doc__[] =
2211"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\
2212Return a tuple of floating point numbers indicating process times.";
2213#endif
2214
2215
2216#ifdef HAVE_SETSID
2217static char posix_setsid__doc__[] =
2218"setsid() -> None\n\
2219Call the system call setsid().";
2220
2221static PyObject *
2222posix_setsid(self, args)
2223	PyObject *self;
2224	PyObject *args;
2225{
2226	if (!PyArg_NoArgs(args))
2227		return NULL;
2228	if (setsid() < 0)
2229		return posix_error();
2230	Py_INCREF(Py_None);
2231	return Py_None;
2232}
2233#endif /* HAVE_SETSID */
2234
2235#ifdef HAVE_SETPGID
2236static char posix_setpgid__doc__[] =
2237"setpgid(pid, pgrp) -> None\n\
2238Call the system call setpgid().";
2239
2240static PyObject *
2241posix_setpgid(self, args)
2242	PyObject *self;
2243	PyObject *args;
2244{
2245	int pid, pgrp;
2246	if (!PyArg_Parse(args, "(ii)", &pid, &pgrp))
2247		return NULL;
2248	if (setpgid(pid, pgrp) < 0)
2249		return posix_error();
2250	Py_INCREF(Py_None);
2251	return Py_None;
2252}
2253#endif /* HAVE_SETPGID */
2254
2255
2256#ifdef HAVE_TCGETPGRP
2257static char posix_tcgetpgrp__doc__[] =
2258"tcgetpgrp(fd) -> pgid\n\
2259Return the process group associated with the terminal given by a fd.";
2260
2261static PyObject *
2262posix_tcgetpgrp(self, args)
2263	PyObject *self;
2264	PyObject *args;
2265{
2266	int fd, pgid;
2267	if (!PyArg_Parse(args, "i", &fd))
2268		return NULL;
2269	pgid = tcgetpgrp(fd);
2270	if (pgid < 0)
2271		return posix_error();
2272	return PyInt_FromLong((long)pgid);
2273}
2274#endif /* HAVE_TCGETPGRP */
2275
2276
2277#ifdef HAVE_TCSETPGRP
2278static char posix_tcsetpgrp__doc__[] =
2279"tcsetpgrp(fd, pgid) -> None\n\
2280Set the process group associated with the terminal given by a fd.";
2281
2282static PyObject *
2283posix_tcsetpgrp(self, args)
2284	PyObject *self;
2285	PyObject *args;
2286{
2287	int fd, pgid;
2288	if (!PyArg_Parse(args, "(ii)", &fd, &pgid))
2289		return NULL;
2290	if (tcsetpgrp(fd, pgid) < 0)
2291		return posix_error();
2292	Py_INCREF(Py_None);
2293	return Py_None;
2294}
2295#endif /* HAVE_TCSETPGRP */
2296
2297/* Functions acting on file descriptors */
2298
2299static char posix_open__doc__[] =
2300"open(filename, flag [, mode=0777]) -> fd\n\
2301Open a file (for low level IO).";
2302
2303static PyObject *
2304posix_open(self, args)
2305	PyObject *self;
2306	PyObject *args;
2307{
2308	char *file;
2309	int flag;
2310	int mode = 0777;
2311	int fd;
2312	if (!PyArg_ParseTuple(args, "si|i", &file, &flag, &mode))
2313		return NULL;
2314
2315	Py_BEGIN_ALLOW_THREADS
2316	fd = open(file, flag, mode);
2317	Py_END_ALLOW_THREADS
2318	if (fd < 0)
2319		return posix_error_with_filename(file);
2320	return PyInt_FromLong((long)fd);
2321}
2322
2323
2324static char posix_close__doc__[] =
2325"close(fd) -> None\n\
2326Close a file descriptor (for low level IO).";
2327
2328static PyObject *
2329posix_close(self, args)
2330	PyObject *self;
2331	PyObject *args;
2332{
2333	int fd, res;
2334	if (!PyArg_Parse(args, "i", &fd))
2335		return NULL;
2336	Py_BEGIN_ALLOW_THREADS
2337	res = close(fd);
2338	Py_END_ALLOW_THREADS
2339	if (res < 0)
2340		return posix_error();
2341	Py_INCREF(Py_None);
2342	return Py_None;
2343}
2344
2345
2346static char posix_dup__doc__[] =
2347"dup(fd) -> fd2\n\
2348Return a duplicate of a file descriptor.";
2349
2350static PyObject *
2351posix_dup(self, args)
2352	PyObject *self;
2353	PyObject *args;
2354{
2355	int fd;
2356	if (!PyArg_Parse(args, "i", &fd))
2357		return NULL;
2358	Py_BEGIN_ALLOW_THREADS
2359	fd = dup(fd);
2360	Py_END_ALLOW_THREADS
2361	if (fd < 0)
2362		return posix_error();
2363	return PyInt_FromLong((long)fd);
2364}
2365
2366
2367static char posix_dup2__doc__[] =
2368"dup2(fd, fd2) -> None\n\
2369Duplicate file descriptor.";
2370
2371static PyObject *
2372posix_dup2(self, args)
2373	PyObject *self;
2374	PyObject *args;
2375{
2376	int fd, fd2, res;
2377	if (!PyArg_Parse(args, "(ii)", &fd, &fd2))
2378		return NULL;
2379	Py_BEGIN_ALLOW_THREADS
2380	res = dup2(fd, fd2);
2381	Py_END_ALLOW_THREADS
2382	if (res < 0)
2383		return posix_error();
2384	Py_INCREF(Py_None);
2385	return Py_None;
2386}
2387
2388
2389static char posix_lseek__doc__[] =
2390"lseek(fd, pos, how) -> newpos\n\
2391Set the current position of a file descriptor.";
2392
2393static PyObject *
2394posix_lseek(self, args)
2395	PyObject *self;
2396	PyObject *args;
2397{
2398	int fd, how;
2399	off_t pos, res;
2400	PyObject *posobj;
2401	if (!PyArg_Parse(args, "(iOi)", &fd, &posobj, &how))
2402		return NULL;
2403#ifdef SEEK_SET
2404	/* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
2405	switch (how) {
2406	case 0: how = SEEK_SET; break;
2407	case 1: how = SEEK_CUR; break;
2408	case 2: how = SEEK_END; break;
2409	}
2410#endif /* SEEK_END */
2411
2412#if !defined(HAVE_LARGEFILE_SUPPORT)
2413	pos = PyInt_AsLong(posobj);
2414#else
2415	pos = PyLong_Check(posobj) ?
2416		PyLong_AsLongLong(posobj) : PyInt_AsLong(posobj);
2417#endif
2418	if (PyErr_Occurred())
2419		return NULL;
2420
2421	Py_BEGIN_ALLOW_THREADS
2422	res = lseek(fd, pos, how);
2423	Py_END_ALLOW_THREADS
2424	if (res < 0)
2425		return posix_error();
2426
2427#if !defined(HAVE_LARGEFILE_SUPPORT)
2428	return PyInt_FromLong(res);
2429#else
2430	return PyLong_FromLongLong(res);
2431#endif
2432}
2433
2434
2435static char posix_read__doc__[] =
2436"read(fd, buffersize) -> string\n\
2437Read a file descriptor.";
2438
2439static PyObject *
2440posix_read(self, args)
2441	PyObject *self;
2442	PyObject *args;
2443{
2444	int fd, size, n;
2445	PyObject *buffer;
2446	if (!PyArg_Parse(args, "(ii)", &fd, &size))
2447		return NULL;
2448	buffer = PyString_FromStringAndSize((char *)NULL, size);
2449	if (buffer == NULL)
2450		return NULL;
2451	Py_BEGIN_ALLOW_THREADS
2452	n = read(fd, PyString_AsString(buffer), size);
2453	Py_END_ALLOW_THREADS
2454	if (n < 0) {
2455		Py_DECREF(buffer);
2456		return posix_error();
2457	}
2458	if (n != size)
2459		_PyString_Resize(&buffer, n);
2460	return buffer;
2461}
2462
2463
2464static char posix_write__doc__[] =
2465"write(fd, string) -> byteswritten\n\
2466Write a string to a file descriptor.";
2467
2468static PyObject *
2469posix_write(self, args)
2470	PyObject *self;
2471	PyObject *args;
2472{
2473	int fd, size;
2474	char *buffer;
2475	if (!PyArg_Parse(args, "(is#)", &fd, &buffer, &size))
2476		return NULL;
2477	Py_BEGIN_ALLOW_THREADS
2478	size = write(fd, buffer, size);
2479	Py_END_ALLOW_THREADS
2480	if (size < 0)
2481		return posix_error();
2482	return PyInt_FromLong((long)size);
2483}
2484
2485
2486static char posix_fstat__doc__[]=
2487"fstat(fd) -> (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2488Like stat(), but for an open file descriptor.";
2489
2490static PyObject *
2491posix_fstat(self, args)
2492	PyObject *self;
2493	PyObject *args;
2494{
2495	int fd;
2496	struct stat st;
2497	int res;
2498	if (!PyArg_Parse(args, "i", &fd))
2499		return NULL;
2500	Py_BEGIN_ALLOW_THREADS
2501	res = fstat(fd, &st);
2502	Py_END_ALLOW_THREADS
2503	if (res != 0)
2504		return posix_error();
2505#if !defined(HAVE_LARGEFILE_SUPPORT)
2506	return Py_BuildValue("(llllllllll)",
2507			     (long)st.st_mode,
2508			     (long)st.st_ino,
2509			     (long)st.st_dev,
2510			     (long)st.st_nlink,
2511			     (long)st.st_uid,
2512			     (long)st.st_gid,
2513			     (long)st.st_size,
2514			     (long)st.st_atime,
2515			     (long)st.st_mtime,
2516			     (long)st.st_ctime);
2517#else
2518	return Py_BuildValue("(lLllllLlll)",
2519			     (long)st.st_mode,
2520			     (LONG_LONG)st.st_ino,
2521			     (long)st.st_dev,
2522			     (long)st.st_nlink,
2523			     (long)st.st_uid,
2524			     (long)st.st_gid,
2525			     (LONG_LONG)st.st_size,
2526			     (long)st.st_atime,
2527			     (long)st.st_mtime,
2528			     (long)st.st_ctime);
2529#endif
2530}
2531
2532
2533static char posix_fdopen__doc__[] =
2534"fdopen(fd, [, mode='r' [, bufsize]]) -> file_object\n\
2535Return an open file object connected to a file descriptor.";
2536
2537static PyObject *
2538posix_fdopen(self, args)
2539	PyObject *self;
2540	PyObject *args;
2541{
2542	extern int fclose Py_PROTO((FILE *));
2543	int fd;
2544	char *mode = "r";
2545	int bufsize = -1;
2546	FILE *fp;
2547	PyObject *f;
2548	if (!PyArg_ParseTuple(args, "i|si", &fd, &mode, &bufsize))
2549		return NULL;
2550
2551	Py_BEGIN_ALLOW_THREADS
2552	fp = fdopen(fd, mode);
2553	Py_END_ALLOW_THREADS
2554	if (fp == NULL)
2555		return posix_error();
2556	f = PyFile_FromFile(fp, "(fdopen)", mode, fclose);
2557	if (f != NULL)
2558		PyFile_SetBufSize(f, bufsize);
2559	return f;
2560}
2561
2562
2563#ifdef HAVE_PIPE
2564static char posix_pipe__doc__[] =
2565"pipe() -> (read_end, write_end)\n\
2566Create a pipe.";
2567
2568static PyObject *
2569posix_pipe(self, args)
2570	PyObject *self;
2571	PyObject *args;
2572{
2573#if defined(PYOS_OS2)
2574    HFILE read, write;
2575    APIRET rc;
2576
2577    if (!PyArg_Parse(args, ""))
2578        return NULL;
2579
2580	Py_BEGIN_ALLOW_THREADS
2581    rc = DosCreatePipe( &read, &write, 4096);
2582	Py_END_ALLOW_THREADS
2583    if (rc != NO_ERROR)
2584        return os2_error(rc);
2585
2586    return Py_BuildValue("(ii)", read, write);
2587#else
2588#if !defined(MS_WIN32)
2589	int fds[2];
2590	int res;
2591	if (!PyArg_Parse(args, ""))
2592		return NULL;
2593	Py_BEGIN_ALLOW_THREADS
2594	res = pipe(fds);
2595	Py_END_ALLOW_THREADS
2596	if (res != 0)
2597		return posix_error();
2598	return Py_BuildValue("(ii)", fds[0], fds[1]);
2599#else /* MS_WIN32 */
2600	HANDLE read, write;
2601	int read_fd, write_fd;
2602	BOOL ok;
2603	if (!PyArg_Parse(args, ""))
2604		return NULL;
2605	Py_BEGIN_ALLOW_THREADS
2606	ok = CreatePipe(&read, &write, NULL, 0);
2607	Py_END_ALLOW_THREADS
2608	if (!ok)
2609		return posix_error();
2610	read_fd = _open_osfhandle((long)read, 0);
2611	write_fd = _open_osfhandle((long)write, 1);
2612	return Py_BuildValue("(ii)", read_fd, write_fd);
2613#endif /* MS_WIN32 */
2614#endif
2615}
2616#endif  /* HAVE_PIPE */
2617
2618
2619#ifdef HAVE_MKFIFO
2620static char posix_mkfifo__doc__[] =
2621"mkfifo(file, [, mode=0666]) -> None\n\
2622Create a FIFO (a POSIX named pipe).";
2623
2624static PyObject *
2625posix_mkfifo(self, args)
2626	PyObject *self;
2627	PyObject *args;
2628{
2629	char *file;
2630	int mode = 0666;
2631	int res;
2632	if (!PyArg_ParseTuple(args, "s|i", &file, &mode))
2633		return NULL;
2634	Py_BEGIN_ALLOW_THREADS
2635	res = mkfifo(file, mode);
2636	Py_END_ALLOW_THREADS
2637	if (res < 0)
2638		return posix_error();
2639	Py_INCREF(Py_None);
2640	return Py_None;
2641}
2642#endif
2643
2644
2645#ifdef HAVE_FTRUNCATE
2646static char posix_ftruncate__doc__[] =
2647"ftruncate(fd, length) -> None\n\
2648Truncate a file to a specified length.";
2649
2650static PyObject *
2651posix_ftruncate(self, args)
2652	PyObject *self; /* Not used */
2653	PyObject *args;
2654{
2655	int fd;
2656	off_t length;
2657	int res;
2658	PyObject *lenobj;
2659
2660	if (!PyArg_Parse(args, "(iO)", &fd, &lenobj))
2661		return NULL;
2662
2663#if !defined(HAVE_LARGEFILE_SUPPORT)
2664	length = PyInt_AsLong(lenobj);
2665#else
2666	length = PyLong_Check(lenobj) ?
2667		PyLong_AsLongLong(lenobj) : PyInt_AsLong(lenobj);
2668#endif
2669	if (PyErr_Occurred())
2670		return NULL;
2671
2672	Py_BEGIN_ALLOW_THREADS
2673	res = ftruncate(fd, length);
2674	Py_END_ALLOW_THREADS
2675	if (res < 0) {
2676		PyErr_SetFromErrno(PyExc_IOError);
2677		return NULL;
2678	}
2679	Py_INCREF(Py_None);
2680	return Py_None;
2681}
2682#endif
2683
2684#ifdef NeXT
2685#define HAVE_PUTENV
2686/* Steve Spicklemire got this putenv from NeXTAnswers */
2687static int
2688putenv(char *newval)
2689{
2690	extern char **environ;
2691
2692	static int firstTime = 1;
2693	char **ep;
2694	char *cp;
2695	int esiz;
2696	char *np;
2697
2698	if (!(np = strchr(newval, '=')))
2699		return 1;
2700	*np = '\0';
2701
2702	/* look it up */
2703	for (ep=environ ; *ep ; ep++)
2704	{
2705		/* this should always be true... */
2706		if (cp = strchr(*ep, '='))
2707		{
2708			*cp = '\0';
2709			if (!strcmp(*ep, newval))
2710			{
2711				/* got it! */
2712				*cp = '=';
2713				break;
2714			}
2715			*cp = '=';
2716		}
2717		else
2718		{
2719			*np = '=';
2720			return 1;
2721		}
2722	}
2723
2724	*np = '=';
2725	if (*ep)
2726	{
2727		/* the string was already there:
2728		   just replace it with the new one */
2729		*ep = newval;
2730		return 0;
2731	}
2732
2733	/* expand environ by one */
2734	for (esiz=2, ep=environ ; *ep ; ep++)
2735		esiz++;
2736	if (firstTime)
2737	{
2738		char **epp;
2739		char **newenv;
2740		if (!(newenv = malloc(esiz * sizeof(char *))))
2741			return 1;
2742
2743		for (ep=environ, epp=newenv ; *ep ;)
2744			*epp++ = *ep++;
2745		*epp++ = newval;
2746		*epp = (char *) 0;
2747		environ = newenv;
2748	}
2749	else
2750	{
2751		if (!(environ = realloc(environ, esiz * sizeof(char *))))
2752			return 1;
2753		environ[esiz - 2] = newval;
2754		environ[esiz - 1] = (char *) 0;
2755		firstTime = 0;
2756	}
2757
2758	return 0;
2759}
2760#endif /* NeXT */
2761
2762
2763#ifdef HAVE_PUTENV
2764static char posix_putenv__doc__[] =
2765"putenv(key, value) -> None\n\
2766Change or add an environment variable.";
2767
2768#ifdef __BEOS__
2769/* We have putenv(), but not in the headers (as of PR2). - [cjh] */
2770int putenv( const char *str );
2771#endif
2772
2773static PyObject *
2774posix_putenv(self, args)
2775	PyObject *self;
2776	PyObject *args;
2777{
2778        char *s1, *s2;
2779        char *new;
2780
2781	if (!PyArg_ParseTuple(args, "ss", &s1, &s2))
2782		return NULL;
2783
2784#if defined(PYOS_OS2)
2785    if (stricmp(s1, "BEGINLIBPATH") == 0) {
2786        APIRET rc;
2787
2788        if (strlen(s2) == 0)  /* If New Value is an Empty String */
2789            s2 = NULL;        /* Then OS/2 API Wants a NULL to Undefine It */
2790
2791        rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH);
2792        if (rc != NO_ERROR)
2793            return os2_error(rc);
2794
2795    } else if (stricmp(s1, "ENDLIBPATH") == 0) {
2796        APIRET rc;
2797
2798        if (strlen(s2) == 0)  /* If New Value is an Empty String */
2799            s2 = NULL;        /* Then OS/2 API Wants a NULL to Undefine It */
2800
2801        rc = DosSetExtLIBPATH(s2, END_LIBPATH);
2802        if (rc != NO_ERROR)
2803            return os2_error(rc);
2804    } else {
2805#endif
2806
2807	/* XXX This leaks memory -- not easy to fix :-( */
2808	if ((new = malloc(strlen(s1) + strlen(s2) + 2)) == NULL)
2809                return PyErr_NoMemory();
2810	(void) sprintf(new, "%s=%s", s1, s2);
2811	if (putenv(new)) {
2812                posix_error();
2813                return NULL;
2814	}
2815
2816#if defined(PYOS_OS2)
2817    }
2818#endif
2819	Py_INCREF(Py_None);
2820        return Py_None;
2821}
2822#endif /* putenv */
2823
2824#ifdef HAVE_STRERROR
2825static char posix_strerror__doc__[] =
2826"strerror(code) -> string\n\
2827Translate an error code to a message string.";
2828
2829PyObject *
2830posix_strerror(self, args)
2831	PyObject *self;
2832	PyObject *args;
2833{
2834	int code;
2835	char *message;
2836	if (!PyArg_ParseTuple(args, "i", &code))
2837		return NULL;
2838	message = strerror(code);
2839	if (message == NULL) {
2840		PyErr_SetString(PyExc_ValueError,
2841				"strerror code out of range");
2842		return NULL;
2843	}
2844	return PyString_FromString(message);
2845}
2846#endif /* strerror */
2847
2848
2849#ifdef HAVE_SYS_WAIT_H
2850
2851#ifdef WIFSTOPPED
2852static char posix_WIFSTOPPED__doc__[] =
2853"WIFSTOPPED(status) -> Boolean\n\
2854See Unix documentation.";
2855
2856static PyObject *
2857posix_WIFSTOPPED(self, args)
2858	PyObject *self;
2859	PyObject *args;
2860{
2861#ifdef UNION_WAIT
2862	union wait status;
2863#define status_i (status.w_status)
2864#else
2865	int status;
2866#define status_i status
2867#endif
2868	status_i = 0;
2869
2870	if (!PyArg_Parse(args, "i", &status_i))
2871	{
2872		return NULL;
2873	}
2874
2875	return Py_BuildValue("i", WIFSTOPPED(status));
2876}
2877#endif /* WIFSTOPPED */
2878
2879#ifdef WIFSIGNALED
2880static char posix_WIFSIGNALED__doc__[] =
2881"WIFSIGNALED(status) -> Boolean\n\
2882See Unix documentation.";
2883
2884static PyObject *
2885posix_WIFSIGNALED(self, args)
2886	PyObject *self;
2887	PyObject *args;
2888{
2889#ifdef UNION_WAIT
2890	union wait status;
2891#define status_i (status.w_status)
2892#else
2893	int status;
2894#define status_i status
2895#endif
2896	status_i = 0;
2897
2898	if (!PyArg_Parse(args, "i", &status_i))
2899	{
2900		return NULL;
2901	}
2902
2903	return Py_BuildValue("i", WIFSIGNALED(status));
2904}
2905#endif /* WIFSIGNALED */
2906
2907#ifdef WIFEXITED
2908static char posix_WIFEXITED__doc__[] =
2909"WIFEXITED(status) -> Boolean\n\
2910See Unix documentation.";
2911
2912static PyObject *
2913posix_WIFEXITED(self, args)
2914	PyObject *self;
2915	PyObject *args;
2916{
2917#ifdef UNION_WAIT
2918	union wait status;
2919#define status_i (status.w_status)
2920#else
2921	int status;
2922#define status_i status
2923#endif
2924	status_i = 0;
2925
2926	if (!PyArg_Parse(args, "i", &status_i))
2927	{
2928		return NULL;
2929	}
2930
2931	return Py_BuildValue("i", WIFEXITED(status));
2932}
2933#endif /* WIFEXITED */
2934
2935#ifdef WEXITSTATUS
2936static char posix_WEXITSTATUS__doc__[] =
2937"WEXITSTATUS(status) -> integer\n\
2938See Unix documentation.";
2939
2940static PyObject *
2941posix_WEXITSTATUS(self, args)
2942	PyObject *self;
2943	PyObject *args;
2944{
2945#ifdef UNION_WAIT
2946	union wait status;
2947#define status_i (status.w_status)
2948#else
2949	int status;
2950#define status_i status
2951#endif
2952	status_i = 0;
2953
2954	if (!PyArg_Parse(args, "i", &status_i))
2955	{
2956		return NULL;
2957	}
2958
2959	return Py_BuildValue("i", WEXITSTATUS(status));
2960}
2961#endif /* WEXITSTATUS */
2962
2963#ifdef WTERMSIG
2964static char posix_WTERMSIG__doc__[] =
2965"WTERMSIG(status) -> integer\n\
2966See Unix documentation.";
2967
2968static PyObject *
2969posix_WTERMSIG(self, args)
2970	PyObject *self;
2971	PyObject *args;
2972{
2973#ifdef UNION_WAIT
2974	union wait status;
2975#define status_i (status.w_status)
2976#else
2977	int status;
2978#define status_i status
2979#endif
2980	status_i = 0;
2981
2982	if (!PyArg_Parse(args, "i", &status_i))
2983	{
2984		return NULL;
2985	}
2986
2987	return Py_BuildValue("i", WTERMSIG(status));
2988}
2989#endif /* WTERMSIG */
2990
2991#ifdef WSTOPSIG
2992static char posix_WSTOPSIG__doc__[] =
2993"WSTOPSIG(status) -> integer\n\
2994See Unix documentation.";
2995
2996static PyObject *
2997posix_WSTOPSIG(self, args)
2998	PyObject *self;
2999	PyObject *args;
3000{
3001#ifdef UNION_WAIT
3002	union wait status;
3003#define status_i (status.w_status)
3004#else
3005	int status;
3006#define status_i status
3007#endif
3008	status_i = 0;
3009
3010	if (!PyArg_Parse(args, "i", &status_i))
3011	{
3012		return NULL;
3013	}
3014
3015	return Py_BuildValue("i", WSTOPSIG(status));
3016}
3017#endif /* WSTOPSIG */
3018
3019#endif /* HAVE_SYS_WAIT_H */
3020
3021
3022#if defined(HAVE_FSTATVFS)
3023#include <sys/statvfs.h>
3024
3025static char posix_fstatvfs__doc__[] =
3026"fstatvfs(fd) -> \
3027(bsize,frsize,blocks,bfree,bavail,files,ffree,favail,fsid,flag, namemax)\n\
3028Perform an fstatvfs system call on the given fd.";
3029
3030static PyObject *
3031posix_fstatvfs(self, args)
3032	PyObject *self;
3033	PyObject *args;
3034{
3035	int fd, res;
3036	struct statvfs st;
3037	if (!PyArg_ParseTuple(args, "i", &fd))
3038		return NULL;
3039	Py_BEGIN_ALLOW_THREADS
3040	res = fstatvfs(fd, &st);
3041	Py_END_ALLOW_THREADS
3042	if (res != 0)
3043		return posix_error();
3044#if !defined(HAVE_LARGEFILE_SUPPORT)
3045	return Py_BuildValue("(lllllllllll)",
3046		    (long) st.f_bsize,
3047		    (long) st.f_frsize,
3048		    (long) st.f_blocks,
3049		    (long) st.f_bfree,
3050		    (long) st.f_bavail,
3051		    (long) st.f_files,
3052		    (long) st.f_ffree,
3053		    (long) st.f_favail,
3054		    (long) st.f_fsid,
3055		    (long) st.f_flag,
3056		    (long) st.f_namemax);
3057#else
3058	return Py_BuildValue("(llLLLLLLlll)",
3059		    (long) st.f_bsize,
3060		    (long) st.f_frsize,
3061		    (LONG_LONG) st.f_blocks,
3062		    (LONG_LONG) st.f_bfree,
3063		    (LONG_LONG) st.f_bavail,
3064		    (LONG_LONG) st.f_files,
3065		    (LONG_LONG) st.f_ffree,
3066		    (LONG_LONG) st.f_favail,
3067		    (long) st.f_fsid,
3068		    (long) st.f_flag,
3069		    (long) st.f_namemax);
3070#endif
3071}
3072#endif /* HAVE_FSTATVFS */
3073
3074
3075#if defined(HAVE_STATVFS)
3076#include <sys/statvfs.h>
3077
3078static char posix_statvfs__doc__[] =
3079"statvfs(path) -> \
3080(bsize,frsize,blocks,bfree,bavail,files,ffree,favail,fsid,flag, namemax)\n\
3081Perform a statvfs system call on the given path.";
3082
3083static PyObject *
3084posix_statvfs(self, args)
3085	PyObject *self;
3086	PyObject *args;
3087{
3088	char *path;
3089	int res;
3090	struct statvfs st;
3091	if (!PyArg_ParseTuple(args, "s", &path))
3092		return NULL;
3093	Py_BEGIN_ALLOW_THREADS
3094	res = statvfs(path, &st);
3095	Py_END_ALLOW_THREADS
3096	if (res != 0)
3097		return posix_error_with_filename(path);
3098#if !defined(HAVE_LARGEFILE_SUPPORT)
3099	return Py_BuildValue("(lllllllllll)",
3100		    (long) st.f_bsize,
3101		    (long) st.f_frsize,
3102		    (long) st.f_blocks,
3103		    (long) st.f_bfree,
3104		    (long) st.f_bavail,
3105		    (long) st.f_files,
3106		    (long) st.f_ffree,
3107		    (long) st.f_favail,
3108		    (long) st.f_fsid,
3109		    (long) st.f_flag,
3110		    (long) st.f_namemax);
3111#else	/* HAVE_LARGEFILE_SUPPORT */
3112	return Py_BuildValue("(llLLLLLLlll)",
3113		    (long) st.f_bsize,
3114		    (long) st.f_frsize,
3115		    (LONG_LONG) st.f_blocks,
3116		    (LONG_LONG) st.f_bfree,
3117		    (LONG_LONG) st.f_bavail,
3118		    (LONG_LONG) st.f_files,
3119		    (LONG_LONG) st.f_ffree,
3120		    (LONG_LONG) st.f_favail,
3121		    (long) st.f_fsid,
3122		    (long) st.f_flag,
3123		    (long) st.f_namemax);
3124#endif
3125}
3126#endif /* HAVE_STATVFS */
3127
3128
3129static PyMethodDef posix_methods[] = {
3130	{"access",	posix_access, 0, posix_access__doc__},
3131#ifdef HAVE_TTYNAME
3132	{"ttyname",	posix_ttyname, 0, posix_ttyname__doc__},
3133#endif
3134	{"chdir",	posix_chdir, 0, posix_chdir__doc__},
3135	{"chmod",	posix_chmod, 0, posix_chmod__doc__},
3136#ifdef HAVE_CHOWN
3137	{"chown",	posix_chown, 0, posix_chown__doc__},
3138#endif /* HAVE_CHOWN */
3139#ifdef HAVE_GETCWD
3140	{"getcwd",	posix_getcwd, 0, posix_getcwd__doc__},
3141#endif
3142#ifdef HAVE_LINK
3143	{"link",	posix_link, 0, posix_link__doc__},
3144#endif /* HAVE_LINK */
3145	{"listdir",	posix_listdir, 0, posix_listdir__doc__},
3146	{"lstat",	posix_lstat, 0, posix_lstat__doc__},
3147	{"mkdir",	posix_mkdir, 1, posix_mkdir__doc__},
3148#ifdef HAVE_NICE
3149	{"nice",	posix_nice, 0, posix_nice__doc__},
3150#endif /* HAVE_NICE */
3151#ifdef HAVE_READLINK
3152	{"readlink",	posix_readlink, 0, posix_readlink__doc__},
3153#endif /* HAVE_READLINK */
3154	{"rename",	posix_rename, 0, posix_rename__doc__},
3155	{"rmdir",	posix_rmdir, 0, posix_rmdir__doc__},
3156	{"stat",	posix_stat, 0, posix_stat__doc__},
3157#ifdef HAVE_SYMLINK
3158	{"symlink",	posix_symlink, 0, posix_symlink__doc__},
3159#endif /* HAVE_SYMLINK */
3160#ifdef HAVE_SYSTEM
3161	{"system",	posix_system, 0, posix_system__doc__},
3162#endif
3163	{"umask",	posix_umask, 0, posix_umask__doc__},
3164#ifdef HAVE_UNAME
3165	{"uname",	posix_uname, 0, posix_uname__doc__},
3166#endif /* HAVE_UNAME */
3167	{"unlink",	posix_unlink, 0, posix_unlink__doc__},
3168	{"remove",	posix_unlink, 0, posix_remove__doc__},
3169	{"utime",	posix_utime, 0, posix_utime__doc__},
3170#ifdef HAVE_TIMES
3171	{"times",	posix_times, 0, posix_times__doc__},
3172#endif /* HAVE_TIMES */
3173	{"_exit",	posix__exit, 0, posix__exit__doc__},
3174#ifdef HAVE_EXECV
3175	{"execv",	posix_execv, 0, posix_execv__doc__},
3176	{"execve",	posix_execve, 0, posix_execve__doc__},
3177#endif /* HAVE_EXECV */
3178#ifdef HAVE_SPAWNV
3179	{"spawnv",	posix_spawnv, 0, posix_spawnv__doc__},
3180	{"spawnve",	posix_spawnve, 0, posix_spawnve__doc__},
3181#endif /* HAVE_SPAWNV */
3182#ifdef HAVE_FORK
3183	{"fork",	posix_fork, 0, posix_fork__doc__},
3184#endif /* HAVE_FORK */
3185#ifdef HAVE_GETEGID
3186	{"getegid",	posix_getegid, 0, posix_getegid__doc__},
3187#endif /* HAVE_GETEGID */
3188#ifdef HAVE_GETEUID
3189	{"geteuid",	posix_geteuid, 0, posix_geteuid__doc__},
3190#endif /* HAVE_GETEUID */
3191#ifdef HAVE_GETGID
3192	{"getgid",	posix_getgid, 0, posix_getgid__doc__},
3193#endif /* HAVE_GETGID */
3194	{"getpid",	posix_getpid, 0, posix_getpid__doc__},
3195#ifdef HAVE_GETPGRP
3196	{"getpgrp",	posix_getpgrp, 0, posix_getpgrp__doc__},
3197#endif /* HAVE_GETPGRP */
3198#ifdef HAVE_GETPPID
3199	{"getppid",	posix_getppid, 0, posix_getppid__doc__},
3200#endif /* HAVE_GETPPID */
3201#ifdef HAVE_GETUID
3202	{"getuid",	posix_getuid, 0, posix_getuid__doc__},
3203#endif /* HAVE_GETUID */
3204#ifdef HAVE_KILL
3205	{"kill",	posix_kill, 0, posix_kill__doc__},
3206#endif /* HAVE_KILL */
3207#ifdef HAVE_PLOCK
3208	{"plock",	posix_plock, 0, posix_plock__doc__},
3209#endif /* HAVE_PLOCK */
3210#ifdef HAVE_POPEN
3211	{"popen",	posix_popen, 1, posix_popen__doc__},
3212#endif /* HAVE_POPEN */
3213#ifdef HAVE_SETUID
3214	{"setuid",	posix_setuid, 0, posix_setuid__doc__},
3215#endif /* HAVE_SETUID */
3216#ifdef HAVE_SETGID
3217	{"setgid",	posix_setgid, 0, posix_setgid__doc__},
3218#endif /* HAVE_SETGID */
3219#ifdef HAVE_SETPGRP
3220	{"setpgrp",	posix_setpgrp, 0, posix_setpgrp__doc__},
3221#endif /* HAVE_SETPGRP */
3222#ifdef HAVE_WAIT
3223	{"wait",	posix_wait, 0, posix_wait__doc__},
3224#endif /* HAVE_WAIT */
3225#ifdef HAVE_WAITPID
3226	{"waitpid",	posix_waitpid, 0, posix_waitpid__doc__},
3227#endif /* HAVE_WAITPID */
3228#ifdef HAVE_SETSID
3229	{"setsid",	posix_setsid, 0, posix_setsid__doc__},
3230#endif /* HAVE_SETSID */
3231#ifdef HAVE_SETPGID
3232	{"setpgid",	posix_setpgid, 0, posix_setpgid__doc__},
3233#endif /* HAVE_SETPGID */
3234#ifdef HAVE_TCGETPGRP
3235	{"tcgetpgrp",	posix_tcgetpgrp, 0, posix_tcgetpgrp__doc__},
3236#endif /* HAVE_TCGETPGRP */
3237#ifdef HAVE_TCSETPGRP
3238	{"tcsetpgrp",	posix_tcsetpgrp, 0, posix_tcsetpgrp__doc__},
3239#endif /* HAVE_TCSETPGRP */
3240	{"open",	posix_open, 1, posix_open__doc__},
3241	{"close",	posix_close, 0, posix_close__doc__},
3242	{"dup",		posix_dup, 0, posix_dup__doc__},
3243	{"dup2",	posix_dup2, 0, posix_dup2__doc__},
3244	{"lseek",	posix_lseek, 0, posix_lseek__doc__},
3245	{"read",	posix_read, 0, posix_read__doc__},
3246	{"write",	posix_write, 0, posix_write__doc__},
3247	{"fstat",	posix_fstat, 0, posix_fstat__doc__},
3248	{"fdopen",	posix_fdopen,	1, posix_fdopen__doc__},
3249#ifdef HAVE_PIPE
3250	{"pipe",	posix_pipe, 0, posix_pipe__doc__},
3251#endif
3252#ifdef HAVE_MKFIFO
3253	{"mkfifo",	posix_mkfifo, 1, posix_mkfifo__doc__},
3254#endif
3255#ifdef HAVE_FTRUNCATE
3256	{"ftruncate",	posix_ftruncate, 1, posix_ftruncate__doc__},
3257#endif
3258#ifdef HAVE_PUTENV
3259	{"putenv",	posix_putenv, 1, posix_putenv__doc__},
3260#endif
3261#ifdef HAVE_STRERROR
3262	{"strerror",	posix_strerror, 1, posix_strerror__doc__},
3263#endif
3264#ifdef HAVE_FSYNC
3265	{"fsync",       posix_fsync, 0, posix_fsync__doc__},
3266#endif
3267#ifdef HAVE_FDATASYNC
3268	{"fdatasync",   posix_fdatasync,  0, posix_fdatasync__doc__},
3269#endif
3270#ifdef HAVE_SYS_WAIT_H
3271#ifdef WIFSTOPPED
3272        {"WIFSTOPPED",	posix_WIFSTOPPED, 0, posix_WIFSTOPPED__doc__},
3273#endif /* WIFSTOPPED */
3274#ifdef WIFSIGNALED
3275        {"WIFSIGNALED",	posix_WIFSIGNALED, 0, posix_WIFSIGNALED__doc__},
3276#endif /* WIFSIGNALED */
3277#ifdef WIFEXITED
3278        {"WIFEXITED",	posix_WIFEXITED, 0, posix_WIFEXITED__doc__},
3279#endif /* WIFEXITED */
3280#ifdef WEXITSTATUS
3281        {"WEXITSTATUS",	posix_WEXITSTATUS, 0, posix_WEXITSTATUS__doc__},
3282#endif /* WEXITSTATUS */
3283#ifdef WTERMSIG
3284        {"WTERMSIG",	posix_WTERMSIG, 0, posix_WTERMSIG__doc__},
3285#endif /* WTERMSIG */
3286#ifdef WSTOPSIG
3287        {"WSTOPSIG",	posix_WSTOPSIG, 0, posix_WSTOPSIG__doc__},
3288#endif /* WSTOPSIG */
3289#endif /* HAVE_SYS_WAIT_H */
3290#ifdef HAVE_FSTATVFS
3291	{"fstatvfs",	posix_fstatvfs, 1, posix_fstatvfs__doc__},
3292#endif
3293#ifdef HAVE_STATVFS
3294	{"statvfs",	posix_statvfs, 1, posix_statvfs__doc__},
3295#endif
3296	{NULL,		NULL}		 /* Sentinel */
3297};
3298
3299
3300static int
3301ins(d, symbol, value)
3302        PyObject* d;
3303        char* symbol;
3304        long value;
3305{
3306        PyObject* v = PyInt_FromLong(value);
3307        if (!v || PyDict_SetItemString(d, symbol, v) < 0)
3308                return -1;                   /* triggers fatal error */
3309
3310        Py_DECREF(v);
3311        return 0;
3312}
3313
3314#if defined(PYOS_OS2)
3315/* Insert Platform-Specific Constant Values (Strings & Numbers) of Common Use */
3316static int insertvalues(PyObject *d)
3317{
3318    APIRET    rc;
3319    ULONG     values[QSV_MAX+1];
3320    PyObject *v;
3321    char     *ver, tmp[10];
3322
3323    Py_BEGIN_ALLOW_THREADS
3324    rc = DosQuerySysInfo(1, QSV_MAX, &values[1], sizeof(values));
3325    Py_END_ALLOW_THREADS
3326
3327    if (rc != NO_ERROR) {
3328        os2_error(rc);
3329        return -1;
3330    }
3331
3332    if (ins(d, "meminstalled", values[QSV_TOTPHYSMEM])) return -1;
3333    if (ins(d, "memkernel",    values[QSV_TOTRESMEM])) return -1;
3334    if (ins(d, "memvirtual",   values[QSV_TOTAVAILMEM])) return -1;
3335    if (ins(d, "maxpathlen",   values[QSV_MAX_PATH_LENGTH])) return -1;
3336    if (ins(d, "maxnamelen",   values[QSV_MAX_COMP_LENGTH])) return -1;
3337    if (ins(d, "revision",     values[QSV_VERSION_REVISION])) return -1;
3338    if (ins(d, "timeslice",    values[QSV_MIN_SLICE])) return -1;
3339
3340    switch (values[QSV_VERSION_MINOR]) {
3341    case 0:  ver = "2.00"; break;
3342    case 10: ver = "2.10"; break;
3343    case 11: ver = "2.11"; break;
3344    case 30: ver = "3.00"; break;
3345    case 40: ver = "4.00"; break;
3346    case 50: ver = "5.00"; break;
3347    default:
3348        sprintf(tmp, "%d-%d", values[QSV_VERSION_MAJOR],
3349                              values[QSV_VERSION_MINOR]);
3350        ver = &tmp[0];
3351    }
3352
3353    /* Add Indicator of the Version of the Operating System */
3354    v = PyString_FromString(ver);
3355    if (!v || PyDict_SetItemString(d, "version", v) < 0)
3356        return -1;
3357    Py_DECREF(v);
3358
3359    /* Add Indicator of Which Drive was Used to Boot the System */
3360    tmp[0] = 'A' + values[QSV_BOOT_DRIVE] - 1;
3361    tmp[1] = ':';
3362    tmp[2] = '\0';
3363
3364    v = PyString_FromString(tmp);
3365    if (!v || PyDict_SetItemString(d, "bootdrive", v) < 0)
3366        return -1;
3367    Py_DECREF(v);
3368
3369    return 0;
3370}
3371#endif
3372
3373static int
3374all_ins(d)
3375        PyObject* d;
3376{
3377#ifdef F_OK
3378        if (ins(d, "F_OK", (long)F_OK)) return -1;
3379#endif
3380#ifdef R_OK
3381        if (ins(d, "R_OK", (long)R_OK)) return -1;
3382#endif
3383#ifdef W_OK
3384        if (ins(d, "W_OK", (long)W_OK)) return -1;
3385#endif
3386#ifdef X_OK
3387        if (ins(d, "X_OK", (long)X_OK)) return -1;
3388#endif
3389#ifdef WNOHANG
3390        if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
3391#endif
3392#ifdef O_RDONLY
3393        if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
3394#endif
3395#ifdef O_WRONLY
3396        if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
3397#endif
3398#ifdef O_RDWR
3399        if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
3400#endif
3401#ifdef O_NDELAY
3402        if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
3403#endif
3404#ifdef O_NONBLOCK
3405        if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
3406#endif
3407#ifdef O_APPEND
3408        if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
3409#endif
3410#ifdef O_DSYNC
3411        if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
3412#endif
3413#ifdef O_RSYNC
3414        if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
3415#endif
3416#ifdef O_SYNC
3417        if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
3418#endif
3419#ifdef O_NOCTTY
3420        if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
3421#endif
3422#ifdef O_CREAT
3423        if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
3424#endif
3425#ifdef O_EXCL
3426        if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
3427#endif
3428#ifdef O_TRUNC
3429        if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
3430#endif
3431#ifdef O_BINARY
3432        if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
3433#endif
3434#ifdef O_TEXT
3435        if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
3436#endif
3437
3438#ifdef HAVE_SPAWNV
3439        if (ins(d, "_P_WAIT", (long)_P_WAIT)) return -1;
3440        if (ins(d, "_P_NOWAIT", (long)_P_NOWAIT)) return -1;
3441        if (ins(d, "_P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
3442        if (ins(d, "_P_NOWAITO", (long)_P_NOWAITO)) return -1;
3443        if (ins(d, "_P_DETACH", (long)_P_DETACH)) return -1;
3444#endif
3445
3446#if defined(PYOS_OS2)
3447        if (insertvalues(d)) return -1;
3448#endif
3449        return 0;
3450}
3451
3452
3453#if ( defined(_MSC_VER) || defined(__WATCOMC__) ) && !defined(__QNX__)
3454#define INITFUNC initnt
3455#define MODNAME "nt"
3456#else
3457#if defined(PYOS_OS2)
3458#define INITFUNC initos2
3459#define MODNAME "os2"
3460#else
3461#define INITFUNC initposix
3462#define MODNAME "posix"
3463#endif
3464#endif
3465
3466DL_EXPORT(void)
3467INITFUNC()
3468{
3469	PyObject *m, *d, *v;
3470
3471	m = Py_InitModule4(MODNAME,
3472			   posix_methods,
3473			   posix__doc__,
3474			   (PyObject *)NULL,
3475			   PYTHON_API_VERSION);
3476	d = PyModule_GetDict(m);
3477
3478	/* Initialize environ dictionary */
3479	v = convertenviron();
3480	if (v == NULL || PyDict_SetItemString(d, "environ", v) != 0)
3481		return;
3482	Py_DECREF(v);
3483
3484        if (all_ins(d))
3485                return;
3486
3487	Py_INCREF(PyExc_OSError);
3488	PosixError = PyExc_OSError;
3489	PyDict_SetItemString(d, "error", PosixError);
3490}
3491