class SysInfo

specifically lib/platform.rb.
Portions of this code were originally from Amazon’s EC2 AMI tools,
A container for the platform specific system information.
= SysInfo

def execute_platform_specific(dtype)


e.g. find_uptime_ruby_unix_osx
The name of the method will be in the format: +dtype-VM-OS-IMPL+.
Look for and execute a platform specific method.
def execute_platform_specific(dtype)
  criteria = [@vm, @os, @impl]
  while !criteria.empty?
    meth = [dtype, criteria].join('_').to_sym
    return self.send(meth) if SysInfo.private_method_defined?(meth)
    criteria.pop
  end
  raise "#{dtype}_#{@vm}_#{@os}_#{@impl} not implemented"
end

def find_hostname; Socket.gethostname; end

Return the hostname for the local machine
def find_hostname; Socket.gethostname; end

def find_ipaddress_internal

NOTE: This does not open a connection to the IP address.
from: http://coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/
Return the local IP address which receives external traffic
def find_ipaddress_internal
  # turn off reverse DNS resolution temporarily
  orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
  UDPSocket.open {|s| s.connect('65.74.177.129', 1); s.addr.last } # GitHub IP
ensure
  Socket.do_not_reverse_lookup = orig
end

def find_network_info

Returns [hostname, ipaddr (internal), uptime]
def find_network_info
  hostname, ipaddr, uptime = :unknown, :unknown, :unknown
  begin
    hostname = find_hostname
    ipaddr = find_ipaddress_internal
    uptime = find_uptime
  rescue => ex # Be silent!
  end
  [hostname, ipaddr, uptime]
end

def find_platform_info

Returns [vm, os, impl, arch]
def find_platform_info
  vm, os, impl, arch = :ruby, :unknown, :unknown, :unknown
  IMPLEMENTATIONS.each do |r, o, i|
    next unless RUBY_PLATFORM =~ r
    os, impl = [o, i]
    break
  end
  ARCHITECTURES.each do |r, a|
    next unless RUBY_PLATFORM =~ r
    arch = a
    break
  end
  os == :java ? guess_java : [vm, os, impl, arch]
end

def find_uptime

On Windows, see also: net statistics server
Based on Ruby Quiz solutions by: Matthias Reitinger
'sysctl -b kern.boottime' os osx, and 'who -b' on unix.
Returns the local uptime in hours. Use Win32API in Windows,
def find_uptime
  hours = 0
  begin
    seconds = execute_platform_specific("find_uptime") || 0
    hours = seconds / 3600 # seconds to hours
  rescue => ex
    #puts ex.message  # TODO: implement debug?
  end
  hours
end

def find_uptime_java_windows_windows

Ruby 1.9.1: Win32API is now deprecated in favor of using the DL library.
http://msdn.microsoft.com/en-us/library/ms724408(VS.85).aspx
http://www.oreillynet.com/ruby/blog/2008/01/jruby_meets_the_windows_api_1.html
Ya, this is kinda wack. Ruby -> Java -> Kernel32. See:
def find_uptime_java_windows_windows
  kernel32 = com.sun.jna.NativeLibrary.getInstance('kernel32')
  buf = java.nio.ByteBuffer.allocate(256)
  (kernel32.getFunction('GetTickCount').invokeInt([256, buf].to_java).to_f / 1000).to_f
end

def find_uptime_ruby_unix

This should work for most unix flavours.
def find_uptime_ruby_unix
  # who is sloooooow. Use File.read('/proc/uptime')
  (Time.now.to_i - Time.parse(`who -b 2>/dev/null`).to_f)
end

def find_uptime_ruby_unix_osx

def find_uptime_ruby_unix_osx
  # This is faster than "who" and could work on BSD also.
  (Time.now.to_f - Time.at(`sysctl -b kern.boottime 2>/dev/null`.unpack('L').first).to_f).to_f
end

def find_uptime_ruby_windows_windows

def find_uptime_ruby_windows_windows
  # Win32API is required in self.guess
  getTickCount = Win32API.new("kernel32", "GetTickCount", nil, 'L')
  ((getTickCount.call()).to_f / 1000).to_f
end

def getpwattr(pwattr)

without relying on ENV['HOME'] being present.
As an example, `getpwdattr(:home)` will return the user's home directory
Returns a named attribute of the user's /etc/password entry, or nil.
def getpwattr(pwattr)
  passwd = Etc.getpwuid(Process::Sys.getuid) || {}
  passwd[pwattr]
end

def guess_java

Determine the values for vm, os, impl, and arch when running on Java.
def guess_java
  vm, os, impl, arch = :java, :unknown, :unknown, :unknown
  require 'java'
  include_class java.lang.System unless defined?(System)
  osname = System.getProperty("os.name")
  IMPLEMENTATIONS.each do |r, o, i|
    next unless osname =~ r
    os, impl = [o, i]
    break
  end
  osarch = System.getProperty("os.arch")
  ARCHITECTURES.each do |r, a|
    next unless osarch =~ r
    arch = a
    break
  end
  [vm, os, impl, arch]
end

def home; execute_platform_specific(:home); end

Returns the path to the current user's home directory
def home; execute_platform_specific(:home); end

def home_java

def home_java
  if @impl == :windows
    File.expand_path(ENV['USERPROFILE'])
  else
    File.expand_path(getpwattr(:dir))
  end
end

def home_ruby_unix; File.expand_path(getpwattr(:dir)); end

def home_ruby_unix; File.expand_path(getpwattr(:dir)); end

def home_ruby_windows; File.expand_path(ENV['USERPROFILE']); end

def home_ruby_windows; File.expand_path(ENV['USERPROFILE']); end

def initialize

def initialize
  @vm, @os, @impl, @arch = find_platform_info
  @hostname, @ipaddress_internal, @uptime = find_network_info
  @ruby = RUBY_VERSION.split('.').collect { |v| v.to_i }
  @user = getpwattr(:name) || ENV['USER']
  require 'Win32API' if @os == :windows && @vm == :ruby
end

def ip_address_internal_alt

but the other code is cleaner. I'm keeping this old version here for now.
NOTE: This code predates the current ip_address_internal. It was just as well

local IP.
traffic goes through. It's also possible the hostname isn't resolvable to the
doesn't guarantee that it will return the address for the interface external
According to coderrr (see comments on blog link above), this implementation
Returns the local IP address based on the hostname.
def ip_address_internal_alt
  ipaddr = :unknown
  begin
    saddr = Socket.getaddrinfo(  Socket.gethostname, nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)
    ipaddr = saddr.select{|type| type[0] == 'AF_INET' }[0][3]
  rescue => ex
  end
  ipaddr
end

def paths; execute_platform_specific(:paths); end

Returns the environment paths as an Array
def paths; execute_platform_specific(:paths); end

def paths_java

Not tested!
def paths_java
  delim = @impl == :windows ? ';' : ':'
  (ENV['PATH'] || '').split(delim)
end

def paths_ruby_unix; (ENV['PATH'] || '').split(':'); end

def paths_ruby_unix; (ENV['PATH'] || '').split(':'); end

def paths_ruby_windows; (ENV['PATH'] || '').split(';'); end # Not tested!

Not tested!
def paths_ruby_windows; (ENV['PATH'] || '').split(';'); end # Not tested!

def platform

e.g. java-unix-osx-x86_64
Returns a String of the full platform descriptor in the format: VM-OS-IMPL-ARCH
def platform
  "#{@vm}-#{@os}-#{@impl}-#{@arch}"
end

def shell; execute_platform_specific(:shell); end

Returns the name of the current shell
def shell; execute_platform_specific(:shell); end

def shell_ruby_unix; (ENV['SHELL'] || getpwattr(:shell) || 'bash').to_sym; end

def shell_ruby_unix; (ENV['SHELL'] || getpwattr(:shell) || 'bash').to_sym; end

def shell_ruby_windows; :dos; end

def shell_ruby_windows; :dos; end

def tmpdir; execute_platform_specific(:tmpdir); end

Returns the path to the current temp directory
def tmpdir; execute_platform_specific(:tmpdir); end

def tmpdir_java

def tmpdir_java
  default = @impl == :windows ? 'C:\\temp' : '/tmp'
  (Dir.tmpdir || default)
end

def tmpdir_ruby_unix; (Dir.tmpdir || '/tmp'); end

def tmpdir_ruby_unix; (Dir.tmpdir || '/tmp'); end

def tmpdir_ruby_windows; (Dir.tmpdir || 'C:\\temp'); end

def tmpdir_ruby_windows; (Dir.tmpdir || 'C:\\temp'); end