--- esound-0.2.38.orig/esdlib.c	2008-07-10 10:10:31.000000000 -0400
+++ esound-0.2.38/esdlib.c	2008-07-10 15:37:00.000000000 -0400
@@ -20,9 +20,11 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <sys/wait.h>
+#include <poll.h>
 
 #include <sys/un.h>
 
+
 #ifndef SUN_LEN
 #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path)  \
                      + strlen ((ptr)->sun_path))
@@ -149,6 +151,84 @@ int esd_get_latency(int esd)
     return lag;
 }
 
+static ssize_t
+read_timeout (int fd, char *buf, size_t buflen, int timeout)
+{
+	struct pollfd pfd[1];
+	int flags, rv;
+	ssize_t n;
+	
+	pfd[0].fd = fd;
+	pfd[0].events = POLLIN;
+	
+	do {
+		pfd[0].revents = 0;
+		rv = poll (pfd, 1, timeout);
+	} while (rv == -1 && errno == EINTR);
+	
+	if (rv < 1 || !(pfd[0].revents & POLLIN)) {
+		errno = ETIMEDOUT;
+		return -1;
+	}
+	
+	if ((flags = fcntl (fd, F_GETFL)) == -1)
+		return -1;
+	
+	fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+	
+	if ((n = read (fd, buf, buflen)) == -1) {
+		rv = errno;
+		fcntl (fd, F_SETFL, flags);
+		errno = rv;
+		return -1;
+	}
+	
+	fcntl (fd, F_SETFL, flags);
+	
+	return n;
+}
+
+static ssize_t
+write_timeout (int fd, const char *buf, size_t buflen, int timeout)
+{
+	struct pollfd pfd[1];
+	size_t nwritten = 0;
+	int flags, rv;
+	ssize_t n;
+	
+	if ((flags = fcntl (fd, F_GETFL)) == -1)
+		return -1;
+	
+	fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+	
+	do {
+		pfd[0].fd = fd;
+		pfd[0].events = POLLOUT;
+		
+		do {
+			pfd[0].revents = 0;
+			rv = poll (pfd, 1, timeout);
+		} while (rv == -1 && errno == EINTR);
+		
+		if (rv < 1 || !(pfd[0].revents & POLLOUT)) {
+			fcntl (fd, F_SETFL, flags);
+			errno = ETIMEDOUT;
+			return -1;
+		}
+		
+		do {
+			n = write (fd, buf + nwritten, buflen - nwritten);
+		} while (n == -1 && errno == EINTR);
+		
+		if (n > 0)
+			nwritten += n;
+	} while (nwritten < buflen);
+	
+	fcntl (fd, F_SETFL, flags);
+	
+	return nwritten;
+}
+
 /**
  * esd_send_auth: send authorization to esd
  * @sock: ESD socket
@@ -162,7 +242,8 @@ int esd_send_auth( int sock )
 {
     int auth_fd = -1;
     int endian = ESD_ENDIAN_KEY;
-    int reply;
+    struct pollfd pfd[1];
+    int reply, rv;
     char *auth_filename = NULL;
     unsigned char auth_key[ESD_KEY_LEN];
     const char *home = NULL;
@@ -207,25 +288,26 @@ int esd_send_auth( int sock )
 	}
 
 	esound_genrand(auth_key, ESD_KEY_LEN);
-	write( auth_fd, auth_key, ESD_KEY_LEN);
-    } else
+	write_timeout( auth_fd, auth_key, ESD_KEY_LEN, 100);
+    } else {
       /* read the key from the authorization file */
-      if ( ESD_KEY_LEN != read( auth_fd, auth_key, ESD_KEY_LEN ) )
+      if ( ESD_KEY_LEN != read_timeout( auth_fd, auth_key, ESD_KEY_LEN, 100 ) )
 	goto exit_fd;
-
+    }
+    
     /* send the key to the server */
-    if ( ESD_KEY_LEN != write( sock, auth_key, ESD_KEY_LEN ) )
+    if ( ESD_KEY_LEN != write_timeout( sock, auth_key, ESD_KEY_LEN, 100 ) )
 	/* send key failed */
 	goto exit_fd;
 
     /* send the key to the server */
-    if ( sizeof(endian) != write( sock, &endian, sizeof(endian) ) )
+    if ( sizeof(endian) != write_timeout( sock, &endian, sizeof(endian), 100 ) )
 	/* send key failed */
 	goto exit_fd;
 
     /* read auth reply. esd will reply 1 as an int for yes and 0 for no */
     /* then close the connection */
-    if ( sizeof(reply) != read( sock, &reply, sizeof(reply) ) ) {
+    if ( sizeof(reply) != read_timeout( sock, &reply, sizeof(reply), 100 ) ) {
 	/* read ok failed */
 	retval = 0;
 	goto exit_fd;
@@ -408,6 +490,43 @@ int esd_resume( int esd )
     return ok;
 }
 
+static int
+connect_timeout (int sockfd, const struct sockaddr *serv_addr, size_t addrlen, int timeout)
+{
+	struct pollfd pfd[1];
+	int flags, rv;
+	
+	if ((flags = fcntl (sockfd, F_GETFL)) == -1)
+		return -1;
+	
+	fcntl (sockfd, F_SETFL, flags | O_NONBLOCK);
+	
+	if (connect (sockfd, serv_addr, addrlen) == 0) {
+		fcntl (sockfd, F_SETFL, flags);
+		return 0;
+	}
+	
+	if (errno != EINPROGRESS)
+		return -1;
+	
+	pfd[0].fd = sockfd;
+	pfd[0].events = POLLIN | POLLOUT;
+	
+	do {
+		pfd[0].revents = 0;
+		rv = poll (pfd, 1, timeout);
+	} while (rv == -1 && errno == EINTR);
+	
+	if (pfd[0].revents & (POLLIN | POLLOUT)) {
+		/* success, we are now connected */
+		fcntl (sockfd, F_SETFL, flags);
+		return 0;
+	}
+	
+	/* took too long / error connecting, either way: epic fail */
+	return -1;
+}
+
 /**
  * esd_connect_tcpip: make a TCPIP connection to ESD
  * @host: specifies hostname and port to connect to as "hostname:port"
@@ -512,7 +631,7 @@ esd_connect_tcpip(const char *host)
            goto error_out;
          }
 
-         if ( connect( socket_out, res->ai_addr, res->ai_addrlen ) != -1 ) 
+         if ( connect_timeout ( socket_out, res->ai_addr, res->ai_addrlen, 1000 ) != -1 ) 
            break;
 
          close ( socket_out );
@@ -596,9 +715,9 @@ esd_connect_tcpip(const char *host)
     socket_addr.sin_family = AF_INET;
     socket_addr.sin_port = htons( port );
   
-    if ( connect( socket_out,
-		  (struct sockaddr *) &socket_addr,
-		  sizeof(struct sockaddr_in) ) < 0 )
+    if ( connect_timeout ( socket_out,
+			   (struct sockaddr *) &socket_addr,
+			   sizeof(struct sockaddr_in), 1000 ) < 0 )
 	goto error_out;
 
     }
@@ -650,8 +769,7 @@ esd_connect_unix(void)
     socket_unix.sun_family = AF_UNIX;
     strncpy(socket_unix.sun_path, ESD_UNIX_SOCKET_NAME, sizeof(socket_unix.sun_path));
   
-    if ( connect( socket_out,
-		  (struct sockaddr *) &socket_unix, SUN_LEN(&socket_unix) ) < 0 )
+    if ( connect_timeout ( socket_out, (struct sockaddr *) &socket_unix, SUN_LEN(&socket_unix), 100 ) < 0 )
 	goto error_out;
   
     return socket_out;
