Forwarding Alert Email

[posted 2000/03/01]

A member of pikt-users asked:  "I need to forward the dead crucial processes to emails other then the one specified for Urgent alerts."

And I replied:

If you want the same alert message, header and all, to go to two or more persons, the easiest way is simply to redefine your =pikturgent with two or more addressees, for example (in macros.cfg),

pikturgent      jane.russell\@theoutlaw.com howard.hughes\@theoutlaw.com

Or, if you do as we do, use NIS aliases, just keep your current macro definition, for example,

pikturgent      pikt-urgent

where pikt-urgent is an alias defined in your NIS map, then add the extra addressees in the NIS entry.

Or, yes, do it the way you did, defining another macro

piktfido        root [email protected] [email protected] // fido-mail

pikturgent      =piktfido

(I changed "piktcrucial" to "pikturgent" in your example for consistency. I'm a bit surprised if you don't have to put a '\' before the '@' in your addresses.)

But while pondering your question, I thought of situations where you might want forwarding of alert email to one or more non-standard extra addressees.  Following is another method (with variant) that you might try.

To demonstrate, I registered a new Test alert in alerts.cfg:

Test
        timing          =piktnever
        mailcmd         "=mailx -s 'PIKT Alert on =pikthostname: Test' pikt-test"
        alarms
                        OtherMailTest

And here is OtherMailTest, variant 1:

OtherMailTest   // variant 1

        init
                status active
                level notice
                task "this is a test"
                input file "/etc/hosts"

        begin
                set #isopenmail = #false()

        rule
                output mail $inline
                if $inline =~ "loghost|localhost"
                        if ! #isopenmail
                                if #popen(MAIL, "=mailx -s 'test'
                                                 robert.osterlund\@egbdf",
                                                "w") != #err()
                                        set #isopenmail = #true()
                                else
                                        output mail "\#popen() failure for:
                                                     =mailx -s 'test'
                                                     robert.osterlund\@egbdf"
                                        quit
                                endif
                        endif
                        do #write(MAIL, $inline)
                endif

        end
                if #isopenmail
                        do #pclose(MAIL)
                endif

(I installed the script using 'piktc -iv +A Test +H vienna' and ran it at the command line using 'pikt +A Test'.)

This is just a toy script to demonstrate some points.  It goes through /etc/hosts, and outputs every line to whoever receive(s) the alert mail as defined in 'mailcmd' in alerts.cfg.  In addition, it sends lines matching either "loghost" or "localhost" to a different addressee, in this case myself.  Note that only matching lines are sent; no alert header is sent (unless we write extra script code to do that).

In the script, we set and test the #isopenmail variable to #popen() and #pclose() the MAIL filehandle just once and at just the right moments. (We don't test the return value of the #pclose() call, just assuming that the MAIL filehandle was #pclose()'ed properly.)

I can see where one might want to do this sort of thing often--forwarding alert email output to additional addressees beyond what's defined in the mailcmd (or your alert addressee macros).  Using the new macro feature in PIKT 1.9.0, here is one way you might do it.  Following is variant 2 of OtherMailTest:

OtherMailTest   // variant 2

        init
                status active
                level notice
                task "this is a test"
                input file "/etc/hosts"

        rule
                output mail $inline
                if $inline =~ "loghost|localhost"
                        =output_other_mail(OTHERMAIL, 'test',
                                                      robert.osterlund\@egbdf,
                                                      $inline)
                endif

Much simpler than variant 1, no?  And here is the =output_other_mail macro definition (in macros.cfg):

output_other_mail(F, S, R, L)   // output conditional mail to addressee(s)
                                // beyond those specified in the alert
                                // mailcmd; we don't #pclose() the (F)
                                // filehandle at the end, instead letting
                                // pikt do it
                                // (F) is the filehandle name (e.g., MAIL)
                                // (S) is the subject (e.g., 'check this out')
                                // (R) is the recipient (e.g., 'berto\@gsbrgo')
                                // (L) is the line (e.g., $inline)

                if ! #defined(#isopen(F))
                        set #isopen(F) = #false()
                fi
                if ! #isopen(F)
                        if #popen((F), "=mailx -s (S) (R)", "w") != #err()
                                set #isopen(F) = #true()
                        else
                                output mail "\#popen() failure for:
                                             =mailx -s (S) (R)"
                                quit
                        fi
                fi
                do #write((F), (L))

(It would be possible to complexify this macro definition to automatically determine a suitable 'F' from the supplied 'R'.  Then you could call this macro supplying just three arguments--the subject, the recipient, the line. But, naw!, that's too complicated.)

Here is what piktc preprocesses variant 2 into:

OtherMailTest
        init 
                status active 
                level notice 
                task "this is a test" 
                input file "/etc/hosts" 
        rule 
                output mail $inline 
                if $inline =~ "loghost|localhost" 
                if ! #defined ( #isopenOTHERMAIL ) 
                set #isopenOTHERMAIL = #false ( ) 
                fi 
                if ! #isopenOTHERMAIL 
                if #popen ( OTHERMAIL , "/usr/bin/mailx -s 'test'
                                         robert.osterlund\@egbdf"
                                      , "w" ) != #err ( ) 
                set #isopenOTHERMAIL = #true ( ) 
                else 
                output mail "\#popen() failure for: /usr/bin/mailx -s 'test'
                             robert.osterlund\@egbdf" 
                quit 
                fi 
                fi 
                do #write ( OTHERMAIL , $inline ) 
                endif 

The goal here was to write a one-liner macro that you can use without having to include separate begin and end script sections.

Each time we have a line match, we check to see if our open variable is defined:

                if ! #defined(#isopen(F))
                        set #isopen(F) = #false()
                fi

'#isopen(F) looks like a function call, but it's not.  The '(F)' is how we specify the 'F' macro parameter in the macro definition.  Since the 'F' argument in the example macro reference is 'OTHERMAIL', the above macro code gets expanded to

                if ! #defined( #isopenOTHERMAIL )
                set #isopenOTHERMAIL = #false ( )
                fi

The first and only time we call #define(), this will generate a WARNING message in the alert log:

Feb 29 13:56:56 WARNING: in exprinput(), OtherMailTest, attempt to reference nonexistent value for var isopenOTHERMAIL (1)

This is harmless.  (If this bothers you, you would have to include a separate begin section where you initialize the #isopenOTHERMAIL variable, like what's done in script variant 1.)

Wait a minute?  Where's the #pclose() at the end of the variant 2 script? It's not in the =output_other_mail macro definition either.

It's a little known fact that pikt closes all still open filehandles at the end of every script.  Ordinarily it's good programming practice to call #fclose() and #pclose() explicitly.  But in this case, in order that we can have a convenient one-liner macro and not be forced to have a separate end section to do the #pclose(), we let pikt close the filehandle for us.

There are of course other ways we could solve this problem of special email routing.

I might place on the todo list adding a new 'output mail' variant,

        output mail "<addressee(s)>" "<text>"

But as you see, you don't have to wait for me to code that into the pikt script interpreter.  You can achieve the same effect using the =output_other_mail macro immediately.

The =output_other_mail macro is the sort of thing that, after further polishing, could be a candidate for inclusion in the PIKT standard config library.  We want to build up a large collection of macros, scripts, data sets, etc., so that you don't have to reinvent the wheel.

For more examples, see Developer's Notes.

 
Home | FAQ | News | Intro | Samples | Tutorial | Reference | Software
Developer's Notes | Licensing | Authors | Pikt-Users | Pikt-Workers | Related Projects | Site Index | Privacy Policy | Contact Us
Page best viewed at 1024x768 or greater.   Page last updated 2019-01-12.   This site is PIKT® powered.
Copyright © 1998-2019 Robert Osterlund. All rights reserved.
Home FAQ News Intro Samples Tutorial Reference Software
PIKT Logo
PIKT Page Title
View sample
wtmp changes
Pikt script