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