Re: Changing Resolv::DNS

From: Daniel Hobe <daniel@...>
Date: 2004-05-16 17:37:56 UTC
List: ruby-core #2884
Any objections to getting this committed to the tree?

On Wednesday 05 May 2004 01:41 pm, Daniel Hobe wrote:
> I like this.  Creates a more unified Resolv class.
>
> > In article <200405011554.53670.daniel@nightrunner.com>,
> >
> >   Daniel Hobe <daniel@nightrunner.com> writes:
> >> Resolv::DNS.new('/etc/foo')
> >> -or-
> >> Resolv::DNS.new({nameserver=>['192.168.10.1','192.168.10.2'],
> >>                  search=>['ruby-lang.org','ruby-doc.org'],
> >>                  ndots => 2})
> >
> > I feel this initialization style is good enough.
> >
> > However I'd like to just change Config instead of defining a subclass.
> >
> > Index: lib/resolv.rb
> > ===================================================================
> > RCS file: /src/ruby/lib/resolv.rb,v
> > retrieving revision 1.19
> > diff -u -r1.19 resolv.rb
> > --- lib/resolv.rb	23 Apr 2004 05:22:24 -0000	1.19
> > +++ lib/resolv.rb	4 May 2004 07:26:35 -0000
> > @@ -10,9 +10,10 @@
> >    Resolv.getaddress("www.ruby-lang.org")
> >    Resolv.getname("210.251.121.214")
> >
> > -  dns = Resolv::DNS.new
> > -  dns.getresources("www.ruby-lang.org",
> > Resolv::DNS::Resource::IN::A).collect {|r| r.address}
> > -  dns.getresources("ruby-lang.org",
> > Resolv::DNS::Resource::IN::MX).collect {|r| [r.exchange.to_s,
> > r.preference]}
> > +  Resolv::DNS.open {|dns|
> > +    dns.getresources("www.ruby-lang.org",
> > Resolv::DNS::Resource::IN::A).collect {|r| r.address}
> > +    dns.getresources("ruby-lang.org",
> > Resolv::DNS::Resource::IN::MX).collect {|r| [r.exchange.to_s,
> > r.preference]}
> > +  }
> >
> >  == Resolv class
> >
> > @@ -57,10 +58,17 @@
> >  DNS stub resolver.
> >
> >  === class methods
> > ---- Resolv::DNS.new(resolv_conf='/etc/resolv.conf')
> > +--- Resolv::DNS.new(config_info=nil)
> >
> > ---- Resolv::DNS.open(resolv_conf='/etc/resolv.conf')
> > ---- Resolv::DNS.open(resolv_conf='/etc/resolv.conf') {|dns| ...}
> > +    ((|config_info|)) should be nil, a string or a hash.
> > +    If nil is given, /etc/resolv.conf and platform specific information
> > is used.
> > +    If a string is given, it should be a filename which format is same
> > as /etc/resolv.conf.
> > +    If a hash is given, it may contains information for nameserver,
> > search and ndots as follows.
> > +
> > +      Resolv::DNS.new({:nameserver=>["210.251.121.21"],
> >
> > :search=>["ruby-lang.org"], :ndots=>1})
> >
> > +
> > +--- Resolv::DNS.open(config_info=nil)
> > +--- Resolv::DNS.open(config_info=nil) {|dns| ...}
> >
> >  === methods
> >  --- Resolv::DNS#close
> > @@ -369,9 +377,9 @@
> >        end
> >      end
> >
> > -    def initialize(config="/etc/resolv.conf")
> > +    def initialize(config_info=nil)
> >        @mutex = Mutex.new
> > -      @config = Config.new(config)
> > +      @config = Config.new(config_info)
> >        @initialized = nil
> >      end
> >
> > @@ -704,47 +712,81 @@
> >      end
> >
> >      class Config
> > -      def initialize(filename="/etc/resolv.conf")
> > +      def initialize(config_info=nil)
> >          @mutex = Mutex.new
> > -        @filename = filename
> > +        @config_info = config_info
> >          @initialized = nil
> >        end
> >
> > +      def Config.parse_resolv_conf(filename)
> > +        nameserver = []
> > +        search = nil
> > +        ndots = 1
> > +        open(filename) {|f|
> > +          f.each {|line|
> > +            line.sub!(/[#;].*/, '')
> > +            keyword, *args = line.split(/\s+/)
> > +            args.each { |arg|
> > +              arg.untaint
> > +            }
> > +            next unless keyword
> > +            case keyword
> > +            when 'nameserver'
> > +              nameserver += args
> > +            when 'domain'
> > +              search = [args[0]]
> > +            when 'search'
> > +              search = args
> > +            end
> > +          }
> > +        }
> > +        return { :nameserver => nameserver, :search => search, :ndots =>
> > ndots }
> > +      end
> > +
> > +      def Config.default_config_hash(filename="/etc/resolv.conf")
> > +        if File.exist? filename
> > +          config_hash = Config.parse_resolv_conf(filename)
> > +        else
> > +          if /mswin32|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM
> > +            search, nameserver = Win32::Resolv.get_resolv_info
> > +            config_hash = {}
> > +            config_hash[:nameserver] = nameserver if nameserver
> > +            config_hash[:search] = [search] if search
> > +          end
> > +        end
> > +        config_hash
> > +      end
> > +
> >        def lazy_initialize
> >          @mutex.synchronize {
> >            unless @initialized
> >              @nameserver = []
> >              @search = nil
> >              @ndots = 1
> > -            begin
> > -              open(@filename) {|f|
> > -                f.each {|line|
> > -                  line.sub!(/[#;].*/, '')
> > -                  keyword, *args = line.split(/\s+/)
> > -                  args.each { |arg|
> > -                    arg.untaint
> > -                  }
> > -                  next unless keyword
> > -                  case keyword
> > -                  when 'nameserver'
> > -                    @nameserver += args
> > -                  when 'domain'
> > -                    @search = [Label.split(args[0])]
> > -                  when 'search'
> > -                    @search = args.map {|arg| Label.split(arg)}
> > -                  end
> > -                }
> > -              }
> > -            rescue Errno::ENOENT
> > -              if /mswin32|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM
> > -                search, nameserver = Win32::Resolv.get_resolv_info
> > -                @search = [search] if search
> > -                @nameserver = nameserver if nameserver
> > +            case @config_info
> > +            when nil
> > +              config_hash = Config.default_config_hash
> > +            when String
> > +              config_hash = Config.parse_resolv_conf(@config_info)
> > +            when Hash
> > +              config_hash = @config_info.dup
> > +              if String === config_hash[:nameserver]
> > +                config_hash[:nameserver] = [config_hash[:nameserver]]
> >                end
> > +              if String === config_hash[:search]
> > +                config_hash[:search] = [config_hash[:search]]
> > +              end
> > +            else
> > +              raise ArgumentError.new("invalid resolv configuration:
> > #{@config_info.inspect}")
> >              end
> > +            @nameserver = config_hash[:nameserver] if
> > config_hash.include? :nameserver
> > +            @search = config_hash[:search] if config_hash.include?
> >
> > :search
> >
> > +            @ndots = config_hash[:ndots] if config_hash.include? :ndots
> >
> >              @nameserver = ['0.0.0.0'] if @nameserver.empty?
> > -            unless @search
> > +            if @search
> > +              @search = @search.map {|arg| Label.split(arg) }
> > +            else
> >                hostname = Socket.gethostname
> >                if /\./ =~ hostname
> >                  @search = [Label.split($')]
> > @@ -752,6 +794,21 @@
> >                  @search = [[]]
> >                end
> >              end
> > +
> > +            if !@nameserver.kind_of?(Array) ||
> > +               !@nameserver.all? {|ns| String === ns }
> > +              raise ArgumentError.new("invalid nameserver config:
> > #{@nameserver.inspect}")
> > +            end
> > +
> > +            if !@search.kind_of?(Array) ||
> > +               !@search.all? {|ls| ls.all? {|l| Label::Str === l } }
> > +              raise ArgumentError.new("invalid search config:
> > #{@search.inspect}")
> > +            end
> > +
> > +            if !@ndots.kind_of?(Integer)
> > +              raise ArgumentError.new("invalid ndots config:
> > #{@ndots.inspect}")
> > +            end
> > +
> >              @initialized = true
> >            end
> >          }
> > --
> > Tanaka Akira

-- 
Daniel Hobe <daniel@nightrunner.com>
http://www.nightrunner.com

In This Thread