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