|
|
@ -23,7 +23,6 @@
|
|
|
|
// redirected from a file (NCOPTION_TOSS_INPUT)
|
|
|
|
// redirected from a file (NCOPTION_TOSS_INPUT)
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME still need to:
|
|
|
|
// FIXME still need to:
|
|
|
|
// integrate main specials trie with automaton, enable input_errors
|
|
|
|
|
|
|
|
// probably want pipes/eventfds rather than SIGCONT
|
|
|
|
// probably want pipes/eventfds rather than SIGCONT
|
|
|
|
|
|
|
|
|
|
|
|
static sig_atomic_t resize_seen;
|
|
|
|
static sig_atomic_t resize_seen;
|
|
|
@ -50,6 +49,12 @@ typedef struct cursorloc {
|
|
|
|
int y, x; // 0-indexed cursor location
|
|
|
|
int y, x; // 0-indexed cursor location
|
|
|
|
} cursorloc;
|
|
|
|
} cursorloc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef __MINGW64__
|
|
|
|
|
|
|
|
typedef int ipipe;
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
typedef PHANDLE ipipe;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// local state for the input thread. don't put this large struct on the stack.
|
|
|
|
// local state for the input thread. don't put this large struct on the stack.
|
|
|
|
typedef struct inputctx {
|
|
|
|
typedef struct inputctx {
|
|
|
|
int stdinfd; // bulk in fd. always >= 0 (almost always 0). we do not
|
|
|
|
int stdinfd; // bulk in fd. always >= 0 (almost always 0). we do not
|
|
|
@ -100,7 +105,7 @@ typedef struct inputctx {
|
|
|
|
unsigned drain; // drain away bulk input?
|
|
|
|
unsigned drain; // drain away bulk input?
|
|
|
|
ncsharedstats *stats; // stats shared with notcurses context
|
|
|
|
ncsharedstats *stats; // stats shared with notcurses context
|
|
|
|
|
|
|
|
|
|
|
|
int readypipes[2]; // pipes[0]: poll()able fd indicating the presence of user input
|
|
|
|
ipipe readypipes[2]; // pipes[0]: poll()able fd indicating the presence of user input
|
|
|
|
struct initial_responses* initdata;
|
|
|
|
struct initial_responses* initdata;
|
|
|
|
struct initial_responses* initdata_complete;
|
|
|
|
struct initial_responses* initdata_complete;
|
|
|
|
} inputctx;
|
|
|
|
} inputctx;
|
|
|
@ -438,10 +443,16 @@ send_synth_signal(int sig){
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
mark_pipe_ready(int pipes[static 2]){
|
|
|
|
mark_pipe_ready(ipipe pipes[static 2]){
|
|
|
|
char sig = 1;
|
|
|
|
char sig = 1;
|
|
|
|
|
|
|
|
#ifndef __MINGW64__
|
|
|
|
if(write(pipes[1], &sig, sizeof(sig)) != 1){
|
|
|
|
if(write(pipes[1], &sig, sizeof(sig)) != 1){
|
|
|
|
logwarn("error writing to readypipe (%d) (%s)\n", pipes[1], strerror(errno));
|
|
|
|
logwarn("error writing to readypipe (%d) (%s)\n", pipes[1], strerror(errno));
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
DWORD wrote;
|
|
|
|
|
|
|
|
if(!WriteFile(pipes[1], &sig, sizeof(sig), &wrote, NULL) || wrote != sizeof(sig)){
|
|
|
|
|
|
|
|
logwarn("error writing to readypipe\n");
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1321,18 +1332,27 @@ build_cflow_automaton(inputctx* ictx){
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
endpipes(int pipes[static 2]){
|
|
|
|
closepipe(ipipe p){
|
|
|
|
if(pipes[0] >= 0){
|
|
|
|
#ifndef __MINGW64__
|
|
|
|
close(pipes[0]);
|
|
|
|
if(p >= 0){
|
|
|
|
|
|
|
|
close(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(pipes[1] >= 0){
|
|
|
|
#else
|
|
|
|
close(pipes[1]);
|
|
|
|
if(p){
|
|
|
|
|
|
|
|
CloseHandle(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
|
|
endpipes(ipipe pipes[static 2]){
|
|
|
|
|
|
|
|
closepipe(pipes[0]);
|
|
|
|
|
|
|
|
closepipe(pipes[1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// only linux and freebsd13+ have eventfd(), so we'll fall back to pipes sigh.
|
|
|
|
// only linux and freebsd13+ have eventfd(), so we'll fall back to pipes sigh.
|
|
|
|
static int
|
|
|
|
static int
|
|
|
|
getpipes(int pipes[static 2]){
|
|
|
|
getpipes(ipipe pipes[static 2]){
|
|
|
|
#ifndef __MINGW64__
|
|
|
|
#ifndef __MINGW64__
|
|
|
|
#ifndef __APPLE__
|
|
|
|
#ifndef __APPLE__
|
|
|
|
if(pipe2(pipes, O_CLOEXEC | O_NONBLOCK)){
|
|
|
|
if(pipe2(pipes, O_CLOEXEC | O_NONBLOCK)){
|
|
|
@ -1345,19 +1365,21 @@ getpipes(int pipes[static 2]){
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(set_fd_cloexec(pipes[0], 1, NULL) || set_fd_nonblocking(pipes[0], 1, NULL)){
|
|
|
|
if(set_fd_cloexec(pipes[0], 1, NULL) || set_fd_nonblocking(pipes[0], 1, NULL)){
|
|
|
|
logerror("couldn't prep pipe[0] (%d) (%s)\n", pipes[0], strerror(errno));
|
|
|
|
logerror("couldn't prep pipe[0] (%s)\n", strerror(errno));
|
|
|
|
endpipes(pipes);
|
|
|
|
endpipes(pipes);
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(set_fd_cloexec(pipes[1], 1, NULL) || set_fd_nonblocking(pipes[1], 1, NULL)){
|
|
|
|
if(set_fd_cloexec(pipes[1], 1, NULL) || set_fd_nonblocking(pipes[1], 1, NULL)){
|
|
|
|
logerror("couldn't prep pipe[1] (%d) (%s)\n", pipes[1], strerror(errno));
|
|
|
|
logerror("couldn't prep pipe[1] (%s)\n", strerror(errno));
|
|
|
|
endpipes(pipes);
|
|
|
|
endpipes(pipes);
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// FIXME what to do on windows?
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#else // windows
|
|
|
|
#else // windows
|
|
|
|
pipes[0] = pipes[1] = -1;
|
|
|
|
if(!CreatePipe(&pipes[0], &pipes[1], NULL, BUFSIZ)){
|
|
|
|
|
|
|
|
logerror("couldn't get pipes (%u)\n", GetLastError());
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -2026,7 +2048,13 @@ int stop_inputlayer(tinfo* ti){
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int inputready_fd(const inputctx* ictx){
|
|
|
|
int inputready_fd(const inputctx* ictx){
|
|
|
|
|
|
|
|
#ifndef __MINGW64__
|
|
|
|
return ictx->readypipes[0];
|
|
|
|
return ictx->readypipes[0];
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
(void)ictx;
|
|
|
|
|
|
|
|
logerror("readiness descriptor unavailable on windows\n");
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline uint32_t
|
|
|
|
static inline uint32_t
|
|
|
@ -2073,9 +2101,15 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){
|
|
|
|
}else if(ictx->ivalid){
|
|
|
|
}else if(ictx->ivalid){
|
|
|
|
logtrace("draining event readiness pipe\n");
|
|
|
|
logtrace("draining event readiness pipe\n");
|
|
|
|
char c;
|
|
|
|
char c;
|
|
|
|
|
|
|
|
#ifndef __MINGW64__
|
|
|
|
while(read(ictx->readypipes[0], &c, sizeof(c)) == 1){
|
|
|
|
while(read(ictx->readypipes[0], &c, sizeof(c)) == 1){
|
|
|
|
// FIXME accelerate;
|
|
|
|
// FIXME accelerate?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
while(ReadFile(ictx->readypipes[0], &c, sizeof(c), NULL, NULL)){
|
|
|
|
|
|
|
|
// FIXME accelerate?
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&ictx->ilock);
|
|
|
|
pthread_mutex_unlock(&ictx->ilock);
|
|
|
|
if(sendsignal){
|
|
|
|
if(sendsignal){
|
|
|
|