home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-02-04 | 40.0 KB | 1,040 lines |
- Newsgroups: comp.sources.misc
- From: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
- Subject: v35i027: procmail - mail processing package v2.80, Part06/11
- Message-ID: <1993Feb5.020459.16607@sparky.imd.sterling.com>
- X-Md4-Signature: 570d6b94a6b1da31e9495ca6f644f790
- Date: Fri, 5 Feb 1993 02:04:59 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
- Posting-number: Volume 35, Issue 27
- Archive-name: procmail/part06
- Environment: sendmail, smail, MMDF, mailsurr, UNIX, POSIX
- Supersedes: procmail: Volume 31, Issue 40-44
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 6 (of 11)."
- # Contents: procmail280/HISTORY procmail280/mailinglist/INTRO
- # procmail280/man/procmailex.man procmail280/src/goodies.c
- # Wrapped by berg@hathi on Thu Feb 4 15:27:59 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'procmail280/HISTORY' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail280/HISTORY'\"
- else
- echo shar: Extracting \"'procmail280/HISTORY'\" \(9070 characters\)
- sed "s/^X//" >'procmail280/HISTORY' <<'END_OF_FILE'
- X Only the last entry is complete, the others might have been condensed.
- X
- X1990/12/07: v1.00
- X1990/12/12: v1.01
- X1991/02/04: v1.02
- X1991/02/13: v1.10
- X1991/02/21: v1.20
- X1991/02/22: v1.21
- X1991/03/01: v1.30
- X1991/03/15: v1.35
- X Started using RCS to manage the source
- X1991/06/04: v1.99
- X1991/06/10: v2.00
- X1991/06/11: v2.01
- X1991/06/12: v2.02
- X1991/06/20: v2.03
- X1991/07/04: v2.10
- X1991/07/12: v2.11
- X1991/10/02: v2.20 (never released)
- X1991/10/18: v2.30
- X Implemented a custom regular expression library (fully egrep
- X compatible), should eliminate the annoyances with incompatible
- X egreps
- X Accomplished the doubtful milestone of having a source file
- X (regexp.c) which provokes a compiler error on an old compiler
- X (if using the optimiser)
- X Ignoring leading spaces on condition lines now (means that
- X everything can be indented in the rcfile)
- X1991/10/22: v2.31
- X1991/12/05: v2.40
- X Made procmail capable of healing the recipient's mail spool file
- X Tricked NFS into supplying an access_time<modification_time for the
- X folders written
- X1991/12/13: v2.50
- X1992/01/22: v2.60
- X1992/01/31: v2.61
- X1992/04/30: v2.70
- X Made procmail & lockfile clock skew independent (important during
- X LOCKTIMEOUT)
- X Made procmail accept multiple recipients (this was not as trivial
- X as it sounds!), in order for complete compatibility with mailers
- X like smail 2.x
- X Expanded the mail-delivery-agent instructions in examples/advanced,
- X this includes specific intstructions for smail 2.x
- X Made special entries in config.h for semi-permanent environment-
- X variable overrides
- X Made formail more intelligent, it can now parse full-fledged
- X RFC822 addresses (quoting et al)
- X A complete rewrite of formail, the code got bigger, the runtime
- X requirement got bigger, it got slower, but, it's more structured
- X (so much for structured programming :-)
- X Made procmail check the permissions of its invoker, generate
- X an overriding From_ line if necessary, and consequently made it
- X accept the -f option (fromwhom), and also the alternate obsolete
- X -r option of course
- X Wiped out the ./include tree, made autoconf check it instead (the
- X compile line looks so terribly clean now :-)
- X Procmail makes an additional security check on the rcfiles before
- X accepting them (owner and permissions, see man page)
- X1992/07/01: v2.71
- X Sharpened the autoconf "const" check, to catch buggy AIX compilers
- X Made the MAILBOX_SEPARATORS more orthogonal (i.e. you can define
- X one or both now)
- X Added the -A option to formail, the only option that was missing
- X (to be able to boldly add header fields)
- X Fixed some typos and extended the procmailex man page by a popular
- X example
- X Enhanced the MH directory delivery mode, procmail uses the MH
- X method of finding the next number now (this requires procmail
- X to read the directory)
- X Fixed a typo in the WIFEXITED substitute macro (for non-POSIX
- X systems), should fix all erroneous "program failed" messages
- X Fixed a problem on byte-aligned machines with the 'i' flag
- X Now throwing away all environment variables starting with LD_
- X (not just LD_LIBRARY_PATH), but only on those machines that
- X have the security hole (i.e. SunOS)
- X Created logfile summariser (in shell-script form), by popular
- X demand (examples/mailstat)
- X Gave procmail, formail, lockfile and mailstat a more verbose
- X command line help (called up by -h or -?)
- X1993/02/04: v2.80
- X Started using CVS to manage the source (god's gift to programmers)
- X In procmail, lockfile and formail I built in a sanity check now,
- X in case they would be called with argc==0
- X Provided an *extensive* generic mailinglist example (well, it's
- X more than an example really :-)
- X Created the mailinglist swiss-army-knife utility "multigram"
- X Extended the man pages (including more examples)
- X Substantially changed the examples/advanced mailer integration
- X instructions (especially for smail)
- X Provided for brain damaged compilers that misparse #include lines
- X Enhanced lockfile a lot:
- X - the -r option really specifies *re*tries now
- X - concatenated and/or seperate options are allowed now
- X - fixed an inconsistency with removing lockfiles by force
- X - lockfile is more intelligent about locks which are impossible
- X to acquire (it sees it now and displays an appropriate error
- X message)
- X - related to this, lockfile now can return a whole range of
- X standard exitcodes to describe the error
- X - dropped the suid support for lockfile, sgid support however
- X was consolidated (with more descriptive error messages)
- X Changes to formail:
- X - formail does *NOT* CONCATENATE continued header-fields by
- X default now anymore, specify the -c option for this
- X - fixed the sender-determination-code, v2.71 didn't comply
- X with RFC-822 on some points
- X - the sender-determination-code now minimises the mailaddress
- X - taught formail about some more headers, previously formail
- X would refuse to split some mail-articles because it didn't
- X recognise the second field
- X - made it strip the <> on generated mail addresses
- X - reorganised the known header-fields into the header.h file
- X (to allow convenient additions)
- X - introduced the -l option, for generating procmail-alike
- X summaries
- X - introduced the -R option for renaming header-fields
- X - taught it about the Resent- fields when looking for a reply
- X address
- X - made sure that it does not generate an extra empty line at
- X the end of a mail with no body
- X - fixed the '-nnn' option, somehow this got broken
- X - added the -X option for extracting complete fields (to make
- X the toolset complete)
- X - defined away one const, for buggy Convex "ANSI" C compilers
- X Changes to procmail:
- X - procmail does *NOT* CONCATENATE continued header-fields
- X anymore, filter through "formail -c" for this
- X - procmail only escapes bogus From_ lines now when writing a
- X regular mailfolder (otherwise it's unchanged)
- X - changed the method for turning on extended diagnostics, the
- X preceding colon is not supported anymore, use VERBOSE=on
- X - worked over the mailbox-healing code, some changes were
- X needed to ensure complete functionality when the system
- X mailbox is in the user's home directory
- X - taught procmail about $? (see sh(1))
- X - added the INCLUDERC keyword, to permit unlimited nesting
- X of included rcfiles
- X - any program started in backquotes by procmail now has the
- X complete mail on its stdin
- X - all diagnostics logged by procmail will now be preceded by
- X a "procmail: " for easy identification
- X - as long as no LOGFILE has been specified, all diagnostics
- X will be mailed back to the sender (instead of /dev/null)
- X - when a program is specified on an action line, you can
- X precede the line by an environment variable name and an
- X equal sign; this will read in the (unlimited length) text
- X from stdout into this variable
- X - backslash-newline pairs on continued program-action lines
- X will be simply passed on now; unless the backslash-newline
- X pair is on an otherwise empty line, in which case only the
- X newline remains
- X - comsat/biff is fully supported now
- X - added the TRAP keyword, to allow for temporary file cleanup
- X - in explicit delivery mode, unknown users are now rejected
- X - system mailboxes with their suid or sgid bits set will not
- X be delivered to anymore, they are presumed to contain SysV
- X autoforwarding information
- X - a condition line of a recipe can now start with '?' in order
- X to use the exitcode of a program as true or false
- X - the ^TO and ^FROM_DAEMON special keywords can now be used
- X anywhere in the regular expression (^TO has been extended
- X as well)
- X - taught the ^^ special token to the internal egrep
- X - more than doubled the speed of the builtin regexp library
- X (which was already fast :-)
- X - procmail uses and defines LOGNAME instead of USER
- X Changes to the installation scripts:
- X - preset values for $(MAKE), $(CC) and $(SHELL) are respected
- X in Makefiles now
- X - a POSIX conforming grep is recognised and used
- X - the need for any -D_POSIX_SOURCE is recognised automatically
- X - to make sure that all this is possible, the Makefiles are
- X created in a two step-process now (make init)
- X - missing libraries for network/socket and opendir support
- X are searched for (you won't believe what names people picked
- X for network support libraries, not in your wildest dreams :-)
- X - the autoconf script now performs a reliability test on kernel
- X locking support
- X - also, network support for comsat tries to build up a compile
- X time cache for trivial get*byname() calls
- END_OF_FILE
- if test 9070 -ne `wc -c <'procmail280/HISTORY'`; then
- echo shar: \"'procmail280/HISTORY'\" unpacked with wrong size!
- fi
- # end of 'procmail280/HISTORY'
- fi
- if test -f 'procmail280/mailinglist/INTRO' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail280/mailinglist/INTRO'\"
- else
- echo shar: Extracting \"'procmail280/mailinglist/INTRO'\" \(9350 characters\)
- sed "s/^X//" >'procmail280/mailinglist/INTRO' <<'END_OF_FILE'
- X$Id: INTRO,v 1.5 1993/01/28 14:21:56 berg Exp $
- X
- X How to set up mailing lists
- X ---------------------------
- X
- X Written by Stephen R. van den Berg.
- X berg@pool.informatik.rwth-aachen.de
- X berg@physik.tu-muenchen.de
- X
- XThis document mainly describes a sendmail environment, much of it applies
- Xto non-sendmail mail agents as well.
- X
- X
- XContents:
- X--------- 1. Intro
- X 2. Bouncing mail
- X 3. The disadvantages
- X 4. How to circumvent these disadvantages
- X 5. Why use procmail to filter the mailinglist mail?
- X 6. How do I use procmail to filter the mailinglist mail?
- X
- X1. Intro
- X -----
- X
- XThe simplest and most direct way to setup a mailinglist is by inserting a line
- Xin the /usr/lib/aliases file looking like:
- X
- Xmylist: fred,john, wilma, barney@bedrock, pebbles
- X
- XNow all the mail arriving at your machine for "mylist" (either local or
- Xmylist@your.domain) will be automatically forwarded to all the mentioned
- Xaddresses (fred, john, etc.).
- X
- XThe address mylist@your.domain is intended for submissions to the list that
- Xare supposed to be forwarded to all the subscribers. For the administrative
- Xtasks like removals from the list, new subscriptions to the list, or address
- Xchanges of subscribers, it is common practice to create a second entry in the
- X/usr/lib/aliases file:
- X
- Xmylist-request: your_login_name@your.domain
- X
- X
- X2. Bouncing mail
- X -------------
- X
- XIn order to deal with bouncing mail gracefully, an extra precaution should
- Xbe taken. If for example mail to wilma bounces (user non-existent, mail
- Xfilesystem full, etc.), it will bounce back to the original sender.
- XNow, the only person that should be concerned with distribution failures
- Xshould be the mylist-request holder. Therefore you should be using a
- Xsendmail special alias like:
- X
- Xowner-mylist: mylist-request@your.domain
- X
- XThis way local mail will bounce back to mylist-request@your.domain.
- X
- X
- X3. The disadvantages
- X -----------------
- X
- XIf you are using the above methods, some obvious disadvantages come to mind
- Xhowever:
- X
- Xa. The subscriber list cannot exceed 1000 bytes (on many sendmails).
- Xb. The subscriber list cannot be changed on-the-fly (/usr/lib/aliases needs
- X to be edited, and newaliases has to be run).
- Xc. People cannot be prevented from submitting messages like "Please remove
- X me from this mailinglist" to mylist (and thereby annoying all subscribers).
- Xd. People cannot be guarded from themselves in case they insert
- X "Return-Receipt-To:" fields in their headers (if they are particularly
- X unlucky, they will receive an acknowledge mail from *every* subscriber's
- X sendmail).
- Xe. People including "Errors-To:" or "Sender:" fields can cause the bounce
- X messages to bypass owner-mylist anyway.
- Xf. There is no way of limiting the number of submitters, i.e. every person
- X who knows the name of the mailing list and who can send mail to your.domain
- X is able to submit messages to the list. This means, for example, that you
- X cannot limit a mailing list to local users (i.e. only local users can
- X submit).
- Xg. You are unable to insert a "Reply-To: mylist@your.domain" in case you
- X would want to (this makes replying to the list easier, too easy as some
- X people say).
- X
- X
- X4. How to circumvent these disadvantages
- X -------------------------------------
- X
- Xa. Can be circumvented by using nested aliases like:
- X mylist: mylist1, mylist2
- X mylist1: fred,john
- X mylist2: wilma,barney@bedrock,pebbles
- X This can however, become extremely messy to maintain.
- X
- Xb. This can be avoided if you use aliases like:
- X mylist: :include:/path/to/the/memberfile
- X The memberfile should contain:
- X fred,john,wilma,barney@bedrock,pebbles
- X This will also take care of the upper limit on aliases expansions and
- X newaliases need not be run again every time you change the file.
- X
- Xc. Can only be taken care of by using a mailfilter like procmail.
- X
- Xd. Can only be taken care of by using a mailfilter like procmail.
- X
- Xe. Can only be taken care of by using a mailfilter like procmail.
- X
- Xf. Can only be taken care of by using a mailfilter like procmail.
- X
- Xg. Can only be taken care of by using a mailfilter like procmail.
- X
- X
- X5. Why use procmail to filter the mailinglist mail?
- X ------------------------------------------------
- X
- XInstead of using a mailfilter you could also take care of most of the problems
- Xthree till seven by editing the sendmail.cf file. I would strongly recommend
- Xagainst this approach however, since this will be too much of a customising
- Xoperation and surely will not be a trivial task (in all cases). As a general
- Xrule: don't mess with a sendmail.cf file once it works :-).
- X
- XNow, you could, instead of procmail, simply use immediate VNIX commands
- Xlike grep, sed or awk to do the mail filtering. Again, there are some obvious
- Xdisadvantages with this approach:
- X
- XA. In case any system resources go out (no more file descriptors, no more
- X swap space, process table full, file system full (for temporary files))
- X your awk or shell script will fail generously (i.e. several bad things
- X could happen: mail munged, truncated, lost, hanging awk or sh programs,
- X etc., you get the picture).
- X
- XB. All mail headers (including From: and Reply-To:) could very well be
- X multi-line headers; it will be very difficult to make it understandable
- X to awk that somehow the header line could continue on the next line
- X (in case you want to remove a header, or do some complicated substitution).
- X
- XC. Another hairy problem will be determining the end of the header, of course
- X that is solvable, but you have to make some extra precautions in your
- X awk script to ensure that any substitutions/changes will not occur in
- X the body of the message (further degrading performance and increasing the
- X load on your machine).
- X
- XD. Starting programs directly from within aliases or .forward files can get
- X extremely messy, since the environment the program starts in is
- X potentially hostile.
- X
- XProcmail does not *directly* allow you to change any headers, but that
- Xfeature is not really necessary since you can tell procmail to send ONLY the
- Xheader through some filter of your choice.
- X
- XTo comment on the previously mentioned three disadvantages:
- X
- XA. Procmail takes care of that. Should the filter have problems anyway,
- X procmail will graciously notice that the filter was in some kind of
- X trouble, and will try something else with the original unmunged mail
- X (you can specify what it should do of course, obvious choices: try
- X the same filter again, drop the mail in a file and send you a notice,
- X forward the mail to you instead (unfiltered), etc.)
- X
- XB. In order to make consistent scanning of the header possible using the
- X egrep regular expressions built in to procmail, procmail will internally
- X concatenate any headers that were continued according to the RCF 822
- X recommendations, in order for external filters to benefit from this, you
- X would use the formail program to pre-filter the mail.
- X
- XC. Procmail can be told to send the header, the body or both through the
- X filter, hence your filter need not watch out to avoid doing any
- X substitutions in the body, and the filter can therefore be a lot simpler.
- X
- XD. Procmail makes no assumptions about the environment it is started in, it
- X assumes that everything is hostile and fights its way back to the
- X civilised world by initialising *everything* to sane and expected default
- X values. Thereby providing a warm bed for any program started from within
- X procmail.
- X
- XBut procmail has some additional advantages as well:
- X
- X -- It will probably all go a bit faster, since only the header of the mail
- X is being piped through the filter. Also, procmail reads in the mail in
- X 16KB chunks, not line by line as sed does.
- X
- X -- You could use procmail to filter out any messages to the normal mailing
- X list that should have gone to the mylist-request and remail them to
- X mylist-request.
- X
- XWell, anyway, as you see, procmail does not give you everything you would want,
- Xbut this was intentional in accordance to the true VNIX spirit (modularity).
- XWhat procmail does provide is a *very* reliable hook (you might say it
- Xprovides an anchor :-) for any mail processing you might do. For the more
- Xcomplex things you still have to use shell scripts or call other programs
- Xfrom within procmail, but then again, that saves you from learning any
- Xparticular syntax procmail would have had to do the same.
- X
- XAs it happens, the accompanying formail program is able to cater to most
- X(if not all) of your needs regarding mail munging.
- X
- X
- X6. How do I use procmail to filter the mailinglist mail?
- X -----------------------------------------------------
- X
- XIn order to cater for most wishes regarding mailinglist setup, I took the
- Xliberty to write some rcfiles for procmail that can readily be used to create
- Xany number of mailinglists in a comfortable and simple way.
- X
- XSee the FEATURES file in this directory for more information on what
- Xthese mailinglist scripts will do for you.
- X
- XIf the scripts do not exactly do what you would have liked, you are invited to
- Xedit them to taste. Perhaps you could send your changes to the procmail
- Xmailinglist if you feel that they could be useful to others.
- X
- XTo get started I suggest you read the INSTALL file in this directory.
- X
- XFor operating instructions you should read the Manual file in this directory.
- X
- X
- XP.S. Any suggestions/corrections/improvements on this document are welcome.
- END_OF_FILE
- if test 9350 -ne `wc -c <'procmail280/mailinglist/INTRO'`; then
- echo shar: \"'procmail280/mailinglist/INTRO'\" unpacked with wrong size!
- fi
- # end of 'procmail280/mailinglist/INTRO'
- fi
- if test -f 'procmail280/man/procmailex.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail280/man/procmailex.man'\"
- else
- echo shar: Extracting \"'procmail280/man/procmailex.man'\" \(8735 characters\)
- sed "s/^X//" >'procmail280/man/procmailex.man' <<'END_OF_FILE'
- X.Id $Id: procmailex.man,v 1.10 1993/01/29 13:32:49 berg Exp $
- X.de Sx
- X.PP
- X.ne \\$1
- X.Rs
- X..
- X.de Ex
- X.Re
- X.PP
- X..
- 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
- 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 mailling list into the mailfolder
- Xscubafile (uses the locallockfile scubafile.lock).
- X.Sx 3
- X::
- 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 7
- X:2 +CONTINUE+
- X^From.*peter
- X^Subject:.*compilers
- X! william@somewhere.edu
- X
- X :+ALSO_NEXT_RECIPE+
- X petcompil
- X.Ex
- XAn equivalent, but slightly slower solution that accomplishes the same:
- X.Sx 9
- X:2 +CONTINUE+
- X^From.*peter
- X^Subject:.*compilers
- X! william@somewhere.edu
- X
- X :2
- X ^From.*peter
- X ^Subject:.*compilers
- X petcompil
- 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:+PASS_HEAD++WAIT_EXIT++CONTINUE+:
- X!From +[^ ]*(postmaster|Mailer)
- X| uncompress headc.Z; cat >>headc; compress headc
- X.Ex
- XForward all mails shorter than 1000 bytes to my home address (no lockfile
- Xneeded on this recipe).
- X.Sx 3
- X:
- 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::
- X^Subject:.*surfing.*Digest
- X| formail +FM_SKIP+1 \-+FM_DIGEST++FM_SPLIT+ cat >>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::
- X^From[ :].*(postmaster|Mailer)
- 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: 2 +PASS_HEAD+ +CONTINUE+
- X!^FROM_DAEMON
- X!^From +YOUR_LOGIN_NAME
- 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, an autoreply will be sent (using the
- X`+ALSO_N_IF_SUCC+' flag functionality). 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 14
- XSHELL=/bin/sh # for other shells, this might need adjustment
- XALREADYSENT=$HOME/vacation # the vacation database
- X
- X: 2 +PASS_HEAD++WAIT_EXIT_QUIET++CONTINUE+: # the lockfile is important
- X!^FROM_DAEMON
- X!^From +YOUR_LOGIN_NAME
- X| FROM="`formail \-+FM_REPLY++FM_EXTRACT+ To:`" ;\e
- X if fgrep \-e "$FROM" <$ALREADYSENT ;\e
- X then exit 1 ;\e
- X else echo "$FROM" >>$ALREADYSENT ;\e
- X fi
- X
- X :+ALSO_N_IF_SUCC++PASS_HEAD++CONTINUE+
- X | (formail \-+FM_REPLY++FM_ADD_ALWAYS+"Precedence: junk";\e
- X echo "Mail received.") | $SENDMAIL \-t
- 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:
- 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 has to exist already.
- X.Sx 3
- X:
- X(^TO|^Subject:.*)TeX[^t]
- Xtexmail/.
- 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::
- Xmeeting
- 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:+IGNORE_WRITERR+
- X? test ! \-d $MONTHFOLDER
- X| mkdir $MONTHFOLDER
- X
- X::
- Xmeeting
- 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::
- Xmeeting
- X${MONTHFOLDER}/meeting
- X.Ex
- 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=/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 simply use:
- X.Sx 2
- XTRAP="exit 1;" # The trailing semi-colon is important
- X # since exit is not a standalone program
- X.Ex
- XThe following recipe prints every incoming mail that looks like a postscript
- Xfile.
- X.Sx 3
- X:+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
- X:2 +HEAD_GREP++BODY_GREP+ +PASS_BODY+
- X^^(.+$)*From[ :].*print-server
- X^^(.+$)*^%!
- X| lpr
- 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:+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
- 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:+BODY_GREP+:
- X$^From.*${URGMATCH}.*
- Xurgent
- X.Re
- X.Sh "SEE ALSO"
- X.na
- X.nh
- X.BR procmail (1),
- X.BR procmailrc (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 8735 -ne `wc -c <'procmail280/man/procmailex.man'`; then
- echo shar: \"'procmail280/man/procmailex.man'\" unpacked with wrong size!
- fi
- # end of 'procmail280/man/procmailex.man'
- fi
- if test -f 'procmail280/src/goodies.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail280/src/goodies.c'\"
- else
- echo shar: Extracting \"'procmail280/src/goodies.c'\" \(9142 characters\)
- sed "s/^X//" >'procmail280/src/goodies.c' <<'END_OF_FILE'
- X/************************************************************************
- X * Collection of library-worthy routines *
- X * *
- X * Copyright (c) 1990-1992, S.R. van den Berg, The Netherlands *
- X * #include "README" *
- X ************************************************************************/
- X#ifdef RCS
- Xstatic /*const*/char rcsid[]=
- X "$Id: goodies.c,v 1.13 1993/01/13 15:20:55 berg Exp $";
- X#endif
- X#include "procmail.h"
- X#include "sublib.h"
- X#include "robust.h"
- X#include "shell.h"
- X#include "misc.h"
- X#include "pipes.h"
- X#include "common.h"
- X#include "cstdio.h"
- X#include "goodies.h"
- X
- Xlong Stdfilled;
- X#ifndef GOT_bin_test
- Xconst char test[]="test";
- X#endif
- X
- X#define NOTHING_YET (-1) /* readparse understands a very complete */
- X#define SKIPPING_SPACE 0 /* subset of the standard /bin/sh syntax */
- X#define NORMAL_TEXT 1 /* that includes single-, double- and back- */
- X#define DOUBLE_QUOTED 2 /* quotes, backslashes and $subtitutions */
- X#define SINGLE_QUOTED 3
- X
- X#define fgetc() (*fpgetc)() /* some compilers previously choked on it */
- X
- X/* sarg==0 : normal parsing, split up arguments like in /bin/sh
- X * sarg==1 : environment assignment parsing, parse up till first whitespace
- X * sarg==2 : normal parsing, split up arguments by single spaces
- X */
- Xvoid readparse(p,fpgetc,sarg)register char*p;int(*const fpgetc)();
- X const int sarg;
- X{ static i;int got;char*startb;
- X for(got=NOTHING_YET;;) /* buf2 is used as scratch space */
- Xloop:
- X { i=fgetc();
- X if(buf+linebuf-3<p) /* doesn't catch everything, just a hint */
- X { nlog("Exceeded LINEBUF\n");p=buf+linebuf-3;goto ready;
- X }
- Xnewchar:
- X switch(i)
- X { case EOF: /* check sarg too to prevent warnings in the recipe- */
- X if(sarg!=2&&got>NORMAL_TEXT) /* condition expansion code */
- Xearly_eof: nlog(unexpeof);
- Xready: if(got!=SKIPPING_SPACE||sarg) /* not terminated yet or sarg==2 ? */
- X *p++='\0';
- X *p=TMNATE;return;
- X case '\\':
- X if(got==SINGLE_QUOTED)
- X break;
- X switch(i=fgetc())
- X { case EOF:goto early_eof; /* can't quote EOF */
- X case '\n':continue; /* concatenate lines */
- X case '#':
- X if(got>SKIPPING_SPACE) /* escaped comment at start of word? */
- X goto noesc; /* apparently not, literally */
- X case ' ':case '\t':case '\'':
- X if(got==DOUBLE_QUOTED)
- X goto noesc;
- X case '"':case '\\':case '$':case '`':goto nodelim;
- X }
- X if(got>NORMAL_TEXT)
- Xnoesc: *p++='\\'; /* nothing to escape, just echo both */
- X break;
- X case '`':
- X if(got==SINGLE_QUOTED)
- X goto nodelim;
- X for(startb=p;;) /* mark your position */
- X { switch(i=fgetc()) /* copy till next backquote */
- X { case '\\':
- X switch(i=fgetc())
- X { case EOF:nlog(unexpeof);goto forcebquote;
- X case '\n':continue;
- X case '"':
- X if(got!=DOUBLE_QUOTED)
- X break;
- X case '\\':case '$':case '`':goto escaped;
- X }
- X *p++='\\';break;
- X case '"':
- X if(got!=DOUBLE_QUOTED) /* missing closing backquote? */
- X break;
- Xforcebquote: case EOF:case '`':
- X { int osh=sh;
- X *p='\0';
- X if(!(sh=!!strpbrk(startb,tgetenv(shellmetas))))
- X { const char*save=sgetcp;
- X sgetcp=p=tstrdup(startb);readparse(startb,sgetc,0);
- X#ifndef GOT_bin_test
- X if(!strcmp(test,startb))
- X strcpy(startb,p),sh=1; /* oops, `test' found */
- X#endif
- X free(p);sgetcp=save; /* chopped up */
- X } /* drop source buffer, read from program */
- X startb=
- X fromprog(p=startb,startb,(size_t)(buf-startb+linebuf-3));
- X sh=osh; /* restore sh */
- X if(got!=DOUBLE_QUOTED)
- X { i=0;startb=p;goto simplsplit; /* split it up */
- X }
- X if(i=='"'||got<=SKIPPING_SPACE) /* missing closing ` ? */
- X got=NORMAL_TEXT; /* or sarg!=0 ? */
- X p=startb;goto loop;
- X }
- X case '\n':i=';'; /* newlines separate commands */
- X }
- Xescaped: *p++=i;
- X }
- X case '"':
- X switch(got)
- X { case DOUBLE_QUOTED:got=NORMAL_TEXT;continue; /* closing " */
- X case SINGLE_QUOTED:goto nodelim;
- X }
- X got=DOUBLE_QUOTED;continue; /* opening " */
- X case '\'':
- X switch(got)
- X { case DOUBLE_QUOTED:goto nodelim;
- X case SINGLE_QUOTED:got=NORMAL_TEXT;continue;} /* closing ' */
- X got=SINGLE_QUOTED;continue; /* opening ' */
- X case '#':
- X if(got>SKIPPING_SPACE) /* comment at start of word? */
- X break;
- X while((i=fgetc())!=EOF&&i!='\n'); /* skip till EOL */
- X goto ready;
- X case '$':
- X if(got==SINGLE_QUOTED)
- X break;
- X if(EOF==(i=fgetc()))
- X { *p++='$';goto ready;
- X }
- X startb=buf2;
- X if(i=='{') /* ${name} */
- X { while(EOF!=(i=fgetc())&&alphanum(i))
- X *startb++=i;
- X *startb='\0';
- X if(i!='}')
- X { nlog("Bad substitution of");logqnl(buf2);continue;
- X }
- X i='\0';
- X }
- X else if(alphanum(i)) /* $name */
- X { do *startb++=i;
- X while(EOF!=(i=fgetc())&&alphanum(i));
- X if(i==EOF)
- X i='\0';
- X *startb='\0';
- X }
- X else if(i=='$') /* $$ =pid */
- X { ultstr(0,(unsigned long)thepid,p);goto ieofstr;
- X }
- X else if(i=='?') /* $? =exitcode from last started program */
- X { strcpy(p,"-1");
- X if(lexitcode>=0)
- X ultstr(0,(unsigned long)lexitcode,p);
- X goto ieofstr;
- X }
- X else if(i=='-') /* $- =lastfolder */
- X { strcpy(p,lastfolder);
- Xieofstr: i='\0';goto eofstr;
- X }
- X else
- X { *p++='$';goto newchar; /* not a substitution */
- X }
- X startb=(char*)tgetenv(buf2);
- X if(got!=DOUBLE_QUOTED)
- Xsimplsplit: for(;;startb++) /* simply split it up in arguments */
- X { switch(*startb)
- X { case ' ':case '\t':case '\n':
- X if(got<=SKIPPING_SPACE)
- X continue;
- X *p++=sarg?' ':'\0';got=SKIPPING_SPACE;continue;
- X case '\0':goto eeofstr;
- X }
- X *p++= *startb;got=NORMAL_TEXT;
- X }
- X else
- X { strcpy(p,startb); /* simply copy it */
- Xeofstr: if(got<=SKIPPING_SPACE) /* can only occur if sarg!=0 */
- X got=NORMAL_TEXT;
- X p=strchr(p,'\0');
- X }
- Xeeofstr: if(i) /* already read next character? */
- X goto newchar;
- X continue;
- X case ' ':case '\t':
- X switch(got)
- X { case NORMAL_TEXT:
- X if(sarg==1)
- X goto ready; /* already fetched a single argument */
- X got=SKIPPING_SPACE;*p++=sarg?' ':'\0'; /* space or \0 sep. */
- X case NOTHING_YET:case SKIPPING_SPACE:continue; /* skip space */
- X }
- X case '\n':
- X if(got<=NORMAL_TEXT)
- X goto ready; /* EOL means we're ready */
- X }
- Xnodelim:
- X *p++=i; /* ah, a normal character */
- X if(got<=SKIPPING_SPACE) /* should we bother to change mode? */
- X got=NORMAL_TEXT;
- X }
- X}
- X
- Xwaitfor(pid)const pid_t pid; /* wait for a specific process */
- X{ int i;pid_t j;
- X while(pid!=(j=wait(&i))||WIFSTOPPED(i))
- X if(-1==j)
- X return -1;
- X return lexitcode=WIFEXITED(i)?WEXITSTATUS(i):-1;
- X}
- X
- Xstatic struct lienv{struct lienv*enext;char ename[255];}*myenv;
- Xstatic char**lastenv;
- X /* smart putenv, the way it was supposed to be */
- Xvoid sputenv(a)const char*const a;
- X{ static alloced;int i,remove;char*split,**preenv;struct lienv*curr,**last;
- X yell("Assigning",a);remove=0;
- X if(!(split=strchr(a,'='))) /* assignment or removal? */
- X remove=1,split=strchr(a,'\0');
- X i=split-a;
- X for(curr= *(last= &myenv);curr;curr= *(last= &curr->enext)) /* is it one */
- X if(!strncmp(a,curr->ename,i)&&curr->ename[i]=='=') /* I made earlier? */
- X { split=curr->ename;*last=curr->enext;free(curr);
- X for(preenv=environ;*preenv!=split;preenv++);
- X goto wipenv;
- X }
- X for(preenv=environ;*preenv;preenv++) /* is it in the standard */
- X if(!strncmp(a,*preenv,i)&&(*preenv)[i]=='=') /* environment? */
- Xwipenv:
- X { while(*preenv=preenv[1]) /* wipe this entry out of the environment */
- X preenv++;
- X break;
- X }
- X i=(preenv-environ+2)*sizeof*environ;
- X if(alloced) /* have we ever alloced the environ array before? */
- X environ=realloc(environ,i);
- X else
- X alloced=1,environ=tmemmove(malloc(i),environ,i-sizeof*environ);
- X if(!remove) /* if not remove, then add it to both environments */
- X { for(preenv=environ;*preenv;preenv++);
- X curr=malloc(ioffsetof(struct lienv,ename[0])+(i=strlen(a)+1));
- X tmemmove(*(lastenv=preenv)=curr->ename,a,i);preenv[1]=0;curr->enext=myenv;
- X myenv=curr;
- X }
- X}
- X /* between calling primeStdout() and retStdout() */
- Xvoid primeStdout P((void)) /* *no* environment changes are allowed! */
- X{ char*p;
- X if((p=strchr(buf,'\0'))[-1]!='=') /* does it end in an '='? */
- X *p='=',p[1]='\0'; /* make sure it does */
- X sputenv(buf);Stdout=(char*)myenv;
- X Stdfilled=ioffsetof(struct lienv,ename[0])+strlen(myenv->ename);
- X}
- X
- Xvoid retStdout(newmyenv)char*const newmyenv; /* see note on primeStdout() */
- X{ if(newmyenv[Stdfilled-1]=='\n') /* strip one trailing newline */
- X Stdfilled--;
- X newmyenv[Stdfilled]='\0';*lastenv=(myenv=(struct lienv*)newmyenv)->ename;
- X Stdout=0;
- X}
- X
- Xvoid postStdout P((void)) /* throw it into the keyword parser */
- X{ const char*p;size_t i;
- X p= *lastenv;tmemmove(buf,p,i=strchr(p,'=')-p);buf[i]='\0';asenv(p+i+1);
- X}
- END_OF_FILE
- if test 9142 -ne `wc -c <'procmail280/src/goodies.c'`; then
- echo shar: \"'procmail280/src/goodies.c'\" unpacked with wrong size!
- fi
- # end of 'procmail280/src/goodies.c'
- fi
- echo shar: End of archive 6 \(of 11\).
- cp /dev/null ark6isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 11 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Sincerely, berg@pool.informatik.rwth-aachen.de
- Stephen R. van den Berg (AKA BuGless). berg@physik.tu-muenchen.de
-
- "Be spontaneous!"
-
- exit 0 # Just in case...
-