home *** CD-ROM | disk | FTP | other *** search
- From: berg@marvin.e17.physik.tu-muenchen.de (Stephen R. van den Berg)
- Newsgroups: comp.sources.misc
- Subject: v16i103: procmail - mail processing package, Part01/01
- Message-ID: <1991Feb15.204604.11417@sparky.IMD.Sterling.COM>
- Date: 15 Feb 91 20:46:04 GMT
- Approved: kent@sparky.imd.sterling.com
- X-Checksum-Snefru: 88b9049f 80f979f6 529d317b a1748a93
-
- Submitted-by: Stephen R. van den Berg <berg@marvin.e17.physik.tu-muenchen.de>
- Posting-number: Volume 16, Issue 103
- Archive-name: procmail/part01
-
- The Procmail mail processing package. (v1.10 1991-02-13)
-
- Can be used to create mail-servers, mailing lists, sort your incoming mail
- (real convenient when subscribing to one or more mailing lists),
- preprocess your mail, or selectively forward certain incoming mail
- automatically to someone, etc...
-
- Procmail was designed to deliver the mail under the worst conditions
- (file system full, process table full, missing support files,
- unavailable executables; it all doesn't matter).
- Should (in the unlikely event) procmail be unable to deliver your mail
- somewhere, the mail will bounce back to the sender.
-
- Advantages: This package is small (boils down to one executable)
- and therefore robust, but still doesn't lack any mayor
- features you would want.
-
- Cheers,
- Stephen R. van den Berg at RWTH-Aachen, Germany.
-
- ---- Cut Here and feed the following to sh ----
- #!/bin/sh
- # This is Procmail, a shell archive (produced by shar 3.49)
- # To extract the files from this archive, save it to a file, remove
- # everything above the "!/bin/sh" line above, and type "sh file_name".
- #
- # made 02/13/1991 15:33 UTC by berg@marvin.e17.physik.tu-muenchen.de
- #
- # existing files will NOT be overwritten unless -c is specified
- #
- # This shar contains:
- # length mode name
- # ------ ---------- ------------------------------------------
- # 1086 -rw-r--r-- HISTORY
- # 814 -rw-r--r-- Makefile
- # 698 -rw-r--r-- Manifest
- # 3105 -rw-r--r-- README
- # 29 -rw-r--r-- forward
- # 1974 -rw-r--r-- lockfile.1
- # 2071 -rw-r--r-- lockfile.c
- # 12759 -rw-r--r-- procmail.1
- # 22067 -rw-r--r-- procmail.c
- # 310 -rw-r--r-- procmailrc
- # 364 -rw-r--r-- rmail
- # 1015 -rw-r--r-- sysexits.h
- #
- # ============= HISTORY ==============
- if test -f 'HISTORY' -a X"$1" != X"-c"; then
- echo 'x - skipping HISTORY (File already exists)'
- else
- echo 'x - extracting HISTORY (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'HISTORY' &&
- X1990-12-07: v1.00
- X First release (after 2 weeks of coding and testing)
- X1990-12-12: v1.01
- X Added fsync to procmail.c
- X Removed longjmp in lockfile.c out of the signal handler
- X (not portable, so I'm told)
- X1991-02-04: v1.02
- X Changes to procmail.c:
- X Added physical-write-error check
- X Altered egrep invocation (left out the -s flag, not supported
- X on all machines; this didn't change functionality though)
- X Avoided the 'dirty' allocation of one more byte than needed by
- X rewriting the bogus_header_replace routine
- X Made the finding bogus headers more robust
- X Added sysV lines in Makefile
- X1991-02-13: v1.10
- X Changes to procmail.c:
- X Fixed slight error in parsing the recipe when 'h' and 'b' where
- X specified
- X Started using the official exit codes
- X Made sure that the procmail is not influenced by falsely
- X set environment variables like LOCKSLEEP
- SHAR_EOF
- chmod 0644 HISTORY ||
- echo 'restore of HISTORY failed'
- Wc_c="`wc -c < 'HISTORY'`"
- test 1086 -eq "$Wc_c" ||
- echo 'HISTORY: original size 1086, current size' "$Wc_c"
- fi
- # ============= Makefile ==============
- if test -f 'Makefile' -a X"$1" != X"-c"; then
- echo 'x - skipping Makefile (File already exists)'
- else
- echo 'x - extracting Makefile (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
- XBASENAME = /global # change to your home directory if need be
- XBINDIR = ${BASENAME}/bin
- XMANDIR = ${BASENAME}/man/man1
- X
- XOCFLAGS = -O
- XOLDFLAGS = -s
- X
- X# Uncomment appropiately (for sysV and the like):
- XCFLAGS = ${OCFLAGS} #-DSYSV -DNOfsync -DNO_ANSI_PROT -Dvoid=char
- XLDFLAGS = ${OLDFLAGS} #-lbsd
- X
- XCC = cc
- XINSTALL= install -m 755
- XRM= rm -f
- X
- Xall: procmail lockfile
- X
- Xprocmail: procmail.o
- X ${CC} ${CFLAGS} -o procmail procmail.o ${LDFLAGS}
- X
- Xprocmail.o: procmail.c
- X ${CC} ${CFLAGS} -c procmail.c
- X
- Xlockfile: lockfile.o
- X ${CC} ${CFLAGS} -o lockfile lockfile.o ${LDFLAGS}
- X
- Xlockfile.o: lockfile.c
- X ${CC} ${CFLAGS} -c lockfile.c
- X
- Xinstall: all
- X ${INSTALL} procmail lockfile ${BINDIR}
- X chmod 644 procmail.1 lockfile.1
- X cp procmail.1 lockfile.1 ${MANDIR}
- X
- Xclean:
- X ${RM} procmail.o lockfile.o procmail lockfile
- SHAR_EOF
- chmod 0644 Makefile ||
- echo 'restore of Makefile failed'
- Wc_c="`wc -c < 'Makefile'`"
- test 814 -eq "$Wc_c" ||
- echo 'Makefile: original size 814, current size' "$Wc_c"
- fi
- # ============= Manifest ==============
- if test -f 'Manifest' -a X"$1" != X"-c"; then
- echo 'x - skipping Manifest (File already exists)'
- else
- echo 'x - extracting Manifest (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'Manifest' &&
- XMakefile We all know what that is.
- XREADME Important, read it.
- XHISTORY Recent and ancient changes (or bugs) documented.
- Xlockfile.1 Man page for lockfile.
- Xlockfile.c You guessed it.
- XManifest Right again.
- Xprocmail.1 Yes, the man page for procmail.
- Xprocmail.c Yes, exactly.
- Xsysexits.h Substitute for the machines that don't have it (is it ever
- X needed?)
- Xprocmailrc A sample .procmailrc file
- Xrmail A sample shell script that demonstrates how to use
- X lockfiles while reading the mail (to ensure mail integrity
- X as soon as you exit the mail program)
- Xforward A sample .forward file
- SHAR_EOF
- chmod 0644 Manifest ||
- echo 'restore of Manifest failed'
- Wc_c="`wc -c < 'Manifest'`"
- test 698 -eq "$Wc_c" ||
- echo 'Manifest: original size 698, current size' "$Wc_c"
- fi
- # ============= README ==============
- if test -f 'README' -a X"$1" != X"-c"; then
- echo 'x - skipping README (File already exists)'
- else
- echo 'x - extracting README (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'README' &&
- XSome legal stuff:
- X
- XUse this software package at your own risk. The programmer can not
- Xbe held liable for any incurred damages due to the use of this software.
- X
- XYou are encouraged to distribute this package freely. This package is
- Xhowever not to be not sold (minor transfer costs excepted) or included in
- Xany commercially sold software package (if you want to do this anyway,
- Xcontact me (address below), and we'll work something out).
- X
- XIf you distribute it, please leave the package in tact. If you have some
- Ximportant changes that might be usefull to the rest of the world, contact
- Xme instead.
- X
- X----------------------
- X
- XThe Procmail mail processing package. (v1.10 1991-02-13)
- X
- XCan be used to create mail-servers, mailing lists, sort your incoming mail
- X(real convenient when subscribing to one or more mailing lists),
- Xpreprocess your mail, or selectively forward certain incoming mail
- Xautomatically to someone.
- X
- XTo install it, edit the Makefile accordingly (if it doesn't compile at first,
- Xcheck if some extra header files should be included (or left out) in order
- Xto make any used types/defines/declarations for the library compatible).
- X
- XBTW, the warnings you get about 'loop not entered at top': they're normal :-).
- XSome older compilers could complain about ambiguous assignments, if they
- Xassume normal assigns, you're safe.
- X
- XIf you run procmail by hand and pipe in some sample mail, then make
- Xsure that if you kill procmail, you use "kill pid" and NOT "kill -9 pid".
- XShould procmail seem to hang, check if the $LOCKFILE is still present.
- XIf you kill procmail with "kill pid" it will clean up the $LOCKFILE
- Xitself.
- X
- XIf you really want to, you can change some of the defines at the start
- Xof procmail.c to suit your needs. They should be sufficient for most
- Xpeople though.
- X
- XEvery user that wants to use procmail should have a .forward and a
- X.procmailrc file in his HOME directory. For starters, you can look
- Xat the supplied example "forward" and "procmailrc" files.
- X(BTW, be sure to make .forward *world* readable).
- X
- XFor more info about the program, see the man page.
- X
- X----------------------
- X
- XAlthough I can't guarantee that the procmail (or lockfile) program
- Xwill perform as required, I must say that I made the utmost effort
- Xto make procmail as robust as any program can be.
- X
- XProcmail was designed to deliver the mail under the worst conditions
- X(file system full, process table full, missing support files,
- Xunavailable executables; it all doesn't matter).
- XShould (in the unlikely event) procmail be unable to deliver your mail
- Xsomewhere, the mail will bounce back to the sender.
- X
- XHowever, as with any program, bugs can not be completely ruled out.
- XI tested the program extensively, and believe it should be relatively
- Xbug free (no known bug at the time). Should, however, anyone
- Xfind any bugs (highly unlikely :-), I would be pleased (well, sort of :-)
- Xto hear about it. Please send me the patches or bug report.
- XI'll look at them and will try to fix it in a future release.
- X
- XCheers,
- X Stephen R. van den Berg at RWTH-Aachen, Germany.
- X
- XInternet E-mail: berg@marvin.e17.physik.tu-muenchen.de
- SHAR_EOF
- chmod 0644 README ||
- echo 'restore of README failed'
- Wc_c="`wc -c < 'README'`"
- test 3105 -eq "$Wc_c" ||
- echo 'README: original size 3105, current size' "$Wc_c"
- fi
- # ============= forward ==============
- if test -f 'forward' -a X"$1" != X"-c"; then
- echo 'x - skipping forward (File already exists)'
- else
- echo 'x - extracting forward (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'forward' &&
- X"|exec /global/bin/procmail"
- SHAR_EOF
- chmod 0644 forward ||
- echo 'restore of forward failed'
- Wc_c="`wc -c < 'forward'`"
- test 29 -eq "$Wc_c" ||
- echo 'forward: original size 29, current size' "$Wc_c"
- fi
- # ============= lockfile.1 ==============
- if test -f 'lockfile.1' -a X"$1" != X"-c"; then
- echo 'x - skipping lockfile.1 (File already exists)'
- else
- echo 'x - extracting lockfile.1 (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'lockfile.1' &&
- X.\" @(#)lockfile.1 1.29 90/12/07 SMI;
- X.de Sh
- X.br
- X.ne 6
- X.SH \\$1
- X..
- X.de Ss
- X.br
- X.ne 6
- X.SS \\$1
- X..
- X.TH LOCKFILE 1 "07 December 1990"
- X.SH NAME
- Xlockfile \- conditional semaphore-file creator
- X.SH SYNOPSIS
- X.B lockfile
- X[
- X.BI \- sleeptime
- X] [
- X.BI \-r retries
- X] [
- X.B \-!
- X]
- X.I filename
- X\&.\|.\|.
- X.Sh "DESCRIPTION"
- X.B lockfile
- Xcan be used to create one or more
- X.I semaphore
- X.IR files .
- XIf
- X.B lockfile
- Xcan't create all the specified files (in the specified order), it waits
- X.I sleeptime
- X(defaults to 8) seconds and retries the last file that didn't succeed.
- XYou can specify the number of
- X.I retries
- Xto do until failure is returned.
- XIf the number of
- X.I retries
- Xis 0 (default)
- X.B lockfile
- Xwill retry forever.
- X.LP
- XIf the number of
- X.I retries
- Xexpires before all files have been created,
- X.B lockfile
- Xreturns failure and removes all the files it created up till that point.
- X.LP
- XThe return value of
- X.B lockfile
- Xcan be easily inverted by specifying
- X.B \-!
- Xas an argument (handy in shell scripts).
- X.LP
- XAll flags can be specified anywhere on the command line, they will be
- Xprocessed when encountered. The command line is simply parsed from
- Xleft to right.
- X.LP
- XAll files created by
- X.B lockfile
- Xwill have access permission 0, and therefore will have to be removed
- Xwith
- X.B rm
- X.BR \-f .
- X.Sh "SEE ALSO"
- X.LP
- X.BR rm (1),
- X.BR mail (1),
- X.BR binmail (1),
- X.BR sendmail (8),
- X.BR procmail (1)
- X.Sh "BUGS & SPECIAL FEATURES"
- X.LP
- X.B lockfile
- Xis only a simple program and can't process concatenated options.
- X.LP
- XMultiple
- X.B \-!
- Xflags will not toggle the return status.
- X.Sh "NOTES"
- X.LP
- XSince flags can occur anywhere on the command line, any filename starting
- Xwith an '-' has to be preceded by another '-'.
- X.LP
- XThe number of
- X.I retries
- Xis global. That is, it is not reset when a new file is being created.
- XIt can, however, be reset by specifying
- X.RI \-r newretries
- Xafter every file on the command line.
- X.Sh "AUTHOR"
- X.LP
- XStephen R. van den Berg at RWTH-Aachen, Germany
- X.RS
- Xberg@marvin.e17.physik.tu-muenchen.de
- X.RE
- SHAR_EOF
- chmod 0644 lockfile.1 ||
- echo 'restore of lockfile.1 failed'
- Wc_c="`wc -c < 'lockfile.1'`"
- test 1974 -eq "$Wc_c" ||
- echo 'lockfile.1: original size 1974, current size' "$Wc_c"
- fi
- # ============= lockfile.c ==============
- if test -f 'lockfile.c' -a X"$1" != X"-c"; then
- echo 'x - skipping lockfile.c (File already exists)'
- else
- echo 'x - extracting lockfile.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'lockfile.c' &&
- X/************************************************************************
- X * lockfile.c a conditional semaphore-file creator *
- X * *
- X * Version 1.02 1990-12-07 *
- X * Is relatively bug free. *
- X * *
- X * Created by S.R.van den Berg, The Netherlands *
- X * The sources can be freely copied for any use. *
- X * *
- X * If you have had to make major changes in order to get it *
- X * running on a different machine, please send me the patches. *
- X * That way I might include them in a future version. *
- X ************************************************************************/
- X#include <stdio.h>
- X#include <fcntl.h>
- X#include <signal.h>
- X
- Xint exitflag;
- X
- Xvoid failure(){
- X exitflag=1;}
- X
- Xmain(argc,argv)char*argv[];{int sleepsec,retries,i,invert;char**p,*cp;
- X sleepsec=8;retries=invert=0;
- X if(argc<2){
- X putse("Usage: lockfile [-nnn] [-rnnn] [-!] file ...\n");return 2;}
- Xagain:
- X p=argv+1;signal(SIGHUP,failure);signal(SIGINT,failure);
- X signal(SIGQUIT,failure);signal(SIGTERM,failure);
- X do
- X if(*(cp=*p)=='-')
- X switch(cp[1]){
- X case'!':invert=1;break;
- X case'r':retries=strtol(cp+2,NULL,10);break;
- X case'-':cp++;goto filename;
- X default:
- X if(sleepsec>=0)
- X sleepsec=strtol(cp+1,NULL,10);}
- X else
- Xfilename:
- X if(sleepsec<0)
- X unlink(cp);
- X else{
- X while(0>(i=open(cp,O_WRONLY|O_CREAT|O_EXCL|O_SYNC,0))){
- X if(exitflag||retries==1){
- X sleepsec=-1;*p=0;goto again;}
- X sleep(sleepsec);
- X if(retries)
- X retries--;}
- X close(i);}
- X while(*++p);
- Xreturn invert^(sleepsec<0);}
- X
- X#define STDERR 2
- X
- Xputse(a)char*a;{char*b;
- X b=a-1;
- X while(*++b);
- X write(STDERR,a,b-a);}
- SHAR_EOF
- chmod 0644 lockfile.c ||
- echo 'restore of lockfile.c failed'
- Wc_c="`wc -c < 'lockfile.c'`"
- test 2071 -eq "$Wc_c" ||
- echo 'lockfile.c: original size 2071, current size' "$Wc_c"
- fi
- # ============= procmail.1 ==============
- if test -f 'procmail.1' -a X"$1" != X"-c"; then
- echo 'x - skipping procmail.1 (File already exists)'
- else
- echo 'x - extracting procmail.1 (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmail.1' &&
- X.\" @(#)procmail.1 1.29 91/02/13 SMI;
- X.de Sh
- X.br
- X.ne 6
- X.SH \\$1
- X..
- X.de Ss
- X.br
- X.ne 6
- X.SS \\$1
- X..
- X.de Tp
- X.br
- X.ne 6
- X.TP \\$1
- X..
- X.TH PROCMAIL 1 "13 February 1991"
- X.SH NAME
- Xprocmail \- autonomous mail processor
- X.SH SYNOPSIS
- X.B procmail
- X[
- X.IB environmentvariable = value
- X|
- X.I rcfilename
- X]
- X\&.\|.\|.
- X.Sh "DESCRIPTION"
- X.LP
- XFor a quick start, see
- X.B NOTES
- Xat the end.
- X.LP
- X.B procmail
- Xfirst sets some environment variables to default values, then, if no
- Xarguments are specified, it reads the mail message from stdin until an
- XEOF, separates
- Xthe body from the header and starts to look for a file named
- X.B .procmailrc
- Xin your home directory.
- X.LP
- X.Ss "Defaults"
- X.Tp 22
- X.B USER, HOME and SHELL
- XYour (the recipient's) defaults
- X.Tp
- X.B SHELLMETA
- X"'`{}()[]*?|<>~;!\\
- X.Tp
- X.B SHELLFLAGS
- X-c
- X.Tp
- X.B MAILDIR
- X$HOME
- X.Tp
- X.BR DEFAULT
- X$MAILDIR/.mailbox
- X.Tp
- X.B ORGMAIL
- X/var/spool/mail/$USER
- X.Tp
- X.B GREP
- X/usr/bin/egrep
- X.Tp
- X.B SENDMAIL
- X/usr/lib/sendmail
- X.Tp
- X.B LOCKEXT
- X\&.lock
- X.Tp
- X.B LOCKSLEEP
- X8
- X.Ss "Environment"
- X.Tp 12
- X.B MAILDIR
- XDefault directory while
- X.B procmail
- Xis executing (that means that all paths are relative to $MAILDIR).
- X.Tp
- X.B DEFAULT
- XDefault mailbox file (if not told otherwise,
- X.B procmail
- Xwill dump mail in this file)
- X.Tp
- X.B LOGFILE
- XAll incoming messages will be logged here with their 'From' and 'Subject'
- Xlines in the header. This file will also contain any error or diagnostic
- Xmessages from
- X.BR procmail .
- X(Normally none :-). If this file is not specified it defaults to
- X.BR /dev/null.
- X.Tp
- X.B ORGMAIL
- XUsually the system mailbox (ORiGinal MAILbox). If, for some obscure
- Xreason (like "filesystem full") the mail could not be delivered, then this
- Xfile will be the last resort. If
- X.B procmail
- Xfails to save the mail in here (deep, deep trouble :-), then the mail
- Xwill bounce back to the sender.
- X.Tp
- X.B LOCKFILE
- XGlobal semaphore file. If this file already exists,
- X.B procmail
- Xwill wait until it has gone before proceeding, and will create it itself
- X(cleaning it up when ready, of course). If more than one lockfile are
- Xspecified, then the previous one will be removed before trying to create
- Xthe new one.
- X.Tp
- X.B LOCKEXT
- XDefault extension that is appended to a destination file to determine
- Xwhat local lockfile to use (only if turned on, on a per-recipe basis).
- X.Tp
- X.B LOCKSLEEP
- XNumber of seconds
- X.B procmail
- Xwill sleep before retrying on a lockfile (if it already existed).
- X.Tp
- X.B HOST
- XIf this is not the hostname of the machine, processing of the current
- Xrcfile will immediately cease. If other rcfiles were specified on the
- Xcommand line, processing will continue with the next one. If all rcfiles
- Xare exhausted, the program will terminate, but will not generate an error
- X(i.e. to the mailer it will seem that the mail has been delivered).
- X.Tp
- X.B UMASK
- XThe name says it all (if it doesn't, then forget about this one :-). It
- Xis taken as an octal number. If not specified, it defaults to 077.
- X.Tp
- X.B GREP
- XThe program that gets called for parsing regular expressions.
- X.br
- XIt is called as: $GREP -e "$*" [-i];
- X.Tp
- X.B SHELLMETA
- XIf any of the characters in
- X.B SHELLMETA
- Xappears in the line specifying a filter or program, the line will be feeded
- Xto
- X.B $SHELL
- Xinstead of being executed directly.
- X.Tp
- X.B SHELLFLAGS
- XAny invocation of
- X.B $SHELL
- Xwill be like:
- X.br
- X$SHELL $SHELLFLAGS "$*";
- X.Tp
- X.B SENDMAIL
- XIf you're not using the
- X.I forwarding facility
- Xdon't worry about this one. It specifies the program being called to
- Xforward any mail.
- X.br
- XIt gets invoked as: $SENDMAIL $*;
- X.Sh "ARGUMENTS"
- X.LP
- XAny arguments containing an '=' are considered to be environment variable
- Xassignments, they will
- X.B all
- Xbe evaluated after the default values have been
- Xassigned and before the
- X.B first
- Xrcfile is parsed.
- X.LP
- XAny other arguments are presumed to be rcfiles;
- X.B procmail
- Xwill start with the first one it finds on the command line. The following
- Xones will only be parsed if the preceding ones have a not matching
- X.B HOST
- Xdirective entry.
- X.LP
- XIf no rcfiles are specified, it looks for $HOME/.sortmailrc. If not even
- Xthat can be found processing will continue according to the default
- Xsettings of the environment variables and the ones specified on the command
- Xline.
- X.Sh "RCFILE FORMAT"
- X.LP
- XEnvironment variable assignments and recipes can be freely intermixed
- Xin the rcfile. If any environment variable has a special meaning to
- X.BR procmail ,
- Xit will used appropiately the moment it is parsed. (i.e. you can
- Xchange the default directory whenever you want by specifying a new
- X.BR MAILDIR ,
- Xswitch lockfiles by specifying a new
- X.B LOCKFILE
- X(normal persons won't need this particular application though), change
- Xthe umask at any time, etc., the possibilities are endless :-).
- X.LP
- XValues being assigned to environment variables (in the rcfile) can not
- Xcontain any space, tab, newline or '#' characters. Anything on a line
- Xfrom the first '#' till EOL is considered comment.
- X.Ss "Recipes"
- X.LP
- XA line starting with ':' marks the beginning of a recipe. It has the
- Xfollowing format:
- X.LP
- X: [
- X.I number
- X] [
- X.I options
- X] [ : [
- X.I locallockfile
- X] ]
- X.LP
- XThe
- X.I number
- Xis optional
- X(defaults to 1) and specifies the number of conditionals following this
- Xline. Conditionals are complete lines that are passed onto
- X.B $GREP
- X.BR literally ,
- Xconditionals are anded; if
- X.I number
- Xis zero, then the condition is always true and no conditionals are expected
- Xnext.
- X.LP
- X.I Options
- Xcan be any of the following (don't insert spaces in between, from the first
- Xcharacter that is not a valid option till EOL will be skipped without notice):
- X.Tp 5
- X.B H
- XFeed the header to $GREP (default)
- X.Tp
- X.B B
- XFeed the body to $GREP
- X.Tp
- X.B I
- XTell $GREP to ignore case
- X.Tp
- X.B h
- XFeed the header to the pipe (default)
- X.Tp
- X.B b
- XFeed the body to the pipe (default)
- X.Tp
- X.B f
- XConsider the pipe as a filter (ignored if a file)
- X.Tp
- X.B c
- XContinue processing rcfile even if this recipe matches (not needed if 'f'
- Xspecified)
- X.Tp
- X.B w
- XWait for the process to finish (and check if it was successfull, normally
- Xignored). If you specify 'f' and it matches, and the original mailer
- Xwill be told that the mail has already been delivered. If you want
- X.B procmail
- Xto stall telling the mailer that the mail has been delivered, until
- Xit really has been, you'll have to specify 'w' together with every 'f'.
- XIf you don't, the mailer will be told that the mail has been delivered
- Xsuccesfully as soon as the first 'f' without a 'w' has been processed.
- XThis option is also advisable if you specified any
- X.I locallockfile
- Xon this recipe.
- X.Tp
- X.B s
- XMake
- X.B procmail
- Xsecure. If any fork fails in the current recipe, retry until it succeeds
- X(usefull when running on machines that occasionally have a full process tables,
- Xto ensure normal delivery in any case). If a fork fails and 's' is
- Xnot specified, it simply is logged in $LOGFILE and parsing of the rcfile
- Xcontinues (eventually delivering to $DEFAULT if no more recipes match).
- X.Ss "Local lockfile"
- X.LP
- XIf you put a second ':' on the first recipe line, then
- X.B procmail
- Xwill use a
- X.I locallockfile
- X(for this recipe only). You optionally can specify
- Xthe
- X.I locallockfile
- Xto use; if you don't however,
- X.B procmail
- Xwill use the filename specified as the destination (or the filename
- Xfollowing the first '>>') and will append $LOCKEXT to it.
- X.Ss "Recipe destination"
- X.LP
- XThe next line can start with the following characters:
- X.Tp
- X.B !
- XForwards to all the specified mail addresses (comments are
- X.B not
- Xignored on
- Xthis line).
- X.Tp
- X.B |
- XStarts the specified program, possibly in $SHELL if any
- Xof the $METASHELL characters are found (that means comments are normally
- Xprocessed by the shell on
- X.B this
- Xline).
- X.LP
- XAnything else will be taken as a filename (relative to $MAILDIR). After the
- Xfilename everything will be ignored till EOL.
- X.Sh "EXAMPLES"
- X.LP
- XSome example recipes are listed below:
- X.LP
- XSort out all mail to mailling list scuba-dive.
- X.RS
- X.LP
- X:
- X.PD 0
- X.LP
- X^TOscuba
- X.LP
- Xscubafile
- X.PD
- X.LP
- X.RE
- XForward all mail from peter about compilers to william (and keep a copy
- Xof it here in petcompil).
- X.RS
- X.LP
- X:2 bc
- X.PD 0
- X.LP
- X^From.*peter
- X.LP
- X^Subject:.*compilers
- X.LP
- X! william@somewhere.edu
- X.LP
- X:2
- X.LP
- X^From.*peter
- X.LP
- X^Subject:.*compilers
- X.LP
- Xpetcompil
- X.PD
- X.RE
- X.LP
- XAdd the headers of all messages to 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 'w'; otherwise the lockfile would be removed as
- Xsoon as the pipe had accepted the mail.
- X.RS
- X.LP
- X:0hwc:
- X.PD 0
- X.LP
- X| uncompress headc.Z; cat >>headc; compress headc
- X.RE
- X.PD
- X.LP
- XPrepend a linecount at the beginning of all multi part messages
- X(and don't allow
- X.B procmail
- Xto terminate early if the filter succeeds). Use "templock" as lockfile.
- X.RS
- X.LP
- X:wbf:templock
- X.PD 0
- X.LP
- X^Subject:.*\\(.*(/|of).*\\)
- X.LP
- X|echo "wc output:";tee tempf|wc;cat tempf;rm tempf
- X.PD
- X.RE
- X.LP
- XDump all mail from at jobs into one file, filter out the interesting
- Xparts of the header first.
- X.LP
- X.RS
- X:2fh
- X.PD 0
- X.LP
- X^From root
- X.LP
- X^Subject: Output from "at" job
- X.LP
- X|echo "From at job";echo;egrep "^Date:"
- X.LP
- X:b
- X.LP
- X^From at job
- X.LP
- Xatjunk
- X.RE
- X.PD
- X.Sh "FILES"
- X.PD 0
- X.Tp 22
- X.B /etc/passwd
- Xto get the recipients USER, HOME and SHELL variable defaults
- X.Tp
- X.B /var/spool/mail/$USER
- Xdefault last resort to put mail
- X.Tp
- X.B $HOME/.procmailrc
- Xdefault rc file
- X.Tp
- X.B $HOME/.mailbox
- Xdefault mailbox
- X.Tp
- X.B /var/spool/mail/$USER.lock
- Xlockfile for standard system mail directory (not used by
- X.B procmail
- Xunless you explicitly tell it to)
- X.Tp
- X.B /lib/sendmail
- Xdefault mail forwarder
- X.Tp
- X.B /usr/bin/egrep
- Xdefault regular expression parser
- X.PD
- X.Sh "SEE ALSO"
- X.LP
- X.BR sh (1),
- X.BR csh (1),
- X.BR mail (1),
- X.BR binmail (1),
- X.BR uucp (1C),
- X.BR aliases (5),
- X.BR sendmail (8),
- X.BR egrep (1V),
- X.BR lockfile (1)
- X.Sh "DIAGNOSTICS"
- X.Tp 23
- XError while writing to "x"
- Xnonexistent subdirectory, no write permission, or disk full
- X.Tp
- XFailed forking "x"
- Xnot possible if 's' flag specified on the recipe
- X.Tp
- XProgram failure of "x"
- Xsome pipe or program that was started by
- X.B procmail
- Xreturned a non-null value
- X.Tp
- XFailed to execute "x"
- Xprogram not in path, or not executable
- X.Tp
- XCouldn't unlink "x"
- Xlockfile was already gone, or write permission to the directory were the
- Xlockfile is has been denied
- X.Tp
- XOut of memory
- Xprobably a runaway filter that dumps junk into
- X.BR procmail,
- Xor the system could be out of swapspace
- X.Tp
- XLockfailure
- Xcan only occur if you specify some real weird (and illegal) lockfilenames
- X.PD
- X.Sh "BUGS & SPECIAL FEATURES"
- X.LP
- XIf you don't explicitly tell
- X.B procmail
- Xto wait (option 'w') for the pipe or program to finish, it won't wait
- Xand will terminate early (not knowing if the pipe or program returns
- Xsuccess).
- X.LP
- XThe only substitutions of environment variables that can be handled by
- X.B procmail
- Xitself are of the type $name.
- X.LP
- XA line buffer of 2048 bytes is used when processing the
- X.BR rcfile ,
- Xany environment variable expansions
- X.B have
- Xto fit within this limit.
- X.LP
- XRace conditions sometimes result in a failure to remove a lock file
- X(e.g. forwarding mail to yourself (on the same account) could (not
- Xnecessarily) be a problem).
- X.LP
- XIn the unlikely event that you absolutely need to kill
- X.B procmail
- Xbefore it has finished, then first try and use
- Xthe regular kill command (SIGTERM), otherwise some
- X.I lockfiles
- Xmight not get removed.
- X.LP
- XYou should create a shell script that uses
- X.BR lockfile (1)
- Xbefore invoking
- Xthe mail program on any mailbox file other than the system mailbox.
- X.Sh "NOTES"
- X.LP
- XAny program executed from within
- X.B procmail
- Xwill be searched for in the PATH variable (you have to specify it though).
- XIt is advisable however, to specify an absolute path for $GREP, because
- Xit get's executed fairly often.
- X.LP
- XIf the regular expression starts with "^TO" it will be substituted by
- X"^(To|Cc|Apparently-To):.*", which should catch all destination
- Xspecifications.
- X.LP
- XAny lines in the body of the message that look like postmarks are prepended
- Xwith '>' (disarms bogus mailheaders). The regular expression that is used
- Xto search for these postmarks is:
- X.RS
- X\\n\\nFrom +[^\\t\\n ]+ +[^\\n\\t]
- X.RE
- X.LP
- XShould the uid
- X.B procmail
- Xis running under have no corresponding /etc/passwd entry, then HOME will
- Xdefault to /tmp, USER will default to #uid.
- X.LP
- XYour .forward (beware, it
- X.B has
- Xto be world readable) file should contain (include the quotes):
- X.LP
- X"|exec /global/bin/procmail"
- X.Ss "A sample small .procmailrc:"
- X.PD 0
- X.LP
- XPATH=/bin:/usr/bin:/global/bin:/usr/local/bin
- X.LP
- XMAILDIR=$HOME/mail #you'd better make sure it exists
- X.LP
- XDEFAULT=$MAILDIR/mbox
- X.LP
- XLOGFILE=$MAILDIR/from
- X.LP
- XLOCKFILE=$HOME/.lockmail
- X.LP
- X:
- X.LP
- X^From.*berg
- X.LP
- Xfrom_me
- X.LP
- X:
- X.LP
- X^Subject:.*Flame
- X.LP
- X/dev/null
- X.PD
- X.Sh "AUTHOR"
- X.LP
- XStephen R. van den Berg at RWTH-Aachen, Germany
- X.RS
- Xberg@marvin.e17.physik.tu-muenchen.de
- X.RE
- SHAR_EOF
- chmod 0644 procmail.1 ||
- echo 'restore of procmail.1 failed'
- Wc_c="`wc -c < 'procmail.1'`"
- test 12759 -eq "$Wc_c" ||
- echo 'procmail.1: original size 12759, current size' "$Wc_c"
- fi
- # ============= procmail.c ==============
- if test -f 'procmail.c' -a X"$1" != X"-c"; then
- echo 'x - skipping procmail.c (File already exists)'
- else
- echo 'x - extracting procmail.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmail.c' &&
- X/************************************************************************
- X * procmail.c an autonomous mail processor *
- X * *
- X * Version 1.10 1991-02-04 *
- X * Seems to be relatively bug free. *
- X * *
- X * Copyright (c) 1990-1991, S.R.van den Berg, The Netherlands *
- X * The sources can be freely copied for non-commercial use. *
- X * *
- X * Don't complain about the formatting, I know it's *
- X * unconventional, but it's my standard format (I have my *
- X * reasons). If you don't like it, feed it through your *
- X * favourite C beautifier. The program has been tested on *
- X * SUN's, but should work on almost every *NIX system that *
- X * has a fork() and execvp() command. The only things that *
- X * might need some changes are the include files. *
- X * There might be one problem if your system doesn't know *
- X * fsync(fd). Define NOfsync in that case. *
- X * *
- X * If you have had to make major changes in order to get it *
- X * running on a different machine, please send me the patches. *
- X * That way I might include them in a future version. *
- X * *
- X * Please note that this program essentially is supposed to be *
- X * static, that means no extra features (IMHO no more are *
- X * needed) are supposed to be added. *
- X ************************************************************************/
- X#ifdef NOsync /* If you don't want syncs at all define */
- X#define fsync(fd) 0 /* NOsync. Only recommended if procmail */
- X#define sync() 0 /* isn't used in a networked environment */
- X#else
- X# ifdef NOfsync /* If you don't have fsync, define NOfsync */
- X# define fsync(fd) 0 /* sync will be used instead. Is a bit */
- X# endif /* slower, but works nevertheless */
- X#endif
- X
- X#include <stdio.h>
- X#ifndef NO_ANSI_PROT /* define this if your headers are not ansi */
- X# include <stdlib.h>
- X#else
- X char*getenv();
- X typedef int pid_t;
- X#endif
- X#include <fcntl.h>
- X#include <pwd.h>
- X#include <sys/wait.h>
- X#include <signal.h>
- X#include <malloc.h>
- X#include <string.h>
- X#include <errno.h>
- X#ifndef SYSV
- X#include <sysexits.h>
- X#else
- X#include <bsd/sysexits.h>
- X#endif
- X#include "sysexits.h"
- X#ifndef SEEK_SET
- X#define SEEK_SET 0
- X#endif
- Xextern char**environ;
- X#define STDIN 0
- X#define STDOUT 1
- X#define STDERR 2
- Xtypedef unsigned t_buf; /* for malloc, realloc and memmove
- X This type determines the maximum message length */
- X
- X#define BFSIZ 2048 /* max expanded line length */
- X#define BLKSIZ (1<<14) /* blocksize while reading/writing */
- X#define PROCMAILRC ".procmailrc"
- X#define SUSPENSION 64
- X#define DEFlocksleep 8
- X#define DEFlocksleeps "8"
- X#define TOkey "^TO"
- X#define TOkeylen 3
- X#define TOsubstitute "^(To|Cc|Apparently-To):.*"
- X#define DEFshellmeta "\"'`{}()[]*?|<>~;!\\" /* never put '$' in here */
- X#define DEFmaildir "$HOME"
- X#define DEFdefault "$MAILDIR/.mailbox"
- X#define DEForgmail "/var/spool/mail/$USER"
- X#define DEFgrep "/usr/bin/egrep"
- X#define DEFsendmail "/usr/lib/sendmail"
- X#define DEFlockext ".lock"
- X#define DEFshellflags "-c"
- X
- Xchar buf[BFSIZ],buf2[BFSIZ],maildir[]="MAILDIR",defaultf[]="DEFAULT",
- X logfile[]="LOGFILE",lockfile[]="LOCKFILE",grep[]="GREP",host[]="HOST",
- X locksleep[]="LOCKSLEEP",orgmail[]="ORGMAIL",eumask[]="UMASK",
- X shellmeta[]="SHELLMETA",shellflags[]="SHELLFLAGS",shell[]="SHELL",
- X sendmail[]="SENDMAIL",lockext[]="LOCKEXT",devnull[]="/dev/null",
- X newline[]="\n",binsh[]="/bin/sh",home[]="HOME",tmp[]="/tmp",user[]="USER",
- X **gargv,*rcfile=PROCMAILRC,*globlock,*loclock,*tolock;
- X#define PREAD (poutfd[0])
- X#define PWRITE (poutfd[1])
- X#define tscrc(a,b) (0<fscanf(rc,a,b))
- X#define scrc(a,b) fscanf(rc,a,b)
- Xint retval=EX_CANTCREAT,flaggerd=1,verrgrandchild,sh,pwait,secur,locking,
- X nextexit,locknext;
- Xpid_t mother;
- XFILE*rc;
- X
- X#ifndef __STDC__
- Xvoid*memmove(to,from,count)register void*to,*from;register t_buf count;{
- X void*old;
- X old=to;count++;--(char*)to;--(char*)from;
- X if(to<=from){
- X goto jiasc;
- X do{
- X *++(char*)to=*++(char*)from;
- Xjiasc:;}
- X while(--count);}
- X else{
- X (char*)to+=count;(char*)from+=count;
- X goto jidesc;
- X do{
- X *--(char*)to=*--(char*)from;
- Xjidesc:;}
- X while(--count);}
- X return old;}
- X#endif
- X
- Xpid_t sfork(){pid_t i; /* if secur is set, it doesn't return */
- X while((i=fork())&&secur&&i==-1) /* until the fork was successfull */
- X sleep(SUSPENSION);
- X return i;}
- X
- Xvoid*tmalloc(len)t_buf len;{void*p;
- X if(p=malloc(len))
- X return p;
- X nomemerr();}
- X
- Xvoid*trealloc(old,len)void*old;t_buf len;{
- X if(old=realloc(old,len))
- X return old;
- X nomemerr();}
- X
- Xvoid terminate(){
- X if(locking){
- X nextexit=1;return;}
- X sync(); /* sorry, but this is mail we're dealing with, safety first */
- X unlock(&loclock); /* local lock files are removed in any case */
- X if(mother&&mother!=getpid())
- X if(retval!=EX_OK) /* tell mam we're in trouble, let her clean up the mess */
- X kill(mother,SIGQUIT); /* don't try this at home, kids :-) */
- X else{
- X kill(mother,SIGHUP);goto allok;} /* You can go home mam, everything ok */
- X else
- Xallok: /* global lockfile should be removed by the last surviving */
- X unlock(&globlock); /* procmail */
- X exit(retval);}
- X
- Xvoid flagger(){ /* hey, we received a SIGHUP */
- X flaggerd=1;}
- X
- Xvoid errgrandchild(){ /* my grandchildren scream in despair */
- X verrgrandchild=1;}
- X
- Xlong dump(s,source,len)int s;char*source;long len;{int i;long ol;
- X if(s>=0){
- X ol=len;
- X while(i=rwrite(s,source,BLKSIZ<len?BLKSIZ:(int)len)){
- X if(i<0){
- X i=0;goto writefin;}
- X len-=i;source+=i;}
- X if(!len&&(ol<2||!(source[-1]=='\n'&&source[-2]=='\n')))
- X rwrite(s,newline,1); /* message always ends with a newline */
- Xwritefin:
- X if(fsync(s)&&errno!=EINVAL)
- X len++; /* if there is a physical write error */
- X rclose(s);return len-i;}
- X return len?len:-1;} /* return an error even if nothing was to be sent */
- X
- Xlong pipin(line,source,len)char*line,*source;long len;{pid_t pid;
- X int poutfd[2];
- X pipe(poutfd);
- X if(!(pid=sfork(line))){
- X rclose(PWRITE);redirect(PREAD);callnewprog(line);}
- X rclose(PREAD);forkerr(pid,line);
- X if(len=dump(PWRITE,source,len))
- X writeerr(line);
- X if(pwait&&waitfor(pid)){
- X progerr(line);len=1;}
- X return len;}
- X
- Xchar*readdyn(bf,filled)char*bf;long*filled;{int i;
- X goto jumpin;
- X do{
- X *filled+=i;
- Xjumpin:
- X bf=trealloc(bf,(t_buf)*filled+BLKSIZ);} /* dynamic adjust */
- X while(0<(i=read(STDIN,bf+*filled,BLKSIZ)));
- X if(!*filled)
- X return trealloc(bf,1);
- X return trealloc(bf,(t_buf)*filled);} /* minimize the buffer space */
- X
- Xchar*cat(a,b)char*a,*b;{
- X return strcat(strcpy(buf,a),b);}
- X
- Xchar*findel(start,end)register char*start,*end;{/* find the first empty line */
- X while(start<end)
- X if(*start++=='\n'&&start<end&&*start=='\n')
- X return start+1;
- X return end;}
- X
- Xmain(argc,argv)char*argv[];{static char flags[10];int i;
- X char*themail,*thebody,*chp,*startchar,*chp2;long tobesent,filled,rcoffset;
- X mother=getpid();setbuf(stdin,(void*)0);umask(077);
- X sprintf(buf,"%u",i=getuid());setpwent();
- X {struct passwd*pass;
- X if(pass=getpwuid(i)){ /* find user defaults in /etc/passwd */
- X setdef(home,pass->pw_dir);chdir(pass->pw_dir);
- X setdef(user,pass->pw_name?pass->pw_name:buf);setdef(shell,pass->pw_shell);}
- X else{ /* user could not be found, set reasonable defaults */
- X setdef(home,tmp);chdir(tmp);setdef(user,buf);setdef(shell,binsh);}}
- X endpwent();setdef(shellmeta,DEFshellmeta);setdef(shellflags,DEFshellflags);
- X setdef(maildir,DEFmaildir);setdef(defaultf,DEFdefault);
- X setdef(orgmail,DEForgmail);setdef(grep,DEFgrep);setdef(sendmail,DEFsendmail);
- X setdef(lockext,DEFlockext);setdef(locksleep,DEFlocksleeps);
- X chdir(getenv(maildir));fdreopena(devnull,STDERR);fdreopena(devnull,STDOUT);
- X gargv=argv+1;nextrcfile();
- X thebody=themail=tmalloc((t_buf)(argc=1));filled=rcoffset=0;
- Xchangedmail:
- X themail=readdyn(themail,&filled); /* read in the mail */
- Xonlyhead:
- X startchar=filled+(thebody=themail);
- X while(thebody<startchar&&*thebody++=='\n'); /* skip leading garbage */
- X thebody=findel(thebody,startchar); /* find the end of the header */
- X chp=thebody;
- X do{ /* search for bogus headers */
- X if(startchar-chp<8) /* we're looking for: */
- X break; /* "\n\nFrom +[^\t\n ]+ +[^\n\t]" */
- X if(0>=sscanf(chp,"From%1[ ]",buf)) /* thats the regular expression */
- X continue; /* that defines the start of a mail */
- X chp2=chp;chp+=5; /* message. */
- X#define SKIPWHILE(x) while(x){ if(++chp>=startchar) break;}
- X SKIPWHILE(*chp==' ')
- X SKIPWHILE((i=*chp)&&i!=' '&&i!='\t'&&i!='\n')
- X SKIPWHILE(*chp==' ')
- X if((i=*chp)&&i!='\n'&&i!='\t'){ /* insert '>' before bogus header */
- X i=startchar[-1];memmove(chp2+1,chp2,(t_buf)(startchar-chp2)-1);
- X *chp2='>';themail=trealloc(chp2=themail,++filled);
- X#define ADJUST(x) ((x)=themail+((x)-chp2))
- X ADJUST(thebody);ADJUST(startchar);ADJUST(chp);*startchar++=i;}}
- X while(startchar>(chp=findel(chp,startchar)));
- X waitflagger(); /* if we're a child, wait for the parental guidance */
- Xchangerc:
- X rc=fopen(strcat(cat(getenv(home),"/"),rcfile),"r");
- X fseek(rc,rcoffset,SEEK_SET);signal(SIGINT,terminate);
- X signal(SIGQUIT,terminate);signal(SIGTERM,terminate);signal(SIGHUP,SIG_IGN);
- Xgoon:
- X while(unlock(&loclock),!feof(rc)||argv[argc]){
- X while(chp=argv[argc]){ /* interpret command line specs first */
- X argc++;strcpy(buf2,chp);
- X if(chp=strchr(buf2,'=')){
- X chp++;goto argenv;}}
- X if(tscrc(" %1[:]",flags)){ /* check for a recipe */
- X skipblanks();i=sh=1;
- X if(tscrc("%[0-9]",buf2)){
- X sscanf(buf2,"%d",&sh);skipblanks();}
- X *flags='\0';scrc("%9[HBIhbfcws]",flags);skipblanks();
- X if(tolock) /* clear temporary buffer for lockfile name */
- X free(tolock);
- X tolock=0;
- X if((locknext=(tscrc("%1[:]",buf)))&&
- X (skipblanks(),tscrc("%[^ \t\n#]",buf)))
- X tolock=strdup(buf);
- X startchar=themail;tobesent=thebody-themail;
- X if(strchr(flags,'B')) /* what needs to be piped into grep? */
- X if(strchr(flags,'H'))
- X tobesent=filled;
- X else{
- X startchar=thebody;tobesent=filled-tobesent;}
- X while(sh--){ /* any conditions (left) */
- X skiptoeol();scrc("%[^\n]",buf2);
- X if(!strncmp(buf2,TOkey,TOkeylen))
- X cat(TOsubstitute,buf2+TOkeylen);
- X else
- X strcpy(buf,buf2);
- X if(i) /* check out all conditions */
- X i=!grepin(buf,startchar,tobesent,!strchr(flags,'I'));}
- X startchar=themail;tobesent=filled; /* body, header or both? */
- X if(strchr(flags,'h')){
- X if(!strchr(flags,'b'))
- X tobesent=thebody-themail;}
- X else if(strchr(flags,'b'))
- X tobesent-=(startchar=thebody)-themail;
- X chp=buf+strlen(cat(getenv(sendmail)," "));sh=0;
- X pwait=!!strchr(flags,'w');secur=!!strchr(flags,'s');
- X if(tscrc(" ! %[^\n]",chp)){ /* forward the mail */
- X if(i)
- X goto forward;}
- X else if(tscrc("| %[^\n]",buf2)){ /* pipe the mail */
- X if(i){
- X if(sh=!!strpbrk(buf2,getenv(shellmeta)))
- X strcpy(buf,buf2);
- X else
- X parse();
- X chp=buf;*buf2='\0';
- X while(i=*chp) /* find the implicit lockfile name ('>>name') */
- X if(chp++,i=='>'&&*chp=='>'){
- X while((i=*++chp)==' '||i=='\t');
- X sscanf(chp,"%[^ \t\n#'\");|<>]",buf2);break;}
- X lcllock();
- X if(strchr(flags,'f')){
- X if(startchar==themail&&tobesent!=filled){ /* if only 'h' */
- X char*dest;long dfilled=0;
- X if(pipthrough(buf,startchar,tobesent))
- X goto goon;
- X dest=readdyn(tmalloc(1),&dfilled);filled-=tobesent;
- X if(tobesent<dfilled) /* adjust buffer size (only bigger) */
- X themail=trealloc(themail,(t_buf)(dfilled+filled));
- X memmove(themail+dfilled,themail+tobesent,(t_buf)filled);
- X memmove(themail,dest,(t_buf)dfilled);free(dest);
- X themail=trealloc(themail,(t_buf)(filled+=dfilled));
- X goto onlyhead;} /* and determine the header again */
- X rcoffset=ftell(rc); /* needed because we have to fclose it */
- X if(pipthrough(buf,startchar,tobesent))
- X goto goon;
- X filled=startchar-themail;goto changedmail;}
- Xforward: if(!pipin(buf,startchar,tobesent)&&!strchr(flags,'c'))
- X goto mailed;}}
- X else{ /* append the mail to a file */
- X scrc("%s",buf2);skipcomment();
- X if(i){
- X parse();strcpy(buf2,buf);lcllock();
- X if(!dump(opena(buf),startchar,tobesent)&&!strchr(flags,'c'))
- X goto mailed;}}}
- X else if(tscrc("%[A-Z_a-z0-9] = ",buf)){ /* then it must be an assignment */
- X *(chp=buf+strlen(buf))='=';*++chp='\0';scrc("%[^ \t\n#]",chp);
- X skipcomment();strcpy(buf2,buf);
- Xargenv:
- X parse();putenv(strdup(buf));chp[-1]='\0';
- X if(!strcmp(buf,maildir))
- X chdir(chp);
- X else if(!strcmp(buf,logfile))
- X fdreopena(chp,STDERR);
- X else if(!strcmp(buf,lockfile))
- X lockit(chp,&globlock);
- X else if(!strcmp(buf,eumask)){
- X sscanf(chp,"%o",&i);umask(i);}
- X else if(!strcmp(buf,host)){
- X *buf2='\0';gethostname(buf2,BFSIZ);
- X if(strcmp(chp,buf2)){
- X if(nextrcfile()){
- X fclose(rc);rcoffset=0;goto changerc;}
- X retval=EX_OK;terminate();}}}
- X else if(!skipcomment()){ /* either comment or garbage */
- X scrc("%[^\n] ",buf);log("Skipped: \"");log(buf);logqnl();}}
- X if(dump(opena(chp=getenv(defaultf)),themail,filled)){ /* default maildest */
- X writeerr(chp); /* if it fails, don't panic, try the last resort */
- X if(dump(opena(chp=getenv(orgmail)),themail,filled))
- X writeerr(chp);goto mailerr;} /* now you can panic */
- Xmailed:
- X retval=EX_OK; /* we're home free, mail delivered */
- Xmailerr:
- X unlock(&loclock); /* any local lock file still around? */
- X do{
- X chp=buf-1;
- X while(themail<thebody&&chp<buf+BFSIZ-1&&(*++chp=*themail++)!='\n');
- X if(chp<buf)
- X chp++;
- X *chp='\0';
- X if(0<sscanf(buf,"From%*1[^:]%[^\n]",buf2)){
- X log("From ");goto foundsorf;}
- X else if(0<sscanf(buf,"Subject:%[^\n]",buf2)){
- X log(" Subject:");
- Xfoundsorf:
- X log(buf2);log(newline);}} /* log it's arrival */
- X while(themail<thebody);
- X terminate();}
- X
- Xsetdef(name,contents)char*name,*contents;{
- X strcat(strcat(strcpy(buf2,name),"="),contents);parse();putenv(strdup(buf));}
- X
- Xskipblanks(){
- X fscanf(rc,"%*[ \t]");}
- X
- Xskiptoeol(){
- X fscanf(rc,"%*[^\n]");return fgetc(rc);}
- X
- Xskipcomment(){char i[2]; /* no comment :-) */
- X if(tscrc("%1[\n]",i))
- X return 1;
- X skipblanks();return scrc("%1[#]",i)?skiptoeol():feof(rc);}
- X
- Xpipthrough(line,source,len)char*line,*source;long len;{pid_t pidf,pid;
- X int pinfd[2],poutfd[2];
- X#define PWR2 (pinfd[1])
- X#define PRD2 (pinfd[0])
- X pipe(poutfd);pipe(pinfd);
- X if(!(pidf=sfork())){ /* the filter is started here */
- X rclose(PWRITE);redirect(PREAD);rclose(STDOUT);dup(PWR2);rclose(PWR2);
- X rclose(PRD2);callnewprog(line);}
- X rclose(PREAD);rclose(PWR2);
- X if(forkerr(pidf,line)){
- X rclose(PRD2);return 1;}
- X flaggerd=0;signal(SIGHUP,flagger);
- X if(!(pid=sfork())){ /* this process will read back the filtered mail */
- X rclose(PWRITE);signal(SIGHUP,flagger);kill(getppid(),SIGHUP);redirect(PRD2);
- X if(!pwait&&mother){ /* if the wait chain ends here, notify mother */
- X kill(mother,SIGHUP);mother=0;} /* everything ok mam, go ahead and die */
- X return 0;} /* we will go ahead however (with or without mother) */
- X rclose(PRD2);
- X if(forkerr(pid,"procmail")){ /* An ingenious signal communication system */
- X kill(pidf,SIGTERM);return 1;} /* will ensure that NO lock file and */
- X if(dump(PWRITE,source,len)){ /* NO mail get's lost. */
- X kill(pidf,SIGTERM);kill(pid,SIGTERM);writeerr(line);return 1;}
- X waitflagger();verrgrandchild=flaggerd=0;signal(SIGQUIT,errgrandchild);
- X if(pwait){
- X if(waitfor(pidf)){ /* if the pipe fails, we will continue ourselves */
- X progerr(line);kill(pid,SIGTERM);return 1;}
- X for(kill(pid,SIGHUP),loclock=0;;sleep(SUSPENSION)){
- X if(flaggerd)
- X break;
- X if(verrgrandchild){ /* Check if one of my grandchildren has paniced */
- X signal(SIGQUIT,terminate);return 1;}}}
- X else
- X kill(pid,SIGHUP); /* if we don't wait, signal that we're bailing out */
- X exit(EX_OK);} /* go ahead child, you have control */
- X
- Xwaitflagger(){
- X while(!flaggerd)
- X sleep(SUSPENSION);}
- X
- Xgrepin(expr,source,len,casesens)char*expr,*source;long len;{pid_t pid;
- X int poutfd[2];static char*newargv[5]={0,"-e"};
- X newargv[3]=casesens?(char*)0:"-i";*newargv=getenv(grep);newargv[2]=expr;
- X pipe(poutfd);
- X if(!(pid=sfork())){
- X rclose(PWRITE);redirect(PREAD);shexec(newargv);}
- X rclose(PREAD);dump(PWRITE,source,len);
- X if(!forkerr(pid,*newargv))
- X return waitfor(pid);
- X return 127;}
- X
- Xwaitfor(pid)pid_t pid;{int i;
- X while(pid!=wait(&i)||(i&127)==127);
- X return i>>8&255;}
- X
- Xredirect(pip){
- X getstdinpipe(pip);fclose(rc);}
- X
- Xgetstdinpipe(pip){
- X rclose(STDIN);dup(pip);rclose(pip);}
- X
- Xcallnewprog(newname)char*newname;{int argc;char*endp,**newargv;
- X register char*p;
- X p=newname;
- X if(sh){char*newargv[4]; /* should we start a shell? */
- X newargv[3]=0;newargv[2]=p;newargv[1]=getenv(shellflags);
- X *newargv=getenv(shell);shexec(newargv);}
- X argc=2;
- X while(*p){ /* If no shell, we'll have to chop up the arguments ourselves */
- X if(*p==' '||*p=='\t'){
- X argc++;*p='\0';
- X while(*++p==' '||*p=='\t')
- X *p='\0';
- X continue;}
- X p++;}
- X endp=p;*(newargv=tmalloc(argc*sizeof*newargv))=p=newname;argc=1;
- X for(;;){
- X while(*p)
- X p++;
- X while(!*p){
- X if(p==endp){
- X newargv[argc]=0;shexec(newargv);}
- X p++;}
- X newargv[argc++]=p;}}
- X
- Xparse(){int i;char*org,*dest,*bd; /* Implicitly copies from buf2 to buf */
- X dest=buf;org=buf2;
- X while(i=*org++)
- X if(i!='$')
- X *dest++=i;
- X else{ /* substitute the thing... */
- X bd=buf2;
- X while((i=*org)>='A'&&i<='Z'||i>='a'&&i<='z'||i>='0'&&i<='9'||i=='_'){
- X *bd++=i;org++;}
- X *bd='\0';
- X if(bd=getenv(buf2)){
- X strcpy(dest,bd);
- X while(*dest)
- X dest++;}}
- X *dest='\0';}
- X
- Xwriteerr(line)char*line;{
- X log("Error while writing to \"");log(line);logqnl();}
- X
- Xforkerr(pid,a)pid_t pid;char*a;{
- X if(pid==-1){
- X log("Failed forking \"");log(a);logqnl();return 1;}
- X return 0;}
- X
- Xprogerr(line)char*line;{
- X log("Program failure of \"");log(line);logqnl();}
- X
- Xlog(a)char*a;{char*b;
- X b=a-1;
- X while(*++b);
- X rwrite(STDERR,a,b-a);}
- X
- Xopena(a)char*a;{
- Xreturn open(a,O_WRONLY|O_APPEND|O_CREAT,0666);}
- X
- Xfdreopena(a,fd)char*a;{ /* Currently only works for 0,1,2 */
- X rclose(fd);return opena(a);}
- X
- Xshexec(argv)char**argv;{int i;char**newargv,**p;
- X execvp(*argv,argv); /* if this one fails, we retry it as a shell script */
- X for(p=argv,i=1;i++,*p++;);
- X newargv=tmalloc(i*sizeof*p);
- X for(*(p=newargv)=binsh;*++p=*++argv;);
- X execve(*newargv,newargv,environ); /* no shell script? -> trouble */
- X log("Failed to execute \"");log(*argv);logqnl();exit(EX_UNAVAILABLE);}
- X
- Xunlock(lockp)char**lockp;{
- X locking=1;
- X if(*lockp){
- X if(unlink(*lockp)){
- X log("Couldn't unlink \"");log(*lockp);logqnl();}
- X free(*lockp);*lockp=0;}
- X locking=0;}
- X
- Xnomemerr(){
- X log("Out of memory\nbuffer 0: \"");log(buf);log("\"\nbuffer 1: \"");
- X log(buf2);logqnl();retval=EX_OSERR;terminate();}
- X
- Xlogqnl(){
- X log("\"\n");}
- X
- Xnextrcfile(){char*p; /* find the next rcfile specified on the command line */
- X while(p=*gargv){
- X gargv++;
- X if(!strchr(p,'=')){
- X rcfile=p;return 1;}}
- X return 0;}
- X
- Xrclose(fd){int i; /* a sysV secure close (signal immune) */
- X while((i=close(fd))&&errno==EINTR);
- X return i;}
- X
- Xrwrite(fd,a,len)void*a;{int i; /* a sysV secure write (signal immune) */
- X while(0>(i=write(fd,a,len))&&errno==EINTR);
- X return i;}
- X
- Xlockit(name,lockp)char*name,**lockp;{int i;
- X unlock(lockp); /* unlock any previous lockfile FIRST */
- X for(locking=1;;){ /* to prevent deadlocks (I hate deadlocks) */
- X if(0<=(i=open(name,O_WRONLY|O_CREAT|O_EXCL|O_SYNC,0))){
- X rclose(i);*lockp=strdup(name);
- Xterm: locking=0;
- X if(nextexit)
- X terminate();
- X return;}
- X if(errno==ENAMETOOLONG){ /* if too long, make it shorter and retry */
- X if(0<(i=strlen(name)-1)){
- X name[i]='\0';continue;}
- X log("Lockfailure\n");return;}
- X i=DEFlocksleep;sscanf(getenv(locksleep),"%i",&i);sleep(i);
- X if(nextexit)
- X goto term;}}
- X
- Xlcllock(){ /* lock a local file (if need be) */
- X if(locknext)
- X if(tolock)
- X lockit(tolock,&loclock);
- X else
- X lockit(strcat(buf2,getenv(lockext)),&loclock);}
- X
- X/* That's all folks */
- SHAR_EOF
- chmod 0644 procmail.c ||
- echo 'restore of procmail.c failed'
- Wc_c="`wc -c < 'procmail.c'`"
- test 22067 -eq "$Wc_c" ||
- echo 'procmail.c: original size 22067, current size' "$Wc_c"
- fi
- # ============= procmailrc ==============
- if test -f 'procmailrc' -a X"$1" != X"-c"; then
- echo 'x - skipping procmailrc (File already exists)'
- else
- echo 'x - extracting procmailrc (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmailrc' &&
- XPATH=$HOME/bin:/usr/bin:/global/bin:/usr/ucb:/bin
- XMAILDIR=$HOME/mail # You'd better make sure it exists
- XDEFAULT=$MAILDIR/mbox
- XLOGFILE=$MAILDIR/from
- XLOCKFILE=$HOME/.lockmail
- X
- X::
- X^From.*thf
- Xtodd
- X
- X:2fh
- X^From root
- X^Subject: Output from "at" job
- X|echo "From at job";echo;egrep "^Date:"
- X:b
- X^From at job
- Xatjunk
- X
- SHAR_EOF
- chmod 0644 procmailrc ||
- echo 'restore of procmailrc failed'
- Wc_c="`wc -c < 'procmailrc'`"
- test 310 -eq "$Wc_c" ||
- echo 'procmailrc: original size 310, current size' "$Wc_c"
- fi
- # ============= rmail ==============
- if test -f 'rmail' -a X"$1" != X"-c"; then
- echo 'x - skipping rmail (File already exists)'
- else
- echo 'x - extracting rmail (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'rmail' &&
- X#!/bin/sh
- X#
- X# specify the mailbox file you want to read on the command line
- X#
- Xcd $HOME/mail
- XLOCKFILE=$HOME/.lockmail
- Xif lockfile -! -r1 $LOCKFILE
- Xthen
- X echo Mail is currently arriving, please wait...
- X while
- X lockfile -! -4 -r2 $LOCKFILE
- X do
- X echo Mail is still arriving...
- X done
- Xfi
- X#
- X# Call you favourite mailer here.
- X#
- X/usr/ucb/mail -f $*
- X#
- X#
- X#
- Xrm -f $LOCKFILE
- SHAR_EOF
- chmod 0644 rmail ||
- echo 'restore of rmail failed'
- Wc_c="`wc -c < 'rmail'`"
- test 364 -eq "$Wc_c" ||
- echo 'rmail: original size 364, current size' "$Wc_c"
- fi
- # ============= sysexits.h ==============
- if test -f 'sysexits.h' -a X"$1" != X"-c"; then
- echo 'x - skipping sysexits.h (File already exists)'
- else
- echo 'x - extracting sysexits.h (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'sysexits.h' &&
- X#ifndef EX_OK
- X# define EX_OK 0 /* successful termination */
- X
- X# define EX__BASE 64 /* base value for error messages */
- X
- X# define EX_USAGE 64 /* command line usage error */
- X# define EX_DATAERR 65 /* data format error */
- X# define EX_NOINPUT 66 /* cannot open input */
- X# define EX_NOUSER 67 /* addressee unknown */
- X# define EX_NOHOST 68 /* host name unknown */
- X# define EX_UNAVAILABLE 69 /* service unavailable */
- X# define EX_SOFTWARE 70 /* internal software error */
- X# define EX_OSERR 71 /* system error (e.g., can't fork) */
- X# define EX_OSFILE 72 /* critical OS file missing */
- X# define EX_CANTCREAT 73 /* can't create (user) output file */
- X# define EX_IOERR 74 /* input/output error */
- X# define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
- X# define EX_PROTOCOL 76 /* remote error in protocol */
- X# define EX_NOPERM 77 /* permission denied */
- X#endif
- SHAR_EOF
- chmod 0644 sysexits.h ||
- echo 'restore of sysexits.h failed'
- Wc_c="`wc -c < 'sysexits.h'`"
- test 1015 -eq "$Wc_c" ||
- echo 'sysexits.h: original size 1015, current size' "$Wc_c"
- fi
- exit 0
-
-
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-