Index: instruby.rb
===================================================================
--- instruby.rb	(revision 23088)
+++ instruby.rb	(working copy)
@@ -162,9 +162,91 @@ def install(src, dest, options = {})
 end
 
-def ln_sf(src, dest)
-  super(src, with_destdir(dest))
+def ln(src, dest, options = {})
+  super(with_destdir(src), with_destdir(dest), options)
+rescue NotImplementedError
+else
   $installed_list.puts dest if $installed_list
 end
 
+def ln_sf(src, dest, options = {})
+  super(src, with_destdir(dest), options)
+rescue NotImplementedError
+else
+  $installed_list.puts dest if $installed_list
+end
+
+def hardsymln?
+  require 'tmpdir'
+  Dir.mktmpdir do |d|
+    File.symlink(".", "x")
+    File.link("x", "y")
+  end
+rescue SystemCallError
+  false
+else
+  true
+end
+
+major = CONFIG["MAJOR"]
+minor = CONFIG["MINOR"]
+teeny = CONFIG["TEENY"]
+version = [major, minor, teeny]
+os = CONFIG["target_os"]
+
+module Versioned
+  def create_dest(file, dest, options = {})
+    name = File.basename(file)
+    base = File.basename(name, options.delete(:ext) || '.*')
+    ext = name[base.length .. -1]
+    real = nil
+    symln = nil
+    hardsymln = hardsymln?
+    force = options.fetch(:force) {$force}
+    self.each do |ver|
+      ver = File.join(dest, n = base+ver+ext)
+      if !real
+        yield(file, ver, options)
+        real = n
+      elsif hardsymln and symln and !
+	begin
+	  ln(symln, ver, :force => force)
+	rescue Errno::EEXIST
+          true
+	rescue
+	  hardsymln = false
+        else
+          true
+	end
+      else
+        ln_sf(real, ver)
+	symln = ver
+      end
+    end
+    real
+  end
+  def install(*args)
+    create_dest(*args) {|*v| super(*v)}
+  end
+  def open_for_install(path, mode, &block)
+    create_dest(*File.split(path).reverse) do |src, dest, options|
+      super(dest, mode, &block)
+    end
+  end
+end
+
+CommVersions = [0..-1, 0..-2].map {|r|
+  r = version[r]
+  ["-.", "-", ""].map {|mid| mid[0, 1] + r.join(mid[1, 1])}
+}.flatten! << ""
+CommVersions.extend(Versioned)
+LibVersions = [0..-1, 0..-2].map {|r| version[r].join(".")}
+ArchVersions = LibVersions.map {|r|
+  ["#{r}-#{os}", "#{r.delete('.')}-#{os}"]
+}.flatten!
+ArchVersions.concat(CommVersions)
+ArchVersions.extend(Versioned)
+LibVersions.each {|r| r.sub!(/\A/, "-")}
+LibVersions.extend(Versioned)
+
 $made_dirs = {}
 def makedirs(dirs)
@@ -305,7 +387,7 @@ install?(:local, :arch, :bin, :'bin-arch
   prepare "binary commands", bindir
 
-  install ruby_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip
+  ArchVersions.install ruby_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip
   if rubyw_install_name and !rubyw_install_name.empty?
-    install rubyw_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip
+    ArchVersions.install rubyw_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip
   end
   if File.exist? goruby_install_name+exeext
@@ -329,5 +411,9 @@ install?(:local, :arch, :lib) do
 
   prepare "arch files", archlibdir
-  install "rbconfig.rb", archlibdir, :mode => $data_mode
+  open_for_install(File.join(archlibdir, "rbconfig.rb"), $data_mode) do
+    File.read("rbconfig.rb").sub(/^(\s*CONFIG\["RUBY_SO_NAME"\]\s*=\s*"ruby)(?=")/) {
+      $1 + LibVersions[0]
+    }
+  end
   if CONFIG["ARCHFILE"]
     for file in CONFIG["ARCHFILE"].split
@@ -379,4 +465,5 @@ install?(:local, :comm, :bin, :'bin-comm
 
   ruby_shebang = File.join(bindir, ruby_install_name)
+  ruby_shebang << "-" << version
   if File::ALT_SEPARATOR
     ruby_bin = ruby_shebang.tr(File::SEPARATOR, File::ALT_SEPARATOR)
@@ -400,5 +487,5 @@ install?(:local, :comm, :bin, :'bin-comm
     cmd = File.join(bindir, name)
     cmd << ".#{$cmdtype}" if $cmdtype
-    open_for_install(cmd, $script_mode) do
+    CommVersions.open_for_install(cmd, $script_mode) do
       case $cmdtype
       when "bat"
