Annotation of embedaddon/tmux/osdep-freebsd.c, revision 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>