]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - bin/pkill/pkill.c
zfs: merge openzfs/zfs@2e2a46e0a
[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  * SPDX-License-Identifier: BSD-2-Clause
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 #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, *mstr, **pargv, *p, *q, *pidfile;
135         const char *execf, *coref;
136         size_t bufsz;
137         int ancestors, debug_opt, did_action;
138         int i, ch, bestidx, rv, criteria, pidfromfile, pidfilelock;
139         size_t jsz;
140         int (*action)(const struct kinfo_proc *);
141         struct kinfo_proc *kp;
142         struct list *li;
143         struct timeval best_tval;
144         regex_t reg;
145         regmatch_t regmatch;
146         pid_t pid;
147
148         setlocale(LC_ALL, "");
149
150         if (strcmp(getprogname(), "pgrep") == 0) {
151                 action = grepact;
152                 pgrep = 1;
153         } else {
154                 action = killact;
155                 p = argv[1];
156
157                 if (argc > 1 && p[0] == '-') {
158                         p++;
159                         i = (int)strtol(p, &q, 10);
160                         if (*q == '\0') {
161                                 signum = i;
162                                 argv++;
163                                 argc--;
164                         } else {
165                                 if (strncasecmp(p, "SIG", 3) == 0)
166                                         p += 3;
167                                 for (i = 1; i < NSIG; i++)
168                                         if (strcasecmp(sys_signame[i], p) == 0)
169                                                 break;
170                                 if (i != NSIG) {
171                                         signum = i;
172                                         argv++;
173                                         argc--;
174                                 }
175                         }
176                 }
177         }
178
179         buf = NULL;
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          * If we're not matching args, we only need a buffer large enough to
316          * hold some relatively short error strings.  Otherwise, we have to
317          * assume we'll need up to ARG_MAX bytes for arguments.
318          */
319         bufsz = _POSIX2_LINE_MAX;
320         if (matchargs) {
321                 long arg_max;
322
323                 arg_max = sysconf(_SC_ARG_MAX);
324                 if (arg_max == -1)
325                         arg_max = ARG_MAX;
326
327                 /*
328                  * The absolute worst case scenario is ARG_MAX single-byte
329                  * arguments which we'll then separate with spaces and NUL
330                  * terminate.
331                  */
332                 bufsz = (arg_max * 2) + 1;
333         }
334
335         buf = malloc(bufsz);
336         if (buf == NULL)
337                 err(STATUS_ERROR, "malloc");
338
339         /*
340          * Retrieve the list of running processes from the kernel.
341          */
342         kd = kvm_openfiles(execf, coref, NULL, O_RDONLY, buf);
343         if (kd == NULL)
344                 errx(STATUS_ERROR, "Cannot open kernel files (%s)", buf);
345
346         /*
347          * Use KERN_PROC_PROC instead of KERN_PROC_ALL, since we
348          * just want processes and not individual kernel threads.
349          */
350         if (pidfromfile >= 0)
351                 plist = kvm_getprocs(kd, KERN_PROC_PID, pidfromfile, &nproc);
352         else
353                 plist = kvm_getprocs(kd, KERN_PROC_PROC, 0, &nproc);
354         if (plist == NULL) {
355                 errx(STATUS_ERROR, "Cannot get process list (%s)",
356                     kvm_geterr(kd));
357         }
358
359         /*
360          * Allocate memory which will be used to keep track of the
361          * selection.
362          */
363         if ((selected = malloc(nproc)) == NULL) {
364                 err(STATUS_ERROR, "Cannot allocate memory for %d processes",
365                     nproc);
366         }
367         memset(selected, 0, nproc);
368
369         /*
370          * Refine the selection.
371          */
372         for (; *argv != NULL; argv++) {
373                 if ((rv = regcomp(&reg, *argv, cflags)) != 0) {
374                         regerror(rv, &reg, buf, bufsz);
375                         errx(STATUS_BADUSAGE,
376                             "Cannot compile regular expression `%s' (%s)",
377                             *argv, buf);
378                 }
379
380                 for (i = 0, kp = plist; i < nproc; i++, kp++) {
381                         if (PSKIP(kp)) {
382                                 if (debug_opt > 0)
383                                     fprintf(stderr, "* Skipped %5d %3d %s\n",
384                                         kp->ki_pid, kp->ki_uid, kp->ki_comm);
385                                 continue;
386                         }
387
388                         if (matchargs &&
389                             (pargv = kvm_getargv(kd, kp, 0)) != NULL) {
390                                 jsz = 0;
391                                 while (jsz < bufsz && *pargv != NULL) {
392                                         jsz += snprintf(buf + jsz,
393                                             bufsz - jsz,
394                                             pargv[1] != NULL ? "%s " : "%s",
395                                             pargv[0]);
396                                         pargv++;
397                                 }
398                                 mstr = buf;
399                         } else
400                                 mstr = kp->ki_comm;
401
402                         rv = regexec(&reg, mstr, 1, &regmatch, 0);
403                         if (rv == 0) {
404                                 if (fullmatch) {
405                                         if (regmatch.rm_so == 0 &&
406                                             regmatch.rm_eo ==
407                                             (off_t)strlen(mstr))
408                                                 selected[i] = 1;
409                                 } else
410                                         selected[i] = 1;
411                         } else if (rv != REG_NOMATCH) {
412                                 regerror(rv, &reg, buf, bufsz);
413                                 errx(STATUS_ERROR,
414                                     "Regular expression evaluation error (%s)",
415                                     buf);
416                         }
417                         if (debug_opt > 1) {
418                                 const char *rv_res = "NoMatch";
419                                 if (selected[i])
420                                         rv_res = "Matched";
421                                 fprintf(stderr, "* %s %5d %3d %s\n", rv_res,
422                                     kp->ki_pid, kp->ki_uid, mstr);
423                         }
424                 }
425
426                 regfree(&reg);
427         }
428
429         for (i = 0, kp = plist; i < nproc; i++, kp++) {
430                 if (PSKIP(kp))
431                         continue;
432
433                 if (pidfromfile >= 0 && kp->ki_pid != pidfromfile) {
434                         selected[i] = 0;
435                         continue;
436                 }
437
438                 SLIST_FOREACH(li, &ruidlist, li_chain)
439                         if (kp->ki_ruid == (uid_t)li->li_number)
440                                 break;
441                 if (SLIST_FIRST(&ruidlist) != NULL && li == NULL) {
442                         selected[i] = 0;
443                         continue;
444                 }
445
446                 SLIST_FOREACH(li, &rgidlist, li_chain)
447                         if (kp->ki_rgid == (gid_t)li->li_number)
448                                 break;
449                 if (SLIST_FIRST(&rgidlist) != NULL && li == NULL) {
450                         selected[i] = 0;
451                         continue;
452                 }
453
454                 SLIST_FOREACH(li, &euidlist, li_chain)
455                         if (kp->ki_uid == (uid_t)li->li_number)
456                                 break;
457                 if (SLIST_FIRST(&euidlist) != NULL && li == NULL) {
458                         selected[i] = 0;
459                         continue;
460                 }
461
462                 SLIST_FOREACH(li, &ppidlist, li_chain)
463                         if (kp->ki_ppid == (pid_t)li->li_number)
464                                 break;
465                 if (SLIST_FIRST(&ppidlist) != NULL && li == NULL) {
466                         selected[i] = 0;
467                         continue;
468                 }
469
470                 SLIST_FOREACH(li, &pgrplist, li_chain)
471                         if (kp->ki_pgid == (pid_t)li->li_number)
472                                 break;
473                 if (SLIST_FIRST(&pgrplist) != NULL && li == NULL) {
474                         selected[i] = 0;
475                         continue;
476                 }
477
478                 SLIST_FOREACH(li, &tdevlist, li_chain) {
479                         if (li->li_number == -1 &&
480                             (kp->ki_flag & P_CONTROLT) == 0)
481                                 break;
482                         if (kp->ki_tdev == (dev_t)li->li_number)
483                                 break;
484                 }
485                 if (SLIST_FIRST(&tdevlist) != NULL && li == NULL) {
486                         selected[i] = 0;
487                         continue;
488                 }
489
490                 SLIST_FOREACH(li, &sidlist, li_chain)
491                         if (kp->ki_sid == (pid_t)li->li_number)
492                                 break;
493                 if (SLIST_FIRST(&sidlist) != NULL && li == NULL) {
494                         selected[i] = 0;
495                         continue;
496                 }
497
498                 SLIST_FOREACH(li, &jidlist, li_chain) {
499                         /* A particular jail ID, including 0 (not in jail) */
500                         if (kp->ki_jid == (int)li->li_number)
501                                 break;
502                         /* Any jail */
503                         if (kp->ki_jid > 0 && li->li_number == -1)
504                                 break;
505                 }
506                 if (SLIST_FIRST(&jidlist) != NULL && li == NULL) {
507                         selected[i] = 0;
508                         continue;
509                 }
510
511                 SLIST_FOREACH(li, &classlist, li_chain) {
512                         /*
513                          * We skip P_SYSTEM processes to match ps(1) output.
514                          */
515                         if ((kp->ki_flag & P_SYSTEM) == 0 &&
516                             strcmp(kp->ki_loginclass, li->li_name) == 0)
517                                 break;
518                 }
519                 if (SLIST_FIRST(&classlist) != NULL && li == NULL) {
520                         selected[i] = 0;
521                         continue;
522                 }
523
524                 if (argc == 0)
525                         selected[i] = 1;
526         }
527
528         if (!ancestors) {
529                 pid = mypid;
530                 while (pid) {
531                         for (i = 0, kp = plist; i < nproc; i++, kp++) {
532                                 if (PSKIP(kp))
533                                         continue;
534                                 if (kp->ki_pid == pid) {
535                                         selected[i] = 0;
536                                         pid = kp->ki_ppid;
537                                         break;
538                                 }
539                         }
540                         if (i == nproc) {
541                                 if (pid == mypid)
542                                         pid = getppid();
543                                 else
544                                         break;  /* Maybe we're in a jail ? */
545                         }
546                 }
547         }
548
549         if (newest || oldest) {
550                 best_tval.tv_sec = 0;
551                 best_tval.tv_usec = 0;
552                 bestidx = -1;
553
554                 for (i = 0, kp = plist; i < nproc; i++, kp++) {
555                         if (!selected[i])
556                                 continue;
557                         if (bestidx == -1) {
558                                 /* The first entry of the list which matched. */
559                                 ;
560                         } else if (timercmp(&kp->ki_start, &best_tval, >)) {
561                                 /* This entry is newer than previous "best". */
562                                 if (oldest)     /* but we want the oldest */
563                                         continue;
564                         } else {
565                                 /* This entry is older than previous "best". */
566                                 if (newest)     /* but we want the newest */
567                                         continue;
568                         }
569                         /* This entry is better than previous "best" entry. */
570                         best_tval.tv_sec = kp->ki_start.tv_sec;
571                         best_tval.tv_usec = kp->ki_start.tv_usec;
572                         bestidx = i;
573                 }
574
575                 memset(selected, 0, nproc);
576                 if (bestidx != -1)
577                         selected[bestidx] = 1;
578         }
579
580         /*
581          * Take the appropriate action for each matched process, if any.
582          */
583         did_action = 0;
584         for (i = 0, rv = 0, kp = plist; i < nproc; i++, kp++) {
585                 if (PSKIP(kp))
586                         continue;
587                 if (selected[i]) {
588                         if (longfmt && !pgrep) {
589                                 did_action = 1;
590                                 printf("kill -%d %d\n", signum, kp->ki_pid);
591                         }
592                         if (inverse)
593                                 continue;
594                 } else if (!inverse)
595                         continue;
596                 rv |= (*action)(kp);
597         }
598         if (rv && pgrep && !quiet)
599                 putchar('\n');
600         if (!did_action && !pgrep && longfmt)
601                 fprintf(stderr,
602                     "No matching processes belonging to you were found\n");
603
604         free(buf);
605         exit(rv ? STATUS_MATCH : STATUS_NOMATCH);
606 }
607
608 static void
609 usage(void)
610 {
611         const char *ustr;
612
613         if (pgrep)
614                 ustr = "[-LSfilnoqvx] [-d delim]";
615         else
616                 ustr = "[-signal] [-ILfilnovx]";
617
618         fprintf(stderr,
619                 "usage: %s %s [-F pidfile] [-G gid] [-M core] [-N system]\n"
620                 "             [-P ppid] [-U uid] [-c class] [-g pgrp] [-j jail]\n"
621                 "             [-s sid] [-t tty] [-u euid] pattern ...\n",
622                 getprogname(), ustr);
623
624         exit(STATUS_BADUSAGE);
625 }
626
627 static void
628 show_process(const struct kinfo_proc *kp)
629 {
630         char **argv;
631
632         if (quiet) {
633                 assert(pgrep);
634                 return;
635         }
636         if ((longfmt || !pgrep) && matchargs &&
637             (argv = kvm_getargv(kd, kp, 0)) != NULL) {
638                 printf("%d ", (int)kp->ki_pid);
639                 for (; *argv != NULL; argv++) {
640                         printf("%s", *argv);
641                         if (argv[1] != NULL)
642                                 putchar(' ');
643                 }
644         } else if (longfmt || !pgrep)
645                 printf("%d %s", (int)kp->ki_pid, kp->ki_comm);
646         else
647                 printf("%d", (int)kp->ki_pid);
648 }
649
650 static int
651 killact(const struct kinfo_proc *kp)
652 {
653         int ch, first;
654
655         if (interactive) {
656                 /*
657                  * Be careful, ask before killing.
658                  */
659                 printf("kill ");
660                 show_process(kp);
661                 printf("? ");
662                 fflush(stdout);
663                 first = ch = getchar();
664                 while (ch != '\n' && ch != EOF)
665                         ch = getchar();
666                 if (first != 'y' && first != 'Y')
667                         return (1);
668         }
669         if (kill(kp->ki_pid, signum) == -1) {
670                 /* 
671                  * Check for ESRCH, which indicates that the process
672                  * disappeared between us matching it and us
673                  * signalling it; don't issue a warning about it.
674                  */
675                 if (errno != ESRCH)
676                         warn("signalling pid %d", (int)kp->ki_pid);
677                 /*
678                  * Return 0 to indicate that the process should not be
679                  * considered a match, since we didn't actually get to
680                  * signal it.
681                  */
682                 return (0);
683         }
684         return (1);
685 }
686
687 static int
688 grepact(const struct kinfo_proc *kp)
689 {
690         static bool first = true;
691
692         if (!quiet && !first)
693                 printf("%s", delim);
694         show_process(kp);
695         first = false;
696         return (1);
697 }
698
699 static void
700 makelist(struct listhead *head, enum listtype type, char *src)
701 {
702         struct list *li;
703         struct passwd *pw;
704         struct group *gr;
705         struct stat st;
706         const char *cp;
707         char *sp, *ep, buf[MAXPATHLEN];
708         int empty;
709
710         empty = 1;
711
712         while ((sp = strsep(&src, ",")) != NULL) {
713                 if (*sp == '\0')
714                         usage();
715
716                 if ((li = malloc(sizeof(*li))) == NULL) {
717                         err(STATUS_ERROR, "Cannot allocate %zu bytes",
718                             sizeof(*li));
719                 }
720
721                 SLIST_INSERT_HEAD(head, li, li_chain);
722                 empty = 0;
723
724                 if (type != LT_CLASS)
725                         li->li_number = (uid_t)strtol(sp, &ep, 0);
726
727                 if (type != LT_CLASS && *ep == '\0') {
728                         switch (type) {
729                         case LT_PGRP:
730                                 if (li->li_number == 0)
731                                         li->li_number = getpgrp();
732                                 break;
733                         case LT_SID:
734                                 if (li->li_number == 0)
735                                         li->li_number = getsid(mypid);
736                                 break;
737                         case LT_JAIL:
738                                 if (li->li_number < 0)
739                                         errx(STATUS_BADUSAGE,
740                                              "Negative jail ID `%s'", sp);
741                                 /* For compatibility with old -j */
742                                 if (li->li_number == 0)
743                                         li->li_number = -1;     /* any jail */
744                                 break;
745                         case LT_TTY:
746                                 if (li->li_number < 0)
747                                         errx(STATUS_BADUSAGE,
748                                              "Negative /dev/pts tty `%s'", sp);
749                                 snprintf(buf, sizeof(buf), _PATH_DEV "pts/%s",
750                                     sp);
751                                 if (stat(buf, &st) != -1)
752                                         goto foundtty;
753                                 if (errno == ENOENT)
754                                         errx(STATUS_BADUSAGE, "No such tty: `"
755                                             _PATH_DEV "pts/%s'", sp);
756                                 err(STATUS_ERROR, "Cannot access `"
757                                     _PATH_DEV "pts/%s'", sp);
758                                 break;
759                         default:
760                                 break;
761                         }
762                         continue;
763                 }
764
765                 switch (type) {
766                 case LT_USER:
767                         if ((pw = getpwnam(sp)) == NULL)
768                                 errx(STATUS_BADUSAGE, "Unknown user `%s'", sp);
769                         li->li_number = pw->pw_uid;
770                         break;
771                 case LT_GROUP:
772                         if ((gr = getgrnam(sp)) == NULL)
773                                 errx(STATUS_BADUSAGE, "Unknown group `%s'", sp);
774                         li->li_number = gr->gr_gid;
775                         break;
776                 case LT_TTY:
777                         if (strcmp(sp, "-") == 0) {
778                                 li->li_number = -1;
779                                 break;
780                         } else if (strcmp(sp, "co") == 0) {
781                                 cp = "console";
782                         } else {
783                                 cp = sp;
784                         }
785
786                         snprintf(buf, sizeof(buf), _PATH_DEV "%s", cp);
787                         if (stat(buf, &st) != -1)
788                                 goto foundtty;
789
790                         snprintf(buf, sizeof(buf), _PATH_DEV "tty%s", cp);
791                         if (stat(buf, &st) != -1)
792                                 goto foundtty;
793
794                         if (errno == ENOENT)
795                                 errx(STATUS_BADUSAGE, "No such tty: `%s'", sp);
796                         err(STATUS_ERROR, "Cannot access `%s'", sp);
797
798 foundtty:               if ((st.st_mode & S_IFCHR) == 0)
799                                 errx(STATUS_BADUSAGE, "Not a tty: `%s'", sp);
800
801                         li->li_number = st.st_rdev;
802                         break;
803                 case LT_JAIL: {
804                         int jid;
805
806                         if (strcmp(sp, "none") == 0)
807                                 li->li_number = 0;
808                         else if (strcmp(sp, "any") == 0)
809                                 li->li_number = -1;
810                         else if ((jid = jail_getid(sp)) != -1)
811                                 li->li_number = jid;
812                         else if (*ep != '\0')
813                                 errx(STATUS_BADUSAGE,
814                                      "Invalid jail ID or name `%s'", sp);
815                         break;
816                 }
817                 case LT_CLASS:
818                         li->li_number = -1;
819                         li->li_name = strdup(sp);
820                         if (li->li_name == NULL)
821                                 err(STATUS_ERROR, "Cannot allocate memory");
822                         break;
823                 default:
824                         usage();
825                 }
826         }
827
828         if (empty)
829                 usage();
830 }
831
832 static int
833 takepid(const char *pidfile, int pidfilelock)
834 {
835         char *endp, line[BUFSIZ];
836         FILE *fh;
837         long rval;
838
839         fh = fopen(pidfile, "r");
840         if (fh == NULL)
841                 err(STATUS_ERROR, "Cannot open pidfile `%s'", pidfile);
842
843         if (pidfilelock) {
844                 /*
845                  * If we can lock pidfile, this means that daemon is not
846                  * running, so would be better not to kill some random process.
847                  */
848                 if (flock(fileno(fh), LOCK_EX | LOCK_NB) == 0) {
849                         (void)fclose(fh);
850                         errx(STATUS_ERROR, "File '%s' can be locked", pidfile);
851                 } else {
852                         if (errno != EWOULDBLOCK) {
853                                 errx(STATUS_ERROR,
854                                     "Error while locking file '%s'", pidfile);
855                         }
856                 }
857         }
858
859         if (fgets(line, sizeof(line), fh) == NULL) {
860                 if (feof(fh)) {
861                         (void)fclose(fh);
862                         errx(STATUS_ERROR, "Pidfile `%s' is empty", pidfile);
863                 }
864                 (void)fclose(fh);
865                 err(STATUS_ERROR, "Cannot read from pid file `%s'", pidfile);
866         }
867         (void)fclose(fh);
868
869         rval = strtol(line, &endp, 10);
870         if (*endp != '\0' && !isspace((unsigned char)*endp))
871                 errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
872         else if (rval < MIN_PID || rval > MAX_PID)
873                 errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
874         return (rval);
875 }