1 /* $NetBSD: pkill.c,v 1.16 2005/10/10 22:13:20 kleink Exp $ */
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
8 * This code is derived from software contributed to The NetBSD Foundation
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD: src/bin/pkill/pkill.c,v 1.12 2011/02/04 16:40:50 jilles Exp $");
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/sysctl.h>
40 #include <sys/queue.h>
67 #include <sys/proc_info.h>
68 #include <os/assumes.h>
72 #define STATUS_MATCH 0
73 #define STATUS_NOMATCH 1
74 #define STATUS_BADUSAGE 2
75 #define STATUS_ERROR 3
81 /* Ignore system processes and myself. */
82 #define PSKIP(kp) ((pid_t)xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_PID)) == mypid || \
83 ((xpc_uint64_get_value(sysmon_row_get_value(kp, SYSMON_ATTR_PROC_FLAGS)) & PROC_FLAG_SYSTEM) != 0))
85 /* Ignore system-processes (if '-S' flag is not specified) and myself. */
86 #define PSKIP(kp) ((kp)->ki_pid == mypid || \
87 (!kthreads && ((kp)->ki_flag & P_KTHREAD) != 0))
103 SLIST_ENTRY(list
) li_chain
;
107 SLIST_HEAD(listhead
, list
);
110 static sysmon_table_t plist
;
112 static struct kinfo_proc
*plist
;
114 static char *selected
;
115 static const char *delim
= "\n";
118 static int signum
= SIGTERM
;
121 static int interactive
;
124 static int matchargs
;
125 static int fullmatch
;
129 static int cflags
= REG_EXTENDED
;
136 static struct listhead euidlist
= SLIST_HEAD_INITIALIZER(euidlist
);
137 static struct listhead ruidlist
= SLIST_HEAD_INITIALIZER(ruidlist
);
138 static struct listhead rgidlist
= SLIST_HEAD_INITIALIZER(rgidlist
);
139 static struct listhead pgrplist
= SLIST_HEAD_INITIALIZER(pgrplist
);
140 static struct listhead ppidlist
= SLIST_HEAD_INITIALIZER(ppidlist
);
141 static struct listhead tdevlist
= SLIST_HEAD_INITIALIZER(tdevlist
);
143 static struct listhead sidlist
= SLIST_HEAD_INITIALIZER(sidlist
);
144 static struct listhead jidlist
= SLIST_HEAD_INITIALIZER(jidlist
);
147 static void usage(void) __attribute__((__noreturn__
));
149 static int killact(const sysmon_row_t
);
150 static int grepact(const sysmon_row_t
);
152 static int killact(const struct kinfo_proc
*);
153 static int grepact(const struct kinfo_proc
*);
155 static void makelist(struct listhead
*, enum listtype
, char *);
156 static int takepid(const char *, int);
159 static sysmon_table_t
160 copy_process_info(void)
162 dispatch_semaphore_t sema
;
163 sysmon_request_t request
;
164 __block sysmon_table_t result
= NULL
;
166 sema
= dispatch_semaphore_create(0);
167 request
= sysmon_request_create_with_error(SYSMON_REQUEST_TYPE_PROCESS
, ^(sysmon_table_t table
, const char *error_str
) {
169 result
= sysmon_retain(table
);
171 fprintf(stderr
, "sysmon request failed with error: %s\n", error_str
);
173 dispatch_semaphore_signal(sema
);
175 sysmon_request_add_attribute(request
, SYSMON_ATTR_PROC_PID
);
176 sysmon_request_add_attribute(request
, SYSMON_ATTR_PROC_FLAGS
);
177 sysmon_request_add_attribute(request
, SYSMON_ATTR_PROC_UID
);
178 sysmon_request_add_attribute(request
, SYSMON_ATTR_PROC_COMM
);
179 sysmon_request_add_attribute(request
, SYSMON_ATTR_PROC_ARGUMENTS
);
180 sysmon_request_add_attribute(request
, SYSMON_ATTR_PROC_RUID
);
181 sysmon_request_add_attribute(request
, SYSMON_ATTR_PROC_RGID
);
182 sysmon_request_add_attribute(request
, SYSMON_ATTR_PROC_PPID
);
183 sysmon_request_add_attribute(request
, SYSMON_ATTR_PROC_PGID
);
184 sysmon_request_add_attribute(request
, SYSMON_ATTR_PROC_TDEV
);
185 sysmon_request_add_attribute(request
, SYSMON_ATTR_PROC_START
);
186 sysmon_request_execute(request
);
187 dispatch_semaphore_wait(sema
, DISPATCH_TIME_FOREVER
);
188 dispatch_release(sema
);
189 sysmon_release(request
);
193 #endif /* __APPLE__ */
196 main(int argc
, char **argv
)
199 char buf
[_POSIX2_LINE_MAX
], *bufp
, *mstr
, *p
, *q
, *pidfile
;
202 char buf
[_POSIX2_LINE_MAX
], *mstr
, **pargv
, *p
, *q
, *pidfile
;
203 const char *execf
, *coref
;
205 int ancestors
, debug_opt
, did_action
;
206 int i
, ch
, bestidx
, rv
, criteria
, pidfromfile
, pidfilelock
;
209 int (*action
)(const sysmon_row_t
);
213 int (*action
)(const struct kinfo_proc
*);
214 struct kinfo_proc
*kp
;
220 struct timeval best_tval
;
226 setlocale(LC_ALL
, "");
228 if (strcmp(getprogname(), "pgrep") == 0) {
235 if (argc
> 1 && p
[0] == '-') {
237 i
= (int)strtol(p
, &q
, 10);
243 if (strncasecmp(p
, "SIG", 3) == 0)
245 for (i
= 1; i
< NSIG
; i
++)
246 if (strcasecmp(sys_signame
[i
], p
) == 0)
265 coref
= _PATH_DEVNULL
;
269 while ((ch
= getopt(argc
, argv
, "DF:G:ILP:U:ad:fg:ilnoqt:u:vx")) != -1)
271 while ((ch
= getopt(argc
, argv
, "DF:G:ILM:N:P:SU:ad:fg:ij:lnoqs:t:u:vx")) != -1)
282 makelist(&rgidlist
, LT_GROUP
, optarg
);
302 makelist(&ppidlist
, LT_GENERIC
, optarg
);
313 makelist(&ruidlist
, LT_USER
, optarg
);
328 makelist(&pgrplist
, LT_PGRP
, optarg
);
336 makelist(&jidlist
, LT_JID
, optarg
);
358 makelist(&sidlist
, LT_SID
, optarg
);
361 #endif /* !__APPLE__ */
363 makelist(&tdevlist
, LT_TTY
, optarg
);
367 makelist(&euidlist
, LT_USER
, optarg
);
387 if (newest
&& oldest
)
388 errx(STATUS_ERROR
, "Options -n and -o are mutually exclusive");
390 pidfromfile
= takepid(pidfile
, pidfilelock
);
394 "Option -L doesn't make sense without -F");
402 plist
= copy_process_info();
404 errx(STATUS_ERROR
, "Cannot get process list");
406 nproc
= sysmon_table_get_count(plist
);
409 * Retrieve the list of running processes from the kernel.
411 kd
= kvm_openfiles(execf
, coref
, NULL
, O_RDONLY
, buf
);
413 errx(STATUS_ERROR
, "Cannot open kernel files (%s)", buf
);
416 * Use KERN_PROC_PROC instead of KERN_PROC_ALL, since we
417 * just want processes and not individual kernel threads.
419 plist
= kvm_getprocs(kd
, KERN_PROC_PROC
, 0, &nproc
);
421 errx(STATUS_ERROR
, "Cannot get process list (%s)",
427 * Allocate memory which will be used to keep track of the
430 if ((selected
= malloc(nproc
)) == NULL
) {
431 err(STATUS_ERROR
, "Cannot allocate memory for %d processes",
434 memset(selected
, 0, nproc
);
437 * Refine the selection.
439 for (; *argv
!= NULL
; argv
++) {
440 if ((rv
= regcomp(®
, *argv
, cflags
)) != 0) {
441 regerror(rv
, ®
, buf
, sizeof(buf
));
442 errx(STATUS_BADUSAGE
,
443 "Cannot compile regular expression `%s' (%s)",
448 for (i
= 0; i
< nproc
; i
++) {
449 kp
= sysmon_table_get_row(plist
, i
);
451 for (i
= 0, kp
= plist
; i
< nproc
; i
++, kp
++) {
455 fprintf(stderr
, "* Skipped %5d %3d %s\n",
457 (pid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PID
)),
458 (uid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_UID
)),
459 xpc_string_get_string_ptr(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_COMM
)));
461 kp
->ki_pid
, kp
->ki_uid
, kp
->ki_comm
);
468 (pargv
= sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_ARGUMENTS
)) != NULL
) {
470 os_assert(sizeof(buf
) == _POSIX2_LINE_MAX
);
472 xpc_array_apply(pargv
, ^(size_t index
, xpc_object_t value
) {
473 if (jsz
>= _POSIX2_LINE_MAX
) {
476 jsz
+= snprintf(bufp
+ jsz
,
477 _POSIX2_LINE_MAX
- jsz
,
478 index
< xpc_array_get_count(pargv
) - 1 ? "%s " : "%s",
479 xpc_string_get_string_ptr(value
));
484 (pargv
= kvm_getargv(kd
, kp
, 0)) != NULL
) {
486 while (jsz
< sizeof(buf
) && *pargv
!= NULL
) {
487 jsz
+= snprintf(buf
+ jsz
,
489 pargv
[1] != NULL
? "%s " : "%s",
499 * comm is limited to 15 bytes (MAXCOMLEN - 1).
500 * Try to use argv[0] (trimmed) if available.
503 pargv
= sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_ARGUMENTS
);
504 if (pargv
!= NULL
&& xpc_array_get_count(pargv
) > 0) {
505 const char *tmp
= xpc_array_get_string(pargv
, 0);
507 mstr
= strrchr(tmp
, '/');
516 /* Fall back to "comm" if we failed to get argv[0]. */
517 if (mstr
== NULL
|| *mstr
== '\0') {
518 mstr
= (char *)xpc_string_get_string_ptr(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_COMM
));
521 /* Couldn't find process name, it probably exited. */
530 rv
= regexec(®
, mstr
, 1, ®match
, 0);
533 if (regmatch
.rm_so
== 0 &&
539 } else if (rv
!= REG_NOMATCH
) {
540 regerror(rv
, ®
, buf
, sizeof(buf
));
542 "Regular expression evaluation error (%s)",
546 const char *rv_res
= "NoMatch";
549 fprintf(stderr
, "* %s %5d %3d %s\n", rv_res
,
551 (pid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PID
)),
552 (uid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_UID
)),
555 kp
->ki_pid
, kp
->ki_uid
, mstr
);
564 for (i
= 0; i
< nproc
; i
++) {
565 kp
= sysmon_table_get_row(plist
, i
);
567 for (i
= 0, kp
= plist
; i
< nproc
; i
++, kp
++) {
573 if (pidfromfile
>= 0 && (pid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PID
)) != pidfromfile
) {
575 if (pidfromfile
>= 0 && kp
->ki_pid
!= pidfromfile
) {
581 SLIST_FOREACH(li
, &ruidlist
, li_chain
)
583 if ((uid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_RUID
)) == (uid_t
)li
->li_number
)
585 if (kp
->ki_ruid
== (uid_t
)li
->li_number
)
588 if (SLIST_FIRST(&ruidlist
) != NULL
&& li
== NULL
) {
593 SLIST_FOREACH(li
, &rgidlist
, li_chain
)
595 if ((gid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_RGID
)) == (gid_t
)li
->li_number
)
597 if (kp
->ki_rgid
== (gid_t
)li
->li_number
)
600 if (SLIST_FIRST(&rgidlist
) != NULL
&& li
== NULL
) {
605 SLIST_FOREACH(li
, &euidlist
, li_chain
)
607 if ((uid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_UID
)) == (uid_t
)li
->li_number
)
609 if (kp
->ki_uid
== (uid_t
)li
->li_number
)
612 if (SLIST_FIRST(&euidlist
) != NULL
&& li
== NULL
) {
617 SLIST_FOREACH(li
, &ppidlist
, li_chain
)
619 if ((pid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PPID
)) == (pid_t
)li
->li_number
)
621 if (kp
->ki_ppid
== (pid_t
)li
->li_number
)
624 if (SLIST_FIRST(&ppidlist
) != NULL
&& li
== NULL
) {
629 SLIST_FOREACH(li
, &pgrplist
, li_chain
)
631 if ((pid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PGID
)) == (pid_t
)li
->li_number
)
633 if (kp
->ki_pgid
== (pid_t
)li
->li_number
)
636 if (SLIST_FIRST(&pgrplist
) != NULL
&& li
== NULL
) {
641 SLIST_FOREACH(li
, &tdevlist
, li_chain
) {
642 if (li
->li_number
== -1 &&
644 (xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_FLAGS
)) & PROC_FLAG_CONTROLT
) == 0)
646 (kp
->ki_flag
& P_CONTROLT
) == 0)
650 if ((dev_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_TDEV
)) == (dev_t
)li
->li_number
)
652 if (kp
->ki_tdev
== (dev_t
)li
->li_number
)
656 if (SLIST_FIRST(&tdevlist
) != NULL
&& li
== NULL
) {
662 SLIST_FOREACH(li
, &sidlist
, li_chain
)
663 if (kp
->ki_sid
== (pid_t
)li
->li_number
)
665 if (SLIST_FIRST(&sidlist
) != NULL
&& li
== NULL
) {
670 SLIST_FOREACH(li
, &jidlist
, li_chain
) {
671 /* A particular jail ID, including 0 (not in jail) */
672 if (kp
->ki_jid
== (int)li
->li_number
)
675 if (kp
->ki_jid
> 0 && li
->li_number
== -1)
678 if (SLIST_FIRST(&jidlist
) != NULL
&& li
== NULL
) {
682 #endif /* !__APPLE__ */
692 for (i
= 0; i
< nproc
; i
++) {
693 kp
= sysmon_table_get_row(plist
, i
);
695 for (i
= 0, kp
= plist
; i
< nproc
; i
++, kp
++) {
700 if ((pid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PID
)) == pid
) {
702 pid
= (pid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PPID
));
706 if (kp
->ki_pid
== pid
) {
717 break; /* Maybe we're in a jail ? */
722 if (newest
|| oldest
) {
726 best_tval
.tv_sec
= 0;
727 best_tval
.tv_usec
= 0;
732 for (i
= 0; i
< nproc
; i
++) {
733 kp
= sysmon_table_get_row(plist
, i
);
735 for (i
= 0, kp
= plist
; i
< nproc
; i
++, kp
++) {
740 /* The first entry of the list which matched. */
743 } else if (xpc_date_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_START
)) > best_tval
) {
745 } else if (timercmp(&kp
->ki_start
, &best_tval
, >)) {
747 /* This entry is newer than previous "best". */
748 if (oldest
) /* but we want the oldest */
751 /* This entry is older than previous "best". */
752 if (newest
) /* but we want the newest */
755 /* This entry is better than previous "best" entry. */
757 best_tval
= xpc_date_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_START
));
759 best_tval
.tv_sec
= kp
->ki_start
.tv_sec
;
760 best_tval
.tv_usec
= kp
->ki_start
.tv_usec
;
765 memset(selected
, 0, nproc
);
767 selected
[bestidx
] = 1;
771 * Take the appropriate action for each matched process, if any.
775 for (i
= 0, rv
= 0; i
< nproc
; i
++) {
776 kp
= sysmon_table_get_row(plist
, i
);
778 for (i
= 0, rv
= 0, kp
= plist
; i
< nproc
; i
++, kp
++) {
783 if (longfmt
&& !pgrep
) {
786 printf("kill -%d %d\n", signum
, (int)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PID
)));
788 printf("kill -%d %d\n", signum
, kp
->ki_pid
);
797 if (!did_action
&& !pgrep
&& longfmt
)
799 "No matching processes belonging to you were found\n");
801 exit(rv
? STATUS_MATCH
: STATUS_NOMATCH
);
811 ustr
= "[-Lfilnoqvx] [-d delim]";
813 ustr
= "[-LSfilnoqvx] [-d delim]";
816 ustr
= "[-signal] [-ILfilnovx]";
820 "usage: %s %s [-F pidfile] [-G gid]\n"
821 " [-P ppid] [-U uid] [-g pgrp]\n"
823 "usage: %s %s [-F pidfile] [-G gid] [-M core] [-N system]\n"
824 " [-P ppid] [-U uid] [-g pgrp] [-j jid] [-s sid]\n"
826 " [-t tty] [-u euid] pattern ...\n", getprogname(),
829 exit(STATUS_BADUSAGE
);
834 show_process(const sysmon_row_t kp
)
836 show_process(const struct kinfo_proc
*kp
)
850 if ((longfmt
|| !pgrep
) && matchargs
&&
851 (argv
= sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_ARGUMENTS
)) != NULL
) {
852 printf("%d ", (int)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PID
)));
853 (void)xpc_array_apply(argv
, ^(size_t index
, xpc_object_t value
) {
854 printf("%s", xpc_string_get_string_ptr(value
));
855 if (index
< xpc_array_get_count(argv
) - 1)
859 } else if (longfmt
|| !pgrep
)
861 (int)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PID
)),
862 xpc_string_get_string_ptr(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_COMM
)));
864 printf("%d", (int)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PID
)));
866 if ((longfmt
|| !pgrep
) && matchargs
&&
867 (argv
= kvm_getargv(kd
, kp
, 0)) != NULL
) {
868 printf("%d ", (int)kp
->ki_pid
);
869 for (; *argv
!= NULL
; argv
++) {
874 } else if (longfmt
|| !pgrep
)
875 printf("%d %s", (int)kp
->ki_pid
, kp
->ki_comm
);
877 printf("%d", (int)kp
->ki_pid
);
883 killact(const sysmon_row_t kp
)
885 killact(const struct kinfo_proc
*kp
)
892 * Be careful, ask before killing.
898 first
= ch
= getchar();
899 while (ch
!= '\n' && ch
!= EOF
)
901 if (first
!= 'y' && first
!= 'Y')
905 if (kill((pid_t
)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PID
)), signum
) == -1) {
907 if (kill(kp
->ki_pid
, signum
) == -1) {
910 * Check for ESRCH, which indicates that the process
911 * disappeared between us matching it and us
912 * signalling it; don't issue a warning about it.
916 warn("signalling pid %d", (int)xpc_uint64_get_value(sysmon_row_get_value(kp
, SYSMON_ATTR_PROC_PID
)));
918 warn("signalling pid %d", (int)kp
->ki_pid
);
921 * Return 0 to indicate that the process should not be
922 * considered a match, since we didn't actually get to
932 grepact(const sysmon_row_t kp
)
934 grepact(const struct kinfo_proc
*kp
)
945 makelist(struct listhead
*head
, enum listtype type
, char *src
)
952 char *sp
, *ep
, buf
[MAXPATHLEN
];
957 while ((sp
= strsep(&src
, ",")) != NULL
) {
961 if ((li
= malloc(sizeof(*li
))) == NULL
) {
962 err(STATUS_ERROR
, "Cannot allocate %zu bytes",
966 SLIST_INSERT_HEAD(head
, li
, li_chain
);
969 li
->li_number
= (uid_t
)strtol(sp
, &ep
, 0);
973 if (li
->li_number
== 0)
974 li
->li_number
= getpgrp();
978 if (li
->li_number
== 0)
979 li
->li_number
= getsid(mypid
);
982 if (li
->li_number
< 0)
983 errx(STATUS_BADUSAGE
,
984 "Negative jail ID `%s'", sp
);
985 /* For compatibility with old -j */
986 if (li
->li_number
== 0)
987 li
->li_number
= -1; /* any jail */
989 #endif /* !__APPLE__ */
991 if (li
->li_number
< 0)
992 errx(STATUS_BADUSAGE
,
993 "Negative /dev/pts tty `%s'", sp
);
994 snprintf(buf
, sizeof(buf
), _PATH_DEV
"pts/%s",
996 if (stat(buf
, &st
) != -1)
999 errx(STATUS_BADUSAGE
, "No such tty: `"
1000 _PATH_DEV
"pts/%s'", sp
);
1001 err(STATUS_ERROR
, "Cannot access `"
1002 _PATH_DEV
"pts/%s'", sp
);
1012 if ((pw
= getpwnam(sp
)) == NULL
)
1013 errx(STATUS_BADUSAGE
, "Unknown user `%s'", sp
);
1014 li
->li_number
= pw
->pw_uid
;
1017 if ((gr
= getgrnam(sp
)) == NULL
)
1018 errx(STATUS_BADUSAGE
, "Unknown group `%s'", sp
);
1019 li
->li_number
= gr
->gr_gid
;
1022 if (strcmp(sp
, "-") == 0) {
1025 } else if (strcmp(sp
, "co") == 0) {
1031 snprintf(buf
, sizeof(buf
), _PATH_DEV
"%s", cp
);
1032 if (stat(buf
, &st
) != -1)
1035 snprintf(buf
, sizeof(buf
), _PATH_DEV
"tty%s", cp
);
1036 if (stat(buf
, &st
) != -1)
1039 if (errno
== ENOENT
)
1040 errx(STATUS_BADUSAGE
, "No such tty: `%s'", sp
);
1041 err(STATUS_ERROR
, "Cannot access `%s'", sp
);
1043 foundtty
: if ((st
.st_mode
& S_IFCHR
) == 0)
1044 errx(STATUS_BADUSAGE
, "Not a tty: `%s'", sp
);
1046 li
->li_number
= st
.st_rdev
;
1050 if (strcmp(sp
, "none") == 0)
1052 else if (strcmp(sp
, "any") == 0)
1054 else if (*ep
!= '\0')
1055 errx(STATUS_BADUSAGE
,
1056 "Invalid jail ID `%s'", sp
);
1058 #endif /* !__APPLE__ */
1069 takepid(const char *pidfile
, int pidfilelock
)
1071 char *endp
, line
[BUFSIZ
];
1075 fh
= fopen(pidfile
, "r");
1077 err(STATUS_ERROR
, "Cannot open pidfile `%s'", pidfile
);
1081 * If we can lock pidfile, this means that daemon is not
1082 * running, so would be better not to kill some random process.
1084 if (flock(fileno(fh
), LOCK_EX
| LOCK_NB
) == 0) {
1086 errx(STATUS_ERROR
, "File '%s' can be locked", pidfile
);
1088 if (errno
!= EWOULDBLOCK
) {
1090 "Error while locking file '%s'", pidfile
);
1095 if (fgets(line
, sizeof(line
), fh
) == NULL
) {
1098 errx(STATUS_ERROR
, "Pidfile `%s' is empty", pidfile
);
1101 err(STATUS_ERROR
, "Cannot read from pid file `%s'", pidfile
);
1105 rval
= strtol(line
, &endp
, 10);
1106 if (*endp
!= '\0' && !isspace((unsigned char)*endp
))
1107 errx(STATUS_ERROR
, "Invalid pid in file `%s'", pidfile
);
1108 else if (rval
< MIN_PID
|| rval
> MAX_PID
)
1109 errx(STATUS_ERROR
, "Invalid pid in file `%s'", pidfile
);