*** milter-greylist-4.0a6/Makefile.in.ORIG	Fri Feb  2 08:00:06 2007
--- milter-greylist-4.0a6/Makefile.in	Thu Jun 21 14:01:55 2007
***************
*** 54,60 ****
  
  OBJ= 		milter-greylist.o pending.o sync.o dnsrbl.o list.o macro.o \
  		conf_yacc.o dump_yacc.o conf.o autowhite.o dump.o spf.o \
! 		acl.o urlcheck.o stat.o clock.o geoip.o
  SRC= 		milter-greylist.c pending.c sync.c conf.c macro.c stat.c \
  		clock.c autowhite.c dump.c spf.c acl.c dnsrbl.c list.c \
  		urlcheck.c geoip.c
--- 54,60 ----
  
  OBJ= 		milter-greylist.o pending.o sync.o dnsrbl.o list.o macro.o \
  		conf_yacc.o dump_yacc.o conf.o autowhite.o dump.o spf.o \
! 		acl.o urlcheck.o stat.o clock.o geoip.o file_ext.o
  SRC= 		milter-greylist.c pending.c sync.c conf.c macro.c stat.c \
  		clock.c autowhite.c dump.c spf.c acl.c dnsrbl.c list.c \
  		urlcheck.c geoip.c
*** milter-greylist-4.0a6/conf.c.ORIG	Tue Feb  6 15:29:55 2007
--- milter-greylist-4.0a6/conf.c	Thu Jun 21 13:21:23 2007
***************
*** 75,80 ****
--- 75,81 ----
  #include "dump.h"
  #include "list.h"
  #include "macro.h"
+ #include "file_ext.h"
  #include "milter-greylist.h"
  
  /* #define CONF_DEBUG */
***************
*** 157,165 ****
  		mg_log(LOG_INFO, "%sloading config file \"%s\"", 
  		    conf_cold ? "" : "re", conffile);
  
! 	if ((stream = fopen(conffile, "r")) == NULL) {
  		mg_log(LOG_ERR, "cannot open config file %s: %s", 
! 		    conffile, strerror(errno));
  
  		if (conf_cold)
  			exit(EX_OSERR);
--- 158,167 ----
  		mg_log(LOG_INFO, "%sloading config file \"%s\"", 
  		    conf_cold ? "" : "re", conffile);
  
! 	errno = 0;
! 	if ((stream = Fopen(conffile, "r")) == NULL) {
  		mg_log(LOG_ERR, "cannot open config file %s: %s", 
! 		    conffile, (errno == 0 ? "out of stdio streams" : strerror(errno)) );
  
  		if (conf_cold)
  			exit(EX_OSERR);
***************
*** 190,196 ****
  
  		TSS_SET(conf_key, threadconf);
  
! 		fclose(stream);
  
  		if (!conf_cold || newconf->c_debug) {
  			(void)gettimeofday(&tv2, NULL);
--- 192,198 ----
  
  		TSS_SET(conf_key, threadconf);
  
! 		Fclose(stream);
  
  		if (!conf_cold || newconf->c_debug) {
  			(void)gettimeofday(&tv2, NULL);
*** milter-greylist-4.0a6/dnsrbl.c.ORIG	Mon Mar 26 21:29:04 2007
--- milter-greylist-4.0a6/dnsrbl.c	Thu Jun 21 15:09:39 2007
***************
*** 43,48 ****
--- 43,51 ----
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
+ #ifdef HAVE_STRINGS_H
+ #include <strings.h>            /* bzero, ... */
+ #endif
  #include <syslog.h>
  #include <errno.h>
  #include <sysexits.h>
***************
*** 63,69 ****
  #define NS_MAXMSG	65535
  #endif
  
! #ifdef res_ninit
  #define HAVE_RESN	1
  #ifndef res_ndestroy
  #define res_ndestroy(res)	res_nclose(res)
--- 66,72 ----
  #define NS_MAXMSG	65535
  #endif
  
! #if (defined(res_ninit) || (__RES >= 19991006) )
  #define HAVE_RESN	1
  #ifndef res_ndestroy
  #define res_ndestroy(res)	res_nclose(res)
*** milter-greylist-4.0a6/dump.c.ORIG	Mon Sep  4 23:28:18 2006
--- milter-greylist-4.0a6/dump.c	Thu Jun 21 13:14:57 2007
***************
*** 67,72 ****
--- 67,73 ----
  #include "sync.h"
  #include "dump.h"
  #include "autowhite.h"
+ #include "file_ext.h"
  #include "milter-greylist.h"
  
  /*
***************
*** 245,253 ****
  		exit(EX_OSERR);
  	}
  
! 	if ((dump = fdopen(dumpfd, "w")) == NULL) {
! 		mg_log(LOG_ERR, "cannot write dumpfile \"%s\": %s", 
! 		    newdumpfile, strerror(errno));
  		exit(EX_OSERR);
  	}
  	
--- 246,257 ----
  		exit(EX_OSERR);
  	}
  
! 	errno = 0;
! 	if ((dump = Fdopen(dumpfd, "w")) == NULL) {
!                 mg_log(LOG_ERR, "cannot write dumpfile \"%s\": %s", 
!                     newdumpfile, (errno == 0 ? "out of stdio streams" : strerror(errno) ) );
!                 close(dumpfd);
!                 unlink(newdumpfile);            /* clean up ... */
  		exit(EX_OSERR);
  	}
  	
***************
*** 269,275 ****
  	fprintf(dump, "#\n# Summary: %d records, %d greylisted, %d "
  	    "whitelisted\n#\n", done, greylisted_count, whitelisted_count);
  
! 	fclose(dump);
  	if (s_buffer)
  		free(s_buffer);
  
--- 273,279 ----
  	fprintf(dump, "#\n# Summary: %d records, %d greylisted, %d "
  	    "whitelisted\n#\n", done, greylisted_count, whitelisted_count);
  
! 	Fclose(dump);	/* should close the dumpfd descriptor also */
  	if (s_buffer)
  		free(s_buffer);
  
***************
*** 276,281 ****
--- 280,286 ----
  	if (rename(newdumpfile, conf.c_dumpfile) != 0) {
  		mg_log(LOG_ERR, "cannot replace \"%s\" by \"%s\": %s\n",
  		    conf.c_dumpfile, newdumpfile, strerror(errno));
+                 unlink(newdumpfile);            /* clean up ... */
  		exit(EX_OSERR);
  	}
  
*** milter-greylist-4.0a6/file_ext.c.ORIG	Thu Jun 21 14:04:18 2007
--- milter-greylist-4.0a6/file_ext.c	Fri Jun 15 10:33:19 2007
***************
*** 0 ****
--- 1,364 ----
+ /*
+  * file_ext.c  Stdio stream function replacement for limited stdio implementations
+  *
+  * 2007-06-04 Johann E. Klasek, klasek@zid.tuwien.ac.at
+  *
+  *
+  * Description:
+  *	Some stdio stream implementation suffers from limitation or
+  *	backward compatibility. Especially Solaris 9 and previous
+  *	versions in the LWP32 programming model have a limit in the
+  *	FILE datastructure where the file descriptor field has only
+  *	a width of 8 bits. Therefore stdio streams are only
+  *	capable in handling file descriptors in the range from 0 to 255.
+  *	Some application accessing the FILE structure components directly
+  *	(e.g. the _file field) through the past years. The structure has
+  *	never be change to provide backward compatibility for and prevent 
+  *	breaking existing applications (binaries).
+  *	Even Solaris 9 offers a maximum number of 65536 file descriptors
+  *	only descriptors 0 to 255 can be stored into the FILE structure.
+  *	If descriptor values greater 255 are passed to e.g. fdopen()
+  *	this library function simply fails with errno unset!
+  *
+  *	Solaris 10 offers several solution to cope with this situation
+  *	(based on source or binary applications).
+  *
+  * 	The solution is mainly for versions previous to Solaris 10.
+  *	This module provides a replacement for the functions
+  *	fdopen() and fclose(). The idea is to reserve a pool of
+  *	open descriptors (associated /dev/null)
+  *	with values <256 which are aquired as needed by fdopen_ext().
+  *	On the other hand fclose_ext() tries to return a descriptor
+  *	lower than 256 to the reserved pool. The latter is could not
+  *	assured in all cases because the real fclose() call releases
+  * 	the associated description which could not be reclaimed without
+  *	a delay. A parallel running thread could grab the closed
+  *	descriptor during the delay ...
+  *	The whole system works only in situations where not more
+  *	then 256 streams are used in parallel despite the maximum
+  *	number of open descriptors could grow much greater.
+  *
+  * References:
+  *	http://developers.sun.com/solaris/articles/stdio_256.html
+  *	http://www.science.uva.nl/pub/solaris/solaris2.html
+  *		3.48) How can I increase the number of file descriptors per process?
+  *	http://www.research.att.com/~gsf/download/ref/sfio/sfio.html
+  */
+ 
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <stdlib.h>
+ #include <errno.h>
+ #include <syslog.h>
+ #include <sysexits.h>
+ 
+ #include <string.h>
+ 
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ 
+ #include <stdarg.h>
+ 
+ #include "file_ext.h"
+ 
+ /* size of the pool of low descriptors, from 4 to 256 */
+ #define FD_POOL_SIZE 64
+ 
+ /* an array of free/used descriptors - representing the pool */
+ static char fd_pool[256];
+ 
+ /* the current count of free low descriptors */
+ static int fd_pool_free=0;
+ 
+ #ifdef USE_FD_POOL
+ 
+ /* take logging function from milter-greylist */
+ #include "milter-greylist.h"
+ 
+ #define fe_log mg_log
+ 
+ #else
+ 
+ /* ... otherwise define our own ... */
+ 
+ /* log to syslog if set */
+ static int fe_log_syslog=0;
+ 
+ static
+ /* VARARGS */
+ void
+ fe_log(int level, char *fmt, ...) {
+         va_list ap;
+ 
+         va_start(ap, fmt);
+ 
+         if (! fe_log_syslog) {
+                 vfprintf(stderr, fmt, ap);
+                 fprintf(stderr, "\n");
+         }
+         else
+                 vsyslog(level, fmt, ap);
+ 
+         va_end(ap);
+         return;
+ }
+ 
+ #endif
+ 
+ /* public file which is used to aquire new open descriptors ... */
+ #define FNAME "/dev/null"
+ 
+ 
+ /***
+  *** aquire a new open file descriptor (by means of an open dummy file)
+  ***
+  *** return: >=0 | -1 ... open descriptor | error
+  ***/
+ 
+ int fd_new_desc() {
+ 	int descriptor;
+ 
+         if ((descriptor = open(FNAME, O_RDWR)) < 0) {
+                 fe_log(LOG_ERR, "file_ext: can't create dummy file descriptor file %s: %s", FNAME,
+                         strerror(errno));
+                 return -1;
+         }
+ 	return descriptor;
+ }
+ 
+ 
+ /***
+  *** aquire a new low valued open file descriptor 
+  ***
+  *** return: 0 <= descriptor < 256 
+  ***/
+ 
+ int fd_new_low_desc() {
+ 	int descriptor;
+ 
+         if ((descriptor = fd_new_desc()) >= 256 || descriptor < 0) {
+                 fe_log(LOG_ERR, "file_ext: %s", (descriptor < 0 ? "can't allocate a new descriptor" : "can't allocate small dummy file descriptor (<256) - out of luck!") );
+                 exit(EX_OSERR);	/* fatal situation - must exit */
+         }
+ 	return descriptor;
+ }
+ 
+ 
+ /***
+  *** initialize the module - build up the low file descriptor pool
+  ***
+  *** return: 0
+  ***/
+ 
+ int file_ext_init(void) {
+ 	int i;
+ 	memset(fd_pool,0, sizeof(fd_pool));
+ 
+ 	for(i=0;i<FD_POOL_SIZE;i++) {
+ 	    fd_pool[fd_new_low_desc()] = 1;
+ 	}
+ 
+         fd_pool_free=FD_POOL_SIZE;
+ 
+ 	return 0;
+ }
+ 
+ 
+ /***
+  *** fclose() replacement
+  ***
+  *** return: < 0 | otherwise  ... error | ok
+  ***/
+ 
+ int fclose_ext(FILE *stream) {
+ 
+   int old_descriptor = fileno(stream);
+   int descriptor;
+   int new_descriptor = 0;
+   int ret, err;
+ 
+   if ( old_descriptor < 256 && old_descriptor >=0 ) {
+ 
+ 	if ( fd_pool_free >= FD_POOL_SIZE ) {
+ 		return fclose(stream);	/* pool is full, we dont want a low descriptor back ... */
+ 					/* just pass to the original function */
+ 	}
+ 
+ 	/* we try to get a descriptor >= 256, if not put it back to */
+ 	/* the low file descriptor pool */
+ 	while( (new_descriptor = fd_new_desc()) < 256 && new_descriptor >= 0
+ 	       && fd_pool_free < FD_POOL_SIZE ) {
+ 		if (fd_pool[new_descriptor] == 0) {
+ 			fd_pool[new_descriptor] = 1;
+ 			fd_pool_free++;
+         		fe_log(LOG_INFO, "fclose_ext: adding new descriptor %d into low fd pool", 
+ 				new_descriptor);
+ 		}
+ 		
+ 	}
+ 	if ( new_descriptor < 256 && new_descriptor >= 0 && fd_pool_free >= FD_POOL_SIZE ) {
+ 		close(new_descriptor);  /* not needed anymore ... */
+ 		return fclose(stream);	/* got only low valued descriptor but the pool is full ... */
+ 					/* pass to the original function */
+ 	}
+ 	if ( fd_pool_free >= FD_POOL_SIZE ) {
+ 		close(new_descriptor);  /* not needed anymore ... */
+ 		return fclose(stream);	/* got only low valued descriptor and the pool is full ... */
+ 					/* pass to the original function */
+ 	}
+ 	if ( new_descriptor < 0 ) {
+ 		ret = fclose(stream); /* closes also the descriptor of the stream! */
+ 		err = errno;
+ 		descriptor = fd_new_desc(); /* try to allocate again, after the fclose(), maybe */
+ 						/* we can reclaim the closed descriptor ... */
+ 		if ( descriptor < 0 ) {
+         		fe_log(LOG_ERR, "fclose_ext: fd_new_desc failed: low descriptor %d lost! (%s)",
+ 			old_descriptor, strerror(errno));
+ 		}
+ 	}
+ 	else { /* new_descriptor >= 256 */
+ 
+ 		ret = fclose(stream); /* closes also the descriptor of the stream! */
+ 		err = errno;
+ 		descriptor = dup(new_descriptor); /* grab the closed/returned descriptor - the lowest */
+ 					  /* available descriptor will be aquired - bit of racy ... */
+ 					  /* maybe some other systemcall of another thread is faster */
+ 		if ( descriptor < 0 ) {
+         		fe_log(LOG_ERR, "fclose_ext: dup failed: low descriptor %d lost! (%s)",
+ 			old_descriptor, strerror(errno));
+ 		}
+ 		close(new_descriptor);
+ 	}
+ 	/* but if we are in luck, we got some other low descriptor, not necessarily the one from the */
+ 	/* closed stream */
+ 	if ( descriptor >= 256 ) {
+         	fe_log(LOG_ERR, "fclose_ext: low descriptor %d lost!", old_descriptor);
+ 		close(descriptor);
+ 	}
+ 	else if ( descriptor < 0 ) {
+ 		/* do nothing, an error has been already emitted above */
+ 	}
+ 	else if ( fd_pool[descriptor] == 0 ) {
+ 	    if ( fd_pool_free >= FD_POOL_SIZE ) {
+ 		/* pool already full, we do not need this low descriptor, release it */
+ 		close(descriptor);
+ 	    }
+ 	    else {
+ 		fd_pool[descriptor] = 1;
+ 		fd_pool_free++;
+         	fe_log(LOG_INFO, "fclose_ext: taking descriptor %d back into low fd pool", descriptor);
+ 	    }
+ 
+ 	}
+ 	/* else: fd_pool[descriptor] == 1 : some strangeness, descriptor already marked as */
+ 	/*	released into the FD pool. Should neven happen ... */
+ 
+ 
+ 	errno = err;		/* restore state from original fclose() call */
+ 	return ret;
+   }
+   else return fclose(stream);	/* descriptor not in lower range, let original function handle this case */
+ 
+ }
+ 
+ 
+ /***
+  *** get_pool_desc
+  ***
+  *** return: < 0 | otherwise  ... error | descriptor (in range 0-255)
+  ***/
+ 
+ int get_pool_desc(int desc) {
+ 	int i;
+ 	int fd;
+ 
+ 	if (desc < 0) return desc;
+ 
+ 	for(i=0; i<256; i++) {
+ 		if (fd_pool[i] == 1) {
+ 			/* dup a large fd to a small fd  */
+ 			fd = dup2(desc, i); close(desc);
+ 			fd_pool[i] = 0;
+ 			fd_pool_free--;
+         		fe_log(LOG_INFO, "fdopen_ext: get_pool_desc: descriptor %d reused as %d", desc, i);
+ 			break;
+ 		}
+ 	}
+ 	if (i >= 256 || fd_pool_free == 0) {
+ 		return -1;
+ 	}
+ 	return i;
+ }
+ 
+ 
+ 
+ /***
+  *** fdopen_ext
+  ***
+  *** return: NULL | otherwise  ... error | new opened stream
+  ***/
+ 
+ FILE *fdopen_ext(int fd, char *mode) {
+ 	int descriptor;
+ 
+ 	if (fd >= 256) {
+ 	  /* if we got a non low descriptor, try to map it into to low descriptor pool */
+ 	  descriptor = get_pool_desc(fd);
+ 	  if (descriptor < 0) {
+         		fe_log(LOG_ERR, "fdopen_ext: no free low file descriptor");
+ 			return fdopen(fd, mode);
+ 	  }
+ 	  return fdopen(descriptor, mode);
+ 	}
+ 	return fdopen(fd, mode);
+ 
+ }
+ 
+ 
+ 
+ /***
+  *** fopen_ext
+  ***
+  *** return: NULL | otherwise  ... error | new opened stream
+  ***/
+ 
+ FILE *fopen_ext(char *path, char *mode) {
+ 	int descriptor;
+ 	FILE *stream;
+ 	int err;
+ 
+ 	descriptor = fd_new_desc();
+ 	if (descriptor >= 256) {
+ 		descriptor = get_pool_desc(descriptor);
+ 	}
+ 	if (descriptor < 0) return fopen(path, mode);
+ 
+ 	/* we have a low descriptor */
+ 	close(descriptor); 
+ 
+ 	/* after releasing it, we hope the following fopen() call can aquire it ... */
+ 	stream = fopen(path, mode);
+ 	err = errno;
+ 
+ 	if (stream != NULL) {
+ 		if ( descriptor == fileno(stream) ) {
+ 			/* we are in luck, fopen has successfully aquired our low descriptor ... */
+ 			return stream;
+ 		}
+ 		else {
+ 			/* descriptor missed, some other has taken it, but fopen() successful! */
+ 			fe_log(LOG_INFO, "fopen_ext: descriptor %d lost!", descriptor);
+ 			errno = err;
+ 			return stream;
+ 		}
+ 	}
+ 	else {
+ 		fe_log(LOG_ERR, "fopen_ext: failed and descriptor %d lost!", descriptor);
+ 		errno = err;
+ 		return stream;
+ 	}
+ 
+ 	/* not very safe and can be raced out by other threads which may took the descriptor */
+ 	/* earlier ... :( */
+ }
*** milter-greylist-4.0a6/file_ext.h.ORIG	Thu Jun 21 14:04:27 2007
--- milter-greylist-4.0a6/file_ext.h	Fri Jun  8 14:54:58 2007
***************
*** 0 ****
--- 1,23 ----
+ 
+ 
+ 
+ #ifdef USE_FD_POOL
+ 
+ #include <stdio.h>
+ 
+ extern int file_ext_init(void);
+ extern int fclose_ext(FILE *stream);
+ extern FILE *fdopen_ext(int fd, char *mode);
+ extern FILE *fopen_ext(char *path, char *mode);
+ 
+ # define Fopen(path,mode) fopen_ext(path,mode)
+ # define Fdopen(fd,mode) fdopen_ext(fd,mode)
+ # define Fclose(stream) fclose_ext(stream)
+ 
+ #else
+ 
+ # define Fopen(path,mode) fopen(path,mode)
+ # define Fdopen(fd,mode) fdopen(fd,mode)
+ # define Fclose(stream) fclose(stream)
+ 
+ #endif
*** milter-greylist-4.0a6/milter-greylist.c.ORIG	Tue Jun  5 05:18:21 2007
--- milter-greylist-4.0a6/milter-greylist.c	Thu Jun 21 13:38:46 2007
***************
*** 88,93 ****
--- 88,94 ----
  #include "spf.h"
  #include "autowhite.h"
  #include "stat.h"
+ #include "file_ext.h"
  #include "milter-greylist.h"
  #ifdef USE_DNSRBL
  #include "dnsrbl.h"
***************
*** 1223,1228 ****
--- 1224,1234 ----
  #endif
  	macro_init();
  
+ #ifdef USE_FD_POOL
+         /* initialize file descriptor pool */
+         file_ext_init();
+ #endif
+ 
  	/*
  	 * Load config file
  	 * We can do this without locking exceptlist, as
*** milter-greylist-4.0a6/sync.c.ORIG	Fri Mar 16 04:58:04 2007
--- milter-greylist-4.0a6/sync.c	Thu Jun 21 14:06:59 2007
***************
*** 57,62 ****
--- 57,63 ----
  #include "sync.h"
  #include "conf.h"
  #include "autowhite.h"
+ #include "file_ext.h"
  #include "milter-greylist.h"
  
  #define SYNC_PROTO_CURRENT 3
***************
*** 112,118 ****
  			sync_free(sync);
  			
  		if (peer->p_stream != NULL)
! 			fclose(peer->p_stream);
  
  		LIST_REMOVE(peer, p_list);
  		pthread_mutex_destroy(&peer->p_mtx);
--- 113,119 ----
  			sync_free(sync);
  			
  		if (peer->p_stream != NULL)
! 			Fclose(peer->p_stream);
  
  		LIST_REMOVE(peer, p_list);
  		pthread_mutex_destroy(&peer->p_mtx);
***************
*** 275,281 ****
  		mg_log(LOG_ERR, "closing connexion with peer %s: "
  		    "send buffer would overflow (%d entries queued)", 
  		    peer->p_name, peer->p_qlen);
! 		fclose(peer->p_stream);
  		peer->p_stream = NULL;
  		return -1;
  	}
--- 276,282 ----
  		mg_log(LOG_ERR, "closing connexion with peer %s: "
  		    "send buffer would overflow (%d entries queued)", 
  		    peer->p_name, peer->p_qlen);
! 		Fclose(peer->p_stream);
  		peer->p_stream = NULL;
  		return -1;
  	}
***************
*** 287,293 ****
  		    "complete line \"%s\" - bytes written: %i", 
  		    peer->p_name, strerror(errno), peer->p_qlen, 
  		    line, bw);
! 		fclose(peer->p_stream);
  		peer->p_stream = NULL;
  		return -1;
  	}
--- 288,294 ----
  		    "complete line \"%s\" - bytes written: %i", 
  		    peer->p_name, strerror(errno), peer->p_qlen, 
  		    line, bw);
! 		Fclose(peer->p_stream);
  		peer->p_stream = NULL;
  		return -1;
  	}
***************
*** 305,311 ****
  				mg_log(LOG_ERR, "lost connexion with peer %s: "
  		  		  "%s (%d entries queued)", 
  				    peer->p_name, strerror(errno), peer->p_qlen);
! 				fclose(peer->p_stream);
  				peer->p_stream = NULL;
  				return -1;
  			}
--- 306,312 ----
  				mg_log(LOG_ERR, "lost connexion with peer %s: "
  		  		  "%s (%d entries queued)", 
  				    peer->p_name, strerror(errno), peer->p_qlen);
! 				Fclose(peer->p_stream);
  				peer->p_stream = NULL;
  				return -1;
  			}
***************
*** 314,320 ****
  		mg_log(LOG_ERR, "lost connexion with peer %s: "
  		    "%s (%d entries queued)", 
  		    peer->p_name, strerror(errno), peer->p_qlen);
! 		fclose(peer->p_stream);
  		peer->p_stream = NULL;
  		return -1;
  	}
--- 315,321 ----
  		mg_log(LOG_ERR, "lost connexion with peer %s: "
  		    "%s (%d entries queued)", 
  		    peer->p_name, strerror(errno), peer->p_qlen);
! 		Fclose(peer->p_stream);
  		peer->p_stream = NULL;
  		return -1;
  	}
***************
*** 330,336 ****
  		mg_log(LOG_ERR, "Unexpected reply \"%s\" from %s, "
  		    "closing connexion (%d entries queued)", 
  		    line, peer->p_name, peer->p_qlen);
! 		fclose(peer->p_stream);
  		peer->p_stream = NULL;
  		return -1;
  	}
--- 331,337 ----
  		mg_log(LOG_ERR, "Unexpected reply \"%s\" from %s, "
  		    "closing connexion (%d entries queued)", 
  		    line, peer->p_name, peer->p_qlen);
! 		Fclose(peer->p_stream);
  		peer->p_stream = NULL;
  		return -1;
  	}
***************
*** 340,346 ****
  		mg_log(LOG_ERR, "Unexpected reply \"%s\" from %s, "
  		    "closing connexion (%d entries queued)", 
  		    line, peer->p_name, peer->p_qlen);
! 		fclose(peer->p_stream);
  		peer->p_stream = NULL;
  		return -1;
  	}
--- 341,347 ----
  		mg_log(LOG_ERR, "Unexpected reply \"%s\" from %s, "
  		    "closing connexion (%d entries queued)", 
  		    line, peer->p_name, peer->p_qlen);
! 		Fclose(peer->p_stream);
  		peer->p_stream = NULL;
  		return -1;
  	}
***************
*** 533,546 ****
  		    peer->p_name, strerror(errno));
  	}
  
! 	if ((stream = fdopen(s, "w+")) == NULL) {
  		mg_log(LOG_ERR, "cannot sync with peer %s, "
  		    "fdopen failed: %s (%d entries queued)", 
! 		    peer->p_name, strerror(errno), peer->p_qlen);
  		close(s);
  		return -1;
  	}
  
  	if (setvbuf(stream, NULL, _IOLBF, 0) != 0)
  		mg_log(LOG_ERR, "cannot set line buffering with peer %s: %s", 
  		    peer->p_name, strerror(errno));
--- 534,553 ----
  		    peer->p_name, strerror(errno));
  	}
  
! 	errno = 0;
! 	if ((stream = Fdopen(s, "w+")) == NULL) {
  		mg_log(LOG_ERR, "cannot sync with peer %s, "
  		    "fdopen failed: %s (%d entries queued)", 
! 		    peer->p_name, (errno == 0 ? "out of stdio streams" : strerror(errno)), 
! 		    peer->p_qlen);
  		close(s);
  		return -1;
  	}
  
+ #ifdef USE_FD_POOL
+ 	s = fileno(stream);     /* the socket descriptor could have been replaced by Fdopen() ! */
+ #endif
+ 
  	if (setvbuf(stream, NULL, _IOLBF, 0) != 0)
  		mg_log(LOG_ERR, "cannot set line buffering with peer %s: %s", 
  		    peer->p_name, strerror(errno));
***************
*** 586,592 ****
  	return 0;
  
  bad:
! 	fclose(stream);
  	peer->p_stream = NULL;
  
  	return -1;
--- 593,599 ----
  	return 0;
  
  bad:
! 	Fclose(stream);
  	peer->p_stream = NULL;
  
  	return -1;
***************
*** 704,712 ****
  			mg_log(LOG_ERR, "incoming connexion "
  			    "failed: %s", strerror(errno));
  
! 			if (errno != ECONNABORTED)
! 				exit(EX_OSERR);
! 			continue;
  		}
  		unmappedaddr(SA(&raddr), &raddrlen);
  
--- 711,744 ----
  			mg_log(LOG_ERR, "incoming connexion "
  			    "failed: %s", strerror(errno));
  
!                         if ( 0
! #ifdef EAGAIN
!                             || errno == EAGAIN
! #endif /* EAGAIN */
! #ifdef ECONNABORTED
!                             || errno == ECONNABORTED
! #endif /* ECONNABORTED */
! #ifdef EMFILE
!                             || errno == EMFILE
! #endif /* EMFILE */
! #ifdef ENFILE
!                             || errno == ENFILE
! #endif /* ENFILE */
! #ifdef ENOBUFS
!                             || errno == ENOBUFS
! #endif /* ENOBUFS */
! #ifdef ENOMEM
!                             || errno == ENOMEM
! #endif /* ENOMEM */
! #ifdef ENOSR
!                             || errno == ENOSR
! #endif /* ENOSR */
! #ifdef EWOULDBLOCK
!                             || errno == EWOULDBLOCK
! #endif /* EWOULDBLOCK */
!                         ) continue;
!                         exit(EX_OSERR);
! 
  		}
  		unmappedaddr(SA(&raddr), &raddrlen);
  
***************
*** 738,744 ****
  			fprintf(stream, "105 No more peers, shutting down!\n");
  
  			PEER_UNLOCK;
! 			fclose(stream);
  			pthread_mutex_lock(&sync_master_lock);
  			close(sms->sock);
  			sms->sock = -1;
--- 770,776 ----
  			fprintf(stream, "105 No more peers, shutting down!\n");
  
  			PEER_UNLOCK;
! 			Fclose(stream);
  			pthread_mutex_lock(&sync_master_lock);
  			close(sms->sock);
  			sms->sock = -1;
***************
*** 796,802 ****
  			    peerstr);
  			fprintf(stream, 
  			    "106 You have no permission to talk, go away!\n");
! 			fclose(stream);
  			continue;
  		}
  
--- 828,834 ----
  			    peerstr);
  			fprintf(stream, 
  			    "106 You have no permission to talk, go away!\n");
! 			Fclose(stream);
  			continue;
  		}
  
***************
*** 805,811 ****
  			mg_log(LOG_ERR, "incoming connexion from %s failed, "
  			    "pthread_create failed: %s", 
  			    peerstr, strerror(error));
! 			fclose(stream);
  			continue;
  		}
  		if ((error = pthread_detach(tid)) != 0) {
--- 837,843 ----
  			mg_log(LOG_ERR, "incoming connexion from %s failed, "
  			    "pthread_create failed: %s", 
  			    peerstr, strerror(error));
! 			Fclose(stream);
  			continue;
  		}
  		if ((error = pthread_detach(tid)) != 0) {
***************
*** 1170,1176 ****
  	}
  
  	fprintf(stream, "202 Good bye\n");
! 	fclose(stream);
  
  	conf_release();
  
--- 1202,1208 ----
  	}
  
  	fprintf(stream, "202 Good bye\n");
! 	Fclose(stream);
  
  	conf_release();
  
