all of the previous solutions seem to make the following assumptions -

$stderr and $stdout are global objects which all of ruby send messages
bound to 'stderr' and 'stdout' to, and that the constants STDERR and
STDOUT also point to these same objects.  that being the case (?), can
someone tell me why the following DOES NOT WORK?

======================================================================
#!/usr/bin/env ruby

require 'delegate'


# simplest possible example 
# of a redirectable IO class

class DupableIO < SimpleDelegator
  def initialize io
    @io = io 
    super(@io)
  end
  def duplicate io
    __setobj__ io 
  end
  def unduplicate
    __setobj__ @io
  end
end


# output goes to stderr
`ls non_existent_file`

# global stdout delegates all his calls to constant object STDOUT
$stdout = DupableIO.new STDOUT

# global stderr delegates all his calls to constant object STDERR
$stderr = DupableIO.new STDERR

# a normal io (File) object
$log = open 'logfile', 'w'


# output STILL goes to stderr (correct)
`ls non_existent_file`

# now tell stderr and stdout to delegate 
# their calls to the log object
$stderr.duplicate $log
$stdout.duplicate $log

# output goes to logfile (correct)
$stderr.puts 'foo'

======================================================================


in particular it would seem that, somewhere, some test is made of
$stderr and $stdout BEFORE actually using them - something along the
lines of

if $stderr.type == IO
	... use it
else
	... open up 2 and use it
end

how else to explain the above behavior.  it's really unfortunate
because i think this type of solution is in the 'ruby spirit' : what
we require is an IO object which can, temporarily, make calls on
another IO object.  this IS the delegate pattern to a 'T' - it would
be nice to be able to use it.

- ara howard

ahoward / fsl.noaa.gov