source: python/trunk/Modules/posixmodule.c@ 385

Last change on this file since 385 was 10, checked in by Yuri Dario, 15 years ago

python: merged offline changes.

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