diff -Naur stunnel-4.05/src/client.c stunnel-4.05.with.poll.steven/src/client.c
--- stunnel-4.05/src/client.c	2004-02-10 20:17:54.000000000 +0100
+++ stunnel-4.05.with.poll.steven/src/client.c	2004-04-01 15:42:01.000000000 +0200
@@ -132,19 +132,29 @@
 
     if(init_local(c))
         return -1;
+
     if(!options.option.client && !c->opt->protocol) {
+
         /* Server mode and no protocol negotiation needed */
         if(init_ssl(c))
+	{
             return -1;
+	}
         if(init_remote(c))
+	{
             return -1;
+	}
+
+
     } else {
+
         if(init_remote(c))
             return -1;
         if(negotiate(c)<0) {
             log(LOG_ERR, "Protocol negotiations failed");
             return -1;
         }
+
         if(init_ssl(c))
             return -1;
     }
@@ -213,6 +223,8 @@
             free(c->resolved_addresses);
     } else /* NOT in remote mode */
         fd=connect_local(c);
+
+
     if(fd<0) {
         log(LOG_ERR, "Failed to initialize remote connection");
         return -1;
@@ -230,16 +242,20 @@
     c->remote_fd.is_socket=1; /* Always! */
     if(set_socket_options(fd, 2)<0)
         return -1;
+
+
     return 0; /* OK */
 }
 
 static int init_ssl(CLI *c) {
     int i, err;
 
+
     if(!(c->ssl=SSL_new(ctx))) {
         sslerror("SSL_new");
         return -1;
     }
+
 #if SSLEAY_VERSION_NUMBER >= 0x0922
     SSL_set_session_id_context(c->ssl, sid_ctx, strlen(sid_ctx));
 #endif
@@ -273,6 +289,7 @@
     }
 
     while(1) {
+
         if(options.option.client)
             i=SSL_connect(c->ssl);
         else
@@ -307,6 +324,302 @@
     return 0; /* OK */
 }
 
+#ifdef USE_POLL_NOT_SELECT
+
+static int transfer(CLI *c) { /* transfer data */
+    struct poll_fdset rw_set;
+    int num, err;
+    int check_SSL_pending;
+    int ssl_closing;
+        /* 0=not closing SSL, 1=initiate SSL_shutdown,
+         * 2=retry SSL_shutdown, 3=SSL_shutdown done */
+    int ready;
+    int timeout = 0;
+    
+    int returnvalue = -1;
+
+
+    POLL_FDSET_INIT(&rw_set);	
+
+    c->sock_ptr=c->ssl_ptr=0;
+    sock_rd=sock_wr=ssl_rd=ssl_wr=1;
+    c->sock_bytes=c->ssl_bytes=0;
+    ssl_closing=0;
+
+    while(((sock_rd||c->sock_ptr)&&ssl_wr)||((ssl_rd||c->ssl_ptr)&&sock_wr)) {
+
+        POLL_FD_ZERO(&rw_set); /* Setup rd_set */
+        if(sock_rd && c->sock_ptr<BUFFSIZE) /* socket input buffer not full*/
+            POLL_FD_SET(c->sock_rfd->fd, &rw_set, POLL_READ_FLAGS);
+        if(ssl_rd && (
+                c->ssl_ptr<BUFFSIZE || /* SSL input buffer not full */
+                ((c->sock_ptr||ssl_closing) && SSL_want_read(c->ssl))
+                /* I want to SSL_write or SSL_shutdown but read from the
+                 * underlying socket needed for the SSL protocol */
+                )) {
+            POLL_FD_SET(c->ssl_rfd->fd, &rw_set, POLL_READ_FLAGS);
+        }
+
+        if(sock_wr && c->ssl_ptr) /* SSL input buffer not empty */
+            POLL_FD_SET(c->sock_wfd->fd, &rw_set, POLL_WRITE_FLAGS);
+        if (ssl_wr && (
+                c->sock_ptr || /* socket input buffer not empty */
+                ssl_closing==1 || /* initiate SSL_shutdown */
+                ((c->ssl_ptr<BUFFSIZE || ssl_closing==2) &&
+                    SSL_want_write(c->ssl))
+                /* I want to SSL_read or SSL_shutdown but write to the
+                 * underlying socket needed for the SSL protocol */
+                )) {
+            POLL_FD_SET(c->ssl_wfd->fd, &rw_set, POLL_WRITE_FLAGS);
+        }
+
+        timeout = 1000 * (sock_rd ||
+            (ssl_wr&&c->sock_ptr) || (sock_wr&&c->ssl_ptr) ?
+            c->opt->timeout_idle : c->opt->timeout_close);
+
+        ready=spoll(&rw_set, timeout); 
+
+        if(ready<0) { /* Break the connection for others */
+            sockerror("select");
+            returnvalue = -1; goto cleanup;
+        }
+        if(!ready) { /* Timeout */
+            if(sock_rd) { /* No traffic for a long time */
+                log(LOG_DEBUG, "select timeout: connection reset");
+                returnvalue = -1; goto cleanup;
+            } else { /* Timeout waiting for SSL close_notify */
+                log(LOG_DEBUG, "select timeout waiting for SSL close_notify");
+                break; /* Leave the while() loop */
+            }
+        }
+
+        if(ssl_closing==1 /* initiate SSL_shutdown */ || (ssl_closing==2 && (
+                (SSL_want_read(c->ssl) && POLL_FD_ISSET(c->ssl_rfd->fd, &rw_set,POLL_READ_FLAGS)) ||
+                (SSL_want_write(c->ssl) && POLL_FD_ISSET(c->ssl_wfd->fd, &rw_set, POLL_WRITE_FLAGS))
+                ))) {
+
+            switch(SSL_shutdown(c->ssl)) { /* Send close_notify */
+            case 1: /* the shutdown was successfully completed */
+                log(LOG_INFO, "SSL_shutdown successfully sent close_notify");
+                ssl_wr=0; /* SSL write closed */
+                /* TODO: It's not really closed.  We need to distinguish
+                 * closed SSL and closed underlying file descriptor */
+                ssl_closing=3; /* done! */
+                break;
+            case 0: /* the shutdown is not yet finished */
+                log(LOG_DEBUG, "SSL_shutdown retrying");
+                ssl_closing=2; /* next time just retry SSL_shutdown */
+                break;
+            case -1: /* a fatal error occurred */
+                sslerror("SSL_shutdown");
+                returnvalue = -1; goto cleanup;
+            }
+        }
+
+        /* Set flag to try and read any buffered SSL data if we made */
+        /* room in the buffer by writing to the socket */
+        check_SSL_pending = 0;
+
+        if(sock_wr && POLL_FD_ISSET(c->sock_wfd->fd, &rw_set,POLL_WRITE_FLAGS)) {
+            switch(num=writesocket(c->sock_wfd->fd, c->ssl_buff, c->ssl_ptr)) {
+            case -1: /* error */
+                switch(get_last_socket_error()) {
+                case EINTR:
+                    log(LOG_DEBUG,
+                        "writesocket interrupted by a signal: retrying");
+                    break;
+                case EWOULDBLOCK:
+                    log(LOG_NOTICE, "writesocket would block: retrying");
+                    break;
+                default:
+                    sockerror("writesocket");
+                    returnvalue = -1; goto cleanup;
+                }
+                break;
+            case 0:
+                log(LOG_DEBUG, "No data written to the socket: retrying");
+                break;
+            default:
+                memmove(c->ssl_buff, c->ssl_buff+num, c->ssl_ptr-num);
+                if(c->ssl_ptr==BUFFSIZE)
+                    check_SSL_pending=1;
+                c->ssl_ptr-=num;
+                c->sock_bytes+=num;
+                if(!ssl_rd && !c->ssl_ptr) {
+                    shutdown(c->sock_wfd->fd, SHUT_WR);
+                    log(LOG_DEBUG,
+                        "Socket write shutdown (no more data to send)");
+                    sock_wr=0;
+                }
+            }
+        }
+
+        if(ssl_wr && ( /* SSL sockets are still open */
+                (c->sock_ptr && POLL_FD_ISSET(c->ssl_wfd->fd, &rw_set,POLL_WRITE_FLAGS)) ||
+                /* See if application data can be written */
+                (SSL_want_read(c->ssl) && POLL_FD_ISSET(c->ssl_rfd->fd, &rw_set,POLL_READ_FLAGS))
+                /* I want to SSL_write but read from the underlying */
+                /* socket needed for the SSL protocol */
+                )) {
+            num=SSL_write(c->ssl, c->sock_buff, c->sock_ptr);
+
+            err=SSL_get_error(c->ssl, num);
+            switch(err) {
+            case SSL_ERROR_NONE:
+                memmove(c->sock_buff, c->sock_buff+num, c->sock_ptr-num);
+                c->sock_ptr-=num;
+                c->ssl_bytes+=num;
+                if(!ssl_closing && !sock_rd && !c->sock_ptr && ssl_wr) {
+                    log(LOG_DEBUG,
+                        "SSL write shutdown (no more data to send)");
+                    ssl_closing=1;
+                }
+                break;
+            case SSL_ERROR_WANT_WRITE:
+            case SSL_ERROR_WANT_READ:
+            case SSL_ERROR_WANT_X509_LOOKUP:
+                log(LOG_DEBUG, "SSL_write returned WANT_: retrying");
+                break;
+            case SSL_ERROR_SYSCALL:
+                if(num<0) { /* really an error */
+                    switch(get_last_socket_error()) {
+                    case EINTR:
+                        log(LOG_DEBUG,
+                            "SSL_write interrupted by a signal: retrying");
+                        break;
+                    case EAGAIN:
+                        log(LOG_DEBUG,
+                            "SSL_write returned EAGAIN: retrying");
+                        break; 
+                    default:
+                        sockerror("SSL_write (ERROR_SYSCALL)");
+                        returnvalue = -1; goto cleanup;
+                    }
+                }
+                break;
+            case SSL_ERROR_ZERO_RETURN: /* close_notify received */
+                log(LOG_DEBUG, "SSL closed on SSL_write");
+                ssl_rd=ssl_wr=0;
+                break;
+            case SSL_ERROR_SSL:
+                sslerror("SSL_write");
+                returnvalue = -1; goto cleanup;
+            default:
+                log(LOG_ERR, "SSL_write/SSL_get_error returned %d", err);
+                returnvalue = -1; goto cleanup;
+            }
+        }
+
+        if(sock_rd && POLL_FD_ISSET(c->sock_rfd->fd, &rw_set,POLL_READ_FLAGS)) {
+            switch(num=readsocket(c->sock_rfd->fd,
+                c->sock_buff+c->sock_ptr, BUFFSIZE-c->sock_ptr)) {
+            case -1:
+                switch(get_last_socket_error()) {
+                case EINTR:
+                    log(LOG_DEBUG,
+                        "readsocket interrupted by a signal: retrying");
+                    break;
+                case EWOULDBLOCK:
+                    log(LOG_NOTICE, "readsocket would block: retrying");
+                    break;
+                default:
+                    sockerror("readsocket");
+                    returnvalue = -1; goto cleanup;
+                }
+                break;
+            case 0: /* close */
+                log(LOG_DEBUG, "Socket closed on read");
+                sock_rd=0;
+                if(!ssl_closing && !c->sock_ptr && ssl_wr) {
+                    log(LOG_DEBUG,
+                        "SSL write shutdown (output buffer empty)");
+                    ssl_closing=1;
+                }
+                break;
+            default:
+                c->sock_ptr+=num;
+            }
+        }
+
+        if(ssl_rd && ( /* SSL sockets are still open */
+                (c->ssl_ptr<BUFFSIZE && POLL_FD_ISSET(c->ssl_rfd->fd, &rw_set,POLL_READ_FLAGS)) ||
+                /* See if there's any application data coming in */
+                (SSL_want_write(c->ssl) && POLL_FD_ISSET(c->ssl_wfd->fd, &rw_set,POLL_WRITE_FLAGS)) ||
+                /* I want to SSL_read but write to the underlying */
+                /* socket needed for the SSL protocol */
+                (check_SSL_pending && SSL_pending(c->ssl))
+                /* Write made space from full buffer */
+                )) {
+            num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr);
+
+            err=SSL_get_error(c->ssl, num);
+            switch(err) {
+            case SSL_ERROR_NONE:
+                c->ssl_ptr+=num;
+                break;
+            case SSL_ERROR_WANT_WRITE:
+            case SSL_ERROR_WANT_READ:
+            case SSL_ERROR_WANT_X509_LOOKUP:
+                log(LOG_DEBUG, "SSL_read returned WANT_: retrying");
+                break;
+            case SSL_ERROR_SYSCALL:
+                if(num<0) { /* not EOF */
+                    switch(get_last_socket_error()) {
+                    case EINTR:
+                        log(LOG_DEBUG,
+                            "SSL_read interrupted by a signal: retrying");
+                        break;
+                    case EAGAIN:
+                        log(LOG_DEBUG,
+                            "SSL_read returned EAGAIN: retrying");
+                        break; 
+                    default:
+                        sockerror("SSL_read (ERROR_SYSCALL)");
+                        returnvalue = -1; goto cleanup;
+                    }
+                } else { /* EOF */
+                    log(LOG_DEBUG, "SSL socket closed on SSL_read");
+                    ssl_rd=ssl_wr=0;
+                }
+                break;
+            case SSL_ERROR_ZERO_RETURN: /* close_notify received */
+                log(LOG_DEBUG, "SSL closed on SSL_read");
+                ssl_rd=0;
+                if(!ssl_closing && !c->sock_ptr && ssl_wr) {
+                    log(LOG_DEBUG,
+                        "SSL write shutdown (output buffer empty)");
+                    ssl_closing=1;
+                }
+                if(!c->ssl_ptr && sock_wr) {
+                    shutdown(c->sock_wfd->fd, SHUT_WR);
+                    log(LOG_DEBUG,
+                        "Socket write shutdown (output buffer empty)");
+                    sock_wr=0;
+                }
+                break;
+            case SSL_ERROR_SSL:
+                sslerror("SSL_read");
+                returnvalue = -1; goto cleanup;
+            default:
+                log(LOG_ERR, "SSL_read/SSL_get_error returned %d", err);
+                returnvalue = -1; goto cleanup;
+            }
+        }
+    }
+
+    returnvalue = 0; /* OK */ goto cleanup;
+
+cleanup:
+
+    /* free the set */
+    POLL_FD_ZERO(&rw_set);
+
+    return returnvalue;
+}
+
+
+#else
+
 static int transfer(CLI *c) { /* transfer data */
     fd_set rd_set, wr_set;
     int num, err, fdno;
@@ -592,6 +905,8 @@
     return 0; /* OK */
 }
 
+#endif /* USE_POLL_NOT_SELECT */
+
 static void cleanup(CLI *c, int error) {
         /* Cleanup SSL */
     if(c->ssl) { /* SSL initialized */
diff -Naur stunnel-4.05/src/common.h stunnel-4.05.with.poll.steven/src/common.h
--- stunnel-4.05/src/common.h	2004-02-14 13:20:08.000000000 +0100
+++ stunnel-4.05.with.poll.steven/src/common.h	2004-04-05 18:04:24.000000000 +0200
@@ -266,6 +266,186 @@
 #define safename(s) \
     do {char *p; for(p=(s); *p; p++) if(!isalnum((int)*p)) *p='.';} while(0)
 
+
+#define USE_POLL_NOT_SELECT 1
+
+
+#ifdef USE_POLL_NOT_SELECT
+# define __USE_XOPEN
+# include <sys/poll.h>
+
+struct poll_fdset
+{
+        struct pollfd *fds;
+        int count;
+};
+
+#include "prototypes.h"
+#define POLL_READ_FLAGS         (POLLIN)// | POLLPRI | POLLRDNORM | POLLRDBAND)
+#define POLL_WRITE_FLAGS        (POLLOUT)// | POLLWRNORM | POLLWRBAND)
+
+/* binary search */
+static int find_poll_fd_index(int fd,struct poll_fdset *set)
+{
+	int start, end, current;
+
+	start = 0;
+	end = set->count - 1;
+
+	if(!set->fds)
+		return -1;
+
+	while(end - start > 0)
+	{
+		current = (start + end) / 2;
+
+		if(set->fds[current].fd == fd)
+		{
+			return current;
+		}
+		else if (set->fds[current].fd < fd)
+		{
+			start = current + 1;
+		}
+		else
+		{
+			end = current - 1;
+		}
+	}
+
+	if(set->fds[start].fd == fd)
+		return start;
+
+	return -1;
+}
+
+/* find the place where fd needs to be inserted */
+static int find_smallest_bigger_poll_fd_index(int fd,struct poll_fdset *set)
+{
+	int start, end, current;
+
+	start = 0;
+	end = set->count - 1;
+
+	if(!set->fds)
+		return 0;
+
+	while(end - start > 0)
+	{
+		current = (start + end) / 2;
+
+		if(set->fds[current].fd == fd)
+		{
+			return current + 1;
+		}
+		else if (set->fds[current].fd < fd)
+		{
+			start = current + 1;
+		}
+		else
+		{
+			end = current - 1;
+		}
+	}
+
+	if(set->fds[start].fd < fd)
+		return start+1;
+	else
+		return start;
+}
+
+static int POLL_FD_ISSET(int fd, struct poll_fdset *set, int flags)
+{
+        int i;
+	int result;
+
+	if((i = find_poll_fd_index(fd,set)) < 0)
+	{
+		//printf("POLL_FD_SET(): testing fd %d for flag %d -> FD NOT FOUND !!!!!!!\n",fd,flags);
+		return 0;
+	}
+
+	return (set->fds[i].revents & flags);
+}
+
+static void POLL_FD_SET(int fd, struct poll_fdset *set, int flags)
+{
+	int i;
+	struct pollfd *tmp = NULL;
+	
+        if(!set)
+                return;
+
+	if((i = find_poll_fd_index(fd,set)) >= 0)
+	{
+		set->fds[i].events |= flags;
+		return;
+	}
+	
+	/* fd not in set yet, add it */
+
+	i = find_smallest_bigger_poll_fd_index(fd,set);
+
+	/* i is now the index of the slot where we have to insert this fd */
+	
+        set->count++;
+        set->fds = (struct pollfd *)realloc(set->fds,set->count * sizeof(struct pollfd));
+	tmp = (struct pollfd *)malloc(set->count * sizeof(struct pollfd));
+	
+        if(!set->fds)
+        {
+                log(LOG_ERR, "POLL_FD_SET(): realloc failed!");
+                return;
+        }
+
+	if(i < set->count - 1)
+	{
+		/* move the old data */
+		/* copy to temp buffer and back to the set, but shifted by 1 slot */
+		memcpy(tmp, &(set->fds[i]), (set->count - i - 1) * sizeof(struct pollfd));
+		memcpy(&(set->fds[i+1]), tmp, (set->count - i - 1) * sizeof(struct pollfd));
+	}
+	
+        set->fds[i].fd = fd;
+        set->fds[i].events = flags;
+        set->fds[i].revents = 0;
+
+	free(tmp);
+}
+
+static void POLL_FDSET_INIT(struct poll_fdset *set)
+{
+	memset(set,0,sizeof(struct poll_fdset));
+}
+
+static void POLL_FD_ZERO(struct poll_fdset *set)
+{
+        if(!set)
+                return;
+
+        if(set->fds) free(set->fds);
+
+        set->fds = NULL;
+        set->count = 0;
+}
+
+static void POLL_COPY_SET(struct poll_fdset *to,struct poll_fdset *from)
+{
+	POLL_FD_ZERO(to);
+
+	to->fds = (struct pollfd *)malloc(from->count * sizeof(struct pollfd));
+	if(!to->fds)
+	{
+		log(LOG_ERR, "POLL_COPY_SET(): malloc failed!");
+		return;
+	}
+	
+	memcpy(to->fds,from->fds,from->count * sizeof(struct pollfd));
+	to->count = from->count;
+}
+
+#endif /* USE_POLL_NOT_SELECT */
+    
 #endif /* defined COMMON_H */
 
 /* End of common.h */
diff -Naur stunnel-4.05/src/protocol.c stunnel-4.05.with.poll.steven/src/protocol.c
--- stunnel-4.05/src/protocol.c	2004-01-25 18:18:34.000000000 +0100
+++ stunnel-4.05.with.poll.steven/src/protocol.c	2004-04-01 15:42:20.000000000 +0200
@@ -260,6 +260,21 @@
 }
 
 static int RFC2487(int fd) {
+
+#ifdef USE_POLL_NOT_SELECT
+	struct poll_fdset fdsRead;
+	int result;
+
+	POLL_FDSET_INIT(&fdsRead);
+	POLL_FD_ZERO(&fdsRead);
+	POLL_FD_SET(fd, &fdsRead, POLL_READ_FLAGS);
+	
+	result = spoll(&fdsRead,0);
+
+	POLL_FD_ZERO(&fdsRead); // free it
+
+	switch(result) {
+#else
     fd_set         fdsRead;
     struct timeval timeout;
 
@@ -268,6 +283,9 @@
     timeout.tv_sec=timeout.tv_usec=0; /* don't wait */
 
     switch(sselect(fd+1, &fdsRead, NULL, NULL, &timeout)) {
+
+#endif
+	    
     case 0: /* fd not ready to read */
         log(LOG_DEBUG, "RFC 2487 detected");
         return 1;
diff -Naur stunnel-4.05/src/prototypes.h stunnel-4.05.with.poll.steven/src/prototypes.h
--- stunnel-4.05/src/prototypes.h	2004-02-10 20:15:05.000000000 +0100
+++ stunnel-4.05.with.poll.steven/src/prototypes.h	2004-04-01 15:13:53.000000000 +0200
@@ -256,12 +256,22 @@
 
 /**************************************** Prototypes for select.c */
 
+#ifdef USE_POLL_NOT_SELECT
+int spoll(struct poll_fdset *, int);
+int waitforsocket(int, int, int);
+#ifndef USE_WIN32
+void spoll_init(struct poll_fdset *);
+void exec_status(void);
+#endif
+#else
 int sselect(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 int waitforsocket(int, int, int);
 #ifndef USE_WIN32
 void sselect_init(fd_set *, int *);
 void exec_status(void);
 #endif
+#endif /* USE_POLL_NOT_SELECT */
+
 int write_blocking(CLI *, int fd, u8 *, int);
 int read_blocking(CLI *, int fd, u8 *, int);
 /* descriptor versions of fprintf/fscanf */
diff -Naur stunnel-4.05/src/sselect.c stunnel-4.05.with.poll.steven/src/sselect.c
--- stunnel-4.05/src/sselect.c	2004-01-25 18:18:07.000000000 +0100
+++ stunnel-4.05.with.poll.steven/src/sselect.c	2004-04-01 15:43:35.000000000 +0200
@@ -52,6 +52,29 @@
 
 #endif
 
+#ifdef USE_POLL_NOT_SELECT
+void spoll_init(struct poll_fdset *set) 
+{
+    if(pipe(signal_pipe)) 
+    {
+        ioerror("pipe");
+        exit(1);
+    }
+    
+    alloc_fd(signal_pipe[0]);
+    alloc_fd(signal_pipe[1]);
+#ifdef FD_CLOEXEC
+    /* close the pipe in child execvp */
+    fcntl(signal_pipe[0], F_SETFD, FD_CLOEXEC);
+    fcntl(signal_pipe[1], F_SETFD, FD_CLOEXEC);
+#endif
+    
+    POLL_FD_SET(signal_pipe[0], set, POLL_READ_FLAGS);
+    signal(SIGCHLD, sigchld_handler);
+}
+
+#else
+
 void sselect_init(fd_set *set, int *n) {
     if(pipe(signal_pipe)) {
         ioerror("pipe");
@@ -70,8 +93,34 @@
     signal(SIGCHLD, sigchld_handler);
 }
 
+#endif /* USE_POLL_NOT_SELECT */
 #endif /* USE_WIN32 */
 
+
+#ifdef USE_POLL_NOT_SELECT
+int spoll(struct poll_fdset *set, int timeout) 
+{
+    int retval;
+
+	    if (0 > read(signal_pipe[0], signal_buffer, sizeof(signal_buffer))) 
+	    {	
+#ifdef USE_PTHREAD
+			    exec_status(); /* Report status of 'exec' process */
+#endif /* USE_PTHREAD */
+#ifdef USE_FORK
+			    client_status(); /* Report status of client process */
+#endif /* USE_FORK */
+	    }
+	    
+    do 
+    { /* Skip "Interrupted system call" errors */
+	    retval = poll(set->fds, set->count, timeout);
+    } 
+    while(retval<0 && get_last_socket_error()==EINTR);
+    return retval;
+}
+
+#else
 int sselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
         struct timeval *timeout) {
     int retval;
@@ -99,9 +148,27 @@
     } while(retval<0 && get_last_socket_error()==EINTR);
     return retval;
 }
+#endif /* USE_POLL_NOT_SELECT */
 
 int waitforsocket(int fd, int dir, int timeout) {
     /* dir: 0 for read, 1 for write */
+
+#ifdef USE_POLL_NOT_SELECT
+	struct pollfd set;
+	int ready;
+
+	log(LOG_DEBUG, "waitforsocket: FD=%d, DIR=%s", fd, dir ? "write" : "read");
+
+	set.fd = fd;
+	if(dir) /* write */
+		set.events = POLL_WRITE_FLAGS;
+	else /* read */
+		set.events = POLL_READ_FLAGS;
+	
+	set.revents = 0;
+
+	ready = poll(&set, 1, 1000 * timeout);
+#else
     struct timeval tv;
     fd_set set;
     int ready;
@@ -112,6 +179,7 @@
     tv.tv_sec=timeout;
     tv.tv_usec=0;
     ready=sselect(fd+1, dir ? NULL : &set, dir ? &set : NULL, NULL, &tv);
+#endif /* USE_POLL_NOT_SELECT */
     switch(ready) {
     case -1:
         sockerror("waitforsocket");
diff -Naur stunnel-4.05/src/stunnel.c stunnel-4.05.with.poll.steven/src/stunnel.c
--- stunnel-4.05/src/stunnel.c	2004-02-14 15:12:27.000000000 +0100
+++ stunnel-4.05.with.poll.steven/src/stunnel.c	2004-04-05 15:46:48.000000000 +0200
@@ -116,6 +116,101 @@
     log_close();
 }
 
+#ifdef USE_POLL_NOT_SELECT
+
+static void daemon_loop(void) {
+    struct sockaddr_in addr;
+    struct poll_fdset base_set, current_set;
+    LOCAL_OPTIONS *opt;
+
+    get_limits();
+    POLL_FDSET_INIT(&base_set);
+    POLL_FDSET_INIT(&current_set);
+
+    POLL_FD_ZERO(&base_set);
+    if(!local_options.next) {
+        log(LOG_ERR, "No connections defined in config file");
+        exit(1);
+    }
+
+    num_clients=0;
+
+
+    /* bind local ports */
+    for(opt=local_options.next; opt; opt=opt->next) {
+        if(!opt->option.accept) /* no need to bind this service */
+            continue;
+        if((opt->fd=socket(AF_INET, SOCK_STREAM, 0))<0) {
+            sockerror("local socket");
+            exit(1);
+        }
+        if(alloc_fd(opt->fd))
+            exit(1);
+        if(set_socket_options(opt->fd, 0)<0)
+            exit(1);
+        memset(&addr, 0, sizeof(addr));
+        addr.sin_family=AF_INET;
+        addr.sin_addr.s_addr=*opt->localnames;
+        addr.sin_port=opt->localport;
+        safe_ntoa(opt->local_address, addr.sin_addr);
+        if(bind(opt->fd, (struct sockaddr *)&addr, sizeof(addr))) {
+            log(LOG_ERR, "Error binding %s to %s:%d", opt->servname,
+                opt->local_address, ntohs(addr.sin_port));
+            sockerror("bind");
+            exit(1);
+        }
+        log(LOG_DEBUG, "%s bound to %s:%d", opt->servname,
+            opt->local_address, ntohs(addr.sin_port));
+        if(listen(opt->fd, 5)) {
+            sockerror("listen");
+            exit(1);
+        }
+#ifdef FD_CLOEXEC
+        fcntl(opt->fd, F_SETFD, FD_CLOEXEC); /* close socket in child execvp */
+#endif
+        POLL_FD_SET(opt->fd, &base_set,POLL_READ_FLAGS); 
+    }
+
+#ifndef USE_WIN32
+    spoll_init(&base_set);
+#endif
+
+
+#if !defined (USE_WIN32) && !defined (__vms)
+    if(!(options.option.foreground))
+        daemonize();
+    drop_privileges();
+    create_pid();
+#endif /* !defined USE_WIN32 && !defined (__vms) */
+
+    /* create exec+connect services */
+    for(opt=local_options.next; opt; opt=opt->next) {
+        if(opt->option.accept) /* skip ordinary (accepting) services */
+            continue;
+        enter_critical_section(CRIT_CLIENTS); /* for multi-cpu machines */
+        num_clients++;
+        leave_critical_section(CRIT_CLIENTS);
+        create_client(-1, -1, alloc_client_session(opt, -1, -1), client);
+    }
+
+    while(1) {
+
+	POLL_COPY_SET(&current_set, &base_set);
+        if(spoll(&current_set, -1)<0) 
+            /* non-critical error */
+            log_error(LOG_INFO, get_last_socket_error(), "main loop select");
+        else 
+	{
+            for(opt=local_options.next; opt; opt=opt->next)
+                if(POLL_FD_ISSET(opt->fd, &current_set,POLL_READ_FLAGS))
+                    accept_connection(opt);
+	}
+    }
+    log(LOG_ERR, "INTERNAL ERROR: End of infinite loop 8-)");
+}
+
+#else
+
 static void daemon_loop(void) {
     struct sockaddr_in addr;
     fd_set base_set, current_set;
@@ -203,6 +298,8 @@
     log(LOG_ERR, "INTERNAL ERROR: End of infinite loop 8-)");
 }
 
+#endif /* USE_POLL_NOT_SELECT */
+
 static void accept_connection(LOCAL_OPTIONS *opt) {
     struct sockaddr_in addr;
     int err, s, addrlen=sizeof(addr);
@@ -272,7 +369,12 @@
     if(fds_ulimit==RLIM_INFINITY)
         fds_ulimit=-1;
 #endif
+
+#ifdef USE_POLL_NOT_SELECT
+    max_fds=fds_ulimit;
+#else
     max_fds=fds_ulimit<FD_SETSIZE ? fds_ulimit : FD_SETSIZE;
+#endif /* USE_POLL_NOT_SELECT */
     if(max_fds<16) /* stunnel needs at least 16 file desriptors to work */
         max_fds=16;
     max_clients=max_fds>=256 ? max_fds*125/256 : (max_fds-6)/2;
