home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / OPENSTEP / Languages / Python / python-14-src / Modules / posixmodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-17  |  34.2 KB  |  1,818 lines

  1. /***********************************************************
  2. Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
  3. The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its
  8. documentation for any purpose and without fee is hereby granted,
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI or Corporation for National Research Initiatives or
  13. CNRI not be used in advertising or publicity pertaining to
  14. distribution of the software without specific, written prior
  15. permission.
  16.  
  17. While CWI is the initial source for this software, a modified version
  18. is made available by the Corporation for National Research Initiatives
  19. (CNRI) at the Internet address ftp://ftp.python.org.
  20.  
  21. STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
  22. REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  23. MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
  24. CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  25. DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  26. PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  27. TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  28. PERFORMANCE OF THIS SOFTWARE.
  29.  
  30. ******************************************************************/
  31.  
  32. /* POSIX module implementation */
  33.  
  34. /* This file is also used for Windows NT and MS-Win.  In that case the module
  35.    actually calls itself 'nt', not 'posix', and a few functions are
  36.    either unimplemented or implemented differently.  The source
  37.    assumes that for Windows NT, the macro 'MS_WIN32' is defined independent
  38.    of the compiler used.  Different compilers define their own feature
  39.    test macro, e.g. '__BORLANDC__' or '_MSC_VER'. */
  40.  
  41. /* See also ../Dos/dosmodule.c */
  42.  
  43. #ifdef NeXT
  44. #include <libc.h>
  45. #endif
  46.  
  47. #include "allobjects.h"
  48. #include "modsupport.h"
  49. #include "ceval.h"
  50.  
  51. #include <string.h>
  52. #include <errno.h>
  53. #include <sys/types.h>
  54. #include <sys/stat.h>
  55. #ifdef HAVE_SYS_WAIT_H
  56. #include <sys/wait.h>        /* For WNOHANG */
  57. #endif
  58.  
  59. #include "mytime.h"        /* For clock_t on some systems */
  60.  
  61. #ifdef HAVE_FCNTL_H
  62. #include <fcntl.h>
  63. #endif /* HAVE_FCNTL_H */
  64.  
  65. /* Various compilers have only certain posix functions */
  66. #ifdef __WATCOMC__        /* Watcom compiler */
  67. #define HAVE_GETCWD     1
  68. #define HAVE_OPENDIR    1
  69. #define HAVE_SYSTEM    1
  70. #if defined(__OS2__)
  71. #define HAVE_EXECV      1
  72. #define HAVE_WAIT       1
  73. #endif
  74. #include <process.h>
  75. #else
  76. #ifdef __BORLANDC__        /* Borland compiler */
  77. #define HAVE_EXECV      1
  78. #define HAVE_GETCWD     1
  79. #define HAVE_GETEGID    1
  80. #define HAVE_GETEUID    1
  81. #define HAVE_GETGID     1
  82. #define HAVE_GETPPID    1
  83. #define HAVE_GETUID     1
  84. #define HAVE_KILL       1
  85. #define HAVE_OPENDIR    1
  86. #define HAVE_PIPE       1
  87. #define HAVE_POPEN      1
  88. #define HAVE_SYSTEM    1
  89. #define HAVE_WAIT       1
  90. #else
  91. #ifdef _MSC_VER        /* Microsoft compiler */
  92. #define HAVE_GETCWD     1
  93. #ifdef MS_WIN32
  94. #define HAVE_EXECV      1
  95. #define HAVE_PIPE       1
  96. #define HAVE_POPEN      1
  97. #define HAVE_SYSTEM    1
  98. #else /* 16-bit Windows */
  99. #endif /* !MS_WIN32 */
  100. #else            /* all other compilers */
  101. /* Unix functions that the configure script doesn't check for */
  102. #define HAVE_EXECV      1
  103. #define HAVE_FORK       1
  104. #define HAVE_GETCWD     1
  105. #define HAVE_GETEGID    1
  106. #define HAVE_GETEUID    1
  107. #define HAVE_GETGID     1
  108. #define HAVE_GETPPID    1
  109. #define HAVE_GETUID     1
  110. #define HAVE_KILL       1
  111. #define HAVE_OPENDIR    1
  112. #define HAVE_PIPE       1
  113. #define HAVE_POPEN      1
  114. #define HAVE_SYSTEM    1
  115. #define HAVE_WAIT       1
  116. #endif  /* _MSC_VER */
  117. #endif  /* __BORLANDC__ */
  118. #endif  /* ! __WATCOMC__ */
  119.  
  120. #ifndef _MSC_VER
  121.  
  122. #ifdef HAVE_UNISTD_H
  123. #include <unistd.h>
  124. #endif
  125.  
  126. #ifdef NeXT
  127. #undef HAVE_UTIME_H
  128. extern char * getcwd(char *buf, int size);
  129. #endif
  130.  
  131. #ifdef HAVE_UNISTD_H
  132. /* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */
  133. extern int rename();
  134. extern int pclose();
  135. extern int lstat();
  136. extern int symlink();
  137. #else /* !HAVE_UNISTD_H */
  138. #if defined(__WATCOMC__) || defined(_MSC_VER)
  139. extern int mkdir PROTO((const char *));
  140. #else
  141. extern int mkdir PROTO((const char *, mode_t));
  142. #endif
  143. extern int chdir PROTO((const char *));
  144. extern int rmdir PROTO((const char *));
  145. extern int chmod PROTO((const char *, mode_t));
  146. extern int chown PROTO((const char *, uid_t, gid_t));
  147. extern char *getcwd PROTO((char *, int));
  148. extern char *strerror PROTO((int));
  149. extern int link PROTO((const char *, const char *));
  150. extern int rename PROTO((const char *, const char *));
  151. extern int stat PROTO((const char *, struct stat *));
  152. extern int unlink PROTO((const char *));
  153. extern int pclose PROTO((FILE *));
  154. #ifdef HAVE_SYMLINK
  155. extern int symlink PROTO((const char *, const char *));
  156. #endif /* HAVE_SYMLINK */
  157. #ifdef HAVE_LSTAT
  158. extern int lstat PROTO((const char *, struct stat *));
  159. #endif /* HAVE_LSTAT */
  160. #endif /* !HAVE_UNISTD_H */
  161.  
  162. #endif /* !_MSC_VER */
  163.  
  164. #ifdef HAVE_UTIME_H
  165. #include <utime.h>
  166. #endif /* HAVE_UTIME_H */
  167.  
  168. #ifdef HAVE_SYS_UTIME_H
  169. #include <sys/utime.h>
  170. #define HAVE_UTIME_H /* pretend we do for the rest of this file */
  171. #endif /* HAVE_SYS_UTIME_H */
  172.  
  173. #ifdef HAVE_SYS_TIMES_H
  174. #include <sys/times.h>
  175. #endif /* HAVE_SYS_TIMES_H */
  176.  
  177. #ifdef HAVE_SYS_PARAM_H
  178. #include <sys/param.h>
  179. #endif /* HAVE_SYS_PARAM_H */
  180.  
  181. #ifdef HAVE_SYS_UTSNAME_H
  182. #include <sys/utsname.h>
  183. #endif /* HAVE_SYS_UTSNAME_H */
  184.  
  185. #ifndef MAXPATHLEN
  186. #define MAXPATHLEN 1024
  187. #endif /* MAXPATHLEN */
  188.  
  189. #ifdef HAVE_DIRENT_H
  190. #include <dirent.h>
  191. #define NAMLEN(dirent) strlen((dirent)->d_name)
  192. #else
  193. #ifdef __WATCOMC__
  194. #include <direct.h>
  195. #define NAMLEN(dirent) strlen((dirent)->d_name)
  196. #else
  197. #define dirent direct
  198. #define NAMLEN(dirent) (dirent)->d_namlen
  199. #endif
  200. #ifdef HAVE_SYS_NDIR_H
  201. #include <sys/ndir.h>
  202. #endif
  203. #ifdef HAVE_SYS_DIR_H
  204. #include <sys/dir.h>
  205. #endif
  206. #ifdef HAVE_NDIR_H
  207. #include <ndir.h>
  208. #endif
  209. #endif
  210.  
  211. #ifdef _MSC_VER
  212. #include <direct.h>
  213. #include <io.h>
  214. #include <process.h>
  215. #include <windows.h>
  216. #ifdef MS_WIN32
  217. #define popen    _popen
  218. #define pclose    _pclose
  219. #else /* 16-bit Windows */
  220. #include <dos.h>
  221. #include <ctype.h>
  222. #endif /* MS_WIN32 */
  223. #endif /* _MSC_VER */
  224.  
  225. #ifdef OS2
  226. #include <io.h>
  227. #endif /* OS2 */
  228.  
  229. /* Return a dictionary corresponding to the POSIX environment table */
  230.  
  231. #if !defined(_MSC_VER) && !defined(__WATCOMC__)
  232. extern char **environ;
  233. #endif /* !_MSC_VER */
  234.  
  235. static object *
  236. convertenviron()
  237. {
  238.     object *d;
  239.     char **e;
  240.     d = newdictobject();
  241.     if (d == NULL)
  242.         return NULL;
  243.     if (environ == NULL)
  244.         return d;
  245.     /* XXX This part ignores errors */
  246.     for (e = environ; *e != NULL; e++) {
  247.         object *v;
  248.         char *p = strchr(*e, '=');
  249.         if (p == NULL)
  250.             continue;
  251.         v = newstringobject(p+1);
  252.         if (v == NULL)
  253.             continue;
  254.         *p = '\0';
  255.         (void) dictinsert(d, *e, v);
  256.         *p = '=';
  257.         DECREF(v);
  258.     }
  259.     return d;
  260. }
  261.  
  262.  
  263. static object *PosixError; /* Exception posix.error */
  264.  
  265. /* Set a POSIX-specific error from errno, and return NULL */
  266.  
  267. static object * posix_error()
  268. {
  269.     return err_errno(PosixError);
  270. }
  271.  
  272.  
  273. /* POSIX generic methods */
  274.  
  275. static object *
  276. posix_1str(args, func)
  277.     object *args;
  278.     int (*func) FPROTO((const char *));
  279. {
  280.     char *path1;
  281.     int res;
  282.     if (!getargs(args, "s", &path1))
  283.         return NULL;
  284.     BGN_SAVE
  285.     res = (*func)(path1);
  286.     END_SAVE
  287.     if (res < 0)
  288.         return posix_error();
  289.     INCREF(None);
  290.     return None;
  291. }
  292.  
  293. static object *
  294. posix_2str(args, func)
  295.     object *args;
  296.     int (*func) FPROTO((const char *, const char *));
  297. {
  298.     char *path1, *path2;
  299.     int res;
  300.     if (!getargs(args, "(ss)", &path1, &path2))
  301.         return NULL;
  302.     BGN_SAVE
  303.     res = (*func)(path1, path2);
  304.     END_SAVE
  305.     if (res < 0)
  306.         return posix_error();
  307.     INCREF(None);
  308.     return None;
  309. }
  310.  
  311. static object *
  312. posix_strint(args, func)
  313.     object *args;
  314.     int (*func) FPROTO((const char *, int));
  315. {
  316.     char *path;
  317.     int i;
  318.     int res;
  319.     if (!getargs(args, "(si)", &path, &i))
  320.         return NULL;
  321.     BGN_SAVE
  322.     res = (*func)(path, i);
  323.     END_SAVE
  324.     if (res < 0)
  325.         return posix_error();
  326.     INCREF(None);
  327.     return None;
  328. }
  329.  
  330. static object *
  331. posix_strintint(args, func)
  332.     object *args;
  333.     int (*func) FPROTO((const char *, int, int));
  334. {
  335.     char *path;
  336.     int i,i2;
  337.     int res;
  338.     if (!getargs(args, "(sii)", &path, &i, &i2))
  339.         return NULL;
  340.     BGN_SAVE
  341.     res = (*func)(path, i, i2);
  342.     END_SAVE
  343.     if (res < 0)
  344.         return posix_error();
  345.     INCREF(None);
  346.     return None;
  347. }
  348.  
  349. static object *
  350. posix_do_stat(self, args, statfunc)
  351.     object *self;
  352.     object *args;
  353.     int (*statfunc) FPROTO((const char *, struct stat *));
  354. {
  355.     struct stat st;
  356.     char *path;
  357.     int res;
  358.     if (!getargs(args, "s", &path))
  359.         return NULL;
  360.     BGN_SAVE
  361.     res = (*statfunc)(path, &st);
  362.     END_SAVE
  363.     if (res != 0)
  364.         return posix_error();
  365.     return mkvalue("(llllllllll)",
  366.             (long)st.st_mode,
  367.             (long)st.st_ino,
  368.             (long)st.st_dev,
  369.             (long)st.st_nlink,
  370.             (long)st.st_uid,
  371.             (long)st.st_gid,
  372.             (long)st.st_size,
  373.             (long)st.st_atime,
  374.             (long)st.st_mtime,
  375.             (long)st.st_ctime);
  376. }
  377.  
  378.  
  379. /* POSIX methods */
  380.  
  381. static object *
  382. posix_chdir(self, args)
  383.     object *self;
  384.     object *args;
  385. {
  386.     return posix_1str(args, chdir);
  387. }
  388.  
  389. static object *
  390. posix_chmod(self, args)
  391.     object *self;
  392.     object *args;
  393. {
  394.     return posix_strint(args, chmod);
  395. }
  396.  
  397. #ifdef HAVE_CHOWN
  398. static object *
  399. posix_chown(self, args)
  400.     object *self;
  401.     object *args;
  402. {
  403.     return posix_strintint(args, chown);
  404. }
  405. #endif /* HAVE_CHOWN */
  406.  
  407. #ifdef HAVE_GETCWD
  408. static object *
  409. posix_getcwd(self, args)
  410.     object *self;
  411.     object *args;
  412. {
  413.     char buf[1026];
  414.     char *res;
  415.     if (!getnoarg(args))
  416.         return NULL;
  417.     BGN_SAVE
  418.     res = getcwd(buf, sizeof buf);
  419.     END_SAVE
  420.     if (res == NULL)
  421.         return posix_error();
  422.     return newstringobject(buf);
  423. }
  424. #endif
  425.  
  426. #ifdef HAVE_LINK
  427. static object *
  428. posix_link(self, args)
  429.     object *self;
  430.     object *args;
  431. {
  432.     return posix_2str(args, link);
  433. }
  434. #endif /* HAVE_LINK */
  435.  
  436. static object *
  437. posix_listdir(self, args)
  438.     object *self;
  439.     object *args;
  440. {
  441. #if defined(MS_WIN32) && !defined(HAVE_OPENDIR)
  442.  
  443.     char *name;
  444.     int len;
  445.     object *d, *v;
  446.     HANDLE hFindFile;
  447.     WIN32_FIND_DATA FileData;
  448.     char namebuf[MAX_PATH+5];
  449.  
  450.     if (!getargs(args, "s#", &name, &len))
  451.         return NULL;
  452.     if (len >= MAX_PATH) {
  453.         err_setstr(ValueError, "path too long");
  454.         return NULL;
  455.     }
  456.     strcpy(namebuf, name);
  457.     if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
  458.         namebuf[len++] = '/';
  459.     strcpy(namebuf + len, "*.*");
  460.  
  461.     if ((d = newlistobject(0)) == NULL)
  462.         return NULL;
  463.  
  464.     hFindFile = FindFirstFile(namebuf, &FileData);
  465.     if (hFindFile == INVALID_HANDLE_VALUE) {
  466.         errno = GetLastError();
  467.         return posix_error();
  468.     }
  469.     do {
  470.         if (FileData.cFileName[0] == '.' &&
  471.             (FileData.cFileName[1] == '\0' ||
  472.              FileData.cFileName[1] == '.' &&
  473.              FileData.cFileName[2] == '\0'))
  474.             continue;
  475.         v = newstringobject(FileData.cFileName);
  476.         if (v == NULL) {
  477.             DECREF(d);
  478.             d = NULL;
  479.             break;
  480.         }
  481.         if (addlistitem(d, v) != 0) {
  482.             DECREF(v);
  483.             DECREF(d);
  484.             d = NULL;
  485.             break;
  486.         }
  487.         DECREF(v);
  488.     } while (FindNextFile(hFindFile, &FileData) == TRUE);
  489.  
  490.     if (FindClose(hFindFile) == FALSE) {
  491.         errno = GetLastError();
  492.         return posix_error();
  493.     }
  494.  
  495.     return d;
  496.  
  497. #else /* !MS_WIN32 */
  498. #ifdef _MSC_VER /* 16-bit Windows */
  499.  
  500. #ifndef MAX_PATH
  501. #define MAX_PATH    250
  502. #endif
  503.     char *name, *pt;
  504.     int len;
  505.     object *d, *v;
  506.     char namebuf[MAX_PATH+5];
  507.     struct _find_t ep;
  508.  
  509.     if (!getargs(args, "s#", &name, &len))
  510.         return NULL;
  511.     if (len >= MAX_PATH) {
  512.         err_setstr(ValueError, "path too long");
  513.         return NULL;
  514.     }
  515.     strcpy(namebuf, name);
  516.     for (pt = namebuf; *pt; pt++)
  517.         if (*pt == '/')
  518.             *pt = '\\';
  519.     if (namebuf[len-1] != '\\')
  520.         namebuf[len++] = '\\';
  521.     strcpy(namebuf + len, "*.*");
  522.  
  523.     if ((d = newlistobject(0)) == NULL)
  524.         return NULL;
  525.  
  526.     if (_dos_findfirst(namebuf, _A_RDONLY |
  527.             _A_HIDDEN | _A_SYSTEM | _A_SUBDIR, &ep) != 0){
  528.         errno = ENOENT;
  529.         return posix_error();
  530.     }
  531.     do {
  532.         if (ep.name[0] == '.' &&
  533.             (ep.name[1] == '\0' ||
  534.              ep.name[1] == '.' &&
  535.              ep.name[2] == '\0'))
  536.             continue;
  537.         strcpy(namebuf, ep.name);
  538.         for (pt = namebuf; *pt; pt++)
  539.             if (isupper(*pt))
  540.                 *pt = tolower(*pt);
  541.         v = newstringobject(namebuf);
  542.         if (v == NULL) {
  543.             DECREF(d);
  544.             d = NULL;
  545.             break;
  546.         }
  547.         if (addlistitem(d, v) != 0) {
  548.             DECREF(v);
  549.             DECREF(d);
  550.             d = NULL;
  551.             break;
  552.         }
  553.         DECREF(v);
  554.     } while (_dos_findnext(&ep) == 0);
  555.  
  556.     return d;
  557.  
  558. #else
  559.  
  560.     char *name;
  561.     object *d, *v;
  562.     DIR *dirp;
  563.     struct dirent *ep;
  564.     if (!getargs(args, "s", &name))
  565.         return NULL;
  566.     BGN_SAVE
  567.     if ((dirp = opendir(name)) == NULL) {
  568.         RET_SAVE
  569.         return posix_error();
  570.     }
  571.     if ((d = newlistobject(0)) == NULL) {
  572.         closedir(dirp);
  573.         RET_SAVE
  574.         return NULL;
  575.     }
  576.     while ((ep = readdir(dirp)) != NULL) {
  577.         if (ep->d_name[0] == '.' &&
  578.             (NAMLEN(ep) == 1 ||
  579.              ep->d_name[1] == '.' && NAMLEN(ep) == 2))
  580.             continue;
  581.         v = newsizedstringobject(ep->d_name, NAMLEN(ep));
  582.         if (v == NULL) {
  583.             DECREF(d);
  584.             d = NULL;
  585.             break;
  586.         }
  587.         if (addlistitem(d, v) != 0) {
  588.             DECREF(v);
  589.             DECREF(d);
  590.             d = NULL;
  591.             break;
  592.         }
  593.         DECREF(v);
  594.     }
  595.     closedir(dirp);
  596.     END_SAVE
  597.  
  598.     return d;
  599.  
  600. #endif /* !_MSC_VER */
  601. #endif /* !MS_WIN32 */
  602. }
  603.  
  604. static object *
  605. posix_mkdir(self, args)
  606.     object *self;
  607.     object *args;
  608. {
  609.     int res;
  610.     char *path;
  611.     int mode = 0777;
  612.     if (!newgetargs(args, "s|i", &path, &mode))
  613.         return NULL;
  614.     BGN_SAVE
  615. #if defined(__WATCOMC__) || defined(_MSC_VER)
  616.     res = mkdir(path);
  617. #else
  618.     res = mkdir(path, mode);
  619. #endif
  620.     END_SAVE
  621.     if (res < 0)
  622.         return posix_error();
  623.     INCREF(None);
  624.     return None;
  625. }
  626.  
  627. #ifdef HAVE_NICE
  628. static object *
  629. posix_nice(self, args)
  630.     object *self;
  631.     object *args;
  632. {
  633.     int increment, value;
  634.  
  635.     if (!getargs(args, "i", &increment))
  636.         return NULL;
  637.     value = nice(increment);
  638.     if (value == -1)
  639.         return posix_error();
  640.     return newintobject((long) value);
  641. }
  642. #endif /* HAVE_NICE */
  643.  
  644. static object *
  645. posix_rename(self, args)
  646.     object *self;
  647.     object *args;
  648. {
  649.     return posix_2str(args, rename);
  650. }
  651.  
  652. static object *
  653. posix_rmdir(self, args)
  654.     object *self;
  655.     object *args;
  656. {
  657.     return posix_1str(args, rmdir);
  658. }
  659.  
  660. static object *
  661. posix_stat(self, args)
  662.     object *self;
  663.     object *args;
  664. {
  665.     return posix_do_stat(self, args, stat);
  666. }
  667.  
  668. #ifdef HAVE_SYSTEM
  669. static object *
  670. posix_system(self, args)
  671.     object *self;
  672.     object *args;
  673. {
  674.     char *command;
  675.     long sts;
  676.     if (!getargs(args, "s", &command))
  677.         return NULL;
  678.     BGN_SAVE
  679.     sts = system(command);
  680.     END_SAVE
  681.     return newintobject(sts);
  682. }
  683. #endif
  684.  
  685. static object *
  686. posix_umask(self, args)
  687.     object *self;
  688.     object *args;
  689. {
  690.     int i;
  691.     if (!getintarg(args, &i))
  692.         return NULL;
  693.     i = umask(i);
  694.     if (i < 0)
  695.         return posix_error();
  696.     return newintobject((long)i);
  697. }
  698.  
  699. static object *
  700. posix_unlink(self, args)
  701.     object *self;
  702.     object *args;
  703. {
  704.     return posix_1str(args, unlink);
  705. }
  706.  
  707. #ifdef HAVE_UNAME
  708. static object *
  709. posix_uname(self, args)
  710.     object *self;
  711.     object *args;
  712. {
  713.     struct utsname u;
  714.     object *v;
  715.     int res;
  716.     if (!getnoarg(args))
  717.         return NULL;
  718.     BGN_SAVE
  719.     res = uname(&u);
  720.     END_SAVE
  721.     if (res < 0)
  722.         return posix_error();
  723.     return mkvalue("(sssss)",
  724.                u.sysname,
  725.                u.nodename,
  726.                u.release,
  727.                u.version,
  728.                u.machine);
  729. }
  730. #endif /* HAVE_UNAME */
  731.  
  732. static object *
  733. posix_utime(self, args)
  734.     object *self;
  735.     object *args;
  736. {
  737.     char *path;
  738.     long atime, mtime;
  739.     int res;
  740.  
  741. #ifdef HAVE_UTIME_H
  742.     struct utimbuf buf;
  743. #define ATIME buf.actime
  744. #define MTIME buf.modtime
  745. #define UTIME_ARG &buf
  746. #else /* HAVE_UTIME_H */
  747.     time_t buf[2];
  748. #define ATIME buf[0]
  749. #define MTIME buf[1]
  750. #define UTIME_ARG buf
  751. #endif /* HAVE_UTIME_H */
  752.  
  753.     if (!getargs(args, "(s(ll))", &path, &atime, &mtime))
  754.         return NULL;
  755.     ATIME = atime;
  756.     MTIME = mtime;
  757.     BGN_SAVE
  758.     res = utime(path, UTIME_ARG);
  759.     END_SAVE
  760.     if (res < 0)
  761.         return posix_error();
  762.     INCREF(None);
  763.     return None;
  764. #undef UTIME_ARG
  765. #undef ATIME
  766. #undef MTIME
  767. }
  768.  
  769.  
  770. /* Process operations */
  771.  
  772. static object *
  773. posix__exit(self, args)
  774.     object *self;
  775.     object *args;
  776. {
  777.     int sts;
  778.     if (!getintarg(args, &sts))
  779.         return NULL;
  780.     _exit(sts);
  781.     /* NOTREACHED */
  782. }
  783.  
  784. #ifdef HAVE_EXECV
  785. static object *
  786. posix_execv(self, args)
  787.     object *self;
  788.     object *args;
  789. {
  790.     char *path;
  791.     object *argv;
  792.     char **argvlist;
  793.     int i, argc;
  794.     object *(*getitem) PROTO((object *, int));
  795.  
  796.     /* execv has two arguments: (path, argv), where
  797.        argv is a list or tuple of strings. */
  798.  
  799.     if (!getargs(args, "(sO)", &path, &argv))
  800.         return NULL;
  801.     if (is_listobject(argv)) {
  802.         argc = getlistsize(argv);
  803.         getitem = getlistitem;
  804.     }
  805.     else if (is_tupleobject(argv)) {
  806.         argc = gettuplesize(argv);
  807.         getitem = gettupleitem;
  808.     }
  809.     else {
  810.  badarg:
  811.         err_badarg();
  812.         return NULL;
  813.     }
  814.  
  815.     argvlist = NEW(char *, argc+1);
  816.     if (argvlist == NULL)
  817.         return NULL;
  818.     for (i = 0; i < argc; i++) {
  819.         if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) {
  820.             DEL(argvlist);
  821.             goto badarg;
  822.         }
  823.     }
  824.     argvlist[argc] = NULL;
  825.  
  826. #ifdef BAD_EXEC_PROTOTYPES
  827.     execv(path, (const char **) argvlist);
  828. #else /* BAD_EXEC_PROTOTYPES */
  829.     execv(path, argvlist);
  830. #endif /* BAD_EXEC_PROTOTYPES */
  831.  
  832.     /* If we get here it's definitely an error */
  833.  
  834.     DEL(argvlist);
  835.     return posix_error();
  836. }
  837.  
  838. static object *
  839. posix_execve(self, args)
  840.     object *self;
  841.     object *args;
  842. {
  843.     char *path;
  844.     object *argv, *env;
  845.     char **argvlist;
  846.     char **envlist;
  847.     object *key, *val;
  848.     int i, pos, argc, envc;
  849.     object *(*getitem) PROTO((object *, int));
  850.  
  851.     /* execve has three arguments: (path, argv, env), where
  852.        argv is a list or tuple of strings and env is a dictionary
  853.        like posix.environ. */
  854.  
  855.     if (!getargs(args, "(sOO)", &path, &argv, &env))
  856.         return NULL;
  857.     if (is_listobject(argv)) {
  858.         argc = getlistsize(argv);
  859.         getitem = getlistitem;
  860.     }
  861.     else if (is_tupleobject(argv)) {
  862.         argc = gettuplesize(argv);
  863.         getitem = gettupleitem;
  864.     }
  865.     else {
  866.         err_setstr(TypeError, "argv must be tuple or list");
  867.         return NULL;
  868.     }
  869.     if (!is_dictobject(env)) {
  870.         err_setstr(TypeError, "env must be dictionary");
  871.         return NULL;
  872.     }
  873.  
  874.     argvlist = NEW(char *, argc+1);
  875.     if (argvlist == NULL) {
  876.         err_nomem();
  877.         return NULL;
  878.     }
  879.     for (i = 0; i < argc; i++) {
  880.         if (!getargs((*getitem)(argv, i),
  881.                  "s;argv must be list of strings",
  882.                  &argvlist[i])) {
  883.             goto fail_1;
  884.         }
  885.     }
  886.     argvlist[argc] = NULL;
  887.  
  888.     i = getmappingsize(env);
  889.     envlist = NEW(char *, i + 1);
  890.     if (envlist == NULL) {
  891.         err_nomem();
  892.         goto fail_1;
  893.     }
  894.     pos = 0;
  895.     envc = 0;
  896.     while (mappinggetnext(env, &pos, &key, &val)) {
  897.         char *p, *k, *v;
  898.         if (!getargs(key, "s;non-string key in env", &k) ||
  899.             !getargs(val, "s;non-string value in env", &v)) {
  900.             goto fail_2;
  901.         }
  902.         p = NEW(char, getstringsize(key) + getstringsize(val) + 2);
  903.         if (p == NULL) {
  904.             err_nomem();
  905.             goto fail_2;
  906.         }
  907.         sprintf(p, "%s=%s", k, v);
  908.         envlist[envc++] = p;
  909.     }
  910.     envlist[envc] = 0;
  911.  
  912.  
  913. #ifdef BAD_EXEC_PROTOTYPES
  914.     execve(path, (const char **)argvlist, envlist);
  915. #else /* BAD_EXEC_PROTOTYPES */
  916.     execve(path, argvlist, envlist);
  917. #endif /* BAD_EXEC_PROTOTYPES */
  918.     
  919.     /* If we get here it's definitely an error */
  920.  
  921.     (void) posix_error();
  922.  
  923.  fail_2:
  924.     while (--envc >= 0)
  925.         DEL(envlist[envc]);
  926.     DEL(envlist);
  927.  fail_1:
  928.     DEL(argvlist);
  929.  
  930.     return NULL;
  931. }
  932. #endif /* HAVE_EXECV */
  933.  
  934. #ifdef HAVE_FORK
  935. static object *
  936. posix_fork(self, args)
  937.     object *self;
  938.     object *args;
  939. {
  940.     int pid;
  941.     if (!getnoarg(args))
  942.         return NULL;
  943.     pid = fork();
  944.     if (pid == -1)
  945.         return posix_error();
  946.     return newintobject((long)pid);
  947. }
  948. #endif
  949.  
  950. #ifdef HAVE_GETEGID
  951. static object *
  952. posix_getegid(self, args)
  953.     object *self;
  954.     object *args;
  955. {
  956.     if (!getnoarg(args))
  957.         return NULL;
  958.     return newintobject((long)getegid());
  959. }
  960. #endif
  961.  
  962. #ifdef HAVE_GETEUID
  963. static object *
  964. posix_geteuid(self, args)
  965.     object *self;
  966.     object *args;
  967. {
  968.     if (!getnoarg(args))
  969.         return NULL;
  970.     return newintobject((long)geteuid());
  971. }
  972. #endif
  973.  
  974. #ifdef HAVE_GETGID
  975. static object *
  976. posix_getgid(self, args)
  977.     object *self;
  978.     object *args;
  979. {
  980.     if (!getnoarg(args))
  981.         return NULL;
  982.     return newintobject((long)getgid());
  983. }
  984. #endif
  985.  
  986. static object *
  987. posix_getpid(self, args)
  988.     object *self;
  989.     object *args;
  990. {
  991.     if (!getnoarg(args))
  992.         return NULL;
  993.     return newintobject((long)getpid());
  994. }
  995.  
  996. #ifdef HAVE_GETPGRP
  997. static object *
  998. posix_getpgrp(self, args)
  999.     object *self;
  1000.     object *args;
  1001. {
  1002.     if (!getnoarg(args))
  1003.         return NULL;
  1004. #ifdef GETPGRP_HAVE_ARG
  1005.     return newintobject((long)getpgrp(0));
  1006. #else /* GETPGRP_HAVE_ARG */
  1007.     return newintobject((long)getpgrp());
  1008. #endif /* GETPGRP_HAVE_ARG */
  1009. }
  1010. #endif /* HAVE_GETPGRP */
  1011.  
  1012. #ifdef HAVE_SETPGRP
  1013. static object *
  1014. posix_setpgrp(self, args)
  1015.     object *self;
  1016.     object *args;
  1017. {
  1018.     if (!getnoarg(args))
  1019.         return NULL;
  1020. #ifdef SETPGRP_HAVE_ARG
  1021.     if (setpgrp(0, 0) < 0)
  1022. #else /* SETPGRP_HAVE_ARG */
  1023.     if (setpgrp() < 0)
  1024. #endif /* SETPGRP_HAVE_ARG */
  1025.         return posix_error();
  1026.     INCREF(None);
  1027.     return None;
  1028. }
  1029.  
  1030. #endif /* HAVE_SETPGRP */
  1031.  
  1032. #ifdef HAVE_GETPPID
  1033. static object *
  1034. posix_getppid(self, args)
  1035.     object *self;
  1036.     object *args;
  1037. {
  1038.     if (!getnoarg(args))
  1039.         return NULL;
  1040.     return newintobject((long)getppid());
  1041. }
  1042. #endif
  1043.  
  1044. #ifdef HAVE_GETUID
  1045. static object *
  1046. posix_getuid(self, args)
  1047.     object *self;
  1048.     object *args;
  1049. {
  1050.     if (!getnoarg(args))
  1051.         return NULL;
  1052.     return newintobject((long)getuid());
  1053. }
  1054. #endif
  1055.  
  1056. #ifdef HAVE_KILL
  1057. static object *
  1058. posix_kill(self, args)
  1059.     object *self;
  1060.     object *args;
  1061. {
  1062.     int pid, sig;
  1063.     if (!getargs(args, "(ii)", &pid, &sig))
  1064.         return NULL;
  1065.     if (kill(pid, sig) == -1)
  1066.         return posix_error();
  1067.     INCREF(None);
  1068.     return None;
  1069. }
  1070. #endif
  1071.  
  1072. #ifdef HAVE_PLOCK
  1073.  
  1074. #ifdef HAVE_SYS_LOCK_H
  1075. #include <sys/lock.h>
  1076. #endif
  1077.  
  1078. static object *
  1079. posix_plock(self, args)
  1080.     object *self;
  1081.     object *args;
  1082. {
  1083.     int op;
  1084.     if (!getargs(args, "i", &op))
  1085.         return NULL;
  1086.     if (plock(op) == -1)
  1087.         return posix_error();
  1088.     INCREF(None);
  1089.     return None;
  1090. }
  1091. #endif
  1092.  
  1093. #ifdef HAVE_POPEN
  1094. static object *
  1095. posix_popen(self, args)
  1096.     object *self;
  1097.     object *args;
  1098. {
  1099.     char *name;
  1100.     char *mode = "r";
  1101.     int bufsize = -1;
  1102.     FILE *fp;
  1103.     object *f;
  1104.     if (!newgetargs(args, "s|si", &name, &mode, &bufsize))
  1105.         return NULL;
  1106.     BGN_SAVE
  1107.     fp = popen(name, mode);
  1108.     END_SAVE
  1109.     if (fp == NULL)
  1110.         return posix_error();
  1111.     f = newopenfileobject(fp, name, mode, pclose);
  1112.     if (f != NULL)
  1113.         setfilebufsize(f, bufsize);
  1114.     return f;
  1115. }
  1116. #endif /* HAVE_POPEN */
  1117.  
  1118. #ifdef HAVE_SETUID
  1119. static object *
  1120. posix_setuid(self, args)
  1121.     object *self;
  1122.     object *args;
  1123. {
  1124.     int uid;
  1125.     if (!getargs(args, "i", &uid))
  1126.         return NULL;
  1127.     if (setuid(uid) < 0)
  1128.         return posix_error();
  1129.     INCREF(None);
  1130.     return None;
  1131. }
  1132. #endif /* HAVE_SETUID */
  1133.  
  1134. #ifdef HAVE_SETGID
  1135. static object *
  1136. posix_setgid(self, args)
  1137.     object *self;
  1138.     object *args;
  1139. {
  1140.     int gid;
  1141.     if (!getargs(args, "i", &gid))
  1142.         return NULL;
  1143.     if (setgid(gid) < 0)
  1144.         return posix_error();
  1145.     INCREF(None);
  1146.     return None;
  1147. }
  1148. #endif /* HAVE_SETGID */
  1149.  
  1150. #ifdef HAVE_WAITPID
  1151. static object *
  1152. posix_waitpid(self, args)
  1153.     object *self;
  1154.     object *args;
  1155. {
  1156.     int pid, options, sts = 0;
  1157.     if (!getargs(args, "(ii)", &pid, &options))
  1158.         return NULL;
  1159.     BGN_SAVE
  1160.     pid = waitpid(pid, &sts, options);
  1161.     END_SAVE
  1162.     if (pid == -1)
  1163.         return posix_error();
  1164.     else
  1165.         return mkvalue("ii", pid, sts);
  1166. }
  1167. #endif /* HAVE_WAITPID */
  1168.  
  1169. #ifdef HAVE_WAIT
  1170. static object *
  1171. posix_wait(self, args)
  1172.     object *self;
  1173.     object *args;
  1174. {
  1175.     int pid;
  1176. #if NeXT && !defined (_POSIX_SOURCE)
  1177.     union wait sts;
  1178. #else
  1179.     int sts;
  1180. #endif
  1181.     BGN_SAVE
  1182.     pid = wait(&sts);
  1183.     END_SAVE
  1184.     if (pid == -1)
  1185.         return posix_error();
  1186.     else
  1187. #if NeXT && !defined (_POSIX_SOURCE)
  1188.             return mkvalue("ii", pid, sts.w_status);
  1189. #else
  1190.         return mkvalue("ii", pid, sts);
  1191. #endif
  1192. }
  1193. #endif
  1194.  
  1195. static object *
  1196. posix_lstat(self, args)
  1197.     object *self;
  1198.     object *args;
  1199. {
  1200. #ifdef HAVE_LSTAT
  1201.     return posix_do_stat(self, args, lstat);
  1202. #else /* !HAVE_LSTAT */
  1203.     return posix_do_stat(self, args, stat);
  1204. #endif /* !HAVE_LSTAT */
  1205. }
  1206.  
  1207. #ifdef HAVE_READLINK
  1208. static object *
  1209. posix_readlink(self, args)
  1210.     object *self;
  1211.     object *args;
  1212. {
  1213.     char buf[MAXPATHLEN];
  1214.     char *path;
  1215.     int n;
  1216.     if (!getargs(args, "s", &path))
  1217.         return NULL;
  1218.     BGN_SAVE
  1219.     n = readlink(path, buf, (int) sizeof buf);
  1220.     END_SAVE
  1221.     if (n < 0)
  1222.         return posix_error();
  1223.     return newsizedstringobject(buf, n);
  1224. }
  1225. #endif /* HAVE_READLINK */
  1226.  
  1227. #ifdef HAVE_SYMLINK
  1228. static object *
  1229. posix_symlink(self, args)
  1230.     object *self;
  1231.     object *args;
  1232. {
  1233.     return posix_2str(args, symlink);
  1234. }
  1235. #endif /* HAVE_SYMLINK */
  1236.  
  1237. #ifdef HAVE_TIMES
  1238. #ifndef HZ
  1239. #define HZ 60 /* Universal constant :-) */
  1240. #endif /* HZ */
  1241. static object *
  1242. posix_times(self, args)
  1243.     object *self;
  1244.     object *args;
  1245. {
  1246.     struct tms t;
  1247.     clock_t c;
  1248.     if (!getnoarg(args))
  1249.         return NULL;
  1250.     errno = 0;
  1251.     c = times(&t);
  1252.     if (c == (clock_t) -1)
  1253.         return posix_error();
  1254.     return mkvalue("ddddd",
  1255.                (double)t.tms_utime / HZ,
  1256.                (double)t.tms_stime / HZ,
  1257.                (double)t.tms_cutime / HZ,
  1258.                (double)t.tms_cstime / HZ,
  1259.                (double)c / HZ);
  1260. }
  1261. #endif /* HAVE_TIMES */
  1262. #ifdef MS_WIN32
  1263. #define HAVE_TIMES    /* so the method table will pick it up */
  1264. static object *
  1265. posix_times(self, args)
  1266.     object *self;
  1267.     object *args;
  1268. {
  1269.     FILETIME create, exit, kernel, user;
  1270.     HANDLE hProc;
  1271.     if (!getnoarg(args))
  1272.         return NULL;
  1273.     hProc = GetCurrentProcess();
  1274.     GetProcessTimes(hProc,&create, &exit, &kernel, &user);
  1275.     return mkvalue("ddddd",
  1276.                (double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime) / 2E6,
  1277.                (double)(user.dwHighDateTime*2E32+user.dwLowDateTime) / 2E6,
  1278.                (double)0,
  1279.                (double)0,
  1280.                (double)0);
  1281. }
  1282. #endif /* MS_WIN32 */
  1283.  
  1284. #ifdef HAVE_SETSID
  1285. static object *
  1286. posix_setsid(self, args)
  1287.     object *self;
  1288.     object *args;
  1289. {
  1290.     if (!getnoarg(args))
  1291.         return NULL;
  1292.     if (setsid() < 0)
  1293.         return posix_error();
  1294.     INCREF(None);
  1295.     return None;
  1296. }
  1297. #endif /* HAVE_SETSID */
  1298.  
  1299. #ifdef HAVE_SETPGID
  1300. static object *
  1301. posix_setpgid(self, args)
  1302.     object *self;
  1303.     object *args;
  1304. {
  1305.     int pid, pgrp;
  1306.     if (!getargs(args, "(ii)", &pid, &pgrp))
  1307.         return NULL;
  1308.     if (setpgid(pid, pgrp) < 0)
  1309.         return posix_error();
  1310.     INCREF(None);
  1311.     return None;
  1312. }
  1313. #endif /* HAVE_SETPGID */
  1314.  
  1315. #ifdef HAVE_TCGETPGRP
  1316. static object *
  1317. posix_tcgetpgrp(self, args)
  1318.     object *self;
  1319.     object *args;
  1320. {
  1321.     int fd, pgid;
  1322.     if (!getargs(args, "i", &fd))
  1323.         return NULL;
  1324.     pgid = tcgetpgrp(fd);
  1325.     if (pgid < 0)
  1326.         return posix_error();
  1327.     return newintobject((long)pgid);
  1328. }
  1329. #endif /* HAVE_TCGETPGRP */
  1330.  
  1331. #ifdef HAVE_TCSETPGRP
  1332. static object *
  1333. posix_tcsetpgrp(self, args)
  1334.     object *self;
  1335.     object *args;
  1336. {
  1337.     int fd, pgid;
  1338.     if (!getargs(args, "(ii)", &fd, &pgid))
  1339.         return NULL;
  1340.     if (tcsetpgrp(fd, pgid) < 0)
  1341.         return posix_error();
  1342.        INCREF(None);
  1343.     return None;
  1344. }
  1345. #endif /* HAVE_TCSETPGRP */
  1346.  
  1347. /* Functions acting on file descriptors */
  1348.  
  1349. static object *
  1350. posix_open(self, args)
  1351.     object *self;
  1352.     object *args;
  1353. {
  1354.     char *file;
  1355.     int flag;
  1356.     int mode = 0777;
  1357.     int fd;
  1358.     if (!getargs(args, "(si)", &file, &flag)) {
  1359.         err_clear();
  1360.         if (!getargs(args, "(sii)", &file, &flag, &mode))
  1361.             return NULL;
  1362.     }
  1363.     BGN_SAVE
  1364.     fd = open(file, flag, mode);
  1365.     END_SAVE
  1366.     if (fd < 0)
  1367.         return posix_error();
  1368.     return newintobject((long)fd);
  1369. }
  1370.  
  1371. static object *
  1372. posix_close(self, args)
  1373.     object *self;
  1374.     object *args;
  1375. {
  1376.     int fd, res;
  1377.     if (!getargs(args, "i", &fd))
  1378.         return NULL;
  1379.     BGN_SAVE
  1380.     res = close(fd);
  1381.     END_SAVE
  1382.     if (res < 0)
  1383.         return posix_error();
  1384.     INCREF(None);
  1385.     return None;
  1386. }
  1387.  
  1388. static object *
  1389. posix_dup(self, args)
  1390.     object *self;
  1391.     object *args;
  1392. {
  1393.     int fd;
  1394.     if (!getargs(args, "i", &fd))
  1395.         return NULL;
  1396.     BGN_SAVE
  1397.     fd = dup(fd);
  1398.     END_SAVE
  1399.     if (fd < 0)
  1400.         return posix_error();
  1401.     return newintobject((long)fd);
  1402. }
  1403.  
  1404. static object *
  1405. posix_dup2(self, args)
  1406.     object *self;
  1407.     object *args;
  1408. {
  1409.     int fd, fd2, res;
  1410.     if (!getargs(args, "(ii)", &fd, &fd2))
  1411.         return NULL;
  1412.     BGN_SAVE
  1413.     res = dup2(fd, fd2);
  1414.     END_SAVE
  1415.     if (res < 0)
  1416.         return posix_error();
  1417.     INCREF(None);
  1418.     return None;
  1419. }
  1420.  
  1421. static object *
  1422. posix_lseek(self, args)
  1423.     object *self;
  1424.     object *args;
  1425. {
  1426.     int fd, how;
  1427.     long pos, res;
  1428.     if (!getargs(args, "(ili)", &fd, &pos, &how))
  1429.         return NULL;
  1430. #ifdef SEEK_SET
  1431.     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
  1432.     switch (how) {
  1433.     case 0: how = SEEK_SET; break;
  1434.     case 1: how = SEEK_CUR; break;
  1435.     case 2: how = SEEK_END; break;
  1436.     }
  1437. #endif /* SEEK_END */
  1438.     BGN_SAVE
  1439.     res = lseek(fd, pos, how);
  1440.     END_SAVE
  1441.     if (res < 0)
  1442.         return posix_error();
  1443.     return newintobject(res);
  1444. }
  1445.  
  1446. static object *
  1447. posix_read(self, args)
  1448.     object *self;
  1449.     object *args;
  1450. {
  1451.     int fd, size, n;
  1452.     object *buffer;
  1453.     if (!getargs(args, "(ii)", &fd, &size))
  1454.         return NULL;
  1455.     buffer = newsizedstringobject((char *)NULL, size);
  1456.     if (buffer == NULL)
  1457.         return NULL;
  1458.     BGN_SAVE
  1459.     n = read(fd, getstringvalue(buffer), size);
  1460.     END_SAVE
  1461.     if (n < 0) {
  1462.         DECREF(buffer);
  1463.         return posix_error();
  1464.     }
  1465.     if (n != size)
  1466.         resizestring(&buffer, n);
  1467.     return buffer;
  1468. }
  1469.  
  1470. static object *
  1471. posix_write(self, args)
  1472.     object *self;
  1473.     object *args;
  1474. {
  1475.     int fd, size;
  1476.     char *buffer;
  1477.     if (!getargs(args, "(is#)", &fd, &buffer, &size))
  1478.         return NULL;
  1479.     BGN_SAVE
  1480.     size = write(fd, buffer, size);
  1481.     END_SAVE
  1482.     if (size < 0)
  1483.         return posix_error();
  1484.     return newintobject((long)size);
  1485. }
  1486.  
  1487. static object *
  1488. posix_fstat(self, args)
  1489.     object *self;
  1490.     object *args;
  1491. {
  1492.     int fd;
  1493.     struct stat st;
  1494.     int res;
  1495.     if (!getargs(args, "i", &fd))
  1496.         return NULL;
  1497.     BGN_SAVE
  1498.     res = fstat(fd, &st);
  1499.     END_SAVE
  1500.     if (res != 0)
  1501.         return posix_error();
  1502.     return mkvalue("(llllllllll)",
  1503.             (long)st.st_mode,
  1504.             (long)st.st_ino,
  1505.             (long)st.st_dev,
  1506.             (long)st.st_nlink,
  1507.             (long)st.st_uid,
  1508.             (long)st.st_gid,
  1509.             (long)st.st_size,
  1510.             (long)st.st_atime,
  1511.             (long)st.st_mtime,
  1512.             (long)st.st_ctime);
  1513. }
  1514.  
  1515. static object *
  1516. posix_fdopen(self, args)
  1517.     object *self;
  1518.     object *args;
  1519. {
  1520.     extern int fclose PROTO((FILE *));
  1521.     int fd;
  1522.     char *mode = "r";
  1523.     int bufsize = -1;
  1524.     FILE *fp;
  1525.     object *f;
  1526.     if (!newgetargs(args, "i|si", &fd, &mode, &bufsize))
  1527.         return NULL;
  1528.     BGN_SAVE
  1529.     fp = fdopen(fd, mode);
  1530.     END_SAVE
  1531.     if (fp == NULL)
  1532.         return posix_error();
  1533.     f = newopenfileobject(fp, "(fdopen)", mode, fclose);
  1534.     if (f != NULL)
  1535.         setfilebufsize(f, bufsize);
  1536.     return f;
  1537. }
  1538.  
  1539. #ifdef HAVE_PIPE
  1540. static object *
  1541. posix_pipe(self, args)
  1542.     object *self;
  1543.     object *args;
  1544. {
  1545. #if !defined(MS_WIN32)
  1546.     int fds[2];
  1547.     int res;
  1548.     if (!getargs(args, ""))
  1549.         return NULL;
  1550.     BGN_SAVE
  1551.     res = pipe(fds);
  1552.     END_SAVE
  1553.     if (res != 0)
  1554.         return posix_error();
  1555.     return mkvalue("(ii)", fds[0], fds[1]);
  1556. #else /* MS_WIN32 */
  1557.     HANDLE read, write;
  1558.     BOOL ok;
  1559.     if (!getargs(args, ""))
  1560.         return NULL;
  1561.     BGN_SAVE
  1562.     ok = CreatePipe( &read, &write, NULL, 0);
  1563.     END_SAVE
  1564.     if (!ok)
  1565.         return posix_error();
  1566.     return mkvalue("(ii)", read, write);
  1567. #endif /* MS_WIN32 */
  1568. }
  1569. #endif  /* HAVE_PIPE */
  1570.  
  1571. #ifdef HAVE_MKFIFO
  1572. static object *
  1573. posix_mkfifo(self, args)
  1574.     object *self;
  1575.     object *args;
  1576. {
  1577.     char *file;
  1578.     int mode = 0666;
  1579.     int res;
  1580.     if (!newgetargs(args, "s|i", &file, &mode))
  1581.         return NULL;
  1582.     BGN_SAVE
  1583.     res = mkfifo(file, mode);
  1584.     END_SAVE
  1585.     if (res < 0)
  1586.         return posix_error();
  1587.     INCREF(None);
  1588.     return None;
  1589. }
  1590. #endif
  1591.  
  1592. #ifdef HAVE_FTRUNCATE
  1593. static object *
  1594. posix_ftruncate(self, args)
  1595.     object *self; /* Not used */
  1596.     object *args;
  1597. {
  1598.     int fd;
  1599.     long length;
  1600.     int res;
  1601.  
  1602.     if (!getargs(args, "(il)", &fd, &length))
  1603.         return NULL;
  1604.  
  1605.     BGN_SAVE
  1606.     res = ftruncate(fd, length);
  1607.     END_SAVE
  1608.     if (res < 0) {
  1609.         err_errno(IOError);
  1610.         return NULL;
  1611.     }
  1612.     INCREF(None);
  1613.     return None;
  1614. }
  1615. #endif
  1616.  
  1617. #ifdef HAVE_PUTENV
  1618. static object * 
  1619. posix_putenv(self,args)
  1620.     object *self;
  1621.     object *args;
  1622. {
  1623.         char *s1, *s2;
  1624.         char *new;
  1625.  
  1626.     if (!newgetargs(args, "ss", &s1, &s2))
  1627.         return NULL;
  1628.     /* XXX This leaks memory -- not easy to fix :-( */
  1629.     if ((new = malloc(strlen(s1) + strlen(s2) + 2)) == NULL)
  1630.                 return err_nomem();
  1631.     (void) sprintf(new, "%s=%s", s1, s2);
  1632.     if (putenv(new)) {
  1633.                 posix_error();
  1634.                 return NULL;
  1635.     }
  1636.     INCREF(None);
  1637.         return None;
  1638. }
  1639. #endif
  1640.  
  1641. static struct methodlist posix_methods[] = {
  1642.     {"chdir",    posix_chdir},
  1643.     {"chmod",    posix_chmod},
  1644. #ifdef HAVE_CHOWN
  1645.     {"chown",    posix_chown},
  1646. #endif /* HAVE_CHOWN */
  1647. #ifdef HAVE_GETCWD
  1648.     {"getcwd",    posix_getcwd},
  1649. #endif
  1650. #ifdef HAVE_LINK
  1651.     {"link",    posix_link},
  1652. #endif /* HAVE_LINK */
  1653.     {"listdir",    posix_listdir},
  1654.     {"lstat",    posix_lstat},
  1655.     {"mkdir",    posix_mkdir, 1},
  1656. #ifdef HAVE_NICE
  1657.     {"nice",    posix_nice},
  1658. #endif /* HAVE_NICE */
  1659. #ifdef HAVE_READLINK
  1660.     {"readlink",    posix_readlink},
  1661. #endif /* HAVE_READLINK */
  1662.     {"rename",    posix_rename},
  1663.     {"rmdir",    posix_rmdir},
  1664.     {"stat",    posix_stat},
  1665. #ifdef HAVE_SYMLINK
  1666.     {"symlink",    posix_symlink},
  1667. #endif /* HAVE_SYMLINK */
  1668. #ifdef HAVE_SYSTEM
  1669.     {"system",    posix_system},
  1670. #endif
  1671.     {"umask",    posix_umask},
  1672. #ifdef HAVE_UNAME
  1673.     {"uname",    posix_uname},
  1674. #endif /* HAVE_UNAME */
  1675.     {"unlink",    posix_unlink},
  1676.     {"remove",    posix_unlink},
  1677.     {"utime",    posix_utime},
  1678. #ifdef HAVE_TIMES
  1679.     {"times",    posix_times},
  1680. #endif /* HAVE_TIMES */
  1681.     {"_exit",    posix__exit},
  1682. #ifdef HAVE_EXECV
  1683.     {"execv",    posix_execv},
  1684.     {"execve",    posix_execve},
  1685. #endif /* HAVE_EXECV */
  1686. #ifdef HAVE_FORK
  1687.     {"fork",    posix_fork},
  1688. #endif /* HAVE_FORK */
  1689. #ifdef HAVE_GETEGID
  1690.     {"getegid",    posix_getegid},
  1691. #endif /* HAVE_GETEGID */
  1692. #ifdef HAVE_GETEUID
  1693.     {"geteuid",    posix_geteuid},
  1694. #endif /* HAVE_GETEUID */
  1695. #ifdef HAVE_GETGID
  1696.     {"getgid",    posix_getgid},
  1697. #endif /* HAVE_GETGID */
  1698.     {"getpid",    posix_getpid},
  1699. #ifdef HAVE_GETPGRP
  1700.     {"getpgrp",    posix_getpgrp},
  1701. #endif /* HAVE_GETPGRP */
  1702. #ifdef HAVE_GETPPID
  1703.     {"getppid",    posix_getppid},
  1704. #endif /* HAVE_GETPPID */
  1705. #ifdef HAVE_GETUID
  1706.     {"getuid",    posix_getuid},
  1707. #endif /* HAVE_GETUID */
  1708. #ifdef HAVE_KILL
  1709.     {"kill",    posix_kill},
  1710. #endif /* HAVE_KILL */
  1711. #ifdef HAVE_PLOCK
  1712.     {"plock",    posix_plock},
  1713. #endif /* HAVE_PLOCK */
  1714. #ifdef HAVE_POPEN
  1715.     {"popen",    posix_popen,    1},
  1716. #endif /* HAVE_POPEN */
  1717. #ifdef HAVE_SETUID
  1718.     {"setuid",    posix_setuid},
  1719. #endif /* HAVE_SETUID */
  1720. #ifdef HAVE_SETGID
  1721.     {"setgid",    posix_setgid},
  1722. #endif /* HAVE_SETGID */
  1723. #ifdef HAVE_SETPGRP
  1724.     {"setpgrp",    posix_setpgrp},
  1725. #endif /* HAVE_SETPGRP */
  1726. #ifdef HAVE_WAIT
  1727.     {"wait",    posix_wait},
  1728. #endif /* HAVE_WAIT */
  1729. #ifdef HAVE_WAITPID
  1730.     {"waitpid",    posix_waitpid},
  1731. #endif /* HAVE_WAITPID */
  1732. #ifdef HAVE_SETSID
  1733.     {"setsid",    posix_setsid},
  1734. #endif /* HAVE_SETSID */
  1735. #ifdef HAVE_SETPGID
  1736.     {"setpgid",    posix_setpgid},
  1737. #endif /* HAVE_SETPGID */
  1738. #ifdef HAVE_TCGETPGRP
  1739.     {"tcgetpgrp",    posix_tcgetpgrp},
  1740. #endif /* HAVE_TCGETPGRP */
  1741. #ifdef HAVE_TCSETPGRP
  1742.     {"tcsetpgrp",    posix_tcsetpgrp},
  1743. #endif /* HAVE_TCSETPGRP */
  1744.     {"open",    posix_open},
  1745.     {"close",    posix_close},
  1746.     {"dup",        posix_dup},
  1747.     {"dup2",    posix_dup2},
  1748.     {"lseek",    posix_lseek},
  1749.     {"read",    posix_read},
  1750.     {"write",    posix_write},
  1751.     {"fstat",    posix_fstat},
  1752.     {"fdopen",    posix_fdopen,    1},
  1753. #ifdef HAVE_PIPE
  1754.     {"pipe",    posix_pipe},
  1755. #endif
  1756. #ifdef HAVE_MKFIFO
  1757.     {"mkfifo",    posix_mkfifo, 1},
  1758. #endif
  1759. #ifdef HAVE_FTRUNCATE
  1760.     {"ftruncate",    posix_ftruncate, 1},
  1761. #endif
  1762. #ifdef HAVE_PUTENV
  1763.     {"putenv",    posix_putenv, 1},
  1764. #endif
  1765.     {NULL,        NULL}         /* Sentinel */
  1766. };
  1767.  
  1768.  
  1769. #if defined(_MSC_VER) || defined(__WATCOMC__)
  1770. void
  1771. initnt()
  1772. {
  1773.     object *m, *d, *v;
  1774.     
  1775.     m = initmodule("nt", posix_methods);
  1776.     d = getmoduledict(m);
  1777.     
  1778.     /* Initialize nt.environ dictionary */
  1779.     v = convertenviron();
  1780.     if (v == NULL || dictinsert(d, "environ", v) != 0)
  1781.         fatal("can't define nt.environ");
  1782.     DECREF(v);
  1783.     
  1784.     /* Initialize nt.error exception */
  1785.     PosixError = newstringobject("nt.error");
  1786.     if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
  1787.         fatal("can't define nt.error");
  1788. }
  1789. #else /* not a PC port */
  1790. void
  1791. initposix()
  1792. {
  1793.     object *m, *d, *v;
  1794.     
  1795.     m = initmodule("posix", posix_methods);
  1796.     d = getmoduledict(m);
  1797.     
  1798.     /* Initialize posix.environ dictionary */
  1799.     v = convertenviron();
  1800.     if (v == NULL || dictinsert(d, "environ", v) != 0)
  1801.         fatal("can't define posix.environ");
  1802.     DECREF(v);
  1803.     
  1804. #ifdef WNOHANG
  1805.     /* Export WNOHANG symbol */
  1806.     v = newintobject((long)WNOHANG);
  1807.     if (v == NULL || dictinsert(d, "WNOHANG", v) != 0)
  1808.         fatal("can't define posix.WNOHANG");
  1809.     DECREF(v);
  1810. #endif
  1811.     
  1812.     /* Initialize posix.error exception */
  1813.     PosixError = newstringobject("posix.error");
  1814.     if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
  1815.         fatal("can't define posix.error");
  1816. }
  1817. #endif /* !_MSC_VER */
  1818.