• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     for (i = fd_from; i < fd_to; i++)
6680         if (_PyVerify_fd(i))
6681             close(i);
6682     Py_END_ALLOW_THREADS
6683     Py_RETURN_NONE;
6684 }
6685 
6686 
6687 PyDoc_STRVAR(posix_dup__doc__,
6688 "dup(fd) -> fd2\n\n\
6689 Return a duplicate of a file descriptor.");
6690 
6691 static PyObject *
posix_dup(PyObject * self,PyObject * args)6692 posix_dup(PyObject *self, PyObject *args)
6693 {
6694     int fd;
6695     if (!PyArg_ParseTuple(args, "i:dup", &fd))
6696         return NULL;
6697     if (!_PyVerify_fd(fd))
6698         return posix_error();
6699     Py_BEGIN_ALLOW_THREADS
6700     fd = dup(fd);
6701     Py_END_ALLOW_THREADS
6702     if (fd < 0)
6703         return posix_error();
6704     return PyInt_FromLong((long)fd);
6705 }
6706 
6707 
6708 PyDoc_STRVAR(posix_dup2__doc__,
6709 "dup2(old_fd, new_fd)\n\n\
6710 Duplicate file descriptor.");
6711 
6712 static PyObject *
posix_dup2(PyObject * self,PyObject * args)6713 posix_dup2(PyObject *self, PyObject *args)
6714 {
6715     int fd, fd2, res;
6716     if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
6717         return NULL;
6718     if (!_PyVerify_fd_dup2(fd, fd2))
6719         return posix_error();
6720     Py_BEGIN_ALLOW_THREADS
6721     res = dup2(fd, fd2);
6722     Py_END_ALLOW_THREADS
6723     if (res < 0)
6724         return posix_error();
6725     Py_INCREF(Py_None);
6726     return Py_None;
6727 }
6728 
6729 
6730 PyDoc_STRVAR(posix_lseek__doc__,
6731 "lseek(fd, pos, how) -> newpos\n\n\
6732 Set the current position of a file descriptor.\n\
6733 Return the new cursor position in bytes, starting from the beginning.");
6734 
6735 static PyObject *
posix_lseek(PyObject * self,PyObject * args)6736 posix_lseek(PyObject *self, PyObject *args)
6737 {
6738     int fd, how;
6739 #if defined(MS_WIN64) || defined(MS_WINDOWS)
6740     PY_LONG_LONG pos, res;
6741 #else
6742     off_t pos, res;
6743 #endif
6744     PyObject *posobj;
6745     if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
6746         return NULL;
6747 #ifdef SEEK_SET
6748     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
6749     switch (how) {
6750     case 0: how = SEEK_SET; break;
6751     case 1: how = SEEK_CUR; break;
6752     case 2: how = SEEK_END; break;
6753     }
6754 #endif /* SEEK_END */
6755 
6756 #if !defined(HAVE_LARGEFILE_SUPPORT)
6757     pos = PyInt_AsLong(posobj);
6758 #else
6759     pos = PyLong_Check(posobj) ?
6760         PyLong_AsLongLong(posobj) : PyInt_AsLong(posobj);
6761 #endif
6762     if (PyErr_Occurred())
6763         return NULL;
6764 
6765     if (!_PyVerify_fd(fd))
6766         return posix_error();
6767     Py_BEGIN_ALLOW_THREADS
6768 #if defined(MS_WIN64) || defined(MS_WINDOWS)
6769     res = _lseeki64(fd, pos, how);
6770 #else
6771     res = lseek(fd, pos, how);
6772 #endif
6773     Py_END_ALLOW_THREADS
6774     if (res < 0)
6775         return posix_error();
6776 
6777 #if !defined(HAVE_LARGEFILE_SUPPORT)
6778     return PyInt_FromLong(res);
6779 #else
6780     return PyLong_FromLongLong(res);
6781 #endif
6782 }
6783 
6784 
6785 PyDoc_STRVAR(posix_read__doc__,
6786 "read(fd, buffersize) -> string\n\n\
6787 Read a file descriptor.");
6788 
6789 static PyObject *
posix_read(PyObject * self,PyObject * args)6790 posix_read(PyObject *self, PyObject *args)
6791 {
6792     int fd, size, n;
6793     PyObject *buffer;
6794     if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
6795         return NULL;
6796     if (size < 0) {
6797         errno = EINVAL;
6798         return posix_error();
6799     }
6800     buffer = PyString_FromStringAndSize((char *)NULL, size);
6801     if (buffer == NULL)
6802         return NULL;
6803     if (!_PyVerify_fd(fd)) {
6804         Py_DECREF(buffer);
6805         return posix_error();
6806     }
6807     Py_BEGIN_ALLOW_THREADS
6808     n = read(fd, PyString_AsString(buffer), size);
6809     Py_END_ALLOW_THREADS
6810     if (n < 0) {
6811         Py_DECREF(buffer);
6812         return posix_error();
6813     }
6814     if (n != size)
6815         _PyString_Resize(&buffer, n);
6816     return buffer;
6817 }
6818 
6819 
6820 PyDoc_STRVAR(posix_write__doc__,
6821 "write(fd, string) -> byteswritten\n\n\
6822 Write a string to a file descriptor.");
6823 
6824 static PyObject *
posix_write(PyObject * self,PyObject * args)6825 posix_write(PyObject *self, PyObject *args)
6826 {
6827     Py_buffer pbuf;
6828     int fd;
6829     Py_ssize_t size, len;
6830 
6831     if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf))
6832         return NULL;
6833     if (!_PyVerify_fd(fd)) {
6834         PyBuffer_Release(&pbuf);
6835         return posix_error();
6836     }
6837     len = pbuf.len;
6838     Py_BEGIN_ALLOW_THREADS
6839 #if defined(MS_WIN64) || defined(MS_WINDOWS)
6840     if (len > INT_MAX)
6841         len = INT_MAX;
6842     size = write(fd, pbuf.buf, (int)len);
6843 #else
6844     size = write(fd, pbuf.buf, len);
6845 #endif
6846     Py_END_ALLOW_THREADS
6847     PyBuffer_Release(&pbuf);
6848     if (size < 0)
6849         return posix_error();
6850     return PyInt_FromSsize_t(size);
6851 }
6852 
6853 
6854 PyDoc_STRVAR(posix_fstat__doc__,
6855 "fstat(fd) -> stat result\n\n\
6856 Like stat(), but for an open file descriptor.");
6857 
6858 static PyObject *
posix_fstat(PyObject * self,PyObject * args)6859 posix_fstat(PyObject *self, PyObject *args)
6860 {
6861     int fd;
6862     STRUCT_STAT st;
6863     int res;
6864     if (!PyArg_ParseTuple(args, "i:fstat", &fd))
6865         return NULL;
6866 #ifdef __VMS
6867     /* on OpenVMS we must ensure that all bytes are written to the file */
6868     fsync(fd);
6869 #endif
6870     if (!_PyVerify_fd(fd))
6871         return posix_error();
6872     Py_BEGIN_ALLOW_THREADS
6873     res = FSTAT(fd, &st);
6874     Py_END_ALLOW_THREADS
6875     if (res != 0) {
6876 #ifdef MS_WINDOWS
6877         return win32_error("fstat", NULL);
6878 #else
6879         return posix_error();
6880 #endif
6881     }
6882 
6883     return _pystat_fromstructstat(&st);
6884 }
6885 
6886 
6887 PyDoc_STRVAR(posix_fdopen__doc__,
6888 "fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\
6889 Return an open file object connected to a file descriptor.");
6890 
6891 static PyObject *
posix_fdopen(PyObject * self,PyObject * args)6892 posix_fdopen(PyObject *self, PyObject *args)
6893 {
6894     int fd;
6895     char *orgmode = "r";
6896     int bufsize = -1;
6897     FILE *fp;
6898     PyObject *f;
6899     char *mode;
6900     if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize))
6901         return NULL;
6902 
6903     /* Sanitize mode.  See fileobject.c */
6904     mode = PyMem_MALLOC(strlen(orgmode)+3);
6905     if (!mode) {
6906         PyErr_NoMemory();
6907         return NULL;
6908     }
6909     strcpy(mode, orgmode);
6910     if (_PyFile_SanitizeMode(mode)) {
6911         PyMem_FREE(mode);
6912         return NULL;
6913     }
6914     if (!_PyVerify_fd(fd)) {
6915         PyMem_FREE(mode);
6916         return posix_error();
6917     }
6918 #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
6919     {
6920         struct stat buf;
6921         const char *msg;
6922         PyObject *exc;
6923         if (fstat(fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
6924             PyMem_FREE(mode);
6925             msg = strerror(EISDIR);
6926             exc = PyObject_CallFunction(PyExc_IOError, "(iss)",
6927                                         EISDIR, msg, "<fdopen>");
6928             if (exc) {
6929                 PyErr_SetObject(PyExc_IOError, exc);
6930                 Py_DECREF(exc);
6931             }
6932             return NULL;
6933         }
6934     }
6935 #endif
6936     /* The dummy filename used here must be kept in sync with the value
6937        tested against in gzip.GzipFile.__init__() - see issue #13781. */
6938     f = PyFile_FromFile(NULL, "<fdopen>", orgmode, fclose);
6939     if (f == NULL) {
6940         PyMem_FREE(mode);
6941         return NULL;
6942     }
6943     Py_BEGIN_ALLOW_THREADS
6944 #if !defined(MS_WINDOWS) && defined(HAVE_FCNTL_H)
6945     if (mode[0] == 'a') {
6946         /* try to make sure the O_APPEND flag is set */
6947         int flags;
6948         flags = fcntl(fd, F_GETFL);
6949         if (flags != -1)
6950             fcntl(fd, F_SETFL, flags | O_APPEND);
6951         fp = fdopen(fd, mode);
6952         if (fp == NULL && flags != -1)
6953             /* restore old mode if fdopen failed */
6954             fcntl(fd, F_SETFL, flags);
6955     } else {
6956         fp = fdopen(fd, mode);
6957     }
6958 #else
6959     fp = fdopen(fd, mode);
6960 #endif
6961     Py_END_ALLOW_THREADS
6962     PyMem_FREE(mode);
6963     if (fp == NULL) {
6964         Py_DECREF(f);
6965         return posix_error();
6966     }
6967     /* We now know we will succeed, so initialize the file object. */
6968     ((PyFileObject *)f)->f_fp = fp;
6969     PyFile_SetBufSize(f, bufsize);
6970     return f;
6971 }
6972 
6973 PyDoc_STRVAR(posix_isatty__doc__,
6974 "isatty(fd) -> bool\n\n\
6975 Return True if the file descriptor 'fd' is an open file descriptor\n\
6976 connected to the slave end of a terminal.");
6977 
6978 static PyObject *
posix_isatty(PyObject * self,PyObject * args)6979 posix_isatty(PyObject *self, PyObject *args)
6980 {
6981     int fd;
6982     if (!PyArg_ParseTuple(args, "i:isatty", &fd))
6983         return NULL;
6984     if (!_PyVerify_fd(fd))
6985         return PyBool_FromLong(0);
6986     return PyBool_FromLong(isatty(fd));
6987 }
6988 
6989 #ifdef HAVE_PIPE
6990 PyDoc_STRVAR(posix_pipe__doc__,
6991 "pipe() -> (read_end, write_end)\n\n\
6992 Create a pipe.");
6993 
6994 static PyObject *
posix_pipe(PyObject * self,PyObject * noargs)6995 posix_pipe(PyObject *self, PyObject *noargs)
6996 {
6997 #if defined(PYOS_OS2)
6998     HFILE read, write;
6999     APIRET rc;
7000 
7001     Py_BEGIN_ALLOW_THREADS
7002     rc = DosCreatePipe( &read, &write, 4096);
7003     Py_END_ALLOW_THREADS
7004     if (rc != NO_ERROR)
7005         return os2_error(rc);
7006 
7007     return Py_BuildValue("(ii)", read, write);
7008 #else
7009 #if !defined(MS_WINDOWS)
7010     int fds[2];
7011     int res;
7012     Py_BEGIN_ALLOW_THREADS
7013     res = pipe(fds);
7014     Py_END_ALLOW_THREADS
7015     if (res != 0)
7016         return posix_error();
7017     return Py_BuildValue("(ii)", fds[0], fds[1]);
7018 #else /* MS_WINDOWS */
7019     HANDLE read, write;
7020     int read_fd, write_fd;
7021     BOOL ok;
7022     Py_BEGIN_ALLOW_THREADS
7023     ok = CreatePipe(&read, &write, NULL, 0);
7024     Py_END_ALLOW_THREADS
7025     if (!ok)
7026         return win32_error("CreatePipe", NULL);
7027     read_fd = _open_osfhandle((Py_intptr_t)read, 0);
7028     write_fd = _open_osfhandle((Py_intptr_t)write, 1);
7029     return Py_BuildValue("(ii)", read_fd, write_fd);
7030 #endif /* MS_WINDOWS */
7031 #endif
7032 }
7033 #endif  /* HAVE_PIPE */
7034 
7035 
7036 #ifdef HAVE_MKFIFO
7037 PyDoc_STRVAR(posix_mkfifo__doc__,
7038 "mkfifo(filename [, mode=0666])\n\n\
7039 Create a FIFO (a POSIX named pipe).");
7040 
7041 static PyObject *
posix_mkfifo(PyObject * self,PyObject * args)7042 posix_mkfifo(PyObject *self, PyObject *args)
7043 {
7044     char *filename;
7045     int mode = 0666;
7046     int res;
7047     if (!PyArg_ParseTuple(args, "s|i:mkfifo", &filename, &mode))
7048         return NULL;
7049     Py_BEGIN_ALLOW_THREADS
7050     res = mkfifo(filename, mode);
7051     Py_END_ALLOW_THREADS
7052     if (res < 0)
7053         return posix_error();
7054     Py_INCREF(Py_None);
7055     return Py_None;
7056 }
7057 #endif
7058 
7059 
7060 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
7061 PyDoc_STRVAR(posix_mknod__doc__,
7062 "mknod(filename [, mode=0600, device])\n\n\
7063 Create a filesystem node (file, device special file or named pipe)\n\
7064 named filename. mode specifies both the permissions to use and the\n\
7065 type of node to be created, being combined (bitwise OR) with one of\n\
7066 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
7067 device defines the newly created device special file (probably using\n\
7068 os.makedev()), otherwise it is ignored.");
7069 
7070 
7071 static PyObject *
posix_mknod(PyObject * self,PyObject * args)7072 posix_mknod(PyObject *self, PyObject *args)
7073 {
7074     char *filename;
7075     int mode = 0600;
7076     dev_t device = 0;
7077     int res;
7078     if (!PyArg_ParseTuple(args, "s|iO&:mknod",
7079         &filename, &mode,
7080         _Py_Dev_Converter, &device))
7081         return NULL;
7082     Py_BEGIN_ALLOW_THREADS
7083     res = mknod(filename, mode, device);
7084     Py_END_ALLOW_THREADS
7085     if (res < 0)
7086         return posix_error();
7087     Py_INCREF(Py_None);
7088     return Py_None;
7089 }
7090 #endif
7091 
7092 #ifdef HAVE_DEVICE_MACROS
7093 PyDoc_STRVAR(posix_major__doc__,
7094 "major(device) -> major number\n\
7095 Extracts a device major number from a raw device number.");
7096 
7097 static PyObject *
posix_major(PyObject * self,PyObject * args)7098 posix_major(PyObject *self, PyObject *args)
7099 {
7100     dev_t device;
7101     if (!PyArg_ParseTuple(args, "O&:major", _Py_Dev_Converter, &device))
7102         return NULL;
7103     return PyInt_FromLong((long)major(device));
7104 }
7105 
7106 PyDoc_STRVAR(posix_minor__doc__,
7107 "minor(device) -> minor number\n\
7108 Extracts a device minor number from a raw device number.");
7109 
7110 static PyObject *
posix_minor(PyObject * self,PyObject * args)7111 posix_minor(PyObject *self, PyObject *args)
7112 {
7113     dev_t device;
7114     if (!PyArg_ParseTuple(args, "O&:minor", _Py_Dev_Converter, &device))
7115         return NULL;
7116     return PyInt_FromLong((long)minor(device));
7117 }
7118 
7119 PyDoc_STRVAR(posix_makedev__doc__,
7120 "makedev(major, minor) -> device number\n\
7121 Composes a raw device number from the major and minor device numbers.");
7122 
7123 static PyObject *
posix_makedev(PyObject * self,PyObject * args)7124 posix_makedev(PyObject *self, PyObject *args)
7125 {
7126     int major, minor;
7127     if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
7128         return NULL;
7129     return _PyInt_FromDev(makedev(major, minor));
7130 }
7131 #endif /* device macros */
7132 
7133 
7134 #ifdef HAVE_FTRUNCATE
7135 PyDoc_STRVAR(posix_ftruncate__doc__,
7136 "ftruncate(fd, length)\n\n\
7137 Truncate a file to a specified length.");
7138 
7139 static PyObject *
posix_ftruncate(PyObject * self,PyObject * args)7140 posix_ftruncate(PyObject *self, PyObject *args)
7141 {
7142     int fd;
7143     off_t length;
7144     int res;
7145     PyObject *lenobj;
7146 
7147     if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj))
7148         return NULL;
7149 
7150 #if !defined(HAVE_LARGEFILE_SUPPORT)
7151     length = PyInt_AsLong(lenobj);
7152 #else
7153     length = PyLong_Check(lenobj) ?
7154         PyLong_AsLongLong(lenobj) : PyInt_AsLong(lenobj);
7155 #endif
7156     if (PyErr_Occurred())
7157         return NULL;
7158 
7159     Py_BEGIN_ALLOW_THREADS
7160     res = ftruncate(fd, length);
7161     Py_END_ALLOW_THREADS
7162     if (res < 0)
7163         return posix_error();
7164     Py_INCREF(Py_None);
7165     return Py_None;
7166 }
7167 #endif
7168 
7169 #ifdef HAVE_PUTENV
7170 PyDoc_STRVAR(posix_putenv__doc__,
7171 "putenv(key, value)\n\n\
7172 Change or add an environment variable.");
7173 
7174 /* Save putenv() parameters as values here, so we can collect them when they
7175  * get re-set with another call for the same key. */
7176 static PyObject *posix_putenv_garbage;
7177 
7178 static PyObject *
posix_putenv(PyObject * self,PyObject * args)7179 posix_putenv(PyObject *self, PyObject *args)
7180 {
7181     char *s1, *s2;
7182     char *newenv;
7183     PyObject *newstr;
7184     size_t len;
7185 
7186     if (!PyArg_ParseTuple(args, "ss:putenv", &s1, &s2))
7187         return NULL;
7188 
7189 #if defined(PYOS_OS2)
7190     if (stricmp(s1, "BEGINLIBPATH") == 0) {
7191         APIRET rc;
7192 
7193         rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH);
7194         if (rc != NO_ERROR)
7195             return os2_error(rc);
7196 
7197     } else if (stricmp(s1, "ENDLIBPATH") == 0) {
7198         APIRET rc;
7199 
7200         rc = DosSetExtLIBPATH(s2, END_LIBPATH);
7201         if (rc != NO_ERROR)
7202             return os2_error(rc);
7203     } else {
7204 #endif
7205 
7206     /* Search from index 1 because on Windows starting '=' is allowed for
7207        defining hidden environment variables. */
7208     if (*s1 == '\0' || strchr(s1 + 1, '=') != NULL) {
7209         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7210         return NULL;
7211     }
7212 
7213     /* XXX This can leak memory -- not easy to fix :-( */
7214     len = strlen(s1) + strlen(s2) + 2;
7215 #ifdef MS_WINDOWS
7216     if (_MAX_ENV < (len - 1)) {
7217         PyErr_Format(PyExc_ValueError,
7218                      "the environment variable is longer than %u bytes",
7219                      _MAX_ENV);
7220         return NULL;
7221     }
7222 #endif
7223     /* len includes space for a trailing \0; the size arg to
7224        PyString_FromStringAndSize does not count that */
7225     newstr = PyString_FromStringAndSize(NULL, (int)len - 1);
7226     if (newstr == NULL)
7227         return PyErr_NoMemory();
7228     newenv = PyString_AS_STRING(newstr);
7229     PyOS_snprintf(newenv, len, "%s=%s", s1, s2);
7230     if (putenv(newenv)) {
7231         Py_DECREF(newstr);
7232         posix_error();
7233         return NULL;
7234     }
7235     /* Install the first arg and newstr in posix_putenv_garbage;
7236      * this will cause previous value to be collected.  This has to
7237      * happen after the real putenv() call because the old value
7238      * was still accessible until then. */
7239     if (PyDict_SetItem(posix_putenv_garbage,
7240                        PyTuple_GET_ITEM(args, 0), newstr)) {
7241         /* really not much we can do; just leak */
7242         PyErr_Clear();
7243     }
7244     else {
7245         Py_DECREF(newstr);
7246     }
7247 
7248 #if defined(PYOS_OS2)
7249     }
7250 #endif
7251     Py_INCREF(Py_None);
7252     return Py_None;
7253 }
7254 #endif /* putenv */
7255 
7256 #ifdef HAVE_UNSETENV
7257 PyDoc_STRVAR(posix_unsetenv__doc__,
7258 "unsetenv(key)\n\n\
7259 Delete an environment variable.");
7260 
7261 static PyObject *
posix_unsetenv(PyObject * self,PyObject * args)7262 posix_unsetenv(PyObject *self, PyObject *args)
7263 {
7264     char *s1;
7265 #ifndef HAVE_BROKEN_UNSETENV
7266     int err;
7267 #endif
7268 
7269     if (!PyArg_ParseTuple(args, "s:unsetenv", &s1))
7270         return NULL;
7271 
7272 #ifdef HAVE_BROKEN_UNSETENV
7273     unsetenv(s1);
7274 #else
7275     err = unsetenv(s1);
7276     if (err)
7277         return posix_error();
7278 #endif
7279 
7280     /* Remove the key from posix_putenv_garbage;
7281      * this will cause it to be collected.  This has to
7282      * happen after the real unsetenv() call because the
7283      * old value was still accessible until then.
7284      */
7285     if (PyDict_DelItem(posix_putenv_garbage,
7286                        PyTuple_GET_ITEM(args, 0))) {
7287         /* really not much we can do; just leak */
7288         PyErr_Clear();
7289     }
7290 
7291     Py_INCREF(Py_None);
7292     return Py_None;
7293 }
7294 #endif /* unsetenv */
7295 
7296 PyDoc_STRVAR(posix_strerror__doc__,
7297 "strerror(code) -> string\n\n\
7298 Translate an error code to a message string.");
7299 
7300 static PyObject *
posix_strerror(PyObject * self,PyObject * args)7301 posix_strerror(PyObject *self, PyObject *args)
7302 {
7303     int code;
7304     char *message;
7305     if (!PyArg_ParseTuple(args, "i:strerror", &code))
7306         return NULL;
7307     message = strerror(code);
7308     if (message == NULL) {
7309         PyErr_SetString(PyExc_ValueError,
7310                         "strerror() argument out of range");
7311         return NULL;
7312     }
7313     return PyString_FromString(message);
7314 }
7315 
7316 
7317 #ifdef HAVE_SYS_WAIT_H
7318 
7319 #ifdef WCOREDUMP
7320 PyDoc_STRVAR(posix_WCOREDUMP__doc__,
7321 "WCOREDUMP(status) -> bool\n\n\
7322 Return True if the process returning 'status' was dumped to a core file.");
7323 
7324 static PyObject *
posix_WCOREDUMP(PyObject * self,PyObject * args)7325 posix_WCOREDUMP(PyObject *self, PyObject *args)
7326 {
7327     WAIT_TYPE status;
7328     WAIT_STATUS_INT(status) = 0;
7329 
7330     if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
7331         return NULL;
7332 
7333     return PyBool_FromLong(WCOREDUMP(status));
7334 }
7335 #endif /* WCOREDUMP */
7336 
7337 #ifdef WIFCONTINUED
7338 PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
7339 "WIFCONTINUED(status) -> bool\n\n\
7340 Return True if the process returning 'status' was continued from a\n\
7341 job control stop.");
7342 
7343 static PyObject *
posix_WIFCONTINUED(PyObject * self,PyObject * args)7344 posix_WIFCONTINUED(PyObject *self, PyObject *args)
7345 {
7346     WAIT_TYPE status;
7347     WAIT_STATUS_INT(status) = 0;
7348 
7349     if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
7350         return NULL;
7351 
7352     return PyBool_FromLong(WIFCONTINUED(status));
7353 }
7354 #endif /* WIFCONTINUED */
7355 
7356 #ifdef WIFSTOPPED
7357 PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
7358 "WIFSTOPPED(status) -> bool\n\n\
7359 Return True if the process returning 'status' was stopped.");
7360 
7361 static PyObject *
posix_WIFSTOPPED(PyObject * self,PyObject * args)7362 posix_WIFSTOPPED(PyObject *self, PyObject *args)
7363 {
7364     WAIT_TYPE status;
7365     WAIT_STATUS_INT(status) = 0;
7366 
7367     if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
7368         return NULL;
7369 
7370     return PyBool_FromLong(WIFSTOPPED(status));
7371 }
7372 #endif /* WIFSTOPPED */
7373 
7374 #ifdef WIFSIGNALED
7375 PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
7376 "WIFSIGNALED(status) -> bool\n\n\
7377 Return True if the process returning 'status' was terminated by a signal.");
7378 
7379 static PyObject *
posix_WIFSIGNALED(PyObject * self,PyObject * args)7380 posix_WIFSIGNALED(PyObject *self, PyObject *args)
7381 {
7382     WAIT_TYPE status;
7383     WAIT_STATUS_INT(status) = 0;
7384 
7385     if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
7386         return NULL;
7387 
7388     return PyBool_FromLong(WIFSIGNALED(status));
7389 }
7390 #endif /* WIFSIGNALED */
7391 
7392 #ifdef WIFEXITED
7393 PyDoc_STRVAR(posix_WIFEXITED__doc__,
7394 "WIFEXITED(status) -> bool\n\n\
7395 Return true if the process returning 'status' exited using the exit()\n\
7396 system call.");
7397 
7398 static PyObject *
posix_WIFEXITED(PyObject * self,PyObject * args)7399 posix_WIFEXITED(PyObject *self, PyObject *args)
7400 {
7401     WAIT_TYPE status;
7402     WAIT_STATUS_INT(status) = 0;
7403 
7404     if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
7405         return NULL;
7406 
7407     return PyBool_FromLong(WIFEXITED(status));
7408 }
7409 #endif /* WIFEXITED */
7410 
7411 #ifdef WEXITSTATUS
7412 PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
7413 "WEXITSTATUS(status) -> integer\n\n\
7414 Return the process return code from 'status'.");
7415 
7416 static PyObject *
posix_WEXITSTATUS(PyObject * self,PyObject * args)7417 posix_WEXITSTATUS(PyObject *self, PyObject *args)
7418 {
7419     WAIT_TYPE status;
7420     WAIT_STATUS_INT(status) = 0;
7421 
7422     if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
7423         return NULL;
7424 
7425     return Py_BuildValue("i", WEXITSTATUS(status));
7426 }
7427 #endif /* WEXITSTATUS */
7428 
7429 #ifdef WTERMSIG
7430 PyDoc_STRVAR(posix_WTERMSIG__doc__,
7431 "WTERMSIG(status) -> integer\n\n\
7432 Return the signal that terminated the process that provided the 'status'\n\
7433 value.");
7434 
7435 static PyObject *
posix_WTERMSIG(PyObject * self,PyObject * args)7436 posix_WTERMSIG(PyObject *self, PyObject *args)
7437 {
7438     WAIT_TYPE status;
7439     WAIT_STATUS_INT(status) = 0;
7440 
7441     if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
7442         return NULL;
7443 
7444     return Py_BuildValue("i", WTERMSIG(status));
7445 }
7446 #endif /* WTERMSIG */
7447 
7448 #ifdef WSTOPSIG
7449 PyDoc_STRVAR(posix_WSTOPSIG__doc__,
7450 "WSTOPSIG(status) -> integer\n\n\
7451 Return the signal that stopped the process that provided\n\
7452 the 'status' value.");
7453 
7454 static PyObject *
posix_WSTOPSIG(PyObject * self,PyObject * args)7455 posix_WSTOPSIG(PyObject *self, PyObject *args)
7456 {
7457     WAIT_TYPE status;
7458     WAIT_STATUS_INT(status) = 0;
7459 
7460     if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
7461         return NULL;
7462 
7463     return Py_BuildValue("i", WSTOPSIG(status));
7464 }
7465 #endif /* WSTOPSIG */
7466 
7467 #endif /* HAVE_SYS_WAIT_H */
7468 
7469 
7470 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
7471 #ifdef _SCO_DS
7472 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
7473    needed definitions in sys/statvfs.h */
7474 #define _SVID3
7475 #endif
7476 #include <sys/statvfs.h>
7477 
7478 static PyObject*
_pystatvfs_fromstructstatvfs(struct statvfs st)7479 _pystatvfs_fromstructstatvfs(struct statvfs st) {
7480     PyObject *v = PyStructSequence_New(&StatVFSResultType);
7481     if (v == NULL)
7482         return NULL;
7483 
7484 #if !defined(HAVE_LARGEFILE_SUPPORT)
7485     PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
7486     PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
7487     PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long) st.f_blocks));
7488     PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long) st.f_bfree));
7489     PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long) st.f_bavail));
7490     PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long) st.f_files));
7491     PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong((long) st.f_ffree));
7492     PyStructSequence_SET_ITEM(v, 7, PyInt_FromLong((long) st.f_favail));
7493     PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
7494     PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
7495 #else
7496     PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
7497     PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
7498     PyStructSequence_SET_ITEM(v, 2,
7499                               PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
7500     PyStructSequence_SET_ITEM(v, 3,
7501                               PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
7502     PyStructSequence_SET_ITEM(v, 4,
7503                               PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
7504     PyStructSequence_SET_ITEM(v, 5,
7505                               PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
7506     PyStructSequence_SET_ITEM(v, 6,
7507                               PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
7508     PyStructSequence_SET_ITEM(v, 7,
7509                               PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
7510     PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
7511     PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
7512 #endif
7513 
7514     return v;
7515 }
7516 
7517 PyDoc_STRVAR(posix_fstatvfs__doc__,
7518 "fstatvfs(fd) -> statvfs result\n\n\
7519 Perform an fstatvfs system call on the given fd.");
7520 
7521 static PyObject *
posix_fstatvfs(PyObject * self,PyObject * args)7522 posix_fstatvfs(PyObject *self, PyObject *args)
7523 {
7524     int fd, res;
7525     struct statvfs st;
7526 
7527     if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
7528         return NULL;
7529     Py_BEGIN_ALLOW_THREADS
7530     res = fstatvfs(fd, &st);
7531     Py_END_ALLOW_THREADS
7532     if (res != 0)
7533         return posix_error();
7534 
7535     return _pystatvfs_fromstructstatvfs(st);
7536 }
7537 #endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
7538 
7539 
7540 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
7541 #include <sys/statvfs.h>
7542 
7543 PyDoc_STRVAR(posix_statvfs__doc__,
7544 "statvfs(path) -> statvfs result\n\n\
7545 Perform a statvfs system call on the given path.");
7546 
7547 static PyObject *
posix_statvfs(PyObject * self,PyObject * args)7548 posix_statvfs(PyObject *self, PyObject *args)
7549 {
7550     char *path;
7551     int res;
7552     struct statvfs st;
7553     if (!PyArg_ParseTuple(args, "s:statvfs", &path))
7554         return NULL;
7555     Py_BEGIN_ALLOW_THREADS
7556     res = statvfs(path, &st);
7557     Py_END_ALLOW_THREADS
7558     if (res != 0)
7559         return posix_error_with_filename(path);
7560 
7561     return _pystatvfs_fromstructstatvfs(st);
7562 }
7563 #endif /* HAVE_STATVFS */
7564 
7565 
7566 #ifdef HAVE_TEMPNAM
7567 PyDoc_STRVAR(posix_tempnam__doc__,
7568 "tempnam([dir[, prefix]]) -> string\n\n\
7569 Return a unique name for a temporary file.\n\
7570 The directory and a prefix may be specified as strings; they may be omitted\n\
7571 or None if not needed.");
7572 
7573 static PyObject *
posix_tempnam(PyObject * self,PyObject * args)7574 posix_tempnam(PyObject *self, PyObject *args)
7575 {
7576     PyObject *result = NULL;
7577     char *dir = NULL;
7578     char *pfx = NULL;
7579     char *name;
7580 
7581     if (!PyArg_ParseTuple(args, "|zz:tempnam", &dir, &pfx))
7582     return NULL;
7583 
7584     if (PyErr_Warn(PyExc_RuntimeWarning,
7585                    "tempnam is a potential security risk to your program") < 0)
7586         return NULL;
7587 
7588     if (PyErr_WarnPy3k("tempnam has been removed in 3.x; "
7589                        "use the tempfile module", 1) < 0)
7590         return NULL;
7591 
7592 #ifdef MS_WINDOWS
7593     name = _tempnam(dir, pfx);
7594 #else
7595     name = tempnam(dir, pfx);
7596 #endif
7597     if (name == NULL)
7598         return PyErr_NoMemory();
7599     result = PyString_FromString(name);
7600     free(name);
7601     return result;
7602 }
7603 #endif
7604 
7605 
7606 #ifdef HAVE_TMPFILE
7607 PyDoc_STRVAR(posix_tmpfile__doc__,
7608 "tmpfile() -> file object\n\n\
7609 Create a temporary file with no directory entries.");
7610 
7611 static PyObject *
posix_tmpfile(PyObject * self,PyObject * noargs)7612 posix_tmpfile(PyObject *self, PyObject *noargs)
7613 {
7614     FILE *fp;
7615 
7616     if (PyErr_WarnPy3k("tmpfile has been removed in 3.x; "
7617                        "use the tempfile module", 1) < 0)
7618         return NULL;
7619 
7620     fp = tmpfile();
7621     if (fp == NULL)
7622         return posix_error();
7623     return PyFile_FromFile(fp, "<tmpfile>", "w+b", fclose);
7624 }
7625 #endif
7626 
7627 
7628 #ifdef HAVE_TMPNAM
7629 PyDoc_STRVAR(posix_tmpnam__doc__,
7630 "tmpnam() -> string\n\n\
7631 Return a unique name for a temporary file.");
7632 
7633 static PyObject *
posix_tmpnam(PyObject * self,PyObject * noargs)7634 posix_tmpnam(PyObject *self, PyObject *noargs)
7635 {
7636     char buffer[L_tmpnam];
7637     char *name;
7638 
7639     if (PyErr_Warn(PyExc_RuntimeWarning,
7640                    "tmpnam is a potential security risk to your program") < 0)
7641         return NULL;
7642 
7643     if (PyErr_WarnPy3k("tmpnam has been removed in 3.x; "
7644                        "use the tempfile module", 1) < 0)
7645         return NULL;
7646 
7647 #ifdef USE_TMPNAM_R
7648     name = tmpnam_r(buffer);
7649 #else
7650     name = tmpnam(buffer);
7651 #endif
7652     if (name == NULL) {
7653         PyObject *err = Py_BuildValue("is", 0,
7654 #ifdef USE_TMPNAM_R
7655                                       "unexpected NULL from tmpnam_r"
7656 #else
7657                                       "unexpected NULL from tmpnam"
7658 #endif
7659                                       );
7660         PyErr_SetObject(PyExc_OSError, err);
7661         Py_XDECREF(err);
7662         return NULL;
7663     }
7664     return PyString_FromString(buffer);
7665 }
7666 #endif
7667 
7668 
7669 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
7670  * It maps strings representing configuration variable names to
7671  * integer values, allowing those functions to be called with the
7672  * magic names instead of polluting the module's namespace with tons of
7673  * rarely-used constants.  There are three separate tables that use
7674  * these definitions.
7675  *
7676  * This code is always included, even if none of the interfaces that
7677  * need it are included.  The #if hackery needed to avoid it would be
7678  * sufficiently pervasive that it's not worth the loss of readability.
7679  */
7680 struct constdef {
7681     char *name;
7682     long value;
7683 };
7684 
7685 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)7686 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
7687               size_t tablesize)
7688 {
7689     if (PyInt_Check(arg)) {
7690         *valuep = PyInt_AS_LONG(arg);
7691         return 1;
7692     }
7693     if (PyString_Check(arg)) {
7694         /* look up the value in the table using a binary search */
7695         size_t lo = 0;
7696         size_t mid;
7697         size_t hi = tablesize;
7698         int cmp;
7699         char *confname = PyString_AS_STRING(arg);
7700         while (lo < hi) {
7701             mid = (lo + hi) / 2;
7702             cmp = strcmp(confname, table[mid].name);
7703             if (cmp < 0)
7704                 hi = mid;
7705             else if (cmp > 0)
7706                 lo = mid + 1;
7707             else {
7708                 *valuep = table[mid].value;
7709                 return 1;
7710             }
7711         }
7712         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
7713     }
7714     else
7715         PyErr_SetString(PyExc_TypeError,
7716                         "configuration names must be strings or integers");
7717     return 0;
7718 }
7719 
7720 
7721 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
7722 static struct constdef  posix_constants_pathconf[] = {
7723 #ifdef _PC_ABI_AIO_XFER_MAX
7724     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
7725 #endif
7726 #ifdef _PC_ABI_ASYNC_IO
7727     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
7728 #endif
7729 #ifdef _PC_ASYNC_IO
7730     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
7731 #endif
7732 #ifdef _PC_CHOWN_RESTRICTED
7733     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
7734 #endif
7735 #ifdef _PC_FILESIZEBITS
7736     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
7737 #endif
7738 #ifdef _PC_LAST
7739     {"PC_LAST", _PC_LAST},
7740 #endif
7741 #ifdef _PC_LINK_MAX
7742     {"PC_LINK_MAX",     _PC_LINK_MAX},
7743 #endif
7744 #ifdef _PC_MAX_CANON
7745     {"PC_MAX_CANON",    _PC_MAX_CANON},
7746 #endif
7747 #ifdef _PC_MAX_INPUT
7748     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
7749 #endif
7750 #ifdef _PC_NAME_MAX
7751     {"PC_NAME_MAX",     _PC_NAME_MAX},
7752 #endif
7753 #ifdef _PC_NO_TRUNC
7754     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
7755 #endif
7756 #ifdef _PC_PATH_MAX
7757     {"PC_PATH_MAX",     _PC_PATH_MAX},
7758 #endif
7759 #ifdef _PC_PIPE_BUF
7760     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
7761 #endif
7762 #ifdef _PC_PRIO_IO
7763     {"PC_PRIO_IO",      _PC_PRIO_IO},
7764 #endif
7765 #ifdef _PC_SOCK_MAXBUF
7766     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
7767 #endif
7768 #ifdef _PC_SYNC_IO
7769     {"PC_SYNC_IO",      _PC_SYNC_IO},
7770 #endif
7771 #ifdef _PC_VDISABLE
7772     {"PC_VDISABLE",     _PC_VDISABLE},
7773 #endif
7774 };
7775 
7776 static int
conv_path_confname(PyObject * arg,int * valuep)7777 conv_path_confname(PyObject *arg, int *valuep)
7778 {
7779     return conv_confname(arg, valuep, posix_constants_pathconf,
7780                          sizeof(posix_constants_pathconf)
7781                            / sizeof(struct constdef));
7782 }
7783 #endif
7784 
7785 #ifdef HAVE_FPATHCONF
7786 PyDoc_STRVAR(posix_fpathconf__doc__,
7787 "fpathconf(fd, name) -> integer\n\n\
7788 Return the configuration limit name for the file descriptor fd.\n\
7789 If there is no limit, return -1.");
7790 
7791 static PyObject *
posix_fpathconf(PyObject * self,PyObject * args)7792 posix_fpathconf(PyObject *self, PyObject *args)
7793 {
7794     PyObject *result = NULL;
7795     int name, fd;
7796 
7797     if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
7798                          conv_path_confname, &name)) {
7799         long limit;
7800 
7801         errno = 0;
7802         limit = fpathconf(fd, name);
7803         if (limit == -1 && errno != 0)
7804             posix_error();
7805         else
7806             result = PyInt_FromLong(limit);
7807     }
7808     return result;
7809 }
7810 #endif
7811 
7812 
7813 #ifdef HAVE_PATHCONF
7814 PyDoc_STRVAR(posix_pathconf__doc__,
7815 "pathconf(path, name) -> integer\n\n\
7816 Return the configuration limit name for the file or directory path.\n\
7817 If there is no limit, return -1.");
7818 
7819 static PyObject *
posix_pathconf(PyObject * self,PyObject * args)7820 posix_pathconf(PyObject *self, PyObject *args)
7821 {
7822     PyObject *result = NULL;
7823     int name;
7824     char *path;
7825 
7826     if (PyArg_ParseTuple(args, "sO&:pathconf", &path,
7827                          conv_path_confname, &name)) {
7828     long limit;
7829 
7830     errno = 0;
7831     limit = pathconf(path, name);
7832     if (limit == -1 && errno != 0) {
7833         if (errno == EINVAL)
7834             /* could be a path or name problem */
7835             posix_error();
7836         else
7837             posix_error_with_filename(path);
7838     }
7839     else
7840         result = PyInt_FromLong(limit);
7841     }
7842     return result;
7843 }
7844 #endif
7845 
7846 #ifdef HAVE_CONFSTR
7847 static struct constdef posix_constants_confstr[] = {
7848 #ifdef _CS_ARCHITECTURE
7849     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
7850 #endif
7851 #ifdef _CS_HOSTNAME
7852     {"CS_HOSTNAME",     _CS_HOSTNAME},
7853 #endif
7854 #ifdef _CS_HW_PROVIDER
7855     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
7856 #endif
7857 #ifdef _CS_HW_SERIAL
7858     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
7859 #endif
7860 #ifdef _CS_INITTAB_NAME
7861     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
7862 #endif
7863 #ifdef _CS_LFS64_CFLAGS
7864     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
7865 #endif
7866 #ifdef _CS_LFS64_LDFLAGS
7867     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
7868 #endif
7869 #ifdef _CS_LFS64_LIBS
7870     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
7871 #endif
7872 #ifdef _CS_LFS64_LINTFLAGS
7873     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
7874 #endif
7875 #ifdef _CS_LFS_CFLAGS
7876     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
7877 #endif
7878 #ifdef _CS_LFS_LDFLAGS
7879     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
7880 #endif
7881 #ifdef _CS_LFS_LIBS
7882     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
7883 #endif
7884 #ifdef _CS_LFS_LINTFLAGS
7885     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
7886 #endif
7887 #ifdef _CS_MACHINE
7888     {"CS_MACHINE",      _CS_MACHINE},
7889 #endif
7890 #ifdef _CS_PATH
7891     {"CS_PATH", _CS_PATH},
7892 #endif
7893 #ifdef _CS_RELEASE
7894     {"CS_RELEASE",      _CS_RELEASE},
7895 #endif
7896 #ifdef _CS_SRPC_DOMAIN
7897     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
7898 #endif
7899 #ifdef _CS_SYSNAME
7900     {"CS_SYSNAME",      _CS_SYSNAME},
7901 #endif
7902 #ifdef _CS_VERSION
7903     {"CS_VERSION",      _CS_VERSION},
7904 #endif
7905 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
7906     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
7907 #endif
7908 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
7909     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
7910 #endif
7911 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
7912     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
7913 #endif
7914 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
7915     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
7916 #endif
7917 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
7918     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
7919 #endif
7920 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
7921     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
7922 #endif
7923 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
7924     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
7925 #endif
7926 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
7927     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
7928 #endif
7929 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
7930     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
7931 #endif
7932 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
7933     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
7934 #endif
7935 #ifdef _CS_XBS5_LP64_OFF64_LIBS
7936     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
7937 #endif
7938 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
7939     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
7940 #endif
7941 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
7942     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
7943 #endif
7944 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
7945     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
7946 #endif
7947 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
7948     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
7949 #endif
7950 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
7951     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
7952 #endif
7953 #ifdef _MIPS_CS_AVAIL_PROCESSORS
7954     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
7955 #endif
7956 #ifdef _MIPS_CS_BASE
7957     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
7958 #endif
7959 #ifdef _MIPS_CS_HOSTID
7960     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
7961 #endif
7962 #ifdef _MIPS_CS_HW_NAME
7963     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
7964 #endif
7965 #ifdef _MIPS_CS_NUM_PROCESSORS
7966     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
7967 #endif
7968 #ifdef _MIPS_CS_OSREL_MAJ
7969     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
7970 #endif
7971 #ifdef _MIPS_CS_OSREL_MIN
7972     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
7973 #endif
7974 #ifdef _MIPS_CS_OSREL_PATCH
7975     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
7976 #endif
7977 #ifdef _MIPS_CS_OS_NAME
7978     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
7979 #endif
7980 #ifdef _MIPS_CS_OS_PROVIDER
7981     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
7982 #endif
7983 #ifdef _MIPS_CS_PROCESSORS
7984     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
7985 #endif
7986 #ifdef _MIPS_CS_SERIAL
7987     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
7988 #endif
7989 #ifdef _MIPS_CS_VENDOR
7990     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
7991 #endif
7992 };
7993 
7994 static int
conv_confstr_confname(PyObject * arg,int * valuep)7995 conv_confstr_confname(PyObject *arg, int *valuep)
7996 {
7997     return conv_confname(arg, valuep, posix_constants_confstr,
7998                          sizeof(posix_constants_confstr)
7999                            / sizeof(struct constdef));
8000 }
8001 
8002 PyDoc_STRVAR(posix_confstr__doc__,
8003 "confstr(name) -> string\n\n\
8004 Return a string-valued system configuration variable.");
8005 
8006 static PyObject *
posix_confstr(PyObject * self,PyObject * args)8007 posix_confstr(PyObject *self, PyObject *args)
8008 {
8009     PyObject *result = NULL;
8010     int name;
8011     char buffer[256];
8012 
8013     if (PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) {
8014     int len;
8015 
8016     errno = 0;
8017     len = confstr(name, buffer, sizeof(buffer));
8018     if (len == 0) {
8019         if (errno) {
8020         posix_error();
8021         }
8022         else {
8023         result = Py_None;
8024         Py_INCREF(Py_None);
8025         }
8026     }
8027     else {
8028         if ((unsigned int)len >= sizeof(buffer)) {
8029         result = PyString_FromStringAndSize(NULL, len-1);
8030         if (result != NULL)
8031             confstr(name, PyString_AS_STRING(result), len);
8032         }
8033         else
8034         result = PyString_FromStringAndSize(buffer, len-1);
8035     }
8036     }
8037     return result;
8038 }
8039 #endif
8040 
8041 
8042 #ifdef HAVE_SYSCONF
8043 static struct constdef posix_constants_sysconf[] = {
8044 #ifdef _SC_2_CHAR_TERM
8045     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
8046 #endif
8047 #ifdef _SC_2_C_BIND
8048     {"SC_2_C_BIND",     _SC_2_C_BIND},
8049 #endif
8050 #ifdef _SC_2_C_DEV
8051     {"SC_2_C_DEV",      _SC_2_C_DEV},
8052 #endif
8053 #ifdef _SC_2_C_VERSION
8054     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
8055 #endif
8056 #ifdef _SC_2_FORT_DEV
8057     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
8058 #endif
8059 #ifdef _SC_2_FORT_RUN
8060     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
8061 #endif
8062 #ifdef _SC_2_LOCALEDEF
8063     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
8064 #endif
8065 #ifdef _SC_2_SW_DEV
8066     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
8067 #endif
8068 #ifdef _SC_2_UPE
8069     {"SC_2_UPE",        _SC_2_UPE},
8070 #endif
8071 #ifdef _SC_2_VERSION
8072     {"SC_2_VERSION",    _SC_2_VERSION},
8073 #endif
8074 #ifdef _SC_ABI_ASYNCHRONOUS_IO
8075     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
8076 #endif
8077 #ifdef _SC_ACL
8078     {"SC_ACL",  _SC_ACL},
8079 #endif
8080 #ifdef _SC_AIO_LISTIO_MAX
8081     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
8082 #endif
8083 #ifdef _SC_AIO_MAX
8084     {"SC_AIO_MAX",      _SC_AIO_MAX},
8085 #endif
8086 #ifdef _SC_AIO_PRIO_DELTA_MAX
8087     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
8088 #endif
8089 #ifdef _SC_ARG_MAX
8090     {"SC_ARG_MAX",      _SC_ARG_MAX},
8091 #endif
8092 #ifdef _SC_ASYNCHRONOUS_IO
8093     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
8094 #endif
8095 #ifdef _SC_ATEXIT_MAX
8096     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
8097 #endif
8098 #ifdef _SC_AUDIT
8099     {"SC_AUDIT",        _SC_AUDIT},
8100 #endif
8101 #ifdef _SC_AVPHYS_PAGES
8102     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
8103 #endif
8104 #ifdef _SC_BC_BASE_MAX
8105     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
8106 #endif
8107 #ifdef _SC_BC_DIM_MAX
8108     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
8109 #endif
8110 #ifdef _SC_BC_SCALE_MAX
8111     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
8112 #endif
8113 #ifdef _SC_BC_STRING_MAX
8114     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
8115 #endif
8116 #ifdef _SC_CAP
8117     {"SC_CAP",  _SC_CAP},
8118 #endif
8119 #ifdef _SC_CHARCLASS_NAME_MAX
8120     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
8121 #endif
8122 #ifdef _SC_CHAR_BIT
8123     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
8124 #endif
8125 #ifdef _SC_CHAR_MAX
8126     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
8127 #endif
8128 #ifdef _SC_CHAR_MIN
8129     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
8130 #endif
8131 #ifdef _SC_CHILD_MAX
8132     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
8133 #endif
8134 #ifdef _SC_CLK_TCK
8135     {"SC_CLK_TCK",      _SC_CLK_TCK},
8136 #endif
8137 #ifdef _SC_COHER_BLKSZ
8138     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
8139 #endif
8140 #ifdef _SC_COLL_WEIGHTS_MAX
8141     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
8142 #endif
8143 #ifdef _SC_DCACHE_ASSOC
8144     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
8145 #endif
8146 #ifdef _SC_DCACHE_BLKSZ
8147     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
8148 #endif
8149 #ifdef _SC_DCACHE_LINESZ
8150     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
8151 #endif
8152 #ifdef _SC_DCACHE_SZ
8153     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
8154 #endif
8155 #ifdef _SC_DCACHE_TBLKSZ
8156     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
8157 #endif
8158 #ifdef _SC_DELAYTIMER_MAX
8159     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
8160 #endif
8161 #ifdef _SC_EQUIV_CLASS_MAX
8162     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
8163 #endif
8164 #ifdef _SC_EXPR_NEST_MAX
8165     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
8166 #endif
8167 #ifdef _SC_FSYNC
8168     {"SC_FSYNC",        _SC_FSYNC},
8169 #endif
8170 #ifdef _SC_GETGR_R_SIZE_MAX
8171     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
8172 #endif
8173 #ifdef _SC_GETPW_R_SIZE_MAX
8174     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
8175 #endif
8176 #ifdef _SC_ICACHE_ASSOC
8177     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
8178 #endif
8179 #ifdef _SC_ICACHE_BLKSZ
8180     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
8181 #endif
8182 #ifdef _SC_ICACHE_LINESZ
8183     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
8184 #endif
8185 #ifdef _SC_ICACHE_SZ
8186     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
8187 #endif
8188 #ifdef _SC_INF
8189     {"SC_INF",  _SC_INF},
8190 #endif
8191 #ifdef _SC_INT_MAX
8192     {"SC_INT_MAX",      _SC_INT_MAX},
8193 #endif
8194 #ifdef _SC_INT_MIN
8195     {"SC_INT_MIN",      _SC_INT_MIN},
8196 #endif
8197 #ifdef _SC_IOV_MAX
8198     {"SC_IOV_MAX",      _SC_IOV_MAX},
8199 #endif
8200 #ifdef _SC_IP_SECOPTS
8201     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
8202 #endif
8203 #ifdef _SC_JOB_CONTROL
8204     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
8205 #endif
8206 #ifdef _SC_KERN_POINTERS
8207     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
8208 #endif
8209 #ifdef _SC_KERN_SIM
8210     {"SC_KERN_SIM",     _SC_KERN_SIM},
8211 #endif
8212 #ifdef _SC_LINE_MAX
8213     {"SC_LINE_MAX",     _SC_LINE_MAX},
8214 #endif
8215 #ifdef _SC_LOGIN_NAME_MAX
8216     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
8217 #endif
8218 #ifdef _SC_LOGNAME_MAX
8219     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
8220 #endif
8221 #ifdef _SC_LONG_BIT
8222     {"SC_LONG_BIT",     _SC_LONG_BIT},
8223 #endif
8224 #ifdef _SC_MAC
8225     {"SC_MAC",  _SC_MAC},
8226 #endif
8227 #ifdef _SC_MAPPED_FILES
8228     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
8229 #endif
8230 #ifdef _SC_MAXPID
8231     {"SC_MAXPID",       _SC_MAXPID},
8232 #endif
8233 #ifdef _SC_MB_LEN_MAX
8234     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
8235 #endif
8236 #ifdef _SC_MEMLOCK
8237     {"SC_MEMLOCK",      _SC_MEMLOCK},
8238 #endif
8239 #ifdef _SC_MEMLOCK_RANGE
8240     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
8241 #endif
8242 #ifdef _SC_MEMORY_PROTECTION
8243     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
8244 #endif
8245 #ifdef _SC_MESSAGE_PASSING
8246     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
8247 #endif
8248 #ifdef _SC_MMAP_FIXED_ALIGNMENT
8249     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
8250 #endif
8251 #ifdef _SC_MQ_OPEN_MAX
8252     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
8253 #endif
8254 #ifdef _SC_MQ_PRIO_MAX
8255     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
8256 #endif
8257 #ifdef _SC_NACLS_MAX
8258     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
8259 #endif
8260 #ifdef _SC_NGROUPS_MAX
8261     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
8262 #endif
8263 #ifdef _SC_NL_ARGMAX
8264     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
8265 #endif
8266 #ifdef _SC_NL_LANGMAX
8267     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
8268 #endif
8269 #ifdef _SC_NL_MSGMAX
8270     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
8271 #endif
8272 #ifdef _SC_NL_NMAX
8273     {"SC_NL_NMAX",      _SC_NL_NMAX},
8274 #endif
8275 #ifdef _SC_NL_SETMAX
8276     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
8277 #endif
8278 #ifdef _SC_NL_TEXTMAX
8279     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
8280 #endif
8281 #ifdef _SC_NPROCESSORS_CONF
8282     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
8283 #endif
8284 #ifdef _SC_NPROCESSORS_ONLN
8285     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
8286 #endif
8287 #ifdef _SC_NPROC_CONF
8288     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
8289 #endif
8290 #ifdef _SC_NPROC_ONLN
8291     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
8292 #endif
8293 #ifdef _SC_NZERO
8294     {"SC_NZERO",        _SC_NZERO},
8295 #endif
8296 #ifdef _SC_OPEN_MAX
8297     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
8298 #endif
8299 #ifdef _SC_PAGESIZE
8300     {"SC_PAGESIZE",     _SC_PAGESIZE},
8301 #endif
8302 #ifdef _SC_PAGE_SIZE
8303     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
8304 #endif
8305 #ifdef _SC_PASS_MAX
8306     {"SC_PASS_MAX",     _SC_PASS_MAX},
8307 #endif
8308 #ifdef _SC_PHYS_PAGES
8309     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
8310 #endif
8311 #ifdef _SC_PII
8312     {"SC_PII",  _SC_PII},
8313 #endif
8314 #ifdef _SC_PII_INTERNET
8315     {"SC_PII_INTERNET", _SC_PII_INTERNET},
8316 #endif
8317 #ifdef _SC_PII_INTERNET_DGRAM
8318     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
8319 #endif
8320 #ifdef _SC_PII_INTERNET_STREAM
8321     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
8322 #endif
8323 #ifdef _SC_PII_OSI
8324     {"SC_PII_OSI",      _SC_PII_OSI},
8325 #endif
8326 #ifdef _SC_PII_OSI_CLTS
8327     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
8328 #endif
8329 #ifdef _SC_PII_OSI_COTS
8330     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
8331 #endif
8332 #ifdef _SC_PII_OSI_M
8333     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
8334 #endif
8335 #ifdef _SC_PII_SOCKET
8336     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
8337 #endif
8338 #ifdef _SC_PII_XTI
8339     {"SC_PII_XTI",      _SC_PII_XTI},
8340 #endif
8341 #ifdef _SC_POLL
8342     {"SC_POLL", _SC_POLL},
8343 #endif
8344 #ifdef _SC_PRIORITIZED_IO
8345     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
8346 #endif
8347 #ifdef _SC_PRIORITY_SCHEDULING
8348     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
8349 #endif
8350 #ifdef _SC_REALTIME_SIGNALS
8351     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
8352 #endif
8353 #ifdef _SC_RE_DUP_MAX
8354     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
8355 #endif
8356 #ifdef _SC_RTSIG_MAX
8357     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
8358 #endif
8359 #ifdef _SC_SAVED_IDS
8360     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
8361 #endif
8362 #ifdef _SC_SCHAR_MAX
8363     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
8364 #endif
8365 #ifdef _SC_SCHAR_MIN
8366     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
8367 #endif
8368 #ifdef _SC_SELECT
8369     {"SC_SELECT",       _SC_SELECT},
8370 #endif
8371 #ifdef _SC_SEMAPHORES
8372     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
8373 #endif
8374 #ifdef _SC_SEM_NSEMS_MAX
8375     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
8376 #endif
8377 #ifdef _SC_SEM_VALUE_MAX
8378     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
8379 #endif
8380 #ifdef _SC_SHARED_MEMORY_OBJECTS
8381     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
8382 #endif
8383 #ifdef _SC_SHRT_MAX
8384     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
8385 #endif
8386 #ifdef _SC_SHRT_MIN
8387     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
8388 #endif
8389 #ifdef _SC_SIGQUEUE_MAX
8390     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
8391 #endif
8392 #ifdef _SC_SIGRT_MAX
8393     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
8394 #endif
8395 #ifdef _SC_SIGRT_MIN
8396     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
8397 #endif
8398 #ifdef _SC_SOFTPOWER
8399     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
8400 #endif
8401 #ifdef _SC_SPLIT_CACHE
8402     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
8403 #endif
8404 #ifdef _SC_SSIZE_MAX
8405     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
8406 #endif
8407 #ifdef _SC_STACK_PROT
8408     {"SC_STACK_PROT",   _SC_STACK_PROT},
8409 #endif
8410 #ifdef _SC_STREAM_MAX
8411     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
8412 #endif
8413 #ifdef _SC_SYNCHRONIZED_IO
8414     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
8415 #endif
8416 #ifdef _SC_THREADS
8417     {"SC_THREADS",      _SC_THREADS},
8418 #endif
8419 #ifdef _SC_THREAD_ATTR_STACKADDR
8420     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
8421 #endif
8422 #ifdef _SC_THREAD_ATTR_STACKSIZE
8423     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
8424 #endif
8425 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
8426     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
8427 #endif
8428 #ifdef _SC_THREAD_KEYS_MAX
8429     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
8430 #endif
8431 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
8432     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
8433 #endif
8434 #ifdef _SC_THREAD_PRIO_INHERIT
8435     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
8436 #endif
8437 #ifdef _SC_THREAD_PRIO_PROTECT
8438     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
8439 #endif
8440 #ifdef _SC_THREAD_PROCESS_SHARED
8441     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
8442 #endif
8443 #ifdef _SC_THREAD_SAFE_FUNCTIONS
8444     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
8445 #endif
8446 #ifdef _SC_THREAD_STACK_MIN
8447     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
8448 #endif
8449 #ifdef _SC_THREAD_THREADS_MAX
8450     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
8451 #endif
8452 #ifdef _SC_TIMERS
8453     {"SC_TIMERS",       _SC_TIMERS},
8454 #endif
8455 #ifdef _SC_TIMER_MAX
8456     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
8457 #endif
8458 #ifdef _SC_TTY_NAME_MAX
8459     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
8460 #endif
8461 #ifdef _SC_TZNAME_MAX
8462     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
8463 #endif
8464 #ifdef _SC_T_IOV_MAX
8465     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
8466 #endif
8467 #ifdef _SC_UCHAR_MAX
8468     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
8469 #endif
8470 #ifdef _SC_UINT_MAX
8471     {"SC_UINT_MAX",     _SC_UINT_MAX},
8472 #endif
8473 #ifdef _SC_UIO_MAXIOV
8474     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
8475 #endif
8476 #ifdef _SC_ULONG_MAX
8477     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
8478 #endif
8479 #ifdef _SC_USHRT_MAX
8480     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
8481 #endif
8482 #ifdef _SC_VERSION
8483     {"SC_VERSION",      _SC_VERSION},
8484 #endif
8485 #ifdef _SC_WORD_BIT
8486     {"SC_WORD_BIT",     _SC_WORD_BIT},
8487 #endif
8488 #ifdef _SC_XBS5_ILP32_OFF32
8489     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
8490 #endif
8491 #ifdef _SC_XBS5_ILP32_OFFBIG
8492     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
8493 #endif
8494 #ifdef _SC_XBS5_LP64_OFF64
8495     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
8496 #endif
8497 #ifdef _SC_XBS5_LPBIG_OFFBIG
8498     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
8499 #endif
8500 #ifdef _SC_XOPEN_CRYPT
8501     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
8502 #endif
8503 #ifdef _SC_XOPEN_ENH_I18N
8504     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
8505 #endif
8506 #ifdef _SC_XOPEN_LEGACY
8507     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
8508 #endif
8509 #ifdef _SC_XOPEN_REALTIME
8510     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
8511 #endif
8512 #ifdef _SC_XOPEN_REALTIME_THREADS
8513     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
8514 #endif
8515 #ifdef _SC_XOPEN_SHM
8516     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
8517 #endif
8518 #ifdef _SC_XOPEN_UNIX
8519     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
8520 #endif
8521 #ifdef _SC_XOPEN_VERSION
8522     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
8523 #endif
8524 #ifdef _SC_XOPEN_XCU_VERSION
8525     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
8526 #endif
8527 #ifdef _SC_XOPEN_XPG2
8528     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
8529 #endif
8530 #ifdef _SC_XOPEN_XPG3
8531     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
8532 #endif
8533 #ifdef _SC_XOPEN_XPG4
8534     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
8535 #endif
8536 };
8537 
8538 static int
conv_sysconf_confname(PyObject * arg,int * valuep)8539 conv_sysconf_confname(PyObject *arg, int *valuep)
8540 {
8541     return conv_confname(arg, valuep, posix_constants_sysconf,
8542                          sizeof(posix_constants_sysconf)
8543                            / sizeof(struct constdef));
8544 }
8545 
8546 PyDoc_STRVAR(posix_sysconf__doc__,
8547 "sysconf(name) -> integer\n\n\
8548 Return an integer-valued system configuration variable.");
8549 
8550 static PyObject *
posix_sysconf(PyObject * self,PyObject * args)8551 posix_sysconf(PyObject *self, PyObject *args)
8552 {
8553     PyObject *result = NULL;
8554     int name;
8555 
8556     if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
8557         int value;
8558 
8559         errno = 0;
8560         value = sysconf(name);
8561         if (value == -1 && errno != 0)
8562             posix_error();
8563         else
8564             result = PyInt_FromLong(value);
8565     }
8566     return result;
8567 }
8568 #endif
8569 
8570 
8571 /* This code is used to ensure that the tables of configuration value names
8572  * are in sorted order as required by conv_confname(), and also to build
8573  * the exported dictionaries that are used to publish information about the
8574  * names available on the host platform.
8575  *
8576  * Sorting the table at runtime ensures that the table is properly ordered
8577  * when used, even for platforms we're not able to test on.  It also makes
8578  * it easier to add additional entries to the tables.
8579  */
8580 
8581 static int
cmp_constdefs(const void * v1,const void * v2)8582 cmp_constdefs(const void *v1,  const void *v2)
8583 {
8584     const struct constdef *c1 =
8585     (const struct constdef *) v1;
8586     const struct constdef *c2 =
8587     (const struct constdef *) v2;
8588 
8589     return strcmp(c1->name, c2->name);
8590 }
8591 
8592 static int
setup_confname_table(struct constdef * table,size_t tablesize,char * tablename,PyObject * module)8593 setup_confname_table(struct constdef *table, size_t tablesize,
8594                      char *tablename, PyObject *module)
8595 {
8596     PyObject *d = NULL;
8597     size_t i;
8598     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
8599     d = PyDict_New();
8600     if (d == NULL)
8601         return -1;
8602 
8603     for (i=0; i < tablesize; ++i) {
8604         PyObject *o = PyInt_FromLong(table[i].value);
8605         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
8606             Py_XDECREF(o);
8607             Py_DECREF(d);
8608             return -1;
8609         }
8610         Py_DECREF(o);
8611     }
8612     return PyModule_AddObject(module, tablename, d);
8613 }
8614 
8615 /* Return -1 on failure, 0 on success. */
8616 static int
setup_confname_tables(PyObject * module)8617 setup_confname_tables(PyObject *module)
8618 {
8619 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
8620     if (setup_confname_table(posix_constants_pathconf,
8621                              sizeof(posix_constants_pathconf)
8622                                / sizeof(struct constdef),
8623                              "pathconf_names", module))
8624         return -1;
8625 #endif
8626 #ifdef HAVE_CONFSTR
8627     if (setup_confname_table(posix_constants_confstr,
8628                              sizeof(posix_constants_confstr)
8629                                / sizeof(struct constdef),
8630                              "confstr_names", module))
8631         return -1;
8632 #endif
8633 #ifdef HAVE_SYSCONF
8634     if (setup_confname_table(posix_constants_sysconf,
8635                              sizeof(posix_constants_sysconf)
8636                                / sizeof(struct constdef),
8637                              "sysconf_names", module))
8638         return -1;
8639 #endif
8640     return 0;
8641 }
8642 
8643 
8644 PyDoc_STRVAR(posix_abort__doc__,
8645 "abort() -> does not return!\n\n\
8646 Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
8647 in the hardest way possible on the hosting operating system.");
8648 
8649 static PyObject *
posix_abort(PyObject * self,PyObject * noargs)8650 posix_abort(PyObject *self, PyObject *noargs)
8651 {
8652     abort();
8653     /*NOTREACHED*/
8654     Py_FatalError("abort() called from Python code didn't abort!");
8655     return NULL;
8656 }
8657 
8658 #ifdef MS_WINDOWS
8659 PyDoc_STRVAR(win32_startfile__doc__,
8660 "startfile(filepath [, operation]) - Start a file with its associated\n\
8661 application.\n\
8662 \n\
8663 When \"operation\" is not specified or \"open\", this acts like\n\
8664 double-clicking the file in Explorer, or giving the file name as an\n\
8665 argument to the DOS \"start\" command: the file is opened with whatever\n\
8666 application (if any) its extension is associated.\n\
8667 When another \"operation\" is given, it specifies what should be done with\n\
8668 the file.  A typical operation is \"print\".\n\
8669 \n\
8670 startfile returns as soon as the associated application is launched.\n\
8671 There is no option to wait for the application to close, and no way\n\
8672 to retrieve the application's exit status.\n\
8673 \n\
8674 The filepath is relative to the current directory.  If you want to use\n\
8675 an absolute path, make sure the first character is not a slash (\"/\");\n\
8676 the underlying Win32 ShellExecute function doesn't work if it is.");
8677 
8678 static PyObject *
win32_startfile(PyObject * self,PyObject * args)8679 win32_startfile(PyObject *self, PyObject *args)
8680 {
8681     char *filepath;
8682     Py_UNICODE *wpath;
8683     char *operation = NULL;
8684     HINSTANCE rc;
8685 
8686     PyObject *woperation = NULL;
8687     if (!PyArg_ParseTuple(args, "u|s:startfile",
8688                           &wpath, &operation)) {
8689         PyErr_Clear();
8690         goto normal;
8691     }
8692 
8693     if (operation) {
8694         woperation = PyUnicode_DecodeASCII(operation,
8695                                            strlen(operation), NULL);
8696         if (!woperation) {
8697             PyErr_Clear();
8698             operation = NULL;
8699             goto normal;
8700         }
8701     }
8702 
8703     Py_BEGIN_ALLOW_THREADS
8704     rc = ShellExecuteW((HWND)0, woperation ? PyUnicode_AS_UNICODE(woperation) : 0,
8705         wpath,
8706         NULL, NULL, SW_SHOWNORMAL);
8707     Py_END_ALLOW_THREADS
8708 
8709     Py_XDECREF(woperation);
8710     if (rc <= (HINSTANCE)32) {
8711         PyObject *errval = win32_error_unicode("startfile", wpath);
8712         return errval;
8713     }
8714     Py_INCREF(Py_None);
8715     return Py_None;
8716 
8717 normal:
8718     if (!PyArg_ParseTuple(args, "et|s:startfile",
8719                           Py_FileSystemDefaultEncoding, &filepath,
8720                           &operation))
8721         return NULL;
8722     Py_BEGIN_ALLOW_THREADS
8723     rc = ShellExecute((HWND)0, operation, filepath,
8724                       NULL, NULL, SW_SHOWNORMAL);
8725     Py_END_ALLOW_THREADS
8726     if (rc <= (HINSTANCE)32) {
8727         PyObject *errval = win32_error("startfile", filepath);
8728         PyMem_Free(filepath);
8729         return errval;
8730     }
8731     PyMem_Free(filepath);
8732     Py_INCREF(Py_None);
8733     return Py_None;
8734 }
8735 #endif /* MS_WINDOWS */
8736 
8737 #ifdef HAVE_GETLOADAVG
8738 PyDoc_STRVAR(posix_getloadavg__doc__,
8739 "getloadavg() -> (float, float, float)\n\n\
8740 Return the number of processes in the system run queue averaged over\n\
8741 the last 1, 5, and 15 minutes or raises OSError if the load average\n\
8742 was unobtainable");
8743 
8744 static PyObject *
posix_getloadavg(PyObject * self,PyObject * noargs)8745 posix_getloadavg(PyObject *self, PyObject *noargs)
8746 {
8747     double loadavg[3];
8748     if (getloadavg(loadavg, 3)!=3) {
8749         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
8750         return NULL;
8751     } else
8752         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
8753 }
8754 #endif
8755 
8756 PyDoc_STRVAR(posix_urandom__doc__,
8757 "urandom(n) -> str\n\n\
8758 Return n random bytes suitable for cryptographic use.");
8759 
8760 static PyObject *
posix_urandom(PyObject * self,PyObject * args)8761 posix_urandom(PyObject *self, PyObject *args)
8762 {
8763     Py_ssize_t size;
8764     PyObject *result;
8765     int ret;
8766 
8767      /* Read arguments */
8768     if (!PyArg_ParseTuple(args, "n:urandom", &size))
8769         return NULL;
8770     if (size < 0)
8771         return PyErr_Format(PyExc_ValueError,
8772                             "negative argument not allowed");
8773     result = PyBytes_FromStringAndSize(NULL, size);
8774     if (result == NULL)
8775         return NULL;
8776 
8777     ret = _PyOS_URandom(PyBytes_AS_STRING(result),
8778                         PyBytes_GET_SIZE(result));
8779     if (ret == -1) {
8780         Py_DECREF(result);
8781         return NULL;
8782     }
8783     return result;
8784 }
8785 
8786 #ifdef HAVE_SETRESUID
8787 PyDoc_STRVAR(posix_setresuid__doc__,
8788 "setresuid(ruid, euid, suid)\n\n\
8789 Set the current process's real, effective, and saved user ids.");
8790 
8791 static PyObject*
posix_setresuid(PyObject * self,PyObject * args)8792 posix_setresuid (PyObject *self, PyObject *args)
8793 {
8794     uid_t ruid, euid, suid;
8795     if (!PyArg_ParseTuple(args, "O&O&O&:setresuid",
8796                           _Py_Uid_Converter, &ruid,
8797                           _Py_Uid_Converter, &euid,
8798                           _Py_Uid_Converter, &suid))
8799         return NULL;
8800     if (setresuid(ruid, euid, suid) < 0)
8801         return posix_error();
8802     Py_RETURN_NONE;
8803 }
8804 #endif
8805 
8806 #ifdef HAVE_SETRESGID
8807 PyDoc_STRVAR(posix_setresgid__doc__,
8808 "setresgid(rgid, egid, sgid)\n\n\
8809 Set the current process's real, effective, and saved group ids.");
8810 
8811 static PyObject*
posix_setresgid(PyObject * self,PyObject * args)8812 posix_setresgid (PyObject *self, PyObject *args)
8813 {
8814     gid_t rgid, egid, sgid;
8815     if (!PyArg_ParseTuple(args, "O&O&O&:setresgid",
8816                           _Py_Gid_Converter, &rgid,
8817                           _Py_Gid_Converter, &egid,
8818                           _Py_Gid_Converter, &sgid))
8819         return NULL;
8820     if (setresgid(rgid, egid, sgid) < 0)
8821         return posix_error();
8822     Py_RETURN_NONE;
8823 }
8824 #endif
8825 
8826 #ifdef HAVE_GETRESUID
8827 PyDoc_STRVAR(posix_getresuid__doc__,
8828 "getresuid() -> (ruid, euid, suid)\n\n\
8829 Get tuple of the current process's real, effective, and saved user ids.");
8830 
8831 static PyObject*
posix_getresuid(PyObject * self,PyObject * noargs)8832 posix_getresuid (PyObject *self, PyObject *noargs)
8833 {
8834     uid_t ruid, euid, suid;
8835     if (getresuid(&ruid, &euid, &suid) < 0)
8836         return posix_error();
8837     return Py_BuildValue("(NNN)", _PyInt_FromUid(ruid),
8838                                   _PyInt_FromUid(euid),
8839                                   _PyInt_FromUid(suid));
8840 }
8841 #endif
8842 
8843 #ifdef HAVE_GETRESGID
8844 PyDoc_STRVAR(posix_getresgid__doc__,
8845 "getresgid() -> (rgid, egid, sgid)\n\n\
8846 Get tuple of the current process's real, effective, and saved group ids.");
8847 
8848 static PyObject*
posix_getresgid(PyObject * self,PyObject * noargs)8849 posix_getresgid (PyObject *self, PyObject *noargs)
8850 {
8851     uid_t rgid, egid, sgid;
8852     if (getresgid(&rgid, &egid, &sgid) < 0)
8853         return posix_error();
8854     return Py_BuildValue("(NNN)", _PyInt_FromGid(rgid),
8855                                   _PyInt_FromGid(egid),
8856                                   _PyInt_FromGid(sgid));
8857 }
8858 #endif
8859 
8860 static PyMethodDef posix_methods[] = {
8861     {"access",          posix_access, METH_VARARGS, posix_access__doc__},
8862 #ifdef HAVE_TTYNAME
8863     {"ttyname",         posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
8864 #endif
8865     {"chdir",           posix_chdir, METH_VARARGS, posix_chdir__doc__},
8866 #ifdef HAVE_CHFLAGS
8867     {"chflags",         posix_chflags, METH_VARARGS, posix_chflags__doc__},
8868 #endif /* HAVE_CHFLAGS */
8869     {"chmod",           posix_chmod, METH_VARARGS, posix_chmod__doc__},
8870 #ifdef HAVE_FCHMOD
8871     {"fchmod",          posix_fchmod, METH_VARARGS, posix_fchmod__doc__},
8872 #endif /* HAVE_FCHMOD */
8873 #ifdef HAVE_CHOWN
8874     {"chown",           posix_chown, METH_VARARGS, posix_chown__doc__},
8875 #endif /* HAVE_CHOWN */
8876 #ifdef HAVE_LCHMOD
8877     {"lchmod",          posix_lchmod, METH_VARARGS, posix_lchmod__doc__},
8878 #endif /* HAVE_LCHMOD */
8879 #ifdef HAVE_FCHOWN
8880     {"fchown",          posix_fchown, METH_VARARGS, posix_fchown__doc__},
8881 #endif /* HAVE_FCHOWN */
8882 #ifdef HAVE_LCHFLAGS
8883     {"lchflags",        posix_lchflags, METH_VARARGS, posix_lchflags__doc__},
8884 #endif /* HAVE_LCHFLAGS */
8885 #ifdef HAVE_LCHOWN
8886     {"lchown",          posix_lchown, METH_VARARGS, posix_lchown__doc__},
8887 #endif /* HAVE_LCHOWN */
8888 #ifdef HAVE_CHROOT
8889     {"chroot",          posix_chroot, METH_VARARGS, posix_chroot__doc__},
8890 #endif
8891 #ifdef HAVE_CTERMID
8892     {"ctermid",         posix_ctermid, METH_NOARGS, posix_ctermid__doc__},
8893 #endif
8894 #ifdef HAVE_GETCWD
8895     {"getcwd",          posix_getcwd, METH_NOARGS, posix_getcwd__doc__},
8896 #ifdef Py_USING_UNICODE
8897     {"getcwdu",         posix_getcwdu, METH_NOARGS, posix_getcwdu__doc__},
8898 #endif
8899 #endif
8900 #ifdef HAVE_LINK
8901     {"link",            posix_link, METH_VARARGS, posix_link__doc__},
8902 #endif /* HAVE_LINK */
8903     {"listdir",         posix_listdir, METH_VARARGS, posix_listdir__doc__},
8904     {"lstat",           posix_lstat, METH_VARARGS, posix_lstat__doc__},
8905     {"mkdir",           posix_mkdir, METH_VARARGS, posix_mkdir__doc__},
8906 #ifdef HAVE_NICE
8907     {"nice",            posix_nice, METH_VARARGS, posix_nice__doc__},
8908 #endif /* HAVE_NICE */
8909 #ifdef HAVE_READLINK
8910     {"readlink",        posix_readlink, METH_VARARGS, posix_readlink__doc__},
8911 #endif /* HAVE_READLINK */
8912     {"rename",          posix_rename, METH_VARARGS, posix_rename__doc__},
8913     {"rmdir",           posix_rmdir, METH_VARARGS, posix_rmdir__doc__},
8914     {"stat",            posix_stat, METH_VARARGS, posix_stat__doc__},
8915     {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
8916 #ifdef HAVE_SYMLINK
8917     {"symlink",         posix_symlink, METH_VARARGS, posix_symlink__doc__},
8918 #endif /* HAVE_SYMLINK */
8919 #ifdef HAVE_SYSTEM
8920     {"system",          posix_system, METH_VARARGS, posix_system__doc__},
8921 #endif
8922     {"umask",           posix_umask, METH_VARARGS, posix_umask__doc__},
8923 #ifdef HAVE_UNAME
8924     {"uname",           posix_uname, METH_NOARGS, posix_uname__doc__},
8925 #endif /* HAVE_UNAME */
8926     {"unlink",          posix_unlink, METH_VARARGS, posix_unlink__doc__},
8927     {"remove",          posix_unlink, METH_VARARGS, posix_remove__doc__},
8928     {"utime",           posix_utime, METH_VARARGS, posix_utime__doc__},
8929 #ifdef HAVE_TIMES
8930     {"times",           posix_times, METH_NOARGS, posix_times__doc__},
8931 #endif /* HAVE_TIMES */
8932     {"_exit",           posix__exit, METH_VARARGS, posix__exit__doc__},
8933 #ifdef HAVE_EXECV
8934     {"execv",           posix_execv, METH_VARARGS, posix_execv__doc__},
8935     {"execve",          posix_execve, METH_VARARGS, posix_execve__doc__},
8936 #endif /* HAVE_EXECV */
8937 #ifdef HAVE_SPAWNV
8938     {"spawnv",          posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
8939     {"spawnve",         posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
8940 #if defined(PYOS_OS2)
8941     {"spawnvp",         posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__},
8942     {"spawnvpe",        posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__},
8943 #endif /* PYOS_OS2 */
8944 #endif /* HAVE_SPAWNV */
8945 #ifdef HAVE_FORK1
8946     {"fork1",       posix_fork1, METH_NOARGS, posix_fork1__doc__},
8947 #endif /* HAVE_FORK1 */
8948 #ifdef HAVE_FORK
8949     {"fork",            posix_fork, METH_NOARGS, posix_fork__doc__},
8950 #endif /* HAVE_FORK */
8951 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
8952     {"openpty",         posix_openpty, METH_NOARGS, posix_openpty__doc__},
8953 #endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
8954 #ifdef HAVE_FORKPTY
8955     {"forkpty",         posix_forkpty, METH_NOARGS, posix_forkpty__doc__},
8956 #endif /* HAVE_FORKPTY */
8957 #ifdef HAVE_GETEGID
8958     {"getegid",         posix_getegid, METH_NOARGS, posix_getegid__doc__},
8959 #endif /* HAVE_GETEGID */
8960 #ifdef HAVE_GETEUID
8961     {"geteuid",         posix_geteuid, METH_NOARGS, posix_geteuid__doc__},
8962 #endif /* HAVE_GETEUID */
8963 #ifdef HAVE_GETGID
8964     {"getgid",          posix_getgid, METH_NOARGS, posix_getgid__doc__},
8965 #endif /* HAVE_GETGID */
8966 #ifdef HAVE_GETGROUPS
8967     {"getgroups",       posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
8968 #endif
8969     {"getpid",          posix_getpid, METH_NOARGS, posix_getpid__doc__},
8970 #ifdef HAVE_GETPGRP
8971     {"getpgrp",         posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__},
8972 #endif /* HAVE_GETPGRP */
8973 #ifdef HAVE_GETPPID
8974     {"getppid",         posix_getppid, METH_NOARGS, posix_getppid__doc__},
8975 #endif /* HAVE_GETPPID */
8976 #ifdef HAVE_GETUID
8977     {"getuid",          posix_getuid, METH_NOARGS, posix_getuid__doc__},
8978 #endif /* HAVE_GETUID */
8979 #ifdef HAVE_GETLOGIN
8980     {"getlogin",        posix_getlogin, METH_NOARGS, posix_getlogin__doc__},
8981 #endif
8982 #ifdef HAVE_KILL
8983     {"kill",            posix_kill, METH_VARARGS, posix_kill__doc__},
8984 #endif /* HAVE_KILL */
8985 #ifdef HAVE_KILLPG
8986     {"killpg",          posix_killpg, METH_VARARGS, posix_killpg__doc__},
8987 #endif /* HAVE_KILLPG */
8988 #ifdef HAVE_PLOCK
8989     {"plock",           posix_plock, METH_VARARGS, posix_plock__doc__},
8990 #endif /* HAVE_PLOCK */
8991 #ifdef HAVE_POPEN
8992     {"popen",           posix_popen, METH_VARARGS, posix_popen__doc__},
8993 #ifdef MS_WINDOWS
8994     {"popen2",          win32_popen2, METH_VARARGS},
8995     {"popen3",          win32_popen3, METH_VARARGS},
8996     {"popen4",          win32_popen4, METH_VARARGS},
8997     {"startfile",       win32_startfile, METH_VARARGS, win32_startfile__doc__},
8998     {"kill",    win32_kill, METH_VARARGS, win32_kill__doc__},
8999 #else
9000 #if defined(PYOS_OS2) && defined(PYCC_GCC)
9001     {"popen2",          os2emx_popen2, METH_VARARGS},
9002     {"popen3",          os2emx_popen3, METH_VARARGS},
9003     {"popen4",          os2emx_popen4, METH_VARARGS},
9004 #endif
9005 #endif
9006 #endif /* HAVE_POPEN */
9007 #ifdef HAVE_SETUID
9008     {"setuid",          posix_setuid, METH_VARARGS, posix_setuid__doc__},
9009 #endif /* HAVE_SETUID */
9010 #ifdef HAVE_SETEUID
9011     {"seteuid",         posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
9012 #endif /* HAVE_SETEUID */
9013 #ifdef HAVE_SETEGID
9014     {"setegid",         posix_setegid, METH_VARARGS, posix_setegid__doc__},
9015 #endif /* HAVE_SETEGID */
9016 #ifdef HAVE_SETREUID
9017     {"setreuid",        posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
9018 #endif /* HAVE_SETREUID */
9019 #ifdef HAVE_SETREGID
9020     {"setregid",        posix_setregid, METH_VARARGS, posix_setregid__doc__},
9021 #endif /* HAVE_SETREGID */
9022 #ifdef HAVE_SETGID
9023     {"setgid",          posix_setgid, METH_VARARGS, posix_setgid__doc__},
9024 #endif /* HAVE_SETGID */
9025 #ifdef HAVE_SETGROUPS
9026     {"setgroups",       posix_setgroups, METH_O, posix_setgroups__doc__},
9027 #endif /* HAVE_SETGROUPS */
9028 #ifdef HAVE_INITGROUPS
9029     {"initgroups",      posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
9030 #endif /* HAVE_INITGROUPS */
9031 #ifdef HAVE_GETPGID
9032     {"getpgid",         posix_getpgid, METH_VARARGS, posix_getpgid__doc__},
9033 #endif /* HAVE_GETPGID */
9034 #ifdef HAVE_SETPGRP
9035     {"setpgrp",         posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__},
9036 #endif /* HAVE_SETPGRP */
9037 #ifdef HAVE_WAIT
9038     {"wait",            posix_wait, METH_NOARGS, posix_wait__doc__},
9039 #endif /* HAVE_WAIT */
9040 #ifdef HAVE_WAIT3
9041     {"wait3",           posix_wait3, METH_VARARGS, posix_wait3__doc__},
9042 #endif /* HAVE_WAIT3 */
9043 #ifdef HAVE_WAIT4
9044     {"wait4",           posix_wait4, METH_VARARGS, posix_wait4__doc__},
9045 #endif /* HAVE_WAIT4 */
9046 #if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
9047     {"waitpid",         posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
9048 #endif /* HAVE_WAITPID */
9049 #ifdef HAVE_GETSID
9050     {"getsid",          posix_getsid, METH_VARARGS, posix_getsid__doc__},
9051 #endif /* HAVE_GETSID */
9052 #ifdef HAVE_SETSID
9053     {"setsid",          posix_setsid, METH_NOARGS, posix_setsid__doc__},
9054 #endif /* HAVE_SETSID */
9055 #ifdef HAVE_SETPGID
9056     {"setpgid",         posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
9057 #endif /* HAVE_SETPGID */
9058 #ifdef HAVE_TCGETPGRP
9059     {"tcgetpgrp",       posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
9060 #endif /* HAVE_TCGETPGRP */
9061 #ifdef HAVE_TCSETPGRP
9062     {"tcsetpgrp",       posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
9063 #endif /* HAVE_TCSETPGRP */
9064     {"open",            posix_open, METH_VARARGS, posix_open__doc__},
9065     {"close",           posix_close_, METH_VARARGS, posix_close__doc__},
9066     {"closerange",      posix_closerange, METH_VARARGS, posix_closerange__doc__},
9067     {"dup",             posix_dup, METH_VARARGS, posix_dup__doc__},
9068     {"dup2",            posix_dup2, METH_VARARGS, posix_dup2__doc__},
9069     {"lseek",           posix_lseek, METH_VARARGS, posix_lseek__doc__},
9070     {"read",            posix_read, METH_VARARGS, posix_read__doc__},
9071     {"write",           posix_write, METH_VARARGS, posix_write__doc__},
9072     {"fstat",           posix_fstat, METH_VARARGS, posix_fstat__doc__},
9073     {"fdopen",          posix_fdopen, METH_VARARGS, posix_fdopen__doc__},
9074     {"isatty",          posix_isatty, METH_VARARGS, posix_isatty__doc__},
9075 #ifdef HAVE_PIPE
9076     {"pipe",            posix_pipe, METH_NOARGS, posix_pipe__doc__},
9077 #endif
9078 #ifdef HAVE_MKFIFO
9079     {"mkfifo",          posix_mkfifo, METH_VARARGS, posix_mkfifo__doc__},
9080 #endif
9081 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
9082     {"mknod",           posix_mknod, METH_VARARGS, posix_mknod__doc__},
9083 #endif
9084 #ifdef HAVE_DEVICE_MACROS
9085     {"major",           posix_major, METH_VARARGS, posix_major__doc__},
9086     {"minor",           posix_minor, METH_VARARGS, posix_minor__doc__},
9087     {"makedev",         posix_makedev, METH_VARARGS, posix_makedev__doc__},
9088 #endif
9089 #ifdef HAVE_FTRUNCATE
9090     {"ftruncate",       posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
9091 #endif
9092 #ifdef HAVE_PUTENV
9093     {"putenv",          posix_putenv, METH_VARARGS, posix_putenv__doc__},
9094 #endif
9095 #ifdef HAVE_UNSETENV
9096     {"unsetenv",        posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__},
9097 #endif
9098     {"strerror",        posix_strerror, METH_VARARGS, posix_strerror__doc__},
9099 #ifdef HAVE_FCHDIR
9100     {"fchdir",          posix_fchdir, METH_O, posix_fchdir__doc__},
9101 #endif
9102 #ifdef HAVE_FSYNC
9103     {"fsync",       posix_fsync, METH_O, posix_fsync__doc__},
9104 #endif
9105 #ifdef HAVE_FDATASYNC
9106     {"fdatasync",   posix_fdatasync,  METH_O, posix_fdatasync__doc__},
9107 #endif
9108 #ifdef HAVE_SYS_WAIT_H
9109 #ifdef WCOREDUMP
9110     {"WCOREDUMP",       posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__},
9111 #endif /* WCOREDUMP */
9112 #ifdef WIFCONTINUED
9113     {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__},
9114 #endif /* WIFCONTINUED */
9115 #ifdef WIFSTOPPED
9116     {"WIFSTOPPED",      posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
9117 #endif /* WIFSTOPPED */
9118 #ifdef WIFSIGNALED
9119     {"WIFSIGNALED",     posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
9120 #endif /* WIFSIGNALED */
9121 #ifdef WIFEXITED
9122     {"WIFEXITED",       posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
9123 #endif /* WIFEXITED */
9124 #ifdef WEXITSTATUS
9125     {"WEXITSTATUS",     posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
9126 #endif /* WEXITSTATUS */
9127 #ifdef WTERMSIG
9128     {"WTERMSIG",        posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
9129 #endif /* WTERMSIG */
9130 #ifdef WSTOPSIG
9131     {"WSTOPSIG",        posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
9132 #endif /* WSTOPSIG */
9133 #endif /* HAVE_SYS_WAIT_H */
9134 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
9135     {"fstatvfs",        posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
9136 #endif
9137 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
9138     {"statvfs",         posix_statvfs, METH_VARARGS, posix_statvfs__doc__},
9139 #endif
9140 #ifdef HAVE_TMPFILE
9141     {"tmpfile",         posix_tmpfile, METH_NOARGS, posix_tmpfile__doc__},
9142 #endif
9143 #ifdef HAVE_TEMPNAM
9144     {"tempnam",         posix_tempnam, METH_VARARGS, posix_tempnam__doc__},
9145 #endif
9146 #ifdef HAVE_TMPNAM
9147     {"tmpnam",          posix_tmpnam, METH_NOARGS, posix_tmpnam__doc__},
9148 #endif
9149 #ifdef HAVE_CONFSTR
9150     {"confstr",         posix_confstr, METH_VARARGS, posix_confstr__doc__},
9151 #endif
9152 #ifdef HAVE_SYSCONF
9153     {"sysconf",         posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
9154 #endif
9155 #ifdef HAVE_FPATHCONF
9156     {"fpathconf",       posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
9157 #endif
9158 #ifdef HAVE_PATHCONF
9159     {"pathconf",        posix_pathconf, METH_VARARGS, posix_pathconf__doc__},
9160 #endif
9161     {"abort",           posix_abort, METH_NOARGS, posix_abort__doc__},
9162 #ifdef MS_WINDOWS
9163     {"_getfullpathname",        posix__getfullpathname, METH_VARARGS, NULL},
9164     {"_isdir",                  posix__isdir, METH_VARARGS, posix__isdir__doc__},
9165 #endif
9166 #ifdef HAVE_GETLOADAVG
9167     {"getloadavg",      posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__},
9168 #endif
9169 #ifdef HAVE_SETRESUID
9170     {"setresuid",       posix_setresuid, METH_VARARGS, posix_setresuid__doc__},
9171 #endif
9172 #ifdef HAVE_SETRESGID
9173     {"setresgid",       posix_setresgid, METH_VARARGS, posix_setresgid__doc__},
9174 #endif
9175 #ifdef HAVE_GETRESUID
9176     {"getresuid",       posix_getresuid, METH_NOARGS, posix_getresuid__doc__},
9177 #endif
9178 #ifdef HAVE_GETRESGID
9179     {"getresgid",       posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
9180 #endif
9181     {"urandom",         posix_urandom,   METH_VARARGS, posix_urandom__doc__},
9182     {NULL,              NULL}            /* Sentinel */
9183 };
9184 
9185 
9186 static int
ins(PyObject * module,char * symbol,long value)9187 ins(PyObject *module, char *symbol, long value)
9188 {
9189     return PyModule_AddIntConstant(module, symbol, value);
9190 }
9191 
9192 #if defined(PYOS_OS2)
9193 /* Insert Platform-Specific Constant Values (Strings & Numbers) of Common Use */
insertvalues(PyObject * module)9194 static int insertvalues(PyObject *module)
9195 {
9196     APIRET    rc;
9197     ULONG     values[QSV_MAX+1];
9198     PyObject *v;
9199     char     *ver, tmp[50];
9200 
9201     Py_BEGIN_ALLOW_THREADS
9202     rc = DosQuerySysInfo(1L, QSV_MAX, &values[1], sizeof(ULONG) * QSV_MAX);
9203     Py_END_ALLOW_THREADS
9204 
9205     if (rc != NO_ERROR) {
9206         os2_error(rc);
9207         return -1;
9208     }
9209 
9210     if (ins(module, "meminstalled", values[QSV_TOTPHYSMEM])) return -1;
9211     if (ins(module, "memkernel",    values[QSV_TOTRESMEM])) return -1;
9212     if (ins(module, "memvirtual",   values[QSV_TOTAVAILMEM])) return -1;
9213     if (ins(module, "maxpathlen",   values[QSV_MAX_PATH_LENGTH])) return -1;
9214     if (ins(module, "maxnamelen",   values[QSV_MAX_COMP_LENGTH])) return -1;
9215     if (ins(module, "revision",     values[QSV_VERSION_REVISION])) return -1;
9216     if (ins(module, "timeslice",    values[QSV_MIN_SLICE])) return -1;
9217 
9218     switch (values[QSV_VERSION_MINOR]) {
9219     case 0:  ver = "2.00"; break;
9220     case 10: ver = "2.10"; break;
9221     case 11: ver = "2.11"; break;
9222     case 30: ver = "3.00"; break;
9223     case 40: ver = "4.00"; break;
9224     case 50: ver = "5.00"; break;
9225     default:
9226         PyOS_snprintf(tmp, sizeof(tmp),
9227                       "%d-%d", values[QSV_VERSION_MAJOR],
9228                       values[QSV_VERSION_MINOR]);
9229         ver = &tmp[0];
9230     }
9231 
9232     /* Add Indicator of the Version of the Operating System */
9233     if (PyModule_AddStringConstant(module, "version", tmp) < 0)
9234         return -1;
9235 
9236     /* Add Indicator of Which Drive was Used to Boot the System */
9237     tmp[0] = 'A' + values[QSV_BOOT_DRIVE] - 1;
9238     tmp[1] = ':';
9239     tmp[2] = '\0';
9240 
9241     return PyModule_AddStringConstant(module, "bootdrive", tmp);
9242 }
9243 #endif
9244 
9245 static int
all_ins(PyObject * d)9246 all_ins(PyObject *d)
9247 {
9248 #ifdef F_OK
9249     if (ins(d, "F_OK", (long)F_OK)) return -1;
9250 #endif
9251 #ifdef R_OK
9252     if (ins(d, "R_OK", (long)R_OK)) return -1;
9253 #endif
9254 #ifdef W_OK
9255     if (ins(d, "W_OK", (long)W_OK)) return -1;
9256 #endif
9257 #ifdef X_OK
9258     if (ins(d, "X_OK", (long)X_OK)) return -1;
9259 #endif
9260 #ifdef NGROUPS_MAX
9261     if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
9262 #endif
9263 #ifdef TMP_MAX
9264     if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
9265 #endif
9266 #ifdef WCONTINUED
9267     if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
9268 #endif
9269 #ifdef WNOHANG
9270     if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
9271 #endif
9272 #ifdef WUNTRACED
9273     if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
9274 #endif
9275 #ifdef O_RDONLY
9276     if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
9277 #endif
9278 #ifdef O_WRONLY
9279     if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
9280 #endif
9281 #ifdef O_RDWR
9282     if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
9283 #endif
9284 #ifdef O_NDELAY
9285     if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
9286 #endif
9287 #ifdef O_NONBLOCK
9288     if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
9289 #endif
9290 #ifdef O_APPEND
9291     if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
9292 #endif
9293 #ifdef O_DSYNC
9294     if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
9295 #endif
9296 #ifdef O_RSYNC
9297     if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
9298 #endif
9299 #ifdef O_SYNC
9300     if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
9301 #endif
9302 #ifdef O_NOCTTY
9303     if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
9304 #endif
9305 #ifdef O_CREAT
9306     if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
9307 #endif
9308 #ifdef O_EXCL
9309     if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
9310 #endif
9311 #ifdef O_TRUNC
9312     if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
9313 #endif
9314 #ifdef O_BINARY
9315     if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
9316 #endif
9317 #ifdef O_TEXT
9318     if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
9319 #endif
9320 #ifdef O_LARGEFILE
9321     if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
9322 #endif
9323 #ifdef O_SHLOCK
9324     if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
9325 #endif
9326 #ifdef O_EXLOCK
9327     if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
9328 #endif
9329 
9330 /* MS Windows */
9331 #ifdef O_NOINHERIT
9332     /* Don't inherit in child processes. */
9333     if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
9334 #endif
9335 #ifdef _O_SHORT_LIVED
9336     /* Optimize for short life (keep in memory). */
9337     /* MS forgot to define this one with a non-underscore form too. */
9338     if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
9339 #endif
9340 #ifdef O_TEMPORARY
9341     /* Automatically delete when last handle is closed. */
9342     if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
9343 #endif
9344 #ifdef O_RANDOM
9345     /* Optimize for random access. */
9346     if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
9347 #endif
9348 #ifdef O_SEQUENTIAL
9349     /* Optimize for sequential access. */
9350     if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
9351 #endif
9352 
9353 /* GNU extensions. */
9354 #ifdef O_ASYNC
9355     /* Send a SIGIO signal whenever input or output
9356        becomes available on file descriptor */
9357     if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1;
9358 #endif
9359 #ifdef O_DIRECT
9360     /* Direct disk access. */
9361     if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
9362 #endif
9363 #ifdef O_DIRECTORY
9364     /* Must be a directory.      */
9365     if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
9366 #endif
9367 #ifdef O_NOFOLLOW
9368     /* Do not follow links.      */
9369     if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
9370 #endif
9371 #ifdef O_NOATIME
9372     /* Do not update the access time. */
9373     if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1;
9374 #endif
9375 
9376     /* These come from sysexits.h */
9377 #ifdef EX_OK
9378     if (ins(d, "EX_OK", (long)EX_OK)) return -1;
9379 #endif /* EX_OK */
9380 #ifdef EX_USAGE
9381     if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
9382 #endif /* EX_USAGE */
9383 #ifdef EX_DATAERR
9384     if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
9385 #endif /* EX_DATAERR */
9386 #ifdef EX_NOINPUT
9387     if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
9388 #endif /* EX_NOINPUT */
9389 #ifdef EX_NOUSER
9390     if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
9391 #endif /* EX_NOUSER */
9392 #ifdef EX_NOHOST
9393     if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
9394 #endif /* EX_NOHOST */
9395 #ifdef EX_UNAVAILABLE
9396     if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
9397 #endif /* EX_UNAVAILABLE */
9398 #ifdef EX_SOFTWARE
9399     if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
9400 #endif /* EX_SOFTWARE */
9401 #ifdef EX_OSERR
9402     if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
9403 #endif /* EX_OSERR */
9404 #ifdef EX_OSFILE
9405     if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
9406 #endif /* EX_OSFILE */
9407 #ifdef EX_CANTCREAT
9408     if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
9409 #endif /* EX_CANTCREAT */
9410 #ifdef EX_IOERR
9411     if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
9412 #endif /* EX_IOERR */
9413 #ifdef EX_TEMPFAIL
9414     if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
9415 #endif /* EX_TEMPFAIL */
9416 #ifdef EX_PROTOCOL
9417     if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
9418 #endif /* EX_PROTOCOL */
9419 #ifdef EX_NOPERM
9420     if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
9421 #endif /* EX_NOPERM */
9422 #ifdef EX_CONFIG
9423     if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
9424 #endif /* EX_CONFIG */
9425 #ifdef EX_NOTFOUND
9426     if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
9427 #endif /* EX_NOTFOUND */
9428 
9429 #ifdef HAVE_SPAWNV
9430 #if defined(PYOS_OS2) && defined(PYCC_GCC)
9431     if (ins(d, "P_WAIT", (long)P_WAIT)) return -1;
9432     if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1;
9433     if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1;
9434     if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1;
9435     if (ins(d, "P_SESSION", (long)P_SESSION)) return -1;
9436     if (ins(d, "P_DETACH", (long)P_DETACH)) return -1;
9437     if (ins(d, "P_PM", (long)P_PM)) return -1;
9438     if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1;
9439     if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1;
9440     if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1;
9441     if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1;
9442     if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1;
9443     if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1;
9444     if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1;
9445     if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1;
9446     if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1;
9447     if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1;
9448     if (ins(d, "P_TILDE", (long)P_TILDE)) return -1;
9449     if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1;
9450     if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1;
9451 #else
9452     if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
9453     if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
9454     if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
9455     if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
9456     if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
9457 #endif
9458 #endif
9459 
9460 #if defined(PYOS_OS2)
9461     if (insertvalues(d)) return -1;
9462 #endif
9463     return 0;
9464 }
9465 
9466 
9467 #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__)) && !defined(__QNX__)
9468 #define INITFUNC initnt
9469 #define MODNAME "nt"
9470 
9471 #elif defined(PYOS_OS2)
9472 #define INITFUNC initos2
9473 #define MODNAME "os2"
9474 
9475 #else
9476 #define INITFUNC initposix
9477 #define MODNAME "posix"
9478 #endif
9479 
9480 PyMODINIT_FUNC
INITFUNC(void)9481 INITFUNC(void)
9482 {
9483     PyObject *m, *v;
9484 
9485     m = Py_InitModule3(MODNAME,
9486                        posix_methods,
9487                        posix__doc__);
9488     if (m == NULL)
9489         return;
9490 
9491     /* Initialize environ dictionary */
9492     v = convertenviron();
9493     Py_XINCREF(v);
9494     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
9495         return;
9496     Py_DECREF(v);
9497 
9498     if (all_ins(m))
9499         return;
9500 
9501     if (setup_confname_tables(m))
9502         return;
9503 
9504     Py_INCREF(PyExc_OSError);
9505     PyModule_AddObject(m, "error", PyExc_OSError);
9506 
9507 #ifdef HAVE_PUTENV
9508     if (posix_putenv_garbage == NULL)
9509         posix_putenv_garbage = PyDict_New();
9510 #endif
9511 
9512     if (!initialized) {
9513         stat_result_desc.name = MODNAME ".stat_result";
9514         stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
9515         stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
9516         stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
9517         PyStructSequence_InitType(&StatResultType, &stat_result_desc);
9518         structseq_new = StatResultType.tp_new;
9519         StatResultType.tp_new = statresult_new;
9520 
9521         statvfs_result_desc.name = MODNAME ".statvfs_result";
9522         PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
9523 #ifdef NEED_TICKS_PER_SECOND
9524 #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
9525         ticks_per_second = sysconf(_SC_CLK_TCK);
9526 #  elif defined(HZ)
9527         ticks_per_second = HZ;
9528 #  else
9529         ticks_per_second = 60; /* magic fallback value; may be bogus */
9530 #  endif
9531 #endif
9532     }
9533     Py_INCREF((PyObject*) &StatResultType);
9534     PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
9535     Py_INCREF((PyObject*) &StatVFSResultType);
9536     PyModule_AddObject(m, "statvfs_result",
9537                        (PyObject*) &StatVFSResultType);
9538     initialized = 1;
9539 
9540 #ifdef __APPLE__
9541     /*
9542      * Step 2 of weak-linking support on Mac OS X.
9543      *
9544      * The code below removes functions that are not available on the
9545      * currently active platform.
9546      *
9547      * This block allow one to use a python binary that was build on
9548      * OSX 10.4 on OSX 10.3, without loosing access to new APIs on
9549      * OSX 10.4.
9550      */
9551 #ifdef HAVE_FSTATVFS
9552     if (fstatvfs == NULL) {
9553         if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
9554             return;
9555         }
9556     }
9557 #endif /* HAVE_FSTATVFS */
9558 
9559 #ifdef HAVE_STATVFS
9560     if (statvfs == NULL) {
9561         if (PyObject_DelAttrString(m, "statvfs") == -1) {
9562             return;
9563         }
9564     }
9565 #endif /* HAVE_STATVFS */
9566 
9567 # ifdef HAVE_LCHOWN
9568     if (lchown == NULL) {
9569         if (PyObject_DelAttrString(m, "lchown") == -1) {
9570             return;
9571         }
9572     }
9573 #endif /* HAVE_LCHOWN */
9574 
9575 
9576 #endif /* __APPLE__ */
9577 
9578 }
9579 
9580 #ifdef __cplusplus
9581 }
9582 #endif
9583 
9584 
9585