From 6125e8a367a77684aa245e898f80dac3009a301a Mon Sep 17 00:00:00 2001
From: "Rafael G. Martins" <rafael@rafaelmartins.eng.br>
Date: Wed, 1 Mar 2017 23:10:54 +0100
Subject: make: implement binary lookup in a more portable way

---
 src/blogc-make/exec.c             | 38 +++++++++++---------------------------
 src/blogc-make/main.c             |  9 +++++++++
 tests/blogc-make/check_atom.c     |  2 ++
 tests/blogc-make/check_exec.c     |  2 ++
 tests/blogc-make/check_rules.c    |  2 ++
 tests/blogc-make/check_settings.c |  2 ++
 6 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/src/blogc-make/exec.c b/src/blogc-make/exec.c
index 2fc46d8..1dab7fd 100644
--- a/src/blogc-make/exec.c
+++ b/src/blogc-make/exec.c
@@ -14,13 +14,6 @@
 #include <sys/wait.h>
 #include <errno.h>
 #include <libgen.h>
-
-#ifdef __FreeBSD__
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#endif
-
 #include "../common/error.h"
 #include "../common/file.h"
 #include "../common/utils.h"
@@ -28,6 +21,8 @@
 #include "exec.h"
 #include "settings.h"
 
+extern const char *argv0;
+
 
 char*
 bm_exec_find_binary(const char *bin, const char *env)
@@ -39,26 +34,15 @@ bm_exec_find_binary(const char *bin, const char *env)
     }
 
     // second try: same dir as current exec
-    char *path = realpath("/proc/self/exe", NULL);  // Linux
-#ifdef __FreeBSD__
-    if (path == NULL) {
-        path = realpath("/proc/curproc/file", NULL);  // FreeBSD with /proc
-        if (path == NULL) {
-            // FreeBSD without /proc (default for 11.0)
-            int name[4];
-            name[0] = CTL_KERN;
-            name[1] = KERN_PROC;
-            name[2] = KERN_PROC_PATHNAME;
-            name[3] = -1;
-            char buf[PATH_MAX];
-            size_t buf_len = sizeof(buf);
-            if (-1 != sysctl(name, 4, buf, &buf_len, NULL, 0)) {
-                path = bc_strdup_printf("%.*s", buf_len, buf);
-            }
-        }
-    }
-#endif
-    if (path != NULL) {
+    // we rely on some assumptions here:
+    //
+    // - if binary is called without a directory, that means location will
+    //   be resolved from $PATH, we don't care about doing a dir lookup.
+    // - we *never* call chdir anywhere in the code, so we can assume
+    //   that relative paths will work as expected.
+    // - windows path sep is not supported
+    if (argv0 != NULL && (NULL != strchr(argv0, '/'))) {
+        char *path = bc_strdup(argv0);
         char *dir = bc_strdup(dirname(path));
         free(path);
         char *tmp = bc_strdup_printf("%s/%s", dir, bin);
diff --git a/src/blogc-make/main.c b/src/blogc-make/main.c
index 05b3205..e5a5ac4 100644
--- a/src/blogc-make/main.c
+++ b/src/blogc-make/main.c
@@ -19,6 +19,10 @@
 #include "ctx.h"
 #include "rules.h"
 
+// is this beautiful? no. but there's no point in passing something that is
+// essentially global to every function in exec.c
+const char *argv0 = NULL;
+
 
 static void
 print_help(void)
@@ -57,6 +61,11 @@ main(int argc, char **argv)
 {
     setlocale(LC_ALL, "");
 
+    // i really hope that no operating system omits argv[0], but ...
+    if (argc > 0) {
+        argv0 = argv[0];
+    }
+
     int rv = 0;
     bc_error_t *err = NULL;
 
diff --git a/tests/blogc-make/check_atom.c b/tests/blogc-make/check_atom.c
index 6faa53e..e487d30 100644
--- a/tests/blogc-make/check_atom.c
+++ b/tests/blogc-make/check_atom.c
@@ -20,6 +20,8 @@
 #include "../../src/common/error.h"
 #include "../../src/common/utils.h"
 
+const char *argv0 = NULL;
+
 
 static void
 test_atom_file(void **state)
diff --git a/tests/blogc-make/check_exec.c b/tests/blogc-make/check_exec.c
index 7b7f3bc..43ef161 100644
--- a/tests/blogc-make/check_exec.c
+++ b/tests/blogc-make/check_exec.c
@@ -18,6 +18,8 @@
 #include "../../src/blogc-make/settings.h"
 #include "../../src/common/utils.h"
 
+const char *argv0 = NULL;
+
 
 static void
 test_build_blogc_cmd_with_settings(void **state)
diff --git a/tests/blogc-make/check_rules.c b/tests/blogc-make/check_rules.c
index c8bd9a8..773ff06 100644
--- a/tests/blogc-make/check_rules.c
+++ b/tests/blogc-make/check_rules.c
@@ -17,6 +17,8 @@
 #include "../../src/blogc-make/rules.h"
 #include "../../src/common/utils.h"
 
+const char *argv0 = NULL;
+
 
 static void
 test_rule_parse_args(void **state)
diff --git a/tests/blogc-make/check_settings.c b/tests/blogc-make/check_settings.c
index 93aed59..3bdc9c5 100644
--- a/tests/blogc-make/check_settings.c
+++ b/tests/blogc-make/check_settings.c
@@ -18,6 +18,8 @@
 #include "../../src/common/error.h"
 #include "../../src/common/utils.h"
 
+const char *argv0 = NULL;
+
 
 static void
 test_settings_empty(void **state)
-- 
cgit v1.2.3-18-g5258