This commit is contained in:
Mars 2025-05-03 02:11:25 -04:00
parent f5c138bc86
commit 84df352751
Signed by: pupbrained
GPG key ID: 0FF5B8826803F895

View file

@ -43,16 +43,13 @@ namespace {
mib[2] = pid; mib[2] = pid;
mib[3] = KERN_PROC_PATHNAME; // The specific subcommand mib[3] = KERN_PROC_PATHNAME; // The specific subcommand
if (sysctl(mib, 4, exePathBuf.data(), &size, nullptr, 0) == -1) { if (sysctl(mib, 4, exePathBuf.data(), &size, nullptr, 0) == -1)
// Fallback for older systems or if KERN_PROC_PATHNAME is restricted/unavailable
// Note: KERN_PROC_ARGS might give args too, need parsing.
// For simplicity, we'll just report the error for now.
return Err(DracError::withErrno(std::format("sysctl KERN_PROC_PATHNAME failed for pid {}", pid))); return Err(DracError::withErrno(std::format("sysctl KERN_PROC_PATHNAME failed for pid {}", pid)));
}
if (size == 0 || exePathBuf[0] == '\0') { if (size == 0 || exePathBuf[0] == '\0')
return Err(DracError(DracErrorCode::NotFound, std::format("sysctl KERN_PROC_PATHNAME returned empty path for pid {}", pid))); return Err(
} DracError(DracErrorCode::NotFound, std::format("sysctl KERN_PROC_PATHNAME returned empty path for pid {}", pid))
);
exePathBuf[std::min(size, exePathBuf.size() - 1)] = '\0'; exePathBuf[std::min(size, exePathBuf.size() - 1)] = '\0';
@ -150,53 +147,49 @@ namespace {
pid_t peer_pid = -1; // Initialize PID pid_t peer_pid = -1; // Initialize PID
#if defined(__FreeBSD__) || defined(__DragonFly__) #if defined(__FreeBSD__) || defined(__DragonFly__)
struct xucred cred; // Use xucred on FreeBSD/DragonFly struct xucred cred;
socklen_t len = sizeof(cred);
if (getsockopt(fileDescriptor, SOL_SOCKET, LOCAL_PEERCRED, &cred, &len) == -1) {
return Err(DracError::withErrno("Failed to get socket credentials (LOCAL_PEERCRED)"));
}
if (len != sizeof(cred) || cred.cr_version != XUCRED_VERSION) {
return Err(DracError(DracErrorCode::PlatformSpecific, "Invalid xucred structure received"));
}
peer_pid = cred.cr_pid; // <<< Get PID from xucred
#elif defined(__NetBSD__) socklen_t len = sizeof(cred);
if (getsockopt(fileDescriptor, SOL_SOCKET, LOCAL_PEERCRED, &cred, &len) == -1)
return Err(DracError::withErrno("Failed to get socket credentials (LOCAL_PEERCRED)"));
if (len != sizeof(cred) || cred.cr_version != XUCRED_VERSION)
return Err(DracError(DracErrorCode::PlatformSpecific, "Invalid xucred structure received"));
peer_pid = cred.cr_pid;
#elif defined(__NetBSD__)
uid_t euid; uid_t euid;
gid_t egid; gid_t egid;
if (getpeereid(fileDescriptor, &euid, &egid) == -1) {
if (getpeereid(fileDescriptor, &euid, &egid) == -1)
return Err(DracError::withErrno("getpeereid failed on Wayland socket")); return Err(DracError::withErrno("getpeereid failed on Wayland socket"));
}
return "Wayland Compositor (Unknown Path)"; return "Wayland Compositor (Unknown Path)";
#endif #endif
if (peer_pid <= 0) { if (peer_pid <= 0)
return Err(DracError(DracErrorCode::PlatformSpecific, "Failed to obtain a valid peer PID")); return Err(DracError(DracErrorCode::PlatformSpecific, "Failed to obtain a valid peer PID"));
}
// --- Use the helper function to get the path ---
Result<String, DracError> exePathResult = GetPathByPid(peer_pid); Result<String, DracError> exePathResult = GetPathByPid(peer_pid);
if (!exePathResult) { if (!exePathResult) {
// Forward the error from GetPathByPid
return Err(std::move(exePathResult).error()); return Err(std::move(exePathResult).error());
} }
const String& exeRealPath = *exePathResult; const String& exeRealPath = *exePathResult;
// --- Extract filename from path (OS-independent) ---
StringView compositorNameView; StringView compositorNameView;
if (const usize lastSlash = exeRealPath.rfind('/'); lastSlash != String::npos) {
if (const usize lastSlash = exeRealPath.rfind('/'); lastSlash != String::npos)
compositorNameView = StringView(exeRealPath).substr(lastSlash + 1); compositorNameView = StringView(exeRealPath).substr(lastSlash + 1);
} else { else
compositorNameView = exeRealPath; // Path is just the filename compositorNameView = exeRealPath;
}
if (compositorNameView.empty() || compositorNameView == "." || compositorNameView == "/") if (compositorNameView.empty() || compositorNameView == "." || compositorNameView == "/")
return Err(DracError(DracErrorCode::NotFound, "Failed to get compositor name from path")); return Err(DracError(DracErrorCode::NotFound, "Failed to get compositor name from path"));
// --- Heuristic cleanup (OS-independent) ---
if (constexpr StringView wrappedSuffix = "-wrapped"; compositorNameView.length() > 1 + wrappedSuffix.length() && if (constexpr StringView wrappedSuffix = "-wrapped"; compositorNameView.length() > 1 + wrappedSuffix.length() &&
compositorNameView[0] == '.' && compositorNameView.ends_with(wrappedSuffix)) { compositorNameView[0] == '.' && compositorNameView.ends_with(wrappedSuffix)) {
const StringView cleanedView = const StringView cleanedView =
@ -238,13 +231,14 @@ namespace os {
} }
utsname uts; utsname uts;
if (uname(&uts) == -1) if (uname(&uts) == -1)
return Err(DracError::withErrno(std::format("Failed to open {} and uname() call also failed", path))); return Err(DracError::withErrno(std::format("Failed to open {} and uname() call also failed", path)));
String osName = uts.sysname; String osName = uts.sysname;
if (osName.empty()) if (osName.empty())
return Err(DracError(DracErrorCode::ParseError,"uname() returned empty sysname or release")); return Err(DracError(DracErrorCode::ParseError, "uname() returned empty sysname or release"));
return osName; return osName;
} }
@ -253,11 +247,11 @@ namespace os {
u64 mem = 0; u64 mem = 0;
usize size = sizeof(mem); usize size = sizeof(mem);
#ifdef __NetBSD__ #ifdef __NetBSD__
sysctlbyname("hw.physmem64", &mem, &size, nullptr, 0); sysctlbyname("hw.physmem64", &mem, &size, nullptr, 0);
#else #else
sysctlbyname("hw.physmem", &mem, &size, nullptr, 0); sysctlbyname("hw.physmem", &mem, &size, nullptr, 0);
#endif #endif
return mem; return mem;
} }
@ -446,40 +440,33 @@ namespace os {
Array<char, 256> buffer {}; Array<char, 256> buffer {};
usize size = buffer.size(); usize size = buffer.size();
#if defined(__FreeBSD__) || defined(__DragonFly__) #if defined(__FreeBSD__) || defined(__DragonFly__)
// Use kenv on FreeBSD / DragonFly int result = kenv(KENV_GET, "smbios.system.product", buffer.data(), buffer.size() - 1); // Ensure space for null
int result = kenv(KENV_GET, "smbios.system.product", buffer.data(), buffer.size() -1); // Ensure space for null
if (result == -1) { if (result == -1) {
// Fallback: Maybe try hw.model? if (sysctlbyname("hw.model", buffer.data(), &size, nullptr, 0) == -1)
if (sysctlbyname("hw.model", buffer.data(), &size, nullptr, 0) == -1) {
return Err(DracError::withErrno("kenv smbios.system.product failed and sysctl hw.model also failed")); return Err(DracError::withErrno("kenv smbios.system.product failed and sysctl hw.model also failed"));
}
buffer[std::min(size, buffer.size() - 1)] = '\0'; // Null terminate sysctl result buffer[std::min(size, buffer.size() - 1)] = '\0';
return String(buffer.data()); return String(buffer.data());
} }
// kenv should null-terminate, but let's be safe if result > 0 (bytes written)
if (result > 0) buffer[result] = '\0';
else buffer[0] = '\0'; // Ensure null if result was 0 (empty string?)
#elif defined(__NetBSD__) if (result > 0)
// Use sysctl on NetBSD buffer[result] = '\0';
constexpr const char* netbsd_mib = "machdep.dmi.system-product"; else
if (sysctlbyname(netbsd_mib, buffer.data(), &size, nullptr, 0) == -1) { buffer[0] = '\0';
// Fallback: Try hw.model on NetBSD too
size = buffer.size(); // reset size for next attempt #elif defined(__NetBSD__)
if (sysctlbyname("hw.model", buffer.data(), &size, nullptr, 0) == -1) { if (sysctlbyname("machdep.dmi.system-product", buffer.data(), &size, nullptr, 0) == -1)
return Err(DracError::withErrno(std::format("sysctlbyname failed for both {} and hw.model", netbsd_mib))); return Err(DracError::withErrno(std::format("sysctlbyname failed for")));
}
}
// Ensure null termination for sysctl results
buffer[std::min(size, buffer.size() - 1)] = '\0'; buffer[std::min(size, buffer.size() - 1)] = '\0';
#endif #endif
// Ensure the buffer isn't empty before returning if (buffer[0] == '\0')
if(buffer[0] == '\0') {
return Err(DracError(DracErrorCode::NotFound, "Failed to get host product information (empty result)")); return Err(DracError(DracErrorCode::NotFound, "Failed to get host product information (empty result)"));
}
return String(buffer.data());} return String(buffer.data());
}
fn GetKernelVersion() -> Result<String, DracError> { fn GetKernelVersion() -> Result<String, DracError> {
utsname uts; utsname uts;
@ -508,4 +495,4 @@ namespace os {
fn GetPackageCount() -> Result<u64, DracError> { return shared::GetPackageCount(); } fn GetPackageCount() -> Result<u64, DracError> { return shared::GetPackageCount(); }
} // namespace os } // namespace os
#endif // __FreeBSD__ || __DragonFly__ #endif // __FreeBSD__ || __DragonFly__ || __NetBSD__