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.
.\" 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
pgrep, pkill \- look up or signal processes based on name and other attributes
.SH SYNOPSIS
@ -211,7 +211,8 @@ Fatal error: out of memory etc.
.SH NOTES
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
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
The running
.B pgrep

179
pgrep.c
View File

@ -49,11 +49,27 @@
#include "nls.h"
#include "signals.h"
#include "xalloc.h"
#include "proc/readproc.h"
#include "proc/devname.h"
#include "proc/sysinfo.h"
#include <proc/pids.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;
struct el {
@ -381,15 +397,19 @@ static int match_strlist (const char *restrict value, const struct el *restrict
return found;
}
static int match_ns (const proc_t *task,
const struct procps_namespaces *namespaces)
static int match_ns (const int pid,
const struct procps_namespaces *match_ns)
{
struct procps_namespaces proc_ns;
int found = 1;
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 (task->ns.ns[i] != namespaces->ns[i])
if (proc_ns.ns[i] != match_ns->ns[i])
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)
{
regex_t *preg = NULL;
@ -482,8 +472,13 @@ static regex_t * do_regcomp (void)
static struct el * select_procs (int *num)
{
PROCTAB *ptp;
proc_t task;
#define PIDS_GETINT(e) PROCPS_PIDS_VAL(EU_ ## e, s_int, stack)
#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 */
pid_t saved_pid = 0; /* for new/old support */
int matches = 0;
@ -491,12 +486,10 @@ static struct el * select_procs (int *num)
regex_t *preg;
pid_t myself = getpid();
struct el *list = NULL;
char cmdline[CMDSTRSIZE];
char cmdsearch[CMDSTRSIZE];
char cmdoutput[CMDSTRSIZE];
struct procps_namespaces namespaces;
char *task_cmdline;
ptp = do_openproc();
preg = do_regcomp();
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_oldest) saved_pid = INT_MAX;
if (opt_ns_pid && procps_ns_read_pid(opt_ns_pid, &namespaces) < 0) {
fputs(_("Error reading reference namespace information\n"),
stderr);
exit (EXIT_FATAL);
if (opt_ns_pid && procps_ns_read_pid(opt_ns_pid, &nsp) < 0) {
xerrx(EXIT_FATAL,
_("Error reading reference namespace information\n"));
}
memset(&task, 0, sizeof (task));
while(readproc(ptp, &task)) {
if (procps_pids_new(&info, 11, Items) < 0)
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;
if (task.XXXID == myself)
if (PIDS_GETINT(TGID) == myself)
continue;
else if (opt_newest && task.start_time < saved_start_time)
else if (opt_newest && PIDS_GETULL(STARTTIME) < saved_start_time)
match = 0;
else if (opt_oldest && task.start_time > saved_start_time)
else if (opt_oldest && PIDS_GETULL(STARTTIME) > saved_start_time)
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;
else if (opt_pid && ! match_numlist (task.tgid, opt_pid))
else if (opt_pid && ! match_numlist (PIDS_GETINT(TGID), opt_pid))
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;
else if (opt_euid && ! match_numlist (task.euid, opt_euid))
else if (opt_euid && ! match_numlist (PIDS_GETINT(EUID), opt_euid))
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;
else if (opt_rgid && ! match_numlist (task.rgid, opt_rgid))
else if (opt_rgid && ! match_numlist (PIDS_GETINT(RGID), opt_rgid))
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;
else if (opt_ns_pid && ! match_ns (&task, &namespaces))
else if (opt_ns_pid && ! match_ns (PIDS_GETINT(TGID), &nsp))
match = 0;
else if (opt_term) {
if (task.tty == 0) {
int task_tty = PIDS_GETINT(TTY);
if (task_tty == 0) {
match = 0;
} else {
char tty[256];
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);
}
}
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 bytes = sizeof (cmdline) - 1;
@ -555,7 +558,7 @@ static struct el * select_procs (int *num)
/* make room for SPC in loop below */
--bytes;
strncpy (cmdline, task.cmdline[i], bytes);
strncpy (cmdline, pid_cmdline[i], bytes);
bytes -= strlen (task.cmdline[i++]);
while (task.cmdline[i] && bytes > 0) {
strncat (cmdline, " ", bytes);
@ -563,19 +566,20 @@ static struct el * select_procs (int *num)
bytes -= strlen (task.cmdline[i++]) + 1;
}
}
#endif
if (opt_long || opt_longlong || (match && opt_pattern)) {
if (opt_longlong && task.cmdline)
strncpy (cmdoutput, cmdline, CMDSTRSIZE);
if (opt_longlong && task_cmdline)
strncpy (cmdoutput, task_cmdline, CMDSTRSIZE);
else
strncpy (cmdoutput, task.cmd, CMDSTRSIZE);
strncpy (cmdoutput, PIDS_GETSTR(CMD), CMDSTRSIZE);
}
if (match && opt_pattern) {
if (opt_full && task.cmdline)
strncpy (cmdsearch, cmdline, CMDSTRSIZE);
if (opt_full && task_cmdline)
strncpy (cmdsearch, task_cmdline, CMDSTRSIZE);
else
strncpy (cmdsearch, task.cmd, CMDSTRSIZE);
strncpy (cmdsearch, PIDS_GETSTR(CMD), CMDSTRSIZE);
if (regexec (preg, cmdsearch, 0, NULL, 0) != 0)
match = 0;
@ -583,19 +587,19 @@ static struct el * select_procs (int *num)
if (match ^ opt_negate) { /* Exclusive OR is neat */
if (opt_newest) {
if (saved_start_time == task.start_time &&
saved_pid > task.XXXID)
if (saved_start_time == PIDS_GETULL(STARTTIME) &&
saved_pid > PIDS_GETINT(TGID))
continue;
saved_start_time = task.start_time;
saved_pid = task.XXXID;
saved_start_time = PIDS_GETULL(STARTTIME);
saved_pid = PIDS_GETINT(TGID);
matches = 0;
}
if (opt_oldest) {
if (saved_start_time == task.start_time &&
saved_pid < task.XXXID)
if (saved_start_time == PIDS_GETULL(STARTTIME) &&
saved_pid < PIDS_GETINT(TGID))
continue;
saved_start_time = task.start_time;
saved_pid = task.XXXID;
saved_start_time = PIDS_GETULL(STARTTIME);
saved_pid = PIDS_GETINT(TGID);
matches = 0;
}
if (matches == size) {
@ -603,14 +607,14 @@ static struct el * select_procs (int *num)
list = xrealloc(list, size * sizeof *list);
}
if (list && (opt_long || opt_longlong || opt_echo)) {
list[matches].num = task.XXXID;
list[matches].num = PIDS_GETINT(TGID);
list[matches++].str = xstrdup (cmdoutput);
} else if (list) {
list[matches++].num = task.XXXID;
list[matches++].num = PIDS_GETINT(TGID);
} else {
xerrx(EXIT_FAILURE, _("internal error"));
xerrx(EXIT_FATAL, _("internal error"));
}
#if 0
// pkill does not need subtasks!
// this control is still done at
// 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;
return list;
}
@ -673,6 +671,9 @@ static int signal_option(int *argc, char **argv)
}
}
return -1;
#undef PIDS_GETINT
#undef PIDS_GETULL
#undef PIDS_GETSTR
}
static void parse_opts (int argc, char **argv)