#!/usr/bin/ruby # vim: et sw=2 VER="(6893dbd)" ME="bldx: " $chdr="1;36" $cinf="1;37" $cadd="1;32" $cdel="1;31" $chk_fields=["ip"] $incl=[] $excl=[] $fld=nil $opt=nil $mode="normal" def in_list(s,list) for i in list if i.match(s) return true end end return false end def regexfix2(str) tmp=[] for t in str.scan(/(_)|(\|)|([^_\|]*)/).flatten.compact tmp.push(t) if not t.empty? end res="" while t=tmp.shift case t when "_" then res+=(tmp.empty? or tmp[0]=="|") ? '([ ."\[\]\(\)\{\}]+|$)' : '[ ."\[\]\(\)\{\}]+' when "|" then res+="|" else res+="#{t}" end end return res end def chk_net(str) st=str.split("/") return false if st.length>2 pf=32 if st.length==2 return false if !st[1] or st[1].length>2 return false if !/^[0-9]+$/.match(st[1]) pf=st[1].to_i end return false if pf<1 or pf>32 st=st[0].split(".") return false if st.length!=4 4.times do n=st.shift return false if !n or n.length>3 return false if !/^[0-9]+$/.match(n) n=n.to_i return false if n<0 or n>255 (pf-=8; next) if pf>7 bf=255<<(8-pf) return false if n!=(n&bf) pf=0 end return true end class Block attr_reader :la, :name Line=Struct.new :port, :ln, :lp, :arr, :del, :add, :ln2, :lp2 Line1=Struct.new :s0, :arr def initialize(h) @hdr=h @fld=nil @sep=nil @flds=[] @ft=[] @la=[] @ca=[] @arr=[] @name=/^#!? ([^ ]*)/.match(h)[1] end def hdr(h) @hdr=h end def fld(f,s) @fld=f @sep=s tmp=@fld.scan(/[^\t]*\t*/) tmp.delete_if { |t| t.empty? } tc=0 for t in tmp @flds<n k=1+(n-i) return if k>=st1.length str=st1[k] z=@la.last if i==1 and !z.ln2 and not (st1[1].start_with?("!") or st1[1].start_with?("-")) st2=st1[1].split(":") z.ln2=st2[0] z.lp2=st2[1] end else return if st1.length<2 return if st1[0]=="-" or st1[1].start_with?("-") port=st1[0] st2=st1[1].split(":") ln=st2[0] lp=st2[1] i=@flds.index($fld) return if i>=st1.length str=st1[i] if !z=find(port) z=Line.new(port,ln,lp,[],[],[]) @la<n i=1+(n-i) return if i>=tmp.length str=tmp[i] return if str=="?" or str.start_with?("-") or str.start_with?("!") z=@la.last z.arr<=tmp.length str=tmp[i] return if str=="?" or str.start_with?("-") or str.start_with?("!") z=Line1.new(tmp[0],[str]) if !z @la<n i=1+(n-i) return if i>=tmp.length str=tmp[i] else i=@flds.index($fld) return if i>=tmp.length str=tmp[i] end return if str=="?" or str.start_with?("-") or str.start_with?("!") arr=[] for v in str.split(",") if v.include?("-") t=v.split("-") t[0].to_i.upto(t[1].to_i) { |x| arr<mcs end mcs=7 if mcs<7 sep="-"*mcs out.puts "\e[#{$chdr}m%s\e[m" % @hdr out.puts @flds[0],sep @ca.each { |t| out.puts t.s0 } out.puts sep return end col=[] col<<@flds[0].length/8+1 col<<@flds[i].length/8+1 lcs=@flds[i].length for t in @ca c=t.s0.length/8+1 col[0]=c if c>col[0] for u in t.arr c=u.length lcs=c if c>lcs c=c/8+1 col[1]=c if c>col[1] end end mcs=col[0]*8+lcs tmp=@flds[0] c=col[0]-(@flds[0].length/8) tab="\t"*c tmp+=tab+@flds[i] sep="-"*mcs out.puts "\e[#{$chdr}m%s\e[m" % @hdr out.puts tmp,sep for t in @ca tmp=t.s0 c=col[0]-(t.s0.length/8) tab="\t"*c tmp+=tab+t.arr[0] out.puts tmp l=t.arr.length-1 next if t.arr.length<1 l.times do |i| tab="\t"*col[0] out.puts tab+t.arr[i] end end out.puts sep return end def output(out) if $opt=="list" return if @arr.empty? @arr.sort! do |x,y| next -1 if x.start_with?("+") or x.start_with?("*") next 1 if y.start_with?("+") or y.start_with?("*") next x.to_i<=>y.to_i end arr=combine(@arr) c=$chdr out.puts "\e[#{c}m%s\e[m" % @hdr out.puts "#{$fld}: %s" % to_str(arr) return end if $opt=="cmp" return if @ca.empty? c=$chdr out.puts "\e[#{c}m%s\e[m" % @hdr for l in @ca next if l.arr.empty? arr=combine(l.arr) str=l.ln str+=":"+l.lp if l.lp c=$cinf out.puts "\e[#{c}mport: %s\e[m link: %s" % [l.port,str] out.puts "#{$fld}: %s" % to_str(arr) end return end if $opt=="get" c=$chdr out.puts "\e[#{c}m%s\e[m" % @hdr for l in @la next if l.arr.empty? arr=combine(l.arr) str=l.ln str+=":"+l.lp if l.lp c=$cinf out.puts "\e[#{c}mport: %s\e[m link: %s" % [l.port,str] out.puts "#{$fld}: %s" % to_str(arr) end return end if $opt=="chk" return if @ca.empty? output_chk(out) return end return if prepare<1 c=$chdr out.puts "\e[#{c}m%s\e[m" % @hdr for l in @la next if l.del.empty? and l.add.empty? str=l.ln str+=":"+l.lp if l.lp c=$cinf out.puts "\e[#{c}mport: %s\e[m link: %s" % [l.port,str] c=$cdel out.puts "del: \e[#{c}m%s\e[m" % to_str(l.del) if not l.del.empty? c=$cadd out.puts "add: \e[#{c}m%s\e[m" % to_str(l.add) if not l.add.empty? end return end private def find(port) for l in @la return l if l.port==port end return nil end def to_str(arr) if $mode=="huawei" tmp=[] for s in arr (tmp<y.to_i end l.add.sort! do |x,y| next -1 if x.start_with?("+") or x.start_with?("*") next 1 if y.start_with?("+") or y.start_with?("*") next x.to_i<=>y.to_i end l.del=combine(l.del) l.add=combine(l.add) end return cnt end end def usage me=ME.delete(":") puts "Usage: "+me+"" puts " -B - include blocks matching RegEx " puts " -S - skip blocks matching RegEx " puts " -l - make list from (aggregation)" puts " -cmp - compare given list (links.txt)" puts " -get - get given list (links.txt)" puts " -chk - validate " exit end def p_diff(isdf) blocks=[] bl=fld=nil inbl=false igbl=false st=" " for l in $stdin l.chop! next if l.empty? st=l.slice!(0,1) if isdf if inbl if l.start_with?("-----") blocks<=ARGV.length $fld=ARGV[i] if $opt=="chk" and not $chk_fields.include?($fld) $stderr.puts ME+"unsupported field: "+$fld exit end case $opt when "cmp" then blocks=p_diff(false) when "get" then blocks=p_diff(false) when "list" then blocks=p_data when "chk" then blocks=p_data else blocks=p_diff(true) end exit if blocks.empty? do_cmp(blocks) if $opt=="cmp" if $opt=="chk" blocks.each { |b| b.chk } end if $istty out=IO.popen("less -fqRFX","w") else out=$stdout end begin blocks.each { |b| b.output(out) } rescue Errno::EPIPE end out.close if out!=$stdout