home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-06-18 | 43.8 KB | 1,147 lines |
- Newsgroups: comp.sources.misc
- From: Stephen R. van den Berg <berg@messua.informatik.rwth-aachen.de>
- Subject: v20i050: procmail - mail processing program v2.02, Part02/03
- Message-ID: <1991Jun17.043123.1899@sparky.IMD.Sterling.COM>
- X-Md4-Signature: 5542db79dfa88d913086900e268b3f17
- Date: Mon, 17 Jun 1991 04:31:23 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: Stephen R. van den Berg <berg@messua.informatik.rwth-aachen.de>
- Posting-number: Volume 20, Issue 50
- Archive-name: procmail/part02
- Environment: UNIX, sendmail
- Supersedes: procmail: Volume 17, Issue 31-32
-
- ---- Cut Here and feed the following to sh ----
- #!/bin/sh
- # This is part 02 of procmail
- # ============= procmail/README ==============
- if test ! -d 'procmail'; then
- echo 'x - creating directory procmail'
- mkdir 'procmail'
- fi
- if test -f 'procmail/README' -a X"$1" != X"-c"; then
- echo 'x - skipping procmail/README (File already exists)'
- else
- echo 'x - extracting procmail/README (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmail/README' &&
- XSome legal stuff:
- X
- XUse this software package at your own risk. The programmer can not
- Xbe held liable for any incurred damages due to the use of this software.
- X
- XYou are encouraged to distribute this package freely. This package is
- Xhowever not to be sold (minor transfer costs excepted) or included in
- Xany commercially sold software package (if you want to do this anyway,
- Xcontact me (address below), and we'll work something out).
- X
- XIf you distribute it, please leave the package in tact. If you have some
- Ximportant changes that might be usefull to the rest of the world, contact
- Xme instead.
- X
- X-------------------------- SYSTEM REQUIREMENTS -------------------------------
- X
- XA ".forward" file (or equivalent) mechanism for forwarding mail, *grep or
- Xequivalent.
- X
- XThe most important system calls that need to be supported (among others):
- Xfork(),read(),write(),dup(),wait(),pipe(),getpwent()
- X
- XFor a more complete list of all library references see "includes.h"
- X
- X------------------------------ DESCRIPTION -----------------------------------
- X
- XThe procmail mail processing program. (v2.02 1991/06/12)
- X
- XCan be used to create mail-servers, mailing lists, sort your incoming mail
- Xinto separate folders/files (real convenient when subscribing to one or more
- Xmailing lists), preprocess your mail, or selectively forward certain incoming
- Xmail automatically to someone.
- X
- XFor installation instructions see the INSTALL file.
- X
- X----------------------
- X
- XAlthough I can't guarantee that the procmail program will perform as
- Xrequired, I must say that I made the utmost effort to make procmail as
- Xrobust as any program can be (every conceivable system error is caught *and*
- Xhandled).
- X
- Xprocmail was designed to deliver the mail under the worst conditions
- X(file system full, out of swap space, process table full, file table full,
- Xmissing support files, unavailable executables; it all doesn't matter).
- XShould (in the unlikely event) procmail be unable to deliver your mail
- Xsomewhere, the mail will bounce back to the sender.
- X
- XFor a more extensive list of features see the FEATURES file.
- X
- XHowever, as with any program, bugs can not be completely ruled out.
- XI tested the program extensively, and believe it should be relatively
- Xbug free (no known bug at the time). Should, however, anyone find any
- Xbugs (highly unlikely :-), I would be pleased (well, sort of :-) to hear
- Xabout it. Please send me the patches or bug report.
- XI'll look at them and will try to fix it in a future release.
- X(BTW, if you should find any spelling or grammar errors in these files,
- Xit's not priority one, but if you were sending me mail anyway, don't hesitate
- Xto point them out to me; I like correct English just as much as you do).
- X
- XPlease note that this program essentially is supposed to be static, that
- Xmeans no extra features (honouring the *NIX spirit) are supposed to be
- Xadded (though any usefull suggestions will be appreciated and evaluated if
- Xtime permits).
- X
- XCheers,
- X Stephen R. van den Berg at RWTH-Aachen, Germany.
- X
- XInternet E-mail: berg@messua.informaik.rwth-aachen.de
- X berg@physik.tu-muenchen.de
- X
- XOr: P.O.Box 21074
- X 6369 ZG Simpelveld
- X The Netherlands
- X
- X----------------------
- X
- XP.S. I don't mind if you feed the program files through your favourite C
- X beautifier first, so any patches need not necessarily be from the
- X original sources; I apply these patches by hand anyway.
- SHAR_EOF
- chmod 0644 procmail/README ||
- echo 'restore of procmail/README failed'
- Wc_c="`wc -c < 'procmail/README'`"
- test 3358 -eq "$Wc_c" ||
- echo 'procmail/README: original size 3358, current size' "$Wc_c"
- fi
- # ============= procmail/STYLE ==============
- if test -f 'procmail/STYLE' -a X"$1" != X"-c"; then
- echo 'x - skipping procmail/STYLE (File already exists)'
- else
- echo 'x - extracting procmail/STYLE (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmail/STYLE' &&
- XDon't complain about the formatting of my C code. I know it's unconventional,
- Xbut it's my standard format. If you don't like it, feed it through your
- Xfavourite C beautifier.
- X
- XYes, I do have my reasons for formatting it this way:
- X1. consistent, functional indenting
- X2. I got used to it
- X3. the C compiler doesn't mind at all
- X4. I get more program text on my screen when editing, hence I don't have to
- X scroll as often to see other parts of the program while working, (you won't
- X believe this, I know) and therefore it helps to get a better overview of
- X the program
- X5. I hate it when I have to scroll back the screen those 5 lines just to see
- X the top of the loop (and then back down to look at the end again, etc.)
- X
- XAnd, now don't start flaming me about "bad practice", I don't consider this
- Xformatting method bad practice (it's properly indented).
- X
- XI consider "bad practice" to be unportable or non-ANSI code, which my code is
- Xcertainly not.
- SHAR_EOF
- chmod 0644 procmail/STYLE ||
- echo 'restore of procmail/STYLE failed'
- Wc_c="`wc -c < 'procmail/STYLE'`"
- test 951 -eq "$Wc_c" ||
- echo 'procmail/STYLE: original size 951, current size' "$Wc_c"
- fi
- # ============= procmail/common.c ==============
- if test -f 'procmail/common.c' -a X"$1" != X"-c"; then
- echo 'x - skipping procmail/common.c (File already exists)'
- else
- echo 'x - extracting procmail/common.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmail/common.c' &&
- X/************************************************************************
- X * A some common routines for procmail and formail *
- 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: common.c,v 2.0 1991/06/10 14:35:35 berg Rel $";
- X#endif
- X#include "includes.h"
- X
- Xvoid*tmalloc();
- Xextern const char binsh[];
- X
- X#ifdef NOmemmove
- Xvoid*memmove(To,From,count)void*To,*From;register size_t count;{
- X#ifdef NObcopy
- X register char*to=To,*from=From;/*void*old;*/ /* silly compromise, throw */
- X /*old=to;*/count++;--to;--from; /* away space to be syntactically correct */
- X if(to<=from){
- X goto jiasc;
- X do{
- X *++to= *++from; /* copy from above */
- Xjiasc:;}
- X while(--count);}
- X else{
- X to+=count;from+=count;
- X goto jidesc;
- X do{
- X *--to= *--from; /* copy from below */
- Xjidesc:;}
- X while(--count);}
- X return To/*old*/;}
- X#else
- X bcopy(From,To,count);return To;}
- X#endif
- X#endif
- X
- X#include "shell.h"
- X
- Xshexec(argv)const char *const*argv;{int i;const char**newargv,**p;
- X execvp(*argv,argv); /* if this one fails, we retry it as a shell script */
- X for(p=(const char**)argv,i=1;i++,*p++;); /* count the arguments */
- X newargv=malloc(i*sizeof*p);
- X for(*(p=newargv)=binsh;*++p= *++argv;);
- X execve(*newargv,newargv,environ); /* no shell script? -> trouble */
- X log("Failed to execute");logqnl(*argv);exit(EX_UNAVAILABLE);}
- SHAR_EOF
- chmod 0644 procmail/common.c ||
- echo 'restore of procmail/common.c failed'
- Wc_c="`wc -c < 'procmail/common.c'`"
- test 1611 -eq "$Wc_c" ||
- echo 'procmail/common.c: original size 1611, current size' "$Wc_c"
- fi
- # ============= procmail/exopen.c ==============
- if test -f 'procmail/exopen.c' -a X"$1" != X"-c"; then
- echo 'x - skipping procmail/exopen.c (File already exists)'
- else
- echo 'x - extracting procmail/exopen.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmail/exopen.c' &&
- X/************************************************************************
- X * Collection of NFS secure exclusive open routines *
- 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: exopen.c,v 2.0 1991/06/10 14:35:35 berg Rel $";
- X#endif
- X#include "config.h"
- X#include "includes.h"
- X#include "exopen.h"
- X
- Xconst char*hostname();
- Xextern pid_t thepid;
- X
- Xconst char*hostname(){static char name[HOSTNAMElen+1];
- X#ifdef NOuname
- X gethostname(name,HOSTNAMElen+1);
- X#else
- X struct utsname names;
- X uname(&names);strncpy(name,names.nodename,HOSTNAMElen);
- X#endif
- X name[HOSTNAMElen]='\0';return name;}
- X
- Xultoan(val,dest)unsigned long val;char*dest;{register i; /* convert to */
- X do{ /* a number within the set [0-9A-Za-z-_] */
- X i=val&0x3f;
- X *dest++=i+(i<10?'0':i<10+26?'A'-10:i<10+26+26?'a'-10-26:
- X i==10+26+26?'-'-10-26-26:'_'-10-26-27);}
- X while(val>>=6);
- X *dest='\0';}
- X
- Xunique(full,p,mode)const char*const full;char*const p;const mode_t mode;{
- X unsigned long retry=3;int i; /* create unique file name */
- X do{
- X ultoan(SERIALmask&(retry<<16)+(unsigned long)thepid,p+1);
- X *p='_';strcat(p,hostname());}
- X while(0>(i=ropen(full,O_WRONLY|O_CREAT|O_EXCL|O_SYNC,mode))&&errno==EEXIST
- X &&retry--); /* casually check if it already exists (highly unlikely) */
- X if(i<0){
- X writeerr(full);return 0;}
- X rclose(i);return 1;}
- X /* rename MUST fail if already existent */
- Xmyrename(old,new)const char*const old,*const new;{int i,serrno;
- X i=link(old,new);serrno=errno;unlink(old);errno=serrno;return i;}
- SHAR_EOF
- chmod 0644 procmail/exopen.c ||
- echo 'restore of procmail/exopen.c failed'
- Wc_c="`wc -c < 'procmail/exopen.c'`"
- test 1788 -eq "$Wc_c" ||
- echo 'procmail/exopen.c: original size 1788, current size' "$Wc_c"
- fi
- # ============= procmail/Manifest ==============
- if test -f 'procmail/Manifest' -a X"$1" != X"-c"; then
- echo 'x - skipping procmail/Manifest (File already exists)'
- else
- echo 'x - extracting procmail/Manifest (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmail/Manifest' &&
- XMakefile We all know what that is.
- XREADME Important, read it.
- XINSTALL A description of what has to be done to install procmail.
- XHISTORY Recent and ancient changes (or bugs) documented.
- XFEATURES A summary of all the things procmail is particularly good at.
- XSTYLE A short explanation of why the source looks so "awkward"
- Xlockfile.c main program for lockfile
- Xformail.c main program for formail
- XManifest You guessed it.
- Xprocmail.c main program for procmail.
- Xnonint.c Collection of routines that don't return ints.
- Xretint.c Collection of routines that return ints.
- Xgoodies.c Some real nice routines, deserve to be put in a library.
- Xcommon.c Some routines that are used by procmail and formail.
- Xexopen.c Collection of routines about an NFS secure excl. open.
- Xexopen.h The very same.
- Xprocmail.h Include file with all declarations.
- X
- Xincludes.h System include files are all referenced here.
- Xconfig.h The file to edit if you want to change, yes, the configuration.
- Xautoconf The shell script that seizes your compiler and machine,
- X and then creates a file called autoconf.h describing the
- X kludges that are going to be applied for your installation.
- X
- Xshell.h Defines a few 'shell' macros for malloc and the like.
- Xman/* Yes, the man pages (made in a labour camp).
- Xinclude/* A few files that are supposed to fool your compiler into
- X thinking that it has ANSI and POSIX conforming include files.
- Xexamples/?procmailrc
- X Sample .procmailrc files.
- Xexamples/?rmail
- X Sample shell scripts that demonstrate how to use
- X lockfiles while reading the mail (to ensure mail integrity
- X as soon as you exit the mail program).
- Xexamples/forward
- X A sample .forward file.
- Xexamples/advanced
- X Some extra info for network mounted mailboxes, examples of
- X advanced .procmailrc expressions and using procmail as
- X a local delivery agent.
- SHAR_EOF
- chmod 0644 procmail/Manifest ||
- echo 'restore of procmail/Manifest failed'
- Wc_c="`wc -c < 'procmail/Manifest'`"
- test 1814 -eq "$Wc_c" ||
- echo 'procmail/Manifest: original size 1814, current size' "$Wc_c"
- fi
- # ============= procmail/lockfile.c ==============
- if test -f 'procmail/lockfile.c' -a X"$1" != X"-c"; then
- echo 'x - skipping procmail/lockfile.c (File already exists)'
- else
- echo 'x - extracting procmail/lockfile.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmail/lockfile.c' &&
- X/************************************************************************
- X * lockfile.c a conditional semaphore-file creator *
- X * *
- X * Is relatively bug free. *
- X * *
- X * Created by S.R.van den Berg, The Netherlands *
- X * This file can be freely copied for any use. *
- X ************************************************************************/
- X#ifdef RCS
- Xstatic char rcsid[]="$Id: lockfile.c,v 2.1 1991/06/11 14:00:41 berg Rel $";
- X#endif
- Xstatic char rcsdate[]="$Date: 1991/06/11 14:00:41 $";
- X#include "config.h" /* overkill, I know, only need DIRSEP */
- X#include "includes.h"
- X
- Xvolatile int exitflag;
- Xpid_t thepid;
- Xconst char dirsep[]=DIRSEP;
- X
- Xvoid failure(){
- X exitflag=1;}
- X
- Xmain(argc,argv)const int argc;const char*argv[];{const char**p,*cp;
- X int sleepsec,retries,i,invert,force,suspend,retval=0;
- X static char usage[]=
- X "Usage: lockfile -nnn | -rnnn | -! | -lnnn | -snnn | file ...\n";
- X sleepsec=8;force=retries=invert=0;suspend=16;thepid=getpid();
- X if(argc<2){
- X putse(usage);return EX_USAGE;}
- Xagain:
- X p=argv+1;signal(SIGHUP,failure);signal(SIGINT,failure);
- X signal(SIGQUIT,failure);signal(SIGTERM,failure);
- X while(*p)
- X if(*(cp= *p++)=='-')
- X switch(cp[1]){
- X case '!':invert=1;break;
- X case 'r':retries=strtol(cp+2,(char**)0,10);break;
- X case 'l':force=strtol(cp+2,(char**)0,10);break;
- X case 's':suspend=strtol(cp+2,(char**)0,10);break;
- X default:
- X if(cp[1]-'0'>(unsigned)9){
- X putse(usage);retval=EX_USAGE;goto failure;}
- X if(sleepsec>=0)
- X sleepsec=strtol(cp+1,(char**)0,10);}
- X else
- X if(sleepsec<0)
- X unlink(cp);
- X else{
- X while(0>NFSxopen(cp)){struct stat buf;time_t t;
- X if(exitflag||retries==1){
- Xfailure: sleepsec= -1;p[-1]=0;goto again;}
- X if(force&&(t=time((time_t*)0),!stat(cp,&buf))&&
- X force<t-buf.st_mtime){
- X unlink(cp);putse("Forcing lock on \"");putse(cp);putse("\"\n");
- X sleep(suspend);}
- X else
- X sleep(sleepsec);
- X if(retries)
- X retries--;}}
- Xreturn retval?retval:invert^(sleepsec<0)?EX_CANTCREAT:EX_OK;}
- X
- Xputse(a)char*a;{char*b;
- X b=a-1;
- X while(*++b);
- X write(STDERR,a,b-a);}
- X
- X#include "exopen.h"
- X
- XNFSxopen(name)char*name;{char*p,*q;int j= -1,i;
- X for(q=name;p=strpbrk(q,dirsep);q=p+1);
- X i=q-name;
- X if(!(p=malloc(i+UNIQnamelen)))
- X return exitflag=1;
- X strncpy(p,name,i);
- X if(unique(p,p+i,0))
- X j=myrename(p,name);
- X free(p);return j;}
- X
- Xvoid*tmalloc(len)const size_t len;{ /* stub */
- X return malloc(len);}
- X
- Xropen(name,mode,mask)const char*const name;const mode_t mask;{ /* stub */
- X return open(name,mode,mask);}
- X
- Xrclose(fd)const int fd;{ /* stub */
- X return close(fd);}
- X
- Xwriteerr(a)const char*const a;{} /* stub */
- SHAR_EOF
- chmod 0644 procmail/lockfile.c ||
- echo 'restore of procmail/lockfile.c failed'
- Wc_c="`wc -c < 'procmail/lockfile.c'`"
- test 2698 -eq "$Wc_c" ||
- echo 'procmail/lockfile.c: original size 2698, current size' "$Wc_c"
- fi
- # ============= procmail/goodies.c ==============
- if test -f 'procmail/goodies.c' -a X"$1" != X"-c"; then
- echo 'x - skipping procmail/goodies.c (File already exists)'
- else
- echo 'x - extracting procmail/goodies.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmail/goodies.c' &&
- X/************************************************************************
- X * Collection of library-worthy routines *
- 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: goodies.c,v 2.1 1991/06/11 12:59:16 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
- Xreadparse(p,fgetc,sarg)register char*p;int(*const fgetc)();
- X const int sarg;{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;}
- Xnewchar:
- X switch(i){
- X case EOF:
- X if(got>NORMAL_TEXT)
- Xearly_eof: log(unexpeof);
- Xready: if(got!=SKIPPING_SPACE||sarg) /* not terminated yet or sarg==2 ? */
- Xready0: *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 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 *p++='\\';break;
- X case '"':
- X if(got!=DOUBLE_QUOTED) /* missing closing backquote? */
- X break;
- Xforcebquote: case EOF:case '`':*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, drop source buffer */
- X startb=fromprog(p=startb,startb); /* read from program */
- X if(got!=DOUBLE_QUOTED){
- X i=0;startb=p;goto simplsplit;} /* split it up */
- X if(i=='"') /* was there a missing closing ` ? */
- X got=NORMAL_TEXT; /* yes, terminate " */
- X p=startb;goto loop;
- X case '\n':i=';';} /* newlines separate commands */
- Xescaped: *p++=i;}
- X case '"':
- X switch(got){
- X case DOUBLE_QUOTED:got=NORMAL_TEXT;continue; /* closing " */
- X case SINGLE_QUOTED:goto nodelim;}
- 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 startb=buf2;
- X if(i=='{'){ /* ${name} */
- X while(EOF!=(i=fgetc())&&alphanum(i))
- X *startb++=i;
- X *startb='\0';
- X if(i!='}'){
- Xbadsubst: log("Bad substitution of");logqnl(buf2);continue;}
- X i='\0';}
- 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 else if(i=='$'){ /* $$=pid */
- X ultostr(0,(unsigned long)thepid,p);i='\0';goto eofstr;}
- X else{
- X *p++='$';goto newchar;} /* not a substitution */
- X startb=(char*)tgetenv(buf2);
- X if(got!=DOUBLE_QUOTED)
- Xsimplsplit: for(;;startb++){ /* simply split it up in arguments */
- X switch(*startb){
- X case ' ':case '\t':case '\n':
- X if(got<=SKIPPING_SPACE)
- X continue;
- X *p++='\0';got=SKIPPING_SPACE;continue;
- X case '\0':goto eeofstr;}
- X *p++= *startb;got=NORMAL_TEXT;}
- X else{
- X strcpy(p,startb); /* simply copy it */
- Xeofstr: p=strchr(p,'\0');}
- 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 case '\n':
- X if(got<=NORMAL_TEXT)
- X goto ready;} /* EOL means we're ready */
- Xnodelim:
- X *p++=i; /* ah, a normal character */
- X if(got<=SKIPPING_SPACE) /* should we bother to change mode? */
- X got=NORMAL_TEXT;}}
- X
- Xultostr(minwidth,val,dest)unsigned long val;char*dest;{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
- 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;a=tstrdup(a); /* make working copy */
- X if(!(split=strchr(a,'='))){ /* assignment or removal? */
- X remove=1;i=strlen(a);*(split=i+(a=realloc(a,i+2)))='=';
- X split[1]='\0';}
- X i= ++split-a;
- X for(curr= *(last= &myenv);curr;curr= *(last= &curr->next))
- X if(!strncmp(a,curr->name,i)){ /* is it one I created earlier? */
- X split=curr->name;*last=curr->next;free(curr);
- X for(preenv=environ;*preenv!=split;preenv++);
- X goto wipenv;}
- X for(preenv=environ;*preenv;preenv++)
- X if(!strncmp(a,*preenv,i)){ /* is it in the standard environment? */
- Xwipenv:
- X while(*preenv=preenv[1]) /* wipe this entry out of the environment */
- X preenv++;
- X break;}
- 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(curr->name-(char*)curr+strlen(a)+1);
- X strcpy(*preenv=curr->name,a);free(a);preenv[1]=0;curr->next=myenv;
- X myenv=curr;}}
- SHAR_EOF
- chmod 0644 procmail/goodies.c ||
- echo 'restore of procmail/goodies.c failed'
- Wc_c="`wc -c < 'procmail/goodies.c'`"
- test 7091 -eq "$Wc_c" ||
- echo 'procmail/goodies.c: original size 7091, current size' "$Wc_c"
- fi
- # ============= procmail/procmail.c ==============
- if test -f 'procmail/procmail.c' -a X"$1" != X"-c"; then
- echo 'x - skipping procmail/procmail.c (File already exists)'
- else
- echo 'x - extracting procmail/procmail.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmail/procmail.c' &&
- X/************************************************************************
- X * procmail.c an autonomous mail processor *
- 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: procmail.c,v 2.3 1991/06/12 10:23:06 berg Rel $";
- X#endif
- X#include "config.h"
- X#define MAIN
- X#include "procmail.h"
- X#include "shell.h"
- X
- X#define VERSION "procmail v2.02 1991/06/12 written by Stephen R.van den Berg\n\
- X\t\t\t\tberg@messua.informatik.rwth-aachen.de\n\
- X\t\t\t\tberg@physik.tu-muenchen.de\n"
- X
- Xchar*buf,*buf2,*globlock,*loclock,*tolock,*lastfolder;
- Xconst char grep[]="GREP",shellflags[]="SHELLFLAGS",shell[]="SHELL",
- X shellmetas[]="SHELLMETAS",lockext[]="LOCKEXT",newline[]="\n",binsh[]=BinSh,
- X unexpeof[]="Unexpected EOL\n",*const*gargv,*sgetcp,*rcfile=PROCMAILRC,
- X dirsep[]=DIRSEP,msgprefix[]="MSGPREFIX",devnull[]=DevNull,
- X executing[]="Executing",oquote[]=" \"",cquote[]="\"\n",
- X whilstwfor[]=" whilst waiting for ";
- Xstatic const char linebufs[]="LINEBUF",tokey[]=TOkey,eumask[]="UMASK",
- X tosubstitute[]=TOsubstitute,lockfile[]="LOCKFILE",defaultf[]="DEFAULT",
- X maildir[]="MAILDIR",couldnread[]="Couldn't read",logfile[]="LOGFILE",
- X orgmail[]="ORGMAIL",user[]="USER",tmp[]=Tmp,home[]="HOME",sfolder[]=FOLDER,
- X sendmail[]="SENDMAIL",host[]="HOST";
- Xstruct varval strenvvar[]={{"LOCKSLEEP",DEFlocksleep},
- X {"LOCKTIMEOUT",DEFlocktimeout},{"SUSPEND",DEFsuspend},
- X {"NORESRETRY",DEFnoresretry}};
- Xlong lastdump;
- Xint retval=EX_CANTCREAT,sh,pwait,lcking,locknext,verbose,linebuf=DEFlinebuf,
- X rc= -1;
- Xvolatile int flaggerd=2,nextexit;
- Xpid_t thepid;
- X
- Xmain(argc,argv)const char*const argv[];{static char flags[NRRECFLAGS];int i;
- X char*themail,*thebody,*chp,*startchar,*chp2;long tobesent,filled;
- X if((chp=(char*)argv[argc=1])&&*chp=='-'&&*++chp&&!chp[1])
- X switch(*chp){ /* these options are mutually exclusive */
- X case VERSIONOPT:log(VERSION);return EX_OK;
- X case DEBUGOPT:verbose=1;
- X default:*environ=0;
- X case PRESERVOPT:argc++;}
- X else
- X *environ=0; /* drop the environment */
- X gargv=argv+argc;umask(077);thepid=getpid();fclose(stdout);fclose(stderr);
- X rclose(STDOUT);rclose(STDERR); /* don't trust the stdio library */
- X if(0>opena(devnull)||0>opena(console))
- X return EX_OSFILE;
- X setbuf(stdin,(char*)0);buf=malloc(linebuf);buf2=malloc(linebuf);chdir(tmp);
- X ultostr(0,(unsigned long)(i=getuid()),buf);
- X setpwent();
- X {struct passwd*pass;
- X if(pass=getpwuid(i)){ /* find user defaults in /etc/passwd */
- X setdef(home,pass->pw_dir);chdir(pass->pw_dir);
- X setdef(user,pass->pw_name?pass->pw_name:buf);setdef(shell,pass->pw_shell);}
- X else{ /* user could not be found, set reasonable defaults */
- X setdef(home,tmp);setdef(user,buf);setdef(shell,binsh);}}
- X endpwent();setdef(shellmetas,DEFshellmetas);setdef(shellflags,DEFshellflags);
- X setdef(maildir,DEFmaildir);setdef(defaultf,DEFdefault);
- X setdef(orgmail,DEForgmail);setdef(grep,DEFgrep);setdef(sendmail,DEFsendmail);
- X setdef(lockext,DEFlockext);setdef(msgprefix,DEFmsgprefix);
- X chdir(getenv(maildir));nextrcfile();thebody=themail=malloc(1);filled=0;
- X signal(SIGTERM,sterminate);signal(SIGINT,sterminate);
- X signal(SIGHUP,sterminate);signal(SIGQUIT,flagger);
- Xchangedmail:
- X themail=readdyn(themail,&filled); /* read in the mail */
- Xonlyhead:
- X startchar=filled+(thebody=themail);
- X while(thebody<startchar&&*thebody++=='\n'); /* skip leading garbage */
- X while(thebody<startchar&&startchar>(thebody=findnl(thebody,startchar)))
- X switch(*thebody++){
- X case '\n':goto eofheader; /* empty line marks end of header */
- X case '\t':case ' ':thebody[-2]=' ';} /* concatenate continuated lines */
- Xeofheader:
- X if((chp=thebody)<startchar){
- X goto firstel; /* search for bogus headers */
- X do{
- X if(*chp++!='\n'||chp==startchar) /* is the line really empty? */
- X continue;
- Xfirstel:
- X *startchar='\0'; /* put a terminator at the end for sscanf */
- X if(0>=sscanf(chp,FromSCAN,buf)){
- X chp--;continue;} /* no match, back up, and on we go */
- X tmemmove(chp+1,chp,startchar++-chp);*chp='>'; /* insert '>' before */
- X themail=realloc(chp2=themail,++filled+1); /* bogus header */
- X#define ADJUST(x) ((x)=themail+((x)-chp2))
- X ADJUST(thebody);ADJUST(startchar);ADJUST(chp);}/* find next empty line */
- X while(startchar>(chp=findnl(chp,startchar)));}
- Xdo{ /* main rcfile interpreter loop */
- X while(chp=(char*)argv[argc]){ /* interpret command line specs first */
- X argc++;strcpy(buf,chp);
- X if(chp=strchr(buf,'=')){
- X strcpy(sgetcp=buf2,++chp);readparse(chp,sgetc,0);goto argenv;}}
- X if(rc<0) /* open new rc file */
- X while(*buf='\0',0>bopen(strcat(
- X strchr(dirsep,*rcfile)?buf:cat(tgetenv(home),MCDIRSEP),rcfile))){
- X log(couldnread);logqnl(buf);
- X if(!nextrcfile()) /* not available? try the next */
- X goto nomore_rc;}
- X unlock(&loclock); /* unlock any local lockfile after every parsed line */
- X do skipspace(); /* skip whitespace */
- X while(testb('\n'));
- X if(testb(':')){ /* check for a recipe */
- X readparse(buf,getb,2);i=sh=1;*buf2='\0';
- X if(0>=sscanf(buf,"%d%[^\n]",&sh,buf2)) /* nr of conditions */
- X strcpy(buf2,buf);
- X *buf= *flags='\0';
- X if(0>=sscanf(buf2,RECFLAGS,flags,buf)) /* read the flags */
- X strcpy(buf,buf2);
- X if(tolock) /* clear temporary buffer for lockfile name */
- X free(tolock);
- X tolock=0;*buf2='\0';
- X if((locknext=':'==*buf)&&0<sscanf(buf,": %[^ \t\n] %[^\n]",buf,buf2))
- X tolock=tstrdup(buf); /* yep, local lockfile specified */
- X if(*buf2)
- X skipped(buf2); /* display any leftovers */
- X startchar=themail;tobesent=thebody-themail;
- X if(strchr(flags,'B')) /* what needs to be piped into grep? */
- X if(strchr(flags,'H'))
- X tobesent=filled;
- X else{
- X startchar=thebody;tobesent=filled-tobesent;}
- X while(sh--){ /* any conditions (left) */
- X getbl(buf2);
- X if(!strncmp(buf2,tokey,STRLEN(tokey))) /* magic TOkey? */
- X cat(tosubstitute,buf2+STRLEN(tokey));
- X else if(*buf=='!'&&!strncmp(buf2+1,tokey,STRLEN(tokey))) /* !TOkey? */
- X strcat(cat("!",tosubstitute),buf2+1+STRLEN(tokey));
- X else
- X strcpy(buf,buf2);
- X if(i){ /* check out all conditions */
- X i=!grepin((*buf=='!'||*buf=='\\')+buf,startchar,tobesent,
- X !!strchr(flags,'D'))^*buf=='!';
- X if(verbose){
- X log(i?"M":"No m");log("atch on");logqnl(buf);}}}
- X startchar=themail;tobesent=filled; /* body, header or both? */
- X if(strchr(flags,'h')){
- X if(!strchr(flags,'b'))
- X tobesent=thebody-themail;}
- X else if(strchr(flags,'b'))
- X tobesent-=(startchar=thebody)-themail;
- X chp=strchr(strcpy(buf,tgetenv(sendmail)),'\0');sh=0;
- X pwait=!!strchr(flags,'w');
- X if(testb('!')){ /* forward the mail */
- X readparse(chp+1,getb,0);
- X if(i)
- X goto forward;}
- X else if(testb('|')){ /* pipe the mail */
- X getbl(buf2);
- X for(chp=buf2;*(chp=strchr(chp,'\0')-1)=='\\'&&getbl(chp););
- X if(i){
- X if(sh=!!strpbrk(buf2,tgetenv(shellmetas)))
- X strcpy(buf,buf2); /* copy literally, shell will parse */
- X else{
- X sgetcp=buf2;readparse(buf,sgetc,0);} /* parse it yourself */
- X chp=buf;*buf2='\0';
- X while(i= *chp) /* find the implicit lockfile name ('>>name') */
- X if(chp++,i=='>'&&*chp=='>'){
- X while((i= *++chp)==' '||i=='\t');
- X sscanf(chp,EOFName,buf2);break;}
- X lcllock();
- X if(strchr(flags,'f')){
- X if(startchar==themail&&tobesent!=filled){ /* if only 'h' */
- X long dfilled=0;
- X if(pipthrough(buf,startchar,tobesent))
- X continue;
- X chp=readdyn(malloc(1),&dfilled);filled-=tobesent;
- X if(tobesent<dfilled) /* adjust buffer size (grow only) */
- X themail=realloc(themail,dfilled+filled);
- X tmemmove(themail+dfilled,thebody,filled);
- X tmemmove(themail,chp,dfilled);free(chp);
- X themail=realloc(themail,1+(filled+=dfilled));goto onlyhead;}
- X if(pipthrough(buf,startchar,tobesent))
- X continue;
- X filled=startchar-themail;goto changedmail;}
- Xforward: if(!pipin(buf,startchar,tobesent)&&!strchr(flags,'c'))
- X goto mailed;}}
- X else{ /* dump the mail into a mailbox file or directory */
- X readparse(buf,getb,0);chp2=chp=strchr(buf,'\0')+1;
- X while(*chp!=TMNATE){ /* concatenate all other arguments */
- X while(*chp++);
- X chp[-1]=' ';}
- X *chp=chp[-1]='\0';
- X if(*chp2)
- X skipped(chp2); /* report any leftovers */
- X if(i){
- X strcpy(buf2,buf);lcllock();strcpy(buf2,buf);
- X if(!dump(deliver(buf2),startchar,tobesent)&&!strchr(flags,'c'))
- X goto mailed;
- X writeerr(buf);}}}
- X else if(testb('#')) /* no comment :-) */
- X getbl(buf);
- X else{ /* then it must be an assignment */
- X for(*(chp=buf)='\0';;){ /* get the variable name */
- X switch(i=getb()){
- X case ' ':case '\t':skipspace();i=testb('=')?'=':0;
- X case '\n':case '=':case EOF:
- X *chp='\0';goto eofvarname;}
- X if(!alphanum(*chp++=i))
- X for(;;*chp++=i) /* it was garbage after all */
- X switch(i=getb()){
- X case ' ':case '\t':case '\n':case EOF:*chp='\0';
- X skipped(buf);goto mainloop;}}
- Xeofvarname:
- X if(i!='='){ /* removal or assignment? */
- X sputenv(buf);continue;}
- X *chp='=';readparse(++chp,getb,1);
- Xargenv:
- X sputenv(buf);chp[-1]='\0';
- X if(!strcmp(buf,linebufs)){
- X if((linebuf=renvint(0L,chp)+XTRAlinebuf)<MINlinebuf+XTRAlinebuf)
- X linebuf=MINlinebuf+XTRAlinebuf; /* check minimum size */
- X free(buf);free(buf2);buf=malloc(linebuf);buf2=malloc(linebuf);}
- X else if(!strcmp(buf,maildir)){
- X if(chdir(chp)){
- X log("Couldn't chdir to");logqnl(chp);}}
- X else if(!strcmp(buf,logfile)){
- X close(STDERR);
- X if(0>opena(chp))
- X if(0>opena(console))
- X retval=EX_OSFILE; /* bad news, but can't tell anyone */
- X else
- X writeerr(chp);}
- X else if(!strcmp(buf,lockfile))
- X lockit(chp,&globlock);
- X else if(!strcmp(buf,eumask)){
- X sscanf(chp,"%o",&i);umask(i);}
- X else if(!strcmp(buf,host)){
- X if(strcmp(chp,chp2=(char*)hostname())){
- X yell("HOST mismatched",chp2);
- X if(rc<0||!nextrcfile()){ /* if no rcfile opened yet */
- X retval=EX_OK;terminate();} /* exit gracefully as well */
- X rclose(rc);rc= -1;}}
- X else{
- X i=MAXvarvals;
- X do /* several numeric assignments */
- X if(!strcmp(buf,strenvvar[i].name)){
- X strenvvar[i].val=renvint(strenvvar[i].val,chp);break;}
- X while(i--);}}
- Xmainloop:
- X ;}
- X while(rc<0||!testb(EOF)); /* main interpreter loop */
- Xnomore_rc:
- X if(dump(deliver(tgetenv(defaultf)),themail,filled)){ /* default */
- X writeerr(buf); /* if it fails, don't panic, try the last resort */
- X if(dump(deliver(tgetenv(orgmail)),themail,filled))
- X writeerr(buf);goto mailerr;} /* now you can panic */
- Xmailed:
- X retval=EX_OK; /* we're home free, mail delivered */
- Xmailerr:
- X unlock(&loclock); /* any local lock file still around? */
- X for(;themail<thebody;){
- X chp=buf-1;
- X while(themail<thebody&&chp<buf+linebuf-1&&(*++chp= *themail++)!='\n');
- X if(chp<buf)
- X chp++;
- X *chp='\0';
- X if(0<sscanf(buf,SFROM_S,buf2)){ /* find case sensitive "From " */
- X log(SFROM);goto foundsorf;}
- X else if(0<sscanf(buf,SSUBJECT_S,buf2)){ /* case insensitive "Subject:" ? */
- X log(SSUBJECT);
- Xfoundsorf:
- X log(buf2);log(newline);}} /* log its arrival */
- X log(sfolder);i=strlen(strncpy(buf,lastfolder,MAXfoldlen))+STRLEN(sfolder);
- X buf[MAXfoldlen]='\0';
- X while(chp=strchr(buf,'\t'))
- X *chp=' '; /* take out all tabs */
- X log(buf);i-=i%TABWIDTH; /* tell where we last dumped it */
- X do log(TABCHAR);
- X while((i+=TABWIDTH)<LENoffset);
- X ultostr(7,lastdump,buf);log(buf);log(newline);terminate();}
- X
- Xdirmail(){struct stat stbuf; /* directory name is expected in buf */
- X strcpy(buf2,strcat(buf,MCDIRSEP));
- X if(unique(buf2,strchr(buf2,'\0'),0666)){
- X stat(buf2,&stbuf);
- X ultoan((unsigned long)stbuf.st_ino, /* filename with i-node number */
- X strchr(strcat(buf,tgetenv(msgprefix)),'\0'));
- X if(!myrename(buf2,buf)) /* rename it, we need the same i-node */
- X return opena(buf);}
- X return -1;}
- SHAR_EOF
- chmod 0644 procmail/procmail.c ||
- echo 'restore of procmail/procmail.c failed'
- Wc_c="`wc -c < 'procmail/procmail.c'`"
- test 12352 -eq "$Wc_c" ||
- echo 'procmail/procmail.c: original size 12352, current size' "$Wc_c"
- fi
- # ============= procmail/nonint.c ==============
- if test -f 'procmail/nonint.c' -a X"$1" != X"-c"; then
- echo 'x - skipping procmail/nonint.c (File already exists)'
- else
- echo 'x - extracting procmail/nonint.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'procmail/nonint.c' &&
- X/************************************************************************
- X * Collection of routines that don't return int *
- 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: nonint.c,v 2.0 1991/06/10 14:35:35 berg Rel $";
- X#endif
- X#include "config.h"
- X#include "procmail.h"
- X
- X#define nomemretry noresretry
- X#define noforkretry noresretry
- X
- Xvoid*tmalloc(len)const size_t len;{void*p;int i; /* this malloc can survive */
- X if(p=malloc(len)) /* a temporary "out of swap space" condition */
- X return p;
- X if(p=malloc(1))
- X free(p); /* works on some systems with latent free */
- X for(lcking=2,i=nomemretry;i<0||i--;){
- X suspend(); /* problems? don't panic, wait a few secs till */
- X if(p=malloc(len)){ /* some other process has paniced (and died 8-) */
- X lcking=0;return p;}}
- X nomemerr();}
- X
- Xvoid*trealloc(old,len)void*const old;const size_t len;{void*p;int i;
- X if(p=realloc(old,len))
- X return p; /* for comment see tmalloc above */
- X if(p=malloc(1))
- X free(p);
- X for(lcking=2,i=nomemretry;i<0||i--;){
- X suspend();
- X if(p=realloc(old,len)){
- X lcking=0;return p;}}
- X nomemerr();}
- X /* line buffered to keep concurrent entries untangled */
- Xlog(new)const char*const new;{int lnew,i;static lold;static char*old;char*p;
- X if(lnew=strlen(new)){ /* anything? */
- X if(nextexit)
- X goto direct; /* carefull, in terminate code */
- X i=lold+lnew;
- X if(p=lold?realloc(old,i):malloc(i)){
- X memmove((old=p)+lold,new,(size_t)lnew); /* append */
- X if(p[(lold=i)-1]=='\n'){ /* EOL? */
- X rwrite(STDERR,p,i);lold=0;free(p);}} /* flush the line(s) */
- X else{ /* no memory, force flush */
- X if(lold){
- X rwrite(STDERR,old,i);lold=0;free(old);}
- Xdirect:
- X rwrite(STDERR,new,lnew);}}}
- X
- X#include "shell.h"
- X
- Xpid_t sfork(){pid_t i;int r; /* this fork can survive a temporary */
- X r=noforkretry; /* "process table full" condition */
- X while((i=fork())==-1){
- X lcking=3;
- X if(!(r<0||r--))
- X break;
- X suspend();}
- X lcking=0;return i;}
- X
- Xextern char*backblock; /* see retint.c for comment */
- Xextern long backlen;
- Xpid_t pidfilt,pidchild;
- Xextern pbackfd[2];
- X
- Xvoid sterminate(){static const char*const msg[]={newline,0,
- X "memory\n","fork\n","file descriptor\n"};
- X signal(SIGTERM,SIG_IGN);signal(SIGHUP,SIG_IGN);signal(SIGINT,SIG_IGN);
- X if(pidchild) /* 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(1!=lcking){
- X if(1<lcking)
- X log(whilstwfor);
- X log(msg[lcking]);terminate();}}}
- X
- Xvoid stermchild(){
- X signal(SIGHUP,SIG_IGN);signal(SIGINT,SIG_IGN);signal(SIGQUIT,SIG_IGN);
- X signal(SIGTERM,SIG_IGN);kill(pidfilt,SIGTERM);kill(thepid,SIGQUIT);
- X log("Rescue of unfiltered data ");
- X if(dump(PWRB,backblock,backlen)) /* pump back the data through the backpipe */
- X log("failed\n");
- X else
- X log("succeeded\n");
- X exit(EX_UNAVAILABLE);}
- X
- Xvoid flagger(){ /* hey, we received a SIGQUIT */
- X signal(SIGQUIT,flagger);flaggerd=1;}
- X
- Xlong dump(s,source,len)const int s;const char*source;long len;{int i;
- X if(s>=0){
- X lastdump=len;
- X while(i=rwrite(s,source,BLKSIZ<len?BLKSIZ:(int)len)){
- X if(i<0){
- X i=0;goto writefin;}
- X len-=i;source+=i;}
- X if(!len&&(lastdump<2||!(source[-1]=='\n'&&source[-2]=='\n')))
- X lastdump++,rwrite(s,newline,1); /* message always ends with a newline */
- Xwritefin:
- X rclose(s);return len-i;}
- X return len?len:-1;} /* return an error even if nothing was to be sent */
- X
- Xlong pipin(line,source,len)char*const line;const char*source;long len;{
- X pid_t pid;int poutfd[2];
- X rpipe(poutfd);
- X if(!(pid=sfork())){ /* spawn program */
- X rclose(PWRO);rclose(rc);getstdin(PRDO);callnewprog(line);}
- X rclose(PRDO);forkerr(pid,line);
- X if(len=dump(PWRO,source,len)) /* dump mail in the pipe */
- X writeerr(line); /* pipe was shut in our face, get mad */
- X if(pwait&&waitfor(pid)!=EX_OK){ /* optionally check the exitcode */
- X progerr(line);len=1;}
- X if(!sh){char*p;
- X for(p=line;;) /* change back the \0's into blanks for printing */
- X if(!*p++)
- X if(*p!=TMNATE)
- X p[-1]=' ';
- X else
- X break;}
- X lastfolder=cstr(lastfolder,line);return len;}
- X
- Xchar*readdyn(bf,filled)char*bf;long*const filled;{int i;long oldsize;
- X oldsize= *filled;goto jumpin;
- X do{
- X *filled+=i; /* change listed buffer size */
- Xjumpin:
- X bf=realloc(bf,*filled+BLKSIZ); /* dynamically adjust the buffer size */
- Xjumpback:;}
- X while(0<(i=rread(STDIN,bf+*filled,BLKSIZ))); /* read mail */
- X switch(flaggerd){
- X case 0:waitflagger(); /* wait for the filter to finish */
- X case 1:getstdin(PRDB); /* filter ready, get backpipe */
- X if(1==rread(STDIN,buf,1)){ /* backup pipe closed? */
- X bf=realloc(bf,(*filled=oldsize+1)+BLKSIZ);bf[oldsize]= *buf;flaggerd=2;
- X goto jumpback;}} /* filter goofed, rescue data */
- X pidchild=0; /* child must be gone by now */
- X if(!*filled)
- X return realloc(bf,1); /* +1 for housekeeping purposes */
- X return realloc(bf,*filled+1);} /* minimize the buffer space */
- X
- Xchar*fromprog(name,dest)char*const name;char*dest;{int pinfd[2];long nls;
- X rpipe(pinfd);
- X if(!(pidchild=fork())){ /* spawn program */
- X rclose(STDIN);opena(devnull);rclose(PRDI);rclose(rc);rclose(STDOUT);
- X rdup(PWRI);rclose(PWRI);callnewprog(name);}
- X rclose(PWRI);nls=0;
- X if(!forkerr(pidchild,name))
- X while(0<rread(PRDI,dest,1)) /* read its lips */
- X if(*dest=='\n') /* carefull with newlines */
- X nls++; /* trailing ones should be discarded */
- X else{
- X if(nls)
- X for(dest[nls]= *dest;*dest++='\n',--nls;); /* fill them in */
- X dest++;}
- X pidchild=0;rclose(PRDI);*dest='\0';return dest;}
- X
- Xchar*cat(a,b)const char*const a,*const b;{
- X return strcat(strcpy(buf,a),b);}
- X
- Xchar*findnl(start,end)register const char*start,*end;{
- X while(start<end) /* find the first newline */
- X if(*start++=='\n')
- X return(char*)start;
- X return(char*)end;}
- X
- Xchar*tstrdup(a)const char*const a;{int i;
- X i=strlen(a)+1;return tmemmove(malloc(i),a,i);}
- X
- Xconst char*tgetenv(a)const char*a;{const char*b;
- X return(b=getenv(a))?b:"";}
- X
- Xchar*cstr(a,b)const char*const a,*const b;{ /* dynamic buffer management */
- X if(a)
- X free(a);
- X return tstrdup(b);}
- X
- Xlong renvint(i,env)long i;const char*const env;{
- X sscanf(tgetenv(env),"%d",&i);return i;} /* parse it like a decimal nr */
- SHAR_EOF
- chmod 0644 procmail/nonint.c ||
- echo 'restore of procmail/nonint.c failed'
- Wc_c="`wc -c < 'procmail/nonint.c'`"
- test 6650 -eq "$Wc_c" ||
- echo 'procmail/nonint.c: original size 6650, current size' "$Wc_c"
- fi
- true || echo 'restore of procmail/retint.c failed'
- echo End of part 2, continue with part 3
- 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.
-