Merge "Sometimes the compiler is very right! Found bug in bessel routines for float."
diff --git a/libc/stdio/flockfile.c b/libc/stdio/flockfile.c
index a81879e..bfb081c 100644
--- a/libc/stdio/flockfile.c
+++ b/libc/stdio/flockfile.c
@@ -205,8 +205,6 @@
             lock->file = NULL;
         }
         lock_table_unlock(t);
-
-        if (lock != NULL)
-            free(lock);
+        free(lock);
     }
 }
diff --git a/libc/string/strndup.c b/libc/string/strndup.c
index da9a55f..9dca79c 100644
--- a/libc/string/strndup.c
+++ b/libc/string/strndup.c
@@ -31,12 +31,14 @@
 char*  strndup(const char*  s, size_t n)
 {
     size_t  slen = (size_t)strlen(s);
-    int     len  = slen < n ? slen : n;
-    char*   copy = malloc(len+1);
+    char*   copy;
 
+    if (slen < n)
+        n = slen;
+    copy = malloc(n+1);
     if (copy) {
-        memcpy( copy, s, len );
-        copy[len] = 0;
+        memcpy(copy, s, n);
+        copy[n] = 0;
     }
     return copy;
 }
diff --git a/libm/bsdsrc/b_exp.c b/libm/bsdsrc/b_exp.c
index 32873b9..107bc89 100644
--- a/libm/bsdsrc/b_exp.c
+++ b/libm/bsdsrc/b_exp.c
@@ -76,16 +76,16 @@
 
 #include "mathimpl.h"
 
-const static double p1 = 0x1.555555555553ep-3;
-const static double p2 = -0x1.6c16c16bebd93p-9;
-const static double p3 = 0x1.1566aaf25de2cp-14;
-const static double p4 = -0x1.bbd41c5d26bf1p-20;
-const static double p5 = 0x1.6376972bea4d0p-25;
-const static double ln2hi = 0x1.62e42fee00000p-1;
-const static double ln2lo = 0x1.a39ef35793c76p-33;
-const static double lnhuge = 0x1.6602b15b7ecf2p9;
-const static double lntiny = -0x1.77af8ebeae354p9;
-const static double invln2 = 0x1.71547652b82fep0;
+static const double p1 = 0x1.555555555553ep-3;
+static const double p2 = -0x1.6c16c16bebd93p-9;
+static const double p3 = 0x1.1566aaf25de2cp-14;
+static const double p4 = -0x1.bbd41c5d26bf1p-20;
+static const double p5 = 0x1.6376972bea4d0p-25;
+static const double ln2hi = 0x1.62e42fee00000p-1;
+static const double ln2lo = 0x1.a39ef35793c76p-33;
+static const double lnhuge = 0x1.6602b15b7ecf2p9;
+static const double lntiny = -0x1.77af8ebeae354p9;
+static const double invln2 = 0x1.71547652b82fep0;
 
 #if 0
 double exp(x)
diff --git a/libm/src/e_atan2.c b/libm/src/e_atan2.c
index 073f81b..56c05a5 100644
--- a/libm/src/e_atan2.c
+++ b/libm/src/e_atan2.c
@@ -68,7 +68,7 @@
 	if(((ix|((lx|-lx)>>31))>0x7ff00000)||
 	   ((iy|((ly|-ly)>>31))>0x7ff00000))	/* x or y is NaN */
 	   return x+y;
-	if((hx-0x3ff00000|lx)==0) return atan(y);   /* x=1.0 */
+	if(((hx-0x3ff00000) | lx)==0) return atan(y);   /* x=1.0 */
 	m = ((hy>>31)&1)|((hx>>30)&2);	/* 2*sign(x)+sign(y) */
 
     /* when y = 0 */
diff --git a/linker/linker.c b/linker/linker.c
index 451e96c..8dde941 100644
--- a/linker/linker.c
+++ b/linker/linker.c
@@ -58,6 +58,9 @@
 #define LDPATH_BUFSIZE 512
 #define LDPATH_MAX 8
 
+#define LDPRELOAD_BUFSIZE 512
+#define LDPRELOAD_MAX 8
+
 /* >>> IMPORTANT NOTE - READ ME BEFORE MODIFYING <<<
  *
  * Do NOT use malloc() and friends or pthread_*() code here.
@@ -112,6 +115,11 @@
 static char ldpaths_buf[LDPATH_BUFSIZE];
 static const char *ldpaths[LDPATH_MAX + 1];
 
+static char ldpreloads_buf[LDPRELOAD_BUFSIZE];
+static const char *ldpreload_names[LDPRELOAD_MAX + 1];
+
+static soinfo *preloads[LDPRELOAD_MAX + 1];
+
 int debug_verbosity;
 static int pid;
 
@@ -451,6 +459,7 @@
     Elf32_Sym *s;
     unsigned *d;
     soinfo *lsi = si;
+    int i;
 
     /* Look for symbols in the local scope first (the object who is
      * searching). This happens with C++ templates on i386 for some
@@ -459,6 +468,14 @@
     if(s != NULL)
         goto done;
 
+    /* Next, look for it in the preloads list */
+    for(i = 0; preloads[i] != NULL; i++) {
+        lsi = preloads[i];
+        s = _do_lookup_in_so(lsi, name, &elf_hash);
+        if(s != NULL)
+            goto done;
+    }
+
     for(d = si->dynamic; *d; d += 2) {
         if(d[0] == DT_NEEDED){
             lsi = (soinfo *)d[1];
@@ -1866,6 +1883,23 @@
         goto fail;
     }
 
+    /* if this is the main executable, then load all of the preloads now */
+    if(si->flags & FLAG_EXE) {
+        int i;
+        memset(preloads, 0, sizeof(preloads));
+        for(i = 0; ldpreload_names[i] != NULL; i++) {
+            soinfo *lsi = find_library(ldpreload_names[i]);
+            if(lsi == 0) {
+                strlcpy(tmp_err_buf, linker_get_error(), sizeof(tmp_err_buf));
+                DL_ERR("%5d could not load needed library '%s' for '%s' (%s)",
+                       pid, ldpreload_names[i], si->name, tmp_err_buf);
+                goto fail;
+            }
+            lsi->refcount++;
+            preloads[i] = lsi;
+        }
+    }
+
     for(d = si->dynamic; *d; d += 2) {
         if(d[0] == DT_NEEDED){
             DEBUG("%5d %s needs %s\n", pid, si->name, si->strtab + d[1]);
@@ -1982,6 +2016,30 @@
     }
 }
 
+static void parse_preloads(char *path, char *delim)
+{
+    size_t len;
+    char *ldpreloads_bufp = ldpreloads_buf;
+    int i = 0;
+
+    len = strlcpy(ldpreloads_buf, path, sizeof(ldpreloads_buf));
+
+    while (i < LDPRELOAD_MAX && (ldpreload_names[i] = strsep(&ldpreloads_bufp, delim))) {
+        if (*ldpreload_names[i] != '\0') {
+            ++i;
+        }
+    }
+
+    /* Forget the last path if we had to truncate; this occurs if the 2nd to
+     * last char isn't '\0' (i.e. not originally a delim). */
+    if (i > 0 && len >= sizeof(ldpreloads_buf) &&
+            ldpreloads_buf[sizeof(ldpreloads_buf) - 2] != '\0') {
+        ldpreload_names[i - 1] = NULL;
+    } else {
+        ldpreload_names[i] = NULL;
+    }
+}
+
 int main(int argc, char **argv)
 {
     return 0;
@@ -2001,6 +2059,7 @@
     soinfo *si;
     struct link_map * map;
     char *ldpath_env = NULL;
+    char *ldpreload_env = NULL;
 
     /* Setup a temporary TLS area that is used to get a working
      * errno for system calls.
@@ -2032,6 +2091,8 @@
             debug_verbosity = atoi(((char*) vecs[0]) + 6);
         } else if(!strncmp((char*) vecs[0], "LD_LIBRARY_PATH=", 16)) {
             ldpath_env = (char*) vecs[0] + 16;
+        } else if(!strncmp((char*) vecs[0], "LD_PRELOAD=", 11)) {
+            ldpreload_env = (char*) vecs[0] + 11;
         }
         vecs++;
     }
@@ -2095,6 +2156,10 @@
     if (ldpath_env && getuid() == geteuid() && getgid() == getegid())
         parse_library_path(ldpath_env, ":");
 
+    if (ldpreload_env && getuid() == geteuid() && getgid() == getegid()) {
+        parse_preloads(ldpreload_env, " :");
+    }
+
     if(link_image(si, 0)) {
         char errmsg[] = "CANNOT LINK EXECUTABLE\n";
         write(2, __linker_dl_err_buf, strlen(__linker_dl_err_buf));