Skip to content

Commit

Permalink
win32: revise poll(2) for use in nc
Browse files Browse the repository at this point in the history
Upstream commit 5b3b468 (nc: use poll() instead of select())
changed `nc` to use poll(2) instead of select(2), obviously.

In busybox-w32 select(2) had already been hacked to support `nc`.
To avoid hacking poll(2) too the upstream change was reverted
(c2002ea).  Later `nc` was altered to include the code for both
poll and select (3c85cc0).

Make the changes necessary for poll(2) to work with `nc` on Windows.
These are all in the function windows_compute_revents().

  Treat a character file that isn't a console as a normal file.
  Without this `nc 127.0.0.1 1234 </dev/null` doesn't work.

  Return 0 instead of POLLHUP if GetNumberOfConsoleInputEvents()
  indicates no events are available.  Without this communication
  between two instances of `nc` which are both using keyboard
  input isn't as asynchronous as one would like.

  Only process key press events:  key releases are ignored.  Without
  this `nc 127.0.0.1 1234` won't receive anything from the server
  until the local user presses a key.

  In the default case, which now includes disk files and character
  files, detect polling for reads as well as writes.  Without this
  `nc 127.0.0.1 1234 <local_file` doesn't work.
  • Loading branch information
rmyorston committed Mar 3, 2023
1 parent e9ea698 commit 0678b84
Showing 1 changed file with 11 additions and 7 deletions.
18 changes: 11 additions & 7 deletions win32/poll.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,18 +219,17 @@ windows_compute_revents (HANDLE h, int *p_sought)
return happened;

case FILE_TYPE_CHAR:
ret = WaitForSingleObject (h, 0);
if (!IsConsoleHandle (h))
return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;

// Fall through to default case for non-console, e.g. /dev/null.
if (IsConsoleHandle (h)) {
nbuffer = avail = 0;
bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
if (bRet)
{
/* Input buffer. */
*p_sought &= POLLIN | POLLRDNORM;
if (nbuffer == 0)
return POLLHUP;
// Having no unread events isn't an error condition.
return 0 /* was POLLHUP */;
if (!*p_sought)
return 0;

Expand All @@ -240,7 +239,9 @@ windows_compute_revents (HANDLE h, int *p_sought)
return POLLHUP;

for (i = 0; i < avail; i++)
if (irbuffer[i].EventType == KEY_EVENT)
// Ignore key release.
if (irbuffer[i].EventType == KEY_EVENT &&
irbuffer[i].Event.KeyEvent.bKeyDown)
return *p_sought;
return 0;
}
Expand All @@ -250,13 +251,16 @@ windows_compute_revents (HANDLE h, int *p_sought)
*p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
return *p_sought;
}
}
/* fall through */

default:
ret = WaitForSingleObject (h, 0);
if (ret == WAIT_OBJECT_0)
return *p_sought & ~(POLLPRI | POLLRDBAND);

return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
// Add (POLLIN | POLLRDNORM). Why only support write?
return *p_sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND);
}
}

Expand Down

0 comments on commit 0678b84

Please sign in to comment.