From b9b484fb82482d49ec8b67a62e26d491e895bb39 Mon Sep 17 00:00:00 2001 From: high on tantor Date: Thu, 23 Apr 2026 20:17:19 -0400 Subject: [PATCH 01/10] Add More Reliable OpenBSD Executable Path Solution --- drivers/unix/os_unix.cpp | 136 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 6 deletions(-) diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index f42c957f0d..9ef2b57d23 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -63,13 +63,18 @@ #include #endif -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) #include #endif #if defined(__OpenBSD__) #include +#include #include +#include +#include +#include +#include #endif #if defined(__NetBSD__) @@ -1146,11 +1151,130 @@ String OS_Unix::get_executable_path() const { } return b; #elif defined(__OpenBSD__) - char resolved_path[MAXPATHLEN]; - - realpath(OS::get_executable_path().utf8().get_data(), resolved_path); - - return String(resolved_path); + std::string path; + auto is_exe = [](std::string exe) { + int cntp = 0; + std::string res; + kvm_t *kd = nullptr; + kinfo_file *kif = nullptr; + bool error = false; + kd = kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); + if (!kd) return res; + if ((kif = kvm_getfiles(kd, KERN_FILE_BYPID, getpid(), sizeof(struct kinfo_file), &cntp))) { + for (int i = 0; i < cntp && kif[i].fd_fd < 0; i++) { + if (kif[i].fd_fd == KERN_FILE_TEXT) { + struct stat st; + fallback: + char buffer[PATH_MAX]; + if (!stat(exe.c_str(), &st) && (st.st_mode & S_IXUSR) && + (st.st_mode & S_IFREG) && realpath(exe.c_str(), buffer) && + st.st_dev == (dev_t)kif[i].va_fsid && st.st_ino == (ino_t)kif[i].va_fileid) { + res = buffer; + } + if (res.empty() && !error) { + error = true; + std::size_t last_slash_pos = exe.find_last_of("/"); + if (last_slash_pos != std::string::npos) { + exe = exe.substr(0, last_slash_pos + 1) + kif[i].p_comm; + goto fallback; + } + } + break; + } + } + } + kvm_close(kd); + return res; + }; + auto cppstr_getenv = [](std::string name) { + const char *cresult = getenv(name.c_str()); + std::string result = cresult ? cresult : ""; + return result; + }; + int cntp = 0; + kvm_t *kd = nullptr; + kinfo_proc *proc_info = nullptr; + std::vector buffer; + bool error = false, retried = false; + kd = kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); + if (!kd) { + path.clear(); + return path; + } + if ((proc_info = kvm_getprocs(kd, KERN_PROC_PID, getpid(), sizeof(struct kinfo_proc), &cntp))) { + char **cmd = kvm_getargv(kd, proc_info, 0); + if (cmd) { + for (int i = 0; cmd[i]; i++) { + buffer.push_back(cmd[i]); + } + } + } + kvm_close(kd); + if (!buffer.empty()) { + std::string argv0; + if (!buffer[0].empty()) { + fallback: + std::size_t slash_pos = buffer[0].find('/'); + std::size_t colon_pos = buffer[0].find(':'); + if (slash_pos == 0) { + argv0 = buffer[0]; + path = is_exe(argv0); + } else if (slash_pos == std::string::npos || slash_pos > colon_pos) { + std::string penv = cppstr_getenv("PATH"); + if (!penv.empty()) { + retry: + std::string tmp; + std::stringstream sstr(penv); + while (std::getline(sstr, tmp, ':')) { + argv0 = tmp + "/" + buffer[0]; + path = is_exe(argv0); + if (!path.empty()) break; + if (slash_pos > colon_pos) { + argv0 = tmp + "/" + buffer[0].substr(0, colon_pos); + path = is_exe(argv0); + if (!path.empty()) break; + } + } + } + if (path.empty() && !retried) { + retried = true; + penv = "/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin"; + std::string home = cppstr_getenv("HOME"); + if (!home.empty()) { + penv = home + "/bin:" + penv; + } + goto retry; + } + } + if (path.empty() && slash_pos > 0) { + std::string pwd = cppstr_getenv("PWD"); + if (!pwd.empty()) { + argv0 = pwd + "/" + buffer[0]; + path = is_exe(argv0); + } + if (path.empty()) { + char cwd[PATH_MAX]; + if (getcwd(cwd, PATH_MAX)) { + argv0 = std::string(cwd) + "/" + buffer[0]; + path = is_exe(argv0); + } + } + } + } + if (path.empty() && !error) { + error = true; + buffer.clear(); + std::string underscore = cppstr_getenv("_"); + if (!underscore.empty()) { + buffer.push_back(underscore); + goto fallback; + } + } + } + if (!path.empty()) { + errno = 0; + } + return String(path.c_str()); #elif defined(__NetBSD__) int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; char buf[MAXPATHLEN]; From 028f0192e7aa1a77890e36a1e9b98fc319afd277 Mon Sep 17 00:00:00 2001 From: high on tantor Date: Thu, 23 Apr 2026 20:27:22 -0400 Subject: [PATCH 02/10] Fix Formatting --- drivers/unix/os_unix.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 9ef2b57d23..0a4fd6cf10 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -1159,16 +1159,18 @@ String OS_Unix::get_executable_path() const { kinfo_file *kif = nullptr; bool error = false; kd = kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); - if (!kd) return res; + if (!kd) { + return res; + } if ((kif = kvm_getfiles(kd, KERN_FILE_BYPID, getpid(), sizeof(struct kinfo_file), &cntp))) { for (int i = 0; i < cntp && kif[i].fd_fd < 0; i++) { if (kif[i].fd_fd == KERN_FILE_TEXT) { struct stat st; - fallback: + fallback: char buffer[PATH_MAX]; if (!stat(exe.c_str(), &st) && (st.st_mode & S_IXUSR) && - (st.st_mode & S_IFREG) && realpath(exe.c_str(), buffer) && - st.st_dev == (dev_t)kif[i].va_fsid && st.st_ino == (ino_t)kif[i].va_fileid) { + (st.st_mode & S_IFREG) && realpath(exe.c_str(), buffer) && + st.st_dev == (dev_t)kif[i].va_fsid && st.st_ino == (ino_t)kif[i].va_fileid) { res = buffer; } if (res.empty() && !error) { @@ -1213,26 +1215,30 @@ String OS_Unix::get_executable_path() const { if (!buffer.empty()) { std::string argv0; if (!buffer[0].empty()) { - fallback: + fallback: std::size_t slash_pos = buffer[0].find('/'); std::size_t colon_pos = buffer[0].find(':'); if (slash_pos == 0) { argv0 = buffer[0]; path = is_exe(argv0); - } else if (slash_pos == std::string::npos || slash_pos > colon_pos) { + } else if (slash_pos == std::string::npos || slash_pos > colon_pos) { std::string penv = cppstr_getenv("PATH"); if (!penv.empty()) { - retry: + retry: std::string tmp; std::stringstream sstr(penv); while (std::getline(sstr, tmp, ':')) { argv0 = tmp + "/" + buffer[0]; path = is_exe(argv0); - if (!path.empty()) break; + if (!path.empty()) { + break; + } if (slash_pos > colon_pos) { argv0 = tmp + "/" + buffer[0].substr(0, colon_pos); path = is_exe(argv0); - if (!path.empty()) break; + if (!path.empty()) { + break; + } } } } From af782e7b71cc952012bd4b382ddc1c822ddc0266 Mon Sep 17 00:00:00 2001 From: high on tantor Date: Thu, 23 Apr 2026 21:01:46 -0400 Subject: [PATCH 03/10] Various Fixes --- drivers/unix/os_unix.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 0a4fd6cf10..6b4636408c 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -1169,7 +1169,7 @@ String OS_Unix::get_executable_path() const { fallback: char buffer[PATH_MAX]; if (!stat(exe.c_str(), &st) && (st.st_mode & S_IXUSR) && - (st.st_mode & S_IFREG) && realpath(exe.c_str(), buffer) && + S_ISREG(st.st_mode) && realpath(exe.c_str(), buffer) && st.st_dev == (dev_t)kif[i].va_fsid && st.st_ino == (ino_t)kif[i].va_fileid) { res = buffer; } @@ -1279,8 +1279,12 @@ String OS_Unix::get_executable_path() const { } if (!path.empty()) { errno = 0; + } else { + char resolved_path[MAXPATHLEN]; + realpath(OS::get_executable_path().utf8().get_data(), resolved_path); + return String(resolved_path); } - return String(path.c_str()); + return String::utf8(path.c_str()); #elif defined(__NetBSD__) int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; char buf[MAXPATHLEN]; From 06e570994d146647ae353c13dfe08ad17152d774 Mon Sep 17 00:00:00 2001 From: high on tantor Date: Thu, 23 Apr 2026 21:04:56 -0400 Subject: [PATCH 04/10] Add Warning --- drivers/unix/os_unix.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 6b4636408c..f30bb54512 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -1282,6 +1282,7 @@ String OS_Unix::get_executable_path() const { } else { char resolved_path[MAXPATHLEN]; realpath(OS::get_executable_path().utf8().get_data(), resolved_path); + WARN_PRINT("Couldn't get executable path and there is no remaining fallback method"); return String(resolved_path); } return String::utf8(path.c_str()); From 6da2fe415811b5c89df9506ac049d619f09f06bb Mon Sep 17 00:00:00 2001 From: high on tantor Date: Thu, 23 Apr 2026 21:15:38 -0400 Subject: [PATCH 05/10] Fix Warning --- drivers/unix/os_unix.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index f30bb54512..01b11ebdf4 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -1277,13 +1277,9 @@ String OS_Unix::get_executable_path() const { } } } - if (!path.empty()) { - errno = 0; - } else { - char resolved_path[MAXPATHLEN]; - realpath(OS::get_executable_path().utf8().get_data(), resolved_path); - WARN_PRINT("Couldn't get executable path and there is no remaining fallback method"); - return String(resolved_path); + if (path.empty()) { + WARN_PRINT("Couldn't get executable path from any of the methods tried"); + return OS::get_executable_path(); } return String::utf8(path.c_str()); #elif defined(__NetBSD__) From e1d1f574a40346a73405e5f8840872674861ddc3 Mon Sep 17 00:00:00 2001 From: high on tantor Date: Thu, 23 Apr 2026 21:21:01 -0400 Subject: [PATCH 06/10] If You Insist. --- drivers/unix/os_unix.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 01b11ebdf4..3e7502fbdb 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -1278,8 +1278,10 @@ String OS_Unix::get_executable_path() const { } } if (path.empty()) { + char resolved_path[MAXPATHLEN]; + realpath(OS::get_executable_path().utf8().get_data(), resolved_path); WARN_PRINT("Couldn't get executable path from any of the methods tried"); - return OS::get_executable_path(); + return String(resolved_path); } return String::utf8(path.c_str()); #elif defined(__NetBSD__) From 8e9f97670e5f594029d89ac88b28914d981111b2 Mon Sep 17 00:00:00 2001 From: high on tantor Date: Thu, 23 Apr 2026 21:32:04 -0400 Subject: [PATCH 07/10] Type Mismatch Fix --- drivers/unix/os_unix.cpp | 135 +++++++++++++++++++-------------------- 1 file changed, 67 insertions(+), 68 deletions(-) diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 3e7502fbdb..70eab7960b 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -1199,91 +1199,90 @@ String OS_Unix::get_executable_path() const { std::vector buffer; bool error = false, retried = false; kd = kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); - if (!kd) { - path.clear(); - return path; - } - if ((proc_info = kvm_getprocs(kd, KERN_PROC_PID, getpid(), sizeof(struct kinfo_proc), &cntp))) { - char **cmd = kvm_getargv(kd, proc_info, 0); - if (cmd) { - for (int i = 0; cmd[i]; i++) { - buffer.push_back(cmd[i]); + if (kd) { + if ((proc_info = kvm_getprocs(kd, KERN_PROC_PID, getpid(), sizeof(struct kinfo_proc), &cntp))) { + char **cmd = kvm_getargv(kd, proc_info, 0); + if (cmd) { + for (int i = 0; cmd[i]; i++) { + buffer.push_back(cmd[i]); + } } } - } - kvm_close(kd); - if (!buffer.empty()) { - std::string argv0; - if (!buffer[0].empty()) { - fallback: - std::size_t slash_pos = buffer[0].find('/'); - std::size_t colon_pos = buffer[0].find(':'); - if (slash_pos == 0) { - argv0 = buffer[0]; - path = is_exe(argv0); - } else if (slash_pos == std::string::npos || slash_pos > colon_pos) { - std::string penv = cppstr_getenv("PATH"); - if (!penv.empty()) { - retry: - std::string tmp; - std::stringstream sstr(penv); - while (std::getline(sstr, tmp, ':')) { - argv0 = tmp + "/" + buffer[0]; - path = is_exe(argv0); - if (!path.empty()) { - break; - } - if (slash_pos > colon_pos) { - argv0 = tmp + "/" + buffer[0].substr(0, colon_pos); + kvm_close(kd); + if (!buffer.empty()) { + std::string argv0; + if (!buffer[0].empty()) { + fallback: + std::size_t slash_pos = buffer[0].find('/'); + std::size_t colon_pos = buffer[0].find(':'); + if (slash_pos == 0) { + argv0 = buffer[0]; + path = is_exe(argv0); + } else if (slash_pos == std::string::npos || slash_pos > colon_pos) { + std::string penv = cppstr_getenv("PATH"); + if (!penv.empty()) { + retry: + std::string tmp; + std::stringstream sstr(penv); + while (std::getline(sstr, tmp, ':')) { + argv0 = tmp + "/" + buffer[0]; path = is_exe(argv0); if (!path.empty()) { break; } + if (slash_pos > colon_pos) { + argv0 = tmp + "/" + buffer[0].substr(0, colon_pos); + path = is_exe(argv0); + if (!path.empty()) { + break; + } + } } } - } - if (path.empty() && !retried) { - retried = true; - penv = "/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin"; - std::string home = cppstr_getenv("HOME"); - if (!home.empty()) { - penv = home + "/bin:" + penv; + if (path.empty() && !retried) { + retried = true; + penv = "/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin"; + std::string home = cppstr_getenv("HOME"); + if (!home.empty()) { + penv = home + "/bin:" + penv; + } + goto retry; } - goto retry; - } - } - if (path.empty() && slash_pos > 0) { - std::string pwd = cppstr_getenv("PWD"); - if (!pwd.empty()) { - argv0 = pwd + "/" + buffer[0]; - path = is_exe(argv0); } - if (path.empty()) { - char cwd[PATH_MAX]; - if (getcwd(cwd, PATH_MAX)) { - argv0 = std::string(cwd) + "/" + buffer[0]; + if (path.empty() && slash_pos > 0) { + std::string pwd = cppstr_getenv("PWD"); + if (!pwd.empty()) { + argv0 = pwd + "/" + buffer[0]; path = is_exe(argv0); } + if (path.empty()) { + char cwd[PATH_MAX]; + if (getcwd(cwd, PATH_MAX)) { + argv0 = std::string(cwd) + "/" + buffer[0]; + path = is_exe(argv0); + } + } } } - } - if (path.empty() && !error) { - error = true; - buffer.clear(); - std::string underscore = cppstr_getenv("_"); - if (!underscore.empty()) { - buffer.push_back(underscore); - goto fallback; + if (path.empty() && !error) { + error = true; + buffer.clear(); + std::string underscore = cppstr_getenv("_"); + if (!underscore.empty()) { + buffer.push_back(underscore); + goto fallback; + } } } + if (!path.empty()) { + return String::utf8(path.c_str()); + } } - if (path.empty()) { - char resolved_path[MAXPATHLEN]; - realpath(OS::get_executable_path().utf8().get_data(), resolved_path); - WARN_PRINT("Couldn't get executable path from any of the methods tried"); - return String(resolved_path); - } - return String::utf8(path.c_str()); + char resolved_path[MAXPATHLEN]; + realpath(OS::get_executable_path().utf8().get_data(), resolved_path); + WARN_PRINT("Couldn't get executable path from any of the methods tried"); + return String(resolved_path); +} #elif defined(__NetBSD__) int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; char buf[MAXPATHLEN]; From 092d1372151a3de39f21233f99791c550335fe6c Mon Sep 17 00:00:00 2001 From: high on tantor Date: Thu, 23 Apr 2026 21:38:57 -0400 Subject: [PATCH 08/10] Add -lkvm Flag --- platform/linuxbsd/detect.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index a99c0db77f..67ebf60556 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -533,6 +533,9 @@ def configure(env: "SConsEnvironment"): if platform.system() == "FreeBSD": env.Append(LINKFLAGS=["-lkvm"]) + if platform.system() == "OpenBSD": + env.Append(LINKFLAGS=["-lkvm"]) + # Link those statically for portability if env["use_static_cpp"]: env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"]) From 69e9a4d216e8b0d67fc82774c9f5ba4dbb8efade Mon Sep 17 00:00:00 2001 From: high on tantor Date: Thu, 23 Apr 2026 21:44:04 -0400 Subject: [PATCH 09/10] Add UTF-8 --- drivers/unix/os_unix.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 70eab7960b..43d261ce2a 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -1280,8 +1280,8 @@ String OS_Unix::get_executable_path() const { } char resolved_path[MAXPATHLEN]; realpath(OS::get_executable_path().utf8().get_data(), resolved_path); - WARN_PRINT("Couldn't get executable path from any of the methods tried"); - return String(resolved_path); + WARN_PRINT("Couldn't get executable path from any of the methods tried"); + return String::utf8(resolved_path); } #elif defined(__NetBSD__) int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; @@ -1297,7 +1297,7 @@ String OS_Unix::get_executable_path() const { realpath(buf, resolved_path); - return String(resolved_path); + return String::utf8(resolved_path); #elif defined(__FreeBSD__) int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; char buf[MAXPATHLEN]; From 9df82875e95a2369a5edaa8be7c50b38875b59ec Mon Sep 17 00:00:00 2001 From: high on tantor Date: Thu, 23 Apr 2026 21:46:47 -0400 Subject: [PATCH 10/10] Update os_unix.cpp --- drivers/unix/os_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 43d261ce2a..61906d9e88 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -1280,7 +1280,7 @@ String OS_Unix::get_executable_path() const { } char resolved_path[MAXPATHLEN]; realpath(OS::get_executable_path().utf8().get_data(), resolved_path); - WARN_PRINT("Couldn't get executable path from any of the methods tried"); + WARN_PRINT("Couldn't get executable path from any of the methods tried"); return String::utf8(resolved_path); } #elif defined(__NetBSD__)