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); +}