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