diff options
Diffstat (limited to 'local/snmpconf')
-rwxr-xr-x | local/snmpconf | 933 |
1 files changed, 933 insertions, 0 deletions
diff --git a/local/snmpconf b/local/snmpconf new file mode 100755 index 0000000..37a5136 --- /dev/null +++ b/local/snmpconf @@ -0,0 +1,933 @@ +#!/usr/bin/perl -w + +# +# 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/local/share/snmp/snmpconf-data"; +} + +# default config file path +if (defined(&my_getenv("SNMPCONFPATH"))) { + $confpath = &my_getenv("SNMPCONFPATH"); +} +else { + $confpath = "/usr/local/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 +# separated by : (Unix) or ; (Win32) +# +my $ENV_SEPARATOR = ':'; +if ($^O eq 'MSWin32') { + $ENV_SEPARATOR = ';'; +} +my @searchpath = split(/$ENV_SEPARATOR/, $confpath); +push @searchpath, "/usr/local/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/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}; + } + } +} + |