added -C option to enable running on more than 1 node
[tridge/junkcode.git] / socketpair.c
1 #include <sys/types.h>
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <sys/socket.h>
5
6 /* work out what fcntl flag to use for non-blocking */
7 #ifdef O_NONBLOCK
8 # define NONBLOCK_FLAG O_NONBLOCK
9 #elif defined(SYSV)
10 # define NONBLOCK_FLAG O_NDELAY
11 #else 
12 # define NONBLOCK_FLAG FNDELAY
13 #endif
14
15 #define socklen_t int
16
17 /****************************************************************************
18 Set a fd into nonblocking mode.
19 ****************************************************************************/
20 int set_nonblocking(int fd)
21 {
22         int val;
23
24         if((val = fcntl(fd, F_GETFL, 0)) == -1)
25                 return -1;
26         if (!(val & NONBLOCK_FLAG)) {
27                 val |= NONBLOCK_FLAG;
28                 fcntl(fd, F_SETFL, val);
29         }
30         return 0;
31 }
32
33 /****************************************************************************
34 Set a fd into blocking mode.
35 ****************************************************************************/
36 int set_blocking(int fd)
37 {
38         int val;
39
40         if((val = fcntl(fd, F_GETFL, 0)) == -1)
41                 return -1;
42         if (val & NONBLOCK_FLAG) {
43                 val &= ~NONBLOCK_FLAG;
44                 fcntl(fd, F_SETFL, val);
45         }
46         return 0;
47 }
48
49 int socketpair_tcp(int fd[2])
50 {
51         int listener;
52         struct sockaddr sock;
53         socklen_t socklen = sizeof(sock);
54         int len = socklen;
55         int one = 1;
56         int connect_done = 0;
57
58         fd[0] = fd[1] = listener = -1;
59
60         memset(&sock, 0, sizeof(sock));
61         
62         if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
63
64         setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
65
66         if (listen(listener, 1) != 0) goto failed;
67
68         if (getsockname(listener, &sock, &socklen) != 0) goto failed;
69
70         if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
71
72         setsockopt(fd[1],SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
73
74         set_nonblocking(fd[1]);
75
76         if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
77                 if (errno != EINPROGRESS) goto failed;
78         } else {
79                 connect_done = 1;
80         }
81
82         if ((fd[0] = accept(listener, &sock, &len)) == -1) goto failed;
83
84         setsockopt(fd[0],SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
85
86         close(listener);
87         if (connect_done == 0) {
88                 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0) goto failed;
89         }
90
91         set_blocking(fd[1]);
92
93         /* all OK! */
94         return 0;
95
96  failed:
97         if (fd[0] != -1) close(fd[0]);
98         if (fd[1] != -1) close(fd[1]);
99         if (listener != -1) close(listener);
100         return -1;
101 }
102
103
104 main() { 
105        int fd[2], ret;
106        char buf[1024*1024];
107        int maxfd;
108        fd_set set;
109
110
111        alarm(5);
112        if (socketpair_tcp(fd) != 0) exit(1);
113
114        FD_ZERO(&set);
115        FD_SET(fd[0], &set);
116        maxfd = fd[0] > fd[1] ? fd[0] : fd[1];
117        select(maxfd+1, NULL, &set, NULL, NULL);
118        ret = write(fd[0], buf, sizeof(buf));
119        if (ret > 0 && ret < sizeof(buf)) exit(0);
120        exit(1);
121