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