162306a36Sopenharmony_ci#include <errno.h> 262306a36Sopenharmony_ci#include <signal.h> 362306a36Sopenharmony_ci#include <stdbool.h> 462306a36Sopenharmony_ci#include <stdlib.h> 562306a36Sopenharmony_ci#include <unistd.h> 662306a36Sopenharmony_ci#include <linux/kernel.h> 762306a36Sopenharmony_ci#ifdef HAVE_BACKTRACE_SUPPORT 862306a36Sopenharmony_ci#include <execinfo.h> 962306a36Sopenharmony_ci#endif 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "../../util/debug.h" 1262306a36Sopenharmony_ci#include "../browser.h" 1362306a36Sopenharmony_ci#include "../helpline.h" 1462306a36Sopenharmony_ci#include "../ui.h" 1562306a36Sopenharmony_ci#include "../util.h" 1662306a36Sopenharmony_ci#include "../libslang.h" 1762306a36Sopenharmony_ci#include "../keysyms.h" 1862306a36Sopenharmony_ci#include "tui.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic volatile int ui__need_resize; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciextern struct perf_error_ops perf_tui_eops; 2362306a36Sopenharmony_ciextern bool tui_helpline__set; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ciextern void hist_browser__init_hpp(void); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_civoid ui__refresh_dimensions(bool force) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci if (force || ui__need_resize) { 3062306a36Sopenharmony_ci ui__need_resize = 0; 3162306a36Sopenharmony_ci mutex_lock(&ui__lock); 3262306a36Sopenharmony_ci SLtt_get_screen_size(); 3362306a36Sopenharmony_ci SLsmg_reinit_smg(); 3462306a36Sopenharmony_ci mutex_unlock(&ui__lock); 3562306a36Sopenharmony_ci } 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic void ui__sigwinch(int sig __maybe_unused) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci ui__need_resize = 1; 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic void ui__setup_sigwinch(void) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci static bool done; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci if (done) 4862306a36Sopenharmony_ci return; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci done = true; 5162306a36Sopenharmony_ci pthread__unblock_sigwinch(); 5262306a36Sopenharmony_ci signal(SIGWINCH, ui__sigwinch); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ciint ui__getch(int delay_secs) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL; 5862306a36Sopenharmony_ci fd_set read_set; 5962306a36Sopenharmony_ci int err, key; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci ui__setup_sigwinch(); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci FD_ZERO(&read_set); 6462306a36Sopenharmony_ci FD_SET(0, &read_set); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci if (delay_secs) { 6762306a36Sopenharmony_ci timeout.tv_sec = delay_secs; 6862306a36Sopenharmony_ci timeout.tv_usec = 0; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci err = select(1, &read_set, NULL, NULL, ptimeout); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci if (err == 0) 7462306a36Sopenharmony_ci return K_TIMER; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (err == -1) { 7762306a36Sopenharmony_ci if (errno == EINTR) 7862306a36Sopenharmony_ci return K_RESIZE; 7962306a36Sopenharmony_ci return K_ERROR; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci key = SLang_getkey(); 8362306a36Sopenharmony_ci if (key != K_ESC) 8462306a36Sopenharmony_ci return key; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci FD_ZERO(&read_set); 8762306a36Sopenharmony_ci FD_SET(0, &read_set); 8862306a36Sopenharmony_ci timeout.tv_sec = 0; 8962306a36Sopenharmony_ci timeout.tv_usec = 20; 9062306a36Sopenharmony_ci err = select(1, &read_set, NULL, NULL, &timeout); 9162306a36Sopenharmony_ci if (err == 0) 9262306a36Sopenharmony_ci return K_ESC; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci SLang_ungetkey(key); 9562306a36Sopenharmony_ci return SLkp_getkey(); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci#ifdef HAVE_BACKTRACE_SUPPORT 9962306a36Sopenharmony_cistatic void ui__signal_backtrace(int sig) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci void *stackdump[32]; 10262306a36Sopenharmony_ci size_t size; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci ui__exit(false); 10562306a36Sopenharmony_ci psignal(sig, "perf"); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci printf("-------- backtrace --------\n"); 10862306a36Sopenharmony_ci size = backtrace(stackdump, ARRAY_SIZE(stackdump)); 10962306a36Sopenharmony_ci backtrace_symbols_fd(stackdump, size, STDOUT_FILENO); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci exit(0); 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci#else 11462306a36Sopenharmony_ci# define ui__signal_backtrace ui__signal 11562306a36Sopenharmony_ci#endif 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic void ui__signal(int sig) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci ui__exit(false); 12062306a36Sopenharmony_ci psignal(sig, "perf"); 12162306a36Sopenharmony_ci exit(0); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ciint ui__init(void) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci int err; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci SLutf8_enable(-1); 12962306a36Sopenharmony_ci SLtt_get_terminfo(); 13062306a36Sopenharmony_ci SLtt_get_screen_size(); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci err = SLsmg_init_smg(); 13362306a36Sopenharmony_ci if (err < 0) 13462306a36Sopenharmony_ci goto out; 13562306a36Sopenharmony_ci err = SLang_init_tty(-1, 0, 0); 13662306a36Sopenharmony_ci if (err < 0) 13762306a36Sopenharmony_ci goto out; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci err = SLkp_init(); 14062306a36Sopenharmony_ci if (err < 0) { 14162306a36Sopenharmony_ci pr_err("TUI initialization failed.\n"); 14262306a36Sopenharmony_ci goto out; 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci SLkp_define_keysym("^(kB)", SL_KEY_UNTAB); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci signal(SIGSEGV, ui__signal_backtrace); 14862306a36Sopenharmony_ci signal(SIGFPE, ui__signal_backtrace); 14962306a36Sopenharmony_ci signal(SIGINT, ui__signal); 15062306a36Sopenharmony_ci signal(SIGQUIT, ui__signal); 15162306a36Sopenharmony_ci signal(SIGTERM, ui__signal); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci perf_error__register(&perf_tui_eops); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci ui_helpline__init(); 15662306a36Sopenharmony_ci ui_browser__init(); 15762306a36Sopenharmony_ci tui_progress__init(); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci hist_browser__init_hpp(); 16062306a36Sopenharmony_ciout: 16162306a36Sopenharmony_ci return err; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_civoid ui__exit(bool wait_for_ok) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci if (wait_for_ok && tui_helpline__set) 16762306a36Sopenharmony_ci ui__question_window("Fatal Error", 16862306a36Sopenharmony_ci ui_helpline__last_msg, 16962306a36Sopenharmony_ci "Press any key...", 0); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci SLtt_set_cursor_visibility(1); 17262306a36Sopenharmony_ci if (mutex_trylock(&ui__lock)) { 17362306a36Sopenharmony_ci SLsmg_refresh(); 17462306a36Sopenharmony_ci SLsmg_reset_smg(); 17562306a36Sopenharmony_ci mutex_unlock(&ui__lock); 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci SLang_reset_tty(); 17862306a36Sopenharmony_ci perf_error__unregister(&perf_tui_eops); 17962306a36Sopenharmony_ci} 180