home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyth_os2.zip / python-1.0.2 / OS2 / Modules / posixmodule.c < prev    next >
C/C++ Source or Header  |  1994-06-02  |  28KB  |  1,430 lines

  1. /***********************************************************
  2. Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
  3. Amsterdam, 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 not be used in advertising or publicity pertaining to
  13. distribution of the software without specific, written prior permission.
  14.  
  15. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  18. FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  21. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /* POSIX module implementation */
  26.  
  27. #ifdef _M_IX86
  28. #define NT
  29. #endif
  30.  
  31. #include "allobjects.h"
  32. #include "modsupport.h"
  33. #include "ceval.h"
  34.  
  35. #include <signal.h>
  36. #include <string.h>
  37. #include <setjmp.h>
  38. #include <errno.h>
  39. #include <sys/types.h>
  40. #include <sys/stat.h>
  41.  
  42. #include "mytime.h"        /* For clock_t on some systems */
  43.  
  44. #ifdef HAVE_FCNTL_H
  45. #include <fcntl.h>
  46. #endif
  47.  
  48. #ifdef HAVE_UNISTD_H
  49. #include <unistd.h>
  50. #else /* !HAVE_UNISTD_H */
  51. extern int mkdir PROTO((const char *, mode_t));
  52. extern int chdir PROTO((const char *));
  53. extern int rmdir PROTO((const char *));
  54. extern int chmod PROTO((const char *, mode_t));
  55. extern int chown PROTO((const char *, uid_t, gid_t));
  56. extern char *getcwd PROTO((char *, int));
  57. extern char *strerror PROTO((int));
  58. extern int link PROTO((const char *, const char *));
  59. extern int rename PROTO((const char *, const char *));
  60. extern int stat PROTO((const char *, struct stat *));
  61. extern int unlink PROTO((const char *));
  62. extern int pclose PROTO((FILE *));
  63. #ifdef HAVE_SYMLINK
  64. extern int symlink PROTO((const char *, const char *));
  65. #endif
  66. #ifdef HAVE_LSTAT
  67. extern int lstat PROTO((const char *, struct stat *));
  68. #endif
  69. #endif /* !HAVE_UNISTD_H */
  70.  
  71. #if 1
  72. /* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */
  73. extern int rename();
  74. extern int pclose();
  75. extern int lstat();
  76. extern int symlink();
  77. #endif
  78.  
  79. #ifdef HAVE_UTIME_H
  80. #include <utime.h>
  81. #endif
  82.  
  83. #ifdef HAVE_SYS_TIMES_H
  84. #include <sys/times.h>
  85. #endif
  86.  
  87. #ifdef HAVE_SYS_PARAM_H
  88. #include <sys/param.h>
  89. #endif
  90.  
  91. #ifdef HAVE_SYS_UTSNAME_H
  92. #include <sys/utsname.h>
  93. #endif
  94.  
  95. #ifndef MAXPATHLEN
  96. #define MAXPATHLEN 1024
  97. #endif
  98.  
  99. /* unistd.h defines _POSIX_VERSION on POSIX.1 systems.  */
  100. #if defined(DIRENT) || defined(_POSIX_VERSION)
  101. #include <dirent.h>
  102. #define NLENGTH(dirent) (strlen((dirent)->d_name))
  103. #else /* not (DIRENT or _POSIX_VERSION) */
  104. #define dirent direct
  105. #define NLENGTH(dirent) ((dirent)->d_namlen)
  106. #ifdef SYSNDIR
  107. #include <sys/ndir.h>
  108. #endif /* SYSNDIR */
  109. #ifdef SYSDIR
  110. #include <sys/dir.h>
  111. #endif /* SYSDIR */
  112. #ifdef NDIR
  113. #include <ndir.h>
  114. #endif /* NDIR */
  115. #endif /* not (DIRENT or _POSIX_VERSION) */
  116.  
  117. #ifdef NT
  118. #include <direct.h>
  119. #include <io.h>
  120. #include <process.h>
  121. #include <windows.h>
  122. #define popen   _popen
  123. #endif /* NT */
  124.  
  125. #ifdef OS2
  126. #include <io.h>
  127. #endif
  128.  
  129. /* Return a dictionary corresponding to the POSIX environment table */
  130.  
  131. extern char **environ;
  132.  
  133. static object *
  134. convertenviron()
  135. {
  136.     object *d;
  137.     char **e;
  138.     d = newdictobject();
  139.     if (d == NULL)
  140.         return NULL;
  141.     if (environ == NULL)
  142.         return d;
  143.     /* XXX This part ignores errors */
  144.     for (e = environ; *e != NULL; e++) {
  145.         object *v;
  146.         char *p = strchr(*e, '=');
  147.         if (p == NULL)
  148.             continue;
  149.         v = newstringobject(p+1);
  150.         if (v == NULL)
  151.             continue;
  152.         *p = '\0';
  153.         (void) dictinsert(d, *e, v);
  154.         *p = '=';
  155.         DECREF(v);
  156.     }
  157.     return d;
  158. }
  159.  
  160.  
  161. static object *PosixError; /* Exception posix.error */
  162.  
  163. /* Set a POSIX-specific error from errno, and return NULL */
  164.  
  165. static object * posix_error() {     return err_errno(PosixError);
  166. }
  167.  
  168.  
  169. /* POSIX generic methods */
  170.  
  171. static object *
  172. posix_1str(args, func)
  173.     object *args;
  174.     int (*func) FPROTO((const char *));
  175. {
  176.     char *path1;
  177.     int res;
  178.     if (!getargs(args, "s", &path1))
  179.         return NULL;
  180.     BGN_SAVE
  181.     res = (*func)(path1);
  182.     END_SAVE
  183.     if (res < 0)
  184.         return posix_error();
  185.     INCREF(None);
  186.     return None;
  187. }
  188.  
  189. static object *
  190. posix_2str(args, func)
  191.     object *args;
  192.     int (*func) FPROTO((const char *, const char *));
  193. {
  194.     char *path1, *path2;
  195.     int res;
  196.     if (!getargs(args, "(ss)", &path1, &path2))
  197.         return NULL;
  198.     BGN_SAVE
  199.     res = (*func)(path1, path2);
  200.     END_SAVE
  201.     if (res < 0)
  202.         return posix_error();
  203.     INCREF(None);
  204.     return None;
  205. }
  206.  
  207. static object *
  208. posix_strint(args, func)
  209.     object *args;
  210.     int (*func) FPROTO((const char *, int));
  211. {
  212.     char *path;
  213.     int i;
  214.     int res;
  215.     if (!getargs(args, "(si)", &path, &i))
  216.         return NULL;
  217.     BGN_SAVE
  218.     res = (*func)(path, i);
  219.     END_SAVE
  220.     if (res < 0)
  221.         return posix_error();
  222.     INCREF(None);
  223.     return None;
  224. }
  225.  
  226. static object *
  227. posix_strintint(args, func)
  228.     object *args;
  229.     int (*func) FPROTO((const char *, int, int));
  230. {
  231.     char *path;
  232.     int i,i2;
  233.     int res;
  234.     if (!getargs(args, "(sii)", &path, &i, &i2))
  235.         return NULL;
  236.     BGN_SAVE
  237.     res = (*func)(path, i, i2);
  238.     END_SAVE
  239.     if (res < 0)
  240.         return posix_error();
  241.     INCREF(None);
  242.     return None;
  243. }
  244.  
  245. static object *
  246. posix_do_stat(self, args, statfunc)
  247.     object *self;
  248.     object *args;
  249.     int (*statfunc) FPROTO((const char *, struct stat *));
  250. {
  251.     struct stat st;
  252.     char *path;
  253.     int res;
  254.     if (!getargs(args, "s", &path))
  255.         return NULL;
  256.     BGN_SAVE
  257.     res = (*statfunc)(path, &st);
  258.     END_SAVE
  259.     if (res != 0)
  260.         return posix_error();
  261.     return mkvalue("(llllllllll)",
  262.             (long)st.st_mode,
  263.             (long)st.st_ino,
  264.             (long)st.st_dev,
  265.             (long)st.st_nlink,
  266.             (long)st.st_uid,
  267.             (long)st.st_gid,
  268.             (long)st.st_size,
  269.             (long)st.st_atime,
  270.             (long)st.st_mtime,
  271.             (long)st.st_ctime);
  272. }
  273.  
  274.  
  275. /* POSIX methods */
  276.  
  277. static object *
  278. posix_chdir(self, args)
  279.     object *self;
  280.     object *args;
  281. {
  282.     return posix_1str(args, chdir);
  283. }
  284.  
  285. static object *
  286. posix_chmod(self, args)
  287.     object *self;
  288.     object *args;
  289. {
  290.     return posix_strint(args, chmod);
  291. }
  292.  
  293. #ifdef HAVE_CHOWN
  294. static object *
  295. posix_chown(self, args)
  296.     object *self;
  297.     object *args;
  298. {
  299.     return posix_strintint(args, chown);
  300. }
  301. #endif
  302.  
  303. static object *
  304. posix_getcwd(self, args)
  305.     object *self;
  306.     object *args;
  307. {
  308.     char buf[1026];
  309.     char *res;
  310.     if (!getnoarg(args))
  311.         return NULL;
  312.     BGN_SAVE
  313.     res = getcwd(buf, sizeof buf);
  314.     END_SAVE
  315.     if (res == NULL)
  316.         return posix_error();
  317.     return newstringobject(buf);
  318. }
  319.  
  320. #ifdef HAVE_LINK
  321. static object *
  322. posix_link(self, args)
  323.     object *self;
  324.     object *args;
  325. {
  326.     return posix_2str(args, link);
  327. }
  328. #endif
  329.  
  330. #ifdef NT
  331. static object *
  332. posix_listdir(self, args)
  333.     object *self;
  334.     object *args;
  335. {
  336.     char *name;
  337.     int len;
  338.     object *d, *v;
  339.     HANDLE hFindFile;
  340.     WIN32_FIND_DATA FileData;
  341.     char namebuf[MAX_PATH+5];
  342.  
  343.     if (!getargs(args, "s#", &name, &len))
  344.         return NULL;
  345.     if (len >= MAX_PATH) {
  346.         err_setstr(ValueError, "path too long");
  347.         return NULL;
  348.     }
  349.     strcpy(namebuf, name);
  350.     if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
  351.         namebuf[len++] = '/';
  352.     strcpy(namebuf + len, "*.*");
  353.  
  354.     if ((d = newlistobject(0)) == NULL)
  355.         return NULL;
  356.  
  357.     hFindFile = FindFirstFile(namebuf, &FileData);
  358.     if (hFindFile == INVALID_HANDLE_VALUE) {
  359.         errno = GetLastError();
  360.         return posix_error();
  361.     }
  362.     do {
  363.         v = newstringobject(FileData.cFileName);
  364.         if (v == NULL) {
  365.             DECREF(d);
  366.             d = NULL;
  367.             break;
  368.         }
  369.         if (addlistitem(d, v) != 0) {
  370.             DECREF(v);
  371.             DECREF(d);
  372.             d = NULL;
  373.             break;
  374.         }
  375.         DECREF(v);
  376.     } while (FindNextFile(hFindFile, &FileData) == TRUE);
  377.  
  378.     if (FindClose(hFindFile) == FALSE) {
  379.         errno = GetLastError();
  380.         return posix_error();
  381.     }
  382.  
  383.     return d;
  384. }
  385. #else /* ! NT */
  386. static object *
  387. posix_listdir(self, args)
  388.     object *self;
  389.     object *args;
  390. {
  391.     char *name;
  392.     object *d, *v;
  393.     DIR *dirp;
  394.     struct dirent *ep;
  395.     if (!getargs(args, "s", &name))
  396.         return NULL;
  397.     BGN_SAVE
  398.     if ((dirp = opendir(name)) == NULL) {
  399.         RET_SAVE
  400.         return posix_error();
  401.     }
  402.     if ((d = newlistobject(0)) == NULL) {
  403.         closedir(dirp);
  404.         RET_SAVE
  405.         return NULL;
  406.     }
  407.     while ((ep = readdir(dirp)) != NULL) {
  408.         v = newstringobject(ep->d_name);
  409.         if (v == NULL) {
  410.             DECREF(d);
  411.             d = NULL;
  412.             break;
  413.         }
  414.         if (addlistitem(d, v) != 0) {
  415.             DECREF(v);
  416.             DECREF(d);
  417.             d = NULL;
  418.             break;
  419.         }
  420.         DECREF(v);
  421.     }
  422.     closedir(dirp);
  423.     END_SAVE
  424.  
  425.     return d;
  426. }
  427. #endif /* ! NT */
  428.  
  429. static object *
  430. posix_mkdir(self, args)
  431.     object *self;
  432.     object *args;
  433. {
  434.     return posix_strint(args, mkdir);
  435. }
  436.  
  437. #ifdef HAVE_NICE
  438. static object *
  439. posix_nice(self, args)
  440.     object *self;
  441.     object *args;
  442. {
  443.     int increment, value;
  444.  
  445.     if (!getargs(args, "i", &increment))
  446.         return NULL;
  447.     value = nice(increment);
  448.     if (value == -1)
  449.         return posix_error();
  450.     return newintobject((long) value);
  451. }
  452. #endif /* HAVE_NICE */
  453.  
  454. static object *
  455. posix_rename(self, args)
  456.     object *self;
  457.     object *args;
  458. {
  459.     return posix_2str(args, rename);
  460. }
  461.  
  462. static object *
  463. posix_rmdir(self, args)
  464.     object *self;
  465.     object *args;
  466. {
  467.     return posix_1str(args, rmdir);
  468. }
  469.  
  470. static object *
  471. posix_stat(self, args)
  472.     object *self;
  473.     object *args;
  474. {
  475.     return posix_do_stat(self, args, stat);
  476. }
  477.  
  478. static object *
  479. posix_system(self, args)
  480.     object *self;
  481.     object *args;
  482. {
  483.     char *command;
  484.     long sts;
  485.     if (!getargs(args, "s", &command))
  486.         return NULL;
  487.     BGN_SAVE
  488.     sts = system(command);
  489.     END_SAVE
  490.     return newintobject(sts);
  491. }
  492.  
  493. static object *
  494. posix_umask(self, args)
  495.     object *self;
  496.     object *args;
  497. {
  498.     int i;
  499.     if (!getintarg(args, &i))
  500.         return NULL;
  501.     i = umask(i);
  502.     if (i < 0)
  503.         return posix_error();
  504.     return newintobject((long)i);
  505. }
  506.  
  507. static object *
  508. posix_unlink(self, args)
  509.     object *self;
  510.     object *args;
  511. {
  512.     return posix_1str(args, unlink);
  513. }
  514.  
  515. #ifdef HAVE_UNAME
  516. static object *
  517. posix_uname(self, args)
  518.     object *self;
  519.     object *args;
  520. {
  521.     struct utsname u;
  522.     object *v;
  523.     int res;
  524.     if (!getnoarg(args))
  525.         return NULL;
  526.     BGN_SAVE
  527.     res = uname(&u);
  528.     END_SAVE
  529.     if (res < 0)
  530.         return posix_error();
  531.     return mkvalue("(sssss)",
  532.                u.sysname,
  533.                u.nodename,
  534.                u.release,
  535.                u.version,
  536.                u.machine);
  537. }
  538. #endif /* HAVE_UNAME */
  539.  
  540. static object *
  541. posix_utime(self, args)
  542.     object *self;
  543.     object *args;
  544. {
  545.     char *path;
  546.     int res;
  547.  
  548. #ifdef HAVE_UTIME_H
  549.     struct utimbuf buf;
  550. #define ATIME buf.actime
  551. #define MTIME buf.modtime
  552. #define UTIME_ARG &buf
  553. #else
  554.     time_t buf[2];
  555. #define ATIME buf[0]
  556. #define MTIME buf[1]
  557. #define UTIME_ARG buf
  558. #endif
  559.  
  560.     if (!getargs(args, "(s(ll))", &path, &ATIME, &MTIME))
  561.         return NULL;
  562.     BGN_SAVE
  563.     res = utime(path, UTIME_ARG);
  564.     END_SAVE
  565.     if (res < 0)
  566.         return posix_error();
  567.     INCREF(None);
  568.     return None;
  569. #undef UTIME_ARG
  570. #undef ATIME
  571. #undef MTIME
  572. }
  573.  
  574.  
  575. /* Process operations */
  576.  
  577. static object *
  578. posix__exit(self, args)
  579.     object *self;
  580.     object *args;
  581. {
  582.     int sts;
  583.     if (!getintarg(args, &sts))
  584.         return NULL;
  585.     _exit(sts);
  586.     /* NOTREACHED */
  587. }
  588.  
  589. static object *
  590. posix_execv(self, args)
  591.     object *self;
  592.     object *args;
  593. {
  594.     char *path;
  595.     object *argv;
  596.     char **argvlist;
  597.     int i, argc;
  598.     object *(*getitem) PROTO((object *, int));
  599.  
  600.     /* execv has two arguments: (path, argv), where
  601.        argv is a list or tuple of strings. */
  602.  
  603.     if (!getargs(args, "(sO)", &path, &argv))
  604.         return NULL;
  605.     if (is_listobject(argv)) {
  606.         argc = getlistsize(argv);
  607.         getitem = getlistitem;
  608.     }
  609.     else if (is_tupleobject(argv)) {
  610.         argc = gettuplesize(argv);
  611.         getitem = gettupleitem;
  612.     }
  613.     else {
  614.  badarg:
  615.         err_badarg();
  616.         return NULL;
  617.     }
  618.  
  619.     argvlist = NEW(char *, argc+1);
  620.     if (argvlist == NULL)
  621.         return NULL;
  622.     for (i = 0; i < argc; i++) {
  623.         if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) {
  624.             DEL(argvlist);
  625.             goto badarg;
  626.         }
  627.     }
  628.     argvlist[argc] = NULL;
  629.  
  630. #ifdef BAD_EXEC_PROTOTYPES
  631.     execv(path, (const char **) argvlist);
  632. #else
  633.     execv(path, argvlist);
  634. #endif
  635.  
  636.     /* If we get here it's definitely an error */
  637.  
  638.     DEL(argvlist);
  639.     return posix_error();
  640. }
  641.  
  642. static object *
  643. posix_execve(self, args)
  644.     object *self;
  645.     object *args;
  646. {
  647.     char *path;
  648.     object *argv, *env;
  649.     char **argvlist;
  650.     char **envlist;
  651.     object *key, *val;
  652.     int i, pos, argc, envc;
  653.     object *(*getitem) PROTO((object *, int));
  654.  
  655.     /* execve has three arguments: (path, argv, env), where
  656.        argv is a list or tuple of strings and env is a dictionary
  657.        like posix.environ. */
  658.  
  659.     if (!getargs(args, "(sOO)", &path, &argv, &env))
  660.         return NULL;
  661.     if (is_listobject(argv)) {
  662.         argc = getlistsize(argv);
  663.         getitem = getlistitem;
  664.     }
  665.     else if (is_tupleobject(argv)) {
  666.         argc = gettuplesize(argv);
  667.         getitem = gettupleitem;
  668.     }
  669.     else {
  670.         err_setstr(TypeError, "argv must be tuple or list");
  671.         return NULL;
  672.     }
  673.     if (!is_dictobject(env)) {
  674.         err_setstr(TypeError, "env must be dictionary");
  675.         return NULL;
  676.     }
  677.  
  678.     argvlist = NEW(char *, argc+1);
  679.     if (argvlist == NULL) {
  680.         err_nomem();
  681.         return NULL;
  682.     }
  683.     for (i = 0; i < argc; i++) {
  684.         if (!getargs((*getitem)(argv, i),
  685.                  "s;argv must be list of strings",
  686.                  &argvlist[i])) {
  687.             goto fail_1;
  688.         }
  689.     }
  690.     argvlist[argc] = NULL;
  691.  
  692.     i = getmappingsize(env);
  693.     envlist = NEW(char *, i + 1);
  694.     if (envlist == NULL) {
  695.         err_nomem();
  696.         goto fail_1;
  697.     }
  698.     pos = 0;
  699.     envc = 0;
  700.     while (mappinggetnext(env, &pos, &key, &val)) {
  701.         char *p, *k, *v;
  702.         if (!getargs(key, "s;non-string key in env", &k) ||
  703.             !getargs(val, "s;non-string value in env", &v)) {
  704.             goto fail_2;
  705.         }
  706.         p = NEW(char, getstringsize(key) + getstringsize(val) + 2);
  707.         if (p == NULL) {
  708.             err_nomem();
  709.             goto fail_2;
  710.         }
  711.         sprintf(p, "%s=%s", k, v);
  712.         envlist[envc++] = p;
  713.     }
  714.     envlist[envc] = 0;
  715.  
  716.  
  717. #ifdef BAD_EXEC_PROTOTYPES
  718.     execve(path, (const char **)argvlist, envlist);
  719. #else
  720.     execve(path, argvlist, envlist);
  721. #endif
  722.     
  723.     /* If we get here it's definitely an error */
  724.  
  725.     (void) posix_error();
  726.  
  727.  fail_2:
  728.     while (--envc >= 0)
  729.         DEL(envlist[envc]);
  730.     DEL(envlist);
  731.  fail_1:
  732.     DEL(argvlist);
  733.  
  734.     return NULL;
  735. }
  736.  
  737. static object *
  738. posix_fork(self, args)
  739.     object *self;
  740.     object *args;
  741. {
  742.     int pid;
  743.     if (!getnoarg(args))
  744.         return NULL;
  745.     pid = fork();
  746.     if (pid == -1)
  747.         return posix_error();
  748.     return newintobject((long)pid);
  749. }
  750.  
  751. static object *
  752. posix_getegid(self, args)
  753.     object *self;
  754.     object *args;
  755. {
  756.     if (!getnoarg(args))
  757.         return NULL;
  758.     return newintobject((long)getegid());
  759. }
  760.  
  761. static object *
  762. posix_geteuid(self, args)
  763.     object *self;
  764.     object *args;
  765. {
  766.     if (!getnoarg(args))
  767.         return NULL;
  768.     return newintobject((long)geteuid());
  769. }
  770.  
  771. static object *
  772. posix_getgid(self, args)
  773.     object *self;
  774.     object *args;
  775. {
  776.     if (!getnoarg(args))
  777.         return NULL;
  778.     return newintobject((long)getgid());
  779. }
  780.  
  781. static object *
  782. posix_getpid(self, args)
  783.     object *self;
  784.     object *args;
  785. {
  786.     if (!getnoarg(args))
  787.         return NULL;
  788.     return newintobject((long)getpid());
  789. }
  790.  
  791. #ifdef HAVE_GETPGRP
  792. static object *
  793. posix_getpgrp(self, args)
  794.     object *self;
  795.     object *args;
  796. {
  797.     if (!getnoarg(args))
  798.         return NULL;
  799. #ifdef GETPGRP_HAVE_ARG
  800.     return newintobject((long)getpgrp(0));
  801. #else
  802.     return newintobject((long)getpgrp());
  803. #endif
  804. }
  805. #endif /* HAVE_GETPGRP */
  806.  
  807. #ifdef HAVE_SETPGRP
  808. static object *
  809. posix_setpgrp(self, args)
  810.     object *self;
  811.     object *args;
  812. {
  813.     if (!getnoarg(args))
  814.         return NULL;
  815. #ifdef GETPGRP_HAVE_ARG
  816.     if (setpgrp(0, 0) < 0)
  817. #else
  818.     if (setpgrp() < 0)
  819. #endif
  820.         return posix_error();
  821.     INCREF(None);
  822.     return None;
  823. }
  824.  
  825. #endif /* HAVE_SETPGRP */
  826.  
  827. static object *
  828. posix_getppid(self, args)
  829.     object *self;
  830.     object *args;
  831. {
  832.     if (!getnoarg(args))
  833.         return NULL;
  834.     return newintobject((long)getppid());
  835. }
  836.  
  837. static object *
  838. posix_getuid(self, args)
  839.     object *self;
  840.     object *args;
  841. {
  842.     if (!getnoarg(args))
  843.         return NULL;
  844.     return newintobject((long)getuid());
  845. }
  846.  
  847. static object *
  848. posix_kill(self, args)
  849.     object *self;
  850.     object *args;
  851. {
  852.     int pid, sig;
  853.     if (!getargs(args, "(ii)", &pid, &sig))
  854.         return NULL;
  855.     if (kill(pid, sig) == -1)
  856.         return posix_error();
  857.     INCREF(None);
  858.     return None;
  859. }
  860.  
  861. static object *
  862. posix_popen(self, args)
  863.     object *self;
  864.     object *args;
  865. {
  866.     char *name, *mode;
  867.     FILE *fp;
  868.     if (!getargs(args, "(ss)", &name, &mode))
  869.         return NULL;
  870.     BGN_SAVE
  871.     fp = popen(name, mode);
  872.     END_SAVE
  873.     if (fp == NULL)
  874.         return posix_error();
  875.     /* From now on, ignore SIGPIPE and let the error checking
  876.        do the work. */
  877. #ifdef NT
  878.     return newopenfileobject(fp, name, mode, fclose);
  879. #else /* ! NT */
  880.     (void) signal(SIGPIPE, SIG_IGN);
  881.     return newopenfileobject(fp, name, mode, pclose);
  882. #endif /* ! NT */
  883. }
  884.  
  885. #ifdef HAVE_SETUID
  886. static object *
  887. posix_setuid(self, args)
  888.     object *self;
  889.     object *args;
  890. {
  891.     int uid;
  892.     if (!getargs(args, "i", &uid))
  893.         return NULL;
  894.     if (setuid(uid) < 0)
  895.         return posix_error();
  896.     INCREF(None);
  897.     return None;
  898. }
  899. #endif
  900.  
  901. #ifdef HAVE_GETUID
  902. static object *
  903. posix_setgid(self, args)
  904.     object *self;
  905.     object *args;
  906. {
  907.     int gid;
  908.     if (!getargs(args, "i", &gid))
  909.         return NULL;
  910.     if (setgid(gid) < 0)
  911.         return posix_error();
  912.     INCREF(None);
  913.     return None;
  914. }
  915. #endif
  916.  
  917. #ifdef HAVE_WAITPID
  918. static object *
  919. posix_waitpid(self, args)
  920.     object *self;
  921.     object *args;
  922. {
  923.     int pid, options, sts;
  924.     if (!getargs(args, "(ii)", &pid, &options))
  925.         return NULL;
  926.     BGN_SAVE
  927.     pid = waitpid(pid, &sts, options);
  928.     END_SAVE
  929.     if (pid == -1)
  930.         return posix_error();
  931.     else
  932.         return mkvalue("ii", pid, sts);
  933. }
  934. #endif /* HAVE_WAITPID */
  935.  
  936. static object *
  937. posix_wait(self, args)
  938.     object *self;
  939.     object *args;
  940. {
  941.     int pid, sts;
  942.     BGN_SAVE
  943.     pid = wait(&sts);
  944.     END_SAVE
  945.     if (pid == -1)
  946.         return posix_error();
  947.     else
  948.         return mkvalue("ii", pid, sts);
  949. }
  950.  
  951. static object *
  952. posix_lstat(self, args)
  953.     object *self;
  954.     object *args;
  955. {
  956. #ifdef HAVE_LSTAT
  957.     return posix_do_stat(self, args, lstat);
  958. #else /* !HAVE_LSTAT */
  959.     return posix_do_stat(self, args, stat);
  960. #endif /* !HAVE_LSTAT */
  961. }
  962.  
  963. #ifdef HAVE_READLINK
  964. static object *
  965. posix_readlink(self, args)
  966.     object *self;
  967.     object *args;
  968. {
  969.     char buf[MAXPATHLEN];
  970.     char *path;
  971.     int n;
  972.     if (!getargs(args, "s", &path))
  973.         return NULL;
  974.     BGN_SAVE
  975.     n = readlink(path, buf, (int) sizeof buf);
  976.     END_SAVE
  977.     if (n < 0)
  978.         return posix_error();
  979.     return newsizedstringobject(buf, n);
  980. }
  981. #endif /* HAVE_READLINK */
  982.  
  983. #ifdef HAVE_SYMLINK
  984. static object *
  985. posix_symlink(self, args)
  986.     object *self;
  987.     object *args;
  988. {
  989.     return posix_2str(args, symlink);
  990. }
  991. #endif /* HAVE_SYMLINK */
  992.  
  993. #ifdef HAVE_TIMES
  994. #ifndef HZ
  995. #define HZ 60 /* Universal constant :-) */
  996. #endif
  997. static object *
  998. posix_times(self, args)
  999.     object *self;
  1000.     object *args;
  1001. {
  1002.     struct tms t;
  1003.     clock_t c;
  1004.     if (!getnoarg(args))
  1005.         return NULL;
  1006.     errno = 0;
  1007.     c = times(&t);
  1008.     if (c == (clock_t) -1)
  1009.         return posix_error();
  1010.     return mkvalue("dddd",
  1011.                (double)t.tms_utime / HZ,
  1012.                (double)t.tms_stime / HZ,
  1013.                (double)t.tms_cutime / HZ,
  1014.                (double)t.tms_cstime / HZ);
  1015. }
  1016. #endif /* HAVE_TIMES */
  1017.  
  1018. #ifdef HAVE_SETSID
  1019. static object *
  1020. posix_setsid(self, args)
  1021.     object *self;
  1022.     object *args;
  1023. {
  1024.     if (!getnoarg(args))
  1025.         return NULL;
  1026.     if (setsid() < 0)
  1027.         return posix_error();
  1028.     INCREF(None);
  1029.     return None;
  1030. }
  1031. #endif /* HAVE_SETSID */
  1032.  
  1033. #ifdef HAVE_SETPGID
  1034. static object *
  1035. posix_setpgid(self, args)
  1036.     object *self;
  1037.     object *args;
  1038. {
  1039.     int pid, pgrp;
  1040.     if (!getargs(args, "(ii)", &pid, &pgrp))
  1041.         return NULL;
  1042.     if (setpgid(pid, pgrp) < 0)
  1043.         return posix_error();
  1044.     INCREF(None);
  1045.     return None;
  1046. }
  1047. #endif /* HAVE_SETPGID */
  1048.  
  1049. #ifdef HAVE_TCGETPGRP
  1050. static object *
  1051. posix_tcgetpgrp(self, args)
  1052.     object *self;
  1053.     object *args;
  1054. {
  1055.     int fd, pgid;
  1056.     if (!getargs(args, "i", &fd))
  1057.         return NULL;
  1058.     pgid = tcgetpgrp(fd);
  1059.     if (pgid < 0)
  1060.         return posix_error();
  1061.     return newintobject((long)pgid);
  1062. }
  1063. #endif /* HAVE_TCGETPGRP */
  1064.  
  1065. #ifdef HAVE_TCSETPGRP
  1066. static object *
  1067. posix_tcsetpgrp(self, args)
  1068.     object *self;
  1069.     object *args;
  1070. {
  1071.     int fd, pgid;
  1072.     if (!getargs(args, "(ii)", &fd, &pgid))
  1073.         return NULL;
  1074.     if (tcsetpgrp(fd, pgid) < 0)
  1075.         return posix_error();
  1076.        INCREF(None);
  1077.     return None;
  1078. }
  1079. #endif /* HAVE_TCSETPGRP */
  1080.  
  1081. /* Functions acting on file descriptors */
  1082.  
  1083. static object *
  1084. posix_open(self, args)
  1085.     object *self;
  1086.     object *args;
  1087. {
  1088.     char *file;
  1089.     int flag;
  1090.     int mode = 0777;
  1091.     int fd;
  1092.     if (!getargs(args, "(si)", &file, &flag)) {
  1093.         err_clear();
  1094.         if (!getargs(args, "(sii)", &file, &flag, &mode))
  1095.             return NULL;
  1096.     }
  1097.     BGN_SAVE
  1098.     fd = open(file, flag, mode);
  1099.     END_SAVE
  1100.     if (fd < 0)
  1101.         return posix_error();
  1102.     return newintobject((long)fd);
  1103. }
  1104.  
  1105. static object *
  1106. posix_close(self, args)
  1107.     object *self;
  1108.     object *args;
  1109. {
  1110.     int fd, res;
  1111.     if (!getargs(args, "i", &fd))
  1112.         return NULL;
  1113.     BGN_SAVE
  1114.     res = close(fd);
  1115.     END_SAVE
  1116.     if (res < 0)
  1117.         return posix_error();
  1118.     INCREF(None);
  1119.     return None;
  1120. }
  1121.  
  1122. static object *
  1123. posix_dup(self, args)
  1124.     object *self;
  1125.     object *args;
  1126. {
  1127.     int fd;
  1128.     if (!getargs(args, "i", &fd))
  1129.         return NULL;
  1130.     BGN_SAVE
  1131.     fd = dup(fd);
  1132.     END_SAVE
  1133.     if (fd < 0)
  1134.         return posix_error();
  1135.     return newintobject((long)fd);
  1136. }
  1137.  
  1138. static object *
  1139. posix_dup2(self, args)
  1140.     object *self;
  1141.     object *args;
  1142. {
  1143.     int fd, fd2, res;
  1144.     if (!getargs(args, "(ii)", &fd, &fd2))
  1145.         return NULL;
  1146.     BGN_SAVE
  1147.     res = dup2(fd, fd2);
  1148.     END_SAVE
  1149.     if (res < 0)
  1150.         return posix_error();
  1151.     INCREF(None);
  1152.     return None;
  1153. }
  1154.  
  1155. static object *
  1156. posix_lseek(self, args)
  1157.     object *self;
  1158.     object *args;
  1159. {
  1160.     int fd, how;
  1161.     long pos, res;
  1162.     if (!getargs(args, "(ili)", &fd, &pos, &how))
  1163.         return NULL;
  1164. #ifdef SEEK_SET
  1165.     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
  1166.     switch (how) {
  1167.     case 0: how = SEEK_SET; break;
  1168.     case 1: how = SEEK_CUR; break;
  1169.     case 2: how = SEEK_END; break;
  1170.     }
  1171. #endif
  1172.     BGN_SAVE
  1173.     res = lseek(fd, pos, how);
  1174.     END_SAVE
  1175.     if (res < 0)
  1176.         return posix_error();
  1177.     return newintobject(res);
  1178. }
  1179.  
  1180. static object *
  1181. posix_read(self, args)
  1182.     object *self;
  1183.     object *args;
  1184. {
  1185.     int fd, size;
  1186.     object *buffer;
  1187.     if (!getargs(args, "(ii)", &fd, &size))
  1188.         return NULL;
  1189.     buffer = newsizedstringobject((char *)NULL, size);
  1190.     if (buffer == NULL)
  1191.         return NULL;
  1192.     BGN_SAVE
  1193.     size = read(fd, getstringvalue(buffer), size);
  1194.     END_SAVE
  1195.     if (size < 0) {
  1196.         DECREF(buffer);
  1197.         return posix_error();
  1198.     }
  1199.     resizestring(&buffer, size);
  1200.     return buffer;
  1201. }
  1202.  
  1203. static object *
  1204. posix_write(self, args)
  1205.     object *self;
  1206.     object *args;
  1207. {
  1208.     int fd, size;
  1209.     char *buffer;
  1210.     if (!getargs(args, "(is#)", &fd, &buffer, &size))
  1211.         return NULL;
  1212.     BGN_SAVE
  1213.     size = write(fd, buffer, size);
  1214.     END_SAVE
  1215.     if (size < 0)
  1216.         return posix_error();
  1217.     return newintobject((long)size);
  1218. }
  1219.  
  1220. static object *
  1221. posix_fstat(self, args)
  1222.     object *self;
  1223.     object *args;
  1224. {
  1225.     int fd;
  1226.     struct stat st;
  1227.     int res;
  1228.     if (!getargs(args, "i", &fd))
  1229.         return NULL;
  1230.     BGN_SAVE
  1231.     res = fstat(fd, &st);
  1232.     END_SAVE
  1233.     if (res != 0)
  1234.         return posix_error();
  1235.     return mkvalue("(llllllllll)",
  1236.             (long)st.st_mode,
  1237.             (long)st.st_ino,
  1238.             (long)st.st_dev,
  1239.             (long)st.st_nlink,
  1240.             (long)st.st_uid,
  1241.             (long)st.st_gid,
  1242.             (long)st.st_size,
  1243.             (long)st.st_atime,
  1244.             (long)st.st_mtime,
  1245.             (long)st.st_ctime);
  1246. }
  1247.  
  1248. static object *
  1249. posix_fdopen(self, args)
  1250.     object *self;
  1251.     object *args;
  1252. {
  1253.     extern int fclose PROTO((FILE *));
  1254.     int fd;
  1255.     char *mode;
  1256.     FILE *fp;
  1257.     if (!getargs(args, "(is)", &fd, &mode))
  1258.         return NULL;
  1259.     BGN_SAVE
  1260.     fp = fdopen(fd, mode);
  1261.     END_SAVE
  1262.     if (fp == NULL)
  1263.         return posix_error();
  1264.     /* From now on, ignore SIGPIPE and let the error checking
  1265.        do the work. */
  1266. #ifndef NT
  1267.     (void) signal(SIGPIPE, SIG_IGN);
  1268. #endif /* ! NT */
  1269.     return newopenfileobject(fp, "(fdopen)", mode, fclose);
  1270. }
  1271.  
  1272. static object *
  1273. posix_pipe(self, args)
  1274.     object *self;
  1275.     object *args;
  1276. {
  1277.     int fds[2];
  1278.     int res;
  1279.     if (!getargs(args, ""))
  1280.         return NULL;
  1281.     BGN_SAVE
  1282.     res = pipe(fds);
  1283.     END_SAVE
  1284.     if (res != 0)
  1285.         return posix_error();
  1286.     return mkvalue("(ii)", fds[0], fds[1]);
  1287. }
  1288.  
  1289. static struct methodlist posix_methods[] = {
  1290.     {"chdir",    posix_chdir},
  1291.     {"chmod",    posix_chmod},
  1292. #ifdef HAVE_CHOWN
  1293.     {"chown",    posix_chown},
  1294. #endif
  1295.     {"getcwd",    posix_getcwd},
  1296. #ifdef HAVE_LINK
  1297.     {"link",    posix_link},
  1298. #endif 
  1299.     {"listdir",    posix_listdir},
  1300.     {"lstat",    posix_lstat},
  1301.     {"mkdir",    posix_mkdir},
  1302. #ifdef HAVE_NICE
  1303.     {"nice",    posix_nice},
  1304. #endif
  1305. #ifdef HAVE_READLINK
  1306.     {"readlink",    posix_readlink},
  1307. #endif
  1308.     {"rename",    posix_rename},
  1309.     {"rmdir",    posix_rmdir},
  1310.     {"stat",    posix_stat},
  1311. #ifdef HAVE_SYMLINK
  1312.     {"symlink",    posix_symlink},
  1313. #endif
  1314.     {"system",    posix_system},
  1315.     {"umask",    posix_umask},
  1316. #ifdef HAVE_UNAME
  1317.     {"uname",    posix_uname},
  1318. #endif
  1319.     {"unlink",    posix_unlink},
  1320. #ifndef NT
  1321.     {"utime",    posix_utime},
  1322. #endif /* ! NT */
  1323. #ifdef HAVE_TIMES
  1324.     {"times",    posix_times},
  1325. #endif
  1326.     {"_exit",    posix__exit},
  1327.     {"execv",    posix_execv},
  1328.     {"execve",    posix_execve},
  1329. #ifndef NT
  1330.     {"fork",    posix_fork},
  1331.     {"getegid",    posix_getegid},
  1332.     {"geteuid",    posix_geteuid},
  1333.     {"getgid",    posix_getgid},
  1334. #endif /* ! NT */
  1335.     {"getpid",    posix_getpid},
  1336. #ifdef HAVE_GETPGRP
  1337.     {"getpgrp",    posix_getpgrp},
  1338. #endif
  1339. #ifndef NT
  1340.     {"getppid",    posix_getppid},
  1341.     {"getuid",    posix_getuid},
  1342.     {"kill",    posix_kill},
  1343. #endif /* ! NT */
  1344.     {"popen",    posix_popen},
  1345. #ifdef HAVE_SETUID
  1346.     {"setuid",    posix_setuid},
  1347. #endif
  1348. #ifdef HAVE_SETGID
  1349.     {"setgid",    posix_setgid},
  1350. #endif
  1351. #ifdef HAVE_SETPGRP
  1352.     {"setpgrp",    posix_setpgrp},
  1353. #endif
  1354. #ifndef NT
  1355.     {"wait",    posix_wait},
  1356. #endif /* ! NT */
  1357. #ifdef HAVE_WAITPID
  1358.     {"waitpid",    posix_waitpid},
  1359. #endif
  1360. #ifdef HAVE_SETSID
  1361.     {"setsid",    posix_setsid},
  1362. #endif
  1363. #ifdef HAVE_SETPGID
  1364.     {"setpgid",    posix_setpgid},
  1365. #endif
  1366. #ifdef HAVE_TCGETPGRP
  1367.     {"tcgetpgrp",    posix_tcgetpgrp},
  1368. #endif
  1369. #ifdef HAVE_TCSETPGRP
  1370.     {"tcsetpgrp",    posix_tcsetpgrp},
  1371. #endif
  1372.     {"open",    posix_open},
  1373.     {"close",    posix_close},
  1374.     {"dup",        posix_dup},
  1375.     {"dup2",    posix_dup2},
  1376.     {"lseek",    posix_lseek},
  1377.     {"read",    posix_read},
  1378.     {"write",    posix_write},
  1379.     {"fstat",    posix_fstat},
  1380.     {"fdopen",    posix_fdopen},
  1381. #ifndef NT
  1382.     {"pipe",    posix_pipe},
  1383. #endif /* ! NT */
  1384.  
  1385.     {NULL,        NULL}         /* Sentinel */
  1386. };
  1387.  
  1388.  
  1389. #ifdef NT
  1390. void
  1391. initnt()
  1392. {
  1393.     object *m, *d, *v;
  1394.     
  1395.     m = initmodule("nt", posix_methods);
  1396.     d = getmoduledict(m);
  1397.     
  1398.     /* Initialize nt.environ dictionary */
  1399.     v = convertenviron();
  1400.     if (v == NULL || dictinsert(d, "environ", v) != 0)
  1401.         fatal("can't define nt.environ");
  1402.     DECREF(v);
  1403.     
  1404.     /* Initialize nt.error exception */
  1405.     PosixError = newstringobject("nt.error");
  1406.     if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
  1407.         fatal("can't define nt.error");
  1408. }
  1409. #else /* ! NT */
  1410. void
  1411. initposix()
  1412. {
  1413.     object *m, *d, *v;
  1414.     
  1415.     m = initmodule("posix", posix_methods);
  1416.     d = getmoduledict(m);
  1417.     
  1418.     /* Initialize posix.environ dictionary */
  1419.     v = convertenviron();
  1420.     if (v == NULL || dictinsert(d, "environ", v) != 0)
  1421.         fatal("can't define posix.environ");
  1422.     DECREF(v);
  1423.     
  1424.     /* Initialize posix.error exception */
  1425.     PosixError = newstringobject("posix.error");
  1426.     if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
  1427.         fatal("can't define posix.error");
  1428. }
  1429. #endif /* ! NT */
  1430.