}
sprintf(filename, "/proc/%d/exe", pid);
- if ((exe = get_link_dest(filename)) == NULL) {
- free(cmdline);
- free(status);
- continue;
- }
+ exe = get_link_dest(filename);
+ /* This may fail, if the process isn't ours, but we continue
+ * anyway. */
/*
* Now we've got all our raw data out of /proc. Process it
return -1; /* no match */
}
+static int strnullcmp(const char *a, const char *b)
+{
+ /*
+ * Like strcmp, but cope with NULL inputs by making them compare
+ * identical to each other and before any non-null string.
+ */
+ if (!a || !b)
+ return (b != 0) - (a != 0);
+ else
+ return strcmp(a, b);
+}
+
static int argcmp(const char *const *a, const char *const *b)
{
while (*a && *b) {
return ret;
}
+static struct pidset filter_by_uid(struct pidset in, int uid)
+{
+ /*
+ * Return only those processes with a given uid.
+ */
+ struct pidset ret;
+ int pid;
+
+ pidset_init(&ret);
+ for (pid = pidset_first(&in); pid >= 0; pid = pidset_next(&in)) {
+ const struct procdata *proc = get_proc(pid);
+ if (proc->uid == uid)
+ pidset_add(&ret, pid);
+ }
+ return ret;
+}
+
static struct pidset filter_by_command(struct pidset in, const char **words)
{
/*
if (pidset_in(&in, proc->ppid)) {
/* The parent is in our set too. Is it similar? */
const struct procdata *parent = get_proc(proc->ppid);
- if (!strcmp(parent->exe, proc->exe) &&
+ if (!strnullcmp(parent->exe, proc->exe) &&
!argcmp(parent->argv, proc->argv)) {
/* Yes; don't list it. */
continue;
const char usagemsg[] =
"usage: pid [options] <search-cmd> [<search-arg>...]\n"
"where: -a report all matching pids, not just one\n"
+ " -U report pids of any user, not just ours\n"
" also: pid --version report version number\n"
" pid --help display this help text\n"
" pid --licence display the (MIT) licence text\n"
{
const char **searchwords;
int nsearchwords;
- int all = 0;
+ int all = 0, all_uids = 0;
int doing_opts = 1;
/*
if (doing_opts && *p == '-') {
if (!strcmp(p, "-a") || !strcmp(p, "--all")) {
all = 1;
+ } else if (!strcmp(p, "-U") || !strcmp(p, "--all-uids")) {
+ all_uids = 1;
} else if (!strcmp(p, "--version")) {
version();
return 0;
{
struct pidset procs;
- int pid, npids;
+ int uid, pid, npids;
/*
* Construct our list of processes.
*/
procs = get_processes();
+ uid = getuid();
+ if (uid > 0 && !all_uids)
+ procs = filter_by_uid(procs, uid);
procs = filter_out_self(procs);
procs = filter_by_command(procs, searchwords);
if (!all)