File: robust.c

package info (click to toggle)
procmail 3.22-25+deb9u1
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 2,116 kB
  • sloc: ansic: 9,885; sh: 1,957; makefile: 136
file content (192 lines) | stat: -rw-r--r-- 5,287 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/************************************************************************
 *	The fault-tolerant system-interface				*
 *									*
 *	Copyright (c) 1990-1997, S.R. van den Berg, The Netherlands	*
 *	Copyright (c) 1999-2001, Philip Guenther, The United States	*
 *						of America		*
 *	#include "../README"						*
 ************************************************************************/
#ifdef RCS
static /*const*/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
		       /* set nextexit to prevent elog() from using malloc() */
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);			   /* works on some systems with latent free */
}

void*tmalloc(len)const size_t len;    /* this malloc can survive a temporary */
{ void*p;int i;				    /* "out of swap space" condition */
  lcking|=lck_ALLOCLIB;
  if(p=malloc(len))
     goto ret;
  heapdefrag();heapdefrag();				   /* try some magic */
  for(i=nomemretry;i<0||i--;)
   { suspend();		     /* problems?  don't panic, wait a few secs till */
     if(p=malloc(len))	     /* some other process has paniced (and died 8-) */
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;				    /* for comment see tmalloc above */
  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;			 /* 'fragile' malloc */
{ void*p;
  lcking|=lck_ALLOCLIB;p=malloc(len);lcking&=~lck_ALLOCLIB;
  return p;
}

void*frealloc(old,len)void*const old;const size_t len;	/* 'fragile' realloc */
{ 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))			/* this fork can survive a temporary */
{ pid_t i;int r;			   /* "process table full" condition */
  zombiecollect();elog(empty);r=noforkretry;	  /* flush log, just in case */
  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);						     /* flush stderr */
  if(!*file)						   /* empty LOGFILE? */
     file=devnull;				 /* substitute the bitbucket */
  if(0>(i=opena(file)))			     /* error?	keep the old LOGFILE */
     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;					       /* a SysV secure open */
  for(r=noresretry,lcking|=lck_FILDES;0>(i=open(name,mode,mask));)
     if(errno!=EINTR&&!(errno==ENFILE&&(r<0||r--)))
	break;		 /* survives a temporary "file table full" condition */
  lcking&=~lck_FILDES;
  return i;
}

int rpipe(fd)int fd[2];
{ int i,r;					  /* catch "file table full" */
  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;					  /* catch "file table full" */
  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;	      /* a SysV secure close (signal immune) */
{ int i;
  while((i=close(fd))&&errno==EINTR);
  return i;
}

int rread(fd,a,len)const int fd,len;void*const a;      /* a SysV secure read */
{ int i;
  while(0>(i=read(fd,a,(size_t)len))&&errno==EINTR);
  return i;
}
						      /* a SysV secure write */
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)	  /* if less than 1s timeout */
	ftimeout();				  /* activate it by hand now */
     else		    /* set it manually again, to avoid problems with */
	alarm((unsigned)t);	/* badly implemented sleep library functions */
}

void doumask(mask)const mode_t mask;
{ umask(cumask=mask);
}