summaryrefslogtreecommitdiff
path: root/sysutils/py-psutil
diff options
context:
space:
mode:
authorwiz <wiz@pkgsrc.org>2013-10-12 13:32:36 +0000
committerwiz <wiz@pkgsrc.org>2013-10-12 13:32:36 +0000
commitad68752800b9c024895cadba42c9ff0a16b1e2fa (patch)
treef3e0893ea597a5943428a3753c1ce1751b04f04c /sysutils/py-psutil
parent0df238335d085785022d0af812a494761a3a8ecf (diff)
downloadpkgsrc-ad68752800b9c024895cadba42c9ff0a16b1e2fa.tar.gz
Import py27-psutil-1.0.1 as sysutils/py-psutil.
util is a module providing an interface for retrieving information, on all running processes and system utilization (CPU, memory, disks, network, users) in a portable way by using Python, implementing many functionalities offered by command line tools such as ps, top, df, netstat, who, kill, uptime, free, lsof, ifconfig, nice, ionice, iostat, iotop, pidof, tty, taskset, or pmap. Ported to NetBSD by tron & myself, but more work to do.
Diffstat (limited to 'sysutils/py-psutil')
-rw-r--r--sysutils/py-psutil/DESCR6
-rw-r--r--sysutils/py-psutil/Makefile17
-rw-r--r--sysutils/py-psutil/PLIST43
-rw-r--r--sysutils/py-psutil/distinfo13
-rw-r--r--sysutils/py-psutil/patches/patch-psutil_____init____.py16
-rw-r--r--sysutils/py-psutil/patches/patch-psutil___psnetbsd.py374
-rw-r--r--sysutils/py-psutil/patches/patch-psutil___psutil__netbsd.c1314
-rw-r--r--sysutils/py-psutil/patches/patch-psutil___psutil__netbsd.h57
-rw-r--r--sysutils/py-psutil/patches/patch-psutil_arch_netbsd_process__info.c296
-rw-r--r--sysutils/py-psutil/patches/patch-psutil_arch_netbsd_process__info.h23
-rw-r--r--sysutils/py-psutil/patches/patch-setup.py22
-rw-r--r--sysutils/py-psutil/patches/patch-test_test__psutil.py15
12 files changed, 2196 insertions, 0 deletions
diff --git a/sysutils/py-psutil/DESCR b/sysutils/py-psutil/DESCR
new file mode 100644
index 00000000000..83fd074786e
--- /dev/null
+++ b/sysutils/py-psutil/DESCR
@@ -0,0 +1,6 @@
+util is a module providing an interface for retrieving information,
+on all running processes and system utilization (CPU, memory, disks,
+network, users) in a portable way by using Python, implementing
+many functionalities offered by command line tools such as ps, top,
+df, netstat, who, kill, uptime, free, lsof, ifconfig, nice, ionice,
+iostat, iotop, pidof, tty, taskset, or pmap.
diff --git a/sysutils/py-psutil/Makefile b/sysutils/py-psutil/Makefile
new file mode 100644
index 00000000000..2e1795c27de
--- /dev/null
+++ b/sysutils/py-psutil/Makefile
@@ -0,0 +1,17 @@
+# $NetBSD: Makefile,v 1.1 2013/10/12 13:32:36 wiz Exp $
+
+DISTNAME= psutil-1.0.1
+PKGNAME= ${PYPKGPREFIX}-${DISTNAME}
+CATEGORIES= sysutils
+MASTER_SITES= http://psutil.googlecode.com/files/
+
+MAINTAINER= pkgsrc-users@NetBSD.org
+HOMEPAGE= http://code.google.com/p/psutil/
+COMMENT= Cross-platform process and system utilities module for Python
+LICENSE= modified-bsd
+
+REPLACE_PYTHON= psutil/*py
+
+.include "../../lang/python/application.mk"
+.include "../../lang/python/egg.mk"
+.include "../../mk/bsd.pkg.mk"
diff --git a/sysutils/py-psutil/PLIST b/sysutils/py-psutil/PLIST
new file mode 100644
index 00000000000..8f609f6ad45
--- /dev/null
+++ b/sysutils/py-psutil/PLIST
@@ -0,0 +1,43 @@
+@comment $NetBSD: PLIST,v 1.1 2013/10/12 13:32:36 wiz Exp $
+${PYSITELIB}/_psutil_netbsd.so
+${PYSITELIB}/_psutil_posix.so
+${PYSITELIB}/${EGG_INFODIR}/PKG-INFO
+${PYSITELIB}/${EGG_INFODIR}/SOURCES.txt
+${PYSITELIB}/${EGG_INFODIR}/dependency_links.txt
+${PYSITELIB}/${EGG_INFODIR}/top_level.txt
+${PYSITELIB}/psutil/__init__.py
+${PYSITELIB}/psutil/__init__.pyc
+${PYSITELIB}/psutil/__init__.pyo
+${PYSITELIB}/psutil/_common.py
+${PYSITELIB}/psutil/_common.pyc
+${PYSITELIB}/psutil/_common.pyo
+${PYSITELIB}/psutil/_compat.py
+${PYSITELIB}/psutil/_compat.pyc
+${PYSITELIB}/psutil/_compat.pyo
+${PYSITELIB}/psutil/_error.py
+${PYSITELIB}/psutil/_error.pyc
+${PYSITELIB}/psutil/_error.pyo
+${PYSITELIB}/psutil/_psbsd.py
+${PYSITELIB}/psutil/_psbsd.pyc
+${PYSITELIB}/psutil/_psbsd.pyo
+${PYSITELIB}/psutil/_pslinux.py
+${PYSITELIB}/psutil/_pslinux.pyc
+${PYSITELIB}/psutil/_pslinux.pyo
+${PYSITELIB}/psutil/_psmswindows.py
+${PYSITELIB}/psutil/_psmswindows.pyc
+${PYSITELIB}/psutil/_psmswindows.pyo
+${PYSITELIB}/psutil/_psnetbsd.py
+${PYSITELIB}/psutil/_psnetbsd.pyc
+${PYSITELIB}/psutil/_psnetbsd.pyo
+${PYSITELIB}/psutil/_psosx.py
+${PYSITELIB}/psutil/_psosx.pyc
+${PYSITELIB}/psutil/_psosx.pyo
+${PYSITELIB}/psutil/_psposix.py
+${PYSITELIB}/psutil/_psposix.pyc
+${PYSITELIB}/psutil/_psposix.pyo
+${PYSITELIB}/psutil/_pssunos.py
+${PYSITELIB}/psutil/_pssunos.pyc
+${PYSITELIB}/psutil/_pssunos.pyo
+${PYSITELIB}/psutil/error.py
+${PYSITELIB}/psutil/error.pyc
+${PYSITELIB}/psutil/error.pyo
diff --git a/sysutils/py-psutil/distinfo b/sysutils/py-psutil/distinfo
new file mode 100644
index 00000000000..e8305209510
--- /dev/null
+++ b/sysutils/py-psutil/distinfo
@@ -0,0 +1,13 @@
+$NetBSD: distinfo,v 1.1 2013/10/12 13:32:36 wiz Exp $
+
+SHA1 (psutil-1.0.1.tar.gz) = 3d3abb8b7a5479b7299a8d170ec25179410f24d1
+RMD160 (psutil-1.0.1.tar.gz) = 0b0efc89b7ba972ed186f882ee09573617e0f292
+Size (psutil-1.0.1.tar.gz) = 159515 bytes
+SHA1 (patch-psutil_____init____.py) = aa75a84992250e28db01d5fe13a68ed0cdcea883
+SHA1 (patch-psutil___psnetbsd.py) = 20089b57640a5eb30aeb1f5460624a570f1d3236
+SHA1 (patch-psutil___psutil__netbsd.c) = c251e097ce5c919537176f16406ad6892db955fc
+SHA1 (patch-psutil___psutil__netbsd.h) = 33e3c857f764d8391db747068ade7ea333698ec0
+SHA1 (patch-psutil_arch_netbsd_process__info.c) = c384d12cc47514d6396d779d59c586ef2b42a89a
+SHA1 (patch-psutil_arch_netbsd_process__info.h) = b23075df15749e4e5274ccb9e21d67ac55fdd199
+SHA1 (patch-setup.py) = 10930275eb157ba1319a758933a84d6f0816f390
+SHA1 (patch-test_test__psutil.py) = c0053788aefaf9c651c733a9911e0ca76e6d3537
diff --git a/sysutils/py-psutil/patches/patch-psutil_____init____.py b/sysutils/py-psutil/patches/patch-psutil_____init____.py
new file mode 100644
index 00000000000..d5c598a976a
--- /dev/null
+++ b/sysutils/py-psutil/patches/patch-psutil_____init____.py
@@ -0,0 +1,16 @@
+$NetBSD: patch-psutil_____init____.py,v 1.1 2013/10/12 13:32:36 wiz Exp $
+
+Port to NetBSD.
+
+--- psutil/__init__.py.orig 2013-07-12 15:34:08.000000000 +0000
++++ psutil/__init__.py
+@@ -97,6 +97,9 @@ elif sys.platform.startswith("darwin"):
+ elif sys.platform.startswith("freebsd"):
+ import psutil._psbsd as _psplatform
+
++elif sys.platform.startswith("netbsd"):
++ import psutil._psnetbsd as _psplatform
++
+ elif sys.platform.startswith("sunos"):
+ import psutil._pssunos as _psplatform
+ from psutil._pssunos import (CONN_IDLE,
diff --git a/sysutils/py-psutil/patches/patch-psutil___psnetbsd.py b/sysutils/py-psutil/patches/patch-psutil___psnetbsd.py
new file mode 100644
index 00000000000..ad5acc2d192
--- /dev/null
+++ b/sysutils/py-psutil/patches/patch-psutil___psnetbsd.py
@@ -0,0 +1,374 @@
+$NetBSD: patch-psutil___psnetbsd.py,v 1.1 2013/10/12 13:32:36 wiz Exp $
+
+Port to NetBSD.
+
+--- psutil/_psnetbsd.py.orig 2013-10-12 13:19:29.000000000 +0000
++++ psutil/_psnetbsd.py
+@@ -0,0 +1,367 @@
++#!/usr/bin/env python
++
++# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
++# Use of this source code is governed by a BSD-style license that can be
++# found in the LICENSE file.
++
++"""NetBSD platform implementation."""
++
++import errno
++import os
++import sys
++import warnings
++
++import _psutil_netbsd
++import _psutil_posix
++from psutil import _psposix
++from psutil._error import AccessDenied, NoSuchProcess, TimeoutExpired
++from psutil._compat import namedtuple, wraps
++from psutil._common import *
++
++__extra__all__ = []
++
++# --- constants
++
++# Since these constants get determined at import time we do not want to
++# crash immediately; instead we'll set them to None and most likely
++# we'll crash later as they're used for determining process CPU stats
++# and creation_time
++try:
++ NUM_CPUS = _psutil_netbsd.get_num_cpus()
++except Exception:
++ NUM_CPUS = None
++ warnings.warn("couldn't determine platform's NUM_CPUS", RuntimeWarning)
++try:
++ TOTAL_PHYMEM = _psutil_netbsd.get_virtual_mem()[0]
++except Exception:
++ TOTAL_PHYMEM = None
++ warnings.warn("couldn't determine platform's TOTAL_PHYMEM", RuntimeWarning)
++try:
++ BOOT_TIME = _psutil_netbsd.get_system_boot_time()
++except Exception:
++ BOOT_TIME = None
++ warnings.warn("couldn't determine platform's BOOT_TIME", RuntimeWarning)
++
++
++_PAGESIZE = os.sysconf("SC_PAGE_SIZE")
++_cputimes_ntuple = namedtuple('cputimes', 'user nice system idle irq')
++
++# --- public functions
++
++get_system_boot_time = _psutil_netbsd.get_system_boot_time
++
++nt_virtmem_info = namedtuple('vmem', ' '.join([
++ # all platforms
++ 'total', 'available', 'percent', 'used', 'free',
++ # *BSD specific
++ 'active',
++ 'inactive',
++ 'shared',
++ 'wired']))
++
++def virtual_memory():
++ """System virtual memory as a namedutple."""
++ mem = _psutil_netbsd.get_virtual_mem()
++ total, free, active, inactive, wired, shared = mem
++ avail = inactive + free
++ used = active + wired
++ percent = usage_percent((total - avail), total, _round=1)
++ return nt_virtmem_info(total, avail, percent, used, free,
++ active, inactive, shared, wired)
++
++def swap_memory():
++ """System swap memory as (total, used, free, sin, sout) namedtuple."""
++ total, used, free, sin, sout = \
++ [x * _PAGESIZE for x in _psutil_netbsd.get_swap_mem()]
++ percent = usage_percent(used, total, _round=1)
++ return nt_swapmeminfo(total, used, free, percent, sin, sout)
++
++def get_system_cpu_times():
++ """Return system per-CPU times as a named tuple"""
++ user, nice, system, idle, irq = _psutil_netbsd.get_system_cpu_times()
++ return _cputimes_ntuple(user, nice, system, idle, irq)
++
++def get_system_per_cpu_times():
++ """Return system CPU times as a named tuple"""
++ ret = []
++ for cpu_t in _psutil_netbsd.get_system_per_cpu_times():
++ user, nice, system, idle, irq = cpu_t
++ item = _cputimes_ntuple(user, nice, system, idle, irq)
++ ret.append(item)
++ return ret
++
++# \todo: check this
++# XXX
++# Ok, this is very dirty.
++# On FreeBSD < 8 we cannot gather per-cpu information, see:
++# http://code.google.com/p/psutil/issues/detail?id=226
++# If NUM_CPUS > 1, on first call we return single cpu times to avoid a
++# crash at psutil import time.
++# Next calls will fail with NotImplementedError
++if not hasattr(_psutil_netbsd, "get_system_per_cpu_times"):
++ def get_system_per_cpu_times():
++ if NUM_CPUS == 1:
++ return [get_system_cpu_times]
++ if get_system_per_cpu_times.__called__:
++ raise NotImplementedError("supported only starting from FreeBSD 8")
++ get_system_per_cpu_times.__called__ = True
++ return [get_system_cpu_times]
++get_system_per_cpu_times.__called__ = False
++
++def disk_partitions(all=False):
++ retlist = []
++ partitions = _psutil_netbsd.get_disk_partitions()
++ for partition in partitions:
++ device, mountpoint, fstype, opts = partition
++ if device == 'none':
++ device = ''
++ if not all:
++ if not os.path.isabs(device) \
++ or not os.path.exists(device):
++ continue
++ ntuple = nt_partition(device, mountpoint, fstype, opts)
++ retlist.append(ntuple)
++ return retlist
++
++def get_system_users():
++ retlist = []
++ rawlist = _psutil_netbsd.get_system_users()
++ for item in rawlist:
++ user, tty, hostname, tstamp = item
++ if tty == '~':
++ continue # reboot or shutdown
++ nt = nt_user(user, tty or None, hostname, tstamp)
++ retlist.append(nt)
++ return retlist
++
++get_pid_list = _psutil_netbsd.get_pid_list
++pid_exists = _psposix.pid_exists
++get_disk_usage = _psposix.get_disk_usage
++net_io_counters = _psutil_netbsd.get_net_io_counters
++disk_io_counters = _psutil_netbsd.get_disk_io_counters
++
++
++def wrap_exceptions(fun):
++ """Decorator which translates bare OSError exceptions into
++ NoSuchProcess and AccessDenied.
++ """
++ @wraps(fun)
++ def wrapper(self, *args, **kwargs):
++ try:
++ return fun(self, *args, **kwargs)
++ except OSError:
++ err = sys.exc_info()[1]
++ if err.errno == errno.ESRCH:
++ raise NoSuchProcess(self.pid, self._process_name)
++ if err.errno in (errno.EPERM, errno.EACCES):
++ raise AccessDenied(self.pid, self._process_name)
++ raise
++ return wrapper
++
++_status_map = {
++ _psutil_netbsd.SSTOP : STATUS_STOPPED,
++ _psutil_netbsd.SIDL : STATUS_IDLE,
++ _psutil_netbsd.SACTIVE : STATUS_RUNNING,
++# \todo: to what to map this?
++# _psutil_netbsd.SDYING : STATUS_IDLE,
++ _psutil_netbsd.SDEAD : STATUS_DEAD,
++ _psutil_netbsd.SZOMB : STATUS_ZOMBIE,
++}
++
++_conn_status_map = {_psutil_netbsd.TCPS_ESTABLISHED : CONN_ESTABLISHED,
++ _psutil_netbsd.TCPS_SYN_SENT : CONN_SYN_SENT,
++ _psutil_netbsd.TCPS_SYN_RECEIVED : CONN_SYN_RECV,
++ _psutil_netbsd.TCPS_FIN_WAIT_1 : CONN_FIN_WAIT1,
++ _psutil_netbsd.TCPS_FIN_WAIT_2 : CONN_FIN_WAIT2,
++ _psutil_netbsd.TCPS_TIME_WAIT : CONN_TIME_WAIT,
++ _psutil_netbsd.TCPS_CLOSED : CONN_CLOSE,
++ _psutil_netbsd.TCPS_CLOSE_WAIT : CONN_CLOSE_WAIT,
++ _psutil_netbsd.TCPS_LAST_ACK : CONN_LAST_ACK,
++ _psutil_netbsd.TCPS_LISTEN : CONN_LISTEN,
++ _psutil_netbsd.TCPS_CLOSING : CONN_CLOSING,
++ }
++
++
++class Process(object):
++ """Wrapper class around underlying C implementation."""
++
++ __slots__ = ["pid", "_process_name"]
++
++ def __init__(self, pid):
++ self.pid = pid
++ self._process_name = None
++
++ @wrap_exceptions
++ def get_process_name(self):
++ """Return process name as a string of limited len (15)."""
++ return _psutil_netbsd.get_process_name(self.pid)
++
++ @wrap_exceptions
++ def get_process_exe(self):
++ """Return process executable pathname."""
++ return _psutil_netbsd.get_process_exe(self.pid)
++
++ @wrap_exceptions
++ def get_process_cmdline(self):
++ """Return process cmdline as a list of arguments."""
++ return _psutil_netbsd.get_process_cmdline(self.pid)
++
++ @wrap_exceptions
++ def get_process_terminal(self):
++ tty_nr = _psutil_netbsd.get_process_tty_nr(self.pid)
++ tmap = _psposix._get_terminal_map()
++ try:
++ return tmap[tty_nr]
++ except KeyError:
++ return None
++
++ @wrap_exceptions
++ def get_process_ppid(self):
++ """Return process parent pid."""
++ return _psutil_netbsd.get_process_ppid(self.pid)
++
++ # XXX - available on FreeBSD >= 8 only
++ if hasattr(_psutil_netbsd, "get_process_cwd"):
++ @wrap_exceptions
++ def get_process_cwd(self):
++ """Return process current working directory."""
++ # sometimes we get an empty string, in which case we turn
++ # it into None
++ return _psutil_netbsd.get_process_cwd(self.pid) or None
++
++ @wrap_exceptions
++ def get_process_uids(self):
++ """Return real, effective and saved user ids."""
++ real, effective, saved = _psutil_netbsd.get_process_uids(self.pid)
++ return nt_uids(real, effective, saved)
++
++ @wrap_exceptions
++ def get_process_gids(self):
++ """Return real, effective and saved group ids."""
++ real, effective, saved = _psutil_netbsd.get_process_gids(self.pid)
++ return nt_gids(real, effective, saved)
++
++ @wrap_exceptions
++ def get_cpu_times(self):
++ """return a tuple containing process user/kernel time."""
++ user, system = _psutil_netbsd.get_process_cpu_times(self.pid)
++ return nt_cputimes(user, system)
++
++ @wrap_exceptions
++ def get_memory_info(self):
++ """Return a tuple with the process' RSS and VMS size."""
++ rss, vms = _psutil_netbsd.get_process_memory_info(self.pid)[:2]
++ return nt_meminfo(rss, vms)
++
++ _nt_ext_mem = namedtuple('meminfo', 'rss vms text data stack')
++
++ @wrap_exceptions
++ def get_ext_memory_info(self):
++ return self._nt_ext_mem(*_psutil_netbsd.get_process_memory_info(self.pid))
++
++ @wrap_exceptions
++ def get_process_create_time(self):
++ """Return the start time of the process as a number of seconds since
++ the epoch."""
++ return _psutil_netbsd.get_process_create_time(self.pid)
++
++ @wrap_exceptions
++ def get_process_num_threads(self):
++ """Return the number of threads belonging to the process."""
++ return _psutil_netbsd.get_process_num_threads(self.pid)
++
++ @wrap_exceptions
++ def get_num_ctx_switches(self):
++ return nt_ctxsw(*_psutil_netbsd.get_process_num_ctx_switches(self.pid))
++
++ @wrap_exceptions
++ def get_num_fds(self):
++ """Return the number of file descriptors opened by this process."""
++ return _psutil_netbsd.get_process_num_fds(self.pid)
++
++ @wrap_exceptions
++ def get_process_threads(self):
++ """Return the number of threads belonging to the process."""
++ rawlist = _psutil_netbsd.get_process_threads(self.pid)
++ retlist = []
++ for thread_id, utime, stime in rawlist:
++ ntuple = nt_thread(thread_id, utime, stime)
++ retlist.append(ntuple)
++ return retlist
++
++ @wrap_exceptions
++ def get_open_files(self):
++ """Return files opened by process as a list of namedtuples."""
++ # XXX - C implementation available on FreeBSD >= 8 only
++ # else fallback on lsof parser
++ if hasattr(_psutil_netbsd, "get_process_open_files"):
++ rawlist = _psutil_netbsd.get_process_open_files(self.pid)
++ return [nt_openfile(path, fd) for path, fd in rawlist]
++ else:
++ lsof = _psposix.LsofParser(self.pid, self._process_name)
++ return lsof.get_process_open_files()
++
++ @wrap_exceptions
++ def get_connections(self, kind='inet'):
++ """Return etwork connections opened by a process as a list of
++ namedtuples.
++ """
++ if kind not in conn_tmap:
++ raise ValueError("invalid %r kind argument; choose between %s"
++ % (kind, ', '.join([repr(x) for x in conn_tmap])))
++ families, types = conn_tmap[kind]
++ rawlist = _psutil_netbsd.get_process_connections(self.pid, families,
++ types)
++ ret = []
++ for item in rawlist:
++ fd, fam, type, laddr, raddr, status = item
++ status = _conn_status_map[status]
++ nt = nt_connection(fd, fam, type, laddr, raddr, status)
++ ret.append(nt)
++ return ret
++
++ @wrap_exceptions
++ def process_wait(self, timeout=None):
++ try:
++ return _psposix.wait_pid(self.pid, timeout)
++ except TimeoutExpired:
++ raise TimeoutExpired(self.pid, self._process_name)
++
++ @wrap_exceptions
++ def get_process_nice(self):
++ return _psutil_posix.getpriority(self.pid)
++
++ @wrap_exceptions
++ def set_process_nice(self, value):
++ return _psutil_posix.setpriority(self.pid, value)
++
++ @wrap_exceptions
++ def get_process_status(self):
++ code = _psutil_netbsd.get_process_status(self.pid)
++ if code in _status_map:
++ return _status_map[code]
++ # XXX is this legit? will we even ever get here?
++ return "?"
++
++ @wrap_exceptions
++ def get_process_io_counters(self):
++ rc, wc, rb, wb = _psutil_netbsd.get_process_io_counters(self.pid)
++ return nt_io(rc, wc, rb, wb)
++
++ nt_mmap_grouped = namedtuple('mmap',
++ 'path rss, private, ref_count, shadow_count')
++ nt_mmap_ext = namedtuple('mmap',
++ 'addr, perms path rss, private, ref_count, shadow_count')
++
++ @wrap_exceptions
++ def get_memory_maps(self):
++ return _psutil_netbsd.get_process_memory_maps(self.pid)
++
++ # FreeBSD < 8 does not support kinfo_getfile() and kinfo_getvmmap()
++ if not hasattr(_psutil_netbsd, 'get_process_open_files'):
++ def _not_implemented(self):
++ raise NotImplementedError("supported only starting from FreeBSD 8")
++ get_open_files = _not_implemented
++ get_process_cwd = _not_implemented
++ get_memory_maps = _not_implemented
++ get_num_fds = _not_implemented
diff --git a/sysutils/py-psutil/patches/patch-psutil___psutil__netbsd.c b/sysutils/py-psutil/patches/patch-psutil___psutil__netbsd.c
new file mode 100644
index 00000000000..cf750d114cb
--- /dev/null
+++ b/sysutils/py-psutil/patches/patch-psutil___psutil__netbsd.c
@@ -0,0 +1,1314 @@
+$NetBSD: patch-psutil___psutil__netbsd.c,v 1.1 2013/10/12 13:32:36 wiz Exp $
+
+Port to NetBSD.
+
+--- psutil/_psutil_netbsd.c.orig 2013-10-12 13:19:29.000000000 +0000
++++ psutil/_psutil_netbsd.c
+@@ -0,0 +1,1307 @@
++/*
++ * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
++ * Use of this source code is governed by a BSD-style license that can be
++ * found in the LICENSE file.
++ *
++ * NetBSD platform-specific module methods for _psutil_netbsd
++ */
++
++
++#include <Python.h>
++#include <assert.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <signal.h>
++#include <fcntl.h>
++#include <paths.h>
++#include <sys/types.h>
++#define _KMEMUSER 1 /* needed on NetBSD to get kprocinfo structs */
++#include <sys/sysctl.h>
++#include <sys/param.h>
++#include <sys/user.h>
++#include <sys/proc.h>
++#include <sys/file.h>
++#include <net/route.h>
++
++#include <sys/socket.h>
++#include <sys/socketvar.h> /* for struct xsocket */
++/* for xinpcb struct */
++#include <netinet/in.h>
++#include <netinet/in_systm.h>
++#include <netinet/ip.h>
++#include <netinet/in_pcb.h>
++#include <netinet/tcp.h> /* for tcp_seq type */
++#include <netinet/ip_var.h> /* for struct ipqehead */
++#include <netinet/tcp_timer.h> /* for TCPT_NTIMERS */
++#include <netinet/tcp_var.h> /* for struct xtcpcb */
++#include <netinet/tcp_fsm.h> /* for TCP connection states */
++#include <arpa/inet.h> /* for inet_ntop() */
++
++#include <utmpx.h>
++#include <kvm.h>
++#include <util.h>
++#include <sys/vmmeter.h> /* needed for vmtotal struct */
++#include <sys/mount.h>
++
++#include <net/if.h> /* net io counters */
++#include <net/if_dl.h>
++#include <net/route.h>
++
++#include <netinet/in.h> /* process open files/connections */
++#include <sys/un.h>
++
++#include <stdbool.h>
++
++#include "_psutil_netbsd.h"
++#include "_psutil_common.h"
++#include "arch/bsd/process_info.h"
++
++#define STIME(k) ((k)->p_ustime_sec + (k)->p_ustime_usec/1000000.0)
++#define UTIME(k) ((k)->p_uutime_sec + (k)->p_uutime_usec/1000000.0)
++
++#if !defined(KERN_PROC_INC_THREAD)
++#define KERN_PROC_INC_THREAD 0
++#endif
++
++/* Determine whether and where procfs is mounted. */
++static bool
++psutil_find_procfs(char *buffer, size_t buffer_size)
++{
++ int num, i;
++ struct statvfs *mntbuf;
++
++ num = getmntinfo(&mntbuf, 0);
++ if (num == 0) {
++ return false;
++ }
++
++ for (i = 0; i < num; i++) {
++ if (strcmp(mntbuf[i].f_fstypename, "procfs") == 0) {
++ (void)strlcpy(buffer, mntbuf[i].f_mntonname, buffer_size);
++ return true;
++ }
++ }
++
++ errno = ENOENT;
++ return false;
++}
++
++/*
++ * Utility function which fills a struct kinfo_proc2 struct based on process pid
++ */
++static int
++psutil_get_kinfo_proc(const pid_t pid, struct kinfo_proc2 *proc)
++{
++ int mib[4];
++ size_t size;
++ mib[0] = CTL_KERN;
++ mib[1] = KERN_PROC2;
++ mib[2] = KERN_PROC_PID;
++ mib[3] = pid;
++
++ size = sizeof(struct kinfo_proc2);
++
++ if (sysctl((int*)mib, 4, proc, &size, NULL, 0) == -1) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ return -1;
++ }
++
++ /*
++ * sysctl stores 0 in the size if we can't find the process information.
++ */
++ if (size == 0) {
++ NoSuchProcess();
++ return -1;
++ }
++ return 0;
++}
++
++static int
++psutil_get_pagesize(void)
++{
++ int mib[2];
++ int pagesize;
++ size_t size;
++ mib[0] = CTL_HW;
++ mib[1] = HW_PAGESIZE;
++
++ size = sizeof(int);
++
++ if (sysctl((int*)mib, 2, &pagesize, &size, NULL, 0) == -1) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ return -1;
++ }
++
++ return pagesize;
++}
++
++
++/*
++ * Return a Python list of all the PIDs running on the system.
++ */
++static PyObject*
++get_pid_list(PyObject* self, PyObject* args)
++{
++ struct kinfo_proc2 *proclist = NULL;
++ struct kinfo_proc2 *orig_address = NULL;
++ size_t num_processes;
++ size_t idx;
++ PyObject* retlist = PyList_New(0);
++ PyObject* pid = NULL;
++
++ if (retlist == NULL) {
++ return NULL;
++ }
++ if (psutil_get_proc_list(&proclist, &num_processes) != 0) {
++ PyErr_SetString(PyExc_RuntimeError, "failed to retrieve process list.");
++ goto error;
++ }
++
++ if (num_processes > 0) {
++ orig_address = proclist; // save so we can free it after we're done
++ for (idx=0; idx < num_processes; idx++) {
++ pid = Py_BuildValue("i", proclist->p_pid);
++ if (!pid)
++ goto error;
++ if (PyList_Append(retlist, pid))
++ goto error;
++ Py_DECREF(pid);
++ proclist++;
++ }
++ free(orig_address);
++ }
++
++ return retlist;
++
++error:
++ Py_XDECREF(pid);
++ Py_DECREF(retlist);
++ if (orig_address != NULL) {
++ free(orig_address);
++ }
++ return NULL;
++}
++
++
++/*
++ * Return a Python float indicating the system boot time expressed in
++ * seconds since the epoch.
++ */
++static PyObject*
++get_system_boot_time(PyObject* self, PyObject* args)
++{
++ /* fetch sysctl "kern.boottime" */
++ static int request[2] = { CTL_KERN, KERN_BOOTTIME };
++ struct timeval boottime;
++ size_t len = sizeof(boottime);
++
++ if (sysctl(request, 2, &boottime, &len, NULL, 0) == -1) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ return NULL;
++ }
++ return Py_BuildValue("d", (double)boottime.tv_sec);
++}
++
++
++/*
++ * Return process name from struct kinfo_proc2 as a Python string.
++ */
++static PyObject*
++get_process_name(PyObject* self, PyObject* args)
++{
++ long pid;
++ struct kinfo_proc2 kp;
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ return NULL;
++ }
++ if (psutil_get_kinfo_proc(pid, &kp) == -1) {
++ return NULL;
++ }
++ return Py_BuildValue("s", kp.p_comm);
++}
++
++
++/*
++ * Return process pathname executable.
++ * Thanks to Robert N. M. Watson:
++ * http://fxr.googlebit.com/source/usr.bin/procstat/procstat_bin.c?v=8-CURRENT
++ */
++static PyObject*
++get_process_exe(PyObject* self, PyObject* args)
++{
++ long pid;
++ char procfs[PATH_MAX], exelink[PATH_MAX], pathname[PATH_MAX];
++ ssize_t len;
++
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ PyErr_BadArgument();
++ return NULL;
++ }
++
++ /* Is procfs mounted? */
++ if (! psutil_find_procfs(procfs, sizeof(procfs))) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ return NULL;
++ }
++
++ /* Get the name of the executable from procfs. */
++ (void)snprintf(exelink, sizeof(exelink), "%s/%ld/exe", procfs, pid);
++ len = readlink(exelink, pathname, sizeof(pathname) - 1);
++ if (len == - 1) {
++ if (errno == ENOENT) {
++ return NoSuchProcess();
++ } else {
++ PyErr_SetFromErrno(PyExc_OSError);
++ return NULL;
++ }
++ }
++ pathname[len] = '\0';
++
++ /*
++ * Does the link point to "/"? In this case procfs doesn't know where
++ * the executable is.
++ */
++ if (strcmp(pathname, "/") == 0) {
++ errno = ENOENT;
++ PyErr_SetFromErrno(PyExc_OSError);
++ return NULL;
++ }
++
++ return Py_BuildValue("s", pathname);
++}
++
++
++/*
++ * Return process cmdline as a Python list of cmdline arguments.
++ */
++static PyObject*
++get_process_cmdline(PyObject* self, PyObject* args)
++{
++ long pid;
++ PyObject* arglist = NULL;
++
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ return NULL;
++ }
++
++ // get the commandline, defined in arch/bsd/process_info.c
++ arglist = psutil_get_arg_list(pid);
++
++ // psutil_get_arg_list() returns NULL only if psutil_get_cmd_args failed with ESRCH
++ // (no process with that PID)
++ if (NULL == arglist) {
++ return PyErr_SetFromErrno(PyExc_OSError);
++ }
++ return Py_BuildValue("N", arglist);
++}
++
++
++/*
++ * Return process parent pid from struct kinfo_proc2 as a Python integer.
++ */
++static PyObject*
++get_process_ppid(PyObject* self, PyObject* args)
++{
++ long pid;
++ struct kinfo_proc2 kp;
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ return NULL;
++ }
++ if (psutil_get_kinfo_proc(pid, &kp) == -1) {
++ return NULL;
++ }
++ return Py_BuildValue("l", (long)kp.p_ppid);
++}
++
++
++/*
++ * Return process status as a Python integer.
++ */
++static PyObject*
++get_process_status(PyObject* self, PyObject* args)
++{
++ long pid;
++ struct kinfo_proc2 kp;
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ return NULL;
++ }
++ if (psutil_get_kinfo_proc(pid, &kp) == -1) {
++ return NULL;
++ }
++ return Py_BuildValue("i", (int)kp.p_stat);
++}
++
++
++/*
++ * Return process real, effective and saved user ids from struct kinfo_proc2
++ * as a Python tuple.
++ */
++static PyObject*
++get_process_uids(PyObject* self, PyObject* args)
++{
++ long pid;
++ struct kinfo_proc2 kp;
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ return NULL;
++ }
++ if (psutil_get_kinfo_proc(pid, &kp) == -1) {
++ return NULL;
++ }
++ return Py_BuildValue("lll", (long)kp.p_ruid,
++ (long)kp.p_uid,
++ (long)kp.p_svuid);
++}
++
++
++/*
++ * Return process real, effective and saved group ids from struct kinfo_proc2
++ * as a Python tuple.
++ */
++static PyObject*
++get_process_gids(PyObject* self, PyObject* args)
++{
++ long pid;
++ struct kinfo_proc2 kp;
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ return NULL;
++ }
++ if (psutil_get_kinfo_proc(pid, &kp) == -1) {
++ return NULL;
++ }
++ return Py_BuildValue("lll", (long)kp.p_rgid,
++ (long)kp.p_groups[0],
++ (long)kp.p_svuid);
++}
++
++
++/*
++ * Return process real, effective and saved group ids from struct kinfo_proc2
++ * as a Python tuple.
++ */
++static PyObject*
++get_process_tty_nr(PyObject* self, PyObject* args)
++{
++ long pid;
++ struct kinfo_proc2 kp;
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ return NULL;
++ }
++ if (psutil_get_kinfo_proc(pid, &kp) == -1) {
++ return NULL;
++ }
++ return Py_BuildValue("i", kp.p_tdev);
++}
++
++
++/*
++ * Return the number of context switches performed by process as a tuple.
++ */
++static PyObject*
++get_process_num_ctx_switches(PyObject* self, PyObject* args)
++{
++ long pid;
++ struct kinfo_proc2 kp;
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ return NULL;
++ }
++ if (psutil_get_kinfo_proc(pid, &kp) == -1) {
++ return NULL;
++ }
++ return Py_BuildValue("(ll)", kp.p_uru_nvcsw,
++ kp.p_uru_nivcsw);
++}
++
++
++
++/*
++ * Return number of threads used by process as a Python integer.
++ */
++static PyObject*
++get_process_num_threads(PyObject* self, PyObject* args)
++{
++ long pid;
++ struct kinfo_proc2 kp;
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ return NULL;
++ }
++ if (psutil_get_kinfo_proc(pid, &kp) == -1) {
++ return NULL;
++ }
++ return Py_BuildValue("l", (long)kp.p_nlwps);
++}
++
++
++/*
++ * Retrieves all threads used by process returning a list of tuples
++ * including thread id, user time and system time.
++ * Thanks to Robert N. M. Watson:
++ * http://fxr.googlebit.com/source/usr.bin/procstat/procstat_threads.c?v=8-CURRENT
++ */
++static PyObject*
++get_process_threads(PyObject* self, PyObject* args)
++{
++ long pid;
++ int mib[4];
++ struct kinfo_proc2 *kip = NULL;
++ struct kinfo_proc2 *kipp = NULL;
++ int error;
++ unsigned int i;
++ size_t size;
++ PyObject* retList = PyList_New(0);
++ PyObject* pyTuple = NULL;
++
++ if (retList == NULL)
++ return NULL;
++ if (! PyArg_ParseTuple(args, "l", &pid))
++ goto error;
++
++ /*
++ * We need to re-query for thread information, so don't use *kipp.
++ */
++ mib[0] = CTL_KERN;
++ mib[1] = KERN_PROC;
++ mib[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD;
++ mib[3] = pid;
++
++ size = 0;
++ error = sysctl(mib, 4, NULL, &size, NULL, 0);
++ if (error == -1) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ goto error;
++ }
++ if (size == 0) {
++ NoSuchProcess();
++ goto error;
++ }
++
++ kip = malloc(size);
++ if (kip == NULL) {
++ PyErr_NoMemory();
++ goto error;
++ }
++
++ error = sysctl(mib, 4, kip, &size, NULL, 0);
++ if (error == -1) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ goto error;
++ }
++ if (size == 0) {
++ NoSuchProcess();
++ goto error;
++ }
++
++ for (i = 0; i < size / sizeof(*kipp); i++) {
++ kipp = &kip[i];
++ pyTuple = Py_BuildValue("Idd",
++ /** \todo: unsupported? */
++ 0, // kipp->ki_tid
++ UTIME(kipp),
++ STIME(kipp)
++ );
++ if (pyTuple == NULL)
++ goto error;
++ if (PyList_Append(retList, pyTuple))
++ goto error;
++ Py_DECREF(pyTuple);
++ }
++ free(kip);
++
++ return retList;
++
++error:
++ Py_XDECREF(pyTuple);
++ Py_DECREF(retList);
++ if (kip != NULL) {
++ free(kip);
++ }
++ return NULL;
++}
++
++
++/*
++ * Return a Python tuple (user_time, kernel_time)
++ */
++static PyObject*
++get_process_cpu_times(PyObject* self, PyObject* args)
++{
++ long pid;
++ double user_t, sys_t;
++ struct kinfo_proc2 kp;
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ return NULL;
++ }
++ if (psutil_get_kinfo_proc(pid, &kp) == -1) {
++ return NULL;
++ }
++ // convert from microseconds to seconds
++ user_t = UTIME(&kp);
++ sys_t = STIME(&kp);
++ return Py_BuildValue("(dd)", user_t, sys_t);
++}
++
++
++/*
++ * Return a Python integer indicating the number of CPUs on the system
++ */
++static PyObject*
++get_num_cpus(PyObject* self, PyObject* args)
++{
++ int mib[2];
++ int ncpu;
++ size_t len;
++
++ mib[0] = CTL_HW;
++ mib[1] = HW_NCPU;
++ len = sizeof(ncpu);
++
++ if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ return NULL;
++ }
++
++ return Py_BuildValue("i", ncpu);
++}
++
++
++/*
++ * Return a Python float indicating the process create time expressed in
++ * seconds since the epoch.
++ */
++static PyObject*
++get_process_create_time(PyObject* self, PyObject* args)
++{
++ /** \todo: implement */
++ return NULL;
++}
++
++
++/*
++ * Return a Python float indicating the process create time expressed in
++ * seconds since the epoch.
++ */
++static PyObject*
++get_process_io_counters(PyObject* self, PyObject* args)
++{
++ /** \todo: implement */
++ return NULL;
++}
++
++
++/*
++ * Return extended memory info for a process as a Python tuple.
++ */
++static PyObject*
++get_process_memory_info(PyObject* self, PyObject* args)
++{
++ int pagesize;
++ long pid;
++ struct kinfo_proc2 kp;
++ if (! PyArg_ParseTuple(args, "l", &pid)) {
++ return NULL;
++ }
++ if (psutil_get_kinfo_proc(pid, &kp) == -1) {
++ return NULL;
++ }
++ pagesize = psutil_get_pagesize();
++
++ /** \todo: find replacement for kp.ki_size */
++ return Py_BuildValue("(lllll)", kp.p_vm_rssize * pagesize, // rss
++ 0, //vms(long)kp.ki_size, // vms
++ kp.p_vm_tsize * pagesize, // text
++ kp.p_vm_dsize * pagesize, // data
++ kp.p_vm_ssize * pagesize); // stack
++}
++
++
++/*
++ * Return virtual memory usage statistics.
++ */
++static PyObject*
++get_virtual_mem(PyObject* self, PyObject* args)
++{
++ int mib[2];
++ struct uvmexp_sysctl uvmexp;
++ size_t size;
++ struct vmtotal vm;
++ int64_t pagesize;
++
++ mib[0] = CTL_VM;
++ mib[1] = VM_UVMEXP2;
++ size = sizeof(uvmexp);
++ if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0)
++ goto error;
++
++ mib[0] = CTL_VM;
++ mib[1] = VM_METER;
++ size = sizeof(vm);
++ if (sysctl(mib, 2, &vm, &size, NULL, 0) != 0)
++ goto error;
++
++ pagesize = uvmexp.pagesize;
++ return Py_BuildValue("KKKKKK",
++ uvmexp.npages * pagesize,
++ uvmexp.free * pagesize,
++ uvmexp.active * pagesize,
++ uvmexp.inactive * pagesize,
++ uvmexp.wired * pagesize,
++ (vm.t_vmshr + vm.t_rmshr) * pagesize // shared
++ );
++
++error:
++ PyErr_SetFromErrno(PyExc_OSError);
++ return NULL;
++}
++
++
++/*
++ * Return swap memory stats (see 'swapinfo' cmdline tool)
++ */
++static PyObject*
++get_swap_mem(PyObject* self, PyObject* args)
++{
++ /** \todo: implement; see sbin/swapctl/swaplist.c for possible example code */
++ return NULL;
++}
++
++
++/*
++ * Return a Python tuple representing user, kernel and idle CPU times
++ */
++static PyObject*
++get_system_cpu_times(PyObject* self, PyObject* args)
++{
++ long cpu_time[CPUSTATES];
++ size_t size;
++
++ size = sizeof(cpu_time);
++
++ if (sysctlbyname("kern.cp_time", &cpu_time, &size, NULL, 0) == -1) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ return NULL;
++ }
++
++ return Py_BuildValue("(ddddd)",
++ (double)cpu_time[CP_USER] / CLOCKS_PER_SEC,
++ (double)cpu_time[CP_NICE] / CLOCKS_PER_SEC,
++ (double)cpu_time[CP_SYS] / CLOCKS_PER_SEC,
++ (double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC,
++ (double)cpu_time[CP_INTR] / CLOCKS_PER_SEC
++ );
++}
++
++/*
++ * Return files opened by process as a list of (path, fd) tuples
++ */
++static PyObject*
++get_process_open_files(PyObject* self, PyObject* args)
++{
++ /** \todo: implement */
++ return NULL;
++}
++
++
++/*
++ * Return files opened by process as a list of (path, fd) tuples
++ */
++static PyObject*
++get_process_num_fds(PyObject* self, PyObject* args)
++{
++ /** \todo: implement */
++ return NULL;
++}
++
++
++/*
++ * Return process current working directory.
++ */
++static PyObject*
++get_process_cwd(PyObject* self, PyObject* args)
++{
++ /** \todo: implement */
++ return NULL;
++}
++
++
++static char *
++psutil_fetch_tcplist(void)
++{
++ /** \todo: implement */
++ return NULL;
++}
++
++static int
++psutil_sockaddr_port(int family, struct sockaddr_storage *ss)
++{
++ struct sockaddr_in6 *sin6;
++ struct sockaddr_in *sin;
++
++ if (family == AF_INET) {
++ sin = (struct sockaddr_in *)ss;
++ return (sin->sin_port);
++ } else {
++ sin6 = (struct sockaddr_in6 *)ss;
++ return (sin6->sin6_port);
++ }
++}
++
++static void *
++psutil_sockaddr_addr(int family, struct sockaddr_storage *ss)
++{
++ struct sockaddr_in6 *sin6;
++ struct sockaddr_in *sin;
++
++ if (family == AF_INET) {
++ sin = (struct sockaddr_in *)ss;
++ return (&sin->sin_addr);
++ } else {
++ sin6 = (struct sockaddr_in6 *)ss;
++ return (&sin6->sin6_addr);
++ }
++}
++
++static socklen_t
++psutil_sockaddr_addrlen(int family)
++{
++ if (family == AF_INET)
++ return (sizeof(struct in_addr));
++ else
++ return (sizeof(struct in6_addr));
++}
++
++static int
++psutil_sockaddr_matches(int family, int port, void *pcb_addr,
++ struct sockaddr_storage *ss)
++{
++ if (psutil_sockaddr_port(family, ss) != port)
++ return (0);
++ return (memcmp(psutil_sockaddr_addr(family, ss), pcb_addr,
++ psutil_sockaddr_addrlen(family)) == 0);
++}
++
++static struct tcpcb *
++psutil_search_tcplist(char *buf, struct kinfo_file *kif)
++{
++ /** \todo: implement */
++ return NULL;
++}
++
++// a signaler for connections without an actual status
++static int PSUTIL_CONN_NONE = 128;
++
++/*
++ * Return connections opened by process.
++ */
++static PyObject*
++get_process_connections(PyObject* self, PyObject* args)
++{
++ /** \todo: implement */
++ return NULL;
++}
++
++
++/*
++ * Return a Python list of tuple representing per-cpu times
++ */
++static PyObject*
++get_system_per_cpu_times(PyObject* self, PyObject* args)
++{
++ int mib[2];
++ int ncpu;
++ size_t size;
++ int i;
++ PyObject* py_retlist = PyList_New(0);
++ PyObject* py_cputime = NULL;
++ long cpu_time[MAXCPUS][CPUSTATES];
++
++ if (py_retlist == NULL)
++ return NULL;
++
++ // retrieve the number of cpus
++ mib[0] = CTL_HW;
++ mib[1] = HW_NCPU;
++ size = sizeof(ncpu);
++ if (sysctl(mib, 2, &ncpu, &size, NULL, 0) == -1) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ goto error;
++ }
++
++ // per-cpu info
++ mib[0] = CTL_KERN;
++ mib[1] = KERN_CP_TIME;
++ size = sizeof(cpu_time);
++ if (sysctl(mib, 2, cpu_time, &size, NULL, 0) == -1) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ goto error;
++ }
++
++ for (i = 0; i < ncpu; i++) {
++ py_cputime = Py_BuildValue("(ddddd)",
++ (double)cpu_time[i][CP_USER] / CLOCKS_PER_SEC,
++ (double)cpu_time[i][CP_NICE] / CLOCKS_PER_SEC,
++ (double)cpu_time[i][CP_SYS] / CLOCKS_PER_SEC,
++ (double)cpu_time[i][CP_IDLE] / CLOCKS_PER_SEC,
++ (double)cpu_time[i][CP_INTR] / CLOCKS_PER_SEC
++ );
++ if (!py_cputime)
++ goto error;
++ if (PyList_Append(py_retlist, py_cputime))
++ goto error;
++ Py_DECREF(py_cputime);
++ }
++
++ return py_retlist;
++
++error:
++ Py_XDECREF(py_cputime);
++ Py_DECREF(py_retlist);
++ return NULL;
++}
++
++
++// remove spaces from string
++void remove_spaces(char *str) {
++ char *p1 = str;
++ char *p2 = str;
++ do
++ while (*p2 == ' ')
++ p2++;
++ while (*p1++ = *p2++);
++}
++
++/*
++ * Return a list of tuples for every process memory maps.
++ * 'procstat' cmdline utility has been used as an example.
++ */
++static PyObject*
++get_process_memory_maps(PyObject* self, PyObject* args)
++{
++ /** \todo: implement */
++ return NULL;
++}
++
++
++/*
++ * Return a list of tuples including device, mount point and fs type
++ * for all partitions mounted on the system.
++ */
++static PyObject*
++get_disk_partitions(PyObject* self, PyObject* args)
++{
++ int num;
++ int i;
++ long len;
++ uint64_t flags;
++ char opts[200];
++ struct statvfs *fs = NULL;
++ PyObject* py_retlist = PyList_New(0);
++ PyObject* py_tuple = NULL;
++
++ if (py_retlist == NULL)
++ return NULL;
++
++ // get the number of mount points
++ Py_BEGIN_ALLOW_THREADS
++ num = getvfsstat(NULL, 0, MNT_NOWAIT);
++ Py_END_ALLOW_THREADS
++ if (num == -1) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ goto error;
++ }
++
++ len = sizeof(*fs) * num;
++ fs = malloc(len);
++ if (fs == NULL) {
++ PyErr_NoMemory();
++ goto error;
++ }
++
++ Py_BEGIN_ALLOW_THREADS
++ num = getvfsstat(fs, len, MNT_NOWAIT);
++ Py_END_ALLOW_THREADS
++ if (num == -1) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ goto error;
++ }
++
++ for (i = 0; i < num; i++) {
++ py_tuple = NULL;
++ opts[0] = 0;
++ flags = fs[i].f_flag;
++
++ // see sys/mount.h
++ if (flags & MNT_RDONLY)
++ strlcat(opts, "ro", sizeof(opts));
++ else
++ strlcat(opts, "rw", sizeof(opts));
++ if (flags & ST_NOEXEC)
++ strlcat(opts, ",noexec", sizeof(opts));
++ if (flags & ST_NOSUID)
++ strlcat(opts, ",nosuid", sizeof(opts));
++ if (flags & ST_NODEV)
++ strlcat(opts, ",nodev", sizeof(opts));
++ if (flags & ST_UNION)
++ strlcat(opts, ",union", sizeof(opts));
++ if (flags & ST_SYNCHRONOUS)
++ strlcat(opts, ",sync", sizeof(opts));
++ if (flags & ST_ASYNC)
++ strlcat(opts, ",async", sizeof(opts));
++ if (flags & ST_NOCOREDUMP)
++ strlcat(opts, ",nocoredump", sizeof(opts));
++ if (flags & ST_NOATIME)
++ strlcat(opts, ",noatime", sizeof(opts));
++ if (flags & ST_SYMPERM)
++ strlcat(opts, ",symperm", sizeof(opts));
++ if (flags & ST_NODEVMTIME)
++ strlcat(opts, ",nodevmtime", sizeof(opts));
++ if (flags & ST_LOG)
++ strlcat(opts, ",log", sizeof(opts));
++ if (flags & ST_LOCAL)
++ strlcat(opts, ",local", sizeof(opts));
++ if (flags & ST_QUOTA)
++ strlcat(opts, ",quota", sizeof(opts));
++ if (flags & ST_ROOTFS)
++ strlcat(opts, ",rootfs", sizeof(opts));
++ if (flags & ST_EXRDONLY)
++ strlcat(opts, ",exrdonly", sizeof(opts));
++ if (flags & ST_EXPORTED)
++ strlcat(opts, ",exported", sizeof(opts));
++ if (flags & ST_DEFEXPORTED)
++ strlcat(opts, ",defexported", sizeof(opts));
++ if (flags & ST_EXPORTANON)
++ strlcat(opts, ",exportanon", sizeof(opts));
++ if (flags & ST_EXKERB)
++ strlcat(opts, ",exkerb", sizeof(opts));
++ if (flags & ST_EXNORESPORT)
++ strlcat(opts, ",exnoresport", sizeof(opts));
++ if (flags & ST_EXPUBLIC)
++ strlcat(opts, ",expublic", sizeof(opts));
++
++ py_tuple = Py_BuildValue("(ssss)", fs[i].f_mntfromname, // device
++ fs[i].f_mntonname, // mount point
++ fs[i].f_fstypename, // fs type
++ opts); // options
++ if (!py_tuple)
++ goto error;
++ if (PyList_Append(py_retlist, py_tuple))
++ goto error;
++ Py_DECREF(py_tuple);
++ }
++
++ free(fs);
++ return py_retlist;
++
++error:
++ Py_XDECREF(py_tuple);
++ Py_DECREF(py_retlist);
++ if (fs != NULL)
++ free(fs);
++ return NULL;
++}
++
++
++/*
++ * Return a Python list of named tuples with overall network I/O information
++ */
++static PyObject*
++get_net_io_counters(PyObject* self, PyObject* args)
++{
++ char *buf = NULL, *lim, *next;
++ struct if_msghdr *ifm;
++ int mib[6];
++ size_t len;
++ PyObject* py_retdict = PyDict_New();
++ PyObject* py_ifc_info = NULL;
++ if (py_retdict == NULL)
++ return NULL;
++
++ mib[0] = CTL_NET; // networking subsystem
++ mib[1] = PF_ROUTE; // type of information
++ mib[2] = 0; // protocol (IPPROTO_xxx)
++ mib[3] = 0; // address family
++ mib[4] = NET_RT_IFLIST; // operation
++ mib[5] = 0;
++
++ if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ goto error;
++ }
++
++ buf = malloc(len);
++ if (buf == NULL) {
++ PyErr_NoMemory();
++ goto error;
++ }
++
++ if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
++ PyErr_SetFromErrno(PyExc_OSError);
++ goto error;
++ }
++
++ lim = buf + len;
++
++ for (next = buf; next < lim; ) {
++ py_ifc_info = NULL;
++ ifm = (struct if_msghdr *)next;
++ next += ifm->ifm_msglen;
++
++ if (ifm->ifm_type == RTM_IFINFO) {
++ struct if_msghdr *if2m = (struct if_msghdr *)ifm;
++ struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1);
++ char ifc_name[32];
++
++ strncpy(ifc_name, sdl->sdl_data, sdl->sdl_nlen);
++ ifc_name[sdl->sdl_nlen] = 0;
++ // XXX: ignore usbus interfaces:
++ // http://lists.freebsd.org/pipermail/freebsd-current/2011-October/028752.html
++ // 'ifconfig -a' doesn't show them, nor do we.
++ if (strncmp(ifc_name, "usbus", 5) == 0) {
++ continue;
++ }
++
++ py_ifc_info = Py_BuildValue("(kkkkkkki)",
++ if2m->ifm_data.ifi_obytes,
++ if2m->ifm_data.ifi_ibytes,
++ if2m->ifm_data.ifi_opackets,
++ if2m->ifm_data.ifi_ipackets,
++ if2m->ifm_data.ifi_ierrors,
++ if2m->ifm_data.ifi_oerrors,
++ if2m->ifm_data.ifi_iqdrops,
++ 0); // dropout not supported
++ if (!py_ifc_info)
++ goto error;
++ if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info))
++ goto error;
++ Py_DECREF(py_ifc_info);
++ }
++ else {
++ continue;
++ }
++ }
++
++ free(buf);
++ return py_retdict;
++
++error:
++ Py_XDECREF(py_ifc_info);
++ Py_DECREF(py_retdict);
++ if (buf != NULL)
++ free(buf);
++ return NULL;
++}
++
++
++/*
++ * Return a Python dict of tuples for disk I/O information
++ */
++static PyObject*
++get_disk_io_counters(PyObject* self, PyObject* args)
++{
++ /** \todo: not implemented */
++ return NULL;
++}
++
++
++/*
++ * Return currently connected users as a list of tuples.
++ */
++static PyObject*
++get_system_users(PyObject* self, PyObject* args)
++{
++ PyObject *ret_list = PyList_New(0);
++ PyObject *tuple = NULL;
++
++ if (ret_list == NULL)
++ return NULL;
++
++ struct utmpx *utx;
++
++ while ((utx = getutxent()) != NULL) {
++ if (utx->ut_type != USER_PROCESS)
++ continue;
++ tuple = Py_BuildValue("(sssf)",
++ utx->ut_user, // username
++ utx->ut_line, // tty
++ utx->ut_host, // hostname
++ (float)utx->ut_tv.tv_sec // start time
++ );
++ if (!tuple) {
++ endutxent();
++ goto error;
++ }
++ if (PyList_Append(ret_list, tuple)) {
++ endutxent();
++ goto error;
++ }
++ Py_DECREF(tuple);
++ }
++
++ endutxent();
++ return ret_list;
++
++error:
++ Py_XDECREF(tuple);
++ Py_DECREF(ret_list);
++ return NULL;
++}
++
++
++/*
++ * define the psutil C module methods and initialize the module.
++ */
++static PyMethodDef
++PsutilMethods[] =
++{
++ // --- per-process functions
++
++ {"get_process_name", get_process_name, METH_VARARGS,
++ "Return process name"},
++ {"get_process_connections", get_process_connections, METH_VARARGS,
++ "Return connections opened by process"},
++ {"get_process_exe", get_process_exe, METH_VARARGS,
++ "Return process pathname executable"},
++ {"get_process_cmdline", get_process_cmdline, METH_VARARGS,
++ "Return process cmdline as a list of cmdline arguments"},
++ {"get_process_ppid", get_process_ppid, METH_VARARGS,
++ "Return process ppid as an integer"},
++ {"get_process_uids", get_process_uids, METH_VARARGS,
++ "Return process real effective and saved user ids as a Python tuple"},
++ {"get_process_gids", get_process_gids, METH_VARARGS,
++ "Return process real effective and saved group ids as a Python tuple"},
++ {"get_process_cpu_times", get_process_cpu_times, METH_VARARGS,
++ "Return tuple of user/kern time for the given PID"},
++ {"get_process_create_time", get_process_create_time, METH_VARARGS,
++ "Return a float indicating the process create time expressed in "
++ "seconds since the epoch"},
++ {"get_process_memory_info", get_process_memory_info, METH_VARARGS,
++ "Return extended memory info for a process as a Python tuple."},
++ {"get_process_num_threads", get_process_num_threads, METH_VARARGS,
++ "Return number of threads used by process"},
++ {"get_process_num_ctx_switches", get_process_num_ctx_switches, METH_VARARGS,
++ "Return the number of context switches performed by process"},
++ {"get_process_threads", get_process_threads, METH_VARARGS,
++ "Return process threads"},
++ {"get_process_status", get_process_status, METH_VARARGS,
++ "Return process status as an integer"},
++ {"get_process_io_counters", get_process_io_counters, METH_VARARGS,
++ "Return process IO counters"},
++ {"get_process_tty_nr", get_process_tty_nr, METH_VARARGS,
++ "Return process tty (terminal) number"},
++ {"get_process_open_files", get_process_open_files, METH_VARARGS,
++ "Return files opened by process as a list of (path, fd) tuples"},
++ {"get_process_cwd", get_process_cwd, METH_VARARGS,
++ "Return process current working directory."},
++ {"get_process_memory_maps", get_process_memory_maps, METH_VARARGS,
++ "Return a list of tuples for every process's memory map"},
++ {"get_process_num_fds", get_process_num_fds, METH_VARARGS,
++ "Return the number of file descriptors opened by this process"},
++
++ // --- system-related functions
++
++ {"get_pid_list", get_pid_list, METH_VARARGS,
++ "Returns a list of PIDs currently running on the system"},
++ {"get_num_cpus", get_num_cpus, METH_VARARGS,
++ "Return number of CPUs on the system"},
++ {"get_virtual_mem", get_virtual_mem, METH_VARARGS,
++ "Return system virtual memory usage statistics"},
++ {"get_swap_mem", get_swap_mem, METH_VARARGS,
++ "Return swap mem stats"},
++ {"get_system_cpu_times", get_system_cpu_times, METH_VARARGS,
++ "Return system cpu times as a tuple (user, system, nice, idle, irc)"},
++ {"get_system_per_cpu_times", get_system_per_cpu_times, METH_VARARGS,
++ "Return system per-cpu times as a list of tuples"},
++ {"get_system_boot_time", get_system_boot_time, METH_VARARGS,
++ "Return the system boot time expressed in seconds since the epoch."},
++ {"get_disk_partitions", get_disk_partitions, METH_VARARGS,
++ "Return a list of tuples including device, mount point and "
++ "fs type for all partitions mounted on the system."},
++ {"get_net_io_counters", get_net_io_counters, METH_VARARGS,
++ "Return dict of tuples of networks I/O information."},
++ {"get_disk_io_counters", get_disk_io_counters, METH_VARARGS,
++ "Return a Python dict of tuples for disk I/O information"},
++ {"get_system_users", get_system_users, METH_VARARGS,
++ "Return currently connected users as a list of tuples"},
++
++ {NULL, NULL, 0, NULL}
++};
++
++struct module_state {
++ PyObject *error;
++};
++
++#if PY_MAJOR_VERSION >= 3
++#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
++#else
++#define GETSTATE(m) (&_state)
++#endif
++
++#if PY_MAJOR_VERSION >= 3
++
++static int
++psutil_netbsd_traverse(PyObject *m, visitproc visit, void *arg) {
++ Py_VISIT(GETSTATE(m)->error);
++ return 0;
++}
++
++static int
++psutil_netbsd_clear(PyObject *m) {5A
++ Py_CLEAR(GETSTATE(m)->error);
++ return 0;
++}
++
++static struct PyModuleDef
++moduledef = {
++ PyModuleDef_HEAD_INIT,
++ "psutil_netbsd",
++ NULL,
++ sizeof(struct module_state),
++ PsutilMethods,
++ NULL,
++ psutil_netbsd_traverse,
++ psutil_netbsd_clear,
++ NULL
++};
++
++#define INITERROR return NULL
++
++PyObject *
++PyInit__psutil_netbsd(void)
++
++#else
++#define INITERROR return
++
++void init_psutil_netbsd(void)
++#endif
++{
++#if PY_MAJOR_VERSION >= 3
++ PyObject *module = PyModule_Create(&moduledef);
++#else
++ PyObject *module = Py_InitModule("_psutil_netbsd", PsutilMethods);
++#endif
++ // process status constants
++ PyModule_AddIntConstant(module, "SIDL", SIDL);
++ PyModule_AddIntConstant(module, "SACTIVE", SACTIVE);
++ PyModule_AddIntConstant(module, "SDYING", SDYING);
++ PyModule_AddIntConstant(module, "SSTOP", SSTOP);
++ PyModule_AddIntConstant(module, "SZOMB", SZOMB);
++ PyModule_AddIntConstant(module, "SDEAD", SDEAD);
++ // connection status constants
++ PyModule_AddIntConstant(module, "TCPS_CLOSED", TCPS_CLOSED);
++ PyModule_AddIntConstant(module, "TCPS_CLOSING", TCPS_CLOSING);
++ PyModule_AddIntConstant(module, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT);
++ PyModule_AddIntConstant(module, "TCPS_LISTEN", TCPS_LISTEN);
++ PyModule_AddIntConstant(module, "TCPS_ESTABLISHED", TCPS_ESTABLISHED);
++ PyModule_AddIntConstant(module, "TCPS_SYN_SENT", TCPS_SYN_SENT);
++ PyModule_AddIntConstant(module, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED);
++ PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1);
++ PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2);
++ PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK);
++ PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT);
++
++ if (module == NULL) {
++ INITERROR;
++ }
++#if PY_MAJOR_VERSION >= 3
++ return module;
++#endif
++}
diff --git a/sysutils/py-psutil/patches/patch-psutil___psutil__netbsd.h b/sysutils/py-psutil/patches/patch-psutil___psutil__netbsd.h
new file mode 100644
index 00000000000..2e7167c1b5b
--- /dev/null
+++ b/sysutils/py-psutil/patches/patch-psutil___psutil__netbsd.h
@@ -0,0 +1,57 @@
+$NetBSD: patch-psutil___psutil__netbsd.h,v 1.1 2013/10/12 13:32:36 wiz Exp $
+
+Port to NetBSD.
+
+--- psutil/_psutil_netbsd.h.orig 2013-10-12 13:19:29.000000000 +0000
++++ psutil/_psutil_netbsd.h
+@@ -0,0 +1,50 @@
++/*
++ * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
++ * Use of this source code is governed by a BSD-style license that can be
++ * found in the LICENSE file.
++ *
++ * NetBSD platform-specific module methods for _psutil_netbsd
++ */
++
++#include <Python.h>
++
++// --- per-process functions
++
++static PyObject* get_process_cpu_times(PyObject* self, PyObject* args);
++static PyObject* get_process_name(PyObject* self, PyObject* args);
++static PyObject* get_process_exe(PyObject* self, PyObject* args);
++static PyObject* get_process_cmdline(PyObject* self, PyObject* args);
++static PyObject* get_process_ppid(PyObject* self, PyObject* args);
++static PyObject* get_process_uids(PyObject* self, PyObject* args);
++static PyObject* get_process_gids(PyObject* self, PyObject* args);
++static PyObject* get_process_connections(PyObject* self, PyObject* args);
++static PyObject* get_process_create_time(PyObject* self, PyObject* args);
++static PyObject* get_process_memory_info(PyObject* self, PyObject* args);
++static PyObject* get_process_num_threads(PyObject* self, PyObject* args);
++static PyObject* get_process_num_fds(PyObject* self, PyObject* args);
++static PyObject* get_process_threads(PyObject* self, PyObject* args);
++static PyObject* get_process_status(PyObject* self, PyObject* args);
++static PyObject* get_process_io_counters(PyObject* self, PyObject* args);
++static PyObject* get_process_tty_nr(PyObject* self, PyObject* args);
++static PyObject* get_process_memory_maps(PyObject* self, PyObject* args);
++static PyObject* get_process_num_ctx_switches(PyObject* self, PyObject* args);
++#if NOTYET
++static PyObject* get_process_open_files(PyObject* self, PyObject* args);
++static PyObject* get_process_cwd(PyObject* self, PyObject* args);
++#endif
++
++// --- system-related functions
++
++static PyObject* get_pid_list(PyObject* self, PyObject* args);
++static PyObject* get_num_cpus(PyObject* self, PyObject* args);
++static PyObject* get_virtual_mem(PyObject* self, PyObject* args);
++static PyObject* get_swap_mem(PyObject* self, PyObject* args);
++static PyObject* get_system_cpu_times(PyObject* self, PyObject* args);
++#if NOTYET
++static PyObject* get_system_per_cpu_times(PyObject* self, PyObject* args);
++#endif
++static PyObject* get_system_boot_time(PyObject* self, PyObject* args);
++static PyObject* get_disk_partitions(PyObject* self, PyObject* args);
++static PyObject* get_net_io_counters(PyObject* self, PyObject* args);
++static PyObject* get_disk_io_counters(PyObject* self, PyObject* args);
++static PyObject* get_system_users(PyObject* self, PyObject* args);
diff --git a/sysutils/py-psutil/patches/patch-psutil_arch_netbsd_process__info.c b/sysutils/py-psutil/patches/patch-psutil_arch_netbsd_process__info.c
new file mode 100644
index 00000000000..be6e0a0053e
--- /dev/null
+++ b/sysutils/py-psutil/patches/patch-psutil_arch_netbsd_process__info.c
@@ -0,0 +1,296 @@
+$NetBSD: patch-psutil_arch_netbsd_process__info.c,v 1.1 2013/10/12 13:32:36 wiz Exp $
+
+Port to NetBSD.
+
+--- psutil/arch/netbsd/process_info.c.orig 2013-10-12 13:19:29.000000000 +0000
++++ psutil/arch/netbsd/process_info.c
+@@ -0,0 +1,289 @@
++/*
++ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
++ * Use of this source code is governed by a BSD-style license that can be
++ * found in the LICENSE file.
++ *
++ * Helper functions related to fetching process information. Used by _psutil_netbsd
++ * module methods.
++ */
++
++#include <Python.h>
++#include <assert.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/sysctl.h>
++#include <sys/param.h>
++#include <sys/user.h>
++#include <sys/proc.h>
++#include <signal.h>
++
++#include "process_info.h"
++
++
++/*
++ * Returns a list of all BSD processes on the system. This routine
++ * allocates the list and puts it in *procList and a count of the
++ * number of entries in *procCount. You are responsible for freeing
++ * this list (use "free" from System framework).
++ * On success, the function returns 0.
++ * On error, the function returns a BSD errno value.
++ */
++int
++psutil_get_proc_list(struct kinfo_proc2 **procList, size_t *procCount)
++{
++ int err;
++ struct kinfo_proc2 * result;
++ int done;
++ static const int name[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, 0 };
++ // Declaring name as const requires us to cast it when passing it to
++ // sysctl because the prototype doesn't include the const modifier.
++ size_t length;
++
++ assert( procList != NULL);
++ assert(*procList == NULL);
++ assert(procCount != NULL);
++
++ *procCount = 0;
++
++ /*
++ * We start by calling sysctl with result == NULL and length == 0.
++ * That will succeed, and set length to the appropriate length.
++ * We then allocate a buffer of that size and call sysctl again
++ * with that buffer. If that succeeds, we're done. If that fails
++ * with ENOMEM, we have to throw away our buffer and loop. Note
++ * that the loop causes use to call sysctl with NULL again; this
++ * is necessary because the ENOMEM failure case sets length to
++ * the amount of data returned, not the amount of data that
++ * could have been returned.
++ */
++ result = NULL;
++ done = 0;
++ do {
++ assert(result == NULL);
++ // Call sysctl with a NULL buffer.
++ length = 0;
++ err = sysctl((int *)name, (sizeof(name) / sizeof(*name)) - 1,
++ NULL, &length, NULL, 0);
++ if (err == -1)
++ err = errno;
++
++ // Allocate an appropriately sized buffer based on the results
++ // from the previous call.
++ if (err == 0) {
++ result = malloc(length);
++ if (result == NULL)
++ err = ENOMEM;
++ }
++
++ // Call sysctl again with the new buffer. If we get an ENOMEM
++ // error, toss away our buffer and start again.
++ if (err == 0) {
++ err = sysctl((int *) name, (sizeof(name) / sizeof(*name)) - 1,
++ result, &length, NULL, 0);
++ if (err == -1)
++ err = errno;
++ if (err == 0) {
++ done = 1;
++ }
++ else if (err == ENOMEM) {
++ assert(result != NULL);
++ free(result);
++ result = NULL;
++ err = 0;
++ }
++ }
++ } while (err == 0 && ! done);
++
++ // Clean up and establish post conditions.
++ if (err != 0 && result != NULL) {
++ free(result);
++ result = NULL;
++ }
++
++ *procList = result;
++ *procCount = length / sizeof(struct kinfo_proc2);
++
++ assert((err == 0) == (*procList != NULL));
++ return err;
++}
++
++
++char
++*psutil_get_cmd_path(long pid, size_t *pathsize)
++{
++#if defined(__FreeBSD__)
++ int mib[4];
++ char *path;
++ size_t size = 0;
++
++ /*
++ * Make a sysctl() call to get the raw argument space of the process.
++ */
++ mib[0] = CTL_KERN;
++ mib[1] = KERN_PROC2;
++ mib[2] = KERN_PROC_PATHNAME;
++ mib[3] = pid;
++
++ // call with a null buffer first to determine if we need a buffer
++ if (sysctl(mib, 4, NULL, &size, NULL, 0) == -1) {
++ return NULL;
++ }
++
++ path = malloc(size);
++ if (path == NULL) {
++ PyErr_NoMemory();
++ return NULL;
++ }
++
++ *pathsize = size;
++ if (sysctl(mib, MIB_LEN, path, &size, NULL, 0) == -1) {
++ free(path);
++ return NULL; /* Insufficient privileges */
++ }
++
++ return path;
++#else
++ /* not supported */
++ return NULL;
++#endif
++}
++
++
++/*
++ * XXX no longer used; it probably makese sense to remove it.
++ * Borrowed from psi Python System Information project
++ *
++ * Get command arguments and environment variables.
++ *
++ * Based on code from ps.
++ *
++ * Returns:
++ * 0 for success;
++ * -1 for failure (Exception raised);
++ * 1 for insufficient privileges.
++ */
++char
++*psutil_get_cmd_args(long pid, size_t *argsize)
++{
++ int mib[4], argmax;
++ size_t size = sizeof(argmax);
++ char *procargs = NULL;
++
++ /* Get the maximum process arguments size. */
++ mib[0] = CTL_KERN;
++ mib[1] = KERN_ARGMAX;
++
++ size = sizeof(argmax);
++ if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
++ return NULL;
++
++ /* Allocate space for the arguments. */
++ procargs = (char *)malloc(argmax);
++ if (procargs == NULL) {
++ PyErr_NoMemory();
++ return NULL;
++ }
++
++ /*
++ * Make a sysctl() call to get the raw argument space of the process.
++ */
++ mib[0] = CTL_KERN;
++ mib[1] = KERN_PROC;
++ mib[2] = KERN_PROC_ARGS;
++ mib[3] = pid;
++
++ size = argmax;
++ if (sysctl(mib, 4, procargs, &size, NULL, 0) == -1) {
++ free(procargs);
++ return NULL; /* Insufficient privileges */
++ }
++
++ // return string and set the length of arguments
++ *argsize = size;
++ return procargs;
++}
++
++
++/* returns the command line as a python list object */
++PyObject*
++psutil_get_arg_list(long pid)
++{
++ char *argstr = NULL;
++ int pos = 0;
++ size_t argsize = 0;
++ PyObject *retlist = Py_BuildValue("[]");
++ PyObject *item = NULL;
++
++ if (pid < 0) {
++ return retlist;
++ }
++
++ argstr = psutil_get_cmd_args(pid, &argsize);
++ if (argstr == NULL) {
++ goto error;
++ }
++
++ // args are returned as a flattened string with \0 separators between
++ // arguments add each string to the list then step forward to the next
++ // separator
++ if (argsize > 0) {
++ while(pos < argsize) {
++ item = Py_BuildValue("s", &argstr[pos]);
++ if (!item)
++ goto error;
++ if (PyList_Append(retlist, item))
++ goto error;
++ Py_DECREF(item);
++ pos = pos + strlen(&argstr[pos]) + 1;
++ }
++ }
++
++ free(argstr);
++ return retlist;
++
++error:
++ Py_XDECREF(item);
++ Py_DECREF(retlist);
++ if (argstr != NULL)
++ free(argstr);
++ return NULL;
++}
++
++
++/*
++ * Return 1 if PID exists in the current process list, else 0.
++ */
++int
++psutil_pid_exists(long pid)
++{
++ int kill_ret;
++ if (pid < 0) {
++ return 0;
++ }
++
++ // if kill returns success of permission denied we know it's a valid PID
++ kill_ret = kill(pid , 0);
++ if ((0 == kill_ret) || (EPERM == errno)) {
++ return 1;
++ }
++
++ // otherwise return 0 for PID not found
++ return 0;
++}
++
++
++/*
++ * Set exception to AccessDenied if pid exists else NoSuchProcess.
++ */
++int
++psutil_raise_ad_or_nsp(pid) {
++ if (psutil_pid_exists(pid) == 0) {
++ NoSuchProcess();
++ }
++ else {
++ AccessDenied();
++ }
++}
diff --git a/sysutils/py-psutil/patches/patch-psutil_arch_netbsd_process__info.h b/sysutils/py-psutil/patches/patch-psutil_arch_netbsd_process__info.h
new file mode 100644
index 00000000000..31b70053e49
--- /dev/null
+++ b/sysutils/py-psutil/patches/patch-psutil_arch_netbsd_process__info.h
@@ -0,0 +1,23 @@
+$NetBSD: patch-psutil_arch_netbsd_process__info.h,v 1.1 2013/10/12 13:32:36 wiz Exp $
+
+Port to NetBSD.
+
+--- psutil/arch/netbsd/process_info.h.orig 2013-10-12 13:19:29.000000000 +0000
++++ psutil/arch/netbsd/process_info.h
+@@ -0,0 +1,16 @@
++/*
++ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
++ * Use of this source code is governed by a BSD-style license that can be
++ * found in the LICENSE file.
++ *
++ * Helper functions related to fetching process information. Used by _psutil_netbsd
++ * module methods.
++ */
++
++#include <Python.h>
++
++int psutil_get_proc_list(struct kinfo_proc2 **procList, size_t *procCount);
++char *psutil_get_cmd_args(long pid, size_t *argsize);
++char *psutil_get_cmd_path(long pid, size_t *pathsize);
++int psutil_pid_exists(long pid);
++PyObject* psutil_get_arg_list(long pid);
diff --git a/sysutils/py-psutil/patches/patch-setup.py b/sysutils/py-psutil/patches/patch-setup.py
new file mode 100644
index 00000000000..549f828d931
--- /dev/null
+++ b/sysutils/py-psutil/patches/patch-setup.py
@@ -0,0 +1,22 @@
+$NetBSD: patch-setup.py,v 1.1 2013/10/12 13:32:36 wiz Exp $
+
+Port to NetBSD.
+
+--- setup.py.orig 2013-06-17 10:35:09.000000000 +0000
++++ setup.py
+@@ -108,6 +108,15 @@ elif sys.platform.startswith("freebsd"):
+ libraries=["devstat"],
+ ),
+ posix_extension]
++# NetBSD
++elif sys.platform.startswith("netbsd"):
++ extensions = [Extension('_psutil_netbsd',
++ sources = ['psutil/_psutil_netbsd.c',
++ 'psutil/_psutil_common.c',
++ 'psutil/arch/netbsd/process_info.c'],
++ libraries=[],
++ ),
++ posix_extension]
+ # Linux
+ elif sys.platform.startswith("linux"):
+ extensions = [Extension('_psutil_linux',
diff --git a/sysutils/py-psutil/patches/patch-test_test__psutil.py b/sysutils/py-psutil/patches/patch-test_test__psutil.py
new file mode 100644
index 00000000000..a5f6ad10e4b
--- /dev/null
+++ b/sysutils/py-psutil/patches/patch-test_test__psutil.py
@@ -0,0 +1,15 @@
+$NetBSD: patch-test_test__psutil.py,v 1.1 2013/10/12 13:32:36 wiz Exp $
+
+Port to NetBSD.
+
+--- test/test_psutil.py.orig 2013-07-10 14:02:21.000000000 +0000
++++ test/test_psutil.py
+@@ -62,7 +62,7 @@ POSIX = os.name == 'posix'
+ LINUX = sys.platform.startswith("linux")
+ WINDOWS = sys.platform.startswith("win32")
+ OSX = sys.platform.startswith("darwin")
+-BSD = sys.platform.startswith("freebsd")
++BSD = sys.platform.startswith("freebsd") or sys.platform.startswith("netbsd")
+ SUNOS = sys.platform.startswith("sunos")
+
+