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