procmail
[Top] [All Lists]

Re: store all headers ??

2001-09-04 01:25:19
"Timothy J. Luoma" <luomat(_at_)peak(_dot_)org> writes:
Is there an easy way to store all headers when a message arrives,
store them into a variable, and then put them back later?

Yes, but there's probably an easier way to do whatever you're *really*
trying to do.  A cloning nested block or reordering the recipes is
probably the 'right' choice, but without knowing your goal it's hard
to say.


If you *insist* on doing this, there are a couple ways to go about it.
The simple, but neither particularly inefficient or efficient method
runs something like:

        # Save copy of header in HEADER
        :0 hw
        HEADER=|cat

        ...do whatever here

        # restore the header from $HEADER
        :0 hfwi
        | echo "$HEADER" ;

The semicolon on that last action is to force a shell to be used.
That way you don't have to worry about LINEBUF being too small.

If you need it to be _really_ efficient, then you can do the "save a copy"
using the \/ match operator.  That saves _two_ processes**.  To be robust,
before trying to copy $MATCH into the HEADER variable you need to first
make sure LINEBUF is large enough.  Once you've gone to _that_ trouble
you no longer need the semicolon in the 'restore' recipe's action, so
you save a process on that end too.  This ends up looking something like:


        # Save copy of header in HEADER.  First, match the entire header.
        :0
        * ^^\/(.+$)*
        {
                # Next, make sure LINEBUF is big enough.  Find the size
                # of the value of MATCH, add 20 or so to give room for
                # the 'echo' command, then subtract the current LINEBUF.
                # If it's positive, then LINEBUF isn't big enough.
                :0
                * 20^0
                * MATCH ?? 1^1 > 1
                * $ -$LINEBUF^0
                {
                        # Need to increase LINEBUF.  Add the current LINEBUF
                        # back onto the score from above...
                        :0
                        * $ $=^0
                        * $ $LINEBUF^0
                        {
                                # ...then set LINEBUF to the result
                                LINEBUF = $=
                        }
                }

                # Whew.  Now that we know LINEBUF is big enough,
                # copy MATCH to HEADER
                HEADER = $MATCH
        }

        ...do whatever here

        # restore the header from $HEADER
        :0 hfwi
        | echo "$HEADER"

Caveats: the above requires procmail version 3.14 or later.  You can
make it work with 3.12, 3.13, and 3.13.1 by putting
        # Set LINEBUF to the default if it isn't already set
        :0
        * $${LINEBUF:+!}
        { LINEBUF=2048 }
before this all.

Making it work with versions 3.10 through 3.11pre7 requires changing
that first condition to
        * ^^\/(.*$)*$
because those version will remove a trailing newline from MATCH.  You can
auto-detect for that by looking for the PROCMAIL_VERSION variable,
which also showed up in 3.12, but I think I've already fallen over the
complete-overkill/swatting-a-fly-with-a-tactical-nuclear-weapon edge so
I will shutup.


Philip Guenther



** DANGER DANGER: IMPLEMENTATION DETAILS FOLLOW!
In order to filter data through another program without having to worry
about deadlock, procmail creates an 'auxiliary' process that merely
stuffs the message data into the program in question.  This is done
whenever procmail is capturing the output of the program, such as for
filtering and variable capture actions and for backquote expansion.
For example, for that first recipe above:
        :0 hw
        HEADER=|cat

procmail creates a chain of three processes connected with pipes:

        +-----------+             +----------+
        | auxiliary |   +-----+   | main     |
        | procmail  |-->| cat |-->| procmail |
        | process   |   +-----+   | process  |
        +-----------+             +----------+
              |                         ^
              |     (recovery pipe)     |
              +-------------------------+

The recovery pipe is used to recover the original data when the filtering
process (in this case, cat) fails or fails to read all the data from
the auxiliary process (...but only if this is a filtering or variable
capture action).  There are more details beyond that, but if you really
care you need to read the source instead of listening to my babble.

_______________________________________________
procmail mailing list
procmail(_at_)lists(_dot_)RWTH-Aachen(_dot_)DE
http://MailMan.RWTH-Aachen.DE/mailman/listinfo/procmail

<Prev in Thread] Current Thread [Next in Thread>