[comp.sources.misc] v20i051: procmail - mail processing program v2.02, Part03/03

berg@messua.informatik.rwth-aachen.de (Stephen R. van den Berg) (06/17/91)

Submitted-by: Stephen R. van den Berg <berg@messua.informatik.rwth-aachen.de>
Posting-number: Volume 20, Issue 51
Archive-name: procmail/part03
Environment: UNIX, sendmail
Supersedes: procmail: Volume 17, Issue 31-32

---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is part 03 of procmail
# ============= procmail/retint.c ==============
if test ! -d 'procmail'; then
    echo 'x - creating directory procmail'
    mkdir 'procmail'
fi
if test -f 'procmail/retint.c' -a X"$1" != X"-c"; then
	echo 'x - skipping procmail/retint.c (File already exists)'
else
echo 'x - extracting procmail/retint.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'procmail/retint.c' &&
X/************************************************************************
X *	Collection of routines that return an int (sort of anyway :-)	*
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 *	#include "README"						*
X *									*
X *	#include "STYLE"						*
X *									*
X ************************************************************************/
X#ifdef	RCS
Xstatic char rcsid[]="$Id: retint.c,v 2.0 1991/06/10 14:35:35 berg Rel $";
X#endif
X#include "config.h"
X#include "procmail.h"
X#include "shell.h"
X
Xsetdef(name,contents)const char*const name,*const contents;{
X strcat(strcat(strcpy(sgetcp=buf2,name),"="),contents);
X readparse(buf,sgetc,0);sputenv(buf);}
X
Xchar*backblock;		/* what is to be recovered in case of filter failure */
Xlong backlen;						       /* its length */
Xpid_t pidfilt,pidchild;
Xint pbackfd[2];				       /* the emergency backpipe :-) */
X
Xpipthrough(line,source,len)char*line,*source;const long len;{
X int pinfd[2],poutfd[2];
X rpipe(pbackfd);rpipe(pinfd);flaggerd=0;		 /* main pipes setup */
X if(!(pidchild=fork())){			/* create a sending procmail */
X   backblock=source;backlen=len;signal(SIGTERM,stermchild);
X   signal(SIGINT,stermchild);signal(SIGHUP,stermchild);
X   signal(SIGQUIT,stermchild);rclose(rc);rclose(PRDI);rclose(PRDB);
X   rpipe(poutfd);rclose(STDOUT);
X   if(!(pidfilt=fork())){				/* create the filter */
X      rclose(PWRO);rclose(PWRB);rdup(PWRI);rclose(PWRI);getstdin(PRDO);
X      callnewprog(line);}
X   rclose(PWRI);rclose(PRDO);
X   if(forkerr(pidfilt,line)){
X      rclose(PWRO);stermchild();}
X   if(dump(PWRO,source,len)){		  /* send in the text to be filtered */
X      writeerr(line);stermchild();}
X   if(pwait&&waitfor(pidfilt)!=EX_OK){	 /* check the exitcode of the filter */
X      progerr(line);stermchild();}
X   rclose(PWRB);kill(thepid,SIGQUIT);exit(EX_OK);} /* tell parent to proceed */
X rclose(PWRI);rclose(PWRB);getstdin(PRDI);
X if(forkerr(pidchild,"procmail"))
X    return 1;
X return 0;}		    /* we stay behind to read back the filtered text */
X
Xwaitflagger(){				      /* wait for SIGQUIT from child */
X while(!flaggerd)
X   suspend();}					       /* to prevent polling */
X
Xgrepin(expr,source,len,casesens)const char*const expr,*const source;long len;{
X pid_t pid;int poutfd[2];static const char*newargv[5]={0,"-e"};
X newargv[3]=casesens?(char*)0:"-i";*newargv=tgetenv(grep);newargv[2]=expr;
X rpipe(poutfd);
X if(!(pid=sfork())){					       /* start grep */
X   rclose(PWRO);rclose(rc);getstdin(PRDO);shexec(newargv);}
X rclose(PRDO);len=dump(PWRO,source,len);
X if(!forkerr(pid,*newargv)){
X    if(len)
X       writeerr(*newargv);
X    else
X       return waitfor(pid)!=EX_OK;}			     /* did it grep? */
X return EX_UNAVAILABLE;}
X
Xwaitfor(pid)const pid_t pid;{int i;	      /* wait for a specific process */
X while(pid!=wait(&i)||(i&127)==127);
X return i>>8&255;}
X
Xgetstdin(pip)const int pip;{
X rclose(STDIN);rdup(pip);rclose(pip);}
X
Xcallnewprog(newname)const char*const newname;{
X if(sh){const char*newargv[4];			 /* should we start a shell? */
X   yell(executing,newname);newargv[3]=0;newargv[2]=newname;
X   newargv[1]=tgetenv(shellflags);*newargv=tgetenv(shell);shexec(newargv);}
X {register const char*p;int argc;const char**newargv;
X argc=1;p=newname;	     /* If no shell, chop up the arguments ourselves */
X if(verbose){
X    log(executing);log(oquote);goto no_1st_comma;}
X do{					     /* show chopped up command line */
X   if(verbose){
X      log(",");
Xno_1st_comma:
X      log(p);}
X   while(*p++);}
X while(argc++,*p!=TMNATE);
X if(verbose)
X   log(cquote);
X newargv=malloc(argc*sizeof*newargv);p=newname;argc=0;	 /* alloc argv array */
X do{
X   newargv[argc++]=p;
X   while(*p++);}
X while(*p!=TMNATE);
X newargv[argc]=0;shexec(newargv);}}
X
Xwriteerr(line)const char*const line;{
X log("Error while writing to");logqnl(line);}
X
Xforkerr(pid,a)const pid_t pid;const char*const a;{
X if(pid==-1){
X   log("Failed forking");logqnl(a);return 1;}
X return 0;}
X
Xprogerr(line)const char*const line;{
X log("Program failure of");logqnl(line);}
X
Xopena(a)const char*const a;{
X lastfolder=cstr(lastfolder,a);yell("Opening",a);
X return ropen(a,O_WRONLY|O_APPEND|O_CREAT,0666);}
X
Xyell(a,b)const char*const a,*const b;{		     /* log if -d option set */
X if(verbose){
X   log(a);logqnl(b);}}
X
Xunlock(lockp)const char**const lockp;{
X lcking=1;
X if(*lockp){
X   yell("Unlocking",*lockp);
X   if(unlink(*lockp)){
X      log("Couldn't unlock");logqnl(*lockp);}
X   free(*lockp);*lockp=0;}
X if(nextexit==1){	    /* make sure we are not inside terminate already */
X   log(newline);terminate();}
X lcking=0;}
X
Xnomemerr(){
X log("Out of memory\nbuffer 0: \"");buf[linebuf-1]=buf2[linebuf-1]='\0';
X log(buf);log("\"\nbuffer 1:");logqnl(buf2);retval=EX_OSERR;terminate();}
X
Xlogqnl(a)const char*const a;{
X log(oquote);log(a);log(cquote);}
X
Xnextrcfile(){const char*p;	/* 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)const int fd;{int i;	      /* a sysV secure close (signal immune) */
X while((i=close(fd))&&errno==EINTR);
X return i;}
X
Xrwrite(fd,a,len)const int fd,len;void*const a;{int i; /* a sysV secure write */
X while(0>(i=write(fd,a,(size_t)len))&&errno==EINTR);
X return i;}
X
Xrread(fd,a,len)const int fd,len;void*const a;{int i;   /* a sysV secure read */
X while(0>(i=read(fd,a,(size_t)len))&&errno==EINTR);
X return i;}
X
Xropen(name,mode,mask)const char*const name;const mode_t mask;{int i,r;
X for(r=noresretry;0>(i=open(name,mode,mask));)	       /* a sysV secure open */
X   if(errno!=EINTR)
X      if(!((errno==EMFILE||errno==ENFILE)&&(r<0||r--)))
X	 break;		 /* survives a temporary "file table full" condition */
X return i;}
X
Xrdup(p)const int p;{int i,r;
X for(r=noresretry;0>(i=dup(p));)		  /* catch "file table full" */
X    if(!((errno==EMFILE||errno==ENFILE)&&(r<0||r--)))
X       break;
X return i;}
X
Xrpipe(fd)int fd[2];{int i,r;
X for(r=noresretry;0>(i=pipe(fd));)		  /* catch "file table full" */
X    if(!((errno==EMFILE||errno==ENFILE)&&(r<0||r--))){
X       *fd=fd[1]= -1;break;}
X return i;}
X
Xlockit(name,lockp)char*name;const char**const lockp;{int i;struct stat stbuf;
X unlock(lockp);			       /* unlock any previous lockfile FIRST */
X if(!*name)
X   return;
X for(lcking=1;;){		  /* to prevent deadlocks (I hate deadlocks) */
X   yell("Locking",name);
X   if(!NFSxopen(name)){
X      *lockp=tstrdup(name);			   /* lock acquired, hurray! */
Xterm: if(nextexit){
X	 log(whilstwfor);log("lockfile");logqnl(name);terminate();}
X      lcking=0;return;}		   /* check if it's time for a lock override */
X   if(errno==EEXIST&&!stat(name,&stbuf)&&!stbuf.st_size){time_t t;
X      if(locktimeout&&(t=time((time_t*)0),!stat(name,&stbuf)))	/* from stat */
X	 if(locktimeout<t-stbuf.st_mtime){   /* till unlink should be atomic */
X	 if(unlink(name)){			 /* but can't guarantee that */
X	    log("Forced unlock denied on");logqnl(name);}
X	 else{
X	    log("Forcing lock on");logqnl(name);suspend();}}}
X   else{		       /* maybe filename too long, shorten and retry */
X      if(0<(i=strlen(name)-1)&&!strchr(dirsep,(name[i-1]))){
X	 name[i]='\0';continue;}
X      log("Lockfailure on");logqnl(name);return;}
X   sleep(DEFlocksleep,locksleep);
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,tgetenv(lockext)),&loclock);}
X
Xterminate(){
X nextexit=2;			/* prevent multiple invocations of terminate */
X if(retval!=EX_OK)
X   log("Mail bounced\n");
X unlock(&loclock);unlock(&globlock);exit(retval);}
X
Xsuspend(){
X sleep((unsigned)suspendv);}
X
Xskipspace(){
X while(testb(' ')||testb('\t'));}
X
Xsgetc(){					/* a fake fgetc for a string */
X return *sgetcp?*(uchar*)sgetcp++:EOF;}
X
Xskipped(x)const char*const x;{
X log("Skipped");logqnl(x);}
X
Xstatic uchar rcbuf[STDBUF],*rcbufp,*rcbufend;	 /* buffers for custom stdio */
Xstatic ungetb;						 /* pushed back char */
X
Xbopen(name)const char*const name;{				 /* my fopen */
X rcbufp=rcbufend=0;ungetb= -1;yell("Rcfile:",name);
X return rc=ropen(name,O_RDONLY);}
X
Xgetbl(p)char*p;{int i;char*q;					  /* my gets */
X for(q=p;;){
X   switch(i=getb()){
X      case '\n':case EOF:
X	 *p='\0';return p!=q;}		     /* did we read anything at all? */
X   *p++=i;}}
X
Xgetb(){								 /* my fgetc */
X if(ungetb>=0){int i;				    /* anything pushed back? */
X   i=ungetb;ungetb= -1;return i;}
X if(rcbufp==rcbufend){
X   rcbufend=rcbuf+rread(rc,rcbufp=rcbuf,STDBUF);}		   /* refill */
X return rcbufp<rcbufend?*rcbufp++:EOF;}
X
Xtestb(x)const int x;{int i;	   /* fgetc that only succeeds if it matches */
X if((i=getb())==x)
X   return 1;
X ungetb=i;return 0;}
X
Xalphanum(c)const int c;{
X return c>='0'&&c<='9'||c>='a'&&c<='z'||c>='A'&&c<='Z'||c=='_';}
X				       /* open file or new file in directory */
Xdeliver(boxname)char*const boxname;{struct stat stbuf;
X strcpy(buf,boxname);			 /* boxname can be found back in buf */
X return stat(buf,&stbuf)||!S_ISDIR(stbuf.st_mode)?opena(buf):dirmail();}
X
X#include "exopen.h"
X					/* an NFS secure exclusive file open */
XNFSxopen(name)char*name;{char*p,*q;int j= -1,i;
X for(q=name;p=strpbrk(q,dirsep);q=p+1);			 /* find last DIRSEP */
X i=q-name;strncpy(p=malloc(i+UNIQnamelen),name,i);
X if(unique(p,p+i,0))
X   j=myrename(p,name);		 /* try and rename it, fails if nonexclusive */
X free(p);return j;}
SHAR_EOF
chmod 0644 procmail/retint.c ||
echo 'restore of procmail/retint.c failed'
Wc_c="`wc -c < 'procmail/retint.c'`"
test 9348 -eq "$Wc_c" ||
	echo 'procmail/retint.c: original size 9348, current size' "$Wc_c"
fi
# ============= procmail/shell.h ==============
if test -f 'procmail/shell.h' -a X"$1" != X"-c"; then
	echo 'x - skipping procmail/shell.h (File already exists)'
else
echo 'x - extracting procmail/shell.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'procmail/shell.h' &&
X/*$Id: shell.h,v 2.0 1991/06/10 14:39:08 berg Rel $*/
X
X#define malloc(n)	tmalloc((size_t)(n))
X#define realloc(p,n)	trealloc(p,(size_t)(n))
X#define tmemmove(t,f,n) memmove(t,f,(size_t)(n))
SHAR_EOF
chmod 0644 procmail/shell.h ||
echo 'restore of procmail/shell.h failed'
Wc_c="`wc -c < 'procmail/shell.h'`"
test 188 -eq "$Wc_c" ||
	echo 'procmail/shell.h: original size 188, current size' "$Wc_c"
fi
# ============= procmail/INSTALL ==============
if test -f 'procmail/INSTALL' -a X"$1" != X"-c"; then
	echo 'x - skipping procmail/INSTALL (File already exists)'
else
echo 'x - extracting procmail/INSTALL (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'procmail/INSTALL' &&
XTo install procmail, lockfile and formail: edit Makefile accordingly (if need
Xbe, config.h as well) and type 'make install'.
X
X'make install' will:
X      - execute autoconf (a shell script that repeatedly calls the C compiler
X	to determine if certain features/symbols are supported), which will
X	create a file named autoconf.h
X      - compile the *.c files, create the three binaries: procmail, lockfile,
X	formail
X      - copy these binaries to $(BINDIR)
X      - copy the man pages to $(MANDIR)
X
X
XMinimal requirements:
X
Xprocmail must be installed.
Xlockfile needs only to be installed if you plan to read several mailboxes
X	with one of the standard mailers.
Xformail needs only to be installed if mail sometimes arrives in nonstandard
X	mailbox format (or if you want to generate auto replies, split up
X	mailboxes/digests etc., see the man page of formail for more info).
X
X
XIf things don't compile automagically, I suggest you take a look at:
Xautoconf, autoconf.h, config.h, includes.h
X
XThe program is supposed to be fully ANSI and K&R compliant.
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
XSuggested command line for a test run: "procmail -d LOGFILE=/dev/tty"
X(now type in a mail message).
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 files in "examples".
X(BTW, be sure to make .forward *world* readable).
X
XFor more info about the program, see the man page.
X
X------------------------------------------------------------------------------
X-----------------------Frequently Asked Questions-----------------------------
X------------------------------------------------------------------------------
X
X1. Why does the logfile have lines containing "file -i not found"?
X
X	Your egrep doesn't understand the -i option (ignore case).  Either
X	use a different grep (e.g. set GREP to /bin/grep), or be sure
X	to specify the 'D' option on every recipe.
X
X2. I installed procmail (i.e. typed 'make install'), but how am I supposed to
X   use it?  When I type procmail on the command line it simply does nothing.
X
X	You're not supposed to start procmail from the command line.
X	Be sure to have a .forward and a .procmailrc file in your home
X	directory (see the examples subdirectory or the man page).
SHAR_EOF
chmod 0644 procmail/INSTALL ||
echo 'restore of procmail/INSTALL failed'
Wc_c="`wc -c < 'procmail/INSTALL'`"
test 2542 -eq "$Wc_c" ||
	echo 'procmail/INSTALL: original size 2542, current size' "$Wc_c"
fi
# ============= procmail/Makefile ==============
if test -f 'procmail/Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping procmail/Makefile (File already exists)'
else
echo 'x - extracting procmail/Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'procmail/Makefile' &&
X#$Id: Makefile,v 2.0 1991/06/10 14:39:08 berg Rel $
X
X# change BASENAME to your home directory if need be
XBASENAME = /usr/local
X
XBINDIR	 = $(BASENAME)/bin
XMANDIR	 = $(BASENAME)/man/man1
X
X########################################################################
X# Only edit below this line if you *think* you know what you are doing #
X########################################################################
X
X# Directory for the standard include files
XUSRINCLUDE = /usr/include
X
XOCFLAGS	 = -O
XOLDFLAGS = -s
X
XCFLAGS	= $(OCFLAGS) -I$(USRINCLUDE) -I./include
XLDFLAGS = $(OLDFLAGS)
X
XCC = cc
XO = o
XRM= rm -f
X
XBINS=procmail lockfile formail
X
XOBJ=procmail.$(O) nonint.$(O) goodies.$(O)
X
XDEP=shell.h procmail.h config.h
X
Xall:	autoconf.h $(BINS)
X
Xprocmail: $(OBJ) exopen.$(O) common.$(O) retint.$(O)
X	$(CC) $(CFLAGS) -o procmail $(OBJ) exopen.$(O) common.$(O) \
Xretint.$(O) $(LDFLAGS)
X
Xlockfile: lockfile.$(O) exopen.$(O)
X	$(CC) $(CFLAGS) -o lockfile lockfile.$(O) exopen.$(O) ${LDFLAGS}
X
Xformail: formail.$(O) common.$(O)
X	$(CC) $(CFLAGS) -o formail formail.$(O) common.$(O) ${LDFLAGS}
X
X_autotst: _autotst.c
X	$(CC) $(CFLAGS) -o _autotst _autotst.c $(LDFLAGS)
X
Xautoconf.h: autoconf Makefile
X	/bin/sh autoconf
X
X$(OBJ): $(DEP)
X
Xretint.$(O): $(DEP) exopen.h
X
Xexopen.$(O): config.h includes.h exopen.h
X
Xformail.$(O): config.h includes.h shell.h
X
Xlockfile.$(O): config.h includes.h
X
Xcommon.$(O): includes.h shell.h
X
Xprocmail.h: includes.h
X	touch procmail.h
X
Xincludes.h: autoconf.h
X	touch includes.h
X
X.c.$(O):
X	$(CC) $(CFLAGS) -c $*.c
X
Xinstall: all
X	chmod 755 $(BINS)
X	cp $(BINS) $(BINDIR)
X	chmod 644 man/procmail.1 man/lockfile.1 man/formail.1
X	cp man/procmail.1 man/lockfile.1 man/formail.1 $(MANDIR)
X
Xclean:
X	$(RM) $(OBJ) common.$(O) lockfile.$(O) exopen.$(O) retint.$(O) \
Xformail.$(O) $(BINS) autoconf.h _autotst*
SHAR_EOF
chmod 0644 procmail/Makefile ||
echo 'restore of procmail/Makefile failed'
Wc_c="`wc -c < 'procmail/Makefile'`"
test 1801 -eq "$Wc_c" ||
	echo 'procmail/Makefile: original size 1801, current size' "$Wc_c"
fi
# ============= procmail/autoconf ==============
if test -f 'procmail/autoconf' -a X"$1" != X"-c"; then
	echo 'x - skipping procmail/autoconf (File already exists)'
else
echo 'x - extracting procmail/autoconf (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'procmail/autoconf' &&
X#!/bin/sh
X#$Id: autoconf,v 2.1 1991/06/11 12:59:16 berg Rel $
X
XSHELL=/bin/sh || exec /bin/sh <autoconf # we're in a csh, feed myself to sh
X
XACONF=autoconf.h
Xtrap "rm $ACONF;exit 1" 1 2 3 15
Xcat >$ACONF <<HERE
X/* This file was automagically generated by autoconf */
X
XHERE
X
X# WARNING: in ./include/stdlib.h the const keyword is already used!
X#	   hence the const test has to precede all others.
X
Xcat >_autotst.c <<HERE
Xmain(){const int i;return 0;}
XHERE
X
Xecho 'Testing for const'
Xif make _autotst >/dev/null 2>&1
Xthen
X:
Xelse
X echo '#define const' >>$ACONF
Xfi
Xrm -f _autotst _autotst.o
X
Xcat >_autotst.c <<HERE
Xmain(){volatile int i;return 0;}
XHERE
X 
Xecho 'Testing for volatile'
Xif make _autotst >/dev/null 2>&1
Xthen
X:
Xelse
X echo '#define volatile' >>$ACONF
Xfi
Xrm -f _autotst _autotst.o
X
Xcat >_autotst.c <<HERE
Xmain(){int i;i= -1;return i=-i;}
XHERE
X
Xecho 'Testing for compiler age'
Xmake _autotst >_autotst.rrr 2>&1
X
Xif _autotst
Xthen
X echo 'Aha, this one is genuine antique!'
X echo '#define void char' >>$ACONF
Xfi
Xrm -f _autotst _autotst.o
X
X
Xcat >_autotst.c <<HERE
X#include "includes.h"
Xmain(){int i;
X void*p;
X i=(size_t)1;
X i+=(pid_t)1;
X i+=(time_t)1;
X i+=(mode_t)1;
X return 0;}
XHERE
X
Xecho 'Testing for void*,size_t,pid_t,time_t,mode_t'
Xmake _autotst >_autotst.rrr 2>&1
Xrm -f _autotst _autotst.o
X
Xgrepfor(){
Xif fgrep "$1" _autotst.rrr >/dev/null
Xthen
X echo "$2" >>$ACONF
Xfi
X}
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;'
X
Xcat >_autotst.c <<HERE
X#include "includes.h"
Xmain(){char a[1];
X setpwent();endpwent();memmove(a,"t",1);bcopy("t",a,1);strstr(a,"t");return 0;}
XHERE
X
Xecho 'Testing for memmove & strstr'
Xmake _autotst >_autotst.rrr 2>&1
Xrm -f _autotst _autotst.o
X
Xif fgrep memmove _autotst.rrr >/dev/null
Xthen
X echo '#define NOmemmove' >>$ACONF
X grepfor bcopy '#define NObcopy'
Xfi
Xgrepfor strstr '#define NOstrstr'
Xgrepfor setpwent '#define setpwent()'
Xgrepfor endpwent '#define endpwent()'
X
Xrm -f _autotst*
X
Xecho -----------------------------autoconf.h-----------------------------------
Xcat autoconf.h
Xecho --------------------------------------------------------------------------
SHAR_EOF
chmod 0644 procmail/autoconf ||
echo 'restore of procmail/autoconf failed'
Wc_c="`wc -c < 'procmail/autoconf'`"
test 2224 -eq "$Wc_c" ||
	echo 'procmail/autoconf: original size 2224, current size' "$Wc_c"
fi
# ============= procmail/exopen.h ==============
if test -f 'procmail/exopen.h' -a X"$1" != X"-c"; then
	echo 'x - skipping procmail/exopen.h (File already exists)'
else
echo 'x - extracting procmail/exopen.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'procmail/exopen.h' &&
X/*$Id: exopen.h,v 2.0 1991/06/10 14:39:08 berg Rel $*/
X#define SERIALchars	3
X#define UNIQnamelen	(1+SERIALchars+HOSTNAMElen+1)
X#define SERIALmask	((1L<<6*SERIALchars)-1)
SHAR_EOF
chmod 0644 procmail/exopen.h ||
echo 'restore of procmail/exopen.h failed'
Wc_c="`wc -c < 'procmail/exopen.h'`"
test 170 -eq "$Wc_c" ||
	echo 'procmail/exopen.h: original size 170, current size' "$Wc_c"
fi
# ============= procmail/formail.c ==============
if test -f 'procmail/formail.c' -a X"$1" != X"-c"; then
	echo 'x - skipping procmail/formail.c (File already exists)'
else
echo 'x - extracting procmail/formail.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'procmail/formail.c' &&
X/************************************************************************
X *	formail.c	a mail (re)formatter				*
X *									*
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 *	#include "README"						*
X *									*
X *	#include "STYLE"						*
X *									*
X ************************************************************************/
X#ifdef	RCS
Xstatic char rcsid[]="$Id: formail.c,v 2.3 1991/06/12 10:50:21 berg Rel $";
X#endif
Xstatic char rcsdate[]="$Date: 1991/06/12 10:50:21 $";
X#include "config.h"			/* I know, overkill, only need BinSh */
X#include "includes.h"
X
X#define BSIZE	4096
X
X#define FROM		"From "
X#define UNKNOWN		"foo@bar"
X
X#define Re		(re+1)
X#define Nextchar(x)	do{x=getchar();if(feof(stdin))goto foundeof;}while(0)
X#define putssn(a,l)	tputssn(a,(size_t)(l))
X#define putcs(a)	(errout=putc(a,mystdout))
X#define PRDO		poutfd[0]
X#define PWRO		poutfd[1]
X
Xstatic const char From[]=FROM,replyto[]="Reply-To:",Fromm[]="From:",
X returnpath[]="Return-Path",sender[]="Sender:",outofmem[]="Out of memory\n",
X subject[]="Subject:",re[]=" Re:",couldntw[]="Couldn't write to stdout",
X references[]="References:",messageid[]="Message-ID:",Date[]="Date:";
Xconst char binsh[]=BinSh;
Xstatic struct {const char*const head;const int len,wrepl;}sest[]={
X {sender,STRLEN(sender),0},{replyto,STRLEN(replyto),4},
X {Fromm,STRLEN(Fromm),2},{returnpath,STRLEN(returnpath),1}};
Xstatic struct {const char*const headr;const int lenr;size_t offset;}rex[]={
X {subject,STRLEN(subject)},{references,STRLEN(references)},
X {messageid,STRLEN(messageid)}};
X#define subj	rex[0]
X#define refr	rex[1]
X#define msid	rex[2]
Xstatic struct {const char*const hedr;const int lnr;}cdigest[]={
X {Fromm,STRLEN(Fromm)},{Date,STRLEN(Date)},{subject,STRLEN(subject)}};
X#define mxl(a,b)	mx(STRLEN(a),STRLEN(b))
X#define dig_HDR_LEN	mx(mxl(From,Fromm),mxl(Date,subject))
Xstatic errout,oldstdout;
Xstatic pid_t child= -1;
Xstatic FILE*mystdout;
Xstatic size_t nrskip,nrtotal= -1;
X
X#ifdef	NOstrstr
Xchar*strstr(whole,part)const char*whole,*const part;{size_t len;
X if(!(len=strlen(part)))
X   return(char*)whole;
X while(*whole&&strncmp(whole,part,len))
X   ++whole;
X return *whole?(char*)whole:(char*)0;}
X#endif
X
Xvoid*tmalloc(len)const size_t len;{void*p;
X if(p=malloc(len))
X   return p;
X log(outofmem);exit(EX_OSERR);}
X
Xvoid*trealloc(old,len)void*old;const size_t len;{
X if(old=realloc(old,len))
X   return old;
X log(outofmem);exit(EX_OSERR);}
X
X#include "shell.h"
X
Xmain(argc,argv)const char*const argv[];{time_t t;
X int i,lastm,nowm,thelen=0,split=0,force=0,bogus=1,every=0,areply=0,
X   trust=0,digest=0,nowait=0;
X size_t buflen,p=0,lnl=0,thename,ll;
X char*buf,*chp;
X while(*++argv){
X   if((lastm= **argv)=='+')
X      goto number;
X   else if(lastm!='-')
X      goto usg;
X   for(i=1;;){
X      switch((*argv)[i++]){
X	 case 't':trust=1;continue;    /* trust the sender for valid headers */
X	 case 'r':areply=1;continue;			 /* generate a reply */
X	 case 'f':force=1;continue;		  /* accept arbitrary format */
X	 case 'e':every=1;continue;		      /* split on every From */
X	 case 'd':digest=1;continue;			 /* split up digests */
X	 case 'n':nowait=1;continue;	      /* don't wait for the programs */
X	 case 's':split=1;bogus=0;
X	    if(!(*argv++)[i])
X	       goto parsedoptions;
X	    goto usg;
Xnumber:	 default:
X	    if((*argv)[1]-'0'>(unsigned)9){
Xusg:	       log("Usage: formail [+nnn] [-nnn] [-bfrtned] \
X[-s command argument ...]\n");return EX_USAGE;}
X	    ll=strtol((*argv)+1,(char**)0,10);
X	    if(lastm=='+')
X	       nrskip=ll;
X	    else
X	       nrtotal=ll;
X	    break;
X	 case 'b':bogus=0;continue;		 /* leave bogus Froms intact */
X	 case '\0':;}
X      break;}}
Xparsedoptions:
X mystdout=stdout;
X if(split){
X   oldstdout=dup(STDOUT);fclose(stdout);startprog(argv);}
X while('\n'==(i=getchar()));
X buf=malloc(buflen=BSIZE);t=time((time_t*)0);
X for(;;){					 /* start parsing the header */
X   if((buf[p++]=i)=='\n'){
X      chp=buf+lnl;i=maxindex(rex);
X      while(strnicmp(rex[i].headr,chp,rex[i].lenr)&&i--);
X      if(i>=0)					  /* found anything already? */
X	 rex[i].offset=lnl+rex[i].lenr;
X      else if(!strncmp(From,chp,STRLEN(From))){
X	 if(!lnl){				/* was the real "From " line */
X	    if(!areply)
X	       goto endofheader;
X	    nowm=trust?1:3/*wreply*/;ll=lnl+STRLEN(From);goto foundfrom;}
X	 if(bogus){
X	    tmemmove(chp+1,chp,p++-lnl);*chp='>';}}		   /* disarm */
X      else{
X	 i=maxindex(sest);
X	 do
X	    if(!strnicmp(sest[i].head,chp,sest[i].len)){
X	       nowm=areply?sest[i].wrepl:i;ll=lnl+sest[i].len;
Xfoundfrom:     buf[p]='\0';
X	       if(chp=strchr(buf+ll,'<'))	      /* extract the address */
X		  ll=chp-buf+1;
X	       chp=buf+(ll+=strspn(buf+ll," \t"));
X	       if((i=strcspn(chp,">(\n \t"))&&(!thelen||nowm>lastm)){
X		  thename=ll;thelen=i;
X		  lastm=strstr(chp,".UUCP")?nowm-maxindex(sest)-1:nowm;}
X	       break;}
X	 while(i--);
X	 if(lnl==p-1)
X	    break;}				    /* end of header reached */
X      lnl=p;}
X   if(p>=buflen-2)
X      buf=realloc(buf,buflen+=BSIZE);
Xredigest:
X   i=getchar();
X   if(feof(stdin))
X      i='\n';}			/* make sure the header ends with 2 newlines */
X if(areply||!force){
X   putss(areply?"To: ":From);
X   if(thelen)					/* found any sender address? */
X      putssn(buf+thename,thelen);
X   else
X      putss(UNKNOWN);
X   if(areply){
X      putcs('\n');
X      if(subj.offset){					   /* any Subject: ? */
X	 putss(subject);chp=buf+subj.offset;
X	 if(strnicmp(chp+strspn(chp," "),Re,STRLEN(Re)))
X	    putss(re);			       /* no Re: , add one ourselves */
X	 nlputss(chp);}
X      if(refr.offset||msid.offset){	 /* any Message-ID: or References: ? */
X	 putss(references);
X	 if(refr.offset){
X	    chp=buf+refr.offset;
X	    putssn(chp,strchr(chp,'\n')-chp+!msid.offset);}
X	 if(msid.offset){
X	    nlputss(buf+msid.offset);putss("In-Reply-To:");
X	    nlputss(buf+msid.offset);}}
X      putcs('\n');
X      while(getchar(),!feof(stdin));return EX_OK;}
X   putcs(' ');putss(ctime(&t));}
Xendofheader:
X putssn(buf,p);p=0;lnl=1;
X if(!bogus&&!split)
X   for(;;putcs(i))
X      Nextchar(i);
X for(;;){					       /* continue the quest */
X   do{						 /* read line until not From */
X      if(p==buflen-1)
X	 buf=realloc(buf,++buflen);
X      Nextchar(i=buf[p]);
X      if(++p==STRLEN(From))
X	 if(!strncmp(From,buf,STRLEN(From))){
X	    if(bogus){
X	       putcs('>');break;}				   /* disarm */
X	    else if(every)
X	       goto splitit;
X	    else if(split&&lnl)
X	       lnl=2;}			   /* mark line as possible postmark */
X      if(lnl==1&&digest){
X	 thelen=maxindex(cdigest);
X	 do				      /* check for new digest header */
X	    if(p==cdigest[thelen].lnr&&!strncmp(buf,cdigest[thelen].hedr,p)){
X	       lnl=thelen=0;goto splitit;}	  /* pretend we started over */
X	 while(thelen--);}}
X   while(i!='\n'&&(lnl==2||p<dig_HDR_LEN));
X   if(lnl==2){
X      buf[p]='\0';		 /* perform more thorough check for postmark */
X      for(i=STRLEN(From)-1;buf[++i]==' ';);
X      if(ll=strcspn(buf+i,"\n \t")){
X	 i+=ll;
X	 if(ll=strspn(buf+i," ")&&(ll=buf[i+ll])!='\t'&&ll!='\n'){
Xsplitit:    if(fclose(mystdout)==EOF||errout==EOF){
X	       log(couldntw);log(", continuing...\n");split= -1;}
X	    if(!nowait)
X	       waitforit();
X	    startprog(argv);
X	    if(!lnl)					    /* digest split? */
X	       goto redigest;
X	    i='\n';}}}
X   lnl=p==1;putssn(buf,p);p=0;
X   if(i!='\n')
X      do Nextchar(i);
X      while(putcs(i),i!='\n');}
Xfoundeof:
X putssn(buf,p);
X if(fclose(mystdout)==EOF||errout==EOF){
X   log(couldntw);return EX_IOERR;}
X child= -1;waitforit();return split<0?EX_IOERR:EX_OK;}	/* wait for everyone */
X
Xstrnicmp(a,b,l)register const char*a,*b;register unsigned l;{int i,j;
X if(l)						 /* case insensitive strncmp */
X   do{
X      while(*a&&*a==*b&&--l)
X	 ++a,++b;
X      if(!l)
X	 break;
X      if((i= *a++)>='A'&&i<='Z')
X	 i+='a'-'A';
X      if((j= *b++)>='A'&&j<='Z')
X	 j+='a'-'A';
X      if(j!=i)
X	 return i>j?1:-1;}
X   while(i&&j&&--l);
X return 0;}
X
Xlog(a)const char*const a;{
X fputs(a,stderr);}
X
Xlogqnl(a)const char*a;{
X log(" \"");log(a);log("\"\n");}
X
Xnlputss(a)const char*const a;{
X putssn(a,strchr(a,'\n')+1-a);}
X
Xputss(a)const char*a;{
X while(*a)
X   putcs(*a++);}
X
Xtputssn(a,l)const char*a;size_t l;{
X while(l--)
X   putcs(*a++);}
X
Xstartprog(argv)const char*const*const argv;{int poutfd[2];
X if(!nrtotal)
X   goto squelch;
X if(nrskip){
X   --nrskip;
Xsquelch:
X   if(!(mystdout=fopen(DevNull,"a")))
X      goto nofild;
X   return;}
X if(nrtotal>0)
X   --nrtotal;
X dup(oldstdout);pipe(poutfd);
X if(!(child=fork())){
X   close(oldstdout);close(PWRO);fclose(stdin);dup(PRDO);close(PRDO);
X   shexec(argv);}
X close(STDOUT);close(PRDO);
X if(STDOUT!=dup(PWRO)||!(mystdout=fdopen(STDOUT,"a"))){
Xnofild:
X   log("File table full\n");exit(EX_OSERR);}
X close(PWRO);
X if(0>child){
X   log("Can't fork\n");exit(EX_OSERR);}}
X
Xwaitforit(){int i;
X while(child!=wait(&i)||(i&127)==127);}
SHAR_EOF
chmod 0644 procmail/formail.c ||
echo 'restore of procmail/formail.c failed'
Wc_c="`wc -c < 'procmail/formail.c'`"
test 8833 -eq "$Wc_c" ||
	echo 'procmail/formail.c: original size 8833, current size' "$Wc_c"
fi
# ============= procmail/config.h ==============
if test -f 'procmail/config.h' -a X"$1" != X"-c"; then
	echo 'x - skipping procmail/config.h (File already exists)'
else
echo 'x - extracting procmail/config.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'procmail/config.h' &&
X/*$Id: config.h,v 2.0 1991/06/10 14:35:35 berg Rel $*/
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 DEFlinebuf	2048		 /* default max expanded line length */
X#define BLKSIZ		16384		  /* blocksize while reading/writing */
X#define STDBUF		1024		     /* blocksize for emulated stdio */
X#define HOSTNAMElen	8	  /* nr of significant chararacters for HOST */
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	"$MAILDIR/.mailbox"
X#define DEFmsgprefix	"msg."
X#define DEForgmail	"/usr/spool/mail/$USER"
X#define DEFgrep		"/usr/bin/egrep"
X#define DEFsendmail	"/usr/lib/sendmail"
X#define DEFlockext	".lock"
X#define DEFshellflags	"-c"
X#define DEFlocktimeout	3600			     /* defaults to one hour */
X#define DEFnoresretry	2      /* default nr of retries if no resources left */
X
X#define NRRECFLAGS	(9+1)
X#define RECFLAGS	" %9[HBDIhbfcws] %[^\n]" /* 'I' and 's' are obsolete */
X#define BinSh		"/bin/sh"
X#define Tmp		"/tmp"
X#define DevNull		"/dev/null"
X#define DIRSEP		"/"		 /* directory separator symbols, the */
X				   /* last one should be the most common one */
X
X/* the regular expression we use to look for bogus headers
X	(which I took from /usr/ucb/mail) is:
X					      "\n\nFrom +[^\t\n ]+ +[^\n\t]" */
X
X#define FromSCAN	"From%*[ ]%*[^\t\n ]%*[ ]%1[^\n\t]"
X#define EOFName		"%[^ \t\n#'\")};]"
X
X#define VERSIONOPT	'v'			/* option to display version */
X#define PRESERVOPT	'p'
X#define DEBUGOPT	'd'
X
X#define MINlinebuf	128    /* minimal LINEBUF length (don't change this) */
X#define SFROM		"From "
X#define SFROM_S		"From%*[ ]%74[^\n]"
X#define SSUBJECT	" Subject:"
X#define SSUBJECT_S	\
X		"%*1[Ss]%*1[Uu]%*1[Bb]%*1[Jj]%*1[Ee]%*1[Cc]%*1[Tt]:%70[^\n]"
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
SHAR_EOF
chmod 0644 procmail/config.h ||
echo 'restore of procmail/config.h failed'
Wc_c="`wc -c < 'procmail/config.h'`"
test 2501 -eq "$Wc_c" ||
	echo 'procmail/config.h: original size 2501, current size' "$Wc_c"
fi
# ============= procmail/procmail.h ==============
if test -f 'procmail/procmail.h' -a X"$1" != X"-c"; then
	echo 'x - skipping procmail/procmail.h (File already exists)'
else
echo 'x - extracting procmail/procmail.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'procmail/procmail.h' &&
X/*$Id: procmail.h,v 2.0 1991/06/10 14:35:35 berg Rel $*/
X
X#include "includes.h"
X
Xtypedef unsigned char uchar;
X
X#ifndef console
X#define console devnull
X#endif
X
X#define XTRAlinebuf	2	     /* surplus of LINEBUF (see readparse()) */
X#define TMNATE		'\377'		     /* terminator (see readoarse()) */
X
X#define PRDO	poutfd[0]
X#define PWRO	poutfd[1]
X#define PRDI	pinfd[0]
X#define PWRI	pinfd[1]
X#define PRDB	pbackfd[0]
X#define PWRB	pbackfd[1]
X#define LENoffset	(TABWIDTH*LENtSTOP)
X#define MAXfoldlen	(LENoffset-STRLEN(sfolder)-1)
X#define MCDIRSEP	(dirsep+STRLEN(dirsep)-1)      /* most common DIRSEP */
X
Xstruct varval{const char*const name;long val;};
X#define locksleep	(strenvvar[0].val)
X#define locktimeout	(strenvvar[1].val)
X#define suspendv	(strenvvar[2].val)
X#define noresretry	(strenvvar[3].val)
X#define MAXvarvals	maxindex(strenvvar)
X
X#ifndef MAIN
Xextern char*buf,*buf2,*globlock,*loclock,*tolock,*lastfolder;
Xextern const char grep[],shellflags[],shell[],lockext[],newline[],binsh[],
X unexpeof[],shellmetas[],*const*gargv,*sgetcp,*rcfile,dirsep[],msgprefix[],
X devnull[],executing[],oquote[],cquote[],whilstwfor[];
Xextern struct varval strenvvar[];
Xextern long lastdump;
Xextern sh,pwait,retval,lcking,locknext,verbose,linebuf,rc;
Xextern volatile flaggerd,nextexit;
Xextern pid_t thepid;
X#endif
X
X#ifdef NOmemmove
Xvoid*memmove();
X#endif
X
Xvoid*tmalloc(),*trealloc();
Xpid_t sfork();
Xvoid sterminate(),stermchild(),flagger(),errgrandchild();
Xlong dump(),pipin(),renvint();
Xchar*readdyn(),*fromprog(),*cat(),*findnl(),*tstrdup(),*cstr();
Xconst char*tgetenv(),*hostname();
Xint sgetc(),getb();
SHAR_EOF
chmod 0644 procmail/procmail.h ||
echo 'restore of procmail/procmail.h failed'
Wc_c="`wc -c < 'procmail/procmail.h'`"
test 1582 -eq "$Wc_c" ||
	echo 'procmail/procmail.h: original size 1582, current size' "$Wc_c"
fi
# ============= procmail/HISTORY ==============
if test -f 'procmail/HISTORY' -a X"$1" != X"-c"; then
	echo 'x - skipping procmail/HISTORY (File already exists)'
else
echo 'x - extracting procmail/HISTORY (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'procmail/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 search for 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
X1991/02/21: v1.20
X	    Changes to procmail.c:
X	       Removed library conflict on some machines for 'locking'
X	       Added uname call as alternative for gethostname
X	       Changed name of SHELLMETA to SHELLMETAS (for conformance
X		  with dmake)
X	       Added LOCKTIMEOUT to learn procmail to decide wether or not
X		  a certain lockfile is still 'valid'
X	       Added the function sputenv (smart-putenv) to avoid library
X		  problems and to finally have a putenv that works the
X		  way it was supposed to work all along (you wouldn't believe
X		  how brain damaged this library function is :-)
X	       Changed environment variable assignment to skip trailing blanks
X		  only, and allow intermediate blanks (parsing like make)
X1991/02/22: v1.21
X	    Split up procmail.c in procmail.c, nonint.c, retint.c, procmail.h,
X	       config.h, sysexits.h, shell.h
X	    Changes to lockfile.c:
X	       Added -l option (locktimeout)
X	    Moved virtually all configuration stuff from Makefile into
X	       config.h
X	    Added -v option to procmail
X1991/03/01: v1.30
X	    Added out of memory/swap space immunity  (NOMEMRETRY)
X	    Made forced terminations of procmail more reliable and verbose
X	       (previously, procmail would display erroneous error messages
X	       if an attempt was made to kill procmail more than once in
X	       rapid succession)
X	    Fixed up man pages and comments
X	    Included more example files
X	    Made sure that variable substitution works in locallockfile-
X	       specifications too
X1991/03/15: v1.35
X	    Fixed the problem when no rcfile was found (rc!=NULL)
X	    Made my memmove replacement ANSI compatible
X	    Fixed up the Makefile (include file dependencies were incorrect)
X	    Started using RCS to manage the source
X1991/06/04: v1.99
X	    Changed NOMEMRETRY into NORESRETRY, now all machine limitations
X	       are caught
X	    Beefed up the parsing routine, now supports virtually complete
X	       /bin/sh syntax (*all* quotes and escapes are understood)
X	    Cleaned up the code, arranged for all remotely configuration-
X	       dependent looking values to be in config.h
X	    Created an include directory to catch missing include files
X	    Created an autoconf script that determines all installation
X	       specifics (all the user has to do now is make)
X	    Threw out (the last?) BSD specific library routines
X	    ANSI'fied the code, it's now as close as you can get to 'native'
X	       ANSI while maintaining compatibility with K&R
X	    Stopped using the %i identifier from sscanf
X	    Improved the diagnostic messages when procmail is killed (tells
X	       you what it was waiting for)
X	    Made the file locking mechanism RELIABLE over NFS
X	    Procmail now is able to deliver to directories too (AMS --
X	       Andrew Mail System), it creates a uniquely named new file for
X	       every new mail
X	    Threw out the 's' and 'I' options in rcfiles, introduced 'D'
X	    Completely rewrote the filter code, made sure that the pid number
X	       off procmail does not change anymore while filtering
X	    Threw out the stdio library (out of procmail) to avoid the hidden
X	       malloc on fopen (I want to catch all mallocs), reliability
X	       was improved, binary size did not shrink because the getpwent
X	       library links in the stdio library (aargh!)
X	    Procmail ditches the environment completely now upon startup
X	    Provided a -p flag to preserve the environment
X	    Provided a -d flag for debugging purposes (debugging rc scripts)
X	    Improved logfile format, now logs a third entry on mail arrival:
X	       which folder the mail finally went to and how long it was
X	    Made logfile output line buffered to get a cleaner logfile if
X	       several programs write it concurrently
X	    Changes to lockfile.c:
X	       Added -s flag to maintain step with procmail
X	    Created formail.c:
X	       A new (the third) program
X	    Rearranged the routines a bit, so that two object files could be
X	       shared between the three programs
X1991/06/10: v2.00
X	    Changed all "ambiguous assignments" to have a space inserted
X	       (preserves compatibility with older compilers)
X	    Made some more entries in the config.h file
X	    Changes to formail.c:
X	       Added strstr library replacement
X	       Added the option to split digests
X	    Updated the manual files (I hate doing this)
X	    Updated the example files
X1991/06/11: v2.01
X	    Fixed up includes.h and autoconf to be more POSIX compliant
X	    Fixed up small bug in readparse() (goodies.c) that caused trouble
X	       with recursively nested backquotes (nobody will probably ever
X	       use this, but I was testing worst case behaviour)
X	    Documented the $$ environment variable in procmail.1
X1991/06/12: v2.02
X	    Fixed typo in strstr replacement
X	    Fixed runaway line while logging long folder names
SHAR_EOF
chmod 0644 procmail/HISTORY ||
echo 'restore of procmail/HISTORY failed'
Wc_c="`wc -c < 'procmail/HISTORY'`"
test 5739 -eq "$Wc_c" ||
	echo 'procmail/HISTORY: original size 5739, current size' "$Wc_c"
fi
# ============= procmail/FEATURES ==============
if test -f 'procmail/FEATURES' -a X"$1" != X"-c"; then
	echo 'x - skipping procmail/FEATURES (File already exists)'
else
echo 'x - extracting procmail/FEATURES (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'procmail/FEATURES' &&
XFeature summary for procmail:
X	+ Easy to install
X	+ Simple to maintain and configure because
X	  all you need is actually only ONE executable (procmail)
X	  and ONE configuration file (.procmailrc)
X	+ Uses *your* (i.e. easily configurable) favourite regular expression
X	  syntax
X	+ Allows for very-easy-to-use yes-no decisions on where the mail
X	  should go
X	+ Filters, delivers and forwards mail *reliably*
X	+ Provides a stable and guaranteed environment for any programs or
X	  shell scripts you may wish to start upon mail arrival
X	+ Is designed for reliability, once procmail gets hold of your mail
X	  you can consider it delivered
X	+ Is event driven (i.e. gets invoked automagically when mail arrives)
X	+ Performs heroically under even the worst conditions
X	  (file system full, out of swap space, process table full,
X	  file table full, missing support files, unavailable executables,
X	  denied permissions) and tries to deliver the mail somehow anyway
X	  (it usually succeeds were other programs would have given up)
X	+ procmail is the closest you can get to a program that outlives
X	  the swapper :-)
X	+ Absolutely undeliverable mail (after trying every trick in the book)
X	  will bounce back to the sender
X	+ Does not use *any* temporary files
X	+ Is explicitly designed to work under NFS as well
X	+ Performs more reliable mailbox locking than most other mailers
X	  (especially across NFS, DON'T use NFS mounted mailboxes WITHOUT
X	  installing procmail, you may use valuable mail one day)
X	+ Supports both mailfolder standards (single file folders (standard
X	  *NIX format) as well as directory folders (AMS -- Andrew Mail System)
X	  that contain one file per message)
X	+ Variable assignment and substitution is a subset of the standard
X	  /bin/sh syntax
X	+ Provides a mail log file, which logs all mail arrival, shows
X	  in summary whence it came from, what it was about, where it went
X	  (what folder) and how long (in bytes) it was
X	+ Uses this log file to display a wide range of diagnostic and error
X	  messages (if something went wrong)
X	+ Processed mail can contain arbitrary 8-bit characters (including
X	  '\0'); i.e. binary mailings can be processed if the rest of the
X	  mailing system knew how to handle them too
X	+ It has a man page (boy, does *it* have a man page)
X	+ It can be used as a local delivery agent (substitute for /bin/mail)
X
XFeature summary for formail:
X	+ Can generate auto-reply headers
X	+ Can force mail into mailbox format (so that you can process it with
X	  standard mail programs)
X	+ Can split up mailboxes into the individual messages
X	+ Can split up digests into the individual messages
X
XFeature summary for lockfile:
X	+ Provides NFS-secure lockfiles to shell script programmers
SHAR_EOF
chmod 0644 procmail/FEATURES ||
echo 'restore of procmail/FEATURES failed'
Wc_c="`wc -c < 'procmail/FEATURES'`"
test 2717 -eq "$Wc_c" ||
	echo 'procmail/FEATURES: original size 2717, 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.