nobu.nokada / softhome.net wrote:
>>Thanks, it works beautifully. The only thing left is that a user needs 
>>to do:
>>
>>  % LD_LIBRARY_PATH=/path/to/his/ruby/lib /path/to/his/ruby/bin/ruby
>>
>>(or set LD_LIBRARY_PATH in his ~/.bash_profile) otherwise ruby can't 
>>find libruby.so. Is there a way to avoid/get around this?
> 
> a) use static linked ruby
>     configure --disable-shared
> 
> b) prepare a wrapper script like followings, with renaming ruby
>    to ruby-bin.
> 
>     #!/bin/sh
>     LD_LIBRARY_PATH="${0%/*}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" exec "$0-bin" "$@"
> 
>   Although it doesn't work in shebang lines, of course, you may
>   not use user specific paths.

Based on your suggestion, I've created a C wrapper like below. The real 
ruby is renamed to "ruby.real". Advice welcome, since this is probably 
only the 7th or 8th C program I've written, ever. :-)



#include <stdio.h>
#include <errno.h>

int main(int argc, char *argv[]) {
   static char binpath[512+5], libpath[512+6];
   char *p, *env;

   if (readlink("/proc/self/exe", binpath, 511) == -1) {
     fprintf(stderr, "readlink() failed: %s (maybe /proc is not "
                     "mounted or restricted?)\n", strerror(errno));
     exit(1);
   }

   strcpy(libpath, binpath);
   p = libpath + strlen(libpath);
   while (p >= libpath) {
     if (*p == '/') {
       strcpy(p, "/../lib");
       break;
     }
     p--;
   }

   p = (char *)getenv("LD_LIBRARY_PATH");
   if ((env = (char *)malloc(512+1+(p==NULL ? 0:strlen(p)))) == NULL) {
     fprintf(stderr, "malloc() failed: %s\n", strerror(errno));
     exit(1);
   }
   strcat(env, "LD_LIBRARY_PATH=");
   if (p != NULL) {
     strcat(env, p);
     strcat(env, ":");
   }
   strcat(env, libpath);
   if (putenv(env) == -1) {
     fprintf(stderr, "putenv() failed: %s\n", strerror(errno));
     exit(1);
   }

   strcat(binpath, ".real");
   execv(binpath, argv);
   fprintf(stderr, "Can't execute wrapee: %s\n", strerror(errno));
   exit(1);
}

-- 
dave