1 /* $OpenBSD: procname.c,v 1.5 2009/08/09 15:17:50 nicm 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/sysctl.h> 21 #include <sys/stat.h> 22 23 #include <errno.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 #ifndef nitems 29 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) 30 #endif 31 32 #define is_runnable(p) \ 33 ((p)->p_stat == SRUN || (p)->p_stat == SIDL || (p)->p_stat == SONPROC) 34 #define is_stopped(p) \ 35 ((p)->p_stat == SSTOP || (p)->p_stat == SZOMB || (p)->p_stat == SDEAD) 36 37 struct proc *cmp_procs(struct proc *, struct proc *); 38 char *get_proc_name(int, char *); 39 40 struct proc * 41 cmp_procs(struct proc *p1, struct proc *p2) 42 { 43 void *ptr1, *ptr2; 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 ptr1 = LIST_FIRST(&p1->p_children); 71 ptr2 = LIST_FIRST(&p2->p_children); 72 if (ptr1 == NULL && ptr2 != NULL) 73 return (p1); 74 if (ptr1 != NULL && ptr2 == NULL) 75 return (p2); 76 77 if (strcmp(p1->p_comm, p2->p_comm) < 0) 78 return (p1); 79 if (strcmp(p1->p_comm, p2->p_comm) > 0) 80 return (p2); 81 82 if (p1->p_pid > p2->p_pid) 83 return (p1); 84 return (p2); 85 } 86 87 char * 88 get_proc_name(int fd, char *tty) 89 { 90 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PGRP, 0 }; 91 struct stat sb; 92 size_t len; 93 struct kinfo_proc *buf, *newbuf; 94 struct proc *bestp; 95 u_int i; 96 char *name; 97 98 buf = NULL; 99 100 if (stat(tty, &sb) == -1) 101 return (NULL); 102 if ((mib[3] = tcgetpgrp(fd)) == -1) 103 return (NULL); 104 105 retry: 106 if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1) 107 return (NULL); 108 len = (len * 5) / 4; 109 110 if ((newbuf = realloc(buf, len)) == NULL) 111 goto error; 112 buf = newbuf; 113 114 if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1) { 115 if (errno == ENOMEM) 116 goto retry; 117 goto error; 118 } 119 120 bestp = NULL; 121 for (i = 0; i < len / sizeof (struct kinfo_proc); i++) { 122 if (buf[i].kp_eproc.e_tdev != sb.st_rdev) 123 continue; 124 if (bestp == NULL) 125 bestp = &buf[i].kp_proc; 126 else 127 bestp = cmp_procs(&buf[i].kp_proc, bestp); 128 } 129 130 name = NULL; 131 if (bestp != NULL) 132 name = strdup(bestp->p_comm); 133 134 free(buf); 135 return (name); 136 137 error: 138 free(buf); 139 return (NULL); 140 } 141