home *** CD-ROM | disk | FTP | other *** search
- From: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
- Newsgroups: comp.sources.misc
- Subject: v43i059: procmail - mail processing package v3.03, Part04/10
- Date: 5 Jul 1994 20:49:54 -0500
- Organization: Sterling Software
- Sender: kent@sparky.sterling.com
- Approved: kent@sparky.sterling.com
- Message-ID: <2vd2k2$i78@sparky.sterling.com>
- X-Md4-Signature: 1b07b57835a8dc4e8fb6b49ec572b5bc
-
- Submitted-by: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
- Posting-number: Volume 43, Issue 59
- Archive-name: procmail/part04
- Environment: sendmail, ZMailer, smail, MMDF, mailsurr, UNIX, POSIX
- Supersedes: procmail: Volume 38, Issue 19-31
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: procmail-3.03/man/procmail.man
- # procmail-3.03/man/procmailex.man procmail-3.03/src/regexp.c
- # Wrapped by kent@sparky on Tue Jul 5 20:42:13 1994
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 4 (of 10)."'
- if test -f 'procmail-3.03/man/procmail.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail-3.03/man/procmail.man'\"
- else
- echo shar: Extracting \"'procmail-3.03/man/procmail.man'\" \(20759 characters\)
- sed "s/^X//" >'procmail-3.03/man/procmail.man' <<'END_OF_FILE'
- XPlease read the README file in this directory first.
- X.ex
- X.Id $Id: procmail.man,v 1.51 1994/06/28 14:49:23 berg Exp $
- X.TH PROCMAIL 1 \*(Dt BuGless
- X.na
- X.SH NAME
- Xprocmail \- autonomous mail processor
- X.SH SYNOPSIS
- X.B procmail
- X.RB [ \-@PRESERVOPT@@TEMPFAILOPT@@OVERRIDEOPT@ ]
- X.RB [ "\-@FROMWHOPT@ \fIfromwhom\fP" ]
- X.RI [ "parameter\fB=\fPvalue " | " rcfile" ]
- X\&.\|.\|.
- X.br
- X.B procmail
- X.RB [ \-@TEMPFAILOPT@@OVERRIDEOPT@ ]
- X.RB [ "\-@FROMWHOPT@ \fIfromwhom\fP" ]
- X.RB [ "\-@ARGUMENTOPT@ \fIargument\fP" ]
- X.B \-@DELIVEROPT@
- X.I recipient
- X\&.\|.\|.
- X.br
- X.B procmail
- X.RB [ \-@PRESERVOPT@@TEMPFAILOPT@ ]
- X.B \-@MAILFILTOPT@
- X.RI [ "parameter\fB=\fPvalue" ]
- X\&.\|.\|.
- X.I rcfile
- X.if n .ti +0.5i
- X.RI [ argument ]
- X\&.\|.\|.
- X.I mail_from rcpt_to
- X\&.\|.\|.
- X.br
- X.B procmail
- X.B \-@VERSIONOPT@
- X.ad
- X.SH DESCRIPTION
- XFor a quick start, see
- X.B NOTES
- Xat the end.
- X.PP
- X.B Procmail
- Xshould be invoked automatically over the
- X.B @DOT_FORWARD@
- Xfile mechanism as soon as mail arrives. Alternatively, when installed by
- Xa system administrator, it can be invoked from within the mailer immediately.
- XWhen invoked, it first sets some environment variables to default values,
- Xreads the mail message from stdin until an EOF, separates the body from the
- Xheader, and then, if no command line arguments are present, it starts to look
- Xfor a file named
- X.B @PROCMAILRC@
- Xin your home directory. According to the processing recipes in this file,
- Xthe mail message that just arrived gets distributed into the right folder
- X(and more).@ETCRC_desc@
- X.PP
- XIf running suid root or with root privileges, procmail will be able to
- Xperform as a functionally enhanced, backwards compatible mail delivery agent.
- X.PP
- XProcmail can also be used as a general purpose mail filter, i.e. provisions
- Xhave been made to enable procmail to be invoked in a special sendmail rule.
- X.PP
- XThe rcfile format is described in detail in the
- X.BR procmailrc (5)
- Xman page.
- X.PP
- XThe weighted scoring technique is described in detail in the
- X.BR procmailsc (5)
- Xman page.
- X.PP
- XExamples for rcfile recipes can be looked up in the
- X.BR procmailex (5)
- Xman page.
- X.SS Signals
- X.TP 1.2i
- X.B TERMINATE
- XTerminate prematurely and requeue the mail.
- X.TP
- X.B HANGUP
- XTerminate prematurely and bounce the mail.
- X.TP
- X.B INTERRUPT
- XTerminate prematurely and bounce the mail.
- X.TP
- X.B QUIT
- XTerminate prematurely and silently lose the mail.
- X.TP
- X.B ALARM
- XForce a timeout (see
- X.BR TIMEOUT).
- X.TP
- X.B USR1
- XEquivalent to a
- X.BR VERBOSE =on.
- X.TP
- X.B USR2
- XEquivalent to a
- X.BR VERBOSE =off.
- X.SH OPTIONS
- X.TP 0.5i
- X.B \-@VERSIONOPT@
- XProcmail will print its version number and exit.
- X.TP
- X.B \-@PRESERVOPT@
- XPreserve any old environment. Normally procmail clears the environment
- Xupon startup@KEEPENV@. However, in any case: any default values will override
- Xany preexisting environment variables, i.e. procmail will not pay any attention
- Xto any predefined environment variables, it will happily overwrite them
- Xwith its own defaults. For the list of environment variables that procmail
- Xwill preset see the
- X.BR procmailrc (5)
- Xman page. If both \-@PRESERVOPT@ and \-@MAILFILTOPT@ are specified, the
- Xlist of preset environment variables shrinks to just: LOGNAME, HOME, SHELL,
- XORGMAIL and MAILDIR.
- X.TP
- X.B \-@TEMPFAILOPT@
- XMake procmail fail softly, i.e. if procmail cannot deliver the mail to
- Xany of the destinations you gave, the mail will not bounce, but will return
- Xto the mailqueue. Another delivery-attempt will be made at some time in
- Xthe future.
- X.TP
- X.I "\fB\-@FROMWHOPT@\fP fromwhom"
- XCauses procmail to regenerate the leading `@FROM@' line with
- X.I fromwhom
- Xas the sender (instead of \-@FROMWHOPT@ one could use the alternate and
- Xobsolete \-@ALTFROMWHOPT@). If
- X.I fromwhom
- Xconsists merely of a single `@REFRESH_TIME@', then procmail will only
- Xupdate the timestamp on the `@FROM@' line (if present, if not, it will
- Xgenerate a new one).
- X.TP
- X.B \-@OVERRIDEOPT@
- XInstead of allowing anyone to generate `@FROM@' lines, simply override
- Xthe fakes.
- X.TP
- X.I "\fB\-@ARGUMENTOPT@\fP argument"
- XThis will set $1 to be equal to
- X.IR argument .
- XIt can be used to pass meta information along to procmail. This is
- Xtypically done by passing along the $@x information from the sendmail
- Xmailer rule.
- X.TP
- X.I "\fB\-@DELIVEROPT@\fP recipient .\|.\|."
- XThis turns on explicit delivery mode, delivery will be to the local user
- X.IR recipient .
- XThis, of course, only is possible if procmail has root
- Xprivileges@SETRUID@.
- XProcmail will setuid to the intended recipients and shall
- X.I only
- Xread the recipient's @PROCMAILRC@ file (if present, if not, delivery is like
- Xordinary mail). This option is incompatible with
- X.BR \-@PRESERVOPT@ .
- X.TP
- X.B \-@MAILFILTOPT@
- XTurns procmail into a general purpose mail filter. In this mode one rcfile
- Xmust be specified on the command line. After the rcfile, procmail will
- Xaccept an unlimited number of arguments.@ETCRCS_desc@
- XFor some typical usage of this option you should look in the
- X.B EXAMPLES
- Xsection below.
- X.SH ARGUMENTS
- XAny arguments containing an '=' are considered to be environment variable
- Xassignments, they will
- X.I all
- Xbe evaluated after the default values have been
- Xassigned and before the first rcfile is opened.
- X.PP
- XAny other arguments are presumed to be rcfile paths (either absolute,
- Xor if they start with `@chCURDIR@@MCDIRSEP@' relative to the current
- Xdirectory;
- X.B any other relative
- Xpath is relative to $HOME, unless the
- X.B \-@MAILFILTOPT@
- Xoption has been given, in which case all relative paths are relative to the
- Xcurrent directory); procmail will start with the first one it finds on the
- Xcommand line. The following ones will only be parsed if the preceding ones
- Xhave a not matching HOST-directive entry, or in case they should not exist.
- X.PP
- XIf no rcfiles are specified, it looks for
- X.BR $HOME/@PROCMAILRC@ .
- XIf not even that can be found, processing will continue according to
- Xthe default settings of the environment variables and the ones specified
- Xon the command line.
- X.SH EXAMPLES
- XExamples for rcfile recipes can be looked up in the
- X.BR procmailex (5)
- Xman page.
- XA small sample rcfile can be found in the
- X.B NOTES
- Xsection below.
- X.PP
- XThe
- X.B \-@MAILFILTOPT@
- Xoption is typically used when procmail is called from within a rule in the
- Xsendmail.cf file. In order to be able to do this it is convenient to create
- Xan extra `procmail' mailer in your sendmail.cf file (in addition to the perhaps
- Xalready present `local' mailer that starts up procmail). To create such a
- X`procmail' mailer I'd suggest something like:
- X.Sx 2
- XMprocmail, P=@BINDIR@/procmail, F=mSDFMhun, S=11, R=21,
- X A=procmail \-@MAILFILTOPT@ $h $f $u
- X.Ex
- XThis enables you to use rules like the following (most likely in ruleset 0)
- Xto filter mail through the procmail mailer (please note the leading tab
- Xto continue the rule, and the tab to separate the comments):
- X.Sx 4
- XR$*<@some.where>$*
- X $#procmail $@/etc/some.rc $:$1@some.where.procmail$2
- XR$*<@$*.procmail>$*
- X $1<@$2>$3 Already filtered, map back
- X.Ex
- XAnd /etc/some.rc could be as simple as:
- X.Sx 6
- X:0 # sink all junk mail
- X* ^Subject:.*junk
- X/dev/null
- X
- X:0 # pass along all other mail
- X! \-oi \-f "$@"
- X.Ex
- XDo watch out when sending mail from within the /etc/some.rc file, if
- Xyou send mail to addresses which match the first rule again, you could
- Xbe creating an endless mail loop.
- X.SH FILES
- X.TP 2.3i
- X.B /etc/passwd
- Xto set the recipient's LOGNAME, HOME and SHELL variable defaults
- X.TP
- X.B @SYSTEM_MBOX@
- Xsystem mailbox@ETCRC_files@@ETCRCS_files@
- X.TP
- X.B $HOME/@PROCMAILRC@
- Xdefault rcfile
- X.TP
- X.B @SYSTEM_MBOX@@DEFlockext@
- Xlockfile for the system mailbox (not automatically used by procmail, unless
- X$DEFAULT equals @SYSTEM_MBOX@ and procmail is delivering to $DEFAULT)
- X.TP
- X.B @DEFsendmail@
- Xdefault mail forwarder
- X.TP
- X.B @UNIQ_PREFIX@????`hostname`
- Xtemporary `unique' zero-length files created by procmail
- X.SH "SEE ALSO"
- X.na
- X.nh
- X.BR procmailrc (5),
- X.BR procmailsc (5),
- X.BR procmailex (5),
- X.BR sh (1),
- X.BR csh (1),
- X.BR mail (1),
- X.BR mailx (1),
- X.BR binmail (1),
- X.BR uucp (1),
- X.BR aliases (5),
- X.BR sendmail (8),
- X.BR egrep (1),
- X.BR grep (1),
- X.BR biff (1),
- X.BR comsat (8),
- X.BR lockfile (1),
- X.BR formail (1),
- X.BR cron (1)
- X.hy
- X.ad
- X.SH DIAGNOSTICS
- X.TP 2.3i
- XAutoforwarding mailbox found
- XThe system mailbox had its suid or sgid bit set, procmail terminates with
- XEX_NOUSER assuming that this mailbox must not be delivered to.
- X.TP
- XBad substitution of "x"
- XNot a valid environment variable name specified.
- X.TP
- XClosing brace unexpected
- XThere was no corresponding opening brace (nesting block).
- X.TP
- XConflicting options
- XNot all option combinations are useful
- X.TP
- XConflicting x suppressed
- XFlag x is not compatible with some other flag on this recipe.
- X.TP
- XCouldn't create "x"
- XThe system mailbox was missing and could not/will not be created.
- X.TP
- XCouldn't determine implicit lockfile from "x"
- XThere were no `>>' redirectors to be found, using simply `$LOCKEXT' as
- Xlocallockfile.
- X.TP
- XCouldn't unlock "x"
- XLockfile was already gone, or write permission to the directory were the
- Xlockfile is has been denied.
- X.TP
- XDeadlock attempted on "x"
- XThe locallockfile specified on this recipe is equal to a still active
- X$LOCKFILE.@ETCRCS_error@
- X.TP
- XEnforcing stricter permissions on "x"
- XThe system mailbox of the recipient was found to be unsecured, procmail
- Xsecured it.
- X.TP
- XError while writing to "x"
- XNonexistent subdirectory, no write permission, pipe died or disk full.
- X.TP
- XExceeded LINEBUF
- XBuffer overflow detected, LINEBUF was too small, memory might be corrupted.
- X.TP
- XExcessive output quenched from "x"
- XThe program or filter "x" tried to produce too much output for the current
- XLINEBUF, the rest was discarded.
- X.TP
- XExtraneous x ignored
- XThe action line of this recipe makes flag x meaningless.
- X.TP
- XFailed forking "x"
- XProcess table is full (and NORESRETRY has been exhausted).
- X.TP
- XFailed to execute "x"
- XProgram not in path, or not executable.
- X.TP
- XForced unlock denied on "x"
- XNo write permission in the directory where
- X.B lockfile
- X"x" resides, or more than one procmail trying to force a lock at exactly the
- Xsame time.
- X.TP
- XForcing lock on "x"
- X.B Lockfile
- X"x" is going to be removed by force because of a timeout (see also:
- X.BR LOCKTIMEOUT ).
- X.TP
- XIncomplete recipe
- XThe start of a recipe was found, but it stranded in an EOF.
- X.TP
- XInsufficient privileges
- XProcmail either needs root privileges, or must have the
- Xright (e)uid and (e)gid to run in delivery mode. Delivery will proceed
- Xto the invoker.
- X.TP
- XInvalid regexp "x"
- XThe regular expression "x" contains errors (most likely some missing or
- Xextraneous parens).
- X.TP
- XKernel-lock failed
- XWhile trying to use the kernel-supported locking calls, one of them failed
- X(usually indicates an OS error), procmail ignores this error and proceeds.
- X.TP
- XKernel-unlock failed
- XSee above.
- X.TP
- XLock failure on "x"
- XCan only occur if you specify some real weird (and illegal) lockfilenames
- Xor if the
- X.B lockfile
- Xcould not be created because of insufficient permissions or nonexistent
- Xsubdirectories.
- X.TP
- XLost "x"
- XProcmail tried to clone itself but could not find back rcfile "x" (it either
- Xgot removed or it was a relative path and you changed directory since
- Xprocmail opened it last time).
- X.TP
- XMissing closing brace
- XA nesting block was started, but never finished.
- X.TP
- XMissing name
- XThe \-@FROMWHOPT@ option needs an extra argument.
- X.TP
- XMissing argument
- XYou specified the \-@ARGUMENTOPT@ option but forgot the argument.
- X.TP
- XMissing rcfile
- XYou specified the \-@MAILFILTOPT@ option, procmail expects the name of an
- Xrcfile as argument.
- X.TP
- XMissing recipient
- XYou specified the \-@DELIVEROPT@ option or called procmail under a different
- Xname, it expects one or more recipients as arguments.
- X.TP
- XOut of memory
- XThe system is out of swap space (and NORESRETRY has been exhausted).
- X.TP
- XProcessing continued
- XThe unrecognised options on the command line are ignored, proceeding as
- Xusual.
- X.TP
- XProgram failure (nnn) of "x"
- XProgram that was started by procmail returned nnn instead of EX_OK (=@EX_OK@);
- Xif nnn is negative, then this is the signal the program died on.
- X.TP
- XRenaming bogus "x" into "x"
- XThe system mailbox of the recipient was found to be bogus, procmail performed
- Xevasive actions.
- X.TP
- XSkipped: "x"
- XCouldn't do anything with "x" in the rcfile (syntax error), ignoring it.
- X.TP
- XSuspicious rcfile "x"
- XThe owner of the rcfile was not the recipient or root, or the directory that
- Xcontained it was world writable (the rcfile was not used).
- X.TP
- XTerminating prematurely whilst waiting for .\|.\|.
- XProcmail received a signal while it was waiting for .\|.\|.
- X.TP
- XTimeout, terminating "x"
- XTimeout has occurred on program or filter "x".
- X.TP
- XTimeout, was waiting for "x"
- XTimeout has occurred on program, filter or file "x". If it was a program or
- Xfilter, then it didn't seem to be running anymore.
- X.TP
- XTruncating "x" and retrying lock
- X"x" does not seem to be a valid filename or the file is not empty.
- X.TP
- XRescue of unfiltered data succeeded/failed
- XA filter returned unsuccessfully, procmail tried to get back the original text.
- X.TP
- XUnexpected EOL
- XMissing closing quote, or trying to escape EOF.
- X.TP
- XUnknown user "x"
- XThe specified recipient does not have a corresponding uid.
- X.SH "EXTENDED DIAGNOSTICS"
- XExtended diagnostics can be turned on and off through setting the
- XVERBOSE variable.
- X.TP 2.3i
- X[pid] time & date
- XProcmail's pid and a timestamp. Generated whenever procmail logs a
- Xdiagnostic and at least a second has elapsed since the last timestamp.
- X.TP
- XAcquiring kernel-lock
- XProcmail now tries to kernel-lock the most recently opened file(descriptor).
- X.TP
- XAssigning "x"
- XEnvironment variable assignment.
- X.TP
- XBypassed locking "x"
- XThe mail spool directory was not accessible to procmail, it relied solely
- Xon kernel locks.
- X.TP
- XExecuting "x"
- XStarting program "x". If it is started by procmail directly (without an
- Xintermediate shell), procmail will show where it separated the arguments
- Xby inserting commas.
- X.TP
- XHOST mismatched "x"
- XThis host was called "x", HOST contained something else.
- X.TP
- XLocking "x"
- XCreating lockfile "x".
- X.TP
- XLinking to "x"
- XCreating a hardlink between directory folders.
- X.TP
- XMatch on "x"
- XCondition matched.
- X.TP
- XNo match on "x"
- XCondition didn't match, recipe skipped.
- X.TP
- XNotified comsat: "$LOGNAME@offset:file"
- XSent comsat/biff a notice that mail arrived for user $LOGNAME at `offset'
- Xin `file'.
- X.TP
- XOpening "x"
- XOpening file "x" for appending.
- X.TP
- XRcfile: "x"
- XRcfile changed to "x".
- X.TP
- XReiterating kernel-lock
- XWhile attempting several locking methods, one of these failed. Procmail will
- Xreiterate until they all succeed in rapid succession.
- X.TP
- XScore: added newtotal "x"
- XThis condition scored `added' points, which resulted in a `newtotal' score.
- X.TP
- XUnlocking "x"
- XRemoving lockfile "x" again.
- X.SH WARNINGS
- XYou should create a shell script that uses
- X.BR lockfile (1)
- Xbefore invoking your mail shell on any mailbox file other than the system
- Xmailbox (unless of course, your mail shell uses the same lockfiles (local
- Xor global) you specified in your rcfile).
- X.PP
- XIn the unlikely event that you absolutely need to kill procmail before it has
- Xfinished, first try and use the regular kill command (i.e.
- X.I not
- Xkill -9, see the subsection
- X.I Signals
- Xfor suggestions), otherwise some
- X.I lockfiles
- Xmight not get removed.
- X.PP
- XBeware when using the
- X.B \-@TEMPFAILOPT@
- Xoption, if procmail repeatedly is unable to deliver the mail (e.g. due to
- Xan incorrect rcfile), the system mailqueue could fill up. This could
- Xaggravate both the local postmaster and other users.@ETCRC_warn@@ETCRCS_warn@
- X.SH BUGS
- XAfter removing a lockfile by force, procmail waits $SUSPEND seconds before
- Xcreating a new lockfile so that another process that decides to remove the
- Xstale lockfile will not remove the newly created lock by mistake.
- X.PP
- XProcmail uses the regular TERMINATE signal to terminate any runaway filter,
- Xbut it does not check if the filter responds to that signal and it only sends
- Xit to the filter itself, not to any of the filter's children.
- X.PP
- XA continued
- X.B Content-Length:
- Xfield is not handled correctly.
- X.SH MISCELLANEOUS
- XIf there is an existing
- X.B Content-Length:
- Xfield in the header of the mail procmail will trim it to report the right
- Xsize. Procmail does not extend the field in length.
- X.PP
- XIf there is no
- X.B Content-Length:
- Xfield and procmail appends to regular mailfolders, any lines in the body of
- Xthe message that look like postmarks are prepended with `@ESCAP@' (disarms
- Xbogus mailheaders). The regular expression that is used to search for these
- Xpostmarks is:
- X.RS
- X`@FROM_EXPR@'
- X.RE
- X.PP
- XIf the destination name used in explicit delivery mode is not in /etc/passwd,
- Xprocmail will proceed as if explicit delivery mode was not in effect.
- XIf not in explicit delivery mode and
- Xshould the uid procmail is running under, have no corresponding /etc/passwd
- Xentry, then HOME will default to @RootDir@, LOGNAME will default to #uid and
- XSHELL will default to @BinSh@.
- X.PP
- XWhen in explicit delivery mode, procmail will generate a leading `@FROM@'
- Xline if none is present. If one is already present procmail will leave it
- Xintact.@TRUSTED_IDS@
- X.PP
- XFor security reasons procmail will only use an absolute or $HOME relative
- Xrcfile if it is either owned by the recipient or root and not world writable,
- Xor if the directory it is contained in is not world writable.
- X.PP
- XIf @SYSTEM_MBOX@ is a bogus mailbox (i.e. does not belong to the recipient,
- Xis unwritable, is a symbolic link or is a hard link), procmail will upon
- Xstartup try to rename it into a file starting with `@BOGUSprefix@' and
- Xending in an inode-sequence-code. If this turns out to be impossible,
- X.B ORGMAIL
- Xwill have
- X.I no
- Xinitial value, and hence will inhibit delivery without a proper rcfile.
- X.PP
- XIf @SYSTEM_MBOX@ already is a valid mailbox, but has got too loose permissions
- Xon it, procmail will correct this. To prevent procmail from doing this make
- Xsure the u+x bit is set.
- X.PP
- XWhen delivering to directories (or to MH folders) you
- X.B don't
- Xneed to use lockfiles to prevent several concurrently running procmail
- Xprograms from messing up.
- X.PP
- XDelivering to MH folders is slightly more time consuming than delivering
- Xto normal directories or mailboxes, because procmail has to search for
- Xthe next available number (instead of having the filename immediately
- Xavailable).
- X.PP
- XOn general failure procmail will return EX_CANTCREAT, unless option
- X.B \-@TEMPFAILOPT@
- Xis specified, in which case it will return EX_TEMPFAIL.
- X.PP
- XTo make `egrepping' of headers more consistent, procmail concatenates all
- Xcontinued header fields; but only internally. When delivering the mail, line
- Xbreaks will appear as before.
- X.PP
- XIf procmail is called under a name not starting with `procmail' (i.e. if it
- Xis linked to another name and invoked as such), it comes up in explicit
- Xdelivery mode, and expects the recipients' names as command line arguments
- X(as if \-@DELIVEROPT@ had been specified).
- X.PP
- XComsat/biff notifications are done using @COMSATprotocol@. They are sent off
- Xonce when procmail generates the regular logfile entry. The notification
- Xmessages have the following extended format (or as close as you can get when
- Xfinal delivery was not to a file):
- X.RS
- X$LOGNAME@offset_of_message_in_mailbox@COMSATxtrsep@absolute_path_to_mailbox
- X.RE
- X.PP
- XWhenever procmail itself opens a file to deliver to, it
- X@KERNEL_LOCKING@.
- X.PP
- XProcmail is NFS-resistant and eight-bit clean.
- X.br
- X.ne 11
- X.SH NOTES
- XCalling up procmail with the \-@HELPOPT1@ or \-@HELPOPT2@ options will cause
- Xit to display a command-line help and recipe flag quick-reference page.
- X.PP
- X@CF_procmail@
- XIn this case your $HOME/@DOT_FORWARD@ (beware, it
- X.B has
- Xto be world readable) file should contain the line below. Be sure to include
- Xthe single and double quotes, and it
- X.I must
- Xbe an
- X.I absolute
- Xpath. The \fB#\fP\fIYOUR_USERNAME\fP is not actually a parameter that is
- Xrequired by procmail, in fact, it will be discarded by sh before procmail ever
- Xsees it; it is however a necessary kludge against overoptimising sendmail
- Xprograms:
- X.PP
- X.na
- X.nf
- X@FW_content@
- X.fi
- X.ad
- X.PP
- XProcmail can also be invoked to postprocess an already filled system
- Xmailbox. This can be useful if you don't want to or can't use a
- X$HOME/@DOT_FORWARD@ file (in which case the following script could
- Xperiodically be called from within
- X.BR cron (1),
- Xor whenever you start reading mail):
- X.Sx 17
- X#!/bin/sh
- X
- Xif cd $HOME &&
- X test \-s @SYSTEM_MBOX@ &&
- X lockfile \-r0 \-l3600 .newmail.lock 2>/dev/null
- Xthen
- X trap "rm \-f .newmail.lock" 1 2 3 15
- X umask 077
- X lockfile \-l3600 \-ml
- X cat @SYSTEM_MBOX@ >>.newmail &&
- X cat /dev/null >@SYSTEM_MBOX@
- X lockfile \-mu
- X formail \-@FM_SPLIT@ procmail <.newmail &&
- X rm \-f .newmail
- X rm \-f .newmail.lock
- Xfi
- Xexit 0
- X.Ex
- X.ne 14
- X.SS "A sample small @PROCMAILRC@:"
- X.na
- X.nf
- XPATH=/bin:/usr/bin:@BINDIR@
- XMAILDIR=$HOME/Mail #you'd better make sure it exists
- XDEFAULT=$MAILDIR/mbox
- XLOGFILE=$MAILDIR/from
- X:0:
- X* ^From.*berg
- Xfrom_me
- X:0
- X* ^Subject:.*Flame
- X/dev/null
- X.fi
- X.ad
- END_OF_FILE
- if test 20759 -ne `wc -c <'procmail-3.03/man/procmail.man'`; then
- echo shar: \"'procmail-3.03/man/procmail.man'\" unpacked with wrong size!
- fi
- # end of 'procmail-3.03/man/procmail.man'
- fi
- if test -f 'procmail-3.03/man/procmailex.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail-3.03/man/procmailex.man'\"
- else
- echo shar: Extracting \"'procmail-3.03/man/procmailex.man'\" \(14982 characters\)
- sed "s/^X//" >'procmail-3.03/man/procmailex.man' <<'END_OF_FILE'
- XPlease read the README file in this directory first.
- X.ex
- X.Id $Id: procmailex.man,v 1.31 1994/06/14 12:03:19 berg Exp $
- X.TH PROCMAILEX 5 \*(Dt BuGless
- X.na
- X.SH NAME
- Xprocmailex \- procmail rcfile examples
- X.SH SYNOPSIS
- X.B $HOME/@PROCMAILRC@ examples
- X.ad
- X.SH DESCRIPTION
- XFor a description of the rcfile format see
- X.BR procmailrc (5).
- X.PP
- XThe weighted scoring technique is described in detail in the
- X.BR procmailsc (5)
- Xman page.
- X.PP
- XThis man page shows several example recipes. For examples of complete rcfiles
- Xyou can check the NOTES section in
- X.BR procmail (1),
- Xor look at the example rcfiles part of the procmail source distribution
- X(procmail*/examples/?procmailrc).
- X.SH EXAMPLES
- XSort out all mail coming from the scuba-dive mailing list into the mailfolder
- Xscubafile (uses the locallockfile scubafile.lock).
- X.Sx 3
- X:0:
- X* ^TOscuba
- Xscubafile
- X.Ex
- XForward all mail from peter about compilers to william (and keep a copy
- Xof it here in petcompil).
- X.Sx 10
- X:0
- X* ^From.*peter
- X* ^Subject:.*compilers
- X{
- X :0 @CONTINUE@
- X ! william@somewhere.edu
- X
- X :0
- X petcompil
- X}
- X.Ex
- XAn equivalent solution that accomplishes the same:
- X.Sx 7
- X:0 @CONTINUE@
- X* ^From.*peter
- X* ^Subject:.*compilers
- X! william@somewhere.edu
- X
- X :0 @ALSO_NEXT_RECIPE@
- X petcompil
- X.Ex
- XAn equivalent, but slightly slower solution that accomplishes the same:
- X.Sx 9
- X:0 @CONTINUE@
- X* ^From.*peter
- X* ^Subject:.*compilers
- X! william@somewhere.edu
- X
- X :0
- X * ^From.*peter
- X * ^Subject:.*compilers
- X petcompil
- X.Ex
- XIf your system doesn't generate or generates incorrect leading `From '
- Xlines on every mail, you can fix this by calling up procmail with
- Xthe \-@FROMWHOPT@@REFRESH_TIME@ option. To fix the same problem by
- Xdifferent means, you could have inserted the following two
- Xrecipes above all other recipes in your rcfile. They will filter the header
- Xof any mail through the first formail which will strip any leading `From '
- Xline, and then through the second formail which then regenerates it.
- X.Sx 5
- X:0 @FILTER@@PASS_HEAD@@WAIT_EXIT@
- X| formail \-@FM_DEL_INSERT@ "From "
- X
- X:0 @FILTER@@PASS_HEAD@@WAIT_EXIT@
- X| formail
- X.Ex
- XAdd the headers of all messages that didn't come from the postmaster
- Xto your private header collection (for
- Xstatistics or mail debugging); and use the lockfile `headc.lock'. In order
- Xto make sure the lockfile is not removed until the pipe has finished,
- Xyou have to specify option `@WAIT_EXIT@'; otherwise the lockfile would be
- Xremoved as soon as the pipe has accepted the mail.
- X.Sx 3
- X:0 @PASS_HEAD@@WAIT_EXIT@@CONTINUE@:
- X* !@FROMMkey@
- X| uncompress headc.Z; cat >>headc; compress headc
- X.Ex
- XOr, if you would use the more efficient gzip instead of compress:
- X.Sx 3
- X:0 @PASS_HEAD@@WAIT_EXIT@@CONTINUE@:
- X* !@FROMMkey@
- X| gzip >>headc.gz
- X.Ex
- XForward all mails shorter than 1000 bytes to my home address (no lockfile
- Xneeded on this recipe).
- X.Sx 3
- X:0
- X* < 1000
- X! myname@home
- X.Ex
- XSplit up incoming digests from the surfing mailing list into their individual
- Xmessages, and store them into surfing, using surfing.lock as the locallockfile.
- X.Sx 3
- X:0:
- X* ^Subject:.*surfing.*Digest
- X| formail @FM_SKIP@1 \-@FM_DIGEST@@FM_SPLIT@ >>surfing
- X.Ex
- XStore everything coming from the postmaster or mailer-daemon (like bounced
- Xmail) into the file postm, using postm.lock as the locallockfile.
- X.Sx 3
- X:0:
- X* @FROMMkey@
- Xpostm
- X.Ex
- XA simple autoreply recipe. It makes sure that neither mail from any daemon
- X(like bouncing mail or mail from mailing-lists), nor mail coming from yourself
- Xwill be autoreplied. If this precaution would not be taken, disaster could
- Xresult (`ringing' mail). In order for this recipe to autoreply to all the
- Xincoming mail, you should of course insert it before all other recipes in your
- Xrcfile. However, it is advisable to put it
- X.I after
- Xany recipes that process the mails from subscribed mailinglists; it generally
- Xis not a good idea to generate autoreplies to mailinglists (yes, the
- X!^FROM_DAEMON regexp should already catch those, but if the mailinglist
- Xdoesn't follow accepted conventions, this might not be enough).
- X.Sx 4
- X:0 @PASS_HEAD@ @CONTINUE@
- X* !^FROM_DAEMON
- X* !^From +YOUR_USERNAME
- X| (formail \-@FM_REPLY@ \-@FM_ADD_ALWAYS@"Precedence: junk";\e
- X echo "Mail received.") | $SENDMAIL \-t
- X.Ex
- XA more complicated autoreply recipe that implements the functional equivalent
- Xof the well known
- X.BR vacation (1)
- Xprogram. This recipe is based on the same principles as the last one (prevent
- X`ringing' mail). In addition to that however, it maintains a vacation database
- Xby extracting the name of the sender and appending it to the file
- X$ALREADYSENT, if the name is
- X.B not
- Xalready in there. If the name was new, it's name will be appended to the
- Xdatabase and an autoreply will be sent. To reliably extract the name of the
- Xsender, I let formail generate an autoreply header (thereby making it figure
- Xout the most appropriate sender address), and then telling it to extract the
- Xvalue of the `To:' field.
- X.Sx 17
- XSHELL=/bin/sh # for other shells, this might need adjustment
- X
- X:0
- X* !^FROM_DAEMON
- X* !^From +YOUR_USERNAME
- X{
- X FROM=`formail \-@FM_REPLY@@FM_EXTRACT@ To:`
- X ALREADYSENT=$HOME/vacation # the vacation database
- X
- X :0 @CONTINUE@: # the lockfile is important
- X * !? fgrep \-e "$FROM" $ALREADYSENT
- X | echo $FROM >>$ALREADYSENT; \e
- X (formail \-@FM_REPLY@@FM_ADD_ALWAYS@"Precedence: junk"; \e
- X echo "I received your mail,"; \e
- X echo "but I won't be back until Monday."; \e
- X echo "-- "; cat $HOME/.signature \e
- X ) | $SENDMAIL \-t
- X}
- X.Ex
- XStore all messages concerning TeX in separate, unique filenames, in a directory
- Xnamed texmail (this directory has to exist); there is no need to use lockfiles
- Xin this case, so we won't.
- X.Sx 3
- X:0
- X* (^TO|^Subject:.*)TeX[^t]
- Xtexmail
- X.Ex
- XThe same as above, except now we store the mails in numbered files (MH mail
- Xfolder), again the texmail directory should exist already.
- X.Sx 3
- X:0
- X* (^TO|^Subject:.*)TeX[^t]
- Xtexmail/.
- X.Ex
- XOr you could file the mail in several directory folders at the same time.
- XThe following recipe will deliver the mail to two MH-folders and one
- Xdirectory folder. It is actually only one file with two extra hardlinks.
- X.Sx 3
- X:0
- X* (^TO|^Subject:.*)TeX[^t]
- Xtexmail/. wordprocessing dtp/.
- X.Ex
- XStore all the messages about meetings in a folder that is in a directory
- Xthat changes every month. E.g. if it were January 1994, the folder
- Xwould have the name `94-01/meeting' and the locallockfile would be
- X`94-01/meeting.lock'.
- X.Sx 3
- X:0:
- X* meeting
- X`date +%y-%m`/meeting
- X.Ex
- XThe same as above, but, if the `94-01' directory wouldn't have existed, it
- Xis created automatically:
- X.Sx 9
- XMONTHFOLDER=`date +%y-%m`
- X
- X:0 @IGNORE_WRITERR@@CONTINUE@
- X* ? test ! \-d $MONTHFOLDER
- X| mkdir $MONTHFOLDER
- X
- X:0:
- X* meeting
- X${MONTHFOLDER}/meeting
- X.Ex
- XThe same as above, but now by slightly different means:
- X.Sx 6
- XMONTHFOLDER=`date +%y-%m`
- XDUMMY=`test \-d $MONTHFOLDER || mkdir $MONTHFOLDER`
- X
- X:0:
- X* meeting
- X${MONTHFOLDER}/meeting
- X.Ex
- XIf you are subscribed to several mailinglists and people cross-post to
- Xsome of them, you usually receive several duplicate mails (one from every
- Xlist). The following simple recipe eliminates duplicate mails. It tells
- Xformail to keep an 8KB cache file in which it will store the Message-IDs of
- Xthe most recent mails you received. Since Message-IDs are guaranteed to
- Xbe unique for every new mail, they are ideally suited to weed out duplicate
- Xmails. Simply put the following recipe at the top of your rcfile, and
- Xno duplicate mail will get past it.
- X.Sx 2
- X:0 @WAIT_EXIT_QUIET@@PASS_HEAD@: msgid.lock
- X| formail \-@FM_DUPLICATE@ 8192 msgid.cache
- X.Ex
- XWhen delivering to emacs folders (i.e. mailfolders managed by any emacs
- Xmail package, e.g. RMAIL or VM) directly, you should use emacs-compatible
- Xlockfiles. The emacs mailers are a bit braindamaged in that respect, they get
- Xvery upset if someone delivers to mailfolders which they already have in their
- Xinternal buffers. The following recipe assumes that $HOME equals /home/john.
- X.Sx 5
- XMAILDIR=Mail
- X
- X:0:/usr/local/lib/emacs/lock/!home!john!Mail!mailbox
- X* ^Subject:.*whatever
- Xmailbox
- X.Ex
- XAlternatively, you can have procmail deliver into its own set of mailboxes,
- Xwhich you then periodically empty and copy over to your emacs files using
- X.BR movemail .
- XMovemail uses mailbox.lock local lockfiles per mailbox.
- X.PP
- XTo extract certain headers from a mail and put them into environment
- Xvariables you can use any of the following constructs:
- X.Sx 5
- XSUBJECT=`formail \-@FM_EXTRACT@Subject:` # regular field
- XFROM=`formail \-@FM_REPLY@@FM_TRUST@ \-@FM_EXTRACT@To:` # special case
- X
- X:0 @PASS_HEAD@ # alternate method
- XKEYWORDS=| formail \-@FM_EXTRACT@Keywords:
- X.Ex
- XIf you are using temporary files in a procmailrc file, and want to make
- Xsure that they are removed just before procmail exits, you could use
- Xsomething along the lines of:
- X.Sx 2
- XTEMPORARY=$HOME/tmp/pmail.$$
- XTRAP="/bin/rm \-f $TEMPORARY"
- X.Ex
- XThe TRAP keyword can also be used to change the exitcode of procmail.
- XI.e. if you want procmail to return an exitcode of `1' instead of its
- Xregular exitcodes, you could use:
- X.Sx 3
- XEXITCODE=""
- XTRAP="exit 1;" # The trailing semi-colon is important
- X # since exit is not a standalone program
- X.Ex
- XOr, if the exitcode does not need to depend on the programs run from
- Xthe TRAP, you can use a mere:
- X.Sx 1
- XEXITCODE=1
- X.Ex
- XThe following recipe prints every incoming mail that looks like a postscript
- Xfile.
- X.Sx 3
- X:0 @BODY_GREP@@PASS_BODY@
- X* ^^%!
- X| lpr
- X.Ex
- XThe following recipe does the same, but is a bit more selective. It only
- Xprints the postscript file if it comes from the print-server. The first
- Xcondition matches only if it is found in the header (i.e. no preceding empty
- Xline). The second condition only matches at the start of the body (i.e.
- Xright after the
- X.B first
- Xempty line).
- X.Sx 4
- X:0 @HEAD_GREP@@BODY_GREP@ @PASS_BODY@
- X* ^^(.+$)*From[ :].*print-server
- X* ^^(.+$)*^%!
- X| lpr
- X.Ex
- XThe same as above, but now by slightly different means:
- X.Sx 7
- X:0
- X* ^From[ :].*print-server
- X{
- X :0 @BODY_GREP@ @PASS_BODY@
- X * ^^%!
- X | lpr
- X}
- X.Ex
- XSuppose you have two accounts, you use both accounts regularly, but they are
- Xin very distinct places (i.e. you can only read mail that arrived at either one
- Xof the accounts). You would like to forward mail arriving at account one to
- Xaccount two, and the other way around. The first thing that comes to mind is
- Xusing .forward files at both sites; this won't work of course, since you will
- Xbe creating a mail loop. This mail loop can be avoided by inserting the
- Xfollowing recipe in front of all other recipes in the @PROCMAILRC@ files on
- Xboth sites. If you make sure that you add the same X-Loop: field at both
- Xsites, mail can now safely be forwarded to the other account from either of
- Xthem.
- X.Sx 4
- X:0 @CONTINUE@
- X* !^X-Loop: yourname@your.main.mail.address
- X| formail \-@FM_ADD_ALWAYS@ "X-Loop: yourname@your.main.mail.address" | \e
- X $SENDMAIL \-oi yourname@the.other.account
- X.Ex
- XIf someone sends you a mail with the word `retrieve' in the subject, the
- Xfollowing will automatically send back the contents of info_file to the
- Xsender. Like in all recipes where we send mail, we watch out for mail
- Xloops.
- X.Sx 6
- X:0
- X* !^From +YOUR_USERNAME
- X* !^Subject:.*Re:
- X* !^FROM_DAEMON
- X* ^Subject:.*retrieve
- X| (formail \-@FM_REPLY@ ; cat info_file) | $SENDMAIL \-oi \-t
- X.Ex
- XNow follows an example for a very simple fileserver accessible by mail.
- XFor more demanding applications, I suggest you take a look at the mailinglist
- Xpackage included with the procmail source distribution. The most notable
- Xdeficiency of the `fileserver' you see below is that it doesn't do any
- Xaccess checking. It simply looks at the Subject: field in the header and
- Xextracts the names mentioned after the word `request'. These names are
- Xput in the variable FILE, which is subsequently used to cat the files.
- XThe best way to enhance this fileserver would probably be to create a shell
- Xscript to take care of the more complicated checks and operations.
- X.Sx 17
- X:0
- X* !^X-Loop: yourname@your.main.mail.address
- X* !^Subject:.*Re:
- X* !^FROM_DAEMON
- X* ^Subject:.*request
- X{
- X MAILDIR=$HOME/fileserver # chdir to the fileserver directory
- X
- X :0 @PASS_HEAD@ # extract the requested filename(s)
- X FILES=| sed \-n \-e 's/^Subject:.*request \(.*\)/\1/p'
- X
- X :0 @FILTER@ # reverse the mailheader
- X | formail \-@FM_REPLY@@FM_ADD_ALWAYS@ "X-Loop: yourname@your.main.mail.address"
- X
- X :0
- X | (cat; cat $FILES) | $SENDMAIL \-oi \-t
- X}
- X.Ex
- XThe following example preconverts all plain-text mail arriving in certain
- Xencoded MIME formats into a more compact 8-bit format which can be used
- Xand displayed more easily by most programs. The mmencode program is part
- Xof Nathaniel Borenstein's metamail package.
- X.Sx 17
- X:0
- X* ^Content-Type: *text/plain
- X{
- X :0 @FILTER@@PASS_BODY@@WAIT_EXIT@
- X * ^Content-Transfer-Encoding: *quoted-printable
- X | mmencode \-u \-q
- X
- X :0 @ALSO_NEXT_RECIPE@@FILTER@@PASS_HEAD@@WAIT_EXIT@
- X | formail \-@FM_DEL_INSERT@ "Content-Transfer-Encoding: 8bit"
- X
- X :0 @FILTER@@PASS_BODY@@WAIT_EXIT@
- X * ^Content-Transfer-Encoding: *base64
- X | mmencode \-u \-b
- X
- X :0 @ALSO_NEXT_RECIPE@@FILTER@@PASS_HEAD@@WAIT_EXIT@
- X | formail \-@FM_DEL_INSERT@ "Content-Transfer-Encoding: 8bit"
- X}
- X.Ex
- XThe following one is rather exotic, but it only serves to demonstrate a
- Xfeature. Suppose you have a file in your HOME directory called ".urgent",
- Xand the (one) person named in that file is the sender of an incoming mail,
- Xyou'd like that mail to be stored in $MAILDIR/urgent instead of in any of the
- Xnormal mailfolders it would have been sorted in. Then this is what you could
- Xdo (beware, the filelength of $HOME/.urgent should be well below $LINEBUF,
- Xincrease LINEBUF if necessary):
- X.Sx 5
- XURGMATCH=`cat $HOME/.urgent`
- X
- X:0 @BODY_GREP@:
- X* $^From.*${URGMATCH}.*
- Xurgent
- X.Ex
- XAn entirely different application for procmail would be to conditionally
- Xapply filters to a certain (outgoing) text or mail. A typical example
- Xwould be a filter through which you pipe all outgoing mail, in order
- Xto make sure that it will be MIME encoded only if it needs to be.
- XI.e. in this case you could start procmail in the middle of a pipe like:
- X.Sx 1
- Xcat newtext | procmail ./mimeconvert | mail chris@where.ever
- X.Ex
- XThe
- X.B mimeconvert
- Xrcfile could contain something like (the =0x80= and =0xff= should
- Xbe substituted with the real 8-bit characters):
- X.Sx 10
- XDEFAULT=| # pipe to stdout instead of
- X # delivering mail as usual
- X:0 @BODY_GREP@@FILTER@@PASS_BODY@@WAIT_EXIT@
- X* [=0x80=-=0xff=]
- X| mmencode -q
- X
- X :0 @ALSO_NEXT_RECIPE@@FILTER@@PASS_HEAD@@WAIT_EXIT@
- X | formail \-I 'MIME-Version: 1.0' \e
- X \-I 'Content-Type: text/plain; charset=ISO-8859-1' \e
- X \-I 'Content-Transfer-Encoding: quoted-printable'
- X.Ex
- X.SH "SEE ALSO"
- X.na
- X.nh
- X.BR procmail (1),
- X.BR procmailrc (5),
- X.BR procmailsc (5),
- X.BR sh (1),
- X.BR csh (1),
- X.BR mail (1),
- X.BR mailx (1),
- X.BR binmail (1),
- X.BR uucp (1),
- X.BR aliases (5),
- X.BR sendmail (8),
- X.BR egrep (1),
- X.BR grep (1),
- X.BR biff (1),
- X.BR comsat (8),
- X.BR lockfile (1),
- X.BR formail (1)
- X.hy
- X.ad
- END_OF_FILE
- if test 14982 -ne `wc -c <'procmail-3.03/man/procmailex.man'`; then
- echo shar: \"'procmail-3.03/man/procmailex.man'\" unpacked with wrong size!
- fi
- # end of 'procmail-3.03/man/procmailex.man'
- fi
- if test -f 'procmail-3.03/src/regexp.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail-3.03/src/regexp.c'\"
- else
- echo shar: Extracting \"'procmail-3.03/src/regexp.c'\" \(14786 characters\)
- sed "s/^X//" >'procmail-3.03/src/regexp.c' <<'END_OF_FILE'
- X/************************************************************************
- X * Custom regular expression library, *fully* egrep compatible *
- X * *
- X * Seems to be perfect. *
- X * *
- X * Copyright (c) 1991-1994, S.R. van den Berg, The Netherlands *
- X * #include "../README" *
- X ************************************************************************/
- X#ifdef RCS
- Xstatic /*const*/char rcsid[]=
- X "$Id: regexp.c,v 1.39 1994/06/28 16:56:43 berg Exp $";
- X#endif
- X#include "includes.h"
- X#include "robust.h"
- X#include "shell.h"
- X#include "misc.h"
- X#include "regexp.h"
- X
- X#define R_BEG_GROUP '('
- X#define R_OR '|'
- X#define R_END_GROUP ')'
- X#define R_0_OR_MORE '*'
- X#define R_0_OR_1 '?'
- X#define R_1_OR_MORE '+'
- X#define R_DOT '.'
- X#define R_SOL '^'
- X#define R_EOL '$'
- X#define R_BEG_CLASS '['
- X#define R_NOT_CLASS '^'
- X#define R_RANGE '-'
- X#define R_END_CLASS ']'
- X#define R_ESCAPE '\\'
- X
- X#define R_BEG_WORD '<'
- X#define R_END_WORD '>'
- X#define NO_WORD_CLASS "[^a-zA-Z0-9_]"
- X
- X#define BITS_P_CHAR 8
- X#define OPB (1<<BITS_P_CHAR)
- X#define DONE_NODE (OPB<<1)
- X#define DONE_MASK (DONE_NODE-1)
- X#define LOOPL_NODE (OPB<<2)
- X#define LOOPR_NODE (OPB<<3)
- X#define LOOP_MASK (LOOPL_NODE-1)
- X#define OPC_SEMPTY OPB /* stack empty special */
- X#define OPC_TSWITCH (OPB+1) /* task switch special */
- X#define OPC_DOT (OPB+2)
- X#define OPC_BOTEXT (OPB+3)
- X#define OPC_EPS (OPB+4)
- X#define OPC_JUMP (OPB+5)
- X#define OPC_CLASS (OPB+6)
- X#define OPC_FIN (OPB+7)
- X#define OPC_FILL (OPB+8) /* filler opcode, not executed */
- X /* Don't change any opcode above without checking skplen[] */
- X#define bit_type unsigned
- X#define bit_bits (sizeof(bit_type)*8)
- X#define bit_index(which) ((unsigned)(which)/bit_bits)
- X#define bit_mask(which) ((unsigned)1<<(unsigned)(which)%bit_bits)
- X#define bit_toggle(name,which) (name[bit_index(which)]^=bit_mask(which))
- X#define bit_test(name,which) (!!(name[bit_index(which)]&bit_mask(which)))
- X#define bit_set(name,which,value) \
- X (value?(name[bit_index(which)]|=bit_mask(which)):\
- X (name[bit_index(which)]&=~bit_mask(which)))
- X#define bit_field(name,size) bit_type name[((size)+bit_bits-1)/bit_bits]
- X
- X#define SZ(x) (sizeof(struct x))
- X#define Ceps (struct eps*)
- X#define epso(to,add) (Ceps((char*)(to)+(add)))
- X#define ii (aleps.topc)
- X#define jj (aleps.au.jju)
- X#define spawn sp.awn
- X
- Xstatic struct eps*r;
- Xstatic struct{unsigned topc;union{struct eps*tnext;unsigned jju;}au;}aleps;
- Xstatic uchar*p,*cachea,*cachep;
- Xstatic size_t cacher;
- Xstatic case_ignore,errorno;
- X
- Xstruct jump {unsigned opcj_;struct eps*nextj;};
- Xstruct mchar {unsigned opcc_;struct eps*next1_,*p1_,*p2_;};
- Xstruct chclass {unsigned opc_;struct eps*next_,*pos1,*pos2;
- X bit_field(c,OPB);};
- X /* length array, used by skiplen() */
- Xstatic /*const*/char skplen[]= /* it SHOULD have been const, but */
- X {SZ(eps),SZ(jump),SZ(chclass),0,0}; /* some !@#$%^&*() compilers disagree */
- X /* epsilon transition */
- Xstatic void puteps(spot,to)struct eps*const spot;const struct eps*const to;
- X{ spot->opc=OPC_EPS;spot->next=Ceps to;spot->spawn=0;
- X}
- X
- X#define Cc(p,memb) (((struct chclass*)(p))->memb)
- X#define rAc Cc(r,c)
- X
- Xstatic void bseti(i,j)unsigned i;const int j;
- X{ bit_set(rAc,i,j); /* mark 'i' as being in the class */
- X if(case_ignore) /* mark the other case too */
- X { if(i-'A'<'Z'-'A') /* uppercase */
- X i+='a'-'A';
- X else if(i-'a'<'z'-'a') /* lowercase */
- X i-='a'-'A';
- X else
- X return; /* no case */
- X bit_set(rAc,i,j);
- X }
- X}
- X /* general purpose length routine */
- Xstatic struct eps*skiplen(ep)const struct eps*const ep;
- X{ return epso(ep,(ep->opc&DONE_MASK)<OPC_EPS?
- X SZ(mchar):skplen[(ep->opc&DONE_MASK)-OPC_EPS]);
- X}
- X
- Xstatic int por P((const struct eps*const e));
- X
- Xstatic void psimp(e)const struct eps*const e;
- X{ switch(*p)
- X { case R_BEG_GROUP:p++; /* not so simple after all */
- X if(por(e))
- X errorno=1;
- X return;
- X case R_BEG_CLASS: /* a simple class */
- X { unsigned i,j=R_NOT_CLASS==*++p;
- X if(e)
- X { r->opc=OPC_CLASS;r->next=Ceps e;Cc(r,pos1)=Cc(r,pos2)=0;
- X i=maxindex(rAc);
- X do rAc[i]=j?~0:0; /* preset the bit field */
- X while(i--);
- X }
- X if(j) /* skip the 'not' modifier */
- X { p++;
- X if(e)
- X bit_toggle(rAc,'\n');
- X }
- X if(*p==R_END_CLASS) /* right at the start, cannot mean the end */
- X { p++;
- X if(e)
- X i=R_END_CLASS,bit_toggle(rAc,R_END_CLASS);
- X }
- X else if(*p==R_RANGE) /* take it literally */
- X { p++;
- X if(e)
- X i=R_RANGE,bit_toggle(rAc,R_RANGE);
- X }
- X for(;;p++)
- X { switch(*p)
- X { case R_END_CLASS:p++;
- X case '\0':r=epso(r,SZ(chclass));
- X return;
- X case R_RANGE:
- X switch(*++p)
- X { default:
- X if(e)
- X while(++i<*p) /* mark all in the range */
- X bseti(i,!j);
- X break;
- X case '\0':case R_END_CLASS:p--; /* literally */
- X }
- X }
- X if(e)
- X bseti(i= *p,!j); /* a normal character, mark it */
- X }
- X }
- X case '\0':
- X return;
- X case R_DOT: /* matches everything but a newline */
- X if(e)
- X { r->opc=OPC_DOT;
- X goto fine;
- X }
- X goto fine2;
- X case R_EOL:case R_SOL: /* match a newline (in effect) */
- X if(p[1]==R_SOL)
- X { p++;
- X if(e)
- X { r->opc=OPC_BOTEXT;
- X goto fine;
- X }
- X }
- X else if(e)
- X { r->opc='\n';
- X goto fine;
- X }
- X goto fine2;
- X case R_ESCAPE: /* quote something */
- X switch(*++p)
- X { case R_BEG_WORD:case R_END_WORD:
- X { uchar*pold=p;
- X p=(uchar*)NO_WORD_CLASS;psimp(e);p=pold+1;
- X if(e)
- X bit_toggle(Cc(epso(r,-(int)SZ(chclass)),c),'\n');
- X return;
- X }
- X case '\0':p--; /* nothing to quote */
- X }
- X }
- X if(e) /* a regular character */
- X { r->opc=case_ignore&&(unsigned)*p-'A'<'Z'-'A'?*p+'a'-'A':*p;
- Xfine:
- X r->next=Ceps e;Cc(r,pos1)=Cc(r,pos2)=0;
- X }
- Xfine2:
- X p++;r=epso(r,SZ(mchar));
- X}
- X
- X#define EOS(x) (jj?Ceps e:(x))
- X
- Xstatic void pnorm(e)const struct eps*const e;
- X{ void*pold;struct eps*rold;
- X for(;;)
- X { pold=p;rold=r;psimp(Ceps 0);ii= *p; /* skip it first */
- X jj=p[1]==R_OR||p[1]==R_END_GROUP||!p[1];
- X if(e)
- X p=pold,pold=r;
- X switch(ii) /* check for any of the postfix operators */
- X { case R_0_OR_MORE:r++;
- X if(e) /* first an epsilon, then the rest */
- X puteps(rold,EOS(r)),r=rold+1,psimp(rold);
- X goto incagoon;
- X case R_1_OR_MORE: /* first the rest */
- X if(e) /* and then an epsilon */
- X { puteps(r,rold);
- X if(jj)
- X (r+1)->opc=OPC_JUMP,(r+1)->next=Ceps e;
- X r=rold;psimp(Ceps pold);
- X }
- X r++;
- X if(p[1]==R_OR||p[1]==R_END_GROUP||!p[1])
- X r=epso(r,SZ(jump));
- X goto incagoon;
- X case R_0_OR_1:r++;
- X if(e) /* first an epsilon, then the rest */
- X puteps(rold,r=EOS(r)),pold=r,r=rold+1,psimp(Ceps pold);
- Xincagoon: switch(*++p) /* at the end of this group already? */
- X { case R_OR:case R_END_GROUP:case '\0':
- X return;
- X }
- X continue; /* regular end of the group */
- X case R_OR:case R_END_GROUP:case '\0':
- X if(e)
- X r=rold,psimp(e);
- X return;
- X }
- X if(e) /* no fancy postfix operators, plain vanilla */
- X r=rold,psimp(Ceps pold);
- X }
- X}
- X
- Xstatic int por(e)const struct eps*const e;
- X{ uchar*pvold;struct eps*rvold;
- X if(!e)
- X { rvold=r;
- X if(cachea==(pvold=p))
- X { p=cachep;r=epso(rvold,cacher);
- X goto ret0;
- X }
- X }
- X for(;;)
- X { uchar*pold;struct eps*rold;
- X for(pold=p,rold=r;;)
- X { switch(*p)
- X { default:pnorm(Ceps 0);r=rold; /* still in this group */
- X continue;
- X case '\0':case R_END_GROUP: /* found the end of the group */
- X if(p==pold) /* empty 'or' group */
- X { if(e)
- X r->opc=OPC_JUMP,r->next=Ceps e;
- X r=epso(r,SZ(jump));
- X }
- X else
- X p=pold,pnorm(e); /* normal last group */
- X if(!e)
- X { if(*p)
- X p++;
- X cachea=pvold;cachep=p;cacher=(char*)r-(char*)rvold;
- X goto ret0;
- X }
- X if(*p)
- X { p++;
- Xret0: return 0;
- X }
- X return 1;
- X case R_OR:r++;
- X if(p==pold) /* empty 'or' group */
- X { if(e)
- X puteps(rold,e); /* special epsilon */
- X }
- X else
- X { p=pold;pnorm(e); /* normal 'or' group, first an */
- X if(e) /* epsilon, then the rest */
- X puteps(rold,r);
- X }
- X p++;
- X }
- X break;
- X }
- X }
- X}
- X /* go down recursively, mark loopbacks on the way up again */
- Xstatic struct eps*maxback(down)struct eps*down;
- X{ ii=0; /* didn't find a loop at this level (yet) */
- X for(;;)
- X { switch(down->opc&LOOP_MASK) /* chase JUMP chains */
- X { default:
- X goto ret0; /* oops, not an EPS, return */
- X case OPC_JUMP:down->opc=OPC_JUMP|DONE_NODE; /* mark them as used */
- X case OPC_JUMP|DONE_NODE:down=down->next;
- X continue;
- X case OPC_EPS|DONE_NODE:ii=1; /* used EPS found, return loop number */
- X return down->spawn==Ceps&aleps?down:down->spawn;
- X case OPC_EPS:; /* unused EPS found, the work starts */
- X }
- X break;
- X }
- X if(!down->spawn) /* has it been visited (belongs to previous group?) */
- X { struct eps*left; /* no, so process it */
- X down->opc=OPC_EPS|DONE_NODE;down->spawn=Ceps&aleps; /* mark as used */
- X left=maxback(down->next); /* init loop no. and recurse left */
- X if(ii) /* loop found directly below us? */
- X down->opc|=LOOPL_NODE; /* mark a left-loop */
- X ;{ struct eps*right; /* recurse right, take the smallest */
- X if((right=maxback(down+1))&&(char*)left>(char*)right) /* loop no. */
- X left=right;
- X }
- X if(ii) /* loop found directly below? */
- X { down->opc|=LOOPR_NODE; /* mark a right-loop */
- X if(!(down->opc&LOOPL_NODE)) /* if we didn't also have a left-loop */
- X ii=0; /* we tell our predecessor we are not a loop */
- X }
- X if(!left) /* found no loop at all? */
- X { down->spawn=down; /* then give ourselves our own loop no. */
- X goto ret0;
- X }
- X if((down->spawn=left)!=down) /* save the loop no., check if it's us */
- X return left; /* if not, pass the number up */
- X } /* otherwise we are the end of the loop */
- Xret0:
- X return 0; /* no loop whatsoever */
- X}
- X
- Xstruct eps*bregcomp(a,ign_case)const char*const a;
- X{ struct eps*st;size_t i; /* first a trial run, determine memory needed */
- X skplen[OPC_FILL-OPC_EPS]=SZ(eps)-ioffsetof(struct eps,sp); /* a constant! */
- X errorno=0;p=(uchar*)a;case_ignore=ign_case;r=Ceps&aleps;cachea=0;por(Ceps 0);
- X st=r=
- X malloc((i=(char*)r-(char*)&aleps)+sizeof r->opc);
- X p=(uchar*)a;
- X if(!por(epso(st,i))) /* really compile */
- X errorno=1;
- X r->opc=OPC_FIN;
- X if(errorno)
- X nlog("Invalid regexp"),logqnl(a);
- X for(r=st;;st=skiplen(st)) /* simplify the compiled code (i.e. */
- X switch(st->opc) /* take out cyclic epsilon references) */
- X { case OPC_FIN:
- X return r; /* finished */
- X case OPC_EPS: /* check for any closed epsilon circles */
- X if(!st->spawn) /* they can't be executed */
- X { maxback(st); /* if not visited yet, recurse and mark loops */
- X ;{ register struct eps*i;
- X for(i=r;;i=skiplen(i)) /* search the whole program */
- X { switch(i->opc&LOOP_MASK)
- X { default: /* renumber regulars */
- X { register struct eps*f; /* if needed */
- X if(((f=i->next)->opc&DONE_MASK)==OPC_EPS&&f->spawn)
- X { for(;f->spawn!=f;f=f->spawn); /* search start */
- X i->next=f; /* of loop */
- X }
- X } /* spare the used nodes in this group */
- X case OPC_EPS|DONE_NODE:case OPC_JUMP|DONE_NODE:
- X case OPC_FILL:
- X continue;
- X case OPC_FIN:;
- X }
- X break;
- X }
- X }
- X ;{ register struct eps*i;
- X for(i=r;;i=skiplen(i)) /* search the whole program */
- X { switch(i->opc) /* unmark/transform the used nodes */
- X { case OPC_EPS|DONE_NODE|LOOPL_NODE:i->next=i+1;
- X case OPC_EPS|DONE_NODE|LOOPR_NODE:i->sp.sopc=OPC_FILL;
- X case OPC_JUMP|DONE_NODE:i->opc=OPC_JUMP;
- X continue;
- X case OPC_EPS|DONE_NODE|LOOPL_NODE|LOOPR_NODE:
- X case OPC_EPS|DONE_NODE:i->opc=OPC_EPS;
- X default:
- X continue;
- X case OPC_FIN:;
- X }
- X break;
- X }
- X }
- X }
- X }
- X}
- X
- X#define XOR1 \
- X (ioffsetof(struct chclass,pos1)^ioffsetof(struct chclass,pos2))
- X#define PC(this,t) (*(struct eps**)((char*)(this)+(t)))
- X
- Xchar*bregexec(code,text,str,len,ign_case)struct eps*code;
- X const uchar*const text;const uchar*str;size_t len;int ign_case;
- X{ register struct eps*reg,*stack,*other,*thiss;unsigned i,th1,ot1;
- X struct eps*initstack,*initcode;
- X static struct mchar tswitch={OPC_TSWITCH,Ceps&tswitch};
- X static struct eps sempty={OPC_SEMPTY,&sempty};
- X sempty.spawn=initstack= &sempty;
- X if((initcode=code)->opc==OPC_EPS)
- X initcode=(initstack=code)+1,code->spawn= &sempty;
- X th1=ioffsetof(struct chclass,pos1);ot1=ioffsetof(struct chclass,pos2);
- X if(str--==text||*str=='\n') /* make sure any beginning-of-line-hooks catch */
- X { thiss=Ceps&tswitch;len++;i='\n';
- X goto setups;
- X }
- X other=Ceps&tswitch;
- X do
- X { i= *++str; /* get the next real-text character */
- X if(ign_case&&i-'A'<'Z'-'A')
- X i+='a'-'A'; /* transmogrify it to lowercase */
- Xlastrun: /* switch this & other pc-stack */
- X th1^=XOR1;ot1^=XOR1;thiss=other;
- Xsetups:
- X other=Ceps&tswitch;stack=initstack;reg=initcode;
- X goto nostack;
- X for(;;) /* pop next entry off this pc-stack */
- X { thiss=PC(reg=thiss,th1);PC(reg,th1)=0;reg=reg->next;
- X goto nostack;
- X for(;;) /* pop next entry off the work-stack */
- X for(reg=stack->next,stack=stack->spawn;;)
- Xnostack: { switch(reg->opc-OPB)
- X { default:
- X if(i==reg->opc) /* regular character match */
- X goto yep;
- X break; /* push spawned branch on the work-stack */
- X case OPC_EPS-OPB:reg->spawn=stack;reg=(stack=reg)+1;
- X continue;
- X case OPC_JUMP-OPB:reg=reg->next;
- X continue;
- X case OPC_FIN-OPB:
- X return (char*)str; /* one past the match */
- X case OPC_SEMPTY-OPB:
- X goto empty_stack;
- X case OPC_TSWITCH-OPB:
- X goto pcstack_switch;
- X case OPC_BOTEXT-OPB:
- X if(str<text) /* only at the very beginning */
- X goto yep;
- X break;
- X case OPC_CLASS-OPB:
- X if(bit_test(((struct chclass*)reg)->c,i))
- X goto yep; /* character in class */
- X break;
- X case OPC_DOT-OPB: /* dot-wildcard */
- X if(i!='\n')
- Xyep: if(!PC(reg,ot1)) /* state not yet pushed */
- X PC(reg,ot1)=other,other=reg; /* push location onto */
- X } /* other pc-stack */
- X break;
- X }
- Xempty_stack:; /* the work-stack is empty */
- X }
- Xpcstack_switch:; /* this pc-stack is empty */
- X }
- X while(--len); /* still text to search */
- X if(ign_case!=2) /* out of text */
- X { ign_case=2;len=1;str++;
- X goto lastrun; /* check if we just matched */
- X }
- X return 0; /* no match */
- X}
- END_OF_FILE
- if test 14786 -ne `wc -c <'procmail-3.03/src/regexp.c'`; then
- echo shar: \"'procmail-3.03/src/regexp.c'\" unpacked with wrong size!
- fi
- # end of 'procmail-3.03/src/regexp.c'
- fi
- echo shar: End of archive 4 \(of 10\).
- cp /dev/null ark4isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 10 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-