4 * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/param.h>
22 #include <sys/sysctl.h>
35 struct kinfo_proc
*cmp_procs(struct kinfo_proc
*, struct kinfo_proc
*);
36 char *osdep_get_name(int, char *);
37 char *osdep_get_cwd(int);
38 struct event_base
*osdep_event_init(void);
41 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
44 #define is_runnable(p) \
45 ((p)->ki_stat == SRUN || (p)->ki_stat == SIDL)
46 #define is_stopped(p) \
47 ((p)->ki_stat == SSTOP || (p)->ki_stat == SZOMB)
50 cmp_procs(struct kinfo_proc
*p1
, struct kinfo_proc
*p2
)
52 if (is_runnable(p1
) && !is_runnable(p2
))
54 if (!is_runnable(p1
) && is_runnable(p2
))
57 if (is_stopped(p1
) && !is_stopped(p2
))
59 if (!is_stopped(p1
) && is_stopped(p2
))
62 if (p1
->ki_estcpu
> p2
->ki_estcpu
)
64 if (p1
->ki_estcpu
< p2
->ki_estcpu
)
67 if (p1
->ki_slptime
< p2
->ki_slptime
)
69 if (p1
->ki_slptime
> p2
->ki_slptime
)
72 if (strcmp(p1
->ki_comm
, p2
->ki_comm
) < 0)
74 if (strcmp(p1
->ki_comm
, p2
->ki_comm
) > 0)
77 if (p1
->ki_pid
> p2
->ki_pid
)
83 osdep_get_name(int fd
, char *tty
)
85 int mib
[4] = { CTL_KERN
, KERN_PROC
, KERN_PROC_PGRP
, 0 };
88 struct kinfo_proc
*buf
, *newbuf
, *bestp
;
94 if (stat(tty
, &sb
) == -1)
96 if ((mib
[3] = tcgetpgrp(fd
)) == -1)
100 if (sysctl(mib
, nitems(mib
), NULL
, &len
, NULL
, 0) == -1)
104 if ((newbuf
= realloc(buf
, len
)) == NULL
)
108 if (sysctl(mib
, nitems(mib
), buf
, &len
, NULL
, 0) == -1) {
115 for (i
= 0; i
< len
/ sizeof (struct kinfo_proc
); i
++) {
116 if (buf
[i
].ki_tdev
!= sb
.st_rdev
)
121 bestp
= cmp_procs(&buf
[i
], bestp
);
126 name
= strdup(bestp
->ki_comm
);
137 osdep_get_cwd_fallback(int fd
)
139 static char wd
[PATH_MAX
];
140 struct kinfo_file
*info
= NULL
;
144 if ((pgrp
= tcgetpgrp(fd
)) == -1)
147 if ((info
= kinfo_getfile(pgrp
, &nrecords
)) == NULL
)
150 for (i
= 0; i
< nrecords
; i
++) {
151 if (info
[i
].kf_fd
== KF_FD_TYPE_CWD
) {
152 strlcpy(wd
, info
[i
].kf_path
, sizeof wd
);
164 osdep_get_cwd(int fd
)
166 static struct kinfo_file info
;
168 int name
[] = { CTL_KERN
, KERN_PROC
, KERN_PROC_CWD
, 0 };
169 size_t len
= sizeof info
;
172 return (osdep_get_cwd_fallback(fd
));
174 if ((name
[3] = tcgetpgrp(fd
)) == -1)
177 if (sysctl(name
, 4, &info
, &len
, NULL
, 0) == -1) {
178 if (errno
== ENOENT
) {
180 return (osdep_get_cwd_fallback(fd
));
184 return (info
.kf_path
);
186 #else /* !KERN_PROC_CWD */
188 osdep_get_cwd(int fd
)
190 return (osdep_get_cwd_fallback(fd
));
192 #endif /* KERN_PROC_CWD */
195 osdep_event_init(void)
197 struct event_base
*base
;
200 * On some versions of FreeBSD, kqueue doesn't work properly on tty
201 * file descriptors. This is fixed in recent FreeBSD versions.
203 setenv("EVENT_NOKQUEUE", "1", 1);
206 unsetenv("EVENT_NOKQUEUE");