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 >
Wrap
C/C++ Source or Header
|
1998-04-28
|
6KB
|
310 lines
/* 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();
}