ncdirect: set up fatal signal handlers #1271

This commit is contained in:
nick black 2021-01-03 02:36:58 -05:00
parent 3a658dad3e
commit 6d6416064e
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
2 changed files with 35 additions and 22 deletions

View File

@ -28,7 +28,7 @@ typedef struct ncplane ncdirectv;
// We typically install a signal handler for SIG{INT, SEGV, ABRT, QUIT} that // We typically install a signal handler for SIG{INT, SEGV, ABRT, QUIT} that
// restores the screen, and then calls the old signal handler. Set to inhibit // restores the screen, and then calls the old signal handler. Set to inhibit
// registration of these signal handlers. Chosen to match fullscreen mode. // registration of these signal handlers. Chosen to match fullscreen mode.
#define NCDIRECT_NO_QUIT_SIGHANDLERS 0x0008ull #define NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS 0x0008ull
// Initialize a direct-mode Notcurses context on the connected terminal at 'fp'. // Initialize a direct-mode Notcurses context on the connected terminal at 'fp'.
// 'fp' must be a tty. You'll usually want stdout. Direct mode supports a // 'fp' must be a tty. You'll usually want stdout. Direct mode supports a

View File

@ -592,8 +592,33 @@ int get_controlling_tty(FILE* ttyfp){
return open(cbuf, O_RDWR | O_CLOEXEC); return open(cbuf, O_RDWR | O_CLOEXEC);
} }
static int
ncdirect_stop_minimal(void* vnc){
ncdirect* nc = static_cast<ncdirect*>(vnc);
int ret = 0;
if(nc->tcache.op && term_emit("op", nc->tcache.op, nc->ttyfp, true)){
ret = -1;
}
if(nc->tcache.sgr0 && term_emit("sgr0", nc->tcache.sgr0, nc->ttyfp, true)){
ret = -1;
}
if(nc->tcache.oc && term_emit("oc", nc->tcache.oc, nc->ttyfp, true)){
ret = -1;
}
if(nc->ctermfd >= 0){
if(nc->tcache.cnorm && tty_emit("cnorm", nc->tcache.cnorm, nc->ctermfd)){
ret = -1;
}
if(!(nc->flags & NCDIRECT_OPTION_INHIBIT_CBREAK)){
ret |= tcsetattr(nc->ctermfd, TCSANOW, &nc->tpreserved);
}
ret |= close(nc->ctermfd);
}
return ret;
}
ncdirect* ncdirect_init(const char* termtype, FILE* outfp, uint64_t flags){ ncdirect* ncdirect_init(const char* termtype, FILE* outfp, uint64_t flags){
if(flags > (NCDIRECT_OPTION_INHIBIT_CBREAK << 1)){ // allow them through with warning if(flags > (NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS << 1)){ // allow them through with warning
logwarn((struct notcurses*)NULL, "Passed unsupported flags 0x%016jx\n", (uintmax_t)flags); logwarn((struct notcurses*)NULL, "Passed unsupported flags 0x%016jx\n", (uintmax_t)flags);
} }
if(outfp == nullptr){ if(outfp == nullptr){
@ -613,6 +638,11 @@ ncdirect* ncdirect_init(const char* termtype, FILE* outfp, uint64_t flags){
if(encoding && strcmp(encoding, "UTF-8") == 0){ if(encoding && strcmp(encoding, "UTF-8") == 0){
ret->utf8 = true; ret->utf8 = true;
} }
if(setup_signals(ret, (flags & NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS),
true, ncdirect_stop_minimal)){
delete ret;
return nullptr;
}
// we don't need a controlling tty for everything we do; allow a failure here // we don't need a controlling tty for everything we do; allow a failure here
if((ret->ctermfd = get_controlling_tty(ret->ttyfp)) >= 0){ if((ret->ctermfd = get_controlling_tty(ret->ttyfp)) >= 0){
if(!(flags & NCDIRECT_OPTION_INHIBIT_CBREAK)){ if(!(flags & NCDIRECT_OPTION_INHIBIT_CBREAK)){
@ -658,24 +688,7 @@ err:
int ncdirect_stop(ncdirect* nc){ int ncdirect_stop(ncdirect* nc){
int ret = 0; int ret = 0;
if(nc){ if(nc){
if(nc->tcache.op && term_emit("op", nc->tcache.op, nc->ttyfp, true)){ ret |= ncdirect_stop_minimal(nc);
ret = -1;
}
if(nc->tcache.sgr0 && term_emit("sgr0", nc->tcache.sgr0, nc->ttyfp, true)){
ret = -1;
}
if(nc->tcache.oc && term_emit("oc", nc->tcache.oc, nc->ttyfp, true)){
ret = -1;
}
if(nc->ctermfd >= 0){
if(nc->tcache.cnorm && tty_emit("cnorm", nc->tcache.cnorm, nc->ctermfd)){
ret = -1;
}
if(!(nc->flags & NCDIRECT_OPTION_INHIBIT_CBREAK)){
ret |= tcsetattr(nc->ctermfd, TCSANOW, &nc->tpreserved);
}
ret |= close(nc->ctermfd);
}
input_free_esctrie(&nc->input.inputescapes); input_free_esctrie(&nc->input.inputescapes);
delete(nc); delete(nc);
} }