From: Daniel Hobe Date: 2004-05-17T02:37:56+09:00 Subject: Re: Changing Resolv::DNS 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 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 http://www.nightrunner.com