home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-07-15 | 56.3 KB | 1,601 lines |
- Newsgroups: comp.sources.misc
- From: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
- Subject: v31i042: procmail - mail processing program v2.71, Part03/05
- Message-ID: <1992Jul16.204555.20464@sparky.imd.sterling.com>
- X-Md4-Signature: f8343592e71805c3c339495257c01e3a
- Date: Thu, 16 Jul 1992 20:45:55 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
- Posting-number: Volume 31, Issue 42
- Archive-name: procmail/part03
- Environment: UNIX, sendmail, smail, MMDF
- Supersedes: procmail: Volume 29, Issue 90-94
-
- #! /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 3 (of 5)."
- # Contents: procmail/autoconf procmail/config.h
- # procmail/examples/3procmailrc procmail/examples/mailinglist
- # procmail/goodies.c procmail/regexp.c
- # Wrapped by berg@minipicc on Thu Jul 16 14:34:21 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'procmail/autoconf' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail/autoconf'\"
- else
- echo shar: Extracting \"'procmail/autoconf'\" \(9448 characters\)
- sed "s/^X//" >'procmail/autoconf' <<'END_OF_FILE'
- X
- X#$Id: autoconf,v 2.22 1992/06/30 16:42:26 berg Rel $
- X
- XSHELL=$4 || exec $4 autoconf $* # we're in a csh, feed myself to sh
- X
- X# All possible entries in autoconf.h:
- X
- X# #define UNISTD_H_MISSING
- X# #define STDDEF_H_MISSING
- X# #define STDLIB_H_MISSING
- X# #define DIRENT_H_MISSING
- X# #define SYS_DIRENT_H_MISSING
- X# #define NDIR_H_MISSING
- X# #define SYS_DIR_H_MISSING
- X# #define SYS_WAIT_H_MISSING
- X# #define SYS_UTSNAME_H_MISSING
- X# #define STRING_H_MISSING
- X# #define SYSEXITS_H_MISSING
- X# #define SYS_FILE_H_MISSING
- X# #define const
- X# #define volatile
- X# #define void char
- X# typedef int mode_t;
- X# typedef int pid_t;
- X# typedef int uid_t;
- X# typedef int gid_t;
- X# typedef unsigned size_t;
- X# typedef long time_t;
- X# #define NOmemmove
- X# #define NObcopy
- X# #define NOstrcspn
- X# #define NOstrpbrk
- X# #define NOopendir
- X# #define NOrename
- X# #define NOuname
- X# #define strchr(s,c) index(s,c)
- X# #define endpwent()
- X# #define endgrent()
- X# #define strtol(str,ptr,base) ((long)atoi(str))
- X# #define WMACROS_NON_POSIX
- X# #define oBRAIN_DAMAGE
- X# #define LD_ENV_FIX
- X# #define SMALLHEAP
- X# #define SYSTEM_MAILBOX "/usr/spool/mail/$USER"
- X# #define SENDMAIL "/usr/lib/sendmail"
- X
- X# A conforming ANSI compiler and POSIX library should only produce seven
- X# entries in autoconf.h: SYS_FILE_H_MISSING, endpwent(), endgrent(), rename(),
- X# SYSTEM_MAILBOX, LD_ENV_FIX, SENDMAIL (and perhaps SMALLHEAP)
- X# Anything else indicates failure of your installation to comply with either
- X# the ANSI or POSIX standards (but procmail should be installable anyway).
- X
- XPATH=:$PATH
- XACONF=$3
- XMAKE="$2"
- XRM="$5"
- XUSRINC=$6
- XDEVNULL=/dev/null
- Xexport SHELL PATH
- Xif test -f $ACONF
- Xthen
- X trap "exit 1" 1 2 3 15
- Xelse
- X trap "$RM $ACONF; exit 1" 1 2 3 15
- Xfi
- X
- Xif test -n "$LD_LIBRARY_PATH"
- Xthen
- X echo '***************************** WARNING *********************************'
- X echo '* You seem to have set the LD_LIBRARY_PATH variable, this might cause *'
- X echo '* some trouble during the execution of this autoconf script. If you *'
- X echo '* encounter errors about "_autotst not found" or any other *'
- X echo '* irregularities, stop the make, do a: "make clean", *'
- X echo '* clear LD_LIBRARY_PATH from the environment, and start over. *'
- X echo '***************************** WARNING *********************************'
- Xfi
- X
- Xcat >grepfor <<HERE
- Xfgrep -e "\$1" _autotst.rrr >$DEVNULL && echo "\$2" >>$ACONF
- XHERE
- Xchmod 0755 grepfor
- X
- Xcat >$ACONF <<HERE
- X/* This file was automagically generated by autoconf */
- X
- XHERE
- X
- Xif test ! -f $USRINC/stdio.h
- Xthen echo 2>&1 "Panic! I can't find your system include-files."
- X echo 2>&1 "I already looked in \"$USRINC\". Please edit the Makefile"
- X echo 2>&1 "and make sure that the definition of USRINCLUDE is correct,"
- X echo 2>&1 "before retrying another make."
- X exit 1
- Xfi
- Xtest -f $USRINC/unistd.h || echo "#define UNISTD_H_MISSING" >>$ACONF
- Xtest -f $USRINC/stddef.h || echo "#define STDDEF_H_MISSING" >>$ACONF
- Xtest -f $USRINC/stdlib.h || echo "#define STDLIB_H_MISSING" >>$ACONF
- Xif test ! -f $USRINC/dirent.h
- Xthen echo "#define DIRENT_H_MISSING" >>$ACONF
- X if test ! -f $USRINC/sys/dirent.h
- X then echo "#define SYS_DIRENT_H_MISSING" >>$ACONF
- X if test ! -f $USRINC/ndir.h
- X then echo "#define NDIR_H_MISSING" >>$ACONF
- X test -f $USRINC/sys/dir.h ||
- X echo "#define SYS_DIR_H_MISSING" >>$ACONF
- X fi
- X fi
- Xfi
- Xtest -f $USRINC/dirent.h || echo "#define DIRENT_H_MISSING" >>$ACONF
- Xtest -f $USRINC/sys/wait.h || echo "#define SYS_WAIT_H_MISSING" >>$ACONF
- Xtest -f $USRINC/sys/utsname.h || echo "#define SYS_UTSNAME_H_MISSING" >>$ACONF
- Xtest -f $USRINC/string.h || echo "#define STRING_H_MISSING" >>$ACONF
- Xtest -f $USRINC/sysexits.h || echo "#define SYSEXITS_H_MISSING" >>$ACONF
- Xtest -f $USRINC/sys/file.h || echo "#define SYS_FILE_H_MISSING" >>$ACONF
- X
- Xcat >_autotst.c <<HERE
- Xmain()
- X{ char*const*p;char*q;static struct{const int a;int b;}c[2];
- X --(c+1)->b; /* AIX 3.1.5 machines can't do this */
- X p= &q;return 0;
- X}
- XHERE
- X
- Xecho 'Testing for const'
- Xif ${MAKE} _autotst.$1 >_autotst.rrr 2>&1 && test -f _autotst.$1
- Xthen
- X grepfor const '#define const'
- Xelse
- X echo '#define const' >>$ACONF
- Xfi
- X${RM} _autotst.$1
- X
- Xcat >_autotst.c <<HERE
- Xmain(){volatile int i;return(i=0);}
- XHERE
- X
- Xecho 'Testing for volatile'
- Xif ${MAKE} _autotst.$1 >$DEVNULL 2>&1 && test -f _autotst.$1
- Xthen
- X:
- Xelse
- X echo '#define volatile' >>$ACONF
- Xfi
- X${RM} _autotst.$1
- X
- Xcat >_autotst.c <<HERE
- X#include "includes.h"
- Xvoid*vvoid;
- Xmain(){int i;char*p="t";
- X {size_t vsize_t;i=vsize_t=1;}
- X {pid_t vpid_t;i=vpid_t=1;}
- X {time_t vtime_t;i=vtime_t=1;}
- X {mode_t vmode_t;i=vmode_t=1;}
- X {uid_t vuid_t;i=vuid_t=1;}
- X {gid_t vgid_t;i=vgid_t=1;}
- X vvoid=p;
- X return !vvoid;}
- XHERE
- X
- Xecho 'Testing for void*,size_t,pid_t,time_t,mode_t,uid_t,gid_t'
- X${MAKE} _autotst.$1 >_autotst.rrr 2>&1
- X${RM} _autotst.$1
- X
- Xgrepfor void '#define void char'
- Xgrepfor size_t 'typedef unsigned size_t;'
- Xgrepfor pid_t 'typedef int pid_t;'
- Xgrepfor time_t 'typedef long time_t;'
- Xgrepfor mode_t 'typedef int mode_t;'
- Xgrepfor uid_t 'typedef int uid_t;'
- Xgrepfor gid_t 'typedef int gid_t;'
- X
- Xcat >_autotst.c <<HERE
- X#include "includes.h"
- Xmain(){int i;i=1;
- X i+=WIFEXITED(i);
- X i+=WIFSTOPPED(i);
- X i+=WEXITSTATUS(i);
- X return i;}
- XHERE
- X
- Xecho 'Testing for WIFEXITED(), WIFSTOPPED() & WEXITSTATUS()'
- Xif ${MAKE} _autotst.$1 >_autotst.rrr 2>&1
- Xthen
- X grepfor struct '#define WMACROS_NON_POSIX' ||
- X grepfor union '#define WMACROS_NON_POSIX'
- Xelse
- X echo '#define WMACROS_NON_POSIX' >>$ACONF
- Xfi
- X${RM} _autotst.$1
- X
- Xcat >_autotst.c <<HERE
- X#include "includes.h"
- Xmain(){char a[2];
- X endpwent();endgrent();memmove(a,"0",1);bcopy("0",a,1);strcspn(a,"0");
- X strtol("0",(char**)0,10);strchr("0",'0');strpbrk(a,"0");rename(a,"0");
- X opendir("0");
- X#ifndef NOuname
- X {struct utsname b;uname(&b);}
- X#endif
- X return 0;}
- XHERE
- X
- Xecho 'Testing for memmove, strchr, strpbrk, strcspn, strtol & opendir'
- Xif ${MAKE} _autotst.$1 >_autotst.rrr 2>&1
- Xthen
- X:
- Xelse
- X echo 2>&1 "Whoeaaa! There's something fishy going on here."
- X echo 2>&1 "You have a look and see if you detect anything uncanny:"
- X echo 2>&1 "-------------------------------------------------------"
- X cat 2>&1 _autotst.rrr
- X echo 2>&1 "-------------------------------------------------------"
- X echo 2>&1 "I suggest you take a look at the definition of CFLAGS and CC"
- X echo 2>&1 "in the Makefile before you try make again."
- X exit 1
- Xfi
- X${MAKE} _autotst >_autotst.rrr 2>&1
- X${RM} _autotst _autotst.$1
- X
- Xgrepfor strcspn '#define NOstrcspn'
- Xgrepfor strpbrk '#define NOstrpbrk'
- Xgrepfor opendir "
- X#define NOopendir /* the readdir library does not seem to be available */
- X /* this will slightly affect the way a filenumber is */
- X /* selected in MH-folders by procmail */
- X"
- Xgrepfor rename '#define NOrename'
- Xgrepfor strchr '#define strchr(s,c) index(s,c)'
- Xgrepfor uname "\
- X#define NOuname \
- X/* the include files define it, the libraries don't */"
- Xgrepfor setpwent '#define setpwent()'
- Xgrepfor endpwent '#define endpwent()'
- Xgrepfor endgrent '#define endgrent()'
- Xgrepfor strtol '#define strtol(str,ptr,base) ((long)atoi(str))'
- Xgrepfor memmove '#define NOmemmove' &&
- Xif fgrep -e bcopy _autotst.rrr >$DEVNULL
- Xthen
- X echo '#define NObcopy' >>$ACONF
- X
- X echo 'Testing for brain damage'
- X cat >_autotst.c <<HERE
- X#include "includes.h"
- Xstruct tests{int a,b;};
- Xmain(){
- X return offsetof(struct tests,b);}
- XHERE
- X if ${MAKE} _autotst.$1 >$DEVNULL 2>&1
- X then
- X :
- X else
- X echo 'Yep, it is' # ISC chokes on its own offsetof()
- X echo '#define oBRAIN_DAMAGE' >>$ACONF
- X fi
- X ${RM} _autotst.$1
- X
- Xelse
- X
- X cat >_autotst.c <<HERE
- X#include "includes.h"
- X#define M256 256
- X#define F33 33
- Xmain(){int j=0,i=M256-1;static char a[M256];
- X do a[i]=i;while(i--);
- X bcopy(a+F33,a,M256-F33);bcopy(a,a+F33,M256-F33);i=F33-1;
- X do j|=a[i]!=(char)(i+F33);while(i--);i=M256-1;
- X do j|=a[i]!=(char)i;while(--i!=F33-1);return!j;}
- XHERE
- X
- X echo 'Testing for bcopy handling overlaps'
- X ${MAKE} _autotst >$DEVNULL 2>&1
- X
- X if _autotst
- X then
- X echo 'Sorry, incompetent bcopy'
- X echo '#define NObcopy' >>$ACONF
- X fi
- X ${RM} _autotst
- Xfi
- X
- Xfgrep -e LD_ /bin/ld >/dev/null 2>&1 && echo "#define LD_ENV_FIX" >>$ACONF
- X
- Xcat >_autotst.c <<HERE
- X#include "includes.h"
- Xmain(){unsigned long s=(size_t)~0;int i;
- X for(i=1;s>>=1;++i);
- X if(i<=16)
- X puts("#define SMALLHEAP");
- X return 0;}
- XHERE
- X
- Xecho 'Determining the most applicable block size'
- X
- X${MAKE} _autotst >$DEVNULL 2>&1
- X_autotst >>$ACONF
- X${RM} _autotst
- X
- Xif test -d /usr/spool/mail
- Xthen
- X echo '#define SYSTEM_MAILBOX "/usr/spool/mail/$USER"' >>$ACONF
- Xelif test -d /usr/mail
- Xthen
- X echo '#define SYSTEM_MAILBOX "/usr/mail/$USER"' >>$ACONF
- Xelse
- X echo '#define SYSTEM_MAILBOX "$HOME/.mail"' >>$ACONF
- X echo Could not find the system-mailbox directory, supplied substitute
- Xfi
- X
- Xcat >lookfor <<HERE
- Xfor a in /usr/lib /lib /usr/etc /etc /usr/bin /bin /usr/local/bin /usr/lbin \
- X /usr/local/lib /usr/local /usr/.lib
- Xdo
- X if test -f "\$a/\$1"
- X then
- X echo "#define SENDMAIL \"\$a/\$1\"" >>$ACONF
- X exit 0
- X fi
- Xdone
- Xexit 1
- XHERE
- Xchmod 0755 lookfor
- X
- Xif lookfor sendmail || lookfor smail
- Xthen
- X:
- Xelse
- X echo 'Could not find any mailer. It should be a mailer accepting at least'
- X echo "one plain destination address as it's only argument (any sendmail"
- X echo 'compatible mailer will do), and the mail-to-be-sent on stdin.'
- X echo 'What is your mailer called? (You can override this in config.h)'
- X read a
- X echo "#define SENDMAIL \"$a\"" >>$ACONF
- Xfi
- X
- X${RM} _autotst* lookfor grepfor
- X
- Xecho -----------------------------autoconf.h-----------------------------------
- Xcat $ACONF >&2
- Xecho --------------------------------------------------------------------------
- END_OF_FILE
- if test 9448 -ne `wc -c <'procmail/autoconf'`; then
- echo shar: \"'procmail/autoconf'\" unpacked with wrong size!
- fi
- # end of 'procmail/autoconf'
- fi
- if test -f 'procmail/config.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail/config.h'\"
- else
- echo shar: Extracting \"'procmail/config.h'\" \(9697 characters\)
- sed "s/^X//" >'procmail/config.h' <<'END_OF_FILE'
- X/*$Id: config.h,v 2.22 1992/06/30 17:43:44 berg Rel $*/
- X
- X/*#define KERNEL_LOCKS /* uncomment if you want to use kernel locks on file
- X descriptors (not recommended if your system uses a
- X buggy lockd across a net, or if your mailer uses tmp files in updating
- X mailboxes and moves them into place); only advisable if your mailreader
- X can't be convinced to use "dotfile"-locks */
- X
- X/*#define sMAILBOX_SEPARATOR "\1\1\1\1\n" /* sTART- and eNDing separ. */
- X/*#define eMAILBOX_SEPARATOR "\1\1\1\1\n" /* uncomment (one or both)
- X if your mail system uses
- X nonstandard mail separators (non sendmail or smail compatible mailers
- X like MMDF), if yours is even different, uncomment and change the
- X value of course */
- X
- X/* KEEPENV and PRESTENV should be defined as a comma-separated null-terminated
- X list of strings */
- X
- X/* every environment variable appearing in KEEPENV will not be thrown away
- X * upon startup of procmail, e.g. you could define KEEPENV as follows:
- X * #define KEEPENV {"TZ","LANG",0}
- X */
- X#define KEEPENV {"TZ",0}
- X
- X/* every environment variable appearing in PRESTENV will be set or wiped
- X * out of the environment (variables without an '=' sign will be thrown
- X * out), e.g. you could define PRESTENV as follows:
- X * #define PRESTENV {"IFS","PATH=$HOME/bin:/bin:/usr/bin",0}
- X * any side effects (like setting the umask after an assignment to UMASK) will
- X * *not* take place
- X */
- X#define PRESTENV {"IFS",0}
- X
- X/*****************************************************************
- X * Only edit below this line if you have edited this file before *
- X *****************************************************************/
- X
- X/* every user & group appearing in TRUSTED_IDS is allowed to use the -f option
- X if the list is empty (just a terminating 0), everyone can use it
- X TRUSTED_IDS should be defined as a comma-separated null-terminated
- X list of strings */
- X
- X#define TRUSTED_IDS {"root","daemon","uucp","mail","x400",0}
- X
- X/*#define NO_USER_TO_LOWERCASE_HACK /* uncomment if your getpwnam() is
- X case insensitive or if procmail
- X will always be supplied with the correct case in the explicit
- X delivery mode argument */
- X
- X/*#define NO_NFS_ATIME_HACK /* uncomment if you're definitely not using
- X NFS mounted filesystems and can't afford
- X procmail to sleep for 1 sec. before writing a mailbox */
- X
- X/*#define SYSTEM_MBOX "$HOME/.mbox" /* uncomment and/or change if the
- X preset default mailbox is *not*
- X either /usr/spool/mail/$USER or /usr/mail/$USER (it will supersede
- X the value of SYSTEM_MAILBOX) */
- X
- X/*#define DEFsendmail "/bin/mail" /* uncomment and/or change if the
- X preset default SENDMAIL is not
- X suitable */
- X
- X/*#define console "/dev/console" /* uncomment if you want procmail to
- X use the console (or any other
- X terminal) to print any error messages that could not be dumped in the
- X "logfile". (Only recommended for debugging purposes, if you have
- X trouble creating a "logfile") */
- X
- X/************************************************************************
- X * Only edit below this line if you *think* you know what you are doing *
- X ************************************************************************/
- X
- X#define NOBODY_uid 0xfffe /* default uid when no valid recipient */
- X#define NOBODY_gid 0xfffe /* default gid when no valid recipient */
- X#define ROOT_uid 0
- X
- X#define INIT_UMASK (S_IRWXG|S_IRWXO) /* == 077 */
- X#define NORMperm (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
- X /* == 0666, normal mode bits used to create files, before umask */
- X#define LOCKperm 0 /* mode bits used while creating lockfiles */
- X#define MAX_LOCK_SIZE 0 /* lockfiles are expected not to be longer */
- X#ifndef SMALLHEAP
- X#define DEFlinebuf 2048 /* default max expanded line length */
- X#define BLKSIZ 16384 /* blocksize while reading/writing */
- X#define STDBUF 1024 /* blocksize for emulated stdio */
- X#else /* and some lower defaults for the unfortunate amongst us */
- X#define DEFlinebuf 512
- X#define BLKSIZ 1024
- X#define STDBUF 128
- X#endif /* SMALLHEAP */
- X#define HOSTNAMElen 9 /* nr of significant chararacters for HOST */
- X#define BOGUSprefix "BOGUS." /* prepended to bogus mailboxes */
- X#define PROCMAILRC ".procmailrc"
- X#define DEFsuspend 16 /* multi-purpose 'idle loop' period */
- X#define DEFlocksleep 8
- X#define TOkey "^TO"
- X#define TOsubstitute "^(To|Cc|Apparently-To):.*"
- X#define DEFshellmetas "&|<>~;?*[]=" /* never put '$' in here */
- X#define DEFmaildir "$HOME"
- X#define DEFdefault "$ORGMAIL"
- X#define DEFdefaultlock "LOCKFILE=$DEFAULT$LOCKEXT"
- X#define DEFmsgprefix "msg."
- X#define DEFlockext ".lock"
- X#define DEFshellflags "-c"
- X#define DEFlocktimeout 3600 /* defaults to one hour */
- X#define DEFtimeout (DEFlocktimeout-60) /* 60 seconds to clean up */
- X#define DEFnoresretry 4 /* default nr of retries if no resources left */
- X
- X#define BinSh "/bin/sh"
- X#define Tmp "/tmp"
- X#define DEBUGPREFIX ':' /* debug prefix for LOGFILE */
- X#define DevNull "/dev/null"
- X#define chCURDIR '.' /* the current directory */
- X#define DIRSEP "/" /* directory separator symbols, the */
- X /* last one should be the most common one */
- X
- X#define EOFName " \t\n#`'\");"
- X
- X#define HELPOPT1 'h' /* options to get command line help */
- X#define HELPOPT2 '?'
- X
- X#define VERSIONOPT 'v' /* option to display version */
- X#define PRESERVOPT 'p' /* preserve environment */
- X#define TEMPFAILOPT 't' /* return EX_TEMPFAIL on error */
- X#define FROMWHOPT 'f' /* set name on From_ line */
- X#define ALTFROMWHOPT 'r' /* alternate and obsolete form of -f */
- X#define DELIVEROPT 'd' /* deliver mail to named recipient */
- X#define PM_USAGE \
- X "Usage: procmail [-vpt] [-f fromwhom] [parameter=value | rcfile] ...\
- X\n Or: procmail [-vpt] [-f fromwhom] -d recipient ...\n"
- X#define PM_HELP \
- X "\t-v\t\tdisplay the version number and exit\
- X\n\t-p\t\tpreserve (most of) the environment upon startup\
- X\n\t-t\t\tfail softly if mail is undeliverable\
- X\n\t-f fromwhom\t(re)generate the leading 'From ' line\
- X\n\t-d recipient\texplicit delivery mode\n"
- X#define PM_QREFERENCE \
- X "\nRecipe flags quick reference:\
- X\n\tH\tegrep the header (default)\
- X\n\tB\tegrep the body\
- X\n\tD\tdistinguish case\
- X\n\tA\talso execute this recipe if the common condition matched\
- X\n\ta\tsame as 'A', but only if the previous recipe was succesful\
- X\n\th\tfeed the header to the pipe (default)\
- X\n\tb\tfeed the body to the pipe (default)\
- X\n\tf\tfilter\
- X\n\tc\tcontinue with the next recipe in any case\
- X\n\tw\twait for a filter or program\
- X\n\tW\tsame as 'w', but suppresses 'Program failure' messages\
- X\n\ti\tignore write errors\n"
- X
- X#define MINlinebuf 128 /* minimal LINEBUF length (don't change this) */
- X#define FROM_EXPR "\nFrom "
- X#define FROM "From "
- X#define NSUBJECT "^Subject:.*$"
- X#define MAXSUBJECTSHOW 78
- X#define FOLDER " Folder: "
- X#define LENtSTOP 9 /* tab stop at which message length will be logged */
- X
- X#define TABCHAR "\t"
- X#define TABWIDTH 8
- X
- X#define RECFLAGS "HBDAahbfcwWi"
- X#define HEAD_GREP 0
- X#define BODY_GREP 1
- X#define DISTINGUISH_CASE 2
- X#define ALSO_NEXT_RECIPE 3
- X#define ALSO_N_IF_SUCC 4
- X#define PASS_HEAD 5
- X#define PASS_BODY 6
- X#define FILTER 7
- X#define CONTINUE 8
- X#define WAIT_EXIT 9
- X#define WAIT_EXIT_QUIET 10
- X#define IGNORE_WRITERR 11
- X
- X#define UNIQ_PREFIX '_' /* prepended to temporary unique filenames */
- X#define ESCAP '>'
- X
- X /* some formail-specific configuration options: */
- X
- X#define UNKNOWN "foo@bar" /* formail default originator name */
- X#define OLD_PREFIX "Old-" /* formail field-Old-prefix */
- X
- X#define FM_SKIP '+' /* skip the first nnn messages */
- X#define FM_TOTAL '-' /* only spit out a total of nnn messages */
- X#define FM_BOGUS 'b' /* leave bogus Froms intact */
- X#define FM_FORCE 'f' /* force formail to accept an arbitrary format */
- X#define FM_REPLY 'r' /* generate an auto-reply header */
- X#define FM_KEEPB 'k' /* keep the header, when replying */
- X#define FM_TRUST 't' /* trust the sender to supply a valid header */
- X#define FM_SPLIT 's' /* split it up */
- X#define FM_NOWAIT 'n' /* don't wait for the programs */
- X#define FM_EVERY 'e' /* don't require empty lines leading headers */
- X#define FM_MINFIELDS 'm' /* the number of fields that have to be found */
- X#define DEFminfields 2 /* before a header is recognised as such */
- X#define FM_DIGEST 'd' /* split up digests */
- X#define FM_QUIET 'q' /* ignore write errors on stdout */
- X#define FM_EXTRACT 'x' /* extract field contents */
- X#define FM_ADD_IFNOT 'a' /* add a field if not already there */
- X#define FM_ADD_ALWAYS 'A' /* add this field in any case */
- X#define FM_REN_INSERT 'i' /* rename and insert a field */
- X#define FM_DEL_INSERT 'I' /* delete and insert a field */
- X#define FM_USAGE "Usage: \
- Xformail [+nn] [-nn] [-bfrktnedq] [-m nn] [-xaAiI field] [-s prg arg ...]\n"
- X#define FM_HELP \
- X "\t-b\tdon't escape bogus mailbox headers\
- X\n\t-f\tforce formail to pass along any non-mailbox format\
- X\n\t-r\tgenerate an auto-reply header, preserve fields with -i\
- X\n\t-k\ton auto-reply keep the body, prevent escaping with -b\
- X\n\t-t\ttrust the sender for his return address\
- X\n\t-q\tbe quiet about write errors on stdout\
- X\n\t-s prg arg\tsplit the mail, startup prg for every message\
- X\n\t-n\tdon't wait for every prg while splitting\
- X\n\t-e\tdon't require empty lines to preceed a header\
- X\n\t-d\taccept digest format\
- X\n\t-m nn\tmin fields threshold (default 2) for start of message\
- X\n\t+nn\tskip the first nn messages while splitting\
- X\n\t-nn\toutput at most nn messages while splitting\
- X\n\t-x field\textract\
- X\n\t-a field\tadd if not present\
- X\n\t-A field\tadd in any case\
- X\n\t-i field\trename and insert\
- X\n\t-I field\tdelete and insert\n"
- END_OF_FILE
- if test 9697 -ne `wc -c <'procmail/config.h'`; then
- echo shar: \"'procmail/config.h'\" unpacked with wrong size!
- fi
- # end of 'procmail/config.h'
- fi
- if test -f 'procmail/examples/3procmailrc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail/examples/3procmailrc'\"
- else
- echo shar: Extracting \"'procmail/examples/3procmailrc'\" \(1517 characters\)
- sed "s/^X//" >'procmail/examples/3procmailrc' <<'END_OF_FILE'
- X# Please check if all the paths in PATH are reachable, remove the ones that
- X# are not.
- X
- XPATH=$HOME/bin:/usr/bin:/global/bin:/usr/ucb:/bin:/usr/local/bin:
- XMAILDIR = $HOME/Mail # You'd better make sure it exists
- XDEFAULT = $MAILDIR/mbox
- XLOGFILE = $MAILDIR/from
- XLOCKFILE= $HOME/.lockmail
- X
- X # This will create a local lockfile named todd.lock
- X:: # *if* the condition matches
- X^From.*thf
- Xtodd
- X
- XLOCKFILE=$MAILDIR/whatever # This will remove the global lockfile
- X # $HOME/.lockmail and the new lockfile
- X # will be $MAILDIR/whatever
- X
- X
- X # The next recipe will
- X # filter out all messages from "at"
- X # jobs and will put them in a terse format
- X # (only the date and the body) in
- X # a file called $MAILDIR/atjunk
- X: 2 fh
- X^From root
- X^Subject: Output from "at" job
- X|egrep "^Date:"
- X # The next recipe will only be used if
- X # the previous one matched
- X:A
- Xatjunk
- X
- X
- X
- XMAILDIR=$HOME/News # This will change the current directory
- X
- X
- X # The next recipe will create a local lockfile
- X # named $HOME/News/dustbin.lock (*if* the condition
- X # matches), and will feed the body of the message
- X # through `sort` (sorry, couldn't come up with anything
- X # better :-), after which the result will be
- X # appended to $HOME/News/dustbin
- X:b:
- X^Subject:.*rubbish
- X|sort >>dustbin
- X
- X # The next recipe will use the play directory as a MH
- X # folder (of course you need MH to read the mail then)
- X:
- X^Subject:.*games
- Xgames/.
- X
- X# Anything not delivered by now will go to $HOME/Mail/mbox
- X# Using LOCKFILE=$HOME/Mail/mbox.lock
- END_OF_FILE
- if test 1517 -ne `wc -c <'procmail/examples/3procmailrc'`; then
- echo shar: \"'procmail/examples/3procmailrc'\" unpacked with wrong size!
- fi
- # end of 'procmail/examples/3procmailrc'
- fi
- if test -f 'procmail/examples/mailinglist' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail/examples/mailinglist'\"
- else
- echo shar: Extracting \"'procmail/examples/mailinglist'\" \(11170 characters\)
- sed "s/^X//" >'procmail/examples/mailinglist' <<'END_OF_FILE'
- X$Id: mailinglist,v 2.6 1992/04/09 16:17:41 berg Rel $
- X
- X How to set up mailing lists
- X ---------------------------
- X
- X Written by Stephen R. van den Berg.
- X berg@messua.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 7. Now, what does the above all do?
- X 8. The result of this exercise
- X
- X1. Intro
- X -----
- X
- XThe simplest and most direct way to do it is by insert a line in
- Xthe /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 subscribtions to the list, or address
- Xchanges of subscribers one should create a second entry in the /usr/lib/aliases
- Xfile:
- 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 most 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).
- 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 partly 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 You cannot avoid using newaliases however, and it *will* get extremely messy
- X if you have to start using nested aliases.
- 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
- Xh. 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 is working :-).
- X
- XNow, you could, instead of procmail, simply use immediate VNIX commands
- Xlike grep, sed, 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.
- 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. procmail will concatenate any headers that were continued according to
- X the RCF 822 recommendations, i.e. your filters will see one line per header.
- 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
- XProcmail has some additional advantages too:
- 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
- XIf, on the other hand, you want to do more complex things like moderated
- Xmailing lists with several moderators, etc., if would suggest you take
- Xa look at the more complex/specialised mail-server packages like:
- Xlistserv available on cs.bu.edu, author: tasos@cs.bu.edu
- XOf course, most of what these packages can do, can be done with procmail as
- Xwell; it is just that you might be forced to write some additional shell
- Xscripts/programs to accomplish the same.
- X
- X
- X6. How do I use procmail to filter the mailinglist mail?
- X -----------------------------------------------------
- X
- XFirst you have to create these two entries in your /usr/lib/aliases file of
- Xmachine "your.domain" (the mylist: line should be typed in as one long line):
- X
- Xmylist: "|IFS=' ';exec /usr/local/bin/procmail /some/path/listrc subscribers=/some/path/memberlist list=mylist@your.domain listreq=mylist-request@your.domain"
- Xmylist-request: your_login_name@your.domain
- Xowner-mylist: mylist-request
- X
- XCreate a file named /some/path/memberlist which contains the names of the
- Xsubscribers separated by whitespace (blanks, tabs or newlines) like:
- X
- X fred john wilma barney@bedrock pebbles
- X
- XThe /some/path/listrc file should look like the sample listrc file
- Xsupplied in this directory. This listrc file need only be present once,
- Xit will cater for all the mailinglists you'd like to create.
- X
- X
- X7. Now, what does the above all do?
- X --------------------------------
- X
- XIf mail arrives at mylist, first of all procmail will be started using
- X/some/path/listrc as the rcfile. Then it will grep the header to check if
- Xit could be a bounced message after all (from postmaster or mailer-daemon),
- Xor if it probably is a request message. If neither applies, procmail will
- Xfilter just the header of the message through formail.
- X
- Xformail will remove any "Return-Receipt-To:" fields, and will provide plain
- Xsubstitutes for "Errors-To:" and "Sender:". Then it will look for
- Xany "Reply-To:" fields which are already in the header and rewrite them
- Xas "Old-Reply-To:"; after having done this it will add your "Reply-To:"
- Xfield. BTW, the "Return-Receipt-To:" and "Errors-To:" fields are not
- Xrecommended by the RFC-822, they are however commonly supported by most
- Xsendmails; if they are not supported however, they won't hurt, they will
- Xsimply be ignored.
- X
- XThen, the mail is piped into $SENDMAIL which receives, as command line
- Xarguments, the addresses of all subscribers. The option -f will only
- Xtake effect if sendmail is running under daemon privileges; this only
- Xoccurs if the sender of the mail is *not* a local user; if the sender
- Xis a local user, then sendmail (and procmail) runs as the local user.
- X
- X*********************************** WARNING **********************************
- X* *
- X* For this reason it might be wise to allow writing of the memberlist file *
- X* only (to a list maintainer), keep the listrc file under *root supervision* *
- X* (i.e. owned by a very reliable person (e.g. root), world readable, but NOT *
- X* world writeable). *
- X* *
- X******************************************************************************
- X
- X
- X8. The result of this exercise
- X ---------------------------
- X
- XAs you can see, we have addressed and solved every single one of the original
- Xseven problems (well, ok, except problem f, that one is left as an excercise
- Xto the reader; shouldn't be too difficult).
- X
- X
- XP.S. Any suggestions/corrections/improvements on this document are welcome.
- END_OF_FILE
- if test 11170 -ne `wc -c <'procmail/examples/mailinglist'`; then
- echo shar: \"'procmail/examples/mailinglist'\" unpacked with wrong size!
- fi
- # end of 'procmail/examples/mailinglist'
- fi
- if test -f 'procmail/goodies.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail/goodies.c'\"
- else
- echo shar: Extracting \"'procmail/goodies.c'\" \(9223 characters\)
- sed "s/^X//" >'procmail/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 * The sources can be freely copied for non-commercial use. *
- X * #include "README" *
- X * *
- X ************************************************************************/
- X#ifdef RCS
- Xstatic char rcsid[]="$Id: goodies.c,v 2.17 1992/06/03 13:17:41 berg Rel $";
- X#endif
- X#include "config.h"
- X#include "procmail.h"
- X#include "shell.h"
- 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 */
- Xreadparse(p,fpgetc,sarg)register char*p;int(*const fpgetc)();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 { log("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: log(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:log(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 free(p);sgetcp=save; /* chopped up */
- X } /* drop source buffer, read from program */
- X startb=fromprog(p=startb,startb);sh=osh; /* restore sh */
- X if(!sarg&&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 { log("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=='-') /* $- =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(!sarg&&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++='\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
- Xultstr(minwidth,val,dest)unsigned long val;char*dest;
- X{ int i;unsigned long j;
- X j=val;i=0; /* a beauty, isn't it :-) */
- X do i++; /* determine needed width */
- X while(j/=10);
- X while(--minwidth>=i) /* fill up any excess width */
- X *dest++=' ';
- X *(dest+=i)='\0';
- X do *--dest='0'+val%10; /* display value backwards */
- X while(val/=10);
- X}
- X
- Xsputenv(a)char*a; /* smart putenv, the way it was supposed to be */
- X{ static struct lienv{struct lienv*next;char name[255];}*myenv;
- 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->next)) /* is it one */
- X if(!strncmp(a,curr->name,i)&&curr->name[i]=='=') /* I created earlier? */
- X { split=curr->name;*last=curr->next;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,name[0])+(i=strlen(a)+1));
- X tmemmove(*preenv=curr->name,a,i);preenv[1]=0;curr->next=myenv;
- X myenv=curr;
- X }
- X}
- X /* strtol replacement which lacks range checking */
- X#ifdef NOstrtol
- Xlong strtol(start,ptr,base)const char*start,**const ptr;
- X{ long result;const char*str=start;unsigned i;int sign,found;
- X if(base>=36||base<(sign=found=result=0))
- X goto fault;
- X for(;;str++) /* skip leading whitespace */
- X { switch(*str)
- X { case '\t':case '\n':case '\v':case '\f':case '\r':case ' ':continue;
- X }
- X break;
- X }
- X switch(*str) /* any signs? */
- X { case '-':sign=1;
- X case '+':str++;
- X }
- X if(*str=='0') /* leading zero(s)? */
- X { start++;
- X if((i= *++str)=='x'||i=='X') /* leading 0x or 0X? */
- X if(!base||base==16)
- X base=16,str++; /* hexadecimal all right */
- X else
- X goto fault;
- X else if(!base)
- X base=8; /* then it is octal */
- X }
- X else if(!base)
- X base=10; /* or else decimal */
- X goto jumpin;
- X do
- X { found=1;result=result*base+i;++str; /* start converting */
- Xjumpin:
- X if((i= *str-'0')<10);
- X else if(i-'A'+'0'<26)
- X i-='A'-10-'0';
- X else if(i-'a'+'0'<26)
- X i-='a'-10-'0';
- X else
- X break; /* not of this world */
- X }
- X while(i<base); /* still of this world */
- Xfault:
- X if(ptr)
- X *ptr=found?str:start; /* how far did we get */
- X return sign?-result:result;
- X}
- X#endif
- END_OF_FILE
- if test 9223 -ne `wc -c <'procmail/goodies.c'`; then
- echo shar: \"'procmail/goodies.c'\" unpacked with wrong size!
- fi
- # end of 'procmail/goodies.c'
- fi
- if test -f 'procmail/regexp.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail/regexp.c'\"
- else
- echo shar: Extracting \"'procmail/regexp.c'\" \(10571 characters\)
- sed "s/^X//" >'procmail/regexp.c' <<'END_OF_FILE'
- X/************************************************************************
- X * Custom regular expression library, *fully* egrep compatible *
- X * *
- X * Seems to be relatively bug free. *
- X * *
- X * Copyright (c) 1991-1992, S.R. van den Berg, The Netherlands *
- X * The sources can be freely copied for non-commercial use. *
- X * #include "README" *
- X * *
- X ************************************************************************/
- X#ifdef RCS
- Xstatic char rcsid[]="$Id: regexp.c,v 2.13 1992/03/06 12:38:31 berg Rel $";
- X#endif
- X#include "config.h"
- X#include "procmail.h"
- X#include "shell.h"
- X
- X#define R_BEG_GROUP '('
- X#define R_OR '|'
- X#define R_END_GROUP ')'
- X#define R_0_OR_MORE '*'
- X#define R_0_OR_1 '?'
- X#define R_1_OR_MORE '+'
- X#define R_DOT '.'
- X#define R_SOL '^'
- X#define R_EOL '$'
- X#define R_BEG_CLASS '['
- X#define R_NOT_CLASS '^'
- X#define R_RANGE '-'
- X#define R_END_CLASS ']'
- X#define R_ESCAPE '\\'
- X
- X#define BITS_P_CHAR 8
- X#define OPB (1<<BITS_P_CHAR)
- X#define OPC_EPS OPB
- X#define OPC_CLASS (OPB+1)
- X#define OPC_DOT (OPB+2)
- X#define OPC_FIN (OPB+3)
- X
- X#define bit_type unsigned
- X#define bit_bits (sizeof(bit_type)*8)
- X#define bit_index(which) ((unsigned)(which)/bit_bits)
- X#define bit_mask(which) ((unsigned)1<<(unsigned)(which)%bit_bits)
- X#define bit_toggle(name,which) (name[bit_index(which)]^=bit_mask(which))
- X#define bit_test(name,which) (!!(name[bit_index(which)]&bit_mask(which)))
- X#define bit_set(name,which,value) \
- X (value?(name[bit_index(which)]|=bit_mask(which)):\
- X (name[bit_index(which)]&=~bit_mask(which)))
- X#define bit_field(name,size) bit_type name[((size)+bit_bits-1)/bit_bits]
- X
- X#define SZ(x) (sizeof(struct x))
- X#define Ceps (struct eps*)
- X#define epso(to,add) (Ceps((char*)(to)+(add)))
- X#define ii (aleps.topc)
- X#define jjp (aleps.tnext)
- X
- X/* the spawn and stack members are reused in the normal opcodes as pc fields */
- Xstatic struct eps{unsigned opc;struct eps*stack,*spawn,*next;}*r;
- Xstatic struct{unsigned topc;struct eps*tnext;}aleps;
- Xstatic uchar*p;
- Xstatic ignore_case;
- X
- Xstruct chclass {unsigned opc_;struct eps*stack_,*spawn_,*next_;
- X bit_field(c,OPB);};
- X
- Xstatic puteps(spot,to,aswell)struct eps*const spot; /* epsilon transition */
- X const struct eps*const to,*const aswell;
- X{ spot->opc=OPC_EPS;spot->next=to!=spot?Ceps to:Ceps aswell;
- X spot->spawn=aswell!=spot?Ceps aswell:Ceps to;spot->stack=0;
- X}
- X
- Xstatic putneps(spot,to)struct eps*const spot;const struct eps*const to;
- X{ puteps(spot,to,spot+1);
- X}
- X
- X#define rAc (((struct chclass*)r)->c)
- X
- Xstatic bseti(i,j)unsigned i;const int j;
- X{ bit_set(rAc,i,j); /* mark 'i' as being in the class */
- X if(ignore_case) /* mark the other case too */
- X { if(i-'A'<26) /* uppercase */
- X i+='a'-'A';
- X else if(i-'a'<26) /* lowercase */
- X i-='a'-'A';
- X else return; /* no case */
- X bit_set(rAc,i,j);
- X }
- X}
- X
- Xstatic por();
- X
- Xstatic psimp(e)const struct eps*const e;
- X{ switch(*p)
- X { case R_BEG_GROUP:++p;por(e);return; /* not so simple after all */
- X case R_BEG_CLASS: /* a simple class */
- X { unsigned i,j=R_NOT_CLASS==*++p;
- X if(e)
- X { r->opc=OPC_CLASS;r->next=Ceps e;r->spawn=r->stack=0;
- X i=maxindex(rAc);
- X do rAc[i]=j?~0:0; /* preset the bit field */
- X while(i--);
- X }
- X if(j) /* skip the 'not' modifier */
- X { ++p;
- X if(e)
- X bit_toggle(rAc,'\n');
- X }
- X if(*p==R_END_CLASS) /* right at the start, cannot mean the end */
- X { ++p;
- X if(e)
- X i=R_END_CLASS,bit_toggle(rAc,R_END_CLASS);
- X }
- X else if(*p==R_RANGE) /* take it literally */
- X { ++p;
- X if(e)
- X i=R_RANGE,bit_toggle(rAc,R_RANGE);
- X }
- X for(;;++p)
- X { switch(*p)
- X { case R_END_CLASS:++p;
- X case '\0':r=epso(r,SZ(chclass));return;
- X case R_RANGE:
- X switch(*++p)
- X { default:
- X if(e)
- X while(++i<*p) /* mark all in the range */
- X bseti(i,!j);
- X break;
- X case '\0':case R_END_CLASS:--p; /* literally */
- X }
- X }
- X if(e)
- X bseti(i= *p,!j); /* a normal character, mark it */
- X }
- X }
- X case '\0':return;
- X case R_DOT: /* matches everything but a newline */
- X if(e)
- X { r->opc=OPC_DOT;goto fine;
- X }
- X goto fine2;
- X case R_EOL:case R_SOL: /* match a newline (in effect) */
- X if(e)
- X { r->opc='\n';goto fine;
- X }
- X goto fine2;
- X case R_ESCAPE: /* quote something */
- X if(!*++p) /* nothing to quote */
- X --p;
- X }
- X if(e) /* a regular character */
- X { r->opc=ignore_case&&(unsigned)*p-'A'<26?*p+'a'-'A':*p;
- Xfine:
- X r->next=Ceps e;r->spawn=r->stack=0;
- X }
- Xfine2:
- X ++p;++r;
- X}
- X
- X#define EOS(x) (jjp?jjp:(x))
- X
- Xstatic pnorm(e)const struct eps*const e;
- X{ void*pold;struct eps*rold;
- X for(;;)
- X { pold=p;rold=r;psimp(Ceps 0);ii= *p; /* skip it first */
- X jjp=p[1]==R_OR||p[1]==R_END_GROUP||!p[1]?Ceps e:Ceps 0;
- X if(e)
- X p=pold,pold=r;
- X switch(ii) /* check for any of the postfix operators */
- X { case R_0_OR_MORE:++r;
- X if(e) /* first an epsilon, then the rest */
- X putneps(rold,EOS(r)),r=rold+1,psimp(rold);
- X goto incagoon;
- X case R_1_OR_MORE: /* first the rest */
- X if(e) /* and then an epsilon */
- X puteps(r,rold,EOS(r+1)),r=rold,psimp(Ceps pold);
- X ++r;goto incagoon;
- X case R_0_OR_1:++r;
- X if(e) /* first an epsilon, then the rest */
- X putneps(rold,r=EOS(r)),pold=r,r=rold+1,psimp(Ceps pold);
- Xincagoon: switch(*++p) /* at the end of this group already? */
- X { case R_OR:case R_END_GROUP:case '\0':return;
- X }
- X continue; /* regular end of the group */
- X case R_OR:case R_END_GROUP:case '\0':
- X if(e)
- X r=rold,psimp(e);
- X return;
- X }
- X if(e) /* no fancy postfix operators, plain vanilla */
- X r=rold,psimp(Ceps pold);
- X }
- X}
- X
- Xstatic por(e)const struct eps*const e;
- X{ uchar*pold;struct eps*rold;
- X for(;;)
- X for(pold=p;;)
- X { rold=r;
- X switch(*p)
- X { default:pnorm(Ceps 0);r=rold;continue; /* still in this group */
- X case '\0':case R_END_GROUP: /* found the end of the group */
- X if(p==pold) /* empty 'or' group */
- X { if(e)
- X puteps(r,e,e); /* misused epsilon as branch, */
- X ++r; /* let the optimiser (fillout()) take it out */
- X }
- X else
- X p=pold,pnorm(e); /* normal last group */
- X if(*p)
- X ++p;
- X return;
- X case R_OR:++r;
- X if(p==pold) /* empty 'or' group */
- X { if(e)
- X putneps(rold,e); /* special epsilon */
- X }
- X else
- X { p=pold;pnorm(e); /* normal 'or' group, first an */
- X if(e) /* epsilon, then the rest */
- X putneps(rold,r);
- X }
- X ++p;
- X }
- X break;
- X }
- X}
- X
- Xstatic findandrep(old,newv)register struct eps**const old;
- X struct eps*const newv;
- X{ register struct eps*i,*t= *old; /* save the value */
- X for(i=r;i->opc!=OPC_FIN;) /* change all pointers from *old to new */
- X { if(i->next==t)
- X i->next=newv;
- X if(i->spawn==t)
- X i->spawn=newv;
- X switch(i->opc)
- X { case OPC_CLASS:i=epso(i,SZ(chclass));break;
- X default:++i;
- X }
- X }
- X *old=t;
- X}
- X
- X#define drs(m) (*(struct eps**)((char*)*stack+(ioffsetof(struct eps,m)^ofs)))
- X
- Xstatic cstack(stack,ofs)struct eps**const stack;
- X{ if(drs(next)->stack==Ceps p)
- X { findandrep(*stack,drs(next));*stack=drs(spawn);return 1;
- X }
- X return 0;
- X}
- X /* break up any closed epsilon circles, otherwise they can't be executed */
- Xstatic fillout(stack)struct eps**const stack;
- X{ if((*stack)->opc!=OPC_EPS||(*stack)->stack)
- X return 0;
- X (*stack)->stack=Ceps p; /* mark this one as used */
- X#define RECURS(nxt) \
- X do\
- X if(cstack(stack,ioffsetof(struct eps,nxt)^ioffsetof(struct eps,next)))\
- X return 1;\
- X while(fillout(&(*stack)->nxt))
- X RECURS(next);RECURS(spawn);return 0; /* recurse */
- X}
- X
- Xvoid*bregcomp(a,ign_case)char const*a;
- X{ struct eps*st;size_t i; /* first a trial run, determine memory needed */
- X p=(uchar*)a;ignore_case=ign_case;r=Ceps&aleps+1;por(Ceps 0);
- X st=malloc((i=(char*)r-(char*)&aleps)+ioffsetof(struct eps,stack)+sizeof r);
- X putneps(st,r=st+1);p=(uchar*)a;por(Ceps((char*)st+i)); /* really compile */
- X r->opc=OPC_FIN;r->stack=0; /* tack on the end */
- X for(r=st;;) /* simplify the compiled code (i.e. */
- X switch(st->opc) /* take out cyclic epsilon references) */
- X { case OPC_FIN:return r; /* finished */
- X case OPC_CLASS:st=epso(st,SZ(chclass));break; /* skip */
- X case OPC_EPS:p=(uchar*)st;fillout(&st); /* check tree */
- X default:++st; /* skip too */
- X }
- X}
- X
- X#define XOR1 \
- X (ioffsetof(struct eps,spawn)^ioffsetof(struct eps,stack))
- X#define PC(this,t) (*(struct eps**)((char*)(this)+(t)))
- X
- Xchar*bregexec(code,text,len,ign_case)struct eps*code;const uchar*text;
- X size_t len;
- X{ register struct eps*reg,*t,*stack,*other,*thiss;unsigned i,th1,ot1;
- X if(code[1].opc==OPC_EPS)
- X ++code; /* two epsilons at the start would be superfluous */
- X (thiss=code)->stack=0;th1=ioffsetof(struct eps,spawn);
- X ot1=ioffsetof(struct eps,stack);--text;++len;
- X i='\n';goto setups; /* make sure any beginning-of-line-hooks catch */
- X do
- X { i= *++text; /* get the next real-text character */
- Xlastrun: /* switch this & other pc-stack */
- X th1^=XOR1;ot1^=XOR1;thiss=other;
- Xsetups:
- X reg=(other=stack=code)->next;goto nostack;
- X do /* pop next entry off this pc-stack */
- X { reg=(t=thiss)->next;thiss=PC(t,th1);PC(t,th1)=0;goto nostack;
- X do /* pop next entry off the work-stack */
- X { stack=(t=stack)->stack;t->stack=0;reg=t->spawn;
- Xnostack: switch(reg->opc-OPB) /* push spawned branch on the work-stack */
- X { default:
- X if(ign_case&&i-'A'<26)
- X i+='a'-'A'; /* transmogrify it to lowercase */
- X if(i==reg->opc) /* regular character match */
- X goto yep;
- X break;
- X case OPC_EPS-OPB:reg->stack=stack;reg=(stack=reg)->next;
- X goto nostack;
- X case OPC_FIN-OPB: /* hurray! complete regexp match */
- X return(char*)text; /* return one past the match */
- X case OPC_CLASS-OPB:
- X if(bit_test(((struct chclass*)reg)->c,i))
- X goto yep; /* character in class */
- X break;
- X case OPC_DOT-OPB: /* dot-wildcard */
- X if(i!='\n')
- Xyep: if(!PC(reg,ot1)) /* state not yet pushed */
- X PC(reg,ot1)=other,other=reg; /* push location onto */
- X } /* other pc-stack */
- X }
- X while(stack); /* the work-stack is not empty */
- X }
- X while(thiss!=code); /* this pc-stack is not empty */
- X }
- X while(--len); /* still text to search */
- X if(ign_case!=2) /* out of text */
- X { ign_case=2;len=1;++text;goto lastrun; /* check if we just matched */
- X }
- X return 0; /* no match */
- X}
- END_OF_FILE
- if test 10571 -ne `wc -c <'procmail/regexp.c'`; then
- echo shar: \"'procmail/regexp.c'\" unpacked with wrong size!
- fi
- # end of 'procmail/regexp.c'
- fi
- echo shar: End of archive 3 \(of 5\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 5 archives.
- rm -f ark[1-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
-
- He did a quarter of the work in *half* the time!
-
- exit 0 # Just in case...
-