#ifdef RCS
static char rcsid[]=
"$Id: formisc.c,v 1.41 2001/06/27 06:41:27 guenther Exp $";
#endif
#include "includes.h"
#include "formail.h"
#include "sublib.h"
#include "shell.h"
#include "common.h"
#include "acommon.h"
#include "ecommon.h"
#include "formisc.h"
static const char*skipcomment(start)const char*start;
{ for(;;)
switch(*++start)
{ case '\0':start--;
case ')':return start;
case '\\':start++;
break;
case '(':start=skipcomment(start);
}
}
char*skipwords(start)char*start;
{ int delim,hitspc,machref,group;char*target,*oldstart;
group=1;hitspc=machref=0;target=oldstart=start;
if(*start=='<')
start++,machref=1;
for(;;)
{ switch(*start)
{ case '<':
if(machref)
{ target=oldstart;hitspc=0;
goto inc;
}
goto ret;
case '(':start=(char*)skipcomment(start);
case ' ':case '\t':case '\n':hitspc|=1;
inc: start++;
continue;
case ';':
if(group==2)
start[1]='\0';
case ',':
if(group==2)
goto special;
if(machref)
{ machref=2;
goto special;
}
goto retz;
default:
if(!machref&&hitspc==3&&target>oldstart)
case '\0':case '>':
{ if(machref==2)
{ *target++='>';tmemmove(oldstart+1,oldstart,target++-oldstart);
*oldstart='<';
}
retz: *target='\0';
ret: return start;
}
if(*start=='\\')
*target++='\\',start++;
hitspc=2;
goto normal;
case ':':
if(group==1)
group=2;
case '@':case '.':
if(group==1)
group=0;
special: hitspc=0;
normal: *target++= *start++;
continue;
case '[':delim=']';
break;
case '"':*target++=delim='"';start++;
}
;{ int i;
do
if((i= *target++= *start++)==delim)
break;
else if(i=='\\'&&*start)
*target++= *start++;
while(*start);
}
hitspc=2;
}
}
void loadsaved(sp)const struct saved*const sp;
{ switch(*sp->rexp)
{ default:loadchar(' ');
case ' ':case '\t':;
}
loadbuf(sp->rexp,sp->rexl);
}
void loadbuf(text,len)const char*const text;const size_t len;
{ if(buffilled+len>buflen)
buf=realloc(buf,buflen+=Bsize);
tmemmove(buf+buffilled,text,len);buffilled+=len;
}
void loadchar(c)const int c;
{ if(buffilled==buflen)
buf=realloc(buf,buflen+=Bsize);
buf[buffilled++]=c;
}
int pm_getline P((void))
{ if(buflast==EOF)
{ loadchar('\n');
return EOF;
}
loadchar(buflast);
if(buflast!='\n')
{ int ch;
while((ch=getchar())!=EOF&&ch!='\n')
rhash=rhash*67067L+(uchar)ch,loadchar(ch);
loadchar('\n');
}
return buflast=getchar();
}
void elog(a)const char*const a;
{ fputs(a,stderr);
}
void tputssn(a,l)const char*a;size_t l;
{ while(l--)
putcs(*a++);
}
void ltputssn(a,l)const char*a;size_t l;
{ if(logsummary)
Totallen+=l;
else
putssn(a,l);
}
void lputcs(i)const int i;
{ if(logsummary)
Totallen++;
else
putcs(i);
}
void startprog(argv)const char*Const*const argv;
{ if(nrskip)
{ nrskip--;opensink();return;
}
if(nrtotal>0)
nrtotal--;
dup(oldstdout);
if(*argv)
{ int poutfd[2];
static int children;
if(lenfileno>=0)
{ long val=initfileno++;char*chp;
chp=ffileno+LEN_FILENO_VAR;
if(val<0)
*chp++='-';
ultstr(lenfileno-(val<0),val<0?-val:val,chp);
while(*chp==' ')
*chp++='0';
}
pipe(poutfd);
;{ int maxchild=childlimit?childlimit:
(unsigned long)children*CHILD_FACTOR,excode;
while(children&&waitpid((pid_t)-1,&excode,WNOHANG)>0)
if(!WIFSTOPPED(excode))
{ children--;
if((excode=WIFEXITED(excode)?
WEXITSTATUS(excode):-WTERMSIG(excode))!=EXIT_SUCCESS)
retval=excode;
}
while(childlimit&&children>=childlimit||(child=fork())==-1&&children)
for(--children;(excode=waitfor((pid_t)0))!=NO_PROCESS;)
{ if(excode!=EXIT_SUCCESS)
retval=excode;
if(--children<=maxchild)
break;
}
}
if(!child)
{ close(STDIN);close(oldstdout);close(PWRO);dup(PRDO);close(PRDO);
shexec(argv);
}
close(STDOUT);close(PRDO);
if(STDOUT!=dup(PWRO))
nofild();
close(PWRO);
if(-1==child)
nlog("Can't fork\n"),exit(EX_OSERR);
children++;
}
if(!(mystdout=Fdopen(STDOUT,"a")))
nofild();
}
void nofild P((void))
{ nlog("File table full\n");exit(EX_OSERR);
}
void nlog(a)const char*const a;
{ elog(formailn);elog(": ");elog(a);
}
void logqnl(a)const char*const a;
{ elog(" \"");elog(a);elog("\"\n");
}
void closemine P((void))
{ if(fclose(mystdout)==EOF||errout==EOF)
{ if(!quiet)
nlog(couldntw),elog("\n");
exit(EX_IOERR);
}
}
void opensink P((void))
{ if(!(mystdout=fopen(DevNull,"a")))
nofild();
}