#ifdef RCS
static char rcsid[]=
"$Id: robust.c,v 1.33 2001/06/23 08:18:50 guenther Exp $";
#endif
#include "procmail.h"
#include "robust.h"
#include "misc.h"
#include "pipes.h"
#include "common.h"
#include "mailfold.h"
mode_t cumask;
#define nomemretry noresretry
#define noforkretry noresretry
void nomemerr(len)const size_t len;
{ static const char outofmem[]="Out of memory";
nextexit=2;nlog(outofmem);elog("\n");
syslog(LOG_NOTICE,"%s as I tried to allocate %ld bytes\n",outofmem,
(long)len);
if(!privileged&&buf&&buf2)
{ buf[linebuf-1]=buf2[linebuf-1]='\0';elog("buffer 0:");logqnl(buf);
elog("buffer 1:");logqnl(buf2);
}
if(retval!=EX_TEMPFAIL)
retval=EX_OSERR;
Terminate();
}
static void heapdefrag P((void))
{ register void*p;
lcking|=lck_MEMORY;
if(p=malloc(1))
free(p);
}
void*tmalloc(len)const size_t len;
{ void*p;int i;
lcking|=lck_ALLOCLIB;
if(p=malloc(len))
goto ret;
heapdefrag();heapdefrag();
for(i=nomemretry;i<0||i--;)
{ suspend();
if(p=malloc(len))
ret: { lcking&=~(lck_MEMORY|lck_ALLOCLIB);
return p;
}
}
nomemerr(len);
}
void*trealloc(old,len)void*const old;const size_t len;
{ void*p;int i;
lcking|=lck_ALLOCLIB;
if(p=realloc(old,len))
goto ret;
heapdefrag();heapdefrag();
for(i=nomemretry;i<0||i--;)
{ suspend();
if(p=realloc(old,len))
ret: { lcking&=~(lck_MEMORY|lck_ALLOCLIB);
return p;
}
}
nomemerr(len);
}
void*fmalloc(len)const size_t len;
{ void*p;
lcking|=lck_ALLOCLIB;p=malloc(len);lcking&=~lck_ALLOCLIB;
return p;
}
void*frealloc(old,len)void*const old;const size_t len;
{ void*p;
lcking|=lck_ALLOCLIB;p=realloc(old,len);lcking&=~lck_ALLOCLIB;
return p;
}
void tfree(p)void*const p;
{ lcking|=lck_ALLOCLIB;free(p);lcking&=~lck_ALLOCLIB;
}
#include "shell.h"
pid_t sfork P((void))
{ pid_t i;int r;
zombiecollect();elog(empty);r=noforkretry;
while((i=fork())==-1)
{ lcking|=lck_FORK;
if(!(r<0||r--))
break;
if(waitfor((pid_t)0)==NO_PROCESS)
suspend();
}
lcking&=~lck_FORK;
return i;
}
void opnlog(file)const char*file;
{ int i;
elog(empty);
if(!*file)
file=devnull;
if(0>(i=opena(file)))
writeerr(file),syslog(LOG_NOTICE,slogstr,errwwriting,file);
else
rclose(STDERR),rdup(i),rclose(i),logopened=1;
}
int opena(a)const char*const a;
{ yell("Opening",a);
#ifdef O_CREAT
return ropen(a,O_WRONLY|O_APPEND|O_CREAT,NORMperm);
#else
;{ int fd;
return (fd=ropen(a,O_WRONLY,0))<0?creat(a,NORMperm):fd;
}
#endif
}
int ropen(name,mode,mask)const char*const name;const int mode;
const mode_t mask;
{ int i,r;
for(r=noresretry,lcking|=lck_FILDES;0>(i=open(name,mode,mask));)
if(errno!=EINTR&&!(errno==ENFILE&&(r<0||r--)))
break;
lcking&=~lck_FILDES;
return i;
}
int rpipe(fd)int fd[2];
{ int i,r;
for(r=noresretry,lcking|=lck_FILDES;0>(i=pipe(fd));)
if(!(errno==ENFILE&&(r<0||r--)))
{ *fd=fd[1]= -1;
break;
}
lcking&=~lck_FILDES;
return i;
}
int rdup(p)const int p;
{ int i,r;
for(r=noresretry,lcking|=lck_FILDES;0>(i=dup(p));)
if(!(errno==ENFILE&&(r<0||r--)))
break;
lcking&=~lck_FILDES;
return i;
}
int rclose(fd)const int fd;
{ int i;
while((i=close(fd))&&errno==EINTR);
return i;
}
int rread(fd,a,len)const int fd,len;void*const a;
{ int i;
while(0>(i=read(fd,a,(size_t)len))&&errno==EINTR);
return i;
}
int rwrite(fd,a,len)const int fd,len;const void*const a;
{ int i;
while(0>(i=write(fd,a,(size_t)len))&&errno==EINTR);
return i;
}
void ssleep(seconds)const unsigned seconds;
{ long t;
sleep(seconds);
if(alrmtime)
if((t=alrmtime-time((time_t*)0))<=1)
ftimeout();
else
alarm((unsigned)t);
}
void doumask(mask)const mode_t mask;
{ umask(cumask=mask);
}