home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / Python 1.3 / source code / Dos / dosmodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-17  |  11.0 KB  |  615 lines  |  [TEXT/R*ch]

  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 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. /* Operating system module implementation for MS-DOS */
  26. /* Tested with Microsoft C 7.0 (as part of MSVC++ Pro 1.0) */
  27.  
  28. #ifdef QUICKWIN
  29. #include <windows.h>
  30. #endif
  31.  
  32. #ifdef HAVE_CONFIG_H
  33. #include "config.h"
  34. #endif
  35.  
  36. #ifdef MSC_DIRAPI         /* using Microsoft directory interface */
  37. #include <dos.h>
  38. #endif
  39.  
  40. #ifdef BORC_DIRAPI        /* using Borland interface (also gcc) */
  41. #include <dir.h>
  42. #endif
  43.  
  44. #include <stdlib.h>
  45. #include <signal.h>
  46. #include <string.h>
  47. #include <sys/types.h>
  48. #include <sys/stat.h>
  49.  
  50. #include <direct.h> /* chdir(), mkdir(), rmdir(), getcwd() */
  51.  
  52. #include "allobjects.h"
  53. #include "modsupport.h"
  54. #include "ceval.h"
  55.  
  56.  
  57. /* Return a dictionary corresponding to the DOS environment table */
  58.  
  59. static object *
  60. convertenviron()
  61. {
  62.     object *d;
  63.     char **e;
  64.     d = newdictobject();
  65.     if (d == NULL)
  66.         return NULL;
  67.     if (environ == NULL)
  68.         return d;
  69.     /* XXX This part ignores errors */
  70.     for (e = environ; *e != NULL; e++) {
  71.         object *v;
  72.         char *p = strchr(*e, '=');
  73.         if (p == NULL)
  74.             continue;
  75.         v = newstringobject(p+1);
  76.         if (v == NULL)
  77.             continue;
  78.         *p = '\0';
  79.         (void) dictinsert(d, *e, v);
  80.         *p = '=';
  81.         DECREF(v);
  82.     }
  83.     return d;
  84. }
  85.  
  86.  
  87. static object *DosError; /* Exception dos.error */
  88.  
  89. /* Set a DOS-specific error from errno, and return NULL */
  90.  
  91. static object *
  92. dos_error()
  93. {
  94.      return err_errno(DosError);
  95. }
  96.  
  97.  
  98. /* DOS generic methods */
  99.  
  100. static object *
  101. dos_1str(args, func)
  102.     object *args;
  103.     int (*func) FPROTO((const char *));
  104. {
  105.     char *path1;
  106.     int res;
  107.     if (!getargs(args, "s", &path1))
  108.         return NULL;
  109.     BGN_SAVE
  110.     res = (*func)(path1);
  111.     END_SAVE
  112.     if (res < 0)
  113.         return dos_error();
  114.     INCREF(None);
  115.     return None;
  116. }
  117.  
  118. static object *
  119. dos_2str(args, func)
  120.     object *args;
  121.     int (*func) FPROTO((const char *, const char *));
  122. {
  123.     char *path1, *path2;
  124.     int res;
  125.     if (!getargs(args, "(ss)", &path1, &path2))
  126.         return NULL;
  127.     BGN_SAVE
  128.     res = (*func)(path1, path2);
  129.     END_SAVE
  130.     if (res < 0)
  131.         return dos_error();
  132.     INCREF(None);
  133.     return None;
  134. }
  135.  
  136. static object *
  137. dos_strint(args, func)
  138.     object *args;
  139.     int (*func) FPROTO((const char *, int));
  140. {
  141.     char *path;
  142.     int i;
  143.     int res;
  144.     if (!getargs(args, "(si)", &path, &i))
  145.         return NULL;
  146.     BGN_SAVE
  147.     res = (*func)(path, i);
  148.     END_SAVE
  149.     if (res < 0)
  150.         return dos_error();
  151.     INCREF(None);
  152.     return None;
  153. }
  154.  
  155. static object *
  156. dos_do_stat(self, args, statfunc)
  157.     object *self;
  158.     object *args;
  159.     int (*statfunc) FPROTO((const char *, struct stat *));
  160. {
  161.     struct stat st;
  162.     char *path;
  163.     int res;
  164.     if (!getargs(args, "s", &path))
  165.         return NULL;
  166.     BGN_SAVE
  167.     res = (*statfunc)(path, &st);
  168.     END_SAVE
  169.     if (res != 0)
  170.         return dos_error();
  171.     return mkvalue("(llllllllll)",
  172.             (long)st.st_mode,
  173.             (long)st.st_ino,
  174.             (long)st.st_dev,
  175.             (long)st.st_nlink,
  176.             (long)st.st_uid,
  177.             (long)st.st_gid,
  178.             (long)st.st_size,
  179.             (long)st.st_atime,
  180.             (long)st.st_mtime,
  181.             (long)st.st_ctime);
  182. }
  183.  
  184.  
  185. /* DOS methods */
  186.  
  187. static object *
  188. dos_chdir(self, args)
  189.     object *self;
  190.     object *args;
  191. {
  192.     return dos_1str(args, chdir);
  193. }
  194.  
  195. static object *
  196. dos_chmod(self, args)
  197.     object *self;
  198.     object *args;
  199. {
  200.     extern int chmod();
  201.     return dos_strint(args, chmod);
  202. }
  203.  
  204. static object *
  205. dos_getcwd(self, args)
  206.     object *self;
  207.     object *args;
  208. {
  209.     char buf[1026];
  210.     char *res;
  211.     if (!getnoarg(args))
  212.         return NULL;
  213.     BGN_SAVE
  214.     res = getcwd(buf, sizeof buf);
  215.     END_SAVE
  216.     if (res == NULL)
  217.         return dos_error();
  218.     return newstringobject(buf);
  219. }
  220.  
  221. static object *
  222. dos_listdir(self, args)
  223.     object *self;
  224.     object *args;
  225. {
  226.     char *name;
  227.     int len;
  228.     object *d, *v;
  229.     int rv;
  230.     char namebuf[256];
  231.  
  232. #ifdef MSC_DIRAPI
  233. #   define GetFilename(ep)   (ep).name
  234. #   define findnext          _dos_findnext
  235.     struct find_t ep;
  236. #endif
  237.  
  238. #ifdef BORC_DIRAPI
  239. #   define GetFilename(ep)   (ep).ff_name
  240.     struct ffblk ep;
  241. #endif
  242.  
  243.     if (!getargs(args, "s#", &name, &len))
  244.         return NULL;
  245.     if (len >= 250) {
  246.         err_setstr(ValueError, "path too long");
  247.         return NULL;
  248.     }
  249.     strcpy(namebuf, name);
  250.     if (len == 0) {
  251.         strcpy(namebuf, "./");
  252.         len = 2;
  253.     }
  254.     else if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
  255.         namebuf[len++] = '/';
  256.     strcpy(namebuf + len, "*.*");
  257.  
  258.     if ((d = newlistobject(0)) == NULL)
  259.         return NULL;
  260.  
  261. #ifdef MSC_DIRAPI
  262.     if (_dos_findfirst(namebuf,
  263.             _A_HIDDEN | _A_RDONLY | _A_SUBDIR, &ep) != 0)
  264.         return dos_error();
  265. #endif
  266.  
  267. #ifdef BORC_DIRAPI
  268.     if (findfirst(namebuf,
  269.             &ep, FA_HIDDEN | FA_RDONLY | FA_DIREC) != 0)
  270.         return dos_error();
  271. #endif
  272.  
  273.     do {
  274.         char *p;
  275.         for (p = GetFilename(ep); *p != '\0'; p++)
  276.             *p = tolower(*p);
  277.         v = newstringobject(GetFilename(ep));
  278.         if (v == NULL) {
  279.             DECREF(d);
  280.             d = NULL;
  281.             break;
  282.         }
  283.         if (addlistitem(d, v) != 0) {
  284.             DECREF(v);
  285.             DECREF(d);
  286.             d = NULL;
  287.             break;
  288.         }
  289.         DECREF(v);
  290.     } while (findnext(&ep) == 0);
  291.  
  292.     return d;
  293. }
  294.  
  295. static object *
  296. dos_mkdir(self, args)
  297.     object *self;
  298.     object *args;
  299. {
  300.     return dos_strint(args, mkdir);
  301. }
  302.  
  303. static object *
  304. dos_rename(self, args)
  305.     object *self;
  306.     object *args;
  307. {
  308.     return dos_2str(args, rename);
  309. }
  310.  
  311. static object *
  312. dos_rmdir(self, args)
  313.     object *self;
  314.     object *args;
  315. {
  316.     return dos_1str(args, rmdir);
  317. }
  318.  
  319. static object *
  320. dos_stat(self, args)
  321.     object *self;
  322.     object *args;
  323. {
  324.     return dos_do_stat(self, args, stat);
  325. }
  326.  
  327. static object *
  328. dos_system(self, args)
  329.     object *self;
  330.     object *args;
  331. {
  332.     char *command;
  333.     long sts;
  334.     if (!getargs(args, "s", &command))
  335.         return NULL;
  336.     BGN_SAVE
  337.     sts = system(command);
  338.     END_SAVE
  339.     return newintobject(sts);
  340. }
  341.  
  342. static object *
  343. dos_unlink(self, args)
  344.     object *self;
  345.     object *args;
  346. {
  347.     return dos_1str(args, unlink);
  348. }
  349.  
  350. static object *
  351. dos_utime(self, args)
  352.     object *self;
  353.     object *args;
  354. {
  355.     char *path;
  356.     int res;
  357.  
  358. #ifdef UTIME_STRUCT
  359.     struct utimbuf buf;
  360. #define ATIME buf.actime
  361. #define MTIME buf.modtime
  362. #define UTIME_ARG &buf
  363.  
  364. #else
  365.     time_t buf[2];
  366. #define ATIME buf[0]
  367. #define MTIME buf[1]
  368. #define UTIME_ARG buf
  369. #endif
  370.  
  371.     if (!getargs(args, "(s(ll))", &path, &ATIME, &MTIME))
  372.         return NULL;
  373.     BGN_SAVE
  374.     res = utime(path, UTIME_ARG);
  375.     END_SAVE
  376.     if (res < 0)
  377.         return dos_error();
  378.     INCREF(None);
  379.     return None;
  380. #undef UTIME_ARG
  381. #undef ATIME
  382. #undef MTIME
  383. }
  384.  
  385. /* Functions acting on file descriptors */
  386.  
  387. static object *
  388. dos_open(self, args)
  389.     object *self;
  390.     object *args;
  391. {
  392.     char *file;
  393.     int flag;
  394.     int mode = 0777;
  395.     int fd;
  396.     if (!getargs(args, "(si)", &file, &flag)) {
  397.         err_clear();
  398.         if (!getargs(args, "(sii)", &file, &flag, &mode))
  399.             return NULL;
  400.     }
  401.     BGN_SAVE
  402.     fd = open(file, flag, mode);
  403.     END_SAVE
  404.     if (fd < 0)
  405.         return dos_error();
  406.     return newintobject((long)fd);
  407. }
  408.  
  409. static object *
  410. dos_close(self, args)
  411.     object *self;
  412.     object *args;
  413. {
  414.     int fd, res;
  415.     if (!getargs(args, "i", &fd))
  416.         return NULL;
  417.     BGN_SAVE
  418.     res = close(fd);
  419.     END_SAVE
  420.     if (res < 0)
  421.         return dos_error();
  422.     INCREF(None);
  423.     return None;
  424. }
  425.  
  426. static object *
  427. dos_dup(self, args)
  428.     object *self;
  429.     object *args;
  430. {
  431.     int fd;
  432.     if (!getargs(args, "i", &fd))
  433.         return NULL;
  434.     BGN_SAVE
  435.     fd = dup(fd);
  436.     END_SAVE
  437.     if (fd < 0)
  438.         return dos_error();
  439.     return newintobject((long)fd);
  440. }
  441.  
  442. static object *
  443. dos_dup2(self, args)
  444.     object *self;
  445.     object *args;
  446. {
  447.     int fd, fd2, res;
  448.     if (!getargs(args, "(ii)", &fd, &fd2))
  449.         return NULL;
  450.     BGN_SAVE
  451.     res = dup2(fd, fd2);
  452.     END_SAVE
  453.     if (res < 0)
  454.         return dos_error();
  455.     INCREF(None);
  456.     return None;
  457. }
  458.  
  459. static object *
  460. dos_lseek(self, args)
  461.     object *self;
  462.     object *args;
  463. {
  464.     int fd, how;
  465.     long pos, res;
  466.     if (!getargs(args, "(ili)", &fd, &pos, &how))
  467.         return NULL;
  468. #ifdef SEEK_SET
  469.     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
  470.     switch (how) {
  471.     case 0: how = SEEK_SET; break;
  472.     case 1: how = SEEK_CUR; break;
  473.     case 2: how = SEEK_END; break;
  474.     }
  475. #endif
  476.     BGN_SAVE
  477.     res = lseek(fd, pos, how);
  478.     END_SAVE
  479.     if (res < 0)
  480.         return dos_error();
  481.     return newintobject(res);
  482. }
  483.  
  484. static object *
  485. dos_read(self, args)
  486.     object *self;
  487.     object *args;
  488. {
  489.     int fd, size;
  490.     object *buffer;
  491.     if (!getargs(args, "(ii)", &fd, &size))
  492.         return NULL;
  493.     buffer = newsizedstringobject((char *)NULL, size);
  494.     if (buffer == NULL)
  495.         return NULL;
  496.     BGN_SAVE
  497.     size = read(fd, getstringvalue(buffer), size);
  498.     END_SAVE
  499.     if (size < 0) {
  500.         DECREF(buffer);
  501.         return dos_error();
  502.     }
  503.     resizestring(&buffer, size);
  504.     return buffer;
  505. }
  506.  
  507. static object *
  508. dos_write(self, args)
  509.     object *self;
  510.     object *args;
  511. {
  512.     int fd, size;
  513.     char *buffer;
  514.     if (!getargs(args, "(is#)", &fd, &buffer, &size))
  515.         return NULL;
  516.     BGN_SAVE
  517.     size = write(fd, buffer, size);
  518.     END_SAVE
  519.     if (size < 0)
  520.         return dos_error();
  521.     return newintobject((long)size);
  522. }
  523.  
  524. static object *
  525. dos_fstat(self, args)
  526.     object *self;
  527.     object *args;
  528. {
  529.     int fd;
  530.     struct stat st;
  531.     int res;
  532.     if (!getargs(args, "i", &fd))
  533.         return NULL;
  534.     BGN_SAVE
  535.     res = fstat(fd, &st);
  536.     END_SAVE
  537.     if (res != 0)
  538.         return dos_error();
  539.     return mkvalue("(llllllllll)",
  540.             (long)st.st_mode,
  541.             (long)st.st_ino,
  542.             (long)st.st_dev,
  543.             (long)st.st_nlink,
  544.             (long)st.st_uid,
  545.             (long)st.st_gid,
  546.             (long)st.st_size,
  547.             (long)st.st_atime,
  548.             (long)st.st_mtime,
  549.             (long)st.st_ctime);
  550. }
  551.  
  552. static object *
  553. dos_fdopen(self, args)
  554.     object *self;
  555.     object *args;
  556. {
  557.     extern int fclose PROTO((FILE *));
  558.     int fd;
  559.     char *mode;
  560.     FILE *fp;
  561.     if (!getargs(args, "(is)", &fd, &mode))
  562.         return NULL;
  563.     BGN_SAVE
  564.     fp = fdopen(fd, mode);
  565.     END_SAVE
  566.     if (fp == NULL)
  567.         return dos_error();
  568.     return newopenfileobject(fp, "(fdopen)", mode, fclose);
  569. }
  570.  
  571. static struct methodlist dos_methods[] = {
  572.     {"chdir",    dos_chdir},
  573.     {"chmod",    dos_chmod},
  574.     {"getcwd",    dos_getcwd},
  575.     {"listdir",    dos_listdir},
  576.     {"mkdir",    dos_mkdir},
  577.     {"rename",    dos_rename},
  578.     {"rmdir",    dos_rmdir},
  579.     {"stat",    dos_stat},
  580.     {"system",    dos_system},
  581.     {"unlink",    dos_unlink},
  582.     {"utime",    dos_utime},
  583.     {"open",    dos_open},
  584.     {"close",    dos_close},
  585.     {"dup",        dos_dup},
  586.     {"dup2",    dos_dup2},
  587.     {"lseek",    dos_lseek},
  588.     {"read",    dos_read},
  589.     {"write",    dos_write},
  590.     {"fstat",    dos_fstat},
  591.     {"fdopen",    dos_fdopen},
  592.     {NULL,        NULL}         /* Sentinel */
  593. };
  594.  
  595.  
  596. void
  597. initdos()
  598. {
  599.     object *m, *d, *v;
  600.  
  601.     m = initmodule("dos", dos_methods);
  602.     d = getmoduledict(m);
  603.  
  604.     /* Initialize dos.environ dictionary */
  605.     v = convertenviron();
  606.     if (v == NULL || dictinsert(d, "environ", v) != 0)
  607.         fatal("can't define dos.environ");
  608.     DECREF(v);
  609.  
  610.     /* Initialize dos.error exception */
  611.     DosError = newstringobject("dos.error");
  612.     if (DosError == NULL || dictinsert(d, "error", DosError) != 0)
  613.         fatal("can't define dos.error");
  614. }
  615.