source: trunk/essentials/dev-lang/python/Modules/posixmodule.c@ 3951

Last change on this file since 3951 was 3451, checked in by bird, 19 years ago

LIBPATHSTRICT, use opendir and not DosFindFirst, and removed a three warnings.

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