201 lines · 3.7 KB · C
RawDownload
#include <errno.h>#include <signal.h>#include <stdbool.h>#include <stdlib.h>#include <termios.h>#include <unistd.h>#include <linux/kernel.h>#ifdef HAVE_BACKTRACE_SUPPORT#include <execinfo.h>#endif #include "../../util/color.h"#include "../../util/debug.h"#include "../browser.h"#include "../helpline.h"#include "../ui.h"#include "../util.h"#include "../libslang.h"#include "../keysyms.h"#include "tui.h" static volatile int ui__need_resize; extern struct perf_error_ops perf_tui_eops;extern bool tui_helpline__set; extern void hist_browser__init_hpp(void); void ui__refresh_dimensions(bool force){	if (force || ui__need_resize) {		ui__need_resize = 0;		mutex_lock(&ui__lock);		SLtt_get_screen_size();		SLsmg_reinit_smg();		mutex_unlock(&ui__lock);	}} static void ui__sigwinch(int sig __maybe_unused){	ui__need_resize = 1;} static void ui__setup_sigwinch(void){	static bool done; 	if (done)		return; 	done = true;	pthread__unblock_sigwinch();	signal(SIGWINCH, ui__sigwinch);} int ui__getch(int delay_secs){	struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL;	fd_set read_set;	int err, key; 	ui__setup_sigwinch(); 	FD_ZERO(&read_set);	FD_SET(0, &read_set); 	if (delay_secs) {		timeout.tv_sec = delay_secs;		timeout.tv_usec = 0;	}         err = select(1, &read_set, NULL, NULL, ptimeout); 	if (err == 0)		return K_TIMER; 	if (err == -1) {		if (errno == EINTR)			return K_RESIZE;		return K_ERROR;	} 	key = SLang_getkey();	if (key != K_ESC)		return key; 	FD_ZERO(&read_set);	FD_SET(0, &read_set);	timeout.tv_sec = 0;	timeout.tv_usec = 20;        err = select(1, &read_set, NULL, NULL, &timeout);	if (err == 0)		return K_ESC; 	SLang_ungetkey(key);	return SLkp_getkey();} #ifdef HAVE_BACKTRACE_SUPPORTstatic void ui__signal_backtrace(int sig){	void *stackdump[32];	size_t size; 	ui__exit(false);	psignal(sig, "perf"); 	printf("-------- backtrace --------\n");	size = backtrace(stackdump, ARRAY_SIZE(stackdump));	__dump_stack(stdout, stackdump, size); 	exit(0);}#else# define ui__signal_backtrace  ui__signal#endif static void ui__signal(int sig){	ui__exit(false);	psignal(sig, "perf");	exit(0);} static void ui__sigcont(int sig){	static struct termios tty; 	if (sig == SIGTSTP) {		while (tcgetattr(SLang_TT_Read_FD, &tty) == -1 && errno == EINTR)			;		while (write(SLang_TT_Read_FD, PERF_COLOR_RESET, sizeof(PERF_COLOR_RESET) - 1) == -1 && errno == EINTR)			;		raise(SIGSTOP);	} else {		while (tcsetattr(SLang_TT_Read_FD, TCSADRAIN, &tty) == -1 && errno == EINTR)			;		raise(SIGWINCH);	}} int ui__init(void){	int err; 	SLutf8_enable(-1);	SLtt_get_terminfo();	SLtt_get_screen_size(); 	err = SLsmg_init_smg();	if (err < 0)		goto out;	err = SLang_init_tty(-1, 0, 0);	if (err < 0)		goto out;	SLtty_set_suspend_state(true); 	err = SLkp_init();	if (err < 0) {		pr_err("TUI initialization failed.\n");		goto out;	} 	SLkp_define_keysym("^(kB)", SL_KEY_UNTAB); 	signal(SIGSEGV, ui__signal_backtrace);	signal(SIGFPE, ui__signal_backtrace);	signal(SIGINT, ui__signal);	signal(SIGQUIT, ui__signal);	signal(SIGTERM, ui__signal);	signal(SIGTSTP, ui__sigcont);	signal(SIGCONT, ui__sigcont); 	perf_error__register(&perf_tui_eops); 	ui_helpline__init();	ui_browser__init();	tui_progress__init(); 	hist_browser__init_hpp();out:	return err;} void ui__exit(bool wait_for_ok){	if (wait_for_ok && tui_helpline__set)		ui__question_window("Fatal Error",				    ui_helpline__last_msg,				    "Press any key...", 0); 	SLtt_set_cursor_visibility(1);	if (mutex_trylock(&ui__lock)) {		SLsmg_refresh();		SLsmg_reset_smg();		mutex_unlock(&ui__lock);	}	SLang_reset_tty();	perf_error__unregister(&perf_tui_eops);}