ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/trunk/bin/pkill/pkill.c
Revision: 11189
Committed: Sun Jul 1 00:21:10 2018 UTC (5 years, 10 months ago) by laffer1
Content type: text/plain
File size: 19232 byte(s)
Log Message:
sync with freebsd

File Contents

# Content
1 /* $MidnightBSD$ */
2 /* $NetBSD: pkill.c,v 1.16 2005/10/10 22:13:20 kleink Exp $ */
3
4 /*-
5 * Copyright (c) 2002 The NetBSD Foundation, Inc.
6 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Andrew Doran.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD: stable/10/bin/pkill/pkill.c 287269 2015-08-29 02:41:59Z jamie $");
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/sysctl.h>
40 #include <sys/proc.h>
41 #include <sys/queue.h>
42 #include <sys/stat.h>
43 #include <sys/time.h>
44 #include <sys/user.h>
45
46 #include <assert.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_KTHREAD) != 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 plist = kvm_getprocs(kd, KERN_PROC_PROC, 0, &nproc);
324 if (plist == NULL) {
325 errx(STATUS_ERROR, "Cannot get process list (%s)",
326 kvm_geterr(kd));
327 }
328
329 /*
330 * Allocate memory which will be used to keep track of the
331 * selection.
332 */
333 if ((selected = malloc(nproc)) == NULL) {
334 err(STATUS_ERROR, "Cannot allocate memory for %d processes",
335 nproc);
336 }
337 memset(selected, 0, nproc);
338
339 /*
340 * Refine the selection.
341 */
342 for (; *argv != NULL; argv++) {
343 if ((rv = regcomp(&reg, *argv, cflags)) != 0) {
344 regerror(rv, &reg, buf, sizeof(buf));
345 errx(STATUS_BADUSAGE,
346 "Cannot compile regular expression `%s' (%s)",
347 *argv, buf);
348 }
349
350 for (i = 0, kp = plist; i < nproc; i++, kp++) {
351 if (PSKIP(kp)) {
352 if (debug_opt > 0)
353 fprintf(stderr, "* Skipped %5d %3d %s\n",
354 kp->ki_pid, kp->ki_uid, kp->ki_comm);
355 continue;
356 }
357
358 if (matchargs &&
359 (pargv = kvm_getargv(kd, kp, 0)) != NULL) {
360 jsz = 0;
361 while (jsz < sizeof(buf) && *pargv != NULL) {
362 jsz += snprintf(buf + jsz,
363 sizeof(buf) - jsz,
364 pargv[1] != NULL ? "%s " : "%s",
365 pargv[0]);
366 pargv++;
367 }
368 mstr = buf;
369 } else
370 mstr = kp->ki_comm;
371
372 rv = regexec(&reg, mstr, 1, &regmatch, 0);
373 if (rv == 0) {
374 if (fullmatch) {
375 if (regmatch.rm_so == 0 &&
376 regmatch.rm_eo ==
377 (off_t)strlen(mstr))
378 selected[i] = 1;
379 } else
380 selected[i] = 1;
381 } else if (rv != REG_NOMATCH) {
382 regerror(rv, &reg, buf, sizeof(buf));
383 errx(STATUS_ERROR,
384 "Regular expression evaluation error (%s)",
385 buf);
386 }
387 if (debug_opt > 1) {
388 const char *rv_res = "NoMatch";
389 if (selected[i])
390 rv_res = "Matched";
391 fprintf(stderr, "* %s %5d %3d %s\n", rv_res,
392 kp->ki_pid, kp->ki_uid, mstr);
393 }
394 }
395
396 regfree(&reg);
397 }
398
399 for (i = 0, kp = plist; i < nproc; i++, kp++) {
400 if (PSKIP(kp))
401 continue;
402
403 if (pidfromfile >= 0 && kp->ki_pid != pidfromfile) {
404 selected[i] = 0;
405 continue;
406 }
407
408 SLIST_FOREACH(li, &ruidlist, li_chain)
409 if (kp->ki_ruid == (uid_t)li->li_number)
410 break;
411 if (SLIST_FIRST(&ruidlist) != NULL && li == NULL) {
412 selected[i] = 0;
413 continue;
414 }
415
416 SLIST_FOREACH(li, &rgidlist, li_chain)
417 if (kp->ki_rgid == (gid_t)li->li_number)
418 break;
419 if (SLIST_FIRST(&rgidlist) != NULL && li == NULL) {
420 selected[i] = 0;
421 continue;
422 }
423
424 SLIST_FOREACH(li, &euidlist, li_chain)
425 if (kp->ki_uid == (uid_t)li->li_number)
426 break;
427 if (SLIST_FIRST(&euidlist) != NULL && li == NULL) {
428 selected[i] = 0;
429 continue;
430 }
431
432 SLIST_FOREACH(li, &ppidlist, li_chain)
433 if (kp->ki_ppid == (pid_t)li->li_number)
434 break;
435 if (SLIST_FIRST(&ppidlist) != NULL && li == NULL) {
436 selected[i] = 0;
437 continue;
438 }
439
440 SLIST_FOREACH(li, &pgrplist, li_chain)
441 if (kp->ki_pgid == (pid_t)li->li_number)
442 break;
443 if (SLIST_FIRST(&pgrplist) != NULL && li == NULL) {
444 selected[i] = 0;
445 continue;
446 }
447
448 SLIST_FOREACH(li, &tdevlist, li_chain) {
449 if (li->li_number == -1 &&
450 (kp->ki_flag & P_CONTROLT) == 0)
451 break;
452 if (kp->ki_tdev == (dev_t)li->li_number)
453 break;
454 }
455 if (SLIST_FIRST(&tdevlist) != NULL && li == NULL) {
456 selected[i] = 0;
457 continue;
458 }
459
460 SLIST_FOREACH(li, &sidlist, li_chain)
461 if (kp->ki_sid == (pid_t)li->li_number)
462 break;
463 if (SLIST_FIRST(&sidlist) != NULL && li == NULL) {
464 selected[i] = 0;
465 continue;
466 }
467
468 SLIST_FOREACH(li, &jidlist, li_chain) {
469 /* A particular jail ID, including 0 (not in jail) */
470 if (kp->ki_jid == (int)li->li_number)
471 break;
472 /* Any jail */
473 if (kp->ki_jid > 0 && li->li_number == -1)
474 break;
475 }
476 if (SLIST_FIRST(&jidlist) != NULL && li == NULL) {
477 selected[i] = 0;
478 continue;
479 }
480
481 SLIST_FOREACH(li, &classlist, li_chain) {
482 /*
483 * We skip P_SYSTEM processes to match ps(1) output.
484 */
485 if ((kp->ki_flag & P_SYSTEM) == 0 &&
486 strcmp(kp->ki_loginclass, li->li_name) == 0)
487 break;
488 }
489 if (SLIST_FIRST(&classlist) != NULL && li == NULL) {
490 selected[i] = 0;
491 continue;
492 }
493
494 if (argc == 0)
495 selected[i] = 1;
496 }
497
498 if (!ancestors) {
499 pid = mypid;
500 while (pid) {
501 for (i = 0, kp = plist; i < nproc; i++, kp++) {
502 if (PSKIP(kp))
503 continue;
504 if (kp->ki_pid == pid) {
505 selected[i] = 0;
506 pid = kp->ki_ppid;
507 break;
508 }
509 }
510 if (i == nproc) {
511 if (pid == mypid)
512 pid = getppid();
513 else
514 break; /* Maybe we're in a jail ? */
515 }
516 }
517 }
518
519 if (newest || oldest) {
520 best_tval.tv_sec = 0;
521 best_tval.tv_usec = 0;
522 bestidx = -1;
523
524 for (i = 0, kp = plist; i < nproc; i++, kp++) {
525 if (!selected[i])
526 continue;
527 if (bestidx == -1) {
528 /* The first entry of the list which matched. */
529 ;
530 } else if (timercmp(&kp->ki_start, &best_tval, >)) {
531 /* This entry is newer than previous "best". */
532 if (oldest) /* but we want the oldest */
533 continue;
534 } else {
535 /* This entry is older than previous "best". */
536 if (newest) /* but we want the newest */
537 continue;
538 }
539 /* This entry is better than previous "best" entry. */
540 best_tval.tv_sec = kp->ki_start.tv_sec;
541 best_tval.tv_usec = kp->ki_start.tv_usec;
542 bestidx = i;
543 }
544
545 memset(selected, 0, nproc);
546 if (bestidx != -1)
547 selected[bestidx] = 1;
548 }
549
550 /*
551 * Take the appropriate action for each matched process, if any.
552 */
553 did_action = 0;
554 for (i = 0, rv = 0, kp = plist; i < nproc; i++, kp++) {
555 if (PSKIP(kp))
556 continue;
557 if (selected[i]) {
558 if (longfmt && !pgrep) {
559 did_action = 1;
560 printf("kill -%d %d\n", signum, kp->ki_pid);
561 }
562 if (inverse)
563 continue;
564 } else if (!inverse)
565 continue;
566 rv |= (*action)(kp);
567 }
568 if (!did_action && !pgrep && longfmt)
569 fprintf(stderr,
570 "No matching processes belonging to you were found\n");
571
572 exit(rv ? STATUS_MATCH : STATUS_NOMATCH);
573 }
574
575 static void
576 usage(void)
577 {
578 const char *ustr;
579
580 if (pgrep)
581 ustr = "[-LSfilnoqvx] [-d delim]";
582 else
583 ustr = "[-signal] [-ILfilnovx]";
584
585 fprintf(stderr,
586 "usage: %s %s [-F pidfile] [-G gid] [-M core] [-N system]\n"
587 " [-P ppid] [-U uid] [-c class] [-g pgrp] [-j jail]\n"
588 " [-s sid] [-t tty] [-u euid] pattern ...\n",
589 getprogname(), ustr);
590
591 exit(STATUS_BADUSAGE);
592 }
593
594 static void
595 show_process(const struct kinfo_proc *kp)
596 {
597 char **argv;
598
599 if (quiet) {
600 assert(pgrep);
601 return;
602 }
603 if ((longfmt || !pgrep) && matchargs &&
604 (argv = kvm_getargv(kd, kp, 0)) != NULL) {
605 printf("%d ", (int)kp->ki_pid);
606 for (; *argv != NULL; argv++) {
607 printf("%s", *argv);
608 if (argv[1] != NULL)
609 putchar(' ');
610 }
611 } else if (longfmt || !pgrep)
612 printf("%d %s", (int)kp->ki_pid, kp->ki_comm);
613 else
614 printf("%d", (int)kp->ki_pid);
615 }
616
617 static int
618 killact(const struct kinfo_proc *kp)
619 {
620 int ch, first;
621
622 if (interactive) {
623 /*
624 * Be careful, ask before killing.
625 */
626 printf("kill ");
627 show_process(kp);
628 printf("? ");
629 fflush(stdout);
630 first = ch = getchar();
631 while (ch != '\n' && ch != EOF)
632 ch = getchar();
633 if (first != 'y' && first != 'Y')
634 return (1);
635 }
636 if (kill(kp->ki_pid, signum) == -1) {
637 /*
638 * Check for ESRCH, which indicates that the process
639 * disappeared between us matching it and us
640 * signalling it; don't issue a warning about it.
641 */
642 if (errno != ESRCH)
643 warn("signalling pid %d", (int)kp->ki_pid);
644 /*
645 * Return 0 to indicate that the process should not be
646 * considered a match, since we didn't actually get to
647 * signal it.
648 */
649 return (0);
650 }
651 return (1);
652 }
653
654 static int
655 grepact(const struct kinfo_proc *kp)
656 {
657
658 show_process(kp);
659 if (!quiet)
660 printf("%s", delim);
661 return (1);
662 }
663
664 static void
665 makelist(struct listhead *head, enum listtype type, char *src)
666 {
667 struct list *li;
668 struct passwd *pw;
669 struct group *gr;
670 struct stat st;
671 const char *cp;
672 char *sp, *ep, buf[MAXPATHLEN];
673 int empty;
674
675 empty = 1;
676
677 while ((sp = strsep(&src, ",")) != NULL) {
678 if (*sp == '\0')
679 usage();
680
681 if ((li = malloc(sizeof(*li))) == NULL) {
682 err(STATUS_ERROR, "Cannot allocate %zu bytes",
683 sizeof(*li));
684 }
685
686 SLIST_INSERT_HEAD(head, li, li_chain);
687 empty = 0;
688
689 if (type != LT_CLASS)
690 li->li_number = (uid_t)strtol(sp, &ep, 0);
691
692 if (type != LT_CLASS && *ep == '\0') {
693 switch (type) {
694 case LT_PGRP:
695 if (li->li_number == 0)
696 li->li_number = getpgrp();
697 break;
698 case LT_SID:
699 if (li->li_number == 0)
700 li->li_number = getsid(mypid);
701 break;
702 case LT_JAIL:
703 if (li->li_number < 0)
704 errx(STATUS_BADUSAGE,
705 "Negative jail ID `%s'", sp);
706 /* For compatibility with old -j */
707 if (li->li_number == 0)
708 li->li_number = -1; /* any jail */
709 break;
710 case LT_TTY:
711 if (li->li_number < 0)
712 errx(STATUS_BADUSAGE,
713 "Negative /dev/pts tty `%s'", sp);
714 snprintf(buf, sizeof(buf), _PATH_DEV "pts/%s",
715 sp);
716 if (stat(buf, &st) != -1)
717 goto foundtty;
718 if (errno == ENOENT)
719 errx(STATUS_BADUSAGE, "No such tty: `"
720 _PATH_DEV "pts/%s'", sp);
721 err(STATUS_ERROR, "Cannot access `"
722 _PATH_DEV "pts/%s'", sp);
723 break;
724 default:
725 break;
726 }
727 continue;
728 }
729
730 switch (type) {
731 case LT_USER:
732 if ((pw = getpwnam(sp)) == NULL)
733 errx(STATUS_BADUSAGE, "Unknown user `%s'", sp);
734 li->li_number = pw->pw_uid;
735 break;
736 case LT_GROUP:
737 if ((gr = getgrnam(sp)) == NULL)
738 errx(STATUS_BADUSAGE, "Unknown group `%s'", sp);
739 li->li_number = gr->gr_gid;
740 break;
741 case LT_TTY:
742 if (strcmp(sp, "-") == 0) {
743 li->li_number = -1;
744 break;
745 } else if (strcmp(sp, "co") == 0) {
746 cp = "console";
747 } else {
748 cp = sp;
749 }
750
751 snprintf(buf, sizeof(buf), _PATH_DEV "%s", cp);
752 if (stat(buf, &st) != -1)
753 goto foundtty;
754
755 snprintf(buf, sizeof(buf), _PATH_DEV "tty%s", cp);
756 if (stat(buf, &st) != -1)
757 goto foundtty;
758
759 if (errno == ENOENT)
760 errx(STATUS_BADUSAGE, "No such tty: `%s'", sp);
761 err(STATUS_ERROR, "Cannot access `%s'", sp);
762
763 foundtty: if ((st.st_mode & S_IFCHR) == 0)
764 errx(STATUS_BADUSAGE, "Not a tty: `%s'", sp);
765
766 li->li_number = st.st_rdev;
767 break;
768 case LT_JAIL: {
769 int jid;
770
771 if (strcmp(sp, "none") == 0)
772 li->li_number = 0;
773 else if (strcmp(sp, "any") == 0)
774 li->li_number = -1;
775 else if ((jid = jail_getid(sp)) != -1)
776 li->li_number = jid;
777 else if (*ep != '\0')
778 errx(STATUS_BADUSAGE,
779 "Invalid jail ID or name `%s'", sp);
780 break;
781 }
782 case LT_CLASS:
783 li->li_number = -1;
784 li->li_name = strdup(sp);
785 if (li->li_name == NULL)
786 err(STATUS_ERROR, "Cannot allocate memory");
787 break;
788 default:
789 usage();
790 }
791 }
792
793 if (empty)
794 usage();
795 }
796
797 static int
798 takepid(const char *pidfile, int pidfilelock)
799 {
800 char *endp, line[BUFSIZ];
801 FILE *fh;
802 long rval;
803
804 fh = fopen(pidfile, "r");
805 if (fh == NULL)
806 err(STATUS_ERROR, "Cannot open pidfile `%s'", pidfile);
807
808 if (pidfilelock) {
809 /*
810 * If we can lock pidfile, this means that daemon is not
811 * running, so would be better not to kill some random process.
812 */
813 if (flock(fileno(fh), LOCK_EX | LOCK_NB) == 0) {
814 (void)fclose(fh);
815 errx(STATUS_ERROR, "File '%s' can be locked", pidfile);
816 } else {
817 if (errno != EWOULDBLOCK) {
818 errx(STATUS_ERROR,
819 "Error while locking file '%s'", pidfile);
820 }
821 }
822 }
823
824 if (fgets(line, sizeof(line), fh) == NULL) {
825 if (feof(fh)) {
826 (void)fclose(fh);
827 errx(STATUS_ERROR, "Pidfile `%s' is empty", pidfile);
828 }
829 (void)fclose(fh);
830 err(STATUS_ERROR, "Cannot read from pid file `%s'", pidfile);
831 }
832 (void)fclose(fh);
833
834 rval = strtol(line, &endp, 10);
835 if (*endp != '\0' && !isspace((unsigned char)*endp))
836 errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
837 else if (rval < MIN_PID || rval > MAX_PID)
838 errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
839 return (rval);
840 }

Properties

Name Value
svn:keywords MidnightBSD=%H