# New Ticket Created by  Matt Kennedy 
# Please include the string:  [perl #31398]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=31398 >


The current implementation of Parrot_dlopen on OS X doesn't check
DYLD_LIBRARY_PATH for a library if set. This behavior differs from how
the dlcompat implementation works and how dlopen works on other
platforms like linux. It also makes running bytecode that uses loadlib
to load system libraries for extensions or running outside of the root
parrot directory a pain.

This patch modifies config/gen/platform/darwin/dl.c to follow the
behavior for checking DYLD_LIBRARY_PATH and DYLD_FALLBACK_LIBRARY_PATH
described in dyld(1).
-- 
Matt Kennedy
--- config/gen/platform/darwin/dl.c.orig	2004-05-25 11:00:10.000000000 -0400
+++ config/gen/platform/darwin/dl.c	2004-08-30 17:47:54.000000000 -0400
@@ -6,6 +6,66 @@
    wrapper around the native dyld and NSModule API, so we'll use
    the base API directly. This gives us wider compatibility, and
    more control over the behavior. */
+
+/*
+** scan_paths()
+ */
+
+/* Simple routine to walk a colon separated list of directories in a string 
+   and check for a file in each one, returning the first match. */
+static const char *
+scan_paths(const char *filename, const char *libpath)
+{
+    static char buf[PATH_MAX];
+    struct stat st;
+    const char *path;
+    
+    if(!libpath)
+      return NULL;
+    
+    path = strsep((char**)&libpath, ":");
+  
+    while(path) {
+        snprintf(buf, PATH_MAX, "%s/%s", path, filename);
+        if(stat(buf, &st) == 0)
+          return buf;
+        path = strsep((char**)&libpath, ":");
+    }
+    return NULL;
+}
+
+/*
+** get_lib()
+*/
+
+/* Try to expand a filename input into a full file system path following 
+   the behavior described in dyld(1). First looks for the file in 
+   DYLD_LIBRARY_PATH, the DYLD_FALLBACK_LIBRARY_PATH, and lastly uses the 
+   default of /usr/local/lib:/lib:/usr/lib. If the filename cannot be 
+   expanded, the original value passed to the function is returned. */
+static const char *
+get_lib(const char *filename) 
+{
+    const char *rv;
+    char *libpath = getenv("DYLD_LIBRARY_PATH");
+    char fallback[PATH_MAX] = "/usr/local/lib:/lib:/usr/lib";
+    
+    rv = scan_paths(filename, libpath);
+    if(rv)
+      return rv;
+
+    libpath = getenv("DYLD_FALLBACK_LIBRARY_PATH");
+    rv = scan_paths(filename, libpath);
+    if(rv)
+        return rv;
+
+    rv = scan_paths(filename, fallback);
+    if(rv)
+        return rv;
+
+    return filename;
+}
+
 /*
 ** Parrot_dlopen()
 */
@@ -15,13 +75,14 @@
 {
     int dyld_result;
     NSObjectFileImage ofile;
+    const char *fullpath = get_lib(filename);
 
     /* try bundle-style loading first */
-    dyld_result = NSCreateObjectFileImageFromFile(filename, &ofile);
+    dyld_result = NSCreateObjectFileImageFromFile(fullpath, &ofile);
 
     if (NSObjectFileImageSuccess == dyld_result)
     {
-        NSModule module = NSLinkModule(ofile, filename,
+        NSModule module = NSLinkModule(ofile, fullpath,
                               NSLINKMODULE_OPTION_RETURN_ON_ERROR
                               | NSLINKMODULE_OPTION_PRIVATE);
 
@@ -32,7 +93,7 @@
     else
     { /* bundle-style loading didn't work; try dylib-style before giving up */
         const struct mach_header *header =
-                NSAddImage( filename,
+                NSAddImage( fullpath,
                             NSADDIMAGE_OPTION_RETURN_ON_ERROR
                             | NSADDIMAGE_OPTION_WITH_SEARCHING);
 
@@ -61,8 +122,8 @@
                 break;
             default:
                 fprintf(stderr,
-                        "open result was unknown (%i) for filename [%s]\n",
-                        dyld_result, filename);
+                        "open result was unknown (%i) for fullpath [%s]\n",
+                        dyld_result, fullpath);
                 break;
             }
 

Reply via email to