From fb9d74c1950c687ac7748f7c3fcec3ccdaee5a70 Mon Sep 17 00:00:00 2001
From: OBS User unknown <null@suse.de>
Date: Fri, 8 Aug 2008 00:14:10 +0000
Subject: [PATCH] OBS-URL:
 https://build.opensuse.org/package/show/openSUSE:Factory/psmisc?expand=0&rev=8

---
 psmisc-22.6-nfs4fuser.patch | 216 ++++++++++++++++++------------------
 psmisc-22.6-writeonly.patch | 148 ++++++++++++++++++++++++
 psmisc.changes              |   6 +
 psmisc.spec                 |  18 ++-
 4 files changed, 278 insertions(+), 110 deletions(-)
 create mode 100644 psmisc-22.6-writeonly.patch

diff --git a/psmisc-22.6-nfs4fuser.patch b/psmisc-22.6-nfs4fuser.patch
index 23bc269..1fbe482 100644
--- a/psmisc-22.6-nfs4fuser.patch
+++ b/psmisc-22.6-nfs4fuser.patch
@@ -1,5 +1,5 @@
 --- doc/fuser.1
-+++ doc/fuser.1	2008-05-16 15:18:59.027600905 +0200
++++ doc/fuser.1	2008-05-16 15:18:59.000000000 +0200
 @@ -80,8 +80,14 @@ List all known signal names.
  \fIname\fP specifies a file on a mounted file system or a block device that
  is mounted. All processes accessing files on that file system are listed.
@@ -33,7 +33,7 @@
  cannot report on any processes that it doesn't have permission to look at
  the file descriptor table for.  The most common time this problem occurs
 --- src/fuser.c
-+++ src/fuser.c	2007-12-19 18:45:34.954694000 +0100
++++ src/fuser.c	2008-08-07 14:47:58.126764924 +0200
 @@ -32,6 +32,7 @@
  #include <stdlib.h>
  #include <string.h>
@@ -51,34 +51,41 @@
  static uid_t getpiduid(const pid_t pid);
  static int print_matches(struct names *names_head, const opt_type opts, const int sig_number);
  static void kill_matched_proc(struct procs *pptr, const opt_type opts, const int sig_number);
-@@ -72,13 +73,16 @@ static void add_device(struct device_lis
+@@ -72,13 +73,15 @@ static void add_device(struct device_lis
  void scan_mount_devices(const opt_type opts, struct mountdev_list **mount_devices);
  void fill_unix_cache(struct unixsocket_list **unixsocket_head);
  static dev_t find_net_dev(void);
 -static void scan_procs(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head);
-+static void scan_procs(const opt_type opts, struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head);
++static void scan_procs(const opt_type opts, struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct mountdev_list *mounts);
  #ifdef NFS_CHECKS
  static void scan_knfsd(struct names *names_head, struct device_list *dev_head);
  #endif /* NFS_CHECKS */
  #ifdef DEBUG
- static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head);
+-static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head);
++static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct mountdev_list *mounts);
  #endif
 +static struct nfs_points *mnts;
-+static void init_nfs(void);
 +static int check4nfs(const char * path, char * real);
  
  static void usage (const char *errormsg)
  {
-@@ -127,7 +131,7 @@ void print_version()
+@@ -127,7 +130,14 @@ void print_version()
      "For more information about these matters, see the files named COPYING.\n"));
  }
  
 -static void scan_procs(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head)
-+static void scan_procs(const opt_type opts, struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head)
++static int islocatedon(const char * path, const char * loc)
++{
++	if (!path || *path == '\0')
++		return 0;
++	return (strstr(path, loc) == path);
++}
++
++static void scan_procs(const opt_type opts, struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct mountdev_list *mounts)
  {
  	DIR *topproc_dir;
  	struct dirent *topproc_dent;
-@@ -137,6 +141,9 @@ static void scan_procs(struct names *nam
+@@ -137,6 +147,9 @@ static void scan_procs(struct names *nam
  	pid_t pid, my_pid;
  	uid_t uid;
  	struct stat *cwd_stat, *exe_stat, *root_stat;
@@ -88,7 +95,7 @@
  
  	if ( (fd_dirpath = malloc(MAX_PATHNAME)) == NULL)
  		return;
-@@ -157,19 +164,30 @@ static void scan_procs(struct names *nam
+@@ -157,9 +170,10 @@ static void scan_procs(struct names *nam
  			continue;
  		uid = getpiduid(pid);
  
@@ -101,50 +108,43 @@
 +		exe_stat  = get_pidstat(opts, pid,  "exe",  exe_real);
  		/* Scan the devices */
  		for (dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) {
-+			const char* filename = dev_tmp->name->filename;
-+			size_t len = strlen(filename);
  			if (exe_stat != NULL && exe_stat->st_dev == dev_tmp->device) 
- 				add_matched_proc(dev_tmp->name, pid, uid, ACCESS_EXE);
- 			if (root_stat != NULL && root_stat->st_dev == dev_tmp->device) 
+@@ -168,6 +182,14 @@ static void scan_procs(struct names *nam
  				add_matched_proc(dev_tmp->name, pid, uid, ACCESS_ROOT);
  			if (cwd_stat != NULL && cwd_stat->st_dev == dev_tmp->device) 
  				add_matched_proc(dev_tmp->name, pid, uid, ACCESS_CWD);
-+			if (exe_real[0] != '\0' && !strncmp(&exe_real[0],   filename, len))
++			if ((dev_tmp->name->name_space & NAMESPACE_NFS) == 0)
++				continue;
++			if (islocatedon(&exe_real[0],  dev_tmp->name->filename))
 +				add_matched_proc(dev_tmp->name, pid, uid, ACCESS_EXE);
-+			if (root_real[0] != '\0' && !strncmp(&root_real[0], filename, len))
++			if (islocatedon(&root_real[0], dev_tmp->name->filename))
 +				add_matched_proc(dev_tmp->name, pid, uid, ACCESS_ROOT);
-+			if (cwd_real[0] != '\0' && !strncmp(&cwd_real[0],   filename, len))
++			if (islocatedon(&cwd_real[0],  dev_tmp->name->filename))
 +				add_matched_proc(dev_tmp->name, pid, uid, ACCESS_CWD);
  		}
  		for (ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) {
-+			const char* filename = ino_tmp->name->filename;
-+			size_t len = strlen(filename);
  			if (exe_stat != NULL) {
- 				if (exe_stat->st_dev == ino_tmp->device && exe_stat->st_ino == ino_tmp->inode) {
- 					add_matched_proc(ino_tmp->name, pid, uid, ACCESS_EXE);
-@@ -186,6 +204,21 @@ static void scan_procs(struct names *nam
+@@ -186,9 +208,19 @@ static void scan_procs(struct names *nam
  					add_matched_proc(ino_tmp->name, pid, uid, ACCESS_CWD);
  				}
  			}
-+			if (exe_real[0] != '\0') {
-+				if (!strncmp(&exe_real[0],  filename, len)) {
-+					add_matched_proc(ino_tmp->name, pid, uid, ACCESS_EXE);
-+				}
-+			}
-+			if (root_real[0] != '\0') {
-+				if (!strncmp(&root_real[0],  filename, len)) {
-+					add_matched_proc(ino_tmp->name, pid, uid, ACCESS_ROOT);
-+				}
-+			}
-+			if (cwd_real[0] != '\0') {
-+				if (!strncmp(&cwd_real[0],  filename, len)) {
-+					add_matched_proc(ino_tmp->name, pid, uid, ACCESS_CWD);
-+				}
-+			}
++			if ((ino_tmp->name->name_space & NAMESPACE_NFS) == 0)
++				continue;
++			if (islocatedon(&exe_real[0],  ino_tmp->name->filename))
++				add_matched_proc(ino_tmp->name, pid, uid, ACCESS_EXE);
++			if (islocatedon(&root_real[0], ino_tmp->name->filename))
++				add_matched_proc(ino_tmp->name, pid, uid, ACCESS_ROOT);
++			if (islocatedon(&cwd_real[0],  ino_tmp->name->filename))
++				add_matched_proc(ino_tmp->name, pid, uid, ACCESS_CWD);
  		}
++#ifndef __linux__
  		check_dir(pid, "lib", dev_head, ino_head, uid, ACCESS_MMAP);
  		check_dir(pid, "mmap", dev_head, ino_head, uid, ACCESS_MMAP);
-@@ -325,10 +358,26 @@ int parse_mount(struct names *this_name,
++#endif
+ 		check_dir(pid, "fd", dev_head, ino_head, uid, ACCESS_FILE);
+ 		check_map(pid, "maps", dev_head, ino_head, uid, ACCESS_MMAP);
+ 
+@@ -325,10 +357,26 @@ int parse_mount(struct names *this_name,
  	return 0;
  }
  
@@ -172,7 +172,7 @@
  	if (stat(this_name->filename, &st) != 0) {
  		fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename,
  				strerror(errno));
-@@ -342,34 +391,44 @@ int parse_file(struct names *this_name, 
+@@ -342,34 +390,44 @@ int parse_file(struct names *this_name, 
  	return 0;
  }
  
@@ -224,7 +224,7 @@
  
  	if (stat(this_name->filename, &st) != 0) {
  		fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename,
-@@ -388,6 +447,16 @@ int parse_mounts(struct names *this_name
+@@ -388,6 +446,16 @@ int parse_mounts(struct names *this_name
  		}
  	}
  	return 0;
@@ -232,8 +232,8 @@
 +	match_device = -1;
 +	for (mountptr = mounts ; mountptr != NULL ; mountptr = mountptr->next) {
 +		if (strcmp(mountptr->dir, real) == 0) {
-+			printf("Debug: adding parse_mounts() adding %s\n", 
-+					this_name->filename);
++			/*printf("Debug: adding parse_mounts() adding %s\n", 
++					this_name->filename);*/
 +			add_device(dev_list, this_name, match_device);
 +		}
 +	}
@@ -241,47 +241,10 @@
  }
  
  #ifdef WITH_IPV6
-@@ -652,6 +721,117 @@ void find_net6_sockets(struct inode_list
+@@ -652,6 +720,80 @@ void find_net6_sockets(struct inode_list
  }
  #endif
  
-+/*
-+ *     Remember all NFS typed partitions.
-+ */
-+static void init_nfs(void)
-+{
-+	struct stat st;
-+	struct mntent * ent;
-+	FILE * mnt;
-+
-+	mnts = (struct nfs_points*)0;
-+
-+	if (stat("/proc/version", &st) < 0)
-+		return;
-+	if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0)
-+		return;
-+
-+	while ((ent = getmntent(mnt))) {
-+		if (!strcasecmp(MNTTYPE_NFS, ent->mnt_type)) {
-+			struct nfs_points * p = (struct nfs_points*)malloc(sizeof(struct nfs_points));
-+			if (!p)
-+				goto out;
-+			p->name = (char*)malloc(strlen(ent->mnt_dir)+1);
-+			if (!p->name)
-+				goto out;
-+			strcpy(p->name, ent->mnt_dir);
-+			p->nlen = strlen(p->name);
-+			if (mnts)
-+				mnts->prev = p;
-+			p->next = mnts;
-+			p->prev = (struct nfs_points*)0;
-+			mnts = p;
-+		}
-+	}
-+out:
-+	endmntent(mnt);
-+}
-+
 +/*
 + *     Check path is located on a NFS partition.
 + */
@@ -359,7 +322,7 @@
  int main(int argc, char *argv[])
  {
  	opt_type opts; 
-@@ -664,7 +844,7 @@ int main(int argc, char *argv[])
+@@ -664,7 +806,7 @@ int main(int argc, char *argv[])
  	struct device_list *match_devices = NULL;
  	struct unixsocket_list *unixsockets = NULL;
  
@@ -368,7 +331,7 @@
  	struct ip_connections *tcp_connection_list = NULL;
  	struct ip_connections *udp_connection_list = NULL;
  #ifdef WITH_IPV6
-@@ -691,10 +871,6 @@ int main(int argc, char *argv[])
+@@ -691,10 +833,6 @@ int main(int argc, char *argv[])
  	textdomain(PACKAGE);
  #endif
  
@@ -379,19 +342,18 @@
  	/* getopt doesnt like things like -SIGBLAH */
  	for(optc = 1; optc < argc; optc++) {
  		if (argv[optc][0] == '-') { /* its an option */
-@@ -782,6 +958,11 @@ int main(int argc, char *argv[])
+@@ -782,6 +920,10 @@ int main(int argc, char *argv[])
  			}
  			continue;
  		}
 +
-+		init_nfs();
 +		scan_mount_devices(opts, &mount_devices);
 +		fill_unix_cache(&unixsockets);
 +
  		/* File specifications */
  		if ( (this_name = malloc(sizeof(struct names))) == NULL)
  			continue;
-@@ -828,8 +1009,8 @@ int main(int argc, char *argv[])
+@@ -828,8 +970,8 @@ int main(int argc, char *argv[])
  				break;
  			default: /* FILE */
  				this_name->filename = strdup(argv[optc]);
@@ -402,7 +364,7 @@
  				if (opts & OPT_MOUNTPOINT || opts & OPT_MOUNTS)
  					parse_mounts(this_name, mount_devices, &match_devices, opts);
  				break;
-@@ -857,22 +1038,22 @@ int main(int argc, char *argv[])
+@@ -857,22 +999,22 @@ int main(int argc, char *argv[])
  	if (!ipv4_only) {
  #endif
  		if (tcp_connection_list != NULL)
@@ -423,14 +385,15 @@
  	}
  #endif
  #ifdef DEBUG
- 	debug_match_lists(names_head, match_inodes, match_devices);
+-	debug_match_lists(names_head, match_inodes, match_devices);
++	debug_match_lists(names_head, match_inodes, match_devices, mount_devices);
  #endif
 -	scan_procs(names_head, match_inodes, match_devices);
-+	scan_procs(opts, names_head, match_inodes, match_devices);
++	scan_procs(opts, names_head, match_inodes, match_devices, mount_devices);
  #ifdef NFS_CHECKS
      scan_knfsd(names_head, match_devices);
  #endif /* NFS_CHECKS */
-@@ -978,7 +1159,7 @@ static int print_matches(struct names *n
+@@ -978,7 +1120,7 @@ static int print_matches(struct names *n
  
  }
  
@@ -439,7 +402,7 @@
  {
  	char pathname[256];
  	struct stat *st;
-@@ -986,6 +1167,10 @@ static struct stat *get_pidstat(const pi
+@@ -986,6 +1128,10 @@ static struct stat *get_pidstat(const pi
  	if ( (st = malloc(sizeof(struct stat))) == NULL)
  		return NULL;
  	snprintf(pathname, 256, "/proc/%d/%s", pid, filename);
@@ -450,7 +413,14 @@
  	if (stat(pathname, st) != 0) 
  		return NULL;
  	else
-@@ -1019,6 +1204,8 @@ static void check_dir(const pid_t pid, c
+@@ -1012,13 +1158,14 @@ static void check_dir(const pid_t pid, c
+ 	while ( (direntry = readdir(dirp)) != NULL) {
+ 		if (direntry->d_name[0] < '0' || direntry->d_name[0] > '9')
+ 			continue;
+-
+ 		snprintf(filepath, MAX_PATHNAME, "/proc/%d/%s/%s",
+ 			pid, dirname, direntry->d_name);
+ 		if (stat(filepath, &st) != 0) {
  			fprintf(stderr, _("Cannot stat file %s: %s\n"),filepath, strerror(errno));
  		} else {
  			for (dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) {
@@ -459,7 +429,7 @@
  				if (st.st_dev == dev_tmp->device) {
  					if (access == ACCESS_FILE && (lstat(filepath, &lst)==0) && (lst.st_mode & S_IWUSR)) {
  						add_matched_proc(dev_tmp->name, pid,uid, ACCESS_FILEWR|access);
-@@ -1028,6 +1215,8 @@ static void check_dir(const pid_t pid, c
+@@ -1028,6 +1175,8 @@ static void check_dir(const pid_t pid, c
  				}
  			}
  			for (ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) {
@@ -468,7 +438,16 @@
  				if (st.st_dev == ino_tmp->device && st.st_ino == ino_tmp->inode) {
  					if (access == ACCESS_FILE && (lstat(filepath, &lst)==0) && (lst.st_mode & S_IWUSR)) {
  						add_matched_proc(ino_tmp->name, pid,uid, ACCESS_FILEWR|access);
-@@ -1059,12 +1248,18 @@ static void check_map(const pid_t pid, c
+@@ -1039,6 +1188,8 @@ static void check_dir(const pid_t pid, c
+ 		}
+ 	} /* while fd_dent */
+ 	closedir(dirp);
++	free(dirpath);
++	free(filepath);
+ }
+ 
+ static void check_map(const pid_t pid, const char *filename, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access)
+@@ -1059,12 +1210,18 @@ static void check_map(const pid_t pid, c
  		if (sscanf(line, "%*s %*s %*s %x:%x %lld", 
  					&tmp_maj, &tmp_min, &tmp_inode) == 3) {
  			tmp_device = tmp_maj * 256 + tmp_min;
@@ -489,39 +468,62 @@
  		}
  	}
  	fclose(fp);
-@@ -1144,6 +1339,7 @@ void scan_mount_devices(const opt_type o
+@@ -1144,22 +1301,48 @@ void scan_mount_devices(const opt_type o
  	FILE *mntfp;
  	struct mntent *mnt_ptr;
  	struct stat st;
-+	char real[PATH_MAX+1] = "";
- 	
- 	if ( (mntfp = setmntent("/etc/mtab","r")) == NULL) {
- 		fprintf(stderr, _("Cannot open /etc/mtab: %s\n"),
-@@ -1151,10 +1347,22 @@ void scan_mount_devices(const opt_type o
+-	
+-	if ( (mntfp = setmntent("/etc/mtab","r")) == NULL) {
+-		fprintf(stderr, _("Cannot open /etc/mtab: %s\n"),
+-				strerror(errno));
++
++	if (stat("/proc/version", &st) < 0)
++		mntfp = setmntent("/etc/mtab","r");
++	else
++		mntfp = setmntent("/proc/mounts", "r");
++	if (mntfp == NULL) {
++		fprintf(stderr, _("Cannot open /etc/mtab: %s\n"), strerror(errno));
  		return;
  	}
  	while ( (mnt_ptr = getmntent(mntfp)) != NULL) {
-+		real[0] = '\0';
-+		if (check4nfs(mnt_ptr->mnt_dir, real)) {
++		if (!strcasecmp(MNTTYPE_NFS, mnt_ptr->mnt_type)) {
++			/*
++			 *     Remember all NFS typed partitions.
++			 */
++			struct nfs_points * p = (struct nfs_points*)malloc(sizeof(struct nfs_points));
++			if (!p)
++				goto out;
++			p->name = strdup(mnt_ptr->mnt_dir);
++			if (!p->name)
++				goto out;
++			p->nlen = strlen(p->name);
++			if (mnts)
++				mnts->prev = p;
++			p->next = mnts;
++			p->prev = (struct nfs_points*)0;
++			mnts = p;
 +			if ((opts & (OPT_MOUNTPOINT|OPT_MOUNTS)) == 0) {
-+				add_mount_device(mount_devices, mnt_ptr->mnt_fsname, real, (dev_t)-1);
++				add_mount_device(mount_devices, mnt_ptr->mnt_fsname, mnt_ptr->mnt_dir, (dev_t)-1);
 +				continue;
 +			}
-+		}
-+		if ((real[0] != '\0') && (stat(real, &st) == 0)) {
-+			add_mount_device(mount_devices, mnt_ptr->mnt_fsname, real, st.st_dev);
-+			continue;
 +		}
  		if (stat(mnt_ptr->mnt_dir, &st) == 0) {
  			add_mount_device(mount_devices, mnt_ptr->mnt_fsname, mnt_ptr->mnt_dir, st.st_dev);
  		}
  	}
++out:
 +	endmntent(mntfp);
  }
  
  #ifdef DEBUG
+ /* often not used, doesnt need translation */
+-static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head)
++static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, )
+ {
+ 	struct names *nptr;
+ 	struct inode_list *iptr;
 --- src/fuser.h
-+++ src/fuser.h	2007-12-19 18:50:05.501016000 +0100
++++ src/fuser.h	2008-08-07 14:26:47.587191317 +0200
 @@ -80,9 +80,16 @@ struct unixsocket_list {
  	struct unixsocket_list *next;
  };
diff --git a/psmisc-22.6-writeonly.patch b/psmisc-22.6-writeonly.patch
new file mode 100644
index 0000000..7a46bd3
--- /dev/null
+++ b/psmisc-22.6-writeonly.patch
@@ -0,0 +1,148 @@
+--- doc/fuser.1
++++ doc/fuser.1	2008-08-07 14:51:18.000000000 +0200
+@@ -10,6 +10,7 @@ fuser \- identify processes using files 
+ .IR space\  ]
+ .RB [ \-k
+ .RB [ \-i ]
++.RB [ \-w ]
+ .RB [ \- \fIsignal
+ ] ]
+ .RB [ \-muvf ]
+@@ -74,6 +75,9 @@ other \fBfuser\fP processes. The effecti
+ .IP \fB\-i\fP
+ Ask the user for confirmation before killing a process. This option is
+ silently ignored if \fB\-k\fP is not present too.
++.IP \fB\-w\fP
++Kill only processes which have write access. This option is
++silently ignored if \fB\-k\fP is not present too.
+ .IP \fB\-l\fP
+ List all known signal names.
+ .IP \fB\-m\fP
+--- src/fuser.c
++++ src/fuser.c	2008-08-07 15:49:28.714368021 +0200
+@@ -66,7 +66,7 @@ static void check_map(const pid_t pid, c
+ static struct stat *get_pidstat(const opt_type opts, const pid_t pid, const char *filename, char *real);
+ static uid_t getpiduid(const pid_t pid);
+ static int print_matches(struct names *names_head, const opt_type opts, const int sig_number);
+-static void kill_matched_proc(struct procs *pptr, const opt_type opts, const int sig_number);
++static int kill_matched_proc(struct procs *pptr, const opt_type opts, const int sig_number);
+ 
+ int parse_mount(struct names *this_name, struct device_list **dev_list);
+ static void add_device(struct device_list **dev_list, struct names  *this_name, dev_t device);
+@@ -89,7 +89,7 @@ static void usage (const char *errormsg)
+ 		fprintf(stderr, "%s\n", errormsg);
+ 
+   fprintf (stderr, _(
+-    "Usage: fuser [ -a | -s | -c ] [ -n SPACE ] [ -SIGNAL ] [ -kimuv ] NAME...\n"
++    "Usage: fuser [ -a | -s | -c ] [ -n SPACE ] [ -SIGNAL ] [ -kimuvw ] NAME...\n"
+     "             [ - ] [ -n SPACE ] [ -SIGNAL ] [ -kimuv ] NAME...\n"
+     "       fuser -l\n"
+     "       fuser -V\n"
+@@ -106,6 +106,7 @@ static void usage (const char *errormsg)
+     "    -SIGNAL   send this signal instead of SIGKILL\n"
+     "    -u        display user IDs\n"
+     "    -v        verbose output\n"
++    "    -w        kill only processes with write access\n"
+     "    -V        display version information\n"));
+ #ifdef WITH_IPV6
+   fprintf (stderr, _(
+@@ -901,6 +902,9 @@ int main(int argc, char *argv[])
+ 				case 'v':
+ 					opts |= OPT_VERBOSE;
+ 					break;
++				case 'w':
++					opts |= OPT_WRITE;
++					break;
+ 				case 'V':
+ 					print_version();
+ 					return 0;
+@@ -1033,6 +1037,7 @@ static int print_matches(struct names *n
+ 	int len = 0;
+ 	struct passwd *pwent = NULL;
+ 	int have_match = 0;
++	int have_kill = 0;
+ 	
+     	for (nptr = names_head; nptr != NULL ; nptr = nptr->next) {
+ 		if (opts & OPT_SILENT) {
+@@ -1103,21 +1108,23 @@ static int print_matches(struct names *n
+     				len = 0;
+     				first = 0;
+     			}
+-                if (opts & OPT_VERBOSE) {
+-                  /* put a newline if showing all files and no procs*/
+-                  if (nptr->matched_procs == NULL && (opts & OPT_ALLFILES))
+-                    putc('\n', stderr);
+-                } else {
+-    			  if (nptr->matched_procs != NULL || (opts & OPT_ALLFILES))
+-    				putc('\n', stderr);
+-                }
++                	if (opts & OPT_VERBOSE) {
++				/* put a newline if showing all files and no procs*/
++				if (nptr->matched_procs == NULL && (opts & OPT_ALLFILES))
++					putc('\n', stderr);
++			} else {
++				if (nptr->matched_procs != NULL || (opts & OPT_ALLFILES))
++					putc('\n', stderr);
++			}
+ 		} /* be silent */
+ 		if (opts & OPT_KILL)
+-			kill_matched_proc(nptr->matched_procs,  opts, sig_number);
++			have_kill = kill_matched_proc(nptr->matched_procs,  opts, sig_number);
+ 
+ 	} /* next name */
+-	return (have_match==1?0:1);
+-
++	if (opts & OPT_KILL)
++		return (have_kill==1?0:1);
++	else
++		return (have_match==1?0:1);
+ }
+ 
+ static struct stat *get_pidstat(const opt_type opts, const pid_t pid, const char *filename, char *real)
+@@ -1403,21 +1410,26 @@ static int ask(const pid_t pid)
+ 	} /* while */
+ }
+ 
+-static void kill_matched_proc(struct procs *proc_head, const opt_type opts, const int sig_number)
++static int kill_matched_proc(struct procs *proc_head, const opt_type opts, const int sig_number)
+ {
+ 	struct procs *pptr;
++	int ret = 0;
+ 
+ 	for (pptr = proc_head ; pptr != NULL ; pptr = pptr->next ) {
+ 		if ( (opts & OPT_INTERACTIVE) && (ask(pptr->pid) == 0))
+ 			continue;
++		if ((opts & OPT_WRITE) && ((pptr->access & ACCESS_FILEWR) == 0))
++			continue;
+ 		if ( kill (pptr->pid, sig_number) < 0) {
+ 			fprintf(stderr, _("Could not kill process %d: %s\n"),
+ 					pptr->pid,
+ 					strerror(errno)
+ 				);
++			continue;
+ 		}
+-					
++		ret = 1;
+ 	}
++	return ret;
+ }
+ 
+ static dev_t find_net_dev(void)
+--- src/fuser.h
++++ src/fuser.h	2008-08-07 14:26:48.000000000 +0200
+@@ -1,6 +1,6 @@
+ 
+ /* Option Flags */
+-typedef unsigned char opt_type;
++typedef unsigned short opt_type;
+ 
+ #define OPT_VERBOSE 1
+ #define OPT_ALLFILES 2
+@@ -10,6 +10,7 @@ typedef unsigned char opt_type;
+ #define OPT_SILENT 32
+ #define OPT_USER 64
+ #define OPT_MOUNTPOINT 128
++#define OPT_WRITE 256
+ 
+ 
+ struct procs {
diff --git a/psmisc.changes b/psmisc.changes
index ca6dc16..6ee5f73 100644
--- a/psmisc.changes
+++ b/psmisc.changes
@@ -1,3 +1,9 @@
+-------------------------------------------------------------------
+Thu Aug  7 15:12:14 CEST 2008 - werner@suse.de
+
+- Refine NFS patch
+- Add option -w for killing only procs with write access
+
 -------------------------------------------------------------------
 Fri May 16 17:19:31 CEST 2008 - werner@suse.de
 
diff --git a/psmisc.spec b/psmisc.spec
index d4f2ac5..dd0416f 100644
--- a/psmisc.spec
+++ b/psmisc.spec
@@ -2,9 +2,16 @@
 # spec file for package psmisc (Version 22.6)
 #
 # Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany.
-# This file and all modifications and additions to the pristine
-# package are under the same license as the package itself.
 #
+# All modifications and additions to the file contributed by third parties
+# remain the property of their copyright owners, unless otherwise agreed
+# upon. The license for this file, and modifications and additions to the
+# file, is the same license as for the pristine package itself (unless the
+# license for the pristine package is not an Open Source License, in which
+# case the license is the MIT License). An "Open Source License" is a
+# license that conforms to the Open Source Definition (Version 1.9)
+# published by the Open Source Initiative.
+
 # Please submit bugfixes or comments via http://bugs.opensuse.org/
 #
 
@@ -19,7 +26,7 @@ Group:          System/Monitoring
 PreReq:         %fillup_prereq %insserv_prereq
 AutoReqProv:    on
 Version:        22.6
-Release:        28
+Release:        42
 Provides:       ps:/usr/bin/killall
 Summary:        Utilities for managing processes on your system
 Source:         http://switch.dl.sourceforge.net/sourceforge/psmisc/psmisc-%{version}.tar.bz2
@@ -27,6 +34,7 @@ Patch0:         %name-%version.dif
 Patch1:         %name-22.5-pstree.patch
 Patch2:         %name-22.6-nfs4fuser.patch
 Patch3:         %name-22.6-netunix.patch
+Patch4:         %name-22.6-writeonly.patch
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 %define nopeek  s390 s390x ia64
 
@@ -49,6 +57,7 @@ Authors:
 %patch1 -p0 -b .pstree
 %patch2 -p0 -b .nfs4fuser
 %patch3 -p0 -b .netunix
+%patch4 -p0 -b .wrtonly
 %patch0 -p0
 
 %build
@@ -91,6 +100,9 @@ rm -rf $RPM_BUILD_ROOT
 %{_mandir}/man1/pstree.1*
 
 %changelog
+* Thu Aug 07 2008 werner@suse.de
+- Refine NFS patch
+- Add option -w for killing only procs with write access
 * Fri May 16 2008 werner@suse.de
 - Add a warning about fusers option -m due NFS locks
 - Strip @ symbol from file names read from /proc/net/unix