]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - bin/pkill/pkill.c
2 Bugs:
[FreeBSD/FreeBSD.git] / bin / pkill / pkill.c
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 }