snmpconf
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:26k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. #!/usr/bin/perl -w
  2. #
  3. # A simple configuration file builder based on questions listed in
  4. # its own configuration file.  It would certainly be easy to use this
  5. # for other (non-snmp) programs as well.
  6. #
  7. use Getopt::Std;
  8. use Term::ReadLine;
  9. use IO::File;
  10. use Data::Dumper;
  11. use File::Copy;
  12. if ($^O eq 'MSWin32') {
  13.   eval 'require Win32::Registry;';
  14.   if ($@) {
  15.     print "nWarning: Perl module Win32::Registry is not installed.  This module isn";
  16.     print "         required to read the SNMPSHAREPATH and SNMPCONFPATH values from n";
  17.     print "         the registry.  To use snmpconf without the module you need ton";
  18.     print "         define SNMPSHAREPATH and SNMPCONFPATH as environment variablesn";
  19.     print "         or use the -c and -I command line options.n";
  20.   }
  21. }
  22. # globals
  23. %tokenitems=qw(line 1 info 1 comment 1);
  24. %arrayitems=qw(question 1 validanswer 1);
  25. # default folder for snmpconf-data
  26. if (defined(&my_getenv("SNMPSHAREPATH"))) {
  27.   $opts{'c'} = &my_getenv("SNMPSHAREPATH") . "/snmpconf-data";
  28. }
  29. else {
  30.   $opts{'c'} = "/usr/local/share/snmp/snmpconf-data";
  31. }
  32.  
  33. # default config file path
  34. if (defined(&my_getenv("SNMPCONFPATH"))) {
  35.   $confpath = &my_getenv("SNMPCONFPATH");
  36. }
  37. else {
  38.   $confpath = "/usr/local/share/snmp";
  39. }
  40. # home environment variable
  41. if (defined(&my_getenv("HOME"))) {
  42.   $home = &my_getenv("HOME") . "/.snmp";
  43. }
  44. else {
  45.   $home = "(HOME dir - n/a)";
  46. }
  47. # read the argument string
  48. getopts("qadhfc:piI:r:R:g:G", %opts);
  49. # display help
  50. if ($opts{'h'}) {
  51.     print "$0 [options] [FILETOCREATE...]n";
  52.     print "options:n";
  53.     print "  -f           overwrite existing files without promptingn";
  54.     print "  -i           install created files into $confpath.n";
  55.     print "  -p           install created files into $home.n";
  56.     print "  -I DIR       install created files into DIR.n";
  57.     print "  -a           Don't ask any questions, just read in currentn";
  58.     print "                   current .conf files and comment themn";
  59.     print "  -r all|none  Read in all or none of the .conf files found.n";
  60.     print "  -R file,...  Read in a particular list of .conf files.n";
  61.     print "  -g GROUP     Ask a series of GROUPed questions.n";
  62.     print "  -G           List known GROUPs.n";
  63.     print "  -c conf_dir  use alternate configuration directory.n";
  64.     print "  -q           run more quietly with less advice.n";
  65.     print "  -d           turn on debugging output.n";
  66.     print "  -D           turn on debugging dumper output.n";
  67.     exit;
  68. }
  69. # setup terminal interface.
  70. $ENV{'PERL_RL'}='o=0' if (!exists($ENV{'PERL_RL'}));
  71. $term = new Term::ReadLine 'snmpconf';
  72. # read in configuration file set
  73. read_config_files($opts{'c'}, %filetypes);
  74. debug(my_Dumper(%filetypes));
  75. if ($opts{'G'}) {
  76.     Print("nKnown GROUPs of tokens:nn");
  77.     foreach my $group (keys(%groups)) {
  78. print "  $groupn";
  79.     }
  80.     Print("n");
  81.     exit;
  82. }
  83. #
  84. # Expand the search path in case it contains multiple directories
  85. # separated by : (Unix) or ; (Win32)
  86. #
  87. my $ENV_SEPARATOR = ':';
  88. if ($^O eq 'MSWin32') {
  89.   $ENV_SEPARATOR = ';';
  90. }
  91. my @searchpath = split(/$ENV_SEPARATOR/, $confpath);
  92. push @searchpath, "/usr/local/etc/snmp";
  93. push @searchpath, ".";
  94. push @searchpath, "$home";
  95. # Remove trailing /'s or 's
  96. for (my $i=0; $i <= $#searchpath; $i++) {
  97.   $searchpath[$i] =~ /(.*?)([/\])*$/;
  98.   $searchpath[$i] = $1;
  99. }
  100. # Determine persistent directory.  Order of preference:
  101. # file in SNMP_PERSISTENT_FILE environment variable
  102. # directory defined by persistentDir snmp.conf variable
  103. # directory in SNMP_PERSISTENT_DIR environment variable
  104. # default PERSISTENT_DIRECTORY directory
  105. my $persistentDir = "";
  106. my $persistentFile = "";
  107. # SNMP_PERSISTENT_FILE environment variable
  108. if (defined(&my_getenv("SNMP_PERSISTENT_FILE"))) {
  109.   $persistentFile = &my_getenv("SNMP_PERSISTENT_FILE");
  110.   debug ("persistent file: SNMP_PERSISTENT_FILE environment variable setn");
  111. }
  112. # snmp.conf persistentDir
  113. if (!($persistentDir) && !($persistentFile)) {
  114.   foreach my $i (@searchpath) {
  115.     debug ("Searching file $i/snmp.conf for persistentDirn");
  116.     my $temp = get_persistentDir("$i/snmp.conf");
  117.     if ($temp) {
  118.       debug("persistent directory: set to $temp in $i/snmp.confn");
  119.       $persistentDir = $temp;
  120.       last;
  121.     }
  122.   }
  123. }
  124. # SNMP_PERSISTENT_DIR environment variable
  125. if (!($persistentDir) && !($persistentFile)) {
  126.   if (&my_getenv("SNMP_PERSISTENT_DIR")) {
  127.     $persistentDir = &my_getenv("SNMP_PERSISTENT_DIR");
  128.     debug ("persistent directory: SNMP_PERSISTENT_DIR environment variable setn");
  129.   }
  130. }
  131. # PERSISTENT_DIRECTORY default variable
  132. if (!($persistentDir) && !($persistentFile)) {
  133.   $persistentDir = "/var/net-snmp";
  134.   debug ("persistent directory: Using default valuen");
  135. }
  136. # Rebuild search path without persistent folder
  137. # Note:  persistent file handled in Find existing 
  138. # files to possibly read in section
  139. if ($persistentDir) {
  140.   # Remove trailing /'s or 's
  141.   $persistentDir =~ /(.*?)([/\])*$/;
  142.   $persistentDir = $1;
  143.   debug ("persistent directory: $persistentDirn");
  144.   my @searchpath_old = @searchpath;
  145.   @searchpath = ();
  146.   foreach my $path_temp (@searchpath_old) {
  147.     if ($path_temp eq $persistentDir) {
  148.       debug("skipping persistent directory $path_tempn");
  149.       next;
  150.     }
  151.     push @searchpath, $path_temp;
  152.   }
  153. }
  154. # Reset $confpath to the first path
  155. $confpath = $searchpath[0];
  156. #
  157. # Find existing files to possibly read in.
  158. #
  159. push @searchpath, $opts{I} if ($opts{I});
  160. foreach my $i (@searchpath) {
  161.     debug("searching $in");
  162.     foreach my $ft (keys(%filetypes)) {
  163.         if ("$i/$ft" eq $persistentFile) {
  164.           debug("skipping persistent file $i/$ftn");
  165.           next;
  166.         }
  167. debug("searching for $i/$ftn");
  168. $knownfiles{"$i/$ft"} = $ft if (-f "$i/$ft");
  169. my $localft = $ft;
  170. $localft =~ s/.conf/.local.conf/;
  171. $knownfiles{"$i/$localft"} = $ft if (-f "$i/$localft");
  172.     }
  173. }
  174. #
  175. # Ask the user if they want them to be read in and read them
  176. #
  177. if (keys(%knownfiles)) {
  178.     my @files;
  179.     if (defined($opts{'r'})) {
  180. if ($opts{'r'} eq "all" || $opts{'r'} eq "a") {
  181.     @files = keys(%knownfiles);
  182. } elsif ($opts{'r'} ne "none" && $opts{'r'} ne "n") {
  183.     print "unknown argument to -r: $opts{'r'}n";
  184.     exit(1);
  185. }
  186.     } elsif(defined($opts{'R'})) {
  187. @files = split(/s*,s*/,$opts{'R'});
  188. foreach my $i (@files) {
  189.     my $x = $i;
  190.     $x =~ s/.*/([^/]+)$/$1/;
  191.     $knownfiles{$i} = $x;
  192. }
  193. Print("reading: ", join(",",@files),"n");
  194.     } else {
  195. @files = display_menu(-head => "The following installed configuration files were found:n",
  196.       -tail => "Would you like me to read them in?  Their content will be merged with thenoutput files created by this session.nnValid answer examples: "all", "none","3","1,2,5"n",
  197.       -multiple => 1,
  198.       -question => 'Read in which',
  199.       -defaultvalue => 'all',
  200.       sort keys(%knownfiles));
  201.     }
  202.     foreach my $i (@files) {
  203. debug("reading $in");
  204. read_config($i, $knownfiles{$i});
  205.     }
  206. }
  207. if ($opts{'g'}) {
  208.     my @groups = split(/,:s/,$opts{'g'});
  209.     foreach my $group (@groups) {
  210. do_group($group);
  211.     }
  212. } elsif ($#ARGV >= 0) {
  213.     #
  214.     # loop through requested files.
  215.     #
  216.     foreach my $i (@ARGV) {
  217. if (!defined($filetypes{$i})) {
  218.     warn "invalid file: $in";
  219. } else {
  220.     if ($opts{'a'}) {
  221. $didfile{$i} = 1;
  222.     } else {
  223. build_file($term, $i, $filetypes{$i});
  224.     }
  225. }
  226.     }
  227. } else {
  228.     #
  229.     # ask user to select file type to operate on.
  230.     #
  231.     while(1) {
  232. 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",
  233. -question => 'Select File',
  234. -otheranswers => ['quit'],
  235. -mapanswers => { 'q' => 'quit' },
  236. keys(%filetypes));
  237. last if ($line eq "quit");
  238. debug("file selected: $linen");
  239. build_file($term, $line, $filetypes{$line});
  240.     }
  241. }
  242. #
  243. # Write out the results to the output files.
  244. #
  245. output_files(%filetypes, $term);
  246. #
  247. # Display the files that have been created for the user.
  248. #
  249. Print("nnThe following files were created:nn");
  250. @didfiles = keys(%didfile);
  251. foreach my $i (@didfiles) {
  252.     if ($didfile{$i} ne "1") {
  253. if ($opts{'i'} || $opts{'I'}) {
  254.           $opts{'I'} = "$confpath" if (!$opts{'I'});
  255.           if (! (-d "$opts{'I'}") && ! (mkdir ("$opts{'I'}", 0755))) {
  256.     print "nCould not create $opts{'I'} directory: $!n";
  257.     print ("File $didfile{$i} left in current directoryn");
  258.   }
  259.   else {
  260.             move ("$opts{'I'}/$i", "$opts{'I'}/$i.bak") if (-f "$opts{'I'}/$i");
  261.             if (move ("$didfile{$i}", "$opts{'I'}")) {
  262.               print("  $didfile{$i} installed in $opts{'I'}n");     
  263.             }
  264.             else {
  265.               print "nCould not move file $didfile{$i} to $opts{'I'}/$i: $!n";
  266.               print ("File $didfile{$i} left in current directoryn");
  267.             }
  268.           }
  269. } elsif ($opts{'p'}) {
  270.   if (! (-d "$home") && ! (mkdir ("$home", 0755))) {
  271.     print "nCould not create $home directory: $!n";
  272.     print ("File $didfile{$i} left in current directoryn");
  273.   }
  274.   else {     
  275.     move ("$home/$i", "$home/$i.bak") if (-f "$home/$i");
  276.     if (move ("$didfile{$i}", "$home")) {
  277.       print("  $didfile{$i} installed in $homen");
  278.     }
  279.     else {
  280.       print "nCould not move file $didfile{$i} to $home: $!n";
  281.       print ("File $didfile{$i} left in current directoryn");
  282.        }
  283.   }
  284.    } else {
  285.     Print("  $didfile{$i} ",
  286.     ($i ne $didfile{$i})?"[ from $i specifications]":" ","n");
  287.     if ($opts{'d'}) {
  288. open(I,$didfile{$i});
  289. debug("    " . join("    ",<I>) . "n");
  290. close(I);
  291.     }
  292. }
  293.     }
  294. }
  295. if (!$opts{'p'} && !$opts{'i'} && !$opts{'I'}) {
  296.     Print("nThese files should be moved to $confpath if you
  297. want them used by everyone on the system.  In the future, if you add 
  298. the -i option to the command line I'll copy them there automatically for you.
  299. Or, if you want them for your personal use only, copy them to
  300. $home .  In the future, if you add the -p option to the
  301. command line I'll copy them there automatically for you.
  302. ");
  303. }
  304. ###########################################################################
  305. # Functions
  306. ###########################################################################
  307. sub Print {
  308.     print @_ if (!$opts{'q'});
  309. }
  310. #
  311. # handle a group of questions
  312. #
  313. sub get_yn_maybe {
  314.     my $question = shift;
  315.     my $ans = "y";
  316.     if ($question ne "") {
  317. $ans = get_answer($term, $question,
  318.   valid_answers(qw(yes y no n)), 'y');
  319.     }
  320.     return ($ans =~ /^y/)?1:0;
  321. }
  322. sub do_group {
  323.     my $group = shift;
  324.     die "no such group $groupn" if (!$groups{$group});
  325.     foreach my $token (@{$groups{$group}}) {
  326. if ($token->[0] eq "message") {
  327.     Print ("$token->[1] $token->[2]n");
  328. } elsif ($token->[0] eq "subgroup") {
  329.     do_group($token->[1]) if (get_yn_maybe($token->[2]));
  330. } elsif (defined($tokenmap{$token->[1]})) {
  331.     if (get_yn_maybe($token->[2])) {
  332. do {
  333.     do_line($token->[1], $tokenmap{$token->[1]});
  334. } until ($token->[0] ne "multiple" ||
  335.  get_answer($term, "Do another $token->[1] line?",
  336.     valid_answers(qw(yes y no n)), 'y')
  337.  =~ /n/);
  338.     }
  339. } elsif (defined($filetypes{$token->[1]})) {
  340.     $didfile{$token->[1]} = 1;
  341. } else {
  342.     die "invalid member $token->[1] of group $groupn";
  343. }
  344.     }
  345. }
  346. #
  347. # build a particular type of file by operating on sections
  348. #
  349. sub build_file {
  350.     my ($term, $filename, $fileconf) = @_;
  351.     $didfile{$filename} = 1;
  352.     my (@lines);
  353.     while(1) {
  354. my $line = display_menu(-head => "The configuration information which can be put into $filename is dividedninto sections.  Select a configuration section for $filenamenthat you wish to create:n",
  355. -otheranswers => ['finished'],
  356. -mapanswers => { 'f' => 'finished' },
  357. -question => "Select section",
  358. -numeric => 1,
  359. map { $_->{'title'}[0] } @$fileconf);
  360. return @lines if ($line eq "finished");
  361. do_section($fileconf->[$line-1]);
  362.     }
  363. }
  364. #
  365. # configure a particular section by operating on token types
  366. #
  367. sub do_section {
  368.     my $confsect = shift;
  369.     my @lines;
  370.     while(1) {
  371. Print ("nSection: $confsect->{'title'}[0]n");
  372. Print ("Description:n");
  373. Print ("  ", join("n  ",@{$confsect->{'description'}}),"n");
  374. my $line =
  375.     display_menu(-head => "Select from:n",
  376.  -otheranswers => ['finished','list'],
  377.  -mapanswers => { 'f' => 'finished',
  378.   'l' => 'list' },
  379.  -question => 'Select section',
  380.  -descriptions => [map { $confsect->{$_}{info}[0] } 
  381.    @{$confsect->{'thetokens'}}],
  382.  @{$confsect->{'thetokens'}});
  383. return @lines if ($line eq "finished");
  384. if ($line eq "list") {
  385.     print "Lines defined for section "$confsect->{title}[0]" so far:n";
  386.     foreach my $i (@{$confsect->{'thetokens'}}) {
  387. if ($#{$confsect->{$i}{'results'}} >= 0) {
  388.     print "  ",join("n  ",@{$confsect->{$i}{'results'}}),"n";
  389. }
  390.     }
  391.     next;
  392. }
  393. do_line($line, $confsect->{$line});
  394.     }
  395.     return;
  396. }
  397. #
  398. # Ask all the questions related to a particular line type
  399. #
  400. sub do_line {
  401.     my $token = shift;
  402.     my $confline = shift;
  403.     my (@answers, $counter, $i);
  404. #    debug(my_Dumper($confline));
  405.     Print ("nConfiguring: $tokenn");
  406.     Print ("Description:n  ",join("n    ",@{$confline->{'info'}}),"nn");
  407.     for($i=0; $i <= $#{$confline->{'question'}}; $i++) {
  408. if (defined($confline->{'question'}[$i]) &&
  409.     $confline->{'question'}[$i] ne "") {
  410.     my $q = $confline->{'question'}[$i];
  411.     $q =~ s/$(d+)/$answers[$1]/g;
  412.     debug("after: $term, $q, ",$confline->{'validanswer'}[$i],"n");
  413.     $answers[$i] = get_answer($term, $q,
  414.       $confline->{'validanswer'}[$i]);
  415.     $answers[$i] =~ s/"/\"/g;
  416.     $answers[$i] = '"' . $answers[$i] . '"' if ($answers[$i] =~ /s/);
  417. }
  418.     }
  419.     if ($#{$confline->{'line'}} == -1) {
  420. my ($i,$line);
  421. for($i=0; $i <= $#{$confline->{'question'}}; $i++) {
  422.     next if (!defined($confline->{'question'}[$i]) ||
  423.      $confline->{'question'}[$i] eq "");
  424.     $line .= " $" . $i;
  425. }
  426. push @{$confline->{'line'}}, $line;
  427.     }
  428.     foreach my $line (@{$confline->{'line'}}) {
  429. my $finished = $line;
  430. debug("preline: $finishedn");
  431. debug("answers: ",my_Dumper(@answers));
  432. $finished =~ s/$(d+)/$answers[$1]/g;
  433. if ($line =~ s/^evals+//) {
  434.     debug("eval: $finishedn");
  435.     $finished = eval $finished;
  436.     debug("eval results: $finishedn");
  437. }
  438. $finished = $token . " " . $finished;
  439. Print ("nFinished Output: $finishedn");
  440. push @{$confline->{'results'}},$finished;
  441.     }
  442. }
  443. #
  444. # read all sets of config files in the various subdirectories.
  445. #
  446. sub read_config_files {
  447.     my $readdir = shift;
  448.     my $filetypes = shift;
  449.     opendir(DH, $readdir) || die "no such directory $readdir, did you run make install?n";
  450.     my $dir;
  451.     my $configfilename="snmpconf-config";
  452.     while(defined($dir = readdir(DH))) {
  453. next if ($dir =~ /^./);
  454. next if ($dir =~ /CVS/);
  455. debug("dir entry: $dirn");
  456. if (-d "$readdir/$dir" && -f "$readdir/$dir/$configfilename") {
  457.     my $conffile;
  458.     # read the top level configuration inforamation about the direcotry.
  459.     open(I, "$readdir/$dir/$configfilename");
  460.     while(<I>) {
  461. $conffile = $1 if (/forconffile: (.*)/);
  462.     }
  463.     close(I);
  464.     # no README informatino.
  465.     if ($conffile eq "") {
  466. print STDERR "Warning: No 'forconffile' information in $readdir/$dir/$configfilenamen";
  467. next;
  468.     }
  469.     # read all the daat in the directory
  470.     $filetypes->{$conffile} = read_config_items("$readdir/$dir", $conffile);
  471. } else {
  472.     # no README informatino.
  473.     print STDERR "Warning: No $configfilename file found in $readdir/$dirn";
  474. }
  475.     }
  476.     closedir DH;
  477. }
  478. #
  479. # read each configuration file in a directory
  480. #
  481. sub read_config_items {
  482.     my $itemdir = shift;
  483.     my $type = shift;
  484.     opendir(ITEMS, $itemdir);
  485.     my $file;
  486.     my @results;
  487.     while(defined($file = readdir(ITEMS))) {
  488. next if ($file =~ /~$/);
  489. next if ($file =~ /^snmpconf-config$/);
  490. if (-f "$itemdir/$file") {
  491.     my $res = read_config_item("$itemdir/$file", $type);
  492.     if (scalar(keys(%$res)) > 0) {
  493. push @results, $res;
  494.     }
  495. }
  496.     }
  497.     closedir(ITEMS);
  498.     return @results;
  499. }
  500. #
  501. # mark a list of tokens as a special "group"
  502. #
  503. sub read_config_group {
  504.     my ($fh, $group, $type) = @_;
  505.     my $line;
  506.     debug("handling group $groupn");
  507.     push (@{$groups{$group}},['filetype', $type]);
  508.     while($line = <$fh>) {
  509. chomp($line);
  510. next if ($line =~ /^s*$/);
  511. next if ($line =~ /^#/);
  512. return $line if ($line !~ /^(single|multiple|message|filetype|subgroup)/);
  513. my ($type, $token, $rest) = ($line =~ /^(w+)s+([^s]+)s*(.*)/);
  514. debug ("reading group $group : $type -> $token -> $restn");
  515. push (@{$groups{$group}}, [$type, $token, $rest]);
  516.     }
  517.     return;
  518. }
  519. #
  520. # Parse one file
  521. #
  522. sub read_config_item {
  523.     my $itemfile = shift;
  524.     my $itemcount;
  525.     my $type = shift;
  526.     my $fh = new IO::File($itemfile);
  527.     return if (!defined($fh));
  528.     my (%results, $curtoken);
  529.     debug("tokenitems:  ", my_Dumper(%tokenitems));
  530.   topwhile:
  531.     while($line = <$fh>) {
  532. next if ($line =~ /^s*#/);
  533. my ($token, $rest) = ($line =~ /^(w+)s+(.*)/);
  534. next if (!defined($token) || !defined($rest));
  535. while ($token eq 'group') {
  536.     # handle special group list
  537.     my $next = read_config_group($fh, $rest,$type);
  538.     if ($next) {
  539. ($token, $rest) = ($next =~ /^(w+)s+(.*)/);
  540.     } else {
  541. next topwhile;
  542.     }
  543. }
  544. debug("token: $token => $restn");
  545. if ($token eq 'steal') {
  546.     foreach my $stealfrom (keys(%{$results{$rest}})) {
  547. if (!defined($results{$curtoken}{$stealfrom})) {
  548.     @{$results{$curtoken}{$stealfrom}} = 
  549. @{$results{$rest}{$stealfrom}};
  550. }
  551.     }
  552. } elsif (defined($tokenitems{$token})) {
  553.     if (!defined($curtoken)) {
  554. die "error in configuration file $itemfile, no token setn";
  555.     }
  556.     $rest =~ s/^#//;
  557.     push @{$results{$curtoken}{$token}},$rest;
  558. } elsif (defined($arrayitems{$token})) {
  559.     if (!defined($curtoken)) {
  560. die "error in configuration file $itemfile, no token setn";
  561.     }
  562.     my ($num, $newrest) = ($rest =~ /^(d+)s+(.*)/);
  563.     if (!defined($num) || !defined($newrest)) {
  564. warn "invalid config line: $linen";
  565.     } else {
  566. $results{$curtoken}{$token}[$num] = $newrest;
  567.     }
  568. } elsif ($token =~ /^tokens*$/) {
  569.     $rest = lc($rest);
  570.     $curtoken = $rest;
  571.     if (! exists $results{$curtoken}{'defined'}) {
  572. push @{$results{'thetokens'}}, $curtoken;
  573. $results{$curtoken}{'defined'} = 1;
  574.     }
  575.     $tokenmap{$curtoken} = $results{$curtoken};
  576.     debug("current token set to $tokenn");
  577. } else {
  578.     push @{$results{$token}},$rest;
  579. }
  580.     }
  581.     return %results;
  582. }
  583. sub debug {
  584.     print @_ if ($opts{'d'});
  585. }
  586. sub output_files {
  587.     my $filetypes = shift;
  588.     my $term = shift;
  589.     foreach my $ft (keys(%$filetypes)) {
  590. next if (!$didfile{$ft});
  591. my $outputf = $ft;
  592. if (-f $outputf && !$opts{'f'}) {
  593.     print "nError: An $outputf file already exists in this directory.nn";
  594.     my $ans = get_answer($term,"'overwrite', 'skip', 'rename' or 'append'? ",valid_answers(qw(o overwrite r rename s skip a append)));
  595.     next if ($ans =~ /^(s|skip)$/i);
  596.     if ($ans =~ /^(a|append)/) {
  597. $outputf = ">$outputf";
  598.     } elsif ($ans =~ /^(r|rename)$/i) {
  599. # default to rename for error conditions
  600. $outputf = $term->readline("Save to what new file name instead (or 'skip')? ");
  601.     }
  602. }
  603. $didfile{$ft} = $outputf;
  604. open(O,">$outputf") || warn "couldn't write to $outputfn";
  605. print O "#" x 75,"n";
  606. print O "#n# $ftn";
  607. print O "#n#   - created by the snmpconf configuration programn#n";
  608. foreach my $sect (@{$filetypes->{$ft}}) {
  609.     my $secthelp = 0;
  610.     foreach my $token (@{$sect->{'thetokens'}}) {
  611. if ($#{$sect->{$token}{'results'}} >= 0) {
  612.     if ($secthelp++ == 0) {
  613. print O "#" x 75,"n# SECTION: ",
  614. join("n#          ", @{$sect->{title}}), "n#n";
  615. print O "#   ", join("n#   ",@{$sect->{description}}),
  616. "n";
  617.     }
  618.     print O "n# $token: ",
  619.     join("n#   ",@{$sect->{$token}{info}}), "nn";
  620.     foreach my $result (@{$sect->{$token}{'results'}}) {
  621. print O "$resultn";
  622.     }
  623. }
  624.     }
  625.     print O "nnn";
  626. }
  627. if ($#{$unknown{$ft}} > -1) {
  628.     print O "#n# Unknown directives read in from other files by snmpconfn#n";
  629.     foreach my $unknown (@{$unknown{$ft}}) {
  630. print O $unknown,"n";
  631.     }
  632. }
  633. close(O);
  634.     }
  635. }
  636. sub get_answer {
  637.     my ($term, $question, $regexp, $defaultval) = @_;
  638.     $question .= " (default = $defaultval)" if (defined($defaultval) && $defaultval ne "");
  639.     $question .= ": ";
  640.     my $ans = $term->readline($question);
  641.     return $defaultval if ($ans eq "" && defined($defaultval) && 
  642.    $defaultval ne "");
  643.     while (!(!defined($regexp) ||
  644.      $regexp eq "" ||
  645.      $ans =~ /$regexp/)) {
  646. print "invalid answer!  It must match this regular expression: $regexpn";
  647. $ans = $term->readline($question);
  648.     }
  649.     return $defaultval if ($ans eq "" && defined($defaultval) && 
  650.    $defaultval ne "");
  651.     return $ans;
  652. }
  653.     
  654. sub valid_answers {
  655.     my @list;
  656.     foreach $i (@_) {
  657. push @list, $i if ($i);
  658.     }
  659.     return "^(" . join("|",@list) . ")$";
  660. }
  661. sub read_config {
  662.     my $file = shift;
  663.     my $filetype = shift;
  664.     return if (!defined($filetypes{$filetype}));
  665.     if (! -f $file) {
  666. warn "$file does not existn";
  667. return;
  668.     }
  669.     open(I,$file);
  670.     while(<I>) {
  671. next if (/^s*#/);
  672. next if (/^s*$/);
  673. chomp;
  674. my ($token, $rest) = /^s*(w+)s+(.*)/;
  675. $token = lc($token);
  676. next if (defined($alllines{$_})); # drop duplicate lines
  677. if (defined($tokenmap{$token})) {
  678.     push @{$tokenmap{$token}{'results'}},$_;
  679. } else {
  680.     push @{$unknown{$filetype}},$_;
  681. }
  682. $alllines{$_}++;
  683.     }
  684.     close(I);
  685. }
  686. sub display_menu {
  687.     my %config;
  688.     while ($#_ > -1 && $_[0] =~ /^-/) {
  689. my $key = shift;
  690. $config{$key} = shift;
  691.     }
  692.     my $count=1;
  693.     print "n" if (!defined($config{'-dense'}));
  694.     if ($config{'-head'}) {
  695. print $config{'-head'};
  696. print "n" if (!defined($config{'-dense'}));
  697.     }
  698.     my @answers = @_;
  699.     my @list;
  700.     if (defined($config{'-descriptions'}) && 
  701. ref($config{'-descriptions'}) eq "ARRAY") {
  702. @list = @{$config{'-descriptions'}}
  703.     } else {
  704. @list = @_;
  705.     }
  706.     foreach my $i (@list) {
  707. printf "  %2d:  $in", $count++ if ($i);
  708.     }
  709.     print "n" if (!defined($config{'-dense'}));
  710.     if (defined($config{'-otheranswers'})) {
  711. if (ref($config{'-otheranswers'}) eq 'ARRAY') {
  712.     print "Other options: ", join(", ",
  713.   @{$config{'-otheranswers'}}), "n";
  714.     push @answers, @{$config{'-otheranswers'}};
  715.     push @answers, keys(%{$config{'-mapanswers'}});
  716. } else {
  717.     my $maxlen = 0;
  718.     push @answers,keys(%{$config{'-otheranswers'}});
  719.     foreach my $i (keys(%{$config{'-otheranswers'}})) {
  720. $maxlen = length($i) if (length($i) > $maxlen);
  721.     }
  722.     foreach my $i (keys(%{$config{'-otheranswers'}})) {
  723. printf("  %-" . $maxlen . "s: %sn", $i, 
  724.        $config{'-otheranswers'}{$i});
  725.     }
  726. }
  727. print "n" if (!defined($config{'-dense'}));
  728.     }
  729.     if ($config{'-tail'}) {
  730. print $config{'-tail'};
  731. print "n" if (!defined($config{'-dense'}));
  732.     }
  733.     if (defined($config{'-question'})) {
  734. while(1) {
  735.     my $numexpr;
  736.     if ($config{'-multiple'}) {
  737. $numexpr = '[ds,]+|all|a|none|n';
  738.     } else {
  739. $numexpr = 'd+';
  740.     }
  741.     push @answers,"" if ($config{'-defaultvalue'});
  742.     $ans = get_answer($term, $config{'-question'},
  743.       valid_answers($numexpr,@answers),
  744.       $config{'-defaultvalue'});
  745.     if ($config{'-mapanswers'}{$ans}) {
  746. $ans = $config{'-mapanswers'}{$ans};
  747.     }
  748.     if ($ans =~ /^$numexpr$/) {
  749. if ($config{'-multiple'}) {
  750.     my @list = split(/s*,s*/,$ans);
  751.     my @ret;
  752.     $count = 0;
  753.     foreach my $i (@_) {
  754. $count++;
  755. if ($ans eq "all" || $ans eq "a" 
  756.     || grep(/^$count$/,@list)) {
  757.     push @ret, $i;
  758. }
  759.     }
  760.     return @ret;
  761. } else {
  762.     if ($ans <= 0 || $ans > $#_+1) {
  763. warn "invalid selection: $ans [must be 1-" .
  764.     ($#_+1) . "]n";
  765.     } else {
  766. return $ans if ($config{'-numeric'});
  767. $count = 0;
  768. foreach my $i (@_) {
  769.     $count++;
  770.     if ($ans eq $count) {
  771. return $i;
  772.     }
  773. }
  774.     }
  775. }
  776.     } else {
  777. return $ans;
  778.     }
  779. }
  780.     }
  781. }
  782. sub my_Dumper {
  783.     if ($opts{'D'}) {
  784. return Dumper(@_);
  785.     } else {
  786. return "n";
  787.     }
  788. }
  789. sub get_persistentDir {
  790.     my $file = shift;
  791.     my $result = 0;
  792.     if (! -f $file) {
  793. return 0;
  794.     }
  795.     open(I,$file);
  796.     while(<I>) {
  797. next if (/^s*#/);
  798. next if (/^s*$/);
  799. chomp;
  800. my ($token, $rest) = /^s*(w+)s+(.*)/;
  801.         if (lc($token) eq "persistentdir") {
  802.           $result = $rest;
  803.         }
  804.         next;
  805.     }
  806.     close(I);
  807.     return $result;
  808. }
  809. # Usage:   &win32_reg_read("key", "value")
  810. # Example: &win32_reg_read("SOFTWARE\Net-SNMP","SNMPSHAREPATH");
  811. # Returns: Value if found in HKCU or HCLM.  Otherwise an empty string.
  812. sub win32_reg_read {
  813.   my $sub_key = shift;
  814.   my $value = shift;
  815.   require Win32::Registry;
  816.    
  817.   my ($hkey, %key_values, $temp, $no_warn);
  818.  
  819.   # Try HKCU first
  820.   $no_warn = $HKEY_CURRENT_USER;
  821.   if ($HKEY_CURRENT_USER->Open($sub_key, $hkey))
  822.   {
  823.     $hkey->GetValues(%key_values);   
  824.     foreach $temp (sort keys %key_values) {
  825.       if ($temp eq $value) {
  826.         return $key_values{$temp}[2];
  827.       }
  828.     }
  829.     $hkey->Close(); 
  830.   }
  831.   # Try HKLM second
  832.   $no_warn = $HKEY_LOCAL_MACHINE;
  833.   if ($HKEY_LOCAL_MACHINE->Open($sub_key, $hkey))
  834.   {
  835.     $hkey->GetValues(%key_values);
  836.     foreach $temp (sort keys %key_values) {
  837.       if ($temp eq $value) {
  838.         return $key_values{$temp}[2];
  839.       }
  840.     }
  841.     $hkey->Close(); 
  842.   }
  843.   return "";
  844. }
  845. # Usage:   &my_getenv("key")
  846. # Example: &my_getenv("SNMPSHAREPATH");
  847. # Returns: Unix:  Environment variable value (undef if not defined)
  848. #          Win32: HKCUSoftwareNet-SNMP(key) or
  849. #          Win32: HKLMSoftwareNet-SNMP(key) or
  850. #          Win32: Environment variable value (undef if not defined)
  851. sub my_getenv {
  852.   my $key = shift;
  853.   
  854.   # Unix
  855.   if ($^O ne 'MSWin32') {
  856.     return $ENV{$key};
  857.   }
  858.   # Windows
  859.   else {
  860.     my $temp = &win32_reg_read("SOFTWARE\Net-SNMP","$key");
  861.     if ($temp ne "") {
  862.       return $temp;
  863.     }
  864.     else {
  865.       return $ENV{$key};
  866.     }
  867.   }
  868. }