xref: /freebsd/bin/pkill/pkill.c (revision b61a573019428cbdc38ed03be9ecd2482011ea66)
121be3b31SYaroslav Tykhiy /*	$NetBSD: pkill.c,v 1.16 2005/10/10 22:13:20 kleink Exp $	*/
221be3b31SYaroslav Tykhiy 
321be3b31SYaroslav Tykhiy /*-
4*b61a5730SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
51de7b4b8SPedro F. Giffuni  *
621be3b31SYaroslav Tykhiy  * Copyright (c) 2002 The NetBSD Foundation, Inc.
721be3b31SYaroslav Tykhiy  * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
821be3b31SYaroslav Tykhiy  * All rights reserved.
921be3b31SYaroslav Tykhiy  *
1021be3b31SYaroslav Tykhiy  * This code is derived from software contributed to The NetBSD Foundation
1121be3b31SYaroslav Tykhiy  * by Andrew Doran.
1221be3b31SYaroslav Tykhiy  *
1321be3b31SYaroslav Tykhiy  * Redistribution and use in source and binary forms, with or without
1421be3b31SYaroslav Tykhiy  * modification, are permitted provided that the following conditions
1521be3b31SYaroslav Tykhiy  * are met:
1621be3b31SYaroslav Tykhiy  * 1. Redistributions of source code must retain the above copyright
1721be3b31SYaroslav Tykhiy  *    notice, this list of conditions and the following disclaimer.
1821be3b31SYaroslav Tykhiy  * 2. Redistributions in binary form must reproduce the above copyright
1921be3b31SYaroslav Tykhiy  *    notice, this list of conditions and the following disclaimer in the
2021be3b31SYaroslav Tykhiy  *    documentation and/or other materials provided with the distribution.
2121be3b31SYaroslav Tykhiy  *
2221be3b31SYaroslav Tykhiy  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2321be3b31SYaroslav Tykhiy  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2421be3b31SYaroslav Tykhiy  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2521be3b31SYaroslav Tykhiy  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2621be3b31SYaroslav Tykhiy  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2721be3b31SYaroslav Tykhiy  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2821be3b31SYaroslav Tykhiy  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2921be3b31SYaroslav Tykhiy  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3021be3b31SYaroslav Tykhiy  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3121be3b31SYaroslav Tykhiy  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3221be3b31SYaroslav Tykhiy  * POSSIBILITY OF SUCH DAMAGE.
3321be3b31SYaroslav Tykhiy  */
3421be3b31SYaroslav Tykhiy 
3521be3b31SYaroslav Tykhiy #include <sys/cdefs.h>
3621be3b31SYaroslav Tykhiy __FBSDID("$FreeBSD$");
3721be3b31SYaroslav Tykhiy 
3821be3b31SYaroslav Tykhiy #include <sys/types.h>
3921be3b31SYaroslav Tykhiy #include <sys/param.h>
4021be3b31SYaroslav Tykhiy #include <sys/sysctl.h>
4121be3b31SYaroslav Tykhiy #include <sys/proc.h>
4221be3b31SYaroslav Tykhiy #include <sys/queue.h>
4321be3b31SYaroslav Tykhiy #include <sys/stat.h>
4421be3b31SYaroslav Tykhiy #include <sys/time.h>
4521be3b31SYaroslav Tykhiy #include <sys/user.h>
4621be3b31SYaroslav Tykhiy 
477b0706f6SPawel Jakub Dawidek #include <assert.h>
4827181846SLawrence Stewart #include <stdbool.h>
4921be3b31SYaroslav Tykhiy #include <stdio.h>
5021be3b31SYaroslav Tykhiy #include <stdlib.h>
5121be3b31SYaroslav Tykhiy #include <limits.h>
5221be3b31SYaroslav Tykhiy #include <paths.h>
5321be3b31SYaroslav Tykhiy #include <string.h>
5421be3b31SYaroslav Tykhiy #include <unistd.h>
5521be3b31SYaroslav Tykhiy #include <signal.h>
5621be3b31SYaroslav Tykhiy #include <regex.h>
5721be3b31SYaroslav Tykhiy #include <ctype.h>
5821be3b31SYaroslav Tykhiy #include <fcntl.h>
5921be3b31SYaroslav Tykhiy #include <kvm.h>
6021be3b31SYaroslav Tykhiy #include <err.h>
6121be3b31SYaroslav Tykhiy #include <pwd.h>
6221be3b31SYaroslav Tykhiy #include <grp.h>
6321be3b31SYaroslav Tykhiy #include <errno.h>
6421be3b31SYaroslav Tykhiy #include <locale.h>
65c4f0631fSJamie Gritton #include <jail.h>
6621be3b31SYaroslav Tykhiy 
6721be3b31SYaroslav Tykhiy #define	STATUS_MATCH	0
6821be3b31SYaroslav Tykhiy #define	STATUS_NOMATCH	1
6921be3b31SYaroslav Tykhiy #define	STATUS_BADUSAGE	2
7021be3b31SYaroslav Tykhiy #define	STATUS_ERROR	3
7121be3b31SYaroslav Tykhiy 
7221be3b31SYaroslav Tykhiy #define	MIN_PID	5
7321be3b31SYaroslav Tykhiy #define	MAX_PID	99999
7421be3b31SYaroslav Tykhiy 
7521be3b31SYaroslav Tykhiy /* Ignore system-processes (if '-S' flag is not specified) and myself. */
7621be3b31SYaroslav Tykhiy #define	PSKIP(kp)	((kp)->ki_pid == mypid ||			\
77db57c70aSKonstantin Belousov 			 (!kthreads && ((kp)->ki_flag & P_KPROC) != 0))
7821be3b31SYaroslav Tykhiy 
7921be3b31SYaroslav Tykhiy enum listtype {
8021be3b31SYaroslav Tykhiy 	LT_GENERIC,
8121be3b31SYaroslav Tykhiy 	LT_USER,
8221be3b31SYaroslav Tykhiy 	LT_GROUP,
8321be3b31SYaroslav Tykhiy 	LT_TTY,
8421be3b31SYaroslav Tykhiy 	LT_PGRP,
85c4f0631fSJamie Gritton 	LT_JAIL,
86cc55ad3dSEdward Tomasz Napierala 	LT_SID,
87cc55ad3dSEdward Tomasz Napierala 	LT_CLASS
8821be3b31SYaroslav Tykhiy };
8921be3b31SYaroslav Tykhiy 
9021be3b31SYaroslav Tykhiy struct list {
9121be3b31SYaroslav Tykhiy 	SLIST_ENTRY(list) li_chain;
9221be3b31SYaroslav Tykhiy 	long	li_number;
93cc55ad3dSEdward Tomasz Napierala 	char	*li_name;
9421be3b31SYaroslav Tykhiy };
9521be3b31SYaroslav Tykhiy 
9621be3b31SYaroslav Tykhiy SLIST_HEAD(listhead, list);
9721be3b31SYaroslav Tykhiy 
9821be3b31SYaroslav Tykhiy static struct kinfo_proc *plist;
9921be3b31SYaroslav Tykhiy static char	*selected;
10021be3b31SYaroslav Tykhiy static const char *delim = "\n";
10121be3b31SYaroslav Tykhiy static int	nproc;
10221be3b31SYaroslav Tykhiy static int	pgrep;
10321be3b31SYaroslav Tykhiy static int	signum = SIGTERM;
10421be3b31SYaroslav Tykhiy static int	newest;
10521be3b31SYaroslav Tykhiy static int	oldest;
10621be3b31SYaroslav Tykhiy static int	interactive;
10721be3b31SYaroslav Tykhiy static int	inverse;
10821be3b31SYaroslav Tykhiy static int	longfmt;
10921be3b31SYaroslav Tykhiy static int	matchargs;
11021be3b31SYaroslav Tykhiy static int	fullmatch;
11121be3b31SYaroslav Tykhiy static int	kthreads;
11221be3b31SYaroslav Tykhiy static int	cflags = REG_EXTENDED;
1137b0706f6SPawel Jakub Dawidek static int	quiet;
11421be3b31SYaroslav Tykhiy static kvm_t	*kd;
11521be3b31SYaroslav Tykhiy static pid_t	mypid;
11621be3b31SYaroslav Tykhiy 
11713e403fdSAntoine Brodin static struct listhead euidlist = SLIST_HEAD_INITIALIZER(euidlist);
11813e403fdSAntoine Brodin static struct listhead ruidlist = SLIST_HEAD_INITIALIZER(ruidlist);
11913e403fdSAntoine Brodin static struct listhead rgidlist = SLIST_HEAD_INITIALIZER(rgidlist);
12013e403fdSAntoine Brodin static struct listhead pgrplist = SLIST_HEAD_INITIALIZER(pgrplist);
12113e403fdSAntoine Brodin static struct listhead ppidlist = SLIST_HEAD_INITIALIZER(ppidlist);
12213e403fdSAntoine Brodin static struct listhead tdevlist = SLIST_HEAD_INITIALIZER(tdevlist);
12313e403fdSAntoine Brodin static struct listhead sidlist = SLIST_HEAD_INITIALIZER(sidlist);
12413e403fdSAntoine Brodin static struct listhead jidlist = SLIST_HEAD_INITIALIZER(jidlist);
125cc55ad3dSEdward Tomasz Napierala static struct listhead classlist = SLIST_HEAD_INITIALIZER(classlist);
12621be3b31SYaroslav Tykhiy 
12721be3b31SYaroslav Tykhiy static void	usage(void) __attribute__((__noreturn__));
12821be3b31SYaroslav Tykhiy static int	killact(const struct kinfo_proc *);
12921be3b31SYaroslav Tykhiy static int	grepact(const struct kinfo_proc *);
13021be3b31SYaroslav Tykhiy static void	makelist(struct listhead *, enum listtype, char *);
13121be3b31SYaroslav Tykhiy static int	takepid(const char *, int);
13221be3b31SYaroslav Tykhiy 
13321be3b31SYaroslav Tykhiy int
13421be3b31SYaroslav Tykhiy main(int argc, char **argv)
13521be3b31SYaroslav Tykhiy {
1363610bffdSKyle Evans 	char *buf, *mstr, **pargv, *p, *q, *pidfile;
13721be3b31SYaroslav Tykhiy 	const char *execf, *coref;
1383610bffdSKyle Evans 	size_t bufsz;
1393ba0e470SBrian Somers 	int ancestors, debug_opt, did_action;
14021be3b31SYaroslav Tykhiy 	int i, ch, bestidx, rv, criteria, pidfromfile, pidfilelock;
14121be3b31SYaroslav Tykhiy 	size_t jsz;
14221be3b31SYaroslav Tykhiy 	int (*action)(const struct kinfo_proc *);
14321be3b31SYaroslav Tykhiy 	struct kinfo_proc *kp;
14421be3b31SYaroslav Tykhiy 	struct list *li;
14521be3b31SYaroslav Tykhiy 	struct timeval best_tval;
14621be3b31SYaroslav Tykhiy 	regex_t reg;
14721be3b31SYaroslav Tykhiy 	regmatch_t regmatch;
1480a091aebSBrian Somers 	pid_t pid;
14921be3b31SYaroslav Tykhiy 
15021be3b31SYaroslav Tykhiy 	setlocale(LC_ALL, "");
15121be3b31SYaroslav Tykhiy 
15221be3b31SYaroslav Tykhiy 	if (strcmp(getprogname(), "pgrep") == 0) {
15321be3b31SYaroslav Tykhiy 		action = grepact;
15421be3b31SYaroslav Tykhiy 		pgrep = 1;
15521be3b31SYaroslav Tykhiy 	} else {
15621be3b31SYaroslav Tykhiy 		action = killact;
15721be3b31SYaroslav Tykhiy 		p = argv[1];
15821be3b31SYaroslav Tykhiy 
15921be3b31SYaroslav Tykhiy 		if (argc > 1 && p[0] == '-') {
16021be3b31SYaroslav Tykhiy 			p++;
16121be3b31SYaroslav Tykhiy 			i = (int)strtol(p, &q, 10);
16221be3b31SYaroslav Tykhiy 			if (*q == '\0') {
16321be3b31SYaroslav Tykhiy 				signum = i;
16421be3b31SYaroslav Tykhiy 				argv++;
16521be3b31SYaroslav Tykhiy 				argc--;
16621be3b31SYaroslav Tykhiy 			} else {
16712dacf62SJilles Tjoelker 				if (strncasecmp(p, "SIG", 3) == 0)
16821be3b31SYaroslav Tykhiy 					p += 3;
16921be3b31SYaroslav Tykhiy 				for (i = 1; i < NSIG; i++)
17021be3b31SYaroslav Tykhiy 					if (strcasecmp(sys_signame[i], p) == 0)
17121be3b31SYaroslav Tykhiy 						break;
17221be3b31SYaroslav Tykhiy 				if (i != NSIG) {
17321be3b31SYaroslav Tykhiy 					signum = i;
17421be3b31SYaroslav Tykhiy 					argv++;
17521be3b31SYaroslav Tykhiy 					argc--;
17621be3b31SYaroslav Tykhiy 				}
17721be3b31SYaroslav Tykhiy 			}
17821be3b31SYaroslav Tykhiy 		}
17921be3b31SYaroslav Tykhiy 	}
18021be3b31SYaroslav Tykhiy 
1813610bffdSKyle Evans 	buf = NULL;
1820a091aebSBrian Somers 	ancestors = 0;
18321be3b31SYaroslav Tykhiy 	criteria = 0;
18421be3b31SYaroslav Tykhiy 	debug_opt = 0;
18521be3b31SYaroslav Tykhiy 	pidfile = NULL;
18621be3b31SYaroslav Tykhiy 	pidfilelock = 0;
1877b0706f6SPawel Jakub Dawidek 	quiet = 0;
188c08dcaf1SRebecca Cran 	execf = NULL;
189c08dcaf1SRebecca Cran 	coref = _PATH_DEVNULL;
19021be3b31SYaroslav Tykhiy 
191cc55ad3dSEdward Tomasz Napierala 	while ((ch = getopt(argc, argv, "DF:G:ILM:N:P:SU:ac:d:fg:ij:lnoqs:t:u:vx")) != -1)
19221be3b31SYaroslav Tykhiy 		switch (ch) {
19321be3b31SYaroslav Tykhiy 		case 'D':
19421be3b31SYaroslav Tykhiy 			debug_opt++;
19521be3b31SYaroslav Tykhiy 			break;
19621be3b31SYaroslav Tykhiy 		case 'F':
19721be3b31SYaroslav Tykhiy 			pidfile = optarg;
19821be3b31SYaroslav Tykhiy 			criteria = 1;
19921be3b31SYaroslav Tykhiy 			break;
20021be3b31SYaroslav Tykhiy 		case 'G':
20121be3b31SYaroslav Tykhiy 			makelist(&rgidlist, LT_GROUP, optarg);
20221be3b31SYaroslav Tykhiy 			criteria = 1;
20321be3b31SYaroslav Tykhiy 			break;
20421be3b31SYaroslav Tykhiy 		case 'I':
20521be3b31SYaroslav Tykhiy 			if (pgrep)
20621be3b31SYaroslav Tykhiy 				usage();
20721be3b31SYaroslav Tykhiy 			interactive = 1;
20821be3b31SYaroslav Tykhiy 			break;
20921be3b31SYaroslav Tykhiy 		case 'L':
21021be3b31SYaroslav Tykhiy 			pidfilelock = 1;
21121be3b31SYaroslav Tykhiy 			break;
21221be3b31SYaroslav Tykhiy 		case 'M':
21321be3b31SYaroslav Tykhiy 			coref = optarg;
21421be3b31SYaroslav Tykhiy 			break;
21521be3b31SYaroslav Tykhiy 		case 'N':
21621be3b31SYaroslav Tykhiy 			execf = optarg;
21721be3b31SYaroslav Tykhiy 			break;
21821be3b31SYaroslav Tykhiy 		case 'P':
21921be3b31SYaroslav Tykhiy 			makelist(&ppidlist, LT_GENERIC, optarg);
22021be3b31SYaroslav Tykhiy 			criteria = 1;
22121be3b31SYaroslav Tykhiy 			break;
22221be3b31SYaroslav Tykhiy 		case 'S':
22321be3b31SYaroslav Tykhiy 			if (!pgrep)
22421be3b31SYaroslav Tykhiy 				usage();
22521be3b31SYaroslav Tykhiy 			kthreads = 1;
22621be3b31SYaroslav Tykhiy 			break;
22721be3b31SYaroslav Tykhiy 		case 'U':
22821be3b31SYaroslav Tykhiy 			makelist(&ruidlist, LT_USER, optarg);
22921be3b31SYaroslav Tykhiy 			criteria = 1;
23021be3b31SYaroslav Tykhiy 			break;
2310a091aebSBrian Somers 		case 'a':
2320a091aebSBrian Somers 			ancestors++;
2330a091aebSBrian Somers 			break;
234cc55ad3dSEdward Tomasz Napierala 		case 'c':
235cc55ad3dSEdward Tomasz Napierala 			makelist(&classlist, LT_CLASS, optarg);
236cc55ad3dSEdward Tomasz Napierala 			criteria = 1;
237cc55ad3dSEdward Tomasz Napierala 			break;
23821be3b31SYaroslav Tykhiy 		case 'd':
23921be3b31SYaroslav Tykhiy 			if (!pgrep)
24021be3b31SYaroslav Tykhiy 				usage();
24121be3b31SYaroslav Tykhiy 			delim = optarg;
24221be3b31SYaroslav Tykhiy 			break;
24321be3b31SYaroslav Tykhiy 		case 'f':
24421be3b31SYaroslav Tykhiy 			matchargs = 1;
24521be3b31SYaroslav Tykhiy 			break;
24621be3b31SYaroslav Tykhiy 		case 'g':
24721be3b31SYaroslav Tykhiy 			makelist(&pgrplist, LT_PGRP, optarg);
24821be3b31SYaroslav Tykhiy 			criteria = 1;
24921be3b31SYaroslav Tykhiy 			break;
25021be3b31SYaroslav Tykhiy 		case 'i':
25121be3b31SYaroslav Tykhiy 			cflags |= REG_ICASE;
25221be3b31SYaroslav Tykhiy 			break;
25321be3b31SYaroslav Tykhiy 		case 'j':
254c4f0631fSJamie Gritton 			makelist(&jidlist, LT_JAIL, optarg);
25521be3b31SYaroslav Tykhiy 			criteria = 1;
25621be3b31SYaroslav Tykhiy 			break;
25721be3b31SYaroslav Tykhiy 		case 'l':
25821be3b31SYaroslav Tykhiy 			longfmt = 1;
25921be3b31SYaroslav Tykhiy 			break;
26021be3b31SYaroslav Tykhiy 		case 'n':
26121be3b31SYaroslav Tykhiy 			newest = 1;
26221be3b31SYaroslav Tykhiy 			criteria = 1;
26321be3b31SYaroslav Tykhiy 			break;
26421be3b31SYaroslav Tykhiy 		case 'o':
26521be3b31SYaroslav Tykhiy 			oldest = 1;
26621be3b31SYaroslav Tykhiy 			criteria = 1;
26721be3b31SYaroslav Tykhiy 			break;
2687b0706f6SPawel Jakub Dawidek 		case 'q':
2697b0706f6SPawel Jakub Dawidek 			if (!pgrep)
2707b0706f6SPawel Jakub Dawidek 				usage();
2717b0706f6SPawel Jakub Dawidek 			quiet = 1;
2727b0706f6SPawel Jakub Dawidek 			break;
27321be3b31SYaroslav Tykhiy 		case 's':
27421be3b31SYaroslav Tykhiy 			makelist(&sidlist, LT_SID, optarg);
27521be3b31SYaroslav Tykhiy 			criteria = 1;
27621be3b31SYaroslav Tykhiy 			break;
27721be3b31SYaroslav Tykhiy 		case 't':
27821be3b31SYaroslav Tykhiy 			makelist(&tdevlist, LT_TTY, optarg);
27921be3b31SYaroslav Tykhiy 			criteria = 1;
28021be3b31SYaroslav Tykhiy 			break;
28121be3b31SYaroslav Tykhiy 		case 'u':
28221be3b31SYaroslav Tykhiy 			makelist(&euidlist, LT_USER, optarg);
28321be3b31SYaroslav Tykhiy 			criteria = 1;
28421be3b31SYaroslav Tykhiy 			break;
28521be3b31SYaroslav Tykhiy 		case 'v':
28621be3b31SYaroslav Tykhiy 			inverse = 1;
28721be3b31SYaroslav Tykhiy 			break;
28821be3b31SYaroslav Tykhiy 		case 'x':
28921be3b31SYaroslav Tykhiy 			fullmatch = 1;
29021be3b31SYaroslav Tykhiy 			break;
29121be3b31SYaroslav Tykhiy 		default:
29221be3b31SYaroslav Tykhiy 			usage();
29321be3b31SYaroslav Tykhiy 			/* NOTREACHED */
29421be3b31SYaroslav Tykhiy 		}
29521be3b31SYaroslav Tykhiy 
29621be3b31SYaroslav Tykhiy 	argc -= optind;
29721be3b31SYaroslav Tykhiy 	argv += optind;
29821be3b31SYaroslav Tykhiy 	if (argc != 0)
29921be3b31SYaroslav Tykhiy 		criteria = 1;
30021be3b31SYaroslav Tykhiy 	if (!criteria)
30121be3b31SYaroslav Tykhiy 		usage();
30221be3b31SYaroslav Tykhiy 	if (newest && oldest)
30321be3b31SYaroslav Tykhiy 		errx(STATUS_ERROR, "Options -n and -o are mutually exclusive");
30421be3b31SYaroslav Tykhiy 	if (pidfile != NULL)
30521be3b31SYaroslav Tykhiy 		pidfromfile = takepid(pidfile, pidfilelock);
30621be3b31SYaroslav Tykhiy 	else {
30721be3b31SYaroslav Tykhiy 		if (pidfilelock) {
30821be3b31SYaroslav Tykhiy 			errx(STATUS_ERROR,
30921be3b31SYaroslav Tykhiy 			    "Option -L doesn't make sense without -F");
31021be3b31SYaroslav Tykhiy 		}
31121be3b31SYaroslav Tykhiy 		pidfromfile = -1;
31221be3b31SYaroslav Tykhiy 	}
31321be3b31SYaroslav Tykhiy 
31421be3b31SYaroslav Tykhiy 	mypid = getpid();
31521be3b31SYaroslav Tykhiy 
31621be3b31SYaroslav Tykhiy 	/*
3173610bffdSKyle Evans 	 * If we're not matching args, we only need a buffer large enough to
3183610bffdSKyle Evans 	 * hold some relatively short error strings.  Otherwise, we have to
3193610bffdSKyle Evans 	 * assume we'll need up to ARG_MAX bytes for arguments.
3203610bffdSKyle Evans 	 */
3213610bffdSKyle Evans 	bufsz = _POSIX2_LINE_MAX;
3223610bffdSKyle Evans 	if (matchargs) {
3233610bffdSKyle Evans 		long arg_max;
3243610bffdSKyle Evans 
3253610bffdSKyle Evans 		arg_max = sysconf(_SC_ARG_MAX);
3263610bffdSKyle Evans 		if (arg_max == -1)
3273610bffdSKyle Evans 			arg_max = ARG_MAX;
3283610bffdSKyle Evans 
3293610bffdSKyle Evans 		/*
3303610bffdSKyle Evans 		 * The absolute worst case scenario is ARG_MAX single-byte
3313610bffdSKyle Evans 		 * arguments which we'll then separate with spaces and NUL
3323610bffdSKyle Evans 		 * terminate.
3333610bffdSKyle Evans 		 */
3343610bffdSKyle Evans 		bufsz = (arg_max * 2) + 1;
3353610bffdSKyle Evans 	}
3363610bffdSKyle Evans 
3373610bffdSKyle Evans 	buf = malloc(bufsz);
3383610bffdSKyle Evans 	if (buf == NULL)
3393610bffdSKyle Evans 		err(STATUS_ERROR, "malloc");
3403610bffdSKyle Evans 
3413610bffdSKyle Evans 	/*
34221be3b31SYaroslav Tykhiy 	 * Retrieve the list of running processes from the kernel.
34321be3b31SYaroslav Tykhiy 	 */
34421be3b31SYaroslav Tykhiy 	kd = kvm_openfiles(execf, coref, NULL, O_RDONLY, buf);
34521be3b31SYaroslav Tykhiy 	if (kd == NULL)
34621be3b31SYaroslav Tykhiy 		errx(STATUS_ERROR, "Cannot open kernel files (%s)", buf);
34721be3b31SYaroslav Tykhiy 
34821be3b31SYaroslav Tykhiy 	/*
34921be3b31SYaroslav Tykhiy 	 * Use KERN_PROC_PROC instead of KERN_PROC_ALL, since we
35021be3b31SYaroslav Tykhiy 	 * just want processes and not individual kernel threads.
35121be3b31SYaroslav Tykhiy 	 */
35203eea902SEitan Adler 	if (pidfromfile >= 0)
35303eea902SEitan Adler 		plist = kvm_getprocs(kd, KERN_PROC_PID, pidfromfile, &nproc);
35403eea902SEitan Adler 	else
35521be3b31SYaroslav Tykhiy 		plist = kvm_getprocs(kd, KERN_PROC_PROC, 0, &nproc);
35621be3b31SYaroslav Tykhiy 	if (plist == NULL) {
35721be3b31SYaroslav Tykhiy 		errx(STATUS_ERROR, "Cannot get process list (%s)",
35821be3b31SYaroslav Tykhiy 		    kvm_geterr(kd));
35921be3b31SYaroslav Tykhiy 	}
36021be3b31SYaroslav Tykhiy 
36121be3b31SYaroslav Tykhiy 	/*
36221be3b31SYaroslav Tykhiy 	 * Allocate memory which will be used to keep track of the
36321be3b31SYaroslav Tykhiy 	 * selection.
36421be3b31SYaroslav Tykhiy 	 */
36521be3b31SYaroslav Tykhiy 	if ((selected = malloc(nproc)) == NULL) {
36621be3b31SYaroslav Tykhiy 		err(STATUS_ERROR, "Cannot allocate memory for %d processes",
36721be3b31SYaroslav Tykhiy 		    nproc);
36821be3b31SYaroslav Tykhiy 	}
36921be3b31SYaroslav Tykhiy 	memset(selected, 0, nproc);
37021be3b31SYaroslav Tykhiy 
37121be3b31SYaroslav Tykhiy 	/*
37221be3b31SYaroslav Tykhiy 	 * Refine the selection.
37321be3b31SYaroslav Tykhiy 	 */
37421be3b31SYaroslav Tykhiy 	for (; *argv != NULL; argv++) {
37521be3b31SYaroslav Tykhiy 		if ((rv = regcomp(&reg, *argv, cflags)) != 0) {
3763610bffdSKyle Evans 			regerror(rv, &reg, buf, bufsz);
37721be3b31SYaroslav Tykhiy 			errx(STATUS_BADUSAGE,
37821be3b31SYaroslav Tykhiy 			    "Cannot compile regular expression `%s' (%s)",
37921be3b31SYaroslav Tykhiy 			    *argv, buf);
38021be3b31SYaroslav Tykhiy 		}
38121be3b31SYaroslav Tykhiy 
38221be3b31SYaroslav Tykhiy 		for (i = 0, kp = plist; i < nproc; i++, kp++) {
38321be3b31SYaroslav Tykhiy 			if (PSKIP(kp)) {
38421be3b31SYaroslav Tykhiy 				if (debug_opt > 0)
38521be3b31SYaroslav Tykhiy 				    fprintf(stderr, "* Skipped %5d %3d %s\n",
38621be3b31SYaroslav Tykhiy 					kp->ki_pid, kp->ki_uid, kp->ki_comm);
38721be3b31SYaroslav Tykhiy 				continue;
38821be3b31SYaroslav Tykhiy 			}
38921be3b31SYaroslav Tykhiy 
39021be3b31SYaroslav Tykhiy 			if (matchargs &&
39121be3b31SYaroslav Tykhiy 			    (pargv = kvm_getargv(kd, kp, 0)) != NULL) {
39221be3b31SYaroslav Tykhiy 				jsz = 0;
3933610bffdSKyle Evans 				while (jsz < bufsz && *pargv != NULL) {
39421be3b31SYaroslav Tykhiy 					jsz += snprintf(buf + jsz,
3953610bffdSKyle Evans 					    bufsz - jsz,
39621be3b31SYaroslav Tykhiy 					    pargv[1] != NULL ? "%s " : "%s",
39721be3b31SYaroslav Tykhiy 					    pargv[0]);
39821be3b31SYaroslav Tykhiy 					pargv++;
39921be3b31SYaroslav Tykhiy 				}
40021be3b31SYaroslav Tykhiy 				mstr = buf;
40121be3b31SYaroslav Tykhiy 			} else
40221be3b31SYaroslav Tykhiy 				mstr = kp->ki_comm;
40321be3b31SYaroslav Tykhiy 
40421be3b31SYaroslav Tykhiy 			rv = regexec(&reg, mstr, 1, &regmatch, 0);
40521be3b31SYaroslav Tykhiy 			if (rv == 0) {
40621be3b31SYaroslav Tykhiy 				if (fullmatch) {
40721be3b31SYaroslav Tykhiy 					if (regmatch.rm_so == 0 &&
40821be3b31SYaroslav Tykhiy 					    regmatch.rm_eo ==
40921be3b31SYaroslav Tykhiy 					    (off_t)strlen(mstr))
41021be3b31SYaroslav Tykhiy 						selected[i] = 1;
41121be3b31SYaroslav Tykhiy 				} else
41221be3b31SYaroslav Tykhiy 					selected[i] = 1;
41321be3b31SYaroslav Tykhiy 			} else if (rv != REG_NOMATCH) {
4143610bffdSKyle Evans 				regerror(rv, &reg, buf, bufsz);
41521be3b31SYaroslav Tykhiy 				errx(STATUS_ERROR,
41621be3b31SYaroslav Tykhiy 				    "Regular expression evaluation error (%s)",
41721be3b31SYaroslav Tykhiy 				    buf);
41821be3b31SYaroslav Tykhiy 			}
41921be3b31SYaroslav Tykhiy 			if (debug_opt > 1) {
42021be3b31SYaroslav Tykhiy 				const char *rv_res = "NoMatch";
42121be3b31SYaroslav Tykhiy 				if (selected[i])
42221be3b31SYaroslav Tykhiy 					rv_res = "Matched";
42321be3b31SYaroslav Tykhiy 				fprintf(stderr, "* %s %5d %3d %s\n", rv_res,
42421be3b31SYaroslav Tykhiy 				    kp->ki_pid, kp->ki_uid, mstr);
42521be3b31SYaroslav Tykhiy 			}
42621be3b31SYaroslav Tykhiy 		}
42721be3b31SYaroslav Tykhiy 
42821be3b31SYaroslav Tykhiy 		regfree(&reg);
42921be3b31SYaroslav Tykhiy 	}
43021be3b31SYaroslav Tykhiy 
43121be3b31SYaroslav Tykhiy 	for (i = 0, kp = plist; i < nproc; i++, kp++) {
43221be3b31SYaroslav Tykhiy 		if (PSKIP(kp))
43321be3b31SYaroslav Tykhiy 			continue;
43421be3b31SYaroslav Tykhiy 
43521be3b31SYaroslav Tykhiy 		if (pidfromfile >= 0 && kp->ki_pid != pidfromfile) {
43621be3b31SYaroslav Tykhiy 			selected[i] = 0;
43721be3b31SYaroslav Tykhiy 			continue;
43821be3b31SYaroslav Tykhiy 		}
43921be3b31SYaroslav Tykhiy 
44021be3b31SYaroslav Tykhiy 		SLIST_FOREACH(li, &ruidlist, li_chain)
44121be3b31SYaroslav Tykhiy 			if (kp->ki_ruid == (uid_t)li->li_number)
44221be3b31SYaroslav Tykhiy 				break;
44321be3b31SYaroslav Tykhiy 		if (SLIST_FIRST(&ruidlist) != NULL && li == NULL) {
44421be3b31SYaroslav Tykhiy 			selected[i] = 0;
44521be3b31SYaroslav Tykhiy 			continue;
44621be3b31SYaroslav Tykhiy 		}
44721be3b31SYaroslav Tykhiy 
44821be3b31SYaroslav Tykhiy 		SLIST_FOREACH(li, &rgidlist, li_chain)
44921be3b31SYaroslav Tykhiy 			if (kp->ki_rgid == (gid_t)li->li_number)
45021be3b31SYaroslav Tykhiy 				break;
45121be3b31SYaroslav Tykhiy 		if (SLIST_FIRST(&rgidlist) != NULL && li == NULL) {
45221be3b31SYaroslav Tykhiy 			selected[i] = 0;
45321be3b31SYaroslav Tykhiy 			continue;
45421be3b31SYaroslav Tykhiy 		}
45521be3b31SYaroslav Tykhiy 
45621be3b31SYaroslav Tykhiy 		SLIST_FOREACH(li, &euidlist, li_chain)
45721be3b31SYaroslav Tykhiy 			if (kp->ki_uid == (uid_t)li->li_number)
45821be3b31SYaroslav Tykhiy 				break;
45921be3b31SYaroslav Tykhiy 		if (SLIST_FIRST(&euidlist) != NULL && li == NULL) {
46021be3b31SYaroslav Tykhiy 			selected[i] = 0;
46121be3b31SYaroslav Tykhiy 			continue;
46221be3b31SYaroslav Tykhiy 		}
46321be3b31SYaroslav Tykhiy 
46421be3b31SYaroslav Tykhiy 		SLIST_FOREACH(li, &ppidlist, li_chain)
46521be3b31SYaroslav Tykhiy 			if (kp->ki_ppid == (pid_t)li->li_number)
46621be3b31SYaroslav Tykhiy 				break;
46721be3b31SYaroslav Tykhiy 		if (SLIST_FIRST(&ppidlist) != NULL && li == NULL) {
46821be3b31SYaroslav Tykhiy 			selected[i] = 0;
46921be3b31SYaroslav Tykhiy 			continue;
47021be3b31SYaroslav Tykhiy 		}
47121be3b31SYaroslav Tykhiy 
47221be3b31SYaroslav Tykhiy 		SLIST_FOREACH(li, &pgrplist, li_chain)
47321be3b31SYaroslav Tykhiy 			if (kp->ki_pgid == (pid_t)li->li_number)
47421be3b31SYaroslav Tykhiy 				break;
47521be3b31SYaroslav Tykhiy 		if (SLIST_FIRST(&pgrplist) != NULL && li == NULL) {
47621be3b31SYaroslav Tykhiy 			selected[i] = 0;
47721be3b31SYaroslav Tykhiy 			continue;
47821be3b31SYaroslav Tykhiy 		}
47921be3b31SYaroslav Tykhiy 
48021be3b31SYaroslav Tykhiy 		SLIST_FOREACH(li, &tdevlist, li_chain) {
48121be3b31SYaroslav Tykhiy 			if (li->li_number == -1 &&
48221be3b31SYaroslav Tykhiy 			    (kp->ki_flag & P_CONTROLT) == 0)
48321be3b31SYaroslav Tykhiy 				break;
48421be3b31SYaroslav Tykhiy 			if (kp->ki_tdev == (dev_t)li->li_number)
48521be3b31SYaroslav Tykhiy 				break;
48621be3b31SYaroslav Tykhiy 		}
48721be3b31SYaroslav Tykhiy 		if (SLIST_FIRST(&tdevlist) != NULL && li == NULL) {
48821be3b31SYaroslav Tykhiy 			selected[i] = 0;
48921be3b31SYaroslav Tykhiy 			continue;
49021be3b31SYaroslav Tykhiy 		}
49121be3b31SYaroslav Tykhiy 
49221be3b31SYaroslav Tykhiy 		SLIST_FOREACH(li, &sidlist, li_chain)
49321be3b31SYaroslav Tykhiy 			if (kp->ki_sid == (pid_t)li->li_number)
49421be3b31SYaroslav Tykhiy 				break;
49521be3b31SYaroslav Tykhiy 		if (SLIST_FIRST(&sidlist) != NULL && li == NULL) {
49621be3b31SYaroslav Tykhiy 			selected[i] = 0;
49721be3b31SYaroslav Tykhiy 			continue;
49821be3b31SYaroslav Tykhiy 		}
49921be3b31SYaroslav Tykhiy 
50021be3b31SYaroslav Tykhiy 		SLIST_FOREACH(li, &jidlist, li_chain) {
50121be3b31SYaroslav Tykhiy 			/* A particular jail ID, including 0 (not in jail) */
50221be3b31SYaroslav Tykhiy 			if (kp->ki_jid == (int)li->li_number)
50321be3b31SYaroslav Tykhiy 				break;
50421be3b31SYaroslav Tykhiy 			/* Any jail */
50521be3b31SYaroslav Tykhiy 			if (kp->ki_jid > 0 && li->li_number == -1)
50621be3b31SYaroslav Tykhiy 				break;
50721be3b31SYaroslav Tykhiy 		}
50821be3b31SYaroslav Tykhiy 		if (SLIST_FIRST(&jidlist) != NULL && li == NULL) {
50921be3b31SYaroslav Tykhiy 			selected[i] = 0;
51021be3b31SYaroslav Tykhiy 			continue;
51121be3b31SYaroslav Tykhiy 		}
51221be3b31SYaroslav Tykhiy 
513cc55ad3dSEdward Tomasz Napierala 		SLIST_FOREACH(li, &classlist, li_chain) {
514cc55ad3dSEdward Tomasz Napierala 			/*
515cc55ad3dSEdward Tomasz Napierala 			 * We skip P_SYSTEM processes to match ps(1) output.
516cc55ad3dSEdward Tomasz Napierala 			 */
517cc55ad3dSEdward Tomasz Napierala 			if ((kp->ki_flag & P_SYSTEM) == 0 &&
518cc55ad3dSEdward Tomasz Napierala 			    strcmp(kp->ki_loginclass, li->li_name) == 0)
519cc55ad3dSEdward Tomasz Napierala 				break;
520cc55ad3dSEdward Tomasz Napierala 		}
521cc55ad3dSEdward Tomasz Napierala 		if (SLIST_FIRST(&classlist) != NULL && li == NULL) {
522cc55ad3dSEdward Tomasz Napierala 			selected[i] = 0;
523cc55ad3dSEdward Tomasz Napierala 			continue;
524cc55ad3dSEdward Tomasz Napierala 		}
525cc55ad3dSEdward Tomasz Napierala 
52621be3b31SYaroslav Tykhiy 		if (argc == 0)
52721be3b31SYaroslav Tykhiy 			selected[i] = 1;
52821be3b31SYaroslav Tykhiy 	}
52921be3b31SYaroslav Tykhiy 
5300a091aebSBrian Somers 	if (!ancestors) {
5310a091aebSBrian Somers 		pid = mypid;
5320a091aebSBrian Somers 		while (pid) {
5330a091aebSBrian Somers 			for (i = 0, kp = plist; i < nproc; i++, kp++) {
5340a091aebSBrian Somers 				if (PSKIP(kp))
5350a091aebSBrian Somers 					continue;
5360a091aebSBrian Somers 				if (kp->ki_pid == pid) {
5370a091aebSBrian Somers 					selected[i] = 0;
5380a091aebSBrian Somers 					pid = kp->ki_ppid;
5390a091aebSBrian Somers 					break;
5400a091aebSBrian Somers 				}
5410a091aebSBrian Somers 			}
5420a091aebSBrian Somers 			if (i == nproc) {
5430a091aebSBrian Somers 				if (pid == mypid)
5440a091aebSBrian Somers 					pid = getppid();
5450a091aebSBrian Somers 				else
5460a091aebSBrian Somers 					break;	/* Maybe we're in a jail ? */
5470a091aebSBrian Somers 			}
5480a091aebSBrian Somers 		}
5490a091aebSBrian Somers 	}
5500a091aebSBrian Somers 
55121be3b31SYaroslav Tykhiy 	if (newest || oldest) {
55221be3b31SYaroslav Tykhiy 		best_tval.tv_sec = 0;
55321be3b31SYaroslav Tykhiy 		best_tval.tv_usec = 0;
55421be3b31SYaroslav Tykhiy 		bestidx = -1;
55521be3b31SYaroslav Tykhiy 
55621be3b31SYaroslav Tykhiy 		for (i = 0, kp = plist; i < nproc; i++, kp++) {
55721be3b31SYaroslav Tykhiy 			if (!selected[i])
55821be3b31SYaroslav Tykhiy 				continue;
55921be3b31SYaroslav Tykhiy 			if (bestidx == -1) {
56021be3b31SYaroslav Tykhiy 				/* The first entry of the list which matched. */
56121be3b31SYaroslav Tykhiy 				;
56221be3b31SYaroslav Tykhiy 			} else if (timercmp(&kp->ki_start, &best_tval, >)) {
56321be3b31SYaroslav Tykhiy 				/* This entry is newer than previous "best". */
56421be3b31SYaroslav Tykhiy 				if (oldest)	/* but we want the oldest */
56521be3b31SYaroslav Tykhiy 					continue;
56621be3b31SYaroslav Tykhiy 			} else {
56721be3b31SYaroslav Tykhiy 				/* This entry is older than previous "best". */
56821be3b31SYaroslav Tykhiy 				if (newest)	/* but we want the newest */
56921be3b31SYaroslav Tykhiy 					continue;
57021be3b31SYaroslav Tykhiy 			}
57121be3b31SYaroslav Tykhiy 			/* This entry is better than previous "best" entry. */
57221be3b31SYaroslav Tykhiy 			best_tval.tv_sec = kp->ki_start.tv_sec;
57321be3b31SYaroslav Tykhiy 			best_tval.tv_usec = kp->ki_start.tv_usec;
57421be3b31SYaroslav Tykhiy 			bestidx = i;
57521be3b31SYaroslav Tykhiy 		}
57621be3b31SYaroslav Tykhiy 
57721be3b31SYaroslav Tykhiy 		memset(selected, 0, nproc);
57821be3b31SYaroslav Tykhiy 		if (bestidx != -1)
57921be3b31SYaroslav Tykhiy 			selected[bestidx] = 1;
58021be3b31SYaroslav Tykhiy 	}
58121be3b31SYaroslav Tykhiy 
58221be3b31SYaroslav Tykhiy 	/*
58321be3b31SYaroslav Tykhiy 	 * Take the appropriate action for each matched process, if any.
58421be3b31SYaroslav Tykhiy 	 */
5853ba0e470SBrian Somers 	did_action = 0;
58621be3b31SYaroslav Tykhiy 	for (i = 0, rv = 0, kp = plist; i < nproc; i++, kp++) {
58721be3b31SYaroslav Tykhiy 		if (PSKIP(kp))
58821be3b31SYaroslav Tykhiy 			continue;
58921be3b31SYaroslav Tykhiy 		if (selected[i]) {
5903ba0e470SBrian Somers 			if (longfmt && !pgrep) {
5913ba0e470SBrian Somers 				did_action = 1;
5923ba0e470SBrian Somers 				printf("kill -%d %d\n", signum, kp->ki_pid);
5933ba0e470SBrian Somers 			}
59421be3b31SYaroslav Tykhiy 			if (inverse)
59521be3b31SYaroslav Tykhiy 				continue;
59621be3b31SYaroslav Tykhiy 		} else if (!inverse)
59721be3b31SYaroslav Tykhiy 			continue;
59821be3b31SYaroslav Tykhiy 		rv |= (*action)(kp);
59921be3b31SYaroslav Tykhiy 	}
600cf182be5SLawrence Stewart 	if (rv && pgrep && !quiet)
6011e781c6fSLawrence Stewart 		putchar('\n');
6023ba0e470SBrian Somers 	if (!did_action && !pgrep && longfmt)
6033ba0e470SBrian Somers 		fprintf(stderr,
6043ba0e470SBrian Somers 		    "No matching processes belonging to you were found\n");
60521be3b31SYaroslav Tykhiy 
6063610bffdSKyle Evans 	free(buf);
60721be3b31SYaroslav Tykhiy 	exit(rv ? STATUS_MATCH : STATUS_NOMATCH);
60821be3b31SYaroslav Tykhiy }
60921be3b31SYaroslav Tykhiy 
61021be3b31SYaroslav Tykhiy static void
61121be3b31SYaroslav Tykhiy usage(void)
61221be3b31SYaroslav Tykhiy {
61321be3b31SYaroslav Tykhiy 	const char *ustr;
61421be3b31SYaroslav Tykhiy 
61521be3b31SYaroslav Tykhiy 	if (pgrep)
6167b0706f6SPawel Jakub Dawidek 		ustr = "[-LSfilnoqvx] [-d delim]";
61721be3b31SYaroslav Tykhiy 	else
6183ba0e470SBrian Somers 		ustr = "[-signal] [-ILfilnovx]";
61921be3b31SYaroslav Tykhiy 
62021be3b31SYaroslav Tykhiy 	fprintf(stderr,
62121be3b31SYaroslav Tykhiy 		"usage: %s %s [-F pidfile] [-G gid] [-M core] [-N system]\n"
622c4f0631fSJamie Gritton 		"             [-P ppid] [-U uid] [-c class] [-g pgrp] [-j jail]\n"
623cc55ad3dSEdward Tomasz Napierala 		"             [-s sid] [-t tty] [-u euid] pattern ...\n",
624cc55ad3dSEdward Tomasz Napierala 		getprogname(), ustr);
62521be3b31SYaroslav Tykhiy 
62621be3b31SYaroslav Tykhiy 	exit(STATUS_BADUSAGE);
62721be3b31SYaroslav Tykhiy }
62821be3b31SYaroslav Tykhiy 
62921be3b31SYaroslav Tykhiy static void
63021be3b31SYaroslav Tykhiy show_process(const struct kinfo_proc *kp)
63121be3b31SYaroslav Tykhiy {
63221be3b31SYaroslav Tykhiy 	char **argv;
63321be3b31SYaroslav Tykhiy 
6347b0706f6SPawel Jakub Dawidek 	if (quiet) {
6357b0706f6SPawel Jakub Dawidek 		assert(pgrep);
6367b0706f6SPawel Jakub Dawidek 		return;
6377b0706f6SPawel Jakub Dawidek 	}
63821be3b31SYaroslav Tykhiy 	if ((longfmt || !pgrep) && matchargs &&
63921be3b31SYaroslav Tykhiy 	    (argv = kvm_getargv(kd, kp, 0)) != NULL) {
64021be3b31SYaroslav Tykhiy 		printf("%d ", (int)kp->ki_pid);
64121be3b31SYaroslav Tykhiy 		for (; *argv != NULL; argv++) {
64221be3b31SYaroslav Tykhiy 			printf("%s", *argv);
64321be3b31SYaroslav Tykhiy 			if (argv[1] != NULL)
64421be3b31SYaroslav Tykhiy 				putchar(' ');
64521be3b31SYaroslav Tykhiy 		}
64621be3b31SYaroslav Tykhiy 	} else if (longfmt || !pgrep)
64721be3b31SYaroslav Tykhiy 		printf("%d %s", (int)kp->ki_pid, kp->ki_comm);
64821be3b31SYaroslav Tykhiy 	else
64921be3b31SYaroslav Tykhiy 		printf("%d", (int)kp->ki_pid);
65021be3b31SYaroslav Tykhiy }
65121be3b31SYaroslav Tykhiy 
65221be3b31SYaroslav Tykhiy static int
65321be3b31SYaroslav Tykhiy killact(const struct kinfo_proc *kp)
65421be3b31SYaroslav Tykhiy {
65521be3b31SYaroslav Tykhiy 	int ch, first;
65621be3b31SYaroslav Tykhiy 
65721be3b31SYaroslav Tykhiy 	if (interactive) {
65821be3b31SYaroslav Tykhiy 		/*
65921be3b31SYaroslav Tykhiy 		 * Be careful, ask before killing.
66021be3b31SYaroslav Tykhiy 		 */
66121be3b31SYaroslav Tykhiy 		printf("kill ");
66221be3b31SYaroslav Tykhiy 		show_process(kp);
66321be3b31SYaroslav Tykhiy 		printf("? ");
66421be3b31SYaroslav Tykhiy 		fflush(stdout);
66521be3b31SYaroslav Tykhiy 		first = ch = getchar();
66621be3b31SYaroslav Tykhiy 		while (ch != '\n' && ch != EOF)
66721be3b31SYaroslav Tykhiy 			ch = getchar();
66821be3b31SYaroslav Tykhiy 		if (first != 'y' && first != 'Y')
66921be3b31SYaroslav Tykhiy 			return (1);
67021be3b31SYaroslav Tykhiy 	}
67121be3b31SYaroslav Tykhiy 	if (kill(kp->ki_pid, signum) == -1) {
67221be3b31SYaroslav Tykhiy 		/*
67321be3b31SYaroslav Tykhiy 		 * Check for ESRCH, which indicates that the process
67421be3b31SYaroslav Tykhiy 		 * disappeared between us matching it and us
67521be3b31SYaroslav Tykhiy 		 * signalling it; don't issue a warning about it.
67621be3b31SYaroslav Tykhiy 		 */
67721be3b31SYaroslav Tykhiy 		if (errno != ESRCH)
67821be3b31SYaroslav Tykhiy 			warn("signalling pid %d", (int)kp->ki_pid);
67921be3b31SYaroslav Tykhiy 		/*
68021be3b31SYaroslav Tykhiy 		 * Return 0 to indicate that the process should not be
68121be3b31SYaroslav Tykhiy 		 * considered a match, since we didn't actually get to
68221be3b31SYaroslav Tykhiy 		 * signal it.
68321be3b31SYaroslav Tykhiy 		 */
68421be3b31SYaroslav Tykhiy 		return (0);
68521be3b31SYaroslav Tykhiy 	}
68621be3b31SYaroslav Tykhiy 	return (1);
68721be3b31SYaroslav Tykhiy }
68821be3b31SYaroslav Tykhiy 
68921be3b31SYaroslav Tykhiy static int
69021be3b31SYaroslav Tykhiy grepact(const struct kinfo_proc *kp)
69121be3b31SYaroslav Tykhiy {
69227181846SLawrence Stewart 	static bool first = true;
69321be3b31SYaroslav Tykhiy 
69427181846SLawrence Stewart 	if (!quiet && !first)
69521be3b31SYaroslav Tykhiy 		printf("%s", delim);
69627181846SLawrence Stewart 	show_process(kp);
69727181846SLawrence Stewart 	first = false;
69821be3b31SYaroslav Tykhiy 	return (1);
69921be3b31SYaroslav Tykhiy }
70021be3b31SYaroslav Tykhiy 
70121be3b31SYaroslav Tykhiy static void
70221be3b31SYaroslav Tykhiy makelist(struct listhead *head, enum listtype type, char *src)
70321be3b31SYaroslav Tykhiy {
70421be3b31SYaroslav Tykhiy 	struct list *li;
70521be3b31SYaroslav Tykhiy 	struct passwd *pw;
70621be3b31SYaroslav Tykhiy 	struct group *gr;
70721be3b31SYaroslav Tykhiy 	struct stat st;
708eb948eacSEd Schouten 	const char *cp;
70921be3b31SYaroslav Tykhiy 	char *sp, *ep, buf[MAXPATHLEN];
71021be3b31SYaroslav Tykhiy 	int empty;
71121be3b31SYaroslav Tykhiy 
71221be3b31SYaroslav Tykhiy 	empty = 1;
71321be3b31SYaroslav Tykhiy 
71421be3b31SYaroslav Tykhiy 	while ((sp = strsep(&src, ",")) != NULL) {
71521be3b31SYaroslav Tykhiy 		if (*sp == '\0')
71621be3b31SYaroslav Tykhiy 			usage();
71721be3b31SYaroslav Tykhiy 
71821be3b31SYaroslav Tykhiy 		if ((li = malloc(sizeof(*li))) == NULL) {
71921be3b31SYaroslav Tykhiy 			err(STATUS_ERROR, "Cannot allocate %zu bytes",
72021be3b31SYaroslav Tykhiy 			    sizeof(*li));
72121be3b31SYaroslav Tykhiy 		}
72221be3b31SYaroslav Tykhiy 
72321be3b31SYaroslav Tykhiy 		SLIST_INSERT_HEAD(head, li, li_chain);
72421be3b31SYaroslav Tykhiy 		empty = 0;
72521be3b31SYaroslav Tykhiy 
726cc55ad3dSEdward Tomasz Napierala 		if (type != LT_CLASS)
72721be3b31SYaroslav Tykhiy 			li->li_number = (uid_t)strtol(sp, &ep, 0);
728cc55ad3dSEdward Tomasz Napierala 
729cc55ad3dSEdward Tomasz Napierala 		if (type != LT_CLASS && *ep == '\0') {
73021be3b31SYaroslav Tykhiy 			switch (type) {
73121be3b31SYaroslav Tykhiy 			case LT_PGRP:
73221be3b31SYaroslav Tykhiy 				if (li->li_number == 0)
73321be3b31SYaroslav Tykhiy 					li->li_number = getpgrp();
73421be3b31SYaroslav Tykhiy 				break;
73521be3b31SYaroslav Tykhiy 			case LT_SID:
73621be3b31SYaroslav Tykhiy 				if (li->li_number == 0)
73721be3b31SYaroslav Tykhiy 					li->li_number = getsid(mypid);
73821be3b31SYaroslav Tykhiy 				break;
739c4f0631fSJamie Gritton 			case LT_JAIL:
74021be3b31SYaroslav Tykhiy 				if (li->li_number < 0)
74121be3b31SYaroslav Tykhiy 					errx(STATUS_BADUSAGE,
74221be3b31SYaroslav Tykhiy 					     "Negative jail ID `%s'", sp);
74321be3b31SYaroslav Tykhiy 				/* For compatibility with old -j */
74421be3b31SYaroslav Tykhiy 				if (li->li_number == 0)
74521be3b31SYaroslav Tykhiy 					li->li_number = -1;	/* any jail */
74621be3b31SYaroslav Tykhiy 				break;
7472a546db8SDavid E. O'Brien 			case LT_TTY:
7482a546db8SDavid E. O'Brien 				if (li->li_number < 0)
7492a546db8SDavid E. O'Brien 					errx(STATUS_BADUSAGE,
7502a546db8SDavid E. O'Brien 					     "Negative /dev/pts tty `%s'", sp);
7512a546db8SDavid E. O'Brien 				snprintf(buf, sizeof(buf), _PATH_DEV "pts/%s",
7522a546db8SDavid E. O'Brien 				    sp);
7532a546db8SDavid E. O'Brien 				if (stat(buf, &st) != -1)
7542a546db8SDavid E. O'Brien 					goto foundtty;
7552a546db8SDavid E. O'Brien 				if (errno == ENOENT)
7562a546db8SDavid E. O'Brien 					errx(STATUS_BADUSAGE, "No such tty: `"
7572a546db8SDavid E. O'Brien 					    _PATH_DEV "pts/%s'", sp);
7582a546db8SDavid E. O'Brien 				err(STATUS_ERROR, "Cannot access `"
7592a546db8SDavid E. O'Brien 				    _PATH_DEV "pts/%s'", sp);
7602a546db8SDavid E. O'Brien 				break;
76121be3b31SYaroslav Tykhiy 			default:
76221be3b31SYaroslav Tykhiy 				break;
76321be3b31SYaroslav Tykhiy 			}
76421be3b31SYaroslav Tykhiy 			continue;
76521be3b31SYaroslav Tykhiy 		}
76621be3b31SYaroslav Tykhiy 
76721be3b31SYaroslav Tykhiy 		switch (type) {
76821be3b31SYaroslav Tykhiy 		case LT_USER:
76921be3b31SYaroslav Tykhiy 			if ((pw = getpwnam(sp)) == NULL)
77021be3b31SYaroslav Tykhiy 				errx(STATUS_BADUSAGE, "Unknown user `%s'", sp);
77121be3b31SYaroslav Tykhiy 			li->li_number = pw->pw_uid;
77221be3b31SYaroslav Tykhiy 			break;
77321be3b31SYaroslav Tykhiy 		case LT_GROUP:
77421be3b31SYaroslav Tykhiy 			if ((gr = getgrnam(sp)) == NULL)
77521be3b31SYaroslav Tykhiy 				errx(STATUS_BADUSAGE, "Unknown group `%s'", sp);
77621be3b31SYaroslav Tykhiy 			li->li_number = gr->gr_gid;
77721be3b31SYaroslav Tykhiy 			break;
77821be3b31SYaroslav Tykhiy 		case LT_TTY:
77921be3b31SYaroslav Tykhiy 			if (strcmp(sp, "-") == 0) {
78021be3b31SYaroslav Tykhiy 				li->li_number = -1;
78121be3b31SYaroslav Tykhiy 				break;
78221be3b31SYaroslav Tykhiy 			} else if (strcmp(sp, "co") == 0) {
78321be3b31SYaroslav Tykhiy 				cp = "console";
78421be3b31SYaroslav Tykhiy 			} else {
78521be3b31SYaroslav Tykhiy 				cp = sp;
78621be3b31SYaroslav Tykhiy 			}
78721be3b31SYaroslav Tykhiy 
788eb948eacSEd Schouten 			snprintf(buf, sizeof(buf), _PATH_DEV "%s", cp);
78918aa158fSEd Schouten 			if (stat(buf, &st) != -1)
79018aa158fSEd Schouten 				goto foundtty;
79121be3b31SYaroslav Tykhiy 
79218aa158fSEd Schouten 			snprintf(buf, sizeof(buf), _PATH_DEV "tty%s", cp);
79318aa158fSEd Schouten 			if (stat(buf, &st) != -1)
79418aa158fSEd Schouten 				goto foundtty;
79518aa158fSEd Schouten 
79618aa158fSEd Schouten 			if (errno == ENOENT)
79718aa158fSEd Schouten 				errx(STATUS_BADUSAGE, "No such tty: `%s'", sp);
79821be3b31SYaroslav Tykhiy 			err(STATUS_ERROR, "Cannot access `%s'", sp);
79921be3b31SYaroslav Tykhiy 
80018aa158fSEd Schouten foundtty:		if ((st.st_mode & S_IFCHR) == 0)
80121be3b31SYaroslav Tykhiy 				errx(STATUS_BADUSAGE, "Not a tty: `%s'", sp);
80221be3b31SYaroslav Tykhiy 
80321be3b31SYaroslav Tykhiy 			li->li_number = st.st_rdev;
80421be3b31SYaroslav Tykhiy 			break;
805c4f0631fSJamie Gritton 		case LT_JAIL: {
806c4f0631fSJamie Gritton 			int jid;
807c4f0631fSJamie Gritton 
80821be3b31SYaroslav Tykhiy 			if (strcmp(sp, "none") == 0)
80921be3b31SYaroslav Tykhiy 				li->li_number = 0;
81021be3b31SYaroslav Tykhiy 			else if (strcmp(sp, "any") == 0)
81121be3b31SYaroslav Tykhiy 				li->li_number = -1;
812c4f0631fSJamie Gritton 			else if ((jid = jail_getid(sp)) != -1)
813c4f0631fSJamie Gritton 				li->li_number = jid;
81421be3b31SYaroslav Tykhiy 			else if (*ep != '\0')
81521be3b31SYaroslav Tykhiy 				errx(STATUS_BADUSAGE,
816c4f0631fSJamie Gritton 				     "Invalid jail ID or name `%s'", sp);
81721be3b31SYaroslav Tykhiy 			break;
818c4f0631fSJamie Gritton 		}
819cc55ad3dSEdward Tomasz Napierala 		case LT_CLASS:
820cc55ad3dSEdward Tomasz Napierala 			li->li_number = -1;
821cc55ad3dSEdward Tomasz Napierala 			li->li_name = strdup(sp);
822cc55ad3dSEdward Tomasz Napierala 			if (li->li_name == NULL)
823cc55ad3dSEdward Tomasz Napierala 				err(STATUS_ERROR, "Cannot allocate memory");
824cc55ad3dSEdward Tomasz Napierala 			break;
82521be3b31SYaroslav Tykhiy 		default:
82621be3b31SYaroslav Tykhiy 			usage();
82721be3b31SYaroslav Tykhiy 		}
82821be3b31SYaroslav Tykhiy 	}
82921be3b31SYaroslav Tykhiy 
83021be3b31SYaroslav Tykhiy 	if (empty)
83121be3b31SYaroslav Tykhiy 		usage();
83221be3b31SYaroslav Tykhiy }
83321be3b31SYaroslav Tykhiy 
83421be3b31SYaroslav Tykhiy static int
83521be3b31SYaroslav Tykhiy takepid(const char *pidfile, int pidfilelock)
83621be3b31SYaroslav Tykhiy {
83721be3b31SYaroslav Tykhiy 	char *endp, line[BUFSIZ];
83821be3b31SYaroslav Tykhiy 	FILE *fh;
83921be3b31SYaroslav Tykhiy 	long rval;
84021be3b31SYaroslav Tykhiy 
84121be3b31SYaroslav Tykhiy 	fh = fopen(pidfile, "r");
84221be3b31SYaroslav Tykhiy 	if (fh == NULL)
84321be3b31SYaroslav Tykhiy 		err(STATUS_ERROR, "Cannot open pidfile `%s'", pidfile);
84421be3b31SYaroslav Tykhiy 
84521be3b31SYaroslav Tykhiy 	if (pidfilelock) {
84621be3b31SYaroslav Tykhiy 		/*
84721be3b31SYaroslav Tykhiy 		 * If we can lock pidfile, this means that daemon is not
84821be3b31SYaroslav Tykhiy 		 * running, so would be better not to kill some random process.
84921be3b31SYaroslav Tykhiy 		 */
85021be3b31SYaroslav Tykhiy 		if (flock(fileno(fh), LOCK_EX | LOCK_NB) == 0) {
85121be3b31SYaroslav Tykhiy 			(void)fclose(fh);
85221be3b31SYaroslav Tykhiy 			errx(STATUS_ERROR, "File '%s' can be locked", pidfile);
85321be3b31SYaroslav Tykhiy 		} else {
85421be3b31SYaroslav Tykhiy 			if (errno != EWOULDBLOCK) {
85521be3b31SYaroslav Tykhiy 				errx(STATUS_ERROR,
85621be3b31SYaroslav Tykhiy 				    "Error while locking file '%s'", pidfile);
85721be3b31SYaroslav Tykhiy 			}
85821be3b31SYaroslav Tykhiy 		}
85921be3b31SYaroslav Tykhiy 	}
86021be3b31SYaroslav Tykhiy 
86121be3b31SYaroslav Tykhiy 	if (fgets(line, sizeof(line), fh) == NULL) {
86221be3b31SYaroslav Tykhiy 		if (feof(fh)) {
86321be3b31SYaroslav Tykhiy 			(void)fclose(fh);
86421be3b31SYaroslav Tykhiy 			errx(STATUS_ERROR, "Pidfile `%s' is empty", pidfile);
86521be3b31SYaroslav Tykhiy 		}
86621be3b31SYaroslav Tykhiy 		(void)fclose(fh);
86721be3b31SYaroslav Tykhiy 		err(STATUS_ERROR, "Cannot read from pid file `%s'", pidfile);
86821be3b31SYaroslav Tykhiy 	}
86921be3b31SYaroslav Tykhiy 	(void)fclose(fh);
87021be3b31SYaroslav Tykhiy 
87121be3b31SYaroslav Tykhiy 	rval = strtol(line, &endp, 10);
87221be3b31SYaroslav Tykhiy 	if (*endp != '\0' && !isspace((unsigned char)*endp))
87321be3b31SYaroslav Tykhiy 		errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
87421be3b31SYaroslav Tykhiy 	else if (rval < MIN_PID || rval > MAX_PID)
87521be3b31SYaroslav Tykhiy 		errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
87621be3b31SYaroslav Tykhiy 	return (rval);
87721be3b31SYaroslav Tykhiy }
878