1 /* $Id: osdep-freebsd.c,v 1.1.1.1 2011/03/10 09:15:38 jmmv Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> 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 <stdint.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <unistd.h> 31 32 struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *); 33 char *osdep_get_name(int, char *); 34 35 #ifndef nitems 36 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) 37 #endif 38 39 #define is_runnable(p) \ 40 ((p)->ki_stat == SRUN || (p)->ki_stat == SIDL) 41 #define is_stopped(p) \ 42 ((p)->ki_stat == SSTOP || (p)->ki_stat == SZOMB) 43 44 struct kinfo_proc * 45 cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2) 46 { 47 if (is_runnable(p1) && !is_runnable(p2)) 48 return (p1); 49 if (!is_runnable(p1) && is_runnable(p2)) 50 return (p2); 51 52 if (is_stopped(p1) && !is_stopped(p2)) 53 return (p1); 54 if (!is_stopped(p1) && is_stopped(p2)) 55 return (p2); 56 57 if (p1->ki_estcpu > p2->ki_estcpu) 58 return (p1); 59 if (p1->ki_estcpu < p2->ki_estcpu) 60 return (p2); 61 62 if (p1->ki_slptime < p2->ki_slptime) 63 return (p1); 64 if (p1->ki_slptime > p2->ki_slptime) 65 return (p2); 66 67 if (strcmp(p1->ki_comm, p2->ki_comm) < 0) 68 return (p1); 69 if (strcmp(p1->ki_comm, p2->ki_comm) > 0) 70 return (p2); 71 72 if (p1->ki_pid > p2->ki_pid) 73 return (p1); 74 return (p2); 75 } 76 77 char * 78 osdep_get_name(int fd, char *tty) 79 { 80 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PGRP, 0 }; 81 struct stat sb; 82 size_t len; 83 struct kinfo_proc *buf, *newbuf, *bestp; 84 u_int i; 85 char *name; 86 87 buf = NULL; 88 89 if (stat(tty, &sb) == -1) 90 return (NULL); 91 if ((mib[3] = tcgetpgrp(fd)) == -1) 92 return (NULL); 93 94 retry: 95 if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1) 96 return (NULL); 97 len = (len * 5) / 4; 98 99 if ((newbuf = realloc(buf, len)) == NULL) 100 goto error; 101 buf = newbuf; 102 103 if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1) { 104 if (errno == ENOMEM) 105 goto retry; 106 goto error; 107 } 108 109 bestp = NULL; 110 for (i = 0; i < len / sizeof (struct kinfo_proc); i++) { 111 if (buf[i].ki_tdev != sb.st_rdev) 112 continue; 113 if (bestp == NULL) 114 bestp = &buf[i]; 115 else 116 bestp = cmp_procs(&buf[i], bestp); 117 } 118 119 name = NULL; 120 if (bestp != NULL) 121 name = strdup(bestp->ki_comm); 122 123 free(buf); 124 return (name); 125 126 error: 127 free(buf); 128 return (NULL); 129 } 130