From 6fe25a08d76736781d597d237a9a9f46a66676bb Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 15 Jul 2009 17:53:15 +0000 Subject: Improved NetBSD current-process detection from Roy Marples. --- osdep-netbsd.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 11 deletions(-) (limited to 'osdep-netbsd.c') diff --git a/osdep-netbsd.c b/osdep-netbsd.c index be9cba1b..ce1dffc7 100644 --- a/osdep-netbsd.c +++ b/osdep-netbsd.c @@ -1,4 +1,4 @@ -/* $Id: osdep-netbsd.c,v 1.4 2009-06-26 15:54:52 nicm Exp $ */ +/* $Id: osdep-netbsd.c,v 1.5 2009-07-15 17:53:15 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -18,14 +18,18 @@ #include #include +#include #include +#include +#include #include #include -#ifndef nitems -#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) -#endif +#define is_runnable(p) \ + ((p)->p_stat == LSRUN || (p)->p_stat == SIDL) +#define is_stopped(p) \ + ((p)->p_stat == SSTOP || (p)->p_stat == SZOMB) char *osdep_get_name(int, char *); @@ -33,20 +37,80 @@ char * osdep_get_name(int fd, __unused char *tty) { int mib[6]; - size_t len; - struct kinfo_proc2 p; + struct stat sb; + size_t len, i; + struct kinfo_proc2 *buf, *newbuf, *p, *bestp; + char *name; + if (stat(tty, &sb) == -1) + return (NULL); if ((mib[3] = tcgetpgrp(fd)) == -1) return (NULL); + buf = NULL; len = sizeof(p); mib[0] = CTL_KERN; mib[1] = KERN_PROC2; - mib[2] = KERN_PROC_PID; - mib[4] = sizeof(p); - mib[5] = 1; - if (sysctl(mib, nitems(mib), &p, &len, NULL, 0) == -1) + mib[2] = KERN_PROC_PGRP; + mib[4] = sizeof (*buf); + mib[5] = 0; + +retry: + if (sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0) == -1) + return (NULL); + + if ((newbuf = realloc(buf, len * sizeof (*buf))) == NULL) { + free(buf); + return (NULL); + } + buf = newbuf; + + mib[5] = len / sizeof(*buf); + if (sysctl(mib, __arraycount(mib), buf, &len, NULL, 0) == -1) { + if (errno == ENOMEM) + goto retry; /* possible infinite loop? */ + free(buf); return (NULL); + } + + bestp = NULL; + for (i = 0; i < len / sizeof (*buf); i++) { + if (buf[i].p_tdev != sb.st_rdev) + continue; + p = &buf[i]; + if (bestp == NULL) { + bestp = p; + continue; + } + + if (is_runnable(p) && !is_runnable(bestp)) + bestp = p; + else if (!is_runnable(p) && is_runnable(bestp)) + continue; + + if (!is_stopped(p) && is_stopped(bestp)) + bestp = p; + else if (is_stopped(p) && !is_stopped(bestp)) + continue; + + if (p->p_estcpu > bestp->p_estcpu) + bestp = p; + else if (p->p_estcpu < bestp->p_estcpu) + continue; + + if (p->p_slptime < bestp->p_slptime) + bestp = p; + else if (p->p_slptime > bestp->p_slptime) + continue; + + if (p->p_pid > bestp->p_pid) + bestp = p; + } - return (strdup(p.p_comm)); + name = NULL; + if (bestp != NULL) + name = strdup(bestp->p_comm); + + free(buf); + return (name); } -- cgit v1.2.3