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