diff options
author | LEVAI Daniel <leva@ecentrum.hu> | 2013-06-05 19:45:09 -0400 |
---|---|---|
committer | dsomero <xgizzmo@slackbuilds.org> | 2013-06-05 19:45:09 -0400 |
commit | ad59450bd6f03ee48bf6eff514f9640fecd992f5 (patch) | |
tree | 1cfd826b0a54ac98219e6392611b978278198131 | |
parent | eb3cbd0717c55e501c4db21005480f0694fa376b (diff) | |
download | slackbuilds-ad59450bd6f03ee48bf6eff514f9640fecd992f5.tar.gz |
network/ClusterSSH: Updated for version 4.02_01.
Signed-off-by: dsomero <xgizzmo@slackbuilds.org>
-rw-r--r-- | network/ClusterSSH/ClusterSSH.SlackBuild | 19 | ||||
-rw-r--r-- | network/ClusterSSH/ClusterSSH.info | 6 | ||||
-rw-r--r-- | network/ClusterSSH/patches/00-4.01_05.diff | 1641 |
3 files changed, 9 insertions, 1657 deletions
diff --git a/network/ClusterSSH/ClusterSSH.SlackBuild b/network/ClusterSSH/ClusterSSH.SlackBuild index 056e4872a6..82a33b8222 100644 --- a/network/ClusterSSH/ClusterSSH.SlackBuild +++ b/network/ClusterSSH/ClusterSSH.SlackBuild @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2011, 2012, 2013 LEVAI Daniel +# Copyright (c) 2011-2013 LEVAI Daniel # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -24,13 +24,10 @@ PRGNAM=ClusterSSH -VERSION=${VERSION:-4.01_05} -BUILD=${BUILD:-2} +VERSION=${VERSION:-4.02_01} +BUILD=${BUILD:-1} TAG=${TAG:-_SBo} -SRCNAM="App-${PRGNAM}" -SRCVER="4.01_01" - if [ -z "$ARCH" ]; then case "$( uname -m )" in i?86) ARCH=i486 ;; @@ -63,9 +60,9 @@ set -e rm -rf $PKG mkdir -p $TMP $PKG $OUTPUT cd $TMP -rm -rf $SRCNAM-$SRCVER -tar xvf $CWD/$SRCNAM-$SRCVER.tar.gz -cd $SRCNAM-$SRCVER +rm -rf App-$PRGNAM-$VERSION +tar xvf $CWD/App-$PRGNAM-$VERSION.tar.gz +cd App-$PRGNAM-$VERSION chown -R root:root . find . \ \( -perm 777 -o -perm 775 -o -perm 711 -o -perm 555 -o -perm 511 \) \ @@ -73,10 +70,6 @@ find . \ \( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \ -exec chmod 644 {} \; -for diff in $CWD/patches/*.diff; do - patch -E --quiet -p1 < "${diff}" -done - perl Build.PL \ prefix=/usr \ installdirs=vendor \ diff --git a/network/ClusterSSH/ClusterSSH.info b/network/ClusterSSH/ClusterSSH.info index ce529b64f9..e09f56d3e6 100644 --- a/network/ClusterSSH/ClusterSSH.info +++ b/network/ClusterSSH/ClusterSSH.info @@ -1,8 +1,8 @@ PRGNAM="ClusterSSH" -VERSION="4.01_05" +VERSION="4.02_01" HOMEPAGE="http://clusterssh.sourceforge.net" -DOWNLOAD="http://downloads.sourceforge.net/clusterssh/App-ClusterSSH-4.01_01.tar.gz" -MD5SUM="2adcd457d0647409c8948df68d26b155" +DOWNLOAD="http://downloads.sourceforge.net/clusterssh/App-ClusterSSH-4.02_01.tar.gz" +MD5SUM="f8646f0cf644ea1fd114643f1cf60c8b" DOWNLOAD_x86_64="" MD5SUM_x86_64="" REQUIRES="perl-Try-Tiny perl-x11-protocol perl-File-Which perl-Test-Pod perl-Test-Pod-Coverage \ diff --git a/network/ClusterSSH/patches/00-4.01_05.diff b/network/ClusterSSH/patches/00-4.01_05.diff deleted file mode 100644 index d7b05cf631..0000000000 --- a/network/ClusterSSH/patches/00-4.01_05.diff +++ /dev/null @@ -1,1641 +0,0 @@ -diff --git a/Build.PL b/Build.PL -index be3afb3..467c201 100644 ---- a/Build.PL -+++ b/Build.PL -@@ -6,7 +6,7 @@ use Module::Build; - my $build = Module::Build->new( - meta_merge => { - resources => { -- repository => [ -+ Repository => [ - 'http://clusterssh.git.sourceforge.net/', - 'http://github.com/duncs/clusterssh', - ], -@@ -34,6 +34,10 @@ my $build = Module::Build->new( - 'File::Which' => 0, - 'File::Temp' => 0, - 'Test::DistManifest' => 0, -+ 'Test::Differences' => 0, -+ }, -+ configure_requires => { -+ 'Module::Build' => 0, - }, - add_to_cleanup => ['App-ClusterSSH-*'], - create_makefile_pl => 'traditional', -diff --git a/Changes b/Changes -index c1fe7e9..485932d 100644 ---- a/Changes -+++ b/Changes -@@ -1,3 +1,34 @@ -+2013-03-05 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.01_05 -+- New option (-m, --unique-servers) to remove repeated servers when openeing terminals (Thanks to Oliver Meissner) -+- Drop MYMETA.yml and .json files from the distribution -+- Do not set default user name to prevent overriding ssh configuration -+ -+2013-02-26 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.01_04 -+- Fixed 'ccon' not calling the correct command (Sf bug 3605002) -+- Fixed clusters not being defined correctly within the .clusterssh/config file (Sf bug 3605675) -+ -+2013-02-15 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.01_03 -+* Correct documentation for references to $HOME/.clusterssh/config -+* Re-add user back into the configurartion file -+* Add in missing newline for some error messages -+* Allow the path to rsh/ssh/telnet to be defined in the configuration file -+* Move .csshrc to .csshrc.DISABLED since it should no longer be used -+* Error emitted when adding a host via the "Hosts" drop-down (Debian bug ID #578208) -+* Pastes uses a strange keyboard layout (Debian bug ID #364565) -+* Cope with being invoked by 'clusterssh' (Debian bug ID #644368) -+* Fix migration of .csshrc when not working as expected (Debian bug ID #673507) -+* Remove doc references to 'always_tile' as renamed 'window_tiling' (Debian bug ID #697371) -+* Updated manpage whatis entries (patch by Tony Mancill) -+* Fix watch line expression to catch 4.x series tarballs (Debian patch LP ID #1076897) -+* Allow tests to pass successfully when run as root -+* Fix cssh starting if xterm is not installed (Sf bug 3494988) -+* Set WM_CLASS on windows to 'cssh' (Sf bug 3187736) -+ -+2012-12-09 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.01_02 -+* Fix logic when using 'autoclose' on the command line or config file -+* Fix $HOME/.clusterssh/clusters being read in -+* Fix 'ctel', 'crsh' and 'ccon'so they work as expected -+ - 2011-12-09 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.01_01 - * Include missing files from release tarballs - -diff --git a/MANIFEST b/MANIFEST -index cebe4b1..a4b4983 100644 ---- a/MANIFEST -+++ b/MANIFEST -@@ -14,13 +14,11 @@ lib/App/ClusterSSH/Helper.pm - lib/App/ClusterSSH/Host.pm - lib/App/ClusterSSH/L10N.pm - lib/App/ClusterSSH/L10N/en.pm --Makefile --Makefile.old - Makefile.PL - MANIFEST - MANIFEST.SKIP -+META.json - META.yml --MYMETA.json - README - t/00-load.t - t/01l10n.t -diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP -index 3753e38..4900842 100644 ---- a/MANIFEST.SKIP -+++ b/MANIFEST.SKIP -@@ -4,7 +4,11 @@ - ^Build$ - ^.git/ - ^.gitignore -+^Makefile$ -+^Makefile.old$ - ^MANIFEST\.bak$ --^MYMETA.yml$ -+MYMETA.json -+MYMETA.yml -+pm_to_blib - .*\.swp$ - ^WIP_TASKS$ -diff --git a/META.json b/META.json -new file mode 100644 -index 0000000..26b6d74 ---- /dev/null -+++ b/META.json -@@ -0,0 +1,94 @@ -+{ -+ "abstract" : "A container for functions of the ClusterSSH programs", -+ "author" : [ -+ "Duncan Ferguson <duncan_j_ferguson@yahoo.co.uk>" -+ ], -+ "dynamic_config" : 1, -+ "generated_by" : "Module::Build version 0.4003, CPAN::Meta::Converter version 2.112621", -+ "license" : [ -+ "perl_5" -+ ], -+ "meta-spec" : { -+ "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", -+ "version" : "2" -+ }, -+ "name" : "App-ClusterSSH", -+ "prereqs" : { -+ "build" : { -+ "requires" : { -+ "File::Temp" : 0, -+ "File::Which" : 0, -+ "Readonly" : 0, -+ "Test::Differences" : 0, -+ "Test::DistManifest" : 0, -+ "Test::Pod" : 0, -+ "Test::Pod::Coverage" : 0, -+ "Test::Trap" : 0 -+ } -+ }, -+ "configure" : { -+ "requires" : { -+ "Module::Build" : 0 -+ } -+ }, -+ "runtime" : { -+ "requires" : { -+ "Exception::Class" : "1.31", -+ "Locale::Maketext" : 0, -+ "Tk" : "800.022", -+ "Try::Tiny" : 0, -+ "X11::Protocol" : "0.56", -+ "version" : 0 -+ } -+ } -+ }, -+ "provides" : { -+ "App::ClusterSSH" : { -+ "file" : "lib/App/ClusterSSH.pm", -+ "version" : "4.01_05" -+ }, -+ "App::ClusterSSH::Base" : { -+ "file" : "lib/App/ClusterSSH/Base.pm", -+ "version" : "0.02" -+ }, -+ "App::ClusterSSH::Cluster" : { -+ "file" : "lib/App/ClusterSSH/Cluster.pm", -+ "version" : "0.01" -+ }, -+ "App::ClusterSSH::Config" : { -+ "file" : "lib/App/ClusterSSH/Config.pm", -+ "version" : "0.02" -+ }, -+ "App::ClusterSSH::Helper" : { -+ "file" : "lib/App/ClusterSSH/Helper.pm", -+ "version" : "0.02" -+ }, -+ "App::ClusterSSH::Host" : { -+ "file" : "lib/App/ClusterSSH/Host.pm", -+ "version" : "0.03" -+ }, -+ "App::ClusterSSH::L10N" : { -+ "file" : "lib/App/ClusterSSH/L10N.pm", -+ "version" : 0 -+ }, -+ "App::ClusterSSH::L10N::en" : { -+ "file" : "lib/App/ClusterSSH/L10N/en.pm", -+ "version" : 0 -+ } -+ }, -+ "release_status" : "testing", -+ "resources" : { -+ "bugtracker" : { -+ "web" : "http://sourceforge.net/tracker/?group_id=89139" -+ }, -+ "homepage" : "http://clusterssh.sourceforge.net/", -+ "license" : [ -+ "http://dev.perl.org/licenses/" -+ ], -+ "x_Repository" : [ -+ "http://clusterssh.git.sourceforge.net/", -+ "http://github.com/duncs/clusterssh" -+ ] -+ }, -+ "version" : "4.01_05" -+} -diff --git a/META.yml b/META.yml -index bdf1020..7e93bb8 100644 ---- a/META.yml -+++ b/META.yml -@@ -6,13 +6,15 @@ build_requires: - File::Temp: 0 - File::Which: 0 - Readonly: 0 -+ Test::Differences: 0 - Test::DistManifest: 0 - Test::Pod: 0 - Test::Pod::Coverage: 0 - Test::Trap: 0 - configure_requires: -- Module::Build: 0.36 --generated_by: 'Module::Build version 0.3603' -+ Module::Build: 0 -+dynamic_config: 1 -+generated_by: 'Module::Build version 0.4003, CPAN::Meta::Converter version 2.112621' - license: perl - meta-spec: - url: http://module-build.sourceforge.net/META-spec-v1.4.html -@@ -21,7 +23,7 @@ name: App-ClusterSSH - provides: - App::ClusterSSH: - file: lib/App/ClusterSSH.pm -- version: 4.01_01 -+ version: 4.01_05 - App::ClusterSSH::Base: - file: lib/App/ClusterSSH/Base.pm - version: 0.02 -@@ -30,17 +32,19 @@ provides: - version: 0.01 - App::ClusterSSH::Config: - file: lib/App/ClusterSSH/Config.pm -- version: 0.01 -+ version: 0.02 - App::ClusterSSH::Helper: - file: lib/App/ClusterSSH/Helper.pm -- version: 0.01 -+ version: 0.02 - App::ClusterSSH::Host: - file: lib/App/ClusterSSH/Host.pm - version: 0.03 - App::ClusterSSH::L10N: - file: lib/App/ClusterSSH/L10N.pm -+ version: 0 - App::ClusterSSH::L10N::en: - file: lib/App/ClusterSSH/L10N/en.pm -+ version: 0 - requires: - Exception::Class: 1.31 - Locale::Maketext: 0 -@@ -52,7 +56,7 @@ resources: - bugtracker: http://sourceforge.net/tracker/?group_id=89139 - homepage: http://clusterssh.sourceforge.net/ - license: http://dev.perl.org/licenses/ -- repository: -+ x_Repository: - - http://clusterssh.git.sourceforge.net/ - - http://github.com/duncs/clusterssh --version: 4.01_01 -+version: 4.01_05 -diff --git a/Makefile.PL b/Makefile.PL -index 4e126ef..059ea01 100644 ---- a/Makefile.PL -+++ b/Makefile.PL -@@ -1,32 +1,33 @@ --# Note: this file was auto-generated by Module::Build::Compat version 0.3603 -+# Note: this file was auto-generated by Module::Build::Compat version 0.4003 - use ExtUtils::MakeMaker; - WriteMakefile - ( -- 'NAME' => 'App::ClusterSSH', -- 'VERSION_FROM' => 'lib/App/ClusterSSH.pm', -- 'PREREQ_PM' => { -- 'Exception::Class' => '1.31', -- 'File::Temp' => 0, -- 'File::Which' => 0, -- 'Locale::Maketext' => 0, -- 'Readonly' => 0, -- 'Test::DistManifest' => 0, -- 'Test::Pod' => 0, -- 'Test::Pod::Coverage' => 0, -- 'Test::Trap' => 0, -- 'Tk' => '800.022', -- 'Try::Tiny' => 0, -- 'X11::Protocol' => '0.56', -- 'version' => '0' -- }, -- 'INSTALLDIRS' => 'site', -- 'EXE_FILES' => [ -- 'bin/ccon', -- 'bin/crsh', -- 'bin/cscp', -- 'bin/cssh', -- 'bin/ctel' -- ], -- 'PL_FILES' => {} -- ) -+ 'NAME' => 'App::ClusterSSH', -+ 'VERSION_FROM' => 'lib/App/ClusterSSH.pm', -+ 'PREREQ_PM' => { -+ 'Exception::Class' => '1.31', -+ 'File::Temp' => 0, -+ 'File::Which' => 0, -+ 'Locale::Maketext' => 0, -+ 'Readonly' => 0, -+ 'Test::Differences' => 0, -+ 'Test::DistManifest' => 0, -+ 'Test::Pod' => 0, -+ 'Test::Pod::Coverage' => 0, -+ 'Test::Trap' => 0, -+ 'Tk' => '800.022', -+ 'Try::Tiny' => 0, -+ 'X11::Protocol' => '0.56', -+ 'version' => '0' -+ }, -+ 'INSTALLDIRS' => 'site', -+ 'EXE_FILES' => [ -+ 'bin/ccon', -+ 'bin/crsh', -+ 'bin/cscp', -+ 'bin/cssh', -+ 'bin/ctel' -+ ], -+ 'PL_FILES' => {} -+) - ; -diff --git a/THANKS b/THANKS -index 3af7cd0..bc2b3f7 100644 ---- a/THANKS -+++ b/THANKS -@@ -40,3 +40,4 @@ Simon Fraser - Stefan Steiner - Ryan Brown - Brandon Perkins -+Oliver Meissner -diff --git a/bin/cssh b/bin/cssh -index 3a11dc1..6b95202 100755 ---- a/bin/cssh -+++ b/bin/cssh -@@ -66,12 +66,12 @@ that host. Re-selecting it will plug it back in. - =item * - - If your window manager menu bars are obscured by terminal windows see --the C<screen_reserve_XXXXX> options in the F<csshrc> file (see L</"FILES">). -+the C<screen_reserve_XXXXX> options in the F<$HOME/.clusterssh/config> file (see L</"FILES">). - - =item * - - If the terminals overlap too much see the C<terminal_reserve_XXXXX> --options in the F<csshrc> file (see L</"FILES">). -+options in the F<$HOME/.clusterssh/config> file (see L</"FILES">). - - =item * - -@@ -115,7 +115,7 @@ be due to either the C<-xrm> terminal option which enables C<AllowSendEvents> - (some terminal do not require this option, other terminals have another - method for enabling it - see your terminal documention) or the - C<ConnectTimeout> ssh option (see the configuration option C<-o> or file --C<csshrc> below to resolve this). -+C<$HOME/.clusterssh/config> below to resolve this). - - =back - -@@ -201,7 +201,7 @@ F<$HOME/.ssh/config>). - =item --output-config,-u - - Output the current configuration in the same format used by the --F<$HOME/.csshrc> file. -+F<$HOME/.clusterssh/config> file. - - =item --port,-p <port> - -@@ -224,6 +224,10 @@ Enable|Disable window tiling (overriding the config file) - - Specify the initial part of the title used in the console and client windows - -+=item --unique-servers,-m -+ -+Connect to each host only once -+ - =item --use_all_a_records,-A - - If a hostname resolves to multiple IP addresses, toggle whether or not to -@@ -255,7 +259,7 @@ on standard port (e.g not listening on port 22) and ssh_config cannot be used. - =item <tag> ... - - Open a series of xterms defined by <tag> within either /etc/clusters or --F<$HOME/.csshrc> (see L</"FILES">). -+F<$HOME/.clusterssh/config> (see L</"FILES">). - - Note: specifying a username on a cluster tag will override any usernames - defined in the cluster -@@ -354,13 +358,13 @@ nested, but be aware of recursive tags which are not checked for. - - Clusters may also be specified either directly (see C<clusters> configuration - options) or indirectly (see C<extra_cluster_file> configuration option) --in the users F<$HOME/.csshrc> file. -+in the users F<$HOME/.clusterssh/config> file. - - NOTE: there is a special cluster tag called C<default> - any tags or hosts - included within this tag will be automatically opened if no other tags - are specified on the command line. - --=item F</etc/csshrc> & F<$HOME/.csshrc> -+=item F</etc/csshrc> & F<$HOME/.clusterssh/config> - - This file contains configuration overrides - the defaults are as marked. - Default options are overwritten first by the global file, and then by the -@@ -377,10 +381,6 @@ should be written as - - =over - --=item always_tile = yes -- --Setting to anything other than C<yes> does not perform window tiling (see also -G). -- - =item auto_close = 5 - - Close terminal window after this many seconds. If set to 0 will instead wait -@@ -472,10 +472,21 @@ program start - Default key sequence to paste text into the console window using the mouse. - See below notes on shortcuts. - -+=item rsh = rsh -+ -+=item ssh = ssh -+ -+=item telnet = telnet -+ -+Set the path to the specific binary to use for the communication method, else -+uses the first match found in $PATH -+ - =item rsh_args = <blank> - - =item ssh_args = "-x -o ConnectTimeout=10" - -+=item telnet_args = <blank> -+ - Sets any arguments to be used with the communication method (defaults to ssh - arguments). - -@@ -725,7 +736,7 @@ If you have issues running cssh, first try: - C<< cssh -e [user@]<hostname>[:port] >> - - This performs two tests to confirm cssh is able to work properly with the --settings provided within the F<.csshrc> file (or internal defaults). -+settings provided within the F<$HOME/.clusterssh/config> file (or internal defaults). - - 1. test the terminal window works with the options provided - -@@ -734,7 +745,7 @@ settings provided within the F<.csshrc> file (or internal defaults). - Configuration options to watch for in ssh are - - - Doesnt understand "-o ConnectTimeout=10" - remove the option -- in the F<.csshrc> file -+ in the F<$HOME/.clusterssh/config> file - - - OpenSSH-3.8 using untrusted ssh tunnels - use "-Y" instead of "-X" - or use "ForwardX11Trusted yes' in ssh_config (if you change the -@@ -751,7 +762,7 @@ C<< perl -MTk -e 'print $Tk::VERSION,$/' >> - - C<< perl -MX11::Protocol -e 'print $X11::Protocol::VERSION,$/' >> - --C<< cat /etc/csshrc $HOME/.csshrc >> -+C<< cat /etc/csshrc $HOME/.clusterssh/config >> - - =item * - -diff --git a/lib/App/ClusterSSH.pm b/lib/App/ClusterSSH.pm -index 793de94..ec568fc 100644 ---- a/lib/App/ClusterSSH.pm -+++ b/lib/App/ClusterSSH.pm -@@ -3,7 +3,7 @@ package App::ClusterSSH; - use 5.008.004; - use warnings; - use strict; --use version; our $VERSION = version->new('4.01_01'); -+use version; our $VERSION = version->new('4.01_05'); - - use Carp; - -@@ -116,12 +116,13 @@ my @options_spec = ( - 'font|f=s', - 'list|L', - 'use_all_a_records|A', -+ 'unique-servers|m', - ); - my %options; --my %windows; # hash for all window definitions --my %menus; # hash for all menu definitions --my @servers; # array of servers provided on cmdline --my %servers; # hash of server cx info -+my %windows; # hash for all window definitions -+my %menus; # hash for all menu definitions -+my @servers; # array of servers provided on cmdline -+my %servers; # hash of server cx info - my $xdisplay; - my %keyboardmap; - my $sysconfigdir = "/etc"; -@@ -277,53 +278,68 @@ sub load_keyboard_map() { - - logmsg( 1, "Loading keymaps and keycodes" ); - -- foreach ( 0 .. $#keyboard ) { -- if ( defined $keyboard[$_][3] ) { -- if ( defined( $keycodetosym{ $keyboard[$_][3] } ) ) { -- $keyboardmap{ $keycodetosym{ $keyboard[$_][3] } } -- = 'sa' . ( $_ + $min ); -- } -- else { -- logmsg( 2, "Unknown keycode ", $keyboard[$_][3] ) -- if ( $keyboard[$_][3] != 0 ); -- } -- } -- if ( defined $keyboard[$_][2] ) { -- if ( defined( $keycodetosym{ $keyboard[$_][2] } ) ) { -- $keyboardmap{ $keycodetosym{ $keyboard[$_][2] } } -- = 'a' . ( $_ + $min ); -- } -- else { -- logmsg( 2, "Unknown keycode ", $keyboard[$_][2] ) -- if ( $keyboard[$_][2] != 0 ); -- } -- } -- if ( defined $keyboard[$_][1] ) { -- if ( defined( $keycodetosym{ $keyboard[$_][1] } ) ) { -- $keyboardmap{ $keycodetosym{ $keyboard[$_][1] } } -- = 's' . ( $_ + $min ); -- } -- else { -- logmsg( 2, "Unknown keycode ", $keyboard[$_][1] ) -- if ( $keyboard[$_][1] != 0 ); -- } -- } -- if ( defined $keyboard[$_][0] ) { -- if ( defined( $keycodetosym{ $keyboard[$_][0] } ) ) { -- $keyboardmap{ $keycodetosym{ $keyboard[$_][0] } } -- = 'n' . ( $_ + $min ); -+ my %keyboard_modifier_priority = ( -+ 'sa' => 3, # lowest -+ 'a' => 2, -+ 's' => 1, -+ 'n' => 0, # highest -+ ); -+ -+ my %keyboard_stringlike_modifiers = reverse %keyboard_modifier_priority; -+ -+ # try to associate $keyboard=X11->GetKeyboardMapping table with X11::Keysyms -+ foreach my $i ( 0 .. $#keyboard ) { -+ for my $modifier ( 0 .. 3 ) { -+ if ( defined( $keycodetosym{ $keyboard[$i][$modifier] } ) ) { -+ -+ # keyboard layout contains the keycode at $modifier level -+ if (defined( -+ $keyboardmap{ $keycodetosym{ $keyboard[$i][$modifier] -+ } } -+ ) -+ ) -+ { -+ -+# we already have a mapping, let's see whether current one is better (lower shift state) -+ my ( $mod_code, $key_code ) -+ = $keyboardmap{ $keycodetosym{ $keyboard[$i] -+ [$modifier] } } =~ /^(\D+)(\d+)$/; -+ -+ # it is not easy to get around our own alien logic storing modifiers ;-) -+ if ( $modifier < $keyboard_modifier_priority{$mod_code} ) -+ { -+ -+ # YES! current keycode have priority over old one (phew!) -+ $keyboardmap{ $keycodetosym{ $keyboard[$i][$modifier] -+ } } -+ = $keyboard_stringlike_modifiers{$modifier} -+ . ( $i + $min ); -+ } -+ } -+ else { -+ -+ # we don't yet have a mapping... piece of cake! -+ $keyboardmap{ $keycodetosym{ $keyboard[$i][$modifier] } } -+ = $keyboard_stringlike_modifiers{$modifier} -+ . ( $i + $min ); -+ } - } - else { -- logmsg( 2, "Unknown keycode ", $keyboard[$_][0] ) -- if ( $keyboard[$_][0] != 0 ); -+ -+ # we didn't get the code from X11::Keysyms -+ if ( $keyboard[$i][$modifier] != 0 ) { -+ -+ # ignore code=0 -+ logmsg( 2, "Unknown keycode ", $keyboard[$i][$modifier] ); -+ } - } - } -- -- # dont know these two key combs yet... -- #$keyboardmap{ $keycodetosym { $keyboard[$_][4] } } = $_ + $min; -- #$keyboardmap{ $keycodetosym { $keyboard[$_][5] } } = $_ + $min; - } - -+ # dont know these two key combs yet... -+ #$keyboardmap{ $keycodetosym { $keyboard[$_][4] } } = $_ + $min; -+ #$keyboardmap{ $keycodetosym { $keyboard[$_][5] } } = $_ + $min; -+ - #print "$_ => $keyboardmap{$_}\n" foreach(sort(keys(%keyboardmap))); - #print "keysymtocode: $keysymtocode{o}\n"; - #die; -@@ -383,8 +399,9 @@ sub resolve_names(@) { - if ( defined($hostobj) ) { - my @alladdrs = map { inet_ntoa($_) } @{ $hostobj->addr_list }; - if ( $#alladdrs > 0 ) { -- $self->cluster->register_tag($dirty, @alladdrs); -- logmsg( 3, 'Expanded to ', $self->cluster->get_tag($dirty) ); -+ $self->cluster->register_tag( $dirty, @alladdrs ); -+ logmsg( 3, 'Expanded to ', -+ $self->cluster->get_tag($dirty) ); - } - else { - logmsg( 3, 'Only one A record' ); -@@ -407,11 +424,22 @@ sub resolve_names(@) { - # now clean the array up - @servers = grep { $_ !~ m/^$/ } @servers; - -+ if ($self->config->{unique_servers}) { -+ logmsg( 3, 'removing duplicate server names' ); -+ @servers=remove_repeated_servers(@servers); -+ } -+ - logmsg( 3, 'leaving with ', $_ ) foreach (@servers); - logmsg( 2, 'Resolving cluster names: completed' ); - return (@servers); - } - -+sub remove_repeated_servers { -+ my %all=(); -+ @all{@_}=1; -+ return (keys %all); -+} -+ - sub change_main_window_title() { - my ($self) = @_; - my $number = keys(%servers); -@@ -588,7 +616,7 @@ sub open_client_windows(@) { - my $server_object = App::ClusterSSH::Host->parse_host_string($_); - - my $username = $server_object->get_username(); -- $username = $self->config->{user} if ( $self->config->{user} ); -+ $username = $self->config->{user} if ( !$username && $self->config->{user} ); - my $port = $server_object->get_port(); - $port = $self->config->{port} if ( $self->config->{port} ); - my $server = $server_object->get_hostname(); -@@ -751,7 +779,7 @@ sub get_font_size() { - - eval { (%font_info) = $xdisplay->QueryFont($font); } - || die( "Fatal: Unrecognised font used ($terminal_font).\n" -- . "Please amend \$HOME/.csshrc with a valid font (see man page).\n" -+ . "Please amend \$HOME/.clusterssh/config with a valid font (see man page).\n" - ); - - $self->config->{internal_font_width} -@@ -763,7 +791,7 @@ sub get_font_size() { - || !$self->config->{internal_font_height} ) - { - die( "Fatal: Unrecognised font used ($terminal_font).\n" -- . "Please amend \$HOME/.csshrc with a valid font (see man page).\n" -+ . "Please amend \$HOME/.clusterssh/config with a valid font (see man page).\n" - ); - } - -@@ -1134,7 +1162,7 @@ sub add_host_by_name() { - $self->open_client_windows(@names); - } - -- if ( $menus{listbox}->curselection() ) { -+ if ( defined $menus{listbox} && $menus{listbox}->curselection() ) { - my @hosts = $menus{listbox}->get( $menus{listbox}->curselection() ); - logmsg( 2, "host=", join( ' ', @hosts ) ); - $self->open_client_windows( $self->resolve_names(@hosts) ); -@@ -1265,7 +1293,8 @@ sub setup_repeat() { - sub create_windows() { - my ($self) = @_; - logmsg( 2, "create_windows: started" ); -- $windows{main_window} = MainWindow->new( -title => "ClusterSSH" ); -+ $windows{main_window} -+ = MainWindow->new( -title => "ClusterSSH", -class => 'cssh', ); - $windows{main_window}->withdraw; # leave withdrawn until needed - - if ( defined( $self->config->{console_position} ) -@@ -1279,6 +1308,7 @@ sub create_windows() { - -textvariable => \$menus{entrytext}, - -insertborderwidth => 4, - -width => 25, -+ -class => 'cssh', - )->pack( - -fill => "x", - -expand => 1, -@@ -1291,6 +1321,7 @@ sub create_windows() { - -height => $self->config->{history_height}, - -state => 'normal', - -takefocus => 0, -+ -class => 'cssh', - ); - $windows{history}->bindtags(undef); - -@@ -1353,6 +1384,7 @@ sub create_windows() { - -popover => $windows{main_window}, - -overanchor => "c", - -popanchor => "c", -+ -class => 'cssh', - -font => [ - -family => "interface system", - -size => 10, -@@ -1367,6 +1399,7 @@ sub create_windows() { - -overanchor => "c", - -title => "Cssh Documentation", - -buttons => ['Close'], -+ -class => 'cssh', - ); - - my $manpage = `pod2text -l -q=\"\" $0 2>/dev/null`; -@@ -1385,17 +1418,19 @@ sub create_windows() { - -title => "Add Host(s) or Cluster(s)", - -buttons => [ 'Add', 'Cancel' ], - -default_button => 'Add', -+ -class => 'cssh', - ); - - if ( $self->config->{max_addhost_menu_cluster_items} -- && scalar $self->cluster->list_tags() ) -+ && scalar $self->cluster->list_tags() ) - { -- if (scalar -- scalar $self->cluster->list_tags() < $self->config->{max_addhost_menu_cluster_items} ) -+ if (scalar scalar $self->cluster->list_tags() -+ < $self->config->{max_addhost_menu_cluster_items} ) - { - $menus{listbox} = $windows{addhost}->Listbox( - -selectmode => 'extended', - -height => scalar $self->cluster->list_tags(), -+ -class => 'cssh', - )->pack(); - } - else { -@@ -1404,6 +1439,7 @@ sub create_windows() { - -scrollbars => 'e', - -selectmode => 'extended', - -height => $self->config->{max_addhost_menu_cluster_items}, -+ -class => 'cssh', - )->pack(); - } - $menus{listbox}->insert( 'end', sort $self->cluster->list_tags() ); -@@ -1415,6 +1451,7 @@ sub create_windows() { - -width => 20, - -label => 'Host', - -labelPack => [ -side => 'left', ], -+ -class => 'cssh', - )->pack( -side => 'left' ); - logmsg( 2, "create_windows: completed" ); - -@@ -1543,7 +1580,7 @@ sub key_event { - - logmsg( 3, "key=:$key:" ); - if ( $combo =~ /^$key$/ ) { -- logmsg(3, "matched combo"); -+ logmsg( 3, "matched combo" ); - if ( $event eq "KeyRelease" ) { - logmsg( 2, "Received hotkey: $hotkey" ); - send_text_to_all_servers('%s') -@@ -1600,8 +1637,8 @@ sub key_event { - sub create_menubar() { - my ($self) = @_; - logmsg( 2, "create_menubar: started" ); -- $menus{bar} = $windows{main_window}->Menu; -- $windows{main_window}->configure( -menu => $menus{bar} ); -+ $menus{bar} = $windows{main_window}->Menu(); -+ $windows{main_window}->configure( -menu => $menus{bar}, ); - - $menus{file} = $menus{bar}->cascade( - -label => 'File', -@@ -1626,22 +1663,22 @@ sub create_menubar() { - -menuitems => [ - [ "command", - "Retile Windows", -- -command => sub{ $self->retile_hosts }, -+ -command => sub { $self->retile_hosts }, - -accelerator => $self->config->{key_retilehosts}, - ], - - # [ "command", "Capture Terminal", -command => \&capture_terminal, ], - [ "command", - "Toggle active state", -- -command => sub{ $self->toggle_active_state() }, -+ -command => sub { $self->toggle_active_state() }, - ], - [ "command", - "Close inactive sessions", -- -command => sub{ $self->close_inactive_sessions() }, -+ -command => sub { $self->close_inactive_sessions() }, - ], - [ "command", - "Add Host(s) or Cluster(s)", -- -command => sub{ $self->add_host_by_name, }, -+ -command => sub { $self->add_host_by_name, }, - -accelerator => $self->config->{key_addhost}, - ], - '', -@@ -1667,7 +1704,8 @@ sub create_menubar() { - ); - - $windows{main_window}->bind( '<KeyPress>' => [ $self => 'key_event' ], ); -- $windows{main_window}->bind( '<KeyRelease>' => [ $self => 'key_event' ], ); -+ $windows{main_window} -+ ->bind( '<KeyRelease>' => [ $self => 'key_event' ], ); - logmsg( 2, "create_menubar: completed" ); - } - -@@ -1797,12 +1835,15 @@ sub run { - } - - if ( $options{action} ) { -- $self->config->{command} = $options{action} ; -+ $self->config->{command} = $options{action}; - } - -+ $self->config->{unique_servers} = 1 if $options{'unique-servers'}; -+ - $self->config->{auto_quit} = "yes" if $options{autoquit}; - $self->config->{auto_quit} = "no" if $options{'no-autoquit'}; -- $self->config->{auto_close} = $options{autoclose} if $options{'autoclose'}; -+ $self->config->{auto_close} = $options{autoclose} -+ if defined $options{'autoclose'}; - - $self->config->{window_tiling} = "yes" if $options{tile}; - $self->config->{window_tiling} = "no" if $options{'no-tile'}; -@@ -1815,7 +1856,7 @@ sub run { - - $self->config->{terminal_font} = $options{font} if ( $options{font} ); - $self->config->{terminal_args} = $options{'term-args'} -- if ( $options{'term-args'} ); -+ if ( $options{'term-args'} ); - if ( $self->config->{terminal_args} =~ /-class (\w+)/ ) { - $self->config->{terminal_allow_send_events} - = "-xrm '$1.VT100.allowSendEvents:true'"; -@@ -1998,6 +2039,8 @@ the code until this time. - - =item populate_send_menu_entries_from_xml - -+=item remove_repeated_servers -+ - =item resolve_names - - =item retile_hosts -diff --git a/lib/App/ClusterSSH/Base.pm b/lib/App/ClusterSSH/Base.pm -index 95a92ed..e99cca4 100644 ---- a/lib/App/ClusterSSH/Base.pm -+++ b/lib/App/ClusterSSH/Base.pm -@@ -157,7 +157,7 @@ sub set_config { - - =head1 NAME - --App::ClusterSSH::Base -+App::ClusterSSH::Base - Base object provding utility functions - - =head1 SYNOPSIS - -diff --git a/lib/App/ClusterSSH/Cluster.pm b/lib/App/ClusterSSH/Cluster.pm -index aabbbe8..3724b31 100644 ---- a/lib/App/ClusterSSH/Cluster.pm -+++ b/lib/App/ClusterSSH/Cluster.pm -@@ -26,7 +26,7 @@ sub new { - sub get_clusters { - my ( $self, @files ) = @_; - -- for my $file ( '/etc/clusters', @files ) { -+ for my $file ( '/etc/clusters', $ENV{HOME}.'/.clusterssh/clusters',@files ) { - $self->debug(3, 'Loading in config from: ', $file); - $self->read_cluster_file($file); - } -@@ -118,7 +118,7 @@ sub list_tags { - - =head1 NAME - --App::ClusterSSH::Cluster -+App::ClusterSSH::Cluster - Object representing cluster configuration - - =head1 SYNOPSIS - -diff --git a/lib/App/ClusterSSH/Config.pm b/lib/App/ClusterSSH/Config.pm -index dbe7c42..0c2fef0 100644 ---- a/lib/App/ClusterSSH/Config.pm -+++ b/lib/App/ClusterSSH/Config.pm -@@ -4,20 +4,25 @@ use strict; - use warnings; - - use version; --our $VERSION = version->new('0.01'); -+our $VERSION = version->new('0.02'); - - use Carp; - use Try::Tiny; - - use FindBin qw($Script); -+use File::Copy; - - use base qw/ App::ClusterSSH::Base /; - use App::ClusterSSH::Cluster; - - my $clusters; - my %old_clusters; --my @app_specific = (qw/ command title comms method ssh rsh telnet ccon /); --my %default_config = ( -+my @app_specific = (qw/ command title comms method /); -+ -+# list of config items to not write out when writing the default config -+my @ignore_default_config = (qw/ user /); -+ -+my %default_config = ( - terminal => "xterm", - terminal_args => "", - terminal_title_opt => "-T", -@@ -54,9 +59,14 @@ my %default_config = ( - terminal_decoration_height => 10, - terminal_decoration_width => 8, - -- rsh_args => "", -- telnet_args => "", -- ssh_args => "", -+ console => 'console', -+ console_args => '', -+ rsh => 'rsh', -+ rsh_args => "", -+ telnet => 'telnet', -+ telnet_args => "", -+ ssh => 'ssh', -+ ssh_args => "", - - extra_cluster_file => "", - -@@ -76,6 +86,9 @@ my %default_config = ( - use_all_a_records => 0, - - send_menu_xml_file => $ENV{HOME} . '/.csshrc_send_menu', -+ -+ # don't set username here as takes precendence over ssh config -+ user => '', - ); - - sub new { -@@ -84,21 +97,19 @@ sub new { - my $self = $class->SUPER::new(%default_config); - - ( my $comms = $Script ) =~ s/^c//; -- $self->{comms} = $comms; -+ -+ $comms = 'telnet' if ( $comms eq 'tel' ); -+ $comms = 'console' if ( $comms eq 'con' ); -+ $comms = 'ssh' if ( $comms eq 'lusterssh' ); - - # list of allowed comms methods -- if ( 'ssh rsh telnet console' !~ m/\B$comms\B/ ) { -+ if ( 'ssh rsh telnet console' !~ m/\b$comms\b/ ) { - $self->{comms} = 'ssh'; - } -- -- if ( $self->{comms} -- && ( !$self->{ $self->{comms} } || !-e $self->{ $self->{comms} } ) ) -- { -- $self->{ $self->{comms} } = $self->find_binary( $self->{comms} ); -+ else { -+ $self->{comms} = $comms; - } - -- $self->{terminal} = $self->find_binary( $self->{terminal} ); -- - $self->{title} = uc($Script); - - $clusters = App::ClusterSSH::Cluster->new(); -@@ -131,13 +142,39 @@ sub validate_args { - App::ClusterSSH::Exception::Config->throw( - unknown_config => \@unknown_config, - error => $self->loc( -- 'Unknown configuration parameters: [_1]', -+ 'Unknown configuration parameters: [_1]' . $/, - join( ',', @unknown_config ) - ) - ) - ); - } - -+ if ( !$self->{comms} ) { -+ croak( -+ App::ClusterSSH::Exception::Config->throw( -+ error => $self->loc( 'Invalid variable: comms' . $/ ), -+ ), -+ ); -+ } -+ -+ if ( !$self->{ $self->{comms} } ) { -+ croak( -+ App::ClusterSSH::Exception::Config->throw( -+ error => $self->loc( -+ 'Invalid variable: [_1]' . $/, -+ $self->{comms} -+ ), -+ ), -+ ); -+ } -+ -+ # # Don't search for the path to the binary - assume it is on the path -+ # # or defined correctly in the config. -+ # if( !-e $self->{ $self->{comms} } ) -+ # { -+ # $self->{ $self->{comms} } = $self->find_binary( $self->{comms} ); -+ # } -+ - return $self; - } - -@@ -150,7 +187,8 @@ sub parse_config_file { - croak( - App::ClusterSSH::Exception::Config->throw( - error => $self->loc( -- 'File [_1] does not exist or cannot be read', $config_file -+ 'File [_1] does not exist or cannot be read' . $/, -+ $config_file - ), - ), - ); -@@ -182,12 +220,13 @@ sub parse_config_file { - } - close(CFG); - -- # grab any c'lusters from the config before validating it -+ # grab any clusters from the config before validating it - if ( $read_config{clusters} ) { - $self->debug( 3, "Picked up clusters defined in $config_file" ); - foreach my $cluster ( sort split / /, $read_config{clusters} ) { - if ( $read_config{$cluster} ) { -- $clusters->register_tag( $cluster, $read_config{$cluster} ); -+ $clusters->register_tag( $cluster, -+ split( / /, $read_config{$cluster} ) ); - $old_clusters{$cluster} = $read_config{$cluster}; - delete( $read_config{$cluster} ); - } -@@ -205,16 +244,6 @@ sub parse_config_file { - sub load_configs { - my ( $self, @configs ) = @_; - -- if ( -e $ENV{HOME} . '/.csshrc' ) { -- warn( -- $self->loc( -- 'NOTICE: [_1] is no longer used - please see documentation and remove', -- $ENV{HOME} . '/.csshrc' -- ), -- $/ -- ); -- } -- - for my $config ( - '/etc/csshrc', - $ENV{HOME} . '/.csshrc', -@@ -248,6 +277,30 @@ sub load_configs { - sub write_user_config_file { - my ($self) = @_; - -+ # attempt to move the old config file to one side -+ if ( -f "$ENV{HOME}/.csshrc" ) { -+ eval { move( "$ENV{HOME}/.csshrc", "$ENV{HOME}/.csshrc.DISABLED" ) }; -+ -+ if ($@) { -+ croak( -+ App::ClusterSSH::Exception::Config->throw( -+ error => $self->loc( -+ 'Unable to move [_1] to [_2]: [_3]' . $/, -+ '$HOME/.csshrc', '$HOME/.csshrc.DISABLED', $@ -+ ), -+ ) -+ ); -+ } -+ else { -+ warn( -+ $self->loc( -+ 'Moved [_1] to [_2]' . $/, '$HOME/.csshrc', -+ '$HOME/.csshrc.DISABLED' -+ ), -+ ); -+ } -+ } -+ - return if ( -f "$ENV{HOME}/.clusterssh/config" ); - - if ( !-d "$ENV{HOME}/.clusterssh" ) { -@@ -255,7 +308,7 @@ sub write_user_config_file { - croak( - App::ClusterSSH::Exception::Config->throw( - error => $self->loc( -- 'Unable to create directory [_1]: [_2]', -+ 'Unable to create directory [_1]: [_2]' . $/, - '$HOME/.clusterssh', $! - ), - ), -@@ -264,34 +317,58 @@ sub write_user_config_file { - } - } - -+ # Debian #673507 - migrate clusters prior to writing ~/.clusterssh/config -+ # in order to update the extra_cluster_file property -+ if (%old_clusters) { -+ if ( open( my $fh, ">", "$ENV{HOME}/.clusterssh/clusters" ) ) { -+ print $fh '# ' -+ . $self->loc('Tag definitions moved from old .csshrc file'), -+ $/; -+ foreach ( sort( keys(%old_clusters) ) ) { -+ print $fh $_, ' ', join( ' ', $old_clusters{$_} ), $/; -+ } -+ close($fh); -+ } -+ else { -+ croak( -+ App::ClusterSSH::Exception::Config->throw( -+ error => $self->loc( -+ 'Unable to write [_1]: [_2]' . $/, -+ '$HOME/.clusterssh/clusters', -+ $! -+ ), -+ ), -+ ); -+ } -+ } -+ - if ( open( CONFIG, ">", "$ENV{HOME}/.clusterssh/config" ) ) { - foreach ( sort( keys(%$self) ) ) { -- print CONFIG "$_=$self->{$_}\n"; -+ my $comment=''; -+ if ( grep /$_/, @ignore_default_config ) { -+ $comment='#'; -+ } -+ print CONFIG ${comment},$_,'=',$self->{$_},$/; - } - close(CONFIG); -+ warn( -+ $self->loc( -+ 'Created new configuration file within [_1]' . $/, -+ '$HOME/.clusterssh/' -+ ) -+ ); - } - else { - croak( - App::ClusterSSH::Exception::Config->throw( - error => $self->loc( -- 'Unable to write default [_1]: [_2]', -- '$HOME/.clusterssh/config', -- $! -+ 'Unable to write default [_1]: [_2]' . $/, -+ '$HOME/.clusterssh/config', $! - ), - ), - ); - } - -- return $self if ( !%old_clusters ); -- -- if ( open( my $fh, ">", "$ENV{HOME}/.clusterssh/clusters" ) ) { -- print $fh '# ' -- . $self->loc('Tag definitions moved from old .csshrc file'), $/; -- foreach ( sort( keys(%old_clusters) ) ) { -- print $fh $_, ' ', join( ' ', $old_clusters{$_} ), $/; -- } -- close($fh); -- } - return $self; - } - -@@ -303,7 +380,7 @@ sub find_binary { - if ( !$binary ) { - croak( - App::ClusterSSH::Exception::Config->throw( -- error => $self->loc('argument not provided'), -+ error => $self->loc('argument not provided') . $/, - ), - ); - } -@@ -355,7 +432,8 @@ sub find_binary { - croak( - App::ClusterSSH::Exception::Config->throw( - error => $self->loc( -- '"[_1]" binary not found - please amend $PATH or the cssh config file', -+ '"[_1]" binary not found - please amend $PATH or the cssh config file' -+ . $/, - $binary - ), - ), -@@ -373,10 +451,14 @@ sub dump { - print( '# Configuration dump produced by "cssh -u"', $/ ); - - foreach my $key ( sort keys %$self ) { -+ my $comment=''; - if ( grep /$key/, @app_specific ) { - next; - } -- print $key, '=', $self->{$key}, $/; -+ if ( grep /$key/, @ignore_default_config ) { -+ $comment='#'; -+ } -+ print $comment, $key, '=', $self->{$key}, $/; - } - - $self->exit if ( !$no_exit ); -@@ -396,7 +478,7 @@ sub dump { - - =head1 NAME - --ClusterSSH::Config -+ClusterSSH::Config - Object representing application configuration - - =head1 SYNOPSIS - -diff --git a/lib/App/ClusterSSH/Helper.pm b/lib/App/ClusterSSH/Helper.pm -index 07c5898..4289e77 100644 ---- a/lib/App/ClusterSSH/Helper.pm -+++ b/lib/App/ClusterSSH/Helper.pm -@@ -4,7 +4,7 @@ use strict; - use warnings; - - use version; --our $VERSION = version->new('0.01'); -+our $VERSION = version->new('0.02'); - - use Carp; - use Try::Tiny; -@@ -22,12 +22,12 @@ sub new { - sub script { - my ($self, $config ) = @_; - -- my $comms = $config->{comms}; -- my $comms_args = $config->{$comms.'_args'}; -- my $command = $config->{command}; -+ my $comms = $config->{ $config->{comms} }; -+ my $comms_args = $config->{ $config->{comms} . '_args'}; -+ my $config_command = $config->{command}; - my $autoclose = $config->{auto_close}; - -- my $postcommand = $autoclose ? "echo Press RETURN to continue; read IGNORE" : "sleep $autoclose"; -+ my $postcommand = $autoclose ? "echo Sleeping for $autoclose seconds; sleep $autoclose" : "echo Press RETURN to continue; read IGNORE"; # : "sleep $autoclose"; - - # # P = pipe file - # # s = server -@@ -119,7 +119,10 @@ sub script { - \$command .= "\$svr"; - } - } -- \$command .= " \\\"$command\\\" ; $postcommand"; -+ if("$config_command") { -+ \$command .= " \\\"$config_command\\\""; -+ } -+ \$command .= " ; $postcommand"; - warn("Running:\$command\\n"); # for debug purposes - exec(\$command); - HERE -@@ -145,7 +148,7 @@ sub script { - - =head1 NAME - --ClusterSSH::Helper -+ClusterSSH::Helper - Object representing helper script - - =head1 SYNOPSIS - -diff --git a/lib/App/ClusterSSH/Host.pm b/lib/App/ClusterSSH/Host.pm -index c9c00be..7d352e5 100644 ---- a/lib/App/ClusterSSH/Host.pm -+++ b/lib/App/ClusterSSH/Host.pm -@@ -301,7 +301,7 @@ use overload ( - - =head1 NAME - --ClusterSSH::Host -+ClusterSSH::Host - Object representing a host. - - =head1 SYNOPSIS - -diff --git a/t/15config.t b/t/15config.t -index 81d8f70..cce91a6 100644 ---- a/t/15config.t -+++ b/t/15config.t -@@ -8,6 +8,7 @@ use Test::More; - use Test::Trap; - use File::Which qw(which); - use File::Temp qw(tempdir); -+use Test::Differences; - - use Readonly; - -@@ -21,7 +22,7 @@ $config = App::ClusterSSH::Config->new(); - isa_ok( $config, 'App::ClusterSSH::Config' ); - - Readonly::Hash my %default_config => { -- terminal => "/usr/bin/xterm", -+ terminal => "xterm", - terminal_args => "", - terminal_title_opt => "-T", - terminal_colorize => 1, -@@ -59,9 +60,14 @@ Readonly::Hash my %default_config => { - - ssh => '/usr/bin/ssh', - -- rsh_args => "", -- telnet_args => "", -- ssh_args => "", -+ console => 'console', -+ console_args => '', -+ rsh => 'rsh', -+ rsh_args => "", -+ telnet => 'telnet', -+ telnet_args => "", -+ ssh => 'ssh', -+ ssh_args => "", - - extra_cluster_file => "", - -@@ -72,8 +78,8 @@ Readonly::Hash my %default_config => { - history_height => 10, - - command => q{}, -- title => q{15CONFIG.T}, -- comms => q{ssh}, -+ title => q{15CONFIG.T}, -+ comms => q{ssh}, - max_host_menu_items => 30, - - max_addhost_menu_cluster_items => 6, -@@ -88,6 +94,7 @@ Readonly::Hash my %default_config => { - debug => 0, - lang => 'en', - -+ user => '', - }; - my %expected = %default_config; - is_deeply( $config, \%expected, 'default config is correct' ); -@@ -101,7 +108,7 @@ trap { - }; - isa_ok( $trap->die, 'App::ClusterSSH::Exception::Config' ); - is( $trap->die, -- 'Unknown configuration parameters: doesnt_exist,whoops', -+ 'Unknown configuration parameters: doesnt_exist,whoops' . $/, - 'got correct error message' - ); - is_deeply( -@@ -134,7 +141,7 @@ trap { - }; - isa_ok( $trap->die, 'App::ClusterSSH::Exception::Config' ); - is( $trap->die, -- "File $file does not exist or cannot be read", -+ "File $file does not exist or cannot be read" . $/, - 'got correct error message' - ); - -@@ -166,7 +173,7 @@ trap { - is( $trap->leaveby, 'die', 'died ok' ); - isa_ok( $trap->die, 'App::ClusterSSH::Exception::Config' ); - is( $trap->die, -- 'Unknown configuration parameters: missing,rubbish', -+ 'Unknown configuration parameters: missing,rubbish' . $/, - 'die message correct' - ); - isa_ok( $config, "App::ClusterSSH::Config" ); -@@ -197,7 +204,7 @@ trap { - is( $trap->leaveby, 'die', 'died ok' ); - isa_ok( $trap->die, 'App::ClusterSSH::Exception::Config' ); - isa_ok( $config, "App::ClusterSSH::Config" ); --is( $trap->die, 'argument not provided', 'die message correct' ); -+is( $trap->die, 'argument not provided' . $/, 'die message correct' ); - isa_ok( $config, "App::ClusterSSH::Config" ); - is( $trap->stdout, q{}, 'Expecting no STDOUT' ); - is( $trap->stderr, q{}, 'Expecting no STDERR' ); -@@ -210,7 +217,8 @@ is( $trap->leaveby, 'die', 'died ok' ); - isa_ok( $trap->die, 'App::ClusterSSH::Exception::Config' ); - isa_ok( $config, "App::ClusterSSH::Config" ); - is( $trap->die, -- '"missing" binary not found - please amend $PATH or the cssh config file', -+ '"missing" binary not found - please amend $PATH or the cssh config file' -+ . $/, - 'die message correct' - ); - isa_ok( $config, "App::ClusterSSH::Config" ); -@@ -241,11 +249,11 @@ is( $trap->stdout, q{}, 'Expecting no STDOUT' ); - is( $trap->stderr, q{}, 'Expecting no STDERR' ); - is_deeply( $config, \%expected, 'amended config is correct' ); - is( $path, which('ls'), 'Found correct path to "ls"' ); --is( $path, $newpath, 'No change made from find_binary'); -+is( $path, $newpath, 'No change made from find_binary' ); - - # give false path to force another search - trap { -- $newpath = $config->find_binary('/does/not/exist/'.$path); -+ $newpath = $config->find_binary( '/does/not/exist/' . $path ); - }; - is( $trap->leaveby, 'return', 'returned ok' ); - isa_ok( $config, "App::ClusterSSH::Config" ); -@@ -254,7 +262,7 @@ is( $trap->stdout, q{}, 'Expecting no STDOUT' ); - is( $trap->stderr, q{}, 'Expecting no STDERR' ); - is_deeply( $config, \%expected, 'amended config is correct' ); - is( $path, which('ls'), 'Found correct path to "ls"' ); --is( $path, $newpath, 'No change made from find_binary'); -+is( $path, $newpath, 'No change made from find_binary' ); - - note('Checks on loading configs'); - note('empty dir'); -@@ -268,7 +276,10 @@ isa_ok( $config, "App::ClusterSSH::Config" ); - isa_ok( $config, "App::ClusterSSH::Config" ); - is( $trap->die, undef, 'die message correct' ); - is( $trap->stdout, q{}, 'Expecting no STDOUT' ); --is( $trap->stderr, q{}, 'Expecting no STDERR' ); -+is( $trap->stderr, -+ 'Created new configuration file within $HOME/.clusterssh/' . $/, -+ 'Got correct STDERR output for .csshrc' -+); - - #note(qx/ls -laR $ENV{HOME}/); - ok( -d $ENV{HOME} . '/.clusterssh', '.clusterssh dir exists' ); -@@ -292,9 +303,9 @@ isa_ok( $config, "App::ClusterSSH::Config" ); - is( $trap->die, undef, 'die message correct' ); - is( $trap->stdout, q{}, 'Expecting no STDOUT' ); - is( $trap->stderr, -- 'NOTICE: ' -- . $ENV{HOME} -- . '/.csshrc is no longer used - please see documentation and remove' -+ 'Moved $HOME/.csshrc to $HOME/.csshrc.DISABLED' -+ . $/ -+ . 'Created new configuration file within $HOME/.clusterssh/' - . $/, - 'Got correct STDERR output for .csshrc' - ); -@@ -303,6 +314,12 @@ ok( -f $ENV{HOME} . '/.clusterssh/config', '.clusterssh config file exists' ); - is_deeply( $config, \%expected, 'amended config is correct' ); - - note('.csshrc warning and .clusterssh dir plus config'); -+ -+# need to recreate .csshrc as it was just moved -+open( $csshrc, '>', $ENV{HOME} . '/.csshrc' ); -+print $csshrc 'auto_quit = no', $/; -+close($csshrc); -+$expected{auto_quit} = 'no'; - open( $csshrc, '>', $ENV{HOME} . '/.clusterssh/config' ); - print $csshrc 'window_tiling = no', $/; - close($csshrc); -@@ -317,10 +334,7 @@ isa_ok( $config, "App::ClusterSSH::Config" ); - is( $trap->die, undef, 'die message correct' ); - is( $trap->stdout, q{}, 'Expecting no STDOUT' ); - is( $trap->stderr, -- 'NOTICE: ' -- . $ENV{HOME} -- . '/.csshrc is no longer used - please see documentation and remove' -- . $/, -+ 'Moved $HOME/.csshrc to $HOME/.csshrc.DISABLED' . $/, - 'Got correct STDERR output for .csshrc' - ); - ok( -d $ENV{HOME} . '/.clusterssh', '.clusterssh dir exists' ); -@@ -395,7 +409,7 @@ is( $trap->leaveby, 'die', 'died ok' ); - isa_ok( $trap->die, 'App::ClusterSSH::Exception::Config' ); - isa_ok( $config, "App::ClusterSSH::Config" ); - is( $trap->die, -- 'Unable to create directory $HOME/.clusterssh: File exists', -+ 'Unable to create directory $HOME/.clusterssh: File exists' . $/, - 'die message correct' - ); - isa_ok( $config, "App::ClusterSSH::Config" ); -@@ -414,7 +428,7 @@ is( $trap->leaveby, 'die', 'died ok' ); - isa_ok( $trap->die, 'App::ClusterSSH::Exception::Config' ); - isa_ok( $config, "App::ClusterSSH::Config" ); - is( $trap->die, -- 'Unable to write default $HOME/.clusterssh/config: Is a directory', -+ 'Unable to write default $HOME/.clusterssh/config: Is a directory' . $/, - 'die message correct' - ); - isa_ok( $config, "App::ClusterSSH::Config" ); -@@ -434,7 +448,7 @@ is( $trap->leaveby, 'return', 'died ok' ); - isa_ok( $config, "App::ClusterSSH::Config" ); - is( $trap->stdout, q{}, 'Expecting no STDOUT' ); - is( $trap->stderr, -- q{Unable to create directory $HOME/.clusterssh: File exists} . $/, -+ q{Unable to create directory $HOME/.clusterssh: File exists} . $/ . $/, - 'Expecting no STDERR' - ); - -@@ -451,19 +465,23 @@ isa_ok( $config, "App::ClusterSSH::Config" ); - isa_ok( $config, "App::ClusterSSH::Config" ); - is( $trap->stdout, q{}, 'Expecting no STDOUT' ); - is( $trap->stderr, -- q{Unable to write default $HOME/.clusterssh/config: Is a directory} . $/, -+ q{Unable to write default $HOME/.clusterssh/config: Is a directory} -+ . $/ -+ . $/, - 'Expecting no STDERR' - ); - - note('Checking dump'); --$config = App::ClusterSSH::Config->new(); -+$config = App::ClusterSSH::Config->new( -+ send_menu_xml_file => $ENV{HOME} . '/.csshrc_send_menu' ); - trap { - $config->dump(); - }; --my $expected = <<'EOF'; --# Configuration dump produced by "cssh -u" -+my $expected = qq{# Configuration dump produced by "cssh -u" - auto_close=5 - auto_quit=yes -+console=console -+console_args= - console_position= - debug=0 - extra_cluster_file= -@@ -481,16 +499,19 @@ max_host_menu_items=30 - menu_host_autotearoff=0 - menu_send_autotearoff=0 - mouse_paste=Button-2 -+rsh=rsh - rsh_args= - screen_reserve_bottom=60 - screen_reserve_left=0 - screen_reserve_right=0 - screen_reserve_top=0 --send_menu_xml_file=/home/dferguson/.csshrc_send_menu -+send_menu_xml_file=} . $ENV{HOME} . qq{/.csshrc_send_menu - show_history=0 -+ssh=ssh - ssh_args= -+telnet=telnet - telnet_args= --terminal=/usr/bin/xterm -+terminal=xterm - terminal_allow_send_events=-xrm '*.VT100.allowSendEvents:true' - terminal_args= - terminal_bg_style=dark -@@ -507,12 +528,14 @@ terminal_title_opt=-T - unmap_on_redraw=no - use_all_a_records=0 - use_hotkeys=yes -+#user= - window_tiling=yes - window_tiling_direction=right --EOF -+}; -+ - isa_ok( $config, "App::ClusterSSH::Config" ); --is( $trap->die, undef, 'die message correct' ); --is( $trap->stdout, $expected, 'Expecting no STDOUT' ); --is( $trap->stderr, q{}, 'Expecting no STDERR' ); -+is( $trap->die, undef, 'die message correct' ); -+eq_or_diff( $trap->stdout, $expected, 'Expecting no STDOUT' ); -+is( $trap->stderr, q{}, 'Expecting no STDERR' ); - - done_testing(); -diff --git a/t/30cluster.t b/t/30cluster.t -index 487bbfc..1beadec 100644 ---- a/t/30cluster.t -+++ b/t/30cluster.t -@@ -8,6 +8,7 @@ use Test::More; - use Test::Trap; - use File::Which qw(which); - use File::Temp qw(tempdir); -+use English '-no_match_vars'; - - use Readonly; - -@@ -27,24 +28,33 @@ $cluster1->register_tag( 'people', @expected ); - - my @got = $cluster2->get_tag('people'); - --is_deeply( \@got, \@expected, -- 'Shared cluster object' ); -+is_deeply( \@got, \@expected, 'Shared cluster object' ); - - # should pass without issue - trap { - $cluster1->read_cluster_file( $Bin . '/30cluster.doesnt exist' ); - }; --is( ! $trap, '', 'coped with missing file ok' ); -+is( !$trap, '', 'coped with missing file ok' ); - isa_ok( $cluster1, 'App::ClusterSSH::Cluster' ); - --my $no_read=$Bin . '/30cluster.cannot_read'; --chmod 0000, $no_read; --trap { -- $cluster1->read_cluster_file( $no_read ); --}; --chmod 0644, $no_read; --isa_ok( $trap->die, 'App::ClusterSSH::Exception::Cluster' ); --is( $trap->die, "Unable to read file $no_read: Permission denied", 'Error on reading an existing file ok'); -+# no point running this test as root since root cannot be blocked -+# from accessing the file -+if ( $EUID != 0 ) { -+ my $no_read = $Bin . '/30cluster.cannot_read'; -+ chmod 0000, $no_read; -+ trap { -+ $cluster1->read_cluster_file($no_read); -+ }; -+ chmod 0644, $no_read; -+ isa_ok( $trap->die, 'App::ClusterSSH::Exception::Cluster' ); -+ is( $trap->die, -+ "Unable to read file $no_read: Permission denied", -+ 'Error on reading an existing file ok' -+ ); -+} -+else { -+ pass('Cannot test for lack of read access when run as root'); -+} - - @expected = ('host1'); - $cluster1->read_cluster_file( $Bin . '/30cluster.file1' ); -@@ -53,18 +63,15 @@ is_deeply( \@got, \@expected, 'read simple file OK' ); - - @expected = ('host1'); - $cluster1->read_cluster_file( $Bin . '/30cluster.file2' ); --@got=$cluster1->get_tag('tag1'); --is_deeply( \@got, -- \@expected, 'read more complex file OK' ); -+@got = $cluster1->get_tag('tag1'); -+is_deeply( \@got, \@expected, 'read more complex file OK' ); - - @expected = ('host2'); --@got=$cluster1->get_tag('tag2'); --is_deeply( \@got, -- \@expected, 'read more complex file OK' ); -+@got = $cluster1->get_tag('tag2'); -+is_deeply( \@got, \@expected, 'read more complex file OK' ); - - @expected = ( 'host3', 'host4' ); --@got=$cluster1->get_tag('tag3'); --is_deeply( \@got, -- \@expected, 'read more complex file OK' ); -+@got = $cluster1->get_tag('tag3'); -+is_deeply( \@got, \@expected, 'read more complex file OK' ); - - done_testing(); |