class SCPIrcFile

Introduction

SCPIrcFile provides access to data housed in the mrSCPI RC file found at $HOME/.mrSCPIrc or at $MRSCPIRC.

RC File Content

The file has (for now) two kinds of lines: Nickname at SCPIrcFile & Network at SCPIrcFile.

Nickname

Nickname lines look like this:

<space_separated_list_of_nicknames> => <space_separated_list_of_network_annotated_urls>

The components are as follows:

Network

Network lines look like this:

<network_name> <space_separated_list_of_networks>

The components are as follows:

Use

In general SCPIrcFile provides three services:

When nickname strings provided as arguments have no explicitly given network, then the network lines in the RC file are used to try and find one. The host IP addresses are tested for inclusion in each domain listed in the RC file – in the order they are found in the file. If the host has an IP address that is included in one of the networks, then that network name is used for the nickname lookup. If nothing is found, then the network name is left as the empty string – so it will match a network_annotated_url with an empty network.

Public Class Methods

new() click to toggle source
# File src/mrSCPI.rb, line 1234
def initialize ()
  @rcNetworks     = nil
  @rcURLnicknames = nil
  if ENV['HOME'] || ENV['MRSCPIRC'] then
    configFileName = ENV['MRSCPIRC'] || (ENV['HOME'] + '/.mrSCPIrc')
    if FileTest.exist?(configFileName) then
      begin
        configFileFD = open(configFileName, "r")
      rescue
        PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Failed to open RC file!", self, 83)
      end
      if(configFileFD) then
        @rcNetworks     = Array.new
        @rcURLnicknames = Hash.new
        configFileFD.each_line do |line|
          line = line.chomp.gsub(/#.*/, '').downcase.strip.gsub(/  +/, ' ')
          configLineMatchData = line.match(/^([a-zA-Z]+) (.+)$/)
          if configLineMatchData then
            if configLineMatchData[1] == 'nickname' then
              if configLineMatchData[2].match?('=>') then
                (aliases, urls) = configLineMatchData[2].split('=>').map { |x| x.strip.split(/ +/) }
                aliases.each do |a|
                  @rcURLnicknames[a] = (urls.map {|e| ( e.match?('@') ? e : "@#{e}" ).split('@') }).to_h
                end
              else
                PrintyPrintyBangBang.instance.logPrinter(2, "WARNING: RC file: Syntax error in nickname: #{line.inspect}", self)
              end
            elsif configLineMatchData[1] == 'network' then
              netSpecs = configLineMatchData[2].split(/ +/)
              netName  = netSpecs.shift
              netSpecs = netSpecs.map { |x| IPAddr.new(x) }
              @rcNetworks.push([netName, netSpecs])
            else
              PrintyPrintyBangBang.instance.logPrinter(2, "WARNING: RC file: Unrecognized configuration statement: #{line.inspect}", self)
            end
          else
            if line != '' then
              PrintyPrintyBangBang.instance.logPrinter(2, "WARNING: RC file: Syntax error: #{line.inspect}", self)
            end
          end
        end
        configFileFD.close
      else
        PrintyPrintyBangBang.instance.logPrinter(2, "WARNING: RC file: Unable to open file: #{configFileName.inspect}", self)
      end
    else
      PrintyPrintyBangBang.instance.logPrinter(2, "WARNING: RC file missing.", self)
    end
  else
    PrintyPrintyBangBang.instance.logPrinter(2, "WARNING: Can't load RC file (no HOME or MRSCPIRC variable).", self)
  end
end

Public Instance Methods

lookupNetwork(ip_address=nil) click to toggle source

Find a network in the RC file that contains the given ip_address. If ip_address is nil, then the IP addresses of the current host are used. If nothing is found, then an empty string is returned.

# File src/mrSCPI.rb, line 1328
def lookupNetwork (ip_address=nil)
  if !(@rcNetworks.empty?) then
    if ip_address.nil? then
      ip_address = Socket.ip_address_list.select(&:ipv4?).map { |x| IPAddr.new(x.ip_address) }
    end
    dMatch = @rcNetworks.find { |network, nets| nets.any? { |n| ip_address.any? { |a| n.include?(a) } } }
    if dMatch then
      return dMatch.first
    end
  end
  return ''
end
lookupURLnickname(nicknameString) click to toggle source

Helper function to lookup instrument nicknames to URLs. The nicknameString can take one of three forms:

  • network@nickname

  • @nickname

  • nickname

SCPIsession only uses the first two forms. Returns an nil if the lookup failed. Otherwise returns the match as a string.

# File src/mrSCPI.rb, line 1294
def lookupURLnickname (nicknameString)
  if @rcURLnicknames then
    nicknameMatch = nicknameString.match(SCPIregexLibrary.instance.a(:mrs_nickname))
    if nicknameMatch then
      inNetwork  = (nicknameMatch[1].nil? ? '' : nicknameMatch[1].downcase)
      inName     = nicknameMatch[2].downcase

      # Now figure out what network we should use
      if inNetwork == '' then
        inNetwork = lookupNetwork() || inNetwork
      end
      # Now we look for our nickname
      if @rcURLnicknames.empty? then
        PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: No nicknams loaded.", self, 78)
        return nil
      elsif @rcURLnicknames.member?(inName) && @rcURLnicknames[inName].member?(inNetwork) then
        return @rcURLnicknames[inName][inNetwork]
      else
        PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Nickname was not found in the RC file", self, 79)
        return nil
      end
    else
      PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: Invalid nickname string", self, 80)
      return nil
    end
  else
    PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: RC config file errors", self, 81)
    return nil
  end
end
urlParser(urlString) click to toggle source

Parse URLs. Lookup nicknames if requried. Return nil if urlString is invalid and a hash otherwise

# File src/mrSCPI.rb, line 1343
def urlParser (urlString)
  if urlString.match?('@') then
    urlString = SCPIrcFile.instance.lookupURLnickname(urlString)
    if urlString.nil? then
      return nil
    end
  end
  urlMatch = urlString.match(SCPIregexLibrary.instance.a(:mrs_url))
  if urlMatch then
    return { :url          => urlString,
             :net_protocol => (urlMatch[1] && urlMatch[1].to_sym),
             :ip_address   => urlMatch[2],
             :net_port     => (urlMatch[3] && urlMatch[3].to_i) }
  else
    PrintyPrintyBangBang.instance.logPrinter(1, "ERROR: :url was malformed: #{urlString.inspect}", self, 70)
    return nil
  end
end