macros.cfg

(NOTE:  Some of the techniques shown or described on this page--marked in purple--require new features in the latest official PIKT 1.19.0 release (pikt-current.tar.gz) that are unavailable in any previous version.)

The macro config file specifies text string substitutions.  You would use macros to locate in one place (in macros.cfg) common configuration elements, to hide lower-level implementation details, also to write all-purpose, one-size-fits-all higher-level configurations.

For example, here is a simple text-substitution macro specifying so-called "red flags"--worrisome log entries:

///////////////////////////////////////////////////////////////////////////////
// 
// PIKT macros.cfg -- preprocessor text substitutions
// 
///////////////////////////////////////////////////////////////////////////////

...

redflags        fail|error| err |die|down|seg.*fault|terminate|attack|abort

...
And here is a somewhat more complicated macro, with macro argument (M), that hides some implementation details:
output_alarm_log(M)     output log "=logdir/" . $alarm() . ".log" (M)
Here is how you might reference the redflags and output_alarm_log() macros in a Pikt log scanning script:
        rule    // for flagged stuff, report and log
                if $inlin =~~ "=redflags"
                        output mail $inlin
#ifdef log
                        =output_alarm_log($inlin)
#endifdef
                        next
                endif
And here is how that rule would appear, with full macro expansion, and with the 'log' define set to TRUE, when installed on a PIKT client system:
        rule
                if $inlin =~~ "fail|error| err |die|down|seg.*fault|terminate|attack|abort"
                        output mail $inlin
                        output log "/pikt/var/log/" . $alarm() . ".log" $inlin
                        next
                endif

In macros.cfg (or any of its #include files), a macro stanza may take the form

<macro>        <macro definition text>
where the definition text can follow on the same line and/or subsequent indented lines.  In config files, a macro is signified by an equal sign-identifier combination, =<macro>.  Macro definitions, but not macro names, may include embedded macros.  In other words, this is legal:
<macro1>       <macrodef 1>
                  ...
<macro2>       <... =macro1 ...>
A macro definition may only reference other macros defined before it.

Macros of the form

<macro>        <macro definition text>
are simple string substitutions.  Macro stanzas of the form
<macro>(<arg1>, <arg2>, ...)    <text> (<arg1>) <text> (<arg2>) ...
allow you to specify arguments in your macro substitutions.

For example, if you define a macro in macros.cfg like so:

remind(Y,M,D,MSG)    if #now() > #datevalue((Y),(M),(D))
                             output mail (MSG)
                     endif
and reference it in alarms.cfg like so:
        =remind(2000, 2, 15, "Lift the pwherman account restriction.")
this will appear in the .alt file:
        if #now() > #datevalue(2000, 2, 15)
                output mail "Lift the pwherman account restriction."
        endif
Note that in the macro definition, macro parameters must be enclosed within parentheses.  In the macro reference, however, enclosing parentheses are not necessary.  Macro parameters must begin with a letter, followed by any number of letters, digits, or underscores.  (Making macro parameters all caps, as in the examples above, is not a requirement, but it makes it easier to see them in the macro definition if you do so.)

As with simple macros, macros-with-arguments may reference other macros-with-arguments, so all manner of macro nesting is allowed.  For example, these macros.cfg macro definitions are all perfectly legal:

foo1            blah

foo2(A)         blah (A) =foo1

foo3(A, B)      =foo2("=foo1") (B) blahblah =foo2((A)) =foo1=foo1
The macro reference (in a subsequent config file)
                =foo3("yadda, yadda", =foo1)
would preprocess to
        blah "blah" blah blah blahblah blah "yadda, yadda" blah blahblah
A self-referencing macro definition or macro reference is an error, for example:
foo(A)          blah =foo((A))
or
                =foo(=foo("yadda, yadda"))
You may employ macros within piktc command lines, for the +C (command) item (when specifying program paths, for example), or when specifying +|-A (alert), +|-P (program), +|-F (file), and/or +|-O (object) items.  See the piktc section of the Reference for details.

Although macro definitions, including the specification of macro parameters, may span multiple lines in macros.cfg, a macro reference is restricted to a single line.  In other words (and unless and until we can code otherwise), spanning a macro reference across multiple lines is illegal, for example:

      =remind(
#if perf
               2005,
#else
               2000,
#endif
               2, 15, "Lift the temporary pwherman account restriction.")
We hope to add this flexibility, but for various reasons it won't be easy.

If you define a macro to encompass an entire Pikt script, you may not end the script with a quoted string.  (For examples of Pikt script macros, see the PIKT Introduction.  For example, if you define a dmesg scanning script macro

dmesg_scan(BYPASS)

        init
                status __PIKTSTATUS__
                level __PIKTLEVEL__
                task "Scan the dmesg output for troublesome or noteworthy entries"
                input proc "if [ -e /pikt/var/histories/log/dmesg__PIKTALERT__.bak ];
                            then /usr/bin/diff /pikt/var/histories/log/dmesg__PIKTALERT__.bak
                                       /pikt/var/histories/log/dmesg__PIKTALERT__ |
                                 /usr/bin/egrep '>' | /usr/bin/cut -b 3- 2>/dev/null;
                            else /bin/cat /pikt/var/histories/log/dmesg__PIKTALERT__ 2>/dev/null;
                            fi"

        [...]

        end
                doexec wait "/bin/mv /pikt/var/histories/log/dmesg__PIKTALERT__
                                 /pikt/var/histories/log/dmesg__PIKTALERT__.bak"
the "=mv =hstdir/log/dmesg=piktalert =hstdir/log/dmesg=piktalert.bak" string will cause a parse error.  (This is a bug in the piktc preprocessor that we have been unable to fix.)  The solution is to append a Pikt statement that has no practical effect, such as "quit":
        end
                doexec wait "/bin/mv /pikt/var/histories/log/dmesg__PIKTALERT__
                                 /pikt/var/histories/log/dmesg__PIKTALERT__.bak"
                quit
For script macros that end with a rule section, you can append a dummy end section (without real purpose, except as a bug workaround):
        end
                quit
Or you could append a null operation to the final rule such as:
        rule
                ...
                pause 0
or:
        rule
                ...
                do #true()
To repeat, these workarounds are needed for script macros only.  They are not necessary for directly coded Pikt scripts (in alarms.cfg) or other ordinary macros.

There are a limited number of built-in, pre-defined macros:

  • piktdir:  resolves to the PIKT home directory
Host and operating system macros:
  • pikthostname:  translates to the name of the machine that piktc is currently processing
  • piktmaster:  the name of the master control machine
  • pikthosts:  a list of all hosts defined in systems.cfg
  • piktopsystems:  a list of all operating systems defined in systems.cfg
As piktc does its processing:
  • piktalert:  the current alert stanza (in alerts.cfg)
  • piktalarm:  the current alarm stanza (in alarms.cfg)
  • piktprogram:  the current program stanza (in programs.cfg)
  • piktfile:  the current file stanza (in files.cfg)
  • piktobject:  the current objects stanza (in objects.cfg)
If you specify alarm status and severity levels on a per-alert basis in alerts.cfg, you may reference the following macros in your alarms.cfg:
  • piktstatus: the alert-wide alarm status
  • piktlevel: the alert-wide alarm level
For example, if you specify this in your alerts.cfg:
Urgent
        ...
        status          suspended
        level           urgent
        ...
you could then do this in alarms.cfg:
ScanSyslog
        init
                status =piktstatus
                level =piktlevel
                ...
When the ScanSyslog alarm is installed on the PIKT slave system, the actual result would be:
ScanSyslog
        init
                status suspended
                level urgent
                ...
Two timing macros especially useful in alerts.cfg:
  • piktnever:  resolves to a special timing string that signals piktd to bypass the current alert
  • piktalways:  resolves to a special timing string that signals piktd to run the current alert every minute of every day
A general built-in macro useful in any of the config files is:
  • pikttest: resolves to the string 'test' when used with 'piktc -T' (for test mode), otherwise the null string
You can specify that =pikttest resolve to some other arbitrary string using the pikttest_substitution setting in PIKT.conf, for example (to capitalize the word 'test'):
pikttest_substitution           "Test"
The following built-in macros are intended for PIKT.conf management:
  • piktuid:  resolves to the uid (as specified in keys.conf) for the current host
  • piktgid:  resolves to the gid (as specified in keys.conf) for the current host
  • piktdataenctyp:  resolves to the data_encryption_type (as specified in keys.conf) for the current host
  • piktauthenctyp:  resolves to the auth_encryption_type (as specified in keys.conf) for the current host
  • piktprivate_key:  resolves to the private_key (as specified in keys.conf) for the current host
See the keys.conf section of this Reference for more detail.

The following built-in macros are useful for document formatting (and are especially important when defining other macros):

  • piktnullchar:  resolves to the null character (also:  =_)
  • piktspacechar:  resolves to the space character
  • pikttabchar:  resolves to the tab character
  • piktnewlinechar:  resolves to the newline character
If you wanted to define a 'spc' macro in defines.cfg, this would not work:
spc
for then you would have no stanza body.  And neither would this work:
spc             " "
for then " " would be inserted, including the quotation marks, into your text.  This is the correct way to define the 'spc' macro:
spc             =piktspacechar
The special '=_' pre-defined macro is a kind of null macro, used to separate a macro component from the following text.  For example, if you have defined '=dash' in macros.cfg as
dash            --
the following would not work as intended
=dashIn the first case ...
because piktc would complain about not finding the '=dashIn' macro.  You would solve this problem by redoing the line this way:
=dash=_In the first case ...
for then the =_ provides the needed separation between '=dash' and 'In'.  Just to be clear, in the example, the after-preprocessing result would be
--In the first case ...
Refer to the sample macros.cfg for example macro definitions.  Refer to the sample alarms.cfg for many more example macro references.

prev page 1st page next page
 
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
kill idle
user sessions
Pikt script