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