1 /* $OpenBSD: procname.c,v 1.14 2015/01/16 06:40:13 deraadt 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> /* MAXCOMLEN */ 20 #include <sys/types.h> 21 #include <sys/proc.h> 22 #include <sys/sysctl.h> 23 #include <sys/stat.h> 24 25 #include <errno.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <unistd.h> 29 30 #ifndef nitems 31 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) 32 #endif 33 34 #define is_runnable(p) \ 35 ((p)->p_stat == SRUN || (p)->p_stat == SIDL || (p)->p_stat == SONPROC) 36 #define is_stopped(p) \ 37 ((p)->p_stat == SSTOP || (p)->p_stat == SDEAD) 38 39 struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *); 40 char *get_proc_name(int, char *); 41 42 struct kinfo_proc * 43 cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2) 44 { 45 if (is_runnable(p1) && !is_runnable(p2)) 46 return (p1); 47 if (!is_runnable(p1) && is_runnable(p2)) 48 return (p2); 49 50 if (is_stopped(p1) && !is_stopped(p2)) 51 return (p1); 52 if (!is_stopped(p1) && is_stopped(p2)) 53 return (p2); 54 55 if (p1->p_estcpu > p2->p_estcpu) 56 return (p1); 57 if (p1->p_estcpu < p2->p_estcpu) 58 return (p2); 59 60 if (p1->p_slptime < p2->p_slptime) 61 return (p1); 62 if (p1->p_slptime > p2->p_slptime) 63 return (p2); 64 65 if ((p1->p_flag & P_SINTR) && !(p2->p_flag & P_SINTR)) 66 return (p1); 67 if (!(p1->p_flag & P_SINTR) && (p2->p_flag & P_SINTR)) 68 return (p2); 69 70 if (strcmp(p1->p_comm, p2->p_comm) < 0) 71 return (p1); 72 if (strcmp(p1->p_comm, p2->p_comm) > 0) 73 return (p2); 74 75 if (p1->p_pid > p2->p_pid) 76 return (p1); 77 return (p2); 78 } 79 80 char * 81 get_proc_name(int fd, char *tty) 82 { 83 int mib[6] = { CTL_KERN, KERN_PROC, KERN_PROC_PGRP, 0, 84 sizeof(struct kinfo_proc), 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 goto error; 101 len = (len * 5) / 4; 102 103 if ((newbuf = realloc(buf, len)) == NULL) 104 goto error; 105 buf = newbuf; 106 107 mib[5] = (int)(len / sizeof(struct kinfo_proc)); 108 if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1) { 109 if (errno == ENOMEM) 110 goto retry; 111 goto error; 112 } 113 114 bestp = NULL; 115 for (i = 0; i < len / sizeof (struct kinfo_proc); i++) { 116 if ((dev_t)buf[i].p_tdev != sb.st_rdev) 117 continue; 118 if (bestp == NULL) 119 bestp = &buf[i]; 120 else 121 bestp = cmp_procs(&buf[i], bestp); 122 } 123 124 name = NULL; 125 if (bestp != NULL) 126 name = strdup(bestp->p_comm); 127 128 free(buf); 129 return (name); 130 131 error: 132 free(buf); 133 return (NULL); 134 } 135