Annotation of embedaddon/tmux/osdep-freebsd.c, revision 1.1.1.1
1.1 misho 1: /* $OpenBSD$ */
2:
3: /*
4: * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
5: *
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.
9: *
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.
17: */
18:
19: #include <sys/param.h>
20: #include <sys/proc.h>
21: #include <sys/stat.h>
22: #include <sys/sysctl.h>
23: #include <sys/user.h>
24:
25: #include <err.h>
26: #include <errno.h>
27: #include <event.h>
28: #include <stdint.h>
29: #include <stdlib.h>
30: #include <string.h>
31: #include <unistd.h>
32: #include <libutil.h>
33:
34: struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
35: char *osdep_get_name(int, char *);
36: char *osdep_get_cwd(int);
37: struct event_base *osdep_event_init(void);
38:
39: #ifndef nitems
40: #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
41: #endif
42:
43: #define is_runnable(p) \
44: ((p)->ki_stat == SRUN || (p)->ki_stat == SIDL)
45: #define is_stopped(p) \
46: ((p)->ki_stat == SSTOP || (p)->ki_stat == SZOMB)
47:
48: struct kinfo_proc *
49: cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2)
50: {
51: if (is_runnable(p1) && !is_runnable(p2))
52: return (p1);
53: if (!is_runnable(p1) && is_runnable(p2))
54: return (p2);
55:
56: if (is_stopped(p1) && !is_stopped(p2))
57: return (p1);
58: if (!is_stopped(p1) && is_stopped(p2))
59: return (p2);
60:
61: if (p1->ki_estcpu > p2->ki_estcpu)
62: return (p1);
63: if (p1->ki_estcpu < p2->ki_estcpu)
64: return (p2);
65:
66: if (p1->ki_slptime < p2->ki_slptime)
67: return (p1);
68: if (p1->ki_slptime > p2->ki_slptime)
69: return (p2);
70:
71: if (strcmp(p1->ki_comm, p2->ki_comm) < 0)
72: return (p1);
73: if (strcmp(p1->ki_comm, p2->ki_comm) > 0)
74: return (p2);
75:
76: if (p1->ki_pid > p2->ki_pid)
77: return (p1);
78: return (p2);
79: }
80:
81: char *
82: osdep_get_name(int fd, char *tty)
83: {
84: int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PGRP, 0 };
85: struct stat sb;
86: size_t len;
87: struct kinfo_proc *buf, *newbuf, *bestp;
88: u_int i;
89: char *name;
90:
91: buf = NULL;
92:
93: if (stat(tty, &sb) == -1)
94: return (NULL);
95: if ((mib[3] = tcgetpgrp(fd)) == -1)
96: return (NULL);
97:
98: retry:
99: if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1)
100: return (NULL);
101: len = (len * 5) / 4;
102:
103: if ((newbuf = realloc(buf, len)) == NULL)
104: goto error;
105: buf = newbuf;
106:
107: if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1) {
108: if (errno == ENOMEM)
109: goto retry;
110: goto error;
111: }
112:
113: bestp = NULL;
114: for (i = 0; i < len / sizeof (struct kinfo_proc); i++) {
115: if (buf[i].ki_tdev != sb.st_rdev)
116: continue;
117: if (bestp == NULL)
118: bestp = &buf[i];
119: else
120: bestp = cmp_procs(&buf[i], bestp);
121: }
122:
123: name = NULL;
124: if (bestp != NULL)
125: name = strdup(bestp->ki_comm);
126:
127: free(buf);
128: return (name);
129:
130: error:
131: free(buf);
132: return (NULL);
133: }
134:
135: static char *
136: osdep_get_cwd_fallback(int fd)
137: {
138: static char wd[PATH_MAX];
139: struct kinfo_file *info = NULL;
140: pid_t pgrp;
141: int nrecords, i;
142:
143: if ((pgrp = tcgetpgrp(fd)) == -1)
144: return (NULL);
145:
146: if ((info = kinfo_getfile(pgrp, &nrecords)) == NULL)
147: return (NULL);
148:
149: for (i = 0; i < nrecords; i++) {
150: if (info[i].kf_fd == KF_FD_TYPE_CWD) {
151: strlcpy(wd, info[i].kf_path, sizeof wd);
152: free(info);
153: return (wd);
154: }
155: }
156:
157: free(info);
158: return (NULL);
159: }
160:
161: #ifdef KERN_PROC_CWD
162: char *
163: osdep_get_cwd(int fd)
164: {
165: static struct kinfo_file info;
166: static int fallback;
167: int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_CWD, 0 };
168: size_t len = sizeof info;
169:
170: if (fallback)
171: return (osdep_get_cwd_fallback(fd));
172:
173: if ((name[3] = tcgetpgrp(fd)) == -1)
174: return (NULL);
175:
176: if (sysctl(name, 4, &info, &len, NULL, 0) == -1) {
177: if (errno == ENOENT) {
178: fallback = 1;
179: return (osdep_get_cwd_fallback(fd));
180: }
181: return (NULL);
182: }
183: return (info.kf_path);
184: }
185: #else /* !KERN_PROC_CWD */
186: char *
187: osdep_get_cwd(int fd)
188: {
189: return (osdep_get_cwd_fallback(fd));
190: }
191: #endif /* KERN_PROC_CWD */
192:
193: struct event_base *
194: osdep_event_init(void)
195: {
196: /*
197: * On some versions of FreeBSD, kqueue doesn't work properly on tty
198: * file descriptors. This is fixed in recent FreeBSD versions.
199: */
200: setenv("EVENT_NOKQUEUE", "1", 1);
201: return (event_init());
202: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>