Changeset 150
- Timestamp:
- 05/31/04 09:15:50 (4 years ago)
- Files:
-
- manage/trunk/CLI/CLI.pm (modified) (11 diffs)
- manage/trunk/drivers/fw (deleted)
- manage/trunk/manage (modified) (11 diffs)
- manage/trunk/plugins (moved) (moved from manage/trunk/drivers)
- manage/trunk/plugins/fw.pm (added)
- manage/trunk/plugins/log.pm (added)
- manage/trunk/plugins/nat.pm (added)
- manage/trunk/README (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
manage/trunk/CLI/CLI.pm
r149 r150 4 4 use warnings; 5 5 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); 6 use base qw(Exporter); 6 7 7 8 use Getopt::Mixed; 8 9 use IO::Handle; 9 10 use Net::DNS; 10 use Text:: Wrap;11 use Text::Format; 11 12 use Term::ReadKey; 12 13 use POSIX qw(ctermid floor); 13 14 require Exporter;15 16 @ISA = qw(Exporter);17 14 18 15 $VERSION = 0.1; … … 22 19 # new CLI( 23 20 # grammar => $GRAMMAR, 21 # stringpattern => '\'(?:\\.|[^\'])*\'|"(?:\\.|[^"])*"', 22 # delimiter => '\s+|($stringpattern)', 24 23 # ) 25 24 sub new(%) { … … 30 29 die("Grammar not defined") unless defined($args{grammar}); 31 30 $self->{grammar} = $args{grammar}; 31 # String pattern 32 32 if (defined($args{stringpattern})) { 33 33 $self->{stringpattern} = $args{stringpattern}; … … 35 35 $self->{stringpattern} = '\'(?:\\.|[^\'])*\'|"(?:\\.|[^"])*"'; 36 36 } 37 # Delimiter 37 38 if (defined($args{delimiter})) { 38 $self->{tokenpattern} = $args{ tokenpattern}39 $self->{tokenpattern} = $args{delimiter}; 39 40 } else { 40 41 $self->{tokenpattern} = "\\s+|($self->{stringpattern})"; 41 42 } 43 44 # Merge plugins 45 if (defined($args{plugins})) { 46 my ($width, $height) = GetTerminalSize(*STDIN); 47 my $format = new Text::Format( 48 columns => $width, 49 firstIndent => 0, 50 leftMargin => 4, 51 ); 52 53 if (opendir(D, $args{plugins})) { 54 while (my $file = readdir(D)) { 55 if ($file =~ /^[^.].*\.pm$/) { 56 $file =~ s/\.pm$//; 57 if (my $plugin = do("$args{plugins}/$file.pm")) { 58 $self->{plugins}->{$file} = $plugin; 59 $self->merge($plugin); 60 } else { 61 $| = 1; 62 print("\e[1m\e[31mCLI plugin '$file' error:\e[22m\n" . $format->format($@) . "\e[0m"); 63 $| = 0; 64 } 65 } 66 } 67 } 68 #$self->merge($args{plugins}); 69 } 70 return $self; 71 } 72 73 # Merge a grammar 74 sub merge($) { 75 my $self = shift; 76 my $grammar = shift; 77 78 sub recursive_merge($$); 79 sub recursive_merge($$) { 80 my ($merge, $grammar) = @_; 81 82 for my $key (keys(%$merge)) { 83 if (defined($grammar->{$key})) { 84 recursive_merge($merge->{$key}, $grammar->{$key}); 85 } else { 86 $grammar->{$key} = $merge->{$key}; 87 } 88 } 89 } 90 91 recursive_merge($grammar, $self->{grammar}); 42 92 return $self; 43 93 } … … 60 110 my $help = ""; 61 111 my %commands = (); 112 my $format = new Text::Format( 113 columns => $width, 114 firstIndent => 0, 115 ); 62 116 63 117 # Trailing tokens after help … … 65 119 66 120 # Construct help string 67 $Text::Wrap::columns = $width; 68 $help .= wrap("", "", $cmd{HELPHEADER}) . "\n" if $cmd{HELPHEADER}; 121 $help .= $format->format($cmd{HELPHEADER}) . "\n" if $cmd{HELPHEADER}; 69 122 70 123 for my $key (keys %cmd) { … … 73 126 if (ref($cmd{$key}) eq 'HASH' and $cmd{$key}->{HELP}) { 74 127 my ($name, $hstr); 128 my $type = ref($cmd{$key}->{HELP}); 75 129 76 if (ref($cmd{$key}->{HELP}) eq 'ARRAY') { 77 ($name, $hstr) = @{$cmd{$key}->{HELP}}; 78 } else { 79 $name = $key; 80 $hstr = $cmd{$key}->{HELP}; 81 } 82 83 $commands{$name} = $hstr; 130 if ($type eq 'CODE') { 131 %commands = (%commands, $cmd{$key}->{HELP}->()); 132 } else { 133 if ($type eq 'ARRAY') { 134 ($name, $hstr) = @{$cmd{$key}->{HELP}}; 135 } else { 136 $name = $key; 137 $hstr = $cmd{$key}->{HELP}; 138 } 139 $commands{$name} = $hstr; 140 } 84 141 } else { 85 142 $commands{$key} = ''; … … 92 149 if ($cmd{ACTION}) { 93 150 if (ref($cmd{ACTION}) eq 'HASH' and $cmd{ACTION}->{HELP}) { 94 $commands{'<eol>'} = $cmd{ACTION}->{HELP}; 151 if (ref($cmd{ACTION}->{HELP}) eq 'ARRAY') { 152 $commands{'<eol>'} = $cmd{ACTION}->{HELP}->[1]; 153 } elsif (ref($cmd{ACTION}->{HELP}) eq 'SCALAR') { 154 $commands{'<eol>'} = $cmd{ACTION}->{HELP}; 155 } else { 156 $commands{'<eol>'} = "\e[31m\e[1m(expected SCALAR or ARRAY help, not CODE)\e[0m"; 157 } 95 158 } elsif ($cmd{ACTIONHELP}) { 96 159 $commands{'<eol>'} = $cmd{ACTIONHELP}; 97 160 } elsif ($cmd{HELP}) { 98 $commands{'<eol>'} = $cmd{HELP}; 161 if (ref($cmd{HELP}) eq 'ARRAY') { 162 $commands{'<eol>'} = $cmd{HELP}->[1]; 163 } elsif (ref($cmd{HELP}) eq 'SCALAR') { 164 $commands{'<eol>'} = $cmd{HELP}; 165 } else { 166 $commands{'<eol>'} = "\e[31m\e[1m(expected SCALAR or ARRAY help, not CODE)\e[0m"; 167 } 99 168 } else { 100 169 $commands{'<eol>'} = "\e[31m\e[1m(need ACTIONHELP, ACTION->HELP or HELP entry)\e[0m"; … … 102 171 } 103 172 173 my $keywidth = 0; 174 for my $name (sort keys %commands) { 175 $keywidth = length($name) if length($name) > $keywidth; 176 } 177 $format->leftMargin($keywidth + 2); 104 178 for my $name (sort keys %commands) { 105 179 if ($commands{$name}) { 106 $help .= wrap(sprintf(" \e[1m%-19s\e[0m ", $name), (" " x 19), $commands{$name}) . "\n";180 $help .= sprintf(" \e[1m%-${keywidth}s\e[0m ", $name) . substr($format->format($commands{$name}), $keywidth + 2); 107 181 } else { 108 182 $help .= sprintf(" \e[1m%-16s\e[0m\n", $name); … … 111 185 112 186 $help .= "\n" if $cmd{HELPFOOTER} or $cmd{HELPHEADER}; 113 $help .= "\n" . $cmd{HELPFOOTER}if $cmd{HELPFOOTER};187 $help .= $cmd{HELPFOOTER} . "\n" if $cmd{HELPFOOTER}; 114 188 return ('ERROR', 'No help available.') unless defined($help) and $help ne ''; 115 189 return ('HELP', $help); … … 212 286 } 213 287 214 END {215 }216 217 288 1; manage/trunk/manage
r149 r150 2 2 3 3 # Add cli-parser to our module include path 4 BEGIN { push(@INC, " /root/projects/CLI"); }4 BEGIN { push(@INC, "./CLI"); } 5 5 6 6 use warnings; … … 21 21 my $BANNER = ''; 22 22 my $SQLSERVER = '127.0.0.1'; 23 my $ DRIVERS = './drivers';23 my $PLUGINS = './plugins'; 24 24 25 25 my %CONF = ( 26 'prompt' => [ \$PROMPT, '.*', 'CLI prompt.' ], 27 'banner' => [ \$BANNER, '.*', 'Startup banner.' ], 28 'sqlserver' => [ \$SQLSERVER, '.*', 'SQL server where logs are stored.' ], 29 'driverbase' => [ \$DRIVERS, '.*', 'Driver base directory.' ], 26 'prompt' => { 27 value => \$PROMPT, 28 pattern => '.*', 29 help => 'CLI prompt.' 30 }, 31 'banner' => { 32 value => \$BANNER, 33 pattern => '.*', 34 help => 'Startup banner.' 35 }, 36 'sqlserver' => { 37 value => \$SQLSERVER, 38 pattern => '.*', 39 help => 'SQL server where logs are stored.' 40 }, 41 'plugins' => { 42 value => \$PLUGINS, 43 pattern => '.*', 44 help => 'Driver base directory.' 45 }, 46 30 47 ); 31 48 my $BREAK = 0; … … 140 157 entered exactly as shown. Words enclosed in \e[1m< >\e[22m are user defined. 141 158 ", 142 'log' => {143 HELPHEADER => "Use the \e[1mlog\e[22m command to view, query and filter system logs.\n",144 HELP => 'Manipulate logs.',145 'tail' => {146 HELP => 'Tail the system logs.',147 ACTION => sub {148 }149 },150 ACTION => sub { print("Dumping all logs.\n"); },151 ACTIONHELP => 'Dump todays logs.',152 },153 159 # 'fw' => { 154 160 # HELP => 'Firewall management.', … … 168 174 169 175 if ($CONF{$key}) { 170 if ($value =~ /$CONF{$key} [1]/) {171 ${$CONF{$key} [0]} = $value;176 if ($value =~ /$CONF{$key}->{pattern}/) { 177 ${$CONF{$key}->{value}} = $value; 172 178 } else { 173 179 error("Value for '$key' is invalid."); … … 177 183 } 178 184 }, 179 HELP => [ '<value>', 'Setting value.' ], 180 }, 181 HELP => [ '<key>', 'Setting to query/modify.' ], 185 HELP => [ '<value>', 'Set value.' ], 186 }, 187 HELP => sub { 188 my %help; 189 190 for my $key (keys(%CONF)) { 191 $help{$key} = $CONF{$key}->{help}; 192 } 193 return %help; 194 }, 182 195 ACTION => { 183 196 ACTION => sub { … … 185 198 186 199 if ($CONF{$key}) { 187 print("\e[1m\e[32m$key='\e[22m${$CONF{$key} [0]}\e[1m'\e[0m\n");200 print("\e[1m\e[32m$key='\e[22m${$CONF{$key}->{value}}\e[1m'\e[0m\n"); 188 201 } else { 189 202 error("No such setting '$key'."); … … 201 214 202 215 for my $key (sort keys %CONF) { 203 push(@rows, [$ALTCOLOURS[++$row % 2], $key, ${$CONF{$key} [0]}, $CONF{$key}[2]]);216 push(@rows, [$ALTCOLOURS[++$row % 2], $key, ${$CONF{$key}->{value}}, $CONF{$key}->{help}]); 204 217 } 205 218 format_columns( … … 218 231 $term->ornaments(0); 219 232 my $termattribs = $term->Attribs; 220 my $cli = new CLI(grammar => $GRAMMAR); 233 my $CLI = new CLI( 234 grammar => $GRAMMAR, 235 plugins => ${$CONF{plugins}->{value}}, 236 ); 221 237 222 238 # Turn off filename completion … … 224 240 # Map the ? key to auto-magic help 225 241 $term->add_defun('dns-help', sub { 226 my ($type, $action, $args) = $ cli->parse($termattribs->{line_buffer} . ' ?');242 my ($type, $action, $args) = $CLI->parse($termattribs->{line_buffer} . ' ?'); 227 243 if ($type eq 'HELP') { 228 244 print("\n$action"); … … 231 247 }, ord('?')); 232 248 233 sub load_drivers($;$) {234 my $drivers = shift;235 my $base = shift;236 237 $base = $GRAMMAR unless defined($base);238 239 if (!opendir(D, $drivers)) {240 error("Could not load drivers from '$drivers'");241 return undef;242 }243 while (my $cmd = readdir(D)) {244 next if $cmd =~ /^\./;245 print("$cmd\n");246 }247 close(D);248 }249 250 249 sub exec_line { 251 my ($type, $action, $args) = $ cli->parse("@_");250 my ($type, $action, $args) = $CLI->parse("@_"); 252 251 253 252 if ($type eq 'HELP') { … … 260 259 } 261 260 262 load_drivers($DRIVERS);263 264 261 # Command line? 265 262 if (@ARGV) {
