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-stream.c $(srcdir)/pl-string.c \
|
||||||
$(srcdir)/pl-table.c \
|
$(srcdir)/pl-table.c \
|
||||||
$(srcdir)/pl-text.c $(srcdir)/pl-utf8.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 \
|
OBJS=pl-buffer.o pl-ctype.o pl-error.o pl-feature.o \
|
||||||
pl-file.o pl-os.o \
|
pl-file.o pl-os.o \
|
||||||
pl-stream.o pl-string.o pl-table.o pl-text.o pl-utf8.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@
|
SOBJS=plstream@SHLIB_SUFFIX@
|
||||||
|
|
||||||
#in some systems we just create a single object, in others we need to
|
#in some systems we just create a single object, in others we need to
|
||||||
@ -61,48 +61,16 @@ SOBJS=plstream@SHLIB_SUFFIX@
|
|||||||
|
|
||||||
all: $(SOBJS)
|
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
|
uxnt.o: $(srcdir)/uxnt/uxnt.c
|
||||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/uxnt/uxnt.c -o uxnt.o
|
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/uxnt/uxnt.c -o uxnt.o
|
||||||
|
|
||||||
utf8.o: $(srcdir)/uxnt/utf8.c
|
utf8.o: $(srcdir)/uxnt/utf8.c
|
||||||
$(CC) -c $(CFLAGS) $(SHLIB_CFLAGS) $(srcdir)/uxnt/utf8.c -o utf8.o
|
$(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_SUFFIX@: %.o
|
||||||
@DO_SECOND_LD@ @SHLIB_LD@ -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) |\
|
makedepend -f - -- $(CFLAGS) -I$(srcdir)/../../H -I$(srcdir)/../../include -- $(C_SOURCES) |\
|
||||||
sed 's|.*/\([^:]*\):|\1:|' >> Makefile ;\
|
sed 's|.*/\([^:]*\):|\1:|' >> Makefile ;\
|
||||||
fi
|
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