xref: /minix3/external/bsd/tmux/dist/osdep-freebsd.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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