From: Daniel Hobe Date: 2004-05-06T05:41:21+09:00 Subject: Re: Changing Resolv::DNS 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