Fix Android multicall build

ober

f1347baa0ea481e747c61a50ec3eb2cba1e00759

diff --git a/data/error-fixes.sexp b/data/error-fixes.sexp
index c085552..1239f5c 100644
--- a/data/error-fixes.sexp
+++ b/data/error-fixes.sexp
@@ -2580,4 +2580,18 @@
    ("pattern"
      .
      "mktemp: failed to create directory via template .*/tmp/.*: Permission denied")
-   ("type" . "build")))
+   ("type" . "build"))
+ (("code_example"
+    .
+    "#if defined(__ANDROID__)\nstatic int *jerboa_errno_location(void) { return __errno(); }\nstatic int jerboa_ioctl(int fd, unsigned long request, void *arg) { return ioctl(fd, request, arg); }\nstatic mode_t jerboa_umask(mode_t mode) { return umask(mode); }\n#endif")
+   ("explanation"
+     .
+     "Bionic uses __errno instead of glibc's __errno_location and exposes some libc calls through clang overloadable/fortify declarations, making direct function-address registration ambiguous. A wrapper provides a single concrete symbol signature for Chez foreign-procedure lookup.")
+   ("fix"
+     .
+     "On Android/bionic, do not register libc symbols by taking direct addresses of bionic overloadable/fortified functions. Register small compatibility wrappers instead: map __errno_location to __errno(), wrap ioctl(int,unsigned long,void*), wrap variadic open(const char*,int,...), and wrap umask(mode_t).")
+   ("id" . "android-bionic-multicall-libc-wrappers")
+   ("pattern"
+     .
+     "use of undeclared identifier '__errno_location'|address of overloaded function 'ioctl' is ambiguous|address of overloaded function 'open' is ambiguous|address of overloaded function 'umask' is ambiguous")
+   ("type" . "compile")))
diff --git a/support/build-jerboa-multicall.ss b/support/build-jerboa-multicall.ss
index 5e1bdf4..17bd163 100644
--- a/support/build-jerboa-multicall.ss
+++ b/support/build-jerboa-multicall.ss
@@ -387,6 +387,16 @@
         [(string-suffix? m "nt")  'windows]
         [else 'linux]))
 (define target-os (machine->os machine))
+(define termux-prefix
+  (let ([p (getenv "PREFIX")])
+    (if (and p (> (string-length p) 0))
+        p
+        "/data/data/com.termux/files/usr")))
+(define termux-android-native?
+  (and (not cross?)
+       (eq? target-os 'linux)
+       (or (env "TERMUX_VERSION" #f)
+           (string-prefix? "/data/data/com.termux/files/usr" termux-prefix))))
 (define bundle-tar-command
   (if (eq? target-os 'darwin)
       "COPYFILE_DISABLE=1 tar --no-xattrs --no-mac-metadata"
@@ -1499,7 +1509,9 @@
         [(freebsd) "-lm -lpthread"]
         [(darwin)  "-lm -lpthread"]
         [else      "-lm -lpthread"])
-      (cond [(string-suffix? machine "osx") "-lm -lpthread -lncurses -liconv"]
+      (cond [termux-android-native?
+             (format "-L~a/lib -lm -ldl -lpthread -lncurses -liconv" termux-prefix)]
+            [(string-suffix? machine "osx") "-lm -lpthread -lncurses -liconv"]
             [(string-suffix? machine "fb")  "-lm -lpthread -lncurses -L/usr/local/lib -liconv"]
             [else "-lm -ldl -lpthread -lncurses"])))
 ;; Libs jerbuild must pass when it links an ON-TARGET binary against this
diff --git a/support/multicall-main.c b/support/multicall-main.c
index 9e568e5..c9f9cfc 100644
--- a/support/multicall-main.c
+++ b/support/multicall-main.c
@@ -20,6 +20,7 @@
 #include <fcntl.h>
 #include <pwd.h>
 #include <signal.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -51,6 +52,31 @@
 
 static ssize_t (*const posix_write_fn)(int, const void *, size_t) = write;
 
+#if defined(__ANDROID__)
+static int *jerboa_errno_location(void) {
+    return __errno();
+}
+
+static int jerboa_ioctl(int fd, unsigned long request, void *arg) {
+    return ioctl(fd, request, arg);
+}
+
+static int jerboa_open(const char *path, int flags, ...) {
+    mode_t mode = 0;
+    if ((flags & O_CREAT) != 0) {
+        va_list ap;
+        va_start(ap, flags);
+        mode = (mode_t)va_arg(ap, int);
+        va_end(ap);
+    }
+    return open(path, flags, mode);
+}
+
+static mode_t jerboa_umask(mode_t mode) {
+    return umask(mode);
+}
+#endif
+
 static void call_scheme_1(const char *who, ptr arg) {
     Scall1(Stop_level_value(Sstring_to_symbol(who)), arg);
 }
@@ -245,7 +271,29 @@ static const char *ensure_extracted(void) {
 }
 
 static const char *write_program_tmpfile(void) {
-    static char path[] = "/tmp/jerboa-prog-XXXXXX";
+    static char path[4096];
+    const char *tmpdir = getenv("TMPDIR");
+    if (tmpdir == NULL || tmpdir[0] == '\0' || access(tmpdir, W_OK) != 0) {
+        const char *prefix = getenv("PREFIX");
+        if (prefix != NULL && prefix[0] != '\0') {
+            int n = snprintf(path, sizeof(path), "%s/tmp", prefix);
+            if (n > 0 && (size_t)n < sizeof(path) && access(path, W_OK) == 0) {
+                tmpdir = path;
+            } else {
+                tmpdir = NULL;
+            }
+        } else {
+            tmpdir = NULL;
+        }
+    }
+    if (tmpdir == NULL || tmpdir[0] == '\0') {
+        tmpdir = (access("/tmp", W_OK) == 0) ? "/tmp" : ".";
+    }
+    int len = snprintf(path, sizeof(path), "%s/jerboa-prog-XXXXXX", tmpdir);
+    if (len <= 0 || (size_t)len >= sizeof(path)) {
+        fprintf(stderr, "temporary path too long\n");
+        exit(1);
+    }
     int fd = mkstemp(path);
     if (fd < 0) { perror("mkstemp"); exit(1); }
     if (write_all_retry(fd, program_boot_data, program_boot_size) != 0) {
@@ -273,7 +321,10 @@ static void configure_embedded_library_paths(void) {
  * host executable to publish them explicitly. */
 static void register_symbols(void) {
     Sforeign_symbol("strerror", (void *)strerror);
-#if defined(__APPLE__) || defined(__FreeBSD__)
+#if defined(__ANDROID__)
+    Sforeign_symbol("__errno_location", (void *)jerboa_errno_location);
+    Sforeign_symbol("__errno", (void *)jerboa_errno_location);
+#elif defined(__APPLE__) || defined(__FreeBSD__)
     Sforeign_symbol("__error", (void *)__error);
 #else
     Sforeign_symbol("__errno_location", (void *)__errno_location);
@@ -298,14 +349,22 @@ static void register_symbols(void) {
     Sforeign_symbol("getppid", (void *)getppid);
     Sforeign_symbol("getrlimit", (void *)getrlimit);
     Sforeign_symbol("getuid", (void *)getuid);
+#if defined(__ANDROID__)
+    Sforeign_symbol("ioctl", (void *)jerboa_ioctl);
+#else
     Sforeign_symbol("ioctl", (void *)ioctl);
+#endif
     Sforeign_symbol("isatty", (void *)isatty);
     Sforeign_symbol("kill", (void *)kill);
     Sforeign_symbol("localtime", (void *)localtime);
     Sforeign_symbol("lseek", (void *)lseek);
     Sforeign_symbol("lstat", (void *)lstat);
     Sforeign_symbol("mkfifo", (void *)mkfifo);
+#if defined(__ANDROID__)
+    Sforeign_symbol("open", (void *)jerboa_open);
+#else
     Sforeign_symbol("open", (void *)open);
+#endif
     Sforeign_symbol("pipe", (void *)pipe);
     Sforeign_symbol("read", (void *)read);
     Sforeign_symbol("readlink", (void *)readlink);
@@ -333,7 +392,11 @@ static void register_symbols(void) {
     Sforeign_symbol("tcgetpgrp", (void *)tcgetpgrp);
     Sforeign_symbol("tcsetattr", (void *)tcsetattr);
     Sforeign_symbol("tcsetpgrp", (void *)tcsetpgrp);
+#if defined(__ANDROID__)
+    Sforeign_symbol("umask", (void *)jerboa_umask);
+#else
     Sforeign_symbol("umask", (void *)umask);
+#endif
     Sforeign_symbol("unlink", (void *)unlink);
     Sforeign_symbol("unsetenv", (void *)unsetenv);
     Sforeign_symbol("waitpid", (void *)waitpid);