summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--network/ClusterSSH/ClusterSSH.SlackBuild19
-rw-r--r--network/ClusterSSH/ClusterSSH.info6
-rw-r--r--network/ClusterSSH/patches/00-4.01_05.diff1641
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();