diff options
author | Brent Cook <busterb@gmail.com> | 2017-01-15 10:17:13 -0600 |
---|---|---|
committer | Brent Cook <busterb@gmail.com> | 2017-01-15 16:00:16 -0600 |
commit | dbd5fb28ec73a2d47ad0dd4530728f835dcf65aa (patch) | |
tree | 86b2828d33db7ccb3d837918172c3d5154e7a466 | |
parent | dfb6b11e5a5ba21c6658d87b4df83c2a05d2deab (diff) | |
download | portable-dbd5fb28ec73a2d47ad0dd4530728f835dcf65aa.tar.gz portable-dbd5fb28ec73a2d47ad0dd4530728f835dcf65aa.tar.bz2 portable-dbd5fb28ec73a2d47ad0dd4530728f835dcf65aa.zip |
add windows versions of socketpair / pipe
-rw-r--r-- | tests/compat/pipe2.c | 127 |
1 files changed, 119 insertions, 8 deletions
diff --git a/tests/compat/pipe2.c b/tests/compat/pipe2.c index e2aaa28..7600783 100644 --- a/tests/compat/pipe2.c +++ b/tests/compat/pipe2.c | |||
@@ -1,12 +1,110 @@ | |||
1 | /* | 1 | /* |
2 | * Public domain | 2 | * Public domain |
3 | * | ||
4 | * pipe2/pipe/socketpair emulation | ||
5 | * Brent Cook <bcook@openbsd.org> | ||
3 | */ | 6 | */ |
4 | 7 | ||
8 | #include <errno.h> | ||
5 | #include <fcntl.h> | 9 | #include <fcntl.h> |
6 | #include <unistd.h> | 10 | #include <unistd.h> |
7 | #include <sys/socket.h> | 11 | #include <sys/socket.h> |
12 | |||
8 | #undef socketpair | 13 | #undef socketpair |
9 | 14 | ||
15 | #ifdef _WIN32 | ||
16 | |||
17 | static int setfd(int fd, int flag) | ||
18 | { | ||
19 | int rc = -1; | ||
20 | if (flag & FD_CLOEXEC) { | ||
21 | HANDLE h = (HANDLE)_get_osfhandle(fd); | ||
22 | if (h != NULL) | ||
23 | rc = SetHandleInformation(h, HANDLE_FLAG_INHERIT, 0) == 0 ? -1 : 0; | ||
24 | } | ||
25 | return rc; | ||
26 | } | ||
27 | |||
28 | static int setfl(int fd, int flag) | ||
29 | { | ||
30 | int rc = -1; | ||
31 | if (flag & O_NONBLOCK) { | ||
32 | long mode = 1; | ||
33 | rc = ioctlsocket(fd, FIONBIO, &mode); | ||
34 | } | ||
35 | return rc; | ||
36 | } | ||
37 | |||
38 | int socketpair(int domain, int type, int protocol, int socket_vector[2]) | ||
39 | { | ||
40 | if (domain != AF_UNIX || !(type & SOCK_STREAM) || protocol != PF_UNSPEC) | ||
41 | return -1; | ||
42 | |||
43 | socket_vector[0] = -1; | ||
44 | socket_vector[1] = -1; | ||
45 | |||
46 | int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | ||
47 | if (listener == -1) { | ||
48 | return -1; | ||
49 | } | ||
50 | |||
51 | struct sockaddr_in addr = { | ||
52 | .sin_family = AF_INET, | ||
53 | .sin_addr.s_addr = htonl(INADDR_LOOPBACK), | ||
54 | .sin_port = 0, | ||
55 | }; | ||
56 | |||
57 | int yes = 1, e; | ||
58 | if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, | ||
59 | (void *)&yes, sizeof yes) == -1) | ||
60 | goto err; | ||
61 | |||
62 | if (bind(listener, (struct sockaddr *)&addr, sizeof addr) != 0) | ||
63 | goto err; | ||
64 | |||
65 | memset(&addr, 0, sizeof addr); | ||
66 | socklen_t addrlen = sizeof addr; | ||
67 | if (getsockname(listener, (struct sockaddr *)&addr, &addrlen) != 0) | ||
68 | goto err; | ||
69 | |||
70 | addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | ||
71 | addr.sin_family = AF_INET; | ||
72 | |||
73 | if (listen(listener, 1) != 0) | ||
74 | goto err; | ||
75 | |||
76 | socket_vector[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0); | ||
77 | if (socket_vector[0] == -1) | ||
78 | goto err; | ||
79 | |||
80 | if (connect(socket_vector[0], (struct sockaddr *)&addr, sizeof addr) != 0) | ||
81 | goto err; | ||
82 | |||
83 | socket_vector[1] = accept(listener, NULL, NULL); | ||
84 | if (socket_vector[1] == -1) | ||
85 | goto err; | ||
86 | |||
87 | closesocket(listener); | ||
88 | return 0; | ||
89 | |||
90 | err: | ||
91 | e = WSAGetLastError(); | ||
92 | closesocket(listener); | ||
93 | closesocket(socket_vector[0]); | ||
94 | closesocket(socket_vector[1]); | ||
95 | WSASetLastError(e); | ||
96 | socket_vector[0] = -1; | ||
97 | socket_vector[1] = -1; | ||
98 | return -1; | ||
99 | } | ||
100 | |||
101 | int pipe(int fildes[2]) | ||
102 | { | ||
103 | return socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, PF_UNSPEC, fildes); | ||
104 | } | ||
105 | |||
106 | #else | ||
107 | |||
10 | static int setfd(int fd, int flag) | 108 | static int setfd(int fd, int flag) |
11 | { | 109 | { |
12 | int flags = fcntl(fd, F_GETFD); | 110 | int flags = fcntl(fd, F_GETFD); |
@@ -20,18 +118,25 @@ static int setfl(int fd, int flag) | |||
20 | flags |= flag; | 118 | flags |= flag; |
21 | return fcntl(fd, F_SETFL, flags); | 119 | return fcntl(fd, F_SETFL, flags); |
22 | } | 120 | } |
121 | #endif | ||
23 | 122 | ||
24 | int pipe2(int fildes[2], int flags) | 123 | int pipe2(int fildes[2], int flags) |
25 | { | 124 | { |
26 | int rc = pipe(fildes); | 125 | int rc = pipe(fildes); |
27 | if (rc == 0) { | 126 | if (rc == 0) { |
28 | if (flags & O_NONBLOCK) { | 127 | if (flags & O_NONBLOCK) { |
29 | setfl(fildes[0], O_NONBLOCK); | 128 | rc |= setfl(fildes[0], O_NONBLOCK); |
30 | setfl(fildes[1], O_NONBLOCK); | 129 | rc |= setfl(fildes[1], O_NONBLOCK); |
31 | } | 130 | } |
32 | if (flags & O_CLOEXEC) { | 131 | if (flags & O_CLOEXEC) { |
33 | setfd(fildes[0], FD_CLOEXEC); | 132 | rc |= setfd(fildes[0], FD_CLOEXEC); |
34 | setfd(fildes[1], FD_CLOEXEC); | 133 | rc |= setfd(fildes[1], FD_CLOEXEC); |
134 | } | ||
135 | if (rc != 0) { | ||
136 | int e = errno; | ||
137 | close(fildes[0]); | ||
138 | close(fildes[1]); | ||
139 | errno = e; | ||
35 | } | 140 | } |
36 | } | 141 | } |
37 | return rc; | 142 | return rc; |
@@ -44,12 +149,18 @@ int bsd_socketpair(int domain, int type, int protocol, int socket_vector[2]) | |||
44 | int rc = socketpair(domain, type, protocol, socket_vector); | 149 | int rc = socketpair(domain, type, protocol, socket_vector); |
45 | if (rc == 0) { | 150 | if (rc == 0) { |
46 | if (flags & SOCK_NONBLOCK) { | 151 | if (flags & SOCK_NONBLOCK) { |
47 | setfl(socket_vector[0], O_NONBLOCK); | 152 | rc |= setfl(socket_vector[0], O_NONBLOCK); |
48 | setfl(socket_vector[1], O_NONBLOCK); | 153 | rc |= setfl(socket_vector[1], O_NONBLOCK); |
49 | } | 154 | } |
50 | if (flags & SOCK_CLOEXEC) { | 155 | if (flags & SOCK_CLOEXEC) { |
51 | setfd(socket_vector[0], FD_CLOEXEC); | 156 | rc |= setfd(socket_vector[0], FD_CLOEXEC); |
52 | setfd(socket_vector[1], FD_CLOEXEC); | 157 | rc |= setfd(socket_vector[1], FD_CLOEXEC); |
158 | } | ||
159 | if (rc != 0) { | ||
160 | int e = errno; | ||
161 | close(socket_vector[0]); | ||
162 | close(socket_vector[1]); | ||
163 | errno = e; | ||
53 | } | 164 | } |
54 | } | 165 | } |
55 | return rc; | 166 | return rc; |