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