Format of RUBYOPT

Hello all,

I’m working on fixing the remaining installer problems in the
One-Click Installer so we can finally release it, and one of those
involves the manipulation of the RUBYOPT environment variable. On that
note, I was wondering the format of that. If there are multiple
entrys, how are they formatted? Just spaces in between?

In other words, if I am to add rubygems as a new option while
preserving the older options, what would I do? Just add it with a
space prefix at the end of RUBYOPT?

In my testing there seemed to be cases when RUBYOPT was not read and I
also got errors sometimes, so I want to ensure I don’t break someone’s
system by setting an invalid RUBYOPT.

Thanks,
Ryan

On Tue, 25 Apr 2006, Ryan L. wrote:

space prefix at the end of RUBYOPT?

In my testing there seemed to be cases when RUBYOPT was not read and I
also got errors sometimes, so I want to ensure I don’t break someone’s
system by setting an invalid RUBYOPT.

Thanks,
Ryan

if you look in ruby.c you’ll see that it’s literally parsed as part of
the
commandline - except only the switchs ‘IdvwrK’ and ‘T’ are accepted. it
looks
like it is indeed space separated.

harp:~ > cat rubylib/a.rb
A=42

harp:~ > RUBYOPT="-ryaml -Irubylib/ -ra" ruby -e “p [YAML, A]”
[YAML, 42]

seems to work.

cheers.

-a

On 4/24/06, Ryan L. [email protected] wrote:

In other words, if I am to add rubygems as a new option while
preserving the older options, what would I do? Just add it with a
space prefix at the end of RUBYOPT?

Responding to my own thread: Given that the above is true, I wrote
Ruby script to work out the logic of this and here is the result:

$already_defined = {}

def add_to_rubyopt(var, rubyopt)
a = rubyopt.split(’ ‘)
if not a.include?(var)
a << var
$already_defined[var] = nil
else
$already_defined[var] = true
end
a.join(’ ')
end

def del_from_rubyopt(var, rubyopt)
if not $already_defined[var]
a = rubyopt.split(’ ‘)
a.delete(var)
a.join(’ ')
else
rubyopt
end
end

require ‘test/unit’

class RubyOptTest < Test::Unit::TestCase
def test_add_to_rubyopt
var = ‘rubygems’
# Before and after tests
[
[‘’, var],
[‘w’, “w #{var}”],
[‘w v somethinglong’, “w v somethinglong #{var}”]
].each do |before, after|
assert_equal(after, add_to_rubyopt(var, before))
assert_equal(before, del_from_rubyopt(var, after))
end
# Here nothing should be changed
[var, “w #{var}”, “w v #{var} somethinglong”].each do |s|
assert_equal(s, add_to_rubyopt(var, s))
assert_equal(s, del_from_rubyopt(var, s))
end
end
end
END

If the logic of the above seems wrong in any way, let me know. Now the
trick is writing the above in the NSIS scripting language (it’s
practically like assembler compared to Ruby, grrr.)

Ryan

On 4/24/06, Ryan L. [email protected] wrote:

A=42
ruby: No such file or directory – rubygems (LoadError)

C:_Ryan\ruby_installer\svn\NSIS>ruby -rubygems -e ‘puts “hello”’
hello

Maybe to be safe I should always just add -rubygems (i.e with a dash
prefix.)

Ryan

I only recently discovered this myself… with a single option you can
omit
the “-”, but with multiple, the “-” is required.

Curt

On 4/24/06, [email protected] [email protected] wrote:

seems to work.

Hmmm, OK. Then why does setting RUBYOPT to just rubygems work (it has
no dash?) That doesn’t work on the command-line (at least on Windows):

C:_Ryan\ruby_installer\svn\NSIS>ruby rubygems -e ‘puts “hello”’
ruby: No such file or directory – rubygems (LoadError)

C:_Ryan\ruby_installer\svn\NSIS>ruby -rubygems -e ‘puts “hello”’
hello

Maybe to be safe I should always just add -rubygems (i.e with a dash
prefix.)

Ryan

On 4/24/06, Ryan L. [email protected] wrote:

OK, so not only do I need to check for an existing RUBYOPT, but if is
defined and it only has one option, I need to add a dash to the
existing if it lacks it, then add -rubygems. Then on uninstall this
needs to be restored. Nice. I’m glad I’m prototyping this in Ruby.

And here is the modified test:

$old_value = {}

def add_to_env(add_this, env_var_name, env_var_value, split_char=’ ')
result = env_var_value
a = env_var_value.split(split_char)
if not (a.include?(add_this) or a.include?(“-#{add_this}”))
$old_value[env_var_name] = env_var_value
if a.length == 1 and a[0][0].chr != ‘-’
a[0] = ‘-’ + a[0]
end
a << “-#{add_this}”
result = a.join(split_char)
end
result
end

def restore_env(env_var_name, env_var_value)
if $old_value[env_var_name]
result = $old_value[env_var_name]
$old_value[env_var_name] = nil
result
else
env_var_value
end
end

require ‘test/unit’

class RubyOptTest < Test::Unit::TestCase
def test_add_to_rubyopt
to_add = ‘rubygems’
env_var = ‘RUBYOPT’
# Before and after tests
[
[‘’, “-#{to_add}”],
[‘w’, “-w -#{to_add}”],
[‘-w -v -somethinglong’, “-w -v -somethinglong -#{to_add}”]
].each do |before, after|
assert_equal(after, add_to_env(to_add, env_var, before))
assert_equal(before, restore_env(env_var, after))
end
# Here nothing should be changed
[to_add, “-w -#{to_add}”, “-w -v -#{to_add} -somethinglong”].each do
|s|
assert_equal(s, add_to_env(to_add, env_var, s))
assert_equal(s, restore_env(env_var, s))
end
end
end
END

Again if anything looks wrong let me know :slight_smile:

Ryan

On Tue, 25 Apr 2006, Ryan L. wrote:

[YAML, 42]
hello

Maybe to be safe I should always just add -rubygems (i.e with a dash prefix.)

ruby.c, in proc_options:

 731     if (rb_safe_level() == 0 && (s = getenv("RUBYOPT"))) {
 732         while (ISSPACE(*s)) s++;
 733         if (*s == 'T' || (*s == '-' && *(s+1) == 'T')) {
 734             int numlen;
 735             int v = 1;
 736
 737             if (*s != 'T') ++s;
 738             if (*++s) {
 739                 v = scan_oct(s, 2, &numlen);
 740                 if (numlen == 0) v = 1;
 741             }
 742             rb_set_safe_level(v);
 743         }

in the else block we eat the dash and any space, iff present. then we
look
for the opt char

 744         else {
 745             while (s && *s) {
 746                 if (*s == '-') {
 747                     s++;
 748                     if (ISSPACE(*s)) {
 749                         do {s++;} while (ISSPACE(*s));
 750                         continue;
 751                     }
 752                 }
 753                 if (!*s) break;
 754                 if (!strchr("IdvwrK", *s))
 755                     rb_raise(rb_eRuntimeError, "illegal switch 

in RUBYOPT: -%c", *s);

now, given RUBYOPT=-rubygems, and *s==r, we call moreswitches

 756                 s = moreswitches(s);
 757             }
 758         }
 759     }

so in this function

 433 static char*
 434 moreswitches(s)
 435     char *s;
 436 {
 437     int argc; char *argv[3];
 438     char *p = s;
 439
 440     argc = 2; argv[0] = argv[2] = 0;
 441     while (*s && !ISSPACE(*s))
 442         s++;
 443     argv[1] = ALLOCA_N(char, s-p+2);
 444     argv[1][0] = '-';
 445     strncpy(argv[1]+1, p, s-p);
 446     argv[1][s-p+1] = '\0';
 447     proc_options(argc, argv);
 448     while (*s && ISSPACE(*s))
 449         s++;
 450     return s;
 451 }

we eat whitespace, setup argv=[0, “-rubygems”, 0] and argc == 2. then
recurse
into proc_options (the first method shown).

so, as far as i can tell (and i’ve had three beers), proc_options finds
the
‘r’, jumps into moreswitches which restores the ‘-’, and the were back
into
proc_options with ‘-rubygems’, which works because of the ‘ubygems’
hack. the
parsing of RUBYOPT looks as if it ignores ‘-’ or lack thereof be design,
but i
certainly can’t be knowing.

good luck! :wink:

-a

On 4/24/06, Curt H. [email protected] wrote:

I only recently discovered this myself… with a single option you can omit
the “-”, but with multiple, the “-” is required.

OK, so not only do I need to check for an existing RUBYOPT, but if is
defined and it only has one option, I need to add a dash to the
existing if it lacks it, then add -rubygems. Then on uninstall this
needs to be restored. Nice. I’m glad I’m prototyping this in Ruby.

Ryan

On Tue, 25 Apr 2006, Wilson B. wrote:

To summarize, if you’re going to alter RUBYOPT by appending something, you
should append a space and then ‘-rrubygems’, to be sure?

it looks that way to me. but caveat emptor.

-a

On 4/24/06, [email protected] [email protected] wrote:

 733         if (*s == 'T' || (*s == '-' && *(s+1) == 'T')) {

 749                         do {s++;} while (ISSPACE(*s));

 434 moreswitches(s)
 445     strncpy(argv[1]+1, p, s-p);


To summarize, if you’re going to alter RUBYOPT by appending something,
you should append a space and then ‘-rrubygems’, to be sure?