PageRenderTime 73ms CodeModel.GetById 20ms app.highlight 47ms RepoModel.GetById 1ms app.codeStats 0ms

/bin/pkill/pkill.c

https://bitbucket.org/freebsd/freebsd-head/
C | 805 lines | 658 code | 74 blank | 73 comment | 252 complexity | 46c1810f2b21dd8f93201c929c2b2ea6 MD5 | raw file
  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
 75enum listtype {
 76	LT_GENERIC,
 77	LT_USER,
 78	LT_GROUP,
 79	LT_TTY,
 80	LT_PGRP,
 81	LT_JID,
 82	LT_SID
 83};
 84
 85struct list {
 86	SLIST_ENTRY(list) li_chain;
 87	long	li_number;
 88};
 89
 90SLIST_HEAD(listhead, list);
 91
 92static struct kinfo_proc *plist;
 93static char	*selected;
 94static const char *delim = "\n";
 95static int	nproc;
 96static int	pgrep;
 97static int	signum = SIGTERM;
 98static int	newest;
 99static int	oldest;
100static int	interactive;
101static int	inverse;
102static int	longfmt;
103static int	matchargs;
104static int	fullmatch;
105static int	kthreads;
106static int	cflags = REG_EXTENDED;
107static int	quiet;
108static kvm_t	*kd;
109static pid_t	mypid;
110
111static struct listhead euidlist = SLIST_HEAD_INITIALIZER(euidlist);
112static struct listhead ruidlist = SLIST_HEAD_INITIALIZER(ruidlist);
113static struct listhead rgidlist = SLIST_HEAD_INITIALIZER(rgidlist);
114static struct listhead pgrplist = SLIST_HEAD_INITIALIZER(pgrplist);
115static struct listhead ppidlist = SLIST_HEAD_INITIALIZER(ppidlist);
116static struct listhead tdevlist = SLIST_HEAD_INITIALIZER(tdevlist);
117static struct listhead sidlist = SLIST_HEAD_INITIALIZER(sidlist);
118static struct listhead jidlist = SLIST_HEAD_INITIALIZER(jidlist);
119
120static void	usage(void) __attribute__((__noreturn__));
121static int	killact(const struct kinfo_proc *);
122static int	grepact(const struct kinfo_proc *);
123static void	makelist(struct listhead *, enum listtype, char *);
124static int	takepid(const char *, int);
125
126int
127main(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, did_action;
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			longfmt = 1;
246			break;
247		case 'n':
248			newest = 1;
249			criteria = 1;
250			break;
251		case 'o':
252			oldest = 1;
253			criteria = 1;
254			break;
255		case 'q':
256			if (!pgrep)
257				usage();
258			quiet = 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	did_action = 0;
532	for (i = 0, rv = 0, kp = plist; i < nproc; i++, kp++) {
533		if (PSKIP(kp))
534			continue;
535		if (selected[i]) {
536			if (longfmt && !pgrep) {
537				did_action = 1;
538				printf("kill -%d %d\n", signum, kp->ki_pid);
539			}
540			if (inverse)
541				continue;
542		} else if (!inverse)
543			continue;
544		rv |= (*action)(kp);
545	}
546	if (!did_action && !pgrep && longfmt)
547		fprintf(stderr,
548		    "No matching processes belonging to you were found\n");
549
550	exit(rv ? STATUS_MATCH : STATUS_NOMATCH);
551}
552
553static void
554usage(void)
555{
556	const char *ustr;
557
558	if (pgrep)
559		ustr = "[-LSfilnoqvx] [-d delim]";
560	else
561		ustr = "[-signal] [-ILfilnovx]";
562
563	fprintf(stderr,
564		"usage: %s %s [-F pidfile] [-G gid] [-M core] [-N system]\n"
565		"             [-P ppid] [-U uid] [-g pgrp] [-j jid] [-s sid]\n"
566		"             [-t tty] [-u euid] pattern ...\n", getprogname(),
567		ustr);
568
569	exit(STATUS_BADUSAGE);
570}
571
572static void
573show_process(const struct kinfo_proc *kp)
574{
575	char **argv;
576
577	if (quiet) {
578		assert(pgrep);
579		return;
580	}
581	if ((longfmt || !pgrep) && matchargs &&
582	    (argv = kvm_getargv(kd, kp, 0)) != NULL) {
583		printf("%d ", (int)kp->ki_pid);
584		for (; *argv != NULL; argv++) {
585			printf("%s", *argv);
586			if (argv[1] != NULL)
587				putchar(' ');
588		}
589	} else if (longfmt || !pgrep)
590		printf("%d %s", (int)kp->ki_pid, kp->ki_comm);
591	else
592		printf("%d", (int)kp->ki_pid);
593}
594
595static int
596killact(const struct kinfo_proc *kp)
597{
598	int ch, first;
599
600	if (interactive) {
601		/*
602		 * Be careful, ask before killing.
603		 */
604		printf("kill ");
605		show_process(kp);
606		printf("? ");
607		fflush(stdout);
608		first = ch = getchar();
609		while (ch != '\n' && ch != EOF)
610			ch = getchar();
611		if (first != 'y' && first != 'Y')
612			return (1);
613	}
614	if (kill(kp->ki_pid, signum) == -1) {
615		/* 
616		 * Check for ESRCH, which indicates that the process
617		 * disappeared between us matching it and us
618		 * signalling it; don't issue a warning about it.
619		 */
620		if (errno != ESRCH)
621			warn("signalling pid %d", (int)kp->ki_pid);
622		/*
623		 * Return 0 to indicate that the process should not be
624		 * considered a match, since we didn't actually get to
625		 * signal it.
626		 */
627		return (0);
628	}
629	return (1);
630}
631
632static int
633grepact(const struct kinfo_proc *kp)
634{
635
636	show_process(kp);
637	if (!quiet)
638		printf("%s", delim);
639	return (1);
640}
641
642static void
643makelist(struct listhead *head, enum listtype type, char *src)
644{
645	struct list *li;
646	struct passwd *pw;
647	struct group *gr;
648	struct stat st;
649	const char *cp;
650	char *sp, *ep, buf[MAXPATHLEN];
651	int empty;
652
653	empty = 1;
654
655	while ((sp = strsep(&src, ",")) != NULL) {
656		if (*sp == '\0')
657			usage();
658
659		if ((li = malloc(sizeof(*li))) == NULL) {
660			err(STATUS_ERROR, "Cannot allocate %zu bytes",
661			    sizeof(*li));
662		}
663
664		SLIST_INSERT_HEAD(head, li, li_chain);
665		empty = 0;
666
667		li->li_number = (uid_t)strtol(sp, &ep, 0);
668		if (*ep == '\0') {
669			switch (type) {
670			case LT_PGRP:
671				if (li->li_number == 0)
672					li->li_number = getpgrp();
673				break;
674			case LT_SID:
675				if (li->li_number == 0)
676					li->li_number = getsid(mypid);
677				break;
678			case LT_JID:
679				if (li->li_number < 0)
680					errx(STATUS_BADUSAGE,
681					     "Negative jail ID `%s'", sp);
682				/* For compatibility with old -j */
683				if (li->li_number == 0)
684					li->li_number = -1;	/* any jail */
685				break;
686			case LT_TTY:
687				if (li->li_number < 0)
688					errx(STATUS_BADUSAGE,
689					     "Negative /dev/pts tty `%s'", sp);
690				snprintf(buf, sizeof(buf), _PATH_DEV "pts/%s",
691				    sp);
692				if (stat(buf, &st) != -1)
693					goto foundtty;
694				if (errno == ENOENT)
695					errx(STATUS_BADUSAGE, "No such tty: `"
696					    _PATH_DEV "pts/%s'", sp);
697				err(STATUS_ERROR, "Cannot access `"
698				    _PATH_DEV "pts/%s'", sp);
699				break;
700			default:
701				break;
702			}
703			continue;
704		}
705
706		switch (type) {
707		case LT_USER:
708			if ((pw = getpwnam(sp)) == NULL)
709				errx(STATUS_BADUSAGE, "Unknown user `%s'", sp);
710			li->li_number = pw->pw_uid;
711			break;
712		case LT_GROUP:
713			if ((gr = getgrnam(sp)) == NULL)
714				errx(STATUS_BADUSAGE, "Unknown group `%s'", sp);
715			li->li_number = gr->gr_gid;
716			break;
717		case LT_TTY:
718			if (strcmp(sp, "-") == 0) {
719				li->li_number = -1;
720				break;
721			} else if (strcmp(sp, "co") == 0) {
722				cp = "console";
723			} else {
724				cp = sp;
725			}
726
727			snprintf(buf, sizeof(buf), _PATH_DEV "%s", cp);
728			if (stat(buf, &st) != -1)
729				goto foundtty;
730
731			snprintf(buf, sizeof(buf), _PATH_DEV "tty%s", cp);
732			if (stat(buf, &st) != -1)
733				goto foundtty;
734
735			if (errno == ENOENT)
736				errx(STATUS_BADUSAGE, "No such tty: `%s'", sp);
737			err(STATUS_ERROR, "Cannot access `%s'", sp);
738
739foundtty:		if ((st.st_mode & S_IFCHR) == 0)
740				errx(STATUS_BADUSAGE, "Not a tty: `%s'", sp);
741
742			li->li_number = st.st_rdev;
743			break;
744		case LT_JID:
745			if (strcmp(sp, "none") == 0)
746				li->li_number = 0;
747			else if (strcmp(sp, "any") == 0)
748				li->li_number = -1;
749			else if (*ep != '\0')
750				errx(STATUS_BADUSAGE,
751				     "Invalid jail ID `%s'", sp);
752			break;
753		default:
754			usage();
755		}
756	}
757
758	if (empty)
759		usage();
760}
761
762static int
763takepid(const char *pidfile, int pidfilelock)
764{
765	char *endp, line[BUFSIZ];
766	FILE *fh;
767	long rval;
768
769	fh = fopen(pidfile, "r");
770	if (fh == NULL)
771		err(STATUS_ERROR, "Cannot open pidfile `%s'", pidfile);
772
773	if (pidfilelock) {
774		/*
775		 * If we can lock pidfile, this means that daemon is not
776		 * running, so would be better not to kill some random process.
777		 */
778		if (flock(fileno(fh), LOCK_EX | LOCK_NB) == 0) {
779			(void)fclose(fh);
780			errx(STATUS_ERROR, "File '%s' can be locked", pidfile);
781		} else {
782			if (errno != EWOULDBLOCK) {
783				errx(STATUS_ERROR,
784				    "Error while locking file '%s'", pidfile);
785			}
786		}
787	}
788
789	if (fgets(line, sizeof(line), fh) == NULL) {
790		if (feof(fh)) {
791			(void)fclose(fh);
792			errx(STATUS_ERROR, "Pidfile `%s' is empty", pidfile);
793		}
794		(void)fclose(fh);
795		err(STATUS_ERROR, "Cannot read from pid file `%s'", pidfile);
796	}
797	(void)fclose(fh);
798
799	rval = strtol(line, &endp, 10);
800	if (*endp != '\0' && !isspace((unsigned char)*endp))
801		errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
802	else if (rval < MIN_PID || rval > MAX_PID)
803		errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
804	return (rval);
805}