home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / libsrc / c / dos / exec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-05  |  11.4 KB  |  505 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <strings.h>
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <go32.h>
  7. #include <dpmi.h>
  8. #include "process.h"
  9.  
  10. #define environ ((const char **)environ)
  11.  
  12. #define scan_ptr() \
  13.     char const **ptr; \
  14.     for (ptr = &argv0; *ptr; ptr++); \
  15.     ptr = (char const **)(*++ptr);
  16.  
  17. int execl(const char *path, const char *argv0, ...)
  18. {
  19.   return spawnve(P_OVERLAY, path, &argv0, environ);
  20. }
  21.  
  22. int execle(const char *path, const char *argv0, ... /*, const char **envp */)
  23. {
  24.   scan_ptr();
  25.   return spawnve(P_OVERLAY, path, &argv0, ptr);
  26. }
  27.  
  28. int execlp(const char *path, const char *argv0, ...)
  29. {
  30.   return spawnvpe(P_OVERLAY, path, &argv0, environ);
  31. }
  32.  
  33. int execlpe(const char *path, const char *argv0, ... /*, const char **envp */)
  34. {
  35.   scan_ptr();
  36.   return spawnvpe(P_OVERLAY, path, &argv0, ptr);
  37. }
  38.  
  39. /*-------------------------------------------------*/
  40.  
  41. int execv(const char *path, const char **argv)
  42. {
  43.   return spawnve(P_OVERLAY, path, argv, environ);
  44. }
  45.  
  46. int execve(const char *path, const char **argv, const char **envp)
  47. {
  48.   return spawnve(P_OVERLAY, path, argv, envp);
  49. }
  50.  
  51. int execvp(const char *path, const char **argv)
  52. {
  53.   return spawnvpe(P_OVERLAY, path, argv, environ);
  54. }
  55.  
  56. int execvpe(const char *path, const char **argv, const char **envp)
  57. {
  58.   return spawnvpe(P_OVERLAY, path, argv, envp);
  59. }
  60.  
  61. /*-------------------------------------------------*/
  62.  
  63. int spawnl(int mode, const char *path, const char *argv0, ...)
  64. {
  65.   return spawnve(mode, path, &argv0, environ);
  66. }
  67.  
  68. int spawnle(int mode, const char *path, const char *argv0, ... /*, const char **envp */)
  69. {
  70.   scan_ptr();
  71.   return spawnve(mode, path, &argv0, ptr);
  72. }
  73.  
  74. int spawnlp(int mode, const char *path, const char *argv0, ...)
  75. {
  76.   return spawnvpe(mode, path, &argv0, environ);
  77. }
  78.  
  79. int spawnlpe(int mode, const char *path, const char *argv0, ... /*, const char **envp */)
  80. {
  81.   scan_ptr();
  82.   return spawnvpe(mode, path, &argv0, ptr);
  83. }
  84.  
  85. /*-------------------------------------------------*/
  86.  
  87. typedef struct {
  88.   u_short eseg;
  89.   u_short argoff;
  90.   u_short argseg;
  91.   u_short fcb1_off;
  92.   u_short fcb1_seg;
  93.   u_short fcb2_off;
  94.   u_short fcb2_seg;
  95. } Execp;
  96.  
  97. static Execp parm;
  98.  
  99. static u_long tbuf;
  100.  
  101. static u_long talloc(size_t amt)
  102. {
  103.   u_long rv = tbuf;
  104.   tbuf += amt;
  105.   return rv;
  106. }
  107.  
  108. static int direct_exec_tail(const char *program, const char *args, const char **envp)
  109. {
  110.   _go32_dpmi_registers r;
  111.   u_long program_la;
  112.   u_long arg_la;
  113.   u_long parm_la;
  114.   u_long env_la, env_e_la;
  115.   char arg_header[3];
  116.   int i;
  117.  
  118.   program_la = talloc(strlen(program)+1);
  119.   arg_la = talloc(strlen(args)+3);
  120.   parm_la = talloc(sizeof(Execp));
  121.  
  122.   dosmemput(program, strlen(program)+1, program_la);
  123.   
  124.   arg_header[0] = strlen(args);
  125.   arg_header[1] = '\r';
  126.   dosmemput(arg_header, 1, arg_la);
  127.   dosmemput(args, strlen(args), arg_la+1);
  128.   dosmemput(arg_header+1, 1, arg_la+1+strlen(args));
  129.  
  130.   do {
  131.     env_la = talloc(1);
  132.   } while (env_la & 15);
  133.   talloc(-1);
  134.   for (i=0; envp[i]; i++)
  135.   {
  136.     env_e_la = talloc(strlen(envp[i])+1);
  137.     dosmemput(envp[i], strlen(envp[i])+1, env_e_la);
  138.   }
  139.   arg_header[0] = 0;
  140.   arg_header[1] = 1;
  141.   arg_header[2] = 0;
  142.   dosmemput(arg_header, 3, talloc(3));
  143.   env_e_la = talloc(strlen(program)+1);
  144.   dosmemput(program, strlen(program)+1, env_e_la);
  145.  
  146.   parm.eseg = env_la / 16;
  147.   parm.argseg = arg_la / 16;
  148.   parm.argoff = arg_la & 15;
  149.   dosmemput(&parm, sizeof(parm), parm_la);
  150.  
  151.   memset(&r, 0, sizeof(r));
  152.   r.x.ax = 0x4b00;
  153.   r.x.ds = program_la / 16;
  154.   r.x.dx = program_la & 15;
  155.   r.x.es = parm_la / 16;
  156.   r.x.bx = parm_la & 15;
  157.   _go32_dpmi_simulate_int(0x21, &r);
  158.   if (r.x.flags & 1)
  159.   {
  160.     errno = r.x.ax;
  161.     return -1;
  162.   }
  163.   
  164.   memset(&r, 0, sizeof(r));
  165.   r.h.ah = 0x4d;
  166.   _go32_dpmi_simulate_int(0x21, &r);
  167.   
  168.   if (r.x.flags & 1)
  169.   {
  170.     errno = r.x.ax;
  171.     return -1;
  172.   }
  173.   return r.x.ax;
  174. }
  175.  
  176. static int direct_exec(const char *program, const char **argv, const char **envp)
  177. {
  178.   int i, arglen;
  179.   char *args, *argp;
  180.  
  181.   tbuf = _go32_info_block.linear_address_of_transfer_buffer;
  182.  
  183.   arglen = 0;
  184.   for (i=1; argv[i]; i++)
  185.     arglen += strlen(argv[i]) + 1;
  186.   args = (char *)malloc(arglen+1);
  187.   argp = args;
  188.   for (i=1; argv[i]; i++)
  189.   {
  190.     const char *p = argv[i];
  191.     if (argp - args > 125)
  192.       break;
  193.     *argp++ = ' ';
  194.     while (*p)
  195.     {
  196.       if (argp - args > 125)
  197.         break;
  198.       *argp++ = *p++;
  199.     }
  200.   }
  201.   *argp = 0;
  202.   
  203.   return direct_exec_tail(program, args, envp);
  204. }
  205.  
  206. typedef struct {
  207.   char magic[16];
  208.   int struct_length;
  209.   char go32[16];
  210. } StubInfo;
  211. #define STUB_INFO_MAGIC "StubInfoMagic!!"
  212.  
  213. static int go32_exec(const char *program, const char **argv, const char **envp)
  214. {
  215.   int is_stubbed = 0;
  216.   int found_si = 0;
  217.   StubInfo si;
  218.   unsigned short header[3];
  219.   int pf, has_dot, i;
  220.   char *go32, *sip;
  221.   const char *pp, *pe;
  222.   char rpath[80], *rp;
  223.   int stub_offset, argc;
  224.  
  225.   int si_la, rm_la, rm_seg;
  226.   short *rm_argv;
  227.   char cmdline[34];
  228.   
  229.   pf = open(program, O_RDONLY|O_BINARY);
  230.  
  231.   read(pf, header, sizeof(header));
  232.   if (header[0] == 0x010b || header[0] == 0x014c)
  233.   {
  234.     is_stubbed = 1;
  235.   }
  236.   else if (header[0] == 0x5a4d)
  237.   {
  238.     int header_offset = (long)header[2]*512L;
  239.     if (header[1])
  240.       header_offset += (long)header[1] - 512L;
  241.     lseek(pf, header_offset - 4, 0);
  242.     read(pf, &stub_offset, 4);
  243.     header[0] = 0;
  244.     read(pf, header, sizeof(header));
  245.     if (header[0] == 0x010b)
  246.       is_stubbed = 1;
  247.     if (header[0] == 0x014c)
  248.       is_stubbed = 1;
  249.     lseek(pf, stub_offset, 0);
  250.     read(pf, &si, sizeof(si));
  251.     if (memcmp(STUB_INFO_MAGIC, si.magic, 16) == 0)
  252.       found_si = 1;
  253.   }
  254.   if (!is_stubbed)
  255.   {
  256.     close(pf);
  257.     return direct_exec(program, argv, envp);
  258.   }
  259.  
  260.   if (found_si)
  261.     go32 = si.go32;
  262.   else
  263.     go32 = "go32.exe";
  264.   has_dot = 0;
  265.   for (i=0; go32[i]; i++)
  266.     if (go32[i] == '.')
  267.       has_dot = 1;
  268.   if (!has_dot)
  269.     strcpy(go32+i, ".exe");
  270.   for (i=0; envp[i]; i++)
  271.     if (strncmp(envp[i], "PATH=", 5) == 0)
  272.       pp = envp[i]+5;
  273.   strcpy(rpath, go32);
  274.   while (access(rpath, 0))
  275.   {
  276.     char *ptr;
  277.     rp = rpath;
  278.     for (pe=pp; *pe && *pe != ';'; pe++)
  279.       *rp++ = *pe;
  280.     pp = pe+1;
  281.     if (rp > rpath && rp[-1] != '/' && rp[-1] != '\\' && rp[-1] != ':')
  282.       *rp++ = '/';
  283.     for (ptr = go32; *ptr; ptr++)
  284.       *rp++ = *ptr;
  285.     *rp = 0;
  286.     if (access(rpath, 0) == 0)
  287.       break;
  288.     if (*pe == 0)
  289.       return direct_exec(program, argv, envp); /* give up and just run it */
  290.   }
  291.  
  292.   if (found_si)
  293.   {  
  294.     lseek(pf, stub_offset, 0);
  295.     sip = (char *)malloc(si.struct_length);
  296.     read(pf, sip, si.struct_length);
  297.   }
  298.   close(pf);
  299.  
  300.   argv[0] = program; /* since that's where we really found it */
  301.  
  302.   tbuf = _go32_info_block.linear_address_of_transfer_buffer;
  303.  
  304.   if (found_si)
  305.   {
  306.     si_la = talloc(si.struct_length);
  307.     dosmemput(sip, si.struct_length, si_la);
  308.     free(sip);
  309.   }
  310.   
  311.   for (argc=0; argv[argc]; argc++);
  312.   rm_la = talloc(2*(argc+1));
  313.   rm_seg = (_go32_info_block.linear_address_of_transfer_buffer >> 4) & 0xffff;
  314.   rm_argv = (short *)malloc((argc+1) * sizeof(short));
  315.   for (i=0; i<argc; i++)
  316.   {
  317.     int sl = strlen(argv[i]) + 1;
  318.     int q = talloc(sl);
  319.     dosmemput(argv[i], sl, q);
  320.     rm_argv[i] = (q - (rm_seg<<4)) & 0xffff;
  321.   }
  322.   rm_argv[i] = 0;
  323.   dosmemput(rm_argv, 2*(argc+1), rm_la);
  324.   
  325.   sprintf(cmdline, " !proxy %04x %04x %04x %04x %04x",
  326.     argc, rm_seg, (rm_la - (rm_seg<<4))&0xffff,
  327.     rm_seg, (si_la - (rm_seg<<4))&0xffff);
  328.   if (!found_si)
  329.     cmdline[22] = 0; /* remove stub information */
  330.  
  331.   return direct_exec_tail(rpath, cmdline, envp);
  332. }
  333.  
  334. static int command_exec(const char *program, const char **argv, const char **envp)
  335. {
  336.   const char *comspec=0;
  337.   char *cmdline;
  338.   char *newargs[3];
  339.   int cmdlen;
  340.   int i;
  341.   
  342.   cmdlen = strlen(program) + 4;
  343.   for (i=0; argv[i]; i++)
  344.     cmdlen += strlen(argv[i]) + 1;
  345.   cmdline = (char *)malloc(cmdlen);
  346.   
  347.   strcpy(cmdline, "/c ");
  348.   for (i=0; program[i]; i++)
  349.   {
  350.     if (program[i] == '/')
  351.       cmdline[i+3] = '\\';
  352.     else
  353.       cmdline[i+3] = program[i];
  354.   }
  355.   cmdline[i+3] = 0;
  356.   for (i=1; argv[i]; i++)
  357.   {
  358.     strcat(cmdline, " ");
  359.     strcat(cmdline, argv[i]);
  360.   }
  361.   for (i=0; envp[i]; i++)
  362.     if (strncmp(envp[i], "COMSPEC=", 8) == 0)
  363.       comspec = envp[i]+8;
  364.   if (!comspec)
  365.     for (i=0; environ[i]; i++)
  366.       if (strncmp(environ[i], "COMSPEC=", 8) == 0)
  367.         comspec = environ[i]+8;
  368.   if (!comspec)
  369.     comspec = "c:/command.com";
  370.   newargs[0] = comspec;
  371.   newargs[1] = cmdline;
  372.   newargs[2] = 0;
  373.   i = direct_exec(comspec, (const char **)newargs, envp);
  374.   free(cmdline);
  375.   return i;
  376. }
  377.  
  378. static int script_exec(const char *program, const char **argv, const char **envp)
  379. {
  380.   return go32_exec(program, argv, envp);
  381. }
  382.  
  383. static struct {
  384.   char *extension;
  385.   int (*interp)(const char *, const char **, const char **);
  386. } interpreters[] = {
  387.   { ".com", direct_exec },
  388.   { ".exe", go32_exec },
  389.   { ".bat", command_exec },
  390.   { 0,      script_exec }
  391. };
  392. #define INTERP_NO_EXT 3
  393.  
  394. int spawnv(int mode, const char *path, const char **argv)
  395. {
  396.   return spawnve(mode, path, argv, environ);
  397. }
  398.  
  399. int spawnve(int mode, const char *path, const char **argv, const char **envp)
  400. {
  401.   /* This is the one that does the work! */
  402.   int i = -1;
  403.   char rpath[80], *rp, *rd=0;
  404.   fflush(stdout); /* just in case */
  405.   for (rp=rpath; *path; *rp++ = *path++)
  406.   {
  407.     if (*path == '.')
  408.       rd = rp;
  409.     if (*path == '\\' || *path == '/')
  410.       rd = 0;
  411.   }
  412.   *rp = 0;
  413.   if (rd)
  414.   {
  415.     for (i=0; interpreters[i].extension; i++)
  416.       if (stricmp(rd, interpreters[i].extension) == 0)
  417.         break;
  418.   }
  419.   while (access(rpath, 0))
  420.   {
  421.     i++;
  422.     if (interpreters[i].extension == 0 || rd)
  423.     {
  424.       errno = ENOENT;
  425.       return -1;
  426.     }
  427.     strcpy(rp, interpreters[i].extension);
  428.   }
  429.   if (i == -1)
  430.     i = INTERP_NO_EXT;
  431.   i = interpreters[i].interp(rpath, argv, envp);
  432.   if (mode == P_OVERLAY)
  433.     exit(i);
  434.   return i;
  435. }
  436.  
  437. int spawnvp(int mode, const char *path, const char **argv)
  438. {
  439.   return spawnvpe(mode, path, argv, environ);
  440. }
  441.  
  442. int spawnvpe(int mode, const char *path, const char **argv, const char **envp)
  443. {
  444.   const char *pp, *pe, *ptr;
  445.   char rpath[80], *rp, *rd;
  446.   int hasdot = 0, i, tried_dot = 0;
  447.  
  448.   for (ptr=path; *ptr; ptr++)
  449.   {
  450.     if (*ptr == '.')
  451.       hasdot = 1;
  452.     if (*ptr == '/' || *ptr == '\\' || *ptr == ':')
  453.       return spawnve(mode, path, argv, envp);
  454.   }
  455.  
  456.   pp = 0;
  457.   for (i=0; envp[i]; i++)
  458.     if (strncmp(envp[i], "PATH=", 5) == 0)
  459.       pp = envp[i] + 5;
  460.   if (pp == 0)
  461.     return spawnve(mode, path, argv, envp);
  462.  
  463.   while (1)
  464.   {
  465.     if (!tried_dot)
  466.     {
  467.       rp = rpath;
  468.       pe = pp;
  469.       tried_dot = 1;
  470.     }
  471.     else
  472.     {
  473.       rp = rpath;
  474.       for (pe = pp; *pe && *pe != ';'; pe++)
  475.         *rp++ = *pe;
  476.       pp = pe+1;
  477.       if (rp > rpath && rp[-1] != '/' && rp[-1] != '\\' && rp[-1] != ':')
  478.         *rp++ = '/';
  479.     }
  480.     for (ptr = path; *ptr; ptr++)
  481.       *rp++ = *ptr;
  482.     *rp = 0;
  483.     
  484.     if (hasdot)
  485.     {
  486.       if (access(rpath, 0) == 0)
  487.         return spawnve(mode, rpath, argv, envp);
  488.     }
  489.     else
  490.     {
  491.       for (i=0; interpreters[i].extension; i++)
  492.       {
  493.         strcpy(rp, interpreters[i].extension);
  494.         if (access(rpath, 0) == 0)
  495.           return spawnve(mode, rpath, argv, envp);
  496.       }
  497.     }
  498.     if (*pe == 0)
  499.     {
  500.       errno = ENOENT;
  501.       return -1;
  502.     }
  503.   }
  504. }
  505.