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