1*0a6a1f1dSLionel Sambuc /* Id */
2eda6f593SDavid van Moolenbroek
3eda6f593SDavid van Moolenbroek /*
4eda6f593SDavid van Moolenbroek * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
5eda6f593SDavid van Moolenbroek *
6eda6f593SDavid van Moolenbroek * Permission to use, copy, modify, and distribute this software for any
7eda6f593SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
8eda6f593SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
9eda6f593SDavid van Moolenbroek *
10eda6f593SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11eda6f593SDavid van Moolenbroek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12eda6f593SDavid van Moolenbroek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13eda6f593SDavid van Moolenbroek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14eda6f593SDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15eda6f593SDavid van Moolenbroek * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16eda6f593SDavid van Moolenbroek * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17eda6f593SDavid van Moolenbroek */
18eda6f593SDavid van Moolenbroek
19eda6f593SDavid van Moolenbroek #include <sys/param.h>
20eda6f593SDavid van Moolenbroek #include <sys/proc.h>
21eda6f593SDavid van Moolenbroek #include <sys/stat.h>
22eda6f593SDavid van Moolenbroek #include <sys/sysctl.h>
23eda6f593SDavid van Moolenbroek #include <sys/user.h>
24eda6f593SDavid van Moolenbroek
25eda6f593SDavid van Moolenbroek #include <err.h>
26eda6f593SDavid van Moolenbroek #include <errno.h>
27eda6f593SDavid van Moolenbroek #include <event.h>
28eda6f593SDavid van Moolenbroek #include <stdint.h>
29eda6f593SDavid van Moolenbroek #include <stdlib.h>
30eda6f593SDavid van Moolenbroek #include <string.h>
31eda6f593SDavid van Moolenbroek #include <unistd.h>
32*0a6a1f1dSLionel Sambuc #include <libutil.h>
33eda6f593SDavid van Moolenbroek
34eda6f593SDavid van Moolenbroek struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
35eda6f593SDavid van Moolenbroek char *osdep_get_name(int, char *);
36*0a6a1f1dSLionel Sambuc char *osdep_get_cwd(int);
37eda6f593SDavid van Moolenbroek struct event_base *osdep_event_init(void);
38eda6f593SDavid van Moolenbroek
39eda6f593SDavid van Moolenbroek #ifndef nitems
40eda6f593SDavid van Moolenbroek #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
41eda6f593SDavid van Moolenbroek #endif
42eda6f593SDavid van Moolenbroek
43eda6f593SDavid van Moolenbroek #define is_runnable(p) \
44eda6f593SDavid van Moolenbroek ((p)->ki_stat == SRUN || (p)->ki_stat == SIDL)
45eda6f593SDavid van Moolenbroek #define is_stopped(p) \
46eda6f593SDavid van Moolenbroek ((p)->ki_stat == SSTOP || (p)->ki_stat == SZOMB)
47eda6f593SDavid van Moolenbroek
48eda6f593SDavid van Moolenbroek struct kinfo_proc *
cmp_procs(struct kinfo_proc * p1,struct kinfo_proc * p2)49eda6f593SDavid van Moolenbroek cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2)
50eda6f593SDavid van Moolenbroek {
51eda6f593SDavid van Moolenbroek if (is_runnable(p1) && !is_runnable(p2))
52eda6f593SDavid van Moolenbroek return (p1);
53eda6f593SDavid van Moolenbroek if (!is_runnable(p1) && is_runnable(p2))
54eda6f593SDavid van Moolenbroek return (p2);
55eda6f593SDavid van Moolenbroek
56eda6f593SDavid van Moolenbroek if (is_stopped(p1) && !is_stopped(p2))
57eda6f593SDavid van Moolenbroek return (p1);
58eda6f593SDavid van Moolenbroek if (!is_stopped(p1) && is_stopped(p2))
59eda6f593SDavid van Moolenbroek return (p2);
60eda6f593SDavid van Moolenbroek
61eda6f593SDavid van Moolenbroek if (p1->ki_estcpu > p2->ki_estcpu)
62eda6f593SDavid van Moolenbroek return (p1);
63eda6f593SDavid van Moolenbroek if (p1->ki_estcpu < p2->ki_estcpu)
64eda6f593SDavid van Moolenbroek return (p2);
65eda6f593SDavid van Moolenbroek
66eda6f593SDavid van Moolenbroek if (p1->ki_slptime < p2->ki_slptime)
67eda6f593SDavid van Moolenbroek return (p1);
68eda6f593SDavid van Moolenbroek if (p1->ki_slptime > p2->ki_slptime)
69eda6f593SDavid van Moolenbroek return (p2);
70eda6f593SDavid van Moolenbroek
71eda6f593SDavid van Moolenbroek if (strcmp(p1->ki_comm, p2->ki_comm) < 0)
72eda6f593SDavid van Moolenbroek return (p1);
73eda6f593SDavid van Moolenbroek if (strcmp(p1->ki_comm, p2->ki_comm) > 0)
74eda6f593SDavid van Moolenbroek return (p2);
75eda6f593SDavid van Moolenbroek
76eda6f593SDavid van Moolenbroek if (p1->ki_pid > p2->ki_pid)
77eda6f593SDavid van Moolenbroek return (p1);
78eda6f593SDavid van Moolenbroek return (p2);
79eda6f593SDavid van Moolenbroek }
80eda6f593SDavid van Moolenbroek
81eda6f593SDavid van Moolenbroek char *
osdep_get_name(int fd,char * tty)82eda6f593SDavid van Moolenbroek osdep_get_name(int fd, char *tty)
83eda6f593SDavid van Moolenbroek {
84eda6f593SDavid van Moolenbroek int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PGRP, 0 };
85eda6f593SDavid van Moolenbroek struct stat sb;
86eda6f593SDavid van Moolenbroek size_t len;
87eda6f593SDavid van Moolenbroek struct kinfo_proc *buf, *newbuf, *bestp;
88eda6f593SDavid van Moolenbroek u_int i;
89eda6f593SDavid van Moolenbroek char *name;
90eda6f593SDavid van Moolenbroek
91eda6f593SDavid van Moolenbroek buf = NULL;
92eda6f593SDavid van Moolenbroek
93eda6f593SDavid van Moolenbroek if (stat(tty, &sb) == -1)
94eda6f593SDavid van Moolenbroek return (NULL);
95eda6f593SDavid van Moolenbroek if ((mib[3] = tcgetpgrp(fd)) == -1)
96eda6f593SDavid van Moolenbroek return (NULL);
97eda6f593SDavid van Moolenbroek
98eda6f593SDavid van Moolenbroek retry:
99eda6f593SDavid van Moolenbroek if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1)
100eda6f593SDavid van Moolenbroek return (NULL);
101eda6f593SDavid van Moolenbroek len = (len * 5) / 4;
102eda6f593SDavid van Moolenbroek
103eda6f593SDavid van Moolenbroek if ((newbuf = realloc(buf, len)) == NULL)
104eda6f593SDavid van Moolenbroek goto error;
105eda6f593SDavid van Moolenbroek buf = newbuf;
106eda6f593SDavid van Moolenbroek
107eda6f593SDavid van Moolenbroek if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1) {
108eda6f593SDavid van Moolenbroek if (errno == ENOMEM)
109eda6f593SDavid van Moolenbroek goto retry;
110eda6f593SDavid van Moolenbroek goto error;
111eda6f593SDavid van Moolenbroek }
112eda6f593SDavid van Moolenbroek
113eda6f593SDavid van Moolenbroek bestp = NULL;
114eda6f593SDavid van Moolenbroek for (i = 0; i < len / sizeof (struct kinfo_proc); i++) {
115eda6f593SDavid van Moolenbroek if (buf[i].ki_tdev != sb.st_rdev)
116eda6f593SDavid van Moolenbroek continue;
117eda6f593SDavid van Moolenbroek if (bestp == NULL)
118eda6f593SDavid van Moolenbroek bestp = &buf[i];
119eda6f593SDavid van Moolenbroek else
120eda6f593SDavid van Moolenbroek bestp = cmp_procs(&buf[i], bestp);
121eda6f593SDavid van Moolenbroek }
122eda6f593SDavid van Moolenbroek
123eda6f593SDavid van Moolenbroek name = NULL;
124eda6f593SDavid van Moolenbroek if (bestp != NULL)
125eda6f593SDavid van Moolenbroek name = strdup(bestp->ki_comm);
126eda6f593SDavid van Moolenbroek
127eda6f593SDavid van Moolenbroek free(buf);
128eda6f593SDavid van Moolenbroek return (name);
129eda6f593SDavid van Moolenbroek
130eda6f593SDavid van Moolenbroek error:
131eda6f593SDavid van Moolenbroek free(buf);
132eda6f593SDavid van Moolenbroek return (NULL);
133eda6f593SDavid van Moolenbroek }
134eda6f593SDavid van Moolenbroek
135*0a6a1f1dSLionel Sambuc char *
osdep_get_cwd(int fd)136*0a6a1f1dSLionel Sambuc osdep_get_cwd(int fd)
137*0a6a1f1dSLionel Sambuc {
138*0a6a1f1dSLionel Sambuc static char wd[PATH_MAX];
139*0a6a1f1dSLionel Sambuc struct kinfo_file *info = NULL;
140*0a6a1f1dSLionel Sambuc pid_t pgrp;
141*0a6a1f1dSLionel Sambuc int nrecords, i;
142*0a6a1f1dSLionel Sambuc
143*0a6a1f1dSLionel Sambuc if ((pgrp = tcgetpgrp(fd)) == -1)
144*0a6a1f1dSLionel Sambuc return (NULL);
145*0a6a1f1dSLionel Sambuc
146*0a6a1f1dSLionel Sambuc if ((info = kinfo_getfile(pgrp, &nrecords)) == NULL)
147*0a6a1f1dSLionel Sambuc return (NULL);
148*0a6a1f1dSLionel Sambuc
149*0a6a1f1dSLionel Sambuc for (i = 0; i < nrecords; i++) {
150*0a6a1f1dSLionel Sambuc if (info[i].kf_fd == KF_FD_TYPE_CWD) {
151*0a6a1f1dSLionel Sambuc strlcpy(wd, info[i].kf_path, sizeof wd);
152*0a6a1f1dSLionel Sambuc free(info);
153*0a6a1f1dSLionel Sambuc return (wd);
154*0a6a1f1dSLionel Sambuc }
155*0a6a1f1dSLionel Sambuc }
156*0a6a1f1dSLionel Sambuc
157*0a6a1f1dSLionel Sambuc free(info);
158*0a6a1f1dSLionel Sambuc return (NULL);
159*0a6a1f1dSLionel Sambuc }
160*0a6a1f1dSLionel Sambuc
161eda6f593SDavid van Moolenbroek struct event_base *
osdep_event_init(void)162eda6f593SDavid van Moolenbroek osdep_event_init(void)
163eda6f593SDavid van Moolenbroek {
164eda6f593SDavid van Moolenbroek /*
165eda6f593SDavid van Moolenbroek * On some versions of FreeBSD, kqueue doesn't work properly on tty
166eda6f593SDavid van Moolenbroek * file descriptors. This is fixed in recent FreeBSD versions.
167eda6f593SDavid van Moolenbroek */
168eda6f593SDavid van Moolenbroek setenv("EVENT_NOKQUEUE", "1", 1);
169eda6f593SDavid van Moolenbroek return (event_init());
170eda6f593SDavid van Moolenbroek }
171