$OpenBSD: patch-libs_ksysguard_lsofui_lsof_cpp,v 1.2 2016/05/01 16:24:09 zhuk Exp $
Use kvm_getfiles() instead of starting lsof(1).
--- libs/ksysguard/lsofui/lsof.cpp.orig	Fri Jun 26 06:17:21 2015
+++ libs/ksysguard/lsofui/lsof.cpp	Sat Apr 30 03:14:56 2016
@@ -1,12 +1,25 @@
 #include <QString>
-#include <QProcess>
+#ifdef HAVE_KVM_H
+# include <sys/types.h>
+# include <sys/sysctl.h>
+# include <fcntl.h>
+# include <kvm.h>
+# include <limits.h>
+#else
+# include <QProcess>
+#endif
 #include <klocale.h>
 
 #include "lsof.h"
 
 struct KLsofWidgetPrivate {
 	qlonglong pid;
+#ifdef HAVE_KVM_H
+	kvm_t *kd;
+	char errbuf[_POSIX2_LINE_MAX];
+#else
 	QProcess *process;
+#endif
 };
 
 KLsofWidget::KLsofWidget(QWidget *parent) : QTreeWidget(parent), d(new KLsofWidgetPrivate)
@@ -19,12 +32,23 @@ KLsofWidget::KLsofWidget(QWidget *parent) : QTreeWidge
 	setSortingEnabled(true);
 	setAllColumnsShowFocus(true);
 	setHeaderLabels(QStringList() << i18nc("Short for File Descriptor", "FD") << i18n("Type") << i18n("Object"));
+#ifdef HAVE_KVM_H
+	d->kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, d->errbuf);
+#else
 	d->process = new QProcess(this);
 	connect(d->process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(finished(int,QProcess::ExitStatus)));
+#endif
 }
 
 KLsofWidget::~KLsofWidget()
 {
+#ifdef HAVE_KVM_H
+	if (d->kd)
+		kvm_close(d->kd);
+#else
+	if (d->process)
+		delete d->process;
+#endif
         delete d;
 }
 
@@ -38,9 +62,68 @@ void KLsofWidget::setPid(qlonglong pid) {
 	update();
 }
 
+#ifdef HAVE_KVM_H
+
+static QString fileTypeName(int ftype, int vtype) {
+	static QString vtype_names[] = {
+		QString::fromLatin1("no type"),
+		QString::fromLatin1("file"),
+		QString::fromLatin1("directory"),
+		QString::fromLatin1("blockdev"),
+		QString::fromLatin1("chardev"),
+		QString::fromLatin1("symlink"),
+		QString::fromLatin1("socket"),
+		QString::fromLatin1("named pipe"),
+		QString::fromLatin1("bad")
+	};
+
+// taken from sys/file.h on OpenBSD 5.9-CURRENT
+#ifndef DTYPE_VNODE
+# define DTYPE_VNODE     1       /* file */
+# define DTYPE_SOCKET    2       /* communications endpoint */
+# define DTYPE_PIPE      3       /* pipe */
+# define DTYPE_KQUEUE    4       /* event queue */
+#endif
+
+	switch (ftype) {
+	case DTYPE_SOCKET:
+		return QString::fromLatin1("socket");
+	case DTYPE_PIPE:
+		return QString::fromLatin1("pipe");
+	case DTYPE_KQUEUE:
+		return QString::fromLatin1("kqueue");
+	case DTYPE_VNODE:
+		if (vtype >= 0 && vtype <= sizeof(vtype_names)/sizeof(vtype_names[0]))
+			return vtype_names[vtype];
+	}
+	return QString::fromLatin1("unknown");
+}
+
 bool KLsofWidget::update()
 {
+	struct kinfo_file *files;
+	int cnt;
+
 	clear();
+	if (d->kd == NULL)
+		return false;
+	if ((files = kvm_getfiles(d->kd, KERN_FILE_BYPID, (int)d->pid, sizeof(struct kinfo_file), &cnt)) == NULL)
+		return false;
+
+	for (int i = 0; i < cnt; i++) {
+		QTreeWidgetItem *process = new QTreeWidgetItem(this);
+		process->setText(0, QString::number(files[i].fd_fd));
+		process->setText(1, fileTypeName(files[i].f_type, files[i].v_type));
+		process->setText(2, QString::fromLocal8Bit(files[i].f_mntonname));
+	}
+	return true;
+}
+
+#else	// HAVE_KVM_H
+
+bool KLsofWidget::update()
+{
+	clear();
 	QStringList args;
 	d->process->waitForFinished();
 	args << "-Fftn";
@@ -85,5 +168,7 @@ void KLsofWidget::finished ( int exitCode, QProcess::E
 		}
 	}
 }
+
+#endif	// HAVE_KVM_H
 
 #include "lsof.moc"
