source: vendor/python/2.5/Modules/posixmodule.c

Last change on this file was 3225, checked in by bird, 18 years ago

Python 2.5

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