On Tue, 13 May 2003 08:39:34 +0900, Brian Candler wrote:

[snip top - continued from previous post]

> But then you say that you want to do this without modifying existing Ruby
> code. You can always replace 'system' and 'backtick' with your own versions
> if you wish. But I still don't think it makes sense.

mm.. I better state more exactly what "existing Ruby code" means here. 
This is NOT the core of ruby.  I am working on a programmers-editor where
the backend is ruby and the frontend is c++ (ruby embedded into c++).
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.

http://prdownloads.sourceforge.net/metaeditor/aeditorlib-0.1.tar.gz?download

Enough advertisement.. I hope you understand my rationale now ?

 
> The environment in which a Unix program runs looks, at its simplest, like
> this:
> 
>                  MAIN
>                +---------------------------------+
>                |                                 |
>                | FD                              |
> stdin -------> | 0                               |
> stdout<------- | 1                               |
> stderr<------- | 2                               |
>                |                                 |
>                |                                 |
>                +---------------------------------+
> 
> It can ignore stdin/stdout/stderr of course - as it would if it were a GUI
> program, say.
> 
> Now, from this main program, you want to call a function, which happens to
> be written in Ruby.
> 
> It must be true that either:
> 
> * This function makes no use of stdin/stdout/stderr at all. In that case
>   there is no problem, agreed?

Agree: puts, print, p, printf, write.. OK

 
> * This function *does* communicate on stdin/stdout/stderr.
> 
> So I think you are saying in the second case you want to run it in a
> 'sandbox', a simulated Unix environment where it gets its own private
> stdin/stdout/stderr:

Yes yes yes yes... We should have painted such diagram several days ago,
then we could have avoided much of this confusion.

 
>                +---------------------------------+
>                |                                 |
>                |               +-----------+     |
> stdin -------> | 0      obj0-->| 0 Sandbox |     |
> stdout<------- | 1      obj1<--| 1         |     |
> stderr<------- | 2      obj2<--| 2         |     |
>                |               +-----------+     |
>                |                                 |
>                +---------------------------------+
> 
> I think you are asking for the Ruby interpreter to be the sandbox itself,
> and to trap every single possible case where output might be written to
> stdout/stderr, and have it redirect to Ruby IO calls instead. 

Putting Ruby into a sandbox is what my RCR proposal is about.
This is currently not possible.. therefore the RCR.


> 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);
    }
}

OK.. again assignment to stdout is illegal. freopen should be used instead.
Admitted.. I havn't yet tried reopen'ing stdout/stderr :-)


> Rewriting 'system' and backtick would catch some cases, but certainly not
> all.

Agree.. A nicer solution is what we are looking for.

 
> The only way to guarantee trapping of all output on fd 1 in the Sandbox into
> some string object 'obj1' is to do it at the Unix API layer. This means
> creating a new pipe and pass one end of it to the code running in the
> Sandbox as fd 1. This then *forces* you to use a separate process, because
> it must be possible for the Sandbox to be doing work and writing to one end
> of the pipe whilst the main program is reading the other end of the pipe.
> (You could also use native threads, but Ruby doesn't play safely with
> threads)

I run ruby in one semaphore protected thread.. no extra process.
I have a thread in C++ which is flushing the pipe and stores it into a
text-buffer.
 

[snip summary]

I will look at the summary later :-)

--
Simon Strandgaard