From: daz Date: 2005-07-29T12:56:01+09:00 Subject: Re: redirecting stdout in an extension Mark Probert wrote: > > Hi .. > > On Wed, 2005-07-27 at 08:32 +0900, Guillaume Marcais wrote: > > On Wed, 2005-07-27 at 08:15 +0900, Mark Probert wrote: > > > > > > Any ideas on how to redirect stdout in an extension and then revert it > > > back to its default behaviour? freopen() redirects, though I am not > > > sure of returning to normal programming. > > > > > > > Just a guess. I don't know how well it will play with the Ruby > > interpreter. > > > Not so well, unfortunately: > > $ ruby foo.rb > test.rb:29:in `write': Bad file descriptor (Errno::EBADF) > from test.rb:29:in `puts' > from test.rb:29 > > Thanks for the suggestion. I would think that there might be some > facility hidden with the API that might allow this redirection to > happen, but I have no idea of what it might be .. > Hi Mark, I was thinking that a reply would pop up suggesting rb_io_reopen() but just discovered what you already know ... it's not exposed :( Here's my adaptation of a fairly well established method blagged (including most comments) from the ether. In short, the chant goes: open, dup, dup2, close <"redirecting"> dup2, close Will it work in a Ruby ext ? #------------------- require 'redir1' puts Time.now Time.redir1('foo/blah.txt') puts File.read('dummy.tmp') #------------------- #-> Fri Jul 29 04:14:10 2005 #-> Fri Jul 29 04:14:10 2005 - foo/blah.txt Result as expected. (C below) daz (almost useless extension) /////////////////////////////////////////////////////////////////////// #include "ruby.h" #include int foo_dump(char *fname) { VALUE t = rb_class_new_instance(0, NULL, rb_cTime); // time and filename to STDOUT (possibly redirected) printf("%s - %s\n", RSTRING(rb_inspect(t))->ptr, fname); return 0; } VALUE redir1(VALUE self, VALUE o_name) { VALUE rval; /* our result */ char *fname; /* holds the filename */ int new_fh, sv_so, so_fh = _fileno(stdout); /* OR so_fh = STDOUT_FILENO */ fname = StringValuePtr(o_name); new_fh = open("dummy.tmp", O_CREAT | O_WRONLY, S_IREAD | S_IWRITE); if (new_fh < 0) rb_sys_fail("can't open file for STDOUT redirection"); /* create a duplicate handle for standard output */ sv_so = dup(so_fh); /* redirect standard output to output file by duplicating the file handle onto the file handle for standard output. */ dup2(new_fh, so_fh); /* close the handle for output file */ close(new_fh); /* will be redirected into output file */ rval = (foo_dump(fname) == -1) ? Qnil : Qtrue; /* restore original standard output handle */ dup2(sv_so, so_fh); /* close duplicate handle for STDOUT */ close(sv_so); return rval; } void Init_redir1() { rb_define_singleton_method(rb_cTime, "redir1", redir1, 1); } ///////////////////////////////////////////////////////////////////////