in reply to Re^2: STDERR Restore after redirect
in thread STDERR Restore after redirect

Just use local() within a block as tybalt89 suggested to save and then restore the filehandles.

sub SendMemberMail { my ($subject,$from,$to,$port,$cc,$bcc,$heading,$body,$closing,$signi +ture,$auth) = @_; warn("In SendMemberMail before redirect of STDERR & STDOUT"); $Mail::sendMail::mailcfg{'debug'} = 6; $Mail::sendMail::mailcfg{'port'} = $port; my $message = "$heading\n\n$body\n\n$closing\n\n$signiture\n"; my %mail = ( To => $to, From => $from, Cc => $cc, Bcc => $bcc, Subject => $subject, Message => $message, ); if ($auth == 1) { $mail{'Auth'} = { user => '', password => '', method => 'PLAIN LOGIN', required => 1 }; }; my $logfile = '/home/abcus/public_html/httpsdocs/cgi-bin/lib/perl/Ma +il/mail.log'; open my $fh, '>>', $logfile or die "Error opening $logfile : $!"; SEND: { local *STDOUT = $fh; local *STDERR = $fh; if ( SendMail(%mail) ) { print $Mail::sendMail::log; } else { print $Mail::sendMail::error; } } close $fh; select STDOUT; # Test original handles print "stdout 2\n"; warn("warn stderr 2\n"); return 1; }
Note: Using Mail::sendMail as described here
poj

Replies are listed 'Best First'.
Re^4: STDERR Restore after redirect
by tultalk (Monk) on Apr 28, 2018 at 02:19 UTC

    Thanks

    I tried the local before and it did not work. Will try again

    I put some code in the sub that fails to print:

    sub CreateUserFeedbackForm { my ($message) = @_; if(!defined('STDOUT')){ warn("No STDOUT"); } elsif (defined('STDOUT')){ warn("STDOUT Defined"); } if(!defined('STDERR')) { warn("No STDOUT"); } elsif (defined('STDERR')) { warn("STDERR Defined"); }

    Result in my error log below:

    Fri Apr 27 16:43:31 2018 manage_users.cgi: STDOUT Defined at manage_users.cgi line 806. STDERR Defined at manage_users.cgi line 814. Fri Apr 27 16:43:31 2018 manage_users.cgi: STDERR Defined at manage_users.cgi line 814. At exit of sub CreateUserFeedbackForm at manage_users.cgi line 964. Fri Apr 27 16:43:31 2018 manage_users.cgi: At exit of sub CreateUserFeedbackForm at manage_users.cgi line 964.

    Since both returned "defined" my next question: Does that mean they are functional?

    I guess I could try writing to the handles to see but thought maybe some Monk could say "Yes defined means it is functional"

    Thanks

      if(!defined('STDOUT')){ ... }

      The strings  'STDOUT' and  'STDERR' are literal strings and not file handles. Strings are always defined. Even '' (the empty string) and '0', both of which are false, are both defined.

      I'm not sure of the best way to test if a file handle is functional, nor am I quite sure what "functional" means in this context.


      Give a man a fish:  <%-{-{-{-<

        Is this not a test for a file handle?

        open my $oldSTDOUT, ">&STDOUT"; open OLDERR, ">&",\*STDERR; open(STDOUT, ">&", $oldSTDOUT) or warn("Can't open STDOUT"); + open(STDERR, ">&OLDERR") or warn("Can't open STDERR");

        Neither published a warn

Re^4: STDERR Restore after redirect
by tultalk (Monk) on Apr 28, 2018 at 16:23 UTC

    <Hi>

    Thanks for input. As I stated before I already tried the local and the results were the same. So I tried again.

    Going through block of code and eliminating items step by step, commenting out #print "stdout 2\n"; and the program executed and printed html form as desired. Have no idea what effect that line could have to cause the failure. Ir was added for testing after some other problem.

    Bizarre/p>

    What is the SEND() for? What does it do?

      From poj's reply:   SEND: { ... }

      What is the SEND() for? What does it do?

      In this case, SEND is not a function call (as the () argument list operator you use would suggest), but is the label of a block that establishes a scope for the local-ization of changes to the global STDOUT and STDERR system file handles. (Update: See Compound Statements and Basic BLOCKs, both in perlsyn.)

      The label is not syntactically or semantically necessary for the establishment or operation of the scope in this case, but serves a purely documentary function: What's happening in the block? We're SENDing something. At the end of the block (or scope), the values of STDOUT and STDERR that existed before entering the block/scope are automatically restored.

      Update: If you haven't already, take a look at Coping with Scoping by Dominus, especially the discussions of local and package variables.


      Give a man a fish:  <%-{-{-{-<

        And what to make of this?

        When to Use my and When to Use local Always use my; never use local.

      see BLOCKS

      SEND: is just an optional LABEL to make the block more visible. The block {} restricts the scope of the local().

      poj

        Hi. Thanks all. Moving on to the STARTTLS mode.

        If I should start new topic, warn me.

        AUTH PLAIN failed: 554 Security failure
        Server said: 554 Security failure
        

        MIME::Base64 encode/decode

        my $encodedString = "AUTH PLAIN " . encode_base64(join("\0", $auth->{user}, $auth->{ +user}, $auth->{password}), $CRLF); my $decodedString = decode_base64($encodedString) +; warn("decodedString '$decodedString'");

        Encode produces:

        AUTH PLAIN d2VibWFzdGVyXEBid21qY20udXMAd2VibWFzdGVyXEBid21qY20udXMAd21 +ANDA5MTNXTQ==

        Decode produces:

        D<5ݕѕqݵݕѕqݵݵ ]4

        I thought the decoded string would be that same as the input string.No?