chiark / gitweb /
Merge branches 'idx/verh' and 'idx/qmqpc'
[qmail] / timeoutconn.c
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <netinet/in.h>
4 #include <arpa/inet.h>
5 #include "ndelay.h"
6 #include "select.h"
7 #include "error.h"
8 #include "readwrite.h"
9 #include "ip.h"
10 #include "byte.h"
11 #include "timeoutconn.h"
12
13 int timeoutconn(s,ip,port,timeout)
14 int s;
15 struct ip_address *ip;
16 unsigned int port;
17 int timeout;
18 {
19   char ch;
20   struct sockaddr_in sin;
21   char *x;
22   fd_set wfds;
23   struct timeval tv;
24  
25   byte_zero(&sin,sizeof(sin));
26   byte_copy(&sin.sin_addr,4,ip);
27   x = (char *) &sin.sin_port;
28   x[1] = port; port >>= 8; x[0] = port;
29   sin.sin_family = AF_INET;
30  
31   if (ndelay_on(s) == -1) return -1;
32  
33   /* XXX: could bind s */
34  
35   if (connect(s,(struct sockaddr *) &sin,sizeof(sin)) == 0) {
36     ndelay_off(s);
37     return 0;
38   }
39   if ((errno != error_inprogress) && (errno != error_wouldblock)) return -1;
40  
41   FD_ZERO(&wfds);
42   FD_SET(s,&wfds);
43   tv.tv_sec = timeout; tv.tv_usec = 0;
44  
45   if (select(s + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1;
46   if (FD_ISSET(s,&wfds)) {
47     int dummy;
48     dummy = sizeof(sin);
49     if (getpeername(s,(struct sockaddr *) &sin,&dummy) == -1) {
50       read(s,&ch,1);
51       return -1;
52     }
53     ndelay_off(s);
54     return 0;
55   }
56  
57   errno = error_timeout; /* note that connect attempt is continuing */
58   return -1;
59 }