home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / os2pipe.c < prev    next >
C/C++ Source or Header  |  1998-04-28  |  6KB  |  310 lines

  1.  
  2. /* pipe routines for OS/2
  3.  *  lee johnson, spring 1995
  4.  */
  5. #define INCL_DOSFILEMGR
  6. #define INCL_DOSQUEUES
  7. #define INCL_DOSERRORS
  8. #define INCL_NOPMAPI
  9. #include <os2.h>
  10.  
  11. #include "estruct.h"
  12.  
  13. #include <process.h>
  14.  
  15. #ifndef EOS2ERR
  16. #define EOS2ERR EINVAL
  17. #endif
  18.  
  19. #ifndef EOUTOFMEM
  20. #define EOUTOFMEM ENOMEM
  21. #endif
  22.  
  23. #if CC_WATCOM
  24. #define _fdopen fdopen
  25. #define _cwait  cwait
  26. #endif
  27.  
  28. /* We have one pipe running from the parent to the child... */
  29. static HFILE pipe_p_to_c = NULLHANDLE, pipe_c_from_p = NULLHANDLE;
  30.  
  31. /* ...and another running from the child to the parent. */
  32. static HFILE pipe_c_to_p = NULLHANDLE, pipe_p_from_c = NULLHANDLE;
  33.  
  34. static FILE *vile_in  = NULL;    /* stream attached to pipe_p_from_c */
  35. static FILE *vile_out = NULL;    /* stream attached to pipe_p_to_c */
  36.  
  37. static int pid = -1;
  38.  
  39. static void
  40. DupError(APIRET rc)
  41. {
  42.     switch(rc)
  43.     {
  44.     case ERROR_TOO_MANY_OPEN_FILES:
  45.         errno = EMFILE;
  46.         break;
  47.  
  48.     case ERROR_INVALID_HANDLE:
  49.     case ERROR_INVALID_TARGET_HANDLE:
  50.         errno = EBADF;
  51.         break;
  52.  
  53.     default:
  54.         errno = EOS2ERR;
  55.         break;
  56.     }
  57. }
  58.  
  59. int
  60. _os2_command(char *command)
  61. {
  62.     char buffer[1024];
  63.     char *shell;
  64.  
  65.     if ((shell = getenv("COMSPEC")) != NULL)
  66.     {
  67.         sprintf(buffer, "/C %s", command);
  68.         return spawnlp(P_NOWAIT, shell, shell, buffer, NULL);
  69.     }
  70.     else
  71.     {
  72.         return -1;
  73.     }
  74. }
  75.  
  76. static void
  77. close_pipes(void)
  78. {
  79.     if (vile_in != NULL)
  80.     {
  81.         TRACE(("close_pipes, vile_in #%d\n", fileno(vile_in)))
  82.         fclose(vile_in);
  83.         vile_in = NULL;
  84.         pipe_p_from_c = NULLHANDLE;
  85.     }
  86.     else if (pipe_p_from_c != NULLHANDLE)
  87.     {
  88.         TRACE(("close_pipes, pipe_p_from_c #%d\n", pipe_p_from_c))
  89.         DosClose(pipe_p_from_c);
  90.         pipe_p_from_c = NULLHANDLE;
  91.     }
  92.  
  93.     if (vile_out != NULL)
  94.     {
  95.         TRACE(("close_pipes, vile_out #%d\n", fileno(vile_out)))
  96.         fclose(vile_out);
  97.         vile_out = NULL;
  98.         pipe_p_to_c = NULLHANDLE;
  99.     }
  100.     else if (pipe_p_to_c != NULLHANDLE)
  101.     {
  102.         TRACE(("close_pipes, pipe_p_to_c #%d\n", pipe_p_to_c))
  103.         DosClose(pipe_p_to_c);
  104.         pipe_p_to_c = NULLHANDLE;
  105.     }
  106.  
  107.     if (pipe_c_to_p != NULLHANDLE)
  108.     {
  109.         TRACE(("close_pipes, pipe_c_to_p #%d\n", pipe_c_to_p))
  110.         DosClose(pipe_c_to_p);
  111.         pipe_c_to_p = NULLHANDLE;
  112.     }
  113.     if (pipe_c_from_p != NULLHANDLE)
  114.     {
  115.         TRACE(("close_pipes, pipe_c_from_p #%d\n", pipe_c_from_p))
  116.         DosClose(pipe_c_from_p);
  117.         pipe_c_from_p = NULLHANDLE;
  118.     }
  119. }
  120.  
  121. int
  122. inout_popen(FILE **infile, FILE **outfile, char *command)
  123. {
  124.     HFILE save_in, save_out, save_err;
  125.     HFILE fd;
  126.     APIRET rc;
  127.  
  128.     save_in = save_out = save_err = NULLHANDLE;
  129.  
  130.     /* We have one pipe running from the parent to the child... */
  131.     pipe_p_to_c = pipe_c_from_p = NULLHANDLE;
  132.  
  133.     /* ...and another running from the child to the parent. */
  134.     pipe_c_to_p = pipe_p_from_c = NULLHANDLE;
  135.  
  136.     vile_in = vile_out = NULL;
  137.  
  138.     /* Create the pipes we'll use for IPC. */
  139.     rc = DosCreatePipe(&pipe_p_from_c, &pipe_c_to_p, 4096);
  140.     if (rc != NO_ERROR)
  141.     {
  142.         errno = EOUTOFMEM;
  143.         goto Error;
  144.     }
  145.     rc = DosCreatePipe(&pipe_c_from_p, &pipe_p_to_c, 4096);
  146.     if (rc != NO_ERROR)
  147.     {
  148.         errno = EOUTOFMEM;
  149.         goto Error;
  150.     }
  151.  
  152.     /*
  153.      * Save standard I/O handles.
  154.      */
  155.     save_in = ~0;
  156.     if (DosDupHandle(0, &save_in) != NO_ERROR)
  157.     {
  158.         DupError(rc);
  159.         goto Error;
  160.     }
  161.  
  162.     save_out = ~0;
  163.     if (DosDupHandle(1, &save_out) != NO_ERROR)
  164.     {
  165.         DupError(rc);
  166.         goto Error;
  167.     }
  168.  
  169.     save_err = ~0;
  170.     if (DosDupHandle(2, &save_err) != NO_ERROR)
  171.     {
  172.         DupError(rc);
  173.         goto Error;
  174.     }
  175.  
  176.     /*
  177.      * Redirect standard file handles for the CHILD PROCESS.
  178.      */
  179.  
  180.     /* Get standard input from the read end of the p_to_c pipe. */
  181.     fd = 0;
  182.     if (DosDupHandle(pipe_c_from_p, &fd) != NO_ERROR)
  183.     {
  184.         DupError(rc);
  185.         goto Error;
  186.     }
  187.  
  188.     /* Send standard output to the write end of the c_to_p pipe. */
  189.     fd = 1;
  190.     if (DosDupHandle(pipe_c_to_p, &fd) != NO_ERROR)
  191.     {
  192.         DupError(rc);
  193.         goto Error;
  194.     }
  195.  
  196.     /* Send error output to the write end of the c_to_p pipe. */
  197.     fd = 2;
  198.     if (DosDupHandle(pipe_c_to_p, &fd) != NO_ERROR)
  199.     {
  200.         DupError(rc);
  201.         goto Error;
  202.     }
  203.  
  204.     /*
  205.      * Ensure that the p_to_c pipe will close cleanly when the parent
  206.      * process (vile) is done with it.
  207.      */
  208.     if (DosSetFHState(pipe_p_to_c, OPEN_FLAGS_NOINHERIT) != NO_ERROR)
  209.         goto Error;
  210.  
  211.     /* Launch the command. */
  212.     if ((pid = _os2_command((char *)command)) < 0)
  213.         goto Error;
  214.  
  215.     /*
  216.      * Ensure that the c_to_p pipe will close cleanly when the child
  217.      * process is done with it.
  218.      */
  219.     DosClose(pipe_c_to_p);
  220.     pipe_c_to_p = NULLHANDLE;
  221.  
  222.     /* Connect the read end of the c_to_p pipe to a stream. */
  223.     if (infile != NULL
  224.         && (vile_in = *infile = _fdopen(pipe_p_from_c, "r")) == NULL)
  225.         goto Error;
  226.     TRACE(("inout_popen, vile_in #%d\n", fileno(vile_in)))
  227.  
  228.     /* Connect the write end of the p_to_c pipe to a stream. */
  229.     if (outfile != NULL
  230.         && (vile_out = *outfile = _fdopen(pipe_p_to_c, "w")) == NULL)
  231.         goto Error;
  232.     TRACE(("inout_popen, vile_out #%d\n", fileno(vile_out)))
  233.  
  234.     /* Restore redirected file handles. */
  235.     if (save_in != NULLHANDLE)
  236.     {
  237.         fd = 0;
  238.         DosDupHandle(save_in, &fd);
  239.         DosClose(save_in);
  240.         TRACE(("inout_popen, dup 0: #%d, #%d\n", save_in, fd))
  241.     }
  242.     if (save_out != NULLHANDLE)
  243.     {
  244.         fd = 1;
  245.         DosDupHandle(save_out, &fd);
  246.         DosClose(save_out);
  247.         TRACE(("inout_popen, dup 1: #%d, #%d\n", save_out, fd))
  248.     }
  249.     if (save_err != NULLHANDLE)
  250.     {
  251.         fd = 2;
  252.         DosDupHandle(save_err, &fd);
  253.         DosClose(save_err);
  254.         TRACE(("inout_popen, dup 2: #%d, #%d\n", save_err, fd))
  255.     }
  256.  
  257.     return TRUE;
  258.  
  259. Error:
  260.     TRACE(("inout_popen, Error\n"))
  261.     /* Restore redirected file handles. */
  262.     if (save_in != NULLHANDLE)
  263.     {
  264.         fd = 0;
  265.         DosDupHandle(save_in, &fd);
  266.     }
  267.     if (save_out != NULLHANDLE)
  268.     {
  269.         fd = 1;
  270.         DosDupHandle(save_out, &fd);
  271.     }
  272.     if (save_err != NULLHANDLE)
  273.     {
  274.         fd = 2;
  275.         DosDupHandle(save_err, &fd);
  276.     }
  277.  
  278.     close_pipes();
  279.     return FALSE;
  280. }
  281.  
  282. int
  283. softfork(void)
  284. {
  285.     return FALSE;
  286. }
  287.  
  288. void
  289. npflush(void)
  290. {
  291.     if (vile_out != NULL)
  292.     {
  293.         TRACE(("npflush, vile_out #%d\n", fileno(vile_out)))
  294.         fflush(vile_out);
  295.         fclose(vile_out);
  296.         vile_out = NULL;
  297.         pipe_p_to_c = NULLHANDLE;
  298.     }
  299. }
  300.  
  301. void
  302. npclose(FILE *pipe_file)
  303. {
  304.     int wait_status;
  305.  
  306.     npflush();
  307.     _cwait(&wait_status, pid, WAIT_CHILD);
  308.     close_pipes();
  309. }
  310.