Merge "Switch to the upstream OpenBSD getenv/putenv/setenv implementation."
diff --git a/libc/Android.mk b/libc/Android.mk
index b674adf..ca46929 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -68,8 +68,6 @@
     bionic/sigblock.c \
     bionic/siginterrupt.c \
     bionic/sigsetmask.c \
-    bionic/strntoimax.c \
-    bionic/strntoumax.c \
     bionic/system_properties_compat.c \
     bionic/unlockpt.c \
     stdio/findfp.c \
diff --git a/libc/bionic/ndk_cruft.cpp b/libc/bionic/ndk_cruft.cpp
index 7826651..2fed492 100644
--- a/libc/bionic/ndk_cruft.cpp
+++ b/libc/bionic/ndk_cruft.cpp
@@ -116,4 +116,72 @@
   return s;
 }
 
+static inline int digitval(int ch) {
+  unsigned d;
+
+  d = (unsigned)(ch - '0');
+  if (d < 10) return (int)d;
+
+  d = (unsigned)(ch - 'a');
+  if (d < 6) return (int)(d+10);
+
+  d = (unsigned)(ch - 'A');
+  if (d < 6) return (int)(d+10);
+
+  return -1;
+}
+
+// This non-standard function was in our <inttypes.h> for some reason.
+extern "C" uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) {
+  const unsigned char*  p   = (const unsigned char *)nptr;
+  const unsigned char*  end = p + n;
+  int                   minus = 0;
+  uintmax_t             v = 0;
+  int                   d;
+
+  while (p < end && isspace(*p)) {
+    p++;
+  }
+
+  if (p < end) {
+    char c = p[0];
+    if (c == '-' || c == '+') {
+      minus = (c == '-');
+      p++;
+    }
+  }
+
+  if (base == 0) {
+    if (p+2 < end && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+      p += 2;
+      base = 16;
+    } else if (p+1 < end && p[0] == '0') {
+      p   += 1;
+      base = 8;
+    } else {
+      base = 10;
+    }
+  } else if (base == 16) {
+    if (p+2 < end && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+      p += 2;
+    }
+  }
+
+  while (p < end && (d = digitval(*p)) >= 0 && d < base) {
+    v = v*base + d;
+    p += 1;
+  }
+
+  if (endptr) {
+    *endptr = (char*) p;
+  }
+
+  return minus ? -v : v;
+}
+
+// This non-standard function was in our <inttypes.h> for some reason.
+extern "C" intmax_t strntoimax(const char* nptr, char** endptr, int base, size_t n) {
+  return (intmax_t) strntoumax(nptr, endptr, base, n);
+}
+
 #endif
diff --git a/libc/include/inttypes.h b/libc/include/inttypes.h
index 2fd2415..5199e4d 100644
--- a/libc/include/inttypes.h
+++ b/libc/include/inttypes.h
@@ -261,9 +261,6 @@
 intmax_t	strtoimax(const char *, char **, int);
 uintmax_t	strtoumax(const char *, char **, int);
 
-intmax_t	strntoimax(const char *nptr, char **endptr, int base, size_t n);
-uintmax_t	strntoumax(const char *nptr, char **endptr, int base, size_t n);
-
 __END_DECLS
 
 #endif /* _INTTYPES_H_ */
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 14dff2b..872cc5b 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -40,7 +40,6 @@
 typedef int (*fn)(void);
 #define LIBNAME "libdlext_test.so"
 #define LIBSIZE 1024*1024 // how much address space to reserve for it
-#define RELRO_FILE "/data/local/tmp/libdlext_test.relro"
 
 
 class DlExtTest : public ::testing::Test {
@@ -154,7 +153,11 @@
   extinfo.reserved_size = LIBSIZE;
 
   int relro_fd;
-  relro_fd = open(RELRO_FILE, O_CREAT | O_RDWR | O_TRUNC, 0644);
+  char relro_file[PATH_MAX];
+  const char* android_data = getenv("ANDROID_DATA");
+  ASSERT_TRUE(android_data != NULL);
+  snprintf(relro_file, sizeof(relro_file), "%s/local/tmp/libdlext_test.relro", android_data);
+  relro_fd = open(relro_file, O_CREAT | O_RDWR | O_TRUNC, 0644);
   extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO;
   ASSERT_NOERROR(relro_fd);
   extinfo.relro_fd = relro_fd;
@@ -178,7 +181,7 @@
   ASSERT_TRUE(WIFEXITED(status));
   ASSERT_EQ(0, WEXITSTATUS(status));
 
-  relro_fd = open(RELRO_FILE, O_RDONLY);
+  relro_fd = open(relro_file, O_RDONLY);
   ASSERT_NOERROR(relro_fd);
   extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_USE_RELRO;
   extinfo.relro_fd = relro_fd;