summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2016-01-07 11:15:50 +0000
committerGiampaolo Rodola <g.rodola@gmail.com>2016-01-07 11:15:50 +0000
commitc397447cace6123873997836b703d268bc23ed24 (patch)
tree00875be6c7ed290f473c2fd0ada3c874c9f425d2
parent24f7b2e87c3ab3308c12578b22f69dec8c0948ef (diff)
parent7e98e0b9ba6426be86dfcea02c9d2ef18d3554b5 (diff)
downloadpsutil-c397447cace6123873997836b703d268bc23ed24.tar.gz
Merge branch 'master' of git://github.com/0-wiz-0/psutil into 0-wiz-0-master
-rw-r--r--psutil/__init__.py3
-rw-r--r--psutil/_psbsd.py41
-rw-r--r--psutil/_psutil_bsd.c162
-rw-r--r--psutil/_psutil_posix.c10
-rw-r--r--psutil/arch/bsd/netbsd.c676
-rw-r--r--psutil/arch/bsd/netbsd.h30
-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.c2
-rw-r--r--setup.py13
-rw-r--r--test/test_psutil.py3
11 files changed, 1402 insertions, 63 deletions
diff --git a/psutil/__init__.py b/psutil/__init__.py
index 727b1b64..2ab1b7f2 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -123,7 +123,8 @@ 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"):
diff --git a/psutil/_psbsd.py b/psutil/_psbsd.py
index a772e264..3449473e 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 = {
@@ -60,6 +61,15 @@ elif OPENBSD:
cext.SRUN: _common.STATUS_WAKING,
cext.SONPROC: _common.STATUS_RUNNING,
}
+elif NETBSD:
+ PROC_STATUSES = {
+ cext.SIDL: _common.STATUS_IDLE,
+ cext.SACTIVE: _common.STATUS_RUNNING,
+ cext.SDYING: _common.STATUS_ZOMBIE,
+ cext.SSTOP: _common.STATUS_STOPPED,
+ cext.SZOMB: _common.STATUS_ZOMBIE,
+ cext.SDEAD: _common.STATUS_DEAD,
+ }
TCP_STATUSES = {
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
@@ -76,7 +86,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 +169,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 +286,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 +346,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:
@@ -426,6 +439,24 @@ 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)
+ return list(ret)
+
families, types = conn_tmap[kind]
rawlist = cext.proc_connections(self.pid, families, types)
ret = []
diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c
index 278504f8..6c194e8b 100644
--- a/psutil/_psutil_bsd.c
+++ b/psutil/_psutil_bsd.c
@@ -15,6 +15,9 @@
* - 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,15 @@
#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_*
+#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 +111,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 +141,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 +190,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 +229,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 +248,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 +268,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 +278,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 +293,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 +303,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 +318,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 +337,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 +346,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 +360,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 +369,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 +405,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 +425,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 +435,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
@@ -438,7 +454,7 @@ 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)
@@ -451,7 +467,7 @@ psutil_proc_memory_info(PyObject *self, PyObject *args) {
ptoa(kp.ki_tsize), // text
ptoa(kp.ki_dsize), // data
ptoa(kp.ki_ssize)); // stack
-#elif __OpenBSD__
+#elif defined(__OpenBSD__)
ptoa(kp.p_vm_rssize), // rss
// vms, this is how ps does it, see:
// http://anoncvs.spacehopper.org/openbsd-src/tree/bin/ps/print.c#n461
@@ -459,6 +475,9 @@ psutil_proc_memory_info(PyObject *self, PyObject *args) {
ptoa(kp.p_vm_tsize), // text
ptoa(kp.p_vm_dsize), // data
ptoa(kp.p_vm_ssize)); // stack
+#else
+/* not implemented */
+ 0, 0, 0, 0, 0);
#endif
}
@@ -472,7 +491,7 @@ psutil_cpu_times(PyObject *self, PyObject *args) {
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 +518,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 +549,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 +591,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 +604,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 +623,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 +637,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 +675,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 +828,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 +862,7 @@ psutil_users(PyObject *self, PyObject *args) {
#else
struct utmpx *utx;
+ setutxent();
while ((utx = getutxent()) != NULL) {
if (utx->ut_type != USER_PROCESS)
continue;
@@ -883,20 +934,21 @@ PsutilMethods[] = {
"Return process tty (terminal) number"},
{"proc_cwd", psutil_proc_cwd, METH_VARARGS,
"Return process current working directory."},
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 || __OpenBSD__
+#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 +958,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 +985,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 +1063,13 @@ 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", 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);
#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..8b38613d
--- /dev/null
+++ b/psutil/arch/bsd/netbsd.c
@@ -0,0 +1,676 @@
+/*
+ * 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;
+
+ 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, active, inactive, wired, cached, free;
+ size_t size = sizeof(total);
+ struct uvmexp_sysctl uvmexp;
+ int mib[] = {CTL_VM, VM_UVMEXP2};
+ long pagesize = getpagesize();
+ size = sizeof(uvmexp);
+
+ if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
+ warn("failed to get vm.uvmexp");
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+ return Py_BuildValue("KKKKKKKK",
+ (unsigned long long) uvmexp.npages * pagesize,
+ (unsigned long long) uvmexp.free * pagesize,
+ (unsigned long long) uvmexp.active * pagesize,
+ (unsigned long long) uvmexp.inactive * pagesize,
+ (unsigned long long) uvmexp.wired * pagesize,
+ (unsigned long long) 0,
+ (unsigned long long) 0,
+ (unsigned long long) 0
+ );
+}
+
+
+PyObject *
+psutil_swap_mem(PyObject *self, PyObject *args) {
+ uint64_t swap_total, swap_free;
+ struct swapent *swdev;
+ int nswap, i;
+
+ if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) == 0) {
+ warn("failed to get swap device count");
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ if ((swdev = calloc(nswap, sizeof(*swdev))) == NULL) {
+ warn("failed to allocate memory for swdev structures");
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ if (swapctl(SWAP_STATS, swdev, nswap) == -1) {
+ free(swdev);
+ warn("failed to get swap stats");
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ // 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);
+ return Py_BuildValue("(LLLII)",
+ swap_total * DEV_BSIZE,
+ (swap_total - swap_free) * DEV_BSIZE,
+ swap_free * DEV_BSIZE,
+ 0, // XXX swap in
+ 0); // XXX swap out
+}
+
+
+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_proc_cwd(PyObject *self, PyObject *args) {
+ // Not implemented
+ return NULL;
+}
+
+
+// see sys/kern/kern_sysctl.c lines 1100 and
+// usr.bin/fstat/fstat.c print_inet_details()
+static char *
+psutil_convert_ipv4(int family, uint32_t addr[4]) {
+ struct in_addr a;
+ memcpy(&a, addr, sizeof(a));
+ return inet_ntoa(a);
+}
+
+
+static char *
+psutil_inet6_addrstr(struct in6_addr *p) {
+ struct sockaddr_in6 sin6;
+ static char hbuf[NI_MAXHOST];
+ const int niflags = NI_NUMERICHOST;
+
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_addr = *p;
+ if (IN6_IS_ADDR_LINKLOCAL(p) &&
+ *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] != 0) {
+ sin6.sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
+ sin6.sin6_addr.s6_addr[2] = sin6.sin6_addr.s6_addr[3] = 0;
+ }
+
+ if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
+ hbuf, sizeof(hbuf), NULL, 0, niflags))
+ return "invalid";
+
+ return hbuf;
+}
+
+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_retlist = PyList_New(0);
+ PyObject *py_cputime = NULL;
+
+ 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_retdict = PyDict_New();
+ PyObject *py_disk_info = NULL;
+ 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) {
+ warn("can't malloc");
+ PyErr_NoMemory();
+ goto error;
+ }
+ if (sysctl(mib, 2, stats, &len, NULL, 0) < 0 ) {
+ warn("could not read HW_IOSTATS");
+ 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..71cca52e
--- /dev/null
+++ b/psutil/arch/bsd/netbsd.h
@@ -0,0 +1,30 @@
+/*
+ * 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_cwd(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..24a05524 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;
}
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/test_psutil.py b/test/test_psutil.py
index d8c910ab..fba71d20 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_')]