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