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 * $FreeBSD: head/bin/pkill/pkill.c 256050 2013-10-04 16:08:44Z trasz $
33 */
34
35 #include <sys/user.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/sysctl.h>
39 #include <sys/queue.h>
40 #include <sys/stat.h>
41 #include <sys/fcntl.h>
42 #include <sys/time.h>
43
44 #include <assert.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <limits.h>
48 #include <paths.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <signal.h>
52 #include <regex.h>
53 #include <ctype.h>
54 #include <kvm.h>
55 #include <err.h>
56 #include <pwd.h>
57 #include <grp.h>
58 #include <errno.h>
59 #include <locale.h>
60
61 #define STATUS_MATCH 0
62 #define STATUS_NOMATCH 1
63 #define STATUS_BADUSAGE 2
64 #define STATUS_ERROR 3
65
66 #define MIN_PID 5
67 #define MAX_PID PID_MAX
68
69 /* Ignore system-processes (if '-S' flag is not specified) and myself. */
70 #define PSKIP(kp) ((kp)->kp_pid == mypid || \
71 (!kthreads && (kp)->kp_pid <= 0))
72
73 enum listtype {
74 LT_GENERIC,
75 LT_USER,
76 LT_GROUP,
77 LT_TTY,
78 LT_PGRP,
79 LT_JID,
80 LT_SID,
81 LT_CLASS
82 };
83
84 struct list {
85 SLIST_ENTRY(list) li_chain;
86 long li_number;
87 char *li_name;
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 static struct listhead classlist = SLIST_HEAD_INITIALIZER(classlist);
120
121 static void usage(void) __attribute__((__noreturn__));
122 static int killact(const struct kinfo_proc *);
123 static int grepact(const struct kinfo_proc *);
124 static void makelist(struct listhead *, enum listtype, char *);
125 static int takepid(const char *, int);
126
127 int
main(int argc,char ** argv)128 main(int argc, char **argv)
129 {
130 char buf[_POSIX2_LINE_MAX], *mstr, **pargv, *p, *q, *pidfile, *tdev;
131 const char *execf, *coref;
132 int ancestors, debug_opt, did_action;
133 int i, ch, bestidx, rv, criteria, pidfromfile, pidfilelock;
134 size_t jsz;
135 int (*action)(const struct kinfo_proc *);
136 struct kinfo_proc *kp;
137 struct list *li;
138 struct timeval best_tval;
139 regex_t reg;
140 regmatch_t regmatch;
141 pid_t pid;
142
143 setlocale(LC_ALL, "");
144
145 if (strcmp(getprogname(), "pgrep") == 0) {
146 action = grepact;
147 pgrep = 1;
148 } else {
149 action = killact;
150 p = argv[1];
151
152 if (argc > 1 && p[0] == '-') {
153 p++;
154 i = (int)strtol(p, &q, 10);
155 if (*q == '\0') {
156 signum = i;
157 argv++;
158 argc--;
159 } else {
160 if (strncasecmp(p, "SIG", 3) == 0)
161 p += 3;
162 for (i = 1; i < NSIG; i++)
163 if (strcasecmp(sys_signame[i], p) == 0)
164 break;
165 if (i != NSIG) {
166 signum = i;
167 argv++;
168 argc--;
169 }
170 }
171 }
172 }
173
174 ancestors = 0;
175 criteria = 0;
176 debug_opt = 0;
177 pidfile = NULL;
178 pidfilelock = 0;
179 quiet = 0;
180 execf = NULL;
181 coref = _PATH_DEVNULL;
182
183 while ((ch = getopt(argc, argv, "DF:G:ILM:N:P:STU:ac:d:fg:ij:lnoqs:t:u:vx")) != -1) {
184 switch (ch) {
185 case 'D':
186 debug_opt++;
187 break;
188 case 'F':
189 pidfile = optarg;
190 criteria = 1;
191 break;
192 case 'G':
193 makelist(&rgidlist, LT_GROUP, optarg);
194 criteria = 1;
195 break;
196 case 'I':
197 if (pgrep)
198 usage();
199 interactive = 1;
200 break;
201 case 'L':
202 pidfilelock = 1;
203 break;
204 case 'M':
205 coref = optarg;
206 break;
207 case 'N':
208 execf = optarg;
209 break;
210 case 'P':
211 makelist(&ppidlist, LT_GENERIC, optarg);
212 criteria = 1;
213 break;
214 case 'S':
215 if (!pgrep)
216 usage();
217 kthreads = 1;
218 break;
219 case 'T':
220 tdev = ttyname(0);
221 if (tdev == NULL)
222 err(STATUS_ERROR, "Not a terminal");
223 if ((tdev = strdup(tdev)) == NULL)
224 err(STATUS_ERROR, "Cannot allocate memory");
225 makelist(&tdevlist, LT_TTY, tdev);
226 criteria = 1;
227 break;
228 case 'U':
229 makelist(&ruidlist, LT_USER, optarg);
230 criteria = 1;
231 break;
232 case 'a':
233 ancestors++;
234 break;
235 case 'c':
236 makelist(&classlist, LT_CLASS, optarg);
237 criteria = 1;
238 break;
239 case 'd':
240 if (!pgrep)
241 usage();
242 delim = optarg;
243 break;
244 case 'f':
245 matchargs = 1;
246 break;
247 case 'g':
248 makelist(&pgrplist, LT_PGRP, optarg);
249 criteria = 1;
250 break;
251 case 'i':
252 cflags |= REG_ICASE;
253 break;
254 case 'j':
255 makelist(&jidlist, LT_JID, optarg);
256 criteria = 1;
257 break;
258 case 'l':
259 longfmt = 1;
260 break;
261 case 'n':
262 newest = 1;
263 criteria = 1;
264 break;
265 case 'o':
266 oldest = 1;
267 criteria = 1;
268 break;
269 case 'q':
270 if (!pgrep)
271 usage();
272 quiet = 1;
273 break;
274 case 's':
275 makelist(&sidlist, LT_SID, optarg);
276 criteria = 1;
277 break;
278 case 't':
279 makelist(&tdevlist, LT_TTY, optarg);
280 criteria = 1;
281 break;
282 case 'u':
283 makelist(&euidlist, LT_USER, optarg);
284 criteria = 1;
285 break;
286 case 'v':
287 inverse = 1;
288 break;
289 case 'x':
290 fullmatch = 1;
291 break;
292 default:
293 usage();
294 /* NOTREACHED */
295 }
296 }
297
298 argc -= optind;
299 argv += optind;
300 if (argc != 0)
301 criteria = 1;
302 if (!criteria)
303 usage();
304 if (newest && oldest)
305 errx(STATUS_ERROR, "Options -n and -o are mutually exclusive");
306 if (pidfile != NULL)
307 pidfromfile = takepid(pidfile, pidfilelock);
308 else {
309 if (pidfilelock) {
310 errx(STATUS_ERROR,
311 "Option -L doesn't make sense without -F");
312 }
313 pidfromfile = -1;
314 }
315
316 mypid = getpid();
317
318 /*
319 * Retrieve the list of running processes from the kernel.
320 */
321 kd = kvm_openfiles(execf, coref, NULL, O_RDONLY, buf);
322 if (kd == NULL)
323 errx(STATUS_ERROR, "Cannot open kernel files (%s)", buf);
324
325 if (pidfromfile >= 0)
326 plist = kvm_getprocs(kd, KERN_PROC_PID, pidfromfile, &nproc);
327 else
328 plist = kvm_getprocs(kd, KERN_PROC_ALL, 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(®, *argv, cflags)) != 0) {
349 regerror(rv, ®, 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->kp_pid, kp->kp_uid, kp->kp_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->kp_comm;
376
377 rv = regexec(®, mstr, 1, ®match, 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, ®, 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->kp_pid, kp->kp_uid, mstr);
398 }
399 }
400
401 regfree(®);
402 }
403
404 for (i = 0, kp = plist; i < nproc; i++, kp++) {
405 if (PSKIP(kp))
406 continue;
407
408 if (pidfromfile >= 0 && kp->kp_pid != pidfromfile) {
409 selected[i] = 0;
410 continue;
411 }
412
413 SLIST_FOREACH(li, &ruidlist, li_chain)
414 if (kp->kp_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->kp_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->kp_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->kp_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->kp_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->kp_flags & P_CONTROLT) == 0)
456 break;
457 if (kp->kp_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->kp_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->kp_jailid == (int)li->li_number)
476 break;
477 /* Any jail */
478 if (kp->kp_jailid > 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->kp_flags & P_SYSTEM) == 0)
491 break;
492 }
493 if (SLIST_FIRST(&classlist) != NULL && li == NULL) {
494 selected[i] = 0;
495 continue;
496 }
497
498 if (argc == 0)
499 selected[i] = 1;
500 }
501
502 if (!ancestors) {
503 pid = mypid;
504 while (pid) {
505 for (i = 0, kp = plist; i < nproc; i++, kp++) {
506 if (PSKIP(kp))
507 continue;
508 if (kp->kp_pid == pid) {
509 selected[i] = 0;
510 pid = kp->kp_ppid;
511 break;
512 }
513 }
514 if (i == nproc) {
515 if (pid == mypid)
516 pid = getppid();
517 else
518 break; /* Maybe we're in a jail ? */
519 }
520 }
521 }
522
523 if (newest || oldest) {
524 best_tval.tv_sec = 0;
525 best_tval.tv_usec = 0;
526 bestidx = -1;
527
528 for (i = 0, kp = plist; i < nproc; i++, kp++) {
529 if (!selected[i])
530 continue;
531 if (bestidx == -1) {
532 /* The first entry of the list which matched. */
533 ;
534 } else if (timercmp(&kp->kp_start, &best_tval, >)) {
535 /* This entry is newer than previous "best". */
536 if (oldest) /* but we want the oldest */
537 continue;
538 } else {
539 /* This entry is older than previous "best". */
540 if (newest) /* but we want the newest */
541 continue;
542 }
543 /* This entry is better than previous "best" entry. */
544 best_tval.tv_sec = kp->kp_start.tv_sec;
545 best_tval.tv_usec = kp->kp_start.tv_usec;
546 bestidx = i;
547 }
548
549 memset(selected, 0, nproc);
550 if (bestidx != -1)
551 selected[bestidx] = 1;
552 }
553
554 /*
555 * Take the appropriate action for each matched process, if any.
556 */
557 did_action = 0;
558 for (i = 0, rv = 0, kp = plist; i < nproc; i++, kp++) {
559 if (PSKIP(kp))
560 continue;
561 if (selected[i]) {
562 if (longfmt && !pgrep) {
563 did_action = 1;
564 printf("kill -%d %d\n", signum, kp->kp_pid);
565 }
566 if (inverse)
567 continue;
568 } else if (!inverse)
569 continue;
570 rv |= (*action)(kp);
571 }
572 if (!did_action && !pgrep && longfmt)
573 fprintf(stderr,
574 "No matching processes belonging to you were found\n");
575
576 exit(rv ? STATUS_MATCH : STATUS_NOMATCH);
577 }
578
579 static void
usage(void)580 usage(void)
581 {
582 const char *ustr;
583
584 if (pgrep)
585 ustr = "[-LSTfilnoqvx] [-d delim]";
586 else
587 ustr = "[-signal] [-ILTfilnovx]";
588
589 fprintf(stderr,
590 "usage: %s %s [-F pidfile] [-G gid] [-M core] [-N system]\n"
591 " [-P ppid] [-U uid] [-c class] [-g pgrp] [-j jid]\n"
592 " [-s sid] [-t tty] [-u euid] pattern ...\n",
593 getprogname(), ustr);
594
595 exit(STATUS_BADUSAGE);
596 }
597
598 static void
show_process(const struct kinfo_proc * kp)599 show_process(const struct kinfo_proc *kp)
600 {
601 char **argv;
602
603 if (quiet) {
604 assert(pgrep);
605 return;
606 }
607 if ((longfmt || !pgrep) && matchargs &&
608 (argv = kvm_getargv(kd, kp, 0)) != NULL) {
609 printf("%d ", (int)kp->kp_pid);
610 for (; *argv != NULL; argv++) {
611 printf("%s", *argv);
612 if (argv[1] != NULL)
613 putchar(' ');
614 }
615 } else if (longfmt || !pgrep)
616 printf("%d %s", (int)kp->kp_pid, kp->kp_comm);
617 else
618 printf("%d", (int)kp->kp_pid);
619 }
620
621 static int
killact(const struct kinfo_proc * kp)622 killact(const struct kinfo_proc *kp)
623 {
624 int ch, first;
625
626 if (interactive) {
627 /*
628 * Be careful, ask before killing.
629 */
630 printf("kill ");
631 show_process(kp);
632 printf("? ");
633 fflush(stdout);
634 first = ch = getchar();
635 while (ch != '\n' && ch != EOF)
636 ch = getchar();
637 if (first != 'y' && first != 'Y')
638 return (1);
639 }
640 if (kill(kp->kp_pid, signum) == -1) {
641 /*
642 * Check for ESRCH, which indicates that the process
643 * disappeared between us matching it and us
644 * signalling it; don't issue a warning about it.
645 */
646 if (errno != ESRCH)
647 warn("signalling pid %d", (int)kp->kp_pid);
648 /*
649 * Return 0 to indicate that the process should not be
650 * considered a match, since we didn't actually get to
651 * signal it.
652 */
653 return (0);
654 }
655 return (1);
656 }
657
658 static int
grepact(const struct kinfo_proc * kp)659 grepact(const struct kinfo_proc *kp)
660 {
661
662 show_process(kp);
663 if (!quiet)
664 printf("%s", delim);
665 return (1);
666 }
667
668 static void
makelist(struct listhead * head,enum listtype type,char * src)669 makelist(struct listhead *head, enum listtype type, char *src)
670 {
671 struct list *li;
672 struct passwd *pw;
673 struct group *gr;
674 struct stat st;
675 const char *cp;
676 char *sp, *ep, buf[MAXPATHLEN];
677 int empty;
678
679 empty = 1;
680
681 while ((sp = strsep(&src, ",")) != NULL) {
682 if (*sp == '\0')
683 usage();
684
685 if ((li = malloc(sizeof(*li))) == NULL) {
686 err(STATUS_ERROR, "Cannot allocate %zu bytes",
687 sizeof(*li));
688 }
689
690 SLIST_INSERT_HEAD(head, li, li_chain);
691 empty = 0;
692
693 if (type != LT_CLASS)
694 li->li_number = (uid_t)strtol(sp, &ep, 0);
695
696 if (type != LT_CLASS && *ep == '\0') {
697 switch (type) {
698 case LT_PGRP:
699 if (li->li_number == 0)
700 li->li_number = getpgrp();
701 break;
702 case LT_SID:
703 if (li->li_number == 0)
704 li->li_number = getsid(mypid);
705 break;
706 case LT_JID:
707 if (li->li_number < 0)
708 errx(STATUS_BADUSAGE,
709 "Negative jail ID `%s'", sp);
710 /* For compatibility with old -j */
711 if (li->li_number == 0)
712 li->li_number = -1; /* any jail */
713 break;
714 case LT_TTY:
715 if (li->li_number < 0)
716 errx(STATUS_BADUSAGE,
717 "Negative /dev/pts tty `%s'", sp);
718 snprintf(buf, sizeof(buf), _PATH_DEV "pts/%s",
719 sp);
720 if (stat(buf, &st) != -1)
721 goto foundtty;
722 if (errno == ENOENT)
723 errx(STATUS_BADUSAGE, "No such tty: `"
724 _PATH_DEV "pts/%s'", sp);
725 err(STATUS_ERROR, "Cannot access `"
726 _PATH_DEV "pts/%s'", sp);
727 break;
728 default:
729 break;
730 }
731 continue;
732 }
733
734 switch (type) {
735 case LT_USER:
736 if ((pw = getpwnam(sp)) == NULL)
737 errx(STATUS_BADUSAGE, "Unknown user `%s'", sp);
738 li->li_number = pw->pw_uid;
739 break;
740 case LT_GROUP:
741 if ((gr = getgrnam(sp)) == NULL)
742 errx(STATUS_BADUSAGE, "Unknown group `%s'", sp);
743 li->li_number = gr->gr_gid;
744 break;
745 case LT_TTY:
746 if (strcmp(sp, "-") == 0) {
747 li->li_number = -1;
748 break;
749 } else if (strcmp(sp, "co") == 0) {
750 cp = "console";
751 } else {
752 cp = sp;
753 }
754
755 if (strncmp(cp, _PATH_DEV, sizeof(_PATH_DEV)-1) == 0 &&
756 stat(cp, &st) != -1) {
757 goto foundtty;
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
772 foundtty: 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_JID:
778 if (strcmp(sp, "none") == 0)
779 li->li_number = 0;
780 else if (strcmp(sp, "any") == 0)
781 li->li_number = -1;
782 else if (*ep != '\0')
783 errx(STATUS_BADUSAGE,
784 "Invalid jail ID `%s'", sp);
785 break;
786 case LT_CLASS:
787 li->li_number = -1;
788 li->li_name = strdup(sp);
789 if (li->li_name == NULL)
790 err(STATUS_ERROR, "Cannot allocate memory");
791 break;
792 default:
793 usage();
794 }
795 }
796
797 if (empty)
798 usage();
799 }
800
801 static int
takepid(const char * pidfile,int pidfilelock)802 takepid(const char *pidfile, int pidfilelock)
803 {
804 char *endp, line[BUFSIZ];
805 FILE *fh;
806 long rval;
807
808 fh = fopen(pidfile, "r");
809 if (fh == NULL)
810 err(STATUS_ERROR, "Cannot open pidfile `%s'", pidfile);
811
812 if (pidfilelock) {
813 /*
814 * If we can lock pidfile, this means that daemon is not
815 * running, so would be better not to kill some random process.
816 */
817 if (flock(fileno(fh), LOCK_EX | LOCK_NB) == 0) {
818 (void)fclose(fh);
819 errx(STATUS_ERROR, "File '%s' can be locked", pidfile);
820 } else {
821 if (errno != EWOULDBLOCK) {
822 errx(STATUS_ERROR,
823 "Error while locking file '%s'", pidfile);
824 }
825 }
826 }
827
828 if (fgets(line, sizeof(line), fh) == NULL) {
829 if (feof(fh)) {
830 (void)fclose(fh);
831 errx(STATUS_ERROR, "Pidfile `%s' is empty", pidfile);
832 }
833 (void)fclose(fh);
834 err(STATUS_ERROR, "Cannot read from pid file `%s'", pidfile);
835 }
836 (void)fclose(fh);
837
838 rval = strtol(line, &endp, 10);
839 if (*endp != '\0' && !isspace((unsigned char)*endp))
840 errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
841 else if (rval < MIN_PID || rval > MAX_PID)
842 errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
843 return (rval);
844 }
845