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