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 24#include <errno.h> 25#include <limits.h> 26#include <stdlib.h> 27#include <string.h> 28#include <unistd.h> 29 30#include "tmux.h" 31 32#define is_runnable(p) \ 33 ((p)->p_stat == LSRUN || (p)->p_stat == SIDL) 34#define is_stopped(p) \ 35 ((p)->p_stat == SSTOP || (p)->p_stat == SZOMB) 36 37struct kinfo_proc2 *cmp_procs(struct kinfo_proc2 *, struct kinfo_proc2 *); 38 39struct kinfo_proc2 * 40cmp_procs(struct kinfo_proc2 *p1, struct kinfo_proc2 *p2) 41{ 42 if (is_runnable(p1) && !is_runnable(p2)) 43 return (p1); 44 if (!is_runnable(p1) && is_runnable(p2)) 45 return (p2); 46 47 if (is_stopped(p1) && !is_stopped(p2)) 48 return (p1); 49 if (!is_stopped(p1) && is_stopped(p2)) 50 return (p2); 51 52 if (p1->p_estcpu > p2->p_estcpu) 53 return (p1); 54 if (p1->p_estcpu < p2->p_estcpu) 55 return (p2); 56 57 if (p1->p_slptime < p2->p_slptime) 58 return (p1); 59 if (p1->p_slptime > p2->p_slptime) 60 return (p2); 61 62 if (p1->p_pid > p2->p_pid) 63 return (p1); 64 return (p2); 65} 66 67char * 68osdep_get_name(int fd, __unused char *tty) 69{ 70 int mib[6]; 71 struct stat sb; 72 size_t len, i; 73 struct kinfo_proc2 *buf, *newbuf, *bestp; 74 char *name; 75 76 if (stat(tty, &sb) == -1) 77 return (NULL); 78 if ((mib[3] = tcgetpgrp(fd)) == -1) 79 return (NULL); 80 81 buf = NULL; 82 len = sizeof bestp; 83 84 mib[0] = CTL_KERN; 85 mib[1] = KERN_PROC2; 86 mib[2] = KERN_PROC_PGRP; 87 mib[4] = sizeof *buf; 88 89retry: 90 mib[5] = 0; 91 92 if (sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0) == -1) 93 return (NULL); 94 95 if ((newbuf = realloc(buf, len)) == NULL) 96 goto error; 97 buf = newbuf; 98 99 mib[5] = len / (sizeof *buf); 100 if (sysctl(mib, __arraycount(mib), buf, &len, NULL, 0) == -1) { 101 if (errno == ENOMEM) 102 goto retry; 103 goto error; 104 } 105 106 bestp = NULL; 107 for (i = 0; i < len / (sizeof *buf); i++) { 108 if (buf[i].p_tdev != sb.st_rdev) 109 continue; 110 if (bestp == NULL) 111 bestp = &buf[i]; 112 else 113 bestp = cmp_procs(&buf[i], bestp); 114 } 115 116 name = NULL; 117 if (bestp != NULL) 118 name = strdup(bestp->p_comm); 119 120 free(buf); 121 return (name); 122 123error: 124 free(buf); 125 return (NULL); 126} 127 128char * 129osdep_get_cwd(int fd) 130{ 131 static char target[PATH_MAX + 1]; 132 pid_t pgrp; 133#ifdef KERN_PROC_CWD 134 int mib[4]; 135 size_t len; 136#else 137 char *path; 138 ssize_t n; 139#endif 140 141 if ((pgrp = tcgetpgrp(fd)) == -1) 142 return (NULL); 143 144#ifdef KERN_PROC_CWD 145 mib[0] = CTL_KERN; 146 mib[1] = KERN_PROC_ARGS; 147 mib[2] = pgrp; 148 mib[3] = KERN_PROC_CWD; 149 len = sizeof(target); 150 if (sysctl(mib, __arraycount(mib), target, &len, NULL, 0) == 0) 151 return (target); 152#else 153 xasprintf(&path, "/proc/%lld/cwd", (long long) pgrp); 154 n = readlink(path, target, sizeof(target) - 1); 155 free(path); 156 if (n > 0) { 157 target[n] = '\0'; 158 return (target); 159 } 160#endif 161 162 return (NULL); 163} 164 165struct event_base * 166osdep_event_init(void) 167{ 168 return (event_init()); 169} 170