improve system library.

git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@113 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
vsc 2001-06-29 19:30:25 +00:00
parent 54185708f9
commit 3de3c1b7d2
7 changed files with 6375 additions and 2567 deletions

View File

@ -112,7 +112,7 @@ YapA(int i)
X_API Bool X_API Bool
YapIsIntTerm(Term t) YapIsIntTerm(Term t)
{ {
return (IsIntTerm(t) || IsLongIntTerm(t)); return (IsIntegerTerm(t));
} }
X_API Bool X_API Bool

View File

@ -106,7 +106,11 @@ typedef struct
Int pos; Int pos;
} mem_string; } mem_string;
struct { struct {
#if defined(__MINGW32__) || _MSC_VER
HANDLE hdl;
#else
int fd; int fd;
#endif
} pipe; } pipe;
#if USE_SOCKET #if USE_SOCKET
struct { struct {
@ -687,7 +691,17 @@ ConsolePipePutc (int sno, int ch)
ch = '\n'; ch = '\n';
} }
#endif #endif
#if _MSC_VER || defined(__MINGW32__)
{
DWORD written;
if (WriteFile(s->u.pipe.hdl, &c, sizeof(c), &written, NULL) == FALSE) {
PlIOError (SYSTEM_ERROR,TermNil, "write to pipe returned error");
return(EOF);
}
}
#else
write(s->u.pipe.fd, &c, sizeof(c)); write(s->u.pipe.fd, &c, sizeof(c));
#endif
count_output_char(ch,s,sno); count_output_char(ch,s,sno);
return ((int) ch); return ((int) ch);
} }
@ -703,7 +717,17 @@ PipePutc (int sno, int ch)
ch = '\n'; ch = '\n';
} }
#endif #endif
#if _MSC_VER || defined(__MINGW32__)
{
DWORD written;
if (WriteFile(s->u.pipe.hdl, &c, sizeof(c), &written, NULL) == FALSE) {
PlIOError (SYSTEM_ERROR,TermNil, "write to pipe returned error");
return(EOF);
}
}
#else
write(s->u.pipe.fd, &c, sizeof(c)); write(s->u.pipe.fd, &c, sizeof(c));
#endif
console_count_output_char(ch,s,sno); console_count_output_char(ch,s,sno);
return ((int) ch); return ((int) ch);
} }
@ -1082,9 +1106,18 @@ PipeGetc(int sno)
register StreamDesc *s = &Stream[sno]; register StreamDesc *s = &Stream[sno];
register int ch; register int ch;
char c; char c;
int count;
/* should be able to use a buffer */ /* should be able to use a buffer */
#if _MSC_VER || defined(__MINGW32__)
DWORD count;
if (WriteFile(s->u.pipe.hdl, &c, sizeof(c), &count, NULL) == FALSE) {
PlIOError (SYSTEM_ERROR,TermNil, "read from pipe returned error");
return(EOF);
}
#else
int count;
count = read(s->u.pipe.fd, &c, sizeof(char)); count = read(s->u.pipe.fd, &c, sizeof(char));
#endif
printf("reading from pipe %c\n", c);
if (count == 0) { if (count == 0) {
ch = EOF; ch = EOF;
} else if (count > 0) { } else if (count > 0) {
@ -1106,7 +1139,11 @@ ConsolePipeGetc(int sno)
register StreamDesc *s = &Stream[sno]; register StreamDesc *s = &Stream[sno];
register int ch; register int ch;
char c; char c;
#if _MSC_VER || defined(__MINGW32__)
DWORD count;
#else
int count; int count;
#endif
/* send the prompt away */ /* send the prompt away */
if (newline) { if (newline) {
@ -1118,8 +1155,15 @@ ConsolePipeGetc(int sno)
strncpy(Prompt, RepAtom (*AtPrompt)->StrOfAE, MAX_PROMPT); strncpy(Prompt, RepAtom (*AtPrompt)->StrOfAE, MAX_PROMPT);
newline = FALSE; newline = FALSE;
} }
#if _MSC_VER || defined(__MINGW32__)
if (WriteFile(s->u.pipe.hdl, &c, sizeof(c), &count, NULL) == FALSE) {
PlIOError (SYSTEM_ERROR,TermNil, "read from pipe returned error");
return(EOF);
}
#else
/* should be able to use a buffer */ /* should be able to use a buffer */
count = read(s->u.pipe.fd, &c, sizeof(char)); count = read(s->u.pipe.fd, &c, sizeof(char));
#endif
if (count == 0) { if (count == 0) {
ch = EOF; ch = EOF;
} else if (count > 0) { } else if (count > 0) {
@ -1323,7 +1367,11 @@ GetStreamFd(int sno)
} else } else
#endif #endif
if (Stream[sno].status & Pipe_Stream_f) { if (Stream[sno].status & Pipe_Stream_f) {
#if _MSC_VER || defined(__MINGW32__)
return((int)(Stream[sno].u.pipe.hdl));
#else
return(Stream[sno].u.pipe.fd); return(Stream[sno].u.pipe.fd);
#endif
} else if (Stream[sno].status & InMemory_Stream_f) { } else if (Stream[sno].status & InMemory_Stream_f) {
return(-1); return(-1);
} }
@ -1762,16 +1810,25 @@ p_open_pipe_stream (void)
Term t1, t2; Term t1, t2;
StreamDesc *st; StreamDesc *st;
int sno; int sno;
int filedes[2];
#if _MSC_VER || defined(__MINGW32__) #if _MSC_VER || defined(__MINGW32__)
if (_pipe(filedes, 256, O_TEXT) == -1) HANDLE ReadPipe, WritePipe;
#else SECURITY_ATTRIBUTES satt;
if (pipe(filedes) != 0)
#endif satt.nLength = sizeof(satt);
satt.lpSecurityDescriptor = NULL;
satt.bInheritHandle = TRUE;
if (!CreatePipe(&ReadPipe, &WritePipe, &satt, 0))
{ {
return (PlIOError (SYSTEM_ERROR,TermNil, "open_pipe_stream/2 could not create pipe")); return (PlIOError (SYSTEM_ERROR,TermNil, "open_pipe_stream/2 could not create pipe"));
} }
#else
int filedes[2];
if (pipe(filedes) != 0)
{
return (PlIOError (SYSTEM_ERROR,TermNil, "open_pipe_stream/2 could not create pipe"));
}
#endif
for (sno = 0; sno < MaxStreams; ++sno) for (sno = 0; sno < MaxStreams; ++sno)
if (Stream[sno].status & Free_Stream_f) if (Stream[sno].status & Free_Stream_f)
break; break;
@ -1784,8 +1841,15 @@ p_open_pipe_stream (void)
st->linecount = 1; st->linecount = 1;
st->stream_putc = PipePutc; st->stream_putc = PipePutc;
st->stream_getc = PipeGetc; st->stream_getc = PipeGetc;
st->stream_getc_for_read = PipeGetc; if (CharConversionTable != NULL)
st->stream_getc_for_read = ISOGetc;
else
st->stream_getc_for_read = PipeGetc;
#if _MSC_VER || defined(__MINGW32__)
st->u.pipe.hdl = ReadPipe;
#else
st->u.pipe.fd = filedes[0]; st->u.pipe.fd = filedes[0];
#endif
t1 = MkStream (sno); t1 = MkStream (sno);
for (; sno < MaxStreams; ++sno) for (; sno < MaxStreams; ++sno)
if (Stream[sno].status & Free_Stream_f) if (Stream[sno].status & Free_Stream_f)
@ -1803,7 +1867,11 @@ p_open_pipe_stream (void)
st->stream_getc_for_read = ISOGetc; st->stream_getc_for_read = ISOGetc;
else else
st->stream_getc_for_read = st->stream_getc; st->stream_getc_for_read = st->stream_getc;
#if _MSC_VER || defined(__MINGW32__)
st->u.pipe.hdl = WritePipe;
#else
st->u.pipe.fd = filedes[1]; st->u.pipe.fd = filedes[1];
#endif
t2 = MkStream (sno); t2 = MkStream (sno);
return (unify (ARG1, t1) && unify (ARG2, t2)); return (unify (ARG1, t1) && unify (ARG2, t2));
} }
@ -2234,8 +2302,13 @@ CloseStreams (int loud)
continue; continue;
if ((Stream[sno].status & Popen_Stream_f)) if ((Stream[sno].status & Popen_Stream_f))
pclose (Stream[sno].u.file.file); pclose (Stream[sno].u.file.file);
if ((Stream[sno].status & (Pipe_Stream_f|Socket_Stream_f))) #if _MSC_VER || defined(__MINGW32__)
if (Stream[sno].status & Pipe_Stream_f)
CloseHandle (Stream[sno].u.pipe.hdl);
#else
if (Stream[sno].status & (Pipe_Stream_f|Socket_Stream_f))
close (Stream[sno].u.pipe.fd); close (Stream[sno].u.pipe.fd);
#endif
#if USE_SOCKET #if USE_SOCKET
else if (Stream[sno].status & (Socket_Stream_f)) { else if (Stream[sno].status & (Socket_Stream_f)) {
CloseSocket(Stream[sno].u.socket.fd, CloseSocket(Stream[sno].u.socket.fd,
@ -2274,8 +2347,12 @@ CloseStream(int sno)
Stream[sno].u.socket.domain); Stream[sno].u.socket.domain);
} }
#endif #endif
else if (Stream[sno].status & (Pipe_Stream_f)) { else if (Stream[sno].status & Pipe_Stream_f) {
#if _MSC_VER || defined(__MINGW32__)
CloseHandle (Stream[sno].u.pipe.hdl);
#else
close(Stream[sno].u.pipe.fd); close(Stream[sno].u.pipe.fd);
#endif
} }
else if (Stream[sno].status & (InMemory_Stream_f)) { else if (Stream[sno].status & (InMemory_Stream_f)) {
FreeAtomSpace(Stream[sno].u.mem_string.buf); FreeAtomSpace(Stream[sno].u.mem_string.buf);
@ -4612,7 +4689,11 @@ StreamToFileNo(Term t)
int sno = int sno =
CheckStream(t, (Input_Stream_f|Output_Stream_f), "StreamToFileNo"); CheckStream(t, (Input_Stream_f|Output_Stream_f), "StreamToFileNo");
if (Stream[sno].status & Pipe_Stream_f) { if (Stream[sno].status & Pipe_Stream_f) {
#if _MSC_VER || defined(__MINGW32__)
return((int)(Stream[sno].u.pipe.hdl));
#else
return(Stream[sno].u.pipe.fd); return(Stream[sno].u.pipe.fd);
#endif
} else if (Stream[sno].status & Socket_Stream_f) { } else if (Stream[sno].status & Socket_Stream_f) {
return(Stream[sno].u.socket.fd); return(Stream[sno].u.socket.fd);
} else if (Stream[sno].status & (Null_Stream_f|InMemory_Stream_f)) { } else if (Stream[sno].status & (Null_Stream_f|InMemory_Stream_f)) {

13
TO_DO
View File

@ -1,16 +1,14 @@
BEFORE 4.4: BEFORE 4.4:
- mixed constraints and delays. - mixed attributes and delays.
- write infinite terms - write infinite terms
- constraints in DB. - constraints in DB.
- fix SBA plus co-routining - fix SBA plus co-routining
- non-void temporaries going to global - non-void temporaries going to global
- interrupt handling in WIN32
- timestamps on files. - timestamps on files.
- warnings in documentation file. - warnings in documentation file.
- system library - system library
- fix restore when code is moved around. - fix restore when code is moved around.
- library(system) for WIN32 - library(system) for WIN32
- document system(library)
- document new interface functions. - document new interface functions.
- ^C can break code. - ^C can break code.
- add more precision when outputting floats. - add more precision when outputting floats.
@ -26,6 +24,11 @@ TABLING
- make gc work after mutable var changes. - make gc work after mutable var changes.
- knap-sack - knap-sack
PARALLELISM
- copying: Fix stack copying after new stack.
- SBA: fix constraint and unification.
- IAP.
AFTER 4.4(?) AFTER 4.4(?)
- change compilation order for arguments - change compilation order for arguments
- fix code for arithmetic - fix code for arithmetic
@ -35,6 +38,8 @@ AFTER 4.4(?)
- garbage collector cleans up clauses and logical update DB. - garbage collector cleans up clauses and logical update DB.
- atom garbage collector. - atom garbage collector.
- lpdoc. - lpdoc.
- incremental garbage collector.
- threads.
DONE: DONE:
- compilation of bignums. - compilation of bignums.
@ -78,3 +83,5 @@ DONE:
- deterministic trail entries for multi-assignment variables. - deterministic trail entries for multi-assignment variables.
- weird going ons with prompt and readline - weird going ons with prompt and readline
- check library(random) - check library(random)
- document system(library)
- interrupt handling in WIN32

View File

@ -16,6 +16,9 @@
<h2>Yap-4.3.19:</h2> <h2>Yap-4.3.19:</h2>
<ul> <ul>
<li>FIXED: get_list + unify_local was being compiled into
glval, breaking ENV vars </li>
<li>FIXED: abort was crashing in Alpha machines.</li>
<li>FIXED: make ^c-a work within gc.</li> <li>FIXED: make ^c-a work within gc.</li>
<li>FIXED: handle correctly very deep nested terms while gc <li>FIXED: handle correctly very deep nested terms while gc
marking.</li> marking.</li>

8589
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -39,6 +39,7 @@ v/*************************************************************************
shell/1, shell/1,
shell/2, shell/2,
sleep/1, sleep/1,
system/0,
system/1, system/1,
system/2, system/2,
time/1, time/1,
@ -218,55 +219,84 @@ working_directory(OLD, NEW) :-
% %
exec(Command, [StdIn, StdOut, StdErr], PID) :- exec(Command, [StdIn, StdOut, StdErr], PID) :-
G = exec(Command, [StdIn, StdOut, StdErr], PID), G = exec(Command, [StdIn, StdOut, StdErr], PID),
check_command(Command, G), check_command_with_default_shell(Command, TrueCommand, G),
process_inp_stream_for_exec(StdIn, In, G), process_inp_stream_for_exec(StdIn, In, G, [], L1),
process_out_stream_for_exec(StdOut, Out, G), process_out_stream_for_exec(StdOut, Out, G, L1, L2),
process_err_stream_for_exec(StdErr, Err, G), process_err_stream_for_exec(StdErr, Err, G, L2, L3),
( exec_command(Command, In, Out, Err, PID, Error) -> true ; true ), ( exec_command(TrueCommand, In, Out, Err, PID, Error) -> true ; true ),
close_temp_streams(StdIn, In, StdOut, Out, StdErr, Err), close_temp_streams(L3),
handle_system_error(Error, off, G). handle_system_error(Error, off, G).
process_inp_stream_for_exec(Error, _, G) :- var(Error), !, process_inp_stream_for_exec(Error, _, G, L, L) :- var(Error), !,
throw(error(instantiation_error,G)). throw(error(instantiation_error,G)).
process_inp_stream_for_exec(null, 0, _) :- !. process_inp_stream_for_exec(null, null, _, L, L) :- !.
process_inp_stream_for_exec(std, '$stream'(0), _) :- !. process_inp_stream_for_exec(std, 0, _, L, L) :- !.
process_inp_stream_for_exec(pipe(SOut), SInp, _) :- !, process_inp_stream_for_exec(pipe(ForWriting), ForReading, _, L, [ForReading|L]) :- !,
open_pipe_streams(SInp, SOut). open_pipe_streams(ForReading, ForWriting).
process_inp_stream_for_exec(Stream, Stream, _) :- process_inp_stream_for_exec(Stream, Stream, _, L, L) :-
stream_property(Stream, input). stream_property(Stream, input).
process_out_stream_for_exec(Error, _, G) :- var(Error), !, process_out_stream_for_exec(Error, _, G, L, L) :- var(Error), !,
throw(error(instantiation_error,G)). throw(error(instantiation_error,G)).
process_out_stream_for_exec(null, 0, _) :- !. process_out_stream_for_exec(null, null, _, L, L) :- !.
process_out_stream_for_exec(std, '$stream'(1), _) :- !. process_out_stream_for_exec(std, 1, _, L, L) :- !.
process_out_stream_for_exec(pipe(SInp), SOut, _) :- !, process_out_stream_for_exec(pipe(ForReading), ForWriting, _, L, [ForWriting|L]) :- !,
open_pipe_streams(SInp, SOut). open_pipe_streams(ForReading, ForWriting).
process_out_stream_for_exec(Stream, Stream, _) :- process_out_stream_for_exec(Stream, Stream, _, L, L) :-
stream_property(Stream, output). stream_property(Stream, output).
process_err_stream_for_exec(Error, _, G) :- var(Error), !, process_err_stream_for_exec(Error, _, G, L, L) :- var(Error), !,
throw(error(instantiation_error,G)). throw(error(instantiation_error,G)).
process_err_stream_for_exec(null, 0, _) :- !. process_err_stream_for_exec(null, null, _, L, L) :- !.
process_err_stream_for_exec(std, '$stream'(2), _) :- !. process_err_stream_for_exec(std, 2, _, L, L) :- !.
process_err_stream_for_exec(pipe(SInp), SOut, _) :- !, process_err_stream_for_exec(pipe(ForReading), ForWriting, _, L, [ForWriting|L]) :- !,
open_pipe_streams(SInp, SOut). open_pipe_streams(ForReading, ForWriting).
process_err_stream_for_exec(Stream, Stream, _) :- process_err_stream_for_exec(Stream, Stream, _, L, L) :-
stream_property(Stream, output). stream_property(Stream, output).
close_temp_streams(pipe(_), S, _, _, _, _) :- close(S), fail. close_temp_streams([]).
close_temp_streams(_, _, pipe(_), S, _, _) :- close(S), fail. close_temp_streams([S|Ss]) :- close(S),
close_temp_streams(_, _, _, _, pipe(_), S) :- close(S), fail. close_temp_streams(Ss).
close_temp_streams(_, _, _, _, _, _).
popen(Command, Mode, Stream) :- popen(Command, Mode, Stream) :-
G = popen(Command, Mode, Stream), G = popen(Command, Mode, Stream),
check_command(Command, G), check_command_with_default_shell(Command, TrueCommand, G),
check_mode(Mode, M, G), check_mode(Mode, M, G),
popen(Command, M, Stream, Result), do_popen(TrueCommand, M, Stream, Result),
handle_system_error(Result, off, G). handle_system_error(Result, off, G).
do_popen(Command, M, Stream, Result) :- win, !,
win_popen(M, Command, Stream, Result).
do_popen(Command, M, Stream, Result) :-
popen(Command, M, Stream, Result).
win_popen(0, Command, ForReading, Result) :-
open_pipe_streams(ForReading, ForWriting),
exec_command(Command, 0, ForWriting, 2, _, Result),
close(ForWriting).
win_popen(1, Command, ForWriting, Result) :-
open_pipe_streams(Stream, ForWriting),
exec_command(Command, ForReading, 1, 2, _, Result),
close(ForReading).
check_command_with_default_shell(Com, ComF, G) :-
check_command(Com, G),
os_command_postprocess(Com, ComF).
%
% make sure that Windows executes the command from $COMSPEC.
%
os_command_postprocess(Com, ComF) :- win, !,
atom_codes(Com, SC),
append(" /c ", SC, SC1),
getenv('COMSPEC', Shell0),
atom_codes(Shell0, Codes),
append(Codes, SC1, SCF),
atom_codes(ComF, SCF).
os_command_postprocess(Com, Com).
check_command(Com, G) :- var(Com), !, check_command(Com, G) :- var(Com), !,
throw(error(instantiation_error,G)). throw(error(instantiation_error,G)).
check_command(Com, _) :- atom(Com), !. check_command(Com, _) :- atom(Com), !.
@ -283,7 +313,7 @@ check_mode(Mode, G) :-
shell :- shell :-
G = shell, G = shell,
get_shell0(FullCommand), get_shell0(FullCommand),
exec_command(FullCommand, '$stream'(0),'$stream'(1), '$stream'(2), PID, Error), exec_command(FullCommand, 0, 1, 2, PID, Error),
handle_system_error(Error, off, G), handle_system_error(Error, off, G),
wait(PID, _Status, Error), wait(PID, _Status, Error),
handle_system_error(Error, off, G). handle_system_error(Error, off, G).
@ -295,7 +325,7 @@ shell(Command) :-
atom_codes(Command, SC), atom_codes(Command, SC),
append(Shell, SC, ShellCommand), append(Shell, SC, ShellCommand),
atom_codes(FullCommand, ShellCommand), atom_codes(FullCommand, ShellCommand),
exec_command(FullCommand, '$stream'(0),'$stream'(1), '$stream'(2), PID, Error), exec_command(FullCommand, 0, 1, 2, PID, Error),
handle_system_error(Error, off, G), handle_system_error(Error, off, G),
wait(PID, _Status, Error), wait(PID, _Status, Error),
handle_system_error(Error, off, G). handle_system_error(Error, off, G).
@ -307,7 +337,7 @@ shell(Command, Status) :-
atom_codes(Command, SC), atom_codes(Command, SC),
append(Shell, SC, ShellCommand), append(Shell, SC, ShellCommand),
atom_codes(FullCommand, ShellCommand), atom_codes(FullCommand, ShellCommand),
exec_command(FullCommand, '$stream'(0),'$stream'(1), '$stream'(2), PID, Error), exec_command(FullCommand, 0, 1, 2, PID, Error),
handle_system_error(Error, off, G), handle_system_error(Error, off, G),
wait(PID, Status,Error), wait(PID, Status,Error),
handle_system_error(Error, off, G). handle_system_error(Error, off, G).
@ -315,23 +345,36 @@ shell(Command, Status) :-
get_shell0(Shell) :- get_shell0(Shell) :-
getenv('SHELL', Shell), !. getenv('SHELL', Shell), !.
get_shell0(Shell) :- get_shell0(Shell) :-
win, win, !,
getenv('COMSPEC', Shell0). getenv('COMSPEC', Shell0).
get_shell0('/bin/sh').
get_shell(Shell) :- get_shell(Shell) :-
getenv('SHELL', Shell0), !, getenv('SHELL', Shell0), !,
atom_codes(Shell0, Codes), atom_codes(Shell0, Codes),
append(Codes," -c ", Shell). append(Codes," -c ", Shell).
get_shell(Shell) :- get_shell(Shell) :-
win, win, !,
getenv('COMPSEC', Shell0), getenv('COMSPEC', Shell0),
atom_codes(Shell0, Codes), atom_codes(Shell0, Codes),
append(Codes," /c ", Shell). append(Codes," /c ", Shell).
get_shell("/bin/sh -c").
system :-
default_shell(Command),
do_system(Command, _Status, Error),
handle_system_error(Error, off, system).
default_shell(Shell) :- win, !,
getenv('COMSPEC', Shell).
default_shell('/bin/sh').
system(Command, Status) :- system(Command, Status) :-
G = system(Command, Status), G = system(Command, Status),
check_command(Command, G), check_command(Command, G),
do_system(Command, Status). do_system(Command, Status, Error),
handle_system_error(Error, off, G).
sleep(Interval) :- var(Interval), !, sleep(Interval) :- var(Interval), !,
throw(error(instantiation_error,sleep(Interval))). throw(error(instantiation_error,sleep(Interval))).

View File

@ -361,34 +361,40 @@ p_environ(void)
} }
#if defined(__MINGW32__) || _MSC_VER #if defined(__MINGW32__) || _MSC_VER
static int static HANDLE
get_handle(Term ti, int fd, Term tzero) get_handle(Term ti, DWORD fd)
{ {
if (ti == tzero) { if (IsAtomTerm(ti)) {
int new_fd = _dup(fd); HANDLE out;
_close(fd); SECURITY_ATTRIBUTES satt;
return(new_fd);
satt.nLength = sizeof(satt);
satt.lpSecurityDescriptor = NULL;
satt.bInheritHandle = TRUE;
out = CreateFile("NUL",
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
&satt,
OPEN_EXISTING,
0,
NULL);
return(out);
} else { } else {
int sd = YapStreamToFileNo(ti), new_fd; if (IsIntTerm(ti)) {
if (sd == fd) return(GetStdHandle(fd));
return(-1); } else
new_fd = _dup(fd); return((HANDLE)YapStreamToFileNo(ti));
_close(fd);
_dup2(sd, fd);
return(new_fd);
} }
} }
static void static void
restore_descriptor(int fd0, int fd, Term t, Term tzero) close_handle(Term ti, HANDLE h)
{ {
if (fd != -1) { if (IsAtomTerm(ti)) {
if (t != tzero) { CloseHandle(h);
_close(fd0);
}
_dup2(fd, fd0);
} }
} }
#endif #endif
/* execute a command as a detached process */ /* execute a command as a detached process */
@ -396,18 +402,29 @@ static int
execute_command(void) execute_command(void)
{ {
Term ti = ARG2, to = ARG3, te = ARG4; Term ti = ARG2, to = ARG3, te = ARG4;
Term tzero = MkIntTerm(0);
int res; int res;
int inpf, outf, errf;
#if defined(__MINGW32__) || _MSC_VER #if defined(__MINGW32__) || _MSC_VER
HANDLE inpf, outf, errf;
DWORD CreationFlags = 0; DWORD CreationFlags = 0;
STARTUPINFO StartupInfo; STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInformation; PROCESS_INFORMATION ProcessInformation;
inpf = get_handle(ti, 0, tzero); inpf = get_handle(ti, STD_INPUT_HANDLE);
outf = get_handle(to, 1, tzero); if (inpf == INVALID_HANDLE_VALUE) {
errf = get_handle(te, 2, tzero); return(unify(ARG6, WinError()));
if (inpf == -1 && outf == -1 && errf == -1) { }
/* we do not keep a curent stream */ outf = get_handle(to, STD_OUTPUT_HANDLE);
if (outf == INVALID_HANDLE_VALUE) {
close_handle(ti, inpf);
return(unify(ARG6, WinError()));
}
errf = get_handle(te, STD_OUTPUT_HANDLE);
if (errf == INVALID_HANDLE_VALUE) {
close_handle(ti, inpf);
close_handle(to, outf);
return(unify(ARG6, WinError()));
}
if (!IsIntTerm(ti) && !IsIntTerm(to) && !IsIntTerm(te)) {
/* we do not keep a current stream */
CreationFlags = DETACHED_PROCESS; CreationFlags = DETACHED_PROCESS;
} }
StartupInfo.cb = sizeof(STARTUPINFO); StartupInfo.cb = sizeof(STARTUPINFO);
@ -417,9 +434,9 @@ execute_command(void)
StartupInfo.dwFlags = STARTF_USESTDHANDLES; StartupInfo.dwFlags = STARTF_USESTDHANDLES;
StartupInfo.cbReserved2 = 0; StartupInfo.cbReserved2 = 0;
StartupInfo.lpReserved2 = NULL; StartupInfo.lpReserved2 = NULL;
StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); StartupInfo.hStdInput = inpf;
StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); StartupInfo.hStdOutput = outf;
StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); StartupInfo.hStdError = errf;
/* got stdin, stdout and error as I like it */ /* got stdin, stdout and error as I like it */
if (CreateProcess(NULL, if (CreateProcess(NULL,
AtomName(AtomOfTerm(ARG1)), AtomName(AtomOfTerm(ARG1)),
@ -431,19 +448,27 @@ execute_command(void)
NULL, NULL,
&StartupInfo, &StartupInfo,
&ProcessInformation) == FALSE) { &ProcessInformation) == FALSE) {
close_handle(ti, inpf);
close_handle(to, outf);
close_handle(te, errf);
return(unify(ARG6, WinError())); return(unify(ARG6, WinError()));
} }
restore_descriptor(0, inpf, ti, tzero); close_handle(ti, inpf);
restore_descriptor(1, outf, to, tzero); close_handle(to, outf);
restore_descriptor(2, errf, te, tzero); close_handle(te, errf);
res = ProcessInformation.dwProcessId; res = ProcessInformation.dwProcessId;
return(unify(ARG5,MkIntTerm(res))); return(unify(ARG5,MkIntTerm(res)));
#else /* UNIX CODE */ #else /* UNIX CODE */
int inpf, outf, errf;
/* process input first */ /* process input first */
if (ti == tzero) { if (IsAtomTerm(ti)) {
inpf = open("/dev/null", O_RDONLY); inpf = open("/dev/null", O_RDONLY);
} else { } else {
int sd = YapStreamToFileNo(ti); int sd;
if (IsIntTerm(ti))
sd = 0;
else
sd = YapStreamToFileNo(ti);
inpf = dup(sd); inpf = dup(sd);
} }
if (inpf < 0) { if (inpf < 0) {
@ -451,25 +476,36 @@ execute_command(void)
return(unify(ARG6, MkIntTerm(errno))); return(unify(ARG6, MkIntTerm(errno)));
} }
/* then output stream */ /* then output stream */
if (to == tzero) { if (IsAtomTerm(to)) {
outf = open("/dev/zero", O_WRONLY); outf = open("/dev/zero", O_WRONLY);
} else { } else {
int sd = YapStreamToFileNo(to); int sd;
if (IsIntTerm(to))
sd = 1;
else
sd = YapStreamToFileNo(to);
outf = dup(sd); outf = dup(sd);
} }
if (outf < 0) { if (outf < 0) {
/* return an error number */ /* return an error number */
close(inpf);
return(unify(ARG6, MkIntTerm(errno))); return(unify(ARG6, MkIntTerm(errno)));
} }
/* then error stream */ /* then error stream */
if (te == tzero) { if (IsAtomTerm(te)) {
errf = open("/dev/zero", O_WRONLY); errf = open("/dev/zero", O_WRONLY);
} else { } else {
int sd = YapStreamToFileNo(te); int sd;
if (IsIntTerm(te))
sd = 2;
else
sd = YapStreamToFileNo(te);
errf = dup(sd); errf = dup(sd);
} }
if (errf < 0) { if (errf < 0) {
/* return an error number */ /* return an error number */
close(inpf);
close(outf);
return(unify(ARG6, MkIntTerm(errno))); return(unify(ARG6, MkIntTerm(errno)));
} }
/* we are now ready to fork */ /* we are now ready to fork */
@ -518,6 +554,9 @@ do_system(void)
char *command = AtomName(AtomOfTerm(ARG1)); char *command = AtomName(AtomOfTerm(ARG1));
int sys = system(command); int sys = system(command);
#if HAVE_SYSTEM #if HAVE_SYSTEM
if (sys < 0) {
return(unify(ARG3,MkIntTerm(errno)));
}
return(unify(ARG2, MkIntTerm(sys))); return(unify(ARG2, MkIntTerm(sys)));
#endif #endif
} }
@ -730,7 +769,7 @@ init_sys(void)
UserCPredicate("dir_separator", dir_separator, 1); UserCPredicate("dir_separator", dir_separator, 1);
UserCPredicate("p_environ", p_environ, 2); UserCPredicate("p_environ", p_environ, 2);
UserCPredicate("exec_command", execute_command, 6); UserCPredicate("exec_command", execute_command, 6);
UserCPredicate("do_system", do_system, 2); UserCPredicate("do_system", do_system, 3);
UserCPredicate("popen", p_popen, 4); UserCPredicate("popen", p_popen, 4);
UserCPredicate("wait", p_wait, 3); UserCPredicate("wait", p_wait, 3);
UserCPredicate("host_name", host_name, 2); UserCPredicate("host_name", host_name, 2);