Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion CommandLine.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ static void printHelpFlag(const char* name) {
"-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"
"-S --state=STATESCHARS Show only the states matching the given states\n"
"-h --help Print this help screen\n"
"-H --highlight-changes[=DELAY] Highlight new and old processes\n", name);
#ifdef HAVE_GETMOUSE
Expand All @@ -78,6 +79,7 @@ static void printHelpFlag(const char* name) {
typedef struct CommandLineSettings_ {
Hashtable* pidMatchList;
char* commFilter;
char* stateFilter;
uid_t userId;
int sortKey;
int delay;
Expand All @@ -98,6 +100,7 @@ static CommandLineStatus parseArguments(int argc, char** argv, CommandLineSettin
*flags = (CommandLineSettings) {
.pidMatchList = NULL,
.commFilter = NULL,
.stateFilter = NULL,
.userId = (uid_t)-1, // -1 is guaranteed to be an invalid uid_t (see setreuid(2))
.sortKey = 0,
.delay = -1,
Expand Down Expand Up @@ -128,6 +131,7 @@ static CommandLineStatus parseArguments(int argc, char** argv, CommandLineSettin
{"tree", no_argument, 0, 't'},
{"pid", required_argument, 0, 'p'},
{"filter", required_argument, 0, 'F'},
{"state", required_argument, 0, 'S'},
{"highlight-changes", optional_argument, 0, 'H'},
{"readonly", no_argument, 0, 128},
PLATFORM_LONG_OPTIONS
Expand All @@ -136,7 +140,7 @@ static CommandLineStatus parseArguments(int argc, char** argv, CommandLineSettin

int opt, opti = 0;
/* Parse arguments */
while ((opt = getopt_long(argc, argv, "hVMCs:td:n:u::Up:F:H::", long_opts, &opti))) {
while ((opt = getopt_long(argc, argv, "hVMCs:td:n:u::Up:F:H::S:", long_opts, &opti))) {
if (opt == EOF)
break;

Expand Down Expand Up @@ -255,6 +259,36 @@ static CommandLineStatus parseArguments(int argc, char** argv, CommandLineSettin
}
free_and_xStrdup(&flags->commFilter, optarg);
break;

case 'S':
assert(optarg);
if (optarg[0] == '\0') {
fprintf(stderr, "Error: state filter cannot be empty.\n");
return STATUS_ERROR_EXIT;
}

bool valid_states[256] = { false };
for (ProcessState s = UNKNOWN; s <= SLEEPING; s++) {
char c = Process_stateChar(s);
valid_states[(int)c] = true;
}

bool valid_arg = true;
for (char* c = optarg; *c != '\0' && valid_arg; c++) {
if (*c == ',' || isspace(*c))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be just me, but I prefer isblank rather than isspace here.

continue;

valid_arg &= valid_states[(int)*c];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since valid_arg is a boolean, using a bitwise AND operator doesn't look like a good idea to me.

Suggested change
valid_arg &= valid_states[(int)*c];
if (!valid_states[(int)*c]) {
valid_arg = false;
break;
}

}

if (!valid_arg) {
fprintf(stderr, "Error: invalid state filter value \"%s\".\n", optarg);
return STATUS_ERROR_EXIT;
}

free_and_xStrdup(&flags->stateFilter, optarg);
break;

case 'H': {
const char* delay = optarg;
if (!delay && optind < argc && argv[optind] != NULL &&
Expand Down Expand Up @@ -382,6 +416,9 @@ int CommandLine_run(int argc, char** argv) {
.hideSelection = false,
.hideMeters = false,
};
if (flags.stateFilter) {
free_and_xStrdup(&settings->stateFilter, flags.stateFilter);
}

MainPanel_setState(panel, &state);
if (flags.commFilter)
Expand Down
12 changes: 10 additions & 2 deletions Process.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ void Process_writeCommand(const Process* this, int attr, int baseAttr, RichStrin
}
}

static inline char processStateChar(ProcessState state) {
char Process_stateChar(ProcessState state) {
switch (state) {
case UNKNOWN: return '?';
case RUNNABLE: return 'U';
Expand Down Expand Up @@ -716,7 +716,7 @@ void Process_writeField(const Process* this, RichString* str, RowField field) {
case SESSION: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->session); break;
case STARTTIME: xSnprintf(buffer, n, "%s", this->starttime_show); break;
case STATE:
xSnprintf(buffer, n, "%c ", processStateChar(this->state));
xSnprintf(buffer, n, "%c ", Process_stateChar(this->state));
switch (this->state) {
case RUNNABLE:
case RUNNING:
Expand Down Expand Up @@ -860,6 +860,14 @@ static bool Process_matchesFilter(const Process* this, const Table* table) {
if (pt->pidMatchList && !Hashtable_get(pt->pidMatchList, Process_getThreadGroup(this)))
return true;

const char* stateFilter = host->settings->stateFilter;
if (stateFilter) {
char stateChar = Process_stateChar(this->state);
if (!strchr(stateFilter, stateChar)) {
return true;
}
}

return false;
}

Expand Down
4 changes: 3 additions & 1 deletion Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ typedef enum Tristate_ {

/* Core process states (shared by platforms)
* NOTE: The enum has an ordering that is important!
* See processStateChar in process.c for ProcessSate -> letter mapping */
* See Process_stateChar in process.c for ProcessSate -> letter mapping */
typedef enum ProcessState_ {
UNKNOWN = 1,
RUNNABLE,
Expand Down Expand Up @@ -335,6 +335,8 @@ void Process_makeCommandStr(Process* this, const struct Settings_ *settings);

void Process_writeCommand(const Process* this, int attr, int baseAttr, RichString* str);

char Process_stateChar(ProcessState state);

void Process_updateCPUFieldWidths(float percentage);

#endif
1 change: 1 addition & 0 deletions Settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ static void Settings_deleteScreens(Settings* this) {
}

void Settings_delete(Settings* this) {
free(this->stateFilter);
free(this->filename);
free(this->initialFilename);
Settings_deleteColumns(this);
Expand Down
1 change: 1 addition & 0 deletions Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ typedef struct Settings_ {
#ifdef HAVE_LIBHWLOC
bool topologyAffinity;
#endif
char* stateFilter;

bool changed;
uint64_t lastUpdate;
Expand Down
Loading