Module Name:    src
Committed By:   roy
Date:           Mon Oct  7 06:14:05 UTC 2024

Modified Files:
        src/usr.bin/pkill: pkill.1 pkill.c

Log Message:
pkill(1): Add -F option to use a pidfile and -L to ensure it's locked

Taken from FreeBSD


To generate a diff of this commit:
cvs rdiff -u -r1.32 -r1.33 src/usr.bin/pkill/pkill.1
cvs rdiff -u -r1.33 -r1.34 src/usr.bin/pkill/pkill.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/pkill/pkill.1
diff -u src/usr.bin/pkill/pkill.1:1.32 src/usr.bin/pkill/pkill.1:1.33
--- src/usr.bin/pkill/pkill.1:1.32	Sat Oct 29 08:17:16 2022
+++ src/usr.bin/pkill/pkill.1	Mon Oct  7 06:14:05 2024
@@ -1,4 +1,4 @@
-.\"	$NetBSD: pkill.1,v 1.32 2022/10/29 08:17:16 simonb Exp $
+.\"	$NetBSD: pkill.1,v 1.33 2024/10/07 06:14:05 roy Exp $
 .\"
 .\" Copyright (c) 2002 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd October 29, 2022
+.Dd October 6, 2024
 .Dt PKILL 1
 .Os
 .Sh NAME
@@ -37,8 +37,9 @@
 .Nd find or signal processes by name
 .Sh SYNOPSIS
 .Nm pgrep
-.Op Fl filnqvx
+.Op Fl fiLlnqvx
 .Op Fl d Ar delim
+.Op Fl F Ar pidfile
 .Op Fl G Ar gid
 .Op Fl g Ar pgrp
 .Op Fl P Ar ppid
@@ -49,7 +50,8 @@
 .Ar pattern ...
 .Nm pkill
 .Op Fl signal
-.Op Fl filnvx
+.Op Fl fiLlnvx
+.Op Fl F Ar pidfile
 .Op Fl G Ar gid
 .Op Fl g Ar pgrp
 .Op Fl P Ar ppid
@@ -89,7 +91,7 @@ The following options are available for
 .Nm pkill
 and
 .Nm pgrep :
-.Bl -tag -width xxxxxxxx
+.Bl -tag -width ".Fl F Ar pidfile"
 .It Fl d Ar delim
 Specify a delimiter to be printed between each process ID.
 The default is a newline.
@@ -99,6 +101,10 @@ command.
 .It Fl f
 Match against full argument lists.
 The default is to match against process names.
+.It Fl F Ar pidfile
+Restrict matches to processes which pid is stored in
+.Ar pidfile
+file.
 .It Fl G Ar gid
 Restrict matches to processes with a real group ID in the comma-separated
 list
@@ -114,6 +120,15 @@ or
 command.
 .It Fl i
 Ignore case distinctions in both the process table and the supplied pattern.
+.It Fl L
+The
+.Ar pidfile
+given for the
+.Fl F
+option must be locked with the
+.Xr flock 2
+syscall or created with
+.Xr pidfile_lock 3 .
 .It Fl l
 Long output.
 Print the process name in addition to the process ID for each matching
@@ -181,7 +196,7 @@ This option is valid only when given as 
 .Pp
 The following option is also available for
 .Nm pgrep :
-.Bl -tag -width xxxxxxxx
+.Bl -tag -width ".Fl F Ar pidfile"
 .It Fl q
 Quiet; do not write anything to standard output.
 .El

Index: src/usr.bin/pkill/pkill.c
diff -u src/usr.bin/pkill/pkill.c:1.33 src/usr.bin/pkill/pkill.c:1.34
--- src/usr.bin/pkill/pkill.c:1.33	Sat Oct 29 08:17:16 2022
+++ src/usr.bin/pkill/pkill.c	Mon Oct  7 06:14:05 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: pkill.c,v 1.33 2022/10/29 08:17:16 simonb Exp $	*/
+/*	$NetBSD: pkill.c,v 1.34 2024/10/07 06:14:05 roy Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2022 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: pkill.c,v 1.33 2022/10/29 08:17:16 simonb Exp $");
+__RCSID("$NetBSD: pkill.c,v 1.34 2024/10/07 06:14:05 roy Exp $");
 #endif /* !lint */
 
 #include <sys/types.h>
@@ -52,6 +52,7 @@ __RCSID("$NetBSD: pkill.c,v 1.33 2022/10
 #include <ctype.h>
 #include <kvm.h>
 #include <err.h>
+#include <fcntl.h>
 #include <pwd.h>
 #include <grp.h>
 #include <errno.h>
@@ -62,6 +63,9 @@ __RCSID("$NetBSD: pkill.c,v 1.33 2022/10
 #define	STATUS_BADUSAGE	2
 #define	STATUS_ERROR	3
 
+#define	MIN_PID		5
+#define	MAX_PID		30000 // XXX PID_MAX from sys/proc.h?
+
 enum listtype {
 	LT_GENERIC,
 	LT_USER,
@@ -109,12 +113,13 @@ static int	killact(const struct kinfo_pr
 static int	reniceact(const struct kinfo_proc2 *);
 static int	grepact(const struct kinfo_proc2 *);
 static void	makelist(struct listhead *, enum listtype, char *);
+static int	takepid(const char *, int);
 
 int
 main(int argc, char **argv)
 {
-	char buf[_POSIX2_LINE_MAX], **pargv, *q;
-	int i, j, ch, bestidx, rv, criteria;
+  	char buf[_POSIX2_LINE_MAX], **pargv, *q, *pidfile = NULL;
+	int i, j, ch, bestidx, rv, criteria, pidfromfile, pidfilelock = 0;
 	int (*action)(const struct kinfo_proc2 *);
 	const struct kinfo_proc2 *kp;
 	struct list *li;
@@ -182,12 +187,19 @@ main(int argc, char **argv)
 		} else
 			usage();
 	} else {
-		while ((ch = getopt(argc, argv, "G:P:U:d:fg:ilnqs:t:u:vx")) != -1)
+		while ((ch = getopt(argc, argv, "F:G:LP:U:d:fg:ilnqs:t:u:vx")) != -1)
 			switch (ch) {
+			case 'F':
+				pidfile = optarg;
+				criteria = 1;
+				break;
 			case 'G':
 				makelist(&rgidlist, LT_GROUP, optarg);
 				criteria = 1;
 				break;
+			case 'L':
+				pidfilelock = 1;
+				break;
 			case 'P':
 				makelist(&ppidlist, LT_GENERIC, optarg);
 				criteria = 1;
@@ -253,6 +265,15 @@ main(int argc, char **argv)
 		criteria = 1;
 	if (!criteria)
 		usage();
+	if (pidfile != NULL)
+		pidfromfile = takepid(pidfile, pidfilelock);
+	else {
+		if (pidfilelock) {
+			errx(STATUS_ERROR,
+			    "Option -L doesn't make sense without -F");
+		}
+		pidfromfile = -1;
+	}
 
 	mypid = getpid();
 
@@ -331,6 +352,11 @@ main(int argc, char **argv)
 		if ((kp->p_flag & P_SYSTEM) != 0)
 			continue;
 
+		if (pidfromfile >= 0 && kp->p_pid != pidfromfile) {
+			selected[i] = 0;
+			continue;
+		}
+
 		SLIST_FOREACH(li, &ruidlist, li_chain)
 			if (kp->p_ruid == (uid_t)li->li_number)
 				break;
@@ -449,12 +475,12 @@ usage(void)
 		    getprogname());
 	else {
 		if (pgrep)
-			ustr = "[-filnqvx] [-d delim]";
+			ustr = "[-Lfilnqvx] [-d delim]";
 		else
-			ustr = "[-signal] [-filnvx]";
+			ustr = "[-signal] [-Lfilnvx]";
 
 		(void)fprintf(stderr,
-		    "Usage: %s %s [-G gid] [-g pgrp] [-P ppid] [-s sid] "
+		    "Usage: %s %s [-F pidfile] [-G gid] [-g pgrp] [-P ppid] [-s sid] "
 			   "[-t tty]\n"
 		    "             [-U uid] [-u euid] pattern ...\n",
 			      getprogname(), ustr);
@@ -644,3 +670,48 @@ makelist(struct listhead *head, enum lis
 	if (empty)
 		usage();
 }
+
+static int
+takepid(const char *pidfile, int pidfilelock)
+{
+	char *endp, line[BUFSIZ];
+	FILE *fh;
+	long rval;
+
+	fh = fopen(pidfile, "r");
+	if (fh == NULL)
+		err(STATUS_ERROR, "Cannot open pidfile `%s'", pidfile);
+
+	if (pidfilelock) {
+		/*
+		 * If we can lock pidfile, this means that daemon is not
+		 * running, so would be better not to kill some random process.
+		 */
+		if (flock(fileno(fh), LOCK_EX | LOCK_NB) == 0) {
+			(void)fclose(fh);
+			errx(STATUS_ERROR, "File '%s' can be locked", pidfile);
+		} else {
+			if (errno != EWOULDBLOCK) {
+				errx(STATUS_ERROR,
+				    "Error while locking file '%s'", pidfile);
+			}
+		}
+	}
+
+	if (fgets(line, sizeof(line), fh) == NULL) {
+		if (feof(fh)) {
+			(void)fclose(fh);
+			errx(STATUS_ERROR, "Pidfile `%s' is empty", pidfile);
+		}
+		(void)fclose(fh);
+		err(STATUS_ERROR, "Cannot read from pid file `%s'", pidfile);
+	}
+	(void)fclose(fh);
+
+	rval = strtol(line, &endp, 10);
+	if (*endp != '\0' && !isspace((unsigned char)*endp))
+		errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
+	else if (rval < MIN_PID || rval > MAX_PID)
+		errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
+	return (rval);
+}

Reply via email to