2021-03-23 04:04:54 +00:00
|
|
|
/*
|
|
|
|
htop - CommandLine.c
|
|
|
|
(C) 2004-2011 Hisham H. Muhammad
|
|
|
|
(C) 2020-2021 htop dev team
|
2021-09-22 09:33:00 +00:00
|
|
|
Released under the GNU GPLv2+, see the COPYING file
|
2021-03-23 04:04:54 +00:00
|
|
|
in the source distribution for its full text.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h" // IWYU pragma: keep
|
|
|
|
|
|
|
|
#include "CommandLine.h"
|
|
|
|
|
|
|
|
#include <assert.h>
|
2021-10-04 13:08:55 +00:00
|
|
|
#include <ctype.h>
|
2021-03-23 04:04:54 +00:00
|
|
|
#include <getopt.h>
|
|
|
|
#include <locale.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "Action.h"
|
|
|
|
#include "CRT.h"
|
PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns. The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.
We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.
Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location. Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop. This
final location becomes the preferred place for our own
shipped meter and column files.
The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start. Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-07-11 01:11:29 +00:00
|
|
|
#include "DynamicColumn.h"
|
2021-06-23 07:44:56 +00:00
|
|
|
#include "DynamicMeter.h"
|
2021-03-23 04:04:54 +00:00
|
|
|
#include "Hashtable.h"
|
|
|
|
#include "Header.h"
|
|
|
|
#include "IncSet.h"
|
|
|
|
#include "MainPanel.h"
|
|
|
|
#include "MetersPanel.h"
|
|
|
|
#include "Panel.h"
|
|
|
|
#include "Platform.h"
|
|
|
|
#include "Process.h"
|
|
|
|
#include "ProcessList.h"
|
|
|
|
#include "ProvideCurses.h"
|
|
|
|
#include "ScreenManager.h"
|
|
|
|
#include "Settings.h"
|
|
|
|
#include "UsersTable.h"
|
|
|
|
#include "XUtils.h"
|
|
|
|
|
|
|
|
|
|
|
|
static void printVersionFlag(const char* name) {
|
|
|
|
printf("%s " VERSION "\n", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printHelpFlag(const char* name) {
|
|
|
|
printf("%s " VERSION "\n"
|
2021-07-14 17:20:16 +00:00
|
|
|
COPYRIGHT "\n"
|
2021-09-22 09:33:00 +00:00
|
|
|
"Released under the GNU GPLv2+.\n\n"
|
2021-07-14 17:20:16 +00:00
|
|
|
"-C --no-color Use a monochrome color scheme\n"
|
|
|
|
"-d --delay=DELAY Set the delay between updates, in tenths of seconds\n"
|
|
|
|
"-F --filter=FILTER Show only the commands matching the given filter\n"
|
|
|
|
"-h --help Print this help screen\n"
|
2022-04-07 10:33:22 +00:00
|
|
|
"-H --highlight-changes[=DELAY] Highlight new and old processes\n", name);
|
2022-04-07 09:52:22 +00:00
|
|
|
#ifdef HAVE_GETMOUSE
|
2022-04-07 10:33:22 +00:00
|
|
|
printf("-M --no-mouse Disable the mouse\n");
|
2022-04-07 09:52:22 +00:00
|
|
|
#endif
|
2022-04-07 10:33:22 +00:00
|
|
|
printf("-p --pid=PID[,PID,PID...] Show only the given PIDs\n"
|
2021-07-14 17:20:16 +00:00
|
|
|
" --readonly Disable all system and process changing features\n"
|
|
|
|
"-s --sort-key=COLUMN Sort by COLUMN in list view (try --sort-key=help for a list)\n"
|
|
|
|
"-t --tree Show the tree view (can be combined with -s)\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"
|
2022-04-07 10:33:22 +00:00
|
|
|
"-V --version Print version info\n");
|
2021-03-23 04:04:54 +00:00
|
|
|
Platform_longOptionsUsage(name);
|
|
|
|
printf("\n"
|
2021-07-14 17:20:16 +00:00
|
|
|
"Long options may be passed with a single dash.\n\n"
|
|
|
|
"Press F1 inside %s for online help.\n"
|
|
|
|
"See 'man %s' for more information.\n", name, name);
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------
|
|
|
|
|
|
|
|
typedef struct CommandLineSettings_ {
|
|
|
|
Hashtable* pidMatchList;
|
|
|
|
char* commFilter;
|
|
|
|
uid_t userId;
|
|
|
|
int sortKey;
|
|
|
|
int delay;
|
|
|
|
bool useColors;
|
|
|
|
bool enableMouse;
|
|
|
|
bool treeView;
|
|
|
|
bool allowUnicode;
|
|
|
|
bool highlightChanges;
|
|
|
|
int highlightDelaySecs;
|
2021-01-21 19:27:37 +00:00
|
|
|
bool readonly;
|
2021-03-23 04:04:54 +00:00
|
|
|
} CommandLineSettings;
|
|
|
|
|
2021-10-06 07:45:07 +00:00
|
|
|
static CommandLineStatus parseArguments(const char* program, int argc, char** argv, CommandLineSettings* flags) {
|
2021-03-23 04:04:54 +00:00
|
|
|
|
2021-10-06 07:45:07 +00:00
|
|
|
*flags = (CommandLineSettings) {
|
2021-03-23 04:04:54 +00:00
|
|
|
.pidMatchList = NULL,
|
|
|
|
.commFilter = NULL,
|
|
|
|
.userId = (uid_t)-1, // -1 is guaranteed to be an invalid uid_t (see setreuid(2))
|
|
|
|
.sortKey = 0,
|
|
|
|
.delay = -1,
|
|
|
|
.useColors = true,
|
|
|
|
.enableMouse = true,
|
|
|
|
.treeView = false,
|
|
|
|
.allowUnicode = true,
|
|
|
|
.highlightChanges = false,
|
|
|
|
.highlightDelaySecs = -1,
|
2021-01-21 19:27:37 +00:00
|
|
|
.readonly = false,
|
2021-03-23 04:04:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const 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'},
|
|
|
|
{"no-unicode", no_argument, 0, 'U'},
|
|
|
|
{"tree", no_argument, 0, 't'},
|
|
|
|
{"pid", required_argument, 0, 'p'},
|
|
|
|
{"filter", required_argument, 0, 'F'},
|
|
|
|
{"highlight-changes", optional_argument, 0, 'H'},
|
2021-01-21 19:27:37 +00:00
|
|
|
{"readonly", no_argument, 0, 128},
|
2021-03-23 04:04:54 +00:00
|
|
|
PLATFORM_LONG_OPTIONS
|
2021-07-14 17:18:27 +00:00
|
|
|
{0, 0, 0, 0}
|
2021-03-23 04:04:54 +00:00
|
|
|
};
|
|
|
|
|
2021-07-14 17:18:27 +00:00
|
|
|
int opt, opti = 0;
|
2021-03-23 04:04:54 +00:00
|
|
|
/* Parse arguments */
|
|
|
|
while ((opt = getopt_long(argc, argv, "hVMCs:td:u::Up:F:H::", long_opts, &opti))) {
|
2021-07-14 17:11:18 +00:00
|
|
|
if (opt == EOF)
|
|
|
|
break;
|
2021-03-23 04:04:54 +00:00
|
|
|
switch (opt) {
|
|
|
|
case 'h':
|
|
|
|
printHelpFlag(program);
|
2021-10-06 07:45:07 +00:00
|
|
|
return STATUS_OK_EXIT;
|
2021-03-23 04:04:54 +00:00
|
|
|
case 'V':
|
|
|
|
printVersionFlag(program);
|
2021-10-06 07:45:07 +00:00
|
|
|
return STATUS_OK_EXIT;
|
2021-03-23 04:04:54 +00:00
|
|
|
case 's':
|
|
|
|
assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */
|
|
|
|
if (String_eq(optarg, "help")) {
|
|
|
|
for (int j = 1; j < LAST_PROCESSFIELD; j++) {
|
|
|
|
const char* name = Process_fields[j].name;
|
|
|
|
const char* description = Process_fields[j].description;
|
|
|
|
if (name) printf("%19s %s\n", name, description);
|
|
|
|
}
|
2021-10-06 07:45:07 +00:00
|
|
|
return STATUS_OK_EXIT;
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
2021-10-06 07:45:07 +00:00
|
|
|
flags->sortKey = 0;
|
2021-03-23 04:04:54 +00:00
|
|
|
for (int j = 1; j < LAST_PROCESSFIELD; j++) {
|
|
|
|
if (Process_fields[j].name == NULL)
|
|
|
|
continue;
|
|
|
|
if (String_eq(optarg, Process_fields[j].name)) {
|
2021-10-06 07:45:07 +00:00
|
|
|
flags->sortKey = j;
|
2021-03-23 04:04:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-10-06 07:45:07 +00:00
|
|
|
if (flags->sortKey == 0) {
|
2021-03-23 04:04:54 +00:00
|
|
|
fprintf(stderr, "Error: invalid column \"%s\".\n", optarg);
|
2021-10-06 07:45:07 +00:00
|
|
|
return STATUS_ERROR_EXIT;
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'd':
|
2021-10-06 07:45:07 +00:00
|
|
|
if (sscanf(optarg, "%16d", &(flags->delay)) == 1) {
|
|
|
|
if (flags->delay < 1) flags->delay = 1;
|
|
|
|
if (flags->delay > 100) flags->delay = 100;
|
2021-03-23 04:04:54 +00:00
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Error: invalid delay value \"%s\".\n", optarg);
|
2021-10-06 07:45:07 +00:00
|
|
|
return STATUS_ERROR_EXIT;
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
{
|
|
|
|
const char *username = optarg;
|
|
|
|
if (!username && optind < argc && argv[optind] != NULL &&
|
|
|
|
(argv[optind][0] != '\0' && argv[optind][0] != '-')) {
|
|
|
|
username = argv[optind++];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!username) {
|
2021-10-06 07:45:07 +00:00
|
|
|
flags->userId = geteuid();
|
|
|
|
} else if (!Action_setUserOnly(username, &(flags->userId))) {
|
2021-10-04 13:08:55 +00:00
|
|
|
for (const char *itr = username; *itr; ++itr)
|
|
|
|
if (!isdigit((unsigned char)*itr)) {
|
|
|
|
fprintf(stderr, "Error: invalid user \"%s\".\n", username);
|
2021-10-06 07:45:07 +00:00
|
|
|
return STATUS_ERROR_EXIT;
|
2021-10-04 13:08:55 +00:00
|
|
|
}
|
2021-10-06 07:45:07 +00:00
|
|
|
flags->userId = atol(username);
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'C':
|
2021-10-06 07:45:07 +00:00
|
|
|
flags->useColors = false;
|
2021-03-23 04:04:54 +00:00
|
|
|
break;
|
|
|
|
case 'M':
|
2021-07-14 19:07:43 +00:00
|
|
|
#ifdef HAVE_GETMOUSE
|
2021-10-06 07:45:07 +00:00
|
|
|
flags->enableMouse = false;
|
2021-07-14 19:07:43 +00:00
|
|
|
#endif
|
2021-03-23 04:04:54 +00:00
|
|
|
break;
|
|
|
|
case 'U':
|
2021-10-06 07:45:07 +00:00
|
|
|
flags->allowUnicode = false;
|
2021-03-23 04:04:54 +00:00
|
|
|
break;
|
|
|
|
case 't':
|
2021-10-06 07:45:07 +00:00
|
|
|
flags->treeView = true;
|
2021-03-23 04:04:54 +00:00
|
|
|
break;
|
|
|
|
case 'p': {
|
|
|
|
assert(optarg); /* please clang analyzer, cause optarg can be NULL in the 'u' case */
|
|
|
|
char* argCopy = xStrdup(optarg);
|
|
|
|
char* saveptr;
|
|
|
|
const char* pid = strtok_r(argCopy, ",", &saveptr);
|
|
|
|
|
2021-10-06 07:45:07 +00:00
|
|
|
if (!flags->pidMatchList) {
|
|
|
|
flags->pidMatchList = Hashtable_new(8, false);
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while(pid) {
|
|
|
|
unsigned int num_pid = atoi(pid);
|
2021-10-06 07:45:07 +00:00
|
|
|
// deepcode ignore CastIntegerToAddress: we just want a non-NULL pointer here
|
|
|
|
Hashtable_put(flags->pidMatchList, num_pid, (void *) 1);
|
2021-03-23 04:04:54 +00:00
|
|
|
pid = strtok_r(NULL, ",", &saveptr);
|
|
|
|
}
|
|
|
|
free(argCopy);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'F': {
|
|
|
|
assert(optarg);
|
2021-10-06 07:45:07 +00:00
|
|
|
free_and_xStrdup(&flags->commFilter, optarg);
|
2021-03-23 04:04:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'H': {
|
|
|
|
const char *delay = optarg;
|
|
|
|
if (!delay && optind < argc && argv[optind] != NULL &&
|
|
|
|
(argv[optind][0] != '\0' && argv[optind][0] != '-')) {
|
|
|
|
delay = argv[optind++];
|
|
|
|
}
|
|
|
|
if (delay) {
|
2021-10-06 07:45:07 +00:00
|
|
|
if (sscanf(delay, "%16d", &(flags->highlightDelaySecs)) == 1) {
|
|
|
|
if (flags->highlightDelaySecs < 1)
|
|
|
|
flags->highlightDelaySecs = 1;
|
2021-03-23 04:04:54 +00:00
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Error: invalid highlight delay value \"%s\".\n", delay);
|
2021-10-06 07:45:07 +00:00
|
|
|
return STATUS_ERROR_EXIT;
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-06 07:45:07 +00:00
|
|
|
flags->highlightChanges = true;
|
2021-03-23 04:04:54 +00:00
|
|
|
break;
|
|
|
|
}
|
2021-01-21 19:27:37 +00:00
|
|
|
case 128:
|
2021-10-06 07:45:07 +00:00
|
|
|
flags->readonly = true;
|
2021-01-21 19:27:37 +00:00
|
|
|
break;
|
2021-03-23 04:04:54 +00:00
|
|
|
|
2021-10-06 07:45:07 +00:00
|
|
|
default: {
|
|
|
|
CommandLineStatus status;
|
|
|
|
if ((status = Platform_getLongOption(opt, argc, argv)) != STATUS_OK)
|
|
|
|
return status;
|
|
|
|
break;
|
|
|
|
}
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-06 07:45:07 +00:00
|
|
|
return STATUS_OK;
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
2021-04-07 23:26:48 +00:00
|
|
|
static void CommandLine_delay(ProcessList* pl, unsigned long millisec) {
|
2021-03-23 04:04:54 +00:00
|
|
|
struct timespec req = {
|
|
|
|
.tv_sec = 0,
|
|
|
|
.tv_nsec = millisec * 1000000L
|
|
|
|
};
|
2021-04-07 23:26:48 +00:00
|
|
|
while (nanosleep(&req, &req) == -1)
|
2021-03-23 04:04:54 +00:00
|
|
|
continue;
|
2021-04-07 23:26:48 +00:00
|
|
|
Platform_gettime_realtime(&pl->realtime, &pl->realtimeMs);
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void setCommFilter(State* state, char** commFilter) {
|
|
|
|
ProcessList* pl = state->pl;
|
|
|
|
IncSet* inc = state->mainPanel->inc;
|
|
|
|
|
|
|
|
IncSet_setFilter(inc, *commFilter);
|
|
|
|
pl->incFilter = IncSet_filter(inc);
|
|
|
|
|
|
|
|
free(*commFilter);
|
|
|
|
*commFilter = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CommandLine_run(const char* name, int argc, char** argv) {
|
|
|
|
|
|
|
|
/* initialize locale */
|
|
|
|
const char* lc_ctype;
|
|
|
|
if ((lc_ctype = getenv("LC_CTYPE")) || (lc_ctype = getenv("LC_ALL")))
|
|
|
|
setlocale(LC_CTYPE, lc_ctype);
|
|
|
|
else
|
|
|
|
setlocale(LC_CTYPE, "");
|
|
|
|
|
2021-10-06 07:45:07 +00:00
|
|
|
CommandLineStatus status = STATUS_OK;
|
|
|
|
CommandLineSettings flags = { 0 };
|
|
|
|
|
|
|
|
if ((status = parseArguments(name, argc, argv, &flags)) != STATUS_OK)
|
|
|
|
return status != STATUS_OK_EXIT ? 1 : 0;
|
2021-03-23 04:04:54 +00:00
|
|
|
|
2021-01-21 19:27:37 +00:00
|
|
|
if (flags.readonly)
|
|
|
|
Settings_enableReadonly();
|
|
|
|
|
2021-10-06 07:45:07 +00:00
|
|
|
if (!Platform_init())
|
|
|
|
return 1;
|
2021-03-23 04:04:54 +00:00
|
|
|
|
|
|
|
Process_setupColumnWidths();
|
|
|
|
|
|
|
|
UsersTable* ut = UsersTable_new();
|
PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns. The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.
We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.
Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location. Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop. This
final location becomes the preferred place for our own
shipped meter and column files.
The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start. Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-07-11 01:11:29 +00:00
|
|
|
Hashtable* dc = DynamicColumns_new();
|
2021-06-23 07:44:56 +00:00
|
|
|
Hashtable* dm = DynamicMeters_new();
|
PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns. The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.
We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.
Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location. Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop. This
final location becomes the preferred place for our own
shipped meter and column files.
The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start. Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-07-11 01:11:29 +00:00
|
|
|
if (!dc)
|
|
|
|
dc = Hashtable_new(0, true);
|
2021-03-23 04:04:54 +00:00
|
|
|
|
PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns. The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.
We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.
Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location. Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop. This
final location becomes the preferred place for our own
shipped meter and column files.
The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start. Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-07-11 01:11:29 +00:00
|
|
|
ProcessList* pl = ProcessList_new(ut, dm, dc, flags.pidMatchList, flags.userId);
|
|
|
|
|
|
|
|
Settings* settings = Settings_new(pl->activeCPUs, dc);
|
2021-03-23 04:04:54 +00:00
|
|
|
pl->settings = settings;
|
|
|
|
|
|
|
|
Header* header = Header_new(pl, settings, 2);
|
|
|
|
|
|
|
|
Header_populateFromSettings(header);
|
|
|
|
|
|
|
|
if (flags.delay != -1)
|
|
|
|
settings->delay = flags.delay;
|
|
|
|
if (!flags.useColors)
|
|
|
|
settings->colorScheme = COLORSCHEME_MONOCHROME;
|
2021-07-14 19:07:43 +00:00
|
|
|
#ifdef HAVE_GETMOUSE
|
2021-03-23 04:04:54 +00:00
|
|
|
if (!flags.enableMouse)
|
|
|
|
settings->enableMouse = false;
|
2021-07-14 19:07:43 +00:00
|
|
|
#endif
|
2021-03-23 04:04:54 +00:00
|
|
|
if (flags.treeView)
|
2021-08-31 05:38:52 +00:00
|
|
|
settings->ss->treeView = true;
|
2021-03-23 04:04:54 +00:00
|
|
|
if (flags.highlightChanges)
|
|
|
|
settings->highlightChanges = true;
|
|
|
|
if (flags.highlightDelaySecs != -1)
|
|
|
|
settings->highlightDelaySecs = flags.highlightDelaySecs;
|
|
|
|
if (flags.sortKey > 0) {
|
|
|
|
// -t -s <key> means "tree sorted by key"
|
|
|
|
// -s <key> means "list sorted by key" (previous existing behavior)
|
|
|
|
if (!flags.treeView) {
|
2021-08-31 05:38:52 +00:00
|
|
|
settings->ss->treeView = false;
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
2021-08-31 05:38:52 +00:00
|
|
|
ScreenSettings_setSortKey(settings->ss, flags.sortKey);
|
2021-03-23 04:04:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CRT_init(settings, flags.allowUnicode);
|
|
|
|
|
|
|
|
MainPanel* panel = MainPanel_new();
|
|
|
|
ProcessList_setPanel(pl, (Panel*) panel);
|
|
|
|
|
2022-03-25 13:51:14 +00:00
|
|
|
MainPanel_updateLabels(panel, settings->ss->treeView, flags.commFilter);
|
2021-03-23 04:04:54 +00:00
|
|
|
|
|
|
|
State state = {
|
|
|
|
.settings = settings,
|
|
|
|
.ut = ut,
|
|
|
|
.pl = pl,
|
|
|
|
.mainPanel = panel,
|
|
|
|
.header = header,
|
|
|
|
.pauseProcessUpdate = false,
|
|
|
|
.hideProcessSelection = false,
|
|
|
|
};
|
|
|
|
|
|
|
|
MainPanel_setState(panel, &state);
|
|
|
|
if (flags.commFilter)
|
|
|
|
setCommFilter(&state, &(flags.commFilter));
|
|
|
|
|
|
|
|
ScreenManager* scr = ScreenManager_new(header, settings, &state, true);
|
|
|
|
ScreenManager_add(scr, (Panel*) panel, -1);
|
|
|
|
|
|
|
|
ProcessList_scan(pl, false);
|
2021-04-07 23:26:48 +00:00
|
|
|
CommandLine_delay(pl, 75);
|
2021-03-23 04:04:54 +00:00
|
|
|
ProcessList_scan(pl, false);
|
|
|
|
|
2021-08-31 05:38:52 +00:00
|
|
|
if (settings->ss->allBranchesCollapsed)
|
2021-03-23 04:04:54 +00:00
|
|
|
ProcessList_collapseAllBranches(pl);
|
|
|
|
|
2021-08-31 05:38:52 +00:00
|
|
|
ScreenManager_run(scr, NULL, NULL, NULL);
|
2021-03-23 04:04:54 +00:00
|
|
|
|
|
|
|
Platform_done();
|
|
|
|
|
|
|
|
CRT_done();
|
|
|
|
|
|
|
|
if (settings->changed) {
|
2021-05-16 17:55:31 +00:00
|
|
|
int r = Settings_write(settings, false);
|
2021-03-23 04:04:54 +00:00
|
|
|
if (r < 0)
|
|
|
|
fprintf(stderr, "Can not save configuration to %s: %s\n", settings->filename, strerror(-r));
|
|
|
|
}
|
|
|
|
|
|
|
|
Header_delete(header);
|
|
|
|
ProcessList_delete(pl);
|
|
|
|
|
|
|
|
ScreenManager_delete(scr);
|
|
|
|
MetersPanel_cleanup();
|
|
|
|
|
|
|
|
UsersTable_delete(ut);
|
|
|
|
|
|
|
|
if (flags.pidMatchList)
|
|
|
|
Hashtable_delete(flags.pidMatchList);
|
|
|
|
|
2021-08-14 17:52:26 +00:00
|
|
|
CRT_resetSignalHandlers();
|
|
|
|
|
PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns. The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.
We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.
Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location. Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop. This
final location becomes the preferred place for our own
shipped meter and column files.
The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start. Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-07-11 01:11:29 +00:00
|
|
|
/* Delete these last, since they can get accessed in the crash handler */
|
2021-05-16 17:55:31 +00:00
|
|
|
Settings_delete(settings);
|
2021-09-03 02:11:31 +00:00
|
|
|
DynamicColumns_delete(dc);
|
|
|
|
DynamicMeters_delete(dm);
|
2021-05-16 17:55:31 +00:00
|
|
|
|
2021-03-23 04:04:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|