home *** CD-ROM | disk | FTP | other *** search
/ Internet MPEG Audio Archive / IMAA.mdf / util / dos / l3v100n / rsx / source / sysdj.c < prev    next >
C/C++ Source or Header  |  1994-01-19  |  16KB  |  653 lines

  1. /* This file is SYSDJ.c
  2. ** contains :
  3. **
  4. **        - int21,ah=0xff djgpp syscall handler
  5. **
  6. ** Copyright (c) Rainer Schnitker 92 93
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <malloc.h>
  13. #include <fcntl.h>
  14. #include <direct.h>
  15. #include <io.h>
  16. #include <time.h>
  17. #include <ctype.h>
  18. #include <sys/timeb.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21.  
  22. #include "DPMI.H"
  23. #include "PROCESS.H"
  24. #include "SIGNALS.H"
  25. #include "CDOSX32.H"
  26. #include "START32.H"
  27. #include "COPY32.H"
  28. #include "RSX.H"
  29. #include "DOSERRNO.H"
  30.  
  31. #ifndef __TURBOC__
  32. #define MAXPATH _MAX_PATH
  33. #include <dos.h>
  34. static int stime(time_t *gmt_seconds)
  35. {
  36.     struct tm *pTM;
  37.     struct dostime_t dost;
  38.  
  39.     pTM = gmtime(gmt_seconds);
  40.     dost.hour = (char) pTM->tm_hour;
  41.     dost.minute = (char) pTM->tm_min;
  42.     dost.second = (char) pTM->tm_sec;
  43.     dost.hsecond = 0;
  44.     _dos_settime(&dost);
  45.     return 0;
  46. }
  47. int convert_open_attrib(int att)
  48. {
  49.     int o_rdwr = (att & 0x0F) >> 1;     /* bcc O_R/W flags */
  50.     if (att & 0x800)
  51.         o_rdwr &= O_APPEND;
  52.     return (att & 0xFFF0) | o_rdwr;
  53. }
  54. #endif
  55.  
  56. static int fscan_q(FILE *, char *);
  57. int unixlike_stat(char *, struct stat *);
  58.  
  59.  
  60. /*
  61. **  move  stack,data,bss,heap
  62. **      |-CCCCC---------------------------------SSSS-DDDD-HHH-|
  63. **    0                        ^0x400000
  64. **
  65. **  to the end of text
  66. **      |-CCCCC-SSSS-DDDD-HHH-|
  67. */
  68.  
  69. void compress_memory(void)
  70. {
  71.     DWORD movedmem, newhandle, newaddress;
  72.     DWORD r_esp = ESP & ~4095L;
  73.  
  74.     /* check djgpp segment, and stack */
  75.     if (npz->data_start != 0x400000L || r_esp > npz->data_start)
  76.     return;
  77.  
  78.     movedmem = npz->membytes - r_esp;    /* memory to move */
  79.     if (r_esp - npz->stack_down < movedmem)    /* enough space? */
  80.     return;
  81.  
  82.     cpy32_32(DS, r_esp, DS, npz->stack_down, movedmem);
  83.  
  84.     if (ResizeMem(npz->stack_down + movedmem, npz->memhandle, &newhandle,
  85.           &newaddress)) {
  86.     printf("error:resize memory block\n");
  87.     return;
  88.     }
  89.     if (npz->memaddress != newaddress) {
  90.     npz->memaddress = newaddress;
  91.     SetBaseAddress(npz->code32sel, npz->memaddress);
  92.     SetBaseAddress(npz->data32sel, npz->memaddress);
  93.     SetBaseAddress(npz->data32sel + sel_incr, npz->memaddress);
  94.     }
  95.     npz->p_flags |= PF_COMPRESS;
  96. }
  97.  
  98. void uncompress_memory(void)
  99. {
  100.     DWORD movedmem, newhandle, newaddress;
  101.     DWORD r_esp = ESP & ~4095L;
  102.  
  103.     /* check djgpp segment, and stack */
  104.     if (npz->data_start != 0x400000L || !(npz->p_flags & PF_COMPRESS))
  105.     return;
  106.  
  107.     if (ResizeMem(npz->membytes, npz->memhandle, &newhandle, &newaddress)) {
  108.     printf("Can't switch to parant process: ENOMEM\n");
  109.     shut_down(1);
  110.     }
  111.     if (npz->memaddress != newaddress) {
  112.     npz->memaddress = newaddress;
  113.     SetBaseAddress(npz->code32sel, npz->memaddress);
  114.     SetBaseAddress(npz->data32sel, npz->memaddress);
  115.     SetBaseAddress(npz->data32sel + sel_incr, npz->memaddress);
  116.     }
  117.     movedmem = npz->membytes - r_esp;    /* memory to move */
  118.     cpy32_32(DS, npz->stack_down, DS, r_esp, movedmem);
  119.     npz->p_flags &= ~PF_COMPRESS;
  120. }
  121.  
  122. void def_extention(char *dst, const char *ext)
  123. {
  124.   int dot, sep;
  125.  
  126.   dot = 0; sep = 1;
  127.   while (*dst != 0)
  128.     switch (*dst++)
  129.       {
  130.       case '.':
  131.     dot = 1;
  132.     sep = 0;
  133.         break;
  134.       case ':':
  135.       case '/':
  136.       case '\\':
  137.     dot = 0;
  138.     sep = 1;
  139.         break;
  140.       default:
  141.     sep = 0;
  142.         break;
  143.       }
  144.   if (!dot && !sep)
  145.     {
  146.       *dst++ = '.';
  147.       strcpy (dst, ext);
  148.     }
  149. }
  150.  
  151. char * search_path(char *file, char *path)
  152. {
  153.     char *list, *end;
  154.     int i;
  155.  
  156.     strcpy(path, file);
  157.     if (access(path, 4) == 0)
  158.     return path;
  159.     list = getenv("PATH");
  160.     if (list != NULL)
  161.     for (;;) {
  162.         while (*list == ' ' || *list == '\t')
  163.         ++list;
  164.         if (*list == 0)
  165.         break;
  166.         end = list;
  167.         while (*end != 0 && *end != ';')
  168.         ++end;
  169.         i = end - list;
  170.         while (i > 0 && (list[i - 1] == ' ' || list[i - 1] == '\t'))
  171.         --i;
  172.         if (i != 0) {
  173.         memcpy(path, list, i);
  174.         if (list[i - 1] != '/' && list[i - 1] != '\\' && list[i - 1] != ':')
  175.             path[i++] = '\\';
  176.         strcpy(path + i, file);
  177.         if (access(path, 4) == 0)
  178.             return path;
  179.         }
  180.         if (*end == 0)
  181.         break;
  182.         list = end + 1;
  183.     }
  184.     path[0] = 0;
  185.     return (char *)0;
  186. }
  187.  
  188. struct time32 {
  189.     DWORD secs, usecs;
  190. };
  191.  
  192. struct tz32 {
  193.     DWORD offset, dst;
  194. };
  195.  
  196. struct stat32 {
  197.     short st_dev, st_ino, st_mode, st_nlink,
  198.     st_uid, st_gid, st_rdev, st_align_for_DWORD;
  199.     long st_size, st_atime, st_mtime, st_ctime, st_blksize;
  200. };
  201.  
  202. int i_21_ff(void)
  203. {
  204.     static int dev_count = 1;
  205.     int r,i;
  206.     DWORD p1 = EBX, p2 = ECX;
  207.  
  208.     switch (AX & 0xff) {    /* al=? */
  209.     case 1:
  210.     strcpy32_16(DS, p1, iobuf);    /* p1 -> iobuf */
  211.     r = creat(iobuf, S_IREAD | S_IWRITE);
  212.     break;
  213.  
  214.     case 2:
  215.     strcpy32_16(DS, p1, iobuf);    /* p1 -> iobuf */
  216.     i = (int) (WORD) p2;
  217. #ifndef __TURBOC__
  218.     i = convert_open_attrib(i);
  219. #endif
  220.     r = open(iobuf, i, S_IREAD | S_IWRITE);
  221.     break;
  222.  
  223.     case 3:            /* fstat */
  224.     {
  225.         struct stat32 statbuf32;
  226.         struct stat statbuf;
  227.  
  228.         memset(&statbuf, 0, sizeof(statbuf));
  229.         if ((r = fstat((int) p1, &statbuf)) == -1)
  230.         break;
  231.         statbuf32.st_dev = dev_count++;
  232.         statbuf32.st_ino = statbuf.st_ino;
  233.         statbuf32.st_mode = statbuf.st_mode;
  234.         statbuf32.st_nlink = statbuf.st_nlink;
  235.         statbuf32.st_uid = statbuf.st_uid;
  236.         statbuf32.st_gid = statbuf.st_gid;
  237.         statbuf32.st_rdev = statbuf.st_rdev;
  238.         statbuf32.st_size = statbuf.st_size;
  239.         statbuf32.st_atime = statbuf.st_atime;
  240.         statbuf32.st_mtime = statbuf.st_mtime;
  241.         statbuf32.st_ctime = statbuf.st_ctime;
  242.         statbuf32.st_blksize = 512;
  243.         /* stat -> p2 */
  244.         cpy16_32(DS, p2, &statbuf32, (DWORD) sizeof(statbuf32));
  245.     }
  246.     break;
  247.  
  248.     case 4:            /* get time & day */
  249.     {
  250.         struct time32 time32;
  251.         struct tz32 tz32;
  252.  
  253.         if (p2) {
  254.         tz32.offset = timezone;
  255.         tz32.dst = (long) daylight;
  256.         /* tz -> p2 */
  257.         cpy16_32(DS, p2, &tz32, (DWORD) sizeof(tz32));
  258.         }
  259.         if (p1) {
  260.         time32.secs = 0;
  261.         time((time_t *) & (time32.secs));
  262.         time32.usecs = 0;
  263.         /* time -> p1 */
  264.         cpy16_32(DS, p1, &time32, (DWORD) sizeof(time32));
  265.         }
  266.         r = 0;
  267.     }
  268.     break;
  269.  
  270.     case 5:            /* set time & day */
  271.     {
  272.         struct time32 time32;
  273.         struct tz32 tz32;
  274.  
  275.         if (p2) {
  276.         /* p2 -> tz */
  277.         cpy32_16(DS, p2, &tz32, (DWORD) sizeof(tz32));
  278.         timezone = tz32.offset;
  279.         daylight = (WORD) tz32.dst;
  280.         }
  281.         if (p1) {
  282.         /* p1 -> time */
  283.         cpy32_16(DS, p1, &time32, (DWORD) sizeof(time32));
  284.         stime((time_t *) & (time32.secs));
  285.         }
  286.         r = 0;
  287.     }
  288.     break;
  289.  
  290.     case 6:            /* stat */
  291.     {
  292.         struct stat32 statbuf32;
  293.         struct stat statbuf;
  294.         char fname[128];
  295.  
  296.         memset(&statbuf, 0, sizeof(statbuf));
  297.         strcpy32_16(DS, p1, fname);
  298.  
  299.         r = unixlike_stat(fname, &statbuf);
  300.  
  301.         statbuf32.st_dev = dev_count++;
  302.         statbuf32.st_ino = statbuf.st_ino;
  303.         statbuf32.st_mode = statbuf.st_mode;
  304.         statbuf32.st_nlink = statbuf.st_nlink;
  305.         statbuf32.st_uid = statbuf.st_uid;
  306.         statbuf32.st_gid = statbuf.st_gid;
  307.         statbuf32.st_rdev = statbuf.st_rdev;
  308.         statbuf32.st_size = statbuf.st_size;
  309.         statbuf32.st_atime = statbuf.st_atime;
  310.         statbuf32.st_mtime = statbuf.st_mtime;
  311.         statbuf32.st_ctime = statbuf.st_ctime;
  312.         statbuf32.st_blksize = 512;
  313.         /* stat -> p2 */
  314.         cpy16_32(DS, p2, &statbuf32, (DWORD) sizeof(statbuf32));
  315.     }
  316.     break;
  317.  
  318.     case 7:
  319.     {
  320.         char *argmem;
  321.         char **argp;
  322.         char exe[260];
  323.         int args;
  324.  
  325.         argmem = (char *) malloc(1000);
  326.         argp = (char **) malloc(100);
  327.         if (argmem == NULL || argp == NULL) {
  328.         if (argmem != NULL)
  329.             free(argmem);
  330.         EAX = EMX_ENOMEM;
  331.         return CARRY_ON;
  332.         }
  333.         strcpy32_16(DS, p1, argmem);
  334.  
  335.         /* make strings from cmdline ; build argv */
  336.         argp[0] = argmem;
  337.         args = 1;
  338.         for (i = 0; *(argmem + i) != 0; i++)
  339.         if (*(argmem + i) == ' ') {
  340.             *(argmem + i) = 0;
  341.             if (*(argmem + i + 1) == ' ')
  342.             continue;
  343.             if (*(argmem + i + 1) == 0)
  344.             break;
  345.             argp[args++] = (argmem + i + 1);
  346.         }
  347.         argp[args] = 0;
  348.  
  349.         /* check last argument, response file? */
  350.         if (argp[args - 1][0] == '@') {
  351.         FILE *f;
  352.         char buf[80];
  353.         char *s = &argmem[i + 2];
  354.  
  355.         args--;
  356.         f = fopen(argp[args] + 1, "rt");
  357.  
  358.         while (fscan_q(f, buf) == 1) {
  359.             if (!strcmp(buf, "\032"))
  360.             continue;
  361.             strcpy(s, buf);
  362.             argp[args++] = s;
  363.             s += strlen(buf) + 1;
  364.         }
  365.         fclose(f);
  366.         argp[args] = 0;
  367.         }
  368.         if (access(argmem, 0))
  369.         if (!search_path(argmem, exe)) {
  370.             EAX = EMX_ENOENT;
  371.             free(argmem);
  372.             free(argp);
  373.             return CARRY_ON;
  374.         }
  375.         else {
  376.             argp[0] = exe;
  377.         }
  378.         /* resize memory to the real used page */
  379.         if (npz->entry == 0x1020L)
  380.         compress_memory();
  381.  
  382.         r = exec32(P_WAIT, argp[0], args, argp, org_envc, org_env);
  383.  
  384.         /* if error, try a real-mode prg */
  385.         if (r == EMX_ENOEXEC) {
  386.         r = realmode_prg(argmem, &(argp[0]), org_env);
  387.         uncompress_memory();    /* we switch back to father process */
  388.         }
  389.         if (r) {
  390.         errno = r;
  391.         r = -1;
  392.         }
  393.         free(argmem);
  394.         free(argp);
  395.     }
  396.     break;
  397.  
  398.     case 8:
  399.     /* ioctl: get mode */
  400.     tr.eax = 0x4400;
  401.     tr.ebx = p1;
  402.     realdos();
  403.     i = (WORD) tr.edx;
  404.         if (p2 & 0x8000)    /* O_BINARY */
  405.         i |= 0x20;
  406.     else
  407.         i &= ~0x20;
  408.     /* ioctl: set mode */
  409.     tr.eax = 0x4401;
  410.     tr.ebx = p1;
  411.     tr.edx = (DWORD) i;
  412.     realdos();
  413.         r = setmode((int) p1, (int) p2);
  414.     break;
  415.  
  416.     case 9:
  417.     strcpy32_16(DS, p1, iobuf);    /* p1 -> iobuf */
  418.         r = chmod(iobuf, (int) p2);
  419.     break;
  420.  
  421.     default:
  422.     r = -1;
  423.     break;
  424.     }                /* switch */
  425.  
  426.     if (r == -1) {
  427. #ifdef __TURBOC__
  428.     EAX = (DWORD) doserror_to_errno(_doserrno);
  429. #else
  430.     EAX = errno;
  431. #endif
  432.     return CARRY_ON;
  433.     } else {
  434.     EAX = (DWORD) r;
  435.     return CARRY_OFF;
  436.     }
  437. }
  438.  
  439. static int fscan_q(FILE * f, char *buf)
  440. {
  441.     char *ibuf = buf;
  442.     int c, quote = -1, gotsome = 0, addquote = 0;
  443.     while ((c = fgetc(f)) != EOF) {
  444.     if (c == '\\') {
  445.         char c2 = (char) fgetc(f);
  446.         if (!strchr("\"'`\\ \t\n\r", c2))
  447.         *buf++ = (char) c;
  448.         *buf++ = c2;
  449.         addquote = 0;
  450.     } else if (c == quote) {
  451.         quote = -1;
  452.         if (c == '\'')
  453.         addquote = 1;
  454.     } else if (isspace(c) && (quote == -1)) {
  455.         if (gotsome) {
  456.         if (addquote)
  457.             *buf++ = '\'';
  458.         *buf = 0;
  459.         return 1;
  460.         }
  461.         addquote = 0;
  462.     } else {
  463.         if ((quote == -1) && ((c == '"') || (c == '\''))) {
  464.         quote = c;
  465.         gotsome = 1;
  466.         if ((c == '\'') && (buf == ibuf))
  467.             *buf++ = (char) c;
  468.         } else {
  469.         *buf++ = (char) c;
  470.         gotsome = 1;
  471.         }
  472.         addquote = 0;
  473.     }
  474.     }
  475.     return 0;
  476. }
  477.  
  478. /*
  479.  * An improved version of stat(). This version ensures that "." and ".."
  480.  * appear to exist in all directories, including Novell network drives, and
  481.  * that the root directory also returns the correct result.
  482.  *
  483.  * This function replaces any \'s with /'s in the input string, it should
  484.  * really take a copy of the string first, but this isn't necessary for go32
  485.  * which uses a transfer buffer between the program and the DOS extender
  486.  * anyway.
  487.  *
  488.  * Chris Boucher ccb@southampton.ac.uk
  489.  */
  490.  
  491.  
  492. /*
  493.  * I found the following function on SIMTEL20, it dates back to 1987 but
  494.  * there's no mention of who the author was. I've modified/fixed it quite
  495.  * a bit. It neatly avoids any problems with "." and ".." on Novell networks.
  496.  */
  497. static int rootpath(const char *relpath, char *fullpath);
  498.  
  499.  
  500. int unixlike_stat(char *name, struct stat * buf)
  501. {
  502.     static char path[2 * MAXPATH];
  503.     char *s = name;
  504.     int len;
  505.  
  506.     /* First off, try the standard stat(), if that works then all is well. */
  507.     if (stat(name, buf) == 0) {
  508.     return 0;
  509.     }
  510.     /* Swap all \'s for /'s. */
  511.     while (*s) {
  512.     if (*s == '\\')
  513.         *s = '/';
  514.     s++;
  515.     }
  516.  
  517.     /* Convert path name into root based cannonical form. */
  518.     if (rootpath(name, path) != 0) {
  519.     return -1;
  520.     }
  521.     /* DOS doesn't stat "/" correctly, so fake it here. */
  522.     if (strcmp(path + 1, ":/") == 0
  523.     || strcmp(path + 1, ":") == 0) {
  524.     buf->st_dev = 0;
  525.     buf->st_ino = 0;
  526.     buf->st_mode = S_IREAD | S_IWRITE | S_IFDIR;
  527.     buf->st_uid = buf->st_gid = 0;
  528.     buf->st_nlink = 1;
  529.     buf->st_rdev = 0;
  530.     buf->st_size = 0;
  531.     buf->st_atime = buf->st_mtime = buf->st_ctime = 0;
  532.     return 0;
  533.     }
  534.     /* Now modify the string so that "dir/" works. */
  535.     len = strlen(path);
  536.     if (path[len - 1] == '/')
  537.     path[len - 1] = '\0';
  538.     return stat(path, buf);
  539. }
  540.  
  541.  
  542. /*
  543.  * rootpath  --  convert a pathname argument to root based cannonical form.
  544.  *
  545.  * rootpath determines the current directory, appends the path argument (which
  546.  * may affect which disk the current directory is relative to), and qualifies
  547.  * "." and ".." references.  The result is a complete, simple, path name with
  548.  * drive specifier.
  549.  *
  550.  * If the relative path the user specifies does not include a drive spec., the
  551.  * default drive will be used as the base.  (The default drive will never be
  552.  * changed.)
  553.  *
  554.  *  entry: relpath  -- pointer to the pathname to be expanded
  555.  *         fullpath -- must point to a working buffer, see warning
  556.  *   exit: fullpath -- the full path which results
  557.  * return: -1 if an error occurs, 0 otherwise
  558.  *
  559.  * warning: fullpath must point to a working buffer large enough to hold the
  560.  *          longest possible relative path argument plus the longest possible
  561.  *          current directory path.
  562.  */
  563. static int rootpath(const char *relpath, char *fullpath)
  564. {
  565.     register char *lead, *follow, *s;
  566.     char tempchar;
  567.     int drivenum;
  568.  
  569.     /* Extract drive spec. */
  570.     if ((*relpath != '\0') && (relpath[1] == ':')) {
  571.     drivenum = toupper(*relpath) - 'A';
  572.     relpath += 2;
  573.     } else {
  574.     drivenum = _getdrive();
  575.     }
  576.  
  577.     /* Fill in the drive path. */
  578.     strcpy(fullpath, " :/");
  579.     fullpath[0] = (char) (drivenum + 'A');
  580.  
  581. #ifdef __TURBOC__
  582.     /* Get cwd for drive - also checks that drive exists. */
  583.     if (getcurdir(drivenum + 1, fullpath + 3) == -1) {
  584.     return -1;        /* No such drive - give up. */
  585.     }
  586. #else
  587.     if (!_getdcwd(drivenum +1 , fullpath + 3, _MAX_PATH))
  588.     return -1;
  589. #endif
  590.  
  591.     /* Swap all \'s for /'s. */
  592.     s = fullpath;
  593.     while (*s) {
  594.     if (*s == '\\')
  595.         *s = '/';
  596.     s++;
  597.     }
  598.  
  599.     /* Append relpath to fullpath/base. */
  600.     if (*relpath == '/') {    /* relpath starts at base... */
  601.     strcpy(fullpath + 2, relpath);    /* ...so ignore cwd. */
  602.     } else {            /* relpath is relative to cwd. */
  603.     if (*relpath != '\0') {
  604.         if (strlen(fullpath) > 3) {
  605.         strcat(fullpath, "/");    /* Add a '/' to end of cwd. */
  606.         }
  607.         strcat(fullpath, relpath);    /* Add relpath to end of cwd. */
  608.     }
  609.     }
  610.  
  611.     /* Convert path to cannonical form. */
  612.     lead = fullpath;
  613.     while (*lead != '\0') {
  614.     /* Mark next path segment. */
  615.     follow = lead;
  616.     lead = (char *) strchr(follow + 1, '/');
  617.     if (lead == 0) {
  618.         lead = fullpath + strlen(fullpath);
  619.     }
  620.     tempchar = *lead;
  621.     *lead = '\0';
  622.  
  623.     /* "." segment? */
  624.     if (strcmp(follow + 1, ".") == 0) {
  625.         *lead = tempchar;
  626.         strcpy(follow, lead);    /* Remove "." segment. */
  627.         lead = follow;
  628.     }
  629.     /* ".." segment? */
  630.     else if (strcmp(follow + 1, "..") == 0) {
  631.         *lead = tempchar;
  632.         do {
  633.         if (--follow < fullpath) {
  634.             follow = fullpath + 2;
  635.             break;
  636.         }
  637.         } while (*follow != '/');
  638.         strcpy(follow, lead);    /* Remove ".." segment. */
  639.         lead = follow;
  640.     }
  641.     /* Normal segment. */
  642.     else {
  643.         *lead = tempchar;
  644.     }
  645.     }
  646.  
  647.     if (strlen(fullpath) == 2) {/* 'D:' or some such. */
  648.     strcat(fullpath, "/");
  649.     }
  650.     /* All done. */
  651.     return 0;
  652. }
  653.