X-Git-Url: http://git.refcnt.org/?p=distdns.git;a=blobdiff_plain;f=client.pl;h=2a73f4e6de5f0f9218a98c69758224f40aed0841;hp=9992c9de5d97b96d10048631deb0c3b240eff632;hb=HEAD;hpb=577cd6cddb2b1d6bfa21d682308fde6493d9dab6 diff --git a/client.pl b/client.pl index 9992c9d..2a73f4e 100755 --- a/client.pl +++ b/client.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copyright (c) 2013 Michel Ketterle, Steven Schubiger +# Copyright (c) 2013, 2015 Michel Ketterle, Steven Schubiger # # This file is part of distdns. # @@ -21,18 +21,41 @@ use strict; use warnings; use constant false => 0; -use Config::Tiny; -use Digest::MD5 qw(md5_hex); -use Fcntl ':flock'; -use File::Spec::Functions qw(catfile rel2abs); -use FindBin qw($Bin); -use Getopt::Long qw(:config no_auto_abbrev no_ignore_case); -use JSON qw(decode_json); -use LWP::UserAgent; -use Sys::Hostname qw(hostname); -use Tie::File; +BEGIN +{ + my @modules = ( + [ 'Config::Tiny', [ ] ], + [ 'Digest::MD5', [ qw(md5_hex) ] ], + [ 'Fcntl', [ qw(:flock) ] ], + [ 'File::Spec::Functions', [ qw(catfile rel2abs) ] ], + [ 'FindBin', [ qw($Bin) ] ], + [ 'Getopt::Long', [ qw(:config no_auto_abbrev no_ignore_case) ] ], + [ 'JSON', [ qw(decode_json) ] ], + [ 'LWP::UserAgent', [ ] ], + [ 'POSIX', [ qw(strftime) ] ], + [ 'Sys::Hostname', [ qw(hostname) ] ], + [ 'Tie::File', [ ] ], + ); + my (@missing, @import); + foreach my $module (@modules) { + unless (eval "require $module->[0]; 1") { + push @missing, $module->[0]; + next; + } + unless (eval { $module->[0]->import(@{$module->[1]}); 1 }) { + push @import, $module->[0]; + } + } + if (@missing || @import) { + warn <<"EOT"; +Modules missing: @missing +Import failures: @import +EOT + exit 1; + } +} -my $VERSION = '0.05'; +my $VERSION = '0.07'; my $conf_file = catfile($Bin, 'client.conf'); @@ -40,19 +63,23 @@ sub _die { die "$0: [client] $_[0]" } sub usage { + warn "$_[0]\n" if defined $_[0]; print <<"USAGE"; -Usage: $0 +Usage: $0 [options] -d, --debug server debugging -h, --help this help screen -i, --init initialize session data + -l, --list list remote entries USAGE exit; } my %opts; -GetOptions(\%opts, qw(d|debug h|help i|init)) or usage(); +GetOptions(\%opts, qw(d|debug h|help i|init l|list)) or usage(); usage() if $opts{h}; +usage('Cannot combine --init and --list') if $opts{i} && $opts{l}; + my $config = Config::Tiny->new; $config = Config::Tiny->read($conf_file); @@ -60,13 +87,13 @@ my $get_config_opts = sub { my ($section, $options) = @_; - _die "Section $section missing in $conf_file\n" unless exists $config->{$section}; + _die "Section '$section' missing in $conf_file\n" unless exists $config->{$section}; my %options; @options{@$options} = @{$config->{$section}}{@$options}; foreach my $option (@$options) { - _die "Option $option not set in $conf_file\n" unless defined $options{$option} && length $options{$option}; + _die "Option '$option' not set in $conf_file\n" unless defined $options{$option} && length $options{$option}; } return @options{@$options}; @@ -89,8 +116,7 @@ my $save_session = sub my $get_session = sub { open(my $fh, '<', $session_file) or _die "Cannot open $session_file for reading: $!\nPerhaps try running --init\n"; - my $session = do { local $/; <$fh> }; - chomp $session; + chomp(my $session = <$fh>); close($fh); return $session; @@ -104,6 +130,7 @@ my %params = ( name => $name, debug => $opts{d} || false, init => $opts{i} || false, + list => $opts{l} || false, session => $session, ); @@ -120,36 +147,53 @@ if ($response->is_success) { die "$0: [server] $data->{error}" if defined $data->{error}; - $save_session->($session) if $opts{i}; - - my %list; - foreach my $entry (@{$data->{entries}}) { - my $host = "$entry->{ip}\t" . join '.', @$entry{qw(name pc netz)}; - push @{$list{$entry->{netz}}}, $host; + if ($opts{i}) { + $save_session->($session); } + elsif ($opts{l}) { + format STDOUT_TOP = +IP Name PC Netz Aktualisiert +==================================================================================================== +. + foreach my $entry (sort { $a->{netz} cmp $b->{netz} } @{$data->{entries}}) { + my $updated = strftime '%Y-%m-%d %H:%M:%S', localtime $entry->{time}; + format STDOUT = +@<<<<<<<<<<<<<< @<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<< +@$entry{qw(ip name pc netz)}, $updated +. + write; + } + } + else { + my %list; + foreach my $entry (@{$data->{entries}}) { + my $host = "$entry->{ip}\t" . join '.', @$entry{qw(name pc netz)}; + push @{$list{$entry->{netz}}}, $host; + } - my $o = tie my @hosts, 'Tie::File', $hosts_file or _die "Cannot tie $hosts_file: $!\n"; - $o->flock(LOCK_EX); - - foreach my $network (keys %list) { - my %indexes; - for (my $i = 0; $i < @hosts; $i++) { - if ($hosts[$i] =~ /^\#$network\#$/i) { - $indexes{start} = $i; - } - elsif (exists $indexes{start} && $hosts[$i] =~ /^\#\/$network\#$/i) { - $indexes{end} = $i; - my $count = ($indexes{end} - $indexes{start} > 1) - ? $indexes{end} - $indexes{start} - 1 - : 0; - splice @hosts, $indexes{start} + 1, $count, @{$list{$network}}; - last; + my $o = tie my @hosts, 'Tie::File', $hosts_file or _die "Cannot tie $hosts_file: $!\n"; + $o->flock(LOCK_EX); + + foreach my $network (keys %list) { + my %indexes; + for (my $i = 0; $i < @hosts; $i++) { + if ($hosts[$i] =~ /^\#$network\#$/i) { + $indexes{start} = $i; + } + elsif (exists $indexes{start} && $hosts[$i] =~ /^\#\/$network\#$/i) { + $indexes{end} = $i; + my $count = ($indexes{end} - $indexes{start} > 1) + ? $indexes{end} - $indexes{start} - 1 + : 0; + splice @hosts, $indexes{start} + 1, $count, @{$list{$network}}; + last; + } } } - } - undef $o; - untie @hosts; + undef $o; + untie @hosts; + } } else { warn $response->status_line, "\n";