pgrep.c: Match based on process run state for issue 109

References:
 procps-ng/procps#109
This commit is contained in:
ed 2019-01-03 22:34:14 +00:00 committed by Craig Small
parent 866a27cdcd
commit 7b4ad698cc
2 changed files with 18 additions and 4 deletions

View File

@ -154,6 +154,9 @@ than
\fB\-L\fR, \fB\-\-logpidfile\fR \fB\-L\fR, \fB\-\-logpidfile\fR
Fail if pidfile (see -F) not locked. Fail if pidfile (see -F) not locked.
.TP .TP
\fB\-r\fR, \fB\-\-runstates\fR \fID,R,S,Z,\fP...
Match only processes which match the process state.
.TP
\fB\-\-ns \fIpid\fP \fB\-\-ns \fIpid\fP
Match processes that belong to the same namespaces. Required to run as Match processes that belong to the same namespaces. Required to run as
root to match processes from other users. See \-\-nslist for how to limit root to match processes from other users. See \-\-nslist for how to limit

19
pgrep.c
View File

@ -63,11 +63,12 @@ enum pids_item Items[] = {
PIDS_TIME_START, PIDS_TIME_START,
PIDS_TTY_NAME, PIDS_TTY_NAME,
PIDS_CMD, PIDS_CMD,
PIDS_CMDLINE PIDS_CMDLINE,
PIDS_STATE
}; };
enum rel_items { enum rel_items {
EU_PID, EU_PPID, EU_PGRP, EU_EUID, EU_RUID, EU_RGID, EU_SESSION, EU_PID, EU_PPID, EU_PGRP, EU_EUID, EU_RUID, EU_RGID, EU_SESSION,
EU_TGID, EU_STARTTIME, EU_TTYNAME, EU_CMD, EU_CMDLINE EU_TGID, EU_STARTTIME, EU_TTYNAME, EU_CMD, EU_CMDLINE, EU_STA
}; };
#define grow_size(x) do { \ #define grow_size(x) do { \
if ((x) < 0 || (size_t)(x) >= INT_MAX / 5 / sizeof(struct el)) \ if ((x) < 0 || (size_t)(x) >= INT_MAX / 5 / sizeof(struct el)) \
@ -111,6 +112,7 @@ static struct el *opt_ruid = NULL;
static struct el *opt_nslist = NULL; static struct el *opt_nslist = NULL;
static char *opt_pattern = NULL; static char *opt_pattern = NULL;
static char *opt_pidfile = NULL; static char *opt_pidfile = NULL;
static char *opt_runstates = NULL;
/* by default, all namespaces will be checked */ /* by default, all namespaces will be checked */
static int ns_flags = 0x3f; static int ns_flags = 0x3f;
@ -149,6 +151,7 @@ static int __attribute__ ((__noreturn__)) usage(int opt)
fputs(_(" -x, --exact match exactly with the command name\n"), fp); fputs(_(" -x, --exact match exactly with the command name\n"), fp);
fputs(_(" -F, --pidfile <file> read PIDs from file\n"), fp); fputs(_(" -F, --pidfile <file> read PIDs from file\n"), fp);
fputs(_(" -L, --logpidfile fail if PID file is not locked\n"), fp); fputs(_(" -L, --logpidfile fail if PID file is not locked\n"), fp);
fputs(_(" -r, --runstates <state> match runstates [D,S,Z,...]\n"), fp);
fputs(_(" --ns <PID> match the processes that belong to the same\n" fputs(_(" --ns <PID> match the processes that belong to the same\n"
" namespace as <pid>\n"), fp); " namespace as <pid>\n"), fp);
fputs(_(" --nslist <ns,...> list which namespaces will be considered for\n" fputs(_(" --nslist <ns,...> list which namespaces will be considered for\n"
@ -482,6 +485,7 @@ static struct el * select_procs (int *num)
#define PIDS_GETUNT(e) PIDS_VAL(EU_ ## e, u_int, stack, info) #define PIDS_GETUNT(e) PIDS_VAL(EU_ ## e, u_int, stack, info)
#define PIDS_GETULL(e) PIDS_VAL(EU_ ## e, ull_int, stack, info) #define PIDS_GETULL(e) PIDS_VAL(EU_ ## e, ull_int, stack, info)
#define PIDS_GETSTR(e) PIDS_VAL(EU_ ## e, str, stack, info) #define PIDS_GETSTR(e) PIDS_VAL(EU_ ## e, str, stack, info)
#define PIDS_GETSCH(e) PIDS_VAL(EU_ ## e, s_ch, stack, info)
struct pids_info *info=NULL; struct pids_info *info=NULL;
struct procps_namespaces nsp; struct procps_namespaces nsp;
struct pids_stack *stack; struct pids_stack *stack;
@ -509,7 +513,7 @@ static struct el * select_procs (int *num)
_("Error reading reference namespace information\n")); _("Error reading reference namespace information\n"));
} }
if (procps_pids_new(&info, Items, 12) < 0) if (procps_pids_new(&info, Items, 13) < 0)
xerrx(EXIT_FATAL, xerrx(EXIT_FATAL,
_("Unable to create pid info structure")); _("Unable to create pid info structure"));
which = PIDS_FETCH_TASKS_ONLY; which = PIDS_FETCH_TASKS_ONLY;
@ -543,6 +547,8 @@ static struct el * select_procs (int *num)
match = 0; match = 0;
else if (opt_term) else if (opt_term)
match = match_strlist(PIDS_GETSTR(TTYNAME), opt_term); match = match_strlist(PIDS_GETSTR(TTYNAME), opt_term);
else if (opt_runstates && ! strchr(opt_runstates, PIDS_GETSCH(STA)))
match = 0;
task_cmdline = PIDS_GETSTR(CMDLINE); task_cmdline = PIDS_GETSTR(CMDLINE);
task_cmdline[CMDSTRSIZE -1] = '\0'; task_cmdline[CMDSTRSIZE -1] = '\0';
@ -666,6 +672,7 @@ static void parse_opts (int argc, char **argv)
{"echo", no_argument, NULL, 'e'}, {"echo", no_argument, NULL, 'e'},
{"ns", required_argument, NULL, NS_OPTION}, {"ns", required_argument, NULL, NS_OPTION},
{"nslist", required_argument, NULL, NSLIST_OPTION}, {"nslist", required_argument, NULL, NSLIST_OPTION},
{"runstates", required_argument, NULL, 'r'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'}, {"version", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
@ -684,7 +691,7 @@ static void parse_opts (int argc, char **argv)
strcat (opts, "lad:vw"); strcat (opts, "lad:vw");
} }
strcat (opts, "LF:cfinoxP:g:s:u:U:G:t:?Vh"); strcat (opts, "LF:cfinoxP:g:s:u:U:G:t:r:?Vh");
while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != -1) { while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != -1) {
switch (opt) { switch (opt) {
@ -818,6 +825,10 @@ static void parse_opts (int argc, char **argv)
usage ('?'); usage ('?');
++criteria_count; ++criteria_count;
break; break;
case 'r': /* match by runstate */
opt_runstates = xstrdup (optarg);
++criteria_count;
break;
case NSLIST_OPTION: case NSLIST_OPTION:
opt_nslist = split_list (optarg, conv_ns); opt_nslist = split_list (optarg, conv_ns);
if (opt_nslist == NULL) if (opt_nslist == NULL)