this is not correct thinking.
consider this:
a) fd’s (STDIN_FILENO, STDOUT_FILENO) are managed by the kernel!! neither C
nor ruby has any affect on them where child processes are concerned.
b) FILE *'s (stdin, stdout, rb_stdout, etc) exist in a library which wrap
(but do not ‘contain’, as they are still in kernel space/mngment) fd’s
with a buffer. because these buffers exist as a library they are like
any other user code that you’ve written - the os can never magically
transport them to a child process when a fork, backtick, etc occurs because
it has NO KNOWLEDEGE of them.
so you are left with this delima - any redirection which is to be inherited
across a fork/exec (system, backtick, explicit fork, etc) MUST take place at
the file descriptor (kernel - unix, win, whatever) level and this affects the
entire calling process(es). any tinkering with FILE *'s, iostreams, io
objects in c, c–, or ruby will never have the intended affect unless you
happen to luck out (or know what you are doing) and somehow call methods which
themselves affect the underlying fd’s. considering how confusing io can be,
it’s almost certainly the case that simply understanding how fd’s work at the
c level is the safest and surest thing to do.
in a nutshell, you must affect the fds (1, 2) before executing ruby, but leave
them alone (or restore) them in the calling (c–) process, for example here is
a c program which redirects all stdout and stderr from a child ruby process
into a pipe, without affecting the stdout and stderr of the parent process,
and then reads from that pipe to display it to the terminal - i think
something like this will be in order for your c++ application:
~/eg/ruby/redirect > cat redirect.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include “ruby.h”
/*
gcc redirect.c -I /usr/local/ruby-1.6.6/ /usr/local/ruby-1.6.6/libruby.a -lm -ldl -lcrypt
*/
int
main (argc, argv)
int argc;
char **argv;
{
int fd[2];
pid_t pid;
char *script;
int c;
assert ((script = argv[1]) != NULL);
assert (pipe (fd) == 0);
assert ((pid = fork ()) != -1);
if (pid == 0)
{
assert (close (fd[0]) != -1);
assert (dup2 (fd[1], STDOUT_FILENO) != -1);
assert (dup2 (fd[1], STDERR_FILENO) != -1);
ruby_init ();
ruby_script (script);
rb_load_file (script);
ruby_run ();
}
else
{
write (STDOUT_FILENO, "RUBYOUT:\n", 9);
assert (close (fd[1]) != -1);
while (read (fd[0], &c, 1) && write (STDOUT_FILENO, &c, 1));
assert (close (fd[0]) != -1);
}
return (EXIT_SUCCESS);
}
~/eg/ruby/redirect > cat redirected.rb
ls #{__FILE__}
ls non-existent-file
system ‘ls #{FILE}’
system ‘ls non-existent-file’
STDOUT.puts 42
STDERR.puts 42
$defout.puts 42
$stdout.puts 42
$stderr.puts 42
puts 42
~/eg/ruby/redirect > gcc redirect.c -I /usr/local/ruby-1.6.6/ /usr/local/ruby-1.6.6/libruby.a -lm -ldl -lcrypt
~eg/ruby/redirect > a.out redirected.rb
RUBYOUT:
ls: non-existent-file: No such file or directory
a.out
redirect.c
redirected.rb
ls: non-existent-file: No such file or directory
42
42
42
42
42
42
-a
···
On Mon, 12 May 2003, Simon Strandgaard wrote:
Using system or backquote, then it goes BOOM. The problem as I see it is
localized in Rubys code - not mine! Ruby spawns a child which inherits
stdout/stderr. This child should instead inherit rb_stdout/rb_stderr
instead!!! Can this issue be fixed on Ruby ???
–
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
====================================