Logo Search packages:      
Sourcecode: vile version File versions

os2pipe.c

/* pipe routines for OS/2
 *  lee johnson, spring 1995
 */
#define INCL_DOSFILEMGR
#define INCL_DOSQUEUES
#define INCL_DOSERRORS
#define INCL_NOPMAPI
#include <os2.h>

#include "estruct.h"

#include <process.h>

#ifndef EOS2ERR
#define EOS2ERR EINVAL
#endif

#ifndef EOUTOFMEM
#define EOUTOFMEM ENOMEM
#endif

#if CC_WATCOM
#define _fdopen fdopen
#define _cwait  cwait
#endif

/* We have one pipe running from the parent to the child... */
static HFILE pipe_p_to_c = NULLHANDLE, pipe_c_from_p = NULLHANDLE;

/* ...and another running from the child to the parent. */
static HFILE pipe_c_to_p = NULLHANDLE, pipe_p_from_c = NULLHANDLE;

static FILE *vile_in  = NULL; /* stream attached to pipe_p_from_c */
static FILE *vile_out = NULL; /* stream attached to pipe_p_to_c */

static int pid = -1;

static void
DupError(APIRET rc)
{
      switch(rc)
      {
      case ERROR_TOO_MANY_OPEN_FILES:
            errno = EMFILE;
            break;

      case ERROR_INVALID_HANDLE:
      case ERROR_INVALID_TARGET_HANDLE:
            errno = EBADF;
            break;

      default:
            errno = EOS2ERR;
            break;
      }
}

int
_os2_command(char *command)
{
      char buffer[1024];
      char *shell;

      if ((shell = getenv("COMSPEC")) != NULL)
      {
            sprintf(buffer, "/C %s", command);
            return spawnlp(P_NOWAIT, shell, shell, buffer, NULL);
      }
      else
      {
            return -1;
      }
}

static void
close_pipes(void)
{
      if (vile_in != NULL)
      {
            TRACE(("close_pipes, vile_in #%d\n", fileno(vile_in)));
            fclose(vile_in);
            vile_in = NULL;
            pipe_p_from_c = NULLHANDLE;
      }
      else if (pipe_p_from_c != NULLHANDLE)
      {
            TRACE(("close_pipes, pipe_p_from_c #%d\n", pipe_p_from_c));
            DosClose(pipe_p_from_c);
            pipe_p_from_c = NULLHANDLE;
      }

      if (vile_out != NULL)
      {
            TRACE(("close_pipes, vile_out #%d\n", fileno(vile_out)));
            fclose(vile_out);
            vile_out = NULL;
            pipe_p_to_c = NULLHANDLE;
      }
      else if (pipe_p_to_c != NULLHANDLE)
      {
            TRACE(("close_pipes, pipe_p_to_c #%d\n", pipe_p_to_c));
            DosClose(pipe_p_to_c);
            pipe_p_to_c = NULLHANDLE;
      }

      if (pipe_c_to_p != NULLHANDLE)
      {
            TRACE(("close_pipes, pipe_c_to_p #%d\n", pipe_c_to_p));
            DosClose(pipe_c_to_p);
            pipe_c_to_p = NULLHANDLE;
      }
      if (pipe_c_from_p != NULLHANDLE)
      {
            TRACE(("close_pipes, pipe_c_from_p #%d\n", pipe_c_from_p));
            DosClose(pipe_c_from_p);
            pipe_c_from_p = NULLHANDLE;
      }
}

int
inout_popen(FILE **infile, FILE **outfile, char *command)
{
      HFILE save_in, save_out, save_err;
      HFILE fd;
      APIRET rc;

      save_in = save_out = save_err = NULLHANDLE;

      /* We have one pipe running from the parent to the child... */
      pipe_p_to_c = pipe_c_from_p = NULLHANDLE;

      /* ...and another running from the child to the parent. */
      pipe_c_to_p = pipe_p_from_c = NULLHANDLE;

      vile_in = vile_out = NULL;

      /* Create the pipes we'll use for IPC. */
      rc = DosCreatePipe(&pipe_p_from_c, &pipe_c_to_p, 4096);
      if (rc != NO_ERROR)
      {
            errno = EOUTOFMEM;
            goto Error;
      }
      rc = DosCreatePipe(&pipe_c_from_p, &pipe_p_to_c, 4096);
      if (rc != NO_ERROR)
      {
            errno = EOUTOFMEM;
            goto Error;
      }

      /*
       * Save standard I/O handles.
       */
      save_in = ~0;
      if (DosDupHandle(0, &save_in) != NO_ERROR)
      {
            DupError(rc);
            goto Error;
      }

      save_out = ~0;
      if (DosDupHandle(1, &save_out) != NO_ERROR)
      {
            DupError(rc);
            goto Error;
      }

      save_err = ~0;
      if (DosDupHandle(2, &save_err) != NO_ERROR)
      {
            DupError(rc);
            goto Error;
      }

      /*
       * Redirect standard file handles for the CHILD PROCESS.
       */

      /* Get standard input from the read end of the p_to_c pipe. */
      fd = 0;
      if (DosDupHandle(pipe_c_from_p, &fd) != NO_ERROR)
      {
            DupError(rc);
            goto Error;
      }

      /* Send standard output to the write end of the c_to_p pipe. */
      fd = 1;
      if (DosDupHandle(pipe_c_to_p, &fd) != NO_ERROR)
      {
            DupError(rc);
            goto Error;
      }

      /* Send error output to the write end of the c_to_p pipe. */
      fd = 2;
      if (DosDupHandle(pipe_c_to_p, &fd) != NO_ERROR)
      {
            DupError(rc);
            goto Error;
      }

      /*
       * Ensure that the p_to_c pipe will close cleanly when the parent
       * process (vile) is done with it.
       */
      if (DosSetFHState(pipe_p_to_c, OPEN_FLAGS_NOINHERIT) != NO_ERROR)
            goto Error;

      /* Launch the command. */
      if ((pid = _os2_command((char *)command)) < 0)
            goto Error;

      /*
       * Ensure that the c_to_p pipe will close cleanly when the child
       * process is done with it.
       */
      DosClose(pipe_c_to_p);
      pipe_c_to_p = NULLHANDLE;

      /* Connect the read end of the c_to_p pipe to a stream. */
      if (infile != NULL
            && (vile_in = *infile = _fdopen(pipe_p_from_c, "r")) == NULL)
            goto Error;
      TRACE(("inout_popen, vile_in #%d\n", fileno(vile_in)));

      /* Connect the write end of the p_to_c pipe to a stream. */
      if (outfile != NULL
            && (vile_out = *outfile = _fdopen(pipe_p_to_c, "w")) == NULL)
            goto Error;
      TRACE(("inout_popen, vile_out #%d\n", fileno(vile_out)));

      /* Restore redirected file handles. */
      if (save_in != NULLHANDLE)
      {
            fd = 0;
            DosDupHandle(save_in, &fd);
            DosClose(save_in);
            TRACE(("inout_popen, dup 0: #%d, #%d\n", save_in, fd));
      }
      if (save_out != NULLHANDLE)
      {
            fd = 1;
            DosDupHandle(save_out, &fd);
            DosClose(save_out);
            TRACE(("inout_popen, dup 1: #%d, #%d\n", save_out, fd));
      }
      if (save_err != NULLHANDLE)
      {
            fd = 2;
            DosDupHandle(save_err, &fd);
            DosClose(save_err);
            TRACE(("inout_popen, dup 2: #%d, #%d\n", save_err, fd));
      }

      return TRUE;

Error:
      TRACE(("inout_popen, Error\n"));
      /* Restore redirected file handles. */
      if (save_in != NULLHANDLE)
      {
            fd = 0;
            DosDupHandle(save_in, &fd);
      }
      if (save_out != NULLHANDLE)
      {
            fd = 1;
            DosDupHandle(save_out, &fd);
      }
      if (save_err != NULLHANDLE)
      {
            fd = 2;
            DosDupHandle(save_err, &fd);
      }

      close_pipes();
      return FALSE;
}

int
softfork(void)
{
      return FALSE;
}

void
npflush(void)
{
      if (vile_out != NULL)
      {
            TRACE(("npflush, vile_out #%d\n", fileno(vile_out)));
            fflush(vile_out);
            fclose(vile_out);
            vile_out = NULL;
            pipe_p_to_c = NULLHANDLE;
      }
}

void
npclose(FILE *pipe_file)
{
      int wait_status;

      npflush();
      _cwait(&wait_status, pid, WAIT_CHILD);
      close_pipes();
}

Generated by  Doxygen 1.6.0   Back to index