^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #ifdef HAVE_BACKTRACE_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <execinfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "../../util/debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "../../perf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "../browser.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "../helpline.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "../ui.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "../util.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "../libslang.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "../keysyms.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "tui.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static volatile int ui__need_resize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) extern struct perf_error_ops perf_tui_eops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) extern bool tui_helpline__set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) extern void hist_browser__init_hpp(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) void ui__refresh_dimensions(bool force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (force || ui__need_resize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ui__need_resize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) pthread_mutex_lock(&ui__lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) SLtt_get_screen_size();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) SLsmg_reinit_smg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) pthread_mutex_unlock(&ui__lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void ui__sigwinch(int sig __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) ui__need_resize = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static void ui__setup_sigwinch(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static bool done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) pthread__unblock_sigwinch();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) signal(SIGWINCH, ui__sigwinch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int ui__getch(int delay_secs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) fd_set read_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int err, key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ui__setup_sigwinch();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) FD_ZERO(&read_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) FD_SET(0, &read_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (delay_secs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) timeout.tv_sec = delay_secs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) timeout.tv_usec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) err = select(1, &read_set, NULL, NULL, ptimeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (err == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return K_TIMER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (err == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (errno == EINTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return K_RESIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return K_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) key = SLang_getkey();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (key != K_ESC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) FD_ZERO(&read_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) FD_SET(0, &read_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) timeout.tv_sec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) timeout.tv_usec = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) err = select(1, &read_set, NULL, NULL, &timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (err == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return K_ESC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) SLang_ungetkey(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return SLkp_getkey();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #ifdef HAVE_BACKTRACE_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static void ui__signal_backtrace(int sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) void *stackdump[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ui__exit(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) psignal(sig, "perf");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) printf("-------- backtrace --------\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) size = backtrace(stackdump, ARRAY_SIZE(stackdump));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) backtrace_symbols_fd(stackdump, size, STDOUT_FILENO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) # define ui__signal_backtrace ui__signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static void ui__signal(int sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ui__exit(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) psignal(sig, "perf");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int ui__init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) SLutf8_enable(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) SLtt_get_terminfo();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) SLtt_get_screen_size();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) err = SLsmg_init_smg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) err = SLang_init_tty(-1, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) err = SLkp_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) pr_err("TUI initialization failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) signal(SIGSEGV, ui__signal_backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) signal(SIGFPE, ui__signal_backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) signal(SIGINT, ui__signal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) signal(SIGQUIT, ui__signal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) signal(SIGTERM, ui__signal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) perf_error__register(&perf_tui_eops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ui_helpline__init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ui_browser__init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) tui_progress__init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) hist_browser__init_hpp();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) void ui__exit(bool wait_for_ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (wait_for_ok && tui_helpline__set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ui__question_window("Fatal Error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ui_helpline__last_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) "Press any key...", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) SLtt_set_cursor_visibility(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) SLsmg_refresh();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) SLsmg_reset_smg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) SLang_reset_tty();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) perf_error__unregister(&perf_tui_eops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }