From 6c490ea6579a132fabb7dbd25387bb521f820371 Mon Sep 17 00:00:00 2001
From: Hongxu Jia <hongxu.jia@windriver.com>
Date: Wed, 24 Jul 2013 17:07:22 +0800
Subject: [PATCH] pidof: add -m option

When used with -o, will also omit any processes that have the same
argv[0] and argv[1] as any explicitly omitted process ids. This can be
used to avoid multiple shell scripts concurrently calling pidof returning
each other's pids.

https://bugzilla.redhat.com/show_bug.cgi?id=883856

Upstream-Status: backport
Imported patch from: https://bugzilla.redhat.com/attachment.cgi?id=658166

Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>

---
 man/pidof.8    |  6 +++++
 src/killall5.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/man/pidof.8 b/man/pidof.8
index ebe5f55..2fdc4d3 100644
--- a/man/pidof.8
+++ b/man/pidof.8
@@ -25,6 +25,7 @@ pidof -- find the process ID of a running program.
 .RB [ \-n ]
 .RB [ \-x ]
 .RB [ \-z ]
+.RB [ \-m ]
 .RB [ \-o
 .IR omitpid[,omitpid...] ]
 .RB [ \-o
@@ -76,6 +77,11 @@ is shown. The default separator is a space.
 Tells \fIpidof\fP to omit processes with that process id. The special
 pid \fB%PPID\fP can be used to name the parent process of the \fIpidof\fP
 program, in other words the calling shell or shell script.
+.IP -m
+When used with -o, will also omit any processes that have the same
+argv[0] and argv[1] as any explicitly omitted process ids. This can be
+used to avoid multiple shell scripts concurrently calling pidof returning
+each other's pids.
 .SH "EXIT STATUS"
 .TP
 .B 0
diff --git a/src/killall5.c b/src/killall5.c
index 8b5cb38..a664954 100644
--- a/src/killall5.c
+++ b/src/killall5.c
@@ -126,6 +126,7 @@
 
 /* List of processes. */
 PROC *plist;
+PROC *olist;
 
 /* List of processes to omit. */
 OMIT *omit;
@@ -357,6 +358,20 @@
 		}
 		if (p->shadow)
 			clear_shadow(p->shadow);
+		free(p);
+	}
+}
+
+static void clear_omit(void)
+{
+	OMIT *o;
+	PROC *p;
+	for (o = omit; o; o = omit) {
+		omit = omit->next;
+		free(o);
+	}
+	for (p = olist; p; p = olist) {
+		olist = olist->next;
 		free(p);
 	}
 }
@@ -486,6 +501,7 @@
 	DIR		*dir;
 	FILE		*fp;
 	PROC		*p, *n;
+	OMIT		*o, *m;
 	struct dirent	*d;
 	struct stat	st;
 	char		path[PATH_MAX+1];
@@ -726,6 +742,17 @@
 		p->next = plist;
 		plist = p;
 		p->pid = pid;
+		/* Could be smarter, but it's a small list. */
+		m = omit;
+		for (o = omit; m; o = m) {
+			m = o->next;
+			if (o->pid == p->pid) {
+				n = (PROC*)xmalloc(sizeof(PROC));
+				*n = *p;
+				n->next = olist;
+				olist = n;
+			}
+		}
 	}
 	closedir(dir);
 
@@ -937,6 +964,26 @@
 	return q;
 }
 
+int matches(PROC *o, PROC *p)
+{
+	int ret = 0;
+	char *oargv1, *pargv1;
+	if ((o->argv0 && p->argv0 && !strcmp(o->argv0,p->argv0))) {
+		if (o->argv1 && p->argv1) {
+			if ((oargv1 = canonicalize_file_name(o->argv1)) == NULL)
+				oargv1 = strdup(o->argv1);
+			if ((pargv1 = canonicalize_file_name(p->argv1)) == NULL)
+				pargv1 = strdup(p->argv1);
+			if (! strcmp(oargv1, pargv1)) {
+				ret = 1;
+			}
+			free(oargv1);
+			free(pargv1);
+		}
+	}
+	return ret;
+}
+
 /* Give usage message and exit. */
 void usage(void)
 {
@@ -987,6 +1034,7 @@
 #define PIDOF_OMIT	0x02
 #define PIDOF_NETFS	0x04
 #define PIDOF_QUIET     0x08
+#define PIDOF_OMIT_OMIT_MATCHES	0x08
 
 /*
  *	Pidof functionality.
@@ -1004,6 +1052,7 @@
 	char		tmp[512];
         char            sep = ' ';
 
+	olist = (PROC*)0;
 	omit = (OMIT*)0;
 	nlist = (NFS*)0;
 	opterr = 0;
@@ -1011,7 +1060,7 @@
 	if ((token = getenv("PIDOF_NETFS")) && (strcmp(token,"no") != 0))
 		flags |= PIDOF_NETFS;
 
-	while ((opt = getopt(argc,argv,"qhco:d:sxzn")) != EOF) switch (opt) {
+	while ((opt = getopt(argc,argv,"qhcmo:d:sxzn")) != EOF) switch (opt) {
 		case '?':
 			nsyslog(LOG_ERR,"invalid options on command line!\n");
 			closelog();
@@ -1062,6 +1111,9 @@
                 case 'z':
                         list_dz_processes = TRUE;
                         break;
+		case 'm':
+			flags |= PIDOF_OMIT_OMIT_MATCHES;
+			break;
 		case 'n':
 			flags |= PIDOF_NETFS;
 			break;
@@ -1093,10 +1145,13 @@
 			pid_t spid = 0;
 			while ((p = get_next_from_pid_q(q))) {
 				if ((flags & PIDOF_OMIT) && omit) {
-					OMIT * optr;
-					for (optr = omit; optr; optr = optr->next) {
+					PROC * optr;
+					for (optr = olist; optr; optr = optr->next) {
 						if (optr->pid == p->pid)
 							break;
+						if (flags & PIDOF_OMIT_OMIT_MATCHES)
+							if (matches(optr, p))
+								break;
 					}
 
 					/*
@@ -1138,6 +1193,7 @@
 		printf("\n");
         }
 
+	clear_omit();
 	clear_mnt();
 
 	closelog();