- int n;
- n = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
- if (n == 0) {
- WSANETWORKEVENTS things;
- if (!WSAEnumNetworkEvents(socket, netevent, &things)) {
- if (things.lNetworkEvents & FD_READ)
- back->msg(0, FD_READ);
- if (things.lNetworkEvents & FD_CLOSE) {
- back->msg(0, FD_CLOSE);
- break;
- }
- }
- term_out();
- if (!sending && back->sendok()) {
- /*
- * Create a separate thread to read from stdin.
- * This is a total pain, but I can't find another
- * way to do it:
- *
- * - an overlapped ReadFile or ReadFileEx just
- * doesn't happen; we get failure from
- * ReadFileEx, and ReadFile blocks despite being
- * given an OVERLAPPED structure. Perhaps we
- * can't do overlapped reads on consoles. WHY
- * THE HELL NOT?
- *
- * - WaitForMultipleObjects(netevent, console)
- * doesn't work, because it signals the console
- * when _anything_ happens, including mouse
- * motions and other things that don't cause
- * data to be readable - so we're back to
- * ReadFile blocking.
- */
- idata.event = stdinevent;
- if (!CreateThread(NULL, 0, stdin_read_thread,
- &idata, 0, &threadid)) {
- fprintf(stderr, "Unable to create second thread\n");
- exit(1);
- }
- sending = TRUE;
- }
- } else if (n == 1) {
- if (idata.len > 0) {
- back->send(idata.buffer, idata.len);
- } else {
- back->special(TS_EOF);
- }
- }
+ int n;
+
+ if (!sending && back->sendok()) {
+ /*
+ * Create a separate thread to read from stdin. This is
+ * a total pain, but I can't find another way to do it:
+ *
+ * - an overlapped ReadFile or ReadFileEx just doesn't
+ * happen; we get failure from ReadFileEx, and
+ * ReadFile blocks despite being given an OVERLAPPED
+ * structure. Perhaps we can't do overlapped reads
+ * on consoles. WHY THE HELL NOT?
+ *
+ * - WaitForMultipleObjects(netevent, console) doesn't
+ * work, because it signals the console when
+ * _anything_ happens, including mouse motions and
+ * other things that don't cause data to be readable
+ * - so we're back to ReadFile blocking.
+ */
+ idata.event = stdinevent;
+ idata.eventback = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!CreateThread(NULL, 0, stdin_read_thread,
+ &idata, 0, &in_threadid)) {
+ fprintf(stderr, "Unable to create input thread\n");
+ exit(1);
+ }
+ sending = TRUE;
+ }
+
+ n = WaitForMultipleObjects(4, handles, FALSE, INFINITE);
+ if (n == 0) {
+ WSANETWORKEVENTS things;
+ SOCKET socket;
+ extern SOCKET first_socket(int *), next_socket(int *);
+ extern int select_result(WPARAM, LPARAM);
+ int i, socketstate;
+
+ /*
+ * We must not call select_result() for any socket
+ * until we have finished enumerating within the tree.
+ * This is because select_result() may close the socket
+ * and modify the tree.
+ */
+ /* Count the active sockets. */
+ i = 0;
+ for (socket = first_socket(&socketstate);
+ socket != INVALID_SOCKET;
+ socket = next_socket(&socketstate)) i++;
+
+ /* Expand the buffer if necessary. */
+ if (i > sksize) {
+ sksize = i + 16;
+ sklist = srealloc(sklist, sksize * sizeof(*sklist));
+ }
+
+ /* Retrieve the sockets into sklist. */
+ skcount = 0;
+ for (socket = first_socket(&socketstate);
+ socket != INVALID_SOCKET;
+ socket = next_socket(&socketstate)) {
+ sklist[skcount++] = socket;
+ }
+
+ /* Now we're done enumerating; go through the list. */
+ for (i = 0; i < skcount; i++) {
+ WPARAM wp;
+ socket = sklist[i];
+ wp = (WPARAM) socket;
+ if (!WSAEnumNetworkEvents(socket, NULL, &things)) {
+ noise_ultralight(socket);
+ noise_ultralight(things.lNetworkEvents);
+ if (things.lNetworkEvents & FD_READ)
+ connopen &= select_result(wp, (LPARAM) FD_READ);
+ if (things.lNetworkEvents & FD_CLOSE)
+ connopen &= select_result(wp, (LPARAM) FD_CLOSE);
+ if (things.lNetworkEvents & FD_OOB)
+ connopen &= select_result(wp, (LPARAM) FD_OOB);
+ if (things.lNetworkEvents & FD_WRITE)
+ connopen &= select_result(wp, (LPARAM) FD_WRITE);
+ if (things.lNetworkEvents & FD_ACCEPT)
+ connopen &= select_result(wp, (LPARAM) FD_ACCEPT);
+
+ }
+ }
+ } else if (n == 1) {
+ reading = 0;
+ noise_ultralight(idata.len);
+ if (idata.len > 0) {
+ back->send(idata.buffer, idata.len);
+ } else {
+ back->special(TS_EOF);
+ }
+ } else if (n == 2) {
+ odata.busy = 0;
+ if (!odata.writeret) {
+ fprintf(stderr, "Unable to write to standard output\n");
+ exit(0);
+ }
+ bufchain_consume(&stdout_data, odata.lenwritten);
+ if (bufchain_size(&stdout_data) > 0)
+ try_output(0);
+ back->unthrottle(bufchain_size(&stdout_data) +
+ bufchain_size(&stderr_data));
+ } else if (n == 3) {
+ edata.busy = 0;
+ if (!edata.writeret) {
+ fprintf(stderr, "Unable to write to standard output\n");
+ exit(0);
+ }
+ bufchain_consume(&stderr_data, edata.lenwritten);
+ if (bufchain_size(&stderr_data) > 0)
+ try_output(1);
+ back->unthrottle(bufchain_size(&stdout_data) +
+ bufchain_size(&stderr_data));
+ }
+ if (!reading && back->sendbuffer() < MAX_STDIN_BACKLOG) {
+ SetEvent(idata.eventback);
+ reading = 1;
+ }
+ if (!connopen || back->socket() == NULL)
+ break; /* we closed the connection */