From: ahoward Date: 2003-05-14T05:35:56+09:00 Subject: Re: RCR for child execution On Tue, 13 May 2003, Simon Strandgaard wrote: > On Tue, 13 May 2003 23:44:53 +0900, Brian Candler wrote: > > > On Tue, May 13, 2003 at 06:50:54PM +0900, Simon Strandgaard wrote: > >> > In the general case, your Ruby program could do lots of things which force > >> > a direct output to stdout/stderr. Here is one small valid Ruby program: > >> > > >> > pid = fork do > >> > exec("ls /nonexistent") > >> > end > >> > Process.waitpid(pid) > >> > > >> > How are you going to modify Ruby so that the output of those four lines are > >> > captured in the sandbox? > >> > >> All "child-process" routines should parse rb_stdout to the children, in > >> this case fork. I know I have only mentioned system&backquote before. > >> Well all routines in Rubys Core which spawns children should do this. > > > > Not acceptable... this time I must insist that you answer the question :-) why must this be done in ruby simon? this can all be done from within c or c--: i think this does exactly what you want - it captures all output, including output from any child, from a ruby script run from within c. ----CODE---- #include #include #include #include #include #include #include #include "ruby.h" /* gcc redirect2.c -I /usr/local/ruby-1.6.6/ /usr/local/ruby-1.6.6/libruby.a -lm -ldl -lcrypt */ char *script = "system 'ls'\n" "`ls non-existent-file`\n" "system 'ls non-existent-file'\n" "STDOUT.puts 42\n" "STDERR.puts 42\n" "$defout.puts 42\n" "$stdout.puts 42\n" "$stderr.puts 42\n" "puts 42\n" "pid = fork {exec('ls /nonexistent')}\n" "Process.waitpid(pid)\n" ; int main (argc, argv) int argc; char **argv; { int fd[2]; int f; int __out, __err; int c; /* save */ assert ((__out = dup (STDOUT_FILENO)) != -1); assert ((__err = dup (STDERR_FILENO)) != -1); /* redirect */ assert (pipe (fd) == 0); assert (dup2 (fd[1], STDOUT_FILENO) != -1); assert (dup2 (fd[1], STDERR_FILENO) != -1); /* sandboxed */ ruby_init (); ruby_init_loadpath (); rb_eval_string (script); /* restore */ dup2 (__out, STDOUT_FILENO); dup2 (__err, STDERR_FILENO); /* display */ write (STDOUT_FILENO, "REDIRECTED:\n", 12); assert (close (fd[1]) != -1); while (read (fd[0], &c, 1) && write (STDOUT_FILENO, &c, 1)); assert (close (fd[0]) != -1); return (EXIT_SUCCESS); } ----CODE---- > Kernel#fork does spawn a child.. changes to Rubys Core is necessary. > unix-fork inherit stdin/stdout/stderr from parent to the child process. I > want Rubys Kernel#fork to inherit rb_stdin/rb_stdout/rb_stderr from the > parent to the child process. But hey.. unix-fork() does not take any > arguments. Is this possible? My guess - Yes this should be possible. Here > is some pseudo code. > > void Kernel#fork() { > backup_stdout = stdout; /* what i want */ > stdout = rb_stdout; /* what i want */ > pid = fork(); > if(pid == 0) > stdout = backup_stdout; /* what i want */ > } it is possible, but requires no changes to ruby's core, the above accomplishes this in c. > Again assignment to stdout is illegal.. freopen should be used. I just use > assignment in this pseudo-code in order to keep it simple. Further more > stderr/stdin is left out.. they should of cause also be redirected. if this is done using dup(2) - all is well in the world. > This way stdout/stderr/stdin should be untouched and remain usable in the > C/C++ application. this cannot be the case - but they are restored to their previous values. -a -- ==================================== | Ara Howard | NOAA Forecast Systems Laboratory | Information and Technology Services | Data Systems Group | R/FST 325 Broadway | Boulder, CO 80305-3328 | Email: ara.t.howard@fsl.noaa.gov | Phone: 303-497-7238 | Fax: 303-497-7259 ====================================