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