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