Skip to content

Commit a0794f3

Browse files
melrovieiraBenBE
andcommitted
Added support for the '-S/--state' command-line option to filter processes by state.
This exposes the internal Process state character conversion function so it can be reused for the filter string processing. Multiple characters are allowed for the filter and a process is displayed if any of the provided state characters matches the state of the process currently processed. Co-authored-by: Allison <[email protected]> Co-authored-by: BenBE <[email protected]>
1 parent 744914c commit a0794f3

File tree

5 files changed

+48
-2
lines changed

5 files changed

+48
-2
lines changed

CommandLine.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ static void printHelpFlag(const char* name) {
5454
"-C --no-color Use a monochrome color scheme\n"
5555
"-d --delay=DELAY Set the delay between updates, in tenths of seconds\n"
5656
"-F --filter=FILTER Show only the commands matching the given filter\n"
57+
"-S --state=STATESCHARS Show only the states matching the given states\n"
5758
"-h --help Print this help screen\n"
5859
"-H --highlight-changes[=DELAY] Highlight new and old processes\n", name);
5960
#ifdef HAVE_GETMOUSE
@@ -78,6 +79,7 @@ static void printHelpFlag(const char* name) {
7879
typedef struct CommandLineSettings_ {
7980
Hashtable* pidMatchList;
8081
char* commFilter;
82+
char* stateFilter;
8183
uid_t userId;
8284
int sortKey;
8385
int delay;
@@ -98,6 +100,7 @@ static CommandLineStatus parseArguments(int argc, char** argv, CommandLineSettin
98100
*flags = (CommandLineSettings) {
99101
.pidMatchList = NULL,
100102
.commFilter = NULL,
103+
.stateFilter = NULL,
101104
.userId = (uid_t)-1, // -1 is guaranteed to be an invalid uid_t (see setreuid(2))
102105
.sortKey = 0,
103106
.delay = -1,
@@ -128,6 +131,7 @@ static CommandLineStatus parseArguments(int argc, char** argv, CommandLineSettin
128131
{"tree", no_argument, 0, 't'},
129132
{"pid", required_argument, 0, 'p'},
130133
{"filter", required_argument, 0, 'F'},
134+
{"state", required_argument, 0, 'S'},
131135
{"highlight-changes", optional_argument, 0, 'H'},
132136
{"readonly", no_argument, 0, 128},
133137
PLATFORM_LONG_OPTIONS
@@ -136,7 +140,7 @@ static CommandLineStatus parseArguments(int argc, char** argv, CommandLineSettin
136140

137141
int opt, opti = 0;
138142
/* Parse arguments */
139-
while ((opt = getopt_long(argc, argv, "hVMCs:td:n:u::Up:F:H::", long_opts, &opti))) {
143+
while ((opt = getopt_long(argc, argv, "hVMCs:td:n:u::Up:F:H::S:", long_opts, &opti))) {
140144
if (opt == EOF)
141145
break;
142146

@@ -255,6 +259,33 @@ static CommandLineStatus parseArguments(int argc, char** argv, CommandLineSettin
255259
}
256260
free_and_xStrdup(&flags->commFilter, optarg);
257261
break;
262+
263+
case 'S':
264+
assert(optarg);
265+
if (optarg[0] == '\0') {
266+
fprintf(stderr, "Error: state filter cannot be empty.\n");
267+
return STATUS_ERROR_EXIT;
268+
}
269+
270+
for (char* c = optarg; *c != '\0'; c++) {
271+
bool valid = false;
272+
273+
for (ProcessState s = UNKNOWN; s <= SLEEPING; s++) {
274+
if (*c == processStateChar(s)) {
275+
valid = true;
276+
break;
277+
}
278+
}
279+
280+
if (!valid) {
281+
fprintf(stderr, "Error: invalid state filter value \"%s\".\n", optarg);
282+
return STATUS_ERROR_EXIT;
283+
}
284+
}
285+
286+
free_and_xStrdup(&flags->stateFilter, optarg);
287+
break;
288+
258289
case 'H': {
259290
const char* delay = optarg;
260291
if (!delay && optind < argc && argv[optind] != NULL &&
@@ -382,6 +413,9 @@ int CommandLine_run(int argc, char** argv) {
382413
.hideSelection = false,
383414
.hideMeters = false,
384415
};
416+
if (flags.stateFilter) {
417+
free_and_xStrdup(&settings->stateFilter, flags.stateFilter);
418+
}
385419

386420
MainPanel_setState(panel, &state);
387421
if (flags.commFilter)

Process.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ void Process_writeCommand(const Process* this, int attr, int baseAttr, RichStrin
536536
}
537537
}
538538

539-
static inline char processStateChar(ProcessState state) {
539+
char processStateChar(ProcessState state) {
540540
switch (state) {
541541
case UNKNOWN: return '?';
542542
case RUNNABLE: return 'U';
@@ -860,6 +860,14 @@ static bool Process_matchesFilter(const Process* this, const Table* table) {
860860
if (pt->pidMatchList && !Hashtable_get(pt->pidMatchList, Process_getThreadGroup(this)))
861861
return true;
862862

863+
const char* stateFilter = host->settings->stateFilter;
864+
if (stateFilter) {
865+
char stateChar = processStateChar(this->state);
866+
if (!strchr(stateFilter, stateChar)) {
867+
return true;
868+
}
869+
}
870+
863871
return false;
864872
}
865873

Process.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ void Process_makeCommandStr(Process* this, const struct Settings_ *settings);
335335

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

338+
char processStateChar(ProcessState state);
339+
338340
void Process_updateCPUFieldWidths(float percentage);
339341

340342
#endif

Settings.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ static void Settings_deleteScreens(Settings* this) {
4949
}
5050

5151
void Settings_delete(Settings* this) {
52+
free(this->stateFilter);
5253
free(this->filename);
5354
free(this->initialFilename);
5455
Settings_deleteColumns(this);

Settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ typedef struct Settings_ {
110110
bool topologyAffinity;
111111
#endif
112112

113+
char* stateFilter; // store stateFilter argument
113114
bool changed;
114115
uint64_t lastUpdate;
115116
} Settings;

0 commit comments

Comments
 (0)