home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / os2exec1.zip / OS2EXECD.C < prev    next >
C/C++ Source or Header  |  1993-12-07  |  11KB  |  381 lines

  1. /* os2execd.c */
  2.  
  3. /* Copyright (c) 1992-1993 by Eberhard Mattes */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <direct.h>
  9. #include <process.h>
  10. #define INCL_DOSMISC
  11. #define INCL_DOSNMPIPES
  12. #define INCL_DOSPROCESS
  13. #define INCL_DOSQUEUES
  14. #define INCL_WINWINDOWMGR
  15. #define INCL_WINSWITCHLIST
  16. #include <os2.h>
  17.  
  18. #define FALSE 0
  19. #define TRUE  1
  20.  
  21. typedef unsigned char byte;
  22.  
  23. static byte buf[4096];
  24. static CHAR args[4096+256];
  25. static CHAR prog_buf[256];
  26. static PCHAR org_env;
  27. static PCHAR new_env;
  28. static HPIPE hp;
  29.  
  30. static USHORT org_env_size;
  31. static USHORT new_env_size;
  32. static USHORT new_env_alloc;
  33.  
  34. static void send (byte cmd, byte *src, int len);
  35. static void out_of_mem (void);
  36. int main (int argc, char *argv[]);
  37.  
  38.  
  39. static void out_of_mem (void)
  40. {
  41.   fprintf (stderr, "Out of memory\n");
  42.   exit (2);
  43. }
  44.  
  45.  
  46. static void send (byte cmd, byte *src, int len)
  47. {
  48.   USHORT rc, cb;
  49.  
  50.   buf[0] = (byte)((len + 1) % 256);
  51.   buf[1] = (byte)((len + 1) / 256);
  52.   buf[2] = cmd;
  53.   memmove (buf+3, src, len);
  54.   rc = DosWrite (hp, buf, len+3, &cb);
  55.   if (rc != 0)
  56.     {
  57.       fprintf (stderr, "DosWrite: rc=%hu\n", rc);
  58.       exit (2);
  59.     }
  60. }
  61.  
  62.  
  63. static void no_inherit (HFILE hf)
  64. {
  65.   USHORT state;
  66.  
  67.   if (DosQFHandState (hf, &state) == 0)
  68.     DosSetFHandState (hf, state | OPEN_FLAGS_NOINHERIT);
  69. }
  70.  
  71.  
  72. int main (int argc, char *argv[])
  73. {
  74.   USHORT rc, cb;
  75.   byte header[2], result[12], *p, *q;
  76.   int sys_rc, drive, i, len, verbose, def_sw, cur_sw, quit, output;
  77.   CHAR failname[256], *shell, *prog;
  78.   RESULTCODES results;
  79.   SEL env_sel;
  80.   USHORT cmd_off;
  81.   HWND hwndActive;
  82.   HFILE saved_stdout, saved_stderr, pipe_read, pipe_write, hf;
  83.   PID pid;
  84.  
  85.   puts ("os2execd -- Version 1.1b -- Copyright (c) 1992-1993 by Eberhard Mattes");
  86.   verbose = FALSE; def_sw = FALSE; quit = FALSE;
  87.   for (i = 1; i < argc; ++i)
  88.     if (strcmp (argv[i], "-v") == 0)
  89.       verbose = TRUE;
  90.     else if (strcmp (argv[i], "-s") == 0)
  91.       def_sw = TRUE;
  92.     else
  93.       {
  94.         fprintf (stderr, "Usage: os2execd [-s] [-v]\n\n");
  95.         fprintf (stderr, "  -s  Switch windows\n");
  96.         fprintf (stderr, "  -v  Verbose\n");
  97.         return (2);
  98.       }
  99.   shell = getenv ("COMSPEC");
  100.   if (shell == NULL)
  101.     shell = "cmd.exe";
  102.   if (DosGetEnv (&env_sel, &cmd_off) != 0)
  103.     {
  104.       fprintf (stderr, "DosGetEnv failed\n");
  105.       return (2);
  106.     }
  107.   org_env = MAKEP (env_sel, 0);
  108.   org_env_size = 0;
  109.   while (org_env[org_env_size++] != 0)
  110.     while (org_env[org_env_size++] != 0)
  111.       ;
  112.   new_env_size = new_env_alloc = org_env_size;
  113.   new_env = malloc (new_env_alloc);
  114.   if (new_env == NULL) out_of_mem ();
  115.   memmove (new_env, org_env, org_env_size);
  116.   rc = DosMakeNmPipe ("/pipe/os2exec.em", &hp,
  117.                       NP_ACCESS_DUPLEX | NP_NOINHERIT,
  118.                       NP_WAIT | NP_READMODE_BYTE | NP_TYPE_BYTE
  119.                       | NP_UNLIMITED_INSTANCES,
  120.                       4096, 4096, 0L);
  121.   if (rc != 0)
  122.     {
  123.       fprintf (stderr, "DosMakeNmPipe: rc=%hu\n", rc);
  124.       return (2);
  125.     }
  126. new:
  127.   rc = DosConnectNmPipe (hp);
  128.   if (rc != 0)
  129.     {
  130.       fprintf (stderr, "DosConnectNmPipe: rc=%hu\n", rc);
  131.       return (2);
  132.     }
  133.   if (verbose)
  134.     fprintf (stderr, "--- Connected\n");
  135.   cur_sw = def_sw; output = FALSE;
  136.   for (;;)
  137.     {
  138.       rc = DosRead (hp, header, sizeof (header), &cb);
  139.       if (rc != 0)
  140.         {
  141.           fprintf (stderr, "DosRead: rc=%hu\n", rc);
  142.           return (2);
  143.         }
  144.       if (cb != 2)
  145.         break;
  146.       rc = DosRead (hp, buf, header[0] + 256 * header[1], &cb);
  147.       if (rc != 0)
  148.         {
  149.           fprintf (stderr, "DosRead: rc=%hu\n", rc);
  150.           return (2);
  151.         }
  152.       if (cb == 0)
  153.         break;
  154.       buf[cb] = 0;
  155.       if (verbose)
  156.         {
  157.           fprintf (stderr, "--- Message: <");
  158.           fwrite (buf, cb, 1, stderr);
  159.           fprintf (stderr, ">\n");
  160.         }
  161.       switch (buf[0])
  162.         {
  163.         case 'A':       /* Return code acknowledgement */
  164.           if (verbose)
  165.             fprintf (stderr, "--- Return code acknowledged\n");
  166.           goto done;
  167.  
  168.         case 'C':       /* Command: CMD.EXE */
  169.         case 'X':       /* Command: DosExecPgm */
  170.           if (verbose)
  171.             fprintf (stderr, "--- Command: %s\n", buf+1);
  172.           if (cur_sw)
  173.             {
  174.               hwndActive = WinQueryActiveWindow (HWND_DESKTOP, FALSE);
  175.               WinSwitchToProgram (WinQuerySwitchHandle (0, getpid ()));
  176.             }
  177.           if (buf[0] == 'C')
  178.             {
  179.               prog = shell;
  180.               p = args;
  181.               strcpy (p, shell); p = strchr (p, 0) + 1;
  182.               strcpy (p, "/c ");
  183.               strcat (p, buf+1); p = strchr (p, 0) + 1;
  184.               *p = 0;
  185.             }
  186.           else
  187.             {
  188.               q = buf + 1;
  189.               while (*q == ' ' || *q == '\t')
  190.                 ++q;
  191.               for (i = 0; i < sizeof (prog_buf) - 5; ++i)
  192.                 {
  193.                   if (*q == 0 || *q == ' ' || *q == '\t')
  194.                     break;
  195.                   prog_buf[i] = *q;
  196.                   ++q;
  197.                 }
  198.               prog_buf[i] = 0;
  199.               prog = prog_buf;
  200.               p = args;
  201.               strcpy (p, prog); p = strchr (p, 0) + 1;
  202.               strcpy (p, q); p = strchr (p, 0) + 1;
  203.               *p = 0;
  204.               i = FALSE;
  205.               for (q = prog_buf; *q != 0; ++q)
  206.                 if (*q == ':' || *q == '\\' || *q == ':')
  207.                   i = FALSE;
  208.                 else if (*q == '.')
  209.                   i = TRUE;
  210.               if (!i)
  211.                 strcat (prog_buf, ".exe");
  212.             }
  213.           if (verbose)
  214.             fprintf (stderr, "--- Program: %s\n", prog);
  215.           if (output)
  216.             {
  217.               DosMakePipe (&pipe_read, &pipe_write, 4096);
  218.               saved_stdout = saved_stderr = 0xffff;
  219.               DosDupHandle (1, &saved_stdout);
  220.               DosDupHandle (2, &saved_stderr);
  221.               hf = 1;
  222.               DosDupHandle (pipe_write, &hf);
  223.               hf = 2;
  224.               DosDupHandle (pipe_write, &hf);
  225.               DosClose (pipe_write);
  226.               no_inherit (pipe_read);
  227.               no_inherit (saved_stdout);
  228.               no_inherit (saved_stderr);
  229.  
  230.               rc = DosExecPgm (failname, sizeof (failname),
  231.                                EXEC_ASYNCRESULT,
  232.                                args, new_env, &results, prog);
  233.               hf = 1;
  234.               DosDupHandle (saved_stdout, &hf);
  235.               DosClose (saved_stdout);
  236.               hf = 2;
  237.               DosDupHandle (saved_stderr, &hf);
  238.               DosClose (saved_stderr);
  239.               if (rc == 0)
  240.                 {
  241.                   USHORT rc2, nread;
  242.  
  243.                   for (;;)
  244.                     {
  245.                       rc2 = DosRead (pipe_read, args, 256, &nread);
  246.                       if (rc2 != 0) /* ERROR_BROKEN_PIPE */
  247.                         break;
  248.                       if (nread == 0)
  249.                         break;
  250.                       send ('O', args, nread);
  251.                     }
  252.                   DosCwait (DCWA_PROCESS, DCWW_WAIT, &results, &pid, 0);
  253.                 }
  254.               DosClose (pipe_read);
  255.             }
  256.           else
  257.             rc = DosExecPgm (failname, sizeof (failname),
  258.                              EXEC_SYNC,
  259.                              args, new_env, &results, prog);
  260.           if (rc != 0)
  261.             {
  262.               fprintf (stderr, "--- DosExecPgm failed, rc=%hu\n", rc);
  263.               sys_rc = -1;
  264.             }
  265.           else
  266.             sys_rc = results.codeResult;
  267.           if (cur_sw && hwndActive != NULL)
  268.             WinSwitchToProgram (WinQuerySwitchHandle (hwndActive, 0));
  269.           sprintf (result, "%d", sys_rc);
  270.           send ('R', result, strlen (result));
  271.           if (!output)
  272.             fputchar ('\n');
  273.           memmove (new_env, org_env, org_env_size);
  274.           new_env_size = org_env_size;
  275.           output = FALSE;
  276.           break;
  277.  
  278.         case 'E':
  279.           p = strchr (buf+1, '=');
  280.           if (p != NULL)
  281.             {
  282.               len = (p - (buf+1)) + 1;
  283.               i = 0;
  284.               while (new_env[i] != 0)
  285.                 if (memcmp (new_env+i, buf+1, len) == 0)
  286.                   break;
  287.                 else
  288.                   i += strlen (new_env+i) + 1;
  289.               if (new_env[i] != 0)
  290.                 {
  291.                   len = strlen (new_env+i) + 1;
  292.                   memmove (new_env + i, new_env + i + len,
  293.                            new_env_size - (i + len));
  294.                   new_env_size -= len;
  295.                 }
  296.               len = strlen (buf+1) + 1;
  297.               if (new_env_size + len > new_env_alloc)
  298.                 {
  299.                   new_env_alloc = new_env_size + len;
  300.                   new_env = realloc (new_env, new_env_alloc);
  301.                   if (new_env == NULL) out_of_mem ();
  302.                 }
  303.               memmove (new_env + new_env_size - 1, buf + 1, len);
  304.               new_env_size += len;
  305.               new_env[new_env_size-1] = 0;
  306.             }
  307.           break;
  308.  
  309.         case 'Q':       /* Quit */
  310.           if (verbose)
  311.             fprintf (stderr, "--- Quit\n");
  312.           send ('A', "", 0);
  313.           quit = TRUE;
  314.           goto done;
  315.  
  316.         case 'W':       /* Working directory */
  317.           p = buf + 1;
  318.           drive = toupper (p[0]);
  319.           if (drive >= 'A' && drive <= 'Z' && p[1] == ':')
  320.             {
  321.               if (verbose)
  322.                 fprintf (stderr, "--- Change drive: %c\n", drive);
  323.               _chdrive (drive - 'A' + 1);
  324.               p += 2;
  325.             }
  326.           if (verbose)
  327.             fprintf (stderr, "--- Change directory: %s\n", p);
  328.           chdir (p);
  329.           break;
  330.  
  331.         case 'S':       /* Switch windows */
  332.           switch (buf[1])
  333.             {
  334.             case 'Y':
  335.               cur_sw = TRUE;
  336.               if (verbose)
  337.                 fprintf (stderr, "--- Switch windows: YES\n");
  338.               break;
  339.             case 'N':
  340.               cur_sw = FALSE;
  341.               if (verbose)
  342.                 fprintf (stderr, "--- Switch windows: NO\n");
  343.               break;
  344.             case 'D':
  345.               cur_sw = def_sw;
  346.               if (verbose)
  347.                 fprintf (stderr, "--- Switch windows: DEFAULT\n");
  348.               break;
  349.             default:
  350.               if (verbose)
  351.                 fprintf (stderr, "--- Switch windows: ERROR\n");
  352.               break;
  353.             }
  354.           break;
  355.  
  356.         case 'O':       /* Send output */
  357.           output = TRUE;
  358.           break;
  359.         }
  360.     }
  361. done:
  362.   if (verbose)
  363.     fprintf (stderr, "--- Disconnect\n");
  364.   rc = DosDisConnectNmPipe (hp);
  365.   if (rc != 0)
  366.     {
  367.       fprintf (stderr, "DosDisConnectNmPipe: rc=%hu\n", rc);
  368.       return (2);
  369.     }
  370.   if (!quit)
  371.     goto new;
  372.   
  373.   rc = DosClose (hp);
  374.   if (rc != 0)
  375.     {
  376.       fprintf (stderr, "DosClose: rc=%hu\n", rc);
  377.       return (2);
  378.     }
  379.   return (0);
  380. }
  381.