From: nobu.nokada@... Date: 2004-03-03T11:23:01+09:00 Subject: Re: non-root binary distribution Hi, At Wed, 3 Mar 2004 01:05:21 +0900, David Garamond wrote in [ruby-talk:94067]: > Is there a binary .tar.gz or a relocatable RPM for ruby 1.8.x which can > be installed onto a custom per-user directory without requiring root > privilege? I find it easy to do this with the mswin32 version. Ruby embeds absolute load paths, for the sake of UNIX tradition and security issue. However, it might not be major problem if $SAFE == 0, so you could make relocatable binary with the following path and --enable-load-relative configure option, if you use /proc fs on linux. * configure.in (load-relative): separate load-relative feature from platform. * ruby.c (ruby_init_loadpath): appendant to load-relative feature. [ruby-talk:94067] Index: configure.in =================================================================== RCS file: /cvs/ruby/src/ruby/configure.in,v retrieving revision 1.226 diff -u -2 -p -d -r1.226 configure.in --- configure.in 16 Feb 2004 06:45:31 -0000 1.226 +++ configure.in 3 Mar 2004 01:52:44 -0000 @@ -1387,13 +1387,27 @@ case "$target_os" in ;; esac + +AC_ARG_ENABLE(load-relative, + [ --enable-load-relative enable initial load path relative to ruby], + [loadrelative=$enableval], [loadrelative=no]) + case "$target_os" in cygwin*|mingw*|*djgpp*|os2-emx*) - RUBY_LIB_PREFIX="/lib/ruby" + loadrelative=yes + ;; + linux*) ;; *) - RUBY_LIB_PREFIX="${prefix}/lib/ruby" + loadrelative=no ;; esac -RUBY_LIB_PATH="${RUBY_LIB_PREFIX}/${MAJOR}.${MINOR}" +if test "x$loadrelative" = xyes; then + AC_DEFINE(LOAD_RELATIVE, 1) + AC_DEFINE_UNQUOTED(RUBY_PREFIX, "${prefix}") + RUBY_PREFIX="" +else + RUBY_PREFIX="${prefix}" +fi +RUBY_LIB_PATH="${RUBY_PREFIX}/lib/ruby/${MAJOR}.${MINOR}" AC_ARG_WITH(sitedir, @@ -1402,11 +1416,6 @@ AC_ARG_WITH(sitedir, [sitedir='${prefix}/lib/ruby/site_ruby']) SITE_DIR="`eval \"echo ${sitedir}\"`" -case "$target_os" in - cygwin*|mingw*|*djgpp*|os2-emx*) - RUBY_SITE_LIB_PATH="`expr "$SITE_DIR" : "$prefix\(/.*\)"`" || - RUBY_SITE_LIB_PATH="$SITE_DIR";; - *) - RUBY_SITE_LIB_PATH="$SITE_DIR";; -esac +RUBY_SITE_LIB_PATH="${RUBY_PREFIX}`expr "$SITE_DIR" : "$prefix\(/.*\)"`" || +RUBY_SITE_LIB_PATH="$SITE_DIR" RUBY_SITE_LIB_PATH2="${RUBY_SITE_LIB_PATH}/${MAJOR}.${MINOR}" Index: ruby.c =================================================================== RCS file: /cvs/ruby/src/ruby/ruby.c,v retrieving revision 1.86 diff -u -2 -p -d -r1.86 ruby.c --- ruby.c 21 Jan 2004 16:47:14 -0000 1.86 +++ ruby.c 3 Mar 2004 01:58:56 -0000 @@ -233,4 +233,37 @@ translate_char(p, from, to) #endif +#if defined LOAD_RELATIVE && defined RUBY_PREFIX +#ifdef __linux__ +static char * +getlibpath(lib, size, pos) + char *lib; + int size; + long pos; +{ + FILE *maps = fopen("/proc/self/maps", "r"); + long start, end; + char *p; + + if (!maps) return 0; + *lib = 0; + while (fscanf(maps, "%x-%x", &start, &end) == 2) { + if (start <= pos && pos < end) { + fscanf(maps, " %*s %*s %*s %*s "); + fgets(lib, size, maps); + fclose(maps); + p = strchr(lib, '\n'); + if (p) *p = 0; + return lib; + } + else { + fscanf(maps, "%*[^\n]\n"); + } + } + fclose(maps); + return 0; +} +#endif +#endif + void ruby_init_loadpath() @@ -258,4 +291,11 @@ ruby_init_loadpath() #elif defined(__EMX__) _execname(libpath, FILENAME_MAX); +#elif defined(RUBY_PREFIX) + if (rb_safe_level() > 0 || + !getlibpath(libpath, sizeof libpath, (long)ruby_init_loadpath)) { + strncpy(libpath, RUBY_PREFIX, sizeof libpath); + p = libpath + strlen(libpath); + goto init; + } #endif @@ -267,5 +307,6 @@ ruby_init_loadpath() if (p) { *p = 0; - if (p-libpath > 3 && !strcasecmp(p-4, "/bin")) { + if (p-libpath > 3 && + !(strcasecmp(p-4, "/bin") && strcasecmp(p-4, "/lib"))) { p -= 4; *p = 0; @@ -277,4 +318,5 @@ ruby_init_loadpath() } + init: rest = FILENAME_MAX - (p - libpath); -- Nobu Nakada