home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / gnu / djgpp / libsrc / c / dos / exec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-27  |  11.4 KB  |  503 lines

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