#ifdef RCS
static char rcsid[]=
"$Id: procmail.c,v 1.1.1.1 1999/09/23 17:30:07 wsanchez Exp $";
#endif
#include "../patchlevel.h"
#include "procmail.h"
#include "acommon.h"
#include "sublib.h"
#include "robust.h"
#include "shell.h"
#include "misc.h"
#include "pipes.h"
#include "common.h"
#include "cstdio.h"
#include "exopen.h"
#include "regexp.h"
#include "mcommon.h"
#include "goodies.h"
#include "locking.h"
#include "mailfold.h"
#include "lastdirsep.h"
#include "authenticate.h"
static const char*const nullp,From_[]=FROM,exflags[]=RECFLAGS,
drcfile[]="Rcfile:",pmusage[]=PM_USAGE,*etcrc=ETCRC,
misrecpt[]="Missing recipient\n",extrns[]="Extraneous ",ignrd[]=" ignored\n",
pardir[]=chPARDIR,curdir[]={chCURDIR,'\0'},
insufprivs[]="Insufficient privileges\n",
attemptst[]="Attempt to fake stamp by";
char*buf,*buf2,*loclock,*tolock;
const char shell[]="SHELL",lockfile[]="LOCKFILE",newline[]="\n",binsh[]=BinSh,
unexpeof[]="Unexpected EOL\n",*const*gargv,*const*restargv= &nullp,*sgetcp,
pmrc[]=PROCMAILRC,*rcfile=pmrc,dirsep[]=DIRSEP,devnull[]=DevNull,
lgname[]="LOGNAME",executing[]="Executing",oquote[]=" \"",cquote[]="\"\n",
procmailn[]="procmail",whilstwfor[]=" whilst waiting for ",home[]="HOME",
host[]="HOST",*defdeflock,*argv0="",errwwriting[]="Error while writing to",
slogstr[]="%s \"%s\"",conflicting[]="Conflicting ",orgmail[]="ORGMAIL",
exceededlb[]="Exceeded LINEBUF\n",pathtoolong[]=" path too long";
char*Stdout;
int retval=EX_CANTCREAT,retvl2=EXIT_SUCCESS,sh,pwait,lcking,rcstate,rc= -1,
ignwerr,lexitcode=EXIT_SUCCESS,asgnlastf,accspooldir,crestarg,skiprc,
savstdout,berkeley,mailfilter,erestrict;
size_t linebuf=mx(DEFlinebuf+XTRAlinebuf,1024);
volatile int nextexit;
pid_t thepid;
long filled,lastscore;
char*themail,*thebody;
uid_t uid;
gid_t gid,sgid;
static auth_identity*savepass(spass,uid)auth_identity*const spass;
const uid_t uid;
{ const auth_identity*tpass;
if(auth_filledid(spass)&&auth_whatuid(spass)==uid)
goto ret;
if(tpass=auth_finduid(uid,0))
{ auth_copyid(spass,tpass);
ret: return spass;
}
return (auth_identity*)0;
}
#if 0
#define wipetcrc() (etcrc&&(etcrc=0,closerc(),1))
#else
static int wipetcrc P((void))
{ if(etcrc)
{ etcrc=0;closerc();
return 1;
}
return 0;
}
#endif
main(argc,argv)const char*const argv[];
{ register char*chp,*chp2;register int i;int suppmunreadable;
#if 0
kill(getpid(),SIGSTOP);
#endif
newid();
;{ int presenviron,Deliverymode,override;char*fromwhom=0;
const char*idhint=0;gid_t egid=getegid();
Deliverymode=mailfilter=override=0;
Openlog(procmailn,LOG_PID,LOG_MAIL);
if(argc)
{ Deliverymode=strncmp(lastdirsep(argv0=argv[0]),procmailn,
STRLEN(procmailn));
for(presenviron=argc=0;(chp2=(char*)argv[++argc])&&*chp2=='-';)
for(;;)
{ switch(*++chp2)
{ case VERSIONOPT:elog(procmailn);elog(VERSION);
elog("\nLocking strategies:\tdotlocking");
#ifndef NOfcntl_lock
elog(", fcntl()");
#endif
#ifdef USElockf
elog(", lockf()");
#endif
#ifdef USEflock
elog(", flock()");
#endif
elog("\nDefault rcfile:\t\t");elog(pmrc);
elog("\nYour system mailbox:\t");
elog(auth_mailboxname(auth_finduid(getuid(),0)));
elog(newline);
return EXIT_SUCCESS;
case HELPOPT1:case HELPOPT2:elog(pmusage);elog(PM_HELP);
elog(PM_QREFERENCE);
return EX_USAGE;
case PRESERVOPT:presenviron=1;
continue;
case MAILFILTOPT:mailfilter=1;
continue;
case OVERRIDEOPT:override=1;
continue;
case BERKELEYOPT:case ALTBERKELEYOPT:berkeley=1;
continue;
case TEMPFAILOPT:retval=EX_TEMPFAIL;
continue;
case FROMWHOPT:case ALTFROMWHOPT:
if(*++chp2)
fromwhom=chp2;
else if(chp2=(char*)argv[argc+1])
argc++,fromwhom=chp2;
else
nlog("Missing name\n");
break;
case ARGUMENTOPT:
{ static const char*argv1[]={"",0};
if(*++chp2)
goto setarg;
else if(chp2=(char*)argv[argc+1])
{ argc++;
setarg: *argv1=chp2;restargv=argv1;crestarg=1;
}
else
nlog("Missing argument\n");
break;
}
case DELIVEROPT:
if(!*(chp= ++chp2)&&!(chp=(char*)argv[++argc]))
{ nlog(misrecpt);
break;
}
else
{ Deliverymode=1;
goto last_option;
}
case '-':
if(!*chp2)
{ argc++;
goto last_option;
}
default:nlog("Unrecognised options:");logqnl(chp2);
elog(pmusage);elog("Processing continued\n");
case '\0':;
}
break;
}
}
if(Deliverymode&&!(chp=chp2))
nlog(misrecpt),Deliverymode=0;
last_option:
if(Deliverymode&&presenviron)
{ presenviron=0;
goto conflopt;
}
if(mailfilter)
{ if(Deliverymode)
{ mailfilter=0;
goto conflopt;
}
if(crestarg)
conflopt: nlog(conflicting),elog("options\n"),elog(pmusage);
}
if(!Deliverymode)
idhint=getenv(lgname);
if(!presenviron)
{ const char**emax=(const char**)environ,**ep,*const*kp;
static const char*const keepenv[]=KEEPENV;
for(kp=keepenv;*kp;kp++)
for(i=strlen(*kp),ep=emax;chp2=(char*)*ep;ep++)
if(!strncmp(*kp,chp2,(size_t)i)&&(chp2[i]=='='||chp2[i-1]=='_'))
{ *ep= *emax;*emax++=chp2;
break;
}
*emax=0;
}
#ifdef LD_ENV_FIX
;{ const char**emax=(const char**)environ,**ep;
static const char*ld_[]=
{"LD_","_RLD","LIBPATH=","ELF_LD_","AOUT_LD_",0};
for(ep=emax;*emax;emax++);
for(;*ep;ep++)
{ const char**ldp,*p;
for(ldp=ld_;p= *ldp++;)
if(!strncmp(*ep,p,strlen(p)))
{ *ep--= *--emax;*emax=0;
break;
}
}
}
#endif
;{ auth_identity*pass,*passinvk;auth_identity*spassinvk;int privs;
uid_t euid=geteuid();
spassinvk=auth_newid();passinvk=savepass(spassinvk,uid=getuid());
privs=1;gid=getgid();
;{ static const char*const trusted_ids[]=TRUSTED_IDS;
if(Deliverymode&&*trusted_ids&&uid!=euid)
{ struct group*grp;const char*const*kp;
if(passinvk)
for(chp2=(char*)auth_username(passinvk),kp=trusted_ids;*kp;)
if(!strcmp(chp2,*kp++))
goto privileged;
if(grp=getgrgid(gid))
for(chp2=grp->gr_name,kp=trusted_ids;*kp;)
if(!strcmp(chp2,*kp++))
goto privileged;
privs=0;
}
}
privileged:
endgrent();doumask(INIT_UMASK);
while((savstdout=rdup(STDOUT))<=STDERR)
{ rclose(savstdout);
if(0>(savstdout=opena(devnull)))
goto nodevnull;
syslog(LOG_EMERG,"Descriptor %d was not open\n",savstdout);
}
fclose(stdout);rclose(STDOUT);
if(0>opena(devnull))
nodevnull:
{ writeerr(devnull);syslog(LOG_EMERG,slogstr,errwwriting,devnull);
return EX_OSFILE;
}
#ifdef console
opnlog(console);
#endif
setbuf(stdin,(char*)0);mallocbuffers(linebuf);
#ifdef SIGXCPU
signal(SIGXCPU,SIG_IGN);signal(SIGXFSZ,SIG_IGN);
#endif
#ifdef SIGLOST
signal(SIGLOST,SIG_IGN);
#endif
#if DEFverbose
verboff();verbon();
#else
verbon();verboff();
#endif
#ifdef SIGCHLD
signal(SIGCHLD,SIG_DFL);
#endif
signal(SIGPIPE,SIG_IGN);qsignal(SIGTERM,srequeue);
qsignal(SIGINT,sbounce);qsignal(SIGHUP,sbounce);
qsignal(SIGQUIT,slose);signal(SIGALRM,(void(*)())ftimeout);
ultstr(0,(unsigned long)uid,buf);filled=0;
if(!passinvk||!(chp2=(char*)auth_username(passinvk)))
chp2=buf;
;{ const char*fwhom;size_t lfr,linv;int tstamp;
tstamp=fromwhom&&*fromwhom==REFRESH_TIME&&!fromwhom[1];fwhom=chp2;
if(fromwhom&&!tstamp)
{ if(!privs&&!strcmp(fromwhom,fwhom))
privs=1;
if(!privs&&fromwhom&&override)
{ if(verbose)
nlog(insufprivs);
syslog(LOG_ERR,slogstr,attemptst,fwhom);fromwhom=0;
}
else
fwhom=fromwhom;
}
thebody=themail=
malloc(2*linebuf+(lfr=strlen(fwhom))+(linv=strlen(chp2)));
if(Deliverymode||fromwhom)
{ char*rstart;int r;static const char Fakefield[]=FAKE_FIELD;
;{ time_t t;
t=time((time_t*)0);strcat(strcpy(buf2," "),ctime(&t));
}
lfr+=STRLEN(From_)+(r=strlen(buf2));
if(tstamp)
tstamp=r;
if(privs)
linv=0;
else
linv+=STRLEN(Fakefield)+r;
while(1==(r=rread(STDIN,themail,1))&&*themail=='\n');
i=0;rstart=themail;
if(r>0&&STRLEN(From_)<=(i=rread(
STDIN,rstart+1,(int)(linebuf-2-1))+1)&&eqFrom_(themail))
{ rstart[i]='\0';
if(!(rstart=strchr(rstart,'\n')))
{ do
{ if((i=rread(STDIN,themail,(int)(linebuf-2)))<=0)
break;
themail[i]='\0';
}
while(!(rstart=strchr(themail,'\n')));
i=rstart?i-(++rstart-themail):0;
goto no_from;
}
;{ size_t tfrl;
i-=tfrl= ++rstart-themail;
if(Deliverymode&&override&&!privs)
{ if(verbose)
nlog(insufprivs);
syslog(LOG_ERR,slogstr,attemptst,fwhom);
goto no_from;
}
if(tstamp)
lfr=findtstamp(themail+STRLEN(From_),rstart)
-themail+tstamp;
else if(!fromwhom)
if(linv)
lfr=tfrl;
else
lfr=0,i+=tfrl;
}
}
else
no_from: { tstamp=0;
if(!fromwhom)
linv=0;
}
filled=lfr+linv+i;
if(lfr||linv)
{ r= *rstart;tmemmove(themail+lfr+linv,rstart,i);
rstart=themail+lfr;
if(!linv)
{ rstart[-tstamp]='\0';
if(!tstamp)
strcat(strcpy(themail,From_),fwhom);
}
else
{ if(lfr)
if(tstamp)
strcpy(rstart-tstamp,buf2);
else if(fromwhom)
strcat(strcat(strcpy(themail,From_),fwhom),buf2);
strcat(strcpy(rstart,Fakefield),chp2);
}
strcat(themail,buf2);themail[lfr+linv]=r;
}
}
}
readmail(0,0L);
if(Deliverymode)
do
{ chp2=chp;
if(argv[++argc])
if(pidchild=sfork())
{ if(forkerr(pidchild,procmailn)||
waitfor(pidchild)!=EXIT_SUCCESS)
retvl2=retval;
pidchild=0;
}
else
{ newid();
while(argv[++argc]);
}
}
while(chp=(char*)argv[argc]);
gargv=argv+argc;suppmunreadable=verbose;
if(Deliverymode)
{ if(!(pass=auth_finduser(chp2,-1)))
{ static const char unkuser[]="Unknown user";
nlog(unkuser);logqnl(chp2);syslog(LOG_ERR,slogstr,unkuser,chp2);
return EX_NOUSER;
}
if(enoughprivs(passinvk,euid,egid,auth_whatuid(pass),
auth_whatgid(pass)))
goto Setuser;
nlog(insufprivs);
syslog(LOG_CRIT,"Insufficient privileges to deliver to \"%s\"\n",
chp2);
return EX_NOPERM;
}
else
{ suppmunreadable=nextrcfile();
if(presenviron)
etcrc=0;
if(suppmunreadable)
etcrc=0,scomsat=DEFcomsat;
if(mailfilter)
{ if(!suppmunreadable)
{ nlog("Missing rcfile\n");
return EX_NOINPUT;
}
#ifdef ETCRCS
;{ static const char etcrcs[]=ETCRCS;
if(!strncmp(etcrcs,rcfile,STRLEN(etcrcs)))
{ struct stat stbuf;
for(chp=(char*)rcfile+STRLEN(etcrcs)-1;
chp;
chp=strpbrk(chp,dirsep))
if(!strncmp(pardir,++chp,STRLEN(pardir))&&
(chp+=STRLEN(pardir),strchr(dirsep,*chp)))
goto nospecial;
#ifdef CAN_chown
*(chp=strcpy(buf2,etcrcs)+STRLEN(etcrcs))=chCURDIR;
*++chp='\0';
#endif
if(presenviron||
suppmunreadable!=2||
#ifdef CAN_chown
stat(buf2,&stbuf)||
!S_ISDIR(stbuf.st_mode)||
stbuf.st_uid!=ROOT_uid&&
chown(buf2,ROOT_uid,stbuf.st_gid)||
stbuf.st_mode&(S_IXGRP|S_IXOTH)&&
chmod(buf2,S_IRWXU)||
#endif
lstat(rcfile,&stbuf)||
!enoughprivs(passinvk,euid,egid,stbuf.st_uid,
stbuf.st_gid)||
S_ISDIR(stbuf.st_mode)||
!savepass(spassinvk,stbuf.st_uid)
)
nospecial: { static const char densppr[]=
"Denying special privileges for";
nlog(densppr);logqnl(rcfile);
syslog(LOG_ALERT,slogstr,densppr,rcfile);
}
else
mailfilter=2,passinvk=spassinvk;
}
}
#endif
}
}
if(idhint&&(pass=auth_finduser((char*)idhint,0))&&
passinvk&&auth_whatuid(passinvk)==auth_whatuid(pass)||
(pass=passinvk))
Setuser: { gid=auth_whatgid(pass);uid=auth_whatuid(pass);
if(!*(chp=(char*)auth_username(pass)))
chp=buf;
setdef(lgname,chp);setdef(home,auth_homedir(pass));
if(euid==ROOT_uid)
initgroups(chp,gid);
endgrent();
if(!*(chp=(char*)auth_shell(pass)))
chp=(char*)binsh;
setdef(shell,chp);setdef(orgmail,auth_mailboxname(pass));
}
else
{ setdef(lgname,buf);setdef(home,RootDir);setdef(shell,binsh);
setdef(orgmail,"/tmp/dead.letter");setids();
}
endpwent();auth_freeid(spassinvk);
}
if(!presenviron||!mailfilter)
{ setdef(host,hostname());sputenv(lastfolder);sputenv(exitcode);
initdefenv();
;{ const char*const*kp;static const char*const prestenv[]=PRESTENV;
for(kp=prestenv;*kp;)
{ strcpy((char*)(sgetcp=buf2),*kp++);
if(readparse(buf,sgetc,2))
setoverflow();
else
sputenv(buf);
}
}
}
sgetcp=fdefault;
if(readparse(buf,sgetc,2))
{ nlog(orgmail);elog(pathtoolong);elog(newline);
syslog(LOG_CRIT,"%s%s for LINEBUF for uid \"%lu\"\n",orgmail,
pathtoolong,(unsigned long)uid);
fdefault="";
goto nix_sysmbox;
}
fdefault=tstrdup(buf);
strcpy(chp2=strchr(strcpy(buf,chp=(char*)getenv(orgmail)),'\0'),lockext);
defdeflock=tstrdup(buf);sgid=egid;accspooldir=3;
if(mailfilter||!screenmailbox(chp,chp2,egid,Deliverymode))
nix_sysmbox:
{ rcst_nosgid();sputenv(orgmail);
if(!strcmp(chp,fdefault))
free((char*)fdefault),fdefault="";
}
doumask(INIT_UMASK);
while(chp=(char*)argv[argc])
{ argc++;
if(!asenvcpy(chp)&&mailfilter)
{ gargv= &nullp;
for(restargv=argv+argc;restargv[crestarg];crestarg++);
break;
}
resettmout();
}
}
;{ int lastsucc,lastcond,prevcond;struct dyna_long ifstack;
ifstack.filled=ifstack.tspace=0;ifstack.offs=0;
if(etcrc)
{ if(0<=bopen(etcrc))
{ yell(drcfile,etcrc);
#if !DEFverbose
if(rcstate!=rc_NORMAL)
verbose=0;
#endif
goto startrc;
}
etcrc=0;
}
do
{ resettmout();
if(rc<0)
{ struct stat stbuf;
goto findrc;
do
{ if(suppmunreadable)
fake_rc: readerr(buf);
if(!nextrcfile())
{ skiprc=0;
goto nomore_rc;
}
suppmunreadable=0;
findrc: i=0;
if(rcfile==pmrc&&(i=2))
{ if(*strcpy((char*)(rcfile=buf2),pmrc2buf())=='\0')
pm_overflow: { strcpy(buf,pmrc);
goto fake_rc;
}
}
else if(strchr(dirsep,*rcfile)||
(mailfilter||*rcfile==chCURDIR&&strchr(dirsep,rcfile[1]))&&
(i=1))
strcpy(buf,rcfile);
else
{ *(chp=lastdirsep(pmrc2buf()))='\0';
if(buf[0]=='\0')
goto pm_overflow;
else
strcpy(chp,rcfile);
}
if(mailfilter!=2&&(rcstate==rc_NOSGID||
!rcstate&&!stat(buf,&stbuf)))
setids();
}
while(0>bopen(buf));
if(rcstate!=rc_NORMAL&&mailfilter!=2)
{ closerc();
setids();
if(0>bopen(buf))
goto fake_rc;
}
#ifndef NOfstat
if(fstat(rc,&stbuf))
#else
if(stat(buf,&stbuf))
#endif
{ static const char susprcf[]="Suspicious rcfile";
susp_rc: closerc();nlog(susprcf);logqnl(buf);
syslog(LOG_ALERT,slogstr,susprcf,buf);
goto fake_rc;
}
if(mailfilter==2)
setids();
erestrict=1;
if(i==1)
{ if(!didchd)
setmaildir(curdir);
}
else
{ register char c= *(chp=lastdirsep(buf));
if(((stbuf.st_uid!=uid&&stbuf.st_uid!=ROOT_uid||
stbuf.st_mode&S_IWOTH||
i&&stbuf.st_mode&S_IWGRP&&(NO_CHECK_stgid||stbuf.st_gid!=gid)
)&&strcmp(devnull,buf)||
(*chp='\0',stat(buf,&stbuf))||
#ifdef CAN_chown
!(stbuf.st_mode&S_ISVTX)&&
#endif
((stbuf.st_mode&(S_IWOTH|S_IXOTH))==(S_IWOTH|S_IXOTH)||
i&&(stbuf.st_mode&(S_IWGRP|S_IXGRP))==(S_IWGRP|S_IXGRP)
&&(NO_CHECK_stgid||stbuf.st_gid!=gid))))
{ *chp=c;
goto susp_rc;
}
*chp=c;
}
yell(drcfile,buf);
if(!didchd)
{ if((chp=lastdirsep(pmrc2buf()))>buf)
chp[-1]='\0';
if(buf[0]=='\0')
{ nlog("procmailrc");elog(pathtoolong);elog(newline);
syslog(LOG_CRIT,"procmailrc%s for LINEBUF for uid \"%lu\"\n",
pathtoolong,(unsigned long)uid);
goto nomore_rc;
}
if(chdir(chp=buf))
{ chderr(buf);
if(chdir(chp=(char*)tgetenv(home)))
chderr(chp),chp=(char*)curdir;
}
setmaildir(chp);
}
startrc: lastsucc=lastcond=prevcond=0;
}
unlock(&loclock);
goto commint;
do
{ skipline();
commint: do skipspace();
while(testB('\n'));
}
while(testB('#'));
if(testB(':'))
{ int locknext,succeed;char*startchar;long tobesent;
static char flags[maxindex(exflags)];
do
{ int nrcond;
if(readparse(buf,getb,0))
goto nextrc;
;{ char*chp3;
nrcond=strtol(buf,&chp3,10);chp=chp3;
}
if(chp==buf)
nrcond= -1;
if(tolock)
free(tolock);
for(i=maxindex(flags);flags[i]=0,i--;);
for(tolock=0,locknext=0;;)
{ chp=skpspace(chp);
switch(i= *chp++)
{ default:
if(!(chp2=strchr(exflags,i)))
{ chp--;
break;
}
flags[chp2-exflags]=1;
case '\0':
if(chp!=Tmnate)
continue;
break;
case ':':locknext=1;
if(*chp||++chp!=Tmnate)
tolock=tstrdup(chp),chp=strchr(chp,'\0')+1;
}
concatenate(chp);skipped(chp);
break;
}
i=conditions(flags,prevcond,lastsucc,lastcond,nrcond);
if(!flags[ALSO_NEXT_RECIPE]&&!flags[ALSO_N_IF_SUCC])
lastcond=i==1;
if(!prevcond||!flags[ELSE_DO])
prevcond=i==1;
}
while(i==2);
startchar=themail;tobesent=filled;
if(flags[PASS_HEAD])
{ if(!flags[PASS_BODY])
tobesent=thebody-themail;
}
else if(flags[PASS_BODY])
tobesent-=(startchar=thebody)-themail;
Stdout=0;succeed=sh=0;
pwait=flags[WAIT_EXIT]|flags[WAIT_EXIT_QUIET]<<1;
ignwerr=flags[IGNORE_WRITERR];skipspace();
if(i)
zombiecollect(),concon('\n');
progrm: if(testB('!'))
{ if(!i)
skiprc++;
chp=strchr(strcpy(buf,sendmail),'\0');
if(*flagsendmail)
chp=strchr(strcpy(chp+1,flagsendmail),'\0');
if(readparse(chp+1,getb,0))
goto fail;
if(i)
{ if(startchar==themail)
{ startchar[filled]='\0';
if(eqFrom_(startchar))
do
while(i= *startchar++,--tobesent&&i!='\n');
while(*startchar=='>');
}
goto forward;
}
skiprc--;
}
else if(testB('|'))
{ if(getlline(buf2))
goto commint;
if(i)
{ metaparse(buf2);
if(!sh&&buf+1==Tmnate)
{ *buf='|';*(char*)(Tmnate++)='\0';
goto tostdout;
}
forward: if(locknext)
{ if(!tolock)
{ *buf2='\0';
for(chp=buf;i= *chp++;)
if(i=='>'&&*chp=='>')
{ chp=skpspace(chp+1);
tmemmove(buf2,chp,i=strcspn(chp,EOFName));
buf2[i]='\0';
if(sh)
{ chp=tstrdup(buf);sgetcp=buf2;
if(readparse(buf,sgetc,0))
{ *buf2='\0';
goto nolock;
}
strcpy(buf2,buf);strcpy(buf,chp);free(chp);
}
break;
}
if(!*buf2)
nolock: { nlog("Couldn't determine implicit lockfile from");
logqnl(buf);
}
}
lcllock();
if(!pwait)
pwait=2;
}
rawnonl=flags[RAW_NONL];inittmout(buf);asgnlastf=1;
if(flags[FILTER])
{ if(startchar==themail&&tobesent!=filled)
{ if(!pipthrough(buf,startchar,tobesent))
readmail(1,tobesent),succeed=!pipw;
}
else if(!pipthrough(buf,startchar,tobesent))
filled=startchar-themail,readmail(0,0L),succeed=!pipw;
}
else if(Stdout)
{ if(!pipthrough(buf,startchar,tobesent))
succeed=1,postStdout();
}
else if(!pipin(buf,startchar,tobesent))
if(succeed=1,flags[CONTINUE])
goto logsetlsucc;
else
goto frmailed;
goto setlsucc;
}
}
else if(testB(EOF))
nlog("Incomplete recipe\n");
else
{ int ofiltflag;char*end=buf+linebuf-4;
if(ofiltflag=flags[FILTER])
flags[FILTER]=0,nlog(extrns),elog("filter-flag"),elog(ignrd);
if(chp=gobenv(buf,end))
{ if(chp==end)
{ getlline(buf);
goto fail;
}
if(skipspace())
chp++;
if(testB('='))
{ int c;
*chp++='=';*chp='\0';
if(skipspace())
chp++;
ungetb(c=getb());
switch(c)
{ case '!':case '|':
if(i)
primeStdout(buf);
goto progrm;
}
}
}
else if((chp=strchr(buf,'\0'))==buf&&
testB('{')&&
(*chp++='{',*chp='\0',testB(' ')||
testB('\t')||
testB('\n')))
{ if(locknext&&!flags[CONTINUE])
nlog(extrns),elog("locallockfile"),elog(ignrd);
app_val(&ifstack,(off_t)prevcond);
app_val(&ifstack,(off_t)lastcond);
if(!i)
skiprc++;
else
{ if(locknext)
{ *buf2='\0';lcllock();
if(!pwait)
pwait=2;
}
succeed=1;inittmout(procmailn);
if(flags[CONTINUE])
{ yell("Forking",procmailn);onguard();
if(!(pidchild=sfork()))
{ if(loclock)
free(loclock),loclock=0;
if(globlock)
free(globlock),globlock=0;
newid();offguard();duprcs();
}
else
{ offguard();
if(forkerr(pidchild,procmailn))
succeed=0;
else
{ int excode;
if(pwait&&
(excode=waitfor(pidchild))!=EXIT_SUCCESS)
{ if(!(pwait&2)||verbose)
progerr(procmailn,excode);
succeed=0;
}
pidchild=0;skiprc++;
}
}
}
goto jsetlsucc;
}
continue;
}
if(!i)
skiprc++;
if(readparse(chp,getb,0))
fail: { succeed=0;setoverflow();
goto setlsucc;
}
if(i)
{ if(ofiltflag)
startchar=themail,tobesent=filled;
tostdout: strcpy(buf2,buf);rawnonl=flags[RAW_NONL];
if(locknext)
lcllock();
inittmout(buf);
if(writefolder(buf,strchr(buf,'\0')+1,startchar,tobesent,
ignwerr)&&
(succeed=1,!flags[CONTINUE]))
frmailed: { if(ifstack.offs)
free(ifstack.offs);
goto mailed;
}
logsetlsucc: if(succeed&&flags[CONTINUE]&&lgabstract==2)
logabstract(tgetenv(lastfolder));
setlsucc: rawnonl=0;
jsetlsucc: lastsucc=succeed;lasttell= -1;
}
else
skiprc--;
}
}
else if(testB('}'))
{ if(ifstack.filled)
{ lastcond=ifstack.offs[--ifstack.filled];
prevcond=ifstack.offs[--ifstack.filled];
}
else
nlog("Closing brace unexpected\n");
if(skiprc)
skiprc--;
}
else
{ char*end=buf+linebuf;
if(!(chp=gobenv(buf,end)))
{ if(!*buf)
getbl(buf,buf+linebuf);
skipped(buf);
continue;
}
if(chp==end)
nextrc: if(poprc()||wipetcrc())
continue;
else
break;
skipspace();
if(testB('='))
{ *chp='=';
if(readparse(++chp,getb,1))
{ setoverflow();
continue;
}
}
else
*++chp='\0';
if(!skiprc)
chp2=(char*)sputenv(buf),chp[-1]='\0',asenv(chp2);
}
}
while(rc<0||!testB(EOF)||poprc()||wipetcrc());
nomore_rc:
if(ifstack.offs)
free(ifstack.offs);
}
;{ int succeed;
concon('\n');succeed=0;
if(*(chp=(char*)fdefault))
{ int len,tlen;
setuid(uid);
len=strlen(chp);
if(linebuf<(tlen=len+strlen(lockext)+XTRAlinebuf+UNIQnamelen))
mallocbuffers(linebuf=tlen);
if(strcmp(chp,devnull)&&strcmp(chp,"|"))
{ cat(chp,lockext);
if(!globlock||strcmp(buf,globlock))
lockit(tstrdup(buf),&loclock);
}
if(writefolder(chp,(char*)0,themail,filled,0))
succeed=1;
}
if(!succeed&&*(chp2=(char*)tgetenv(orgmail))&&strcmp(chp2,chp))
{ rawnonl=0;
if(writefolder(chp2,(char*)0,themail,filled,0))
succeed=1;
}
if(succeed)
mailed: rawnonl=0,retval=EXIT_SUCCESS;
}
unlock(&loclock);Terminate();
}
int eqFrom_(a)const char*const a;
{ return !strncmp(a,From_,STRLEN(From_));
}