include popen for mingw compilation
simplify Makefile a tiny bit.
This commit is contained in:
parent
a91e2f9030
commit
3603c6eb07
@ -49,11 +49,11 @@ C_SOURCES=$(srcdir)/pl-buffer.c $(srcdir)/pl-ctype.c \
|
||||
$(srcdir)/pl-stream.c $(srcdir)/pl-string.c \
|
||||
$(srcdir)/pl-table.c \
|
||||
$(srcdir)/pl-text.c $(srcdir)/pl-utf8.c \
|
||||
$(srcdir)/pl-yap.c @ENABLE_WINCONSOLE@ $(srcdir)/uxnt/utf8.c $(srcdir)/uxnt/uxnt.c
|
||||
$(srcdir)/pl-yap.c @ENABLE_WINCONSOLE@ $(srcdir)/popen.c $(srcdir)/uxnt/utf8.c $(srcdir)/uxnt/uxnt.c
|
||||
OBJS=pl-buffer.o pl-ctype.o pl-error.o pl-feature.o \
|
||||
pl-file.o pl-os.o \
|
||||
pl-stream.o pl-string.o pl-table.o pl-text.o pl-utf8.o \
|
||||
pl-yap.o @ENABLE_WINCONSOLE@ utf8.o uxnt.o
|
||||
pl-yap.o @ENABLE_WINCONSOLE@ popen.o utf8.o uxnt.o
|
||||
SOBJS=plstream@SHLIB_SUFFIX@
|
||||
|
||||
#in some systems we just create a single object, in others we need to
|
||||
@ -61,48 +61,16 @@ SOBJS=plstream@SHLIB_SUFFIX@
|
||||
|
||||
all: $(SOBJS)
|
||||
|
||||
pl-buffer.o: $(srcdir)/pl-buffer.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-buffer.c -o pl-buffer.o
|
||||
|
||||
pl-ctype.o: $(srcdir)/pl-ctype.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-ctype.c -o pl-ctype.o
|
||||
|
||||
pl-error.o: $(srcdir)/pl-error.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-error.c -o pl-error.o
|
||||
|
||||
pl-feature.o: $(srcdir)/pl-feature.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-feature.c -o pl-feature.o
|
||||
|
||||
pl-file.o: $(srcdir)/pl-file.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-file.c -o pl-file.o
|
||||
|
||||
pl-os.o: $(srcdir)/pl-os.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-os.c -o pl-os.o
|
||||
|
||||
pl-stream.o: $(srcdir)/pl-stream.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-stream.c -o pl-stream.o
|
||||
|
||||
pl-string.o: $(srcdir)/pl-string.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-string.c -o pl-string.o
|
||||
|
||||
pl-table.o: $(srcdir)/pl-table.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-table.c -o pl-table.o
|
||||
|
||||
pl-text.o: $(srcdir)/pl-text.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-text.c -o pl-text.o
|
||||
|
||||
pl-utf8.o: $(srcdir)/pl-utf8.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-utf8.c -o pl-utf8.o
|
||||
|
||||
pl-yap.o: $(srcdir)/pl-yap.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/pl-yap.c -o pl-yap.o
|
||||
|
||||
uxnt.o: $(srcdir)/uxnt/uxnt.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/uxnt/uxnt.c -o uxnt.o
|
||||
|
||||
utf8.o: $(srcdir)/uxnt/utf8.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/uxnt/utf8.c -o utf8.o
|
||||
|
||||
# default rule
|
||||
%.o : $(srcdir)/C/%.c
|
||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $< -o $@
|
||||
|
||||
@DO_SECOND_LD@%@SHLIB_SUFFIX@: %.o
|
||||
@DO_SECOND_LD@ @SHLIB_LD@ -o $@ $<
|
||||
|
||||
@ -123,3 +91,6 @@ depend: $(HEADERS) $(C_SOURCES)
|
||||
makedepend -f - -- $(CFLAGS) -I$(srcdir)/../../H -I$(srcdir)/../../include -- $(C_SOURCES) |\
|
||||
sed 's|.*/\([^:]*\):|\1:|' >> Makefile ;\
|
||||
fi
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
|
359
packages/PLStream/popen.c
Normal file
359
packages/PLStream/popen.c
Normal file
@ -0,0 +1,359 @@
|
||||
/* popen.c
|
||||
RunSilent() is by Steven Szelei,
|
||||
and pt_popen()/pt_pclose() is by Kurt Keller
|
||||
Modified and comments translated by Steve Donovan
|
||||
|
||||
Please note an extension; if your commmand contains '2>&1'
|
||||
then any error output will be redirected as well to the pipe.
|
||||
|
||||
Put this file in scite\lua\src\lib and add to your project
|
||||
|
||||
to modify liolib.c in the same dir,
|
||||
replace conditional at line 47 with:
|
||||
|
||||
#ifndef USE_POPEN
|
||||
#ifdef __WINDOWS__
|
||||
#define USE_POPEN 1
|
||||
FILE* pt_popen(const char *cmd, const char*mode);
|
||||
int pt_pclose(FILE *file);
|
||||
uintptr_t RunSilent(const char* strCommand);
|
||||
#define popen pt_popen
|
||||
#define pclose pt_pclose
|
||||
#define system RunSilent
|
||||
#endif
|
||||
#else
|
||||
#define USE_POPEN 0
|
||||
#endif
|
||||
|
||||
*/
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SWI-Prolog note:
|
||||
|
||||
This file is copied verbatim from
|
||||
http://lua-users.org/wiki/PipesOnWindows, where it is contributed for
|
||||
using pipes with the LUA programming language. LUA is distributed under
|
||||
the MIT licence which is claimed to be compatible (but less restrictive)
|
||||
with the LGPL license. We therefore assume we can use this file in
|
||||
SWI-Prolog without introducing new license problems.
|
||||
|
||||
This version is heavily modified:
|
||||
|
||||
* Support Unicode commands (commands are specified in UTF-8)
|
||||
* make popen()/pclose() thread-safe.
|
||||
* Fix leak process-handles
|
||||
|
||||
If you find this file and know better, please contact info@swi-prolog.org.
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <io.h>
|
||||
#include "pl-utf8.h"
|
||||
|
||||
DWORD RunSilent(const char* strCommand)
|
||||
{
|
||||
STARTUPINFO StartupInfo;
|
||||
PROCESS_INFORMATION ProcessInfo;
|
||||
char Args[4096];
|
||||
char *pEnvCMD = NULL;
|
||||
char *pDefaultCMD = "CMD.EXE";
|
||||
ULONG rc;
|
||||
|
||||
memset(&StartupInfo, 0, sizeof(StartupInfo));
|
||||
StartupInfo.cb = sizeof(STARTUPINFO);
|
||||
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
|
||||
StartupInfo.wShowWindow = SW_HIDE;
|
||||
|
||||
Args[0] = 0;
|
||||
|
||||
pEnvCMD = getenv("COMSPEC");
|
||||
|
||||
if(pEnvCMD){
|
||||
strcpy(Args, pEnvCMD);
|
||||
} else{
|
||||
strcpy(Args, pDefaultCMD);
|
||||
}
|
||||
|
||||
/* "/c" option - Do the command then terminate the command window */
|
||||
strcat(Args, " /c ");
|
||||
/*the application you would like to run from the command window */
|
||||
strcat(Args, strCommand);
|
||||
|
||||
if (!CreateProcess( NULL, Args, NULL, NULL, FALSE,
|
||||
CREATE_NEW_CONSOLE,
|
||||
NULL,
|
||||
NULL,
|
||||
&StartupInfo,
|
||||
&ProcessInfo))
|
||||
{
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
|
||||
if(!GetExitCodeProcess(ProcessInfo.hProcess, &rc))
|
||||
rc = 0;
|
||||
|
||||
CloseHandle(ProcessInfo.hThread);
|
||||
CloseHandle(ProcessInfo.hProcess);
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Globals for the Routines pt_popen() / pt_pclose()
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
CRITICAL_SECTION lock;
|
||||
#define LOCK() EnterCriticalSection(&lock);
|
||||
#define UNLOCK() LeaveCriticalSection(&lock);
|
||||
|
||||
static void
|
||||
pt_init()
|
||||
{ InitializeCriticalSection(&lock);
|
||||
}
|
||||
|
||||
|
||||
typedef struct pipe_context
|
||||
{ struct pipe_context *next;
|
||||
FILE *fd;
|
||||
HANDLE in[2];
|
||||
HANDLE out[2];
|
||||
HANDLE err[2];
|
||||
char mode; /* 'r' or 'w' */
|
||||
} pipe_context;
|
||||
|
||||
|
||||
static pipe_context *pipes = NULL;
|
||||
|
||||
static pipe_context *
|
||||
allocPipeContext()
|
||||
{ pipe_context *pc = malloc(sizeof(*pc));
|
||||
|
||||
if ( !pc )
|
||||
return NULL;
|
||||
|
||||
pc->in[0] = INVALID_HANDLE_VALUE;
|
||||
pc->in[1] = INVALID_HANDLE_VALUE;
|
||||
pc->out[0] = INVALID_HANDLE_VALUE;
|
||||
pc->out[1] = INVALID_HANDLE_VALUE;
|
||||
pc->err[0] = INVALID_HANDLE_VALUE;
|
||||
pc->err[1] = INVALID_HANDLE_VALUE;
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
discardPipeContext(pipe_context *pc)
|
||||
{ if (pc->in[0] != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(pc->in[0]);
|
||||
if (pc->in[1] != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(pc->in[1]);
|
||||
if (pc->out[0] != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(pc->out[0]);
|
||||
if (pc->out[1] != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(pc->out[1]);
|
||||
if (pc->err[0] != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(pc->err[0]);
|
||||
if (pc->err[1] != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(pc->err[1]);
|
||||
|
||||
free(pc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
linkPipeContext(pipe_context *pc)
|
||||
{ LOCK();
|
||||
pc->next = pipes;
|
||||
pipes = pc;
|
||||
UNLOCK();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
my_pipe(HANDLE *readwrite)
|
||||
{
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
|
||||
sa.nLength = sizeof(sa); /* Length in bytes */
|
||||
sa.bInheritHandle = 1; /* the child must inherit these handles */
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
|
||||
if (! CreatePipe (&readwrite[0],&readwrite[1],&sa,1 << 13))
|
||||
{
|
||||
errno = -1; /* EMFILE; que? */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Replacement for 'popen()' under Windows.
|
||||
|
||||
cmd is taken to be encoded in UTF-8 for compatibility with the Unix
|
||||
version.
|
||||
|
||||
NOTE: if cmd contains '2>&1', we connect the standard error file handle
|
||||
to the standard output file handle.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
utf8towcs(wchar_t *o, const char *src)
|
||||
{ for( ; *src; )
|
||||
{ int wc;
|
||||
|
||||
src = utf8_get_char(src, &wc);
|
||||
*o++ = wc;
|
||||
}
|
||||
*o = 0;
|
||||
}
|
||||
|
||||
|
||||
FILE *
|
||||
pt_popen(const char *cmd, const char *mode)
|
||||
{ FILE *fptr = NULL;
|
||||
PROCESS_INFORMATION piProcInfo;
|
||||
STARTUPINFOW siStartInfo;
|
||||
int success, redirect_error = 0;
|
||||
wchar_t *wcmd = NULL;
|
||||
wchar_t *err2out;
|
||||
pipe_context *pc;
|
||||
|
||||
size_t utf8len = utf8_strlen(cmd, strlen(cmd));
|
||||
if ( !(wcmd = malloc((utf8len+1)*sizeof(wchar_t))) )
|
||||
{ return NULL;
|
||||
}
|
||||
utf8towcs(wcmd, cmd);
|
||||
|
||||
if ( !(pc=allocPipeContext()) )
|
||||
goto finito;
|
||||
if ( !mode || !*mode )
|
||||
goto finito;
|
||||
pc->mode = *mode;
|
||||
if ( pc->mode != 'r' && pc->mode != 'w' )
|
||||
goto finito;
|
||||
|
||||
/*
|
||||
* Shall we redirect stderr to stdout ? */
|
||||
if ( (err2out=wcsstr(wcmd, L"2>&1")) != NULL)
|
||||
{ /* this option doesn't apply to win32 shells, so we clear it out! */
|
||||
wcsncpy(err2out, L" ", 4);
|
||||
redirect_error = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the Pipes... */
|
||||
if (my_pipe(pc->in) == -1 ||
|
||||
my_pipe(pc->out) == -1)
|
||||
goto finito;
|
||||
if ( !redirect_error )
|
||||
{ if ( my_pipe(pc->err) == -1)
|
||||
goto finito;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now create the child process */
|
||||
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
|
||||
siStartInfo.cb = sizeof(STARTUPINFO);
|
||||
siStartInfo.hStdInput = pc->in[0];
|
||||
siStartInfo.hStdOutput = pc->out[1];
|
||||
if ( redirect_error )
|
||||
siStartInfo.hStdError = pc->out[1];
|
||||
else
|
||||
siStartInfo.hStdError = pc->err[1];
|
||||
siStartInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||
|
||||
success = CreateProcessW(NULL,
|
||||
wcmd, // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
CREATE_NO_WINDOW, // creation flags: without window (?)
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&piProcInfo); // receives PROCESS_INFORMATION
|
||||
|
||||
if ( !success )
|
||||
goto finito;
|
||||
|
||||
CloseHandle(piProcInfo.hThread);
|
||||
CloseHandle(piProcInfo.hProcess);
|
||||
|
||||
/*
|
||||
* These handles listen to the Child process */
|
||||
CloseHandle(pc->in[0]); pc->in[0] = INVALID_HANDLE_VALUE;
|
||||
CloseHandle(pc->out[1]); pc->out[1] = INVALID_HANDLE_VALUE;
|
||||
if ( pc->err[1] != INVALID_HANDLE_VALUE )
|
||||
{ CloseHandle(pc->err[1]);
|
||||
pc->err[1] = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if ( pc->mode == 'r' )
|
||||
fptr = _fdopen(_open_osfhandle((long)pc->out[0],_O_BINARY),"r");
|
||||
else
|
||||
fptr = _fdopen(_open_osfhandle((long)pc->in[1],_O_BINARY),"w");
|
||||
|
||||
finito:
|
||||
if ( fptr )
|
||||
{ pc->fd = fptr;
|
||||
linkPipeContext(pc);
|
||||
} else
|
||||
{ if ( pc )
|
||||
discardPipeContext(pc);
|
||||
}
|
||||
if ( wcmd )
|
||||
free(wcmd);
|
||||
|
||||
return fptr;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Replacement for 'pclose()' under Win32
|
||||
------------------------------------------------------------------------------*/
|
||||
int
|
||||
pt_pclose(FILE *fd)
|
||||
{ pipe_context **ppc;
|
||||
int rc;
|
||||
|
||||
if ( !fd )
|
||||
{ errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = fclose(fd);
|
||||
LOCK();
|
||||
for(ppc = &pipes; *ppc; ppc=&(*ppc)->next)
|
||||
{ pipe_context *pc = *ppc;
|
||||
|
||||
if ( pc->fd == fd )
|
||||
{ *ppc = pc->next;
|
||||
|
||||
UNLOCK();
|
||||
if ( pc->err[0] != INVALID_HANDLE_VALUE )
|
||||
CloseHandle(pc->err[0]);
|
||||
if ( pc->mode == 'r' )
|
||||
{ CloseHandle(pc->in[1]);
|
||||
} else
|
||||
{ CloseHandle(pc->out[0]);
|
||||
}
|
||||
|
||||
free(pc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK();
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user