00001 #include "streams.h"
00002 #include "wvstring.h"
00003 #include <assert.h>
00004 #include <errno.h>
00005 #include <conio.h>
00006 #include <stdio.h>
00007 #include <io.h>
00008
00009 #if WIN32
00010
00011 # define DPRINTF
00012 #else
00013 #if 0
00014 # define DPRINTF(x, args...) do { \
00015 printf(x, ## args); fflush(stdout); \
00016 } while (0)
00017 #else
00018 # define DPRINTF(x, args...) do { } while(0)
00019 #endif
00020 #endif
00021
00022
00023
00024
00025
00026 class FixLibcIoBuffers
00027 {
00028 public:
00029 FixLibcIoBuffers()
00030 {
00031 setvbuf(stdout, NULL, _IOLBF, 0);
00032 setvbuf(stderr, NULL, _IONBF, 0);
00033 }
00034 };
00035 static FixLibcIoBuffers fixbufs;
00036
00037
00038
00039
00040
00041
00042
00043 static void errcode(int err)
00044 {
00045 if (err == EIO)
00046 err = EBADF;
00047 if (err == WSAENOTSOCK)
00048 err = EBADF;
00049 SetLastError(err);
00050 errno = err;
00051 }
00052
00053
00054 static bool is_socket(int fd)
00055 {
00056
00057
00058 return (HANDLE)_get_osfhandle(fd) == INVALID_HANDLE_VALUE;
00059 }
00060
00061
00062 int close(int fd)
00063 {
00064 int ret;
00065 if (is_socket(fd))
00066 {
00067 ret = closesocket(fd);
00068 errcode(GetLastError());
00069 }
00070 else
00071 {
00072 ret = _close(fd);
00073 errcode(errno);
00074 }
00075 return ret;
00076 }
00077
00078
00079 int read(int fd, void *buf, size_t count)
00080 {
00081 int ret;
00082 if (is_socket(fd))
00083 {
00084 ret = recv(fd, (char *)buf, count, 0);
00085 errcode(GetLastError());
00086 }
00087 else
00088 {
00089 ret = _read(fd, buf, count);
00090 errcode(errno);
00091 }
00092 return ret;
00093 }
00094
00095
00096 int write(int fd, const void *buf, size_t count)
00097 {
00098 int ret;
00099 if (is_socket(fd))
00100 {
00101 ret = send(fd, (char *)buf, count, 0);
00102 errcode(GetLastError());
00103 }
00104 else
00105 {
00106 ret = _write(fd, buf, count);
00107 errcode(errno);
00108 }
00109 return ret;
00110 }
00111
00112
00113 unsigned int sleep(unsigned int seconds)
00114 {
00115 Sleep(seconds * 1000);
00116 return 0;
00117 }
00118
00119
00120 int socketpair(int family, int type, int protocol, int *sb)
00121 {
00122 SOCKET insock, outsock, newsock;
00123 struct sockaddr_in sock_in;
00124
00125 if (type != SOCK_STREAM)
00126 return -1;
00127
00128 newsock = socket(AF_INET, type, 0);
00129 if (newsock == INVALID_SOCKET)
00130 return -1;
00131
00132 sock_in.sin_family = AF_INET;
00133 sock_in.sin_port = 0;
00134 sock_in.sin_addr.s_addr = INADDR_ANY;
00135 if (bind(newsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
00136 return -1;
00137
00138 int len = sizeof (sock_in);
00139 if (getsockname(newsock, (struct sockaddr *)&sock_in, &len) < 0)
00140 return -1;
00141
00142 if (listen(newsock, 2) < 0)
00143 return -1;
00144
00145 outsock = socket(AF_INET, type, 0);
00146 if (outsock == INVALID_SOCKET)
00147 return -1;
00148
00149 sock_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
00150 if (connect(outsock, (struct sockaddr *)&sock_in, sizeof(sock_in)) < 0)
00151 return -1;
00152
00153
00154 len = sizeof(sock_in);
00155 insock = accept(newsock, (struct sockaddr *)&sock_in, &len);
00156 if (insock == INVALID_SOCKET)
00157 return -1;
00158
00159 if (closesocket(newsock) < 0)
00160 return -1;
00161
00162 sb[0] = insock;
00163 sb[1] = outsock;
00164 return 0;
00165 }
00166
00167
00168 static void CALLBACK completion(DWORD error, DWORD nread, LPOVERLAPPED ov)
00169 {
00170 }
00171
00172
00173 static size_t fake_read(int fd, void *buf, size_t len)
00174 {
00175 HANDLE h = (HANDLE)_get_osfhandle(fd);
00176 INPUT_RECORD p;
00177 DPRINTF("fake_read(%d/%d,%p,%d) = ", fd, (int)h, buf, (int)len);
00178
00179 DWORD ret = 0;
00180 OVERLAPPED ov;
00181 memset(&ov, 0, sizeof(ov));
00182 ov.Offset = SetFilePointer(h, 0, NULL, FILE_CURRENT);
00183
00184 if (PeekNamedPipe(h, NULL, 0, NULL, &ret, NULL))
00185 {
00186
00187
00188
00189 DPRINTF("(stdin is a pipe)\n");
00190 while (PeekNamedPipe(h, NULL, 0, NULL, &ret, NULL) && !ret)
00191 {
00192 DPRINTF(".");
00193 Sleep(100);
00194 }
00195 ReadFile(h, buf, len, &ret, NULL);
00196 }
00197 else if (PeekConsoleInput(h, &p, 1, &ret))
00198 {
00199
00200
00201
00202
00203
00204
00205
00206 DPRINTF("(stdin is a console)\n");
00207
00208 size_t used = 0;
00209 char *xbuf = (char *)buf;
00210 HANDLE hout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
00211 FILE_SHARE_READ | FILE_SHARE_WRITE,
00212 NULL, OPEN_EXISTING, 0, 0);
00213
00214 DWORD conmode = 0;
00215 GetConsoleMode(h, &conmode);
00216 SetConsoleMode(h, conmode &
00217 ~(ENABLE_LINE_INPUT | ENABLE_MOUSE_INPUT | ENABLE_ECHO_INPUT));
00218
00219 while (PeekConsoleInput(h, &p, 1, &ret))
00220 {
00221 DWORD tmp;
00222 if (ret)
00223 {
00224 ReadConsoleInput(h, &p, 1, &ret);
00225 assert(ret);
00226 if (p.EventType == KEY_EVENT && p.Event.KeyEvent.bKeyDown)
00227 {
00228 int key = p.Event.KeyEvent.uChar.AsciiChar;
00229 if (key == '\r')
00230 {
00231 xbuf[used++] = '\n';
00232 WriteConsole(hout, "\r\n", 2, &tmp, NULL);
00233 ret = used;
00234 break;
00235 }
00236 else if (key == '\b' && used > 0)
00237 {
00238 used--;
00239 WriteConsole(hout, "\b \b", 3, &tmp, NULL);
00240 }
00241 else if (key && used < len-1)
00242 {
00243 xbuf[used++] = key;
00244 WriteConsole(hout, xbuf+used-1, 1, &tmp, NULL);
00245 }
00246 }
00247 }
00248 else
00249 {
00250 DPRINTF(".");
00251 WaitForSingleObjectEx(h, 1000, true);
00252 }
00253 }
00254
00255 CloseHandle(hout);
00256 }
00257 else
00258 {
00259
00260
00261
00262 DPRINTF("(stdin is a file)\n");
00263 while (!ret)
00264 {
00265 DPRINTF(".");
00266 int rv = 0;
00267 if (ReadFileEx(h, buf, 0, &ov, &completion))
00268 {
00269 rv = SleepEx(1000, true);
00270 CancelIo(h);
00271 DPRINTF("(rv is %d)\n", rv);
00272 if (rv == WAIT_IO_COMPLETION)
00273 {
00274 ReadFile(h, buf, len, &ret, NULL);
00275 break;
00276 }
00277 else if (!rv)
00278 Sleep(1);
00279 else
00280 return 0;
00281 }
00282 else
00283 {
00284
00285 ReadFile(h, buf, len, &ret, NULL);
00286 break;
00287 }
00288 }
00289 }
00290
00291 DPRINTF("[%d]\n", ret);
00292 return ret;
00293 }
00294
00295
00296 DWORD WINAPI fd2socket_fwd(LPVOID lpThreadParameter)
00297 {
00298
00299 DWORD retval = 0;
00300 const int BUFSIZE = 512;
00301 socket_fd_pair *pair = (socket_fd_pair *)lpThreadParameter;
00302
00303
00304
00305
00306 char buf[BUFSIZE];
00307 while (true)
00308 {
00309 char *ptr = buf;
00310
00311 size_t bytes = fake_read(pair->fd, ptr, BUFSIZE);
00312 if (bytes <= 0) { retval = bytes; break; }
00313 while (bytes > 0)
00314 {
00315 int written = send(pair->socket, ptr, bytes, 0);
00316 if (written < 0) { retval = written; break; }
00317
00318 bytes -= written;
00319 ptr += written;
00320 }
00321 }
00322
00323 shutdown(pair->socket, SD_BOTH);
00324 closesocket(pair->socket);
00325
00326 return retval;
00327 }
00328
00329
00330 DWORD WINAPI socket2fd_fwd(LPVOID lpThreadParameter)
00331 {
00332 DWORD retval = 0;
00333 const int BUFSIZE = 512;
00334 socket_fd_pair *pair = (socket_fd_pair *)lpThreadParameter;
00335
00336 char buf[BUFSIZE];
00337 while (true)
00338 {
00339 char *ptr = buf;
00340 int bytes = recv(pair->socket, ptr, BUFSIZE, 0);
00341 if (bytes <= 0) { retval = bytes; break; }
00342 while (bytes > 0)
00343 {
00344 int written = _write(pair->fd, ptr, bytes);
00345 if (written < 0) { retval = written; break; }
00346 bytes -= written;
00347 ptr += written;
00348 }
00349 }
00350 shutdown(pair->socket, SD_BOTH);
00351 closesocket(pair->socket);
00352
00353 return retval;
00354 }
00355
00356
00357 SocketFromFDMaker::SocketFromFDMaker(int fd,
00358 LPTHREAD_START_ROUTINE lpStartAddress, bool wait)
00359 : m_hThread(0), m_socket(INVALID_SOCKET), m_wait(wait)
00360 {
00361
00362 WSAData wsaData;
00363 WSAStartup(MAKEWORD(2,0), &wsaData);
00364
00365 int s[2];
00366 socketpair(AF_INET, SOCK_STREAM, 0, s);
00367
00368 m_pair.fd = fd;
00369 m_pair.socket = s[0];
00370 m_socket = s[1];
00371
00372 DWORD threadid;
00373 m_hThread = CreateThread(
00374 NULL,
00375 0,
00376 lpStartAddress,
00377 &m_pair,
00378 0,
00379 &threadid
00380 );
00381 assert(m_hThread);
00382 }
00383
00384
00385 SocketFromFDMaker::~SocketFromFDMaker()
00386 {
00387 int result;
00388 if (m_socket != INVALID_SOCKET)
00389 {
00390 result = shutdown(m_socket, SD_BOTH);
00391
00392
00393
00394
00395
00396 assert(result == 0);
00397
00398 if (m_wait)
00399 {
00400
00401
00402
00403 WaitForSingleObject(m_hThread, INFINITE);
00404 }
00405 else
00406 {
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 }
00420
00421 close(m_socket);
00422 }
00423 CloseHandle(m_hThread);
00424 }