theqblas has asked for the wisdom of the Perl Monks concerning the following question:

I have this script sends a report either to STDOUT or to an e-mail address via a library that is a subclass of Mail::Send.

What happens is that based on some command-line option, I am setting the variable $message to either *STDOUT or to $mail_obj->open() (Which returns a bless'ed glob of Mail::Mailer::smtp), I then select($message) and set $~ and $^ to the appropriate format names.

Anyway, when I try to write($message), the output seems to disappear when $message is the Mail::Mailer::smtp object, but when sent to STDOUT it works: e.g.

---- CODE BLOCK ---- { if($opt_mailto) { $mail_obj = VNI::Mailer->new(); $mail_obj->to($opt_mailto); $mail_obj->subject($report_title); $mail_obj->from($from); $message = $mail_obj->open(); } else { $message = *STDOUT; } # select whatever filehandle is in $message for output select($message); # -- further down format MSG_TOP = blah some header for this report --------------------------------- . format MSG = @<<<<< @<<<<<< @<<<<<< @<<<<<< $foo, $bar, $baz, $quux ------------------------------ . $^ = "MSG_TOP"; $~ = "MSG"; foreach (@lusers) { $foo = $_->data; $bar =$_->otherdata; # etc, etc, # THIS WRITE WORKS WHEN $message == *STDOUT # OUTPUT DISAPPEARS OTHERWISE write($message); } # The following prints always work correctly. print $message "Some summary info: $balance\n"; print $message "People who suck: $sucky\n"; } ----- END CODE ----

So when I try doing this using the mail object, all I get is the summary information, but not the report itself.

Why? Why!?!?

This is perl 5.0005_4 on FreeBSD 4.4-STABLE

I tried a few different tricks and none of them worked, and one of the techniques actually caused perl to segfault!

I would think that write() is just a front-end for print(), so I don't know why print() would use the mail-filehandle correctly and write() not. Argh.

-bcd

Replies are listed 'Best First'.
Re: Formatted Output on glob-filehandles
by Thelonius (Priest) on Oct 24, 2002 at 20:10 UTC
    Have you tried write; without any arguments? Another thing you could try is $message->format_write(). I'm just guessing here, in case you couldn't tell.
Re: Formatted Output on glob-filehandles
by Jenda (Abbot) on Oct 24, 2002 at 20:46 UTC

    From the code in Mail::Mailer I would expect a Mail::Mailer::smtp::pipe object anyway try to define the WRITE method like this:

    { package Mail::Mailer::smtp::pipe; sub WRITE { my $fh = $_[0]; print $fh substr($_[1],0,$_[2]) } } # taken from Tie::Handle or { package Mail::Mailer::smtp::pipe; sub WRITE { my $fh = $_[0]; $fh->PRINT(substr($_[1],0,$_[2])) } } or maybe { package Mail::Mailer::smtp::pipe; sub WRITE { my $fh = $_[0]; $fh->format_write(substr($_[1],0,$_[2])) } }

    Of course if the glob really is Mail::Mailer::smtp define the function there :-)

    If this doesn't help (this is just a wild guess!) try to use Devel::TraceSubs to see what functions are called with what parameters.

    Jenda

      Which are 5.6 modules, unfortunately.

      I tried adding those subs to the Mail::Mailer::smtp::pipe package (which the Mail::Mailer::smtp object is tied to), i added the rest of the missing filehandle TIE functions that just print some debugging, nada.

      I don't know..

Re: Formatted Output on glob-filehandles
by VSarkiss (Monsignor) on Oct 24, 2002 at 19:51 UTC

    This is a shot in the dark, so take it with a grain of salt.

    Since you already have the output selected, don't pass it as a parameter to write. Quite possibly, it's being interpreted as an expression that holds a filehandle name rather than a filehandle. In other words, it may be trying to write to a filehandle named HASH(0xabcd) or some such. (That's the normal behaviour of write. Check out perlfunc:write.) If select has succeeded, then just call write with no parameter.

    HTH

      Negatory. I had tried this before posting the message. I tried a few variations on this, like:

      # explicit file handle ($message) write($message); # implicitly use selected output stream write(); # Yah, I know this is wrong, but I had to try it. write(MSG);

      And as far as checking whether select() failed or not, I don't believe there is any way to do this (Please tell me I am wrong, because I can't accept that)