pgrep: Use new library API

Change pgrep to use new library API. Threads now use their own
name instead of parent process.  Updated man page to make note
of it.
This commit is contained in:
Craig Small 2015-09-26 08:19:32 +10:00
parent 86b155b83f
commit b5e3c5e835
2 changed files with 93 additions and 91 deletions

View File

@ -2,7 +2,7 @@
.\" Licensed under version 2 of the GNU General Public License. .\" Licensed under version 2 of the GNU General Public License.
.\" Copyright 2000 Kjetil Torgrim Homme .\" Copyright 2000 Kjetil Torgrim Homme
.\" .\"
.TH PGREP "1" "March 2015" "procps-ng" "User Commands" .TH PGREP "1" "September 2015" "procps-ng" "User Commands"
.SH NAME .SH NAME
pgrep, pkill \- look up or signal processes based on name and other attributes pgrep, pkill \- look up or signal processes based on name and other attributes
.SH SYNOPSIS .SH SYNOPSIS
@ -211,7 +211,8 @@ Fatal error: out of memory etc.
.SH NOTES .SH NOTES
The process name used for matching is limited to the 15 characters present in The process name used for matching is limited to the 15 characters present in
the output of /proc/\fIpid\fP/stat. Use the \-f option to match against the the output of /proc/\fIpid\fP/stat. Use the \-f option to match against the
complete command line, /proc/\fIpid\fP/cmdline. complete command line, /proc/\fIpid\fP/cmdline. Threads may not have the
same process name as the parent process but will have the same command line.
.PP .PP
The running The running
.B pgrep .B pgrep

179
pgrep.c
View File

@ -49,11 +49,27 @@
#include "nls.h" #include "nls.h"
#include "signals.h" #include "signals.h"
#include "xalloc.h" #include "xalloc.h"
#include "proc/readproc.h" #include <proc/pids.h>
#include "proc/devname.h"
#include "proc/sysinfo.h"
#include <proc/namespace.h> #include <proc/namespace.h>
#include <proc/devname.h>
enum pids_item Items[] = {
PROCPS_PIDS_ID_PID,
PROCPS_PIDS_ID_PPID,
PROCPS_PIDS_ID_PGRP,
PROCPS_PIDS_ID_EUID,
PROCPS_PIDS_ID_RUID,
PROCPS_PIDS_ID_RGID,
PROCPS_PIDS_ID_SESSION,
PROCPS_PIDS_TIME_START,
PROCPS_PIDS_TTY,
PROCPS_PIDS_CMD,
PROCPS_PIDS_CMDLINE,
};
enum rel_items {
EU_TGID, EU_PPID, EU_PGRP, EU_EUID, EU_RUID, EU_RGID, EU_SESSION,
EU_STARTTIME, EU_TTY, EU_CMD, EU_CMDLINE
};
static int i_am_pkill = 0; static int i_am_pkill = 0;
struct el { struct el {
@ -381,15 +397,19 @@ static int match_strlist (const char *restrict value, const struct el *restrict
return found; return found;
} }
static int match_ns (const proc_t *task, static int match_ns (const int pid,
const struct procps_namespaces *namespaces) const struct procps_namespaces *match_ns)
{ {
struct procps_namespaces proc_ns;
int found = 1; int found = 1;
int i; int i;
for (i = 0; i < NUM_NS; i++) { if (procps_ns_read_pid(pid, &proc_ns) < 0)
xerrx(EXIT_FATAL,
_("Unable to read process namespace information"));
for (i = 0; i < PROCPS_NS_COUNT; i++) {
if (ns_flags & (1 << i)) { if (ns_flags & (1 << i)) {
if (task->ns.ns[i] != namespaces->ns[i]) if (proc_ns.ns[i] != match_ns->ns[i])
found = 0; found = 0;
} }
} }
@ -420,36 +440,6 @@ static void output_strlist (const struct el *restrict list, int num)
} }
} }
static PROCTAB *do_openproc (void)
{
PROCTAB *ptp;
int flags = 0;
if (opt_pattern || opt_full || opt_longlong)
flags |= PROC_FILLCOM;
if (opt_ruid || opt_rgid)
flags |= PROC_FILLSTATUS;
if (opt_oldest || opt_newest || opt_pgrp || opt_sid || opt_term)
flags |= PROC_FILLSTAT;
if (!(flags & PROC_FILLSTAT))
flags |= PROC_FILLSTATUS; /* FIXME: need one, and PROC_FILLANY broken */
if (opt_ns_pid)
flags |= PROC_FILLNS;
if (opt_euid && !opt_negate) {
int num = opt_euid[0].num;
int i = num;
uid_t *uids = xmalloc (num * sizeof (uid_t));
while (i-- > 0) {
uids[i] = opt_euid[i+1].num;
}
flags |= PROC_UID;
ptp = openproc (flags, uids, num);
} else {
ptp = openproc (flags);
}
return ptp;
}
static regex_t * do_regcomp (void) static regex_t * do_regcomp (void)
{ {
regex_t *preg = NULL; regex_t *preg = NULL;
@ -482,8 +472,13 @@ static regex_t * do_regcomp (void)
static struct el * select_procs (int *num) static struct el * select_procs (int *num)
{ {
PROCTAB *ptp; #define PIDS_GETINT(e) PROCPS_PIDS_VAL(EU_ ## e, s_int, stack)
proc_t task; #define PIDS_GETULL(e) PROCPS_PIDS_VAL(EU_ ## e, ull_int, stack)
#define PIDS_GETSTR(e) PROCPS_PIDS_VAL(EU_ ## e, str, stack)
struct procps_pidsinfo *info=NULL;
struct procps_namespaces nsp;
struct pids_stack *stack;
unsigned long long saved_start_time; /* for new/old support */ unsigned long long saved_start_time; /* for new/old support */
pid_t saved_pid = 0; /* for new/old support */ pid_t saved_pid = 0; /* for new/old support */
int matches = 0; int matches = 0;
@ -491,12 +486,10 @@ static struct el * select_procs (int *num)
regex_t *preg; regex_t *preg;
pid_t myself = getpid(); pid_t myself = getpid();
struct el *list = NULL; struct el *list = NULL;
char cmdline[CMDSTRSIZE];
char cmdsearch[CMDSTRSIZE]; char cmdsearch[CMDSTRSIZE];
char cmdoutput[CMDSTRSIZE]; char cmdoutput[CMDSTRSIZE];
struct procps_namespaces namespaces; char *task_cmdline;
ptp = do_openproc();
preg = do_regcomp(); preg = do_regcomp();
if (opt_newest) saved_start_time = 0ULL; if (opt_newest) saved_start_time = 0ULL;
@ -504,49 +497,59 @@ static struct el * select_procs (int *num)
if (opt_newest) saved_pid = 0; if (opt_newest) saved_pid = 0;
if (opt_oldest) saved_pid = INT_MAX; if (opt_oldest) saved_pid = INT_MAX;
if (opt_ns_pid && procps_ns_read_pid(opt_ns_pid, &namespaces) < 0) { if (opt_ns_pid && procps_ns_read_pid(opt_ns_pid, &nsp) < 0) {
fputs(_("Error reading reference namespace information\n"), xerrx(EXIT_FATAL,
stderr); _("Error reading reference namespace information\n"));
exit (EXIT_FATAL);
} }
memset(&task, 0, sizeof (task)); if (procps_pids_new(&info, 11, Items) < 0)
while(readproc(ptp, &task)) { xerrx(EXIT_FATAL,
_("Unable to create pid info structure"));
if (procps_pids_read_open(info,
((opt_threads && !i_am_pkill)?
PROCPS_REAP_THREADS_TOO:PROCPS_REAP_TASKS_ONLY)) < 0)
xerrx(EXIT_FATAL,
_("Unable to open pids information"));
while ((stack = procps_pids_read_next(info))) {
int match = 1; int match = 1;
if (task.XXXID == myself) if (PIDS_GETINT(TGID) == myself)
continue; continue;
else if (opt_newest && task.start_time < saved_start_time) else if (opt_newest && PIDS_GETULL(STARTTIME) < saved_start_time)
match = 0; match = 0;
else if (opt_oldest && task.start_time > saved_start_time) else if (opt_oldest && PIDS_GETULL(STARTTIME) > saved_start_time)
match = 0; match = 0;
else if (opt_ppid && ! match_numlist (task.ppid, opt_ppid)) else if (opt_ppid && ! match_numlist(PIDS_GETINT(PPID), opt_ppid))
match = 0; match = 0;
else if (opt_pid && ! match_numlist (task.tgid, opt_pid)) else if (opt_pid && ! match_numlist (PIDS_GETINT(TGID), opt_pid))
match = 0; match = 0;
else if (opt_pgrp && ! match_numlist (task.pgrp, opt_pgrp)) else if (opt_pgrp && ! match_numlist (PIDS_GETINT(PGRP), opt_pgrp))
match = 0; match = 0;
else if (opt_euid && ! match_numlist (task.euid, opt_euid)) else if (opt_euid && ! match_numlist (PIDS_GETINT(EUID), opt_euid))
match = 0; match = 0;
else if (opt_ruid && ! match_numlist (task.ruid, opt_ruid)) else if (opt_ruid && ! match_numlist (PIDS_GETINT(RUID), opt_ruid))
match = 0; match = 0;
else if (opt_rgid && ! match_numlist (task.rgid, opt_rgid)) else if (opt_rgid && ! match_numlist (PIDS_GETINT(RGID), opt_rgid))
match = 0; match = 0;
else if (opt_sid && ! match_numlist (task.session, opt_sid)) else if (opt_sid && ! match_numlist (PIDS_GETINT(SESSION), opt_sid))
match = 0; match = 0;
else if (opt_ns_pid && ! match_ns (&task, &namespaces)) else if (opt_ns_pid && ! match_ns (PIDS_GETINT(TGID), &nsp))
match = 0; match = 0;
else if (opt_term) { else if (opt_term) {
if (task.tty == 0) { int task_tty = PIDS_GETINT(TTY);
if (task_tty == 0) {
match = 0; match = 0;
} else { } else {
char tty[256]; char tty[256];
dev_to_tty (tty, sizeof(tty) - 1, dev_to_tty (tty, sizeof(tty) - 1,
task.tty, task.XXXID, ABBREV_DEV); task_tty, PIDS_GETINT(TGID), ABBREV_DEV);
match = match_strlist (tty, opt_term); match = match_strlist (tty, opt_term);
} }
} }
if (task.cmdline && (opt_longlong || opt_full) ) { task_cmdline = PIDS_GETSTR(CMDLINE);
#if 0 // FIXME cmdline stuff
if (pid_cmdline && (opt_longlong || opt_full) ) {
int i = 0; int i = 0;
int bytes = sizeof (cmdline) - 1; int bytes = sizeof (cmdline) - 1;
@ -555,7 +558,7 @@ static struct el * select_procs (int *num)
/* make room for SPC in loop below */ /* make room for SPC in loop below */
--bytes; --bytes;
strncpy (cmdline, task.cmdline[i], bytes); strncpy (cmdline, pid_cmdline[i], bytes);
bytes -= strlen (task.cmdline[i++]); bytes -= strlen (task.cmdline[i++]);
while (task.cmdline[i] && bytes > 0) { while (task.cmdline[i] && bytes > 0) {
strncat (cmdline, " ", bytes); strncat (cmdline, " ", bytes);
@ -563,19 +566,20 @@ static struct el * select_procs (int *num)
bytes -= strlen (task.cmdline[i++]) + 1; bytes -= strlen (task.cmdline[i++]) + 1;
} }
} }
#endif
if (opt_long || opt_longlong || (match && opt_pattern)) { if (opt_long || opt_longlong || (match && opt_pattern)) {
if (opt_longlong && task.cmdline) if (opt_longlong && task_cmdline)
strncpy (cmdoutput, cmdline, CMDSTRSIZE); strncpy (cmdoutput, task_cmdline, CMDSTRSIZE);
else else
strncpy (cmdoutput, task.cmd, CMDSTRSIZE); strncpy (cmdoutput, PIDS_GETSTR(CMD), CMDSTRSIZE);
} }
if (match && opt_pattern) { if (match && opt_pattern) {
if (opt_full && task.cmdline) if (opt_full && task_cmdline)
strncpy (cmdsearch, cmdline, CMDSTRSIZE); strncpy (cmdsearch, task_cmdline, CMDSTRSIZE);
else else
strncpy (cmdsearch, task.cmd, CMDSTRSIZE); strncpy (cmdsearch, PIDS_GETSTR(CMD), CMDSTRSIZE);
if (regexec (preg, cmdsearch, 0, NULL, 0) != 0) if (regexec (preg, cmdsearch, 0, NULL, 0) != 0)
match = 0; match = 0;
@ -583,19 +587,19 @@ static struct el * select_procs (int *num)
if (match ^ opt_negate) { /* Exclusive OR is neat */ if (match ^ opt_negate) { /* Exclusive OR is neat */
if (opt_newest) { if (opt_newest) {
if (saved_start_time == task.start_time && if (saved_start_time == PIDS_GETULL(STARTTIME) &&
saved_pid > task.XXXID) saved_pid > PIDS_GETINT(TGID))
continue; continue;
saved_start_time = task.start_time; saved_start_time = PIDS_GETULL(STARTTIME);
saved_pid = task.XXXID; saved_pid = PIDS_GETINT(TGID);
matches = 0; matches = 0;
} }
if (opt_oldest) { if (opt_oldest) {
if (saved_start_time == task.start_time && if (saved_start_time == PIDS_GETULL(STARTTIME) &&
saved_pid < task.XXXID) saved_pid < PIDS_GETINT(TGID))
continue; continue;
saved_start_time = task.start_time; saved_start_time = PIDS_GETULL(STARTTIME);
saved_pid = task.XXXID; saved_pid = PIDS_GETINT(TGID);
matches = 0; matches = 0;
} }
if (matches == size) { if (matches == size) {
@ -603,14 +607,14 @@ static struct el * select_procs (int *num)
list = xrealloc(list, size * sizeof *list); list = xrealloc(list, size * sizeof *list);
} }
if (list && (opt_long || opt_longlong || opt_echo)) { if (list && (opt_long || opt_longlong || opt_echo)) {
list[matches].num = task.XXXID; list[matches].num = PIDS_GETINT(TGID);
list[matches++].str = xstrdup (cmdoutput); list[matches++].str = xstrdup (cmdoutput);
} else if (list) { } else if (list) {
list[matches++].num = task.XXXID; list[matches++].num = PIDS_GETINT(TGID);
} else { } else {
xerrx(EXIT_FAILURE, _("internal error")); xerrx(EXIT_FATAL, _("internal error"));
} }
#if 0
// pkill does not need subtasks! // pkill does not need subtasks!
// this control is still done at // this control is still done at
// argparse time, but a further // argparse time, but a further
@ -640,17 +644,11 @@ static struct el * select_procs (int *num)
} }
} }
#endif
} }
memset (&task, 0, sizeof (task));
} }
closeproc (ptp);
*num = matches; *num = matches;
return list; return list;
} }
@ -673,6 +671,9 @@ static int signal_option(int *argc, char **argv)
} }
} }
return -1; return -1;
#undef PIDS_GETINT
#undef PIDS_GETULL
#undef PIDS_GETSTR
} }
static void parse_opts (int argc, char **argv) static void parse_opts (int argc, char **argv)