#include <string.h>
#include <errno.h>
#include <stdio.h>
+ #include <unistd.h>
+ #include <sys/wait.h>
+ #include <signal.h>
+`}
+
+in "C Header" `{
+ #include <sys/types.h>
+
+ // FIXME this should be in the "C" block when bug on module blocks is fixed
+ // or, even better, replace the C structure by a Nit object.
+ typedef struct se_exec_data se_exec_data_t;
+ struct se_exec_data {
+ pid_t id;
+ int running;
+ int status;
+ int in_fd;
+ int out_fd;
+ int err_fd;
+ };
`}
# Simple sub-process
redef fun pipeflags do return 3
- redef fun execute
+ redef fun execute do super
+
+ # Write `input` to process and return its output
+ #
+ # Writing and reading are processed line by line,
+ # reading only when something is available.
+ #
+ # ~~~
+ # var proc = new ProcessDuplex("tr", "[:lower:]", "[:upper:]")
+ # assert proc.write_and_read("""
+ # Alice
+ # Bob
+ # """) == """
+ # ALICE
+ # BOB
+ # """
+ # ~~~
+ fun write_and_read(input: Text): String
do
- super
+ var read = new Buffer #new Array[String]
+
+ # Main loop, read and write line by line
+ var prev = 0
+ for delimiter in input.search_all('\n') do
+ write input.substring(prev, delimiter.after-prev)
+ prev = delimiter.after
+
+ while stream_in.poll_in do
+ read.append stream_in.read_line
+ end
+ end
+
+ # Write the last line
+ write input.substring_from(prev)
+ stream_out.close
+
+ # Read the rest, may be everything for some programs
+ read.append stream_in.read_all
+ stream_in.close
+
+ # Clean up
+ wait
+ return read.to_s
end
end
`}
end
-private extern class NativeProcess
- fun id: Int is extern "exec_NativeProcess_NativeProcess_id_0"
+private extern class NativeProcess `{ se_exec_data_t* `}
+
+ fun id: Int `{ return self->id; `}
+ fun status: Int `{ return self->status; `}
+ fun in_fd: Int `{ return self->in_fd; `}
+ fun out_fd: Int `{ return self->out_fd; `}
+ fun err_fd: Int `{ return self->err_fd; `}
fun is_finished: Bool `{
int result = (int)0;
return result;
`}
- fun status: Int is extern "exec_NativeProcess_NativeProcess_status_0"
fun wait `{
int status;
if (self->running) {
self->running = 0;
}
`}
-
- fun in_fd: Int is extern "exec_NativeProcess_NativeProcess_in_fd_0"
- fun out_fd: Int is extern "exec_NativeProcess_NativeProcess_out_fd_0"
- fun err_fd: Int is extern "exec_NativeProcess_NativeProcess_err_fd_0"
end