$OpenBSD: patch-libs_ksysguard_processcore_processes_openbsd_p_cpp,v 1.3 2015/03/30 17:11:45 zhuk Exp $
Rewrite using kvm(3), avoids failures after ABI change.
--- libs/ksysguard/processcore/processes_openbsd_p.cpp.orig	Thu Jan 29 21:49:17 2015
+++ libs/ksysguard/processcore/processes_openbsd_p.cpp	Sat Feb  7 14:45:30 2015
@@ -17,58 +17,64 @@
     Boston, MA 02110-1301, USA.
 */
 
-#include "processes_local_p.h"
-#include "process.h"
-
-#include <klocale.h>
-
-#include <QSet>
-
 #include <sys/param.h>
+#include <sys/proc.h>
 #include <sys/sysctl.h>
-#include <sys/types.h>
-#include <sys/user.h>
-#include <sys/resource.h>
-#if defined(__DragonFly__)
-#include <sys/resourcevar.h>
 #include <err.h>
-#endif
+#include <kvm.h>
 #include <signal.h>
-#include <unistd.h>
+/*
 #include <stdlib.h>
+#include <unistd.h>
+*/
 
+#include <QSet>
 
+#include <klocale.h>
 
+#include "processes_local_p.h"
+#include "process.h"
 
+
 namespace KSysGuard
 {
 
-  class ProcessesLocal::Private
-  {
-    public:
-      Private() {;}
-      ~Private() {;}
-      inline bool readProc(long pid, struct kinfo_proc *p);
-      inline void readProcStatus(struct kinfo_proc *p, Process *process);
-      inline void readProcStat(struct kinfo_proc *p, Process *process);
-      inline void readProcStatm(struct kinfo_proc *p, Process *process);
-      inline bool readProcCmdline(long pid, Process *process);
-    };
+class ProcessesLocal::Private
+{
+public:
+    Private() {
+        m_kvm = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "KSysGuard::ProcessesLocal::Private");
+    }
+    ~Private() {
+        if (m_kvm)
+            kvm_close(m_kvm);
+    }
 
-bool ProcessesLocal::Private::readProc(long pid, struct kinfo_proc *p)
+    inline struct kinfo_proc* getAllProcs(int &cnt);
+    inline struct kinfo_proc* readProc(long pid);
+    inline void readProcStatus(struct kinfo_proc *p, Process *process);
+    inline void readProcStat(struct kinfo_proc *p, Process *process);
+    inline void readProcStatm(struct kinfo_proc *p, Process *process);
+    inline bool readProcCmdline(struct kinfo_proc *p, Process *process);
+
+private:
+    kvm_t *m_kvm;
+};
+
+struct kinfo_proc* ProcessesLocal::Private::getAllProcs(int &cnt)
 {
-    int mib[4];
-    size_t len;
+    if (!m_kvm)
+        return NULL;
+    return kvm_getprocs(m_kvm, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cnt);
+}
 
-    mib[0] = CTL_KERN;
-    mib[1] = KERN_PROC;
-    mib[2] = KERN_PROC_PID;
-    mib[3] = pid;
+struct kinfo_proc* ProcessesLocal::Private::readProc(long pid)
+{
+    int cnt;
 
-    len = sizeof (struct kinfo_proc);
-    if (sysctl(mib, 4, p, &len, NULL, 0) == -1 || !len)
-        return false;
-    return true;
+    if (!m_kvm)
+        return NULL;
+    return kvm_getprocs(m_kvm, KERN_PROC_PID, (pid_t)pid, sizeof(struct kinfo_proc), &cnt);
 }
 
 void ProcessesLocal::Private::readProcStatus(struct kinfo_proc *p, Process *process)
@@ -76,101 +82,73 @@ void ProcessesLocal::Private::readProcStatus(struct ki
     process->setUid(0);
     process->setGid(0);
     process->setTracerpid(-1);
-
-
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500015
-    process->setUid(p->ki_uid);
-    process->setGid(p->ki_pgid);
-    process->setName(QString(p->ki_comm ? p->ki_comm : "????"));
-#elif defined(__DragonFly__) && __DragonFly_version >= 190000
-    process->setUid(p->kp_uid);
-    process->setGid(p->kp_pgid);
-    process->setName(QString(p->kp_comm ? p->kp_comm : "????"));
-#else
-    process->setUid(p->kp_eproc.e_ucred.cr_uid);
-    process->setGid(p->kp_eproc.e_pgid);
-#endif
+    process->setUid(p->p_uid);
+    process->setUid(p->p_gid);
+    QString name(p->p_comm);
+    if (!name.isEmpty())
+        process->setName(QString(p->p_comm));
+    else
+        process->setName("????");
 }
 
-void ProcessesLocal::Private::readProcStat(struct kinfo_proc *p, Process *ps)
+void ProcessesLocal::Private::readProcStat(struct kinfo_proc *p, Process *process)
 {
     int status;
-    struct rusage pru;
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500015
-        ps->setUserTime(p->ki_runtime / 10000);
-        ps->setNiceLevel(p->ki_nice);
-        ps->setVmSize(p->ki_size);
-        ps->setVmRSS(p->ki_rssize * getpagesize());
-        status = p->ki_stat;
-#elif defined(__DragonFly__) && __DragonFly_version >= 190000
-        if (!getrusage(p->kp_pid, &pru)) {
-            errx(1, "failed to get rusage info");
-        }
-        ps->setUserTime(pru.ru_utime.tv_usec / 1000); /*p_runtime / 1000*/
-        ps->setNiceLevel(p->kp_nice);
-        ps->setVmSize(p->kp_vm_map_size);
-        ps->setVmRSS(p->kp_vm_rssize * getpagesize());
-        status = p->kp_stat;
-#else
-        ps->setUserTime(p->kp_proc.p_rtime.tv_sec*100+p->kp_proc.p_rtime.tv_usec/100);
-        ps->setNiceLevel(p->kp_proc.p_nice);
-        ps->setVmSize(p->kp_eproc.e_vm.vm_map.size);
-        ps->setVmRSS(p->kp_eproc.e_vm.vm_rssize * getpagesize());
-        status = p->kp_proc.p_stat;
-#endif
-        ps->setSysTime(0);
+    process->setSysTime(  p->p_ustime_sec*100 + p->p_ustime_usec/10000000 );
+    process->setUserTime( p->p_uutime_sec*100 + p->p_uutime_usec/10000000 );
+    process->setNiceLevel(p->p_nice);
+    process->setVmSize(p->p_vm_map_size);
+    process->setVmRSS(p->p_vm_rssize);
+    status = p->p_stat;
 
-// "idle","run","sleep","stop","zombie"
     switch( status ) {
-      case '0':
-        ps->setStatus(Process::DiskSleep);
+      case SSLEEP:
+        process->setStatus(Process::DiskSleep);
 	break;
-      case '1':
-        ps->setStatus(Process::Running);
+      case SONPROC:
+        process->setStatus(Process::Running);
 	break;
-      case '2':
-        ps->setStatus(Process::Sleeping);
+      case SIDL:
+      case SRUN:
+        process->setStatus(Process::Sleeping);
 	break;
-      case '3':
-        ps->setStatus(Process::Stopped);
+      case SSTOP:
+        process->setStatus(Process::Stopped);
 	break;
-      case '4':
-         ps->setStatus(Process::Zombie);
+      case SDEAD:
+         process->setStatus(Process::Zombie);
          break;
       default:
-         ps->setStatus(Process::OtherStatus);
+         process->setStatus(Process::OtherStatus);
          break;
     }
 }
 
 void ProcessesLocal::Private::readProcStatm(struct kinfo_proc *p, Process *process)
 {
-// TODO
-
-//     unsigned long shared;
-//     process->setVmURSS(process->vmRSS - (shared * sysconf(_SC_PAGESIZE) / 1024));
+    process->setVmURSS(p->p_uru_idrss / 1024);
 }
 
-bool ProcessesLocal::Private::readProcCmdline(long pid, Process *process)
+bool ProcessesLocal::Private::readProcCmdline(struct kinfo_proc *p, Process *process)
 {
-    int mib[4];
-    struct kinfo_proc p;
-    size_t buflen = 256;
-    char buf[256];
+    QString cmdline;
+    size_t len;
+    char **argv, **t;
 
-    mib[0] = CTL_KERN;
-    mib[1] = KERN_PROC;
-    mib[2] = KERN_PROC_ARGS;
-    mib[3] = pid;
-
-    if (sysctl(mib, 4, buf, &buflen, NULL, 0) == -1 || !buflen)
+    if (!m_kvm)
         return false;
-    QString command = QString(buf);
+    argv = kvm_getargv(m_kvm, p, 0);
+    if (!argv)
+        return false;
 
-    //cmdline seperates parameters with the NULL character
-    command.replace('\0', ' ');
-    process->setCommand(command.trimmed());
-
+    len = 0;
+    for (t = argv; *t != NULL; t++)
+        len += strlen(*t) + 1;
+    cmdline.reserve(len);
+    for (t = argv; *t != NULL; t++)
+        cmdline.append(*t).append(' ');
+    cmdline.truncate(len-1);    // zap extra space
+    process->setCommand(cmdline);
     return true;
 }
 
@@ -180,124 +158,94 @@ ProcessesLocal::ProcessesLocal() : d(new Private())
 }
 
 long ProcessesLocal::getParentPid(long pid) {
+    struct kinfo_proc *p;
     Q_ASSERT(pid != 0);
-    long long ppid = -1;
-    struct kinfo_proc p;
-    if(d->readProc(pid, &p))
-    {
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500015
-        ppid = p.ki_ppid;
-#elif defined(__DragonFly__) && __DragonFly_version >= 190000
-        ppid = p.kp_ppid;
-#else
-        ppid = p.kp_eproc.e_ppid;
-#endif
-    }
-    return ppid;
+    p = d->readProc(pid);
+    if (!p)
+        return -1;
+    return p->p_ppid;
 }
 
 bool ProcessesLocal::updateProcessInfo( long pid, Process *process)
 {
-    struct kinfo_proc p;
-    if(!d->readProc(pid, &p)) return false;
-    d->readProcStat(&p, process);
-    d->readProcStatus(&p, process);
-    d->readProcStatm(&p, process);
-    if(!d->readProcCmdline(pid, process)) return false;
+    struct kinfo_proc *p;
 
+    p = d->readProc(pid);
+    if(!p)
+        return false;
+    if(!d->readProcCmdline(p, process))
+        return false;
+    d->readProcStat(p, process);
+    d->readProcStatus(p, process);
+    d->readProcStatm(p, process);
     return true;
 }
 
 QSet<long> ProcessesLocal::getAllPids( )
 {
     QSet<long> pids;
-    int mib[3];
-    size_t len;
-    size_t num;
     struct kinfo_proc *p;
+    int cnt;
 
-    mib[0] = CTL_KERN;
-    mib[1] = KERN_PROC;
-    mib[2] = KERN_PROC_ALL;
-    sysctl(mib, 3, NULL, &len, NULL, 0);
-    p = (kinfo_proc *) malloc(len);
-    sysctl(mib, 3, p, &len, NULL, 0);
-
-    for (num = 0; num < len / sizeof(struct kinfo_proc); num++)
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500015
-        pids.insert(p[num].ki_pid);
-#elif defined(__DragonFly__) && __DragonFly_version >= 190000
-        pids.insert(p[num].kp_pid);
-#else
-        pids.insert(p[num].kp_proc.p_pid);
-#endif
-    free(p);
+    p = d->getAllProcs(cnt);
+    if (p != NULL)
+        while (cnt--)
+            if (p[cnt].p_tid == -1)
+                pids.insert(p[cnt].p_pid);
     return pids;
 }
 
 bool ProcessesLocal::sendSignal(long pid, int sig) {
-    if ( kill( (pid_t)pid, sig ) ) {
-	//Kill failed
-        return false;
-    }
-    return true;
+    return (kill((pid_t)pid, sig) >= 0);
 }
 
 bool ProcessesLocal::setNiceness(long pid, int priority) {
-    if ( setpriority( PRIO_PROCESS, pid, priority ) ) {
-	    //set niceness failed
-	    return false;
-    }
-    return true;
+    return (setpriority(PRIO_PROCESS, pid, priority) >= 0);
 }
 
 bool ProcessesLocal::setScheduler(long pid, int priorityClass, int priority)
 {
-    if(priorityClass == KSysGuard::Process::Other || priorityClass == KSysGuard::Process::Batch)
-	    priority = 0;
-    if(pid <= 0) return false; // check the parameters
-	    return false;
+    Q_UNUSED(pid);
+    Q_UNUSED(priorityClass);
+    Q_UNUSED(priority);
+    return false; // not supported
 }
 
-bool ProcessesLocal::setIoNiceness(long pid, int priorityClass, int priority) {
-    return false; //Not yet supported
+bool ProcessesLocal::setIoNiceness(long pid, int priorityClass, int priority)
+{
+    Q_UNUSED(pid);
+    Q_UNUSED(priorityClass);
+    Q_UNUSED(priority);
+    return false; // not supported
 }
 
-bool ProcessesLocal::supportsIoNiceness() {
-    return false;
+bool ProcessesLocal::supportsIoNiceness()
+{
+    return false; // not supported
 }
 
-long long ProcessesLocal::totalPhysicalMemory() {
+long long ProcessesLocal::totalPhysicalMemory()
+{
+    int64_t nbytes;
+    int mib[] = { CTL_HW, HW_PHYSMEM64 };
+    size_t len = sizeof(nbytes);
 
-    static int physmem_mib[] = { CTL_HW, HW_PHYSMEM };
-    /* get the page size with "getpagesize" and calculate pageshift from
-    * it */
-    int pagesize = ::getpagesize();
-    int pageshift = 0;
-    while (pagesize > 1) {
-	    pageshift++;
-	    pagesize >>= 1;
-    }
-    size_t Total = 0;
-    size_t size = sizeof(Total);
-    sysctl(physmem_mib, 2, &Total, &size, NULL, 0);
-    return Total /= 1024;
+    sysctl(mib, 2, &nbytes, &len, NULL, 0);
+    return nbytes / 1024;
 }
 
-long int KSysGuard::ProcessesLocal::numberProcessorCores()
+#ifndef _SC_NPROCESSORS_ONLN
+long KSysGuard::ProcessesLocal::numberProcessorCores()
 {
-    int mib[2];
     int ncpu;
-    size_t len;
+    size_t len = sizeof(ncpu);
+    int mib[] = { CTL_HW, HW_NCPU };
 
-    mib[0] = CTL_HW;
-    mib[1] = HW_NCPU;
-    len = sizeof(ncpu);
-
-    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1 || !len)
-        return 1;
-    return len;
+    sysctl(mib, 2, &ncpu, &len, NULL, 0);
+    return ncpu;
 }
+#endif
+
 ProcessesLocal::~ProcessesLocal()
 {
    delete d;
