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