Skip to content

Commit 4cf9bd6

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 4cf9bd6

File tree

4 files changed

+56
-3
lines changed

4 files changed

+56
-3
lines changed

CommandLine.c

Lines changed: 43 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,41 @@ static CommandLineStatus parseArguments(int argc, char** argv, CommandLineSettin
255259
}
256260
free_and_xStrdup(&flags->commFilter, optarg);
257261
break;
262+
263+
case 'S':
264+
//ensures that optarg is not NULL
265+
assert(optarg);
266+
267+
// check if the argument is empty
268+
if (optarg[0] == '\0') {
269+
fprintf(stderr, "Error: state filter cannot be empty.\n");
270+
return STATUS_ERROR_EXIT;
271+
}
272+
273+
// for each character in optarg:
274+
// - check if it corresponds to a valid ProcessState enum value
275+
// - if any character is invalid, print an error and exit
276+
for (char* c = optarg; *c != '\0'; c++) {
277+
int valid = 0;
278+
279+
// test all ProcessState enum values
280+
for (ProcessState s = UNKNOWN; s <= SLEEPING; s++) {
281+
if (*c == processStateChar(s)) {
282+
valid = 1; // character is valid
283+
break;
284+
}
285+
}
286+
287+
// if character is invalid, report error and exit
288+
if (!valid) {
289+
fprintf(stderr, "Error: invalid state filter value \"%s\".\n", optarg);
290+
return STATUS_ERROR_EXIT;
291+
}
292+
}
293+
294+
free_and_xStrdup(&flags->stateFilter, optarg);
295+
break;
296+
258297
case 'H': {
259298
const char* delay = optarg;
260299
if (!delay && optind < argc && argv[optind] != NULL &&
@@ -382,6 +421,9 @@ int CommandLine_run(int argc, char** argv) {
382421
.hideSelection = false,
383422
.hideMeters = false,
384423
};
424+
if (flags.stateFilter) {
425+
free_and_xStrdup(&settings->stateFilter, flags.stateFilter);
426+
}
385427

386428
MainPanel_setState(panel, &state);
387429
if (flags.commFilter)

Process.c

Lines changed: 10 additions & 2 deletions
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';
@@ -859,8 +859,16 @@ static bool Process_matchesFilter(const Process* this, const Table* table) {
859859
assert(Object_isA((const Object*) pt, (const ObjectClass*) &ProcessTable_class));
860860
if (pt->pidMatchList && !Hashtable_get(pt->pidMatchList, Process_getThreadGroup(this)))
861861
return true;
862+
const char* stateFilter = host->settings->stateFilter;// stateFilter arguments passed by user
863+
if (stateFilter) {
864+
char stateChar = processStateChar(this->state); //stateChar of current process
865+
if (!strchr(stateFilter, stateChar)) { //checks if stateChar exists in stateFilter arguments
866+
return true; //if stateChar don't exists in string, return true, this hide the process that is not in stateFilter arguments
867+
}
868+
}
862869

863-
return false;
870+
871+
return false; //if stateChar exists in string, return false, for the process that user passed by in stateFilter arguments to appear
864872
}
865873

866874
bool Process_rowMatchesFilter(const Row* super, const Table* table) {

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.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)