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