14 # define DPRINTF(x, args...) do { \
15 printf(x, ## args); fflush(stdout); \
18 # define DPRINTF(x, args...) do { } while(0)
31 setvbuf(stdout, NULL, _IOLBF, 0);
32 setvbuf(stderr, NULL, _IONBF, 0);
43 static void errcode(
int err)
47 if (err == WSAENOTSOCK)
54 static bool is_socket(
int fd)
58 return (HANDLE)_get_osfhandle(fd) == INVALID_HANDLE_VALUE;
67 ret = closesocket(fd);
68 errcode(GetLastError());
79 int read(
int fd,
void *buf,
size_t count)
84 ret = recv(fd, (
char *)buf, count, 0);
85 errcode(GetLastError());
89 ret = _read(fd, buf, count);
96 int write(
int fd,
const void *buf,
size_t count)
101 ret = send(fd, (
char *)buf, count, 0);
102 errcode(GetLastError());
106 ret = _write(fd, buf, count);
113 int socketpair(
int family,
int type,
int protocol,
int *sb)
115 SOCKET insock, outsock, newsock;
116 struct sockaddr_in sock_in;
118 if (type != SOCK_STREAM)
121 newsock = socket(AF_INET, type, 0);
122 if (newsock == INVALID_SOCKET)
125 sock_in.sin_family = AF_INET;
126 sock_in.sin_port = 0;
127 sock_in.sin_addr.s_addr = INADDR_ANY;
128 if (bind(newsock, (
struct sockaddr *) &sock_in,
sizeof (sock_in)) < 0)
131 int len =
sizeof (sock_in);
132 if (getsockname(newsock, (
struct sockaddr *)&sock_in, &len) < 0)
135 if (listen(newsock, 2) < 0)
138 outsock = socket(AF_INET, type, 0);
139 if (outsock == INVALID_SOCKET)
142 sock_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
143 if (connect(outsock, (
struct sockaddr *)&sock_in,
sizeof(sock_in)) < 0)
147 len =
sizeof(sock_in);
148 insock = accept(newsock, (
struct sockaddr *)&sock_in, &len);
149 if (insock == INVALID_SOCKET)
152 if (closesocket(newsock) < 0)
161 static void CALLBACK completion(DWORD error, DWORD nread, LPOVERLAPPED ov)
166 static size_t fake_read(
int fd,
void *buf,
size_t len)
168 HANDLE h = (HANDLE)_get_osfhandle(fd);
170 DPRINTF(
"fake_read(%d/%d,%p,%d) = ", fd, (
int)h, buf, (
int)len);
174 memset(&ov, 0,
sizeof(ov));
175 ov.Offset = SetFilePointer(h, 0, NULL, FILE_CURRENT);
177 if (PeekNamedPipe(h, NULL, 0, NULL, &ret, NULL))
182 DPRINTF(
"(stdin is a pipe)\n");
183 while (PeekNamedPipe(h, NULL, 0, NULL, &ret, NULL) && !ret)
188 ReadFile(h, buf, len, &ret, NULL);
190 else if (PeekConsoleInput(h, &p, 1, &ret))
199 DPRINTF(
"(stdin is a console)\n");
202 char *xbuf = (
char *)buf;
203 HANDLE hout = CreateFile(
"CONOUT$", GENERIC_READ | GENERIC_WRITE,
204 FILE_SHARE_READ | FILE_SHARE_WRITE,
205 NULL, OPEN_EXISTING, 0, 0);
208 GetConsoleMode(h, &conmode);
209 SetConsoleMode(h, conmode &
210 ~(ENABLE_LINE_INPUT | ENABLE_MOUSE_INPUT | ENABLE_ECHO_INPUT));
212 while (PeekConsoleInput(h, &p, 1, &ret))
217 ReadConsoleInput(h, &p, 1, &ret);
219 if (p.EventType == KEY_EVENT && p.Event.KeyEvent.bKeyDown)
221 int key = p.Event.KeyEvent.uChar.AsciiChar;
225 WriteConsole(hout,
"\r\n", 2, &tmp, NULL);
229 else if (key ==
'\b' && used > 0)
232 WriteConsole(hout,
"\b \b", 3, &tmp, NULL);
234 else if (key && used < len-1)
237 WriteConsole(hout, xbuf+used-1, 1, &tmp, NULL);
244 WaitForSingleObjectEx(h, 1000,
true);
255 DPRINTF(
"(stdin is a file)\n");
260 if (ReadFileEx(h, buf, 0, &ov, &completion))
262 rv = SleepEx(1000,
true);
264 DPRINTF(
"(rv is %d)\n", rv);
265 if (rv == WAIT_IO_COMPLETION)
267 ReadFile(h, buf, len, &ret, NULL);
278 ReadFile(h, buf, len, &ret, NULL);
284 DPRINTF(
"[%d]\n", ret);
289 DWORD WINAPI fd2socket_fwd(LPVOID lpThreadParameter)
293 const int BUFSIZE = 512;
304 size_t bytes = fake_read(pair->fd, ptr, BUFSIZE);
305 if (bytes <= 0) { retval = bytes;
break; }
308 int written = send(pair->socket, ptr, bytes, 0);
309 if (written < 0) { retval = written;
break; }
316 shutdown(pair->socket, SD_BOTH);
317 closesocket(pair->socket);
323 DWORD WINAPI socket2fd_fwd(LPVOID lpThreadParameter)
326 const int BUFSIZE = 512;
333 int bytes = recv(pair->socket, ptr, BUFSIZE, 0);
334 if (bytes <= 0) { retval = bytes;
break; }
337 int written = _write(pair->fd, ptr, bytes);
338 if (written < 0) { retval = written;
break; }
343 shutdown(pair->socket, SD_BOTH);
344 closesocket(pair->socket);
350 SocketFromFDMaker::SocketFromFDMaker(
int fd,
351 LPTHREAD_START_ROUTINE lpStartAddress,
bool wait)
352 : m_hThread(0), m_socket(INVALID_SOCKET), m_wait(wait)
356 WSAStartup(MAKEWORD(2,0), &wsaData);
359 result = socketpair(AF_INET, SOCK_STREAM, 0, s);
363 m_pair.socket = s[0];
367 m_hThread = CreateThread(
379 SocketFromFDMaker::~SocketFromFDMaker()
383 if (m_socket != INVALID_SOCKET)
385 result = shutdown(m_socket, SD_BOTH);
393 int e = GetLastError();
394 if (e == WSASYSNOTREADY || e == WSANOTINITIALISED)
396 fprintf(stderr,
"Abnormal termination. Skipping cleanup.\n");
402 "ERROR! Socket #%d was already shut down! (%d)\n",
413 WaitForSingleObject(m_hThread, INFINITE);
433 CloseHandle(m_hThread);