home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 22 gnu
/
22-gnu.zip
/
rcs57pc3.zip
/
diff
/
pc
/
popen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-01-17
|
11KB
|
534 lines
/* popen.c
*
* Author: Kai Uwe Rommel <rommel@ars.de>
* Created: Wed Aug 23 1995
*/
static char *rcsid =
"$Id$";
static char *rcsrev = "$Revision$";
/*
* $Log$
*/
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <string.h>
#ifdef __EMX__
#include <alloca.h>
#endif
#ifdef __IBMC__
#define alloca _alloca
#endif
#ifdef __WATCOMC__
#include <malloc.h>
#define tempnam _tempnam
#endif
#include "popen.h"
#if defined(__OS2__) && !defined(OS2)
#define OS2
#endif
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
#define WIN32
#endif
#ifdef M_I86
FILE *popen(const char *cmd, const char *mode)
{
return (_osmode == DOS_MODE) ? fake_popen(cmd, mode) : _popen(cmd, mode);
}
int pclose(FILE *ptr)
{
return (_osmode == DOS_MODE) ? fake_pclose(ptr) : _pclose(ptr);
}
int pipe(int *handles)
{
return _pipe(handles, 4096, O_BINARY);
}
#else
#ifdef OS2
#define INCL_DOS
#define INCL_NOPM
#include <os2.h>
static int pids[MAXPIPES];
FILE *popen(const char *cmd, const char *mode)
{
HFILE end1, end2, std, old1, old2, temp;
FILE *file;
RESULTCODES res;
char fail[256], cmdline[256], *args, *shell;
const char *ptr;
int fmode, rc;
for (ptr = mode; *ptr; ptr++)
switch (*ptr)
{
case 'r':
std = 1;
break;
case 'w':
std = 0;
break;
case 't':
fmode = O_TEXT;
break;
case 'b':
fmode = O_BINARY;
break;
}
if (DosCreatePipe(&end1, &end2, 4096))
return NULL;
if (std == 0)
{
temp = end1; end1 = end2; end2 = temp;
}
old1 = -1; /* save stdin or stdout */
DosDupHandle(std, &old1);
DosSetFHState(old1, OPEN_FLAGS_NOINHERIT);
temp = std; /* redirect stdin or stdout */
DosDupHandle(end2, &temp);
if (std == 1)
{
old2 = -1; /* save stderr */
DosDupHandle(2, &old2);
DosSetFHState(old2, OPEN_FLAGS_NOINHERIT);
temp = 2; /* redirect stderr */
DosDupHandle(end2, &temp);
}
DosClose(end2);
DosSetFHState(end1, OPEN_FLAGS_NOINHERIT);
if ((shell = getenv("COMSPEC")) == NULL)
shell = "cmd.exe";
strcpy(cmdline, shell);
args = cmdline + strlen(cmdline) + 1; /* skip zero */
strcpy(args, "/c ");
strcat(args, cmd);
args[strlen(args) + 1] = '\0'; /* two zeroes */
rc = DosExecPgm(fail, sizeof(fail), EXEC_ASYNCRESULT, cmdline, 0, &res, shell);
temp = std; /* restore stdin or stdout */
DosDupHandle(old1, &temp);
DosClose(old1);
if (std == 1)
{
temp = 2; /* restore stderr */
DosDupHandle(old2, &temp);
DosClose(old2);
}
if (rc)
{
DosClose(end1);
return NULL;
}
#ifdef __IBMC__
_setmode(end1, fmode);
#endif
file = fdopen(end1, mode);
pids[end1] = res.codeTerminate;
return file;
}
int pclose(FILE *pipe)
{
RESULTCODES rc;
PID pid;
int handle = fileno(pipe);
fclose(pipe);
if (pids[handle])
DosWaitChild(DCWA_PROCESSTREE, DCWW_WAIT, &rc, &pid, pids[handle]);
pids[handle] = 0;
#ifdef __EMX__
return rc.codeTerminate == 0 ? (rc.codeResult << 8) : -1;
#else
return rc.codeTerminate == 0 ? rc.codeResult : -1;
#endif
}
int pipe(int *handles)
{
HFILE end1, end2;
if (DosCreatePipe(&end1, &end2, 4096))
return -1;
#ifdef __IBMC__
_setmode(end1, O_TEXT);
_setmode(end2, O_TEXT);
#endif
handles[0] = (int) end1;
handles[1] = (int) end2;
return 0;
}
#else
#ifdef WIN32
#include <windows.h>
#ifdef __EMX__
/* #define _open_osfhandle(h, m) _imphandle(h)
nolonger needed with RSXNT 1.42 */
#include <mscompat.h>
#endif
PROCESS_INFORMATION pid[MAXPIPES];
FILE *popen(const char *cmd, const char *mode)
{
HANDLE rpipe, wpipe, handle, other;
#ifdef VERSION2
HANDLE old0, old1, old2;
#endif
SECURITY_ATTRIBUTES security;
STARTUPINFO si;
PROCESS_INFORMATION pi;
char buffer[8192];
const char *ptr;
int fhandle, fmode, rc;
OSVERSIONINFO osvi;
static int WindowsNT = -1;
if (WindowsNT == -1)
{
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
WindowsNT = (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
for (fmode = 0, ptr = mode; *ptr; ptr++)
switch (*ptr)
{
case 'r':
fmode |= O_RDONLY;
break;
case 'w':
fmode |= O_WRONLY;
break;
case 't':
fmode |= O_TEXT;
break;
case 'b':
fmode |= O_BINARY;
break;
}
security.nLength = sizeof(security);
security.bInheritHandle = TRUE;
security.lpSecurityDescriptor = NULL;
if (!CreatePipe(&rpipe, &wpipe, &security, 0))
return NULL;
handle = (fmode & O_WRONLY) ? wpipe : rpipe;
other = (fmode & O_WRONLY) ? rpipe : wpipe;
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
fhandle = _open_osfhandle((long) handle, fmode);
if (fhandle < 0 || MAXPIPES <= fhandle)
{
CloseHandle(rpipe);
CloseHandle(wpipe);
return NULL;
}
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
/* Both of the two following versions of redirection work fine. We keep
* them both here just for reference. The one #ifdef'ed VERSION2 is the
* more common one but the other one is (fail-) safer.
*/
#ifdef VERSION2
if (fmode & O_WRONLY)
{
old0 = GetStdHandle(STD_INPUT_HANDLE);
SetStdHandle(STD_INPUT_HANDLE, rpipe);
}
else
{
old1 = GetStdHandle(STD_OUTPUT_HANDLE);
old2 = GetStdHandle(STD_ERROR_HANDLE);
SetStdHandle(STD_OUTPUT_HANDLE, wpipe);
SetStdHandle(STD_ERROR_HANDLE, wpipe);
}
#else
si.dwFlags = STARTF_USESTDHANDLES;
if (fmode & O_WRONLY)
{
si.hStdInput = rpipe;
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
}
else
{
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = wpipe;
si.hStdError = wpipe;
}
#endif
/* Using anonymous pipes and CreateProcess to redirect stdin or stdout does
* only work without any restrictions on Windows NT. On Windows 95, it
* does only work if the child process is also a Win32 application and not
* an old 16-bit executable. The problem is, that the Windows 95 command
* line interpreter or shell (command.com) is also an old 16-bit program.
* The semantics of popen() normally require execution through a shell
* but that can never work on Windows 95 because of this restriction.
* Therefore, if we do not run on Windows NT, we must try to run the command
* without a shell to at least cover _some_ cases. Otherwise we just fail.
*/
if (!WindowsNT)
rc = CreateProcess(NULL, (char *) cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
else
{
if ((ptr = getenv("COMSPEC")) == NULL)
ptr = "cmd.exe";
strcpy(buffer, ptr);
strcat(buffer, " /c ");
strcat(buffer, cmd);
rc = CreateProcess(ptr, buffer, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
}
#ifdef VERSION2
if (fmode & O_WRONLY)
SetStdHandle(STD_INPUT_HANDLE, old0);
else
{
SetStdHandle(STD_OUTPUT_HANDLE, old1);
SetStdHandle(STD_ERROR_HANDLE, old2);
}
#endif
if (rc == 0)
{
CloseHandle(rpipe);
CloseHandle(wpipe);
return NULL;
}
CloseHandle(other);
pid[fhandle] = pi;
return fdopen(fhandle, (char *) mode);
}
int pclose(FILE *pipe)
{
PROCESS_INFORMATION pi;
DWORD rc;
int fhandle = fileno(pipe);
if (fhandle < 0 || MAXPIPES <= fhandle)
return -1;
fclose(pipe);
pi = pid[fhandle];
WaitForSingleObject(pi.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &rc);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
#ifdef __EMX__
return rc << 8;
#else
return rc;
#endif
}
int pipe(int *handles)
{
HANDLE rpipe, wpipe;
SECURITY_ATTRIBUTES security;
security.nLength = sizeof(security);
security.bInheritHandle = TRUE;
security.lpSecurityDescriptor = NULL;
if (!CreatePipe(&rpipe, &wpipe, &security, 0))
return -1;
handles[0] = _open_osfhandle((long) rpipe, O_RDONLY);
handles[1] = _open_osfhandle((long) wpipe, O_WRONLY);
return 0;
}
#else
FILE *popen(const char *cmd, const char *mode)
{
return fake_popen(cmd, mode);
}
int pclose(FILE *pipe)
{
return fake_pclose(pipe);
}
int pipe(int *handles)
{
return -1;
}
#endif
#endif
#endif
typedef enum { unopened = 0, reading, writing } pipemode;
static struct
{
char *name;
char *cmd;
pipemode pmode;
}
pipes[MAXPIPES];
FILE *fake_popen(const char *cmd, const char *mode)
{
FILE *current;
char *name;
int cur;
pipemode curmode;
if(strchr(mode, 'r') != NULL)
curmode = reading;
else if(strchr(mode, 'w') != NULL)
curmode = writing;
else
return NULL;
if ((name = tempnam(NULL, "pi")) == NULL)
return NULL;
if(curmode == reading)
{
char *line = alloca(strlen(cmd) + strlen(name) + 4);
sprintf(line, "%s > %s", cmd, name);
system(line);
if((current = fopen(name, mode)) == NULL)
return NULL;
}
else
{
if((current = fopen(name, mode)) == NULL)
return NULL;
}
cur = fileno(current);
pipes[cur].name = name;
pipes[cur].cmd = strdup(cmd);
pipes[cur].pmode = curmode;
return current;
}
int fake_pclose(FILE *pipe)
{
int cur = fileno(pipe), rval;
if(pipes[cur].pmode == unopened)
return -1;
if(pipes[cur].pmode == reading)
{
rval = fclose(pipe);
unlink(pipes[cur].name);
}
else
{
char *line = alloca(strlen(pipes[cur].cmd) + strlen(pipes[cur].name) + 4);
fclose(pipe);
sprintf(line, "%s < %s", pipes[cur].cmd, pipes[cur].name);
rval = system(line);
unlink(pipes[cur].name);
}
free(pipes[cur].name);
free(pipes[cur].cmd);
pipes[cur].pmode = unopened;
return rval;
}
#ifdef TEST
#include <conio.h>
int main(void)
{
FILE *pipe;
int x = 0;
char line[256];
pipe = popen("diff.exe", "r");
while (fgets(line, sizeof(line), pipe))
{
fputs(line, stdout);
x++;
}
printf("%d lines, rc = %d\n", x, pclose(pipe));
fflush(stdout);
getch();
pipe = popen("more.com", "w");
for (x = 0; x < 32; x++)
fprintf(pipe, "line %d\n", x);
printf("rc = %d\n", pclose(pipe));
return 0;
}
#endif
/* end of popen.c */