File sysvinit-2.86-nfs4pidof.patch of Package sysvinit

--- src/killall5.c
+++ src/killall5.c	2008-10-01 16:42:51.186708662 +0200
@@ -40,6 +40,8 @@
 #include <syslog.h>
 #include <getopt.h>
 #include <stdarg.h>
+#include <mntent.h>
+#include <sys/param.h>
 
 char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl";
 
@@ -56,7 +58,8 @@ typedef struct proc {
 	dev_t dev;		/* Device it is on		  */
 	pid_t pid;		/* Process ID.			  */
 	int sid;		/* Session ID.			  */
-	int kernel;		/* Kernel thread or zombie.	  */
+	char kernel;		/* Kernel thread or zombie.	  */
+	char nfs;		/* Binary is loacted on NFS part. */
 	struct proc *next;	/* Pointer to next struct. 	  */
 } PROC;
 
@@ -73,9 +76,20 @@ typedef struct {
 	PIDQ		*next;
 } PIDQ_HEAD;
 
+typedef struct nfs
+{
+	struct nfs *next;		/* Pointer to next struct. */
+	struct nfs *prev;		/* Pointer to previous st. */
+	char * name;
+	size_t nlen;
+} NFS;
+
 /* List of processes. */
 PROC *plist;
 
+/* List of NFS mountes partitions. */
+NFS *nlist;
+
 /* Did we stop all processes ? */
 int sent_sigstop;
 
@@ -152,6 +166,111 @@ int mount_proc(void)
 	return did_mount;
 }
 
+static inline int isnetfs(const char * type)
+{
+	static const char* netfs[] = {"nfs", "nfs4", "smbfs", "cifs", "afs", "ncpfs", (char*)0};
+	int n;
+	for (n = 0; netfs[n]; n++)
+		if (!strcasecmp(netfs[n], type))
+			return 1;
+	return 0;
+}
+
+/*
+ *	Remember all NFS typed partitions.
+ */
+void init_nfs(void)
+{
+	struct stat st;
+	struct mntent * ent;
+	FILE * mnt;
+
+	nlist = (NFS*)0;
+
+	if (stat("/proc/version", &st) < 0)
+		return;
+	if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0)
+		return;
+
+	while ((ent = getmntent(mnt))) {
+		if (isnetfs(ent->mnt_type)) {
+			NFS * p = (NFS*)xmalloc(sizeof(NFS));
+			p->name = (char*)xmalloc(strlen(ent->mnt_dir)+1);
+			strcpy(p->name, ent->mnt_dir);
+			p->nlen = strlen(p->name);
+			if (nlist)
+				nlist->prev = p;
+			p->next = nlist;
+			p->prev = (NFS*)0;
+			nlist = p;
+		}
+	}
+
+	endmntent(mnt);
+}
+
+/*
+ *	Check path is located on a NFS partition.
+ */
+int check4nfs(const char * path, char * real)
+{
+	char buf[PATH_MAX+1];
+	const char *curr;
+	int deep = MAXSYMLINKS;
+
+	if (!nlist) return 0;
+
+	curr = path;
+	do {
+		const char *prev;
+		int len;
+
+		if ((prev = strdupa(curr)) == NULL) {
+			nsyslog(LOG_ERR, "strdupa(): %s\n", strerror(errno));
+			return 0;
+		}
+
+		errno = 0;
+		if ((len = readlink(curr, buf, PATH_MAX)) < 0)
+			break;
+		buf[len] = '\0';
+
+		if (buf[0] != '/') {
+			const char *slash;
+
+			if ((slash = strrchr(prev, '/'))) {
+				size_t off = slash - prev + 1;
+
+				if (off + len > PATH_MAX)
+					len = PATH_MAX - off;
+
+				memmove(&buf[off], &buf[0], len + 1);
+				memcpy(&buf[0], prev, off);
+			}
+		}
+		curr = &buf[0];
+
+		if (deep-- <= 0) return 0;
+
+	} while (1);
+
+	if (real) strcpy(real, curr);
+
+	if (errno == EINVAL) {
+		NFS *p, *n, *l;
+		n = nlist;
+		l = (NFS*)0;
+		for (p = nlist; n; p = n) {
+			l = p->prev;
+			n = p->next;
+			if (!strncmp(curr, p->name, p->nlen))
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
 int readarg(FILE *fp, char *buf, int sz)
 {
 	int		c = 0, f = 0;
@@ -173,8 +292,8 @@ int readproc()
 	PROC		*p, *n;
 	struct dirent	*d;
 	struct stat	st;
-	char		path[256];
-	char		buf[256];
+	char		path[PATH_MAX+1];
+	char		buf[PATH_MAX+1];
 	char		*s, *q;
 	unsigned long	startcode, endcode;
 	int		pid, f;
@@ -191,6 +310,7 @@ int readproc()
 		n = p->next;
 		if (p->argv0) free(p->argv0);
 		if (p->argv1) free(p->argv1);
+		if (p->statname) free(p->statname);
 		free(p);
 	}
 	plist = NULL;
@@ -225,6 +345,9 @@ int readproc()
 					nsyslog(LOG_ERR,
 					"can't get program name from %s\n",
 						path);
+					if (p->argv0) free(p->argv0);
+					if (p->argv1) free(p->argv1);
+					if (p->statname) free(p->statname);
 					free(p);
 					continue;
 				}
@@ -248,6 +371,9 @@ int readproc()
 				p->sid = 0;
 				nsyslog(LOG_ERR, "can't read sid from %s\n",
 					path);
+				if (p->argv0) free(p->argv0);
+				if (p->argv1) free(p->argv1);
+				if (p->statname) free(p->statname);
 				free(p);
 				continue;
 			}
@@ -256,6 +382,9 @@ int readproc()
 			fclose(fp);
 		} else {
 			/* Process disappeared.. */
+			if (p->argv0) free(p->argv0);
+			if (p->argv1) free(p->argv1);
+			if (p->statname) free(p->statname);
 			free(p);
 			continue;
 		}
@@ -300,13 +429,18 @@ int readproc()
 
 		} else {
 			/* Process disappeared.. */
+			if (p->argv0) free(p->argv0);
+			if (p->argv1) free(p->argv1);
+			if (p->statname) free(p->statname);
 			free(p);
 			continue;
 		}
 
 		/* Try to stat the executable. */
 		snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name);
-		if (stat(path, &st) == 0) {
+		if (check4nfs(path, NULL))
+			p->nfs = 1;
+		if ((p->nfs == 0) && (stat(path, &st) == 0)) {
 			p->dev = st.st_dev;
 			p->ino = st.st_ino;
 		}
@@ -374,12 +508,25 @@ PIDQ_HEAD *pidof(char *prog)
 	PIDQ_HEAD	*q;
 	struct stat	st;
 	char		*s;
+	int		nfs = 0;
 	int		dostat = 0;
 	int		foundone = 0;
 	int		ok = 0;
+	char		real[PATH_MAX+1];
 
 	/* Try to stat the executable. */
-	if (prog[0] == '/' && stat(prog, &st) == 0) dostat++;
+	if (prog[0] == '/') {
+		memset(&real[0], 0, sizeof(real));
+
+		if (check4nfs(prog, real))
+			nfs++;			/* Binary located on NFS partition. */
+
+		if (real[0] != '\0')
+			prog = &real[0];	/* Binary or its symlink located on NFS. */
+
+		if ((nfs == 0) && (stat(prog, &st) == 0))
+			dostat++;		/* Binary located on a local file system. */
+	}
 
 	/* Get basename of program. */
 	if ((s = strrchr(prog, '/')) == NULL)
@@ -393,10 +540,30 @@ PIDQ_HEAD *pidof(char *prog)
 	/* First try to find a match based on dev/ino pair. */
 	if (dostat) {
 		for (p = plist; p; p = p->next) {
-			if (p->dev == st.st_dev && p->ino == st.st_ino) {
-				add_pid_to_q(q, p);
-				foundone++;
-			}
+			if (p->nfs)
+				continue;
+			if (p->dev != st.st_dev || p->ino != st.st_ino)
+				continue;
+			add_pid_to_q(q, p);
+			foundone++;
+		}
+	}
+
+	/* Second try to find a match based on full path name on NFS located binaries */
+	if (!foundone && nfs) {
+		for (p = plist; p; p = p->next) {
+			char exe [PATH_MAX+1];
+			char path[PATH_MAX+1];
+			int len;
+
+			snprintf(exe, sizeof(exe), "/proc/%d/exe", p->pid);
+			if ((len = readlink(exe, path, PATH_MAX)) < 0)
+				continue;
+			path[len] = '\0';
+			if (strcmp(prog, path) != 0)
+				continue;
+			add_pid_to_q(q, p);
+			foundone++;
 		}
 	}
 
@@ -428,7 +595,7 @@ PIDQ_HEAD *pidof(char *prog)
 		if (ok) add_pid_to_q(q, p);
 	}
 
-	 return q;
+	return q;
 }
 
 /* Give usage message and exit. */
@@ -477,6 +644,9 @@ int main_pidof(int argc, char **argv)
 	int		first = 1;
 	int		i, oind, opt, flags = 0;
 
+	/* Which NFS partitions are online? */
+	init_nfs();
+
 	for (oind = PIDOF_OMITSZ-1; oind > 0; oind--)
 		opid[oind] = 0;
 	opterr = 0;
@@ -561,6 +731,7 @@ int main(int argc, char **argv)
 	PROC		*p;
 	int		pid, sid = -1;
 	int		sig = SIGKILL;
+	int		did_mount;
 
 	/* Get program name. */
 	if ((progname = strrchr(argv[0], '/')) == NULL)
@@ -583,7 +754,10 @@ int main(int argc, char **argv)
 	}
 
 	/* First get the /proc filesystem online. */
-	mount_proc();
+	did_mount = mount_proc();
+
+	/* Which NFS partitions are online? */
+	init_nfs();
 
 	/*
 	 *	Ignoring SIGKILL and SIGSTOP do not make sense, but
@@ -608,9 +782,13 @@ int main(int argc, char **argv)
 	/* Now kill all processes except our session. */
 	sid = (int)getsid(0);
 	pid = (int)getpid();
-	for (p = plist; p; p = p->next)
-		if (p->pid != pid && p->sid != sid && !p->kernel)
-			kill(p->pid, sig);
+	for (p = plist; p; p = p->next) {
+		if (p->pid == 1 || p->pid == pid || p->sid == sid || p->kernel) {
+			kill(p->pid, SIGCONT);
+			continue;
+		}
+		kill(p->pid, sig);
+	}
 
 	/* And let them continue. */
 	kill(-1, SIGCONT);
openSUSE Build Service is sponsored by