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