This uses a thread, to prevent hanging:
run_sh_command(StrCmd, OutputLines, ErrorLines, ExitCode) :-
run_command([sh, '-ce', StrCmd], OutputLines, ErrorLines, ExitCode).
run_command(LstCmd, OutputLines, ErrorLines, ExitCode) :-
LstCmd = [ExeName|Args],
setup_call_cleanup(
message_queue_create(ErrorQueue),
setup_call_cleanup(
process_create(
path(ExeName), Args, [
process(PID),
stdout(pipe(OutputStream)),
stderr(pipe(ErrorStream))
]
),
( thread_create(
( read_stream_lines(ErrorStream, ErrorLines),
thread_send_message(ErrorQueue, ErrorLines)
),
ThreadId
),
read_stream_lines(OutputStream, OutputLines),
process_wait(PID, ExitCode),
thread_join(ThreadId),
thread_get_message(ErrorQueue, ErrorLines)
),
( close(OutputStream),
close(ErrorStream)
)
),
message_queue_destroy(ErrorQueue)
).
read_stream_lines(Stream, Lines) :-
read_line_to_codes(Stream, Line1),
read_stream_lines_(Line1, Stream, Lines).
read_stream_lines_(end_of_file, _, Lines) :-
!,
Lines = [].
read_stream_lines_(Codes, Stream, [Line|Lines]) :-
atom_codes(Line, Codes),
read_line_to_codes(Stream, Line2),
read_stream_lines_(Line2, Stream, Lines).