home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-05-12 | 53.5 KB | 1,750 lines |
- Newsgroups: comp.sources.misc
- From: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
- Subject: v29i093: procmail - mail processing program v2.70, Part04/05
- Message-ID: <1992May11.151639.29141@sparky.imd.sterling.com>
- X-Md4-Signature: b0fd81307060d9fbdb8c81a6d3817fbd
- Date: Mon, 11 May 1992 15:16:39 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
- Posting-number: Volume 29, Issue 93
- Archive-name: procmail/part04
- Environment: UNIX, sendmail, smail, MMDF
- Supersedes: procmail: Volume 28, Issue 01-05
-
- #! /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 4 (of 5)."
- # Contents: procmail/examples/1rmail procmail/goodies.c
- # procmail/man/procmail.man procmail/man/procmailrc.man
- # procmail/retint.c
- # Wrapped by berg@drunol on Thu Apr 30 13:42:58 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'procmail/examples/1rmail' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail/examples/1rmail'\"
- else
- echo shar: Extracting \"'procmail/examples/1rmail'\" \(400 characters\)
- sed "s/^X//" >'procmail/examples/1rmail' <<'END_OF_FILE'
- X#!/bin/sh
- X#
- X# specify the mailbox file you want to read on the command line
- X#
- XMAILDIR=$HOME/Mail
- Xcd $MAILDIR
- XLOCKFILE=$HOME/.lockmail
- Xif lockfile -! -r1 $LOCKFILE
- Xthen
- X echo Mail is currently arriving, please wait...
- X while
- X lockfile -! -4 -r2 $LOCKFILE
- X do
- X echo Mail is still arriving...
- X done
- Xfi
- Xtrap "rm -f $LOCKFILE;exit 0" 0 1 2 3 15
- X#
- X# Call you favourite mailer here.
- X#
- X/usr/ucb/mail -f $*
- END_OF_FILE
- if test 400 -ne `wc -c <'procmail/examples/1rmail'`; then
- echo shar: \"'procmail/examples/1rmail'\" unpacked with wrong size!
- fi
- # end of 'procmail/examples/1rmail'
- 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'\" \(9144 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.16 1992/04/09 16:16: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/* 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,fgetc,sarg)register char*p;int(*const fgetc)();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 9144 -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/man/procmail.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail/man/procmail.man'\"
- else
- echo shar: Extracting \"'procmail/man/procmail.man'\" \(11722 characters\)
- sed "s/^X//" >'procmail/man/procmail.man' <<'END_OF_FILE'
- X.de Id
- X.ds Rv \\$3
- X.ds Dt \\$4
- X..
- X.Id $Id: procmail.man,v 2.26 1992/04/29 15:55:09 berg Rel $
- X.de Sh
- X.br
- X.ne 11
- X.SH "\\$1"
- X..
- X.de Ss
- X.br
- X.ne 10
- X.SS "\\$1"
- X..
- X.de Tp
- X.br
- X.ne 9
- X.TP \\$1
- X..
- X.de Rs
- X.na
- X.nf
- X.RS
- X..
- X.de Re
- X.RE
- X.fi
- X.ad
- X..
- X.TH PROCMAIL 1 \*(Dt BuGless
- X.SH NAME
- X.na
- Xprocmail \- autonomous mail processor
- X.SH SYNOPSIS
- X.B procmail
- X.RB [ \-+PRESERVOPT++TEMPFAILOPT+ ]
- X.RB [ "\-+FROMWHOPT+ \fIfromwhom\fP" ]
- X.RI [ "parameter\fB=\fPvalue " | " rcfile" ]
- X\&.\|.\|.
- X.br
- X.B procmail
- X.RB [ \-+PRESERVOPT++TEMPFAILOPT+ ]
- X.RB [ "\-+FROMWHOPT+ \fIfromwhom\fP" ]
- X.B \-+DELIVEROPT+
- X.I recipient
- X\&.\|.\|.
- X.br
- X.B procmail
- X.B \-+VERSIONOPT+
- X.ad
- X.Sh DESCRIPTION
- XFor a quick start, see
- X.B NOTES
- Xat the end.
- X.PP
- X.B Procmail
- Xshould be invoked automatically over the
- X.B +DOT_FORWARD+
- Xfile mechanism as soon as mail arrives. Alternatively, when installed by
- Xa system administrator, it can be invoked from within the mailer immediately.
- XWhen invoked, it first sets some environment variables to default values,
- Xreads the mail message from stdin until an EOF, separates the body from the
- Xheader, and then, if no command line arguments are present, it starts to look
- Xfor a file named
- X.B +PROCMAILRC+
- Xin your home directory. According to the processing recipes in this file,
- Xthe mail message that just arrived gets distributed into the right folder
- X(and more).
- X.PP
- XIf running suid root or with root priviliges, procmail will be able to
- Xperform as a functionally enhanced, backwards compatible mail delivery agent.
- X.PP
- XThe rcfile format is described in detail in the
- X.BR procmailrc (5)
- Xman page.
- X.PP
- XExamples for rcfile recipes can be looked up in the
- X.BR procmailex (5)
- Xman page.
- X.Ss Signals
- X.Tp 1.2i
- X.B TERMINATE
- XTerminate prematurely and requeue the mail.
- X.Tp
- X.B HANGUP
- XTerminate prematurely and bounce the mail.
- X.Tp
- X.B INTERRUPT
- XTerminate prematurely and bounce the mail.
- X.Tp
- X.B QUIT
- XTerminate prematurely and silently lose the mail.
- X.Tp
- X.B ALARM
- XForce a timeout (see
- X.BR TIMEOUT).
- X.Sh OPTIONS
- X.Tp 0.5i
- X.B \-+VERSIONOPT+
- XProcmail will print its version number and exit.
- X.Tp
- X.B \-+PRESERVOPT+
- XPreserve any old environment. Normally procmail clears the environment
- Xupon startup+KEEPENV+. However, in any case: any default values will override
- Xany preexisting environment variables, i.e. procmail will not pay any attention
- Xto any predefined environment variables, it will happily overwrite them
- Xwith his own defaults.
- X.Tp
- X.B \-+TEMPFAILOPT+
- XMake procmail fail softly, i.e. if procmail cannot deliver the mail to
- Xany of the destinations you gave, the mail will not bounce, but will return
- Xto the mailqueue. Another delivery-attempt will be made at some time in
- Xthe future.
- X.Tp
- X.I "\fB\-+FROMWHOPT+\fP fromwhom"
- XCauses procmail to regenerate the leading `+FROM+' line with
- X.I fromwhom
- Xas the sender (instead of \-+FROMWHOPT+ one could use the alternate and
- Xobsolete \-+ALTFROMWHOPT+).
- X.Tp
- X.I "\fB\-+DELIVEROPT+\fP recipient .\|.\|."
- XThis turns on explicit delivery mode, delivery will be to the local user
- X.IR recipient .
- XThis, of course, only is possible if procmail has root priviliges.
- XProcmail will setuid to the intended recipients and shall
- X.I only
- Xread the recipient's +PROCMAILRC+ file (if present, if not, delivery is like
- Xordinary mail).
- X.Sh ARGUMENTS
- XAny arguments containing an '=' are considered to be environment variable
- Xassignments, they will
- X.I all
- Xbe evaluated after the default values have been
- Xassigned and before the first rcfile is opened.
- X.PP
- XAny other arguments are presumed to be rcfile paths (absolute or relative to
- X$HOME); procmail will start with the first one it finds on the command line.
- XThe following ones will only be parsed if the preceding ones have a not
- Xmatching HOST-directive entry, or in case they should not exist.
- X.PP
- XIf no rcfiles are specified, it looks for
- X.BR $HOME/+PROCMAILRC+ .
- XIf not even that can be found, processing will continue according to
- Xthe default settings of the environment variables and the ones specified
- Xon the command line.
- X.Sh CAVEATS
- XAny default values that procmail has for some environment variables will
- X.B always
- Xoverride the ones that were already defined. If you really want to
- Xoverride the defaults, you either have to put them in the
- X.B rcfile
- Xor in the command line as arguments.
- X.Sh FILES
- X.Tp 2.3i
- X.B /etc/passwd
- Xto get the recipient's USER, HOME and SHELL variable defaults
- X.Tp
- X.B +SYSTEM_MBOX+
- Xsystem mailbox
- X.Tp
- X.B $HOME/+PROCMAILRC+
- Xdefault rcfile
- X.Tp
- X.B +SYSTEM_MBOX++DEFlockext+
- Xlockfile for the system mailbox (not used by procmail automatically, unless
- X$DEFAULT equals +SYSTEM_MBOX+ and procmail is delivering to $DEFAULT)
- X.Tp
- X.B +DEFsendmail+
- Xdefault mail forwarder
- X.Tp
- X.B +UNIQ_PREFIX+????`hostname`
- Xtemporary `unique' zero-length files created by procmail
- X.Sh "SEE ALSO"
- X.na
- X.BR procmailrc (5),
- X.BR procmailex (5),
- X.BR sh (1),
- X.BR csh (1),
- X.BR mail (1),
- X.BR binmail (1),
- X.BR uucp (1C),
- X.BR aliases (5),
- X.BR sendmail (8),
- X.BR egrep (1V),
- X.BR lockfile (1),
- X.BR formail (1)
- X.ad
- X.Sh DIAGNOSTICS
- X.Tp 2.3i
- XBad substitution of "x"
- XNot a valid environment variable name specified.
- X.Tp
- XCouldn't unlock "x"
- XLockfile was already gone, or write permission to the directory were the
- Xlockfile is has been denied.
- X.Tp
- XError while writing to "x"
- XNonexistent subdirectory, no write permission, pipe died or disk full.
- X.Tp
- XExceeded LINEBUF
- XBuffer overflow detected, LINEBUF was too small, memory might be corrupted.
- X.Tp
- XFailed forking "x"
- XProcess table is full (and NORESRETRY has been exhausted).
- X.Tp
- XFailed to execute "x"
- XProgram not in path, or not executable.
- X.Tp
- XForced unlock denied on "x"
- XNo write permission in the directory where
- X.B lockfile
- Xresides, or more than one procmail trying to force a lock at exactly the same
- Xtime.
- X.Tp
- XForcing lock on "x"
- XSpecified
- X.B lockfile
- Xis going to be removed by force because of a timeout (see also:
- X.BR LOCKTIMEOUT ).
- X.Tp
- XLock failure on "x"
- XCan only occur if you specify some real weird (and illegal) lockfilenames
- Xor if the
- X.B lockfile
- Xcould not be created because of insufficient permissions or noexistent
- Xsubdirectories.
- X.Tp
- XMissing name
- XThe \-+FROMWHOPT+ option needs an extra argument
- X.Tp
- XMissing recipient
- XYou specified the \-+DELIVEROPT+ option or called procmail under a different
- Xname, it expects one or more recipients as arguments
- X.Tp
- XOut of memory
- XThe system is out of swap space (and NORESRETY has been exhausted).
- X.Tp
- XProcessing continued
- XThe unrecognised options on the command line are ignored, proceeding as
- Xusual.
- X.Tp
- XProgram failure of "x"
- XProgram that was started by procmail didn't return EX_OK (=0).
- X.Tp
- XSkipped: "x"
- XCouldn't do anything with "x" in the rcfile (syntax error), ignoring it.
- X.Tp
- XTerminating prematurely whilst waiting for .\|.\|.
- XProcmail received a signal while it was waiting for .\|.\|.
- X.Tp
- XTimeout, terminating "x"
- XTimeout has occurred on program/filter "x".
- X.Tp
- XTruncating "x" and retrying lock
- X"x" does not seem to be a valid filename or the file is not empty.
- X.Tp
- XRescue of unfiltered data succeeded/failed
- XA filter returned unsuccessfully, procmail tried to get back the original text.
- X.Tp
- XUnexpected EOL
- XMissing closing quote, or trying to escape EOF.
- X.Sh "EXTENDED DIAGNOSTICS"
- X.Tp 2.3i
- XAssigning "x"
- XEnvironment variable assignment
- X.Tp
- XExecuting "x"
- XStarting program "x"
- X.Tp
- XHOST mismatched "x"
- XThis host was called "x", HOST contained something else
- X.Tp
- XLocking "x"
- XCreating lockfile "x"
- X.Tp
- XMatch on "x"
- XCondition matched
- X.Tp
- XNo match on "x"
- XCondition didn't match, recipe skipped
- X.Tp
- XOpening "x"
- XOpening file "x" for appending
- X.Tp
- XRcfile: "x"
- XRcfile changed to "x"
- X.Tp
- XUnlocking "x"
- XRemoving lockfile "x" again
- X.Sh WARNINGS
- XYou should create a shell script that uses
- X.BR lockfile (1)
- Xbefore invoking your mail shell on any mailbox file other than the system
- Xmailbox (unless of course, your mail shell uses the same lockfiles (local
- Xor global) you specified in your rcfile).
- X.PP
- XIn the unlikely event that you absolutely need to kill procmail before it has
- Xfinished, first try and use the regular kill command (i.e.
- X.I not
- Xkill -9, see the subsection
- X.I Signals
- Xfor suggestions), otherwise some
- X.I lockfiles
- Xmight not get removed.
- X.PP
- XBeware when using the
- X.B \-+TEMPFAILOPT+
- Xoption, if procmail repeatedly is unable to deliver the mail (e.g. due to
- Xan incorrect rcfile), the system mailqueue could fill up. This could
- Xaggravate both the local postmaster and other users.
- X.Sh BUGS
- XAfter a lockfile is removed by force, a suspension of $SUSPEND seconds
- Xis taken into account, in order to prevent the inadvertent immediate removal
- Xof any newly created lockfile by another program.
- X.PP
- XProcmail uses the regular TERMINATE signal to terminate any runaway filter,
- Xbut it does not check if the filter responds to that signal and it only sends
- Xit to the filter itself, not to any of the filter's children.
- X.Sh MISCELLANEOUS
- XAny lines in the body of the message that look like postmarks are prepended
- Xwith `+ESCAP+' (disarms bogus mailheaders). The regular expression that is
- Xused to search for these postmarks is:
- X.Rs
- X"+FROM_EXPR+"
- X.Re
- X.PP
- XIf the destination name used in explicit delivery mode is not in /etc/passwd,
- Xprocmail will proceed as if explicit delivery mode was not in effect.
- XIf not in explicit delivery mode and
- Xshould the uid procmail is running under, have no corresponding /etc/passwd
- Xentry, then HOME will default to +Tmp+, USER will default to #uid.
- X.PP
- XWhen in explicit delivery mode, procmail will generate a leading `+FROM+'
- Xline if none is present. If one is already present+TRUSTED_IDS+ procmail will
- Xleave it intact.
- X.PP
- XFor security reasons procmail will only use an rcfile if it is owned by the
- Xrecipient or if the recipient's home directory is not world writeable.
- X.PP
- XIf +SYSTEM_MBOX+ is a bogus mailbox (i.e. does not belong to the recipient,
- Xis unwritable, is a symbolic link or is a hard link), procmail will upon
- Xstartup try to rename it into a file starting with `+BOGUSprefix+' and
- Xending in an inode-sequence-code. If this turns out to be impossible,
- X.B ORGMAIL
- Xwill have
- X.I no
- Xinitial value.
- X.PP
- XWhen delivering to directories (or to MH folders) you
- X.B don't
- Xneed to use lockfiles to prevent several concurrently running procmail
- Xprograms from messing up.
- X.PP
- XDelivering to MH folders is slightly more time consuming than delivering
- Xto normal directories or mailboxes, because procmail has to search for
- Xthe first available number (instead of having the filename immediately
- Xavailable).
- X.PP
- XOn general failure procmail will return EX_CANTCREAT, unless option
- X.B \-+TEMPFAILOPT+
- Xis specified, in which case it will return EX_TEMPFAIL.
- X.PP
- XTo make `egrepping' of headers more consistent, procmail concatenates all
- Xcontinued header fields.
- X.PP
- XIf procmail is called under a different name than `procmail' (i.e. if it
- Xis linked to another name and invoked as such), it comes up in explicit
- Xdelivery mode, and expects the recipients' names as command line arguments
- X(as if \-+DELIVEROPT+ had been specified).
- X.PP
- XProcmail performs the locking in an NFS-secure way.
- X.br
- X.ne 11
- X.Sh NOTES
- XIf procmail is
- X.I not
- Xinstalled globally as the default mail delivery agent (ask your system
- Xadministrator), you have to make sure it is invoked when your mail arrives.
- XIn this case your $HOME/+DOT_FORWARD+ (beware, it
- X.B has
- Xto be world readable) file should contain (include the single and double
- Xquotes,
- X.I must
- Xbe an
- X.I absolute
- Xpath):
- X.PP
- X.na
- X.nf
- X+FW_content+
- X.fi
- X.ad
- X.br
- X.ne 14
- X.Ss "A sample small +PROCMAILRC+:"
- X.na
- X.nf
- XPATH=/bin:/usr/bin:/usr/local/bin
- XMAILDIR=$HOME/Mail #you'd better make sure it exists
- XDEFAULT=$MAILDIR/mbox
- XLOGFILE=$MAILDIR/from
- X::
- X^From.*berg
- Xfrom_me
- X:
- X^Subject:.*Flame
- X/dev/null
- X.fi
- X.ad
- X.Sh AUTHOR
- XStephen R. van den Berg at RWTH-Aachen, Germany
- X.Rs
- Xberg@pool.informatik.rwth-aachen.de
- Xberg@physik.tu-muenchen.de
- X.Re
- END_OF_FILE
- if test 11722 -ne `wc -c <'procmail/man/procmail.man'`; then
- echo shar: \"'procmail/man/procmail.man'\" unpacked with wrong size!
- fi
- # end of 'procmail/man/procmail.man'
- fi
- if test -f 'procmail/man/procmailrc.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail/man/procmailrc.man'\"
- else
- echo shar: Extracting \"'procmail/man/procmailrc.man'\" \(14618 characters\)
- sed "s/^X//" >'procmail/man/procmailrc.man' <<'END_OF_FILE'
- X.de Id
- X.ds Rv \\$3
- X.ds Dt \\$4
- X..
- X.Id $Id: procmailrc.man,v 2.5 1992/04/29 15:55:09 berg Rel $
- X.de Sh
- X.br
- X.ne 11
- X.SH "\\$1"
- X..
- X.de Ss
- X.br
- X.ne 10
- X.SS "\\$1"
- X..
- X.de Tp
- X.br
- X.ne 9
- X.TP \\$1
- X..
- X.de Rs
- X.na
- X.nf
- X.RS
- X..
- X.de Re
- X.RE
- X.fi
- X.ad
- X..
- X.TH PROCMAILRC 5 \*(Dt BuGless
- X.SH NAME
- X.na
- Xprocmailrc \- procmail rcfile
- X.SH SYNOPSIS
- X.B $HOME/+PROCMAILRC+
- X.ad
- X.Sh DESCRIPTION
- XFor a quick start, see
- X.B NOTES
- Xat the end of the
- X.BR procmail (1)
- Xman page.
- X.PP
- XThe rcfile can contain a mixture of environment variable assignments (some
- Xof which have special meanings to procmail), and recipes. In their most
- Xsimple appearance, the recipes are simply one line regular expressions
- Xthat are searched for in the header of the arriving mail, the first recipe
- Xthat matches is used to determine where the mail has to go (usually a file).
- X.PP
- XThis enables you to presort your mail extremely straightforward into several
- Xmailfolders. Bear in mind though that the mail can arrive concurrently in
- Xthese mailfolders, to make sure this does not result in a mess, proper use
- Xof lockfiles is highly recommended.
- X.PP
- XThe environment variable
- X.B assignments
- Xand
- X.B recipes
- Xcan be freely intermixed in the rcfile. If any environment variable has
- Xa special meaning to procmail, it will be used appropiately the moment
- Xit is parsed. (i.e. you can change the current directory whenever you
- Xwant by specifying a new
- X.BR MAILDIR ,
- Xswitch lockfiles by specifying a new
- X.BR LOCKFILE ,
- Xchange the umask at any time, etc., the possibilities are endless :-).
- X.PP
- XThe assignments and substitutions of these environment variables are handled
- Xexactly like in
- X.BR sh (1)
- X(that includes all possible quotes and escapes),
- Xwith the added bonus that blanks around the '=' sign are ignored and that,
- Xif an environment variable appears without a trailing '=', it will be
- Xremoved from the environment.
- X.PP
- X.Ss Comments
- XA word beginning with # and all the following characters up to a NEWLINE
- Xare ignored.
- X.Ss Recipes
- X.PP
- XA line starting with ':' marks the beginning of a recipe. It has the
- Xfollowing format:
- X.PP
- X.Rs
- X: [\fInumber\fP] [\fIflags\fP] [ : [\fIlocallockfile\fP] ]
- X<zero or more conditions (one per line)>
- X<exactly one action line>
- X.Re
- X.PP
- XThe
- X.I number
- Xis optional (defaults to 1) and specifies the number of conditions that
- Xfollow the first line of the recipe. Conditions are complete lines that are
- Xpassed on to the internal egrep
- X.BR literally ,
- Xexcept for leading blanks.
- XIf a condition starts with an '!', the condition is inverted. If you really
- Xwant the condition to start with an '!', precede the '!' by a '\\'.
- XThese conditions are
- X.B completely
- Xcompatible to the normal
- X.BR egrep (1)
- Xregular expressions.
- X.PP
- XA special case condition is one starting with either '<' or '>', this
- Xcondition is true only if the total length of the mail is shorter,
- Xrespectively longer than the specified (in decimal) number of bytes.
- X.PP
- XAnother special case condition is one starting with a '$'. This condition
- Xwill be evaluated according to
- X.BR sh (1)
- Xsubtitution rules inside double quotes, i.e. environment variable
- Xsubstitutions take place here, prior to being interpreted as a condition.
- X.PP
- XConditions are anded; if
- X.I number
- Xis zero, then the condition is always true and no conditions are expected
- Xnext.
- X.PP
- X.I Flags
- Xcan be any of the following:
- X.Tp 0.5i
- X.B +HEAD_GREP+
- XEgrep the header (default).
- X.Tp
- X.B +BODY_GREP+
- XEgrep the body.
- X.Tp
- X.B +DISTINGUISH_CASE+
- XTell the internal egrep to distinguish between upper and lower case (defaults
- Xto ignoring case).
- X.Tp
- X.B +ALSO_NEXT_RECIPE+
- XThis recipe will depend on the last preceding recipe without the
- X`+ALSO_NEXT_RECIPE+' or `+ALSO_N_IF_SUCC+' flag. This allows you to chain
- Xactions that depend on a common condition. The number of conditions that
- Xare expected to follow default to none.
- X.Tp
- X.B +ALSO_N_IF_SUCC+
- XHas the same meaning as the `+ALSO_NEXT_RECIPE+' flag, but will depend on the
- X.I successful
- Xcompletion of the immediately preceding recipe as well.
- X.Tp
- X.B +PASS_HEAD+
- XFeed the header to the pipe (default).
- X.Tp
- X.B +PASS_BODY+
- XFeed the body to the pipe (default).
- X.Tp
- X.B +FILTER+
- XConsider the pipe as a filter (ignored if a file).
- X.Tp
- X.B +CONTINUE+
- XContinue processing rcfile even if this recipe matches (not needed when 'f'
- Xspecified).
- X.Tp
- X.B +WAIT_EXIT+
- XWait for the filter or program to finish and check its exitcode (normally
- Xignored); if the filter is unsuccessful, then the text will
- Xnot have been filtered. This flag is also recommended if you specified any
- X.I locallockfile
- Xon this recipe.
- X.Tp
- X.B +WAIT_EXIT_QUIET+
- XHas the same meaning as the `+ALSO_NEXT_RECIPE+' flag, but will suppress any
- X`Program faillure' messages.
- X.Tp
- X.B +IGNORE_WRITERR+
- XIgnore any write errors on this recipe (i.e. usually due to an early closed
- Xpipe).
- X.Ss "Local lockfile"
- X.PP
- XIf you put a second ':' on the first recipe line, then procmail will use a
- X.I locallockfile
- X(for this recipe only). You can optionally specify the locallockfile
- Xto use; if you don't however, procmail will use the destination filename
- X(or the filename following the first '>>') and will append $LOCKEXT to it.
- X.Ss "Recipe action line"
- X.PP
- XThe action line can start with the following characters:
- X.Tp
- X.B !
- XForwards to all the specified mail addresses.
- X.Tp
- X.B |
- XStarts the specified program, possibly in $SHELL if any
- Xof the characters $SHELLMETAS are found.
- X.PP
- XAnything else will be taken as a mailbox name (either a filename or a
- Xdirectory, absolute or relative to the current directory (see MAILDIR)).
- XIf it is a filename (or nonexistent), the mail will be appended to it.
- X.PP
- XIf it is a directory, the mail will be delivered to a newly created, guaranteed
- Xto be unique file named $MSGPREFIX* in the specified directory. If the
- Xdirectory name ends in "/.", then this directory is presumed to be an MH
- Xfolder; i.e. procmail will use the lowest number it finds available.
- X.Ss "Environment variable defaults"
- X.Tp 2.2i
- X.B "USER, HOME and SHELL"
- XYour (the recipient's) defaults
- X.Tp
- X.B SHELLMETAS
- X\&+DEFshellmetas+
- X.Tp
- X.B SHELLFLAGS
- X\&+DEFshellflags+
- X.Tp
- X.BR ORGMAIL
- X\&+SYSTEM_MBOX+
- X.Tp
- X.B MAILDIR
- X\&+DEFmaildir+
- X.Tp
- X.B DEFAULT
- X\&+DEFdefault+
- X.Tp
- X.B MSGPREFIX
- X\&+DEFmsgprefix+
- X.Tp
- X.B SENDMAIL
- X\&+DEFsendmail+
- X.Tp
- X.B LOCKEXT
- X\&+DEFlockext+
- X.Tp
- X.B LOCKFILE
- X\&+DEFdefaultlock+
- X.br
- X(after procmail closed the last rcfile)+PRESTENV+
- X.Ss Environment
- X.PP
- XBefore you get lost in the multitude of environment variables, keep in mind
- Xthat all of them have reasonable defaults.
- X.Tp 1.2i
- X.B MAILDIR
- XCurrent directory while procmail is executing (that means that all paths
- Xare relative to $MAILDIR).
- X.Tp
- X.B DEFAULT
- XDefault
- X.B mailbox
- Xfile (if not told otherwise, procmail will dump mail in this mailbox).
- XProcmail will automatically use LOCKFILE=$DEFAULT$LOCKEXT prior to writing
- Xto this mailbox.
- X.Tp
- X.B MSGPREFIX
- XFilename prefix that is used when delivering to a directory (not used when
- Xdelivering to an MH directory).
- X.Tp
- X.B LOGFILE
- XAll incoming messages will be logged here with their `+FROM+' and `Subject:'
- Xlines in the header, and an additional line specifying what folder it
- Xfinally went to and how long (in bytes) the message was. This file will
- Xalso contain any error or diagnostic messages from procmail
- X(normally none :-) or any other programs started by procmail. If this file
- Xis not specified it defaults to
- X.BR +console+ .
- XYou can turn on
- X.I extended diagnostics
- Xby prepending a `+DEBUGPREFIX+' to the desired pathname.
- X.Tp
- X.B LOG
- XAnything assigned to this variable will be echoed in $LOGFILE.
- X.Tp
- X.B ORGMAIL
- XUsually the system mailbox (\fBOR\fPi\fBG\fPinal \fBMAIL\fPbox). If, for
- Xsome obscure reason (like `\fBfilesystem full\fP') the mail could not be
- Xdelivered, then this mailbox will be the last resort. If procmail
- Xfails to save the mail in here (deep, deep trouble :-), then the mail
- Xwill bounce back to the sender.
- X.Tp
- X.B LOCKFILE
- XGlobal semaphore file. If this file already exists, procmail
- Xwill wait until it has gone before proceeding, and will create it itself
- X(cleaning it up when ready, of course). If more than one
- X.I lockfile
- Xare specified, then the previous one will be removed before trying to create
- Xthe new one. The use of a global lockfile is discouraged, use locallockfiles
- X(on a per recipe basis) instead.
- X.Tp
- X.B LOCKEXT
- XDefault extension that is appended to a destination file to determine
- Xwhat local
- X.I lockfile
- Xto use (only if turned on, on a per-recipe basis).
- X.Tp
- X.B LOCKSLEEP
- XNumber of seconds procmail will sleep before retrying on a
- X.I lockfile
- X(if it already existed); if not specified, it defaults to +DEFlocksleep+
- Xseconds.
- X.Tp
- X.B LOCKTIMEOUT
- XNumber of seconds that have to have passed since a
- X.I lockfile
- Xwas last modified/created before procmail decides that this must be an
- Xerroneously leftover lockfile that can be removed by force now. If zero,
- Xthen no timeout will be used and procmail will wait forever until the
- Xlockfile is removed; if not specified, it defaults to +DEFlocktimeout+ seconds.
- XThis variable is useful to prevent indefinite hangups of
- X.BR sendmail /procmail.
- XProcmail is immune to clock skews.
- X.Tp
- X.B TIMEOUT
- XNumber of seconds that have to have passed before procmail decides that
- Xsome child it started must be hanging. The offending program will receive
- Xa TERMINATE signal from procmail, and processing of the rcfile will continue.
- XIf zero, then no timeout will be used and procmail will wait forever until the
- Xchild has terminated; if not specified, it defaults to +DEFtimeout+ seconds.
- X.Tp
- X.B HOST
- XIf this is not the
- X.I hostname
- Xof the machine, processing of the current
- X.I rcfile
- Xwill immediately cease. If other rcfiles were specified on the
- Xcommand line, processing will continue with the next one. If all rcfiles
- Xare exhausted, the program will terminate, but will not generate an error
- X(i.e. to the mailer it will seem that the mail has been delivered). Only the
- Xfirst +HOSTNAMElen+ characters of the HOST are significant.
- X.Tp
- X.B UMASK
- XThe name says it all (if it doesn't, then forget about this one :-). It
- Xis taken as an
- X.B octal
- Xnumber. If not specified, it defaults to +INIT_UMASK+.
- X.Tp
- X.B SHELLMETAS
- XIf any of the characters in SHELLMETAS appears in the line specifying
- Xa filter or program, the line will be fed to $SHELL
- Xinstead of being executed directly.
- X.Tp
- X.B SHELLFLAGS
- XAny invocation of $SHELL will be like:
- X.br
- X"$SHELL" "$SHELLFLAGS" "$*";
- X.Tp
- X.B SENDMAIL
- XIf you're not using the
- X.I forwarding
- Xfacility don't worry about this one. It specifies the program being
- Xcalled to forward any mail.
- X.br
- XIt gets invoked as: "$SENDMAIL" "$@";
- X.Tp
- X.B NORESRETRY
- XNumber of retries that are to be made if any `\fBprocess table full\fP',
- X`\fBfile table full\fP', `\fBout of memory\fP' or
- X`\fBout of swap space\fP' error should occur. If this number is negative,
- Xthen procmail will retry indefinitely; if not specified, it defaults to two
- Xtimes. The retries occur with a $SUSPEND second interval. The idea behind
- Xthis is, that if the
- X.I swap
- X.I space
- Xhas been exhausted or the
- X.I process
- X.I table
- Xis full, usually several other programs will either detect this
- Xand abort or crash 8-), and thereby freeing valuable
- X.I resources
- Xfor procmail.
- X.Tp
- X.B SUSPEND
- XNumber of seconds that procmail will pause if it has to wait for something
- Xthat is currently unavailable (memory, fork, etc.); if not specified, it will
- Xdefault to +DEFsuspend+ seconds. See also:
- X.BR LOCKSLEEP .
- X.Tp
- X.B LINEBUF
- XLength of the internal line buffers, cannot be set smaller than +MINlinebuf+.
- XAll lines read from the rcfile
- X.RI ( not
- Xthe mail itself, which can have arbitrary line lengths, or could be a binary
- Xfile for that matter) should not exceed $LINEBUF characters before and after
- Xexpansion. If not specified, it defaults to +DEFlinebuf+.
- X.Tp
- X.B DELIVERED
- XIf set (to a dummy value) procmail will pretend (to the mail agent) the mail
- Xhas been delivered. If mail cannot be delivered after meeting this
- Xassignment, the mail will be lost (i.e. it will not bounce).
- X.Sh EXAMPLES
- XLook in the
- X.BR procmailex (5)
- Xman page.
- X.Sh CAVEATS
- XIf you don't explicitly tell procmail to wait (recipe flag `+WAIT_EXIT+' or
- X`+WAIT_EXIT_QUIET+') for a program to finish, it won't wait and will terminate
- Xearly (not knowing if the program returns success). That also means that any
- Xlocallockfile on this recipe might get removed
- X.I before
- Xthe program has terminated.
- X.PP
- XContinued lines in a recipe that are to be executed are concatenated
- X.I before
- Xbeing parsed, hence
- X.I any
- Xbackslash-newline combinations in them are removed regardless.
- X.PP
- XDon't put comments on the condition lines (the regular expressions) in a recipe,
- Xthese lines are fed to the internal egrep
- X.IR literally .
- X(Except for any
- X.I leading
- Xwhitespace, `!' or `\\', it will be stripped.
- XPrecede it by a `\\' if you want it to be taken literally too.)
- X.PP
- XWatch out for deadlocks when doing unhealthy things like forwarding mail
- Xto your own account. Deadlocks can be broken by proper use of
- X.BR LOCKTIMEOUT .
- X.PP
- XAny default values that procmail has for some environment variables will
- X.B always
- Xoverride the ones that were already defined. If you really want to
- Xoverride the defaults, you either have to put them in the
- X.B rcfile
- Xor on the command line as arguments.
- X.Sh "SEE ALSO"
- X.na
- X.BR procmail (1),
- X.BR procmailex (5),
- X.BR sh (1),
- X.BR csh (1),
- X.BR mail (1),
- X.BR binmail (1),
- X.BR uucp (1C),
- X.BR aliases (5),
- X.BR sendmail (8),
- X.BR egrep (1V),
- X.BR lockfile (1),
- X.BR formail (1)
- X.ad
- X.Sh BUGS
- XThe only substitutions of environment variables that can be handled by
- Xprocmail itself are of the type $name, ${name}, $$ and $\-; whereas $\- will
- Xbe substituted by the name of the last folder delivered to.+UPPERCASE_USERNAMES+
- X.PP
- XA line buffer of length $LINEBUF is used when processing the
- X.IR rcfile ,
- Xany expansions
- X.B have
- Xto fit within this limit; if they don't, behaviour is undefined.
- X.PP
- XIf the global lockfile has a
- X.I relative
- Xpath, and the current directory
- Xis not the same as when the global lockfile was created, then the global
- Xlockfile will not be removed if procmail exits at that point (remedy:
- Xuse
- X.I absolute
- Xpaths to specify global lockfiles).
- X.Sh MISCELLANEOUS
- XWhitespace is ignored in the rcfile, except on the
- Xlines that are fed to the internal egrep where only leading whitespace is
- Xignored; i.e. you can indent everything.
- X.PP
- XIf the regular expression starts with `\fB+TOkey+\fP' it will be substituted by
- X`\fB+TOsubstitute+\fP', which should catch all destination
- Xspecifications.
- X.Sh NOTES
- XFor
- X.I really
- Xcomplicated processing you can even consider calling
- X.B procmail
- Xrecursively.
- X.Sh AUTHOR
- XStephen R. van den Berg at RWTH-Aachen, Germany
- X.Rs
- Xberg@pool.informatik.rwth-aachen.de
- Xberg@physik.tu-muenchen.de
- X.Re
- END_OF_FILE
- if test 14618 -ne `wc -c <'procmail/man/procmailrc.man'`; then
- echo shar: \"'procmail/man/procmailrc.man'\" unpacked with wrong size!
- fi
- # end of 'procmail/man/procmailrc.man'
- fi
- if test -f 'procmail/retint.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail/retint.c'\"
- else
- echo shar: Extracting \"'procmail/retint.c'\" \(13144 characters\)
- sed "s/^X//" >'procmail/retint.c' <<'END_OF_FILE'
- X/************************************************************************
- X * Collection of routines that return an int (sort of anyway :-) *
- 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: retint.c,v 2.26 1992/04/09 16:16:41 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((char*)(sgetcp=buf2),name),"="),contents);
- X readparse(buf,sgetc,2);sputenv(buf);
- X}
- X
- Xchar*lastexec,*backblock;
- Xlong backlen; /* length of backblock, filter recovery block */
- Xpid_t pidfilt;
- 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); /* main pipes setup */
- X if(!(pidchild=sfork())) /* 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=sfork())) /* create the filter */
- X { rclose(PWRO);rclose(PWRB);rdup(PWRI);rclose(PWRI);getstdin(PRDO);
- X callnewprog(line);
- X }
- 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 { if(!(pwait&2)) /* do we put it on report? */
- X progerr(line);
- X stermchild();
- X }
- X rclose(PWRB);exit(EX_OK); /* allow parent to proceed */
- X }
- X rclose(PWRI);rclose(PWRB);getstdin(PRDI);
- X if(forkerr(pidchild,procmailn))
- X return 1;
- X return 0; /* we stay behind to read back the filtered text */
- X}
- X
- Xwaitfor(pid)const pid_t pid; /* wait for a specific process */
- X{ int i;pid_t j;
- X while(pid!=(j=wait(&i))||WIFSTOPPED(i))
- X if(-1==j)
- X return -1;
- X return WIFEXITED(i)?WEXITSTATUS(i):-1;
- X}
- X
- Xgetstdin(pip)const int pip;
- X{ rclose(STDIN);rdup(pip);rclose(pip);
- X}
- X
- Xcallnewprog(newname)const char*const newname;
- X{ if(sh) /* should we start a shell? */
- X { const char*newargv[4];
- X yell(executing,newname);newargv[3]=0;newargv[2]=newname;
- X newargv[1]=tgetenv(shellflags);*newargv=tgetenv(shell);shexec(newargv);
- X }
- 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 }
- X do /* show chopped up command line */
- X { if(verbose)
- X { log(",");
- Xno_1st_comma:
- X log(p);
- X }
- X while(*p++);
- X }
- 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 }
- X while(*p!=TMNATE);
- X newargv[argc]=0;shexec(newargv);
- X }
- X}
- X
- Xwriteerr(line)const char*const line;
- X{ log("Error while writing to");logqnl(line);
- X}
- 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 }
- X return 0;
- X}
- X
- Xprogerr(line)const char*const line;
- X{ log("Program failure of");logqnl(line);
- X}
- X
- Xopena(a)const char*const a;
- X{ lastfolder=cstr(lastfolder,a);yell("Opening",a);
- X#ifdef O_CREAT
- X return ropen(a,O_WRONLY|O_APPEND|O_CREAT,NORMperm);
- X#else
- X {int fd;
- X return(fd=ropen(a,O_WRONLY,0))<0?creat(a,NORMperm):fd;
- X }
- X#endif
- X}
- X
- Xyell(a,b)const char*const a,*const b; /* log if -d option set */
- X{ if(verbose)
- X log(a),logqnl(b);
- X}
- X
- Xunlock(lockp)char**const lockp;
- X{ lcking|=lck_LOCKFILE;
- X if(*lockp)
- X { yell("Unlocking",*lockp);
- X if(unlink(*lockp))
- X log("Couldn't unlock"),logqnl(*lockp);
- X if(!nextexit) /* if not inside a signal handler */
- X free(*lockp);
- X *lockp=0;
- X }
- X lcking&=~lck_LOCKFILE;
- X if(nextexit==1) /* make sure we are not inside terminate already */
- X log(newline),terminate();
- X}
- X
- Xnomemerr() /* set nextexit to prevent log from using malloc() */
- X{ nextexit=2;log("Out of memory\n");
- X if(buf2)
- X { buf[linebuf-1]=buf2[linebuf-1]='\0';log("buffer 0:");logqnl(buf);
- X log("buffer 1:");logqnl(buf2);
- X }
- X if(retval!=EX_TEMPFAIL)
- X retval=EX_OSERR;
- X terminate();
- X}
- X
- Xlogqnl(a)const char*const a;
- X{ log(oquote);log(a);log(cquote);
- X}
- X
- Xnextrcfile() /* next rcfile specified on the command line */
- X{ const char*p;
- X while(p= *gargv)
- X { gargv++;
- X if(!strchr(p,'='))
- X { rcfile=p;return 1;
- X }
- X }
- X return 0;
- X}
- X
- Xrclose(fd)const int fd; /* a SysV secure close (signal immune) */
- X{ int i;
- X while((i=close(fd))&&errno==EINTR);
- X return i;
- X}
- X
- Xrwrite(fd,a,len)const int fd,len;void*const a; /* a SysV secure write */
- X{ int i;
- X while(0>(i=write(fd,a,(size_t)len))&&errno==EINTR);
- X return i;
- X}
- X
- Xrread(fd,a,len)const int fd,len;void*const a; /* a SysV secure read */
- X{ int i;
- X while(0>(i=read(fd,a,(size_t)len))&&errno==EINTR);
- X return i;
- X}
- X
- Xropen(name,mode,mask)const char*const name;const int mode;const mode_t mask;
- X{ int i,r; /* a SysV secure open */
- X for(r=noresretry,lcking|=lck_FILDES;0>(i=open(name,mode,mask));)
- X if(errno!=EINTR&&!((errno==EMFILE||errno==ENFILE)&&(r<0||r--)))
- X break; /* survives a temporary "file table full" condition */
- X lcking&=~lck_FILDES;return i;
- X}
- X
- Xrdup(p)const int p;
- X{ int i,r; /* catch "file table full" */
- X for(r=noresretry,lcking|=lck_FILDES;0>(i=dup(p));)
- X if(!((errno==EMFILE||errno==ENFILE)&&(r<0||r--)))
- X break;
- X lcking&=~lck_FILDES;return i;
- X}
- X
- Xrpipe(fd)int fd[2];
- X{ int i,r; /* catch "file table full" */
- X for(r=noresretry,lcking|=lck_FILDES;0>(i=pipe(fd));)
- X if(!((errno==EMFILE||errno==ENFILE)&&(r<0||r--)))
- X { *fd=fd[1]= -1;break;
- X }
- X lcking&=~lck_FILDES;return i;
- X}
- X
- Xlockit(name,lockp)char*name;const char**const lockp;
- X{ int i,permanent=2,triedforce=0;struct stat stbuf;time_t t;
- X if(*lockp)
- X { if(!strcmp(name,*lockp)) /* compare the previous lockfile to this one */
- X return; /* they're equal, save yourself some effort */
- X unlock(lockp); /* unlock any previous lockfile FIRST */
- X } /* to prevent deadlocks (I hate deadlocks) */
- X if(!*name)
- X return;
- X name=tstrdup(name); /* allocate now, so we won't hang on memory *and* lock */
- X for(lcking|=lck_LOCKFILE;;)
- X { yell("Locking",name); /* in order to cater for clock skew: */
- X if(!NFSxopen(name,LOCKperm,&t)) /* get time t from filesystem */
- X { *lockp=name;break; /* lock acquired, hurray! */
- X }
- X switch(errno)
- X { case EEXIST: /* check if it's time for a lock override */
- X if(!lstat(name,&stbuf)&&stbuf.st_size<=MAX_LOCK_SIZE&&locktimeout
- X &&!lstat(name,&stbuf)&&locktimeout<t-stbuf.st_mtime)
- X /*
- X * stat() till unlink() should be atomic, but can't guarantee that
- X */
- X { if(triedforce) /* already tried, not trying */
- X goto faillock; /* again */
- X if(S_ISDIR(stbuf.st_mode)||unlink(name))
- X triedforce=1,log("Forced unlock denied on"),logqnl(name);
- X else
- X { log("Forcing lock on");logqnl(name);suspend();goto ce;
- X }
- X }
- X else
- X triedforce=0; /* legitimate iteration, clear flag */
- X break;
- X default: /* maybe filename too long, shorten and retry */
- X if(0<(i=strlen(name)-1)&&!strchr(dirsep,name[i-1]))
- X { log("Truncating");logqnl(name);log(" and retrying lock\n");
- X name[i]='\0';continue;
- X }
- Xfaillock: log("Lock failure on");logqnl(name);goto term;
- X case ENOENT:case ENOTDIR:case EIO:case EACCES:
- X if(!--permanent)
- X goto faillock;
- X case ENOSPC:;
- X#ifdef EDQUOT
- X case EDQUOT:;
- X#endif
- X }
- X sleep((unsigned)locksleep);
- Xce: if(nextexit)
- Xterm: { free(name);break; /* drop the preallocated buffer */
- X }
- X }
- X lcking&=~lck_LOCKFILE;
- X if(nextexit)
- X { log(whilstwfor);log("lockfile");logqnl(name);terminate();
- X }
- X}
- 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}
- X
- Xsterminate()
- X{ static const char*const msg[]={"memory","fork", /* crosscheck with */
- X "a file descriptor","a kernel lock"}; /* lck_ defs in procmail.h */
- X ignoreterm();
- X if(pidchild>0) /* don't kill what is not ours, we might be root */
- X kill(pidchild,SIGTERM);
- X if(!nextexit)
- X { nextexit=1;log("Terminating prematurely");
- X if(!(lcking&lck_LOCKFILE))
- X { register unsigned i,j;
- X if(i=(lcking&~(lck_ALLOCLIB|lck_LOCKFILE))>>1)
- X { log(whilstwfor);
- X for(j=0;(i>>=1)&1;++j);
- X log(msg[j]);
- X }
- X log(newline);terminate();
- X }
- X }
- X}
- X
- Xterminate()
- X{ ignoreterm();
- X if(retvl2!=EX_OK)
- X fakedelivery=0,retval=retvl2;
- X if(getpid()==thepid)
- X { if(retval!=EX_OK)
- X { lastfolder=fakedelivery?"**Lost**": /* don't free() here */
- X retval==EX_TEMPFAIL?"**Requeued**":"**Bounced**";
- X }
- X logabstract();nextexit=2;unlock(&loclock);unlock(&globlock);fdunlock();
- X }
- X exit(fakedelivery==2?EX_OK:retval);
- X}
- X
- Xignoreterm()
- X{ signal(SIGTERM,SIG_IGN);signal(SIGHUP,SIG_IGN);signal(SIGINT,SIG_IGN);
- X signal(SIGQUIT,SIG_IGN);
- X}
- X
- Xsuspend()
- X{ long t;
- X sleep((unsigned)suspendv);
- X if(alrmtime)
- X if((t=alrmtime-time((time_t*)0))<=1) /* if less than 1s timeout */
- X ftimeout(); /* activate it by hand now */
- X else /* set it manually again, to avoid problems with */
- X alarm((unsigned)t); /* badly implemented sleep library functions */
- X}
- X
- Xinittmout(progname)const char*const progname;
- X{ lastexec=cstr(lastexec,progname);
- X alrmtime=timeoutv?time((time_t*)0)+(unsigned)timeoutv:0;
- X alarm((unsigned)timeoutv);
- X}
- X
- Xskipspace()
- X{ while(testb(' ')||testb('\t'));
- X}
- X
- Xsgetc() /* a fake fgetc for a string */
- X{ return *sgetcp?*(uchar*)sgetcp++:EOF;
- X}
- X
- Xskipped(x)const char*const x;
- X{ log("Skipped");logqnl(x);
- X}
- X
- Xconcatenate(old)char*const old;
- X{ register char*p=old;
- X while(*p!=TMNATE) /* concatenate all other arguments */
- X { while(*p++);
- X p[-1]=' ';
- X }
- X *p=p[-1]='\0';return*old;
- X}
- X
- Xdetab(p)char*p;
- X{ while(p=strchr(p,'\t'))
- X *p=' '; /* take out all tabs */
- 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,0);
- X}
- X
- Xgetbl(p)char*p; /* my gets */
- X{ int i;char*q;
- 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 }
- X *p++=i;
- X }
- X}
- X
- Xgetb() /* my fgetc */
- X{ if(ungetb>=0) /* anything pushed back? */
- X { int i;
- X i=ungetb;ungetb= -1;return i;
- X }
- X if(rcbufp==rcbufend)
- X rcbufend=rcbuf+rread(rc,rcbufp=rcbuf,STDBUF); /* refill */
- X return rcbufp<rcbufend?*rcbufp++:EOF;
- X}
- X
- Xtestb(x)const int x; /* fgetc that only succeeds if it matches */
- X{ int i;
- X if((i=getb())==x)
- X return 1;
- X ungetb=i;return 0;
- X}
- X
- Xalphanum(c)const int c;
- X{ return c>='0'&&c<='9'||c>='a'&&c<='z'||c>='A'&&c<='Z'||c=='_';
- X}
- X /* open file or new file in directory */
- Xdeliver(boxname)char*const boxname;
- X{ struct stat stbuf;
- X strcpy(buf,boxname); /* boxname can be found back in buf */
- X return stat(buf,&stbuf)||!S_ISDIR(stbuf.st_mode)?
- X (tofolder=1,opena(buf)):dirmail();
- X}
- X
- X#ifdef KERNEL_LOCKS
- Xstatic oldfdlock; /* the fd we locked last */
- X#ifdef F_SETLKW
- Xstatic struct flock flck; /* why can't it be a local variable? */
- X
- Xfdlock(fd) /* the POSIX-fcntl() lock */
- X{ flck.l_type=F_WRLCK;flck.l_whence=SEEK_SET;flck.l_len=0;
- X flck.l_start=tell(fd);lcking|=lck_KERNELL;
- X fd=fcntl(oldfdlock=fd,F_SETLKW,&flck);lcking&=~lck_KERNELL;return fd;
- X}
- X
- Xfdunlock()
- X{ flck.l_type=F_UNLCK;return fcntl(oldfdlock,F_SETLK,&flck);
- X}
- X#else /* F_SETLKW */
- X#ifdef F_LOCK
- Xstatic long oldlockoffset;
- X
- Xfdlock(fd) /* the SysV-lockf() */
- X{ oldlockoffset=tell(fd);lcking|=lck_KERNELL;fd=lockf(oldfdlock=fd,F_LOCK,0L);
- X lcking&=~lck_KERNELL;return fd;
- X}
- X
- Xfdunlock()
- X{ lseek(oldfdlock,oldlockoffset,SEEK_SET);return lockf(oldfdlock,F_ULOCK,0L);
- X}
- X#else /* F_LOCK */
- X#ifdef LOCK_EX
- Xfdlock(fd) /* the BSD-flock() */
- X{ lcking|=lck_KERNELL;fd=flock(oldfdlock=fd,LOCK_EX);lcking&=~lck_KERNELL;
- X return fd;
- X}
- X
- Xfdunlock()
- X{ return flock(oldfdlock,LOCK_UN);
- X}
- X#endif /* LOCK_EX */
- X#endif /* F_LOCK */
- X#endif /* F_SETLKW */
- X#endif /* KERNEL_LOCKS */
- X /* an NFS secure exclusive file open */
- XNFSxopen(name,mode,tim)char*name;const mode_t mode;time_t*const tim;
- X{ char*p;int j= -2,i;struct stat stbuf;
- X i=lastdirsep(name)-name;strncpy(p=malloc(i+UNIQnamelen),name,i);
- X if(unique(p,p+i,mode)) /* try and rename the unique filename */
- X { stat(p,&stbuf);
- X if(tim)
- X *tim=stbuf.st_mtime; /* return the filesystem time to the caller */
- X j=myrename(p,name);
- X }
- X free(p);return j;
- X}
- END_OF_FILE
- if test 13144 -ne `wc -c <'procmail/retint.c'`; then
- echo shar: \"'procmail/retint.c'\" unpacked with wrong size!
- fi
- # end of 'procmail/retint.c'
- fi
- echo shar: End of archive 4 \(of 5\).
- cp /dev/null ark4isdone
- 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
-
- "I have a *cunning* plan!"
-
- exit 0 # Just in case...
-