Fix select() on Windows for timeout (#141)

This commit is contained in:
Justine Tunney 2021-08-26 15:59:55 -07:00
parent 3085ac7837
commit 50937be752
6 changed files with 108 additions and 36 deletions

View file

@ -5725,13 +5725,12 @@ static void ShellCompletion(const char *p, linenoiseCompletions *c) {
}
}
static char *ShellHint(const char *p, int *color, int *bold) {
static char *ShellHint(const char *p, const char **ansi1, const char **ansi2) {
char *h = 0;
linenoiseCompletions c = {0};
ShellCompletion(p, &c);
if (c.len == 1) {
h = strdup(c.cvec[0] + strlen(p));
*bold = 2;
}
linenoiseFreeCompletions(&c);
return h;

View file

@ -23,6 +23,7 @@
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/yoink.inc"
#include "libc/sysv/errfuns.h"
static int GetFdsPopcnt(int nfds, fd_set *fds) {
int i, n = 0;
@ -92,22 +93,38 @@ static struct NtTimeval *TimevalToNtTimeval(struct timeval *tv,
}
}
int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout) {
int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout) {
int n, rc;
struct timespec req, rem;
struct NtTimeval nttimeout, *nttimeoutp;
struct NtFdSet *ntreadfds, *ntwritefds, *ntexceptfds;
nfds = MIN(ARRAYLEN(readfds->fds_bits), ROUNDUP(nfds, 8)) >> 3;
ntreadfds = FdSetToNtFdSet(nfds, readfds);
ntwritefds = FdSetToNtFdSet(nfds, writefds);
ntexceptfds = FdSetToNtFdSet(nfds, exceptfds);
nttimeoutp = TimevalToNtTimeval(timeout, &nttimeout);
rc = __sys_select_nt(0, ntreadfds, ntwritefds, ntexceptfds, nttimeoutp);
NtFdSetToFdSet(nfds, readfds, ntreadfds);
NtFdSetToFdSet(nfds, writefds, ntwritefds);
NtFdSetToFdSet(nfds, exceptfds, ntexceptfds);
free(ntreadfds);
free(ntwritefds);
free(ntexceptfds);
if (readfds || writefds || exceptfds) {
nfds = MIN(ARRAYLEN(readfds->fds_bits), ROUNDUP(nfds, 8)) >> 3;
ntreadfds = FdSetToNtFdSet(nfds, readfds);
ntwritefds = FdSetToNtFdSet(nfds, writefds);
ntexceptfds = FdSetToNtFdSet(nfds, exceptfds);
nttimeoutp = TimevalToNtTimeval(timeout, &nttimeout);
if ((rc = __sys_select_nt(0, ntreadfds, ntwritefds, ntexceptfds,
nttimeoutp)) != -1) {
NtFdSetToFdSet(nfds, readfds, ntreadfds);
NtFdSetToFdSet(nfds, writefds, ntwritefds);
NtFdSetToFdSet(nfds, exceptfds, ntexceptfds);
} else {
__winsockerr();
}
free(ntreadfds);
free(ntwritefds);
free(ntexceptfds);
} else if (timeout) {
req.tv_sec = timeout->tv_sec;
req.tv_nsec = timeout->tv_usec * 1000;
if ((rc = sys_nanosleep_nt(&req, &rem)) != -1) {
timeout->tv_sec = rem.tv_sec;
timeout->tv_usec = rem.tv_nsec / 1000;
}
} else {
rc = einval();
}
return rc;
}

View file

@ -0,0 +1,43 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/struct/timeval.h"
#include "libc/sock/select.h"
#include "libc/sock/sock.h"
#include "libc/testlib/testlib.h"
#include "libc/time/time.h"
TEST(select, allZero) {
/* blocks indefinitely not worth supporting */
/* EXPECT_SYS(0, 0, select(0, 0, 0, 0, 0)); */
}
TEST(select, testSleep) {
int64_t e;
long double n;
struct timeval t = {0, 2000};
n = nowl();
EXPECT_SYS(0, 0, select(0, 0, 0, 0, &t));
e = (nowl() - n) * 1e6;
EXPECT_GT(e, 1000);
if (!IsBsd()) {
/* maybe we should polyfill */
EXPECT_EQ(0, t.tv_sec);
EXPECT_EQ(0, t.tv_usec);
}
}

View file

@ -59,6 +59,27 @@
- Ctrl+R search
- Thompson-Pike Encoding
SHORTCUTS
CTRL-L CLEAR SCREEN
CTRL-N NEXT HISTORY
CTRL-P PREVIOUS HISTORY
CTRL-F FORWARD CHAR
CTRL-B BACKWARD CHAR
CTRL-A BEGINNING OF LINE
CTRL-E END OF LINE
ALT-F FORWARD WORD
ALT-B BACKWARD WORD
CTRL-H DELETE CHAR BACKWARDS
CTRL-ALT-H DELETE WORD BACKWARDS
ALT-H DELETE WORD BACKWARDS
CTRL-W DELETE WORD BACKWARDS
CTRL-D DELETE CHAR FORWARDS
ALT-D DELETE WORD FORWARDS
CTRL-T TRANSPOSE CHARS
CTRL-K DELETE LINE FORWARDS
CTRL-U DELETE LINE BACKWARDS
REFERENCE
The big scary coding you 𝘮𝘶𝘴𝘵 use curses to abstract.
@ -533,25 +554,14 @@ static void abFree(struct abuf *ab) {
/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
* to the right of the prompt. */
static void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {
char seq[26], *p;
if (hintsCallback && plen+l->len < l->cols) {
int color = 0, bold = 0;
char *hint = hintsCallback(l->buf,&color,&bold);
const char *ansi1 = "\e[90m";
const char *ansi2 = "\e[39m";
char *hint = hintsCallback(l->buf,&ansi1,&ansi2);
if (hint) {
int hintlen = strlen(hint);
int hintmaxlen = l->cols-(plen+l->len);
if (hintlen > hintmaxlen) hintlen = hintmaxlen;
if (bold && !color) color = 37;
if (color || bold) {
p=stpcpy(seq,"\e[");
p+=int64toarray_radix10(bold&255,p),*p++=';';
p+=int64toarray_radix10(color&255,p);
p=stpcpy(p,";49m");
abAppend(ab,seq,p-seq);
}
abAppend(ab,hint,hintlen);
if (color != -1 || bold)
abAppend(ab,"\e[0m",4);
if (ansi1) abAppend(ab,ansi1,strlen(ansi1));
abAppend(ab,hint,MIN(l->cols-(plen+l->len),strlen(hint)));
if (ansi2) abAppend(ab,ansi2,strlen(ansi2));
/* Call the function to free the hint returned. */
if (freeHintsCallback) {
freeHintsCallback(hint);
@ -1061,6 +1071,9 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen,
case 'd': /* "\ed" is alt-d */
linenoiseEditDeleteNextWord(&l);
break;
case 'h': /* "\e" is alt-h */
linenoiseEditDeletePrevWord(&l);
break;
case CTRL('H'): /* "\e\b" is ctrl-alt-h */
linenoiseEditDeletePrevWord(&l);
break;

View file

@ -9,7 +9,8 @@ typedef struct linenoiseCompletions {
} linenoiseCompletions;
typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
typedef char *(linenoiseHintsCallback)(const char *, int *, int *);
typedef char *(linenoiseHintsCallback)(const char *, const char **,
const char **);
typedef void(linenoiseFreeHintsCallback)(void *);
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);

View file

@ -778,14 +778,13 @@ TerminalCompletion(const char *p, linenoiseCompletions *c)
}
static char *
TerminalHint(const char *p, int *color, int *bold)
TerminalHint(const char *p, const char **ansi1, const char **ansi2)
{
char *h = 0;
linenoiseCompletions c = {0};
TerminalCompletion(p, &c);
if (c.len == 1) {
h = strdup(c.cvec[0] + strlen(p));
*bold = 2;
}
linenoiseFreeCompletions(&c);
return h;