From: Brian Candler Date: 2003-05-13T16:32:09+09:00 Subject: Re: RCR for child execution On Tue, May 13, 2003 at 09:48:53AM +0900, Simon Strandgaard wrote: > I want users of the editor to be able to use thier own favorite ruby > snippets within the editor... *unmodified* ...they don't have to do popen > or Open3 or other ackward things for executing their favorite scripts. > All Ruby output should go to a text-buffer. You mean like irb? Maybe you should have a look at the source for FreeRIDE and see how it handles this. I haven't installed it, but it sounds like exactly the sort of integrated environment you're talking about, so they must have dealt with the problem you have encountered. > > In the general > > case, this is simply not possible whilst the Sandbox is in the same process > > as you, because it shares fd0/1/2 with the the main program (because both > > Ruby and C *are* part of the same program), and therefore the program has a > > way to write to fd0/1/2. > > Not agree.. I think this *is* possible. > Everytime Ruby spawns a child it should do like this: > > void system(command) { > pid=fork(); > if(pid != 0) { > stdout = rb_stdout; /* what im asking for */ > stderr = rb_stderr; /* what im asking for */ > stdin = rb_stdin; /* what im asking for */ > execv(command); > } > } What you have written cannot work: 1. stdout is a malloc'd FILE* object in the parent's memory space, which is destroyed immediately on exec. You need to modify the file descriptor table using dup2() instead 2. rb_stdout is a VALUE and stdout is a FILE* anyway. Two different things. 3. the file descriptor table holds Unix file descriptors. It cannot point to a Ruby object. If rb_stdout were a StringIO object, you could not possibly insert it into the FD table. You would have to put three pipes into the FD table instead, and the parent would talk down them. Or else a temporary file. But anyway, I wrote "in the general case", not "in the specific case of system() and backtick" 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? Another example would be require 'ext/someobj' a = Someobj.new.dosomething where ext/someobj is a C extension which writes directly to stdout. If your editor environment is going to be general-purpose then it better handle that case too. Modifying certain Ruby commands like 'system' is not the solution to the general problem. > OK.. again assignment to stdout is illegal. freopen should be used instead. > Admitted.. I havn't yet tried reopen'ing stdout/stderr :-) freopen only lets you associate the FD with a file. It would certainly be possible to do STDOUT.reopen("/tmp/capture.out") before calling the snippet you are interested in. Then you can close it and read the file. This sounds like it might be a good solution for your particular problem domain (i.e. an environment for running Ruby interactively). Of course you lose the STDOUT/STDERR given to the main program when it started, so it had better be a graphical environment. But that solution is specific to your problem. I don't think it warrants a modification to Ruby, the general-purpose programming language, itself. Cheers, Brian.