$OpenBSD: patch-common_UnixUtil_cpp,v 1.5 2021/02/09 10:32:33 robert Exp $

Index: common/UnixUtil.cpp
--- common/UnixUtil.cpp.orig
+++ common/UnixUtil.cpp
@@ -28,8 +28,85 @@
 
 using namespace std::string_literals;
 
+#if defined(__OpenBSD__)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/stat.h>
+#include <kvm.h>
+#include <stdlib.h>
+#endif
+
 namespace KC {
 
+#if defined(__OpenBSD__)
+int
+getexepath(char *buf)
+{
+	struct kinfo_file *files;
+	kvm_t *kd = NULL;
+	char errbuf[_POSIX2_LINE_MAX];
+	char **retvalargs;
+	int cnt;
+	size_t len;
+        struct stat sb;
+	pid_t cpid = getpid();
+
+	const int mib[] = { CTL_KERN, KERN_PROC_ARGS, cpid, KERN_PROC_ARGV };
+
+	if (sysctl(mib, 4, NULL, &len, NULL, 0) != -1) {
+		retvalargs = (char **)malloc(len);
+		if (!retvalargs) { 
+			ec_log_err("malloc failed: %s", strerror(errno));
+			goto out;
+		}
+
+		if (sysctl(mib, 4, retvalargs, &len, NULL, 0) < 0) { 
+			ec_log_err("sysctl failed: %s", strerror(errno));
+			goto out;
+		}
+
+		if (realpath(retvalargs[0], buf) == NULL) {
+			ec_log_err("realpath failed: %s", strerror(errno));
+			goto out;
+		}
+
+		free(retvalargs);
+
+		if (stat(buf, &sb) < 0) {
+			ec_log_err("stat failed: %s", strerror(errno));
+			goto out;
+		}
+
+		if ((kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES,
+  		     errbuf)) == NULL) {
+			ec_log_err("kvm_openfiles failed: %s", strerror(errno));
+			goto out;
+		}
+
+		if ((files = kvm_getfiles(kd, KERN_FILE_BYPID, cpid,
+		    sizeof(struct kinfo_file), &cnt)) == NULL) {
+			ec_log_err("kvm_getfiles failed: %s", strerror(errno));
+			goto out;
+		}
+
+		for (int i = 0; i < cnt; i++) {
+			if (files[i].fd_fd == KERN_FILE_TEXT &&
+			    files[i].va_fsid == sb.st_dev &&
+			    files[i].va_fileid == sb.st_ino) {
+				kvm_close(kd);
+				return 1;
+			}
+		}
+	}
+
+out:
+	if (kd)
+		kvm_close(kd);
+
+	return 0;
+}
+#endif
+
 static int unix_runpath()
 {
 	auto ret = chdir("/");
@@ -481,6 +558,15 @@ int ec_reexec(const char *const *argv)
 
 	/* Resolve "exe" symlink before exec to please the sysadmin */
 	std::vector<char> linkbuf(16); /* mutable std::string::data is C++17 only */
+#if !defined(__OpenBSD__) /* XXX NOTYET */
+	if (!getexepath(&linkbuf[0])) {
+		int ret = -errno;
+		ec_log_debug("ec_reexec: readlink: %s", strerror(errno));
+		return ret;
+	}
+	ec_log_debug("Reexecing %s", &linkbuf[0]);
+	execv(&linkbuf[0], const_cast<char **>(argv));
+#else
 	ssize_t linklen;
 	while (true) {
 		linklen = readlink("/proc/self/exe", &linkbuf[0], linkbuf.size());
@@ -496,6 +582,7 @@ int ec_reexec(const char *const *argv)
 	linkbuf[linklen] = '\0';
 	ec_log_debug("Reexecing %s", &linkbuf[0]);
 	execv(&linkbuf[0], const_cast<char **>(argv));
+#endif
 	return -errno;
 }
 
