1 /*
2 htop - CRT.c
3 (C) 2004-2011 Hisham H. Muhammad
4 Released under the GNU GPLv2+, see the COPYING file
5 in the source distribution for its full text.
6 */
7 
8 #include "config.h" // IWYU pragma: keep
9 
10 #include "CRT.h"
11 
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <langinfo.h>
15 #include <signal.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 
21 #include "ProvideCurses.h"
22 #include "XUtils.h"
23 
24 #if !defined(NDEBUG) && defined(HAVE_MEMFD_CREATE)
25 #include <sys/mman.h>
26 #endif
27 
28 #if defined(HAVE_LIBUNWIND_H) && defined(HAVE_LIBUNWIND)
29 # define PRINT_BACKTRACE
30 # define UNW_LOCAL_ONLY
31 # include <libunwind.h>
32 # if defined(HAVE_DLADDR)
33 #  include <dlfcn.h>
34 # endif
35 #elif defined(HAVE_EXECINFO_H)
36 # define PRINT_BACKTRACE
37 # include <execinfo.h>
38 #endif
39 
40 
41 #define ColorIndex(i,j) ((7-(i))*8+(j))
42 
43 #define ColorPair(i,j) COLOR_PAIR(ColorIndex(i,j))
44 
45 #define Black   COLOR_BLACK
46 #define Red     COLOR_RED
47 #define Green   COLOR_GREEN
48 #define Yellow  COLOR_YELLOW
49 #define Blue    COLOR_BLUE
50 #define Magenta COLOR_MAGENTA
51 #define Cyan    COLOR_CYAN
52 #define White   COLOR_WHITE
53 
54 #define ColorPairGrayBlack  ColorPair(Magenta,Magenta)
55 #define ColorIndexGrayBlack ColorIndex(Magenta,Magenta)
56 
57 #define ColorPairWhiteDefault  ColorPair(Red, Red)
58 #define ColorIndexWhiteDefault ColorIndex(Red, Red)
59 
60 static const char* const CRT_treeStrAscii[LAST_TREE_STR] = {
61    [TREE_STR_VERT] = "|",
62    [TREE_STR_RTEE] = "`",
63    [TREE_STR_BEND] = "`",
64    [TREE_STR_TEND] = ",",
65    [TREE_STR_OPEN] = "+",
66    [TREE_STR_SHUT] = "-",
67    [TREE_STR_ASC]  = "+",
68    [TREE_STR_DESC] = "-",
69 };
70 
71 #ifdef HAVE_LIBNCURSESW
72 
73 static const char* const CRT_treeStrUtf8[LAST_TREE_STR] = {
74    [TREE_STR_VERT] = "\xe2\x94\x82", // │
75    [TREE_STR_RTEE] = "\xe2\x94\x9c", // ├
76    [TREE_STR_BEND] = "\xe2\x94\x94", // └
77    [TREE_STR_TEND] = "\xe2\x94\x8c", // ┌
78    [TREE_STR_OPEN] = "+",            // +, TODO use �� 'BOX DRAWINGS LIGHT HORIZONTAL
79                                      // WITH VERTICAL STROKE' (U+1FBAF, "\xf0\x9f\xae\xaf") when
80                                      // Unicode 13 is common
81    [TREE_STR_SHUT] = "\xe2\x94\x80", // ─
82    [TREE_STR_ASC]  = "\xe2\x96\xb3", // △
83    [TREE_STR_DESC] = "\xe2\x96\xbd", // ▽
84 };
85 
86 bool CRT_utf8 = false;
87 
88 #endif
89 
90 const char* const* CRT_treeStr = CRT_treeStrAscii;
91 
92 static const Settings* CRT_crashSettings;
93 static const int* CRT_delay;
94 
95 const char* CRT_degreeSign;
96 
initDegreeSign(void)97 static const char* initDegreeSign(void) {
98 #ifdef HAVE_LIBNCURSESW
99    if (CRT_utf8)
100       return "\xc2\xb0";
101 
102    static char buffer[4];
103    // this might fail if the current locale does not support wide characters
104    int r = snprintf(buffer, sizeof(buffer), "%lc", 176);
105    if (r > 0)
106       return buffer;
107 #endif
108 
109    return "";
110 }
111 
112 const int* CRT_colors;
113 
114 static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
115    [COLORSCHEME_DEFAULT] = {
116       [RESET_COLOR] = ColorPair(White, Black),
117       [DEFAULT_COLOR] = ColorPair(White, Black),
118       [FUNCTION_BAR] = ColorPair(Black, Cyan),
119       [FUNCTION_KEY] = ColorPair(White, Black),
120       [PANEL_HEADER_FOCUS] = ColorPair(Black, Green),
121       [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green),
122       [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan),
123       [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow),
124       [PANEL_SELECTION_UNFOCUS] = ColorPair(Black, White),
125       [FAILED_SEARCH] = ColorPair(Red, Cyan),
126       [FAILED_READ] = A_BOLD | ColorPair(Red, Black),
127       [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan),
128       [UPTIME] = A_BOLD | ColorPair(Cyan, Black),
129       [BATTERY] = A_BOLD | ColorPair(Cyan, Black),
130       [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black),
131       [METER_SHADOW] = A_BOLD | ColorPairGrayBlack,
132       [METER_TEXT] = ColorPair(Cyan, Black),
133       [METER_VALUE] = A_BOLD | ColorPair(Cyan, Black),
134       [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black),
135       [METER_VALUE_IOREAD] = ColorPair(Green, Black),
136       [METER_VALUE_IOWRITE] = ColorPair(Blue, Black),
137       [METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black),
138       [METER_VALUE_OK] = ColorPair(Green, Black),
139       [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
140       [LED_COLOR] = ColorPair(Green, Black),
141       [TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black),
142       [PROCESS] = A_NORMAL,
143       [PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack,
144       [PROCESS_TAG] = A_BOLD | ColorPair(Yellow, Black),
145       [PROCESS_MEGABYTES] = ColorPair(Cyan, Black),
146       [PROCESS_GIGABYTES] = ColorPair(Green, Black),
147       [PROCESS_BASENAME] = A_BOLD | ColorPair(Cyan, Black),
148       [PROCESS_TREE] = ColorPair(Cyan, Black),
149       [PROCESS_RUN_STATE] = ColorPair(Green, Black),
150       [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
151       [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
152       [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
153       [PROCESS_NEW] = ColorPair(Black, Green),
154       [PROCESS_TOMB] = ColorPair(Black, Red),
155       [PROCESS_THREAD] = ColorPair(Green, Black),
156       [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green, Black),
157       [PROCESS_COMM] = ColorPair(Magenta, Black),
158       [PROCESS_THREAD_COMM] = ColorPair(Blue, Black),
159       [BAR_BORDER] = A_BOLD,
160       [BAR_SHADOW] = A_BOLD | ColorPairGrayBlack,
161       [SWAP] = ColorPair(Red, Black),
162       [SWAP_CACHE] = ColorPair(Yellow, Black),
163       [GRAPH_1] = A_BOLD | ColorPair(Cyan, Black),
164       [GRAPH_2] = ColorPair(Cyan, Black),
165       [MEMORY_USED] = ColorPair(Green, Black),
166       [MEMORY_BUFFERS] = ColorPair(Blue, Black),
167       [MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Blue, Black),
168       [MEMORY_CACHE] = ColorPair(Yellow, Black),
169       [MEMORY_SHARED] = ColorPair(Magenta, Black),
170       [HUGEPAGE_1] = ColorPair(Green, Black),
171       [HUGEPAGE_2] = ColorPair(Yellow, Black),
172       [HUGEPAGE_3] = ColorPair(Red, Black),
173       [HUGEPAGE_4] = ColorPair(Blue, Black),
174       [LOAD_AVERAGE_FIFTEEN] = ColorPair(Cyan, Black),
175       [LOAD_AVERAGE_FIVE] = A_BOLD | ColorPair(Cyan, Black),
176       [LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(White, Black),
177       [LOAD] = A_BOLD,
178       [HELP_BOLD] = A_BOLD | ColorPair(Cyan, Black),
179       [HELP_SHADOW] = A_BOLD | ColorPairGrayBlack,
180       [CLOCK] = A_BOLD,
181       [DATE] = A_BOLD,
182       [DATETIME] = A_BOLD,
183       [CHECK_BOX] = ColorPair(Cyan, Black),
184       [CHECK_MARK] = A_BOLD,
185       [CHECK_TEXT] = A_NORMAL,
186       [HOSTNAME] = A_BOLD,
187       [CPU_NICE] = ColorPair(Blue, Black),
188       [CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue, Black),
189       [CPU_NORMAL] = ColorPair(Green, Black),
190       [CPU_SYSTEM] = ColorPair(Red, Black),
191       [CPU_IOWAIT] = A_BOLD | ColorPairGrayBlack,
192       [CPU_IRQ] = ColorPair(Yellow, Black),
193       [CPU_SOFTIRQ] = ColorPair(Magenta, Black),
194       [CPU_STEAL] = ColorPair(Cyan, Black),
195       [CPU_GUEST] = ColorPair(Cyan, Black),
196       [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Cyan, Black),
197       [PRESSURE_STALL_SIXTY] = A_BOLD | ColorPair(Cyan, Black),
198       [PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White, Black),
199       [ZFS_MFU] = ColorPair(Blue, Black),
200       [ZFS_MRU] = ColorPair(Yellow, Black),
201       [ZFS_ANON] = ColorPair(Magenta, Black),
202       [ZFS_HEADER] = ColorPair(Cyan, Black),
203       [ZFS_OTHER] = ColorPair(Magenta, Black),
204       [ZFS_COMPRESSED] = ColorPair(Blue, Black),
205       [ZFS_RATIO] = ColorPair(Magenta, Black),
206       [ZRAM] = ColorPair(Yellow, Black),
207       [DYNAMIC_GRAY] = ColorPairGrayBlack,
208       [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack,
209       [DYNAMIC_RED] = ColorPair(Red, Black),
210       [DYNAMIC_GREEN] = ColorPair(Green, Black),
211       [DYNAMIC_BLUE] = ColorPair(Blue, Black),
212       [DYNAMIC_CYAN] = ColorPair(Cyan, Black),
213       [DYNAMIC_MAGENTA] = ColorPair(Magenta, Black),
214       [DYNAMIC_YELLOW] = ColorPair(Yellow, Black),
215       [DYNAMIC_WHITE] = ColorPair(White, Black),
216    },
217    [COLORSCHEME_MONOCHROME] = {
218       [RESET_COLOR] = A_NORMAL,
219       [DEFAULT_COLOR] = A_NORMAL,
220       [FUNCTION_BAR] = A_REVERSE,
221       [FUNCTION_KEY] = A_NORMAL,
222       [PANEL_HEADER_FOCUS] = A_REVERSE,
223       [PANEL_HEADER_UNFOCUS] = A_REVERSE,
224       [PANEL_SELECTION_FOCUS] = A_REVERSE,
225       [PANEL_SELECTION_FOLLOW] = A_REVERSE,
226       [PANEL_SELECTION_UNFOCUS] = A_BOLD,
227       [FAILED_SEARCH] = A_REVERSE | A_BOLD,
228       [FAILED_READ] = A_BOLD,
229       [PAUSED] = A_BOLD | A_REVERSE,
230       [UPTIME] = A_BOLD,
231       [BATTERY] = A_BOLD,
232       [LARGE_NUMBER] = A_BOLD,
233       [METER_SHADOW] = A_DIM,
234       [METER_TEXT] = A_NORMAL,
235       [METER_VALUE] = A_BOLD,
236       [METER_VALUE_ERROR] = A_BOLD,
237       [METER_VALUE_IOREAD] = A_NORMAL,
238       [METER_VALUE_IOWRITE] = A_NORMAL,
239       [METER_VALUE_NOTICE] = A_BOLD,
240       [METER_VALUE_OK] = A_NORMAL,
241       [METER_VALUE_WARN] = A_BOLD,
242       [LED_COLOR] = A_NORMAL,
243       [TASKS_RUNNING] = A_BOLD,
244       [PROCESS] = A_NORMAL,
245       [PROCESS_SHADOW] = A_DIM,
246       [PROCESS_TAG] = A_BOLD,
247       [PROCESS_MEGABYTES] = A_BOLD,
248       [PROCESS_GIGABYTES] = A_BOLD,
249       [PROCESS_BASENAME] = A_BOLD,
250       [PROCESS_TREE] = A_BOLD,
251       [PROCESS_RUN_STATE] = A_BOLD,
252       [PROCESS_D_STATE] = A_BOLD,
253       [PROCESS_HIGH_PRIORITY] = A_BOLD,
254       [PROCESS_LOW_PRIORITY] = A_DIM,
255       [PROCESS_NEW] = A_BOLD,
256       [PROCESS_TOMB] = A_DIM,
257       [PROCESS_THREAD] = A_BOLD,
258       [PROCESS_THREAD_BASENAME] = A_REVERSE,
259       [PROCESS_COMM] = A_BOLD,
260       [PROCESS_THREAD_COMM] = A_REVERSE,
261       [BAR_BORDER] = A_BOLD,
262       [BAR_SHADOW] = A_DIM,
263       [SWAP] = A_BOLD,
264       [SWAP_CACHE] = A_NORMAL,
265       [GRAPH_1] = A_BOLD,
266       [GRAPH_2] = A_NORMAL,
267       [MEMORY_USED] = A_BOLD,
268       [MEMORY_BUFFERS] = A_NORMAL,
269       [MEMORY_BUFFERS_TEXT] = A_NORMAL,
270       [MEMORY_CACHE] = A_NORMAL,
271       [MEMORY_SHARED] = A_NORMAL,
272       [HUGEPAGE_1] = A_BOLD,
273       [HUGEPAGE_2] = A_NORMAL,
274       [HUGEPAGE_3] = A_REVERSE | A_BOLD,
275       [HUGEPAGE_4] = A_REVERSE,
276       [LOAD_AVERAGE_FIFTEEN] = A_DIM,
277       [LOAD_AVERAGE_FIVE] = A_NORMAL,
278       [LOAD_AVERAGE_ONE] = A_BOLD,
279       [LOAD] = A_BOLD,
280       [HELP_BOLD] = A_BOLD,
281       [HELP_SHADOW] = A_DIM,
282       [CLOCK] = A_BOLD,
283       [DATE] = A_BOLD,
284       [DATETIME] = A_BOLD,
285       [CHECK_BOX] = A_BOLD,
286       [CHECK_MARK] = A_NORMAL,
287       [CHECK_TEXT] = A_NORMAL,
288       [HOSTNAME] = A_BOLD,
289       [CPU_NICE] = A_NORMAL,
290       [CPU_NICE_TEXT] = A_NORMAL,
291       [CPU_NORMAL] = A_BOLD,
292       [CPU_SYSTEM] = A_BOLD,
293       [CPU_IOWAIT] = A_NORMAL,
294       [CPU_IRQ] = A_BOLD,
295       [CPU_SOFTIRQ] = A_BOLD,
296       [CPU_STEAL] = A_DIM,
297       [CPU_GUEST] = A_DIM,
298       [PRESSURE_STALL_THREEHUNDRED] = A_DIM,
299       [PRESSURE_STALL_SIXTY] = A_NORMAL,
300       [PRESSURE_STALL_TEN] = A_BOLD,
301       [ZFS_MFU] = A_NORMAL,
302       [ZFS_MRU] = A_NORMAL,
303       [ZFS_ANON] = A_DIM,
304       [ZFS_HEADER] = A_BOLD,
305       [ZFS_OTHER] = A_DIM,
306       [ZFS_COMPRESSED] = A_BOLD,
307       [ZFS_RATIO] = A_BOLD,
308       [ZRAM] = A_NORMAL,
309       [DYNAMIC_GRAY] = A_DIM,
310       [DYNAMIC_DARKGRAY] = A_DIM,
311       [DYNAMIC_RED] = A_BOLD,
312       [DYNAMIC_GREEN] = A_NORMAL,
313       [DYNAMIC_BLUE] = A_NORMAL,
314       [DYNAMIC_CYAN] = A_BOLD,
315       [DYNAMIC_MAGENTA] = A_NORMAL,
316       [DYNAMIC_YELLOW] = A_NORMAL,
317       [DYNAMIC_WHITE] = A_BOLD,
318    },
319    [COLORSCHEME_BLACKONWHITE] = {
320       [RESET_COLOR] = ColorPair(Black, White),
321       [DEFAULT_COLOR] = ColorPair(Black, White),
322       [FUNCTION_BAR] = ColorPair(Black, Cyan),
323       [FUNCTION_KEY] = ColorPair(Black, White),
324       [PANEL_HEADER_FOCUS] = ColorPair(Black, Green),
325       [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green),
326       [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan),
327       [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow),
328       [PANEL_SELECTION_UNFOCUS] = ColorPair(Blue, White),
329       [FAILED_SEARCH] = ColorPair(Red, Cyan),
330       [FAILED_READ] = ColorPair(Red, White),
331       [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan),
332       [UPTIME] = ColorPair(Yellow, White),
333       [BATTERY] = ColorPair(Yellow, White),
334       [LARGE_NUMBER] = ColorPair(Red, White),
335       [METER_SHADOW] = ColorPair(Blue, White),
336       [METER_TEXT] = ColorPair(Blue, White),
337       [METER_VALUE] = ColorPair(Black, White),
338       [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, White),
339       [METER_VALUE_IOREAD] = ColorPair(Green, White),
340       [METER_VALUE_IOWRITE] = ColorPair(Yellow, White),
341       [METER_VALUE_NOTICE] = A_BOLD | ColorPair(Yellow, White),
342       [METER_VALUE_OK] = ColorPair(Green, White),
343       [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, White),
344       [LED_COLOR] = ColorPair(Green, White),
345       [TASKS_RUNNING] = ColorPair(Green, White),
346       [PROCESS] = ColorPair(Black, White),
347       [PROCESS_SHADOW] = A_BOLD | ColorPair(Black, White),
348       [PROCESS_TAG] = ColorPair(White, Blue),
349       [PROCESS_MEGABYTES] = ColorPair(Blue, White),
350       [PROCESS_GIGABYTES] = ColorPair(Green, White),
351       [PROCESS_BASENAME] = ColorPair(Blue, White),
352       [PROCESS_TREE] = ColorPair(Green, White),
353       [PROCESS_RUN_STATE] = ColorPair(Green, White),
354       [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, White),
355       [PROCESS_HIGH_PRIORITY] = ColorPair(Red, White),
356       [PROCESS_LOW_PRIORITY] = ColorPair(Green, White),
357       [PROCESS_NEW] = ColorPair(White, Green),
358       [PROCESS_TOMB] = ColorPair(White, Red),
359       [PROCESS_THREAD] = ColorPair(Blue, White),
360       [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, White),
361       [PROCESS_COMM] = ColorPair(Magenta, White),
362       [PROCESS_THREAD_COMM] = ColorPair(Green, White),
363       [BAR_BORDER] = ColorPair(Blue, White),
364       [BAR_SHADOW] = ColorPair(Black, White),
365       [SWAP] = ColorPair(Red, White),
366       [SWAP_CACHE] = ColorPair(Yellow, White),
367       [GRAPH_1] = A_BOLD | ColorPair(Blue, White),
368       [GRAPH_2] = ColorPair(Blue, White),
369       [MEMORY_USED] = ColorPair(Green, White),
370       [MEMORY_BUFFERS] = ColorPair(Cyan, White),
371       [MEMORY_BUFFERS_TEXT] = ColorPair(Cyan, White),
372       [MEMORY_CACHE] = ColorPair(Yellow, White),
373       [MEMORY_SHARED] = ColorPair(Magenta, White),
374       [HUGEPAGE_1] = ColorPair(Green, White),
375       [HUGEPAGE_2] = ColorPair(Yellow, White),
376       [HUGEPAGE_3] = ColorPair(Red, White),
377       [HUGEPAGE_4] = ColorPair(Blue, White),
378       [LOAD_AVERAGE_FIFTEEN] = ColorPair(Black, White),
379       [LOAD_AVERAGE_FIVE] = ColorPair(Black, White),
380       [LOAD_AVERAGE_ONE] = ColorPair(Black, White),
381       [LOAD] = ColorPair(Black, White),
382       [HELP_BOLD] = ColorPair(Blue, White),
383       [HELP_SHADOW] = A_BOLD | ColorPair(Black, White),
384       [CLOCK] = ColorPair(Black, White),
385       [DATE] = ColorPair(Black, White),
386       [DATETIME] = ColorPair(Black, White),
387       [CHECK_BOX] = ColorPair(Blue, White),
388       [CHECK_MARK] = ColorPair(Black, White),
389       [CHECK_TEXT] = ColorPair(Black, White),
390       [HOSTNAME] = ColorPair(Black, White),
391       [CPU_NICE] = ColorPair(Cyan, White),
392       [CPU_NICE_TEXT] = ColorPair(Cyan, White),
393       [CPU_NORMAL] = ColorPair(Green, White),
394       [CPU_SYSTEM] = ColorPair(Red, White),
395       [CPU_IOWAIT] = A_BOLD | ColorPair(Black, White),
396       [CPU_IRQ] = ColorPair(Blue, White),
397       [CPU_SOFTIRQ] = ColorPair(Blue, White),
398       [CPU_STEAL] = ColorPair(Cyan, White),
399       [CPU_GUEST] = ColorPair(Cyan, White),
400       [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, White),
401       [PRESSURE_STALL_SIXTY] = ColorPair(Black, White),
402       [PRESSURE_STALL_TEN] = ColorPair(Black, White),
403       [ZFS_MFU] = ColorPair(Cyan, White),
404       [ZFS_MRU] = ColorPair(Yellow, White),
405       [ZFS_ANON] = ColorPair(Magenta, White),
406       [ZFS_HEADER] = ColorPair(Yellow, White),
407       [ZFS_OTHER] = ColorPair(Magenta, White),
408       [ZFS_COMPRESSED] = ColorPair(Cyan, White),
409       [ZFS_RATIO] = ColorPair(Magenta, White),
410       [ZRAM] = ColorPair(Yellow, White),
411       [DYNAMIC_GRAY] = ColorPair(Black, White),
412       [DYNAMIC_DARKGRAY] = A_BOLD | ColorPair(Black, White),
413       [DYNAMIC_RED] = ColorPair(Red, White),
414       [DYNAMIC_GREEN] = ColorPair(Green, White),
415       [DYNAMIC_BLUE] = ColorPair(Blue, White),
416       [DYNAMIC_CYAN] = ColorPair(Yellow, White),
417       [DYNAMIC_MAGENTA] = ColorPair(Magenta, White),
418       [DYNAMIC_YELLOW] = ColorPair(Yellow, White),
419       [DYNAMIC_WHITE] = A_BOLD | ColorPair(Black, White),
420    },
421    [COLORSCHEME_LIGHTTERMINAL] = {
422       [RESET_COLOR] = ColorPair(Black, Black),
423       [DEFAULT_COLOR] = ColorPair(Black, Black),
424       [FUNCTION_BAR] = ColorPair(Black, Cyan),
425       [FUNCTION_KEY] = ColorPair(Black, Black),
426       [PANEL_HEADER_FOCUS] = ColorPair(Black, Green),
427       [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green),
428       [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan),
429       [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow),
430       [PANEL_SELECTION_UNFOCUS] = ColorPair(Blue, Black),
431       [FAILED_SEARCH] = ColorPair(Red, Cyan),
432       [FAILED_READ] = ColorPair(Red, Black),
433       [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan),
434       [UPTIME] = ColorPair(Yellow, Black),
435       [BATTERY] = ColorPair(Yellow, Black),
436       [LARGE_NUMBER] = ColorPair(Red, Black),
437       [METER_SHADOW] = A_BOLD | ColorPairGrayBlack,
438       [METER_TEXT] = ColorPair(Blue, Black),
439       [METER_VALUE] = ColorPair(Black, Black),
440       [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black),
441       [METER_VALUE_IOREAD] = ColorPair(Green, Black),
442       [METER_VALUE_IOWRITE] = ColorPair(Yellow, Black),
443       [METER_VALUE_NOTICE] = A_BOLD | ColorPairWhiteDefault,
444       [METER_VALUE_OK] = ColorPair(Green, Black),
445       [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
446       [LED_COLOR] = ColorPair(Green, Black),
447       [TASKS_RUNNING] = ColorPair(Green, Black),
448       [PROCESS] = ColorPair(Black, Black),
449       [PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack,
450       [PROCESS_TAG] = ColorPair(White, Blue),
451       [PROCESS_MEGABYTES] = ColorPair(Blue, Black),
452       [PROCESS_GIGABYTES] = ColorPair(Green, Black),
453       [PROCESS_BASENAME] = ColorPair(Green, Black),
454       [PROCESS_TREE] = ColorPair(Blue, Black),
455       [PROCESS_RUN_STATE] = ColorPair(Green, Black),
456       [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
457       [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
458       [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
459       [PROCESS_NEW] = ColorPair(Black, Green),
460       [PROCESS_TOMB] = ColorPair(Black, Red),
461       [PROCESS_THREAD] = ColorPair(Blue, Black),
462       [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, Black),
463       [PROCESS_COMM] = ColorPair(Magenta, Black),
464       [PROCESS_THREAD_COMM] = ColorPair(Yellow, Black),
465       [BAR_BORDER] = ColorPair(Blue, Black),
466       [BAR_SHADOW] = ColorPairGrayBlack,
467       [SWAP] = ColorPair(Red, Black),
468       [SWAP_CACHE] = ColorPair(Yellow, Black),
469       [GRAPH_1] = A_BOLD | ColorPair(Cyan, Black),
470       [GRAPH_2] = ColorPair(Cyan, Black),
471       [MEMORY_USED] = ColorPair(Green, Black),
472       [MEMORY_BUFFERS] = ColorPair(Cyan, Black),
473       [MEMORY_BUFFERS_TEXT] = ColorPair(Cyan, Black),
474       [MEMORY_CACHE] = ColorPair(Yellow, Black),
475       [MEMORY_SHARED] = ColorPair(Magenta, Black),
476       [HUGEPAGE_1] = ColorPair(Green, Black),
477       [HUGEPAGE_2] = ColorPair(Yellow, Black),
478       [HUGEPAGE_3] = ColorPair(Red, Black),
479       [HUGEPAGE_4] = ColorPair(Blue, Black),
480       [LOAD_AVERAGE_FIFTEEN] = ColorPair(Black, Black),
481       [LOAD_AVERAGE_FIVE] = ColorPair(Black, Black),
482       [LOAD_AVERAGE_ONE] = ColorPair(Black, Black),
483       [LOAD] = ColorPairWhiteDefault,
484       [HELP_BOLD] = ColorPair(Blue, Black),
485       [HELP_SHADOW] = A_BOLD | ColorPairGrayBlack,
486       [CLOCK] = ColorPairWhiteDefault,
487       [DATE] = ColorPairWhiteDefault,
488       [DATETIME] = ColorPairWhiteDefault,
489       [CHECK_BOX] = ColorPair(Blue, Black),
490       [CHECK_MARK] = ColorPair(Black, Black),
491       [CHECK_TEXT] = ColorPair(Black, Black),
492       [HOSTNAME] = ColorPairWhiteDefault,
493       [CPU_NICE] = ColorPair(Cyan, Black),
494       [CPU_NICE_TEXT] = ColorPair(Cyan, Black),
495       [CPU_NORMAL] = ColorPair(Green, Black),
496       [CPU_SYSTEM] = ColorPair(Red, Black),
497       [CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black),
498       [CPU_IRQ] = A_BOLD | ColorPair(Blue, Black),
499       [CPU_SOFTIRQ] = ColorPair(Blue, Black),
500       [CPU_STEAL] = ColorPair(Black, Black),
501       [CPU_GUEST] = ColorPair(Black, Black),
502       [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, Black),
503       [PRESSURE_STALL_SIXTY] = ColorPair(Black, Black),
504       [PRESSURE_STALL_TEN] = ColorPair(Black, Black),
505       [ZFS_MFU] = ColorPair(Cyan, Black),
506       [ZFS_MRU] = ColorPair(Yellow, Black),
507       [ZFS_ANON] = A_BOLD | ColorPair(Magenta, Black),
508       [ZFS_HEADER] = ColorPair(Black, Black),
509       [ZFS_OTHER] = A_BOLD | ColorPair(Magenta, Black),
510       [ZFS_COMPRESSED] = ColorPair(Cyan, Black),
511       [ZFS_RATIO] = A_BOLD | ColorPair(Magenta, Black),
512       [ZRAM] = ColorPair(Yellow, Black),
513       [DYNAMIC_GRAY] = ColorPairGrayBlack,
514       [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack,
515       [DYNAMIC_RED] = ColorPair(Red, Black),
516       [DYNAMIC_GREEN] = ColorPair(Green, Black),
517       [DYNAMIC_BLUE] = ColorPair(Blue, Black),
518       [DYNAMIC_CYAN] = ColorPair(Cyan, Black),
519       [DYNAMIC_MAGENTA] = ColorPair(Magenta, Black),
520       [DYNAMIC_YELLOW] = ColorPair(Yellow, Black),
521       [DYNAMIC_WHITE] = ColorPairWhiteDefault,
522    },
523    [COLORSCHEME_MIDNIGHT] = {
524       [RESET_COLOR] = ColorPair(White, Blue),
525       [DEFAULT_COLOR] = ColorPair(White, Blue),
526       [FUNCTION_BAR] = ColorPair(Black, Cyan),
527       [FUNCTION_KEY] = A_NORMAL,
528       [PANEL_HEADER_FOCUS] = ColorPair(Black, Cyan),
529       [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Cyan),
530       [PANEL_SELECTION_FOCUS] = ColorPair(Black, White),
531       [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow),
532       [PANEL_SELECTION_UNFOCUS] = A_BOLD | ColorPair(Yellow, Blue),
533       [FAILED_SEARCH] = ColorPair(Red, Cyan),
534       [FAILED_READ] = A_BOLD | ColorPair(Red, Blue),
535       [PAUSED] = A_BOLD | ColorPair(Yellow, Cyan),
536       [UPTIME] = A_BOLD | ColorPair(Yellow, Blue),
537       [BATTERY] = A_BOLD | ColorPair(Yellow, Blue),
538       [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Blue),
539       [METER_SHADOW] = ColorPair(Cyan, Blue),
540       [METER_TEXT] = ColorPair(Cyan, Blue),
541       [METER_VALUE] = A_BOLD | ColorPair(Cyan, Blue),
542       [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Blue),
543       [METER_VALUE_IOREAD] = ColorPair(Green, Blue),
544       [METER_VALUE_IOWRITE] = ColorPair(Black, Blue),
545       [METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Blue),
546       [METER_VALUE_OK] = ColorPair(Green, Blue),
547       [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
548       [LED_COLOR] = ColorPair(Green, Blue),
549       [TASKS_RUNNING] = A_BOLD | ColorPair(Green, Blue),
550       [PROCESS] = ColorPair(White, Blue),
551       [PROCESS_SHADOW] = A_BOLD | ColorPair(Black, Blue),
552       [PROCESS_TAG] = A_BOLD | ColorPair(Yellow, Blue),
553       [PROCESS_MEGABYTES] = ColorPair(Cyan, Blue),
554       [PROCESS_GIGABYTES] = ColorPair(Green, Blue),
555       [PROCESS_BASENAME] = A_BOLD | ColorPair(Cyan, Blue),
556       [PROCESS_TREE] = ColorPair(Cyan, Blue),
557       [PROCESS_RUN_STATE] = ColorPair(Green, Blue),
558       [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Blue),
559       [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Blue),
560       [PROCESS_LOW_PRIORITY] = ColorPair(Green, Blue),
561       [PROCESS_NEW] = ColorPair(Blue, Green),
562       [PROCESS_TOMB] = ColorPair(Blue, Red),
563       [PROCESS_THREAD] = ColorPair(Green, Blue),
564       [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green, Blue),
565       [PROCESS_COMM] = ColorPair(Magenta, Blue),
566       [PROCESS_THREAD_COMM] = ColorPair(Black, Blue),
567       [BAR_BORDER] = A_BOLD | ColorPair(Yellow, Blue),
568       [BAR_SHADOW] = ColorPair(Cyan, Blue),
569       [SWAP] = ColorPair(Red, Blue),
570       [SWAP_CACHE] = A_BOLD | ColorPair(Yellow, Blue),
571       [GRAPH_1] = A_BOLD | ColorPair(Cyan, Blue),
572       [GRAPH_2] = ColorPair(Cyan, Blue),
573       [MEMORY_USED] = A_BOLD | ColorPair(Green, Blue),
574       [MEMORY_BUFFERS] = A_BOLD | ColorPair(Cyan, Blue),
575       [MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Cyan, Blue),
576       [MEMORY_CACHE] = A_BOLD | ColorPair(Yellow, Blue),
577       [MEMORY_SHARED] = A_BOLD | ColorPair(Magenta, Blue),
578       [HUGEPAGE_1] = A_BOLD | ColorPair(Green, Blue),
579       [HUGEPAGE_2] = A_BOLD | ColorPair(Yellow, Blue),
580       [HUGEPAGE_3] = A_BOLD | ColorPair(Red, Blue),
581       [HUGEPAGE_4] = A_BOLD | ColorPair(White, Blue),
582       [LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black, Blue),
583       [LOAD_AVERAGE_FIVE] = A_NORMAL | ColorPair(White, Blue),
584       [LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(White, Blue),
585       [LOAD] = A_BOLD | ColorPair(White, Blue),
586       [HELP_BOLD] = A_BOLD | ColorPair(Cyan, Blue),
587       [HELP_SHADOW] = A_BOLD | ColorPair(Black, Blue),
588       [CLOCK] = ColorPair(White, Blue),
589       [DATE] = ColorPair(White, Blue),
590       [DATETIME] = ColorPair(White, Blue),
591       [CHECK_BOX] = ColorPair(Cyan, Blue),
592       [CHECK_MARK] = A_BOLD | ColorPair(White, Blue),
593       [CHECK_TEXT] = A_NORMAL | ColorPair(White, Blue),
594       [HOSTNAME] = ColorPair(White, Blue),
595       [CPU_NICE] = A_BOLD | ColorPair(Cyan, Blue),
596       [CPU_NICE_TEXT] = A_BOLD | ColorPair(Cyan, Blue),
597       [CPU_NORMAL] = A_BOLD | ColorPair(Green, Blue),
598       [CPU_SYSTEM] = A_BOLD | ColorPair(Red, Blue),
599       [CPU_IOWAIT] = A_BOLD | ColorPair(Black, Blue),
600       [CPU_IRQ] = A_BOLD | ColorPair(Black, Blue),
601       [CPU_SOFTIRQ] = ColorPair(Black, Blue),
602       [CPU_STEAL] = ColorPair(White, Blue),
603       [CPU_GUEST] = ColorPair(White, Blue),
604       [PRESSURE_STALL_THREEHUNDRED] = A_BOLD | ColorPair(Black, Blue),
605       [PRESSURE_STALL_SIXTY] = A_NORMAL | ColorPair(White, Blue),
606       [PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White, Blue),
607       [ZFS_MFU] = A_BOLD | ColorPair(White, Blue),
608       [ZFS_MRU] = A_BOLD | ColorPair(Yellow, Blue),
609       [ZFS_ANON] = A_BOLD | ColorPair(Magenta, Blue),
610       [ZFS_HEADER] = A_BOLD | ColorPair(Yellow, Blue),
611       [ZFS_OTHER] = A_BOLD | ColorPair(Magenta, Blue),
612       [ZFS_COMPRESSED] = A_BOLD | ColorPair(White, Blue),
613       [ZFS_RATIO] = A_BOLD | ColorPair(Magenta, Blue),
614       [ZRAM] = A_BOLD | ColorPair(Yellow, Blue),
615       [DYNAMIC_GRAY] = ColorPairGrayBlack,
616       [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack,
617       [DYNAMIC_RED] = ColorPair(Red, Blue),
618       [DYNAMIC_GREEN] = ColorPair(Green, Blue),
619       [DYNAMIC_BLUE] = ColorPair(Black, Blue),
620       [DYNAMIC_CYAN] = ColorPair(Cyan, Blue),
621       [DYNAMIC_MAGENTA] = ColorPair(Magenta, Blue),
622       [DYNAMIC_YELLOW] = ColorPair(Yellow, Blue),
623       [DYNAMIC_WHITE] = ColorPair(White, Blue),
624    },
625    [COLORSCHEME_BLACKNIGHT] = {
626       [RESET_COLOR] = ColorPair(Cyan, Black),
627       [DEFAULT_COLOR] = ColorPair(Cyan, Black),
628       [FUNCTION_BAR] = ColorPair(Black, Green),
629       [FUNCTION_KEY] = ColorPair(Cyan, Black),
630       [PANEL_HEADER_FOCUS] = ColorPair(Black, Green),
631       [PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green),
632       [PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan),
633       [PANEL_SELECTION_FOLLOW] = ColorPair(Black, Yellow),
634       [PANEL_SELECTION_UNFOCUS] = ColorPair(Black, White),
635       [FAILED_SEARCH] = ColorPair(Red, Green),
636       [FAILED_READ] = A_BOLD | ColorPair(Red, Black),
637       [PAUSED] = A_BOLD | ColorPair(Yellow, Green),
638       [UPTIME] = ColorPair(Green, Black),
639       [BATTERY] = ColorPair(Green, Black),
640       [LARGE_NUMBER] = A_BOLD | ColorPair(Red, Black),
641       [METER_SHADOW] = A_BOLD | ColorPairGrayBlack,
642       [METER_TEXT] = ColorPair(Cyan, Black),
643       [METER_VALUE] = ColorPair(Green, Black),
644       [METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black),
645       [METER_VALUE_IOREAD] = ColorPair(Green, Black),
646       [METER_VALUE_IOWRITE] = ColorPair(Blue, Black),
647       [METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black),
648       [METER_VALUE_OK] = ColorPair(Green, Black),
649       [METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
650       [LED_COLOR] = ColorPair(Green, Black),
651       [TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black),
652       [PROCESS] = ColorPair(Cyan, Black),
653       [PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack,
654       [PROCESS_TAG] = A_BOLD | ColorPair(Yellow, Black),
655       [PROCESS_MEGABYTES] = A_BOLD | ColorPair(Green, Black),
656       [PROCESS_GIGABYTES] = A_BOLD | ColorPair(Yellow, Black),
657       [PROCESS_BASENAME] = A_BOLD | ColorPair(Green, Black),
658       [PROCESS_TREE] = ColorPair(Cyan, Black),
659       [PROCESS_THREAD] = ColorPair(Green, Black),
660       [PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, Black),
661       [PROCESS_COMM] = ColorPair(Magenta, Black),
662       [PROCESS_THREAD_COMM] = ColorPair(Yellow, Black),
663       [PROCESS_RUN_STATE] = ColorPair(Green, Black),
664       [PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
665       [PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
666       [PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
667       [PROCESS_NEW] = ColorPair(Black, Green),
668       [PROCESS_TOMB] = ColorPair(Black, Red),
669       [BAR_BORDER] = A_BOLD | ColorPair(Green, Black),
670       [BAR_SHADOW] = ColorPair(Cyan, Black),
671       [SWAP] = ColorPair(Red, Black),
672       [SWAP_CACHE] = ColorPair(Yellow, Black),
673       [GRAPH_1] = A_BOLD | ColorPair(Green, Black),
674       [GRAPH_2] = ColorPair(Green, Black),
675       [MEMORY_USED] = ColorPair(Green, Black),
676       [MEMORY_BUFFERS] = ColorPair(Blue, Black),
677       [MEMORY_BUFFERS_TEXT] = A_BOLD | ColorPair(Blue, Black),
678       [MEMORY_CACHE] = ColorPair(Yellow, Black),
679       [MEMORY_SHARED] = ColorPair(Magenta, Black),
680       [HUGEPAGE_1] = ColorPair(Green, Black),
681       [HUGEPAGE_2] = ColorPair(Yellow, Black),
682       [HUGEPAGE_3] = ColorPair(Red, Black),
683       [HUGEPAGE_4] = ColorPair(Blue, Black),
684       [LOAD_AVERAGE_FIFTEEN] = ColorPair(Green, Black),
685       [LOAD_AVERAGE_FIVE] = ColorPair(Green, Black),
686       [LOAD_AVERAGE_ONE] = A_BOLD | ColorPair(Green, Black),
687       [LOAD] = A_BOLD,
688       [HELP_BOLD] = A_BOLD | ColorPair(Cyan, Black),
689       [HELP_SHADOW] = A_BOLD | ColorPairGrayBlack,
690       [CLOCK] = ColorPair(Green, Black),
691       [CHECK_BOX] = ColorPair(Green, Black),
692       [CHECK_MARK] = A_BOLD | ColorPair(Green, Black),
693       [CHECK_TEXT] = ColorPair(Cyan, Black),
694       [HOSTNAME] = ColorPair(Green, Black),
695       [CPU_NICE] = ColorPair(Blue, Black),
696       [CPU_NICE_TEXT] = A_BOLD | ColorPair(Blue, Black),
697       [CPU_NORMAL] = ColorPair(Green, Black),
698       [CPU_SYSTEM] = ColorPair(Red, Black),
699       [CPU_IOWAIT] = ColorPair(Yellow, Black),
700       [CPU_IRQ] = A_BOLD | ColorPair(Blue, Black),
701       [CPU_SOFTIRQ] = ColorPair(Blue, Black),
702       [CPU_STEAL] = ColorPair(Cyan, Black),
703       [CPU_GUEST] = ColorPair(Cyan, Black),
704       [PRESSURE_STALL_THREEHUNDRED] = ColorPair(Green, Black),
705       [PRESSURE_STALL_SIXTY] = ColorPair(Green, Black),
706       [PRESSURE_STALL_TEN] = A_BOLD | ColorPair(Green, Black),
707       [ZFS_MFU] = ColorPair(Blue, Black),
708       [ZFS_MRU] = ColorPair(Yellow, Black),
709       [ZFS_ANON] = ColorPair(Magenta, Black),
710       [ZFS_HEADER] = ColorPair(Yellow, Black),
711       [ZFS_OTHER] = ColorPair(Magenta, Black),
712       [ZFS_COMPRESSED] = ColorPair(Blue, Black),
713       [ZFS_RATIO] = ColorPair(Magenta, Black),
714       [ZRAM] = ColorPair(Yellow, Black),
715       [DYNAMIC_GRAY] = ColorPairGrayBlack,
716       [DYNAMIC_DARKGRAY] = A_BOLD | ColorPairGrayBlack,
717       [DYNAMIC_RED] = ColorPair(Red, Black),
718       [DYNAMIC_GREEN] = ColorPair(Green, Black),
719       [DYNAMIC_BLUE] = ColorPair(Blue, Black),
720       [DYNAMIC_CYAN] = ColorPair(Cyan, Black),
721       [DYNAMIC_MAGENTA] = ColorPair(Magenta, Black),
722       [DYNAMIC_YELLOW] = ColorPair(Yellow, Black),
723       [DYNAMIC_WHITE] = ColorPair(White, Black),
724    },
725    [COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated.
726 };
727 
728 int CRT_cursorX = 0;
729 
730 int CRT_scrollHAmount = 5;
731 
732 int CRT_scrollWheelVAmount = 10;
733 
734 ColorScheme CRT_colorScheme = COLORSCHEME_DEFAULT;
735 
736 ATTR_NORETURN
CRT_handleSIGTERM(ATTR_UNUSED int sgn)737 static void CRT_handleSIGTERM(ATTR_UNUSED int sgn) {
738    CRT_done();
739    _exit(0);
740 }
741 
742 #ifndef NDEBUG
743 
744 static int stderrRedirectNewFd = -1;
745 static int stderrRedirectBackupFd = -1;
746 
createStderrCacheFile(void)747 static int createStderrCacheFile(void) {
748 #if defined(HAVE_MEMFD_CREATE)
749    return memfd_create("htop.stderr-redirect", 0);
750 #elif defined(O_TMPFILE)
751    return open("/tmp", O_TMPFILE | O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
752 #else
753    char tmpName[] = "htop.stderr-redirectXXXXXX";
754    mode_t curUmask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
755    int r = mkstemp(tmpName);
756    umask(curUmask);
757    if (r < 0)
758       return r;
759 
760    (void) unlink(tmpName);
761 
762    return r;
763 #endif /* HAVE_MEMFD_CREATE */
764 }
765 
redirectStderr(void)766 static void redirectStderr(void) {
767    stderrRedirectNewFd = createStderrCacheFile();
768    if (stderrRedirectNewFd < 0) {
769       /* ignore failure */
770       return;
771    }
772 
773    stderrRedirectBackupFd = dup(STDERR_FILENO);
774    dup2(stderrRedirectNewFd, STDERR_FILENO);
775 }
776 
dumpStderr(void)777 static void dumpStderr(void) {
778    if (stderrRedirectNewFd < 0)
779       return;
780 
781    fsync(STDERR_FILENO);
782    dup2(stderrRedirectBackupFd, STDERR_FILENO);
783    close(stderrRedirectBackupFd);
784    stderrRedirectBackupFd = -1;
785    lseek(stderrRedirectNewFd, 0, SEEK_SET);
786 
787    bool header = false;
788    char buffer[8192];
789    for (;;) {
790       errno = 0;
791       ssize_t res = read(stderrRedirectNewFd, buffer, sizeof(buffer));
792       if (res < 0) {
793          if (errno == EINTR)
794             continue;
795 
796          break;
797       }
798 
799       if (res == 0) {
800          break;
801       }
802 
803       if (res > 0) {
804          if (!header) {
805             fprintf(stderr, ">>>>>>>>>> stderr output >>>>>>>>>>\n");
806             header = true;
807          }
808          (void)! write(STDERR_FILENO, buffer, res);
809       }
810    }
811 
812    if (header)
813       fprintf(stderr, "\n<<<<<<<<<< stderr output <<<<<<<<<<\n");
814 
815    close(stderrRedirectNewFd);
816    stderrRedirectNewFd = -1;
817 }
818 
819 #else /* !NDEBUG */
820 
redirectStderr(void)821 static void redirectStderr(void) {
822 }
823 
dumpStderr(void)824 static void dumpStderr(void) {
825 }
826 
827 #endif /* !NDEBUG */
828 
829 static struct sigaction old_sig_handler[32];
830 
CRT_installSignalHandlers(void)831 static void CRT_installSignalHandlers(void) {
832    struct sigaction act;
833    sigemptyset (&act.sa_mask);
834    act.sa_flags = (int)SA_RESETHAND | SA_NODEFER;
835    act.sa_handler = CRT_handleSIGSEGV;
836    sigaction (SIGSEGV, &act, &old_sig_handler[SIGSEGV]);
837    sigaction (SIGFPE, &act, &old_sig_handler[SIGFPE]);
838    sigaction (SIGILL, &act, &old_sig_handler[SIGILL]);
839    sigaction (SIGBUS, &act, &old_sig_handler[SIGBUS]);
840    sigaction (SIGPIPE, &act, &old_sig_handler[SIGPIPE]);
841    sigaction (SIGSYS, &act, &old_sig_handler[SIGSYS]);
842    sigaction (SIGABRT, &act, &old_sig_handler[SIGABRT]);
843 
844    signal(SIGINT, CRT_handleSIGTERM);
845    signal(SIGTERM, CRT_handleSIGTERM);
846    signal(SIGQUIT, CRT_handleSIGTERM);
847 }
848 
CRT_resetSignalHandlers(void)849 void CRT_resetSignalHandlers(void) {
850    sigaction (SIGSEGV, &old_sig_handler[SIGSEGV], NULL);
851    sigaction (SIGFPE, &old_sig_handler[SIGFPE], NULL);
852    sigaction (SIGILL, &old_sig_handler[SIGILL], NULL);
853    sigaction (SIGBUS, &old_sig_handler[SIGBUS], NULL);
854    sigaction (SIGPIPE, &old_sig_handler[SIGPIPE], NULL);
855    sigaction (SIGSYS, &old_sig_handler[SIGSYS], NULL);
856    sigaction (SIGABRT, &old_sig_handler[SIGABRT], NULL);
857 
858    signal(SIGINT, SIG_DFL);
859    signal(SIGTERM, SIG_DFL);
860    signal(SIGQUIT, SIG_DFL);
861 }
862 
CRT_init(const Settings * settings,bool allowUnicode)863 void CRT_init(const Settings* settings, bool allowUnicode) {
864    redirectStderr();
865 
866    initscr();
867    noecho();
868    CRT_crashSettings = settings;
869    CRT_delay = &(settings->delay);
870    CRT_colors = CRT_colorSchemes[settings->colorScheme];
871    CRT_colorScheme = settings->colorScheme;
872 
873    for (int i = 0; i < LAST_COLORELEMENT; i++) {
874       unsigned int color = CRT_colorSchemes[COLORSCHEME_DEFAULT][i];
875       CRT_colorSchemes[COLORSCHEME_BROKENGRAY][i] = color == (A_BOLD | ColorPairGrayBlack) ? ColorPair(White, Black) : color;
876    }
877 
878    halfdelay(*CRT_delay);
879    nonl();
880    intrflush(stdscr, false);
881    keypad(stdscr, true);
882 #ifdef HAVE_GETMOUSE
883    mouseinterval(0);
884 #endif
885    curs_set(0);
886 
887    if (has_colors()) {
888       start_color();
889    }
890 
891    const char* termType = getenv("TERM");
892    if (termType && String_eq(termType, "linux")) {
893       CRT_scrollHAmount = 20;
894    } else {
895       CRT_scrollHAmount = 5;
896    }
897 
898    if (termType && (String_startsWith(termType, "xterm") || String_eq(termType, "vt220"))) {
899 #ifdef HTOP_NETBSD
900 #define define_key(s_, k_) define_key((char*)s_, k_)
901 IGNORE_WCASTQUAL_BEGIN
902 #endif
903       define_key("\033[H", KEY_HOME);
904       define_key("\033[F", KEY_END);
905       define_key("\033[7~", KEY_HOME);
906       define_key("\033[8~", KEY_END);
907       define_key("\033OP", KEY_F(1));
908       define_key("\033OQ", KEY_F(2));
909       define_key("\033OR", KEY_F(3));
910       define_key("\033OS", KEY_F(4));
911       define_key("\033O2R", KEY_F(15));
912       define_key("\033[11~", KEY_F(1));
913       define_key("\033[12~", KEY_F(2));
914       define_key("\033[13~", KEY_F(3));
915       define_key("\033[14~", KEY_F(4));
916       define_key("\033[14;2~", KEY_F(15));
917       define_key("\033[17;2~", KEY_F(18));
918       char sequence[3] = "\033a";
919       for (char c = 'a'; c <= 'z'; c++) {
920          sequence[1] = c;
921          define_key(sequence, KEY_ALT('A' + (c - 'a')));
922       }
923 #ifdef HTOP_NETBSD
924 IGNORE_WCASTQUAL_END
925 #undef define_key
926 #endif
927    }
928 
929    CRT_installSignalHandlers();
930 
931    use_default_colors();
932    if (!has_colors())
933       CRT_colorScheme = COLORSCHEME_MONOCHROME;
934    CRT_setColors(CRT_colorScheme);
935 
936 #ifdef HAVE_LIBNCURSESW
937    if (allowUnicode && String_eq(nl_langinfo(CODESET), "UTF-8")) {
938       CRT_utf8 = true;
939    } else {
940       CRT_utf8 = false;
941    }
942 #else
943    (void) allowUnicode;
944 #endif
945 
946    CRT_treeStr =
947 #ifdef HAVE_LIBNCURSESW
948       CRT_utf8 ? CRT_treeStrUtf8 :
949 #endif
950       CRT_treeStrAscii;
951 
952 #ifdef HAVE_GETMOUSE
953 #if NCURSES_MOUSE_VERSION > 1
954    mousemask(BUTTON1_RELEASED | BUTTON4_PRESSED | BUTTON5_PRESSED, NULL);
955 #else
956    mousemask(BUTTON1_RELEASED, NULL);
957 #endif
958 #endif
959 
960    CRT_degreeSign = initDegreeSign();
961 }
962 
CRT_done()963 void CRT_done() {
964    curs_set(1);
965    endwin();
966 
967    dumpStderr();
968 }
969 
CRT_fatalError(const char * note)970 void CRT_fatalError(const char* note) {
971    const char* sysMsg = strerror(errno);
972    CRT_done();
973    fprintf(stderr, "%s: %s\n", note, sysMsg);
974    exit(2);
975 }
976 
CRT_readKey()977 int CRT_readKey() {
978    nocbreak();
979    cbreak();
980    nodelay(stdscr, FALSE);
981    int ret = getch();
982    halfdelay(*CRT_delay);
983    return ret;
984 }
985 
CRT_disableDelay()986 void CRT_disableDelay() {
987    nocbreak();
988    cbreak();
989    nodelay(stdscr, TRUE);
990 }
991 
CRT_enableDelay()992 void CRT_enableDelay() {
993    halfdelay(*CRT_delay);
994 }
995 
CRT_setColors(int colorScheme)996 void CRT_setColors(int colorScheme) {
997    CRT_colorScheme = colorScheme;
998 
999    for (short int i = 0; i < 8; i++) {
1000       for (short int j = 0; j < 8; j++) {
1001          if (ColorIndex(i, j) != ColorIndexGrayBlack && ColorIndex(i, j) != ColorIndexWhiteDefault) {
1002             short int bg = (colorScheme != COLORSCHEME_BLACKNIGHT)
1003                      ? (j == 0 ? -1 : j)
1004                      : j;
1005             init_pair(ColorIndex(i, j), i, bg);
1006          }
1007       }
1008    }
1009 
1010    short int grayBlackFg = COLORS > 8 ? 8 : 0;
1011    short int grayBlackBg = (colorScheme != COLORSCHEME_BLACKNIGHT) ? -1 : 0;
1012    init_pair(ColorIndexGrayBlack, grayBlackFg, grayBlackBg);
1013 
1014    init_pair(ColorIndexWhiteDefault, White, -1);
1015 
1016    CRT_colors = CRT_colorSchemes[colorScheme];
1017 }
1018 
1019 #ifdef PRINT_BACKTRACE
print_backtrace(void)1020 static void print_backtrace(void) {
1021 #if defined(HAVE_LIBUNWIND_H) && defined(HAVE_LIBUNWIND)
1022    unw_context_t context;
1023    unw_getcontext(&context);
1024 
1025    unw_cursor_t cursor;
1026    unw_init_local(&cursor, &context);
1027 
1028    unsigned int item = 0;
1029 
1030    while (unw_step(&cursor) > 0) {
1031       unw_word_t pc;
1032       unw_get_reg(&cursor, UNW_REG_IP, &pc);
1033       if (pc == 0)
1034          break;
1035 
1036       char symbolName[256] = "?";
1037       unw_word_t offset = 0;
1038       unw_get_proc_name(&cursor, symbolName, sizeof(symbolName), &offset);
1039 
1040       unw_proc_info_t pip;
1041       pip.unwind_info = NULL;
1042 
1043       const char* fname = "?";
1044       const void* ptr = 0;
1045       if (unw_get_proc_info(&cursor, &pip) == 0) {
1046          ptr = (const void*)(pip.start_ip + offset);
1047 
1048          #ifdef HAVE_DLADDR
1049          Dl_info dlinfo;
1050          if (dladdr(ptr, &dlinfo) && dlinfo.dli_fname && *dlinfo.dli_fname)
1051             fname = dlinfo.dli_fname;
1052          #endif
1053       }
1054 
1055       const char* frame = "";
1056       if (unw_is_signal_frame(&cursor) > 0)
1057          frame = "{signal frame}";
1058 
1059       fprintf(stderr, "%2u: %#14lx  %s  (%s+%#lx)  [%p]%s%s\n", item++, pc, fname, symbolName, offset, ptr, frame ? "  " : "", frame);
1060    }
1061 #elif defined(HAVE_EXECINFO_H)
1062    void* backtraceArray[256];
1063 
1064    size_t size = backtrace(backtraceArray, ARRAYSIZE(backtraceArray));
1065    backtrace_symbols_fd(backtraceArray, size, STDERR_FILENO);
1066 #else
1067 #error No implementation for print_backtrace()!
1068 #endif
1069 }
1070 #endif
1071 
CRT_handleSIGSEGV(int signal)1072 void CRT_handleSIGSEGV(int signal) {
1073    CRT_done();
1074 
1075    fprintf(stderr, "\n\n"
1076       "FATAL PROGRAM ERROR DETECTED\n"
1077       "============================\n"
1078       "Please check at https://htop.dev/issues whether this issue has already been reported.\n"
1079       "If no similar issue has been reported before, please create a new issue with the following information:\n"
1080       "  - Your "PACKAGE" version: '"VERSION"'\n"
1081       "  - Your OS and kernel version (uname -a)\n"
1082       "  - Your distribution and release (lsb_release -a)\n"
1083       "  - Likely steps to reproduce (How did it happen?)\n"
1084    );
1085 
1086 #ifdef PRINT_BACKTRACE
1087    fprintf(stderr, "  - Backtrace of the issue (see below)\n");
1088 #endif
1089 
1090    fprintf(stderr,
1091       "\n"
1092    );
1093 
1094    const char* signal_str = strsignal(signal);
1095    if (!signal_str) {
1096       signal_str = "unknown reason";
1097    }
1098    fprintf(stderr,
1099       "Error information:\n"
1100       "------------------\n"
1101       "A signal %d (%s) was received.\n"
1102       "\n",
1103       signal, signal_str
1104    );
1105 
1106    fprintf(stderr,
1107       "Setting information:\n"
1108       "--------------------\n");
1109    Settings_write(CRT_crashSettings, true);
1110    fprintf(stderr, "\n\n");
1111 
1112 #ifdef PRINT_BACKTRACE
1113    fprintf(stderr,
1114       "Backtrace information:\n"
1115       "----------------------\n"
1116    );
1117 
1118    print_backtrace();
1119 
1120    fprintf(stderr,
1121       "\n"
1122       "To make the above information more practical to work with, "
1123       "please also provide a disassembly of your "PACKAGE" binary. "
1124       "This can usually be done by running the following command:\n"
1125       "\n"
1126    );
1127 
1128 #ifdef HTOP_DARWIN
1129    fprintf(stderr, "   otool -tvV `which "PACKAGE"` > ~/htop.otool\n");
1130 #else
1131    fprintf(stderr, "   objdump -d -S -w `which "PACKAGE"` > ~/htop.objdump\n");
1132 #endif
1133 
1134    fprintf(stderr,
1135       "\n"
1136       "Please include the generated file in your report.\n"
1137    );
1138 #endif
1139 
1140    fprintf(stderr,
1141       "Running this program with debug symbols or inside a debugger may provide further insights.\n"
1142       "\n"
1143       "Thank you for helping to improve "PACKAGE"!\n"
1144       "\n"
1145    );
1146 
1147    /* Call old sigsegv handler; may be default exit or third party one (e.g. ASAN) */
1148    if (sigaction (signal, &old_sig_handler[signal], NULL) < 0) {
1149       /* This avoids an infinite loop in case the handler could not be reset. */
1150       fprintf(stderr,
1151          "!!! Chained handler could not be restored. Forcing exit.\n"
1152       );
1153       _exit(1);
1154    }
1155 
1156    /* Trigger the previous signal handler. */
1157    raise(signal);
1158 
1159    // Always terminate, even if installed handler returns
1160    fprintf(stderr,
1161       "!!! Chained handler did not exit. Forcing exit.\n"
1162    );
1163    _exit(1);
1164 }
1165