1*cb3e16aeSderaadt /* $OpenBSD: pkill.c,v 1.43 2021/09/01 15:54:40 deraadt Exp $ */
245580423Smillert /* $NetBSD: pkill.c,v 1.5 2002/10/27 11:49:34 kleink Exp $ */
345580423Smillert
445580423Smillert /*-
545580423Smillert * Copyright (c) 2002 The NetBSD Foundation, Inc.
645580423Smillert * All rights reserved.
745580423Smillert *
845580423Smillert * This code is derived from software contributed to The NetBSD Foundation
945580423Smillert * by Andrew Doran.
1045580423Smillert *
1145580423Smillert * Redistribution and use in source and binary forms, with or without
1245580423Smillert * modification, are permitted provided that the following conditions
1345580423Smillert * are met:
1445580423Smillert * 1. Redistributions of source code must retain the above copyright
1545580423Smillert * notice, this list of conditions and the following disclaimer.
1645580423Smillert * 2. Redistributions in binary form must reproduce the above copyright
1745580423Smillert * notice, this list of conditions and the following disclaimer in the
1845580423Smillert * documentation and/or other materials provided with the distribution.
1945580423Smillert *
2045580423Smillert * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2145580423Smillert * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2245580423Smillert * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2345580423Smillert * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2445580423Smillert * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2545580423Smillert * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2645580423Smillert * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2745580423Smillert * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2845580423Smillert * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2945580423Smillert * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3045580423Smillert * POSSIBILITY OF SUCH DAMAGE.
3145580423Smillert */
3245580423Smillert
3345580423Smillert #include <sys/types.h>
3445580423Smillert #include <sys/sysctl.h>
35*cb3e16aeSderaadt #include <sys/signal.h>
3645580423Smillert #include <sys/proc.h>
3745580423Smillert #include <sys/queue.h>
3845580423Smillert #include <sys/stat.h>
391b2463c8Smarkus #include <sys/socket.h>
4045580423Smillert
4145580423Smillert #include <stdio.h>
4245580423Smillert #include <stdlib.h>
4383d16d5cSmillert #include <stdint.h>
4445580423Smillert #include <limits.h>
4545580423Smillert #include <string.h>
4645580423Smillert #include <unistd.h>
4745580423Smillert #include <signal.h>
4845580423Smillert #include <regex.h>
4945580423Smillert #include <ctype.h>
5045580423Smillert #include <kvm.h>
5145580423Smillert #include <err.h>
5245580423Smillert #include <pwd.h>
5345580423Smillert #include <grp.h>
5445580423Smillert #include <errno.h>
5545580423Smillert
5645580423Smillert #define STATUS_MATCH 0
5745580423Smillert #define STATUS_NOMATCH 1
5845580423Smillert #define STATUS_BADUSAGE 2
5945580423Smillert #define STATUS_ERROR 3
6045580423Smillert
6145580423Smillert enum listtype {
6245580423Smillert LT_GENERIC,
6345580423Smillert LT_USER,
6445580423Smillert LT_GROUP,
6545580423Smillert LT_TTY,
6645580423Smillert LT_PGRP,
671b2463c8Smarkus LT_SID,
681b2463c8Smarkus LT_RTABLE
6945580423Smillert };
7045580423Smillert
7145580423Smillert struct list {
7245580423Smillert SLIST_ENTRY(list) li_chain;
7345580423Smillert long li_number;
7445580423Smillert };
7545580423Smillert
7645580423Smillert SLIST_HEAD(listhead, list);
7745580423Smillert
785027561dSguenther struct kinfo_proc *plist;
7945580423Smillert char *selected;
8065e8c1ceSgsoares const char *delim = "\n";
8145580423Smillert int nproc;
8245580423Smillert int pgrep;
8345580423Smillert int signum = SIGTERM;
8445580423Smillert int newest;
8583d16d5cSmillert int oldest;
86d2e6cab4Sespie int quiet;
8745580423Smillert int inverse;
8845580423Smillert int longfmt;
8945580423Smillert int matchargs;
9045580423Smillert int fullmatch;
91e880abb2Stedu int confirmkill;
9245580423Smillert kvm_t *kd;
9345580423Smillert pid_t mypid;
9445580423Smillert
9545580423Smillert struct listhead euidlist = SLIST_HEAD_INITIALIZER(list);
9645580423Smillert struct listhead ruidlist = SLIST_HEAD_INITIALIZER(list);
9745580423Smillert struct listhead rgidlist = SLIST_HEAD_INITIALIZER(list);
9845580423Smillert struct listhead pgrplist = SLIST_HEAD_INITIALIZER(list);
9945580423Smillert struct listhead ppidlist = SLIST_HEAD_INITIALIZER(list);
10045580423Smillert struct listhead tdevlist = SLIST_HEAD_INITIALIZER(list);
10145580423Smillert struct listhead sidlist = SLIST_HEAD_INITIALIZER(list);
1021b2463c8Smarkus struct listhead rtablist = SLIST_HEAD_INITIALIZER(list);
10345580423Smillert
10465e8c1ceSgsoares static void __dead usage(void);
10565e8c1ceSgsoares static int killact(struct kinfo_proc *, int);
10665e8c1ceSgsoares static int grepact(struct kinfo_proc *, int);
10765e8c1ceSgsoares static void makelist(struct listhead *, enum listtype, char *);
10865e8c1ceSgsoares static char *getargv(struct kinfo_proc *);
10965e8c1ceSgsoares static int askyn(struct kinfo_proc *);
11045580423Smillert
11145580423Smillert extern char *__progname;
11245580423Smillert
11365e8c1ceSgsoares static char *
getargv(struct kinfo_proc * kp)114e880abb2Stedu getargv(struct kinfo_proc *kp)
115e880abb2Stedu {
116e880abb2Stedu static char buf[_POSIX2_LINE_MAX];
117e880abb2Stedu char **pargv;
118e880abb2Stedu size_t j;
119e880abb2Stedu
120e880abb2Stedu if ((pargv = kvm_getargv(kd, kp, 0)) == NULL) {
121e880abb2Stedu strlcpy(buf, kp->p_comm, sizeof(buf));
122e880abb2Stedu return buf;
123e880abb2Stedu }
124e880abb2Stedu
125e880abb2Stedu j = 0;
126e880abb2Stedu while (j < sizeof(buf) && *pargv != NULL) {
127e880abb2Stedu int ret;
128e880abb2Stedu
129e880abb2Stedu ret = snprintf(buf + j, sizeof(buf) - j,
130e880abb2Stedu pargv[1] != NULL ? "%s " : "%s", pargv[0]);
131e880abb2Stedu if (ret >= sizeof(buf) - j)
132e880abb2Stedu j += sizeof(buf) - j - 1;
133e880abb2Stedu else if (ret > 0)
134e880abb2Stedu j += ret;
135e880abb2Stedu pargv++;
136e880abb2Stedu }
137e880abb2Stedu return buf;
138e880abb2Stedu }
139e880abb2Stedu
14045580423Smillert int
main(int argc,char ** argv)14145580423Smillert main(int argc, char **argv)
14245580423Smillert {
143e880abb2Stedu char buf[_POSIX2_LINE_MAX], *mstr, *p, *q;
14445580423Smillert int i, j, ch, bestidx, rv, criteria;
1455027561dSguenther int (*action)(struct kinfo_proc *, int);
1465027561dSguenther struct kinfo_proc *kp;
14745580423Smillert struct list *li;
1481bbd613dSmillert u_int32_t bestsec, bestusec;
14945580423Smillert regex_t reg;
15045580423Smillert regmatch_t regmatch;
15145580423Smillert
15245580423Smillert if (strcmp(__progname, "pgrep") == 0) {
15345580423Smillert action = grepact;
15445580423Smillert pgrep = 1;
15545580423Smillert } else {
15645580423Smillert action = killact;
1571bbd613dSmillert p = argv[1];
15845580423Smillert
1591bbd613dSmillert if (argc > 1 && p[0] == '-') {
1601bbd613dSmillert p++;
1611bbd613dSmillert i = (int)strtol(p, &q, 10);
16245580423Smillert if (*q == '\0') {
16345580423Smillert signum = i;
16445580423Smillert argv++;
16545580423Smillert argc--;
16645580423Smillert } else {
1671bbd613dSmillert if (strncasecmp(p, "sig", 3) == 0)
1681bbd613dSmillert p += 3;
16945580423Smillert for (i = 1; i < NSIG; i++)
1701bbd613dSmillert if (strcasecmp(sys_signame[i], p) == 0)
17145580423Smillert break;
17245580423Smillert if (i != NSIG) {
17345580423Smillert signum = i;
17445580423Smillert argv++;
17545580423Smillert argc--;
17645580423Smillert }
17745580423Smillert }
17845580423Smillert }
17945580423Smillert }
18045580423Smillert
18145580423Smillert criteria = 0;
18245580423Smillert
183e880abb2Stedu while ((ch = getopt(argc, argv, "G:P:T:U:d:fg:Ilnoqs:t:u:vx")) != -1)
18445580423Smillert switch (ch) {
18545580423Smillert case 'G':
18645580423Smillert makelist(&rgidlist, LT_GROUP, optarg);
18745580423Smillert criteria = 1;
18845580423Smillert break;
18945580423Smillert case 'P':
19045580423Smillert makelist(&ppidlist, LT_GENERIC, optarg);
19145580423Smillert criteria = 1;
19245580423Smillert break;
1931b2463c8Smarkus case 'T':
1941b2463c8Smarkus makelist(&rtablist, LT_RTABLE, optarg);
1951b2463c8Smarkus criteria = 1;
1961b2463c8Smarkus break;
19745580423Smillert case 'U':
19845580423Smillert makelist(&ruidlist, LT_USER, optarg);
19945580423Smillert criteria = 1;
20045580423Smillert break;
20145580423Smillert case 'd':
20245580423Smillert if (!pgrep)
20345580423Smillert usage();
20445580423Smillert delim = optarg;
20545580423Smillert break;
20645580423Smillert case 'f':
20745580423Smillert matchargs = 1;
20845580423Smillert break;
20945580423Smillert case 'g':
21045580423Smillert makelist(&pgrplist, LT_PGRP, optarg);
21145580423Smillert criteria = 1;
21245580423Smillert break;
213e880abb2Stedu case 'I':
214e880abb2Stedu confirmkill = 1;
215e880abb2Stedu break;
21645580423Smillert case 'l':
21745580423Smillert longfmt = 1;
21845580423Smillert break;
21945580423Smillert case 'n':
22045580423Smillert newest = 1;
22145580423Smillert criteria = 1;
22245580423Smillert break;
22383d16d5cSmillert case 'o':
22483d16d5cSmillert oldest = 1;
22583d16d5cSmillert criteria = 1;
22683d16d5cSmillert break;
227d2e6cab4Sespie case 'q':
228d2e6cab4Sespie quiet = 1;
229d2e6cab4Sespie break;
23045580423Smillert case 's':
23145580423Smillert makelist(&sidlist, LT_SID, optarg);
23245580423Smillert criteria = 1;
23345580423Smillert break;
23445580423Smillert case 't':
23545580423Smillert makelist(&tdevlist, LT_TTY, optarg);
23645580423Smillert criteria = 1;
23745580423Smillert break;
23845580423Smillert case 'u':
23945580423Smillert makelist(&euidlist, LT_USER, optarg);
24045580423Smillert criteria = 1;
24145580423Smillert break;
24245580423Smillert case 'v':
24345580423Smillert inverse = 1;
24445580423Smillert break;
24545580423Smillert case 'x':
24645580423Smillert fullmatch = 1;
24745580423Smillert break;
24845580423Smillert default:
24945580423Smillert usage();
25045580423Smillert /* NOTREACHED */
25145580423Smillert }
25245580423Smillert
25345580423Smillert argc -= optind;
25445580423Smillert argv += optind;
25545580423Smillert if (argc != 0)
25645580423Smillert criteria = 1;
25783d16d5cSmillert if (!criteria || (newest && oldest))
25845580423Smillert usage();
25945580423Smillert
26045580423Smillert mypid = getpid();
26145580423Smillert
26245580423Smillert /*
26345580423Smillert * Retrieve the list of running processes from the kernel.
26445580423Smillert */
26545580423Smillert kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, buf);
26645580423Smillert if (kd == NULL)
26745580423Smillert errx(STATUS_ERROR, "kvm_openfiles(): %s", buf);
26845580423Smillert
2695027561dSguenther plist = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(*plist), &nproc);
27045580423Smillert if (plist == NULL)
2715027561dSguenther errx(STATUS_ERROR, "kvm_getprocs() failed");
27245580423Smillert
2735c17cc01Sderaadt if (matchargs == 0 && confirmkill == 0) {
2745c17cc01Sderaadt if (action == killact) {
2755c17cc01Sderaadt if (pledge("stdio proc", NULL) == -1)
27665e8c1ceSgsoares err(STATUS_ERROR, "pledge");
2775c17cc01Sderaadt } else if (action == grepact) {
2785c17cc01Sderaadt if (pledge("stdio", NULL) == -1)
27965e8c1ceSgsoares err(STATUS_ERROR, "pledge");
2805c17cc01Sderaadt }
2815c17cc01Sderaadt }
282814f35abSderaadt
28345580423Smillert /*
28445580423Smillert * Allocate memory which will be used to keep track of the
28545580423Smillert * selection.
28645580423Smillert */
287db4177c9Stedu if ((selected = calloc(nproc, 1)) == NULL)
28845580423Smillert errx(STATUS_ERROR, "memory allocation failure");
28945580423Smillert
29045580423Smillert /*
29145580423Smillert * Refine the selection.
29245580423Smillert */
29345580423Smillert for (; *argv != NULL; argv++) {
294e2f012a0Srobert if ((rv = regcomp(®, *argv, REG_EXTENDED)) != 0) {
29545580423Smillert regerror(rv, ®, buf, sizeof(buf));
29645580423Smillert errx(STATUS_BADUSAGE, "bad expression: %s", buf);
29745580423Smillert }
29845580423Smillert
29945580423Smillert for (i = 0, kp = plist; i < nproc; i++, kp++) {
3000f1976c8Sguenther if (kp->p_pid == mypid)
30145580423Smillert continue;
30245580423Smillert
303e880abb2Stedu if (matchargs)
304e880abb2Stedu mstr = getargv(kp);
305e880abb2Stedu else
3061bbd613dSmillert mstr = kp->p_comm;
30745580423Smillert
30845580423Smillert rv = regexec(®, mstr, 1, ®match, 0);
30945580423Smillert if (rv == 0) {
31045580423Smillert if (fullmatch) {
31145580423Smillert if (regmatch.rm_so == 0 &&
31245580423Smillert regmatch.rm_eo == strlen(mstr))
31345580423Smillert selected[i] = 1;
31445580423Smillert } else
31545580423Smillert selected[i] = 1;
31645580423Smillert } else if (rv != REG_NOMATCH) {
31745580423Smillert regerror(rv, ®, buf, sizeof(buf));
31845580423Smillert errx(STATUS_ERROR, "regexec(): %s", buf);
31945580423Smillert }
32045580423Smillert }
32145580423Smillert
32245580423Smillert regfree(®);
32345580423Smillert }
32445580423Smillert
32545580423Smillert for (i = 0, kp = plist; i < nproc; i++, kp++) {
3260f1976c8Sguenther if (kp->p_pid == mypid)
32745580423Smillert continue;
32845580423Smillert
32945580423Smillert SLIST_FOREACH(li, &ruidlist, li_chain)
3301bbd613dSmillert if (kp->p_ruid == (uid_t)li->li_number)
33145580423Smillert break;
33245580423Smillert if (SLIST_FIRST(&ruidlist) != NULL && li == NULL) {
33345580423Smillert selected[i] = 0;
33445580423Smillert continue;
33545580423Smillert }
33645580423Smillert
33745580423Smillert SLIST_FOREACH(li, &rgidlist, li_chain)
3381bbd613dSmillert if (kp->p_rgid == (gid_t)li->li_number)
33945580423Smillert break;
34045580423Smillert if (SLIST_FIRST(&rgidlist) != NULL && li == NULL) {
34145580423Smillert selected[i] = 0;
34245580423Smillert continue;
34345580423Smillert }
34445580423Smillert
34545580423Smillert SLIST_FOREACH(li, &euidlist, li_chain)
3461bbd613dSmillert if (kp->p_uid == (uid_t)li->li_number)
34745580423Smillert break;
34845580423Smillert if (SLIST_FIRST(&euidlist) != NULL && li == NULL) {
34945580423Smillert selected[i] = 0;
35045580423Smillert continue;
35145580423Smillert }
35245580423Smillert
35345580423Smillert SLIST_FOREACH(li, &ppidlist, li_chain)
3541bbd613dSmillert if (kp->p_ppid == (uid_t)li->li_number)
35545580423Smillert break;
35645580423Smillert if (SLIST_FIRST(&ppidlist) != NULL && li == NULL) {
35745580423Smillert selected[i] = 0;
35845580423Smillert continue;
35945580423Smillert }
36045580423Smillert
36145580423Smillert SLIST_FOREACH(li, &pgrplist, li_chain)
3621bbd613dSmillert if (kp->p__pgid == (uid_t)li->li_number)
36345580423Smillert break;
36445580423Smillert if (SLIST_FIRST(&pgrplist) != NULL && li == NULL) {
36545580423Smillert selected[i] = 0;
36645580423Smillert continue;
36745580423Smillert }
36845580423Smillert
36945580423Smillert SLIST_FOREACH(li, &tdevlist, li_chain) {
37045580423Smillert if (li->li_number == -1 &&
371447f61ceSguenther (kp->p_psflags & PS_CONTROLT) == 0)
37245580423Smillert break;
3731bbd613dSmillert if (kp->p_tdev == (uid_t)li->li_number)
37445580423Smillert break;
37545580423Smillert }
37645580423Smillert if (SLIST_FIRST(&tdevlist) != NULL && li == NULL) {
37745580423Smillert selected[i] = 0;
37845580423Smillert continue;
37945580423Smillert }
38045580423Smillert
38145580423Smillert SLIST_FOREACH(li, &sidlist, li_chain)
3821bbd613dSmillert if (kp->p_sid == (uid_t)li->li_number)
38345580423Smillert break;
38445580423Smillert if (SLIST_FIRST(&sidlist) != NULL && li == NULL) {
38545580423Smillert selected[i] = 0;
38645580423Smillert continue;
38745580423Smillert }
38845580423Smillert
3891b2463c8Smarkus SLIST_FOREACH(li, &rtablist, li_chain)
3901b2463c8Smarkus if (kp->p_rtableid == (u_int32_t)li->li_number)
3911b2463c8Smarkus break;
3921b2463c8Smarkus if (SLIST_FIRST(&rtablist) != NULL && li == NULL) {
3931b2463c8Smarkus selected[i] = 0;
3941b2463c8Smarkus continue;
3951b2463c8Smarkus }
3961b2463c8Smarkus
39745580423Smillert if (argc == 0)
39845580423Smillert selected[i] = 1;
39945580423Smillert }
40045580423Smillert
40183d16d5cSmillert if (newest || oldest) {
40245580423Smillert bestidx = -1;
40345580423Smillert
40483d16d5cSmillert if (newest)
40583d16d5cSmillert bestsec = bestusec = 0;
40683d16d5cSmillert else
40783d16d5cSmillert bestsec = bestusec = UINT32_MAX;
40883d16d5cSmillert
40945580423Smillert for (i = 0, kp = plist; i < nproc; i++, kp++) {
41045580423Smillert if (!selected[i])
41145580423Smillert continue;
41245580423Smillert
41383d16d5cSmillert if ((newest && (kp->p_ustart_sec > bestsec ||
4141bbd613dSmillert (kp->p_ustart_sec == bestsec
41583d16d5cSmillert && kp->p_ustart_usec > bestusec)))
41683d16d5cSmillert || (oldest && (kp->p_ustart_sec < bestsec ||
41783d16d5cSmillert (kp->p_ustart_sec == bestsec
41883d16d5cSmillert && kp->p_ustart_usec < bestusec)))) {
41983d16d5cSmillert
4201bbd613dSmillert bestsec = kp->p_ustart_sec;
4211bbd613dSmillert bestusec = kp->p_ustart_usec;
42245580423Smillert bestidx = i;
42345580423Smillert }
42445580423Smillert }
42545580423Smillert
42645580423Smillert memset(selected, 0, nproc);
42745580423Smillert if (bestidx != -1)
42845580423Smillert selected[bestidx] = 1;
42945580423Smillert }
43045580423Smillert
43145580423Smillert /*
43245580423Smillert * Take the appropriate action for each matched process, if any.
43345580423Smillert */
434b6c33612Smillert rv = STATUS_NOMATCH;
435b6c33612Smillert for (i = 0, j = 0, kp = plist; i < nproc; i++, kp++) {
4360f1976c8Sguenther if (kp->p_pid == mypid)
43745580423Smillert continue;
43804bf3307Shalex if (selected[i] == inverse)
43945580423Smillert continue;
44045580423Smillert
441a33a3c03Shalex switch ((*action)(kp, j++)) {
442a33a3c03Shalex case STATUS_MATCH:
443a33a3c03Shalex if (rv != STATUS_ERROR)
4440f5777d4Smillert rv = STATUS_MATCH;
445a33a3c03Shalex break;
446a33a3c03Shalex case STATUS_NOMATCH:
447a33a3c03Shalex j--;
448a33a3c03Shalex break;
449a33a3c03Shalex case STATUS_ERROR:
450a33a3c03Shalex rv = STATUS_ERROR;
451a33a3c03Shalex break;
452a33a3c03Shalex }
45345580423Smillert }
454d2e6cab4Sespie if (pgrep && j && !quiet)
455b6c33612Smillert putchar('\n');
45645580423Smillert
45765e8c1ceSgsoares return(rv);
45845580423Smillert }
45945580423Smillert
46065e8c1ceSgsoares static void __dead
usage(void)46145580423Smillert usage(void)
46245580423Smillert {
46345580423Smillert const char *ustr;
46445580423Smillert
46545580423Smillert if (pgrep)
466dbc30627Sajacoutot ustr = "[-flnoqvx] [-d delim]";
46745580423Smillert else
468e880abb2Stedu ustr = "[-signal] [-fIlnoqvx]";
46945580423Smillert
4700ecd6060Sjmc fprintf(stderr, "usage: %s %s [-G gid] [-g pgrp] [-P ppid] [-s sid]"
4712e74a01cSjmc "\n\t[-T rtable] [-t tty] [-U uid] [-u euid] [pattern ...]\n",
4721b2463c8Smarkus __progname, ustr);
47345580423Smillert
4741e77ae25Sjmc exit(STATUS_BADUSAGE);
47545580423Smillert }
47645580423Smillert
47765e8c1ceSgsoares static int
askyn(struct kinfo_proc * kp)478e880abb2Stedu askyn(struct kinfo_proc *kp)
479e880abb2Stedu {
480e880abb2Stedu int first, ch;
481e880abb2Stedu
482e880abb2Stedu printf("kill %d %.60s? ", (int)kp->p_pid, getargv(kp));
483e880abb2Stedu fflush(stdout);
484e880abb2Stedu
485e880abb2Stedu first = ch = getchar();
486e880abb2Stedu while (ch != '\n' && ch != EOF)
487e880abb2Stedu ch = getchar();
488e880abb2Stedu return (first == 'y' || first == 'Y');
489e880abb2Stedu }
490e880abb2Stedu
49165e8c1ceSgsoares static int
killact(struct kinfo_proc * kp,int dummy)4925027561dSguenther killact(struct kinfo_proc *kp, int dummy)
49345580423Smillert {
494e880abb2Stedu int doit;
495e880abb2Stedu
496e880abb2Stedu if (confirmkill) {
497e880abb2Stedu doit = askyn(kp);
498e880abb2Stedu } else {
499d2e6cab4Sespie if (longfmt && !quiet)
50004bf3307Shalex printf("%d %s\n", (int)kp->p_pid, kp->p_comm);
501e880abb2Stedu doit = 1;
502e880abb2Stedu }
50345580423Smillert
504e880abb2Stedu if (doit && kill(kp->p_pid, signum) == -1) {
505a33a3c03Shalex if (errno == ESRCH)
506a33a3c03Shalex return (STATUS_NOMATCH);
5070f5777d4Smillert warn("signalling pid %d", (int)kp->p_pid);
508a33a3c03Shalex return (STATUS_ERROR);
5090f5777d4Smillert }
510a33a3c03Shalex return (STATUS_MATCH);
51145580423Smillert }
51245580423Smillert
51365e8c1ceSgsoares static int
grepact(struct kinfo_proc * kp,int printdelim)5145027561dSguenther grepact(struct kinfo_proc *kp, int printdelim)
51545580423Smillert {
51645580423Smillert char **argv;
51745580423Smillert
518d2e6cab4Sespie if (quiet)
519a33a3c03Shalex return (STATUS_MATCH);
520a33a3c03Shalex if (longfmt && matchargs)
521a33a3c03Shalex if ((argv = kvm_getargv(kd, kp, 0)) == NULL)
522a33a3c03Shalex return (errno == ESRCH ? STATUS_NOMATCH : STATUS_ERROR);
523b6c33612Smillert if (printdelim)
524b6c33612Smillert fputs(delim, stdout);
52545580423Smillert if (longfmt && matchargs) {
5261bbd613dSmillert printf("%d ", (int)kp->p_pid);
52745580423Smillert for (; *argv != NULL; argv++) {
52845580423Smillert printf("%s", *argv);
52945580423Smillert if (argv[1] != NULL)
53045580423Smillert putchar(' ');
53145580423Smillert }
53245580423Smillert } else if (longfmt)
5331bbd613dSmillert printf("%d %s", (int)kp->p_pid, kp->p_comm);
53445580423Smillert else
5351bbd613dSmillert printf("%d", (int)kp->p_pid);
53645580423Smillert
537a33a3c03Shalex return (STATUS_MATCH);
53845580423Smillert }
53945580423Smillert
54065e8c1ceSgsoares static void
makelist(struct listhead * head,enum listtype type,char * src)54145580423Smillert makelist(struct listhead *head, enum listtype type, char *src)
54245580423Smillert {
54345580423Smillert struct list *li;
54445580423Smillert struct stat st;
545b9fc9a72Sderaadt char *sp, *p, buf[PATH_MAX];
546a0f924b8Smillert uid_t uid;
547a0f924b8Smillert gid_t gid;
54845580423Smillert int empty;
54945580423Smillert
55045580423Smillert empty = 1;
55145580423Smillert
55245580423Smillert while ((sp = strsep(&src, ",")) != NULL) {
55345580423Smillert if (*sp == '\0')
55445580423Smillert usage();
55545580423Smillert
55645580423Smillert if ((li = malloc(sizeof(*li))) == NULL)
55745580423Smillert errx(STATUS_ERROR, "memory allocation failure");
55845580423Smillert SLIST_INSERT_HEAD(head, li, li_chain);
55945580423Smillert empty = 0;
56045580423Smillert
5611b2463c8Smarkus li->li_number = strtol(sp, &p, 0);
56245580423Smillert if (*p == '\0') {
56345580423Smillert switch (type) {
56445580423Smillert case LT_PGRP:
56545580423Smillert if (li->li_number == 0)
56645580423Smillert li->li_number = getpgrp();
56745580423Smillert break;
56845580423Smillert case LT_SID:
56945580423Smillert if (li->li_number == 0)
57045580423Smillert li->li_number = getsid(mypid);
57145580423Smillert break;
5721b2463c8Smarkus case LT_RTABLE:
5731b2463c8Smarkus if (li->li_number < 0 ||
5741b2463c8Smarkus li->li_number > RT_TABLEID_MAX)
5751b2463c8Smarkus errx(STATUS_BADUSAGE,
5761b2463c8Smarkus "rtable out of range");
5771b2463c8Smarkus break;
57845580423Smillert case LT_TTY:
57945580423Smillert usage();
58045580423Smillert default:
58145580423Smillert break;
58245580423Smillert }
58345580423Smillert continue;
58445580423Smillert }
58545580423Smillert
58645580423Smillert switch (type) {
58745580423Smillert case LT_USER:
588a0f924b8Smillert if (uid_from_user(sp, &uid) == -1)
58985308c32Sotto errx(STATUS_BADUSAGE, "unknown user `%s'", sp);
590a0f924b8Smillert li->li_number = uid;
59145580423Smillert break;
59245580423Smillert case LT_GROUP:
593a0f924b8Smillert if (gid_from_group(sp, &gid) == -1)
59485308c32Sotto errx(STATUS_BADUSAGE, "unknown group `%s'", sp);
595a0f924b8Smillert li->li_number = gid;
59645580423Smillert break;
59745580423Smillert case LT_TTY:
59845580423Smillert if (strcmp(sp, "-") == 0) {
59945580423Smillert li->li_number = -1;
60045580423Smillert break;
60145580423Smillert } else if (strcmp(sp, "co") == 0)
60245580423Smillert p = "console";
60345580423Smillert else if (strncmp(sp, "tty", 3) == 0)
60445580423Smillert p = sp;
60545580423Smillert else
60645580423Smillert p = NULL;
60745580423Smillert
60845580423Smillert if (p == NULL)
60945580423Smillert snprintf(buf, sizeof(buf), "/dev/tty%s", sp);
61045580423Smillert else
61145580423Smillert snprintf(buf, sizeof(buf), "/dev/%s", p);
61245580423Smillert
6133aaa63ebSderaadt if (stat(buf, &st) == -1) {
61445580423Smillert if (errno == ENOENT)
61545580423Smillert errx(STATUS_BADUSAGE,
61645580423Smillert "no such tty: `%s'", sp);
61745580423Smillert err(STATUS_ERROR, "stat(%s)", sp);
61845580423Smillert }
61945580423Smillert
620dc8143a2Sotto if (!S_ISCHR(st.st_mode))
62145580423Smillert errx(STATUS_BADUSAGE, "not a tty: `%s'", sp);
62245580423Smillert
62345580423Smillert li->li_number = st.st_rdev;
62445580423Smillert break;
62545580423Smillert default:
62645580423Smillert usage();
627522cf29cSderaadt }
62845580423Smillert }
62945580423Smillert
63045580423Smillert if (empty)
63145580423Smillert usage();
63245580423Smillert }
633