$OpenBSD: patch-components_crashcatcher_crashcatcher_cpp,v 1.1 2019/11/25 10:21:25 solene Exp $

Fixes game failing to start.
Upstream commit fe69e5507df97d84d3cb29d760da78f64e41cc07

Index: components/crashcatcher/crashcatcher.cpp
--- components/crashcatcher/crashcatcher.cpp.orig
+++ components/crashcatcher/crashcatcher.cpp
@@ -17,6 +17,7 @@
 #include <components/debug/debuglog.hpp>
 
 #include <boost/filesystem/fstream.hpp>
+#include <boost/filesystem/operations.hpp>
 
 namespace bfs = boost::filesystem;
 
@@ -34,9 +35,13 @@ namespace bfs = boost::filesystem;
 
 #if defined(__APPLE__)
 #include <sys/sysctl.h>
+#include <libproc.h>
 #endif
 
-#define UNUSED(x) (void)(x)
+#if defined(__FreeBSD__)
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#endif
 
 static const char crash_switch[] = "--cc-handle-crash";
 
@@ -413,6 +418,39 @@ static void crash_handler(const char *logfile)
     exit(0);
 }
 
+static void getExecPath(char **argv)
+{
+#if defined (__FreeBSD__)
+    int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
+    size_t size = sizeof(argv0);
+
+    if (sysctl(mib, 4, argv0, &size, nullptr, 0) == 0)
+        return;
+#endif
+
+#if defined (__APPLE__)
+    if(proc_pidpath(getpid(), argv0, sizeof(argv0)) > 0)
+        return;
+#endif
+    int cwdlen;
+    const char *statusPaths[] = {"/proc/self/exe", "/proc/self/file", "/proc/curproc/exe", "/proc/curproc/file"};
+    memset(argv0, 0, sizeof(argv0));
+
+    for(const char *path : statusPaths)
+    {
+        if (readlink(path, argv0, sizeof(argv0)) != -1)
+            return;
+    }
+
+    if(argv[0][0] == '/')
+        snprintf(argv0, sizeof(argv0), "%s", argv[0]);
+    else if (getcwd(argv0, sizeof(argv0)) != NULL)
+    {
+        cwdlen = strlen(argv0);
+        snprintf(argv0+cwdlen, sizeof(argv0)-cwdlen, "/%s", argv[0]);
+    }
+}
+
 int crashCatcherInstallHandlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*))
 {
     struct sigaction sa;
@@ -424,20 +462,7 @@ int crashCatcherInstallHandlers(int argc, char **argv,
 
     cc_user_info = user_info;
 
-    if(argv[0][0] == '/')
-        snprintf(argv0, sizeof(argv0), "%s", argv[0]);
-    else
-    {
-        {
-            /* we don't want to disable "ignoring return value" warnings, so we make
-             * a special exception here. */
-            char * unused;
-            unused = getcwd(argv0, sizeof(argv0));
-            UNUSED(unused);
-        }
-        retval = strlen(argv0);
-        snprintf(argv0+retval, sizeof(argv0)-retval, "/%s", argv[0]);
-    }
+    getExecPath(argv);
 
     /* Set an alternate signal stack so SIGSEGVs caused by stack overflows
      * still run */
@@ -467,20 +492,24 @@ int crashCatcherInstallHandlers(int argc, char **argv,
 
 static bool is_debugger_present()
 {
-#if !defined (__APPLE__)
-    bfs::ifstream file((bfs::path("/proc/self/status")));
-    while (!file.eof())
+#if defined (__linux__)
+    bfs::path procstatus = bfs::path("/proc/self/status");
+    if (bfs::exists(procstatus))
     {
-        std::string word;
-        file >> word;
-        if (word == "TracerPid:")
+        bfs::ifstream file((procstatus));
+        while (!file.eof())
         {
+            std::string word;
             file >> word;
-            return word != "0";
+            if (word == "TracerPid:")
+            {
+                file >> word;
+                return word != "0";
+            }
         }
     }
     return false;
-#else
+#elif defined(__APPLE__)
     int junk;
     int mib[4];
     struct kinfo_proc info;
@@ -508,12 +537,24 @@ static bool is_debugger_present()
     // We're being debugged if the P_TRACED flag is set.
 
     return (info.kp_proc.p_flag & P_TRACED) != 0;
+#elif defined(__FreeBSD__)
+    struct kinfo_proc info;
+    size_t size = sizeof(info);
+    int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
+
+    if (sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) == 0)
+        return (info.ki_flag & P_TRACED) != 0;
+    else
+        perror("Failed to retrieve process info");
+    return false;
+#else
+    return false;
 #endif
 }
 
 void crashCatcherInstall(int argc, char **argv, const std::string &crashLogPath)
 {
-    if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_present())
+    if ((argc == 2 && strcmp(argv[1], crash_switch) == 0) || !is_debugger_present())
     {
         int s[5] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGABRT };
         if (crashCatcherInstallHandlers(argc, argv, 5, s, crashLogPath.c_str(), nullptr) == -1)
