# Non-root binary distribution

**URL:** <https://rubytalk.org/t/non-root-binary-distribution/10377>\
**Category:** ruby-talk\
**Created:** [2 March 2004 16:05 UTC](https://rubytalk.org/t/non-root-binary-distribution/10377 "2004-03-02T16:05:21Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![David\_Garamond2](https://avatars.discourse-cdn.com/v4/letter/d/8dc957/32.png) [@David\_Garamond2](https://rubytalk.org/u/David_Garamond2)\
**Post date:** [2 March 2004 16:05 UTC](https://rubytalk.org/t/non-root-binary-distribution/10377/1 "2004-03-02T16:05:21Z")

</div>

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.

> **···**
>
> –  
> dave

---

<div class="post-metadata">

**Author:** ![Nobuyoshi\_Nakada](https://avatars.discourse-cdn.com/v4/letter/n/edb3f5/32.png) [@Nobuyoshi\_Nakada](https://rubytalk.org/u/Nobuyoshi_Nakada)\
**Post date:** [3 March 2004 02:23 UTC](https://rubytalk.org/t/non-root-binary-distribution/10377/2 "2004-03-03T02:23:01Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![David\_Garamond2](https://avatars.discourse-cdn.com/v4/letter/d/8dc957/32.png) [@David\_Garamond2](https://rubytalk.org/u/David_Garamond2)\
**Post date:** [3 March 2004 16:54 UTC](https://rubytalk.org/t/non-root-binary-distribution/10377/3 "2004-03-03T16:54:48Z")

</div>

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?

> **···**
>
> [nobu.nokada@softhome.net](mailto:nobu.nokada@softhome.net) wrote:
> 
> > > 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.
> 
> –  
> dave

---

<div class="post-metadata">

**Author:** ![Nobuyoshi\_Nakada](https://avatars.discourse-cdn.com/v4/letter/n/edb3f5/32.png) [@Nobuyoshi\_Nakada](https://rubytalk.org/u/Nobuyoshi_Nakada)\
**Post date:** [3 March 2004 23:31 UTC](https://rubytalk.org/t/non-root-binary-distribution/10377/4 "2004-03-03T23:31:27Z")

</div>

Hi,

At Thu, 4 Mar 2004 01:54:48 +0900,  
David Garamond wrote in [ruby-talk:94160]:

> 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.

> **···**
>
> –  
> Nobu Nakada

---

<div class="post-metadata">

**Author:** ![David\_Garamond2](https://avatars.discourse-cdn.com/v4/letter/d/8dc957/32.png) [@David\_Garamond2](https://rubytalk.org/u/David_Garamond2)\
**Post date:** [4 March 2004 15:51 UTC](https://rubytalk.org/t/non-root-binary-distribution/10377/5 "2004-03-04T15:51:39Z")

</div>

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);  
}

> **···**
>
> [nobu.nokada@softhome.net](mailto: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.
> 
> –  
> dave

---

<div class="post-metadata">

**Author:** ![Nobuyoshi\_Nakada](https://avatars.discourse-cdn.com/v4/letter/n/edb3f5/32.png) [@Nobuyoshi\_Nakada](https://rubytalk.org/u/Nobuyoshi_Nakada)\
**Post date:** [4 March 2004 16:35 UTC](https://rubytalk.org/t/non-root-binary-distribution/10377/6 "2004-03-04T16:35:44Z")

</div>

Hi,

At Fri, 5 Mar 2004 00:51:39 +0900,  
David Garamond wrote in [ruby-talk:94230]:

> 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. 🙂

I recommend static-linked binary after all. You’d have no merit  
of shared library at all if you put the copy in each users’  
space.

> #include \<stdio.h\>  
> #include \<errno.h\>
> 
> int main(int argc, char \*argv) {  
> static char binpath[512+5], libpath[512+6];

You’d better to get rid of magic numbers.

> 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=”);

Use strcpy instead of strcat here, content of malloc’ed area is  
not guaranteed.

> **···**
>
> –  
> Nobu Nakada

---

<div class="post-metadata">

**Author:** ![David\_Garamond2](https://avatars.discourse-cdn.com/v4/letter/d/8dc957/32.png) [@David\_Garamond2](https://rubytalk.org/u/David_Garamond2)\
**Post date:** [5 March 2004 10:51 UTC](https://rubytalk.org/t/non-root-binary-distribution/10377/7 "2004-03-05T10:51:08Z")

</div>

> > 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. 🙂
> 
> I recommend static-linked binary after all. You’d have no merit  
> of shared library at all if you put the copy in each users’  
> space.

But will static Ruby be problematic when building extensions? For  
example, I tried with plruby and it didn’t produce a proper plruby.so.  
Maybe most Ruby extensions are developed with a shared Ruby in mind.

> > #include \<stdio.h\>  
> > #include \<errno.h\>
> > 
> > int main(int argc, char \*argv) {  
> > static char binpath[512+5], libpath[512+6];
> 
> You’d better to get rid of magic numbers.
> 
> > 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=”);
> 
> Use strcpy instead of strcat here, content of malloc’ed area is  
> not guaranteed.

Thanks for the suggestions.

> **···**
>
> [nobu.nokada@softhome.net](mailto:nobu.nokada@softhome.net) wrote:
> 
> –  
> dave

---

<div class="post-metadata">

**Author:** ![Nobuyoshi\_Nakada](https://avatars.discourse-cdn.com/v4/letter/n/edb3f5/32.png) [@Nobuyoshi\_Nakada](https://rubytalk.org/u/Nobuyoshi_Nakada)\
**Post date:** [5 March 2004 11:41 UTC](https://rubytalk.org/t/non-root-binary-distribution/10377/8 "2004-03-05T11:41:41Z")

</div>

Hi,

At Fri, 5 Mar 2004 19:51:08 +0900,  
David Garamond wrote in [ruby-talk:94318]:

> But will static Ruby be problematic when building extensions? For  
> example, I tried with plruby and it didn’t produce a proper plruby.so.  
> Maybe most Ruby extensions are developed with a shared Ruby in mind.

Don’t worry, even with --disable-shared, standard extension  
libraries are built properly.

I don’t know how “it didn’t produce a proper” so, but think the  
reason would be another problem.

> **···**
>
> –  
> Nobu Nakada

---

<div class="post-metadata">

**Author:** ![David\_Garamond2](https://avatars.discourse-cdn.com/v4/letter/d/8dc957/32.png) [@David\_Garamond2](https://rubytalk.org/u/David_Garamond2)\
**Post date:** [5 March 2004 12:03 UTC](https://rubytalk.org/t/non-root-binary-distribution/10377/9 "2004-03-05T12:03:51Z")

</div>

Yes, standard extension are all built successfully. I also just tried  
building ruby-postgres and mysql-ruby with no problem. I guess plruby is  
a different case as it tries to link with ruby itself.

Thanks,

> **···**
>
> [nobu.nokada@softhome.net](mailto:nobu.nokada@softhome.net) wrote:
> 
> > At Fri, 5 Mar 2004 19:51:08 +0900,  
> > David Garamond wrote in [ruby-talk:94318]:
> > 
> > > But will static Ruby be problematic when building extensions? For  
> > > example, I tried with plruby and it didn’t produce a proper plruby.so.  
> > > Maybe most Ruby extensions are developed with a shared Ruby in mind.
> > 
> > Don’t worry, even with --disable-shared, standard extension  
> > libraries are built properly.  
> > I don’t know how “it didn’t produce a proper” so, but think the  
> > reason would be another problem.
> 
> –  
> dave
