]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Efi/edk2module.c
0f1c7fe3d1391b75594a4017e65ee83ef56d310b
[mirror_edk2.git] / AppPkg / Applications / Python / Efi / edk2module.c
1 /** @file
2 OS-specific module implementation for EDK II and UEFI.
3 Derived from posixmodule.c in Python 2.7.2.
4
5 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8 #define PY_SSIZE_T_CLEAN
9
10 #include "Python.h"
11 #include "structseq.h"
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <wchar.h>
16 #include <sys/syslimits.h>
17
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21
22 PyDoc_STRVAR(edk2__doc__,
23 "This module provides access to UEFI firmware functionality that is\n\
24 standardized by the C Standard and the POSIX standard (a thinly\n\
25 disguised Unix interface). Refer to the library manual and\n\
26 corresponding UEFI Specification entries for more information on calls.");
27
28 #ifndef Py_USING_UNICODE
29 /* This is used in signatures of functions. */
30 #define Py_UNICODE void
31 #endif
32
33 #ifdef HAVE_SYS_TYPES_H
34 #include <sys/types.h>
35 #endif /* HAVE_SYS_TYPES_H */
36
37 #ifdef HAVE_SYS_STAT_H
38 #include <sys/stat.h>
39 #endif /* HAVE_SYS_STAT_H */
40
41 #ifdef HAVE_SYS_WAIT_H
42 #include <sys/wait.h> /* For WNOHANG */
43 #endif
44
45 #ifdef HAVE_SIGNAL_H
46 #include <signal.h>
47 #endif
48
49 #ifdef HAVE_FCNTL_H
50 #include <fcntl.h>
51 #endif /* HAVE_FCNTL_H */
52
53 #ifdef HAVE_GRP_H
54 #include <grp.h>
55 #endif
56
57 #ifdef HAVE_SYSEXITS_H
58 #include <sysexits.h>
59 #endif /* HAVE_SYSEXITS_H */
60
61 #ifdef HAVE_SYS_LOADAVG_H
62 #include <sys/loadavg.h>
63 #endif
64
65 #ifdef HAVE_UTIME_H
66 #include <utime.h>
67 #endif /* HAVE_UTIME_H */
68
69 #ifdef HAVE_SYS_UTIME_H
70 #include <sys/utime.h>
71 #define HAVE_UTIME_H /* pretend we do for the rest of this file */
72 #endif /* HAVE_SYS_UTIME_H */
73
74 #ifdef HAVE_SYS_TIMES_H
75 #include <sys/times.h>
76 #endif /* HAVE_SYS_TIMES_H */
77
78 #ifdef HAVE_SYS_PARAM_H
79 #include <sys/param.h>
80 #endif /* HAVE_SYS_PARAM_H */
81
82 #ifdef HAVE_SYS_UTSNAME_H
83 #include <sys/utsname.h>
84 #endif /* HAVE_SYS_UTSNAME_H */
85
86 #ifdef HAVE_DIRENT_H
87 #include <dirent.h>
88 #define NAMLEN(dirent) wcslen((dirent)->FileName)
89 #else
90 #define dirent direct
91 #define NAMLEN(dirent) (dirent)->d_namlen
92 #ifdef HAVE_SYS_NDIR_H
93 #include <sys/ndir.h>
94 #endif
95 #ifdef HAVE_SYS_DIR_H
96 #include <sys/dir.h>
97 #endif
98 #ifdef HAVE_NDIR_H
99 #include <ndir.h>
100 #endif
101 #endif
102
103 #ifndef MAXPATHLEN
104 #if defined(PATH_MAX) && PATH_MAX > 1024
105 #define MAXPATHLEN PATH_MAX
106 #else
107 #define MAXPATHLEN 1024
108 #endif
109 #endif /* MAXPATHLEN */
110
111 #define WAIT_TYPE int
112 #define WAIT_STATUS_INT(s) (s)
113
114 /* Issue #1983: pid_t can be longer than a C long on some systems */
115 #if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT
116 #define PARSE_PID "i"
117 #define PyLong_FromPid PyInt_FromLong
118 #define PyLong_AsPid PyInt_AsLong
119 #elif SIZEOF_PID_T == SIZEOF_LONG
120 #define PARSE_PID "l"
121 #define PyLong_FromPid PyInt_FromLong
122 #define PyLong_AsPid PyInt_AsLong
123 #elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG
124 #define PARSE_PID "L"
125 #define PyLong_FromPid PyLong_FromLongLong
126 #define PyLong_AsPid PyInt_AsLongLong
127 #else
128 #error "sizeof(pid_t) is neither sizeof(int), sizeof(long) or sizeof(long long)"
129 #endif /* SIZEOF_PID_T */
130
131 /* Don't use the "_r" form if we don't need it (also, won't have a
132 prototype for it, at least on Solaris -- maybe others as well?). */
133 #if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
134 #define USE_CTERMID_R
135 #endif
136
137 #if defined(HAVE_TMPNAM_R) && defined(WITH_THREAD)
138 #define USE_TMPNAM_R
139 #endif
140
141 /* choose the appropriate stat and fstat functions and return structs */
142 #undef STAT
143 #undef FSTAT
144 #undef STRUCT_STAT
145 #define STAT stat
146 #define FSTAT fstat
147 #define STRUCT_STAT struct stat
148
149 /* dummy version. _PyVerify_fd() is already defined in fileobject.h */
150 #define _PyVerify_fd_dup2(A, B) (1)
151
152 #ifndef UEFI_C_SOURCE
153 /* Return a dictionary corresponding to the POSIX environment table */
154 extern char **environ;
155
156 static PyObject *
157 convertenviron(void)
158 {
159 PyObject *d;
160 char **e;
161 d = PyDict_New();
162 if (d == NULL)
163 return NULL;
164 if (environ == NULL)
165 return d;
166 /* This part ignores errors */
167 for (e = environ; *e != NULL; e++) {
168 PyObject *k;
169 PyObject *v;
170 char *p = strchr(*e, '=');
171 if (p == NULL)
172 continue;
173 k = PyString_FromStringAndSize(*e, (int)(p-*e));
174 if (k == NULL) {
175 PyErr_Clear();
176 continue;
177 }
178 v = PyString_FromString(p+1);
179 if (v == NULL) {
180 PyErr_Clear();
181 Py_DECREF(k);
182 continue;
183 }
184 if (PyDict_GetItem(d, k) == NULL) {
185 if (PyDict_SetItem(d, k, v) != 0)
186 PyErr_Clear();
187 }
188 Py_DECREF(k);
189 Py_DECREF(v);
190 }
191 return d;
192 }
193 #endif /* UEFI_C_SOURCE */
194
195 /* Set a POSIX-specific error from errno, and return NULL */
196
197 static PyObject *
198 posix_error(void)
199 {
200 return PyErr_SetFromErrno(PyExc_OSError);
201 }
202 static PyObject *
203 posix_error_with_filename(char* name)
204 {
205 return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
206 }
207
208
209 static PyObject *
210 posix_error_with_allocated_filename(char* name)
211 {
212 PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
213 PyMem_Free(name);
214 return rc;
215 }
216
217 /* POSIX generic methods */
218
219 #ifndef UEFI_C_SOURCE
220 static PyObject *
221 posix_fildes(PyObject *fdobj, int (*func)(int))
222 {
223 int fd;
224 int res;
225 fd = PyObject_AsFileDescriptor(fdobj);
226 if (fd < 0)
227 return NULL;
228 if (!_PyVerify_fd(fd))
229 return posix_error();
230 Py_BEGIN_ALLOW_THREADS
231 res = (*func)(fd);
232 Py_END_ALLOW_THREADS
233 if (res < 0)
234 return posix_error();
235 Py_INCREF(Py_None);
236 return Py_None;
237 }
238 #endif /* UEFI_C_SOURCE */
239
240 static PyObject *
241 posix_1str(PyObject *args, char *format, int (*func)(const char*))
242 {
243 char *path1 = NULL;
244 int res;
245 if (!PyArg_ParseTuple(args, format,
246 Py_FileSystemDefaultEncoding, &path1))
247 return NULL;
248 Py_BEGIN_ALLOW_THREADS
249 res = (*func)(path1);
250 Py_END_ALLOW_THREADS
251 if (res < 0)
252 return posix_error_with_allocated_filename(path1);
253 PyMem_Free(path1);
254 Py_INCREF(Py_None);
255 return Py_None;
256 }
257
258 static PyObject *
259 posix_2str(PyObject *args,
260 char *format,
261 int (*func)(const char *, const char *))
262 {
263 char *path1 = NULL, *path2 = NULL;
264 int res;
265 if (!PyArg_ParseTuple(args, format,
266 Py_FileSystemDefaultEncoding, &path1,
267 Py_FileSystemDefaultEncoding, &path2))
268 return NULL;
269 Py_BEGIN_ALLOW_THREADS
270 res = (*func)(path1, path2);
271 Py_END_ALLOW_THREADS
272 PyMem_Free(path1);
273 PyMem_Free(path2);
274 if (res != 0)
275 /* XXX how to report both path1 and path2??? */
276 return posix_error();
277 Py_INCREF(Py_None);
278 return Py_None;
279 }
280
281 PyDoc_STRVAR(stat_result__doc__,
282 "stat_result: Result from stat or lstat.\n\n\
283 This object may be accessed either as a tuple of\n\
284 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
285 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
286 \n\
287 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
288 or st_flags, they are available as attributes only.\n\
289 \n\
290 See os.stat for more information.");
291
292 static PyStructSequence_Field stat_result_fields[] = {
293 {"st_mode", "protection bits"},
294 //{"st_ino", "inode"},
295 //{"st_dev", "device"},
296 //{"st_nlink", "number of hard links"},
297 //{"st_uid", "user ID of owner"},
298 //{"st_gid", "group ID of owner"},
299 {"st_size", "total size, in bytes"},
300 /* The NULL is replaced with PyStructSequence_UnnamedField later. */
301 {NULL, "integer time of last access"},
302 {NULL, "integer time of last modification"},
303 {NULL, "integer time of last change"},
304 {"st_atime", "time of last access"},
305 {"st_mtime", "time of last modification"},
306 {"st_ctime", "time of last change"},
307 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
308 {"st_blksize", "blocksize for filesystem I/O"},
309 #endif
310 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
311 {"st_blocks", "number of blocks allocated"},
312 #endif
313 #ifdef HAVE_STRUCT_STAT_ST_RDEV
314 {"st_rdev", "device type (if inode device)"},
315 #endif
316 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
317 {"st_flags", "user defined flags for file"},
318 #endif
319 #ifdef HAVE_STRUCT_STAT_ST_GEN
320 {"st_gen", "generation number"},
321 #endif
322 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
323 {"st_birthtime", "time of creation"},
324 #endif
325 {0}
326 };
327
328 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
329 #define ST_BLKSIZE_IDX 8
330 #else
331 #define ST_BLKSIZE_IDX 12
332 #endif
333
334 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
335 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
336 #else
337 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
338 #endif
339
340 #ifdef HAVE_STRUCT_STAT_ST_RDEV
341 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
342 #else
343 #define ST_RDEV_IDX ST_BLOCKS_IDX
344 #endif
345
346 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
347 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
348 #else
349 #define ST_FLAGS_IDX ST_RDEV_IDX
350 #endif
351
352 #ifdef HAVE_STRUCT_STAT_ST_GEN
353 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
354 #else
355 #define ST_GEN_IDX ST_FLAGS_IDX
356 #endif
357
358 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
359 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
360 #else
361 #define ST_BIRTHTIME_IDX ST_GEN_IDX
362 #endif
363
364 static PyStructSequence_Desc stat_result_desc = {
365 "stat_result", /* name */
366 stat_result__doc__, /* doc */
367 stat_result_fields,
368 10
369 };
370
371 #ifndef UEFI_C_SOURCE /* Not in UEFI */
372 PyDoc_STRVAR(statvfs_result__doc__,
373 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
374 This object may be accessed either as a tuple of\n\
375 (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
376 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
377 \n\
378 See os.statvfs for more information.");
379
380 static PyStructSequence_Field statvfs_result_fields[] = {
381 {"f_bsize", },
382 {"f_frsize", },
383 {"f_blocks", },
384 {"f_bfree", },
385 {"f_bavail", },
386 {"f_files", },
387 {"f_ffree", },
388 {"f_favail", },
389 {"f_flag", },
390 {"f_namemax",},
391 {0}
392 };
393
394 static PyStructSequence_Desc statvfs_result_desc = {
395 "statvfs_result", /* name */
396 statvfs_result__doc__, /* doc */
397 statvfs_result_fields,
398 10
399 };
400
401 static PyTypeObject StatVFSResultType;
402 #endif
403
404 static int initialized;
405 static PyTypeObject StatResultType;
406 static newfunc structseq_new;
407
408 static PyObject *
409 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
410 {
411 PyStructSequence *result;
412 int i;
413
414 result = (PyStructSequence*)structseq_new(type, args, kwds);
415 if (!result)
416 return NULL;
417 /* If we have been initialized from a tuple,
418 st_?time might be set to None. Initialize it
419 from the int slots. */
420 for (i = 7; i <= 9; i++) {
421 if (result->ob_item[i+3] == Py_None) {
422 Py_DECREF(Py_None);
423 Py_INCREF(result->ob_item[i]);
424 result->ob_item[i+3] = result->ob_item[i];
425 }
426 }
427 return (PyObject*)result;
428 }
429
430
431
432 /* If true, st_?time is float. */
433 #if defined(UEFI_C_SOURCE)
434 static int _stat_float_times = 0;
435 #else
436 static int _stat_float_times = 1;
437
438 PyDoc_STRVAR(stat_float_times__doc__,
439 "stat_float_times([newval]) -> oldval\n\n\
440 Determine whether os.[lf]stat represents time stamps as float objects.\n\
441 If newval is True, future calls to stat() return floats, if it is False,\n\
442 future calls return ints. \n\
443 If newval is omitted, return the current setting.\n");
444
445 static PyObject*
446 stat_float_times(PyObject* self, PyObject *args)
447 {
448 int newval = -1;
449
450 if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
451 return NULL;
452 if (newval == -1)
453 /* Return old value */
454 return PyBool_FromLong(_stat_float_times);
455 _stat_float_times = newval;
456 Py_INCREF(Py_None);
457 return Py_None;
458 }
459 #endif /* UEFI_C_SOURCE */
460
461 static void
462 fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
463 {
464 PyObject *fval,*ival;
465 #if SIZEOF_TIME_T > SIZEOF_LONG
466 ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
467 #else
468 ival = PyInt_FromLong((long)sec);
469 #endif
470 if (!ival)
471 return;
472 if (_stat_float_times) {
473 fval = PyFloat_FromDouble(sec + 1e-9*nsec);
474 } else {
475 fval = ival;
476 Py_INCREF(fval);
477 }
478 PyStructSequence_SET_ITEM(v, index, ival);
479 PyStructSequence_SET_ITEM(v, index+3, fval);
480 }
481
482 /* pack a system stat C structure into the Python stat tuple
483 (used by posix_stat() and posix_fstat()) */
484 static PyObject*
485 _pystat_fromstructstat(STRUCT_STAT *st)
486 {
487 unsigned long ansec, mnsec, cnsec;
488 PyObject *v = PyStructSequence_New(&StatResultType);
489 if (v == NULL)
490 return NULL;
491
492 PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st->st_mode));
493 PyStructSequence_SET_ITEM(v, 1,
494 PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
495
496 ansec = mnsec = cnsec = 0;
497 /* The index used by fill_time is the index of the integer time.
498 fill_time will add 3 to the index to get the floating time index.
499 */
500 fill_time(v, 2, st->st_atime, ansec);
501 fill_time(v, 3, st->st_mtime, mnsec);
502 fill_time(v, 4, st->st_mtime, cnsec);
503
504 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
505 PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
506 PyInt_FromLong((long)st->st_blksize));
507 #endif
508 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
509 PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
510 PyInt_FromLong((long)st->st_blocks));
511 #endif
512 #ifdef HAVE_STRUCT_STAT_ST_RDEV
513 PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
514 PyInt_FromLong((long)st->st_rdev));
515 #endif
516 #ifdef HAVE_STRUCT_STAT_ST_GEN
517 PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
518 PyInt_FromLong((long)st->st_gen));
519 #endif
520 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
521 {
522 PyObject *val;
523 unsigned long bsec,bnsec;
524 bsec = (long)st->st_birthtime;
525 #ifdef HAVE_STAT_TV_NSEC2
526 bnsec = st->st_birthtimespec.tv_nsec;
527 #else
528 bnsec = 0;
529 #endif
530 if (_stat_float_times) {
531 val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
532 } else {
533 val = PyInt_FromLong((long)bsec);
534 }
535 PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
536 val);
537 }
538 #endif
539 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
540 PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
541 PyInt_FromLong((long)st->st_flags));
542 #endif
543
544 if (PyErr_Occurred()) {
545 Py_DECREF(v);
546 return NULL;
547 }
548
549 return v;
550 }
551
552 static PyObject *
553 posix_do_stat(PyObject *self, PyObject *args,
554 char *format,
555 int (*statfunc)(const char *, STRUCT_STAT *),
556 char *wformat,
557 int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *))
558 {
559 STRUCT_STAT st;
560 char *path = NULL; /* pass this to stat; do not free() it */
561 char *pathfree = NULL; /* this memory must be free'd */
562 int res;
563 PyObject *result;
564
565 if (!PyArg_ParseTuple(args, format,
566 Py_FileSystemDefaultEncoding, &path))
567 return NULL;
568 pathfree = path;
569
570 Py_BEGIN_ALLOW_THREADS
571 res = (*statfunc)(path, &st);
572 Py_END_ALLOW_THREADS
573
574 if (res != 0) {
575 result = posix_error_with_filename(pathfree);
576 }
577 else
578 result = _pystat_fromstructstat(&st);
579
580 PyMem_Free(pathfree);
581 return result;
582 }
583
584 /* POSIX methods */
585
586 PyDoc_STRVAR(posix_access__doc__,
587 "access(path, mode) -> True if granted, False otherwise\n\n\
588 Use the real uid/gid to test for access to a path. Note that most\n\
589 operations will use the effective uid/gid, therefore this routine can\n\
590 be used in a suid/sgid environment to test if the invoking user has the\n\
591 specified access to the path. The mode argument can be F_OK to test\n\
592 existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
593
594 static PyObject *
595 posix_access(PyObject *self, PyObject *args)
596 {
597 char *path;
598 int mode;
599
600 int res;
601 if (!PyArg_ParseTuple(args, "eti:access",
602 Py_FileSystemDefaultEncoding, &path, &mode))
603 return NULL;
604 Py_BEGIN_ALLOW_THREADS
605 res = access(path, mode);
606 Py_END_ALLOW_THREADS
607 PyMem_Free(path);
608 return PyBool_FromLong(res == 0);
609 }
610
611 #ifndef F_OK
612 #define F_OK 0
613 #endif
614 #ifndef R_OK
615 #define R_OK 4
616 #endif
617 #ifndef W_OK
618 #define W_OK 2
619 #endif
620 #ifndef X_OK
621 #define X_OK 1
622 #endif
623
624 PyDoc_STRVAR(posix_chdir__doc__,
625 "chdir(path)\n\n\
626 Change the current working directory to the specified path.");
627
628 static PyObject *
629 posix_chdir(PyObject *self, PyObject *args)
630 {
631 return posix_1str(args, "et:chdir", chdir);
632 }
633
634 PyDoc_STRVAR(posix_chmod__doc__,
635 "chmod(path, mode)\n\n\
636 Change the access permissions of a file.");
637
638 static PyObject *
639 posix_chmod(PyObject *self, PyObject *args)
640 {
641 char *path = NULL;
642 int i;
643 int res;
644 if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding,
645 &path, &i))
646 return NULL;
647 Py_BEGIN_ALLOW_THREADS
648 res = chmod(path, i);
649 Py_END_ALLOW_THREADS
650 if (res < 0)
651 return posix_error_with_allocated_filename(path);
652 PyMem_Free(path);
653 Py_INCREF(Py_None);
654 return Py_None;
655 }
656
657 #ifdef HAVE_FCHMOD
658 PyDoc_STRVAR(posix_fchmod__doc__,
659 "fchmod(fd, mode)\n\n\
660 Change the access permissions of the file given by file\n\
661 descriptor fd.");
662
663 static PyObject *
664 posix_fchmod(PyObject *self, PyObject *args)
665 {
666 int fd, mode, res;
667 if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
668 return NULL;
669 Py_BEGIN_ALLOW_THREADS
670 res = fchmod(fd, mode);
671 Py_END_ALLOW_THREADS
672 if (res < 0)
673 return posix_error();
674 Py_RETURN_NONE;
675 }
676 #endif /* HAVE_FCHMOD */
677
678 #ifdef HAVE_LCHMOD
679 PyDoc_STRVAR(posix_lchmod__doc__,
680 "lchmod(path, mode)\n\n\
681 Change the access permissions of a file. If path is a symlink, this\n\
682 affects the link itself rather than the target.");
683
684 static PyObject *
685 posix_lchmod(PyObject *self, PyObject *args)
686 {
687 char *path = NULL;
688 int i;
689 int res;
690 if (!PyArg_ParseTuple(args, "eti:lchmod", Py_FileSystemDefaultEncoding,
691 &path, &i))
692 return NULL;
693 Py_BEGIN_ALLOW_THREADS
694 res = lchmod(path, i);
695 Py_END_ALLOW_THREADS
696 if (res < 0)
697 return posix_error_with_allocated_filename(path);
698 PyMem_Free(path);
699 Py_RETURN_NONE;
700 }
701 #endif /* HAVE_LCHMOD */
702
703
704 #ifdef HAVE_CHFLAGS
705 PyDoc_STRVAR(posix_chflags__doc__,
706 "chflags(path, flags)\n\n\
707 Set file flags.");
708
709 static PyObject *
710 posix_chflags(PyObject *self, PyObject *args)
711 {
712 char *path;
713 unsigned long flags;
714 int res;
715 if (!PyArg_ParseTuple(args, "etk:chflags",
716 Py_FileSystemDefaultEncoding, &path, &flags))
717 return NULL;
718 Py_BEGIN_ALLOW_THREADS
719 res = chflags(path, flags);
720 Py_END_ALLOW_THREADS
721 if (res < 0)
722 return posix_error_with_allocated_filename(path);
723 PyMem_Free(path);
724 Py_INCREF(Py_None);
725 return Py_None;
726 }
727 #endif /* HAVE_CHFLAGS */
728
729 #ifdef HAVE_LCHFLAGS
730 PyDoc_STRVAR(posix_lchflags__doc__,
731 "lchflags(path, flags)\n\n\
732 Set file flags.\n\
733 This function will not follow symbolic links.");
734
735 static PyObject *
736 posix_lchflags(PyObject *self, PyObject *args)
737 {
738 char *path;
739 unsigned long flags;
740 int res;
741 if (!PyArg_ParseTuple(args, "etk:lchflags",
742 Py_FileSystemDefaultEncoding, &path, &flags))
743 return NULL;
744 Py_BEGIN_ALLOW_THREADS
745 res = lchflags(path, flags);
746 Py_END_ALLOW_THREADS
747 if (res < 0)
748 return posix_error_with_allocated_filename(path);
749 PyMem_Free(path);
750 Py_INCREF(Py_None);
751 return Py_None;
752 }
753 #endif /* HAVE_LCHFLAGS */
754
755 #ifdef HAVE_CHROOT
756 PyDoc_STRVAR(posix_chroot__doc__,
757 "chroot(path)\n\n\
758 Change root directory to path.");
759
760 static PyObject *
761 posix_chroot(PyObject *self, PyObject *args)
762 {
763 return posix_1str(args, "et:chroot", chroot);
764 }
765 #endif
766
767 #ifdef HAVE_FSYNC
768 PyDoc_STRVAR(posix_fsync__doc__,
769 "fsync(fildes)\n\n\
770 force write of file with filedescriptor to disk.");
771
772 static PyObject *
773 posix_fsync(PyObject *self, PyObject *fdobj)
774 {
775 return posix_fildes(fdobj, fsync);
776 }
777 #endif /* HAVE_FSYNC */
778
779 #ifdef HAVE_FDATASYNC
780
781 #ifdef __hpux
782 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
783 #endif
784
785 PyDoc_STRVAR(posix_fdatasync__doc__,
786 "fdatasync(fildes)\n\n\
787 force write of file with filedescriptor to disk.\n\
788 does not force update of metadata.");
789
790 static PyObject *
791 posix_fdatasync(PyObject *self, PyObject *fdobj)
792 {
793 return posix_fildes(fdobj, fdatasync);
794 }
795 #endif /* HAVE_FDATASYNC */
796
797
798 #ifdef HAVE_CHOWN
799 PyDoc_STRVAR(posix_chown__doc__,
800 "chown(path, uid, gid)\n\n\
801 Change the owner and group id of path to the numeric uid and gid.");
802
803 static PyObject *
804 posix_chown(PyObject *self, PyObject *args)
805 {
806 char *path = NULL;
807 long uid, gid;
808 int res;
809 if (!PyArg_ParseTuple(args, "etll:chown",
810 Py_FileSystemDefaultEncoding, &path,
811 &uid, &gid))
812 return NULL;
813 Py_BEGIN_ALLOW_THREADS
814 res = chown(path, (uid_t) uid, (gid_t) gid);
815 Py_END_ALLOW_THREADS
816 if (res < 0)
817 return posix_error_with_allocated_filename(path);
818 PyMem_Free(path);
819 Py_INCREF(Py_None);
820 return Py_None;
821 }
822 #endif /* HAVE_CHOWN */
823
824 #ifdef HAVE_FCHOWN
825 PyDoc_STRVAR(posix_fchown__doc__,
826 "fchown(fd, uid, gid)\n\n\
827 Change the owner and group id of the file given by file descriptor\n\
828 fd to the numeric uid and gid.");
829
830 static PyObject *
831 posix_fchown(PyObject *self, PyObject *args)
832 {
833 int fd;
834 long uid, gid;
835 int res;
836 if (!PyArg_ParseTuple(args, "ill:chown", &fd, &uid, &gid))
837 return NULL;
838 Py_BEGIN_ALLOW_THREADS
839 res = fchown(fd, (uid_t) uid, (gid_t) gid);
840 Py_END_ALLOW_THREADS
841 if (res < 0)
842 return posix_error();
843 Py_RETURN_NONE;
844 }
845 #endif /* HAVE_FCHOWN */
846
847 #ifdef HAVE_LCHOWN
848 PyDoc_STRVAR(posix_lchown__doc__,
849 "lchown(path, uid, gid)\n\n\
850 Change the owner and group id of path to the numeric uid and gid.\n\
851 This function will not follow symbolic links.");
852
853 static PyObject *
854 posix_lchown(PyObject *self, PyObject *args)
855 {
856 char *path = NULL;
857 long uid, gid;
858 int res;
859 if (!PyArg_ParseTuple(args, "etll:lchown",
860 Py_FileSystemDefaultEncoding, &path,
861 &uid, &gid))
862 return NULL;
863 Py_BEGIN_ALLOW_THREADS
864 res = lchown(path, (uid_t) uid, (gid_t) gid);
865 Py_END_ALLOW_THREADS
866 if (res < 0)
867 return posix_error_with_allocated_filename(path);
868 PyMem_Free(path);
869 Py_INCREF(Py_None);
870 return Py_None;
871 }
872 #endif /* HAVE_LCHOWN */
873
874
875 #ifdef HAVE_GETCWD
876 PyDoc_STRVAR(posix_getcwd__doc__,
877 "getcwd() -> path\n\n\
878 Return a string representing the current working directory.");
879
880 static PyObject *
881 posix_getcwd(PyObject *self, PyObject *noargs)
882 {
883 int bufsize_incr = 1024;
884 int bufsize = 0;
885 char *tmpbuf = NULL;
886 char *res = NULL;
887 PyObject *dynamic_return;
888
889 Py_BEGIN_ALLOW_THREADS
890 do {
891 bufsize = bufsize + bufsize_incr;
892 tmpbuf = malloc(bufsize);
893 if (tmpbuf == NULL) {
894 break;
895 }
896 res = getcwd(tmpbuf, bufsize);
897 if (res == NULL) {
898 free(tmpbuf);
899 }
900 } while ((res == NULL) && (errno == ERANGE));
901 Py_END_ALLOW_THREADS
902
903 if (res == NULL)
904 return posix_error();
905
906 dynamic_return = PyString_FromString(tmpbuf);
907 free(tmpbuf);
908
909 return dynamic_return;
910 }
911
912 #ifdef Py_USING_UNICODE
913 PyDoc_STRVAR(posix_getcwdu__doc__,
914 "getcwdu() -> path\n\n\
915 Return a unicode string representing the current working directory.");
916
917 static PyObject *
918 posix_getcwdu(PyObject *self, PyObject *noargs)
919 {
920 char buf[1026];
921 char *res;
922
923 Py_BEGIN_ALLOW_THREADS
924 res = getcwd(buf, sizeof buf);
925 Py_END_ALLOW_THREADS
926 if (res == NULL)
927 return posix_error();
928 return PyUnicode_Decode(buf, strlen(buf), Py_FileSystemDefaultEncoding,"strict");
929 }
930 #endif /* Py_USING_UNICODE */
931 #endif /* HAVE_GETCWD */
932
933
934 PyDoc_STRVAR(posix_listdir__doc__,
935 "listdir(path) -> list_of_strings\n\n\
936 Return a list containing the names of the entries in the directory.\n\
937 \n\
938 path: path of directory to list\n\
939 \n\
940 The list is in arbitrary order. It does not include the special\n\
941 entries '.' and '..' even if they are present in the directory.");
942
943 static PyObject *
944 posix_listdir(PyObject *self, PyObject *args)
945 {
946 /* XXX Should redo this putting the (now four) versions of opendir
947 in separate files instead of having them all here... */
948
949 char *name = NULL;
950 char *MBname;
951 PyObject *d, *v;
952 DIR *dirp;
953 struct dirent *ep;
954 int arg_is_unicode = 1;
955
956 errno = 0;
957 if (!PyArg_ParseTuple(args, "U:listdir", &v)) {
958 arg_is_unicode = 0;
959 PyErr_Clear();
960 }
961 if (!PyArg_ParseTuple(args, "et:listdir", Py_FileSystemDefaultEncoding, &name))
962 return NULL;
963 Py_BEGIN_ALLOW_THREADS
964 dirp = opendir(name);
965 Py_END_ALLOW_THREADS
966 if (dirp == NULL) {
967 return posix_error_with_allocated_filename(name);
968 }
969 if ((d = PyList_New(0)) == NULL) {
970 Py_BEGIN_ALLOW_THREADS
971 closedir(dirp);
972 Py_END_ALLOW_THREADS
973 PyMem_Free(name);
974 return NULL;
975 }
976 if((MBname = malloc(NAME_MAX)) == NULL) {
977 Py_BEGIN_ALLOW_THREADS
978 closedir(dirp);
979 Py_END_ALLOW_THREADS
980 Py_DECREF(d);
981 PyMem_Free(name);
982 return NULL;
983 }
984 for (;;) {
985 errno = 0;
986 Py_BEGIN_ALLOW_THREADS
987 ep = readdir(dirp);
988 Py_END_ALLOW_THREADS
989 if (ep == NULL) {
990 if ((errno == 0) || (errno == EISDIR)) {
991 break;
992 } else {
993 Py_BEGIN_ALLOW_THREADS
994 closedir(dirp);
995 Py_END_ALLOW_THREADS
996 Py_DECREF(d);
997 return posix_error_with_allocated_filename(name);
998 }
999 }
1000 if (ep->FileName[0] == L'.' &&
1001 (NAMLEN(ep) == 1 ||
1002 (ep->FileName[1] == L'.' && NAMLEN(ep) == 2)))
1003 continue;
1004 if(wcstombs(MBname, ep->FileName, NAME_MAX) == -1) {
1005 free(MBname);
1006 Py_BEGIN_ALLOW_THREADS
1007 closedir(dirp);
1008 Py_END_ALLOW_THREADS
1009 Py_DECREF(d);
1010 PyMem_Free(name);
1011 return NULL;
1012 }
1013 v = PyString_FromStringAndSize(MBname, strlen(MBname));
1014 if (v == NULL) {
1015 Py_DECREF(d);
1016 d = NULL;
1017 break;
1018 }
1019 #ifdef Py_USING_UNICODE
1020 if (arg_is_unicode) {
1021 PyObject *w;
1022
1023 w = PyUnicode_FromEncodedObject(v,
1024 Py_FileSystemDefaultEncoding,
1025 "strict");
1026 if (w != NULL) {
1027 Py_DECREF(v);
1028 v = w;
1029 }
1030 else {
1031 /* fall back to the original byte string, as
1032 discussed in patch #683592 */
1033 PyErr_Clear();
1034 }
1035 }
1036 #endif
1037 if (PyList_Append(d, v) != 0) {
1038 Py_DECREF(v);
1039 Py_DECREF(d);
1040 d = NULL;
1041 break;
1042 }
1043 Py_DECREF(v);
1044 }
1045 Py_BEGIN_ALLOW_THREADS
1046 closedir(dirp);
1047 Py_END_ALLOW_THREADS
1048 PyMem_Free(name);
1049 if(MBname != NULL) {
1050 free(MBname);
1051 }
1052
1053 return d;
1054
1055 } /* end of posix_listdir */
1056
1057 #ifdef MS_WINDOWS
1058 /* A helper function for abspath on win32 */
1059 static PyObject *
1060 posix__getfullpathname(PyObject *self, PyObject *args)
1061 {
1062 /* assume encoded strings won't more than double no of chars */
1063 char inbuf[MAX_PATH*2];
1064 char *inbufp = inbuf;
1065 Py_ssize_t insize = sizeof(inbuf);
1066 char outbuf[MAX_PATH*2];
1067 char *temp;
1068
1069 PyUnicodeObject *po;
1070 if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) {
1071 Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
1072 Py_UNICODE woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
1073 Py_UNICODE *wtemp;
1074 DWORD result;
1075 PyObject *v;
1076 result = GetFullPathNameW(wpath,
1077 sizeof(woutbuf)/sizeof(woutbuf[0]),
1078 woutbuf, &wtemp);
1079 if (result > sizeof(woutbuf)/sizeof(woutbuf[0])) {
1080 woutbufp = malloc(result * sizeof(Py_UNICODE));
1081 if (!woutbufp)
1082 return PyErr_NoMemory();
1083 result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
1084 }
1085 if (result)
1086 v = PyUnicode_FromUnicode(woutbufp, wcslen(woutbufp));
1087 else
1088 v = win32_error_unicode("GetFullPathNameW", wpath);
1089 if (woutbufp != woutbuf)
1090 free(woutbufp);
1091 return v;
1092 }
1093 /* Drop the argument parsing error as narrow strings
1094 are also valid. */
1095 PyErr_Clear();
1096
1097 if (!PyArg_ParseTuple (args, "et#:_getfullpathname",
1098 Py_FileSystemDefaultEncoding, &inbufp,
1099 &insize))
1100 return NULL;
1101 if (!GetFullPathName(inbuf, sizeof(outbuf)/sizeof(outbuf[0]),
1102 outbuf, &temp))
1103 return win32_error("GetFullPathName", inbuf);
1104 if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
1105 return PyUnicode_Decode(outbuf, strlen(outbuf),
1106 Py_FileSystemDefaultEncoding, NULL);
1107 }
1108 return PyString_FromString(outbuf);
1109 } /* end of posix__getfullpathname */
1110 #endif /* MS_WINDOWS */
1111
1112 PyDoc_STRVAR(posix_mkdir__doc__,
1113 "mkdir(path [, mode=0777])\n\n\
1114 Create a directory.");
1115
1116 static PyObject *
1117 posix_mkdir(PyObject *self, PyObject *args)
1118 {
1119 int res;
1120 char *path = NULL;
1121 int mode = 0777;
1122
1123 if (!PyArg_ParseTuple(args, "et|i:mkdir",
1124 Py_FileSystemDefaultEncoding, &path, &mode))
1125 return NULL;
1126 Py_BEGIN_ALLOW_THREADS
1127 res = mkdir(path, mode);
1128 Py_END_ALLOW_THREADS
1129 if (res < 0)
1130 return posix_error_with_allocated_filename(path);
1131 PyMem_Free(path);
1132 Py_INCREF(Py_None);
1133 return Py_None;
1134 }
1135
1136
1137 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
1138 #if defined(HAVE_SYS_RESOURCE_H)
1139 #include <sys/resource.h>
1140 #endif
1141
1142
1143 #ifdef HAVE_NICE
1144 PyDoc_STRVAR(posix_nice__doc__,
1145 "nice(inc) -> new_priority\n\n\
1146 Decrease the priority of process by inc and return the new priority.");
1147
1148 static PyObject *
1149 posix_nice(PyObject *self, PyObject *args)
1150 {
1151 int increment, value;
1152
1153 if (!PyArg_ParseTuple(args, "i:nice", &increment))
1154 return NULL;
1155
1156 /* There are two flavours of 'nice': one that returns the new
1157 priority (as required by almost all standards out there) and the
1158 Linux/FreeBSD/BSDI one, which returns '0' on success and advices
1159 the use of getpriority() to get the new priority.
1160
1161 If we are of the nice family that returns the new priority, we
1162 need to clear errno before the call, and check if errno is filled
1163 before calling posix_error() on a returnvalue of -1, because the
1164 -1 may be the actual new priority! */
1165
1166 errno = 0;
1167 value = nice(increment);
1168 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
1169 if (value == 0)
1170 value = getpriority(PRIO_PROCESS, 0);
1171 #endif
1172 if (value == -1 && errno != 0)
1173 /* either nice() or getpriority() returned an error */
1174 return posix_error();
1175 return PyInt_FromLong((long) value);
1176 }
1177 #endif /* HAVE_NICE */
1178
1179 PyDoc_STRVAR(posix_rename__doc__,
1180 "rename(old, new)\n\n\
1181 Rename a file or directory.");
1182
1183 static PyObject *
1184 posix_rename(PyObject *self, PyObject *args)
1185 {
1186 return posix_2str(args, "etet:rename", rename);
1187 }
1188
1189
1190 PyDoc_STRVAR(posix_rmdir__doc__,
1191 "rmdir(path)\n\n\
1192 Remove a directory.");
1193
1194 static PyObject *
1195 posix_rmdir(PyObject *self, PyObject *args)
1196 {
1197 return posix_1str(args, "et:rmdir", rmdir);
1198 }
1199
1200
1201 PyDoc_STRVAR(posix_stat__doc__,
1202 "stat(path) -> stat result\n\n\
1203 Perform a stat system call on the given path.");
1204
1205 static PyObject *
1206 posix_stat(PyObject *self, PyObject *args)
1207 {
1208 return posix_do_stat(self, args, "et:stat", STAT, NULL, NULL);
1209 }
1210
1211
1212 #ifdef HAVE_SYSTEM
1213 PyDoc_STRVAR(posix_system__doc__,
1214 "system(command) -> exit_status\n\n\
1215 Execute the command (a string) in a subshell.");
1216
1217 static PyObject *
1218 posix_system(PyObject *self, PyObject *args)
1219 {
1220 char *command;
1221 long sts;
1222 if (!PyArg_ParseTuple(args, "s:system", &command))
1223 return NULL;
1224 Py_BEGIN_ALLOW_THREADS
1225 sts = system(command);
1226 Py_END_ALLOW_THREADS
1227 return PyInt_FromLong(sts);
1228 }
1229 #endif
1230
1231
1232 PyDoc_STRVAR(posix_umask__doc__,
1233 "umask(new_mask) -> old_mask\n\n\
1234 Set the current numeric umask and return the previous umask.");
1235
1236 static PyObject *
1237 posix_umask(PyObject *self, PyObject *args)
1238 {
1239 int i;
1240 if (!PyArg_ParseTuple(args, "i:umask", &i))
1241 return NULL;
1242 i = (int)umask(i);
1243 if (i < 0)
1244 return posix_error();
1245 return PyInt_FromLong((long)i);
1246 }
1247
1248
1249 PyDoc_STRVAR(posix_unlink__doc__,
1250 "unlink(path)\n\n\
1251 Remove a file (same as remove(path)).");
1252
1253 PyDoc_STRVAR(posix_remove__doc__,
1254 "remove(path)\n\n\
1255 Remove a file (same as unlink(path)).");
1256
1257 static PyObject *
1258 posix_unlink(PyObject *self, PyObject *args)
1259 {
1260 return posix_1str(args, "et:remove", unlink);
1261 }
1262
1263
1264 static int
1265 extract_time(PyObject *t, time_t* sec, long* usec)
1266 {
1267 time_t intval;
1268 if (PyFloat_Check(t)) {
1269 double tval = PyFloat_AsDouble(t);
1270 PyObject *intobj = PyNumber_Long(t);
1271 if (!intobj)
1272 return -1;
1273 #if SIZEOF_TIME_T > SIZEOF_LONG
1274 intval = PyInt_AsUnsignedLongLongMask(intobj);
1275 #else
1276 intval = PyInt_AsLong(intobj);
1277 #endif
1278 Py_DECREF(intobj);
1279 if (intval == -1 && PyErr_Occurred())
1280 return -1;
1281 *sec = intval;
1282 *usec = (long)((tval - intval) * 1e6); /* can't exceed 1000000 */
1283 if (*usec < 0)
1284 /* If rounding gave us a negative number,
1285 truncate. */
1286 *usec = 0;
1287 return 0;
1288 }
1289 #if SIZEOF_TIME_T > SIZEOF_LONG
1290 intval = PyInt_AsUnsignedLongLongMask(t);
1291 #else
1292 intval = PyInt_AsLong(t);
1293 #endif
1294 if (intval == -1 && PyErr_Occurred())
1295 return -1;
1296 *sec = intval;
1297 *usec = 0;
1298 return 0;
1299 }
1300
1301 PyDoc_STRVAR(posix_utime__doc__,
1302 "utime(path, (atime, mtime))\n\
1303 utime(path, None)\n\n\
1304 Set the access and modified time of the file to the given values. If the\n\
1305 second form is used, set the access and modified times to the current time.");
1306
1307 static PyObject *
1308 posix_utime(PyObject *self, PyObject *args)
1309 {
1310 char *path = NULL;
1311 time_t atime, mtime;
1312 long ausec, musec;
1313 int res;
1314 PyObject* arg;
1315
1316 #if defined(HAVE_UTIMES)
1317 struct timeval buf[2];
1318 #define ATIME buf[0].tv_sec
1319 #define MTIME buf[1].tv_sec
1320 #elif defined(HAVE_UTIME_H)
1321 /* XXX should define struct utimbuf instead, above */
1322 struct utimbuf buf;
1323 #define ATIME buf.actime
1324 #define MTIME buf.modtime
1325 #define UTIME_ARG &buf
1326 #else /* HAVE_UTIMES */
1327 time_t buf[2];
1328 #define ATIME buf[0]
1329 #define MTIME buf[1]
1330 #define UTIME_ARG buf
1331 #endif /* HAVE_UTIMES */
1332
1333
1334 if (!PyArg_ParseTuple(args, "etO:utime",
1335 Py_FileSystemDefaultEncoding, &path, &arg))
1336 return NULL;
1337 if (arg == Py_None) {
1338 /* optional time values not given */
1339 Py_BEGIN_ALLOW_THREADS
1340 res = utime(path, NULL);
1341 Py_END_ALLOW_THREADS
1342 }
1343 else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
1344 PyErr_SetString(PyExc_TypeError,
1345 "utime() arg 2 must be a tuple (atime, mtime)");
1346 PyMem_Free(path);
1347 return NULL;
1348 }
1349 else {
1350 if (extract_time(PyTuple_GET_ITEM(arg, 0),
1351 &atime, &ausec) == -1) {
1352 PyMem_Free(path);
1353 return NULL;
1354 }
1355 if (extract_time(PyTuple_GET_ITEM(arg, 1),
1356 &mtime, &musec) == -1) {
1357 PyMem_Free(path);
1358 return NULL;
1359 }
1360 ATIME = atime;
1361 MTIME = mtime;
1362 #ifdef HAVE_UTIMES
1363 buf[0].tv_usec = ausec;
1364 buf[1].tv_usec = musec;
1365 Py_BEGIN_ALLOW_THREADS
1366 res = utimes(path, buf);
1367 Py_END_ALLOW_THREADS
1368 #else
1369 Py_BEGIN_ALLOW_THREADS
1370 res = utime(path, UTIME_ARG);
1371 Py_END_ALLOW_THREADS
1372 #endif /* HAVE_UTIMES */
1373 }
1374 if (res < 0) {
1375 return posix_error_with_allocated_filename(path);
1376 }
1377 PyMem_Free(path);
1378 Py_INCREF(Py_None);
1379 return Py_None;
1380 #undef UTIME_ARG
1381 #undef ATIME
1382 #undef MTIME
1383 }
1384
1385
1386 /* Process operations */
1387
1388 PyDoc_STRVAR(posix__exit__doc__,
1389 "_exit(status)\n\n\
1390 Exit to the system with specified status, without normal exit processing.");
1391
1392 static PyObject *
1393 posix__exit(PyObject *self, PyObject *args)
1394 {
1395 int sts;
1396 if (!PyArg_ParseTuple(args, "i:_exit", &sts))
1397 return NULL;
1398 _Exit(sts);
1399 return NULL; /* Make gcc -Wall happy */
1400 }
1401
1402 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
1403 static void
1404 free_string_array(char **array, Py_ssize_t count)
1405 {
1406 Py_ssize_t i;
1407 for (i = 0; i < count; i++)
1408 PyMem_Free(array[i]);
1409 PyMem_DEL(array);
1410 }
1411 #endif
1412
1413
1414 #ifdef HAVE_EXECV
1415 PyDoc_STRVAR(posix_execv__doc__,
1416 "execv(path, args)\n\n\
1417 Execute an executable path with arguments, replacing current process.\n\
1418 \n\
1419 path: path of executable file\n\
1420 args: tuple or list of strings");
1421
1422 static PyObject *
1423 posix_execv(PyObject *self, PyObject *args)
1424 {
1425 char *path;
1426 PyObject *argv;
1427 char **argvlist;
1428 Py_ssize_t i, argc;
1429 PyObject *(*getitem)(PyObject *, Py_ssize_t);
1430
1431 /* execv has two arguments: (path, argv), where
1432 argv is a list or tuple of strings. */
1433
1434 if (!PyArg_ParseTuple(args, "etO:execv",
1435 Py_FileSystemDefaultEncoding,
1436 &path, &argv))
1437 return NULL;
1438 if (PyList_Check(argv)) {
1439 argc = PyList_Size(argv);
1440 getitem = PyList_GetItem;
1441 }
1442 else if (PyTuple_Check(argv)) {
1443 argc = PyTuple_Size(argv);
1444 getitem = PyTuple_GetItem;
1445 }
1446 else {
1447 PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list");
1448 PyMem_Free(path);
1449 return NULL;
1450 }
1451 if (argc < 1) {
1452 PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
1453 PyMem_Free(path);
1454 return NULL;
1455 }
1456
1457 argvlist = PyMem_NEW(char *, argc+1);
1458 if (argvlist == NULL) {
1459 PyMem_Free(path);
1460 return PyErr_NoMemory();
1461 }
1462 for (i = 0; i < argc; i++) {
1463 if (!PyArg_Parse((*getitem)(argv, i), "et",
1464 Py_FileSystemDefaultEncoding,
1465 &argvlist[i])) {
1466 free_string_array(argvlist, i);
1467 PyErr_SetString(PyExc_TypeError,
1468 "execv() arg 2 must contain only strings");
1469 PyMem_Free(path);
1470 return NULL;
1471
1472 }
1473 }
1474 argvlist[argc] = NULL;
1475
1476 execv(path, argvlist);
1477
1478 /* If we get here it's definitely an error */
1479
1480 free_string_array(argvlist, argc);
1481 PyMem_Free(path);
1482 return posix_error();
1483 }
1484
1485
1486 PyDoc_STRVAR(posix_execve__doc__,
1487 "execve(path, args, env)\n\n\
1488 Execute a path with arguments and environment, replacing current process.\n\
1489 \n\
1490 path: path of executable file\n\
1491 args: tuple or list of arguments\n\
1492 env: dictionary of strings mapping to strings");
1493
1494 static PyObject *
1495 posix_execve(PyObject *self, PyObject *args)
1496 {
1497 char *path;
1498 PyObject *argv, *env;
1499 char **argvlist;
1500 char **envlist;
1501 PyObject *key, *val, *keys=NULL, *vals=NULL;
1502 Py_ssize_t i, pos, argc, envc;
1503 PyObject *(*getitem)(PyObject *, Py_ssize_t);
1504 Py_ssize_t lastarg = 0;
1505
1506 /* execve has three arguments: (path, argv, env), where
1507 argv is a list or tuple of strings and env is a dictionary
1508 like posix.environ. */
1509
1510 if (!PyArg_ParseTuple(args, "etOO:execve",
1511 Py_FileSystemDefaultEncoding,
1512 &path, &argv, &env))
1513 return NULL;
1514 if (PyList_Check(argv)) {
1515 argc = PyList_Size(argv);
1516 getitem = PyList_GetItem;
1517 }
1518 else if (PyTuple_Check(argv)) {
1519 argc = PyTuple_Size(argv);
1520 getitem = PyTuple_GetItem;
1521 }
1522 else {
1523 PyErr_SetString(PyExc_TypeError,
1524 "execve() arg 2 must be a tuple or list");
1525 goto fail_0;
1526 }
1527 if (!PyMapping_Check(env)) {
1528 PyErr_SetString(PyExc_TypeError,
1529 "execve() arg 3 must be a mapping object");
1530 goto fail_0;
1531 }
1532
1533 argvlist = PyMem_NEW(char *, argc+1);
1534 if (argvlist == NULL) {
1535 PyErr_NoMemory();
1536 goto fail_0;
1537 }
1538 for (i = 0; i < argc; i++) {
1539 if (!PyArg_Parse((*getitem)(argv, i),
1540 "et;execve() arg 2 must contain only strings",
1541 Py_FileSystemDefaultEncoding,
1542 &argvlist[i]))
1543 {
1544 lastarg = i;
1545 goto fail_1;
1546 }
1547 }
1548 lastarg = argc;
1549 argvlist[argc] = NULL;
1550
1551 i = PyMapping_Size(env);
1552 if (i < 0)
1553 goto fail_1;
1554 envlist = PyMem_NEW(char *, i + 1);
1555 if (envlist == NULL) {
1556 PyErr_NoMemory();
1557 goto fail_1;
1558 }
1559 envc = 0;
1560 keys = PyMapping_Keys(env);
1561 vals = PyMapping_Values(env);
1562 if (!keys || !vals)
1563 goto fail_2;
1564 if (!PyList_Check(keys) || !PyList_Check(vals)) {
1565 PyErr_SetString(PyExc_TypeError,
1566 "execve(): env.keys() or env.values() is not a list");
1567 goto fail_2;
1568 }
1569
1570 for (pos = 0; pos < i; pos++) {
1571 char *p, *k, *v;
1572 size_t len;
1573
1574 key = PyList_GetItem(keys, pos);
1575 val = PyList_GetItem(vals, pos);
1576 if (!key || !val)
1577 goto fail_2;
1578
1579 if (!PyArg_Parse(
1580 key,
1581 "s;execve() arg 3 contains a non-string key",
1582 &k) ||
1583 !PyArg_Parse(
1584 val,
1585 "s;execve() arg 3 contains a non-string value",
1586 &v))
1587 {
1588 goto fail_2;
1589 }
1590
1591 #if defined(PYOS_OS2)
1592 /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
1593 if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
1594 #endif
1595 len = PyString_Size(key) + PyString_Size(val) + 2;
1596 p = PyMem_NEW(char, len);
1597 if (p == NULL) {
1598 PyErr_NoMemory();
1599 goto fail_2;
1600 }
1601 PyOS_snprintf(p, len, "%s=%s", k, v);
1602 envlist[envc++] = p;
1603 #if defined(PYOS_OS2)
1604 }
1605 #endif
1606 }
1607 envlist[envc] = 0;
1608
1609 execve(path, argvlist, envlist);
1610
1611 /* If we get here it's definitely an error */
1612
1613 (void) posix_error();
1614
1615 fail_2:
1616 while (--envc >= 0)
1617 PyMem_DEL(envlist[envc]);
1618 PyMem_DEL(envlist);
1619 fail_1:
1620 free_string_array(argvlist, lastarg);
1621 Py_XDECREF(vals);
1622 Py_XDECREF(keys);
1623 fail_0:
1624 PyMem_Free(path);
1625 return NULL;
1626 }
1627 #endif /* HAVE_EXECV */
1628
1629
1630 #ifdef HAVE_SPAWNV
1631 PyDoc_STRVAR(posix_spawnv__doc__,
1632 "spawnv(mode, path, args)\n\n\
1633 Execute the program 'path' in a new process.\n\
1634 \n\
1635 mode: mode of process creation\n\
1636 path: path of executable file\n\
1637 args: tuple or list of strings");
1638
1639 static PyObject *
1640 posix_spawnv(PyObject *self, PyObject *args)
1641 {
1642 char *path;
1643 PyObject *argv;
1644 char **argvlist;
1645 int mode, i;
1646 Py_ssize_t argc;
1647 Py_intptr_t spawnval;
1648 PyObject *(*getitem)(PyObject *, Py_ssize_t);
1649
1650 /* spawnv has three arguments: (mode, path, argv), where
1651 argv is a list or tuple of strings. */
1652
1653 if (!PyArg_ParseTuple(args, "ietO:spawnv", &mode,
1654 Py_FileSystemDefaultEncoding,
1655 &path, &argv))
1656 return NULL;
1657 if (PyList_Check(argv)) {
1658 argc = PyList_Size(argv);
1659 getitem = PyList_GetItem;
1660 }
1661 else if (PyTuple_Check(argv)) {
1662 argc = PyTuple_Size(argv);
1663 getitem = PyTuple_GetItem;
1664 }
1665 else {
1666 PyErr_SetString(PyExc_TypeError,
1667 "spawnv() arg 2 must be a tuple or list");
1668 PyMem_Free(path);
1669 return NULL;
1670 }
1671
1672 argvlist = PyMem_NEW(char *, argc+1);
1673 if (argvlist == NULL) {
1674 PyMem_Free(path);
1675 return PyErr_NoMemory();
1676 }
1677 for (i = 0; i < argc; i++) {
1678 if (!PyArg_Parse((*getitem)(argv, i), "et",
1679 Py_FileSystemDefaultEncoding,
1680 &argvlist[i])) {
1681 free_string_array(argvlist, i);
1682 PyErr_SetString(
1683 PyExc_TypeError,
1684 "spawnv() arg 2 must contain only strings");
1685 PyMem_Free(path);
1686 return NULL;
1687 }
1688 }
1689 argvlist[argc] = NULL;
1690
1691 #if defined(PYOS_OS2) && defined(PYCC_GCC)
1692 Py_BEGIN_ALLOW_THREADS
1693 spawnval = spawnv(mode, path, argvlist);
1694 Py_END_ALLOW_THREADS
1695 #else
1696 if (mode == _OLD_P_OVERLAY)
1697 mode = _P_OVERLAY;
1698
1699 Py_BEGIN_ALLOW_THREADS
1700 spawnval = _spawnv(mode, path, argvlist);
1701 Py_END_ALLOW_THREADS
1702 #endif
1703
1704 free_string_array(argvlist, argc);
1705 PyMem_Free(path);
1706
1707 if (spawnval == -1)
1708 return posix_error();
1709 else
1710 #if SIZEOF_LONG == SIZEOF_VOID_P
1711 return Py_BuildValue("l", (long) spawnval);
1712 #else
1713 return Py_BuildValue("L", (PY_LONG_LONG) spawnval);
1714 #endif
1715 }
1716
1717
1718 PyDoc_STRVAR(posix_spawnve__doc__,
1719 "spawnve(mode, path, args, env)\n\n\
1720 Execute the program 'path' in a new process.\n\
1721 \n\
1722 mode: mode of process creation\n\
1723 path: path of executable file\n\
1724 args: tuple or list of arguments\n\
1725 env: dictionary of strings mapping to strings");
1726
1727 static PyObject *
1728 posix_spawnve(PyObject *self, PyObject *args)
1729 {
1730 char *path;
1731 PyObject *argv, *env;
1732 char **argvlist;
1733 char **envlist;
1734 PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
1735 int mode, pos, envc;
1736 Py_ssize_t argc, i;
1737 Py_intptr_t spawnval;
1738 PyObject *(*getitem)(PyObject *, Py_ssize_t);
1739 Py_ssize_t lastarg = 0;
1740
1741 /* spawnve has four arguments: (mode, path, argv, env), where
1742 argv is a list or tuple of strings and env is a dictionary
1743 like posix.environ. */
1744
1745 if (!PyArg_ParseTuple(args, "ietOO:spawnve", &mode,
1746 Py_FileSystemDefaultEncoding,
1747 &path, &argv, &env))
1748 return NULL;
1749 if (PyList_Check(argv)) {
1750 argc = PyList_Size(argv);
1751 getitem = PyList_GetItem;
1752 }
1753 else if (PyTuple_Check(argv)) {
1754 argc = PyTuple_Size(argv);
1755 getitem = PyTuple_GetItem;
1756 }
1757 else {
1758 PyErr_SetString(PyExc_TypeError,
1759 "spawnve() arg 2 must be a tuple or list");
1760 goto fail_0;
1761 }
1762 if (!PyMapping_Check(env)) {
1763 PyErr_SetString(PyExc_TypeError,
1764 "spawnve() arg 3 must be a mapping object");
1765 goto fail_0;
1766 }
1767
1768 argvlist = PyMem_NEW(char *, argc+1);
1769 if (argvlist == NULL) {
1770 PyErr_NoMemory();
1771 goto fail_0;
1772 }
1773 for (i = 0; i < argc; i++) {
1774 if (!PyArg_Parse((*getitem)(argv, i),
1775 "et;spawnve() arg 2 must contain only strings",
1776 Py_FileSystemDefaultEncoding,
1777 &argvlist[i]))
1778 {
1779 lastarg = i;
1780 goto fail_1;
1781 }
1782 }
1783 lastarg = argc;
1784 argvlist[argc] = NULL;
1785
1786 i = PyMapping_Size(env);
1787 if (i < 0)
1788 goto fail_1;
1789 envlist = PyMem_NEW(char *, i + 1);
1790 if (envlist == NULL) {
1791 PyErr_NoMemory();
1792 goto fail_1;
1793 }
1794 envc = 0;
1795 keys = PyMapping_Keys(env);
1796 vals = PyMapping_Values(env);
1797 if (!keys || !vals)
1798 goto fail_2;
1799 if (!PyList_Check(keys) || !PyList_Check(vals)) {
1800 PyErr_SetString(PyExc_TypeError,
1801 "spawnve(): env.keys() or env.values() is not a list");
1802 goto fail_2;
1803 }
1804
1805 for (pos = 0; pos < i; pos++) {
1806 char *p, *k, *v;
1807 size_t len;
1808
1809 key = PyList_GetItem(keys, pos);
1810 val = PyList_GetItem(vals, pos);
1811 if (!key || !val)
1812 goto fail_2;
1813
1814 if (!PyArg_Parse(
1815 key,
1816 "s;spawnve() arg 3 contains a non-string key",
1817 &k) ||
1818 !PyArg_Parse(
1819 val,
1820 "s;spawnve() arg 3 contains a non-string value",
1821 &v))
1822 {
1823 goto fail_2;
1824 }
1825 len = PyString_Size(key) + PyString_Size(val) + 2;
1826 p = PyMem_NEW(char, len);
1827 if (p == NULL) {
1828 PyErr_NoMemory();
1829 goto fail_2;
1830 }
1831 PyOS_snprintf(p, len, "%s=%s", k, v);
1832 envlist[envc++] = p;
1833 }
1834 envlist[envc] = 0;
1835
1836 #if defined(PYOS_OS2) && defined(PYCC_GCC)
1837 Py_BEGIN_ALLOW_THREADS
1838 spawnval = spawnve(mode, path, argvlist, envlist);
1839 Py_END_ALLOW_THREADS
1840 #else
1841 if (mode == _OLD_P_OVERLAY)
1842 mode = _P_OVERLAY;
1843
1844 Py_BEGIN_ALLOW_THREADS
1845 spawnval = _spawnve(mode, path, argvlist, envlist);
1846 Py_END_ALLOW_THREADS
1847 #endif
1848
1849 if (spawnval == -1)
1850 (void) posix_error();
1851 else
1852 #if SIZEOF_LONG == SIZEOF_VOID_P
1853 res = Py_BuildValue("l", (long) spawnval);
1854 #else
1855 res = Py_BuildValue("L", (PY_LONG_LONG) spawnval);
1856 #endif
1857
1858 fail_2:
1859 while (--envc >= 0)
1860 PyMem_DEL(envlist[envc]);
1861 PyMem_DEL(envlist);
1862 fail_1:
1863 free_string_array(argvlist, lastarg);
1864 Py_XDECREF(vals);
1865 Py_XDECREF(keys);
1866 fail_0:
1867 PyMem_Free(path);
1868 return res;
1869 }
1870
1871 /* OS/2 supports spawnvp & spawnvpe natively */
1872 #if defined(PYOS_OS2)
1873 PyDoc_STRVAR(posix_spawnvp__doc__,
1874 "spawnvp(mode, file, args)\n\n\
1875 Execute the program 'file' in a new process, using the environment\n\
1876 search path to find the file.\n\
1877 \n\
1878 mode: mode of process creation\n\
1879 file: executable file name\n\
1880 args: tuple or list of strings");
1881
1882 static PyObject *
1883 posix_spawnvp(PyObject *self, PyObject *args)
1884 {
1885 char *path;
1886 PyObject *argv;
1887 char **argvlist;
1888 int mode, i, argc;
1889 Py_intptr_t spawnval;
1890 PyObject *(*getitem)(PyObject *, Py_ssize_t);
1891
1892 /* spawnvp has three arguments: (mode, path, argv), where
1893 argv is a list or tuple of strings. */
1894
1895 if (!PyArg_ParseTuple(args, "ietO:spawnvp", &mode,
1896 Py_FileSystemDefaultEncoding,
1897 &path, &argv))
1898 return NULL;
1899 if (PyList_Check(argv)) {
1900 argc = PyList_Size(argv);
1901 getitem = PyList_GetItem;
1902 }
1903 else if (PyTuple_Check(argv)) {
1904 argc = PyTuple_Size(argv);
1905 getitem = PyTuple_GetItem;
1906 }
1907 else {
1908 PyErr_SetString(PyExc_TypeError,
1909 "spawnvp() arg 2 must be a tuple or list");
1910 PyMem_Free(path);
1911 return NULL;
1912 }
1913
1914 argvlist = PyMem_NEW(char *, argc+1);
1915 if (argvlist == NULL) {
1916 PyMem_Free(path);
1917 return PyErr_NoMemory();
1918 }
1919 for (i = 0; i < argc; i++) {
1920 if (!PyArg_Parse((*getitem)(argv, i), "et",
1921 Py_FileSystemDefaultEncoding,
1922 &argvlist[i])) {
1923 free_string_array(argvlist, i);
1924 PyErr_SetString(
1925 PyExc_TypeError,
1926 "spawnvp() arg 2 must contain only strings");
1927 PyMem_Free(path);
1928 return NULL;
1929 }
1930 }
1931 argvlist[argc] = NULL;
1932
1933 Py_BEGIN_ALLOW_THREADS
1934 #if defined(PYCC_GCC)
1935 spawnval = spawnvp(mode, path, argvlist);
1936 #else
1937 spawnval = _spawnvp(mode, path, argvlist);
1938 #endif
1939 Py_END_ALLOW_THREADS
1940
1941 free_string_array(argvlist, argc);
1942 PyMem_Free(path);
1943
1944 if (spawnval == -1)
1945 return posix_error();
1946 else
1947 return Py_BuildValue("l", (long) spawnval);
1948 }
1949
1950
1951 PyDoc_STRVAR(posix_spawnvpe__doc__,
1952 "spawnvpe(mode, file, args, env)\n\n\
1953 Execute the program 'file' in a new process, using the environment\n\
1954 search path to find the file.\n\
1955 \n\
1956 mode: mode of process creation\n\
1957 file: executable file name\n\
1958 args: tuple or list of arguments\n\
1959 env: dictionary of strings mapping to strings");
1960
1961 static PyObject *
1962 posix_spawnvpe(PyObject *self, PyObject *args)
1963 {
1964 char *path;
1965 PyObject *argv, *env;
1966 char **argvlist;
1967 char **envlist;
1968 PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL;
1969 int mode, i, pos, argc, envc;
1970 Py_intptr_t spawnval;
1971 PyObject *(*getitem)(PyObject *, Py_ssize_t);
1972 int lastarg = 0;
1973
1974 /* spawnvpe has four arguments: (mode, path, argv, env), where
1975 argv is a list or tuple of strings and env is a dictionary
1976 like posix.environ. */
1977
1978 if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode,
1979 Py_FileSystemDefaultEncoding,
1980 &path, &argv, &env))
1981 return NULL;
1982 if (PyList_Check(argv)) {
1983 argc = PyList_Size(argv);
1984 getitem = PyList_GetItem;
1985 }
1986 else if (PyTuple_Check(argv)) {
1987 argc = PyTuple_Size(argv);
1988 getitem = PyTuple_GetItem;
1989 }
1990 else {
1991 PyErr_SetString(PyExc_TypeError,
1992 "spawnvpe() arg 2 must be a tuple or list");
1993 goto fail_0;
1994 }
1995 if (!PyMapping_Check(env)) {
1996 PyErr_SetString(PyExc_TypeError,
1997 "spawnvpe() arg 3 must be a mapping object");
1998 goto fail_0;
1999 }
2000
2001 argvlist = PyMem_NEW(char *, argc+1);
2002 if (argvlist == NULL) {
2003 PyErr_NoMemory();
2004 goto fail_0;
2005 }
2006 for (i = 0; i < argc; i++) {
2007 if (!PyArg_Parse((*getitem)(argv, i),
2008 "et;spawnvpe() arg 2 must contain only strings",
2009 Py_FileSystemDefaultEncoding,
2010 &argvlist[i]))
2011 {
2012 lastarg = i;
2013 goto fail_1;
2014 }
2015 }
2016 lastarg = argc;
2017 argvlist[argc] = NULL;
2018
2019 i = PyMapping_Size(env);
2020 if (i < 0)
2021 goto fail_1;
2022 envlist = PyMem_NEW(char *, i + 1);
2023 if (envlist == NULL) {
2024 PyErr_NoMemory();
2025 goto fail_1;
2026 }
2027 envc = 0;
2028 keys = PyMapping_Keys(env);
2029 vals = PyMapping_Values(env);
2030 if (!keys || !vals)
2031 goto fail_2;
2032 if (!PyList_Check(keys) || !PyList_Check(vals)) {
2033 PyErr_SetString(PyExc_TypeError,
2034 "spawnvpe(): env.keys() or env.values() is not a list");
2035 goto fail_2;
2036 }
2037
2038 for (pos = 0; pos < i; pos++) {
2039 char *p, *k, *v;
2040 size_t len;
2041
2042 key = PyList_GetItem(keys, pos);
2043 val = PyList_GetItem(vals, pos);
2044 if (!key || !val)
2045 goto fail_2;
2046
2047 if (!PyArg_Parse(
2048 key,
2049 "s;spawnvpe() arg 3 contains a non-string key",
2050 &k) ||
2051 !PyArg_Parse(
2052 val,
2053 "s;spawnvpe() arg 3 contains a non-string value",
2054 &v))
2055 {
2056 goto fail_2;
2057 }
2058 len = PyString_Size(key) + PyString_Size(val) + 2;
2059 p = PyMem_NEW(char, len);
2060 if (p == NULL) {
2061 PyErr_NoMemory();
2062 goto fail_2;
2063 }
2064 PyOS_snprintf(p, len, "%s=%s", k, v);
2065 envlist[envc++] = p;
2066 }
2067 envlist[envc] = 0;
2068
2069 Py_BEGIN_ALLOW_THREADS
2070 #if defined(PYCC_GCC)
2071 spawnval = spawnvpe(mode, path, argvlist, envlist);
2072 #else
2073 spawnval = _spawnvpe(mode, path, argvlist, envlist);
2074 #endif
2075 Py_END_ALLOW_THREADS
2076
2077 if (spawnval == -1)
2078 (void) posix_error();
2079 else
2080 res = Py_BuildValue("l", (long) spawnval);
2081
2082 fail_2:
2083 while (--envc >= 0)
2084 PyMem_DEL(envlist[envc]);
2085 PyMem_DEL(envlist);
2086 fail_1:
2087 free_string_array(argvlist, lastarg);
2088 Py_XDECREF(vals);
2089 Py_XDECREF(keys);
2090 fail_0:
2091 PyMem_Free(path);
2092 return res;
2093 }
2094 #endif /* PYOS_OS2 */
2095 #endif /* HAVE_SPAWNV */
2096
2097
2098 #ifdef HAVE_FORK1
2099 PyDoc_STRVAR(posix_fork1__doc__,
2100 "fork1() -> pid\n\n\
2101 Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
2102 \n\
2103 Return 0 to child process and PID of child to parent process.");
2104
2105 static PyObject *
2106 posix_fork1(PyObject *self, PyObject *noargs)
2107 {
2108 pid_t pid;
2109 int result = 0;
2110 _PyImport_AcquireLock();
2111 pid = fork1();
2112 if (pid == 0) {
2113 /* child: this clobbers and resets the import lock. */
2114 PyOS_AfterFork();
2115 } else {
2116 /* parent: release the import lock. */
2117 result = _PyImport_ReleaseLock();
2118 }
2119 if (pid == -1)
2120 return posix_error();
2121 if (result < 0) {
2122 /* Don't clobber the OSError if the fork failed. */
2123 PyErr_SetString(PyExc_RuntimeError,
2124 "not holding the import lock");
2125 return NULL;
2126 }
2127 return PyLong_FromPid(pid);
2128 }
2129 #endif
2130
2131
2132 #ifdef HAVE_FORK
2133 PyDoc_STRVAR(posix_fork__doc__,
2134 "fork() -> pid\n\n\
2135 Fork a child process.\n\
2136 Return 0 to child process and PID of child to parent process.");
2137
2138 static PyObject *
2139 posix_fork(PyObject *self, PyObject *noargs)
2140 {
2141 pid_t pid;
2142 int result = 0;
2143 _PyImport_AcquireLock();
2144 pid = fork();
2145 if (pid == 0) {
2146 /* child: this clobbers and resets the import lock. */
2147 PyOS_AfterFork();
2148 } else {
2149 /* parent: release the import lock. */
2150 result = _PyImport_ReleaseLock();
2151 }
2152 if (pid == -1)
2153 return posix_error();
2154 if (result < 0) {
2155 /* Don't clobber the OSError if the fork failed. */
2156 PyErr_SetString(PyExc_RuntimeError,
2157 "not holding the import lock");
2158 return NULL;
2159 }
2160 return PyLong_FromPid(pid);
2161 }
2162 #endif
2163
2164 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
2165 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
2166 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
2167 #define DEV_PTY_FILE "/dev/ptc"
2168 #define HAVE_DEV_PTMX
2169 #else
2170 #define DEV_PTY_FILE "/dev/ptmx"
2171 #endif
2172
2173 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
2174 #ifdef HAVE_PTY_H
2175 #include <pty.h>
2176 #else
2177 #ifdef HAVE_LIBUTIL_H
2178 #include <libutil.h>
2179 #else
2180 #ifdef HAVE_UTIL_H
2181 #include <util.h>
2182 #endif /* HAVE_UTIL_H */
2183 #endif /* HAVE_LIBUTIL_H */
2184 #endif /* HAVE_PTY_H */
2185 #ifdef HAVE_STROPTS_H
2186 #include <stropts.h>
2187 #endif
2188 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
2189
2190 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
2191 PyDoc_STRVAR(posix_openpty__doc__,
2192 "openpty() -> (master_fd, slave_fd)\n\n\
2193 Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
2194
2195 static PyObject *
2196 posix_openpty(PyObject *self, PyObject *noargs)
2197 {
2198 int master_fd, slave_fd;
2199 #ifndef HAVE_OPENPTY
2200 char * slave_name;
2201 #endif
2202 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
2203 PyOS_sighandler_t sig_saved;
2204 #ifdef sun
2205 extern char *ptsname(int fildes);
2206 #endif
2207 #endif
2208
2209 #ifdef HAVE_OPENPTY
2210 if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
2211 return posix_error();
2212 #elif defined(HAVE__GETPTY)
2213 slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
2214 if (slave_name == NULL)
2215 return posix_error();
2216
2217 slave_fd = open(slave_name, O_RDWR);
2218 if (slave_fd < 0)
2219 return posix_error();
2220 #else
2221 master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
2222 if (master_fd < 0)
2223 return posix_error();
2224 sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
2225 /* change permission of slave */
2226 if (grantpt(master_fd) < 0) {
2227 PyOS_setsig(SIGCHLD, sig_saved);
2228 return posix_error();
2229 }
2230 /* unlock slave */
2231 if (unlockpt(master_fd) < 0) {
2232 PyOS_setsig(SIGCHLD, sig_saved);
2233 return posix_error();
2234 }
2235 PyOS_setsig(SIGCHLD, sig_saved);
2236 slave_name = ptsname(master_fd); /* get name of slave */
2237 if (slave_name == NULL)
2238 return posix_error();
2239 slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
2240 if (slave_fd < 0)
2241 return posix_error();
2242 #if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
2243 ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
2244 ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
2245 #ifndef __hpux
2246 ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
2247 #endif /* __hpux */
2248 #endif /* HAVE_CYGWIN */
2249 #endif /* HAVE_OPENPTY */
2250
2251 return Py_BuildValue("(ii)", master_fd, slave_fd);
2252
2253 }
2254 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
2255
2256 #ifdef HAVE_FORKPTY
2257 PyDoc_STRVAR(posix_forkpty__doc__,
2258 "forkpty() -> (pid, master_fd)\n\n\
2259 Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
2260 Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
2261 To both, return fd of newly opened pseudo-terminal.\n");
2262
2263 static PyObject *
2264 posix_forkpty(PyObject *self, PyObject *noargs)
2265 {
2266 int master_fd = -1, result = 0;
2267 pid_t pid;
2268
2269 _PyImport_AcquireLock();
2270 pid = forkpty(&master_fd, NULL, NULL, NULL);
2271 if (pid == 0) {
2272 /* child: this clobbers and resets the import lock. */
2273 PyOS_AfterFork();
2274 } else {
2275 /* parent: release the import lock. */
2276 result = _PyImport_ReleaseLock();
2277 }
2278 if (pid == -1)
2279 return posix_error();
2280 if (result < 0) {
2281 /* Don't clobber the OSError if the fork failed. */
2282 PyErr_SetString(PyExc_RuntimeError,
2283 "not holding the import lock");
2284 return NULL;
2285 }
2286 return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
2287 }
2288 #endif
2289
2290 #ifdef HAVE_GETEGID
2291 PyDoc_STRVAR(posix_getegid__doc__,
2292 "getegid() -> egid\n\n\
2293 Return the current process's effective group id.");
2294
2295 static PyObject *
2296 posix_getegid(PyObject *self, PyObject *noargs)
2297 {
2298 return PyInt_FromLong((long)getegid());
2299 }
2300 #endif
2301
2302
2303 #ifdef HAVE_GETEUID
2304 PyDoc_STRVAR(posix_geteuid__doc__,
2305 "geteuid() -> euid\n\n\
2306 Return the current process's effective user id.");
2307
2308 static PyObject *
2309 posix_geteuid(PyObject *self, PyObject *noargs)
2310 {
2311 return PyInt_FromLong((long)geteuid());
2312 }
2313 #endif
2314
2315
2316 #ifdef HAVE_GETGID
2317 PyDoc_STRVAR(posix_getgid__doc__,
2318 "getgid() -> gid\n\n\
2319 Return the current process's group id.");
2320
2321 static PyObject *
2322 posix_getgid(PyObject *self, PyObject *noargs)
2323 {
2324 return PyInt_FromLong((long)getgid());
2325 }
2326 #endif
2327
2328
2329 PyDoc_STRVAR(posix_getpid__doc__,
2330 "getpid() -> pid\n\n\
2331 Return the current process id");
2332
2333 static PyObject *
2334 posix_getpid(PyObject *self, PyObject *noargs)
2335 {
2336 return PyLong_FromPid(getpid());
2337 }
2338
2339
2340 #ifdef HAVE_GETGROUPS
2341 PyDoc_STRVAR(posix_getgroups__doc__,
2342 "getgroups() -> list of group IDs\n\n\
2343 Return list of supplemental group IDs for the process.");
2344
2345 static PyObject *
2346 posix_getgroups(PyObject *self, PyObject *noargs)
2347 {
2348 PyObject *result = NULL;
2349
2350 #ifdef NGROUPS_MAX
2351 #define MAX_GROUPS NGROUPS_MAX
2352 #else
2353 /* defined to be 16 on Solaris7, so this should be a small number */
2354 #define MAX_GROUPS 64
2355 #endif
2356 gid_t grouplist[MAX_GROUPS];
2357
2358 /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
2359 * This is a helper variable to store the intermediate result when
2360 * that happens.
2361 *
2362 * To keep the code readable the OSX behaviour is unconditional,
2363 * according to the POSIX spec this should be safe on all unix-y
2364 * systems.
2365 */
2366 gid_t* alt_grouplist = grouplist;
2367 int n;
2368
2369 n = getgroups(MAX_GROUPS, grouplist);
2370 if (n < 0) {
2371 if (errno == EINVAL) {
2372 n = getgroups(0, NULL);
2373 if (n == -1) {
2374 return posix_error();
2375 }
2376 if (n == 0) {
2377 /* Avoid malloc(0) */
2378 alt_grouplist = grouplist;
2379 } else {
2380 alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
2381 if (alt_grouplist == NULL) {
2382 errno = EINVAL;
2383 return posix_error();
2384 }
2385 n = getgroups(n, alt_grouplist);
2386 if (n == -1) {
2387 PyMem_Free(alt_grouplist);
2388 return posix_error();
2389 }
2390 }
2391 } else {
2392 return posix_error();
2393 }
2394 }
2395 result = PyList_New(n);
2396 if (result != NULL) {
2397 int i;
2398 for (i = 0; i < n; ++i) {
2399 PyObject *o = PyInt_FromLong((long)alt_grouplist[i]);
2400 if (o == NULL) {
2401 Py_DECREF(result);
2402 result = NULL;
2403 break;
2404 }
2405 PyList_SET_ITEM(result, i, o);
2406 }
2407 }
2408
2409 if (alt_grouplist != grouplist) {
2410 PyMem_Free(alt_grouplist);
2411 }
2412
2413 return result;
2414 }
2415 #endif
2416
2417 #ifdef HAVE_INITGROUPS
2418 PyDoc_STRVAR(posix_initgroups__doc__,
2419 "initgroups(username, gid) -> None\n\n\
2420 Call the system initgroups() to initialize the group access list with all of\n\
2421 the groups of which the specified username is a member, plus the specified\n\
2422 group id.");
2423
2424 static PyObject *
2425 posix_initgroups(PyObject *self, PyObject *args)
2426 {
2427 char *username;
2428 long gid;
2429
2430 if (!PyArg_ParseTuple(args, "sl:initgroups", &username, &gid))
2431 return NULL;
2432
2433 if (initgroups(username, (gid_t) gid) == -1)
2434 return PyErr_SetFromErrno(PyExc_OSError);
2435
2436 Py_INCREF(Py_None);
2437 return Py_None;
2438 }
2439 #endif
2440
2441 #ifdef HAVE_GETPGID
2442 PyDoc_STRVAR(posix_getpgid__doc__,
2443 "getpgid(pid) -> pgid\n\n\
2444 Call the system call getpgid().");
2445
2446 static PyObject *
2447 posix_getpgid(PyObject *self, PyObject *args)
2448 {
2449 pid_t pid, pgid;
2450 if (!PyArg_ParseTuple(args, PARSE_PID ":getpgid", &pid))
2451 return NULL;
2452 pgid = getpgid(pid);
2453 if (pgid < 0)
2454 return posix_error();
2455 return PyLong_FromPid(pgid);
2456 }
2457 #endif /* HAVE_GETPGID */
2458
2459
2460 #ifdef HAVE_GETPGRP
2461 PyDoc_STRVAR(posix_getpgrp__doc__,
2462 "getpgrp() -> pgrp\n\n\
2463 Return the current process group id.");
2464
2465 static PyObject *
2466 posix_getpgrp(PyObject *self, PyObject *noargs)
2467 {
2468 #ifdef GETPGRP_HAVE_ARG
2469 return PyLong_FromPid(getpgrp(0));
2470 #else /* GETPGRP_HAVE_ARG */
2471 return PyLong_FromPid(getpgrp());
2472 #endif /* GETPGRP_HAVE_ARG */
2473 }
2474 #endif /* HAVE_GETPGRP */
2475
2476
2477 #ifdef HAVE_SETPGRP
2478 PyDoc_STRVAR(posix_setpgrp__doc__,
2479 "setpgrp()\n\n\
2480 Make this process the process group leader.");
2481
2482 static PyObject *
2483 posix_setpgrp(PyObject *self, PyObject *noargs)
2484 {
2485 #ifdef SETPGRP_HAVE_ARG
2486 if (setpgrp(0, 0) < 0)
2487 #else /* SETPGRP_HAVE_ARG */
2488 if (setpgrp() < 0)
2489 #endif /* SETPGRP_HAVE_ARG */
2490 return posix_error();
2491 Py_INCREF(Py_None);
2492 return Py_None;
2493 }
2494
2495 #endif /* HAVE_SETPGRP */
2496
2497 #ifdef HAVE_GETPPID
2498 PyDoc_STRVAR(posix_getppid__doc__,
2499 "getppid() -> ppid\n\n\
2500 Return the parent's process id.");
2501
2502 static PyObject *
2503 posix_getppid(PyObject *self, PyObject *noargs)
2504 {
2505 return PyLong_FromPid(getppid());
2506 }
2507 #endif
2508
2509
2510 #ifdef HAVE_GETLOGIN
2511 PyDoc_STRVAR(posix_getlogin__doc__,
2512 "getlogin() -> string\n\n\
2513 Return the actual login name.");
2514
2515 static PyObject *
2516 posix_getlogin(PyObject *self, PyObject *noargs)
2517 {
2518 PyObject *result = NULL;
2519 char *name;
2520 int old_errno = errno;
2521
2522 errno = 0;
2523 name = getlogin();
2524 if (name == NULL) {
2525 if (errno)
2526 posix_error();
2527 else
2528 PyErr_SetString(PyExc_OSError,
2529 "unable to determine login name");
2530 }
2531 else
2532 result = PyString_FromString(name);
2533 errno = old_errno;
2534
2535 return result;
2536 }
2537 #endif
2538
2539 #ifndef UEFI_C_SOURCE
2540 PyDoc_STRVAR(posix_getuid__doc__,
2541 "getuid() -> uid\n\n\
2542 Return the current process's user id.");
2543
2544 static PyObject *
2545 posix_getuid(PyObject *self, PyObject *noargs)
2546 {
2547 return PyInt_FromLong((long)getuid());
2548 }
2549 #endif /* UEFI_C_SOURCE */
2550
2551 #ifdef HAVE_KILL
2552 PyDoc_STRVAR(posix_kill__doc__,
2553 "kill(pid, sig)\n\n\
2554 Kill a process with a signal.");
2555
2556 static PyObject *
2557 posix_kill(PyObject *self, PyObject *args)
2558 {
2559 pid_t pid;
2560 int sig;
2561 if (!PyArg_ParseTuple(args, PARSE_PID "i:kill", &pid, &sig))
2562 return NULL;
2563 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
2564 if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
2565 APIRET rc;
2566 if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
2567 return os2_error(rc);
2568
2569 } else if (sig == XCPT_SIGNAL_KILLPROC) {
2570 APIRET rc;
2571 if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
2572 return os2_error(rc);
2573
2574 } else
2575 return NULL; /* Unrecognized Signal Requested */
2576 #else
2577 if (kill(pid, sig) == -1)
2578 return posix_error();
2579 #endif
2580 Py_INCREF(Py_None);
2581 return Py_None;
2582 }
2583 #endif
2584
2585 #ifdef HAVE_KILLPG
2586 PyDoc_STRVAR(posix_killpg__doc__,
2587 "killpg(pgid, sig)\n\n\
2588 Kill a process group with a signal.");
2589
2590 static PyObject *
2591 posix_killpg(PyObject *self, PyObject *args)
2592 {
2593 int sig;
2594 pid_t pgid;
2595 /* XXX some man pages make the `pgid` parameter an int, others
2596 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
2597 take the same type. Moreover, pid_t is always at least as wide as
2598 int (else compilation of this module fails), which is safe. */
2599 if (!PyArg_ParseTuple(args, PARSE_PID "i:killpg", &pgid, &sig))
2600 return NULL;
2601 if (killpg(pgid, sig) == -1)
2602 return posix_error();
2603 Py_INCREF(Py_None);
2604 return Py_None;
2605 }
2606 #endif
2607
2608 #ifdef HAVE_PLOCK
2609
2610 #ifdef HAVE_SYS_LOCK_H
2611 #include <sys/lock.h>
2612 #endif
2613
2614 PyDoc_STRVAR(posix_plock__doc__,
2615 "plock(op)\n\n\
2616 Lock program segments into memory.");
2617
2618 static PyObject *
2619 posix_plock(PyObject *self, PyObject *args)
2620 {
2621 int op;
2622 if (!PyArg_ParseTuple(args, "i:plock", &op))
2623 return NULL;
2624 if (plock(op) == -1)
2625 return posix_error();
2626 Py_INCREF(Py_None);
2627 return Py_None;
2628 }
2629 #endif
2630
2631
2632 #ifdef HAVE_POPEN
2633 PyDoc_STRVAR(posix_popen__doc__,
2634 "popen(command [, mode='r' [, bufsize]]) -> pipe\n\n\
2635 Open a pipe to/from a command returning a file object.");
2636
2637 #if defined(PYOS_OS2)
2638 #if defined(PYCC_VACPP)
2639 static int
2640 async_system(const char *command)
2641 {
2642 char errormsg[256], args[1024];
2643 RESULTCODES rcodes;
2644 APIRET rc;
2645
2646 char *shell = getenv("COMSPEC");
2647 if (!shell)
2648 shell = "cmd";
2649
2650 /* avoid overflowing the argument buffer */
2651 if (strlen(shell) + 3 + strlen(command) >= 1024)
2652 return ERROR_NOT_ENOUGH_MEMORY
2653
2654 args[0] = '\0';
2655 strcat(args, shell);
2656 strcat(args, "/c ");
2657 strcat(args, command);
2658
2659 /* execute asynchronously, inheriting the environment */
2660 rc = DosExecPgm(errormsg,
2661 sizeof(errormsg),
2662 EXEC_ASYNC,
2663 args,
2664 NULL,
2665 &rcodes,
2666 shell);
2667 return rc;
2668 }
2669
2670 static FILE *
2671 popen(const char *command, const char *mode, int pipesize, int *err)
2672 {
2673 int oldfd, tgtfd;
2674 HFILE pipeh[2];
2675 APIRET rc;
2676
2677 /* mode determines which of stdin or stdout is reconnected to
2678 * the pipe to the child
2679 */
2680 if (strchr(mode, 'r') != NULL) {
2681 tgt_fd = 1; /* stdout */
2682 } else if (strchr(mode, 'w')) {
2683 tgt_fd = 0; /* stdin */
2684 } else {
2685 *err = ERROR_INVALID_ACCESS;
2686 return NULL;
2687 }
2688
2689 /* setup the pipe */
2690 if ((rc = DosCreatePipe(&pipeh[0], &pipeh[1], pipesize)) != NO_ERROR) {
2691 *err = rc;
2692 return NULL;
2693 }
2694
2695 /* prevent other threads accessing stdio */
2696 DosEnterCritSec();
2697
2698 /* reconnect stdio and execute child */
2699 oldfd = dup(tgtfd);
2700 close(tgtfd);
2701 if (dup2(pipeh[tgtfd], tgtfd) == 0) {
2702 DosClose(pipeh[tgtfd]);
2703 rc = async_system(command);
2704 }
2705
2706 /* restore stdio */
2707 dup2(oldfd, tgtfd);
2708 close(oldfd);
2709
2710 /* allow other threads access to stdio */
2711 DosExitCritSec();
2712
2713 /* if execution of child was successful return file stream */
2714 if (rc == NO_ERROR)
2715 return fdopen(pipeh[1 - tgtfd], mode);
2716 else {
2717 DosClose(pipeh[1 - tgtfd]);
2718 *err = rc;
2719 return NULL;
2720 }
2721 }
2722
2723 static PyObject *
2724 posix_popen(PyObject *self, PyObject *args)
2725 {
2726 char *name;
2727 char *mode = "r";
2728 int err, bufsize = -1;
2729 FILE *fp;
2730 PyObject *f;
2731 if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
2732 return NULL;
2733 Py_BEGIN_ALLOW_THREADS
2734 fp = popen(name, mode, (bufsize > 0) ? bufsize : 4096, &err);
2735 Py_END_ALLOW_THREADS
2736 if (fp == NULL)
2737 return os2_error(err);
2738
2739 f = PyFile_FromFile(fp, name, mode, fclose);
2740 if (f != NULL)
2741 PyFile_SetBufSize(f, bufsize);
2742 return f;
2743 }
2744
2745 #elif defined(PYCC_GCC)
2746
2747 /* standard posix version of popen() support */
2748 static PyObject *
2749 posix_popen(PyObject *self, PyObject *args)
2750 {
2751 char *name;
2752 char *mode = "r";
2753 int bufsize = -1;
2754 FILE *fp;
2755 PyObject *f;
2756 if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
2757 return NULL;
2758 Py_BEGIN_ALLOW_THREADS
2759 fp = popen(name, mode);
2760 Py_END_ALLOW_THREADS
2761 if (fp == NULL)
2762 return posix_error();
2763 f = PyFile_FromFile(fp, name, mode, pclose);
2764 if (f != NULL)
2765 PyFile_SetBufSize(f, bufsize);
2766 return f;
2767 }
2768
2769 /* fork() under OS/2 has lots'o'warts
2770 * EMX supports pipe() and spawn*() so we can synthesize popen[234]()
2771 * most of this code is a ripoff of the win32 code, but using the
2772 * capabilities of EMX's C library routines
2773 */
2774
2775 /* These tell _PyPopen() whether to return 1, 2, or 3 file objects. */
2776 #define POPEN_1 1
2777 #define POPEN_2 2
2778 #define POPEN_3 3
2779 #define POPEN_4 4
2780
2781 static PyObject *_PyPopen(char *, int, int, int);
2782 static int _PyPclose(FILE *file);
2783
2784 /*
2785 * Internal dictionary mapping popen* file pointers to process handles,
2786 * for use when retrieving the process exit code. See _PyPclose() below
2787 * for more information on this dictionary's use.
2788 */
2789 static PyObject *_PyPopenProcs = NULL;
2790
2791 /* os2emx version of popen2()
2792 *
2793 * The result of this function is a pipe (file) connected to the
2794 * process's stdin, and a pipe connected to the process's stdout.
2795 */
2796
2797 static PyObject *
2798 os2emx_popen2(PyObject *self, PyObject *args)
2799 {
2800 PyObject *f;
2801 int tm=0;
2802
2803 char *cmdstring;
2804 char *mode = "t";
2805 int bufsize = -1;
2806 if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize))
2807 return NULL;
2808
2809 if (*mode == 't')
2810 tm = O_TEXT;
2811 else if (*mode != 'b') {
2812 PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
2813 return NULL;
2814 } else
2815 tm = O_BINARY;
2816
2817 f = _PyPopen(cmdstring, tm, POPEN_2, bufsize);
2818
2819 return f;
2820 }
2821
2822 /*
2823 * Variation on os2emx.popen2
2824 *
2825 * The result of this function is 3 pipes - the process's stdin,
2826 * stdout and stderr
2827 */
2828
2829 static PyObject *
2830 os2emx_popen3(PyObject *self, PyObject *args)
2831 {
2832 PyObject *f;
2833 int tm = 0;
2834
2835 char *cmdstring;
2836 char *mode = "t";
2837 int bufsize = -1;
2838 if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize))
2839 return NULL;
2840
2841 if (*mode == 't')
2842 tm = O_TEXT;
2843 else if (*mode != 'b') {
2844 PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
2845 return NULL;
2846 } else
2847 tm = O_BINARY;
2848
2849 f = _PyPopen(cmdstring, tm, POPEN_3, bufsize);
2850
2851 return f;
2852 }
2853
2854 /*
2855 * Variation on os2emx.popen2
2856 *
2857 * The result of this function is 2 pipes - the processes stdin,
2858 * and stdout+stderr combined as a single pipe.
2859 */
2860
2861 static PyObject *
2862 os2emx_popen4(PyObject *self, PyObject *args)
2863 {
2864 PyObject *f;
2865 int tm = 0;
2866
2867 char *cmdstring;
2868 char *mode = "t";
2869 int bufsize = -1;
2870 if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize))
2871 return NULL;
2872
2873 if (*mode == 't')
2874 tm = O_TEXT;
2875 else if (*mode != 'b') {
2876 PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
2877 return NULL;
2878 } else
2879 tm = O_BINARY;
2880
2881 f = _PyPopen(cmdstring, tm, POPEN_4, bufsize);
2882
2883 return f;
2884 }
2885
2886 /* a couple of structures for convenient handling of multiple
2887 * file handles and pipes
2888 */
2889 struct file_ref
2890 {
2891 int handle;
2892 int flags;
2893 };
2894
2895 struct pipe_ref
2896 {
2897 int rd;
2898 int wr;
2899 };
2900
2901 /* The following code is derived from the win32 code */
2902
2903 static PyObject *
2904 _PyPopen(char *cmdstring, int mode, int n, int bufsize)
2905 {
2906 struct file_ref stdio[3];
2907 struct pipe_ref p_fd[3];
2908 FILE *p_s[3];
2909 int file_count, i, pipe_err;
2910 pid_t pipe_pid;
2911 char *shell, *sh_name, *opt, *rd_mode, *wr_mode;
2912 PyObject *f, *p_f[3];
2913
2914 /* file modes for subsequent fdopen's on pipe handles */
2915 if (mode == O_TEXT)
2916 {
2917 rd_mode = "rt";
2918 wr_mode = "wt";
2919 }
2920 else
2921 {
2922 rd_mode = "rb";
2923 wr_mode = "wb";
2924 }
2925
2926 /* prepare shell references */
2927 if ((shell = getenv("EMXSHELL")) == NULL)
2928 if ((shell = getenv("COMSPEC")) == NULL)
2929 {
2930 errno = ENOENT;
2931 return posix_error();
2932 }
2933
2934 sh_name = _getname(shell);
2935 if (stricmp(sh_name, "cmd.exe") == 0 || stricmp(sh_name, "4os2.exe") == 0)
2936 opt = "/c";
2937 else
2938 opt = "-c";
2939
2940 /* save current stdio fds + their flags, and set not inheritable */
2941 i = pipe_err = 0;
2942 while (pipe_err >= 0 && i < 3)
2943 {
2944 pipe_err = stdio[i].handle = dup(i);
2945 stdio[i].flags = fcntl(i, F_GETFD, 0);
2946 fcntl(stdio[i].handle, F_SETFD, stdio[i].flags | FD_CLOEXEC);
2947 i++;
2948 }
2949 if (pipe_err < 0)
2950 {
2951 /* didn't get them all saved - clean up and bail out */
2952 int saved_err = errno;
2953 while (i-- > 0)
2954 {
2955 close(stdio[i].handle);
2956 }
2957 errno = saved_err;
2958 return posix_error();
2959 }
2960
2961 /* create pipe ends */
2962 file_count = 2;
2963 if (n == POPEN_3)
2964 file_count = 3;
2965 i = pipe_err = 0;
2966 while ((pipe_err == 0) && (i < file_count))
2967 pipe_err = pipe((int *)&p_fd[i++]);
2968 if (pipe_err < 0)
2969 {
2970 /* didn't get them all made - clean up and bail out */
2971 while (i-- > 0)
2972 {
2973 close(p_fd[i].wr);
2974 close(p_fd[i].rd);
2975 }
2976 errno = EPIPE;
2977 return posix_error();
2978 }
2979
2980 /* change the actual standard IO streams over temporarily,
2981 * making the retained pipe ends non-inheritable
2982 */
2983 pipe_err = 0;
2984
2985 /* - stdin */
2986 if (dup2(p_fd[0].rd, 0) == 0)
2987 {
2988 close(p_fd[0].rd);
2989 i = fcntl(p_fd[0].wr, F_GETFD, 0);
2990 fcntl(p_fd[0].wr, F_SETFD, i | FD_CLOEXEC);
2991 if ((p_s[0] = fdopen(p_fd[0].wr, wr_mode)) == NULL)
2992 {
2993 close(p_fd[0].wr);
2994 pipe_err = -1;
2995 }
2996 }
2997 else
2998 {
2999 pipe_err = -1;
3000 }
3001
3002 /* - stdout */
3003 if (pipe_err == 0)
3004 {
3005 if (dup2(p_fd[1].wr, 1) == 1)
3006 {
3007 close(p_fd[1].wr);
3008 i = fcntl(p_fd[1].rd, F_GETFD, 0);
3009 fcntl(p_fd[1].rd, F_SETFD, i | FD_CLOEXEC);
3010 if ((p_s[1] = fdopen(p_fd[1].rd, rd_mode)) == NULL)
3011 {
3012 close(p_fd[1].rd);
3013 pipe_err = -1;
3014 }
3015 }
3016 else
3017 {
3018 pipe_err = -1;
3019 }
3020 }
3021
3022 /* - stderr, as required */
3023 if (pipe_err == 0)
3024 switch (n)
3025 {
3026 case POPEN_3:
3027 {
3028 if (dup2(p_fd[2].wr, 2) == 2)
3029 {
3030 close(p_fd[2].wr);
3031 i = fcntl(p_fd[2].rd, F_GETFD, 0);
3032 fcntl(p_fd[2].rd, F_SETFD, i | FD_CLOEXEC);
3033 if ((p_s[2] = fdopen(p_fd[2].rd, rd_mode)) == NULL)
3034 {
3035 close(p_fd[2].rd);
3036 pipe_err = -1;
3037 }
3038 }
3039 else
3040 {
3041 pipe_err = -1;
3042 }
3043 break;
3044 }
3045
3046 case POPEN_4:
3047 {
3048 if (dup2(1, 2) != 2)
3049 {
3050 pipe_err = -1;
3051 }
3052 break;
3053 }
3054 }
3055
3056 /* spawn the child process */
3057 if (pipe_err == 0)
3058 {
3059 pipe_pid = spawnlp(P_NOWAIT, shell, shell, opt, cmdstring, (char *)0);
3060 if (pipe_pid == -1)
3061 {
3062 pipe_err = -1;
3063 }
3064 else
3065 {
3066 /* save the PID into the FILE structure
3067 * NOTE: this implementation doesn't actually
3068 * take advantage of this, but do it for
3069 * completeness - AIM Apr01
3070 */
3071 for (i = 0; i < file_count; i++)
3072 p_s[i]->_pid = pipe_pid;
3073 }
3074 }
3075
3076 /* reset standard IO to normal */
3077 for (i = 0; i < 3; i++)
3078 {
3079 dup2(stdio[i].handle, i);
3080 fcntl(i, F_SETFD, stdio[i].flags);
3081 close(stdio[i].handle);
3082 }
3083
3084 /* if any remnant problems, clean up and bail out */
3085 if (pipe_err < 0)
3086 {
3087 for (i = 0; i < 3; i++)
3088 {
3089 close(p_fd[i].rd);
3090 close(p_fd[i].wr);
3091 }
3092 errno = EPIPE;
3093 return posix_error_with_filename(cmdstring);
3094 }
3095
3096 /* build tuple of file objects to return */
3097 if ((p_f[0] = PyFile_FromFile(p_s[0], cmdstring, wr_mode, _PyPclose)) != NULL)
3098 PyFile_SetBufSize(p_f[0], bufsize);
3099 if ((p_f[1] = PyFile_FromFile(p_s[1], cmdstring, rd_mode, _PyPclose)) != NULL)
3100 PyFile_SetBufSize(p_f[1], bufsize);
3101 if (n == POPEN_3)
3102 {
3103 if ((p_f[2] = PyFile_FromFile(p_s[2], cmdstring, rd_mode, _PyPclose)) != NULL)
3104 PyFile_SetBufSize(p_f[0], bufsize);
3105 f = PyTuple_Pack(3, p_f[0], p_f[1], p_f[2]);
3106 }
3107 else
3108 f = PyTuple_Pack(2, p_f[0], p_f[1]);
3109
3110 /*
3111 * Insert the files we've created into the process dictionary
3112 * all referencing the list with the process handle and the
3113 * initial number of files (see description below in _PyPclose).
3114 * Since if _PyPclose later tried to wait on a process when all
3115 * handles weren't closed, it could create a deadlock with the
3116 * child, we spend some energy here to try to ensure that we
3117 * either insert all file handles into the dictionary or none
3118 * at all. It's a little clumsy with the various popen modes
3119 * and variable number of files involved.
3120 */
3121 if (!_PyPopenProcs)
3122 {
3123 _PyPopenProcs = PyDict_New();
3124 }
3125
3126 if (_PyPopenProcs)
3127 {
3128 PyObject *procObj, *pidObj, *intObj, *fileObj[3];
3129 int ins_rc[3];
3130
3131 fileObj[0] = fileObj[1] = fileObj[2] = NULL;
3132 ins_rc[0] = ins_rc[1] = ins_rc[2] = 0;
3133
3134 procObj = PyList_New(2);
3135 pidObj = PyLong_FromPid(pipe_pid);
3136 intObj = PyInt_FromLong((long) file_count);
3137
3138 if (procObj && pidObj && intObj)
3139 {
3140 PyList_SetItem(procObj, 0, pidObj);
3141 PyList_SetItem(procObj, 1, intObj);
3142
3143 fileObj[0] = PyLong_FromVoidPtr(p_s[0]);
3144 if (fileObj[0])
3145 {
3146 ins_rc[0] = PyDict_SetItem(_PyPopenProcs,
3147 fileObj[0],
3148 procObj);
3149 }
3150 fileObj[1] = PyLong_FromVoidPtr(p_s[1]);
3151 if (fileObj[1])
3152 {
3153 ins_rc[1] = PyDict_SetItem(_PyPopenProcs,
3154 fileObj[1],
3155 procObj);
3156 }
3157 if (file_count >= 3)
3158 {
3159 fileObj[2] = PyLong_FromVoidPtr(p_s[2]);
3160 if (fileObj[2])
3161 {
3162 ins_rc[2] = PyDict_SetItem(_PyPopenProcs,
3163 fileObj[2],
3164 procObj);
3165 }
3166 }
3167
3168 if (ins_rc[0] < 0 || !fileObj[0] ||
3169 ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) ||
3170 ins_rc[2] < 0 || (file_count > 2 && !fileObj[2]))
3171 {
3172 /* Something failed - remove any dictionary
3173 * entries that did make it.
3174 */
3175 if (!ins_rc[0] && fileObj[0])
3176 {
3177 PyDict_DelItem(_PyPopenProcs,
3178 fileObj[0]);
3179 }
3180 if (!ins_rc[1] && fileObj[1])
3181 {
3182 PyDict_DelItem(_PyPopenProcs,
3183 fileObj[1]);
3184 }
3185 if (!ins_rc[2] && fileObj[2])
3186 {
3187 PyDict_DelItem(_PyPopenProcs,
3188 fileObj[2]);
3189 }
3190 }
3191 }
3192
3193 /*
3194 * Clean up our localized references for the dictionary keys
3195 * and value since PyDict_SetItem will Py_INCREF any copies
3196 * that got placed in the dictionary.
3197 */
3198 Py_XDECREF(procObj);
3199 Py_XDECREF(fileObj[0]);
3200 Py_XDECREF(fileObj[1]);
3201 Py_XDECREF(fileObj[2]);
3202 }
3203
3204 /* Child is launched. */
3205 return f;
3206 }
3207
3208 /*
3209 * Wrapper for fclose() to use for popen* files, so we can retrieve the
3210 * exit code for the child process and return as a result of the close.
3211 *
3212 * This function uses the _PyPopenProcs dictionary in order to map the
3213 * input file pointer to information about the process that was
3214 * originally created by the popen* call that created the file pointer.
3215 * The dictionary uses the file pointer as a key (with one entry
3216 * inserted for each file returned by the original popen* call) and a
3217 * single list object as the value for all files from a single call.
3218 * The list object contains the Win32 process handle at [0], and a file
3219 * count at [1], which is initialized to the total number of file
3220 * handles using that list.
3221 *
3222 * This function closes whichever handle it is passed, and decrements
3223 * the file count in the dictionary for the process handle pointed to
3224 * by this file. On the last close (when the file count reaches zero),
3225 * this function will wait for the child process and then return its
3226 * exit code as the result of the close() operation. This permits the
3227 * files to be closed in any order - it is always the close() of the
3228 * final handle that will return the exit code.
3229 *
3230 * NOTE: This function is currently called with the GIL released.
3231 * hence we use the GILState API to manage our state.
3232 */
3233
3234 static int _PyPclose(FILE *file)
3235 {
3236 int result;
3237 int exit_code;
3238 pid_t pipe_pid;
3239 PyObject *procObj, *pidObj, *intObj, *fileObj;
3240 int file_count;
3241 #ifdef WITH_THREAD
3242 PyGILState_STATE state;
3243 #endif
3244
3245 /* Close the file handle first, to ensure it can't block the
3246 * child from exiting if it's the last handle.
3247 */
3248 result = fclose(file);
3249
3250 #ifdef WITH_THREAD
3251 state = PyGILState_Ensure();
3252 #endif
3253 if (_PyPopenProcs)
3254 {
3255 if ((fileObj = PyLong_FromVoidPtr(file)) != NULL &&
3256 (procObj = PyDict_GetItem(_PyPopenProcs,
3257 fileObj)) != NULL &&
3258 (pidObj = PyList_GetItem(procObj,0)) != NULL &&
3259 (intObj = PyList_GetItem(procObj,1)) != NULL)
3260 {
3261 pipe_pid = (pid_t) PyLong_AsPid(pidObj);
3262 file_count = (int) PyInt_AsLong(intObj);
3263
3264 if (file_count > 1)
3265 {
3266 /* Still other files referencing process */
3267 file_count--;
3268 PyList_SetItem(procObj,1,
3269 PyInt_FromLong((long) file_count));
3270 }
3271 else
3272 {
3273 /* Last file for this process */
3274 if (result != EOF &&
3275 waitpid(pipe_pid, &exit_code, 0) == pipe_pid)
3276 {
3277 /* extract exit status */
3278 if (WIFEXITED(exit_code))
3279 {
3280 result = WEXITSTATUS(exit_code);
3281 }
3282 else
3283 {
3284 errno = EPIPE;
3285 result = -1;
3286 }
3287 }
3288 else
3289 {
3290 /* Indicate failure - this will cause the file object
3291 * to raise an I/O error and translate the last
3292 * error code from errno. We do have a problem with
3293 * last errors that overlap the normal errno table,
3294 * but that's a consistent problem with the file object.
3295 */
3296 result = -1;
3297 }
3298 }
3299
3300 /* Remove this file pointer from dictionary */
3301 PyDict_DelItem(_PyPopenProcs, fileObj);
3302
3303 if (PyDict_Size(_PyPopenProcs) == 0)
3304 {
3305 Py_DECREF(_PyPopenProcs);
3306 _PyPopenProcs = NULL;
3307 }
3308
3309 } /* if object retrieval ok */
3310
3311 Py_XDECREF(fileObj);
3312 } /* if _PyPopenProcs */
3313
3314 #ifdef WITH_THREAD
3315 PyGILState_Release(state);
3316 #endif
3317 return result;
3318 }
3319
3320 #endif /* PYCC_??? */
3321
3322 #elif defined(MS_WINDOWS)
3323
3324 /*
3325 * Portable 'popen' replacement for Win32.
3326 *
3327 * Written by Bill Tutt <billtut@microsoft.com>. Minor tweaks
3328 * and 2.0 integration by Fredrik Lundh <fredrik@pythonware.com>
3329 * Return code handling by David Bolen <db3l@fitlinxx.com>.
3330 */
3331
3332 #include <malloc.h>
3333 #include <io.h>
3334 #include <fcntl.h>
3335
3336 /* These tell _PyPopen() wether to return 1, 2, or 3 file objects. */
3337 #define POPEN_1 1
3338 #define POPEN_2 2
3339 #define POPEN_3 3
3340 #define POPEN_4 4
3341
3342 static PyObject *_PyPopen(char *, int, int);
3343 static int _PyPclose(FILE *file);
3344
3345 /*
3346 * Internal dictionary mapping popen* file pointers to process handles,
3347 * for use when retrieving the process exit code. See _PyPclose() below
3348 * for more information on this dictionary's use.
3349 */
3350 static PyObject *_PyPopenProcs = NULL;
3351
3352
3353 /* popen that works from a GUI.
3354 *
3355 * The result of this function is a pipe (file) connected to the
3356 * processes stdin or stdout, depending on the requested mode.
3357 */
3358
3359 static PyObject *
3360 posix_popen(PyObject *self, PyObject *args)
3361 {
3362 PyObject *f;
3363 int tm = 0;
3364
3365 char *cmdstring;
3366 char *mode = "r";
3367 int bufsize = -1;
3368 if (!PyArg_ParseTuple(args, "s|si:popen", &cmdstring, &mode, &bufsize))
3369 return NULL;
3370
3371 if (*mode == 'r')
3372 tm = _O_RDONLY;
3373 else if (*mode != 'w') {
3374 PyErr_SetString(PyExc_ValueError, "popen() arg 2 must be 'r' or 'w'");
3375 return NULL;
3376 } else
3377 tm = _O_WRONLY;
3378
3379 if (bufsize != -1) {
3380 PyErr_SetString(PyExc_ValueError, "popen() arg 3 must be -1");
3381 return NULL;
3382 }
3383
3384 if (*(mode+1) == 't')
3385 f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1);
3386 else if (*(mode+1) == 'b')
3387 f = _PyPopen(cmdstring, tm | _O_BINARY, POPEN_1);
3388 else
3389 f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1);
3390
3391 return f;
3392 }
3393
3394 /* Variation on win32pipe.popen
3395 *
3396 * The result of this function is a pipe (file) connected to the
3397 * process's stdin, and a pipe connected to the process's stdout.
3398 */
3399
3400 static PyObject *
3401 win32_popen2(PyObject *self, PyObject *args)
3402 {
3403 PyObject *f;
3404 int tm=0;
3405
3406 char *cmdstring;
3407 char *mode = "t";
3408 int bufsize = -1;
3409 if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize))
3410 return NULL;
3411
3412 if (*mode == 't')
3413 tm = _O_TEXT;
3414 else if (*mode != 'b') {
3415 PyErr_SetString(PyExc_ValueError, "popen2() arg 2 must be 't' or 'b'");
3416 return NULL;
3417 } else
3418 tm = _O_BINARY;
3419
3420 if (bufsize != -1) {
3421 PyErr_SetString(PyExc_ValueError, "popen2() arg 3 must be -1");
3422 return NULL;
3423 }
3424
3425 f = _PyPopen(cmdstring, tm, POPEN_2);
3426
3427 return f;
3428 }
3429
3430 /*
3431 * Variation on <om win32pipe.popen>
3432 *
3433 * The result of this function is 3 pipes - the process's stdin,
3434 * stdout and stderr
3435 */
3436
3437 static PyObject *
3438 win32_popen3(PyObject *self, PyObject *args)
3439 {
3440 PyObject *f;
3441 int tm = 0;
3442
3443 char *cmdstring;
3444 char *mode = "t";
3445 int bufsize = -1;
3446 if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize))
3447 return NULL;
3448
3449 if (*mode == 't')
3450 tm = _O_TEXT;
3451 else if (*mode != 'b') {
3452 PyErr_SetString(PyExc_ValueError, "popen3() arg 2 must be 't' or 'b'");
3453 return NULL;
3454 } else
3455 tm = _O_BINARY;
3456
3457 if (bufsize != -1) {
3458 PyErr_SetString(PyExc_ValueError, "popen3() arg 3 must be -1");
3459 return NULL;
3460 }
3461
3462 f = _PyPopen(cmdstring, tm, POPEN_3);
3463
3464 return f;
3465 }
3466
3467 /*
3468 * Variation on win32pipe.popen
3469 *
3470 * The result of this function is 2 pipes - the processes stdin,
3471 * and stdout+stderr combined as a single pipe.
3472 */
3473
3474 static PyObject *
3475 win32_popen4(PyObject *self, PyObject *args)
3476 {
3477 PyObject *f;
3478 int tm = 0;
3479
3480 char *cmdstring;
3481 char *mode = "t";
3482 int bufsize = -1;
3483 if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize))
3484 return NULL;
3485
3486 if (*mode == 't')
3487 tm = _O_TEXT;
3488 else if (*mode != 'b') {
3489 PyErr_SetString(PyExc_ValueError, "popen4() arg 2 must be 't' or 'b'");
3490 return NULL;
3491 } else
3492 tm = _O_BINARY;
3493
3494 if (bufsize != -1) {
3495 PyErr_SetString(PyExc_ValueError, "popen4() arg 3 must be -1");
3496 return NULL;
3497 }
3498
3499 f = _PyPopen(cmdstring, tm, POPEN_4);
3500
3501 return f;
3502 }
3503
3504 static BOOL
3505 _PyPopenCreateProcess(char *cmdstring,
3506 HANDLE hStdin,
3507 HANDLE hStdout,
3508 HANDLE hStderr,
3509 HANDLE *hProcess)
3510 {
3511 PROCESS_INFORMATION piProcInfo;
3512 STARTUPINFO siStartInfo;
3513 DWORD dwProcessFlags = 0; /* no NEW_CONSOLE by default for Ctrl+C handling */
3514 char *s1,*s2, *s3 = " /c ";
3515 const char *szConsoleSpawn = "w9xpopen.exe";
3516 int i;
3517 Py_ssize_t x;
3518
3519 if (i = GetEnvironmentVariable("COMSPEC",NULL,0)) {
3520 char *comshell;
3521
3522 s1 = (char *)alloca(i);
3523 if (!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
3524 /* x < i, so x fits into an integer */
3525 return (int)x;
3526
3527 /* Explicitly check if we are using COMMAND.COM. If we are
3528 * then use the w9xpopen hack.
3529 */
3530 comshell = s1 + x;
3531 while (comshell >= s1 && *comshell != '\\')
3532 --comshell;
3533 ++comshell;
3534
3535 if (GetVersion() < 0x80000000 &&
3536 _stricmp(comshell, "command.com") != 0) {
3537 /* NT/2000 and not using command.com. */
3538 x = i + strlen(s3) + strlen(cmdstring) + 1;
3539 s2 = (char *)alloca(x);
3540 ZeroMemory(s2, x);
3541 PyOS_snprintf(s2, x, "%s%s%s", s1, s3, cmdstring);
3542 }
3543 else {
3544 /*
3545 * Oh gag, we're on Win9x or using COMMAND.COM. Use
3546 * the workaround listed in KB: Q150956
3547 */
3548 char modulepath[_MAX_PATH];
3549 struct stat statinfo;
3550 GetModuleFileName(NULL, modulepath, sizeof(modulepath));
3551 for (x = i = 0; modulepath[i]; i++)
3552 if (modulepath[i] == SEP)
3553 x = i+1;
3554 modulepath[x] = '\0';
3555 /* Create the full-name to w9xpopen, so we can test it exists */
3556 strncat(modulepath,
3557 szConsoleSpawn,
3558 (sizeof(modulepath)/sizeof(modulepath[0]))
3559 -strlen(modulepath));
3560 if (stat(modulepath, &statinfo) != 0) {
3561 size_t mplen = sizeof(modulepath)/sizeof(modulepath[0]);
3562 /* Eeek - file-not-found - possibly an embedding
3563 situation - see if we can locate it in sys.prefix
3564 */
3565 strncpy(modulepath,
3566 Py_GetExecPrefix(),
3567 mplen);
3568 modulepath[mplen-1] = '\0';
3569 if (modulepath[strlen(modulepath)-1] != '\\')
3570 strcat(modulepath, "\\");
3571 strncat(modulepath,
3572 szConsoleSpawn,
3573 mplen-strlen(modulepath));
3574 /* No where else to look - raise an easily identifiable
3575 error, rather than leaving Windows to report
3576 "file not found" - as the user is probably blissfully
3577 unaware this shim EXE is used, and it will confuse them.
3578 (well, it confused me for a while ;-)
3579 */
3580 if (stat(modulepath, &statinfo) != 0) {
3581 PyErr_Format(PyExc_RuntimeError,
3582 "Can not locate '%s' which is needed "
3583 "for popen to work with your shell "
3584 "or platform.",
3585 szConsoleSpawn);
3586 return FALSE;
3587 }
3588 }
3589 x = i + strlen(s3) + strlen(cmdstring) + 1 +
3590 strlen(modulepath) +
3591 strlen(szConsoleSpawn) + 1;
3592
3593 s2 = (char *)alloca(x);
3594 ZeroMemory(s2, x);
3595 /* To maintain correct argument passing semantics,
3596 we pass the command-line as it stands, and allow
3597 quoting to be applied. w9xpopen.exe will then
3598 use its argv vector, and re-quote the necessary
3599 args for the ultimate child process.
3600 */
3601 PyOS_snprintf(
3602 s2, x,
3603 "\"%s\" %s%s%s",
3604 modulepath,
3605 s1,
3606 s3,
3607 cmdstring);
3608 /* Not passing CREATE_NEW_CONSOLE has been known to
3609 cause random failures on win9x. Specifically a
3610 dialog:
3611 "Your program accessed mem currently in use at xxx"
3612 and a hopeful warning about the stability of your
3613 system.
3614 Cost is Ctrl+C won't kill children, but anyone
3615 who cares can have a go!
3616 */
3617 dwProcessFlags |= CREATE_NEW_CONSOLE;
3618 }
3619 }
3620
3621 /* Could be an else here to try cmd.exe / command.com in the path
3622 Now we'll just error out.. */
3623 else {
3624 PyErr_SetString(PyExc_RuntimeError,
3625 "Cannot locate a COMSPEC environment variable to "
3626 "use as the shell");
3627 return FALSE;
3628 }
3629
3630 ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
3631 siStartInfo.cb = sizeof(STARTUPINFO);
3632 siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
3633 siStartInfo.hStdInput = hStdin;
3634 siStartInfo.hStdOutput = hStdout;
3635 siStartInfo.hStdError = hStderr;
3636 siStartInfo.wShowWindow = SW_HIDE;
3637
3638 if (CreateProcess(NULL,
3639 s2,
3640 NULL,
3641 NULL,
3642 TRUE,
3643 dwProcessFlags,
3644 NULL,
3645 NULL,
3646 &siStartInfo,
3647 &piProcInfo) ) {
3648 /* Close the handles now so anyone waiting is woken. */
3649 CloseHandle(piProcInfo.hThread);
3650
3651 /* Return process handle */
3652 *hProcess = piProcInfo.hProcess;
3653 return TRUE;
3654 }
3655 win32_error("CreateProcess", s2);
3656 return FALSE;
3657 }
3658
3659 /* The following code is based off of KB: Q190351 */
3660
3661 static PyObject *
3662 _PyPopen(char *cmdstring, int mode, int n)
3663 {
3664 HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr,
3665 hChildStderrRd, hChildStderrWr, hChildStdinWrDup, hChildStdoutRdDup,
3666 hChildStderrRdDup, hProcess; /* hChildStdoutWrDup; */
3667
3668 SECURITY_ATTRIBUTES saAttr;
3669 BOOL fSuccess;
3670 int fd1, fd2, fd3;
3671 FILE *f1, *f2, *f3;
3672 long file_count;
3673 PyObject *f;
3674
3675 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
3676 saAttr.bInheritHandle = TRUE;
3677 saAttr.lpSecurityDescriptor = NULL;
3678
3679 if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
3680 return win32_error("CreatePipe", NULL);
3681
3682 /* Create new output read handle and the input write handle. Set
3683 * the inheritance properties to FALSE. Otherwise, the child inherits
3684 * these handles; resulting in non-closeable handles to the pipes
3685 * being created. */
3686 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
3687 GetCurrentProcess(), &hChildStdinWrDup, 0,
3688 FALSE,
3689 DUPLICATE_SAME_ACCESS);
3690 if (!fSuccess)
3691 return win32_error("DuplicateHandle", NULL);
3692
3693 /* Close the inheritable version of ChildStdin
3694 that we're using. */
3695 CloseHandle(hChildStdinWr);
3696
3697 if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
3698 return win32_error("CreatePipe", NULL);
3699
3700 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
3701 GetCurrentProcess(), &hChildStdoutRdDup, 0,
3702 FALSE, DUPLICATE_SAME_ACCESS);
3703 if (!fSuccess)
3704 return win32_error("DuplicateHandle", NULL);
3705
3706 /* Close the inheritable version of ChildStdout
3707 that we're using. */
3708 CloseHandle(hChildStdoutRd);
3709
3710 if (n != POPEN_4) {
3711 if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
3712 return win32_error("CreatePipe", NULL);
3713 fSuccess = DuplicateHandle(GetCurrentProcess(),
3714 hChildStderrRd,
3715 GetCurrentProcess(),
3716 &hChildStderrRdDup, 0,
3717 FALSE, DUPLICATE_SAME_ACCESS);
3718 if (!fSuccess)
3719 return win32_error("DuplicateHandle", NULL);
3720 /* Close the inheritable version of ChildStdErr that we're using. */
3721 CloseHandle(hChildStderrRd);
3722 }
3723
3724 switch (n) {
3725 case POPEN_1:
3726 switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY)) {
3727 case _O_WRONLY | _O_TEXT:
3728 /* Case for writing to child Stdin in text mode. */
3729 fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
3730 f1 = _fdopen(fd1, "w");
3731 f = PyFile_FromFile(f1, cmdstring, "w", _PyPclose);
3732 PyFile_SetBufSize(f, 0);
3733 /* We don't care about these pipes anymore, so close them. */
3734 CloseHandle(hChildStdoutRdDup);
3735 CloseHandle(hChildStderrRdDup);
3736 break;
3737
3738 case _O_RDONLY | _O_TEXT:
3739 /* Case for reading from child Stdout in text mode. */
3740 fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
3741 f1 = _fdopen(fd1, "r");
3742 f = PyFile_FromFile(f1, cmdstring, "r", _PyPclose);
3743 PyFile_SetBufSize(f, 0);
3744 /* We don't care about these pipes anymore, so close them. */
3745 CloseHandle(hChildStdinWrDup);
3746 CloseHandle(hChildStderrRdDup);
3747 break;
3748
3749 case _O_RDONLY | _O_BINARY:
3750 /* Case for readinig from child Stdout in binary mode. */
3751 fd1 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
3752 f1 = _fdopen(fd1, "rb");
3753 f = PyFile_FromFile(f1, cmdstring, "rb", _PyPclose);
3754 PyFile_SetBufSize(f, 0);
3755 /* We don't care about these pipes anymore, so close them. */
3756 CloseHandle(hChildStdinWrDup);
3757 CloseHandle(hChildStderrRdDup);
3758 break;
3759
3760 case _O_WRONLY | _O_BINARY:
3761 /* Case for writing to child Stdin in binary mode. */
3762 fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
3763 f1 = _fdopen(fd1, "wb");
3764 f = PyFile_FromFile(f1, cmdstring, "wb", _PyPclose);
3765 PyFile_SetBufSize(f, 0);
3766 /* We don't care about these pipes anymore, so close them. */
3767 CloseHandle(hChildStdoutRdDup);
3768 CloseHandle(hChildStderrRdDup);
3769 break;
3770 }
3771 file_count = 1;
3772 break;
3773
3774 case POPEN_2:
3775 case POPEN_4:
3776 {
3777 char *m1, *m2;
3778 PyObject *p1, *p2;
3779
3780 if (mode & _O_TEXT) {
3781 m1 = "r";
3782 m2 = "w";
3783 } else {
3784 m1 = "rb";
3785 m2 = "wb";
3786 }
3787
3788 fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
3789 f1 = _fdopen(fd1, m2);
3790 fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
3791 f2 = _fdopen(fd2, m1);
3792 p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
3793 PyFile_SetBufSize(p1, 0);
3794 p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose);
3795 PyFile_SetBufSize(p2, 0);
3796
3797 if (n != 4)
3798 CloseHandle(hChildStderrRdDup);
3799
3800 f = PyTuple_Pack(2,p1,p2);
3801 Py_XDECREF(p1);
3802 Py_XDECREF(p2);
3803 file_count = 2;
3804 break;
3805 }
3806
3807 case POPEN_3:
3808 {
3809 char *m1, *m2;
3810 PyObject *p1, *p2, *p3;
3811
3812 if (mode & _O_TEXT) {
3813 m1 = "r";
3814 m2 = "w";
3815 } else {
3816 m1 = "rb";
3817 m2 = "wb";
3818 }
3819
3820 fd1 = _open_osfhandle((Py_intptr_t)hChildStdinWrDup, mode);
3821 f1 = _fdopen(fd1, m2);
3822 fd2 = _open_osfhandle((Py_intptr_t)hChildStdoutRdDup, mode);
3823 f2 = _fdopen(fd2, m1);
3824 fd3 = _open_osfhandle((Py_intptr_t)hChildStderrRdDup, mode);
3825 f3 = _fdopen(fd3, m1);
3826 p1 = PyFile_FromFile(f1, cmdstring, m2, _PyPclose);
3827 p2 = PyFile_FromFile(f2, cmdstring, m1, _PyPclose);
3828 p3 = PyFile_FromFile(f3, cmdstring, m1, _PyPclose);
3829 PyFile_SetBufSize(p1, 0);
3830 PyFile_SetBufSize(p2, 0);
3831 PyFile_SetBufSize(p3, 0);
3832 f = PyTuple_Pack(3,p1,p2,p3);
3833 Py_XDECREF(p1);
3834 Py_XDECREF(p2);
3835 Py_XDECREF(p3);
3836 file_count = 3;
3837 break;
3838 }
3839 }
3840
3841 if (n == POPEN_4) {
3842 if (!_PyPopenCreateProcess(cmdstring,
3843 hChildStdinRd,
3844 hChildStdoutWr,
3845 hChildStdoutWr,
3846 &hProcess))
3847 return NULL;
3848 }
3849 else {
3850 if (!_PyPopenCreateProcess(cmdstring,
3851 hChildStdinRd,
3852 hChildStdoutWr,
3853 hChildStderrWr,
3854 &hProcess))
3855 return NULL;
3856 }
3857
3858 /*
3859 * Insert the files we've created into the process dictionary
3860 * all referencing the list with the process handle and the
3861 * initial number of files (see description below in _PyPclose).
3862 * Since if _PyPclose later tried to wait on a process when all
3863 * handles weren't closed, it could create a deadlock with the
3864 * child, we spend some energy here to try to ensure that we
3865 * either insert all file handles into the dictionary or none
3866 * at all. It's a little clumsy with the various popen modes
3867 * and variable number of files involved.
3868 */
3869 if (!_PyPopenProcs) {
3870 _PyPopenProcs = PyDict_New();
3871 }
3872
3873 if (_PyPopenProcs) {
3874 PyObject *procObj, *hProcessObj, *intObj, *fileObj[3];
3875 int ins_rc[3];
3876
3877 fileObj[0] = fileObj[1] = fileObj[2] = NULL;
3878 ins_rc[0] = ins_rc[1] = ins_rc[2] = 0;
3879
3880 procObj = PyList_New(2);
3881 hProcessObj = PyLong_FromVoidPtr(hProcess);
3882 intObj = PyInt_FromLong(file_count);
3883
3884 if (procObj && hProcessObj && intObj) {
3885 PyList_SetItem(procObj,0,hProcessObj);
3886 PyList_SetItem(procObj,1,intObj);
3887
3888 fileObj[0] = PyLong_FromVoidPtr(f1);
3889 if (fileObj[0]) {
3890 ins_rc[0] = PyDict_SetItem(_PyPopenProcs,
3891 fileObj[0],
3892 procObj);
3893 }
3894 if (file_count >= 2) {
3895 fileObj[1] = PyLong_FromVoidPtr(f2);
3896 if (fileObj[1]) {
3897 ins_rc[1] = PyDict_SetItem(_PyPopenProcs,
3898 fileObj[1],
3899 procObj);
3900 }
3901 }
3902 if (file_count >= 3) {
3903 fileObj[2] = PyLong_FromVoidPtr(f3);
3904 if (fileObj[2]) {
3905 ins_rc[2] = PyDict_SetItem(_PyPopenProcs,
3906 fileObj[2],
3907 procObj);
3908 }
3909 }
3910
3911 if (ins_rc[0] < 0 || !fileObj[0] ||
3912 ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) ||
3913 ins_rc[2] < 0 || (file_count > 2 && !fileObj[2])) {
3914 /* Something failed - remove any dictionary
3915 * entries that did make it.
3916 */
3917 if (!ins_rc[0] && fileObj[0]) {
3918 PyDict_DelItem(_PyPopenProcs,
3919 fileObj[0]);
3920 }
3921 if (!ins_rc[1] && fileObj[1]) {
3922 PyDict_DelItem(_PyPopenProcs,
3923 fileObj[1]);
3924 }
3925 if (!ins_rc[2] && fileObj[2]) {
3926 PyDict_DelItem(_PyPopenProcs,
3927 fileObj[2]);
3928 }
3929 }
3930 }
3931
3932 /*
3933 * Clean up our localized references for the dictionary keys
3934 * and value since PyDict_SetItem will Py_INCREF any copies
3935 * that got placed in the dictionary.
3936 */
3937 Py_XDECREF(procObj);
3938 Py_XDECREF(fileObj[0]);
3939 Py_XDECREF(fileObj[1]);
3940 Py_XDECREF(fileObj[2]);
3941 }
3942
3943 /* Child is launched. Close the parents copy of those pipe
3944 * handles that only the child should have open. You need to
3945 * make sure that no handles to the write end of the output pipe
3946 * are maintained in this process or else the pipe will not close
3947 * when the child process exits and the ReadFile will hang. */
3948
3949 if (!CloseHandle(hChildStdinRd))
3950 return win32_error("CloseHandle", NULL);
3951
3952 if (!CloseHandle(hChildStdoutWr))
3953 return win32_error("CloseHandle", NULL);
3954
3955 if ((n != 4) && (!CloseHandle(hChildStderrWr)))
3956 return win32_error("CloseHandle", NULL);
3957
3958 return f;
3959 }
3960
3961 /*
3962 * Wrapper for fclose() to use for popen* files, so we can retrieve the
3963 * exit code for the child process and return as a result of the close.
3964 *
3965 * This function uses the _PyPopenProcs dictionary in order to map the
3966 * input file pointer to information about the process that was
3967 * originally created by the popen* call that created the file pointer.
3968 * The dictionary uses the file pointer as a key (with one entry
3969 * inserted for each file returned by the original popen* call) and a
3970 * single list object as the value for all files from a single call.
3971 * The list object contains the Win32 process handle at [0], and a file
3972 * count at [1], which is initialized to the total number of file
3973 * handles using that list.
3974 *
3975 * This function closes whichever handle it is passed, and decrements
3976 * the file count in the dictionary for the process handle pointed to
3977 * by this file. On the last close (when the file count reaches zero),
3978 * this function will wait for the child process and then return its
3979 * exit code as the result of the close() operation. This permits the
3980 * files to be closed in any order - it is always the close() of the
3981 * final handle that will return the exit code.
3982 *
3983 * NOTE: This function is currently called with the GIL released.
3984 * hence we use the GILState API to manage our state.
3985 */
3986
3987 static int _PyPclose(FILE *file)
3988 {
3989 int result;
3990 DWORD exit_code;
3991 HANDLE hProcess;
3992 PyObject *procObj, *hProcessObj, *intObj, *fileObj;
3993 long file_count;
3994 #ifdef WITH_THREAD
3995 PyGILState_STATE state;
3996 #endif
3997
3998 /* Close the file handle first, to ensure it can't block the
3999 * child from exiting if it's the last handle.
4000 */
4001 result = fclose(file);
4002 #ifdef WITH_THREAD
4003 state = PyGILState_Ensure();
4004 #endif
4005 if (_PyPopenProcs) {
4006 if ((fileObj = PyLong_FromVoidPtr(file)) != NULL &&
4007 (procObj = PyDict_GetItem(_PyPopenProcs,
4008 fileObj)) != NULL &&
4009 (hProcessObj = PyList_GetItem(procObj,0)) != NULL &&
4010 (intObj = PyList_GetItem(procObj,1)) != NULL) {
4011
4012 hProcess = PyLong_AsVoidPtr(hProcessObj);
4013 file_count = PyInt_AsLong(intObj);
4014
4015 if (file_count > 1) {
4016 /* Still other files referencing process */
4017 file_count--;
4018 PyList_SetItem(procObj,1,
4019 PyInt_FromLong(file_count));
4020 } else {
4021 /* Last file for this process */
4022 if (result != EOF &&
4023 WaitForSingleObject(hProcess, INFINITE) != WAIT_FAILED &&
4024 GetExitCodeProcess(hProcess, &exit_code)) {
4025 /* Possible truncation here in 16-bit environments, but
4026 * real exit codes are just the lower byte in any event.
4027 */
4028 result = exit_code;
4029 } else {
4030 /* Indicate failure - this will cause the file object
4031 * to raise an I/O error and translate the last Win32
4032 * error code from errno. We do have a problem with
4033 * last errors that overlap the normal errno table,
4034 * but that's a consistent problem with the file object.
4035 */
4036 if (result != EOF) {
4037 /* If the error wasn't from the fclose(), then
4038 * set errno for the file object error handling.
4039 */
4040 errno = GetLastError();
4041 }
4042 result = -1;
4043 }
4044
4045 /* Free up the native handle at this point */
4046 CloseHandle(hProcess);
4047 }
4048
4049 /* Remove this file pointer from dictionary */
4050 PyDict_DelItem(_PyPopenProcs, fileObj);
4051
4052 if (PyDict_Size(_PyPopenProcs) == 0) {
4053 Py_DECREF(_PyPopenProcs);
4054 _PyPopenProcs = NULL;
4055 }
4056
4057 } /* if object retrieval ok */
4058
4059 Py_XDECREF(fileObj);
4060 } /* if _PyPopenProcs */
4061
4062 #ifdef WITH_THREAD
4063 PyGILState_Release(state);
4064 #endif
4065 return result;
4066 }
4067
4068 #else /* which OS? */
4069 static PyObject *
4070 posix_popen(PyObject *self, PyObject *args)
4071 {
4072 char *name;
4073 char *mode = "r";
4074 int bufsize = -1;
4075 FILE *fp;
4076 PyObject *f;
4077 if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize))
4078 return NULL;
4079 /* Strip mode of binary or text modifiers */
4080 if (strcmp(mode, "rb") == 0 || strcmp(mode, "rt") == 0)
4081 mode = "r";
4082 else if (strcmp(mode, "wb") == 0 || strcmp(mode, "wt") == 0)
4083 mode = "w";
4084 Py_BEGIN_ALLOW_THREADS
4085 fp = popen(name, mode);
4086 Py_END_ALLOW_THREADS
4087 if (fp == NULL)
4088 return posix_error();
4089 f = PyFile_FromFile(fp, name, mode, pclose);
4090 if (f != NULL)
4091 PyFile_SetBufSize(f, bufsize);
4092 return f;
4093 }
4094
4095 #endif /* PYOS_??? */
4096 #endif /* HAVE_POPEN */
4097
4098
4099 #ifdef HAVE_SETUID
4100 PyDoc_STRVAR(posix_setuid__doc__,
4101 "setuid(uid)\n\n\
4102 Set the current process's user id.");
4103
4104 static PyObject *
4105 posix_setuid(PyObject *self, PyObject *args)
4106 {
4107 long uid_arg;
4108 uid_t uid;
4109 if (!PyArg_ParseTuple(args, "l:setuid", &uid_arg))
4110 return NULL;
4111 uid = uid_arg;
4112 if (uid != uid_arg) {
4113 PyErr_SetString(PyExc_OverflowError, "user id too big");
4114 return NULL;
4115 }
4116 if (setuid(uid) < 0)
4117 return posix_error();
4118 Py_INCREF(Py_None);
4119 return Py_None;
4120 }
4121 #endif /* HAVE_SETUID */
4122
4123
4124 #ifdef HAVE_SETEUID
4125 PyDoc_STRVAR(posix_seteuid__doc__,
4126 "seteuid(uid)\n\n\
4127 Set the current process's effective user id.");
4128
4129 static PyObject *
4130 posix_seteuid (PyObject *self, PyObject *args)
4131 {
4132 long euid_arg;
4133 uid_t euid;
4134 if (!PyArg_ParseTuple(args, "l", &euid_arg))
4135 return NULL;
4136 euid = euid_arg;
4137 if (euid != euid_arg) {
4138 PyErr_SetString(PyExc_OverflowError, "user id too big");
4139 return NULL;
4140 }
4141 if (seteuid(euid) < 0) {
4142 return posix_error();
4143 } else {
4144 Py_INCREF(Py_None);
4145 return Py_None;
4146 }
4147 }
4148 #endif /* HAVE_SETEUID */
4149
4150 #ifdef HAVE_SETEGID
4151 PyDoc_STRVAR(posix_setegid__doc__,
4152 "setegid(gid)\n\n\
4153 Set the current process's effective group id.");
4154
4155 static PyObject *
4156 posix_setegid (PyObject *self, PyObject *args)
4157 {
4158 long egid_arg;
4159 gid_t egid;
4160 if (!PyArg_ParseTuple(args, "l", &egid_arg))
4161 return NULL;
4162 egid = egid_arg;
4163 if (egid != egid_arg) {
4164 PyErr_SetString(PyExc_OverflowError, "group id too big");
4165 return NULL;
4166 }
4167 if (setegid(egid) < 0) {
4168 return posix_error();
4169 } else {
4170 Py_INCREF(Py_None);
4171 return Py_None;
4172 }
4173 }
4174 #endif /* HAVE_SETEGID */
4175
4176 #ifdef HAVE_SETREUID
4177 PyDoc_STRVAR(posix_setreuid__doc__,
4178 "setreuid(ruid, euid)\n\n\
4179 Set the current process's real and effective user ids.");
4180
4181 static PyObject *
4182 posix_setreuid (PyObject *self, PyObject *args)
4183 {
4184 long ruid_arg, euid_arg;
4185 uid_t ruid, euid;
4186 if (!PyArg_ParseTuple(args, "ll", &ruid_arg, &euid_arg))
4187 return NULL;
4188 if (ruid_arg == -1)
4189 ruid = (uid_t)-1; /* let the compiler choose how -1 fits */
4190 else
4191 ruid = ruid_arg; /* otherwise, assign from our long */
4192 if (euid_arg == -1)
4193 euid = (uid_t)-1;
4194 else
4195 euid = euid_arg;
4196 if ((euid_arg != -1 && euid != euid_arg) ||
4197 (ruid_arg != -1 && ruid != ruid_arg)) {
4198 PyErr_SetString(PyExc_OverflowError, "user id too big");
4199 return NULL;
4200 }
4201 if (setreuid(ruid, euid) < 0) {
4202 return posix_error();
4203 } else {
4204 Py_INCREF(Py_None);
4205 return Py_None;
4206 }
4207 }
4208 #endif /* HAVE_SETREUID */
4209
4210 #ifdef HAVE_SETREGID
4211 PyDoc_STRVAR(posix_setregid__doc__,
4212 "setregid(rgid, egid)\n\n\
4213 Set the current process's real and effective group ids.");
4214
4215 static PyObject *
4216 posix_setregid (PyObject *self, PyObject *args)
4217 {
4218 long rgid_arg, egid_arg;
4219 gid_t rgid, egid;
4220 if (!PyArg_ParseTuple(args, "ll", &rgid_arg, &egid_arg))
4221 return NULL;
4222 if (rgid_arg == -1)
4223 rgid = (gid_t)-1; /* let the compiler choose how -1 fits */
4224 else
4225 rgid = rgid_arg; /* otherwise, assign from our long */
4226 if (egid_arg == -1)
4227 egid = (gid_t)-1;
4228 else
4229 egid = egid_arg;
4230 if ((egid_arg != -1 && egid != egid_arg) ||
4231 (rgid_arg != -1 && rgid != rgid_arg)) {
4232 PyErr_SetString(PyExc_OverflowError, "group id too big");
4233 return NULL;
4234 }
4235 if (setregid(rgid, egid) < 0) {
4236 return posix_error();
4237 } else {
4238 Py_INCREF(Py_None);
4239 return Py_None;
4240 }
4241 }
4242 #endif /* HAVE_SETREGID */
4243
4244 #ifdef HAVE_SETGID
4245 PyDoc_STRVAR(posix_setgid__doc__,
4246 "setgid(gid)\n\n\
4247 Set the current process's group id.");
4248
4249 static PyObject *
4250 posix_setgid(PyObject *self, PyObject *args)
4251 {
4252 long gid_arg;
4253 gid_t gid;
4254 if (!PyArg_ParseTuple(args, "l:setgid", &gid_arg))
4255 return NULL;
4256 gid = gid_arg;
4257 if (gid != gid_arg) {
4258 PyErr_SetString(PyExc_OverflowError, "group id too big");
4259 return NULL;
4260 }
4261 if (setgid(gid) < 0)
4262 return posix_error();
4263 Py_INCREF(Py_None);
4264 return Py_None;
4265 }
4266 #endif /* HAVE_SETGID */
4267
4268 #ifdef HAVE_SETGROUPS
4269 PyDoc_STRVAR(posix_setgroups__doc__,
4270 "setgroups(list)\n\n\
4271 Set the groups of the current process to list.");
4272
4273 static PyObject *
4274 posix_setgroups(PyObject *self, PyObject *groups)
4275 {
4276 int i, len;
4277 gid_t grouplist[MAX_GROUPS];
4278
4279 if (!PySequence_Check(groups)) {
4280 PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
4281 return NULL;
4282 }
4283 len = PySequence_Size(groups);
4284 if (len > MAX_GROUPS) {
4285 PyErr_SetString(PyExc_ValueError, "too many groups");
4286 return NULL;
4287 }
4288 for(i = 0; i < len; i++) {
4289 PyObject *elem;
4290 elem = PySequence_GetItem(groups, i);
4291 if (!elem)
4292 return NULL;
4293 if (!PyInt_Check(elem)) {
4294 if (!PyLong_Check(elem)) {
4295 PyErr_SetString(PyExc_TypeError,
4296 "groups must be integers");
4297 Py_DECREF(elem);
4298 return NULL;
4299 } else {
4300 unsigned long x = PyLong_AsUnsignedLong(elem);
4301 if (PyErr_Occurred()) {
4302 PyErr_SetString(PyExc_TypeError,
4303 "group id too big");
4304 Py_DECREF(elem);
4305 return NULL;
4306 }
4307 grouplist[i] = x;
4308 /* read back to see if it fits in gid_t */
4309 if (grouplist[i] != x) {
4310 PyErr_SetString(PyExc_TypeError,
4311 "group id too big");
4312 Py_DECREF(elem);
4313 return NULL;
4314 }
4315 }
4316 } else {
4317 long x = PyInt_AsLong(elem);
4318 grouplist[i] = x;
4319 if (grouplist[i] != x) {
4320 PyErr_SetString(PyExc_TypeError,
4321 "group id too big");
4322 Py_DECREF(elem);
4323 return NULL;
4324 }
4325 }
4326 Py_DECREF(elem);
4327 }
4328
4329 if (setgroups(len, grouplist) < 0)
4330 return posix_error();
4331 Py_INCREF(Py_None);
4332 return Py_None;
4333 }
4334 #endif /* HAVE_SETGROUPS */
4335
4336 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
4337 static PyObject *
4338 wait_helper(pid_t pid, int status, struct rusage *ru)
4339 {
4340 PyObject *result;
4341 static PyObject *struct_rusage;
4342
4343 if (pid == -1)
4344 return posix_error();
4345
4346 if (struct_rusage == NULL) {
4347 PyObject *m = PyImport_ImportModuleNoBlock("resource");
4348 if (m == NULL)
4349 return NULL;
4350 struct_rusage = PyObject_GetAttrString(m, "struct_rusage");
4351 Py_DECREF(m);
4352 if (struct_rusage == NULL)
4353 return NULL;
4354 }
4355
4356 /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
4357 result = PyStructSequence_New((PyTypeObject*) struct_rusage);
4358 if (!result)
4359 return NULL;
4360
4361 #ifndef doubletime
4362 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
4363 #endif
4364
4365 PyStructSequence_SET_ITEM(result, 0,
4366 PyFloat_FromDouble(doubletime(ru->ru_utime)));
4367 PyStructSequence_SET_ITEM(result, 1,
4368 PyFloat_FromDouble(doubletime(ru->ru_stime)));
4369 #define SET_INT(result, index, value)\
4370 PyStructSequence_SET_ITEM(result, index, PyInt_FromLong(value))
4371 SET_INT(result, 2, ru->ru_maxrss);
4372 SET_INT(result, 3, ru->ru_ixrss);
4373 SET_INT(result, 4, ru->ru_idrss);
4374 SET_INT(result, 5, ru->ru_isrss);
4375 SET_INT(result, 6, ru->ru_minflt);
4376 SET_INT(result, 7, ru->ru_majflt);
4377 SET_INT(result, 8, ru->ru_nswap);
4378 SET_INT(result, 9, ru->ru_inblock);
4379 SET_INT(result, 10, ru->ru_oublock);
4380 SET_INT(result, 11, ru->ru_msgsnd);
4381 SET_INT(result, 12, ru->ru_msgrcv);
4382 SET_INT(result, 13, ru->ru_nsignals);
4383 SET_INT(result, 14, ru->ru_nvcsw);
4384 SET_INT(result, 15, ru->ru_nivcsw);
4385 #undef SET_INT
4386
4387 if (PyErr_Occurred()) {
4388 Py_DECREF(result);
4389 return NULL;
4390 }
4391
4392 return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
4393 }
4394 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
4395
4396 #ifdef HAVE_WAIT3
4397 PyDoc_STRVAR(posix_wait3__doc__,
4398 "wait3(options) -> (pid, status, rusage)\n\n\
4399 Wait for completion of a child process.");
4400
4401 static PyObject *
4402 posix_wait3(PyObject *self, PyObject *args)
4403 {
4404 pid_t pid;
4405 int options;
4406 struct rusage ru;
4407 WAIT_TYPE status;
4408 WAIT_STATUS_INT(status) = 0;
4409
4410 if (!PyArg_ParseTuple(args, "i:wait3", &options))
4411 return NULL;
4412
4413 Py_BEGIN_ALLOW_THREADS
4414 pid = wait3(&status, options, &ru);
4415 Py_END_ALLOW_THREADS
4416
4417 return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
4418 }
4419 #endif /* HAVE_WAIT3 */
4420
4421 #ifdef HAVE_WAIT4
4422 PyDoc_STRVAR(posix_wait4__doc__,
4423 "wait4(pid, options) -> (pid, status, rusage)\n\n\
4424 Wait for completion of a given child process.");
4425
4426 static PyObject *
4427 posix_wait4(PyObject *self, PyObject *args)
4428 {
4429 pid_t pid;
4430 int options;
4431 struct rusage ru;
4432 WAIT_TYPE status;
4433 WAIT_STATUS_INT(status) = 0;
4434
4435 if (!PyArg_ParseTuple(args, PARSE_PID "i:wait4", &pid, &options))
4436 return NULL;
4437
4438 Py_BEGIN_ALLOW_THREADS
4439 pid = wait4(pid, &status, options, &ru);
4440 Py_END_ALLOW_THREADS
4441
4442 return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
4443 }
4444 #endif /* HAVE_WAIT4 */
4445
4446 #ifdef HAVE_WAITPID
4447 PyDoc_STRVAR(posix_waitpid__doc__,
4448 "waitpid(pid, options) -> (pid, status)\n\n\
4449 Wait for completion of a given child process.");
4450
4451 static PyObject *
4452 posix_waitpid(PyObject *self, PyObject *args)
4453 {
4454 pid_t pid;
4455 int options;
4456 WAIT_TYPE status;
4457 WAIT_STATUS_INT(status) = 0;
4458
4459 if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options))
4460 return NULL;
4461 Py_BEGIN_ALLOW_THREADS
4462 pid = waitpid(pid, &status, options);
4463 Py_END_ALLOW_THREADS
4464 if (pid == -1)
4465 return posix_error();
4466
4467 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
4468 }
4469
4470 #elif defined(HAVE_CWAIT)
4471
4472 /* MS C has a variant of waitpid() that's usable for most purposes. */
4473 PyDoc_STRVAR(posix_waitpid__doc__,
4474 "waitpid(pid, options) -> (pid, status << 8)\n\n"
4475 "Wait for completion of a given process. options is ignored on Windows.");
4476
4477 static PyObject *
4478 posix_waitpid(PyObject *self, PyObject *args)
4479 {
4480 Py_intptr_t pid;
4481 int status, options;
4482
4483 if (!PyArg_ParseTuple(args, PARSE_PID "i:waitpid", &pid, &options))
4484 return NULL;
4485 Py_BEGIN_ALLOW_THREADS
4486 pid = _cwait(&status, pid, options);
4487 Py_END_ALLOW_THREADS
4488 if (pid == -1)
4489 return posix_error();
4490
4491 /* shift the status left a byte so this is more like the POSIX waitpid */
4492 return Py_BuildValue("Ni", PyLong_FromPid(pid), status << 8);
4493 }
4494 #endif /* HAVE_WAITPID || HAVE_CWAIT */
4495
4496 #ifdef HAVE_WAIT
4497 PyDoc_STRVAR(posix_wait__doc__,
4498 "wait() -> (pid, status)\n\n\
4499 Wait for completion of a child process.");
4500
4501 static PyObject *
4502 posix_wait(PyObject *self, PyObject *noargs)
4503 {
4504 pid_t pid;
4505 WAIT_TYPE status;
4506 WAIT_STATUS_INT(status) = 0;
4507
4508 Py_BEGIN_ALLOW_THREADS
4509 pid = wait(&status);
4510 Py_END_ALLOW_THREADS
4511 if (pid == -1)
4512 return posix_error();
4513
4514 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
4515 }
4516 #endif
4517
4518
4519 PyDoc_STRVAR(posix_lstat__doc__,
4520 "lstat(path) -> stat result\n\n\
4521 Like stat(path), but do not follow symbolic links.");
4522
4523 static PyObject *
4524 posix_lstat(PyObject *self, PyObject *args)
4525 {
4526 #ifdef HAVE_LSTAT
4527 return posix_do_stat(self, args, "et:lstat", lstat, NULL, NULL);
4528 #else /* !HAVE_LSTAT */
4529 return posix_do_stat(self, args, "et:lstat", STAT, NULL, NULL);
4530 #endif /* !HAVE_LSTAT */
4531 }
4532
4533
4534 #ifdef HAVE_READLINK
4535 PyDoc_STRVAR(posix_readlink__doc__,
4536 "readlink(path) -> path\n\n\
4537 Return a string representing the path to which the symbolic link points.");
4538
4539 static PyObject *
4540 posix_readlink(PyObject *self, PyObject *args)
4541 {
4542 PyObject* v;
4543 char buf[MAXPATHLEN];
4544 char *path;
4545 int n;
4546 #ifdef Py_USING_UNICODE
4547 int arg_is_unicode = 0;
4548 #endif
4549
4550 if (!PyArg_ParseTuple(args, "et:readlink",
4551 Py_FileSystemDefaultEncoding, &path))
4552 return NULL;
4553 #ifdef Py_USING_UNICODE
4554 v = PySequence_GetItem(args, 0);
4555 if (v == NULL) {
4556 PyMem_Free(path);
4557 return NULL;
4558 }
4559
4560 if (PyUnicode_Check(v)) {
4561 arg_is_unicode = 1;
4562 }
4563 Py_DECREF(v);
4564 #endif
4565
4566 Py_BEGIN_ALLOW_THREADS
4567 n = readlink(path, buf, (int) sizeof buf);
4568 Py_END_ALLOW_THREADS
4569 if (n < 0)
4570 return posix_error_with_allocated_filename(path);
4571
4572 PyMem_Free(path);
4573 v = PyString_FromStringAndSize(buf, n);
4574 #ifdef Py_USING_UNICODE
4575 if (arg_is_unicode) {
4576 PyObject *w;
4577
4578 w = PyUnicode_FromEncodedObject(v,
4579 Py_FileSystemDefaultEncoding,
4580 "strict");
4581 if (w != NULL) {
4582 Py_DECREF(v);
4583 v = w;
4584 }
4585 else {
4586 /* fall back to the original byte string, as
4587 discussed in patch #683592 */
4588 PyErr_Clear();
4589 }
4590 }
4591 #endif
4592 return v;
4593 }
4594 #endif /* HAVE_READLINK */
4595
4596
4597 #ifdef HAVE_SYMLINK
4598 PyDoc_STRVAR(posix_symlink__doc__,
4599 "symlink(src, dst)\n\n\
4600 Create a symbolic link pointing to src named dst.");
4601
4602 static PyObject *
4603 posix_symlink(PyObject *self, PyObject *args)
4604 {
4605 return posix_2str(args, "etet:symlink", symlink);
4606 }
4607 #endif /* HAVE_SYMLINK */
4608
4609
4610 #ifdef HAVE_TIMES
4611 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
4612 static long
4613 system_uptime(void)
4614 {
4615 ULONG value = 0;
4616
4617 Py_BEGIN_ALLOW_THREADS
4618 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value));
4619 Py_END_ALLOW_THREADS
4620
4621 return value;
4622 }
4623
4624 static PyObject *
4625 posix_times(PyObject *self, PyObject *noargs)
4626 {
4627 /* Currently Only Uptime is Provided -- Others Later */
4628 return Py_BuildValue("ddddd",
4629 (double)0 /* t.tms_utime / HZ */,
4630 (double)0 /* t.tms_stime / HZ */,
4631 (double)0 /* t.tms_cutime / HZ */,
4632 (double)0 /* t.tms_cstime / HZ */,
4633 (double)system_uptime() / 1000);
4634 }
4635 #else /* not OS2 */
4636 #define NEED_TICKS_PER_SECOND
4637 static long ticks_per_second = -1;
4638 static PyObject *
4639 posix_times(PyObject *self, PyObject *noargs)
4640 {
4641 struct tms t;
4642 clock_t c;
4643 errno = 0;
4644 c = times(&t);
4645 if (c == (clock_t) -1)
4646 return posix_error();
4647 return Py_BuildValue("ddddd",
4648 (double)t.tms_utime / ticks_per_second,
4649 (double)t.tms_stime / ticks_per_second,
4650 (double)t.tms_cutime / ticks_per_second,
4651 (double)t.tms_cstime / ticks_per_second,
4652 (double)c / ticks_per_second);
4653 }
4654 #endif /* not OS2 */
4655 #endif /* HAVE_TIMES */
4656
4657
4658 #ifdef HAVE_TIMES
4659 PyDoc_STRVAR(posix_times__doc__,
4660 "times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
4661 Return a tuple of floating point numbers indicating process times.");
4662 #endif
4663
4664
4665 #ifdef HAVE_GETSID
4666 PyDoc_STRVAR(posix_getsid__doc__,
4667 "getsid(pid) -> sid\n\n\
4668 Call the system call getsid().");
4669
4670 static PyObject *
4671 posix_getsid(PyObject *self, PyObject *args)
4672 {
4673 pid_t pid;
4674 int sid;
4675 if (!PyArg_ParseTuple(args, PARSE_PID ":getsid", &pid))
4676 return NULL;
4677 sid = getsid(pid);
4678 if (sid < 0)
4679 return posix_error();
4680 return PyInt_FromLong((long)sid);
4681 }
4682 #endif /* HAVE_GETSID */
4683
4684
4685 #ifdef HAVE_SETSID
4686 PyDoc_STRVAR(posix_setsid__doc__,
4687 "setsid()\n\n\
4688 Call the system call setsid().");
4689
4690 static PyObject *
4691 posix_setsid(PyObject *self, PyObject *noargs)
4692 {
4693 if (setsid() < 0)
4694 return posix_error();
4695 Py_INCREF(Py_None);
4696 return Py_None;
4697 }
4698 #endif /* HAVE_SETSID */
4699
4700 #ifdef HAVE_SETPGID
4701 PyDoc_STRVAR(posix_setpgid__doc__,
4702 "setpgid(pid, pgrp)\n\n\
4703 Call the system call setpgid().");
4704
4705 static PyObject *
4706 posix_setpgid(PyObject *self, PyObject *args)
4707 {
4708 pid_t pid;
4709 int pgrp;
4710 if (!PyArg_ParseTuple(args, PARSE_PID "i:setpgid", &pid, &pgrp))
4711 return NULL;
4712 if (setpgid(pid, pgrp) < 0)
4713 return posix_error();
4714 Py_INCREF(Py_None);
4715 return Py_None;
4716 }
4717 #endif /* HAVE_SETPGID */
4718
4719
4720 #ifdef HAVE_TCGETPGRP
4721 PyDoc_STRVAR(posix_tcgetpgrp__doc__,
4722 "tcgetpgrp(fd) -> pgid\n\n\
4723 Return the process group associated with the terminal given by a fd.");
4724
4725 static PyObject *
4726 posix_tcgetpgrp(PyObject *self, PyObject *args)
4727 {
4728 int fd;
4729 pid_t pgid;
4730 if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
4731 return NULL;
4732 pgid = tcgetpgrp(fd);
4733 if (pgid < 0)
4734 return posix_error();
4735 return PyLong_FromPid(pgid);
4736 }
4737 #endif /* HAVE_TCGETPGRP */
4738
4739
4740 #ifdef HAVE_TCSETPGRP
4741 PyDoc_STRVAR(posix_tcsetpgrp__doc__,
4742 "tcsetpgrp(fd, pgid)\n\n\
4743 Set the process group associated with the terminal given by a fd.");
4744
4745 static PyObject *
4746 posix_tcsetpgrp(PyObject *self, PyObject *args)
4747 {
4748 int fd;
4749 pid_t pgid;
4750 if (!PyArg_ParseTuple(args, "i" PARSE_PID ":tcsetpgrp", &fd, &pgid))
4751 return NULL;
4752 if (tcsetpgrp(fd, pgid) < 0)
4753 return posix_error();
4754 Py_INCREF(Py_None);
4755 return Py_None;
4756 }
4757 #endif /* HAVE_TCSETPGRP */
4758
4759 /* Functions acting on file descriptors */
4760
4761 PyDoc_STRVAR(posix_open__doc__,
4762 "open(filename, flag [, mode=0777]) -> fd\n\n\
4763 Open a file (for low level IO).");
4764
4765 static PyObject *
4766 posix_open(PyObject *self, PyObject *args)
4767 {
4768 char *file = NULL;
4769 int flag;
4770 int mode = 0777;
4771 int fd;
4772
4773 if (!PyArg_ParseTuple(args, "eti|i",
4774 Py_FileSystemDefaultEncoding, &file,
4775 &flag, &mode))
4776 return NULL;
4777
4778 Py_BEGIN_ALLOW_THREADS
4779 fd = open(file, flag, mode);
4780 Py_END_ALLOW_THREADS
4781 if (fd < 0)
4782 return posix_error_with_allocated_filename(file);
4783 PyMem_Free(file);
4784 return PyInt_FromLong((long)fd);
4785 }
4786
4787
4788 PyDoc_STRVAR(posix_close__doc__,
4789 "close(fd)\n\n\
4790 Close a file descriptor (for low level IO).");
4791
4792 static PyObject *
4793 posix_close(PyObject *self, PyObject *args)
4794 {
4795 int fd, res;
4796 if (!PyArg_ParseTuple(args, "i:close", &fd))
4797 return NULL;
4798 if (!_PyVerify_fd(fd))
4799 return posix_error();
4800 Py_BEGIN_ALLOW_THREADS
4801 res = close(fd);
4802 Py_END_ALLOW_THREADS
4803 if (res < 0)
4804 return posix_error();
4805 Py_INCREF(Py_None);
4806 return Py_None;
4807 }
4808
4809
4810 PyDoc_STRVAR(posix_closerange__doc__,
4811 "closerange(fd_low, fd_high)\n\n\
4812 Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
4813
4814 static PyObject *
4815 posix_closerange(PyObject *self, PyObject *args)
4816 {
4817 int fd_from, fd_to, i;
4818 if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
4819 return NULL;
4820 Py_BEGIN_ALLOW_THREADS
4821 for (i = fd_from; i < fd_to; i++)
4822 if (_PyVerify_fd(i))
4823 close(i);
4824 Py_END_ALLOW_THREADS
4825 Py_RETURN_NONE;
4826 }
4827
4828
4829 PyDoc_STRVAR(posix_dup__doc__,
4830 "dup(fd) -> fd2\n\n\
4831 Return a duplicate of a file descriptor.");
4832
4833 static PyObject *
4834 posix_dup(PyObject *self, PyObject *args)
4835 {
4836 int fd;
4837 if (!PyArg_ParseTuple(args, "i:dup", &fd))
4838 return NULL;
4839 if (!_PyVerify_fd(fd))
4840 return posix_error();
4841 Py_BEGIN_ALLOW_THREADS
4842 fd = dup(fd);
4843 Py_END_ALLOW_THREADS
4844 if (fd < 0)
4845 return posix_error();
4846 return PyInt_FromLong((long)fd);
4847 }
4848
4849
4850 PyDoc_STRVAR(posix_dup2__doc__,
4851 "dup2(old_fd, new_fd)\n\n\
4852 Duplicate file descriptor.");
4853
4854 static PyObject *
4855 posix_dup2(PyObject *self, PyObject *args)
4856 {
4857 int fd, fd2, res;
4858 if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
4859 return NULL;
4860 if (!_PyVerify_fd_dup2(fd, fd2))
4861 return posix_error();
4862 Py_BEGIN_ALLOW_THREADS
4863 res = dup2(fd, fd2);
4864 Py_END_ALLOW_THREADS
4865 if (res < 0)
4866 return posix_error();
4867 Py_INCREF(Py_None);
4868 return Py_None;
4869 }
4870
4871
4872 PyDoc_STRVAR(posix_lseek__doc__,
4873 "lseek(fd, pos, how) -> newpos\n\n\
4874 Set the current position of a file descriptor.");
4875
4876 static PyObject *
4877 posix_lseek(PyObject *self, PyObject *args)
4878 {
4879 int fd, how;
4880 off_t pos, res;
4881 PyObject *posobj;
4882 if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
4883 return NULL;
4884 #ifdef SEEK_SET
4885 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
4886 switch (how) {
4887 case 0: how = SEEK_SET; break;
4888 case 1: how = SEEK_CUR; break;
4889 case 2: how = SEEK_END; break;
4890 }
4891 #endif /* SEEK_END */
4892
4893 #if !defined(HAVE_LARGEFILE_SUPPORT)
4894 pos = PyInt_AsLong(posobj);
4895 #else
4896 pos = PyLong_Check(posobj) ?
4897 PyLong_AsLongLong(posobj) : PyInt_AsLong(posobj);
4898 #endif
4899 if (PyErr_Occurred())
4900 return NULL;
4901
4902 if (!_PyVerify_fd(fd))
4903 return posix_error();
4904 Py_BEGIN_ALLOW_THREADS
4905 res = lseek(fd, pos, how);
4906 Py_END_ALLOW_THREADS
4907 if (res < 0)
4908 return posix_error();
4909
4910 #if !defined(HAVE_LARGEFILE_SUPPORT)
4911 return PyInt_FromLong(res);
4912 #else
4913 return PyLong_FromLongLong(res);
4914 #endif
4915 }
4916
4917
4918 PyDoc_STRVAR(posix_read__doc__,
4919 "read(fd, buffersize) -> string\n\n\
4920 Read a file descriptor.");
4921
4922 static PyObject *
4923 posix_read(PyObject *self, PyObject *args)
4924 {
4925 int fd, size, n;
4926 PyObject *buffer;
4927 if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
4928 return NULL;
4929 if (size < 0) {
4930 errno = EINVAL;
4931 return posix_error();
4932 }
4933 buffer = PyString_FromStringAndSize((char *)NULL, size);
4934 if (buffer == NULL)
4935 return NULL;
4936 if (!_PyVerify_fd(fd)) {
4937 Py_DECREF(buffer);
4938 return posix_error();
4939 }
4940 Py_BEGIN_ALLOW_THREADS
4941 n = read(fd, PyString_AsString(buffer), size);
4942 Py_END_ALLOW_THREADS
4943 if (n < 0) {
4944 Py_DECREF(buffer);
4945 return posix_error();
4946 }
4947 if (n != size)
4948 _PyString_Resize(&buffer, n);
4949 return buffer;
4950 }
4951
4952
4953 PyDoc_STRVAR(posix_write__doc__,
4954 "write(fd, string) -> byteswritten\n\n\
4955 Write a string to a file descriptor.");
4956
4957 static PyObject *
4958 posix_write(PyObject *self, PyObject *args)
4959 {
4960 Py_buffer pbuf;
4961 int fd;
4962 Py_ssize_t size;
4963
4964 if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf))
4965 return NULL;
4966 if (!_PyVerify_fd(fd)) {
4967 PyBuffer_Release(&pbuf);
4968 return posix_error();
4969 }
4970 Py_BEGIN_ALLOW_THREADS
4971 size = write(fd, pbuf.buf, (size_t)pbuf.len);
4972 Py_END_ALLOW_THREADS
4973 PyBuffer_Release(&pbuf);
4974 if (size < 0)
4975 return posix_error();
4976 return PyInt_FromSsize_t(size);
4977 }
4978
4979
4980 PyDoc_STRVAR(posix_fstat__doc__,
4981 "fstat(fd) -> stat result\n\n\
4982 Like stat(), but for an open file descriptor.");
4983
4984 static PyObject *
4985 posix_fstat(PyObject *self, PyObject *args)
4986 {
4987 int fd;
4988 STRUCT_STAT st;
4989 int res;
4990 if (!PyArg_ParseTuple(args, "i:fstat", &fd))
4991 return NULL;
4992 if (!_PyVerify_fd(fd))
4993 return posix_error();
4994 Py_BEGIN_ALLOW_THREADS
4995 res = FSTAT(fd, &st);
4996 Py_END_ALLOW_THREADS
4997 if (res != 0) {
4998 return posix_error();
4999 }
5000
5001 return _pystat_fromstructstat(&st);
5002 }
5003
5004
5005 PyDoc_STRVAR(posix_fdopen__doc__,
5006 "fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n\
5007 Return an open file object connected to a file descriptor.");
5008
5009 static PyObject *
5010 posix_fdopen(PyObject *self, PyObject *args)
5011 {
5012 int fd;
5013 char *orgmode = "r";
5014 int bufsize = -1;
5015 FILE *fp;
5016 PyObject *f;
5017 char *mode;
5018 if (!PyArg_ParseTuple(args, "i|si", &fd, &orgmode, &bufsize))
5019 return NULL;
5020
5021 /* Sanitize mode. See fileobject.c */
5022 mode = PyMem_MALLOC(strlen(orgmode)+3);
5023 if (!mode) {
5024 PyErr_NoMemory();
5025 return NULL;
5026 }
5027 strcpy(mode, orgmode);
5028 if (_PyFile_SanitizeMode(mode)) {
5029 PyMem_FREE(mode);
5030 return NULL;
5031 }
5032 if (!_PyVerify_fd(fd))
5033 return posix_error();
5034 Py_BEGIN_ALLOW_THREADS
5035 #if !defined(MS_WINDOWS) && defined(HAVE_FCNTL_H)
5036 if (mode[0] == 'a') {
5037 /* try to make sure the O_APPEND flag is set */
5038 int flags;
5039 flags = fcntl(fd, F_GETFL);
5040 if (flags != -1)
5041 fcntl(fd, F_SETFL, flags | O_APPEND);
5042 fp = fdopen(fd, mode);
5043 if (fp == NULL && flags != -1)
5044 /* restore old mode if fdopen failed */
5045 fcntl(fd, F_SETFL, flags);
5046 } else {
5047 fp = fdopen(fd, mode);
5048 }
5049 #else
5050 fp = fdopen(fd, mode);
5051 #endif
5052 Py_END_ALLOW_THREADS
5053 PyMem_FREE(mode);
5054 if (fp == NULL)
5055 return posix_error();
5056 f = PyFile_FromFile(fp, "<fdopen>", orgmode, fclose);
5057 if (f != NULL)
5058 PyFile_SetBufSize(f, bufsize);
5059 return f;
5060 }
5061
5062 PyDoc_STRVAR(posix_isatty__doc__,
5063 "isatty(fd) -> bool\n\n\
5064 Return True if the file descriptor 'fd' is an open file descriptor\n\
5065 connected to the slave end of a terminal.");
5066
5067 static PyObject *
5068 posix_isatty(PyObject *self, PyObject *args)
5069 {
5070 int fd;
5071 if (!PyArg_ParseTuple(args, "i:isatty", &fd))
5072 return NULL;
5073 if (!_PyVerify_fd(fd))
5074 return PyBool_FromLong(0);
5075 return PyBool_FromLong(isatty(fd));
5076 }
5077
5078 #ifdef HAVE_PIPE
5079 PyDoc_STRVAR(posix_pipe__doc__,
5080 "pipe() -> (read_end, write_end)\n\n\
5081 Create a pipe.");
5082
5083 static PyObject *
5084 posix_pipe(PyObject *self, PyObject *noargs)
5085 {
5086 #if defined(PYOS_OS2)
5087 HFILE read, write;
5088 APIRET rc;
5089
5090 Py_BEGIN_ALLOW_THREADS
5091 rc = DosCreatePipe( &read, &write, 4096);
5092 Py_END_ALLOW_THREADS
5093 if (rc != NO_ERROR)
5094 return os2_error(rc);
5095
5096 return Py_BuildValue("(ii)", read, write);
5097 #else
5098 #if !defined(MS_WINDOWS)
5099 int fds[2];
5100 int res;
5101 Py_BEGIN_ALLOW_THREADS
5102 res = pipe(fds);
5103 Py_END_ALLOW_THREADS
5104 if (res != 0)
5105 return posix_error();
5106 return Py_BuildValue("(ii)", fds[0], fds[1]);
5107 #else /* MS_WINDOWS */
5108 HANDLE read, write;
5109 int read_fd, write_fd;
5110 BOOL ok;
5111 Py_BEGIN_ALLOW_THREADS
5112 ok = CreatePipe(&read, &write, NULL, 0);
5113 Py_END_ALLOW_THREADS
5114 if (!ok)
5115 return win32_error("CreatePipe", NULL);
5116 read_fd = _open_osfhandle((Py_intptr_t)read, 0);
5117 write_fd = _open_osfhandle((Py_intptr_t)write, 1);
5118 return Py_BuildValue("(ii)", read_fd, write_fd);
5119 #endif /* MS_WINDOWS */
5120 #endif
5121 }
5122 #endif /* HAVE_PIPE */
5123
5124
5125 #ifdef HAVE_MKFIFO
5126 PyDoc_STRVAR(posix_mkfifo__doc__,
5127 "mkfifo(filename [, mode=0666])\n\n\
5128 Create a FIFO (a POSIX named pipe).");
5129
5130 static PyObject *
5131 posix_mkfifo(PyObject *self, PyObject *args)
5132 {
5133 char *filename;
5134 int mode = 0666;
5135 int res;
5136 if (!PyArg_ParseTuple(args, "s|i:mkfifo", &filename, &mode))
5137 return NULL;
5138 Py_BEGIN_ALLOW_THREADS
5139 res = mkfifo(filename, mode);
5140 Py_END_ALLOW_THREADS
5141 if (res < 0)
5142 return posix_error();
5143 Py_INCREF(Py_None);
5144 return Py_None;
5145 }
5146 #endif
5147
5148
5149 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
5150 PyDoc_STRVAR(posix_mknod__doc__,
5151 "mknod(filename [, mode=0600, device])\n\n\
5152 Create a filesystem node (file, device special file or named pipe)\n\
5153 named filename. mode specifies both the permissions to use and the\n\
5154 type of node to be created, being combined (bitwise OR) with one of\n\
5155 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
5156 device defines the newly created device special file (probably using\n\
5157 os.makedev()), otherwise it is ignored.");
5158
5159
5160 static PyObject *
5161 posix_mknod(PyObject *self, PyObject *args)
5162 {
5163 char *filename;
5164 int mode = 0600;
5165 int device = 0;
5166 int res;
5167 if (!PyArg_ParseTuple(args, "s|ii:mknod", &filename, &mode, &device))
5168 return NULL;
5169 Py_BEGIN_ALLOW_THREADS
5170 res = mknod(filename, mode, device);
5171 Py_END_ALLOW_THREADS
5172 if (res < 0)
5173 return posix_error();
5174 Py_INCREF(Py_None);
5175 return Py_None;
5176 }
5177 #endif
5178
5179 #ifdef HAVE_DEVICE_MACROS
5180 PyDoc_STRVAR(posix_major__doc__,
5181 "major(device) -> major number\n\
5182 Extracts a device major number from a raw device number.");
5183
5184 static PyObject *
5185 posix_major(PyObject *self, PyObject *args)
5186 {
5187 int device;
5188 if (!PyArg_ParseTuple(args, "i:major", &device))
5189 return NULL;
5190 return PyInt_FromLong((long)major(device));
5191 }
5192
5193 PyDoc_STRVAR(posix_minor__doc__,
5194 "minor(device) -> minor number\n\
5195 Extracts a device minor number from a raw device number.");
5196
5197 static PyObject *
5198 posix_minor(PyObject *self, PyObject *args)
5199 {
5200 int device;
5201 if (!PyArg_ParseTuple(args, "i:minor", &device))
5202 return NULL;
5203 return PyInt_FromLong((long)minor(device));
5204 }
5205
5206 PyDoc_STRVAR(posix_makedev__doc__,
5207 "makedev(major, minor) -> device number\n\
5208 Composes a raw device number from the major and minor device numbers.");
5209
5210 static PyObject *
5211 posix_makedev(PyObject *self, PyObject *args)
5212 {
5213 int major, minor;
5214 if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
5215 return NULL;
5216 return PyInt_FromLong((long)makedev(major, minor));
5217 }
5218 #endif /* device macros */
5219
5220
5221 #ifdef HAVE_FTRUNCATE
5222 PyDoc_STRVAR(posix_ftruncate__doc__,
5223 "ftruncate(fd, length)\n\n\
5224 Truncate a file to a specified length.");
5225
5226 static PyObject *
5227 posix_ftruncate(PyObject *self, PyObject *args)
5228 {
5229 int fd;
5230 off_t length;
5231 int res;
5232 PyObject *lenobj;
5233
5234 if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj))
5235 return NULL;
5236
5237 #if !defined(HAVE_LARGEFILE_SUPPORT)
5238 length = PyInt_AsLong(lenobj);
5239 #else
5240 length = PyLong_Check(lenobj) ?
5241 PyLong_AsLongLong(lenobj) : PyInt_AsLong(lenobj);
5242 #endif
5243 if (PyErr_Occurred())
5244 return NULL;
5245
5246 Py_BEGIN_ALLOW_THREADS
5247 res = ftruncate(fd, length);
5248 Py_END_ALLOW_THREADS
5249 if (res < 0)
5250 return posix_error();
5251 Py_INCREF(Py_None);
5252 return Py_None;
5253 }
5254 #endif
5255
5256 #ifdef HAVE_PUTENV
5257 PyDoc_STRVAR(posix_putenv__doc__,
5258 "putenv(key, value)\n\n\
5259 Change or add an environment variable.");
5260
5261 /* Save putenv() parameters as values here, so we can collect them when they
5262 * get re-set with another call for the same key. */
5263 static PyObject *posix_putenv_garbage;
5264
5265 static PyObject *
5266 posix_putenv(PyObject *self, PyObject *args)
5267 {
5268 char *s1, *s2;
5269 char *newenv;
5270 PyObject *newstr;
5271 size_t len;
5272
5273 if (!PyArg_ParseTuple(args, "ss:putenv", &s1, &s2))
5274 return NULL;
5275
5276 #if defined(PYOS_OS2)
5277 if (stricmp(s1, "BEGINLIBPATH") == 0) {
5278 APIRET rc;
5279
5280 rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH);
5281 if (rc != NO_ERROR)
5282 return os2_error(rc);
5283
5284 } else if (stricmp(s1, "ENDLIBPATH") == 0) {
5285 APIRET rc;
5286
5287 rc = DosSetExtLIBPATH(s2, END_LIBPATH);
5288 if (rc != NO_ERROR)
5289 return os2_error(rc);
5290 } else {
5291 #endif
5292
5293 /* XXX This can leak memory -- not easy to fix :-( */
5294 len = strlen(s1) + strlen(s2) + 2;
5295 /* len includes space for a trailing \0; the size arg to
5296 PyString_FromStringAndSize does not count that */
5297 newstr = PyString_FromStringAndSize(NULL, (int)len - 1);
5298 if (newstr == NULL)
5299 return PyErr_NoMemory();
5300 newenv = PyString_AS_STRING(newstr);
5301 PyOS_snprintf(newenv, len, "%s=%s", s1, s2);
5302 if (putenv(newenv)) {
5303 Py_DECREF(newstr);
5304 posix_error();
5305 return NULL;
5306 }
5307 /* Install the first arg and newstr in posix_putenv_garbage;
5308 * this will cause previous value to be collected. This has to
5309 * happen after the real putenv() call because the old value
5310 * was still accessible until then. */
5311 if (PyDict_SetItem(posix_putenv_garbage,
5312 PyTuple_GET_ITEM(args, 0), newstr)) {
5313 /* really not much we can do; just leak */
5314 PyErr_Clear();
5315 }
5316 else {
5317 Py_DECREF(newstr);
5318 }
5319
5320 #if defined(PYOS_OS2)
5321 }
5322 #endif
5323 Py_INCREF(Py_None);
5324 return Py_None;
5325 }
5326 #endif /* putenv */
5327
5328 #ifdef HAVE_UNSETENV
5329 PyDoc_STRVAR(posix_unsetenv__doc__,
5330 "unsetenv(key)\n\n\
5331 Delete an environment variable.");
5332
5333 static PyObject *
5334 posix_unsetenv(PyObject *self, PyObject *args)
5335 {
5336 char *s1;
5337
5338 if (!PyArg_ParseTuple(args, "s:unsetenv", &s1))
5339 return NULL;
5340
5341 unsetenv(s1);
5342
5343 /* Remove the key from posix_putenv_garbage;
5344 * this will cause it to be collected. This has to
5345 * happen after the real unsetenv() call because the
5346 * old value was still accessible until then.
5347 */
5348 if (PyDict_DelItem(posix_putenv_garbage,
5349 PyTuple_GET_ITEM(args, 0))) {
5350 /* really not much we can do; just leak */
5351 PyErr_Clear();
5352 }
5353
5354 Py_INCREF(Py_None);
5355 return Py_None;
5356 }
5357 #endif /* unsetenv */
5358
5359 PyDoc_STRVAR(posix_strerror__doc__,
5360 "strerror(code) -> string\n\n\
5361 Translate an error code to a message string.");
5362
5363 static PyObject *
5364 posix_strerror(PyObject *self, PyObject *args)
5365 {
5366 int code;
5367 char *message;
5368 if (!PyArg_ParseTuple(args, "i:strerror", &code))
5369 return NULL;
5370 message = strerror(code);
5371 if (message == NULL) {
5372 PyErr_SetString(PyExc_ValueError,
5373 "strerror() argument out of range");
5374 return NULL;
5375 }
5376 return PyString_FromString(message);
5377 }
5378
5379
5380 #ifdef HAVE_SYS_WAIT_H
5381
5382 #ifdef WCOREDUMP
5383 PyDoc_STRVAR(posix_WCOREDUMP__doc__,
5384 "WCOREDUMP(status) -> bool\n\n\
5385 Return True if the process returning 'status' was dumped to a core file.");
5386
5387 static PyObject *
5388 posix_WCOREDUMP(PyObject *self, PyObject *args)
5389 {
5390 WAIT_TYPE status;
5391 WAIT_STATUS_INT(status) = 0;
5392
5393 if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
5394 return NULL;
5395
5396 return PyBool_FromLong(WCOREDUMP(status));
5397 }
5398 #endif /* WCOREDUMP */
5399
5400 #ifdef WIFCONTINUED
5401 PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
5402 "WIFCONTINUED(status) -> bool\n\n\
5403 Return True if the process returning 'status' was continued from a\n\
5404 job control stop.");
5405
5406 static PyObject *
5407 posix_WIFCONTINUED(PyObject *self, PyObject *args)
5408 {
5409 WAIT_TYPE status;
5410 WAIT_STATUS_INT(status) = 0;
5411
5412 if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
5413 return NULL;
5414
5415 return PyBool_FromLong(WIFCONTINUED(status));
5416 }
5417 #endif /* WIFCONTINUED */
5418
5419 #ifdef WIFSTOPPED
5420 PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
5421 "WIFSTOPPED(status) -> bool\n\n\
5422 Return True if the process returning 'status' was stopped.");
5423
5424 static PyObject *
5425 posix_WIFSTOPPED(PyObject *self, PyObject *args)
5426 {
5427 WAIT_TYPE status;
5428 WAIT_STATUS_INT(status) = 0;
5429
5430 if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
5431 return NULL;
5432
5433 return PyBool_FromLong(WIFSTOPPED(status));
5434 }
5435 #endif /* WIFSTOPPED */
5436
5437 #ifdef WIFSIGNALED
5438 PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
5439 "WIFSIGNALED(status) -> bool\n\n\
5440 Return True if the process returning 'status' was terminated by a signal.");
5441
5442 static PyObject *
5443 posix_WIFSIGNALED(PyObject *self, PyObject *args)
5444 {
5445 WAIT_TYPE status;
5446 WAIT_STATUS_INT(status) = 0;
5447
5448 if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
5449 return NULL;
5450
5451 return PyBool_FromLong(WIFSIGNALED(status));
5452 }
5453 #endif /* WIFSIGNALED */
5454
5455 #ifdef WIFEXITED
5456 PyDoc_STRVAR(posix_WIFEXITED__doc__,
5457 "WIFEXITED(status) -> bool\n\n\
5458 Return true if the process returning 'status' exited using the exit()\n\
5459 system call.");
5460
5461 static PyObject *
5462 posix_WIFEXITED(PyObject *self, PyObject *args)
5463 {
5464 WAIT_TYPE status;
5465 WAIT_STATUS_INT(status) = 0;
5466
5467 if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
5468 return NULL;
5469
5470 return PyBool_FromLong(WIFEXITED(status));
5471 }
5472 #endif /* WIFEXITED */
5473
5474 #ifdef WEXITSTATUS
5475 PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
5476 "WEXITSTATUS(status) -> integer\n\n\
5477 Return the process return code from 'status'.");
5478
5479 static PyObject *
5480 posix_WEXITSTATUS(PyObject *self, PyObject *args)
5481 {
5482 WAIT_TYPE status;
5483 WAIT_STATUS_INT(status) = 0;
5484
5485 if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
5486 return NULL;
5487
5488 return Py_BuildValue("i", WEXITSTATUS(status));
5489 }
5490 #endif /* WEXITSTATUS */
5491
5492 #ifdef WTERMSIG
5493 PyDoc_STRVAR(posix_WTERMSIG__doc__,
5494 "WTERMSIG(status) -> integer\n\n\
5495 Return the signal that terminated the process that provided the 'status'\n\
5496 value.");
5497
5498 static PyObject *
5499 posix_WTERMSIG(PyObject *self, PyObject *args)
5500 {
5501 WAIT_TYPE status;
5502 WAIT_STATUS_INT(status) = 0;
5503
5504 if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
5505 return NULL;
5506
5507 return Py_BuildValue("i", WTERMSIG(status));
5508 }
5509 #endif /* WTERMSIG */
5510
5511 #ifdef WSTOPSIG
5512 PyDoc_STRVAR(posix_WSTOPSIG__doc__,
5513 "WSTOPSIG(status) -> integer\n\n\
5514 Return the signal that stopped the process that provided\n\
5515 the 'status' value.");
5516
5517 static PyObject *
5518 posix_WSTOPSIG(PyObject *self, PyObject *args)
5519 {
5520 WAIT_TYPE status;
5521 WAIT_STATUS_INT(status) = 0;
5522
5523 if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
5524 return NULL;
5525
5526 return Py_BuildValue("i", WSTOPSIG(status));
5527 }
5528 #endif /* WSTOPSIG */
5529
5530 #endif /* HAVE_SYS_WAIT_H */
5531
5532
5533 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
5534 #ifdef _SCO_DS
5535 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
5536 needed definitions in sys/statvfs.h */
5537 #define _SVID3
5538 #endif
5539 #include <sys/statvfs.h>
5540
5541 static PyObject*
5542 _pystatvfs_fromstructstatvfs(struct statvfs st) {
5543 PyObject *v = PyStructSequence_New(&StatVFSResultType);
5544 if (v == NULL)
5545 return NULL;
5546
5547 #if !defined(HAVE_LARGEFILE_SUPPORT)
5548 PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
5549 PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
5550 PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long) st.f_blocks));
5551 PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long) st.f_bfree));
5552 PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long) st.f_bavail));
5553 PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long) st.f_files));
5554 PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong((long) st.f_ffree));
5555 PyStructSequence_SET_ITEM(v, 7, PyInt_FromLong((long) st.f_favail));
5556 PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
5557 PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
5558 #else
5559 PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long) st.f_bsize));
5560 PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long) st.f_frsize));
5561 PyStructSequence_SET_ITEM(v, 2,
5562 PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
5563 PyStructSequence_SET_ITEM(v, 3,
5564 PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
5565 PyStructSequence_SET_ITEM(v, 4,
5566 PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
5567 PyStructSequence_SET_ITEM(v, 5,
5568 PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
5569 PyStructSequence_SET_ITEM(v, 6,
5570 PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
5571 PyStructSequence_SET_ITEM(v, 7,
5572 PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
5573 PyStructSequence_SET_ITEM(v, 8, PyInt_FromLong((long) st.f_flag));
5574 PyStructSequence_SET_ITEM(v, 9, PyInt_FromLong((long) st.f_namemax));
5575 #endif
5576
5577 return v;
5578 }
5579
5580 PyDoc_STRVAR(posix_fstatvfs__doc__,
5581 "fstatvfs(fd) -> statvfs result\n\n\
5582 Perform an fstatvfs system call on the given fd.");
5583
5584 static PyObject *
5585 posix_fstatvfs(PyObject *self, PyObject *args)
5586 {
5587 int fd, res;
5588 struct statvfs st;
5589
5590 if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
5591 return NULL;
5592 Py_BEGIN_ALLOW_THREADS
5593 res = fstatvfs(fd, &st);
5594 Py_END_ALLOW_THREADS
5595 if (res != 0)
5596 return posix_error();
5597
5598 return _pystatvfs_fromstructstatvfs(st);
5599 }
5600 #endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
5601
5602
5603 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
5604 #include <sys/statvfs.h>
5605
5606 PyDoc_STRVAR(posix_statvfs__doc__,
5607 "statvfs(path) -> statvfs result\n\n\
5608 Perform a statvfs system call on the given path.");
5609
5610 static PyObject *
5611 posix_statvfs(PyObject *self, PyObject *args)
5612 {
5613 char *path;
5614 int res;
5615 struct statvfs st;
5616 if (!PyArg_ParseTuple(args, "s:statvfs", &path))
5617 return NULL;
5618 Py_BEGIN_ALLOW_THREADS
5619 res = statvfs(path, &st);
5620 Py_END_ALLOW_THREADS
5621 if (res != 0)
5622 return posix_error_with_filename(path);
5623
5624 return _pystatvfs_fromstructstatvfs(st);
5625 }
5626 #endif /* HAVE_STATVFS */
5627
5628
5629 #ifdef HAVE_TEMPNAM
5630 PyDoc_STRVAR(posix_tempnam__doc__,
5631 "tempnam([dir[, prefix]]) -> string\n\n\
5632 Return a unique name for a temporary file.\n\
5633 The directory and a prefix may be specified as strings; they may be omitted\n\
5634 or None if not needed.");
5635
5636 static PyObject *
5637 posix_tempnam(PyObject *self, PyObject *args)
5638 {
5639 PyObject *result = NULL;
5640 char *dir = NULL;
5641 char *pfx = NULL;
5642 char *name;
5643
5644 if (!PyArg_ParseTuple(args, "|zz:tempnam", &dir, &pfx))
5645 return NULL;
5646
5647 if (PyErr_Warn(PyExc_RuntimeWarning,
5648 "tempnam is a potential security risk to your program") < 0)
5649 return NULL;
5650
5651 if (PyErr_WarnPy3k("tempnam has been removed in 3.x; "
5652 "use the tempfile module", 1) < 0)
5653 return NULL;
5654
5655 name = tempnam(dir, pfx);
5656 if (name == NULL)
5657 return PyErr_NoMemory();
5658 result = PyString_FromString(name);
5659 free(name);
5660 return result;
5661 }
5662 #endif
5663
5664
5665 #ifdef HAVE_TMPFILE
5666 PyDoc_STRVAR(posix_tmpfile__doc__,
5667 "tmpfile() -> file object\n\n\
5668 Create a temporary file with no directory entries.");
5669
5670 static PyObject *
5671 posix_tmpfile(PyObject *self, PyObject *noargs)
5672 {
5673 FILE *fp;
5674
5675 if (PyErr_WarnPy3k("tmpfile has been removed in 3.x; "
5676 "use the tempfile module", 1) < 0)
5677 return NULL;
5678
5679 fp = tmpfile();
5680 if (fp == NULL)
5681 return posix_error();
5682 return PyFile_FromFile(fp, "<tmpfile>", "w+b", fclose);
5683 }
5684 #endif
5685
5686
5687 #ifdef HAVE_TMPNAM
5688 PyDoc_STRVAR(posix_tmpnam__doc__,
5689 "tmpnam() -> string\n\n\
5690 Return a unique name for a temporary file.");
5691
5692 static PyObject *
5693 posix_tmpnam(PyObject *self, PyObject *noargs)
5694 {
5695 char buffer[L_tmpnam];
5696 char *name;
5697
5698 if (PyErr_Warn(PyExc_RuntimeWarning,
5699 "tmpnam is a potential security risk to your program") < 0)
5700 return NULL;
5701
5702 if (PyErr_WarnPy3k("tmpnam has been removed in 3.x; "
5703 "use the tempfile module", 1) < 0)
5704 return NULL;
5705
5706 #ifdef USE_TMPNAM_R
5707 name = tmpnam_r(buffer);
5708 #else
5709 name = tmpnam(buffer);
5710 #endif
5711 if (name == NULL) {
5712 PyObject *err = Py_BuildValue("is", 0,
5713 #ifdef USE_TMPNAM_R
5714 "unexpected NULL from tmpnam_r"
5715 #else
5716 "unexpected NULL from tmpnam"
5717 #endif
5718 );
5719 PyErr_SetObject(PyExc_OSError, err);
5720 Py_XDECREF(err);
5721 return NULL;
5722 }
5723 return PyString_FromString(buffer);
5724 }
5725 #endif
5726
5727
5728 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
5729 * It maps strings representing configuration variable names to
5730 * integer values, allowing those functions to be called with the
5731 * magic names instead of polluting the module's namespace with tons of
5732 * rarely-used constants. There are three separate tables that use
5733 * these definitions.
5734 *
5735 * This code is always included, even if none of the interfaces that
5736 * need it are included. The #if hackery needed to avoid it would be
5737 * sufficiently pervasive that it's not worth the loss of readability.
5738 */
5739 struct constdef {
5740 char *name;
5741 long value;
5742 };
5743
5744 #ifndef UEFI_C_SOURCE
5745 static int
5746 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
5747 size_t tablesize)
5748 {
5749 if (PyInt_Check(arg)) {
5750 *valuep = PyInt_AS_LONG(arg);
5751 return 1;
5752 }
5753 if (PyString_Check(arg)) {
5754 /* look up the value in the table using a binary search */
5755 size_t lo = 0;
5756 size_t mid;
5757 size_t hi = tablesize;
5758 int cmp;
5759 char *confname = PyString_AS_STRING(arg);
5760 while (lo < hi) {
5761 mid = (lo + hi) / 2;
5762 cmp = strcmp(confname, table[mid].name);
5763 if (cmp < 0)
5764 hi = mid;
5765 else if (cmp > 0)
5766 lo = mid + 1;
5767 else {
5768 *valuep = table[mid].value;
5769 return 1;
5770 }
5771 }
5772 PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
5773 }
5774 else
5775 PyErr_SetString(PyExc_TypeError,
5776 "configuration names must be strings or integers");
5777 return 0;
5778 }
5779 #endif /* UEFI_C_SOURCE */
5780
5781 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
5782 static struct constdef posix_constants_pathconf[] = {
5783 #ifdef _PC_ABI_AIO_XFER_MAX
5784 {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
5785 #endif
5786 #ifdef _PC_ABI_ASYNC_IO
5787 {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
5788 #endif
5789 #ifdef _PC_ASYNC_IO
5790 {"PC_ASYNC_IO", _PC_ASYNC_IO},
5791 #endif
5792 #ifdef _PC_CHOWN_RESTRICTED
5793 {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
5794 #endif
5795 #ifdef _PC_FILESIZEBITS
5796 {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
5797 #endif
5798 #ifdef _PC_LAST
5799 {"PC_LAST", _PC_LAST},
5800 #endif
5801 #ifdef _PC_LINK_MAX
5802 {"PC_LINK_MAX", _PC_LINK_MAX},
5803 #endif
5804 #ifdef _PC_MAX_CANON
5805 {"PC_MAX_CANON", _PC_MAX_CANON},
5806 #endif
5807 #ifdef _PC_MAX_INPUT
5808 {"PC_MAX_INPUT", _PC_MAX_INPUT},
5809 #endif
5810 #ifdef _PC_NAME_MAX
5811 {"PC_NAME_MAX", _PC_NAME_MAX},
5812 #endif
5813 #ifdef _PC_NO_TRUNC
5814 {"PC_NO_TRUNC", _PC_NO_TRUNC},
5815 #endif
5816 #ifdef _PC_PATH_MAX
5817 {"PC_PATH_MAX", _PC_PATH_MAX},
5818 #endif
5819 #ifdef _PC_PIPE_BUF
5820 {"PC_PIPE_BUF", _PC_PIPE_BUF},
5821 #endif
5822 #ifdef _PC_PRIO_IO
5823 {"PC_PRIO_IO", _PC_PRIO_IO},
5824 #endif
5825 #ifdef _PC_SOCK_MAXBUF
5826 {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
5827 #endif
5828 #ifdef _PC_SYNC_IO
5829 {"PC_SYNC_IO", _PC_SYNC_IO},
5830 #endif
5831 #ifdef _PC_VDISABLE
5832 {"PC_VDISABLE", _PC_VDISABLE},
5833 #endif
5834 };
5835
5836 static int
5837 conv_path_confname(PyObject *arg, int *valuep)
5838 {
5839 return conv_confname(arg, valuep, posix_constants_pathconf,
5840 sizeof(posix_constants_pathconf)
5841 / sizeof(struct constdef));
5842 }
5843 #endif
5844
5845 #ifdef HAVE_FPATHCONF
5846 PyDoc_STRVAR(posix_fpathconf__doc__,
5847 "fpathconf(fd, name) -> integer\n\n\
5848 Return the configuration limit name for the file descriptor fd.\n\
5849 If there is no limit, return -1.");
5850
5851 static PyObject *
5852 posix_fpathconf(PyObject *self, PyObject *args)
5853 {
5854 PyObject *result = NULL;
5855 int name, fd;
5856
5857 if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
5858 conv_path_confname, &name)) {
5859 long limit;
5860
5861 errno = 0;
5862 limit = fpathconf(fd, name);
5863 if (limit == -1 && errno != 0)
5864 posix_error();
5865 else
5866 result = PyInt_FromLong(limit);
5867 }
5868 return result;
5869 }
5870 #endif
5871
5872
5873 #ifdef HAVE_PATHCONF
5874 PyDoc_STRVAR(posix_pathconf__doc__,
5875 "pathconf(path, name) -> integer\n\n\
5876 Return the configuration limit name for the file or directory path.\n\
5877 If there is no limit, return -1.");
5878
5879 static PyObject *
5880 posix_pathconf(PyObject *self, PyObject *args)
5881 {
5882 PyObject *result = NULL;
5883 int name;
5884 char *path;
5885
5886 if (PyArg_ParseTuple(args, "sO&:pathconf", &path,
5887 conv_path_confname, &name)) {
5888 long limit;
5889
5890 errno = 0;
5891 limit = pathconf(path, name);
5892 if (limit == -1 && errno != 0) {
5893 if (errno == EINVAL)
5894 /* could be a path or name problem */
5895 posix_error();
5896 else
5897 posix_error_with_filename(path);
5898 }
5899 else
5900 result = PyInt_FromLong(limit);
5901 }
5902 return result;
5903 }
5904 #endif
5905
5906 #ifdef HAVE_CONFSTR
5907 static struct constdef posix_constants_confstr[] = {
5908 #ifdef _CS_ARCHITECTURE
5909 {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
5910 #endif
5911 #ifdef _CS_HOSTNAME
5912 {"CS_HOSTNAME", _CS_HOSTNAME},
5913 #endif
5914 #ifdef _CS_HW_PROVIDER
5915 {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
5916 #endif
5917 #ifdef _CS_HW_SERIAL
5918 {"CS_HW_SERIAL", _CS_HW_SERIAL},
5919 #endif
5920 #ifdef _CS_INITTAB_NAME
5921 {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
5922 #endif
5923 #ifdef _CS_LFS64_CFLAGS
5924 {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
5925 #endif
5926 #ifdef _CS_LFS64_LDFLAGS
5927 {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
5928 #endif
5929 #ifdef _CS_LFS64_LIBS
5930 {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
5931 #endif
5932 #ifdef _CS_LFS64_LINTFLAGS
5933 {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
5934 #endif
5935 #ifdef _CS_LFS_CFLAGS
5936 {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
5937 #endif
5938 #ifdef _CS_LFS_LDFLAGS
5939 {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
5940 #endif
5941 #ifdef _CS_LFS_LIBS
5942 {"CS_LFS_LIBS", _CS_LFS_LIBS},
5943 #endif
5944 #ifdef _CS_LFS_LINTFLAGS
5945 {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
5946 #endif
5947 #ifdef _CS_MACHINE
5948 {"CS_MACHINE", _CS_MACHINE},
5949 #endif
5950 #ifdef _CS_PATH
5951 {"CS_PATH", _CS_PATH},
5952 #endif
5953 #ifdef _CS_RELEASE
5954 {"CS_RELEASE", _CS_RELEASE},
5955 #endif
5956 #ifdef _CS_SRPC_DOMAIN
5957 {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
5958 #endif
5959 #ifdef _CS_SYSNAME
5960 {"CS_SYSNAME", _CS_SYSNAME},
5961 #endif
5962 #ifdef _CS_VERSION
5963 {"CS_VERSION", _CS_VERSION},
5964 #endif
5965 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
5966 {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
5967 #endif
5968 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
5969 {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
5970 #endif
5971 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
5972 {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
5973 #endif
5974 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
5975 {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
5976 #endif
5977 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
5978 {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
5979 #endif
5980 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
5981 {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
5982 #endif
5983 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
5984 {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
5985 #endif
5986 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
5987 {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
5988 #endif
5989 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
5990 {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
5991 #endif
5992 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
5993 {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
5994 #endif
5995 #ifdef _CS_XBS5_LP64_OFF64_LIBS
5996 {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
5997 #endif
5998 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
5999 {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
6000 #endif
6001 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
6002 {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
6003 #endif
6004 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
6005 {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
6006 #endif
6007 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
6008 {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
6009 #endif
6010 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
6011 {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
6012 #endif
6013 #ifdef _MIPS_CS_AVAIL_PROCESSORS
6014 {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
6015 #endif
6016 #ifdef _MIPS_CS_BASE
6017 {"MIPS_CS_BASE", _MIPS_CS_BASE},
6018 #endif
6019 #ifdef _MIPS_CS_HOSTID
6020 {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
6021 #endif
6022 #ifdef _MIPS_CS_HW_NAME
6023 {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
6024 #endif
6025 #ifdef _MIPS_CS_NUM_PROCESSORS
6026 {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
6027 #endif
6028 #ifdef _MIPS_CS_OSREL_MAJ
6029 {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
6030 #endif
6031 #ifdef _MIPS_CS_OSREL_MIN
6032 {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
6033 #endif
6034 #ifdef _MIPS_CS_OSREL_PATCH
6035 {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
6036 #endif
6037 #ifdef _MIPS_CS_OS_NAME
6038 {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
6039 #endif
6040 #ifdef _MIPS_CS_OS_PROVIDER
6041 {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
6042 #endif
6043 #ifdef _MIPS_CS_PROCESSORS
6044 {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
6045 #endif
6046 #ifdef _MIPS_CS_SERIAL
6047 {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
6048 #endif
6049 #ifdef _MIPS_CS_VENDOR
6050 {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
6051 #endif
6052 };
6053
6054 static int
6055 conv_confstr_confname(PyObject *arg, int *valuep)
6056 {
6057 return conv_confname(arg, valuep, posix_constants_confstr,
6058 sizeof(posix_constants_confstr)
6059 / sizeof(struct constdef));
6060 }
6061
6062 PyDoc_STRVAR(posix_confstr__doc__,
6063 "confstr(name) -> string\n\n\
6064 Return a string-valued system configuration variable.");
6065
6066 static PyObject *
6067 posix_confstr(PyObject *self, PyObject *args)
6068 {
6069 PyObject *result = NULL;
6070 int name;
6071 char buffer[256];
6072
6073 if (PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) {
6074 int len;
6075
6076 errno = 0;
6077 len = confstr(name, buffer, sizeof(buffer));
6078 if (len == 0) {
6079 if (errno) {
6080 posix_error();
6081 }
6082 else {
6083 result = Py_None;
6084 Py_INCREF(Py_None);
6085 }
6086 }
6087 else {
6088 if ((unsigned int)len >= sizeof(buffer)) {
6089 result = PyString_FromStringAndSize(NULL, len-1);
6090 if (result != NULL)
6091 confstr(name, PyString_AS_STRING(result), len);
6092 }
6093 else
6094 result = PyString_FromStringAndSize(buffer, len-1);
6095 }
6096 }
6097 return result;
6098 }
6099 #endif
6100
6101
6102 #ifdef HAVE_SYSCONF
6103 static struct constdef posix_constants_sysconf[] = {
6104 #ifdef _SC_2_CHAR_TERM
6105 {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
6106 #endif
6107 #ifdef _SC_2_C_BIND
6108 {"SC_2_C_BIND", _SC_2_C_BIND},
6109 #endif
6110 #ifdef _SC_2_C_DEV
6111 {"SC_2_C_DEV", _SC_2_C_DEV},
6112 #endif
6113 #ifdef _SC_2_C_VERSION
6114 {"SC_2_C_VERSION", _SC_2_C_VERSION},
6115 #endif
6116 #ifdef _SC_2_FORT_DEV
6117 {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
6118 #endif
6119 #ifdef _SC_2_FORT_RUN
6120 {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
6121 #endif
6122 #ifdef _SC_2_LOCALEDEF
6123 {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
6124 #endif
6125 #ifdef _SC_2_SW_DEV
6126 {"SC_2_SW_DEV", _SC_2_SW_DEV},
6127 #endif
6128 #ifdef _SC_2_UPE
6129 {"SC_2_UPE", _SC_2_UPE},
6130 #endif
6131 #ifdef _SC_2_VERSION
6132 {"SC_2_VERSION", _SC_2_VERSION},
6133 #endif
6134 #ifdef _SC_ABI_ASYNCHRONOUS_IO
6135 {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
6136 #endif
6137 #ifdef _SC_ACL
6138 {"SC_ACL", _SC_ACL},
6139 #endif
6140 #ifdef _SC_AIO_LISTIO_MAX
6141 {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
6142 #endif
6143 #ifdef _SC_AIO_MAX
6144 {"SC_AIO_MAX", _SC_AIO_MAX},
6145 #endif
6146 #ifdef _SC_AIO_PRIO_DELTA_MAX
6147 {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
6148 #endif
6149 #ifdef _SC_ARG_MAX
6150 {"SC_ARG_MAX", _SC_ARG_MAX},
6151 #endif
6152 #ifdef _SC_ASYNCHRONOUS_IO
6153 {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
6154 #endif
6155 #ifdef _SC_ATEXIT_MAX
6156 {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
6157 #endif
6158 #ifdef _SC_AUDIT
6159 {"SC_AUDIT", _SC_AUDIT},
6160 #endif
6161 #ifdef _SC_AVPHYS_PAGES
6162 {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
6163 #endif
6164 #ifdef _SC_BC_BASE_MAX
6165 {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
6166 #endif
6167 #ifdef _SC_BC_DIM_MAX
6168 {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
6169 #endif
6170 #ifdef _SC_BC_SCALE_MAX
6171 {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
6172 #endif
6173 #ifdef _SC_BC_STRING_MAX
6174 {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
6175 #endif
6176 #ifdef _SC_CAP
6177 {"SC_CAP", _SC_CAP},
6178 #endif
6179 #ifdef _SC_CHARCLASS_NAME_MAX
6180 {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
6181 #endif
6182 #ifdef _SC_CHAR_BIT
6183 {"SC_CHAR_BIT", _SC_CHAR_BIT},
6184 #endif
6185 #ifdef _SC_CHAR_MAX
6186 {"SC_CHAR_MAX", _SC_CHAR_MAX},
6187 #endif
6188 #ifdef _SC_CHAR_MIN
6189 {"SC_CHAR_MIN", _SC_CHAR_MIN},
6190 #endif
6191 #ifdef _SC_CHILD_MAX
6192 {"SC_CHILD_MAX", _SC_CHILD_MAX},
6193 #endif
6194 #ifdef _SC_CLK_TCK
6195 {"SC_CLK_TCK", _SC_CLK_TCK},
6196 #endif
6197 #ifdef _SC_COHER_BLKSZ
6198 {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
6199 #endif
6200 #ifdef _SC_COLL_WEIGHTS_MAX
6201 {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
6202 #endif
6203 #ifdef _SC_DCACHE_ASSOC
6204 {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
6205 #endif
6206 #ifdef _SC_DCACHE_BLKSZ
6207 {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
6208 #endif
6209 #ifdef _SC_DCACHE_LINESZ
6210 {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
6211 #endif
6212 #ifdef _SC_DCACHE_SZ
6213 {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
6214 #endif
6215 #ifdef _SC_DCACHE_TBLKSZ
6216 {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
6217 #endif
6218 #ifdef _SC_DELAYTIMER_MAX
6219 {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
6220 #endif
6221 #ifdef _SC_EQUIV_CLASS_MAX
6222 {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
6223 #endif
6224 #ifdef _SC_EXPR_NEST_MAX
6225 {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
6226 #endif
6227 #ifdef _SC_FSYNC
6228 {"SC_FSYNC", _SC_FSYNC},
6229 #endif
6230 #ifdef _SC_GETGR_R_SIZE_MAX
6231 {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
6232 #endif
6233 #ifdef _SC_GETPW_R_SIZE_MAX
6234 {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
6235 #endif
6236 #ifdef _SC_ICACHE_ASSOC
6237 {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
6238 #endif
6239 #ifdef _SC_ICACHE_BLKSZ
6240 {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
6241 #endif
6242 #ifdef _SC_ICACHE_LINESZ
6243 {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
6244 #endif
6245 #ifdef _SC_ICACHE_SZ
6246 {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
6247 #endif
6248 #ifdef _SC_INF
6249 {"SC_INF", _SC_INF},
6250 #endif
6251 #ifdef _SC_INT_MAX
6252 {"SC_INT_MAX", _SC_INT_MAX},
6253 #endif
6254 #ifdef _SC_INT_MIN
6255 {"SC_INT_MIN", _SC_INT_MIN},
6256 #endif
6257 #ifdef _SC_IOV_MAX
6258 {"SC_IOV_MAX", _SC_IOV_MAX},
6259 #endif
6260 #ifdef _SC_IP_SECOPTS
6261 {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
6262 #endif
6263 #ifdef _SC_JOB_CONTROL
6264 {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
6265 #endif
6266 #ifdef _SC_KERN_POINTERS
6267 {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
6268 #endif
6269 #ifdef _SC_KERN_SIM
6270 {"SC_KERN_SIM", _SC_KERN_SIM},
6271 #endif
6272 #ifdef _SC_LINE_MAX
6273 {"SC_LINE_MAX", _SC_LINE_MAX},
6274 #endif
6275 #ifdef _SC_LOGIN_NAME_MAX
6276 {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
6277 #endif
6278 #ifdef _SC_LOGNAME_MAX
6279 {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
6280 #endif
6281 #ifdef _SC_LONG_BIT
6282 {"SC_LONG_BIT", _SC_LONG_BIT},
6283 #endif
6284 #ifdef _SC_MAC
6285 {"SC_MAC", _SC_MAC},
6286 #endif
6287 #ifdef _SC_MAPPED_FILES
6288 {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
6289 #endif
6290 #ifdef _SC_MAXPID
6291 {"SC_MAXPID", _SC_MAXPID},
6292 #endif
6293 #ifdef _SC_MB_LEN_MAX
6294 {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
6295 #endif
6296 #ifdef _SC_MEMLOCK
6297 {"SC_MEMLOCK", _SC_MEMLOCK},
6298 #endif
6299 #ifdef _SC_MEMLOCK_RANGE
6300 {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
6301 #endif
6302 #ifdef _SC_MEMORY_PROTECTION
6303 {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
6304 #endif
6305 #ifdef _SC_MESSAGE_PASSING
6306 {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
6307 #endif
6308 #ifdef _SC_MMAP_FIXED_ALIGNMENT
6309 {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
6310 #endif
6311 #ifdef _SC_MQ_OPEN_MAX
6312 {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
6313 #endif
6314 #ifdef _SC_MQ_PRIO_MAX
6315 {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
6316 #endif
6317 #ifdef _SC_NACLS_MAX
6318 {"SC_NACLS_MAX", _SC_NACLS_MAX},
6319 #endif
6320 #ifdef _SC_NGROUPS_MAX
6321 {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
6322 #endif
6323 #ifdef _SC_NL_ARGMAX
6324 {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
6325 #endif
6326 #ifdef _SC_NL_LANGMAX
6327 {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
6328 #endif
6329 #ifdef _SC_NL_MSGMAX
6330 {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
6331 #endif
6332 #ifdef _SC_NL_NMAX
6333 {"SC_NL_NMAX", _SC_NL_NMAX},
6334 #endif
6335 #ifdef _SC_NL_SETMAX
6336 {"SC_NL_SETMAX", _SC_NL_SETMAX},
6337 #endif
6338 #ifdef _SC_NL_TEXTMAX
6339 {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
6340 #endif
6341 #ifdef _SC_NPROCESSORS_CONF
6342 {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
6343 #endif
6344 #ifdef _SC_NPROCESSORS_ONLN
6345 {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
6346 #endif
6347 #ifdef _SC_NPROC_CONF
6348 {"SC_NPROC_CONF", _SC_NPROC_CONF},
6349 #endif
6350 #ifdef _SC_NPROC_ONLN
6351 {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
6352 #endif
6353 #ifdef _SC_NZERO
6354 {"SC_NZERO", _SC_NZERO},
6355 #endif
6356 #ifdef _SC_OPEN_MAX
6357 {"SC_OPEN_MAX", _SC_OPEN_MAX},
6358 #endif
6359 #ifdef _SC_PAGESIZE
6360 {"SC_PAGESIZE", _SC_PAGESIZE},
6361 #endif
6362 #ifdef _SC_PAGE_SIZE
6363 {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
6364 #endif
6365 #ifdef _SC_PASS_MAX
6366 {"SC_PASS_MAX", _SC_PASS_MAX},
6367 #endif
6368 #ifdef _SC_PHYS_PAGES
6369 {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
6370 #endif
6371 #ifdef _SC_PII
6372 {"SC_PII", _SC_PII},
6373 #endif
6374 #ifdef _SC_PII_INTERNET
6375 {"SC_PII_INTERNET", _SC_PII_INTERNET},
6376 #endif
6377 #ifdef _SC_PII_INTERNET_DGRAM
6378 {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
6379 #endif
6380 #ifdef _SC_PII_INTERNET_STREAM
6381 {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
6382 #endif
6383 #ifdef _SC_PII_OSI
6384 {"SC_PII_OSI", _SC_PII_OSI},
6385 #endif
6386 #ifdef _SC_PII_OSI_CLTS
6387 {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
6388 #endif
6389 #ifdef _SC_PII_OSI_COTS
6390 {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
6391 #endif
6392 #ifdef _SC_PII_OSI_M
6393 {"SC_PII_OSI_M", _SC_PII_OSI_M},
6394 #endif
6395 #ifdef _SC_PII_SOCKET
6396 {"SC_PII_SOCKET", _SC_PII_SOCKET},
6397 #endif
6398 #ifdef _SC_PII_XTI
6399 {"SC_PII_XTI", _SC_PII_XTI},
6400 #endif
6401 #ifdef _SC_POLL
6402 {"SC_POLL", _SC_POLL},
6403 #endif
6404 #ifdef _SC_PRIORITIZED_IO
6405 {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
6406 #endif
6407 #ifdef _SC_PRIORITY_SCHEDULING
6408 {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
6409 #endif
6410 #ifdef _SC_REALTIME_SIGNALS
6411 {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
6412 #endif
6413 #ifdef _SC_RE_DUP_MAX
6414 {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
6415 #endif
6416 #ifdef _SC_RTSIG_MAX
6417 {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
6418 #endif
6419 #ifdef _SC_SAVED_IDS
6420 {"SC_SAVED_IDS", _SC_SAVED_IDS},
6421 #endif
6422 #ifdef _SC_SCHAR_MAX
6423 {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
6424 #endif
6425 #ifdef _SC_SCHAR_MIN
6426 {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
6427 #endif
6428 #ifdef _SC_SELECT
6429 {"SC_SELECT", _SC_SELECT},
6430 #endif
6431 #ifdef _SC_SEMAPHORES
6432 {"SC_SEMAPHORES", _SC_SEMAPHORES},
6433 #endif
6434 #ifdef _SC_SEM_NSEMS_MAX
6435 {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
6436 #endif
6437 #ifdef _SC_SEM_VALUE_MAX
6438 {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
6439 #endif
6440 #ifdef _SC_SHARED_MEMORY_OBJECTS
6441 {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
6442 #endif
6443 #ifdef _SC_SHRT_MAX
6444 {"SC_SHRT_MAX", _SC_SHRT_MAX},
6445 #endif
6446 #ifdef _SC_SHRT_MIN
6447 {"SC_SHRT_MIN", _SC_SHRT_MIN},
6448 #endif
6449 #ifdef _SC_SIGQUEUE_MAX
6450 {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
6451 #endif
6452 #ifdef _SC_SIGRT_MAX
6453 {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
6454 #endif
6455 #ifdef _SC_SIGRT_MIN
6456 {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
6457 #endif
6458 #ifdef _SC_SOFTPOWER
6459 {"SC_SOFTPOWER", _SC_SOFTPOWER},
6460 #endif
6461 #ifdef _SC_SPLIT_CACHE
6462 {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
6463 #endif
6464 #ifdef _SC_SSIZE_MAX
6465 {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
6466 #endif
6467 #ifdef _SC_STACK_PROT
6468 {"SC_STACK_PROT", _SC_STACK_PROT},
6469 #endif
6470 #ifdef _SC_STREAM_MAX
6471 {"SC_STREAM_MAX", _SC_STREAM_MAX},
6472 #endif
6473 #ifdef _SC_SYNCHRONIZED_IO
6474 {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
6475 #endif
6476 #ifdef _SC_THREADS
6477 {"SC_THREADS", _SC_THREADS},
6478 #endif
6479 #ifdef _SC_THREAD_ATTR_STACKADDR
6480 {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
6481 #endif
6482 #ifdef _SC_THREAD_ATTR_STACKSIZE
6483 {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
6484 #endif
6485 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
6486 {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
6487 #endif
6488 #ifdef _SC_THREAD_KEYS_MAX
6489 {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
6490 #endif
6491 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
6492 {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
6493 #endif
6494 #ifdef _SC_THREAD_PRIO_INHERIT
6495 {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
6496 #endif
6497 #ifdef _SC_THREAD_PRIO_PROTECT
6498 {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
6499 #endif
6500 #ifdef _SC_THREAD_PROCESS_SHARED
6501 {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
6502 #endif
6503 #ifdef _SC_THREAD_SAFE_FUNCTIONS
6504 {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
6505 #endif
6506 #ifdef _SC_THREAD_STACK_MIN
6507 {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
6508 #endif
6509 #ifdef _SC_THREAD_THREADS_MAX
6510 {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
6511 #endif
6512 #ifdef _SC_TIMERS
6513 {"SC_TIMERS", _SC_TIMERS},
6514 #endif
6515 #ifdef _SC_TIMER_MAX
6516 {"SC_TIMER_MAX", _SC_TIMER_MAX},
6517 #endif
6518 #ifdef _SC_TTY_NAME_MAX
6519 {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
6520 #endif
6521 #ifdef _SC_TZNAME_MAX
6522 {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
6523 #endif
6524 #ifdef _SC_T_IOV_MAX
6525 {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
6526 #endif
6527 #ifdef _SC_UCHAR_MAX
6528 {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
6529 #endif
6530 #ifdef _SC_UINT_MAX
6531 {"SC_UINT_MAX", _SC_UINT_MAX},
6532 #endif
6533 #ifdef _SC_UIO_MAXIOV
6534 {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
6535 #endif
6536 #ifdef _SC_ULONG_MAX
6537 {"SC_ULONG_MAX", _SC_ULONG_MAX},
6538 #endif
6539 #ifdef _SC_USHRT_MAX
6540 {"SC_USHRT_MAX", _SC_USHRT_MAX},
6541 #endif
6542 #ifdef _SC_VERSION
6543 {"SC_VERSION", _SC_VERSION},
6544 #endif
6545 #ifdef _SC_WORD_BIT
6546 {"SC_WORD_BIT", _SC_WORD_BIT},
6547 #endif
6548 #ifdef _SC_XBS5_ILP32_OFF32
6549 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
6550 #endif
6551 #ifdef _SC_XBS5_ILP32_OFFBIG
6552 {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
6553 #endif
6554 #ifdef _SC_XBS5_LP64_OFF64
6555 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
6556 #endif
6557 #ifdef _SC_XBS5_LPBIG_OFFBIG
6558 {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
6559 #endif
6560 #ifdef _SC_XOPEN_CRYPT
6561 {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
6562 #endif
6563 #ifdef _SC_XOPEN_ENH_I18N
6564 {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
6565 #endif
6566 #ifdef _SC_XOPEN_LEGACY
6567 {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
6568 #endif
6569 #ifdef _SC_XOPEN_REALTIME
6570 {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
6571 #endif
6572 #ifdef _SC_XOPEN_REALTIME_THREADS
6573 {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
6574 #endif
6575 #ifdef _SC_XOPEN_SHM
6576 {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
6577 #endif
6578 #ifdef _SC_XOPEN_UNIX
6579 {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
6580 #endif
6581 #ifdef _SC_XOPEN_VERSION
6582 {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
6583 #endif
6584 #ifdef _SC_XOPEN_XCU_VERSION
6585 {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
6586 #endif
6587 #ifdef _SC_XOPEN_XPG2
6588 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
6589 #endif
6590 #ifdef _SC_XOPEN_XPG3
6591 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
6592 #endif
6593 #ifdef _SC_XOPEN_XPG4
6594 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
6595 #endif
6596 };
6597
6598 static int
6599 conv_sysconf_confname(PyObject *arg, int *valuep)
6600 {
6601 return conv_confname(arg, valuep, posix_constants_sysconf,
6602 sizeof(posix_constants_sysconf)
6603 / sizeof(struct constdef));
6604 }
6605
6606 PyDoc_STRVAR(posix_sysconf__doc__,
6607 "sysconf(name) -> integer\n\n\
6608 Return an integer-valued system configuration variable.");
6609
6610 static PyObject *
6611 posix_sysconf(PyObject *self, PyObject *args)
6612 {
6613 PyObject *result = NULL;
6614 int name;
6615
6616 if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
6617 int value;
6618
6619 errno = 0;
6620 value = sysconf(name);
6621 if (value == -1 && errno != 0)
6622 posix_error();
6623 else
6624 result = PyInt_FromLong(value);
6625 }
6626 return result;
6627 }
6628 #endif
6629
6630
6631 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) || defined(HAVE_CONFSTR) || defined(HAVE_SYSCONF)
6632 /* This code is used to ensure that the tables of configuration value names
6633 * are in sorted order as required by conv_confname(), and also to build the
6634 * the exported dictionaries that are used to publish information about the
6635 * names available on the host platform.
6636 *
6637 * Sorting the table at runtime ensures that the table is properly ordered
6638 * when used, even for platforms we're not able to test on. It also makes
6639 * it easier to add additional entries to the tables.
6640 */
6641
6642 static int
6643 cmp_constdefs(const void *v1, const void *v2)
6644 {
6645 const struct constdef *c1 =
6646 (const struct constdef *) v1;
6647 const struct constdef *c2 =
6648 (const struct constdef *) v2;
6649
6650 return strcmp(c1->name, c2->name);
6651 }
6652
6653 static int
6654 setup_confname_table(struct constdef *table, size_t tablesize,
6655 char *tablename, PyObject *module)
6656 {
6657 PyObject *d = NULL;
6658 size_t i;
6659
6660 qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
6661 d = PyDict_New();
6662 if (d == NULL)
6663 return -1;
6664
6665 for (i=0; i < tablesize; ++i) {
6666 PyObject *o = PyInt_FromLong(table[i].value);
6667 if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
6668 Py_XDECREF(o);
6669 Py_DECREF(d);
6670 return -1;
6671 }
6672 Py_DECREF(o);
6673 }
6674 return PyModule_AddObject(module, tablename, d);
6675 }
6676 #endif /* HAVE_FPATHCONF || HAVE_PATHCONF || HAVE_CONFSTR || HAVE_SYSCONF */
6677
6678 /* Return -1 on failure, 0 on success. */
6679 static int
6680 setup_confname_tables(PyObject *module)
6681 {
6682 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
6683 if (setup_confname_table(posix_constants_pathconf,
6684 sizeof(posix_constants_pathconf)
6685 / sizeof(struct constdef),
6686 "pathconf_names", module))
6687 return -1;
6688 #endif
6689 #ifdef HAVE_CONFSTR
6690 if (setup_confname_table(posix_constants_confstr,
6691 sizeof(posix_constants_confstr)
6692 / sizeof(struct constdef),
6693 "confstr_names", module))
6694 return -1;
6695 #endif
6696 #ifdef HAVE_SYSCONF
6697 if (setup_confname_table(posix_constants_sysconf,
6698 sizeof(posix_constants_sysconf)
6699 / sizeof(struct constdef),
6700 "sysconf_names", module))
6701 return -1;
6702 #endif
6703 return 0;
6704 }
6705
6706
6707 PyDoc_STRVAR(posix_abort__doc__,
6708 "abort() -> does not return!\n\n\
6709 Abort the interpreter immediately. This 'dumps core' or otherwise fails\n\
6710 in the hardest way possible on the hosting operating system.");
6711
6712 static PyObject *
6713 posix_abort(PyObject *self, PyObject *noargs)
6714 {
6715 abort();
6716 /*NOTREACHED*/
6717 Py_FatalError("abort() called from Python code didn't abort!");
6718 return NULL;
6719 }
6720
6721 #ifdef HAVE_SETRESUID
6722 PyDoc_STRVAR(posix_setresuid__doc__,
6723 "setresuid(ruid, euid, suid)\n\n\
6724 Set the current process's real, effective, and saved user ids.");
6725
6726 static PyObject*
6727 posix_setresuid (PyObject *self, PyObject *args)
6728 {
6729 /* We assume uid_t is no larger than a long. */
6730 long ruid, euid, suid;
6731 if (!PyArg_ParseTuple(args, "lll", &ruid, &euid, &suid))
6732 return NULL;
6733 if (setresuid(ruid, euid, suid) < 0)
6734 return posix_error();
6735 Py_RETURN_NONE;
6736 }
6737 #endif
6738
6739 #ifdef HAVE_SETRESGID
6740 PyDoc_STRVAR(posix_setresgid__doc__,
6741 "setresgid(rgid, egid, sgid)\n\n\
6742 Set the current process's real, effective, and saved group ids.");
6743
6744 static PyObject*
6745 posix_setresgid (PyObject *self, PyObject *args)
6746 {
6747 /* We assume uid_t is no larger than a long. */
6748 long rgid, egid, sgid;
6749 if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid))
6750 return NULL;
6751 if (setresgid(rgid, egid, sgid) < 0)
6752 return posix_error();
6753 Py_RETURN_NONE;
6754 }
6755 #endif
6756
6757 #ifdef HAVE_GETRESUID
6758 PyDoc_STRVAR(posix_getresuid__doc__,
6759 "getresuid() -> (ruid, euid, suid)\n\n\
6760 Get tuple of the current process's real, effective, and saved user ids.");
6761
6762 static PyObject*
6763 posix_getresuid (PyObject *self, PyObject *noargs)
6764 {
6765 uid_t ruid, euid, suid;
6766 long l_ruid, l_euid, l_suid;
6767 if (getresuid(&ruid, &euid, &suid) < 0)
6768 return posix_error();
6769 /* Force the values into long's as we don't know the size of uid_t. */
6770 l_ruid = ruid;
6771 l_euid = euid;
6772 l_suid = suid;
6773 return Py_BuildValue("(lll)", l_ruid, l_euid, l_suid);
6774 }
6775 #endif
6776
6777 #ifdef HAVE_GETRESGID
6778 PyDoc_STRVAR(posix_getresgid__doc__,
6779 "getresgid() -> (rgid, egid, sgid)\n\n\
6780 Get tuple of the current process's real, effective, and saved group ids.");
6781
6782 static PyObject*
6783 posix_getresgid (PyObject *self, PyObject *noargs)
6784 {
6785 uid_t rgid, egid, sgid;
6786 long l_rgid, l_egid, l_sgid;
6787 if (getresgid(&rgid, &egid, &sgid) < 0)
6788 return posix_error();
6789 /* Force the values into long's as we don't know the size of uid_t. */
6790 l_rgid = rgid;
6791 l_egid = egid;
6792 l_sgid = sgid;
6793 return Py_BuildValue("(lll)", l_rgid, l_egid, l_sgid);
6794 }
6795 #endif
6796
6797 static PyMethodDef posix_methods[] = {
6798 {"access", posix_access, METH_VARARGS, posix_access__doc__},
6799 #ifdef HAVE_TTYNAME
6800 {"ttyname", posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
6801 #endif
6802 {"chdir", posix_chdir, METH_VARARGS, posix_chdir__doc__},
6803 #ifdef HAVE_CHFLAGS
6804 {"chflags", posix_chflags, METH_VARARGS, posix_chflags__doc__},
6805 #endif /* HAVE_CHFLAGS */
6806 {"chmod", posix_chmod, METH_VARARGS, posix_chmod__doc__},
6807 #ifdef HAVE_FCHMOD
6808 {"fchmod", posix_fchmod, METH_VARARGS, posix_fchmod__doc__},
6809 #endif /* HAVE_FCHMOD */
6810 #ifdef HAVE_CHOWN
6811 {"chown", posix_chown, METH_VARARGS, posix_chown__doc__},
6812 #endif /* HAVE_CHOWN */
6813 #ifdef HAVE_LCHMOD
6814 {"lchmod", posix_lchmod, METH_VARARGS, posix_lchmod__doc__},
6815 #endif /* HAVE_LCHMOD */
6816 #ifdef HAVE_FCHOWN
6817 {"fchown", posix_fchown, METH_VARARGS, posix_fchown__doc__},
6818 #endif /* HAVE_FCHOWN */
6819 #ifdef HAVE_LCHFLAGS
6820 {"lchflags", posix_lchflags, METH_VARARGS, posix_lchflags__doc__},
6821 #endif /* HAVE_LCHFLAGS */
6822 #ifdef HAVE_LCHOWN
6823 {"lchown", posix_lchown, METH_VARARGS, posix_lchown__doc__},
6824 #endif /* HAVE_LCHOWN */
6825 #ifdef HAVE_CHROOT
6826 {"chroot", posix_chroot, METH_VARARGS, posix_chroot__doc__},
6827 #endif
6828 #ifdef HAVE_CTERMID
6829 {"ctermid", posix_ctermid, METH_NOARGS, posix_ctermid__doc__},
6830 #endif
6831 #ifdef HAVE_GETCWD
6832 {"getcwd", posix_getcwd, METH_NOARGS, posix_getcwd__doc__},
6833 #ifdef Py_USING_UNICODE
6834 {"getcwdu", posix_getcwdu, METH_NOARGS, posix_getcwdu__doc__},
6835 #endif
6836 #endif
6837 #ifdef HAVE_LINK
6838 {"link", posix_link, METH_VARARGS, posix_link__doc__},
6839 #endif /* HAVE_LINK */
6840 {"listdir", posix_listdir, METH_VARARGS, posix_listdir__doc__},
6841 {"lstat", posix_lstat, METH_VARARGS, posix_lstat__doc__},
6842 {"mkdir", posix_mkdir, METH_VARARGS, posix_mkdir__doc__},
6843 #ifdef HAVE_NICE
6844 {"nice", posix_nice, METH_VARARGS, posix_nice__doc__},
6845 #endif /* HAVE_NICE */
6846 #ifdef HAVE_READLINK
6847 {"readlink", posix_readlink, METH_VARARGS, posix_readlink__doc__},
6848 #endif /* HAVE_READLINK */
6849 {"rename", posix_rename, METH_VARARGS, posix_rename__doc__},
6850 {"rmdir", posix_rmdir, METH_VARARGS, posix_rmdir__doc__},
6851 {"stat", posix_stat, METH_VARARGS, posix_stat__doc__},
6852 //{"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
6853 #ifdef HAVE_SYMLINK
6854 {"symlink", posix_symlink, METH_VARARGS, posix_symlink__doc__},
6855 #endif /* HAVE_SYMLINK */
6856 #ifdef HAVE_SYSTEM
6857 {"system", posix_system, METH_VARARGS, posix_system__doc__},
6858 #endif
6859 {"umask", posix_umask, METH_VARARGS, posix_umask__doc__},
6860 #ifdef HAVE_UNAME
6861 {"uname", posix_uname, METH_NOARGS, posix_uname__doc__},
6862 #endif /* HAVE_UNAME */
6863 {"unlink", posix_unlink, METH_VARARGS, posix_unlink__doc__},
6864 {"remove", posix_unlink, METH_VARARGS, posix_remove__doc__},
6865 {"utime", posix_utime, METH_VARARGS, posix_utime__doc__},
6866 #ifdef HAVE_TIMES
6867 {"times", posix_times, METH_NOARGS, posix_times__doc__},
6868 #endif /* HAVE_TIMES */
6869 {"_exit", posix__exit, METH_VARARGS, posix__exit__doc__},
6870 #ifdef HAVE_EXECV
6871 {"execv", posix_execv, METH_VARARGS, posix_execv__doc__},
6872 {"execve", posix_execve, METH_VARARGS, posix_execve__doc__},
6873 #endif /* HAVE_EXECV */
6874 #ifdef HAVE_SPAWNV
6875 {"spawnv", posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
6876 {"spawnve", posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
6877 #if defined(PYOS_OS2)
6878 {"spawnvp", posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__},
6879 {"spawnvpe", posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__},
6880 #endif /* PYOS_OS2 */
6881 #endif /* HAVE_SPAWNV */
6882 #ifdef HAVE_FORK1
6883 {"fork1", posix_fork1, METH_NOARGS, posix_fork1__doc__},
6884 #endif /* HAVE_FORK1 */
6885 #ifdef HAVE_FORK
6886 {"fork", posix_fork, METH_NOARGS, posix_fork__doc__},
6887 #endif /* HAVE_FORK */
6888 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
6889 {"openpty", posix_openpty, METH_NOARGS, posix_openpty__doc__},
6890 #endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
6891 #ifdef HAVE_FORKPTY
6892 {"forkpty", posix_forkpty, METH_NOARGS, posix_forkpty__doc__},
6893 #endif /* HAVE_FORKPTY */
6894 #ifdef HAVE_GETEGID
6895 {"getegid", posix_getegid, METH_NOARGS, posix_getegid__doc__},
6896 #endif /* HAVE_GETEGID */
6897 #ifdef HAVE_GETEUID
6898 {"geteuid", posix_geteuid, METH_NOARGS, posix_geteuid__doc__},
6899 #endif /* HAVE_GETEUID */
6900 #ifdef HAVE_GETGID
6901 {"getgid", posix_getgid, METH_NOARGS, posix_getgid__doc__},
6902 #endif /* HAVE_GETGID */
6903 #ifdef HAVE_GETGROUPS
6904 {"getgroups", posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
6905 #endif
6906 {"getpid", posix_getpid, METH_NOARGS, posix_getpid__doc__},
6907 #ifdef HAVE_GETPGRP
6908 {"getpgrp", posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__},
6909 #endif /* HAVE_GETPGRP */
6910 #ifdef HAVE_GETPPID
6911 {"getppid", posix_getppid, METH_NOARGS, posix_getppid__doc__},
6912 #endif /* HAVE_GETPPID */
6913 #ifdef HAVE_GETUID
6914 {"getuid", posix_getuid, METH_NOARGS, posix_getuid__doc__},
6915 #endif /* HAVE_GETUID */
6916 #ifdef HAVE_GETLOGIN
6917 {"getlogin", posix_getlogin, METH_NOARGS, posix_getlogin__doc__},
6918 #endif
6919 #ifdef HAVE_KILL
6920 {"kill", posix_kill, METH_VARARGS, posix_kill__doc__},
6921 #endif /* HAVE_KILL */
6922 #ifdef HAVE_KILLPG
6923 {"killpg", posix_killpg, METH_VARARGS, posix_killpg__doc__},
6924 #endif /* HAVE_KILLPG */
6925 #ifdef HAVE_PLOCK
6926 {"plock", posix_plock, METH_VARARGS, posix_plock__doc__},
6927 #endif /* HAVE_PLOCK */
6928 #ifdef HAVE_POPEN
6929 {"popen", posix_popen, METH_VARARGS, posix_popen__doc__},
6930 #ifdef MS_WINDOWS
6931 {"popen2", win32_popen2, METH_VARARGS},
6932 {"popen3", win32_popen3, METH_VARARGS},
6933 {"popen4", win32_popen4, METH_VARARGS},
6934 {"startfile", win32_startfile, METH_VARARGS, win32_startfile__doc__},
6935 {"kill", win32_kill, METH_VARARGS, win32_kill__doc__},
6936 #else
6937 #if defined(PYOS_OS2) && defined(PYCC_GCC)
6938 {"popen2", os2emx_popen2, METH_VARARGS},
6939 {"popen3", os2emx_popen3, METH_VARARGS},
6940 {"popen4", os2emx_popen4, METH_VARARGS},
6941 #endif
6942 #endif
6943 #endif /* HAVE_POPEN */
6944 #ifdef HAVE_SETUID
6945 {"setuid", posix_setuid, METH_VARARGS, posix_setuid__doc__},
6946 #endif /* HAVE_SETUID */
6947 #ifdef HAVE_SETEUID
6948 {"seteuid", posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
6949 #endif /* HAVE_SETEUID */
6950 #ifdef HAVE_SETEGID
6951 {"setegid", posix_setegid, METH_VARARGS, posix_setegid__doc__},
6952 #endif /* HAVE_SETEGID */
6953 #ifdef HAVE_SETREUID
6954 {"setreuid", posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
6955 #endif /* HAVE_SETREUID */
6956 #ifdef HAVE_SETREGID
6957 {"setregid", posix_setregid, METH_VARARGS, posix_setregid__doc__},
6958 #endif /* HAVE_SETREGID */
6959 #ifdef HAVE_SETGID
6960 {"setgid", posix_setgid, METH_VARARGS, posix_setgid__doc__},
6961 #endif /* HAVE_SETGID */
6962 #ifdef HAVE_SETGROUPS
6963 {"setgroups", posix_setgroups, METH_O, posix_setgroups__doc__},
6964 #endif /* HAVE_SETGROUPS */
6965 #ifdef HAVE_INITGROUPS
6966 {"initgroups", posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
6967 #endif /* HAVE_INITGROUPS */
6968 #ifdef HAVE_GETPGID
6969 {"getpgid", posix_getpgid, METH_VARARGS, posix_getpgid__doc__},
6970 #endif /* HAVE_GETPGID */
6971 #ifdef HAVE_SETPGRP
6972 {"setpgrp", posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__},
6973 #endif /* HAVE_SETPGRP */
6974 #ifdef HAVE_WAIT
6975 {"wait", posix_wait, METH_NOARGS, posix_wait__doc__},
6976 #endif /* HAVE_WAIT */
6977 #ifdef HAVE_WAIT3
6978 {"wait3", posix_wait3, METH_VARARGS, posix_wait3__doc__},
6979 #endif /* HAVE_WAIT3 */
6980 #ifdef HAVE_WAIT4
6981 {"wait4", posix_wait4, METH_VARARGS, posix_wait4__doc__},
6982 #endif /* HAVE_WAIT4 */
6983 #if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
6984 {"waitpid", posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
6985 #endif /* HAVE_WAITPID */
6986 #ifdef HAVE_GETSID
6987 {"getsid", posix_getsid, METH_VARARGS, posix_getsid__doc__},
6988 #endif /* HAVE_GETSID */
6989 #ifdef HAVE_SETSID
6990 {"setsid", posix_setsid, METH_NOARGS, posix_setsid__doc__},
6991 #endif /* HAVE_SETSID */
6992 #ifdef HAVE_SETPGID
6993 {"setpgid", posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
6994 #endif /* HAVE_SETPGID */
6995 #ifdef HAVE_TCGETPGRP
6996 {"tcgetpgrp", posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
6997 #endif /* HAVE_TCGETPGRP */
6998 #ifdef HAVE_TCSETPGRP
6999 {"tcsetpgrp", posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
7000 #endif /* HAVE_TCSETPGRP */
7001 {"open", posix_open, METH_VARARGS, posix_open__doc__},
7002 {"close", posix_close, METH_VARARGS, posix_close__doc__},
7003 {"closerange", posix_closerange, METH_VARARGS, posix_closerange__doc__},
7004 {"dup", posix_dup, METH_VARARGS, posix_dup__doc__},
7005 {"dup2", posix_dup2, METH_VARARGS, posix_dup2__doc__},
7006 {"lseek", posix_lseek, METH_VARARGS, posix_lseek__doc__},
7007 {"read", posix_read, METH_VARARGS, posix_read__doc__},
7008 {"write", posix_write, METH_VARARGS, posix_write__doc__},
7009 {"fstat", posix_fstat, METH_VARARGS, posix_fstat__doc__},
7010 {"fdopen", posix_fdopen, METH_VARARGS, posix_fdopen__doc__},
7011 {"isatty", posix_isatty, METH_VARARGS, posix_isatty__doc__},
7012 #ifdef HAVE_PIPE
7013 {"pipe", posix_pipe, METH_NOARGS, posix_pipe__doc__},
7014 #endif
7015 #ifdef HAVE_MKFIFO
7016 {"mkfifo", posix_mkfifo, METH_VARARGS, posix_mkfifo__doc__},
7017 #endif
7018 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
7019 {"mknod", posix_mknod, METH_VARARGS, posix_mknod__doc__},
7020 #endif
7021 #ifdef HAVE_DEVICE_MACROS
7022 {"major", posix_major, METH_VARARGS, posix_major__doc__},
7023 {"minor", posix_minor, METH_VARARGS, posix_minor__doc__},
7024 {"makedev", posix_makedev, METH_VARARGS, posix_makedev__doc__},
7025 #endif
7026 #ifdef HAVE_FTRUNCATE
7027 {"ftruncate", posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
7028 #endif
7029 #ifdef HAVE_PUTENV
7030 {"putenv", posix_putenv, METH_VARARGS, posix_putenv__doc__},
7031 #endif
7032 #ifdef HAVE_UNSETENV
7033 {"unsetenv", posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__},
7034 #endif
7035 {"strerror", posix_strerror, METH_VARARGS, posix_strerror__doc__},
7036 #ifdef HAVE_FCHDIR
7037 {"fchdir", posix_fchdir, METH_O, posix_fchdir__doc__},
7038 #endif
7039 #ifdef HAVE_FSYNC
7040 {"fsync", posix_fsync, METH_O, posix_fsync__doc__},
7041 #endif
7042 #ifdef HAVE_FDATASYNC
7043 {"fdatasync", posix_fdatasync, METH_O, posix_fdatasync__doc__},
7044 #endif
7045 #ifdef HAVE_SYS_WAIT_H
7046 #ifdef WCOREDUMP
7047 {"WCOREDUMP", posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__},
7048 #endif /* WCOREDUMP */
7049 #ifdef WIFCONTINUED
7050 {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__},
7051 #endif /* WIFCONTINUED */
7052 #ifdef WIFSTOPPED
7053 {"WIFSTOPPED", posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
7054 #endif /* WIFSTOPPED */
7055 #ifdef WIFSIGNALED
7056 {"WIFSIGNALED", posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
7057 #endif /* WIFSIGNALED */
7058 #ifdef WIFEXITED
7059 {"WIFEXITED", posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
7060 #endif /* WIFEXITED */
7061 #ifdef WEXITSTATUS
7062 {"WEXITSTATUS", posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
7063 #endif /* WEXITSTATUS */
7064 #ifdef WTERMSIG
7065 {"WTERMSIG", posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
7066 #endif /* WTERMSIG */
7067 #ifdef WSTOPSIG
7068 {"WSTOPSIG", posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
7069 #endif /* WSTOPSIG */
7070 #endif /* HAVE_SYS_WAIT_H */
7071 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
7072 {"fstatvfs", posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
7073 #endif
7074 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
7075 {"statvfs", posix_statvfs, METH_VARARGS, posix_statvfs__doc__},
7076 #endif
7077 #ifdef HAVE_TMPFILE
7078 {"tmpfile", posix_tmpfile, METH_NOARGS, posix_tmpfile__doc__},
7079 #endif
7080 #ifdef HAVE_TEMPNAM
7081 {"tempnam", posix_tempnam, METH_VARARGS, posix_tempnam__doc__},
7082 #endif
7083 #ifdef HAVE_TMPNAM
7084 {"tmpnam", posix_tmpnam, METH_NOARGS, posix_tmpnam__doc__},
7085 #endif
7086 #ifdef HAVE_CONFSTR
7087 {"confstr", posix_confstr, METH_VARARGS, posix_confstr__doc__},
7088 #endif
7089 #ifdef HAVE_SYSCONF
7090 {"sysconf", posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
7091 #endif
7092 #ifdef HAVE_FPATHCONF
7093 {"fpathconf", posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
7094 #endif
7095 #ifdef HAVE_PATHCONF
7096 {"pathconf", posix_pathconf, METH_VARARGS, posix_pathconf__doc__},
7097 #endif
7098 {"abort", posix_abort, METH_NOARGS, posix_abort__doc__},
7099 #ifdef HAVE_SETRESUID
7100 {"setresuid", posix_setresuid, METH_VARARGS, posix_setresuid__doc__},
7101 #endif
7102 #ifdef HAVE_SETRESGID
7103 {"setresgid", posix_setresgid, METH_VARARGS, posix_setresgid__doc__},
7104 #endif
7105 #ifdef HAVE_GETRESUID
7106 {"getresuid", posix_getresuid, METH_NOARGS, posix_getresuid__doc__},
7107 #endif
7108 #ifdef HAVE_GETRESGID
7109 {"getresgid", posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
7110 #endif
7111
7112 {NULL, NULL} /* Sentinel */
7113 };
7114
7115
7116 static int
7117 ins(PyObject *module, char *symbol, long value)
7118 {
7119 return PyModule_AddIntConstant(module, symbol, value);
7120 }
7121
7122 static int
7123 all_ins(PyObject *d)
7124 {
7125 #ifdef F_OK
7126 if (ins(d, "F_OK", (long)F_OK)) return -1;
7127 #endif
7128 #ifdef R_OK
7129 if (ins(d, "R_OK", (long)R_OK)) return -1;
7130 #endif
7131 #ifdef W_OK
7132 if (ins(d, "W_OK", (long)W_OK)) return -1;
7133 #endif
7134 #ifdef X_OK
7135 if (ins(d, "X_OK", (long)X_OK)) return -1;
7136 #endif
7137 #ifdef NGROUPS_MAX
7138 if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
7139 #endif
7140 #ifdef TMP_MAX
7141 if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
7142 #endif
7143 #ifdef WCONTINUED
7144 if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
7145 #endif
7146 #ifdef WNOHANG
7147 if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
7148 #endif
7149 #ifdef WUNTRACED
7150 if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
7151 #endif
7152 #ifdef O_RDONLY
7153 if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
7154 #endif
7155 #ifdef O_WRONLY
7156 if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
7157 #endif
7158 #ifdef O_RDWR
7159 if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
7160 #endif
7161 #ifdef O_NDELAY
7162 if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
7163 #endif
7164 #ifdef O_NONBLOCK
7165 if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
7166 #endif
7167 #ifdef O_APPEND
7168 if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
7169 #endif
7170 #ifdef O_DSYNC
7171 if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
7172 #endif
7173 #ifdef O_RSYNC
7174 if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
7175 #endif
7176 #ifdef O_SYNC
7177 if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
7178 #endif
7179 #ifdef O_NOCTTY
7180 if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
7181 #endif
7182 #ifdef O_CREAT
7183 if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
7184 #endif
7185 #ifdef O_EXCL
7186 if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
7187 #endif
7188 #ifdef O_TRUNC
7189 if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
7190 #endif
7191 #ifdef O_BINARY
7192 if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
7193 #endif
7194 #ifdef O_TEXT
7195 if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
7196 #endif
7197 #ifdef O_LARGEFILE
7198 if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
7199 #endif
7200 #ifdef O_SHLOCK
7201 if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
7202 #endif
7203 #ifdef O_EXLOCK
7204 if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
7205 #endif
7206
7207 /* MS Windows */
7208 #ifdef O_NOINHERIT
7209 /* Don't inherit in child processes. */
7210 if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
7211 #endif
7212 #ifdef _O_SHORT_LIVED
7213 /* Optimize for short life (keep in memory). */
7214 /* MS forgot to define this one with a non-underscore form too. */
7215 if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
7216 #endif
7217 #ifdef O_TEMPORARY
7218 /* Automatically delete when last handle is closed. */
7219 if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
7220 #endif
7221 #ifdef O_RANDOM
7222 /* Optimize for random access. */
7223 if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
7224 #endif
7225 #ifdef O_SEQUENTIAL
7226 /* Optimize for sequential access. */
7227 if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
7228 #endif
7229
7230 /* GNU extensions. */
7231 #ifdef O_ASYNC
7232 /* Send a SIGIO signal whenever input or output
7233 becomes available on file descriptor */
7234 if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1;
7235 #endif
7236 #ifdef O_DIRECT
7237 /* Direct disk access. */
7238 if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
7239 #endif
7240 #ifdef O_DIRECTORY
7241 /* Must be a directory. */
7242 if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
7243 #endif
7244 #ifdef O_NOFOLLOW
7245 /* Do not follow links. */
7246 if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
7247 #endif
7248 #ifdef O_NOATIME
7249 /* Do not update the access time. */
7250 if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1;
7251 #endif
7252
7253 /* These come from sysexits.h */
7254 #ifdef EX_OK
7255 if (ins(d, "EX_OK", (long)EX_OK)) return -1;
7256 #endif /* EX_OK */
7257 #ifdef EX_USAGE
7258 if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
7259 #endif /* EX_USAGE */
7260 #ifdef EX_DATAERR
7261 if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
7262 #endif /* EX_DATAERR */
7263 #ifdef EX_NOINPUT
7264 if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
7265 #endif /* EX_NOINPUT */
7266 #ifdef EX_NOUSER
7267 if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
7268 #endif /* EX_NOUSER */
7269 #ifdef EX_NOHOST
7270 if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
7271 #endif /* EX_NOHOST */
7272 #ifdef EX_UNAVAILABLE
7273 if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
7274 #endif /* EX_UNAVAILABLE */
7275 #ifdef EX_SOFTWARE
7276 if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
7277 #endif /* EX_SOFTWARE */
7278 #ifdef EX_OSERR
7279 if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
7280 #endif /* EX_OSERR */
7281 #ifdef EX_OSFILE
7282 if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
7283 #endif /* EX_OSFILE */
7284 #ifdef EX_CANTCREAT
7285 if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
7286 #endif /* EX_CANTCREAT */
7287 #ifdef EX_IOERR
7288 if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
7289 #endif /* EX_IOERR */
7290 #ifdef EX_TEMPFAIL
7291 if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
7292 #endif /* EX_TEMPFAIL */
7293 #ifdef EX_PROTOCOL
7294 if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
7295 #endif /* EX_PROTOCOL */
7296 #ifdef EX_NOPERM
7297 if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
7298 #endif /* EX_NOPERM */
7299 #ifdef EX_CONFIG
7300 if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
7301 #endif /* EX_CONFIG */
7302 #ifdef EX_NOTFOUND
7303 if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
7304 #endif /* EX_NOTFOUND */
7305
7306 #ifdef HAVE_SPAWNV
7307 #if defined(PYOS_OS2) && defined(PYCC_GCC)
7308 if (ins(d, "P_WAIT", (long)P_WAIT)) return -1;
7309 if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1;
7310 if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1;
7311 if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1;
7312 if (ins(d, "P_SESSION", (long)P_SESSION)) return -1;
7313 if (ins(d, "P_DETACH", (long)P_DETACH)) return -1;
7314 if (ins(d, "P_PM", (long)P_PM)) return -1;
7315 if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1;
7316 if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1;
7317 if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1;
7318 if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1;
7319 if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1;
7320 if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1;
7321 if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1;
7322 if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1;
7323 if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1;
7324 if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1;
7325 if (ins(d, "P_TILDE", (long)P_TILDE)) return -1;
7326 if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1;
7327 if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1;
7328 #else
7329 if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
7330 if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
7331 if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
7332 if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
7333 if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
7334 #endif
7335 #endif
7336 return 0;
7337 }
7338
7339 #define INITFUNC initedk2
7340 #define MODNAME "edk2"
7341
7342 PyMODINIT_FUNC
7343 INITFUNC(void)
7344 {
7345 PyObject *m;
7346
7347 #ifndef UEFI_C_SOURCE
7348 PyObject *v;
7349 #endif
7350
7351 m = Py_InitModule3(MODNAME,
7352 posix_methods,
7353 edk2__doc__);
7354 if (m == NULL)
7355 return;
7356
7357 #ifndef UEFI_C_SOURCE
7358 /* Initialize environ dictionary */
7359 v = convertenviron();
7360 Py_XINCREF(v);
7361 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
7362 return;
7363 Py_DECREF(v);
7364 #endif /* UEFI_C_SOURCE */
7365
7366 if (all_ins(m))
7367 return;
7368
7369 if (setup_confname_tables(m))
7370 return;
7371
7372 Py_INCREF(PyExc_OSError);
7373 PyModule_AddObject(m, "error", PyExc_OSError);
7374
7375 #ifdef HAVE_PUTENV
7376 if (posix_putenv_garbage == NULL)
7377 posix_putenv_garbage = PyDict_New();
7378 #endif
7379
7380 if (!initialized) {
7381 stat_result_desc.name = MODNAME ".stat_result";
7382 stat_result_desc.fields[2].name = PyStructSequence_UnnamedField;
7383 stat_result_desc.fields[3].name = PyStructSequence_UnnamedField;
7384 stat_result_desc.fields[4].name = PyStructSequence_UnnamedField;
7385 PyStructSequence_InitType(&StatResultType, &stat_result_desc);
7386 structseq_new = StatResultType.tp_new;
7387 StatResultType.tp_new = statresult_new;
7388
7389 //statvfs_result_desc.name = MODNAME ".statvfs_result";
7390 //PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
7391 #ifdef NEED_TICKS_PER_SECOND
7392 # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
7393 ticks_per_second = sysconf(_SC_CLK_TCK);
7394 # elif defined(HZ)
7395 ticks_per_second = HZ;
7396 # else
7397 ticks_per_second = 60; /* magic fallback value; may be bogus */
7398 # endif
7399 #endif
7400 }
7401 Py_INCREF((PyObject*) &StatResultType);
7402 PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
7403 //Py_INCREF((PyObject*) &StatVFSResultType);
7404 //PyModule_AddObject(m, "statvfs_result",
7405 // (PyObject*) &StatVFSResultType);
7406 initialized = 1;
7407
7408 }
7409
7410 #ifdef __cplusplus
7411 }
7412 #endif
7413
7414