#ifdef RCS
static char rcsid[]=
"$Id: procmail.c,v 1.1.1.3 2003/10/14 23:13:23 rbraun Exp $";
#endif
#include "../patchlevel.h"
#include "procmail.h"
#include "acommon.h"
#include "sublib.h"
#include "robust.h"
#include "shell.h"
#include "misc.h"
#include "memblk.h"
#include "pipes.h"
#include "common.h"
#include "cstdio.h"
#include "exopen.h"
#include "mcommon.h"
#include "goodies.h"
#include "locking.h"
#include "mailfold.h"
#include "lastdirsep.h"
#include "authenticate.h"
#include "lmtp.h"
#include "foldinfo.h"
#include "variables.h"
#include "comsat.h"
#include "from.h"
static const char*const nullp,exflags[]=RECFLAGS,drcfile[]="Rcfile:",
pmusage[]=PM_USAGE,*etcrc=ETCRC,misrecpt[]="Missing recipient\n",
extrns[]="Extraneous ",ignrd[]=" ignored\n",pardir[]=chPARDIR,
defspath[]=DEFSPATH,defmaildir[]=DEFmaildir;
char*buf,*buf2,*loclock;
const char shell[]="SHELL",lockfile[]="LOCKFILE",newline[]="\n",binsh[]=BinSh,
unexpeof[]="Unexpected EOL\n",*const*gargv,*const*restargv= &nullp,*sgetcp,
pmrc[]=PROCMAILRC,*rcfile,dirsep[]=DIRSEP,devnull[]=DevNull,empty[]="",
lgname[]="LOGNAME",executing[]="Executing",oquote[]=" \"",cquote[]="\"\n",
procmailn[]="procmail",whilstwfor[]=" whilst waiting for ",home[]="HOME",
host[]="HOST",*defdeflock=empty,*argv0=empty,curdir[]={chCURDIR,'\0'},
slogstr[]="%s \"%s\"",conflicting[]="Conflicting ",orgmail[]="ORGMAIL",
insufprivs[]="Insufficient privileges\n",defpath[]=DEFPATH,
exceededlb[]="Exceeded LINEBUF\n",errwwriting[]="Error while writing to",
Version[]=VERSION;
int retval=EX_CANTCREAT,retvl2=EXIT_SUCCESS,sh,pwait,rc= -1,
privileged=priv_START,lexitcode=EXIT_SUCCESS,ignwerr,crestarg,savstdout,
berkeley,mailfilter,erestrict,Deliverymode,ifdepth;
struct dyna_array ifstack;
size_t linebuf=mx(DEFlinebuf,1024);
volatile int nextexit,lcking;
pid_t thepid;
long filled,lastscore;
memblk themail;
char*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;
}
#define rct_ABSOLUTE 0
#define rct_CURRENT 1
#define rct_DEFAULT 2
#define rcs_DELIVERED 1
#define rcs_EOF 2
#define rcs_HOST 3
static void
usage P((void));
static int
tryopen P((const int delay_setid,const int rctype,const int dowarning)),
mainloop P((void));
int main(argc,argv)int argc;const char*const argv[];
{ register char*chp,*chp2;
#if 0
kill(getpid(),SIGSTOP);
#endif
newid();
;{ int presenviron,override;char*fromwhom=0;
const char*idhint=0;gid_t egid=getegid();
presenviron=Deliverymode=mailfilter=override=0;
Openlog(procmailn,LOG_PID,LOG_MAIL);
if(argc)
{ Deliverymode=!!strncmp(lastdirsep(argv0=argv[0]),procmailn,
STRLEN(procmailn));
for(argc=0;(chp2=(char*)argv[++argc])&&*chp2=='-';)
for(;;)
{ switch(*++chp2)
{ case VERSIONOPT:
usage();
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 struct dyna_array newargv;
if(*++chp2)
goto setarg;
else if(chp2=(char*)argv[argc+1])
{ argc++;
setarg: app_valp(newargv,(const char*)chp2);
restargv=&(acc_valp(newargv,0));
crestarg++;
}
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 LMTPOPT:
#ifdef LMTP
Deliverymode=2;
goto last_option;
#else
nlog("LMTP support not enabled in this binary\n");
return EX_USAGE;
#endif
case '-':
if(!*++chp2)
{ argc++;
goto last_option;
}
default:nlog("Unrecognised options:");logqnl(chp2);
elog(pmusage);elog("Processing continued\n");
case '\0':;
}
break;
}
}
if(Deliverymode==1&&!(chp=chp2))
nlog(misrecpt),Deliverymode=0;
last_option:
switch(Deliverymode)
{ case 0:
idhint=getenv(lgname);
if(mailfilter&&crestarg)
{ crestarg=0;
conflopt: nlog(conflicting);elog("options\n");elog(pmusage);
}
break;
#ifdef LMTP
case 2:
if(fromwhom)
{ fromwhom=0;
goto confldopt;
}
#endif
case 1:
if(presenviron||mailfilter)
confldopt: { presenviron=mailfilter=0;
goto conflopt;
}
break;
default:
abort();
}
cleanupenv(presenviron);
;{ auth_identity*pass,*passinvk;auth_identity*spassinvk;
uid_t euid=geteuid();
uid=getuid();gid=getgid();
spassinvk=auth_newid();passinvk=savepass(spassinvk,uid);
checkprivFrom_(euid,passinvk?auth_username(passinvk):0,override);
doumask(INIT_UMASK);
while((savstdout=rdup(STDOUT))<=STDERR)
{ rclose(savstdout);
if(0>(savstdout=opena(devnull)))
goto nodevnull;
syslog(LOG_ALERT,"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);allocbuffers(linebuf,1);
#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);
setcomsat(empty);
ultstr(0,(unsigned long)uid,buf);filled=0;
if(!passinvk||!(chp2=(char*)auth_username(passinvk)))
chp2=buf;
#ifdef LMTP
if(Deliverymode==2)
{ auth_identity**rcpts,**lastrcpt,**currcpt;
currcpt=rcpts=lmtp(&lastrcpt,chp2);
if(currcpt+1!=lastrcpt)
lockblock(&themail);
else
private(1);
while(currcpt<lastrcpt)
{ if(!(pidchild=sfork()))
{ setupsigs();
pass= *currcpt++;
while(currcpt<lastrcpt)
auth_freeid(*currcpt++);
freeoverread();
free(rcpts);newid();gargv=&nullp;
goto dorcpt;
}
if(forkerr(pidchild,procmailn))
lexitcode=EX_OSERR;
else
waitfor(pidchild);
lmtpresponse(lexitcode);
pidchild=0;
auth_freeid(*currcpt++);
}
free(rcpts);
flushoverread();
exit(EXIT_SUCCESS);
}
#endif
setupsigs();
makeFrom(fromwhom,chp2);
readmail(0,0L);
if(Deliverymode)
{ if(argv[argc+1])
{ private(0);
lockblock(&themail);
}
else
private(1);
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]);
break;
}
}
while(chp=(char*)argv[argc]);
}
gargv=argv+argc;
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;
}
dorcpt: 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
{ int commandlinerc=nextrcfile();
if(presenviron)
etcrc=0;
if(commandlinerc)
{ etcrc=0;
setcomsat(DEFcomsat);
if(!presenviron)
setdef(scomsat,DEFcomsat);
}
if(mailfilter)
{ if(!commandlinerc)
{ 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||
commandlinerc!=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
}
}
pass=passinvk;
if(passinvk&&idhint)
{ auth_identity*idpass=auth_finduser((char*)idhint,0);
if(idpass)
{ if(auth_whatuid(passinvk)==auth_whatuid(idpass))
pass=idpass;
}
}
if(pass)
Setuser: { gid=auth_whatgid(pass);uid=auth_whatuid(pass);
if(euid==ROOT_uid&&(chp=(char*)auth_username(pass))&&*chp)
initgroups(chp,gid);
endgrent();
}
else
setids();
initdefenv(pass,buf,!presenviron||!mailfilter);
endpwent();auth_freeid(spassinvk);
}
if(buildpath(orgmail,fdefault,(char*)0))
{ fdefault=empty;
goto nix_sysmbox;
}
fdefault=tstrdup(buf);sgid=egid;
chp=(char*)tgetenv(orgmail);
if(mailfilter||!screenmailbox(chp,egid,Deliverymode))
nix_sysmbox:
{ sputenv(orgmail);
if(privileged)
privileged=priv_DONTNEED;
if(!strcmp(chp,fdefault))
free((char*)fdefault),fdefault=empty;
}
}
doumask(INIT_UMASK);
while(chp=(char*)argv[argc])
{ argc++;
if(!asenvcpy(chp)&&mailfilter)
{ gargv= &nullp;
for(restargv=argv+argc;restargv[crestarg];crestarg++);
break;
}
}
if(etcrc)
{ if(0<=bopen(etcrc))
{ yell(drcfile,etcrc);
#if !DEFverbose
if(privileged)
verbose=0;
#endif
eputenv(defspath,buf);
if(mainloop()==rcs_DELIVERED)
goto mailed;
eputenv(defpath,buf);
}
}
erestrict=mailfilter!=2;
if(rcfile&&!mailfilter)
{ int rctype,dowarning;
for(dowarning=1;;)
{ rctype=rct_ABSOLUTE;
if(strchr(dirsep,*rcfile))
strcpy(buf,rcfile);
else if(*rcfile==chCURDIR&&strchr(dirsep,rcfile[1]))
strcpy(buf,rcfile),rctype=rct_CURRENT;
else
if(buildpath(maildir,defmaildir,rcfile))
break;
if(tryopen(0,rctype,dowarning))
{ register int rcs=mainloop();
if(rcs==rcs_DELIVERED)
goto mailed;
if(rcs==rcs_EOF)
break;
if(!nextrcfile())
goto mailed;
}
else
{ dowarning=0;
if(!nextrcfile())
break;
}
}
}
else
{ int rctype;
if(!rcfile)
{ rctype=rct_DEFAULT;
if(buildpath("default rcfile",pmrc,(char*)0))
goto nomore_rc;
}
else
{ rctype=strchr(dirsep,*rcfile)?rct_ABSOLUTE:rct_CURRENT;
strcpy(buf,rcfile);
}
if(tryopen(mailfilter==2,rctype,DEFverbose||mailfilter))
if(mainloop()!=rcs_EOF)
goto mailed;
}
nomore_rc:
if(ifstack.vals)
free(ifstack.vals);
;{ int succeed;
concon('\n');succeed=0;
if(*(chp=(char*)fdefault))
{ int len;
setuid(uid);
if(linebuf<(len=strlen(chp)+strlen(lockext)+UNIQnamelen))
allocbuffers(linebuf=len,1);
if(writefolder(chp,(char*)0,themail.p,filled,0,1))
succeed=1;
}
if(!succeed&&*(chp2=(char*)tgetenv(orgmail))&&strcmp(chp2,chp))
{ rawnonl=0;
if(writefolder(chp2,(char*)0,themail.p,filled,0,0))
succeed=1;
}
if(succeed)
mailed: retval=EXIT_SUCCESS;
}
unlock(&loclock);Terminate();
}
static void usage P((void))
{ 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);
#ifdef GROUP_PER_USER
elog("\n\tIt may be writable by your primary group");
#endif
elog("\nYour system mailbox:\t");
elog(auth_mailboxname(auth_finduid(getuid(),0)));
elog(newline);
#ifdef USE_MMAP
elog("\nLarge messages will be memory mapped during processing.\n");
#endif
}
static int tryopen(delay_setid,rctype,dowarning)
const int delay_setid,rctype,dowarning;
{ struct stat stbuf;
if(!delay_setid&&privileged&&
(privileged==priv_DONTNEED||!stat(buf,&stbuf)))
setids();
if(0>bopen(buf))
{ if(dowarning)
rerr: readerr(buf);
return 0;
}
if(!delay_setid&&privileged)
{ closerc();
setids();
if(0>bopen(buf))
goto rerr;
}
#ifndef NOfstat
if(fstat(rc,&stbuf))
#else
if(stat(buf,&stbuf))
#endif
{ static const char susprcf[]="Suspicious rcfile";
suspicious_rc:
closerc();nlog(susprcf);logqnl(buf);
syslog(LOG_ALERT,slogstr,susprcf,buf);
goto rerr;
}
if(delay_setid)
setids();
if(rctype==rct_CURRENT)
{ if(!didchd)
setmaildir(curdir);
}
else
{ register char*chp=lastdirsep(buf),c;
c= *chp;
if(((stbuf.st_uid!=uid&&stbuf.st_uid!=ROOT_uid||
(stbuf.st_mode&S_IWOTH)||
rctype==rct_DEFAULT&&
(stbuf.st_mode&S_IWGRP)&&
(NO_CHECK_stgid||stbuf.st_gid!=gid)
)&&strcmp(devnull,buf)||
(*chp='\0',stat(buf,&stbuf))||
#ifndef CAN_chown
!(stbuf.st_mode&S_ISVTX)&&
#endif
((stbuf.st_mode&(S_IWOTH|S_IXOTH))==(S_IWOTH|S_IXOTH)||
rctype==rct_DEFAULT&&
(stbuf.st_mode&(S_IWGRP|S_IXGRP))==(S_IWGRP|S_IXGRP)&&
(NO_CHECK_stgid||stbuf.st_gid!=gid))))
{ *chp=c;
goto suspicious_rc;
}
*chp=c;
}
yell(drcfile,buf);
if(!didchd)
{ const char*chp;
if(buildpath(maildir,defmaildir,(char*)0))
exit(EX_OSERR);
if(chdir(chp=buf))
{ chderr(buf);
chp=tgetenv(home);
if(!strcmp(chp,buf)||chdir(chp))
chderr(chp),chp=curdir;
}
setmaildir(chp);
}
return 1;
}
static int mainloop P((void))
{ int lastsucc,lastcond,prevcond,i,skiprc;register char*chp,*tolock;
lastsucc=lastcond=prevcond=skiprc=0;
tolock=0;
do
{ 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,skiprc))
return rcs_EOF;
;{ char*temp;
nrcond=strtol(buf,&temp,10);chp=temp;
}
if(chp==buf)
nrcond= -1;
if(tolock)
free(tolock);
for(i=maxindex(flags);i;i--)
flags[i]=0;
for(tolock=0,locknext=0;;)
{ chp=skpspace(chp);
switch(i= *chp++)
{ default:
;{ char*flg;
if(!(flg=strchr(exflags,i)))
{ chp--;
break;
}
flags[flg-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,skiprc!=0,nrcond);
if(!skiprc)
{ 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.p;tobesent=filled;
if(flags[PASS_HEAD])
{ if(!flags[PASS_BODY])
tobesent=thebody-themail.p;
}
else if(flags[PASS_BODY])
tobesent-=(startchar=thebody)-themail.p;
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|=1;
if(strlcpy(buf,sendmail,linebuf)>=linebuf)
goto fail;
chp=strchr(buf,'\0');
if(*flagsendmail)
{ char*q;int got=0;
if(!(q=simplesplit(chp+1,flagsendmail,buf+linebuf-1,&got)))
goto fail;
*(chp=q)='\0';
}
if(readparse(chp+1,getb,0,skiprc))
goto fail;
if(i)
{ if(startchar==themail.p)
{ startchar[filled]='\0';
startchar=(char*)skipFrom_(startchar,&tobesent);
}
goto forward;
}
skiprc&=~1;
}
else if(testB('|'))
{ chp=buf2;
if(getlline(chp,buf2+linebuf))
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,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(tolock,buf2);
if(!pwait)
pwait=2;
}
rawnonl=flags[RAW_NONL];
if(flags[CONTINUE]&&(flags[FILTER]||Stdout))
nlog(extrns),elog("copy-flag"),elog(ignrd);
inittmout(buf);
if(flags[FILTER])
{ if(startchar==themail.p&&tobesent!=filled)
{ if(!pipthrough(buf,startchar,tobesent))
readmail(1,tobesent),succeed=!pipw;
}
else if(!pipthrough(buf,startchar,tobesent))
{ filled=startchar-themail.p;
readmail(0,tobesent);
succeed=!pipw;
}
}
else if(Stdout)
succeed=!pipthrough(buf,startchar,tobesent);
else if(!pipin(buf,startchar,tobesent,1))
{ succeed=1;
if(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,buf+linebuf);
goto fail;
}
if(skipspace())
chp++;
if(testB('='))
{ int c;
*chp++='=';*chp='\0';
if(skipspace())
chp++;
ungetb(c=getb());
switch(c)
{ case '!':case '|':
if(i)
Stdout = tstrdup(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);
if(flags[PASS_BODY])
nlog(extrns),elog("deliver-body flag"),elog(ignrd);
if(flags[PASS_HEAD])
nlog(extrns),elog("deliver-head flag"),elog(ignrd);
if(flags[IGNORE_WRITERR])
nlog(extrns),elog("ignore-write-error flag"),elog(ignrd);
if(flags[RAW_NONL])
nlog(extrns),elog("raw-mode flag"),elog(ignrd);
if(!i)
skiprc+=2;
else
{ app_vali(ifstack,prevcond);
app_vali(ifstack,lastcond);
if(locknext)
{ lcllock(tolock,"");
if(!pwait)
pwait=2;
}
succeed=1;
if(flags[CONTINUE])
{ yell("Forking",procmailn);
private(0);
inittmout(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,pwait&2);
succeed=0;
}
pidchild=0;skiprc+=2;
ifstack.filled-=2;
}
}
}
goto setlsucc;
}
continue;
}
if(!i)
skiprc|=1;
if(readparse(chp,getb,0,skiprc))
fail: { succeed=0;
goto setlsucc;
}
if(i)
{ if(ofiltflag)
startchar=themail.p,tobesent=filled;
tostdout: rawnonl=flags[RAW_NONL];
if(locknext)
lcllock(tolock,buf);
inittmout(buf);
if(writefolder(buf,strchr(buf,'\0')+1,startchar,tobesent,
ignwerr,0)&&
(succeed=1,!flags[CONTINUE]))
frmailed: { if(ifstack.vals)
free(ifstack.vals);
return rcs_DELIVERED;
}
logsetlsucc: if(succeed&&flags[CONTINUE]&&lgabstract==2)
logabstract(tgetenv(lastfolder));
setlsucc: rawnonl=0;lastsucc=succeed;lasttell= -1;
resettmout();
}
skiprc&=~1;
}
}
else if(testB('}'))
{ if(skiprc>1)
skiprc-=2;
else if(ifstack.filled>ifdepth)
{ lastcond=acc_vali(ifstack,--ifstack.filled);
prevcond=acc_vali(ifstack,--ifstack.filled);
}
else
nlog("Closing brace unexpected\n");
}
else
{ char*end=buf+linebuf;
if(!(chp=gobenv(buf,end)))
{ if(!*buf)
getbl(buf,end);
skipped(buf);
continue;
}
if(chp==end)
break;
skipspace();
if(testB('='))
{ *chp='=';
if(readparse(++chp,getb,1,skiprc))
continue;
}
else
*++chp='\0';
if(!skiprc)
{ const char*p;
p=sputenv(buf);
chp[-1]='\0';
asenv(p);
}
}
if(rc<0)
return rcs_HOST;
}
while(!testB(EOF)||(skiprc=0,poprc()));
return rcs_EOF;
}