xref: /freebsd/bin/pkill/pkill.c (revision 39a60cbc)
1 /*	$NetBSD: pkill.c,v 1.16 2005/10/10 22:13:20 kleink Exp $	*/
2 
3 /*-
4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
5  * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Andrew Doran.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
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.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
42 
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/sysctl.h>
46 #include <sys/proc.h>
47 #include <sys/queue.h>
48 #include <sys/stat.h>
49 #include <sys/time.h>
50 #include <sys/user.h>
51 
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <limits.h>
55 #include <paths.h>
56 #include <string.h>
57 #include <unistd.h>
58 #include <signal.h>
59 #include <regex.h>
60 #include <ctype.h>
61 #include <fcntl.h>
62 #include <kvm.h>
63 #include <err.h>
64 #include <pwd.h>
65 #include <grp.h>
66 #include <errno.h>
67 #include <locale.h>
68 
69 #define	STATUS_MATCH	0
70 #define	STATUS_NOMATCH	1
71 #define	STATUS_BADUSAGE	2
72 #define	STATUS_ERROR	3
73 
74 #define	MIN_PID	5
75 #define	MAX_PID	99999
76 
77 /* Ignore system-processes (if '-S' flag is not specified) and myself. */
78 #define	PSKIP(kp)	((kp)->ki_pid == mypid ||			\
79 			 (!kthreads && ((kp)->ki_flag & P_KTHREAD) != 0))
80 
81 enum listtype {
82 	LT_GENERIC,
83 	LT_USER,
84 	LT_GROUP,
85 	LT_TTY,
86 	LT_PGRP,
87 	LT_JID,
88 	LT_SID
89 };
90 
91 struct list {
92 	SLIST_ENTRY(list) li_chain;
93 	long	li_number;
94 };
95 
96 SLIST_HEAD(listhead, list);
97 
98 static struct kinfo_proc *plist;
99 static char	*selected;
100 static const char *delim = "\n";
101 static int	nproc;
102 static int	pgrep;
103 static int	signum = SIGTERM;
104 static int	newest;
105 static int	oldest;
106 static int	interactive;
107 static int	inverse;
108 static int	longfmt;
109 static int	matchargs;
110 static int	fullmatch;
111 static int	kthreads;
112 static int	cflags = REG_EXTENDED;
113 static kvm_t	*kd;
114 static pid_t	mypid;
115 
116 static struct listhead euidlist = SLIST_HEAD_INITIALIZER(euidlist);
117 static struct listhead ruidlist = SLIST_HEAD_INITIALIZER(ruidlist);
118 static struct listhead rgidlist = SLIST_HEAD_INITIALIZER(rgidlist);
119 static struct listhead pgrplist = SLIST_HEAD_INITIALIZER(pgrplist);
120 static struct listhead ppidlist = SLIST_HEAD_INITIALIZER(ppidlist);
121 static struct listhead tdevlist = SLIST_HEAD_INITIALIZER(tdevlist);
122 static struct listhead sidlist = SLIST_HEAD_INITIALIZER(sidlist);
123 static struct listhead jidlist = SLIST_HEAD_INITIALIZER(jidlist);
124 
125 static void	usage(void) __attribute__((__noreturn__));
126 static int	killact(const struct kinfo_proc *);
127 static int	grepact(const struct kinfo_proc *);
128 static void	makelist(struct listhead *, enum listtype, char *);
129 static int	takepid(const char *, int);
130 
131 int
132 main(int argc, char **argv)
133 {
134 	char buf[_POSIX2_LINE_MAX], *mstr, **pargv, *p, *q, *pidfile;
135 	const char *execf, *coref;
136 	int ancestors, debug_opt;
137 	int i, ch, bestidx, rv, criteria, pidfromfile, pidfilelock;
138 	size_t jsz;
139 	int (*action)(const struct kinfo_proc *);
140 	struct kinfo_proc *kp;
141 	struct list *li;
142 	struct timeval best_tval;
143 	regex_t reg;
144 	regmatch_t regmatch;
145 	pid_t pid;
146 
147 	setlocale(LC_ALL, "");
148 
149 	if (strcmp(getprogname(), "pgrep") == 0) {
150 		action = grepact;
151 		pgrep = 1;
152 	} else {
153 		action = killact;
154 		p = argv[1];
155 
156 		if (argc > 1 && p[0] == '-') {
157 			p++;
158 			i = (int)strtol(p, &q, 10);
159 			if (*q == '\0') {
160 				signum = i;
161 				argv++;
162 				argc--;
163 			} else {
164 				if (strncasecmp(p, "sig", 3) == 0)
165 					p += 3;
166 				for (i = 1; i < NSIG; i++)
167 					if (strcasecmp(sys_signame[i], p) == 0)
168 						break;
169 				if (i != NSIG) {
170 					signum = i;
171 					argv++;
172 					argc--;
173 				}
174 			}
175 		}
176 	}
177 
178 	ancestors = 0;
179 	criteria = 0;
180 	debug_opt = 0;
181 	pidfile = NULL;
182 	pidfilelock = 0;
183 	execf = coref = _PATH_DEVNULL;
184 
185 	while ((ch = getopt(argc, argv, "DF:G:ILM:N:P:SU:ad:fg:ij:lnos:t:u:vx")) != -1)
186 		switch (ch) {
187 		case 'D':
188 			debug_opt++;
189 			break;
190 		case 'F':
191 			pidfile = optarg;
192 			criteria = 1;
193 			break;
194 		case 'G':
195 			makelist(&rgidlist, LT_GROUP, optarg);
196 			criteria = 1;
197 			break;
198 		case 'I':
199 			if (pgrep)
200 				usage();
201 			interactive = 1;
202 			break;
203 		case 'L':
204 			pidfilelock = 1;
205 			break;
206 		case 'M':
207 			coref = optarg;
208 			break;
209 		case 'N':
210 			execf = optarg;
211 			break;
212 		case 'P':
213 			makelist(&ppidlist, LT_GENERIC, optarg);
214 			criteria = 1;
215 			break;
216 		case 'S':
217 			if (!pgrep)
218 				usage();
219 			kthreads = 1;
220 			break;
221 		case 'U':
222 			makelist(&ruidlist, LT_USER, optarg);
223 			criteria = 1;
224 			break;
225 		case 'a':
226 			ancestors++;
227 			break;
228 		case 'd':
229 			if (!pgrep)
230 				usage();
231 			delim = optarg;
232 			break;
233 		case 'f':
234 			matchargs = 1;
235 			break;
236 		case 'g':
237 			makelist(&pgrplist, LT_PGRP, optarg);
238 			criteria = 1;
239 			break;
240 		case 'i':
241 			cflags |= REG_ICASE;
242 			break;
243 		case 'j':
244 			makelist(&jidlist, LT_JID, optarg);
245 			criteria = 1;
246 			break;
247 		case 'l':
248 			if (!pgrep)
249 				usage();
250 			longfmt = 1;
251 			break;
252 		case 'n':
253 			newest = 1;
254 			criteria = 1;
255 			break;
256 		case 'o':
257 			oldest = 1;
258 			criteria = 1;
259 			break;
260 		case 's':
261 			makelist(&sidlist, LT_SID, optarg);
262 			criteria = 1;
263 			break;
264 		case 't':
265 			makelist(&tdevlist, LT_TTY, optarg);
266 			criteria = 1;
267 			break;
268 		case 'u':
269 			makelist(&euidlist, LT_USER, optarg);
270 			criteria = 1;
271 			break;
272 		case 'v':
273 			inverse = 1;
274 			break;
275 		case 'x':
276 			fullmatch = 1;
277 			break;
278 		default:
279 			usage();
280 			/* NOTREACHED */
281 		}
282 
283 	argc -= optind;
284 	argv += optind;
285 	if (argc != 0)
286 		criteria = 1;
287 	if (!criteria)
288 		usage();
289 	if (newest && oldest)
290 		errx(STATUS_ERROR, "Options -n and -o are mutually exclusive");
291 	if (pidfile != NULL)
292 		pidfromfile = takepid(pidfile, pidfilelock);
293 	else {
294 		if (pidfilelock) {
295 			errx(STATUS_ERROR,
296 			    "Option -L doesn't make sense without -F");
297 		}
298 		pidfromfile = -1;
299 	}
300 
301 	mypid = getpid();
302 
303 	/*
304 	 * Retrieve the list of running processes from the kernel.
305 	 */
306 	kd = kvm_openfiles(execf, coref, NULL, O_RDONLY, buf);
307 	if (kd == NULL)
308 		errx(STATUS_ERROR, "Cannot open kernel files (%s)", buf);
309 
310 	/*
311 	 * Use KERN_PROC_PROC instead of KERN_PROC_ALL, since we
312 	 * just want processes and not individual kernel threads.
313 	 */
314 	plist = kvm_getprocs(kd, KERN_PROC_PROC, 0, &nproc);
315 	if (plist == NULL) {
316 		errx(STATUS_ERROR, "Cannot get process list (%s)",
317 		    kvm_geterr(kd));
318 	}
319 
320 	/*
321 	 * Allocate memory which will be used to keep track of the
322 	 * selection.
323 	 */
324 	if ((selected = malloc(nproc)) == NULL) {
325 		err(STATUS_ERROR, "Cannot allocate memory for %d processes",
326 		    nproc);
327 	}
328 	memset(selected, 0, nproc);
329 
330 	/*
331 	 * Refine the selection.
332 	 */
333 	for (; *argv != NULL; argv++) {
334 		if ((rv = regcomp(&reg, *argv, cflags)) != 0) {
335 			regerror(rv, &reg, buf, sizeof(buf));
336 			errx(STATUS_BADUSAGE,
337 			    "Cannot compile regular expression `%s' (%s)",
338 			    *argv, buf);
339 		}
340 
341 		for (i = 0, kp = plist; i < nproc; i++, kp++) {
342 			if (PSKIP(kp)) {
343 				if (debug_opt > 0)
344 				    fprintf(stderr, "* Skipped %5d %3d %s\n",
345 					kp->ki_pid, kp->ki_uid, kp->ki_comm);
346 				continue;
347 			}
348 
349 			if (matchargs &&
350 			    (pargv = kvm_getargv(kd, kp, 0)) != NULL) {
351 				jsz = 0;
352 				while (jsz < sizeof(buf) && *pargv != NULL) {
353 					jsz += snprintf(buf + jsz,
354 					    sizeof(buf) - jsz,
355 					    pargv[1] != NULL ? "%s " : "%s",
356 					    pargv[0]);
357 					pargv++;
358 				}
359 				mstr = buf;
360 			} else
361 				mstr = kp->ki_comm;
362 
363 			rv = regexec(&reg, mstr, 1, &regmatch, 0);
364 			if (rv == 0) {
365 				if (fullmatch) {
366 					if (regmatch.rm_so == 0 &&
367 					    regmatch.rm_eo ==
368 					    (off_t)strlen(mstr))
369 						selected[i] = 1;
370 				} else
371 					selected[i] = 1;
372 			} else if (rv != REG_NOMATCH) {
373 				regerror(rv, &reg, buf, sizeof(buf));
374 				errx(STATUS_ERROR,
375 				    "Regular expression evaluation error (%s)",
376 				    buf);
377 			}
378 			if (debug_opt > 1) {
379 				const char *rv_res = "NoMatch";
380 				if (selected[i])
381 					rv_res = "Matched";
382 				fprintf(stderr, "* %s %5d %3d %s\n", rv_res,
383 				    kp->ki_pid, kp->ki_uid, mstr);
384 			}
385 		}
386 
387 		regfree(&reg);
388 	}
389 
390 	for (i = 0, kp = plist; i < nproc; i++, kp++) {
391 		if (PSKIP(kp))
392 			continue;
393 
394 		if (pidfromfile >= 0 && kp->ki_pid != pidfromfile) {
395 			selected[i] = 0;
396 			continue;
397 		}
398 
399 		SLIST_FOREACH(li, &ruidlist, li_chain)
400 			if (kp->ki_ruid == (uid_t)li->li_number)
401 				break;
402 		if (SLIST_FIRST(&ruidlist) != NULL && li == NULL) {
403 			selected[i] = 0;
404 			continue;
405 		}
406 
407 		SLIST_FOREACH(li, &rgidlist, li_chain)
408 			if (kp->ki_rgid == (gid_t)li->li_number)
409 				break;
410 		if (SLIST_FIRST(&rgidlist) != NULL && li == NULL) {
411 			selected[i] = 0;
412 			continue;
413 		}
414 
415 		SLIST_FOREACH(li, &euidlist, li_chain)
416 			if (kp->ki_uid == (uid_t)li->li_number)
417 				break;
418 		if (SLIST_FIRST(&euidlist) != NULL && li == NULL) {
419 			selected[i] = 0;
420 			continue;
421 		}
422 
423 		SLIST_FOREACH(li, &ppidlist, li_chain)
424 			if (kp->ki_ppid == (pid_t)li->li_number)
425 				break;
426 		if (SLIST_FIRST(&ppidlist) != NULL && li == NULL) {
427 			selected[i] = 0;
428 			continue;
429 		}
430 
431 		SLIST_FOREACH(li, &pgrplist, li_chain)
432 			if (kp->ki_pgid == (pid_t)li->li_number)
433 				break;
434 		if (SLIST_FIRST(&pgrplist) != NULL && li == NULL) {
435 			selected[i] = 0;
436 			continue;
437 		}
438 
439 		SLIST_FOREACH(li, &tdevlist, li_chain) {
440 			if (li->li_number == -1 &&
441 			    (kp->ki_flag & P_CONTROLT) == 0)
442 				break;
443 			if (kp->ki_tdev == (dev_t)li->li_number)
444 				break;
445 		}
446 		if (SLIST_FIRST(&tdevlist) != NULL && li == NULL) {
447 			selected[i] = 0;
448 			continue;
449 		}
450 
451 		SLIST_FOREACH(li, &sidlist, li_chain)
452 			if (kp->ki_sid == (pid_t)li->li_number)
453 				break;
454 		if (SLIST_FIRST(&sidlist) != NULL && li == NULL) {
455 			selected[i] = 0;
456 			continue;
457 		}
458 
459 		SLIST_FOREACH(li, &jidlist, li_chain) {
460 			/* A particular jail ID, including 0 (not in jail) */
461 			if (kp->ki_jid == (int)li->li_number)
462 				break;
463 			/* Any jail */
464 			if (kp->ki_jid > 0 && li->li_number == -1)
465 				break;
466 		}
467 		if (SLIST_FIRST(&jidlist) != NULL && li == NULL) {
468 			selected[i] = 0;
469 			continue;
470 		}
471 
472 		if (argc == 0)
473 			selected[i] = 1;
474 	}
475 
476 	if (!ancestors) {
477 		pid = mypid;
478 		while (pid) {
479 			for (i = 0, kp = plist; i < nproc; i++, kp++) {
480 				if (PSKIP(kp))
481 					continue;
482 				if (kp->ki_pid == pid) {
483 					selected[i] = 0;
484 					pid = kp->ki_ppid;
485 					break;
486 				}
487 			}
488 			if (i == nproc) {
489 				if (pid == mypid)
490 					pid = getppid();
491 				else
492 					break;	/* Maybe we're in a jail ? */
493 			}
494 		}
495 	}
496 
497 	if (newest || oldest) {
498 		best_tval.tv_sec = 0;
499 		best_tval.tv_usec = 0;
500 		bestidx = -1;
501 
502 		for (i = 0, kp = plist; i < nproc; i++, kp++) {
503 			if (!selected[i])
504 				continue;
505 			if (bestidx == -1) {
506 				/* The first entry of the list which matched. */
507 				;
508 			} else if (timercmp(&kp->ki_start, &best_tval, >)) {
509 				/* This entry is newer than previous "best". */
510 				if (oldest)	/* but we want the oldest */
511 					continue;
512 			} else {
513 				/* This entry is older than previous "best". */
514 				if (newest)	/* but we want the newest */
515 					continue;
516 			}
517 			/* This entry is better than previous "best" entry. */
518 			best_tval.tv_sec = kp->ki_start.tv_sec;
519 			best_tval.tv_usec = kp->ki_start.tv_usec;
520 			bestidx = i;
521 		}
522 
523 		memset(selected, 0, nproc);
524 		if (bestidx != -1)
525 			selected[bestidx] = 1;
526 	}
527 
528 	/*
529 	 * Take the appropriate action for each matched process, if any.
530 	 */
531 	for (i = 0, rv = 0, kp = plist; i < nproc; i++, kp++) {
532 		if (PSKIP(kp))
533 			continue;
534 		if (selected[i]) {
535 			if (inverse)
536 				continue;
537 		} else if (!inverse)
538 			continue;
539 		rv |= (*action)(kp);
540 	}
541 
542 	exit(rv ? STATUS_MATCH : STATUS_NOMATCH);
543 }
544 
545 static void
546 usage(void)
547 {
548 	const char *ustr;
549 
550 	if (pgrep)
551 		ustr = "[-LSfilnovx] [-d delim]";
552 	else
553 		ustr = "[-signal] [-ILfinovx]";
554 
555 	fprintf(stderr,
556 		"usage: %s %s [-F pidfile] [-G gid] [-M core] [-N system]\n"
557 		"             [-P ppid] [-U uid] [-g pgrp] [-j jid] [-s sid]\n"
558 		"             [-t tty] [-u euid] pattern ...\n", getprogname(),
559 		ustr);
560 
561 	exit(STATUS_BADUSAGE);
562 }
563 
564 static void
565 show_process(const struct kinfo_proc *kp)
566 {
567 	char **argv;
568 
569 	if ((longfmt || !pgrep) && matchargs &&
570 	    (argv = kvm_getargv(kd, kp, 0)) != NULL) {
571 		printf("%d ", (int)kp->ki_pid);
572 		for (; *argv != NULL; argv++) {
573 			printf("%s", *argv);
574 			if (argv[1] != NULL)
575 				putchar(' ');
576 		}
577 	} else if (longfmt || !pgrep)
578 		printf("%d %s", (int)kp->ki_pid, kp->ki_comm);
579 	else
580 		printf("%d", (int)kp->ki_pid);
581 }
582 
583 static int
584 killact(const struct kinfo_proc *kp)
585 {
586 	int ch, first;
587 
588 	if (interactive) {
589 		/*
590 		 * Be careful, ask before killing.
591 		 */
592 		printf("kill ");
593 		show_process(kp);
594 		printf("? ");
595 		fflush(stdout);
596 		first = ch = getchar();
597 		while (ch != '\n' && ch != EOF)
598 			ch = getchar();
599 		if (first != 'y' && first != 'Y')
600 			return (1);
601 	}
602 	if (kill(kp->ki_pid, signum) == -1) {
603 		/*
604 		 * Check for ESRCH, which indicates that the process
605 		 * disappeared between us matching it and us
606 		 * signalling it; don't issue a warning about it.
607 		 */
608 		if (errno != ESRCH)
609 			warn("signalling pid %d", (int)kp->ki_pid);
610 		/*
611 		 * Return 0 to indicate that the process should not be
612 		 * considered a match, since we didn't actually get to
613 		 * signal it.
614 		 */
615 		return (0);
616 	}
617 	return (1);
618 }
619 
620 static int
621 grepact(const struct kinfo_proc *kp)
622 {
623 
624 	show_process(kp);
625 	printf("%s", delim);
626 	return (1);
627 }
628 
629 static void
630 makelist(struct listhead *head, enum listtype type, char *src)
631 {
632 	struct list *li;
633 	struct passwd *pw;
634 	struct group *gr;
635 	struct stat st;
636 	const char *cp;
637 	char *sp, *ep, buf[MAXPATHLEN];
638 	int empty;
639 
640 	empty = 1;
641 
642 	while ((sp = strsep(&src, ",")) != NULL) {
643 		if (*sp == '\0')
644 			usage();
645 
646 		if ((li = malloc(sizeof(*li))) == NULL) {
647 			err(STATUS_ERROR, "Cannot allocate %zu bytes",
648 			    sizeof(*li));
649 		}
650 
651 		SLIST_INSERT_HEAD(head, li, li_chain);
652 		empty = 0;
653 
654 		li->li_number = (uid_t)strtol(sp, &ep, 0);
655 		if (*ep == '\0') {
656 			switch (type) {
657 			case LT_PGRP:
658 				if (li->li_number == 0)
659 					li->li_number = getpgrp();
660 				break;
661 			case LT_SID:
662 				if (li->li_number == 0)
663 					li->li_number = getsid(mypid);
664 				break;
665 			case LT_JID:
666 				if (li->li_number < 0)
667 					errx(STATUS_BADUSAGE,
668 					     "Negative jail ID `%s'", sp);
669 				/* For compatibility with old -j */
670 				if (li->li_number == 0)
671 					li->li_number = -1;	/* any jail */
672 				break;
673 			default:
674 				break;
675 			}
676 			continue;
677 		}
678 
679 		switch (type) {
680 		case LT_USER:
681 			if ((pw = getpwnam(sp)) == NULL)
682 				errx(STATUS_BADUSAGE, "Unknown user `%s'", sp);
683 			li->li_number = pw->pw_uid;
684 			break;
685 		case LT_GROUP:
686 			if ((gr = getgrnam(sp)) == NULL)
687 				errx(STATUS_BADUSAGE, "Unknown group `%s'", sp);
688 			li->li_number = gr->gr_gid;
689 			break;
690 		case LT_TTY:
691 			if (strcmp(sp, "-") == 0) {
692 				li->li_number = -1;
693 				break;
694 			} else if (strcmp(sp, "co") == 0) {
695 				cp = "console";
696 			} else {
697 				cp = sp;
698 			}
699 
700 			snprintf(buf, sizeof(buf), _PATH_DEV "%s", cp);
701 			if (stat(buf, &st) != -1)
702 				goto foundtty;
703 
704 			snprintf(buf, sizeof(buf), _PATH_DEV "tty%s", cp);
705 			if (stat(buf, &st) != -1)
706 				goto foundtty;
707 
708 			snprintf(buf, sizeof(buf), _PATH_DEV "pts/%s", cp);
709 			if (stat(buf, &st) != -1)
710 				goto foundtty;
711 
712 			if (errno == ENOENT)
713 				errx(STATUS_BADUSAGE, "No such tty: `%s'", sp);
714 			err(STATUS_ERROR, "Cannot access `%s'", sp);
715 
716 foundtty:		if ((st.st_mode & S_IFCHR) == 0)
717 				errx(STATUS_BADUSAGE, "Not a tty: `%s'", sp);
718 
719 			li->li_number = st.st_rdev;
720 			break;
721 		case LT_JID:
722 			if (strcmp(sp, "none") == 0)
723 				li->li_number = 0;
724 			else if (strcmp(sp, "any") == 0)
725 				li->li_number = -1;
726 			else if (*ep != '\0')
727 				errx(STATUS_BADUSAGE,
728 				     "Invalid jail ID `%s'", sp);
729 			break;
730 		default:
731 			usage();
732 		}
733 	}
734 
735 	if (empty)
736 		usage();
737 }
738 
739 static int
740 takepid(const char *pidfile, int pidfilelock)
741 {
742 	char *endp, line[BUFSIZ];
743 	FILE *fh;
744 	long rval;
745 
746 	fh = fopen(pidfile, "r");
747 	if (fh == NULL)
748 		err(STATUS_ERROR, "Cannot open pidfile `%s'", pidfile);
749 
750 	if (pidfilelock) {
751 		/*
752 		 * If we can lock pidfile, this means that daemon is not
753 		 * running, so would be better not to kill some random process.
754 		 */
755 		if (flock(fileno(fh), LOCK_EX | LOCK_NB) == 0) {
756 			(void)fclose(fh);
757 			errx(STATUS_ERROR, "File '%s' can be locked", pidfile);
758 		} else {
759 			if (errno != EWOULDBLOCK) {
760 				errx(STATUS_ERROR,
761 				    "Error while locking file '%s'", pidfile);
762 			}
763 		}
764 	}
765 
766 	if (fgets(line, sizeof(line), fh) == NULL) {
767 		if (feof(fh)) {
768 			(void)fclose(fh);
769 			errx(STATUS_ERROR, "Pidfile `%s' is empty", pidfile);
770 		}
771 		(void)fclose(fh);
772 		err(STATUS_ERROR, "Cannot read from pid file `%s'", pidfile);
773 	}
774 	(void)fclose(fh);
775 
776 	rval = strtol(line, &endp, 10);
777 	if (*endp != '\0' && !isspace((unsigned char)*endp))
778 		errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
779 	else if (rval < MIN_PID || rval > MAX_PID)
780 		errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
781 	return (rval);
782 }
783