PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /usr/bin
Viewing File: /usr/bin/snmpconf
#!/usr/bin/perl # # A simple configuration file builder based on questions listed in # its own configuration file. It would certainly be easy to use this # for other (non-snmp) programs as well. # use Getopt::Std; use Term::ReadLine; use IO::File; use Data::Dumper; use File::Copy; if ($^O eq 'MSWin32') { eval 'require Win32::Registry;'; if ($@) { print "\nWarning: Perl module Win32::Registry is not installed. This module is\n"; print " required to read the SNMPSHAREPATH and SNMPCONFPATH values from \n"; print " the registry. To use snmpconf without the module you need to\n"; print " define SNMPSHAREPATH and SNMPCONFPATH as environment variables\n"; print " or use the -c and -I command line options.\n"; } } # globals %tokenitems=qw(line 1 info 1 comment 1); %arrayitems=qw(question 1 validanswer 1); # default folder for snmpconf-data if (defined(&my_getenv("SNMPSHAREPATH"))) { $opts{'c'} = &my_getenv("SNMPSHAREPATH") . "/snmpconf-data"; } else { $opts{'c'} = "/usr/share/snmp/snmpconf-data"; } # default config file path if (defined(&my_getenv("SNMPCONFPATH"))) { $confpath = &my_getenv("SNMPCONFPATH"); } else { $confpath = "/usr/share/snmp"; } # home environment variable if (defined(&my_getenv("HOME"))) { $home = &my_getenv("HOME") . "/.snmp"; } else { $home = "(HOME dir - n/a)"; } # read the argument string getopts("qadhfc:piI:r:R:g:G", \%opts); # display help if ($opts{'h'}) { print "$0 [options] [FILETOCREATE...]\n"; print "options:\n"; print " -f overwrite existing files without prompting\n"; print " -i install created files into $confpath.\n"; print " -p install created files into $home.\n"; print " -I DIR install created files into DIR.\n"; print " -a Don't ask any questions, just read in current\n"; print " current .conf files and comment them\n"; print " -r all|none Read in all or none of the .conf files found.\n"; print " -R file,... Read in a particular list of .conf files.\n"; print " -g GROUP Ask a series of GROUPed questions.\n"; print " -G List known GROUPs.\n"; print " -c conf_dir use alternate configuration directory.\n"; print " -q run more quietly with less advice.\n"; print " -d turn on debugging output.\n"; print " -D turn on debugging dumper output.\n"; exit; } # setup terminal interface. $ENV{'PERL_RL'}='o=0' if (!exists($ENV{'PERL_RL'})); $term = new Term::ReadLine 'snmpconf'; # read in configuration file set read_config_files($opts{'c'}, \%filetypes); debug(my_Dumper(\%filetypes)); if ($opts{'G'}) { Print("\nKnown GROUPs of tokens:\n\n"); foreach my $group (keys(%groups)) { print " $group\n"; } Print("\n"); exit; } # # Expand the search path in case it contains multiple directories. # my $ENV_SEPARATOR = ':'; my @searchpath = split(/$ENV_SEPARATOR/, $confpath); push @searchpath, "/etc/snmp"; push @searchpath, "."; push @searchpath, "$home"; # Remove trailing /'s or \'s for (my $i=0; $i <= $#searchpath; $i++) { $searchpath[$i] =~ /(.*?)([\/\\])*$/; $searchpath[$i] = $1; } # Determine persistent directory. Order of preference: # # file in SNMP_PERSISTENT_FILE environment variable # directory defined by persistentDir snmp.conf variable # directory in SNMP_PERSISTENT_DIR environment variable # default PERSISTENT_DIRECTORY directory my $persistentDir = ""; my $persistentFile = ""; # SNMP_PERSISTENT_FILE environment variable if (defined(&my_getenv("SNMP_PERSISTENT_FILE"))) { $persistentFile = &my_getenv("SNMP_PERSISTENT_FILE"); debug ("persistent file: SNMP_PERSISTENT_FILE environment variable set\n"); } # snmp.conf persistentDir if (!($persistentDir) && !($persistentFile)) { foreach my $i (@searchpath) { debug ("Searching file $i/snmp.conf for persistentDir\n"); my $temp = get_persistentDir("$i/snmp.conf"); if ($temp) { debug("persistent directory: set to $temp in $i/snmp.conf\n"); $persistentDir = $temp; last; } } } # SNMP_PERSISTENT_DIR environment variable if (!($persistentDir) && !($persistentFile)) { if (&my_getenv("SNMP_PERSISTENT_DIR")) { $persistentDir = &my_getenv("SNMP_PERSISTENT_DIR"); debug ("persistent directory: SNMP_PERSISTENT_DIR environment variable set\n"); } } # PERSISTENT_DIRECTORY default variable if (!($persistentDir) && !($persistentFile)) { $persistentDir = "/var/lib/net-snmp"; debug ("persistent directory: Using default value\n"); } # Rebuild search path without persistent folder # Note: persistent file handled in Find existing # files to possibly read in section if ($persistentDir) { # Remove trailing /'s or \'s $persistentDir =~ /(.*?)([\/\\])*$/; $persistentDir = $1; debug ("persistent directory: $persistentDir\n"); my @searchpath_old = @searchpath; @searchpath = (); foreach my $path_temp (@searchpath_old) { if ($path_temp eq $persistentDir) { debug("skipping persistent directory $path_temp\n"); next; } push @searchpath, $path_temp; } } # Reset $confpath to the first path $confpath = $searchpath[0]; # # Find existing files to possibly read in. # push @searchpath, $opts{I} if ($opts{I}); foreach my $i (@searchpath) { debug("searching $i\n"); foreach my $ft (keys(%filetypes)) { if ("$i/$ft" eq $persistentFile) { debug("skipping persistent file $i/$ft\n"); next; } debug("searching for $i/$ft\n"); $knownfiles{"$i/$ft"} = $ft if (-f "$i/$ft"); my $localft = $ft; $localft =~ s/.conf/.local.conf/; $knownfiles{"$i/$localft"} = $ft if (-f "$i/$localft"); } } # # Ask the user if they want them to be read in and read them # if (keys(%knownfiles)) { my @files; if (defined($opts{'r'})) { if ($opts{'r'} eq "all" || $opts{'r'} eq "a") { @files = keys(%knownfiles); } elsif ($opts{'r'} ne "none" && $opts{'r'} ne "n") { print "unknown argument to -r: $opts{'r'}\n"; exit(1); } } elsif(defined($opts{'R'})) { @files = split(/\s*,\s*/,$opts{'R'}); foreach my $i (@files) { my $x = $i; $x =~ s/.*\/([^\/]+)$/$1/; $knownfiles{$i} = $x; } Print("reading: ", join(",",@files),"\n"); } else { @files = display_menu(-head => "The following installed configuration files were found:\n", -tail => "Would you like me to read them in? Their content will be merged with the\noutput files created by this session.\n\nValid answer examples: \"all\", \"none\",\"3\",\"1,2,5\"\n", -multiple => 1, -question => 'Read in which', -defaultvalue => 'all', sort keys(%knownfiles)); } foreach my $i (@files) { debug("reading $i\n"); read_config($i, $knownfiles{$i}); } } if ($opts{'g'}) { my @groups = split(/,:\s/,$opts{'g'}); foreach my $group (@groups) { do_group($group); } } elsif ($#ARGV >= 0) { # # loop through requested files. # foreach my $i (@ARGV) { if (!defined($filetypes{$i})) { warn "invalid file: $i\n"; } else { if ($opts{'a'}) { $didfile{$i} = 1; } else { build_file($term, $i, $filetypes{$i}); } } } } else { # # ask user to select file type to operate on. # while(1) { my $line = display_menu(-head => "I can create the following types of configuration files for you.\nSelect the file type you wish to create:\n(you can create more than one as you run this program)\n", -question => 'Select File', -otheranswers => ['quit'], -mapanswers => { 'q' => 'quit' }, keys(%filetypes)); last if ($line eq "quit"); debug("file selected: $line\n"); build_file($term, $line, $filetypes{$line}); } } # # Write out the results to the output files. # output_files(\%filetypes, $term); # # Display the files that have been created for the user. # Print("\n\nThe following files were created:\n\n"); @didfiles = keys(%didfile); foreach my $i (@didfiles) { if ($didfile{$i} ne "1") { if ($opts{'i'} || $opts{'I'}) { $opts{'I'} = "$confpath" if (!$opts{'I'}); if (! (-d "$opts{'I'}") && ! (mkdir ("$opts{'I'}", 0755))) { print "\nCould not create $opts{'I'} directory: $!\n"; print ("File $didfile{$i} left in current directory\n"); } else { move ("$opts{'I'}/$i", "$opts{'I'}/$i.bak") if (-f "$opts{'I'}/$i"); if (move ("$didfile{$i}", "$opts{'I'}")) { print(" $didfile{$i} installed in $opts{'I'}\n"); } else { print "\nCould not move file $didfile{$i} to $opts{'I'}/$i: $!\n"; print ("File $didfile{$i} left in current directory\n"); } } } elsif ($opts{'p'}) { if (! (-d "$home") && ! (mkdir ("$home", 0755))) { print "\nCould not create $home directory: $!\n"; print ("File $didfile{$i} left in current directory\n"); } else { move ("$home/$i", "$home/$i.bak") if (-f "$home/$i"); if (move ("$didfile{$i}", "$home")) { print(" $didfile{$i} installed in $home\n"); } else { print "\nCould not move file $didfile{$i} to $home: $!\n"; print ("File $didfile{$i} left in current directory\n"); } } } else { Print(" $didfile{$i} ", ($i ne $didfile{$i})?"[ from $i specifications]":" ","\n"); if ($opts{'d'}) { open(I,$didfile{$i}); debug(" " . join(" ",<I>) . "\n"); close(I); } } } } if (!$opts{'p'} && !$opts{'i'} && !$opts{'I'}) { Print("\nThese files should be moved to $confpath if you want them used by everyone on the system. In the future, if you add the -i option to the command line I'll copy them there automatically for you. Or, if you want them for your personal use only, copy them to $home . In the future, if you add the -p option to the command line I'll copy them there automatically for you. "); } ########################################################################### # Functions ########################################################################### sub Print { print @_ if (!$opts{'q'}); } # # handle a group of questions # sub get_yn_maybe { my $question = shift; my $ans = "y"; if ($question ne "") { $ans = get_answer($term, $question, valid_answers(qw(yes y no n)), 'y'); } return ($ans =~ /^y/)?1:0; } sub do_group { my $group = shift; die "no such group $group\n" if (!$groups{$group}); foreach my $token (@{$groups{$group}}) { if ($token->[0] eq "message") { Print ("$token->[1] $token->[2]\n"); } elsif ($token->[0] eq "subgroup") { do_group($token->[1]) if (get_yn_maybe($token->[2])); } elsif (defined($tokenmap{$token->[1]})) { if (get_yn_maybe($token->[2])) { do { do_line($token->[1], $tokenmap{$token->[1]}); } until ($token->[0] ne "multiple" || get_answer($term, "Do another $token->[1] line?", valid_answers(qw(yes y no n)), 'y') =~ /n/); } } elsif (defined($filetypes{$token->[1]})) { $didfile{$token->[1]} = 1; } else { die "invalid member $token->[1] of group $group\n"; } } } # # build a particular type of file by operating on sections # sub build_file { my ($term, $filename, $fileconf) = @_; $didfile{$filename} = 1; my (@lines); while(1) { my $line = display_menu(-head => "The configuration information which can be put into $filename is divided\ninto sections. Select a configuration section for $filename\nthat you wish to create:\n", -otheranswers => ['finished'], -mapanswers => { 'f' => 'finished' }, -question => "Select section", -numeric => 1, map { $_->{'title'}[0] } @$fileconf); return @lines if ($line eq "finished"); do_section($fileconf->[$line-1]); } } # # configure a particular section by operating on token types # sub do_section { my $confsect = shift; my @lines; while(1) { Print ("\nSection: $confsect->{'title'}[0]\n"); Print ("Description:\n"); Print (" ", join("\n ",@{$confsect->{'description'}}),"\n"); my $line = display_menu(-head => "Select from:\n", -otheranswers => ['finished','list'], -mapanswers => { 'f' => 'finished', 'l' => 'list' }, -question => 'Select section', -descriptions => [map { $confsect->{$_}{info}[0] } @{$confsect->{'thetokens'}}], @{$confsect->{'thetokens'}}); return @lines if ($line eq "finished"); if ($line eq "list") { print "Lines defined for section \"$confsect->{title}[0]\" so far:\n"; foreach my $i (@{$confsect->{'thetokens'}}) { if ($#{$confsect->{$i}{'results'}} >= 0) { print " ",join("\n ",@{$confsect->{$i}{'results'}}),"\n"; } } next; } do_line($line, $confsect->{$line}); } return; } # # Ask all the questions related to a particular line type # sub do_line { my $token = shift; my $confline = shift; my (@answers, $counter, $i); # debug(my_Dumper($confline)); Print ("\nConfiguring: $token\n"); Print ("Description:\n ",join("\n ",@{$confline->{'info'}}),"\n\n"); for($i=0; $i <= $#{$confline->{'question'}}; $i++) { if (defined($confline->{'question'}[$i]) && $confline->{'question'}[$i] ne "") { my $q = $confline->{'question'}[$i]; $q =~ s/\$(\d+)/$answers[$1]/g; debug("after: $term, $q, ",$confline->{'validanswer'}[$i],"\n"); $answers[$i] = get_answer($term, $q, $confline->{'validanswer'}[$i]); $answers[$i] =~ s/\"/\\\"/g; $answers[$i] = '"' . $answers[$i] . '"' if ($answers[$i] =~ /\s/); } } if ($#{$confline->{'line'}} == -1) { my ($i,$line); for($i=0; $i <= $#{$confline->{'question'}}; $i++) { next if (!defined($confline->{'question'}[$i]) || $confline->{'question'}[$i] eq ""); $line .= " \$" . $i; } push @{$confline->{'line'}}, $line; } foreach my $line (@{$confline->{'line'}}) { my $finished = $line; debug("preline: $finished\n"); debug("answers: ",my_Dumper(\@answers)); $finished =~ s/\$(\d+)/$answers[$1]/g; if ($line =~ s/^eval\s+//) { debug("eval: $finished\n"); $finished = eval $finished; debug("eval results: $finished\n"); } $finished = $token . " " . $finished; Print ("\nFinished Output: $finished\n"); push @{$confline->{'results'}},$finished; } } # # read all sets of config files in the various subdirectories. # sub read_config_files { my $readdir = shift; my $filetypes = shift; opendir(DH, $readdir) || die "no such directory $readdir, did you run make install?\n"; my $dir; my $configfilename="snmpconf-config"; while(defined($dir = readdir(DH))) { next if ($dir =~ /^\./); next if ($dir =~ /CVS/); debug("dir entry: $dir\n"); if (-d "$readdir/$dir" && -f "$readdir/$dir/$configfilename") { my $conffile; # read the top level configuration inforamation about the direcotry. open(I, "$readdir/$dir/$configfilename"); while(<I>) { $conffile = $1 if (/forconffile: (.*)/); } close(I); # no README informatino. if ($conffile eq "") { print STDERR "Warning: No 'forconffile' information in $readdir/$dir/$configfilename\n"; next; } # read all the daat in the directory $filetypes->{$conffile} = read_config_items("$readdir/$dir", $conffile); } else { # no README informatino. print STDERR "Warning: No $configfilename file found in $readdir/$dir\n"; } } closedir DH; } # # read each configuration file in a directory # sub read_config_items { my $itemdir = shift; my $type = shift; opendir(ITEMS, $itemdir); my $file; my @results; while(defined($file = readdir(ITEMS))) { next if ($file =~ /~$/); next if ($file =~ /^snmpconf-config$/); if (-f "$itemdir/$file") { my $res = read_config_item("$itemdir/$file", $type); if (scalar(keys(%$res)) > 0) { push @results, $res; } } } closedir(ITEMS); return \@results; } # # mark a list of tokens as a special "group" # sub read_config_group { my ($fh, $group, $type) = @_; my $line; debug("handling group $group\n"); push (@{$groups{$group}},['filetype', $type]); while($line = <$fh>) { chomp($line); next if ($line =~ /^\s*$/); next if ($line =~ /^\#/); return $line if ($line !~ /^(single|multiple|message|filetype|subgroup)/); my ($type, $token, $rest) = ($line =~ /^(\w+)\s+([^\s]+)\s*(.*)/); debug ("reading group $group : $type -> $token -> $rest\n"); push (@{$groups{$group}}, [$type, $token, $rest]); } return; } # # Parse one file # sub read_config_item { my $itemfile = shift; my $itemcount; my $type = shift; my $fh = new IO::File($itemfile); return if (!defined($fh)); my (%results, $curtoken); debug("tokenitems: ", my_Dumper(\%tokenitems)); topwhile: while($line = <$fh>) { next if ($line =~ /^\s*\#/); my ($token, $rest) = ($line =~ /^(\w+)\s+(.*)/); next if (!defined($token) || !defined($rest)); while ($token eq 'group') { # handle special group list my $next = read_config_group($fh, $rest,$type); if ($next) { ($token, $rest) = ($next =~ /^(\w+)\s+(.*)/); } else { next topwhile; } } debug("token: $token => $rest\n"); if ($token eq 'steal') { foreach my $stealfrom (keys(%{$results{$rest}})) { if (!defined($results{$curtoken}{$stealfrom})) { @{$results{$curtoken}{$stealfrom}} = @{$results{$rest}{$stealfrom}}; } } } elsif (defined($tokenitems{$token})) { if (!defined($curtoken)) { die "error in configuration file $itemfile, no token set\n"; } $rest =~ s/^\#//; push @{$results{$curtoken}{$token}},$rest; } elsif (defined($arrayitems{$token})) { if (!defined($curtoken)) { die "error in configuration file $itemfile, no token set\n"; } my ($num, $newrest) = ($rest =~ /^(\d+)\s+(.*)/); if (!defined($num) || !defined($newrest)) { warn "invalid config line: $line\n"; } else { $results{$curtoken}{$token}[$num] = $newrest; } } elsif ($token =~ /^token\s*$/) { $rest = lc($rest); $curtoken = $rest; if (! exists $results{$curtoken}{'defined'}) { push @{$results{'thetokens'}}, $curtoken; $results{$curtoken}{'defined'} = 1; } $tokenmap{$curtoken} = $results{$curtoken}; debug("current token set to $token\n"); } else { push @{$results{$token}},$rest; } } return \%results; } sub debug { print @_ if ($opts{'d'}); } sub output_files { my $filetypes = shift; my $term = shift; foreach my $ft (keys(%$filetypes)) { next if (!$didfile{$ft}); my $outputf = $ft; if (-f $outputf && !$opts{'f'}) { print "\nError: An $outputf file already exists in this directory.\n\n"; my $ans = get_answer($term,"'overwrite', 'skip', 'rename' or 'append'? ",valid_answers(qw(o overwrite r rename s skip a append))); next if ($ans =~ /^(s|skip)$/i); if ($ans =~ /^(a|append)/) { $outputf = ">$outputf"; } elsif ($ans =~ /^(r|rename)$/i) { # default to rename for error conditions $outputf = $term->readline("Save to what new file name instead (or 'skip')? "); } } $didfile{$ft} = $outputf; open(O,">$outputf") || warn "couldn't write to $outputf\n"; print O "#" x 75,"\n"; print O "#\n# $ft\n"; print O "#\n# - created by the snmpconf configuration program\n#\n"; foreach my $sect (@{$filetypes->{$ft}}) { my $secthelp = 0; foreach my $token (@{$sect->{'thetokens'}}) { if ($#{$sect->{$token}{'results'}} >= 0) { if ($secthelp++ == 0) { print O "#" x 75,"\n# SECTION: ", join("\n# ", @{$sect->{title}}), "\n#\n"; print O "# ", join("\n# ",@{$sect->{description}}), "\n"; } print O "\n# $token: ", join("\n# ",@{$sect->{$token}{info}}), "\n\n"; foreach my $result (@{$sect->{$token}{'results'}}) { print O "$result\n"; } } } print O "\n\n\n"; } if ($#{$unknown{$ft}} > -1) { print O "#\n# Unknown directives read in from other files by snmpconf\n#\n"; foreach my $unknown (@{$unknown{$ft}}) { print O $unknown,"\n"; } } close(O); } } sub get_answer { my ($term, $question, $regexp, $defaultval) = @_; $question .= " (default = $defaultval)" if (defined($defaultval) && $defaultval ne ""); $question .= ": "; my $ans = $term->readline($question); return $defaultval if ($ans eq "" && defined($defaultval) && $defaultval ne ""); while (!(!defined($regexp) || $regexp eq "" || $ans =~ /$regexp/)) { print "invalid answer! It must match this regular expression: $regexp\n"; $ans = $term->readline($question); } return $defaultval if ($ans eq "" && defined($defaultval) && $defaultval ne ""); return $ans; } sub valid_answers { my @list; foreach $i (@_) { push @list, $i if ($i); } return "^(" . join("|",@list) . ")\$"; } sub read_config { my $file = shift; my $filetype = shift; return if (!defined($filetypes{$filetype})); if (! -f $file) { warn "$file does not exist\n"; return; } open(I,$file); while(<I>) { next if (/^\s*\#/); next if (/^\s*$/); chomp; my ($token, $rest) = /^\s*(\w+)\s+(.*)/; $token = lc($token); next if (defined($alllines{$_})); # drop duplicate lines if (defined($tokenmap{$token})) { push @{$tokenmap{$token}{'results'}},$_; } else { push @{$unknown{$filetype}},$_; } $alllines{$_}++; } close(I); } sub display_menu { my %config; while ($#_ > -1 && $_[0] =~ /^-/) { my $key = shift; $config{$key} = shift; } my $count=1; print "\n" if (!defined($config{'-dense'})); if ($config{'-head'}) { print $config{'-head'}; print "\n" if (!defined($config{'-dense'})); } my @answers = @_; my @list; if (defined($config{'-descriptions'}) && ref($config{'-descriptions'}) eq "ARRAY") { @list = @{$config{'-descriptions'}} } else { @list = @_; } foreach my $i (@list) { printf " %2d: $i\n", $count++ if ($i); } print "\n" if (!defined($config{'-dense'})); if (defined($config{'-otheranswers'})) { if (ref($config{'-otheranswers'}) eq 'ARRAY') { print "Other options: ", join(", ", @{$config{'-otheranswers'}}), "\n"; push @answers, @{$config{'-otheranswers'}}; push @answers, keys(%{$config{'-mapanswers'}}); } else { my $maxlen = 0; push @answers,keys(%{$config{'-otheranswers'}}); foreach my $i (keys(%{$config{'-otheranswers'}})) { $maxlen = length($i) if (length($i) > $maxlen); } foreach my $i (keys(%{$config{'-otheranswers'}})) { printf(" %-" . $maxlen . "s: %s\n", $i, $config{'-otheranswers'}{$i}); } } print "\n" if (!defined($config{'-dense'})); } if ($config{'-tail'}) { print $config{'-tail'}; print "\n" if (!defined($config{'-dense'})); } if (defined($config{'-question'})) { while(1) { my $numexpr; if ($config{'-multiple'}) { $numexpr = '[\d\s,]+|all|a|none|n'; } else { $numexpr = '\d+'; } push @answers,"" if ($config{'-defaultvalue'}); $ans = get_answer($term, $config{'-question'}, valid_answers($numexpr,@answers), $config{'-defaultvalue'}); if ($config{'-mapanswers'}{$ans}) { $ans = $config{'-mapanswers'}{$ans}; } if ($ans =~ /^$numexpr$/) { if ($config{'-multiple'}) { my @list = split(/\s*,\s*/,$ans); my @ret; $count = 0; foreach my $i (@_) { $count++; if ($ans eq "all" || $ans eq "a" || grep(/^$count$/,@list)) { push @ret, $i; } } return @ret; } else { if ($ans <= 0 || $ans > $#_+1) { warn "invalid selection: $ans [must be 1-" . ($#_+1) . "]\n"; } else { return $ans if ($config{'-numeric'}); $count = 0; foreach my $i (@_) { $count++; if ($ans eq $count) { return $i; } } } } } else { return $ans; } } } } sub my_Dumper { if ($opts{'D'}) { return Dumper(@_); } else { return "\n"; } } sub get_persistentDir { my $file = shift; my $result = 0; if (! -f $file) { return 0; } open(I,$file); while(<I>) { next if (/^\s*\#/); next if (/^\s*$/); chomp; my ($token, $rest) = /^\s*(\w+)\s+(.*)/; if (lc($token) eq "persistentdir") { $result = $rest; } next; } close(I); return $result; } # Usage: &win32_reg_read("key", "value") # Example: &win32_reg_read("SOFTWARE\\Net-SNMP","SNMPSHAREPATH"); # Returns: Value if found in HKCU or HCLM. Otherwise an empty string. sub win32_reg_read { my $sub_key = shift; my $value = shift; require Win32::Registry; my ($hkey, %key_values, $temp, $no_warn); # Try HKCU first $no_warn = $HKEY_CURRENT_USER; if ($HKEY_CURRENT_USER->Open($sub_key, $hkey)) { $hkey->GetValues(\%key_values); foreach $temp (sort keys %key_values) { if ($temp eq $value) { return $key_values{$temp}[2]; } } $hkey->Close(); } # Try HKLM second $no_warn = $HKEY_LOCAL_MACHINE; if ($HKEY_LOCAL_MACHINE->Open($sub_key, $hkey)) { $hkey->GetValues(\%key_values); foreach $temp (sort keys %key_values) { if ($temp eq $value) { return $key_values{$temp}[2]; } } $hkey->Close(); } return ""; } # Usage: &my_getenv("key") # Example: &my_getenv("SNMPSHAREPATH"); # Returns: Unix: Environment variable value (undef if not defined) # Win32: HKCU\Software\Net-SNMP\(key) or # Win32: HKLM\Software\Net-SNMP\(key) or # Win32: Environment variable value (undef if not defined) sub my_getenv { my $key = shift; # Unix if ($^O ne 'MSWin32') { return $ENV{$key}; } # Windows else { my $temp = &win32_reg_read("SOFTWARE\\Net-SNMP","$key"); if ($temp ne "") { return $temp; } else { return $ENV{$key}; } } }