1 /* $NetBSD: pkill.c,v 1.16 2005/10/10 22:13:20 kleink Exp $ */
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
8 * This code is derived from software contributed to The NetBSD Foundation
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
32 * $FreeBSD: head/bin/pkill/pkill.c 256050 2013-10-04 16:08:44Z trasz $
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/sysctl.h>
39 #include <sys/queue.h>
41 #include <sys/fcntl.h>
62 #define STATUS_MATCH 0
63 #define STATUS_NOMATCH 1
64 #define STATUS_BADUSAGE 2
65 #define STATUS_ERROR 3
68 #define MAX_PID PID_MAX
70 /* Ignore system-processes (if '-S' flag is not specified) and myself. */
71 #define PSKIP(kp) ((kp)->kp_pid == mypid || \
72 (!kthreads && (kp)->kp_pid <= 0))
86 SLIST_ENTRY(list
) li_chain
;
91 SLIST_HEAD(listhead
, list
);
93 static struct kinfo_proc
*plist
;
94 static char *selected
;
95 static const char *delim
= "\n";
98 static int signum
= SIGTERM
;
101 static int interactive
;
104 static int matchargs
;
105 static int fullmatch
;
107 static int cflags
= REG_EXTENDED
;
112 static struct listhead euidlist
= SLIST_HEAD_INITIALIZER(euidlist
);
113 static struct listhead ruidlist
= SLIST_HEAD_INITIALIZER(ruidlist
);
114 static struct listhead rgidlist
= SLIST_HEAD_INITIALIZER(rgidlist
);
115 static struct listhead pgrplist
= SLIST_HEAD_INITIALIZER(pgrplist
);
116 static struct listhead ppidlist
= SLIST_HEAD_INITIALIZER(ppidlist
);
117 static struct listhead tdevlist
= SLIST_HEAD_INITIALIZER(tdevlist
);
118 static struct listhead sidlist
= SLIST_HEAD_INITIALIZER(sidlist
);
119 static struct listhead jidlist
= SLIST_HEAD_INITIALIZER(jidlist
);
120 static struct listhead classlist
= SLIST_HEAD_INITIALIZER(classlist
);
122 static void usage(void) __attribute__((__noreturn__
));
123 static int killact(const struct kinfo_proc
*);
124 static int grepact(const struct kinfo_proc
*);
125 static void makelist(struct listhead
*, enum listtype
, char *);
126 static int takepid(const char *, int);
129 main(int argc
, char **argv
)
131 char buf
[_POSIX2_LINE_MAX
], *mstr
, **pargv
, *p
, *q
, *pidfile
;
132 const char *execf
, *coref
;
133 int ancestors
, debug_opt
, did_action
;
134 int i
, ch
, bestidx
, rv
, criteria
, pidfromfile
, pidfilelock
;
136 int (*action
)(const struct kinfo_proc
*);
137 struct kinfo_proc
*kp
;
139 struct timeval best_tval
;
144 setlocale(LC_ALL
, "");
146 if (strcmp(getprogname(), "pgrep") == 0) {
153 if (argc
> 1 && p
[0] == '-') {
155 i
= (int)strtol(p
, &q
, 10);
161 if (strncasecmp(p
, "SIG", 3) == 0)
163 for (i
= 1; i
< NSIG
; i
++)
164 if (strcasecmp(sys_signame
[i
], p
) == 0)
182 coref
= _PATH_DEVNULL
;
184 while ((ch
= getopt(argc
, argv
, "DF:G:ILM:N:P:SU:ac:d:fg:ij:lnoqs:t:u:vx")) != -1)
194 makelist(&rgidlist
, LT_GROUP
, optarg
);
212 makelist(&ppidlist
, LT_GENERIC
, optarg
);
221 makelist(&ruidlist
, LT_USER
, optarg
);
228 makelist(&classlist
, LT_CLASS
, optarg
);
240 makelist(&pgrplist
, LT_PGRP
, optarg
);
247 makelist(&jidlist
, LT_JID
, optarg
);
267 makelist(&sidlist
, LT_SID
, optarg
);
271 makelist(&tdevlist
, LT_TTY
, optarg
);
275 makelist(&euidlist
, LT_USER
, optarg
);
295 if (newest
&& oldest
)
296 errx(STATUS_ERROR
, "Options -n and -o are mutually exclusive");
298 pidfromfile
= takepid(pidfile
, pidfilelock
);
302 "Option -L doesn't make sense without -F");
310 * Retrieve the list of running processes from the kernel.
312 kd
= kvm_openfiles(execf
, coref
, NULL
, O_RDONLY
, buf
);
314 errx(STATUS_ERROR
, "Cannot open kernel files (%s)", buf
);
316 if (pidfromfile
>= 0)
317 plist
= kvm_getprocs(kd
, KERN_PROC_PID
, pidfromfile
, &nproc
);
319 plist
= kvm_getprocs(kd
, KERN_PROC_ALL
, 0, &nproc
);
321 errx(STATUS_ERROR
, "Cannot get process list (%s)",
326 * Allocate memory which will be used to keep track of the
329 if ((selected
= malloc(nproc
)) == NULL
) {
330 err(STATUS_ERROR
, "Cannot allocate memory for %d processes",
333 memset(selected
, 0, nproc
);
336 * Refine the selection.
338 for (; *argv
!= NULL
; argv
++) {
339 if ((rv
= regcomp(®
, *argv
, cflags
)) != 0) {
340 regerror(rv
, ®
, buf
, sizeof(buf
));
341 errx(STATUS_BADUSAGE
,
342 "Cannot compile regular expression `%s' (%s)",
346 for (i
= 0, kp
= plist
; i
< nproc
; i
++, kp
++) {
349 fprintf(stderr
, "* Skipped %5d %3d %s\n",
350 kp
->kp_pid
, kp
->kp_uid
, kp
->kp_comm
);
355 (pargv
= kvm_getargv(kd
, kp
, 0)) != NULL
) {
357 while (jsz
< sizeof(buf
) && *pargv
!= NULL
) {
358 jsz
+= snprintf(buf
+ jsz
,
360 pargv
[1] != NULL
? "%s " : "%s",
368 rv
= regexec(®
, mstr
, 1, ®match
, 0);
371 if (regmatch
.rm_so
== 0 &&
377 } else if (rv
!= REG_NOMATCH
) {
378 regerror(rv
, ®
, buf
, sizeof(buf
));
380 "Regular expression evaluation error (%s)",
384 const char *rv_res
= "NoMatch";
387 fprintf(stderr
, "* %s %5d %3d %s\n", rv_res
,
388 kp
->kp_pid
, kp
->kp_uid
, mstr
);
395 for (i
= 0, kp
= plist
; i
< nproc
; i
++, kp
++) {
399 if (pidfromfile
>= 0 && kp
->kp_pid
!= pidfromfile
) {
404 SLIST_FOREACH(li
, &ruidlist
, li_chain
)
405 if (kp
->kp_ruid
== (uid_t
)li
->li_number
)
407 if (SLIST_FIRST(&ruidlist
) != NULL
&& li
== NULL
) {
412 SLIST_FOREACH(li
, &rgidlist
, li_chain
)
413 if (kp
->kp_rgid
== (gid_t
)li
->li_number
)
415 if (SLIST_FIRST(&rgidlist
) != NULL
&& li
== NULL
) {
420 SLIST_FOREACH(li
, &euidlist
, li_chain
)
421 if (kp
->kp_uid
== (uid_t
)li
->li_number
)
423 if (SLIST_FIRST(&euidlist
) != NULL
&& li
== NULL
) {
428 SLIST_FOREACH(li
, &ppidlist
, li_chain
)
429 if (kp
->kp_ppid
== (pid_t
)li
->li_number
)
431 if (SLIST_FIRST(&ppidlist
) != NULL
&& li
== NULL
) {
436 SLIST_FOREACH(li
, &pgrplist
, li_chain
)
437 if (kp
->kp_pgid
== (pid_t
)li
->li_number
)
439 if (SLIST_FIRST(&pgrplist
) != NULL
&& li
== NULL
) {
444 SLIST_FOREACH(li
, &tdevlist
, li_chain
) {
445 if (li
->li_number
== -1 &&
446 (kp
->kp_flags
& P_CONTROLT
) == 0)
448 if (kp
->kp_tdev
== (dev_t
)li
->li_number
)
451 if (SLIST_FIRST(&tdevlist
) != NULL
&& li
== NULL
) {
456 SLIST_FOREACH(li
, &sidlist
, li_chain
)
457 if (kp
->kp_sid
== (pid_t
)li
->li_number
)
459 if (SLIST_FIRST(&sidlist
) != NULL
&& li
== NULL
) {
464 SLIST_FOREACH(li
, &jidlist
, li_chain
) {
465 /* A particular jail ID, including 0 (not in jail) */
466 if (kp
->kp_jailid
== (int)li
->li_number
)
469 if (kp
->kp_jailid
> 0 && li
->li_number
== -1)
472 if (SLIST_FIRST(&jidlist
) != NULL
&& li
== NULL
) {
477 SLIST_FOREACH(li
, &classlist
, li_chain
) {
479 * We skip P_SYSTEM processes to match ps(1) output.
481 if ((kp
->kp_flags
& P_SYSTEM
) == 0)
484 if (SLIST_FIRST(&classlist
) != NULL
&& li
== NULL
) {
496 for (i
= 0, kp
= plist
; i
< nproc
; i
++, kp
++) {
499 if (kp
->kp_pid
== pid
) {
509 break; /* Maybe we're in a jail ? */
514 if (newest
|| oldest
) {
515 best_tval
.tv_sec
= 0;
516 best_tval
.tv_usec
= 0;
519 for (i
= 0, kp
= plist
; i
< nproc
; i
++, kp
++) {
523 /* The first entry of the list which matched. */
525 } else if (timercmp(&kp
->kp_start
, &best_tval
, >)) {
526 /* This entry is newer than previous "best". */
527 if (oldest
) /* but we want the oldest */
530 /* This entry is older than previous "best". */
531 if (newest
) /* but we want the newest */
534 /* This entry is better than previous "best" entry. */
535 best_tval
.tv_sec
= kp
->kp_start
.tv_sec
;
536 best_tval
.tv_usec
= kp
->kp_start
.tv_usec
;
540 memset(selected
, 0, nproc
);
542 selected
[bestidx
] = 1;
546 * Take the appropriate action for each matched process, if any.
549 for (i
= 0, rv
= 0, kp
= plist
; i
< nproc
; i
++, kp
++) {
553 if (longfmt
&& !pgrep
) {
555 printf("kill -%d %d\n", signum
, kp
->kp_pid
);
563 if (!did_action
&& !pgrep
&& longfmt
)
565 "No matching processes belonging to you were found\n");
567 exit(rv
? STATUS_MATCH
: STATUS_NOMATCH
);
576 ustr
= "[-LSfilnoqvx] [-d delim]";
578 ustr
= "[-signal] [-ILfilnovx]";
581 "usage: %s %s [-F pidfile] [-G gid] [-M core] [-N system]\n"
582 " [-P ppid] [-U uid] [-c class] [-g pgrp] [-j jid]\n"
583 " [-s sid] [-t tty] [-u euid] pattern ...\n",
584 getprogname(), ustr
);
586 exit(STATUS_BADUSAGE
);
590 show_process(const struct kinfo_proc
*kp
)
598 if ((longfmt
|| !pgrep
) && matchargs
&&
599 (argv
= kvm_getargv(kd
, kp
, 0)) != NULL
) {
600 printf("%d ", (int)kp
->kp_pid
);
601 for (; *argv
!= NULL
; argv
++) {
606 } else if (longfmt
|| !pgrep
)
607 printf("%d %s", (int)kp
->kp_pid
, kp
->kp_comm
);
609 printf("%d", (int)kp
->kp_pid
);
613 killact(const struct kinfo_proc
*kp
)
619 * Be careful, ask before killing.
625 first
= ch
= getchar();
626 while (ch
!= '\n' && ch
!= EOF
)
628 if (first
!= 'y' && first
!= 'Y')
631 if (kill(kp
->kp_pid
, signum
) == -1) {
633 * Check for ESRCH, which indicates that the process
634 * disappeared between us matching it and us
635 * signalling it; don't issue a warning about it.
638 warn("signalling pid %d", (int)kp
->kp_pid
);
640 * Return 0 to indicate that the process should not be
641 * considered a match, since we didn't actually get to
650 grepact(const struct kinfo_proc
*kp
)
660 makelist(struct listhead
*head
, enum listtype type
, char *src
)
667 char *sp
, *ep
, buf
[MAXPATHLEN
];
672 while ((sp
= strsep(&src
, ",")) != NULL
) {
676 if ((li
= malloc(sizeof(*li
))) == NULL
) {
677 err(STATUS_ERROR
, "Cannot allocate %zu bytes",
681 SLIST_INSERT_HEAD(head
, li
, li_chain
);
684 if (type
!= LT_CLASS
)
685 li
->li_number
= (uid_t
)strtol(sp
, &ep
, 0);
687 if (type
!= LT_CLASS
&& *ep
== '\0') {
690 if (li
->li_number
== 0)
691 li
->li_number
= getpgrp();
694 if (li
->li_number
== 0)
695 li
->li_number
= getsid(mypid
);
698 if (li
->li_number
< 0)
699 errx(STATUS_BADUSAGE
,
700 "Negative jail ID `%s'", sp
);
701 /* For compatibility with old -j */
702 if (li
->li_number
== 0)
703 li
->li_number
= -1; /* any jail */
706 if (li
->li_number
< 0)
707 errx(STATUS_BADUSAGE
,
708 "Negative /dev/pts tty `%s'", sp
);
709 snprintf(buf
, sizeof(buf
), _PATH_DEV
"pts/%s",
711 if (stat(buf
, &st
) != -1)
714 errx(STATUS_BADUSAGE
, "No such tty: `"
715 _PATH_DEV
"pts/%s'", sp
);
716 err(STATUS_ERROR
, "Cannot access `"
717 _PATH_DEV
"pts/%s'", sp
);
727 if ((pw
= getpwnam(sp
)) == NULL
)
728 errx(STATUS_BADUSAGE
, "Unknown user `%s'", sp
);
729 li
->li_number
= pw
->pw_uid
;
732 if ((gr
= getgrnam(sp
)) == NULL
)
733 errx(STATUS_BADUSAGE
, "Unknown group `%s'", sp
);
734 li
->li_number
= gr
->gr_gid
;
737 if (strcmp(sp
, "-") == 0) {
740 } else if (strcmp(sp
, "co") == 0) {
746 snprintf(buf
, sizeof(buf
), _PATH_DEV
"%s", cp
);
747 if (stat(buf
, &st
) != -1)
750 snprintf(buf
, sizeof(buf
), _PATH_DEV
"tty%s", cp
);
751 if (stat(buf
, &st
) != -1)
755 errx(STATUS_BADUSAGE
, "No such tty: `%s'", sp
);
756 err(STATUS_ERROR
, "Cannot access `%s'", sp
);
758 foundtty
: if ((st
.st_mode
& S_IFCHR
) == 0)
759 errx(STATUS_BADUSAGE
, "Not a tty: `%s'", sp
);
761 li
->li_number
= st
.st_rdev
;
764 if (strcmp(sp
, "none") == 0)
766 else if (strcmp(sp
, "any") == 0)
768 else if (*ep
!= '\0')
769 errx(STATUS_BADUSAGE
,
770 "Invalid jail ID `%s'", sp
);
774 li
->li_name
= strdup(sp
);
775 if (li
->li_name
== NULL
)
776 err(STATUS_ERROR
, "Cannot allocate memory");
788 takepid(const char *pidfile
, int pidfilelock
)
790 char *endp
, line
[BUFSIZ
];
794 fh
= fopen(pidfile
, "r");
796 err(STATUS_ERROR
, "Cannot open pidfile `%s'", pidfile
);
800 * If we can lock pidfile, this means that daemon is not
801 * running, so would be better not to kill some random process.
803 if (flock(fileno(fh
), LOCK_EX
| LOCK_NB
) == 0) {
805 errx(STATUS_ERROR
, "File '%s' can be locked", pidfile
);
807 if (errno
!= EWOULDBLOCK
) {
809 "Error while locking file '%s'", pidfile
);
814 if (fgets(line
, sizeof(line
), fh
) == NULL
) {
817 errx(STATUS_ERROR
, "Pidfile `%s' is empty", pidfile
);
820 err(STATUS_ERROR
, "Cannot read from pid file `%s'", pidfile
);
824 rval
= strtol(line
, &endp
, 10);
825 if (*endp
!= '\0' && !isspace((unsigned char)*endp
))
826 errx(STATUS_ERROR
, "Invalid pid in file `%s'", pidfile
);
827 else if (rval
< MIN_PID
|| rval
> MAX_PID
)
828 errx(STATUS_ERROR
, "Invalid pid in file `%s'", pidfile
);