summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2016-01-11 06:28:34 +0000
committerGiampaolo Rodola <g.rodola@gmail.com>2016-01-11 06:28:34 +0000
commitbcb0c84c9c1a173915a9d2d7aa1e8e930a3e0dfe (patch)
tree0f15fea4bb32f37b4a4bb6c87fe8c9b24637ef28
parentd7805262b79cac9c0540f37b1b47f5c36e6efeaa (diff)
parent116fc6a3436704abb71743a8dd2ef747666af6b8 (diff)
downloadpsutil-bcb0c84c9c1a173915a9d2d7aa1e8e930a3e0dfe.tar.gz
Merge branch '0-wiz-0-master' of github.com:giampaolo/psutil into 0-wiz-0-master
-rw-r--r--docs/index.rst14
-rw-r--r--psutil/__init__.py8
-rw-r--r--psutil/_common.py7
-rw-r--r--psutil/_psbsd.py132
-rw-r--r--psutil/_psutil_bsd.c206
-rw-r--r--psutil/_psutil_posix.c10
-rw-r--r--psutil/arch/bsd/netbsd.c649
-rw-r--r--psutil/arch/bsd/netbsd.h29
-rw-r--r--psutil/arch/bsd/netbsd_socks.c515
-rw-r--r--psutil/arch/bsd/netbsd_socks.h10
-rw-r--r--psutil/arch/bsd/openbsd.c11
-rw-r--r--setup.py13
-rw-r--r--test/_posix.py6
-rw-r--r--test/test_psutil.py7
14 files changed, 1498 insertions, 119 deletions
diff --git a/docs/index.rst b/docs/index.rst
index 3a5f8e62..68e3e5d0 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -8,6 +8,7 @@
Old 1.2.1 documentation is still available
`here <https://code.google.com/p/psutil/wiki/Documentation>`__.
.. versionchanged:: 3.3.0 added support for OpenBSD
+.. versionchanged:: 3.4.0 added support for NetBSD
psutil documentation
====================
@@ -206,7 +207,7 @@ Memory
* **sout**: the number of bytes the system has swapped out from disk
(cumulative)
- **sin** and **sout** on Windows are meaningless and are always set to ``0``.
+ **sin** and **sout** on Windows and OpenBSD are always set to ``0``.
See `examples/meminfo.py <https://github.com/giampaolo/psutil/blob/master/examples/meminfo.py>`__
script providing an example on how to convert bytes in a human readable form.
@@ -1043,7 +1044,7 @@ Process class
...]
>>>
- Availability: All platforms except OpenBSD.
+ Availability: All platforms except OpenBSD and NetBSD.
.. method:: children(recursive=False)
@@ -1302,13 +1303,16 @@ Constants
STATUS_DEAD
STATUS_WAKE_KILL
STATUS_WAKING
- STATUS_IDLE
- STATUS_LOCKED
- STATUS_WAITING
+ STATUS_IDLE (OSX, FreeBSD)
+ STATUS_LOCKED (FreeBSD)
+ STATUS_WAITING (FreeBSD)
+ STATUS_SUSPENDED (NetBSD)
A set of strings representing the status of a process.
Returned by :meth:`psutil.Process.status()`.
+ .. versionadded:: 3.4.0: STATUS_SUSPENDED (NetBSD)
+
.. _const-conn:
.. data:: CONN_ESTABLISHED
CONN_SYN_SENT
diff --git a/psutil/__init__.py b/psutil/__init__.py
index d825d892..f7b4b238 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -123,7 +123,9 @@ elif sys.platform.startswith("win32"):
elif sys.platform.startswith("darwin"):
from . import _psosx as _psplatform
-elif sys.platform.startswith("freebsd") or sys.platform.startswith("openbsd"):
+elif sys.platform.startswith("freebsd") or \
+ sys.platform.startswith("openbsd") or \
+ sys.platform.startswith("netbsd"):
from . import _psbsd as _psplatform
elif sys.platform.startswith("sunos"):
@@ -968,7 +970,9 @@ class Process(object):
except ZeroDivisionError:
return 0.0
- if not _OPENBSD:
+ if hasattr(_psplatform.Process, "memory_maps"):
+ # Available everywhere except OpenBSD and NetBSD.
+
def memory_maps(self, grouped=True):
"""Return process' mapped memory regions as a list of namedtuples
whose fields are variable depending on the platform.
diff --git a/psutil/_common.py b/psutil/_common.py
index 73ac07bc..3ff1cb88 100644
--- a/psutil/_common.py
+++ b/psutil/_common.py
@@ -43,9 +43,10 @@ STATUS_ZOMBIE = "zombie"
STATUS_DEAD = "dead"
STATUS_WAKE_KILL = "wake-kill"
STATUS_WAKING = "waking"
-STATUS_IDLE = "idle" # BSD
-STATUS_LOCKED = "locked" # BSD
-STATUS_WAITING = "waiting" # BSD
+STATUS_IDLE = "idle" # FreeBSD, OSX
+STATUS_LOCKED = "locked" # FreeBSD
+STATUS_WAITING = "waiting" # FreeBSD
+STATUS_SUSPENDED = "suspended" # NetBSD
CONN_ESTABLISHED = "ESTABLISHED"
CONN_SYN_SENT = "SYN_SENT"
diff --git a/psutil/_psbsd.py b/psutil/_psbsd.py
index a772e264..c73f7c8b 100644
--- a/psutil/_psbsd.py
+++ b/psutil/_psbsd.py
@@ -28,6 +28,7 @@ __extra__all__ = []
FREEBSD = sys.platform.startswith("freebsd")
OPENBSD = sys.platform.startswith("openbsd")
+NETBSD = sys.platform.startswith("netbsd")
if FREEBSD:
PROC_STATUSES = {
@@ -39,7 +40,7 @@ if FREEBSD:
cext.SWAIT: _common.STATUS_WAITING,
cext.SLOCK: _common.STATUS_LOCKED,
}
-elif OPENBSD:
+elif OPENBSD or NETBSD:
PROC_STATUSES = {
cext.SIDL: _common.STATUS_IDLE,
cext.SSLEEP: _common.STATUS_SLEEPING,
@@ -50,6 +51,7 @@ elif OPENBSD:
# psutil.STATUS_DEAD. SDEAD really means STATUS_ZOMBIE.
# cext.SZOMB: _common.STATUS_ZOMBIE,
cext.SDEAD: _common.STATUS_ZOMBIE,
+ cext.SZOMB: _common.STATUS_ZOMBIE,
# From http://www.eecs.harvard.edu/~margo/cs161/videos/proc.h.txt
# OpenBSD has SRUN and SONPROC: SRUN indicates that a process
# is runnable but *not* yet running, i.e. is on a run queue.
@@ -61,6 +63,9 @@ elif OPENBSD:
cext.SONPROC: _common.STATUS_RUNNING,
}
+if NETBSD:
+ PROC_STATUSES[cext.SSUSPENDED] = _common.STATUS_SUSPENDED
+
TCP_STATUSES = {
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
@@ -76,7 +81,10 @@ TCP_STATUSES = {
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
}
-PAGESIZE = os.sysconf("SC_PAGE_SIZE")
+if NETBSD:
+ PAGESIZE = os.sysconf("SC_PAGESIZE")
+else:
+ PAGESIZE = os.sysconf("SC_PAGE_SIZE")
AF_LINK = cext_posix.AF_LINK
# extend base mem ntuple with BSD-specific memory metrics
@@ -156,9 +164,9 @@ def cpu_count_logical():
return cext.cpu_count_logical()
-if OPENBSD:
+if OPENBSD or NETBSD:
def cpu_count_physical():
- # OpenBSD does not implement this.
+ # OpenBSD and NetBSD do not implement this.
return 1 if cpu_count_logical() == 1 else None
else:
def cpu_count_physical():
@@ -273,7 +281,7 @@ def net_if_stats():
return ret
-if OPENBSD:
+if OPENBSD or NETBSD:
def pid_exists(pid):
exists = _psposix.pid_exists(pid)
if not exists:
@@ -333,7 +341,7 @@ class Process(object):
@wrap_exceptions
def exe(self):
- if FREEBSD:
+ if FREEBSD or NETBSD:
return cext.proc_exe(self.pid)
else:
# exe cannot be determined on OpenBSD; references:
@@ -351,7 +359,19 @@ class Process(object):
def cmdline(self):
if OPENBSD and self.pid == 0:
return None # ...else it crashes
- return cext.proc_cmdline(self.pid)
+ elif NETBSD:
+ try:
+ return cext.proc_cmdline(self.pid)
+ except OSError as err:
+ if err.errno == errno.EINVAL:
+ if not pid_exists(self.pid):
+ raise NoSuchProcess(self.pid, self._name)
+ else:
+ raise ZombieProcess(self.pid, self._name, self._ppid)
+ else:
+ raise
+ else:
+ return cext.proc_cmdline(self.pid)
@wrap_exceptions
def terminal(self):
@@ -426,6 +446,28 @@ class Process(object):
if kind not in conn_tmap:
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in conn_tmap])))
+
+ if NETBSD:
+ families, types = conn_tmap[kind]
+ ret = set()
+ rawlist = cext.proc_connections(self.pid)
+ for item in rawlist:
+ fd, fam, type, laddr, raddr, status = item
+ if fam in families and type in types:
+ try:
+ status = TCP_STATUSES[status]
+ except KeyError:
+ status = TCP_STATUSES[cext.PSUTIL_CONN_NONE]
+ fam = sockfam_to_enum(fam)
+ type = socktype_to_enum(type)
+ nt = _common.pconn(fd, fam, type, laddr, raddr, status)
+ ret.add(nt)
+ # On NetBSD the underlying C function does not raise NSP
+ # in case the process is gone (and the returned list may
+ # incomplete).
+ self.name() # raise NSP if the process disappeared on us
+ return list(ret)
+
families, types = conn_tmap[kind]
rawlist = cext.proc_connections(self.pid, families, types)
ret = []
@@ -464,59 +506,80 @@ class Process(object):
@wrap_exceptions
def status(self):
code = cext.proc_status(self.pid)
- if code in PROC_STATUSES:
- return PROC_STATUSES[code]
- # XXX is this legit? will we even ever get here?
- return "?"
+ # XXX is '?' legit? (we're not supposed to return it anyway)
+ return PROC_STATUSES.get(code, '?')
@wrap_exceptions
def io_counters(self):
rc, wc, rb, wb = cext.proc_io_counters(self.pid)
return _common.pio(rc, wc, rb, wb)
+ @wrap_exceptions
+ def cwd(self):
+ """Return process current working directory."""
+ # sometimes we get an empty string, in which case we turn
+ # it into None
+ if OPENBSD and self.pid == 0:
+ return None # ...else it would raise EINVAL
+ elif NETBSD:
+ try:
+ return os.readlink("/proc/%s/cwd" % self.pid)
+ except OSError as err:
+ if err.errno == errno.ENOENT:
+ if not pid_exists(self.pid):
+ raise NoSuchProcess(self.pid, self._name)
+ else:
+ raise ZombieProcess(
+ self.pid, self._name, self._ppid)
+ else:
+ raise
+ elif hasattr(cext, 'proc_open_files'):
+ # FreeBSD < 8 does not support functions based on
+ # kinfo_getfile() and kinfo_getvmmap()
+ return cext.proc_cwd(self.pid) or None
+ else:
+ raise NotImplementedError(
+ "supported only starting from FreeBSD 8" if
+ FREEBSD else "")
+
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')
+ def _not_implemented(self):
+ raise NotImplementedError
+
# FreeBSD < 8 does not support functions based on kinfo_getfile()
# and kinfo_getvmmap()
if hasattr(cext, 'proc_open_files'):
-
@wrap_exceptions
def open_files(self):
"""Return files opened by process as a list of namedtuples."""
rawlist = cext.proc_open_files(self.pid)
return [_common.popenfile(path, fd) for path, fd in rawlist]
+ else:
+ open_files = _not_implemented
- @wrap_exceptions
- def cwd(self):
- """Return process current working directory."""
- # sometimes we get an empty string, in which case we turn
- # it into None
- if OPENBSD and self.pid == 0:
- return None # ...else raises EINVAL
- return cext.proc_cwd(self.pid) or None
-
- @wrap_exceptions
- def memory_maps(self):
- return cext.proc_memory_maps(self.pid)
-
+ # FreeBSD < 8 does not support functions based on kinfo_getfile()
+ # and kinfo_getvmmap()
+ if hasattr(cext, 'proc_num_fds'):
@wrap_exceptions
def num_fds(self):
"""Return the number of file descriptors opened by this process."""
- return cext.proc_num_fds(self.pid)
-
+ ret = cext.proc_num_fds(self.pid)
+ if NETBSD:
+ # On NetBSD the underlying C function does not raise NSP
+ # in case the process is gone.
+ self.name() # raise NSP if the process disappeared on us
+ return ret
else:
- def _not_implemented(self):
- raise NotImplementedError("supported only starting from FreeBSD 8")
-
- open_files = _not_implemented
- proc_cwd = _not_implemented
- memory_maps = _not_implemented
num_fds = _not_implemented
+ # --- FreeBSD only APIs
+
if FREEBSD:
+
@wrap_exceptions
def cpu_affinity_get(self):
return cext.proc_cpu_affinity_get(self.pid)
@@ -545,3 +608,6 @@ class Process(object):
"invalid CPU #%i (choose between %s)" % (
cpu, allcpus))
raise
+
+ def memory_maps(self):
+ return cext.proc_memory_maps(self.pid)
diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c
index 278504f8..5d22d881 100644
--- a/psutil/_psutil_bsd.c
+++ b/psutil/_psutil_bsd.c
@@ -9,12 +9,15 @@
* OpenBSD references:
* - OpenBSD source code: http://anoncvs.spacehopper.org/openbsd-src/
*
- * OpenBSD: missing compared to FreeBSD implementation:
+ * OpenBSD / NetBSD: missing APIs compared to FreeBSD implementation:
* - psutil.net_connections()
* - psutil.Process.get/set_cpu_affinity() (not supported natively)
* - psutil.Process.memory_maps()
*/
+#if defined(__NetBSD__)
+#define _KMEMUSER
+#endif
#include <Python.h>
#include <assert.h>
@@ -42,6 +45,7 @@
#include <netinet/in_pcb.h>
#include <netinet/tcp.h>
#include <netinet/tcp_timer.h>
+#include <netinet/ip_var.h>
#include <netinet/tcp_var.h> // for struct xtcpcb
#include <netinet/tcp_fsm.h> // for TCP connection states
#include <arpa/inet.h> // for inet_ntop()
@@ -63,6 +67,9 @@
#include "arch/bsd/freebsd_socks.h"
#elif __OpenBSD__
#include "arch/bsd/openbsd.h"
+#elif __NetBSD__
+ #include "arch/bsd/netbsd.h"
+ #include "arch/bsd/netbsd_socks.h"
#endif
#ifdef __FreeBSD__
@@ -85,6 +92,16 @@
#include <sys/sched.h> // for CPUSTATES & CP_*
#endif
+#if defined(__NetBSD__)
+ #include <utmpx.h>
+ #include <sys/vnode.h> // for VREG
+ #include <sys/sched.h> // for CPUSTATES & CP_*
+ #include <machine/vmparam.h> // for PAGE_SHIFT
+#define _KERNEL
+ #include <uvm/uvm_extern.h>
+#undef _KERNEL
+#endif
+
// convert a timeval struct to a double
#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
@@ -95,7 +112,7 @@
(uint32_t) (bt.frac >> 32) ) >> 32 ) / 1000000)
#endif
-#ifdef __OpenBSD__
+#if defined(__OpenBSD__) || defined (__NetBSD__)
#define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0)
#endif
@@ -125,7 +142,7 @@ psutil_pids(PyObject *self, PyObject *args) {
for (idx = 0; idx < num_processes; idx++) {
#ifdef __FreeBSD__
py_pid = Py_BuildValue("i", proclist->ki_pid);
-#elif __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
py_pid = Py_BuildValue("i", proclist->p_pid);
#endif
if (!py_pid)
@@ -174,14 +191,14 @@ psutil_boot_time(PyObject *self, PyObject *args) {
static PyObject *
psutil_proc_name(PyObject *self, PyObject *args) {
long pid;
- struct kinfo_proc kp;
+ kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
#ifdef __FreeBSD__
return Py_BuildValue("s", kp.ki_comm);
-#elif __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
return Py_BuildValue("s", kp.p_comm);
#endif
}
@@ -213,14 +230,14 @@ psutil_proc_cmdline(PyObject *self, PyObject *args) {
static PyObject *
psutil_proc_ppid(PyObject *self, PyObject *args) {
long pid;
- struct kinfo_proc kp;
+ kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
#ifdef __FreeBSD__
return Py_BuildValue("l", (long)kp.ki_ppid);
-#elif __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
return Py_BuildValue("l", (long)kp.p_ppid);
#endif
}
@@ -232,14 +249,14 @@ psutil_proc_ppid(PyObject *self, PyObject *args) {
static PyObject *
psutil_proc_status(PyObject *self, PyObject *args) {
long pid;
- struct kinfo_proc kp;
+ kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
#ifdef __FreeBSD__
return Py_BuildValue("i", (int)kp.ki_stat);
-#elif __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
return Py_BuildValue("i", (int)kp.p_stat);
#endif
}
@@ -252,7 +269,7 @@ psutil_proc_status(PyObject *self, PyObject *args) {
static PyObject *
psutil_proc_uids(PyObject *self, PyObject *args) {
long pid;
- struct kinfo_proc kp;
+ kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
@@ -262,7 +279,7 @@ psutil_proc_uids(PyObject *self, PyObject *args) {
(long)kp.ki_ruid,
(long)kp.ki_uid,
(long)kp.ki_svuid);
-#elif __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
(long)kp.p_ruid,
(long)kp.p_uid,
(long)kp.p_svuid);
@@ -277,7 +294,7 @@ psutil_proc_uids(PyObject *self, PyObject *args) {
static PyObject *
psutil_proc_gids(PyObject *self, PyObject *args) {
long pid;
- struct kinfo_proc kp;
+ kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
@@ -287,7 +304,7 @@ psutil_proc_gids(PyObject *self, PyObject *args) {
(long)kp.ki_rgid,
(long)kp.ki_groups[0],
(long)kp.ki_svuid);
-#elif __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
(long)kp.p_rgid,
(long)kp.p_groups[0],
(long)kp.p_svuid);
@@ -302,14 +319,14 @@ psutil_proc_gids(PyObject *self, PyObject *args) {
static PyObject *
psutil_proc_tty_nr(PyObject *self, PyObject *args) {
long pid;
- struct kinfo_proc kp;
+ kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
#ifdef __FreeBSD__
return Py_BuildValue("i", kp.ki_tdev);
-#elif __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
return Py_BuildValue("i", kp.p_tdev);
#endif
}
@@ -321,7 +338,7 @@ psutil_proc_tty_nr(PyObject *self, PyObject *args) {
static PyObject *
psutil_proc_num_ctx_switches(PyObject *self, PyObject *args) {
long pid;
- struct kinfo_proc kp;
+ kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
@@ -330,7 +347,7 @@ psutil_proc_num_ctx_switches(PyObject *self, PyObject *args) {
#ifdef __FreeBSD__
kp.ki_rusage.ru_nvcsw,
kp.ki_rusage.ru_nivcsw);
-#elif __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
kp.p_uru_nvcsw,
kp.p_uru_nivcsw);
#endif
@@ -344,7 +361,7 @@ static PyObject *
psutil_proc_cpu_times(PyObject *self, PyObject *args) {
long pid;
double user_t, sys_t;
- struct kinfo_proc kp;
+ kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
@@ -353,7 +370,7 @@ psutil_proc_cpu_times(PyObject *self, PyObject *args) {
#ifdef __FreeBSD__
user_t = PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_utime);
sys_t = PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_stime);
-#elif __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
user_t = PSUTIL_KPT2DOUBLE(kp.p_uutime);
sys_t = PSUTIL_KPT2DOUBLE(kp.p_ustime);
#endif
@@ -389,14 +406,14 @@ psutil_cpu_count_logical(PyObject *self, PyObject *args) {
static PyObject *
psutil_proc_create_time(PyObject *self, PyObject *args) {
long pid;
- struct kinfo_proc kp;
+ kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
#ifdef __FreeBSD__
return Py_BuildValue("d", PSUTIL_TV2DOUBLE(kp.ki_start));
-#elif __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
return Py_BuildValue("d", PSUTIL_KPT2DOUBLE(kp.p_ustart));
#endif
}
@@ -409,7 +426,7 @@ psutil_proc_create_time(PyObject *self, PyObject *args) {
static PyObject *
psutil_proc_io_counters(PyObject *self, PyObject *args) {
long pid;
- struct kinfo_proc kp;
+ kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
@@ -419,7 +436,7 @@ psutil_proc_io_counters(PyObject *self, PyObject *args) {
#ifdef __FreeBSD__
kp.ki_rusage.ru_inblock,
kp.ki_rusage.ru_oublock,
-#elif __OpenBSD__
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
kp.p_uru_inblock,
kp.p_uru_oublock,
#endif
@@ -428,8 +445,8 @@ psutil_proc_io_counters(PyObject *self, PyObject *args) {
}
-#ifdef __OpenBSD__
-#define ptoa(x) ((paddr_t)(x) << PAGE_SHIFT)
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+ #define ptoa(x) ((paddr_t)(x) << PAGE_SHIFT)
#endif
/*
@@ -438,28 +455,37 @@ psutil_proc_io_counters(PyObject *self, PyObject *args) {
static PyObject *
psutil_proc_memory_info(PyObject *self, PyObject *args) {
long pid;
- struct kinfo_proc kp;
+ kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
+
return Py_BuildValue(
"(lllll)",
#ifdef __FreeBSD__
- ptoa(kp.ki_rssize), // rss
- (long)kp.ki_size, // vms
- ptoa(kp.ki_tsize), // text
- ptoa(kp.ki_dsize), // data
- ptoa(kp.ki_ssize)); // stack
-#elif __OpenBSD__
- ptoa(kp.p_vm_rssize), // rss
- // vms, this is how ps does it, see:
+ (long) ptoa(kp.ki_rssize), // rss
+ (long) kp.ki_size, // vms
+ (long) ptoa(kp.ki_tsize), // text
+ (long) ptoa(kp.ki_dsize), // data
+ (long) ptoa(kp.ki_ssize) // stack
+#else
+ (long) ptoa(kp.p_vm_rssize), // rss
+ #ifdef __OpenBSD__
+ // VMS, this is how ps determines it on OpenBSD:
// http://anoncvs.spacehopper.org/openbsd-src/tree/bin/ps/print.c#n461
- ptoa(kp.p_vm_dsize + kp.p_vm_ssize + kp.p_vm_tsize), // vms
- ptoa(kp.p_vm_tsize), // text
- ptoa(kp.p_vm_dsize), // data
- ptoa(kp.p_vm_ssize)); // stack
+ (long) ptoa(kp.p_vm_dsize + kp.p_vm_ssize + kp.p_vm_tsize), // vms
+ #elif __NetBSD__
+ // VMS, this is how top determines it on NetBSD:
+ // ftp://ftp.iij.ad.jp/pub/NetBSD/NetBSD-release-6/src/external/bsd/
+ // top/dist/machine/m_netbsd.c
+ (long) ptoa(kp.p_vm_msize), // vms
+ #endif
+ (long) ptoa(kp.p_vm_tsize), // text
+ (long) ptoa(kp.p_vm_dsize), // data
+ (long) ptoa(kp.p_vm_ssize) // stack
#endif
+ );
}
@@ -468,11 +494,15 @@ psutil_proc_memory_info(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_cpu_times(PyObject *self, PyObject *args) {
+#if defined(__NetBSD__)
+ u_int64_t cpu_time[CPUSTATES];
+#else
long cpu_time[CPUSTATES];
+#endif
size_t size = sizeof(cpu_time);
int ret;
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__NetBSD__)
ret = sysctlbyname("kern.cp_time", &cpu_time, &size, NULL, 0);
#elif __OpenBSD__
int mib[] = {CTL_KERN, KERN_CPTIME};
@@ -499,14 +529,14 @@ psutil_cpu_times(PyObject *self, PyObject *args) {
* utility has the same problem see:
* https://github.com/giampaolo/psutil/issues/595
*/
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 || __OpenBSD__
+#if (defined(__FreeBSD_version) && __FreeBSD_version >= 800000) || __OpenBSD__ || defined(__NetBSD__)
static PyObject *
psutil_proc_open_files(PyObject *self, PyObject *args) {
long pid;
int i, cnt;
struct kinfo_file *freep = NULL;
struct kinfo_file *kif;
- struct kinfo_proc kipp;
+ kinfo_proc kipp;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
@@ -530,11 +560,16 @@ psutil_proc_open_files(PyObject *self, PyObject *args) {
(kif->kf_vnode_type == KF_VTYPE_VREG))
{
py_tuple = Py_BuildValue("(si)", kif->kf_path, kif->kf_fd);
-#else
+#elif defined(__OpenBSD__)
if ((kif->f_type == DTYPE_VNODE) &&
(kif->v_type == VREG))
{
py_tuple = Py_BuildValue("(si)", "", kif->fd_fd);
+#elif defined(__NetBSD__)
+ if ((kif->ki_ftype == DTYPE_VNODE) &&
+ (kif->ki_vtype == VREG))
+ {
+ py_tuple = Py_BuildValue("(si)", "", kif->ki_fd);
#endif
if (py_tuple == NULL)
goto error;
@@ -567,7 +602,11 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
long len;
uint64_t flags;
char opts[200];
+#if defined(__NetBSD__)
+ struct statvfs *fs = NULL;
+#else
struct statfs *fs = NULL;
+#endif
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
@@ -576,7 +615,11 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
// get the number of mount points
Py_BEGIN_ALLOW_THREADS
+#if defined(__NetBSD__)
+ num = getvfsstat(NULL, 0, MNT_NOWAIT);
+#else
num = getfsstat(NULL, 0, MNT_NOWAIT);
+#endif
Py_END_ALLOW_THREADS
if (num == -1) {
PyErr_SetFromErrno(PyExc_OSError);
@@ -591,7 +634,11 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
}
Py_BEGIN_ALLOW_THREADS
+#if defined(__NetBSD__)
+ num = getvfsstat(fs, len, MNT_NOWAIT);
+#else
num = getfsstat(fs, len, MNT_NOWAIT);
+#endif
Py_END_ALLOW_THREADS
if (num == -1) {
PyErr_SetFromErrno(PyExc_OSError);
@@ -601,24 +648,32 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
for (i = 0; i < num; i++) {
py_tuple = NULL;
opts[0] = 0;
+#if defined(__NetBSD__)
+ flags = fs[i].f_flag;
+#else
flags = fs[i].f_flags;
+#endif
// see sys/mount.h
if (flags & MNT_RDONLY)
strlcat(opts, "ro", sizeof(opts));
else
strlcat(opts, "rw", sizeof(opts));
-#ifdef __FreeBSD__
if (flags & MNT_SYNCHRONOUS)
strlcat(opts, ",sync", sizeof(opts));
if (flags & MNT_NOEXEC)
strlcat(opts, ",noexec", sizeof(opts));
if (flags & MNT_NOSUID)
strlcat(opts, ",nosuid", sizeof(opts));
- if (flags & MNT_UNION)
- strlcat(opts, ",union", sizeof(opts));
if (flags & MNT_ASYNC)
strlcat(opts, ",async", sizeof(opts));
+ if (flags & MNT_NOATIME)
+ strlcat(opts, ",noatime", sizeof(opts));
+ if (flags & MNT_SOFTDEP)
+ strlcat(opts, ",softdep", sizeof(opts));
+#ifdef __FreeBSD__
+ if (flags & MNT_UNION)
+ strlcat(opts, ",union", sizeof(opts));
if (flags & MNT_SUIDDIR)
strlcat(opts, ",suiddir", sizeof(opts));
if (flags & MNT_SOFTDEP)
@@ -631,27 +686,33 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
strlcat(opts, ",multilabel", sizeof(opts));
if (flags & MNT_ACLS)
strlcat(opts, ",acls", sizeof(opts));
- if (flags & MNT_NOATIME)
- strlcat(opts, ",noatime", sizeof(opts));
if (flags & MNT_NOCLUSTERR)
strlcat(opts, ",noclusterr", sizeof(opts));
if (flags & MNT_NOCLUSTERW)
strlcat(opts, ",noclusterw", sizeof(opts));
if (flags & MNT_NFS4ACLS)
strlcat(opts, ",nfs4acls", sizeof(opts));
-#elif __OpenBSD__
- if (flags & MNT_SYNCHRONOUS)
- strlcat(opts, ",sync", sizeof(opts));
- if (flags & MNT_NOEXEC)
- strlcat(opts, ",noexec", sizeof(opts));
- if (flags & MNT_NOSUID)
- strlcat(opts, ",nosuid", sizeof(opts));
- if (flags & MNT_ASYNC)
- strlcat(opts, ",async", sizeof(opts));
- if (flags & MNT_SOFTDEP)
- strlcat(opts, ",softdep", sizeof(opts));
- if (flags & MNT_NOATIME)
- strlcat(opts, ",noatime", sizeof(opts));
+#elif __NetBSD__
+ if (flags & MNT_NODEV)
+ strlcat(opts, ",nodev", sizeof(opts));
+ if (flags & MNT_UNION)
+ strlcat(opts, ",union", sizeof(opts));
+ if (flags & MNT_NOCOREDUMP)
+ strlcat(opts, ",nocoredump", sizeof(opts));
+ if (flags & MNT_RELATIME)
+ strlcat(opts, ",relatime", sizeof(opts));
+ if (flags & MNT_IGNORE)
+ strlcat(opts, ",ignore", sizeof(opts));
+ if (flags & MNT_DISCARD)
+ strlcat(opts, ",discard", sizeof(opts));
+ if (flags & MNT_EXTATTR)
+ strlcat(opts, ",extattr", sizeof(opts));
+ if (flags & MNT_LOG)
+ strlcat(opts, ",log", sizeof(opts));
+ if (flags & MNT_SYMPERM)
+ strlcat(opts, ",symperm", sizeof(opts));
+ if (flags & MNT_NODEVMTIME)
+ strlcat(opts, ",nodevmtime", sizeof(opts));
#endif
py_tuple = Py_BuildValue("(ssss)",
fs[i].f_mntfromname, // device
@@ -778,7 +839,7 @@ psutil_users(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;
-#if __FreeBSD_version < 900000 || __OpenBSD__
+#if (defined(__FreeBSD_version) && (__FreeBSD_version < 900000)) || __OpenBSD__
struct utmp ut;
FILE *fp;
@@ -812,6 +873,7 @@ psutil_users(PyObject *self, PyObject *args) {
#else
struct utmpx *utx;
+ setutxent();
while ((utx = getutxent()) != NULL) {
if (utx->ut_type != USER_PROCESS)
continue;
@@ -881,22 +943,25 @@ PsutilMethods[] = {
"Return process IO counters"},
{"proc_tty_nr", psutil_proc_tty_nr, METH_VARARGS,
"Return process tty (terminal) number"},
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
{"proc_cwd", psutil_proc_cwd, METH_VARARGS,
"Return process current working directory."},
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 || __OpenBSD__
+#endif
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 || __OpenBSD__ || defined(__NetBSD__)
{"proc_num_fds", psutil_proc_num_fds, METH_VARARGS,
"Return the number of file descriptors opened by this process"},
#endif
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 || __OpenBSD__
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 || __OpenBSD__ || defined(__NetBSD__)
{"proc_open_files", psutil_proc_open_files, METH_VARARGS,
"Return files opened by process as a list of (path, fd) tuples"},
#endif
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__NetBSD__)
{"proc_exe", psutil_proc_exe, METH_VARARGS,
"Return process pathname executable"},
{"proc_num_threads", psutil_proc_num_threads, METH_VARARGS,
"Return number of threads used by process"},
+#if defined(__FreeBSD__)
{"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS,
"Return a list of tuples for every process's memory map"},
{"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS,
@@ -906,6 +971,7 @@ PsutilMethods[] = {
{"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS,
"Return an XML string to determine the number physical CPUs."},
#endif
+#endif
// --- system-related functions
@@ -932,7 +998,7 @@ PsutilMethods[] = {
"Return a Python dict of tuples for disk I/O information"},
{"users", psutil_users, METH_VARARGS,
"Return currently connected users as a list of tuples"},
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__NetBSD__)
{"net_connections", psutil_net_connections, METH_VARARGS,
"Return system-wide open connections."},
#endif
@@ -1010,6 +1076,16 @@ void init_psutil_bsd(void)
PyModule_AddIntConstant(module, "SZOMB", SZOMB); // unused
PyModule_AddIntConstant(module, "SDEAD", SDEAD);
PyModule_AddIntConstant(module, "SONPROC", SONPROC);
+#elif defined(__NetBSD__)
+ PyModule_AddIntConstant(module, "SIDL", LSIDL);
+ PyModule_AddIntConstant(module, "SRUN", LSRUN);
+ PyModule_AddIntConstant(module, "SSLEEP", LSSLEEP);
+ PyModule_AddIntConstant(module, "SSTOP", LSSTOP);
+ PyModule_AddIntConstant(module, "SZOMB", LSZOMB);
+ PyModule_AddIntConstant(module, "SDEAD", LSDEAD);
+ PyModule_AddIntConstant(module, "SONPROC", LSONPROC);
+ // unique to NetBSD
+ PyModule_AddIntConstant(module, "SSUSPENDED", LSSUSPENDED);
#endif
// connection status constants
diff --git a/psutil/_psutil_posix.c b/psutil/_psutil_posix.c
index 07404206..55bfec9a 100644
--- a/psutil/_psutil_posix.c
+++ b/psutil/_psutil_posix.c
@@ -26,7 +26,7 @@
#include <linux/if_packet.h>
#endif // end linux
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__)
#include <netdb.h>
#include <netinet/in.h>
#include <net/if_dl.h>
@@ -120,7 +120,7 @@ psutil_convert_ipaddr(struct sockaddr *addr, int family) {
data = (const char *)lladdr->sll_addr;
}
#endif
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__)
else if (addr->sa_family == AF_LINK) {
// Note: prior to Python 3.4 socket module does not expose
// AF_LINK so we'll do.
@@ -250,7 +250,7 @@ error:
* net_if_stats() implementation. This is here because it is common
* to both OSX and FreeBSD and I didn't know where else to put it.
*/
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__)
#include <sys/sockio.h>
#include <net/if_media.h>
@@ -478,7 +478,7 @@ PsutilMethods[] = {
"Set process priority"},
{"net_if_addrs", psutil_net_if_addrs, METH_VARARGS,
"Retrieve NICs information"},
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__)
{"net_if_stats", psutil_net_if_stats, METH_VARARGS,
"Return NIC stats."},
#endif
@@ -537,7 +537,7 @@ void init_psutil_posix(void)
PyObject *module = Py_InitModule("_psutil_posix", PsutilMethods);
#endif
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__sun)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__sun) || defined(__NetBSD__)
PyModule_AddIntConstant(module, "AF_LINK", AF_LINK);
#endif
diff --git a/psutil/arch/bsd/netbsd.c b/psutil/arch/bsd/netbsd.c
new file mode 100644
index 00000000..a8c0364c
--- /dev/null
+++ b/psutil/arch/bsd/netbsd.c
@@ -0,0 +1,649 @@
+/*
+ * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil.
+ * All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Platform-specific module methods for NetBSD.
+ */
+
+#if defined(__NetBSD__)
+#define _KMEMUSER
+#endif
+
+#include <Python.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/proc.h>
+#include <sys/swap.h> // for swap_mem
+#include <signal.h>
+#include <kvm.h>
+// connection stuff
+#include <netdb.h> // for NI_MAXHOST
+#include <sys/socket.h>
+#include <sys/sched.h> // for CPUSTATES & CP_*
+#define _KERNEL // for DTYPE_*
+#include <sys/file.h>
+#undef _KERNEL
+#include <sys/disk.h> // struct diskstats
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+#include "netbsd.h"
+#include "netbsd_socks.h"
+#include "../../_psutil_common.h"
+
+#define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0)
+#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
+
+
+// ============================================================================
+// Utility functions
+// ============================================================================
+
+
+int
+psutil_raise_ad_or_nsp(long pid) {
+ // Set exception to AccessDenied if pid exists else NoSuchProcess.
+ if (psutil_pid_exists(pid) == 0)
+ NoSuchProcess();
+ else
+ AccessDenied();
+}
+
+
+int
+psutil_kinfo_proc(pid_t pid, kinfo_proc *proc) {
+ // Fills a kinfo_proc struct based on process pid.
+ int ret;
+ int mib[6];
+ size_t size = sizeof(kinfo_proc);
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC2;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+ mib[4] = size;
+ mib[5] = 1;
+
+ ret = sysctl((int*)mib, 6, proc, &size, NULL, 0);
+ if (ret == -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;
+}
+
+
+struct kinfo_file *
+kinfo_getfile(pid_t pid, int* cnt) {
+ // Mimic's FreeBSD kinfo_file call, taking a pid and a ptr to an
+ // int as arg and returns an array with cnt struct kinfo_file.
+ int mib[6];
+ size_t len;
+ struct kinfo_file* kf;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_FILE2;
+ mib[2] = KERN_FILE_BYPID;
+ mib[3] = (int) pid;
+ mib[4] = sizeof(struct kinfo_file);
+ mib[5] = 0;
+
+ // get the size of what would be returned
+ if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+ if ((kf = malloc(len)) == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ mib[5] = (int)(len / sizeof(struct kinfo_file));
+ if (sysctl(mib, 6, kf, &len, NULL, 0) < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ *cnt = (int)(len / sizeof(struct kinfo_file));
+ return kf;
+}
+
+
+int
+psutil_pid_exists(pid_t pid) {
+ // Return 1 if PID exists in the current process list, else 0, -1
+ // on error.
+ // TODO: this should live in _psutil_posix.c but for some reason if I
+ // move it there I get a "include undefined symbol" error.
+ int ret;
+ if (pid < 0)
+ return 0;
+ ret = kill(pid , 0);
+ if (ret == 0)
+ return 1;
+ else {
+ if (ret == ESRCH)
+ return 0;
+ else if (ret == EPERM)
+ return 1;
+ else {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ }
+}
+
+PyObject *
+psutil_proc_exe(PyObject *self, PyObject *args) {
+#if __NetBSD_Version__ >= 799000000
+ pid_t pid;
+ char pathname[MAXPATHLEN];
+ int error;
+ int mib[4];
+ int ret;
+ size_t size;
+
+ if (! PyArg_ParseTuple(args, "l", &pid))
+ return NULL;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC_ARGS;
+ mib[2] = pid;
+ mib[3] = KERN_PROC_PATHNAME;
+
+ size = sizeof(pathname);
+ error = sysctl(mib, 4, NULL, &size, NULL, 0);
+ if (error == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ error = sysctl(mib, 4, pathname, &size, NULL, 0);
+ if (error == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+ if (size == 0 || strlen(pathname) == 0) {
+ ret = psutil_pid_exists(pid);
+ if (ret == -1)
+ return NULL;
+ else if (ret == 0)
+ return NoSuchProcess();
+ else
+ strcpy(pathname, "");
+ }
+ return Py_BuildValue("s", pathname);
+#else
+ return Py_BuildValue("s", "");
+#endif
+}
+
+PyObject *
+psutil_proc_num_threads(PyObject *self, PyObject *args) {
+ // Return number of threads used by process as a Python integer.
+ long pid;
+ kinfo_proc kp;
+ if (! PyArg_ParseTuple(args, "l", &pid))
+ return NULL;
+ if (psutil_kinfo_proc(pid, &kp) == -1)
+ return NULL;
+ return Py_BuildValue("l", (long)kp.p_nlwps);
+}
+
+PyObject *
+psutil_proc_threads(PyObject *self, PyObject *args) {
+ pid_t pid;
+ int mib[5];
+ int i, nlwps;
+ ssize_t st;
+ size_t size;
+ struct kinfo_lwp *kl = NULL;
+ PyObject *py_retlist = PyList_New(0);
+ PyObject *py_tuple = NULL;
+
+ if (py_retlist == NULL)
+ return NULL;
+ if (! PyArg_ParseTuple(args, "l", &pid))
+ goto error;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_LWP;
+ mib[2] = pid;
+ mib[3] = sizeof(struct kinfo_lwp);
+ mib[4] = 0;
+
+ st = sysctl(mib, 5, NULL, &size, NULL, 0);
+ if (st == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto error;
+ }
+ if (size == 0) {
+ NoSuchProcess();
+ goto error;
+ }
+
+ mib[4] = size / sizeof(size_t);
+ kl = malloc(size);
+ if (kl == NULL) {
+ PyErr_NoMemory();
+ goto error;
+ }
+
+ st = sysctl(mib, 5, kl, &size, NULL, 0);
+ if (st == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto error;
+ }
+ if (size == 0) {
+ NoSuchProcess();
+ goto error;
+ }
+
+ nlwps = (int)(size / sizeof(struct kinfo_lwp));
+ for (i = 0; i < nlwps; i++) {
+ py_tuple = Py_BuildValue("idd",
+ (&kl[i])->l_lid,
+ PSUTIL_KPT2DOUBLE((&kl[i])->l_rtime),
+ PSUTIL_KPT2DOUBLE((&kl[i])->l_rtime));
+ if (py_tuple == NULL)
+ goto error;
+ if (PyList_Append(py_retlist, py_tuple))
+ goto error;
+ Py_DECREF(py_tuple);
+ }
+ free(kl);
+ return py_retlist;
+
+error:
+ Py_XDECREF(py_tuple);
+ Py_DECREF(py_retlist);
+ if (kl != NULL)
+ free(kl);
+ return NULL;
+}
+
+
+// ============================================================================
+// APIS
+// ============================================================================
+
+int
+psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) {
+ // 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.
+ kinfo_proc *result;
+ int done;
+ static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC, 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;
+ char errbuf[_POSIX2_LINE_MAX];
+ kinfo_proc *x;
+ int cnt;
+ kvm_t *kd;
+
+ assert( procList != NULL);
+ assert(*procList == NULL);
+ assert(procCount != NULL);
+
+ kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
+
+ if (kd == NULL) {
+ PyErr_Format(PyExc_RuntimeError, "kvm_openfiles() failed: %s", errbuf);
+ return errno;
+ }
+
+ result = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(kinfo_proc), &cnt);
+ if (result == NULL) {
+ PyErr_Format(PyExc_RuntimeError, "kvm_getproc2() failed");
+ kvm_close(kd);
+ return errno;
+ }
+
+ *procCount = (size_t)cnt;
+
+ size_t mlen = cnt * sizeof(kinfo_proc);
+
+ if ((*procList = malloc(mlen)) == NULL) {
+ PyErr_NoMemory();
+ kvm_close(kd);
+ return errno;
+ }
+
+ memcpy(*procList, result, mlen);
+ assert(*procList != NULL);
+ kvm_close(kd);
+
+ return 0;
+}
+
+
+char *
+psutil_get_cmd_args(pid_t pid, size_t *argsize) {
+ int mib[4];
+ ssize_t st;
+ size_t argmax;
+ size_t size;
+ char *procargs = NULL;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARGMAX;
+
+ size = sizeof(argmax);
+ st = sysctl(mib, 2, &argmax, &size, NULL, 0);
+ if (st == -1) {
+ warn("failed to get kern.argmax");
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ procargs = (char *)malloc(argmax);
+ if (procargs == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC_ARGS;
+ mib[2] = pid;
+ mib[3] = KERN_PROC_ARGV;
+
+ st = sysctl(mib, 4, procargs, &argmax, NULL, 0);
+ if (st == -1) {
+ warn("failed to get kern.procargs");
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ *argsize = argmax;
+ return procargs;
+}
+
+// returns the command line as a python list object
+PyObject *
+psutil_get_cmdline(pid_t pid) {
+ char *argstr = NULL;
+ int pos = 0;
+ size_t argsize = 0;
+ PyObject *py_arg = NULL;
+ PyObject *py_retlist = PyList_New(0);
+
+ if (py_retlist == NULL)
+ return NULL;
+ if (pid == 0)
+ return py_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) {
+ py_arg = Py_BuildValue("s", &argstr[pos]);
+ if (!py_arg)
+ goto error;
+ if (PyList_Append(py_retlist, py_arg))
+ goto error;
+ Py_DECREF(py_arg);
+ pos = pos + strlen(&argstr[pos]) + 1;
+ }
+ }
+
+ free(argstr);
+ return py_retlist;
+
+error:
+ Py_XDECREF(py_arg);
+ Py_DECREF(py_retlist);
+ if (argstr != NULL)
+ free(argstr);
+ return NULL;
+}
+
+
+PyObject *
+psutil_virtual_mem(PyObject *self, PyObject *args) {
+ unsigned int total;
+ size_t size = sizeof(total);
+ struct uvmexp_sysctl uv;
+ int mib[] = {CTL_VM, VM_UVMEXP2};
+ long pagesize = getpagesize();
+ size = sizeof(uv);
+
+ if (sysctl(mib, 2, &uv, &size, NULL, 0) < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ return Py_BuildValue("KKKKKKKK",
+ (unsigned long long) uv.npages * pagesize, // total
+ (unsigned long long) uv.free * pagesize, // free
+ (unsigned long long) uv.active * pagesize, // active
+ (unsigned long long) uv.inactive * pagesize, // inactive
+ (unsigned long long) uv.wired * pagesize, // wired
+ // taken from:
+ // https://github.com/satterly/zabbix-stats/blob/master/src/libs/
+ // zbxsysinfo/netbsd/memory.c
+ (unsigned long long) uv.filepages + uv.execpages * pagesize, // cached
+ (unsigned long long) 0, // buffers
+ (unsigned long long) 0 // shared
+ );
+}
+
+
+PyObject *
+psutil_swap_mem(PyObject *self, PyObject *args) {
+ uint64_t swap_total, swap_free;
+ struct swapent *swdev;
+ int nswap, i;
+
+ nswap = swapctl(SWAP_NSWAP, 0, 0);
+ if (nswap == 0) {
+ // This means there's no swap partition.
+ return Py_BuildValue("(iiiii)", 0, 0, 0, 0, 0);
+ }
+
+ swdev = calloc(nswap, sizeof(*swdev));
+ if (swdev == NULL) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ if (swapctl(SWAP_STATS, swdev, nswap) == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto error;
+ }
+
+ // Total things up.
+ swap_total = swap_free = 0;
+ for (i = 0; i < nswap; i++) {
+ if (swdev[i].se_flags & SWF_ENABLE) {
+ swap_free += (swdev[i].se_nblks - swdev[i].se_inuse);
+ swap_total += swdev[i].se_nblks;
+ }
+ }
+ free(swdev);
+
+ // Get swap in/out
+ unsigned int total;
+ size_t size = sizeof(total);
+ struct uvmexp_sysctl uv;
+ int mib[] = {CTL_VM, VM_UVMEXP2};
+ long pagesize = getpagesize();
+ size = sizeof(uv);
+ if (sysctl(mib, 2, &uv, &size, NULL, 0) < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto error;
+ }
+
+ return Py_BuildValue("(LLLll)",
+ swap_total * DEV_BSIZE,
+ (swap_total - swap_free) * DEV_BSIZE,
+ swap_free * DEV_BSIZE,
+ (long) uv.pgswapin * pagesize, // swap in
+ (long) uv.pgswapout * pagesize); // swap out
+
+error:
+ free(swdev);
+}
+
+
+PyObject *
+psutil_proc_num_fds(PyObject *self, PyObject *args) {
+ long pid;
+ int cnt;
+
+ struct kinfo_file *freep;
+
+ if (! PyArg_ParseTuple(args, "l", &pid))
+ return NULL;
+
+ freep = kinfo_getfile(pid, &cnt);
+ if (freep == NULL) {
+ psutil_raise_ad_or_nsp(pid);
+ return NULL;
+ }
+ free(freep);
+
+ return Py_BuildValue("i", cnt);
+}
+
+
+PyObject *
+psutil_per_cpu_times(PyObject *self, PyObject *args) {
+ static int maxcpus;
+ int mib[3];
+ int ncpu;
+ size_t len;
+ size_t size;
+ int i;
+ PyObject *py_cputime = NULL;
+ PyObject *py_retlist = PyList_New(0);
+
+ if (py_retlist == NULL)
+ return NULL;
+ // retrieve the number of cpus
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ len = sizeof(ncpu);
+ if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto error;
+ }
+ uint64_t cpu_time[CPUSTATES];
+
+ for (i = 0; i < ncpu; i++) {
+ // per-cpu info
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CP_TIME;
+ mib[2] = i;
+ size = sizeof(cpu_time);
+ if (sysctl(mib, 3, &cpu_time, &size, NULL, 0) == -1) {
+ warn("failed to get kern.cptime2");
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ py_cputime = 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);
+ 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;
+}
+
+
+PyObject *
+psutil_disk_io_counters(PyObject *self, PyObject *args) {
+ int i, dk_ndrive, mib[3];
+ size_t len;
+ struct io_sysctl *stats;
+ PyObject *py_disk_info = NULL;
+ PyObject *py_retdict = PyDict_New();
+
+ if (py_retdict == NULL)
+ return NULL;
+ mib[0] = CTL_HW;
+ mib[1] = HW_IOSTATS;
+ mib[2] = sizeof(struct io_sysctl);
+ len = 0;
+ if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0) {
+ warn("can't get HW_IOSTATS");
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto error;
+ }
+ dk_ndrive = (int)(len / sizeof(struct io_sysctl));
+
+ stats = malloc(len);
+ if (stats == NULL) {
+ PyErr_NoMemory();
+ goto error;
+ }
+ if (sysctl(mib, 2, stats, &len, NULL, 0) < 0 ) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto error;
+ }
+
+ for (i = 0; i < dk_ndrive; i++) {
+ py_disk_info = Py_BuildValue(
+ "(KKKKLL)",
+ stats[i].rxfer,
+ stats[i].wxfer,
+ stats[i].rbytes,
+ stats[i].wbytes,
+ // assume half read - half writes.
+ // TODO: why?
+ (long long) PSUTIL_KPT2DOUBLE(stats[i].time) / 2,
+ (long long) PSUTIL_KPT2DOUBLE(stats[i].time) / 2);
+ if (!py_disk_info)
+ goto error;
+ if (PyDict_SetItemString(py_retdict, stats[i].name, py_disk_info))
+ goto error;
+ Py_DECREF(py_disk_info);
+ }
+
+ free(stats);
+ return py_retdict;
+
+error:
+ Py_XDECREF(py_disk_info);
+ Py_DECREF(py_retdict);
+ if (stats != NULL)
+ free(stats);
+ return NULL;
+}
diff --git a/psutil/arch/bsd/netbsd.h b/psutil/arch/bsd/netbsd.h
new file mode 100644
index 00000000..b0b2caaf
--- /dev/null
+++ b/psutil/arch/bsd/netbsd.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil.
+ * All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+
+typedef struct kinfo_proc2 kinfo_proc;
+
+int psutil_kinfo_proc(pid_t pid, kinfo_proc *proc);
+struct kinfo_file * kinfo_getfile(pid_t pid, int* cnt);
+int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount);
+char *psutil_get_cmd_args(pid_t pid, size_t *argsize);
+PyObject * psutil_get_cmdline(pid_t pid);
+int psutil_pid_exists(pid_t pid);
+int psutil_raise_ad_or_nsp(long pid);
+
+//
+PyObject *psutil_proc_threads(PyObject *self, PyObject *args);
+PyObject *psutil_virtual_mem(PyObject *self, PyObject *args);
+PyObject *psutil_swap_mem(PyObject *self, PyObject *args);
+PyObject *psutil_proc_num_fds(PyObject *self, PyObject *args);
+PyObject *psutil_proc_connections(PyObject *self, PyObject *args);
+PyObject *psutil_per_cpu_times(PyObject *self, PyObject *args);
+PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
+PyObject* psutil_proc_exe(PyObject* self, PyObject* args);
+PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args);
diff --git a/psutil/arch/bsd/netbsd_socks.c b/psutil/arch/bsd/netbsd_socks.c
new file mode 100644
index 00000000..0de19165
--- /dev/null
+++ b/psutil/arch/bsd/netbsd_socks.c
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 2009, Giampaolo Rodola'.
+ * Copyright (c) 2015, Ryo ONODERA.
+ * All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include <Python.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/cdefs.h>
+#include <arpa/inet.h>
+#include <sys/queue.h>
+#include <sys/un.h>
+#include <sys/file.h>
+
+// a signaler for connections without an actual status
+int PSUTIL_CONN_NONE = 128;
+
+// Address family filter
+enum af_filter {
+ INET,
+ INET4,
+ INET6,
+ TCP,
+ TCP4,
+ TCP6,
+ UDP,
+ UDP4,
+ UDP6,
+ UNIX,
+ ALL,
+};
+
+// kinfo_file results
+struct kif {
+ SLIST_ENTRY(kif) kifs;
+ struct kinfo_file *kif;
+};
+
+// kinfo_file results list
+SLIST_HEAD(kifhead, kif) kihead = SLIST_HEAD_INITIALIZER(kihead);
+
+
+// kinfo_pcb results
+struct kpcb {
+ SLIST_ENTRY(kpcb) kpcbs;
+ struct kinfo_pcb *kpcb;
+};
+
+// kinfo_pcb results list
+SLIST_HEAD(kpcbhead, kpcb) kpcbhead = SLIST_HEAD_INITIALIZER(kpcbhead);
+
+static void kiflist_init(void);
+static void kiflist_clear(void);
+static void kpcblist_init(void);
+static void kpcblist_clear(void);
+static int get_files(void);
+static int get_sockets(const char *name);
+static void get_info(int aff);
+
+// Initialize kinfo_file results list
+static void
+kiflist_init(void) {
+ SLIST_INIT(&kihead);
+ return;
+}
+
+// Clear kinfo_file results list
+static void
+kiflist_clear(void) {
+ while (!SLIST_EMPTY(&kihead)) {
+ SLIST_REMOVE_HEAD(&kihead, kifs);
+ }
+
+ return;
+}
+
+// Initialize kinof_pcb result list
+static void
+kpcblist_init(void) {
+ SLIST_INIT(&kpcbhead);
+ return;
+}
+
+// Clear kinof_pcb result list
+static void
+kpcblist_clear(void) {
+ while (!SLIST_EMPTY(&kpcbhead)) {
+ SLIST_REMOVE_HEAD(&kpcbhead, kpcbs);
+ }
+
+ return;
+}
+
+
+// Get all open files including socket
+static int
+get_files(void) {
+ size_t len;
+ int mib[6];
+ char *buf;
+ off_t offset;
+ int j;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_FILE2;
+ mib[2] = KERN_FILE_BYFILE;
+ mib[3] = 0;
+ mib[4] = sizeof(struct kinfo_file);
+ mib[5] = 0;
+
+ if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
+ return -1;
+ offset = len % sizeof(off_t);
+ mib[5] = len / sizeof(struct kinfo_file);
+ if ((buf = malloc(len + offset)) == NULL)
+ return -1;
+ if (sysctl(mib, 6, buf + offset, &len, NULL, 0) == -1) {
+ free(buf);
+ return -1;
+ }
+
+ len /= sizeof(struct kinfo_file);
+ struct kinfo_file *ki = (struct kinfo_file *)(buf + offset);
+
+ for (j = 0; j < len; j++) {
+ struct kif *kif = malloc(sizeof(struct kif));
+ kif->kif = &ki[j];
+ SLIST_INSERT_HEAD(&kihead, kif, kifs);
+ }
+
+#if 0
+ // debug
+ struct kif *k;
+ SLIST_FOREACH(k, &kihead, kifs) {
+ printf("%d\n", k->kif->ki_pid);
+ }
+#endif
+
+ return 0;
+}
+
+// Get open sockets
+static int
+get_sockets(const char *name) {
+ size_t namelen;
+ int mib[8];
+ int ret, j;
+ struct kinfo_pcb *pcb;
+ size_t len;
+
+ memset(mib, 0, sizeof(mib));
+
+ if (sysctlnametomib(name, mib, &namelen) == -1)
+ return -1;
+
+ if (sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0) == -1)
+ return -1;
+
+ if ((pcb = malloc(len)) == NULL) {
+ return -1;
+ }
+ memset(pcb, 0, len);
+
+ mib[6] = sizeof(*pcb);
+ mib[7] = len / sizeof(*pcb);
+
+ if (sysctl(mib, __arraycount(mib), pcb, &len, NULL, 0) == -1) {
+ free(pcb);
+ return -1;
+ }
+
+ len /= sizeof(struct kinfo_pcb);
+ struct kinfo_pcb *kp = (struct kinfo_pcb *)pcb;
+
+ for (j = 0; j < len; j++) {
+ struct kpcb *kpcb = malloc(sizeof(struct kpcb));
+ kpcb->kpcb = &kp[j];
+ SLIST_INSERT_HEAD(&kpcbhead, kpcb, kpcbs);
+ }
+
+#if 0
+ // debug
+ struct kif *k;
+ struct kpcb *k;
+ SLIST_FOREACH(k, &kpcbhead, kpcbs) {
+ printf("ki_type: %d\n", k->kpcb->ki_type);
+ printf("ki_family: %d\n", k->kpcb->ki_family);
+ }
+#endif
+
+ return 0;
+}
+
+
+// Collect connections by PID
+PyObject *
+psutil_proc_connections(PyObject *self, PyObject *args) {
+ PyObject *py_retlist = PyList_New(0);
+ PyObject *py_tuple = NULL;
+ PyObject *py_laddr = NULL;
+ PyObject *py_raddr = NULL;
+ pid_t pid;
+
+ if (py_retlist == NULL)
+ return NULL;
+
+ if (! PyArg_ParseTuple(args, "l", &pid))
+ return NULL;
+
+ kiflist_init();
+ kpcblist_init();
+ get_info(ALL);
+
+ struct kif *k;
+ SLIST_FOREACH(k, &kihead, kifs) {
+ struct kpcb *kp;
+ if (k->kif->ki_pid == pid) {
+ SLIST_FOREACH(kp, &kpcbhead, kpcbs) {
+ if (k->kif->ki_fdata == kp->kpcb->ki_sockaddr) {
+ pid_t pid;
+ int32_t fd;
+ int32_t family;
+ int32_t type;
+ char laddr[PATH_MAX];
+ int32_t lport;
+ char raddr[PATH_MAX];
+ int32_t rport;
+ int32_t status;
+
+ pid = k->kif->ki_pid;
+ fd = k->kif->ki_fd;
+ family = kp->kpcb->ki_family;
+ type = kp->kpcb->ki_type;
+ if (kp->kpcb->ki_family == AF_INET) {
+ struct sockaddr_in *sin_src =
+ (struct sockaddr_in *)&kp->kpcb->ki_src;
+ struct sockaddr_in *sin_dst =
+ (struct sockaddr_in *)&kp->kpcb->ki_dst;
+ if (inet_ntop(AF_INET, &sin_src->sin_addr, laddr,
+ sizeof(laddr)) != NULL)
+ lport = ntohs(sin_src->sin_port);
+ py_laddr = Py_BuildValue("(si)", laddr, lport);
+ if (!py_laddr)
+ goto error;
+ if (inet_ntop(AF_INET, &sin_dst->sin_addr, raddr,
+ sizeof(raddr)) != NULL)
+ rport = ntohs(sin_dst->sin_port);
+ py_raddr = Py_BuildValue("(si)", raddr, rport);
+ if (!py_raddr)
+ goto error;
+ if (kp->kpcb->ki_type == SOCK_STREAM) {
+ status = kp->kpcb->ki_tstate;
+ } else {
+ status = PSUTIL_CONN_NONE;
+ }
+
+ py_tuple = Py_BuildValue("(iiiNNi)", fd, AF_INET,
+ type, py_laddr, py_raddr, status);
+ if (!py_tuple)
+ goto error;
+ if (PyList_Append(py_retlist, py_tuple))
+ goto error;
+ } else if (kp->kpcb->ki_family == AF_INET6) {
+ struct sockaddr_in6 *sin6_src =
+ (struct sockaddr_in6 *)&kp->kpcb->ki_src;
+ struct sockaddr_in6 *sin6_dst =
+ (struct sockaddr_in6 *)&kp->kpcb->ki_dst;
+ if (inet_ntop(AF_INET6, &sin6_src->sin6_addr, laddr,
+ sizeof(laddr)) != NULL)
+ lport = ntohs(sin6_src->sin6_port);
+ py_laddr = Py_BuildValue("(si)", laddr, lport);
+ if (!py_laddr)
+ goto error;
+ if (inet_ntop(AF_INET6, &sin6_dst->sin6_addr, raddr,
+ sizeof(raddr)) != NULL)
+ rport = ntohs(sin6_dst->sin6_port);
+ py_raddr = Py_BuildValue("(si)", raddr, rport);
+ if (!py_raddr)
+ goto error;
+ if (kp->kpcb->ki_type == SOCK_STREAM) {
+ status = kp->kpcb->ki_tstate;
+ } else {
+ status = PSUTIL_CONN_NONE;
+ }
+
+ py_tuple = Py_BuildValue("(iiiNNi)", fd, AF_INET6,
+ type, py_laddr, py_raddr, status);
+ if (!py_tuple)
+ goto error;
+ if (PyList_Append(py_retlist, py_tuple))
+ goto error;
+ } else if (kp->kpcb->ki_family == AF_UNIX) {
+ struct sockaddr_un *sun_src =
+ (struct sockaddr_un *)&kp->kpcb->ki_src;
+ struct sockaddr_un *sun_dst =
+ (struct sockaddr_un *)&kp->kpcb->ki_dst;
+ strcpy(laddr, sun_src->sun_path);
+ strcpy(raddr, sun_dst->sun_path);
+ status = PSUTIL_CONN_NONE;
+
+ py_tuple = Py_BuildValue("(iiissi)", fd, AF_UNIX,
+ type, laddr, raddr, status);
+ if (!py_tuple)
+ goto error;
+ if (PyList_Append(py_retlist, py_tuple))
+ goto error;
+ }
+
+
+ }
+ }}
+ }
+
+ kiflist_clear();
+ kpcblist_clear();
+ return py_retlist;
+
+error:
+ Py_XDECREF(py_tuple);
+ Py_XDECREF(py_laddr);
+ Py_XDECREF(py_raddr);
+ return 0;
+}
+
+
+// Collect open file and connections
+static void
+get_info(int aff) {
+ get_files();
+
+ switch (aff) {
+ case INET:
+ get_sockets("net.inet.tcp.pcblist");
+ get_sockets("net.inet.udp.pcblist");
+ get_sockets("net.inet6.tcp6.pcblist");
+ get_sockets("net.inet6.udp6.pcblist");
+ break;
+ case INET4:
+ get_sockets("net.inet.tcp.pcblist");
+ get_sockets("net.inet.udp.pcblist");
+ break;
+ case INET6:
+ get_sockets("net.inet6.tcp6.pcblist");
+ get_sockets("net.inet6.udp6.pcblist");
+ break;
+ case TCP:
+ get_sockets("net.inet.tcp.pcblist");
+ get_sockets("net.inet6.tcp6.pcblist");
+ break;
+ case TCP4:
+ get_sockets("net.inet.tcp.pcblist");
+ break;
+ case TCP6:
+ get_sockets("net.inet6.tcp6.pcblist");
+ break;
+ case UDP:
+ get_sockets("net.inet.udp.pcblist");
+ get_sockets("net.inet6.udp6.pcblist");
+ break;
+ case UDP4:
+ get_sockets("net.inet.udp.pcblist");
+ break;
+ case UDP6:
+ get_sockets("net.inet6.udp6.pcblist");
+ break;
+ case UNIX:
+ get_sockets("net.local.stream.pcblist");
+ get_sockets("net.local.seqpacket.pcblist");
+ get_sockets("net.local.dgram.pcblist");
+ break;
+ case ALL:
+ get_sockets("net.inet.tcp.pcblist");
+ get_sockets("net.inet.udp.pcblist");
+ get_sockets("net.inet6.tcp6.pcblist");
+ get_sockets("net.inet6.udp6.pcblist");
+ get_sockets("net.local.stream.pcblist");
+ get_sockets("net.local.seqpacket.pcblist");
+ get_sockets("net.local.dgram.pcblist");
+ break;
+ }
+ return;
+}
+
+// Collect system wide connections by address family filter
+PyObject *
+psutil_net_connections(PyObject *self, PyObject *args) {
+ PyObject *py_retlist = PyList_New(0);
+ PyObject *py_tuple = NULL;
+ PyObject *py_laddr = NULL;
+ PyObject *py_raddr = NULL;
+
+ if (py_retlist == NULL)
+ return NULL;
+
+ kiflist_init();
+ kpcblist_init();
+ get_info(ALL);
+
+ struct kif *k;
+ SLIST_FOREACH(k, &kihead, kifs) {
+ struct kpcb *kp;
+ SLIST_FOREACH(kp, &kpcbhead, kpcbs) {
+ if (k->kif->ki_fdata == kp->kpcb->ki_sockaddr) {
+ pid_t pid;
+ int32_t fd;
+ int32_t family;
+ int32_t type;
+ char laddr[PATH_MAX];
+ int32_t lport;
+ char raddr[PATH_MAX];
+ int32_t rport;
+ int32_t status;
+
+ pid = k->kif->ki_pid;
+ fd = k->kif->ki_fd;
+ family = kp->kpcb->ki_family;
+ type = kp->kpcb->ki_type;
+ if (kp->kpcb->ki_family == AF_INET) {
+ struct sockaddr_in *sin_src =
+ (struct sockaddr_in *)&kp->kpcb->ki_src;
+ struct sockaddr_in *sin_dst =
+ (struct sockaddr_in *)&kp->kpcb->ki_dst;
+ if (inet_ntop(AF_INET, &sin_src->sin_addr, laddr,
+ sizeof(laddr)) != NULL)
+ lport = ntohs(sin_src->sin_port);
+ py_laddr = Py_BuildValue("(si)", laddr, lport);
+ if (!py_laddr)
+ goto error;
+ if (inet_ntop(AF_INET, &sin_dst->sin_addr, raddr,
+ sizeof(raddr)) != NULL)
+ rport = ntohs(sin_dst->sin_port);
+ py_raddr = Py_BuildValue("(si)", raddr, rport);
+ if (!py_raddr)
+ goto error;
+ if (kp->kpcb->ki_type == SOCK_STREAM) {
+ status = kp->kpcb->ki_tstate;
+ } else {
+ status = PSUTIL_CONN_NONE;
+ }
+
+ py_tuple = Py_BuildValue("(iiiNNii)", fd, AF_INET,
+ type, py_laddr, py_raddr, status, pid);
+ if (!py_tuple)
+ goto error;
+ if (PyList_Append(py_retlist, py_tuple))
+ goto error;
+ } else if (kp->kpcb->ki_family == AF_INET6) {
+ struct sockaddr_in6 *sin6_src =
+ (struct sockaddr_in6 *)&kp->kpcb->ki_src;
+ struct sockaddr_in6 *sin6_dst =
+ (struct sockaddr_in6 *)&kp->kpcb->ki_dst;
+ if (inet_ntop(AF_INET6, &sin6_src->sin6_addr, laddr,
+ sizeof(laddr)) != NULL)
+ lport = ntohs(sin6_src->sin6_port);
+ py_laddr = Py_BuildValue("(si)", laddr, lport);
+ if (!py_laddr)
+ goto error;
+ if (inet_ntop(AF_INET6, &sin6_dst->sin6_addr, raddr,
+ sizeof(raddr)) != NULL)
+ rport = ntohs(sin6_dst->sin6_port);
+ py_raddr = Py_BuildValue("(si)", raddr, rport);
+ if (!py_raddr)
+ goto error;
+ if (kp->kpcb->ki_type == SOCK_STREAM) {
+ status = kp->kpcb->ki_tstate;
+ } else {
+ status = PSUTIL_CONN_NONE;
+ }
+
+ py_tuple = Py_BuildValue("(iiiNNii)", fd, AF_INET6,
+ type, py_laddr, py_raddr, status, pid);
+ if (!py_tuple)
+ goto error;
+ if (PyList_Append(py_retlist, py_tuple))
+ goto error;
+ } else if (kp->kpcb->ki_family == AF_UNIX) {
+ struct sockaddr_un *sun_src =
+ (struct sockaddr_un *)&kp->kpcb->ki_src;
+ struct sockaddr_un *sun_dst =
+ (struct sockaddr_un *)&kp->kpcb->ki_dst;
+ strcpy(laddr, sun_src->sun_path);
+ strcpy(raddr, sun_dst->sun_path);
+ status = PSUTIL_CONN_NONE;
+
+ py_tuple = Py_BuildValue("(iiissii)", fd, AF_UNIX,
+ type, laddr, raddr, status, pid);
+ if (!py_tuple)
+ goto error;
+ if (PyList_Append(py_retlist, py_tuple))
+ goto error;
+ }
+
+
+ }
+ }
+ }
+
+ kiflist_clear();
+ kpcblist_clear();
+ return py_retlist;
+
+error:
+ Py_XDECREF(py_tuple);
+ Py_XDECREF(py_laddr);
+ Py_XDECREF(py_raddr);
+ return 0;
+}
diff --git a/psutil/arch/bsd/netbsd_socks.h b/psutil/arch/bsd/netbsd_socks.h
new file mode 100644
index 00000000..9e6a97c0
--- /dev/null
+++ b/psutil/arch/bsd/netbsd_socks.h
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2009, Giampaolo Rodola'.
+ * Copyright (c) 2015, Ryo ONODERA.
+ * All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+PyObject *psutil_proc_connections(PyObject *, PyObject *);
+PyObject *psutil_net_connections(PyObject *, PyObject *);
diff --git a/psutil/arch/bsd/openbsd.c b/psutil/arch/bsd/openbsd.c
index 82a598d1..a29928ba 100644
--- a/psutil/arch/bsd/openbsd.c
+++ b/psutil/arch/bsd/openbsd.c
@@ -178,6 +178,7 @@ psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) {
result = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cnt);
if (result == NULL) {
+ kvm_close(kd);
err(1, NULL);
return errno;
}
@@ -187,6 +188,7 @@ psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) {
size_t mlen = cnt * sizeof(struct kinfo_proc);
if ((*procList = malloc(mlen)) == NULL) {
+ kvm_close(kd);
err(1, NULL);
return errno;
}
@@ -387,14 +389,13 @@ psutil_swap_mem(PyObject *self, PyObject *args) {
}
if ((swdev = calloc(nswap, sizeof(*swdev))) == NULL) {
- PyErr_SetFromErrno(PyExc_OSError);
+ PyErr_NoMemory();
return NULL;
}
if (swapctl(SWAP_STATS, swdev, nswap) == -1) {
- free(swdev);
PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
+ goto error;
}
// Total things up.
@@ -415,6 +416,10 @@ psutil_swap_mem(PyObject *self, PyObject *args) {
// swapent struct does not provide any info
// about it.
0, 0);
+
+error:
+ free(swdev);
+ return NULL;
}
diff --git a/setup.py b/setup.py
index dd0b0c81..59f3a167 100644
--- a/setup.py
+++ b/setup.py
@@ -151,6 +151,19 @@ elif sys.platform.startswith("openbsd"):
define_macros=[VERSION_MACRO],
libraries=["kvm"])
extensions = [ext, posix_extension]
+# NetBSD
+elif sys.platform.startswith("netbsd"):
+ ext = Extension(
+ 'psutil._psutil_bsd',
+ sources=[
+ 'psutil/_psutil_bsd.c',
+ 'psutil/_psutil_common.c',
+ 'psutil/arch/bsd/netbsd.c',
+ 'psutil/arch/bsd/netbsd_socks.c',
+ ],
+ define_macros=[VERSION_MACRO],
+ libraries=["kvm"])
+ extensions = [ext, posix_extension]
# Linux
elif sys.platform.startswith("linux"):
def get_ethtool_macro():
diff --git a/test/_posix.py b/test/_posix.py
index 35b498a7..10243336 100644
--- a/test/_posix.py
+++ b/test/_posix.py
@@ -262,6 +262,12 @@ class PosixSpecificTestCase(unittest.TestCase):
if failures:
self.fail('\n' + '\n'.join(failures))
+ @unittest.skipUnless(os.path.islink("/proc/%s/cwd" % os.getpid()),
+ "/proc fs not available")
+ def test_cwd_proc(self):
+ self.assertEqual(os.readlink("/proc/%s/cwd" % os.getpid()),
+ psutil.Process().cwd())
+
def main():
test_suite = unittest.TestSuite()
diff --git a/test/test_psutil.py b/test/test_psutil.py
index 5494e27b..8111068b 100644
--- a/test/test_psutil.py
+++ b/test/test_psutil.py
@@ -115,7 +115,8 @@ LINUX = sys.platform.startswith("linux")
OSX = sys.platform.startswith("darwin")
FREEBSD = sys.platform.startswith("freebsd")
OPENBSD = sys.platform.startswith("openbsd")
-BSD = FREEBSD or OPENBSD
+NETBSD = sys.platform.startswith("netbsd")
+BSD = FREEBSD or OPENBSD or NETBSD
SUNOS = sys.platform.startswith("sunos")
VALID_PROC_STATUSES = [getattr(psutil, x) for x in dir(psutil)
if x.startswith('STATUS_')]
@@ -1669,7 +1670,7 @@ class TestProcess(unittest.TestCase):
# def test_memory_info_ex(self):
# # tested later in fetch all test suite
- @unittest.skipIf(OPENBSD, "not available on OpenBSD")
+ @unittest.skipIf(OPENBSD or NETBSD, "not available on this platform")
def test_memory_maps(self):
p = psutil.Process()
maps = p.memory_maps()
@@ -3121,7 +3122,7 @@ class TestExampleScripts(unittest.TestCase):
def test_ifconfig(self):
self.assert_stdout('ifconfig.py')
- @unittest.skipIf(OPENBSD, "OpenBSD does not support memory maps")
+ @unittest.skipIf(OPENBSD or NETBSD, "memory maps not supported")
def test_pmap(self):
self.assert_stdout('pmap.py', args=str(os.getpid()))