mirror of
https://github.com/xzeldon/htop.git
synced 2025-07-15 05:24:36 +03:00
Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
dace850fa6 | |||
4f00a95364 | |||
0ab508e42b | |||
f79591ef1b | |||
746a5f279a | |||
8ee7d58cb0 | |||
db5adbeae0 | |||
f5b3e8d2a3 | |||
809e4db672 | |||
e1e60f38dc | |||
19359cec5a | |||
b0f1336f79 | |||
f861a2c616 | |||
e7f6d1ce5f | |||
47a7d0bd74 | |||
b321177b08 | |||
800d8c735d | |||
f14173038e | |||
fdf8a28e60 | |||
244630f67f | |||
0a835e13bf | |||
4bd0859b80 | |||
338bd829b0 | |||
5c99c6e942 | |||
a850d81bf5 | |||
05a5fdc47f | |||
af84d3dfa9 | |||
df41979afc | |||
d9a5dd4b91 | |||
a48ce9d103 | |||
3f5784a3f0 | |||
3b084db1c4 | |||
979d004214 | |||
5bee902665 | |||
2d14269bcd | |||
b992d52bcf | |||
f97fbd668a | |||
b5e6952cc6 | |||
4a8ae4b5d4 | |||
94b8c2e714 |
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
@ -40,20 +40,20 @@ jobs:
|
||||
- name: Distcheck
|
||||
run: make distcheck DISTCHECK_CONFIGURE_FLAGS=--enable-werror
|
||||
|
||||
build-ubuntu-latest-hwloc:
|
||||
build-ubuntu-latest-full-featured:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Dependencies
|
||||
run: sudo apt-get install libncursesw5-dev libhwloc-dev
|
||||
run: sudo apt-get install libncursesw5-dev libhwloc-dev libnl-3-dev libnl-genl-3-dev
|
||||
- name: Bootstrap
|
||||
run: ./autogen.sh
|
||||
- name: Configure
|
||||
run: ./configure --enable-werror --enable-hwloc
|
||||
run: ./configure --enable-werror --enable-openvz --enable-cgroup --enable-vserver --enable-ancient-vserver --enable-taskstats --enable-unicode --enable-linux-affinity --enable-hwloc --enable-setuid --enable-delayacct
|
||||
- name: Build
|
||||
run: make
|
||||
- name: Distcheck
|
||||
run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-werror --enable-hwloc'
|
||||
run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-werror --enable-openvz --enable-cgroup --enable-vserver --enable-ancient-vserver --enable-taskstats --enable-unicode --enable-linux-affinity --enable-hwloc --enable-setuid --enable-delayacct'
|
||||
|
||||
whitespace_check:
|
||||
runs-on: ubuntu-latest
|
||||
|
1
Action.c
1
Action.c
@ -320,6 +320,7 @@ static Htop_Reaction actionSetAffinity(State* st) {
|
||||
if (!affinity1) return HTOP_OK;
|
||||
int width;
|
||||
Panel* affinityPanel = AffinityPanel_new(st->pl, affinity1, &width);
|
||||
width += 1; /* we add a gap between the panels */
|
||||
Affinity_delete(affinity1);
|
||||
|
||||
void* set = Action_pickFromVector(st, affinityPanel, width, true);
|
||||
|
@ -27,7 +27,7 @@ in the source distribution for its full text.
|
||||
typedef struct MaskItem_ {
|
||||
Object super;
|
||||
const char* text;
|
||||
const char* indent;
|
||||
const char* indent; /* used also as an condition whether this is a tree node */
|
||||
int value; /* tri-state: 0 - off, 1 - some set, 2 - all set */
|
||||
int sub_tree; /* tri-state: 0 - no sub-tree, 1 - open sub-tree, 2 - closed sub-tree */
|
||||
Vector *children;
|
||||
@ -55,20 +55,21 @@ static void MaskItem_delete(Object* cast) {
|
||||
static void MaskItem_display(Object* cast, RichString* out) {
|
||||
MaskItem* this = (MaskItem*)cast;
|
||||
assert (this != NULL);
|
||||
RichString_append(out, CRT_colors[CHECK_BOX], "[");
|
||||
if (this->value == 2)
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], CRT_checkStr[CHECK_STR_FULL]);
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], "x");
|
||||
else if (this->value == 1)
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], CRT_checkStr[CHECK_STR_PARTIAL]);
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], "o");
|
||||
else
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], CRT_checkStr[CHECK_STR_NONE]);
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], " ");
|
||||
RichString_append(out, CRT_colors[CHECK_BOX], "]");
|
||||
RichString_append(out, CRT_colors[CHECK_TEXT], " ");
|
||||
if (this->indent)
|
||||
if (this->indent) {
|
||||
RichString_append(out, CRT_colors[PROCESS_TREE], this->indent);
|
||||
if (this->sub_tree) {
|
||||
RichString_append(out, CRT_colors[PROCESS_TREE],
|
||||
this->sub_tree == 1
|
||||
? CRT_collapStr[COLLAP_STR_OPEN]
|
||||
: CRT_collapStr[COLLAP_STR_CLOSED]);
|
||||
this->sub_tree == 2
|
||||
? CRT_treeStr[TREE_STR_OPEN]
|
||||
: CRT_treeStr[TREE_STR_SHUT]);
|
||||
RichString_append(out, CRT_colors[CHECK_TEXT], " ");
|
||||
}
|
||||
RichString_append(out, CRT_colors[CHECK_TEXT], this->text);
|
||||
@ -84,7 +85,7 @@ static ObjectClass MaskItem_class = {
|
||||
static MaskItem* MaskItem_newMask(const char* text, const char* indent, hwloc_bitmap_t cpuset, bool owner) {
|
||||
MaskItem* this = AllocThis(MaskItem);
|
||||
this->text = xStrdup(text);
|
||||
this->indent = xStrdup(indent);
|
||||
this->indent = xStrdup(indent); /* nonnull for tree node */
|
||||
this->value = 0;
|
||||
this->ownCpuset = owner;
|
||||
this->cpuset = cpuset;
|
||||
@ -98,7 +99,7 @@ static MaskItem* MaskItem_newMask(const char* text, const char* indent, hwloc_bi
|
||||
static MaskItem* MaskItem_newSingleton(const char* text, int cpu, bool isSet) {
|
||||
MaskItem* this = AllocThis(MaskItem);
|
||||
this->text = xStrdup(text);
|
||||
this->indent = NULL;
|
||||
this->indent = NULL; /* not a tree node */
|
||||
this->sub_tree = 0;
|
||||
this->children = Vector_new(Class(MaskItem), true, DEFAULT_SIZE);
|
||||
|
||||
@ -260,7 +261,7 @@ static HandlerResult AffinityPanel_eventHandler(Panel* super, int ch) {
|
||||
|
||||
static MaskItem *AffinityPanel_addObject(AffinityPanel* this, hwloc_obj_t obj, unsigned indent, MaskItem *parent) {
|
||||
const char* type_name = hwloc_obj_type_string(obj->type);
|
||||
const char* index_prefix = " #";
|
||||
const char* index_prefix = "#";
|
||||
unsigned depth = obj->depth;
|
||||
unsigned index = obj->logical_index;
|
||||
size_t off = 0, left = 10 * depth;
|
||||
@ -279,14 +280,13 @@ static MaskItem *AffinityPanel_addObject(AffinityPanel* this, hwloc_obj_t obj, u
|
||||
size_t len = strlen(&indent_buf[off]);
|
||||
off += len, left -= len;
|
||||
}
|
||||
xSnprintf(&indent_buf[off], left, "%s%s ",
|
||||
obj->next_sibling ? CRT_treeStr[TREE_STR_RTEE] : CRT_treeStr[TREE_STR_BEND],
|
||||
CRT_treeStr[TREE_STR_HORZ]);
|
||||
xSnprintf(&indent_buf[off], left, "%s",
|
||||
obj->next_sibling ? CRT_treeStr[TREE_STR_RTEE] : CRT_treeStr[TREE_STR_BEND]);
|
||||
size_t len = strlen(&indent_buf[off]);
|
||||
off += len, left -= len;
|
||||
}
|
||||
|
||||
xSnprintf(buf, 64, "%s%s%u", type_name, index_prefix, index);
|
||||
xSnprintf(buf, 64, "%s %s%u", type_name, index_prefix, index);
|
||||
|
||||
MaskItem *item = MaskItem_newMask(buf, indent_buf, obj->complete_cpuset, false);
|
||||
if (parent)
|
||||
@ -302,8 +302,8 @@ static MaskItem *AffinityPanel_addObject(AffinityPanel* this, hwloc_obj_t obj, u
|
||||
item->sub_tree = 2;
|
||||
}
|
||||
|
||||
/* "[x] " + "|- " * depth + ("[+] ")? + name */
|
||||
unsigned width = (CRT_utf8 ? 2 : 4) + 3 * depth + (item->sub_tree ? (CRT_utf8 ? 2 : 4) : 0) + strlen(buf);
|
||||
/* "[x] " + "|- " * depth + ("- ")?(if root node) + name */
|
||||
unsigned width = 4 + 3 * depth + (2 * !depth) + strlen(buf);
|
||||
if (width > this->width)
|
||||
this->width = width;
|
||||
|
||||
@ -352,7 +352,9 @@ Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity, int* width) {
|
||||
Panel_init(super, 1, 1, 1, 1, Class(MaskItem), false, FunctionBar_new(AffinityPanelFunctions, AffinityPanelKeys, AffinityPanelEvents));
|
||||
|
||||
this->pl = pl;
|
||||
this->width = 15;
|
||||
/* defaults to 15, this also includes the gap between the panels,
|
||||
* but this will be added by the caller */
|
||||
this->width = 14;
|
||||
|
||||
this->cpuids = Vector_new(Class(MaskItem), true, DEFAULT_SIZE);
|
||||
|
||||
|
76
CRT.c
76
CRT.c
@ -59,19 +59,6 @@ typedef enum TreeStr_ {
|
||||
TREE_STR_COUNT
|
||||
} TreeStr;
|
||||
|
||||
typedef enum CheckStr_ {
|
||||
CHECK_STR_NONE,
|
||||
CHECK_STR_PARTIAL,
|
||||
CHECK_STR_FULL,
|
||||
CHECK_STR_COUNT
|
||||
} CheckStr;
|
||||
|
||||
typedef enum CollapStr_ {
|
||||
COLLAP_STR_OPEN,
|
||||
COLLAP_STR_CLOSED,
|
||||
COLLAP_STR_COUNT
|
||||
} CollapStr;
|
||||
|
||||
typedef enum ColorSchemes_ {
|
||||
COLORSCHEME_DEFAULT = 0,
|
||||
COLORSCHEME_MONOCHROME = 1,
|
||||
@ -126,6 +113,7 @@ typedef enum ColorElements_ {
|
||||
LOAD_AVERAGE_FIFTEEN,
|
||||
LOAD_AVERAGE_FIVE,
|
||||
LOAD_AVERAGE_ONE,
|
||||
CHECK_BOX,
|
||||
CHECK_MARK,
|
||||
CHECK_TEXT,
|
||||
CLOCK,
|
||||
@ -171,17 +159,6 @@ const char *CRT_treeStrAscii[TREE_STR_COUNT] = {
|
||||
"-", // TREE_STR_SHUT
|
||||
};
|
||||
|
||||
const char *CRT_checkStrAscii[CHECK_STR_COUNT] = {
|
||||
"[ ]", // CHECK_STR_NONE
|
||||
"[o]", // CHECK_STR_PARTIAL
|
||||
"[x]", // CHECK_STR_FULL
|
||||
};
|
||||
|
||||
const char *CRT_collapStrAscii[COLLAP_STR_COUNT] = {
|
||||
"[-]", // COLLAP_STR_OPEN
|
||||
"[+]", // COLLAP_STR_CLOSED
|
||||
};
|
||||
|
||||
#ifdef HAVE_LIBNCURSESW
|
||||
|
||||
const char *CRT_treeStrUtf8[TREE_STR_COUNT] = {
|
||||
@ -190,31 +167,18 @@ const char *CRT_treeStrUtf8[TREE_STR_COUNT] = {
|
||||
"\xe2\x94\x9c", // TREE_STR_RTEE ├
|
||||
"\xe2\x94\x94", // TREE_STR_BEND └
|
||||
"\xe2\x94\x8c", // TREE_STR_TEND ┌
|
||||
"+", // TREE_STR_OPEN +
|
||||
"+", // TREE_STR_OPEN +, TODO use 🮯 'BOX DRAWINGS LIGHT HORIZONTAL
|
||||
// WITH VERTICAL STROKE' (U+1FBAF, "\xf0\x9f\xae\xaf") when
|
||||
// Unicode 13 is common
|
||||
"\xe2\x94\x80", // TREE_STR_SHUT ─
|
||||
};
|
||||
|
||||
const char *CRT_checkStrUtf8[CHECK_STR_COUNT] = {
|
||||
"\xe2\x98\x90", // CHECK_STR_NONE ☐
|
||||
"\xe2\x98\x92", // CHECK_STR_PARTIAL ☒
|
||||
"\xe2\x98\x91", // CHECK_STR_FULL ☑
|
||||
};
|
||||
|
||||
const char *CRT_collapStrUtf8[COLLAP_STR_COUNT] = {
|
||||
"\xe2\x8a\x9f", // COLLAP_STR_OPEN ⊟
|
||||
"\xe2\x8a\x9e", // COLLAP_STR_CLOSED ⊞
|
||||
};
|
||||
bool CRT_utf8 = false;
|
||||
|
||||
#endif
|
||||
|
||||
bool CRT_utf8 = false;
|
||||
|
||||
const char **CRT_treeStr = CRT_treeStrAscii;
|
||||
|
||||
const char **CRT_checkStr = CRT_checkStrAscii;
|
||||
|
||||
const char **CRT_collapStr = CRT_collapStrAscii;
|
||||
|
||||
static bool CRT_hasColors;
|
||||
|
||||
int CRT_delay = 0;
|
||||
@ -267,7 +231,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[LOAD] = A_BOLD,
|
||||
[HELP_BOLD] = A_BOLD | ColorPair(Cyan,Black),
|
||||
[CLOCK] = A_BOLD,
|
||||
[CHECK_MARK] = A_BOLD | ColorPair(Cyan,Black),
|
||||
[CHECK_BOX] = ColorPair(Cyan,Black),
|
||||
[CHECK_MARK] = A_BOLD,
|
||||
[CHECK_TEXT] = A_NORMAL,
|
||||
[HOSTNAME] = A_BOLD,
|
||||
[CPU_NICE] = ColorPair(Blue,Black),
|
||||
@ -335,7 +300,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[LOAD] = A_BOLD,
|
||||
[HELP_BOLD] = A_BOLD,
|
||||
[CLOCK] = A_BOLD,
|
||||
[CHECK_MARK] = A_BOLD,
|
||||
[CHECK_BOX] = A_BOLD,
|
||||
[CHECK_MARK] = A_NORMAL,
|
||||
[CHECK_TEXT] = A_NORMAL,
|
||||
[HOSTNAME] = A_BOLD,
|
||||
[CPU_NICE] = A_NORMAL,
|
||||
@ -403,6 +369,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[LOAD] = ColorPair(Black,White),
|
||||
[HELP_BOLD] = ColorPair(Blue,White),
|
||||
[CLOCK] = ColorPair(Black,White),
|
||||
[CHECK_BOX] = ColorPair(Blue,White),
|
||||
[CHECK_MARK] = ColorPair(Black,White),
|
||||
[CHECK_TEXT] = ColorPair(Black,White),
|
||||
[HOSTNAME] = ColorPair(Black,White),
|
||||
@ -471,6 +438,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[LOAD] = ColorPair(White,Black),
|
||||
[HELP_BOLD] = ColorPair(Blue,Black),
|
||||
[CLOCK] = ColorPair(White,Black),
|
||||
[CHECK_BOX] = ColorPair(Blue,Black),
|
||||
[CHECK_MARK] = ColorPair(Black,Black),
|
||||
[CHECK_TEXT] = ColorPair(Black,Black),
|
||||
[HOSTNAME] = ColorPair(White,Black),
|
||||
@ -539,7 +507,8 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[LOAD] = A_BOLD | ColorPair(White,Blue),
|
||||
[HELP_BOLD] = A_BOLD | ColorPair(Cyan,Blue),
|
||||
[CLOCK] = ColorPair(White,Blue),
|
||||
[CHECK_MARK] = A_BOLD | ColorPair(Cyan,Blue),
|
||||
[CHECK_BOX] = ColorPair(Cyan,Blue),
|
||||
[CHECK_MARK] = A_BOLD | ColorPair(White,Blue),
|
||||
[CHECK_TEXT] = A_NORMAL | ColorPair(White,Blue),
|
||||
[HOSTNAME] = ColorPair(White,Blue),
|
||||
[CPU_NICE] = A_BOLD | ColorPair(Cyan,Blue),
|
||||
@ -607,6 +576,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[LOAD] = A_BOLD,
|
||||
[HELP_BOLD] = A_BOLD | ColorPair(Cyan,Black),
|
||||
[CLOCK] = ColorPair(Green,Black),
|
||||
[CHECK_BOX] = ColorPair(Green,Black),
|
||||
[CHECK_MARK] = A_BOLD | ColorPair(Green,Black),
|
||||
[CHECK_TEXT] = ColorPair(Cyan,Black),
|
||||
[HOSTNAME] = ColorPair(Green,Black),
|
||||
@ -697,7 +667,7 @@ void CRT_restorePrivileges() {
|
||||
|
||||
// TODO: pass an instance of Settings instead.
|
||||
|
||||
void CRT_init(int delay, int colorScheme) {
|
||||
void CRT_init(int delay, int colorScheme, bool allowUnicode) {
|
||||
initscr();
|
||||
noecho();
|
||||
CRT_delay = delay;
|
||||
@ -763,14 +733,20 @@ void CRT_init(int delay, int colorScheme) {
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
#ifdef HAVE_LIBNCURSESW
|
||||
if(strcmp(nl_langinfo(CODESET), "UTF-8") == 0) {
|
||||
if (allowUnicode && strcmp(nl_langinfo(CODESET), "UTF-8") == 0)
|
||||
CRT_utf8 = true;
|
||||
CRT_treeStr = CRT_treeStrUtf8;
|
||||
CRT_checkStr = CRT_checkStrUtf8;
|
||||
CRT_collapStr = CRT_collapStrUtf8;
|
||||
}
|
||||
else
|
||||
CRT_utf8 = false;
|
||||
#else
|
||||
(void) allowUnicode;
|
||||
#endif
|
||||
|
||||
CRT_treeStr =
|
||||
#ifdef HAVE_LIBNCURSESW
|
||||
CRT_utf8 ? CRT_treeStrUtf8 :
|
||||
#endif
|
||||
CRT_treeStrAscii;
|
||||
|
||||
#if NCURSES_MOUSE_VERSION > 1
|
||||
mousemask(BUTTON1_RELEASED | BUTTON4_PRESSED | BUTTON5_PRESSED, NULL);
|
||||
#else
|
||||
|
30
CRT.h
30
CRT.h
@ -47,19 +47,6 @@ typedef enum TreeStr_ {
|
||||
TREE_STR_COUNT
|
||||
} TreeStr;
|
||||
|
||||
typedef enum CheckStr_ {
|
||||
CHECK_STR_NONE,
|
||||
CHECK_STR_PARTIAL,
|
||||
CHECK_STR_FULL,
|
||||
CHECK_STR_COUNT
|
||||
} CheckStr;
|
||||
|
||||
typedef enum CollapStr_ {
|
||||
COLLAP_STR_OPEN,
|
||||
COLLAP_STR_CLOSED,
|
||||
COLLAP_STR_COUNT
|
||||
} CollapStr;
|
||||
|
||||
typedef enum ColorSchemes_ {
|
||||
COLORSCHEME_DEFAULT = 0,
|
||||
COLORSCHEME_MONOCHROME = 1,
|
||||
@ -114,6 +101,7 @@ typedef enum ColorElements_ {
|
||||
LOAD_AVERAGE_FIFTEEN,
|
||||
LOAD_AVERAGE_FIVE,
|
||||
LOAD_AVERAGE_ONE,
|
||||
CHECK_BOX,
|
||||
CHECK_MARK,
|
||||
CHECK_TEXT,
|
||||
CLOCK,
|
||||
@ -150,28 +138,16 @@ extern void CRT_handleSIGSEGV(int sgn);
|
||||
|
||||
extern const char *CRT_treeStrAscii[TREE_STR_COUNT];
|
||||
|
||||
extern const char *CRT_checkStrAscii[CHECK_STR_COUNT];
|
||||
|
||||
extern const char *CRT_collapStrAscii[COLLAP_STR_COUNT];
|
||||
|
||||
#ifdef HAVE_LIBNCURSESW
|
||||
|
||||
extern const char *CRT_treeStrUtf8[TREE_STR_COUNT];
|
||||
|
||||
extern const char *CRT_checkStrUtf8[CHECK_STR_COUNT];
|
||||
|
||||
extern const char *CRT_collapStrUtf8[COLLAP_STR_COUNT];
|
||||
extern bool CRT_utf8;
|
||||
|
||||
#endif
|
||||
|
||||
extern bool CRT_utf8;
|
||||
|
||||
extern const char **CRT_treeStr;
|
||||
|
||||
extern const char **CRT_checkStr;
|
||||
|
||||
extern const char **CRT_collapStr;
|
||||
|
||||
extern int CRT_delay;
|
||||
|
||||
extern int* CRT_colors;
|
||||
@ -213,7 +189,7 @@ extern void CRT_restorePrivileges();
|
||||
|
||||
// TODO: pass an instance of Settings instead.
|
||||
|
||||
extern void CRT_init(int delay, int colorScheme);
|
||||
extern void CRT_init(int delay, int colorScheme, bool allowUnicode);
|
||||
|
||||
extern void CRT_done();
|
||||
|
||||
|
13
ChangeLog
13
ChangeLog
@ -1,3 +1,16 @@
|
||||
What's new in version 3.0.1
|
||||
|
||||
* Coverity fixes, CI improvements, documentation updates
|
||||
* BUGFIX: Fix early exit with longer sysfs battery paths
|
||||
* BUGFIX: Improve OOM output, fix sorting
|
||||
(thanks to Christian Göttsche)
|
||||
* Rework check buttons and tree open/closed
|
||||
(thanks to Bert Wesarg)
|
||||
* Add -U/--no-unicode option to disable unicode
|
||||
(thanks to Christian Hesse)
|
||||
* Improvements to the affinity panel
|
||||
(thanks to Bert Wesarg)
|
||||
|
||||
What's new in version 3.0.0
|
||||
|
||||
* New maintainers - after a prolonged period of inactivity
|
||||
|
@ -35,11 +35,12 @@ static void CheckItem_delete(Object* cast) {
|
||||
static void CheckItem_display(Object* cast, RichString* out) {
|
||||
CheckItem* this = (CheckItem*)cast;
|
||||
assert (this != NULL);
|
||||
RichString_write(out, CRT_colors[CHECK_BOX], "[");
|
||||
if (CheckItem_get(this))
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], CRT_checkStr[CHECK_STR_FULL]);
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], "x");
|
||||
else
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], CRT_checkStr[CHECK_STR_NONE]);
|
||||
RichString_append(out, CRT_colors[CHECK_TEXT], " ");
|
||||
RichString_append(out, CRT_colors[CHECK_MARK], " ");
|
||||
RichString_append(out, CRT_colors[CHECK_BOX], "] ");
|
||||
RichString_append(out, CRT_colors[CHECK_TEXT], this->text);
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,7 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
|
||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU percentage numerically"), &(settings->showCPUUsage)));
|
||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU frequency"), &(settings->showCPUFrequency)));
|
||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Enable the mouse"), &(settings->enableMouse)));
|
||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Enable vim mode"), &(settings->vimMode)));
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Show topology when selecting affinity by default"), &(settings->topologyAffinity)));
|
||||
#endif
|
||||
|
@ -80,7 +80,7 @@ void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...) {
|
||||
va_start(ap, fmt);
|
||||
attrset(CRT_colors[METER_TEXT]);
|
||||
mvhline(0, 0, ' ', COLS);
|
||||
wmove(stdscr, 0, 0);
|
||||
(void) wmove(stdscr, 0, 0);
|
||||
vw_printw(stdscr, fmt, ap);
|
||||
attrset(CRT_colors[DEFAULT_COLOR]);
|
||||
this->display->needsRedraw = true;
|
||||
|
21
README
21
README
@ -1,13 +1,13 @@
|
||||

|
||||
# [](https://htop.dev)
|
||||
|
||||
[](https://github.com/htop-dev/htop/actions)
|
||||
[](https://scan.coverity.com/projects/21617)
|
||||
[](https://scan.coverity.com/projects/21665)
|
||||
[](https://groups.io/g/htop)
|
||||
[](https://webchat.freenode.net/#htop)
|
||||
[](https://github.com/htop-dev/htop/releases/latest)
|
||||
[](https://bintray.com/htop/source/htop/_latestVersion)
|
||||
|
||||
Introduction
|
||||
------------
|
||||
## Introduction
|
||||
|
||||
`htop` is a cross-platform interactive process viewer.
|
||||
It requires `ncurses`.
|
||||
@ -15,20 +15,23 @@ It requires `ncurses`.
|
||||
For more information and details on how to contribute to `htop`
|
||||
visit [htop.dev](https://htop.dev).
|
||||
|
||||
Build instructions
|
||||
------------------
|
||||
## Build instructions
|
||||
|
||||
This program is distributed as a standard autotools-based package.
|
||||
For detailed instructions see the [INSTALL](/INSTALL) file, which
|
||||
For detailed instructions see the `INSTALL` file, which
|
||||
is created after `./autogen.sh` is run.
|
||||
|
||||
When compiling from a [release tarball](https://github.com/htop-dev/htop/releases/), run:
|
||||
|
||||
./configure && make
|
||||
~~~ shell
|
||||
./configure && make
|
||||
~~~
|
||||
|
||||
For compiling sources downloaded from the Git repository, run:
|
||||
|
||||
./autogen.sh && ./configure && make
|
||||
~~~ shell
|
||||
./autogen.sh && ./configure && make
|
||||
~~~
|
||||
|
||||
By default `make install` will install into `/usr/local`, for changing
|
||||
the path use `./configure --prefix=/some/path`.
|
||||
|
37
configure.ac
37
configure.ac
@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.65)
|
||||
AC_INIT([htop],[3.0.0],[htop@groups.io])
|
||||
AC_INIT([htop],[3.0.1],[htop@groups.io])
|
||||
|
||||
AC_CONFIG_SRCDIR([htop.c])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
@ -111,20 +111,12 @@ AC_SUBST(wextra_flag)
|
||||
# ----------------------------------------------------------------------
|
||||
PROCDIR=/proc
|
||||
|
||||
AC_ARG_ENABLE(proc, [AS_HELP_STRING([--enable-proc], [use Linux-compatible proc filesystem])], enable_proc="yes", enable_proc="no")
|
||||
if test "x$enable_proc" = xyes; then
|
||||
# An enabled proc assumes we're emulating Linux.
|
||||
my_htop_platform=linux
|
||||
AC_DEFINE(HAVE_PROC, 1, [Define if using a Linux-compatible proc filesystem.])
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(proc, [AS_HELP_STRING([--with-proc=DIR], [Location of a Linux-compatible proc filesystem (default=/proc).])],
|
||||
|
||||
if test -n "$withval"; then
|
||||
AC_DEFINE_UNQUOTED(PROCDIR, "$withval", [Path of proc filesystem])
|
||||
PROCDIR="$withval"
|
||||
fi,
|
||||
AC_DEFINE(PROCDIR, "/proc", [Path of proc filesystem]))
|
||||
if test -n "$withval"; then
|
||||
AC_DEFINE_UNQUOTED(PROCDIR, "$withval", [Path of proc filesystem])
|
||||
PROCDIR="$withval"
|
||||
fi,
|
||||
AC_DEFINE(PROCDIR, "/proc", [Path of proc filesystem]))
|
||||
|
||||
if test "x$cross_compiling" = xno; then
|
||||
if test "x$enable_proc" = xyes; then
|
||||
@ -340,3 +332,20 @@ then
|
||||
echo "****************************************************************"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([
|
||||
${PACKAGE_NAME} ${VERSION}
|
||||
|
||||
platform: $my_htop_platform
|
||||
proc directory: $PROCDIR
|
||||
openvz: $enable_openvz
|
||||
cgroup: $enable_cgroup
|
||||
vserver: $enable_vserver
|
||||
ancient vserver: $enable_ancient_vserver
|
||||
taskstats: $enable_taskstats
|
||||
unicode: $enable_unicode
|
||||
linux affinity: $enable_linux_affinity
|
||||
hwlock: $enable_hwloc
|
||||
setuid: $enable_setuid
|
||||
linux delay accounting: $enable_delayacct
|
||||
])
|
||||
|
@ -48,6 +48,9 @@ Sort by this column (use \-\-sort\-key help for a column list)
|
||||
\fB\-u \-\-user=USERNAME\fR
|
||||
Show only the processes of a given user
|
||||
.TP
|
||||
\fB\-U \-\-no-unicode\fR
|
||||
Do not use unicode but ASCII characters for graph meters
|
||||
.TP
|
||||
\fB\-v \-\-version
|
||||
Output version information and exit
|
||||
.TP
|
||||
|
39
htop.c
39
htop.c
@ -29,14 +29,12 @@ in the source distribution for its full text.
|
||||
//#link m
|
||||
|
||||
static void printVersionFlag() {
|
||||
fputs("htop " VERSION " - " COPYRIGHT "\n"
|
||||
"Released under the GNU GPL.\n\n",
|
||||
stdout);
|
||||
fputs("htop " VERSION "\n", stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void printHelpFlag() {
|
||||
fputs("htop " VERSION " - " COPYRIGHT "\n"
|
||||
fputs("htop " VERSION "\n"
|
||||
"Released under the GNU GPL.\n\n"
|
||||
"-C --no-color Use a monochrome color scheme\n"
|
||||
"-m --no-mouse Disable the mouse\n"
|
||||
@ -45,6 +43,7 @@ static void printHelpFlag() {
|
||||
"-s --sort-key=COLUMN Sort by COLUMN (try --sort-key=help for a list)\n"
|
||||
"-t --tree Show the tree view by default\n"
|
||||
"-u --user[=USERNAME] Show only processes for a given user (or $USER)\n"
|
||||
"-U --no-unicode Do not use unicode but plain ASCII\n"
|
||||
"-p --pid=PID,[,PID,PID...] Show only the given PIDs\n"
|
||||
"-v --version Print version info\n"
|
||||
"\n"
|
||||
@ -65,6 +64,7 @@ typedef struct CommandLineSettings_ {
|
||||
bool useColors;
|
||||
bool enableMouse;
|
||||
bool treeView;
|
||||
bool allowUnicode;
|
||||
} CommandLineSettings;
|
||||
|
||||
static CommandLineSettings parseArguments(int argc, char** argv) {
|
||||
@ -77,26 +77,28 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
||||
.useColors = true,
|
||||
.enableMouse = true,
|
||||
.treeView = false,
|
||||
.allowUnicode = true,
|
||||
};
|
||||
|
||||
static struct option long_opts[] =
|
||||
{
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{"delay", required_argument, 0, 'd'},
|
||||
{"sort-key", required_argument, 0, 's'},
|
||||
{"user", optional_argument, 0, 'u'},
|
||||
{"no-color", no_argument, 0, 'C'},
|
||||
{"no-colour",no_argument, 0, 'C'},
|
||||
{"no-mouse", no_argument, 0, 'm'},
|
||||
{"tree", no_argument, 0, 't'},
|
||||
{"pid", required_argument, 0, 'p'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{"delay", required_argument, 0, 'd'},
|
||||
{"sort-key", required_argument, 0, 's'},
|
||||
{"user", optional_argument, 0, 'u'},
|
||||
{"no-color", no_argument, 0, 'C'},
|
||||
{"no-colour", no_argument, 0, 'C'},
|
||||
{"no-mouse", no_argument, 0, 'm'},
|
||||
{"no-unicode", no_argument, 0, 'U'},
|
||||
{"tree", no_argument, 0, 't'},
|
||||
{"pid", required_argument, 0, 'p'},
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
int opt, opti=0;
|
||||
/* Parse arguments */
|
||||
while ((opt = getopt_long(argc, argv, "hvmCs:td:u::p:", long_opts, &opti))) {
|
||||
while ((opt = getopt_long(argc, argv, "hvmCs:td:u:Up:", long_opts, &opti))) {
|
||||
if (opt == EOF) break;
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
@ -150,6 +152,9 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
||||
case 'm':
|
||||
flags.enableMouse = false;
|
||||
break;
|
||||
case 'U':
|
||||
flags.allowUnicode = false;
|
||||
break;
|
||||
case 't':
|
||||
flags.treeView = true;
|
||||
break;
|
||||
@ -200,7 +205,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
CommandLineSettings flags = parseArguments(argc, argv); // may exit()
|
||||
|
||||
#ifdef HAVE_PROC
|
||||
#ifdef HTOP_LINUX
|
||||
if (access(PROCDIR, R_OK) != 0) {
|
||||
fprintf(stderr, "Error: could not read procfs (compiled to look in %s).\n", PROCDIR);
|
||||
exit(1);
|
||||
@ -228,7 +233,7 @@ int main(int argc, char** argv) {
|
||||
if (flags.treeView)
|
||||
settings->treeView = true;
|
||||
|
||||
CRT_init(settings->delay, settings->colorScheme);
|
||||
CRT_init(settings->delay, settings->colorScheme, flags.allowUnicode);
|
||||
|
||||
MainPanel* panel = MainPanel_new();
|
||||
ProcessList_setPanel(pl, (Panel*) panel);
|
||||
|
@ -107,7 +107,7 @@ static ACPresence procAcpiCheck() {
|
||||
if (entryName[0] != 'A')
|
||||
continue;
|
||||
|
||||
char statePath[50];
|
||||
char statePath[256];
|
||||
xSnprintf((char *) statePath, sizeof statePath, "%s/%s/state", power_supplyPath, entryName);
|
||||
FILE* file = fopen(statePath, "r");
|
||||
if (!file) {
|
||||
@ -191,7 +191,7 @@ static void Battery_getSysData(double* level, ACPresence* isOnAC) {
|
||||
if (!dirEntry)
|
||||
break;
|
||||
char* entryName = (char *) dirEntry->d_name;
|
||||
const char filePath[50];
|
||||
const char filePath[256];
|
||||
|
||||
xSnprintf((char *) filePath, sizeof filePath, SYS_POWERSUPPLY_DIR "/%s/type", entryName);
|
||||
int fd1 = open(filePath, O_RDONLY);
|
||||
|
@ -241,7 +241,7 @@ ProcessFieldData Process_fields[] = {
|
||||
#ifdef HAVE_CGROUP
|
||||
[CGROUP] = { .name = "CGROUP", .title = " CGROUP ", .description = "Which cgroup the process is in", .flags = PROCESS_FLAG_LINUX_CGROUP, },
|
||||
#endif
|
||||
[OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, },
|
||||
[OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, },
|
||||
[IO_PRIORITY] = { .name = "IO_PRIORITY", .title = "IO ", .description = "I/O priority", .flags = PROCESS_FLAG_LINUX_IOPRIO, },
|
||||
#ifdef HAVE_DELAYACCT
|
||||
[PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD% ", .description = "CPU delay %", .flags = 0, },
|
||||
@ -264,7 +264,6 @@ ProcessPidColumn Process_pidColumns[] = {
|
||||
{ .id = TGID, .label = "TGID" },
|
||||
{ .id = PGRP, .label = "PGRP" },
|
||||
{ .id = SESSION, .label = "SID" },
|
||||
{ .id = OOM, .label = "OOM" },
|
||||
{ .id = 0, .label = NULL },
|
||||
};
|
||||
|
||||
@ -397,7 +396,7 @@ void LinuxProcess_writeField(Process* this, RichString* str, ProcessField field)
|
||||
#ifdef HAVE_CGROUP
|
||||
case CGROUP: xSnprintf(buffer, n, "%-10s ", lp->cgroup); break;
|
||||
#endif
|
||||
case OOM: xSnprintf(buffer, n, Process_pidFormat, lp->oom); break;
|
||||
case OOM: xSnprintf(buffer, n, "%4u ", lp->oom); break;
|
||||
case IO_PRIORITY: {
|
||||
int klass = IOPriority_class(lp->ioPriority);
|
||||
if (klass == IOPRIO_CLASS_NONE) {
|
||||
@ -493,7 +492,7 @@ long LinuxProcess_compare(const void* v1, const void* v2) {
|
||||
return strcmp(p1->cgroup ? p1->cgroup : "", p2->cgroup ? p2->cgroup : "");
|
||||
#endif
|
||||
case OOM:
|
||||
return (p2->oom - p1->oom);
|
||||
return ((int)p2->oom - (int)p1->oom);
|
||||
#ifdef HAVE_DELAYACCT
|
||||
case PERCENT_CPU_DELAY:
|
||||
return (p2->cpu_delay_percent > p1->cpu_delay_percent ? 1 : -1);
|
||||
|
@ -275,7 +275,8 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui
|
||||
} else if (String_startsWith(buffer, "cpu")) {
|
||||
cpus++;
|
||||
} else if (String_startsWith(buffer, "btime ")) {
|
||||
sscanf(buffer, "btime %lld\n", &btime);
|
||||
if (sscanf(buffer, "btime %lld\n", &btime) != 1)
|
||||
CRT_fatalError("Failed to parse btime from " PROCSTATFILE);
|
||||
break;
|
||||
}
|
||||
} while(true);
|
||||
@ -577,7 +578,7 @@ static void LinuxProcessList_readOpenVZData(LinuxProcess* process, const char* d
|
||||
FILE* file = fopen(filename, "r");
|
||||
if (!file)
|
||||
return;
|
||||
(void) fscanf(file,
|
||||
(void)! fscanf(file,
|
||||
"%*32u %*32s %*1c %*32u %*32u %*32u %*32u %*32u %*32u %*32u "
|
||||
"%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u "
|
||||
"%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u "
|
||||
@ -670,7 +671,7 @@ static void LinuxProcessList_readOomData(LinuxProcess* process, const char* dirn
|
||||
char buffer[PROC_LINE_LENGTH + 1];
|
||||
if (fgets(buffer, PROC_LINE_LENGTH, file)) {
|
||||
unsigned int oom;
|
||||
int ok = sscanf(buffer, "%32u", &oom);
|
||||
int ok = sscanf(buffer, "%u", &oom);
|
||||
if (ok >= 1) {
|
||||
process->oom = oom;
|
||||
}
|
||||
@ -1062,9 +1063,9 @@ static inline void LinuxProcessList_scanMemoryInfo(ProcessList* this) {
|
||||
}
|
||||
|
||||
static inline void LinuxProcessList_scanZfsArcstats(LinuxProcessList* lpl) {
|
||||
unsigned long long int dbufSize;
|
||||
unsigned long long int dnodeSize;
|
||||
unsigned long long int bonusSize;
|
||||
unsigned long long int dbufSize = 0;
|
||||
unsigned long long int dnodeSize = 0;
|
||||
unsigned long long int bonusSize = 0;
|
||||
|
||||
FILE* file = fopen(PROCARCSTATSFILE, "r");
|
||||
if (file == NULL) {
|
||||
@ -1142,10 +1143,10 @@ static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) {
|
||||
char* ok = fgets(buffer, PROC_LINE_LENGTH, file);
|
||||
if (!ok) buffer[0] = '\0';
|
||||
if (i == 0)
|
||||
sscanf(buffer, "cpu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu", &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest, &guestnice);
|
||||
(void) sscanf(buffer, "cpu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu", &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest, &guestnice);
|
||||
else {
|
||||
int cpuid;
|
||||
sscanf(buffer, "cpu%4d %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu", &cpuid, &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest, &guestnice);
|
||||
(void) sscanf(buffer, "cpu%4d %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu", &cpuid, &usertime, &nicetime, &systemtime, &idletime, &ioWait, &irq, &softIrq, &steal, &guest, &guestnice);
|
||||
assert(cpuid == i - 1);
|
||||
}
|
||||
// Guest time is already accounted in usertime
|
||||
@ -1235,7 +1236,7 @@ static inline double LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) {
|
||||
(sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) ||
|
||||
(sscanf(buffer, "cpu MHz: %lf", &frequency) == 1)
|
||||
) {
|
||||
if (cpuid < 0) {
|
||||
if (cpuid < 0 || cpuid > (cpus - 1)) {
|
||||
CRT_fatalError(PROCCPUINFOFILE " is malformed: cpu MHz line without corresponding processor line");
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,6 @@ static void ZfsArcMeter_display(Object* cast, RichString* out) {
|
||||
Meter* this = (Meter*)cast;
|
||||
|
||||
if (this->values[5] > 0) {
|
||||
RichString_write(out, CRT_colors[METER_TEXT], ":");
|
||||
Meter_humanUnit(buffer, this->total, 50);
|
||||
RichString_append(out, CRT_colors[METER_VALUE], buffer);
|
||||
Meter_humanUnit(buffer, this->values[5], 50);
|
||||
@ -100,5 +99,5 @@ MeterClass ZfsArcMeter_class = {
|
||||
.attributes = ZfsArcMeter_attributes,
|
||||
.name = "ZFSARC",
|
||||
.uiName = "ZFS ARC",
|
||||
.caption = "ARC"
|
||||
.caption = "ARC: "
|
||||
};
|
||||
|
Reference in New Issue
Block a user