Skip to content

Commit 2019e60

Browse files
melrovieiraBenBE
authored andcommitted
Added support for the '-S/--state' command-line option to filter processes by state.
- Added support for the '-S/--state' command-line option to filter processes by state. - Implemented validation for the state filter argument (must be one character from "URQWDBPTtZXIS"). - Extended CommandLineSettings struct to include 'stateFilter' field. - Updated parseArguments() to parse and set 'stateFilter' correctly. - Copied 'stateFilter' from flags to Settings in CommandLine_run() after argument parsing. - Applied 'stateFilter' to Settings before UI initialization. - Ensured proper memory management with free_and_xStrdup for 'stateFilter'. - Preserved all original logic and flow; no removals of existing code. Added the stateFilter field to the Settings struct to store the process state filter. Adiciona checagem de estado conforme `stateFilter`. Implement filtering by process state (#1544) - CommandLine.c: * 57l: Add a Help Flag explaining the new feature * 82l: Add stateFilter in struct CommandLineSettings_ to store arguments * 103: Initialize stateFilter as NULL * 134: Add "state", "S" option in struct option * 143: Add "-S" argument in looping * 263: Add case "S" with logic for processing -S flag, ensuring argument is not empty, validate each char against valid process chars * 425: Add copy for settings and memory management - Settings.h: * 113: Add stateFilter pointer to store arguments - Process.h: * 59: Declare processStateChar(ProcessState state) in the header for use in valid character identification logic in CommandLine.c - Process.c: * 539: Remove static inline from processStateChar to allow use in CommandLine.c * 862: Add function that filters by state
1 parent 744914c commit 2019e60

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-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) {

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)