2006-12-19 13:02:02 +00:00
|
|
|
# - perl *-
|
2005-04-25 14:57:28 +00:00
|
|
|
# $Id$
|
|
|
|
#
|
|
|
|
# Script:
|
|
|
|
# $RCSfile$
|
|
|
|
#
|
|
|
|
# Usage:
|
|
|
|
# cssh [options] [hostnames] [...]
|
|
|
|
#
|
|
|
|
# Options:
|
|
|
|
# see pod documentation
|
|
|
|
#
|
|
|
|
# Parameters:
|
|
|
|
# hosts to open connection to
|
|
|
|
#
|
|
|
|
# Purpose:
|
|
|
|
# Concurrently administer multiple remote servers
|
|
|
|
#
|
|
|
|
# Dependencies:
|
|
|
|
# Perl 5.6.0
|
|
|
|
# Tk 800.022
|
|
|
|
#
|
|
|
|
# Limitations:
|
|
|
|
#
|
|
|
|
# Enhancements:
|
|
|
|
#
|
|
|
|
# Notes:
|
|
|
|
#
|
|
|
|
# License:
|
|
|
|
# This code is distributed under the terms of the GPL (GNU General Pulic
|
|
|
|
# License).
|
|
|
|
#
|
|
|
|
# Copyright (C)
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify it
|
|
|
|
# under the terms of the GNU General Public License as published by the
|
|
|
|
# Free Software Foundation; either version 2 of the License, or any later
|
|
|
|
# version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful, but
|
|
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
|
|
# Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License along
|
|
|
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
#
|
|
|
|
# Please see the full text of the licenses is in the file COPYING and also at
|
|
|
|
# http://www.opensource.org/licenses/gpl-license.php
|
|
|
|
#
|
|
|
|
############################################################################
|
2009-09-24 18:31:57 +01:00
|
|
|
my $VERSION = '3.27';
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
### all use statements ###
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
use 5.006_000;
|
|
|
|
use Pod::Usage;
|
2009-04-21 20:14:00 +00:00
|
|
|
use Getopt::Long qw(:config no_ignore_case bundling no_auto_abbrev);
|
2005-04-26 11:43:10 +00:00
|
|
|
use POSIX qw/:sys_wait_h strftime mkfifo/;
|
2005-04-25 14:57:28 +00:00
|
|
|
use File::Temp qw/:POSIX/;
|
|
|
|
use Fcntl;
|
|
|
|
use Tk 800.022;
|
|
|
|
use Tk::Xlib;
|
2007-11-28 22:11:03 +00:00
|
|
|
use Tk::ROText;
|
2005-04-25 14:57:28 +00:00
|
|
|
require Tk::Dialog;
|
|
|
|
require Tk::LabEntry;
|
|
|
|
use X11::Protocol;
|
2006-07-24 19:12:54 +00:00
|
|
|
use X11::Protocol::Constants qw/ Shift Mod5 ShiftMask /;
|
|
|
|
use vars qw/ %keysymtocode %keycodetosym /;
|
2007-11-26 11:11:10 +00:00
|
|
|
use X11::Keysyms '%keysymtocode', 'MISCELLANY', 'XKB_KEYS', '3270', 'LATIN1',
|
2009-03-09 19:02:51 +00:00
|
|
|
'LATIN2', 'LATIN3', 'LATIN4', 'KATAKANA', 'ARABIC', 'CYRILLIC', 'GREEK',
|
|
|
|
'TECHNICAL', 'SPECIAL', 'PUBLISHING', 'APL', 'HEBREW', 'THAI', 'KOREAN';
|
2005-04-25 14:57:28 +00:00
|
|
|
use File::Basename;
|
2005-04-26 11:43:10 +00:00
|
|
|
use Net::hostent;
|
2009-04-06 19:40:13 +00:00
|
|
|
use Carp;
|
2009-08-18 21:13:36 +01:00
|
|
|
use Sys::Hostname;
|
|
|
|
use English;
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
### all global variables ###
|
2005-06-24 16:32:04 +00:00
|
|
|
my $scriptname = $0;
|
|
|
|
$scriptname =~ s!.*/!!; # get the script name, minus the path
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
# Command line options list
|
|
|
|
my @options_spec = (
|
|
|
|
'debug:+',
|
2009-04-22 18:16:58 +00:00
|
|
|
'd', # backwards compatibility - DEPRECATED
|
|
|
|
'D', # backwards compatibility - DEPRECATED
|
2009-04-21 20:14:00 +00:00
|
|
|
'version|v',
|
|
|
|
'help|h|?',
|
|
|
|
'man|H',
|
2009-04-22 18:16:58 +00:00
|
|
|
'action|a=s',
|
2009-04-21 20:14:00 +00:00
|
|
|
'cluster-file|c=s',
|
|
|
|
'config-file|C=s',
|
|
|
|
'evaluate|e=s',
|
|
|
|
'tile|g',
|
|
|
|
'no-tile|G',
|
|
|
|
'username|l=s',
|
|
|
|
'options|o=s',
|
|
|
|
'port|p=i',
|
|
|
|
'autoquit|q',
|
|
|
|
'no-autoquit|Q',
|
|
|
|
'history|s',
|
|
|
|
'term-args|t=s',
|
|
|
|
'title|T=s',
|
|
|
|
'output-config|u',
|
|
|
|
);
|
2005-04-25 14:57:28 +00:00
|
|
|
my %options;
|
|
|
|
my %config;
|
2005-06-24 16:32:04 +00:00
|
|
|
my %clusters; # hash for resolving cluster names
|
|
|
|
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 $helper_script = "";
|
2006-07-24 19:12:54 +00:00
|
|
|
my $xdisplay;
|
|
|
|
my %keyboardmap;
|
2007-12-19 09:53:42 +00:00
|
|
|
my $sysconfigdir = "/etc";
|
2008-01-23 22:18:33 +00:00
|
|
|
my %ssh_hostnames;
|
2006-07-24 19:12:54 +00:00
|
|
|
|
|
|
|
# Fudge to get X11::Keysyms working
|
|
|
|
%keysymtocode = %main::keysymtocode;
|
2007-11-26 11:11:10 +00:00
|
|
|
$keysymtocode{unknown_sym} = 0xFFFFFF; # put in a default "unknown" entry
|
2009-03-09 19:02:51 +00:00
|
|
|
$keysymtocode{EuroSign}
|
|
|
|
= 0x20AC; # Euro sigyn - missing from X11::Protocol::Keysyms
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
# and also map it the other way
|
|
|
|
%keycodetosym = reverse %keysymtocode;
|
|
|
|
|
|
|
|
# Set up UTF-8 on STDOUT
|
|
|
|
binmode STDOUT, ":utf8";
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
#use bytes;
|
2005-05-19 09:41:28 +00:00
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
### all sub-routines ###
|
|
|
|
|
2008-12-20 22:15:54 +00:00
|
|
|
# Pick a color based on a string.
|
2009-03-09 19:02:51 +00:00
|
|
|
sub pick_color {
|
|
|
|
my ($string) = @_;
|
|
|
|
my @components = qw(AA BB CC EE);
|
|
|
|
my $color = 0;
|
|
|
|
for ( my $i = 0; $i < length($string); $i++ ) {
|
|
|
|
$color += ord( substr( $string, $i, 1 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
srand($color);
|
|
|
|
my $ans = '\\#';
|
|
|
|
$ans .= $components[ int( 4 * rand() ) ];
|
|
|
|
$ans .= $components[ int( 4 * rand() ) ];
|
|
|
|
$ans .= $components[ int( 4 * rand() ) ];
|
|
|
|
return $ans;
|
2008-12-20 22:15:54 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:06:36 +00:00
|
|
|
# close a specific host session
|
2007-11-26 11:11:10 +00:00
|
|
|
sub terminate_host($) {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $svr = shift;
|
|
|
|
logmsg( 2, "Killing session for $svr" );
|
|
|
|
if ( !$servers{$svr} ) {
|
|
|
|
logmsg( 2, "Session for $svr not found" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
logmsg( 2, "Killing process $servers{$svr}{pid}" );
|
|
|
|
kill( 9, $servers{$svr}{pid} ) if kill( 0, $servers{$svr}{pid} );
|
|
|
|
delete( $servers{$svr} );
|
2007-11-26 11:06:36 +00:00
|
|
|
}
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
# catch_all exit routine that should always be used
|
2007-11-26 11:11:10 +00:00
|
|
|
sub exit_prog() {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 3, "Exiting via normal routine" );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# for each of the client windows, send a kill
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# to make sure we catch all children, even when they havnt
|
|
|
|
# finished starting or received teh kill signal, do it like this
|
|
|
|
while (%servers) {
|
|
|
|
foreach my $svr ( keys(%servers) ) {
|
|
|
|
terminate_host($svr);
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2009-03-09 19:02:51 +00:00
|
|
|
exit 0;
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# output function according to debug level
|
|
|
|
# $1 = log level (0 to 3)
|
|
|
|
# $2 .. $n = list to pass to print
|
2007-11-26 11:11:10 +00:00
|
|
|
sub logmsg($@) {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $level = shift;
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-22 19:07:32 +00:00
|
|
|
if ( $level > 6 ) {
|
|
|
|
croak('requested debug level should not be above 6');
|
2009-04-06 19:40:13 +00:00
|
|
|
}
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
if ( $level <= $options{debug} ) {
|
2009-04-22 18:16:58 +00:00
|
|
|
print( strftime( "%H:%M:%S: ", localtime ) )
|
|
|
|
if ( $options{debug} > 1 );
|
2009-03-09 19:02:51 +00:00
|
|
|
print @_, $/;
|
|
|
|
}
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# set some application defaults
|
2007-11-26 11:11:10 +00:00
|
|
|
sub load_config_defaults() {
|
2009-03-09 19:02:51 +00:00
|
|
|
$config{terminal} = "xterm";
|
|
|
|
$config{terminal_args} = "";
|
|
|
|
$config{terminal_title_opt} = "-T";
|
|
|
|
$config{terminal_colorize} = 1;
|
|
|
|
$config{terminal_bg_style} = 'dark';
|
|
|
|
$config{terminal_allow_send_events}
|
|
|
|
= "-xrm '*.VT100.allowSendEvents:true'";
|
|
|
|
$config{terminal_font} = "6x13";
|
|
|
|
$config{terminal_size} = "80x24";
|
|
|
|
$config{use_hotkeys} = "yes";
|
|
|
|
$config{key_quit} = "Control-q";
|
2009-04-22 19:07:32 +00:00
|
|
|
$config{key_addhost} = "Control-Shift-plus";
|
2009-03-09 19:02:51 +00:00
|
|
|
$config{key_clientname} = "Alt-n";
|
|
|
|
$config{key_history} = "Alt-h";
|
|
|
|
$config{key_retilehosts} = "Alt-r";
|
|
|
|
$config{key_paste} = "Control-v";
|
|
|
|
$config{mouse_paste} = "Button-2";
|
|
|
|
$config{auto_quit} = "yes";
|
|
|
|
$config{window_tiling} = "yes";
|
|
|
|
$config{window_tiling_direction} = "right";
|
|
|
|
$config{console_position} = "";
|
|
|
|
|
|
|
|
$config{screen_reserve_top} = 0;
|
2009-04-15 21:47:41 +00:00
|
|
|
$config{screen_reserve_bottom} = 60;
|
2009-03-09 19:02:51 +00:00
|
|
|
$config{screen_reserve_left} = 0;
|
|
|
|
$config{screen_reserve_right} = 0;
|
|
|
|
|
2009-04-15 21:47:41 +00:00
|
|
|
$config{terminal_reserve_top} = 5;
|
2009-03-09 19:02:51 +00:00
|
|
|
$config{terminal_reserve_bottom} = 0;
|
2009-04-15 21:47:41 +00:00
|
|
|
$config{terminal_reserve_left} = 5;
|
2009-03-09 19:02:51 +00:00
|
|
|
$config{terminal_reserve_right} = 0;
|
|
|
|
|
|
|
|
$config{terminal_decoration_height} = 10;
|
|
|
|
$config{terminal_decoration_width} = 8;
|
|
|
|
|
|
|
|
( $config{comms} = basename($0) ) =~ s/^.//;
|
|
|
|
$config{comms} =~ s/.pl$//; # for when testing directly out of cvs
|
|
|
|
$config{method} = $config{comms};
|
|
|
|
|
|
|
|
$config{title} = "C" . uc( $config{comms} );
|
|
|
|
|
|
|
|
$config{comms} = "telnet" if ( $config{comms} eq "tel" );
|
|
|
|
|
|
|
|
$config{ $config{comms} } = $config{comms};
|
|
|
|
|
2009-04-03 19:42:22 +00:00
|
|
|
$config{ssh_args} = " -x -o ConnectTimeout=10"
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{ $config{comms} } =~ /ssh$/ );
|
|
|
|
$config{rsh_args} = "";
|
|
|
|
|
|
|
|
$config{telnet_args} = "";
|
|
|
|
|
|
|
|
$config{extra_cluster_file} = "";
|
|
|
|
|
|
|
|
$config{unmap_on_redraw} = "no"; # Debian #329440
|
|
|
|
|
|
|
|
$config{show_history} = 0;
|
|
|
|
$config{history_width} = 40;
|
|
|
|
$config{history_height} = 10;
|
2009-04-15 17:35:22 +00:00
|
|
|
|
2009-04-22 18:58:24 +00:00
|
|
|
$config{command} = q{};
|
|
|
|
$config{max_host_menu_items} = 30;
|
2009-06-04 17:26:16 +00:00
|
|
|
|
|
|
|
$config{max_addhost_menu_cluster_items} = 6;
|
2009-08-11 18:01:06 +01:00
|
|
|
$config{menu_send_autotearoff} = 0;
|
|
|
|
$config{menu_host_autotearoff} = 0;
|
2009-08-18 21:13:36 +01:00
|
|
|
|
|
|
|
$config{send_menu_xml_file} = $ENV{HOME} . '/.csshrc_send_menu';
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# load in config file settings
|
2007-11-26 11:11:10 +00:00
|
|
|
sub parse_config_file($) {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $config_file = shift;
|
|
|
|
logmsg( 2, "Reading in from config file $config_file" );
|
2009-03-09 19:22:36 +00:00
|
|
|
return if ( !-e $config_file || !-r $config_file );
|
2009-03-09 19:02:51 +00:00
|
|
|
|
|
|
|
open( CFG, $config_file ) or die("Couldnt open $config_file: $!");
|
|
|
|
while (<CFG>) {
|
|
|
|
next if ( /^\s*$/ || /^#/ ); # ignore blank lines & commented lines
|
|
|
|
s/#.*//; # remove comments from remaining lines
|
|
|
|
s/\s*$//; # remove trailing whitespace
|
|
|
|
chomp();
|
|
|
|
|
|
|
|
next unless m/\s*(\S+)\s*=\s*(.*)\s*/;
|
|
|
|
my ( $key, $value ) = ( $1, $2 );
|
|
|
|
$config{$key} = $value;
|
|
|
|
logmsg( 3, "$key=$value" );
|
|
|
|
}
|
|
|
|
close(CFG);
|
|
|
|
|
|
|
|
# tidy up entries, just in case
|
|
|
|
$config{terminal_font} =~ s/['"]//g;
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub find_binary($) {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $binary = shift;
|
|
|
|
|
|
|
|
logmsg( 2, "Looking for $binary" );
|
|
|
|
my $path;
|
|
|
|
if ( !-x $binary ) {
|
|
|
|
|
|
|
|
# search the users $PATH and then a few other places to find the binary
|
|
|
|
# just in case $PATH isnt set up right
|
|
|
|
foreach (
|
|
|
|
split( /:/, $ENV{PATH} ), qw!
|
|
|
|
/bin
|
|
|
|
/sbin
|
|
|
|
/usr/sbin
|
|
|
|
/usr/bin
|
|
|
|
/usr/local/bin
|
|
|
|
/usr/local/sbin
|
|
|
|
/opt/local/bin
|
|
|
|
/opt/local/sbin
|
|
|
|
!
|
|
|
|
)
|
|
|
|
{
|
|
|
|
logmsg( 3, "Looking in $_" );
|
|
|
|
|
|
|
|
if ( -x $_ . '/' . $binary ) {
|
|
|
|
$path = $_ . '/' . $binary;
|
|
|
|
logmsg( 2, "Found at $path" );
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logmsg( 2, "Already configured OK" );
|
|
|
|
$path = $binary;
|
|
|
|
}
|
|
|
|
if ( !$path || !-f $path || !-x $path ) {
|
|
|
|
warn(
|
|
|
|
"Terminal binary not found ($binary) - please amend \$PATH or the cssh config file\n"
|
|
|
|
);
|
2009-04-21 20:14:00 +00:00
|
|
|
die unless ( $options{'output-config'} );
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
chomp($path);
|
|
|
|
return $path;
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2005-05-03 13:58:38 +00:00
|
|
|
# make sure our config is sane (i.e. binaries found) and get some extra bits
|
2007-11-26 11:11:10 +00:00
|
|
|
sub check_config() {
|
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# check we have xterm on our path
|
|
|
|
logmsg( 2, "Checking path to xterm" );
|
|
|
|
$config{terminal} = find_binary( $config{terminal} );
|
|
|
|
|
|
|
|
# check we have comms method on our path
|
|
|
|
logmsg( 2, "Checking path to $config{comms}" );
|
|
|
|
$config{ $config{comms} } = find_binary( $config{ $config{comms} } );
|
|
|
|
|
|
|
|
# make sure comms in an accepted value
|
|
|
|
die
|
|
|
|
"FATAL: Only ssh, rsh and telnet protocols are currently supported (comms=$config{comms})\n"
|
|
|
|
if ( $config{comms} !~ /^(:?[rs]sh|telnet)$/ );
|
|
|
|
|
|
|
|
# Set any extra config options given on command line
|
2009-04-21 20:14:00 +00:00
|
|
|
$config{title} = $options{title} if ( $options{title} );
|
2009-03-09 19:02:51 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
$config{auto_quit} = "yes" if $options{autoquit};
|
|
|
|
$config{auto_quit} = "no" if $options{'no-autoquit'};
|
2009-03-09 19:02:51 +00:00
|
|
|
|
|
|
|
# backwards compatibility & tidyup
|
|
|
|
if ( $config{always_tile} ) {
|
|
|
|
if ( !$config{window_tiling} ) {
|
|
|
|
if ( $config{always_tile} eq "never" ) {
|
|
|
|
$config{window_tiling} = "no";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$config{window_tiling} = "yes";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete( $config{always_tile} );
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2009-04-21 20:14:00 +00:00
|
|
|
$config{window_tiling} = "yes" if $options{tile};
|
|
|
|
$config{window_tiling} = "no" if $options{'no-tile'};
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-04-22 18:16:58 +00:00
|
|
|
$config{user} = $options{username} if ( $options{username} );
|
|
|
|
$config{terminal_args} = $options{'term-args'}
|
|
|
|
if ( $options{'term-args'} );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{terminal_args} =~ /-class (\w+)/ ) {
|
|
|
|
$config{terminal_allow_send_events}
|
|
|
|
= "-xrm '$1.VT100.allowSendEvents:true'";
|
|
|
|
}
|
2007-11-26 11:06:36 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$config{internal_previous_state} = ""; # set to default
|
|
|
|
get_font_size();
|
2006-12-19 13:02:02 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$config{extra_cluster_file} =~ s/\s+//g;
|
2007-11-28 22:11:03 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
$config{ssh_args} = $options{options} if ( $options{options} );
|
2009-04-06 19:52:23 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
$config{show_history} = 1 if $options{'show-history'};
|
2009-04-15 17:35:22 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
$config{command} = $options{action} if ( $options{action} );
|
2005-05-05 15:22:06 +00:00
|
|
|
}
|
2005-05-03 13:58:38 +00:00
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub load_configfile() {
|
2009-03-09 19:02:51 +00:00
|
|
|
parse_config_file( $sysconfigdir . '/csshrc' );
|
|
|
|
parse_config_file( $ENV{HOME} . '/.csshrc' );
|
2009-04-21 20:14:00 +00:00
|
|
|
if ( $options{'config-file'} ) {
|
|
|
|
parse_config_file( $options{'config-file'} );
|
2009-03-09 19:02:51 +00:00
|
|
|
}
|
|
|
|
check_config();
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# dump out the config to STDOUT
|
2007-11-26 11:11:10 +00:00
|
|
|
sub dump_config {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $noexit = shift;
|
2005-05-05 15:22:06 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 3, "Dumping config to STDOUT" );
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
print("# Configuration dump produced by 'cssh -u'\n");
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach ( sort( keys(%config) ) ) {
|
|
|
|
next
|
2009-04-21 20:14:00 +00:00
|
|
|
if ( $_ =~ /^internal/ && $options{debug} == 0 )
|
2009-03-09 19:02:51 +00:00
|
|
|
; # do not output internal vars
|
|
|
|
print "$_=$config{$_}\n";
|
|
|
|
}
|
|
|
|
exit_prog if ( !$noexit );
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2008-01-23 22:18:33 +00:00
|
|
|
sub check_ssh_hostnames {
|
2009-03-09 19:02:51 +00:00
|
|
|
return unless ( $config{method} eq "ssh" );
|
2008-01-23 22:18:33 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
my $ssh_config = "$ENV{HOME}/.ssh/config";
|
2008-01-23 22:18:33 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( -r $ssh_config && open( SSHCFG, "<", $ssh_config ) ) {
|
|
|
|
while (<SSHCFG>) {
|
|
|
|
next unless (m/^\s*host\s+([\w\.-]+)/i);
|
|
|
|
$ssh_hostnames{$1} = 1;
|
|
|
|
}
|
|
|
|
close(SSHCFG);
|
2008-01-23 22:18:33 +00:00
|
|
|
}
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
if ( $options{debug} > 1 ) {
|
2009-03-09 19:02:51 +00:00
|
|
|
if (%ssh_hostnames) {
|
|
|
|
logmsg( 2, "Parsed these ssh config hosts:" );
|
|
|
|
logmsg( 2, "- $_" ) foreach ( sort( keys(%ssh_hostnames) ) );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logmsg( 2, "No hostnames parsed from user ssh config file" );
|
|
|
|
}
|
2008-01-23 22:18:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub evaluate_commands {
|
2009-03-09 19:02:51 +00:00
|
|
|
my ( $return, $user, $port, $host );
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# break apart the given host string to check for user or port configs
|
2009-04-21 20:14:00 +00:00
|
|
|
print "{evaluate}=$options{evaluate}\n";
|
|
|
|
$user = $1 if ( $options{evaluate} =~ s/^(.*)@// );
|
|
|
|
$port = $1 if ( $options{evaluate} =~ s/:(\w+)$// );
|
|
|
|
$host = $options{evaluate};
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$user = $user ? "-l $user" : "";
|
2009-03-10 09:37:53 +00:00
|
|
|
if ( $config{comms} eq "telnet" ) {
|
|
|
|
$port = $port ? " $port" : "";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$port = $port ? "-p $port" : "";
|
|
|
|
}
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
print STDERR "Testing terminal - running command:\n";
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
my $terminal_command
|
|
|
|
= "$config{terminal} $config{terminal_allow_send_events} -e \"$^X\" \"-e\" 'print \"Working\\n\" ; sleep 5'";
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
print STDERR $terminal_command, $/;
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
system($terminal_command);
|
|
|
|
print STDERR "\nTesting comms - running command:\n";
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
my $comms_command = $config{ $config{comms} } . " "
|
|
|
|
. $config{ $config{comms} . "_args" };
|
2007-10-25 12:08:15 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{comms} eq "telnet" ) {
|
|
|
|
$comms_command .= " $host $port";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$comms_command .= " $user $port $host echo Working";
|
|
|
|
}
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
print STDERR $comms_command, $/;
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
system($comms_command);
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
exit_prog;
|
2006-07-24 19:12:54 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub load_keyboard_map() {
|
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# load up the keyboard map to convert keysyms to keyboardmap
|
|
|
|
my $min = $xdisplay->{min_keycode};
|
|
|
|
my $count = $xdisplay->{max_keycode} - $min;
|
|
|
|
my @keyboard = $xdisplay->GetKeyboardMapping( $min, $count );
|
|
|
|
|
|
|
|
# @keyboard arry
|
|
|
|
# 0 = plain key
|
|
|
|
# 1 = with shift
|
|
|
|
# 2 = with Alt-GR
|
|
|
|
# 3 = with shift + AltGr
|
|
|
|
# 4 = same as 2 - control/alt?
|
|
|
|
# 5 = same as 3 - shift-control-alt?
|
|
|
|
|
|
|
|
logmsg( 1, "Loading keymaps and keycodes" );
|
|
|
|
|
|
|
|
foreach ( 0 .. $#keyboard ) {
|
2009-04-16 18:27:20 +00:00
|
|
|
if ( defined $keyboard[$_][3] ) {
|
|
|
|
if ( defined( $keycodetosym{ $keyboard[$_][3] } ) ) {
|
|
|
|
$keyboardmap{ $keycodetosym{ $keyboard[$_][3] } }
|
|
|
|
= 'sa' . ( $_ + $min );
|
2009-03-09 19:02:51 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-04-16 18:27:20 +00:00
|
|
|
logmsg( 2, "Unknown keycode ", $keyboard[$_][3] )
|
|
|
|
if ( $keyboard[$_][3] != 0 );
|
2009-03-09 19:02:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
}
|
2009-04-16 18:27:20 +00:00
|
|
|
if ( defined $keyboard[$_][1] ) {
|
|
|
|
if ( defined( $keycodetosym{ $keyboard[$_][1] } ) ) {
|
|
|
|
$keyboardmap{ $keycodetosym{ $keyboard[$_][1] } }
|
|
|
|
= 's' . ( $_ + $min );
|
2009-03-09 19:02:51 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-04-16 18:27:20 +00:00
|
|
|
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 );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logmsg( 2, "Unknown keycode ", $keyboard[$_][0] )
|
|
|
|
if ( $keyboard[$_][0] != 0 );
|
2009-03-09 19:02:51 +00:00
|
|
|
}
|
|
|
|
}
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# dont know these two key combs yet...
|
|
|
|
#$keyboardmap{ $keycodetosym { $keyboard[$_][4] } } = $_ + $min;
|
|
|
|
#$keyboardmap{ $keycodetosym { $keyboard[$_][5] } } = $_ + $min;
|
|
|
|
}
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# print "$_ => $keyboardmap{$_}\n" foreach(sort(keys(%keyboardmap)));
|
|
|
|
# print "keysymtocode: $keysymtocode{o}\n";
|
|
|
|
# die;
|
2006-07-24 19:12:54 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub get_keycode_state($) {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $keysym = shift;
|
|
|
|
$keyboardmap{$keysym} =~ m/^(\D+)(\d+)$/;
|
|
|
|
my ( $state, $code ) = ( $1, $2 );
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "keyboardmap=:", $keyboardmap{$keysym}, ":" );
|
|
|
|
logmsg( 2, "state=$state, code=$code" );
|
2007-11-26 11:11:10 +00:00
|
|
|
|
|
|
|
SWITCH: for ($state) {
|
2009-03-09 19:02:51 +00:00
|
|
|
/^n$/ && do {
|
|
|
|
$state = 0;
|
|
|
|
last SWITCH;
|
|
|
|
};
|
|
|
|
/^s$/ && do {
|
|
|
|
$state = Shift();
|
|
|
|
last SWITCH;
|
|
|
|
};
|
|
|
|
/^a$/ && do {
|
|
|
|
$state = Mod5();
|
|
|
|
last SWITCH;
|
|
|
|
};
|
|
|
|
/^sa$/ && do {
|
|
|
|
$state = Shift() + Mod5();
|
|
|
|
last SWITCH;
|
|
|
|
};
|
|
|
|
|
|
|
|
die("Should never reach here");
|
|
|
|
}
|
|
|
|
|
|
|
|
logmsg( 2, "returning state=:$state: code=:$code:" );
|
|
|
|
|
|
|
|
return ( $state, $code );
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2005-06-09 16:03:26 +00:00
|
|
|
|
2005-06-24 16:32:04 +00:00
|
|
|
# read in all cluster definitions
|
2007-11-26 11:11:10 +00:00
|
|
|
sub get_clusters() {
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# first, read in global file
|
|
|
|
my $cluster_file = '/etc/clusters';
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 3, "Logging for $cluster_file" );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( -f $cluster_file ) {
|
|
|
|
logmsg( 2, "Loading clusters in from $cluster_file" );
|
|
|
|
open( CLUSTERS, $cluster_file ) || die("Couldnt read $cluster_file");
|
|
|
|
while (<CLUSTERS>) {
|
|
|
|
next
|
|
|
|
if ( /^\s*$/ || /^#/ ); # ignore blank lines & commented lines
|
|
|
|
chomp();
|
|
|
|
my @line = split(/\s/);
|
|
|
|
|
|
|
|
#s/^([\w-]+)\s*//; # remote first word and stick into $1
|
|
|
|
|
|
|
|
logmsg(
|
|
|
|
3,
|
|
|
|
"cluster $line[0] = ",
|
|
|
|
join( " ", @line[ 1 .. $#line ] )
|
|
|
|
);
|
|
|
|
$clusters{ $line[0] } = join( " ", @line[ 1 .. $#line ] )
|
|
|
|
; # Now bung in rest of line
|
|
|
|
}
|
|
|
|
close(CLUSTERS);
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2006-12-19 13:02:02 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# Now get any definitions out of %config
|
|
|
|
logmsg( 2, "Looking for csshrc" );
|
|
|
|
if ( $config{clusters} ) {
|
|
|
|
logmsg( 2, "Loading clusters in from csshrc" );
|
|
|
|
|
|
|
|
foreach ( split( /\s+/, $config{clusters} ) ) {
|
|
|
|
if ( !$config{$_} ) {
|
|
|
|
warn(
|
|
|
|
"WARNING: missing cluster definition in .csshrc file ($_)"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logmsg( 3, "cluster $_ = $config{$_}" );
|
|
|
|
$clusters{$_} = $config{$_};
|
|
|
|
}
|
2007-11-26 11:11:10 +00:00
|
|
|
}
|
2009-03-09 19:02:51 +00:00
|
|
|
}
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# and any clusters defined within the config file or on the command line
|
2009-04-21 20:14:00 +00:00
|
|
|
if ( $config{extra_cluster_file} || $options{'cluster-file'} ) {
|
2009-03-09 19:02:51 +00:00
|
|
|
|
|
|
|
# check for multiple entries and push it through glob to catch ~'s
|
|
|
|
foreach my $item ( split( /,/, $config{extra_cluster_file} ),
|
2009-04-21 20:14:00 +00:00
|
|
|
$options{'cluster-file'} )
|
2009-03-09 19:02:51 +00:00
|
|
|
{
|
|
|
|
next unless ($item);
|
|
|
|
|
|
|
|
# cater for people using '$HOME'
|
|
|
|
$item =~ s/\$HOME/$ENV{HOME}/;
|
|
|
|
foreach my $file ( glob($item) ) {
|
|
|
|
if ( !-r $file ) {
|
|
|
|
warn("Unable to read cluster file '$file': $!\n");
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
logmsg( 2, "Loading clusters in from '$file'" );
|
|
|
|
|
|
|
|
open( CLUSTERS, $file ) || die("Couldnt read '$file': $!\n");
|
|
|
|
while (<CLUSTERS>) {
|
|
|
|
next if ( /^\s*$/ || /^#/ );
|
|
|
|
chomp;
|
|
|
|
|
|
|
|
my @line = split(/\s/);
|
|
|
|
logmsg(
|
|
|
|
3,
|
|
|
|
"cluster $line[0] = ",
|
|
|
|
join( " ", @line[ 1 .. $#line ] )
|
|
|
|
);
|
|
|
|
$clusters{ $line[0] } = join( " ", @line[ 1 .. $#line ] )
|
|
|
|
; # Now bung in rest of line
|
|
|
|
}
|
|
|
|
}
|
2007-11-26 11:11:10 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2006-12-19 13:02:02 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Finished loading clusters" );
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub resolve_names(@) {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Resolving cluster names: started" );
|
|
|
|
my @servers = @_;
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach (@servers) {
|
|
|
|
logmsg( 3, "Found server $_" );
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $clusters{$_} ) {
|
|
|
|
push( @servers, split( / /, $clusters{$_} ) );
|
|
|
|
$_ = "";
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
my @cleanarray;
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# now clean the array up
|
|
|
|
foreach (@servers) {
|
|
|
|
push( @cleanarray, $_ ) if ( $_ !~ /^$/ );
|
|
|
|
}
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach (@cleanarray) {
|
|
|
|
logmsg( 3, "leaving with $_" );
|
|
|
|
}
|
|
|
|
logmsg( 2, "Resolving cluster names: completed" );
|
|
|
|
return (@cleanarray);
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub change_main_window_title() {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $number = keys(%servers);
|
|
|
|
$windows{main_window}->title( $config{title} . " [$number]" );
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2007-11-28 22:49:59 +00:00
|
|
|
sub show_history() {
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{show_history} ) {
|
|
|
|
$windows{history}->packForget();
|
|
|
|
$config{show_history} = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$windows{history}->pack(
|
|
|
|
-fill => "x",
|
|
|
|
-expand => 1,
|
|
|
|
);
|
|
|
|
$config{show_history} = 1;
|
|
|
|
}
|
2007-11-28 22:49:59 +00:00
|
|
|
}
|
|
|
|
|
2007-11-28 22:11:03 +00:00
|
|
|
sub update_display_text($) {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $char = shift;
|
2007-11-28 22:11:03 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
return if ( !$config{show_history} );
|
2007-11-28 22:11:03 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Dropping :$char: into display" );
|
2007-11-28 22:11:03 +00:00
|
|
|
|
2007-11-28 22:38:26 +00:00
|
|
|
SWITCH: {
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach ($char) {
|
|
|
|
/^Return$/ && do {
|
|
|
|
$windows{history}->insert( 'end', "\n" );
|
|
|
|
last SWITCH;
|
|
|
|
};
|
|
|
|
|
|
|
|
/^BackSpace$/ && do {
|
|
|
|
$windows{history}->delete('end - 2 chars');
|
|
|
|
last SWITCH;
|
|
|
|
};
|
|
|
|
|
|
|
|
/^(:?Shift|Control|Alt)_(:?R|L)$/ && do {
|
|
|
|
last SWITCH;
|
|
|
|
};
|
|
|
|
|
|
|
|
length($char) > 1 && do {
|
|
|
|
$windows{history}
|
|
|
|
->insert( 'end', chr( $keysymtocode{$char} ) )
|
|
|
|
if ( $keysymtocode{$char} );
|
|
|
|
last SWITCH;
|
|
|
|
};
|
|
|
|
|
|
|
|
do {
|
|
|
|
$windows{history}->insert( 'end', $char );
|
|
|
|
last SWITCH;
|
|
|
|
};
|
|
|
|
}
|
2007-11-28 22:11:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub send_text($@) {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $svr = shift;
|
|
|
|
my $text = join( "", @_ );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "servers{$svr}{wid}=$servers{$svr}{wid}" );
|
2009-08-18 21:13:36 +01:00
|
|
|
logmsg( 3, "Sending to '$svr' text:$text:" );
|
|
|
|
|
|
|
|
# command macro substitution
|
|
|
|
|
|
|
|
# $svr contains a trailing space here, so ensure its stripped off
|
|
|
|
{
|
|
|
|
my $servername = $svr;
|
|
|
|
$servername =~ s/\s+//;
|
|
|
|
$text =~ s/%s/$servername/xsm;
|
|
|
|
}
|
|
|
|
$text =~ s/%h/hostname()/xsme;
|
|
|
|
|
|
|
|
# use connection username, else default to current username
|
|
|
|
{
|
|
|
|
my $username = $servers{$svr}{username};
|
|
|
|
$username ||= getpwuid($UID);
|
|
|
|
$text =~ s/%u/$username/xsm;
|
|
|
|
}
|
|
|
|
$text =~ s/%n/\n/xsm;
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach my $char ( split( //, $text ) ) {
|
|
|
|
next if ( !defined($char) );
|
|
|
|
my $ord = ord($char);
|
|
|
|
$ord = 65293 if ( $ord == 10 ); # convert 'Return' to sym
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( !defined( $keycodetosym{$ord} ) ) {
|
|
|
|
warn("Unknown character in xmodmap keytable: $char ($ord)\n");
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
my $keysym = $keycodetosym{$ord};
|
|
|
|
my $keycode = $keysymtocode{$keysym};
|
|
|
|
|
|
|
|
logmsg( 2, "Looking for char :$char: with ord :$ord:" );
|
|
|
|
logmsg( 2, "Looking for keycode :$keycode:" );
|
|
|
|
logmsg( 2, "Looking for keysym :$keysym:" );
|
|
|
|
logmsg( 2, "Looking for keyboardmap :", $keyboardmap{$keysym}, ":" );
|
|
|
|
my ( $state, $code ) = get_keycode_state($keysym);
|
|
|
|
logmsg( 2, "Got state :$state: code :$code:" );
|
|
|
|
|
|
|
|
for my $event (qw/KeyPress KeyRelease/) {
|
|
|
|
logmsg( 2, "sending event=$event code=:$code: state=:$state:" );
|
|
|
|
$xdisplay->SendEvent(
|
|
|
|
$servers{$svr}{wid},
|
|
|
|
0,
|
|
|
|
$xdisplay->pack_event_mask($event),
|
|
|
|
$xdisplay->pack_event(
|
|
|
|
'name' => $event,
|
|
|
|
'detail' => $code,
|
|
|
|
'state' => $state,
|
|
|
|
'time' => time(),
|
|
|
|
'event' => $servers{$svr}{wid},
|
|
|
|
'root' => $xdisplay->root(),
|
|
|
|
'same_screen' => 1,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2009-03-09 19:02:51 +00:00
|
|
|
$xdisplay->flush();
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2009-08-18 21:13:36 +01:00
|
|
|
sub send_text_to_all_servers {
|
|
|
|
my $text = join( '', @_ );
|
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach my $svr ( keys(%servers) ) {
|
2009-08-18 21:13:36 +01:00
|
|
|
send_text( $svr, $text )
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $servers{$svr}{active} == 1 );
|
|
|
|
}
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub send_resizemove($$$$$) {
|
2009-03-09 19:02:51 +00:00
|
|
|
my ( $win, $x_pos, $y_pos, $x_siz, $y_siz ) = @_;
|
|
|
|
|
|
|
|
logmsg( 3,
|
|
|
|
"Moving window $win to x:$x_pos y:$y_pos (size x:$x_siz y:$y_siz)" );
|
|
|
|
|
|
|
|
#logmsg( 2, "resize move normal: ", $xdisplay->atom('WM_NORMAL_HINTS') );
|
|
|
|
#logmsg( 2, "resize move size: ", $xdisplay->atom('WM_SIZE_HINTS') );
|
|
|
|
|
|
|
|
# set the window to have "user" set size & position, rather than "program"
|
|
|
|
$xdisplay->req(
|
|
|
|
'ChangeProperty',
|
|
|
|
$win,
|
|
|
|
$xdisplay->atom('WM_NORMAL_HINTS'),
|
|
|
|
$xdisplay->atom('WM_SIZE_HINTS'),
|
|
|
|
32,
|
|
|
|
'Replace',
|
|
|
|
|
2009-04-15 21:47:41 +00:00
|
|
|
# create data struct on fly to set bitwise flags
|
|
|
|
pack( 'LLLLL' . 'x[L]' x 12, 1 | 2, $x_pos, $y_pos, $x_siz, $y_siz ),
|
2009-03-09 19:02:51 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
$xdisplay->req(
|
|
|
|
'ConfigureWindow',
|
|
|
|
$win,
|
|
|
|
'x' => $x_pos,
|
|
|
|
'y' => $y_pos,
|
|
|
|
'width' => $x_siz,
|
|
|
|
'height' => $y_siz,
|
|
|
|
);
|
|
|
|
|
|
|
|
#$xdisplay->flush(); # dont flush here, but after all tiling worked out
|
2005-05-05 15:22:06 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub setup_helper_script() {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Setting up helper script" );
|
|
|
|
$helper_script = <<" HERE";
|
2005-04-25 14:57:28 +00:00
|
|
|
my \$pipe=shift;
|
|
|
|
my \$svr=shift;
|
2005-06-09 16:03:26 +00:00
|
|
|
my \$user=shift;
|
2006-07-24 19:12:54 +00:00
|
|
|
my \$port=shift;
|
2007-11-26 11:06:36 +00:00
|
|
|
my \$command="$config{$config{comms}} $config{$config{comms}."_args"} ";
|
2007-10-25 12:08:15 +00:00
|
|
|
open(PIPE, ">", \$pipe) or die("Failed to open pipe: \$!\\n");
|
2006-09-06 18:03:56 +00:00
|
|
|
print PIPE "\$\$:\$ENV{WINDOWID}"
|
2007-10-25 12:08:15 +00:00
|
|
|
or die("Failed to write to pipe: $!\\n");
|
|
|
|
close(PIPE) or die("Failed to close pipe: $!\\n");
|
|
|
|
if(\$svr =~ m/==\$/)
|
2005-06-13 13:56:24 +00:00
|
|
|
{
|
|
|
|
\$svr =~ s/==\$//;
|
2007-10-25 12:08:15 +00:00
|
|
|
warn("\\nWARNING: failed to resolve IP address for \$svr.\\n\\n"
|
2005-06-13 13:56:24 +00:00
|
|
|
);
|
2007-10-25 12:08:15 +00:00
|
|
|
sleep 5;
|
|
|
|
}
|
2007-11-28 22:11:03 +00:00
|
|
|
if(\$user) {
|
2007-10-25 12:08:15 +00:00
|
|
|
unless("$config{comms}" eq "telnet") {
|
2007-11-28 22:11:03 +00:00
|
|
|
\$user = \$user ? "-l \$user " : "";
|
2007-10-25 12:08:15 +00:00
|
|
|
\$command .= \$user;
|
|
|
|
}
|
2005-06-13 13:56:24 +00:00
|
|
|
}
|
2009-04-08 18:23:32 +00:00
|
|
|
if("$config{comms}" eq "telnet") {
|
2009-03-10 09:37:53 +00:00
|
|
|
\$command .= "\$svr \$port";
|
2007-10-25 12:08:15 +00:00
|
|
|
} else {
|
2009-04-08 18:23:32 +00:00
|
|
|
if (\$port) {
|
|
|
|
\$command .= "-p \$port \$svr";
|
|
|
|
} else {
|
2009-04-03 19:48:58 +00:00
|
|
|
\$command .= "\$svr";
|
2009-04-08 18:23:32 +00:00
|
|
|
}
|
2007-10-25 12:08:15 +00:00
|
|
|
}
|
2009-04-15 17:35:22 +00:00
|
|
|
\$command .= " $config{command} || sleep 5";
|
2007-10-25 12:08:15 +00:00
|
|
|
# warn("Running:\$command\\n"); # for debug purposes
|
|
|
|
exec(\$command);
|
2005-04-25 14:57:28 +00:00
|
|
|
HERE
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# eval $helper_script || die ($@); # for debug purposes
|
|
|
|
logmsg( 2, $helper_script );
|
|
|
|
logmsg( 2, "Helper script done" );
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
sub split_hostname {
|
2009-04-07 17:17:30 +00:00
|
|
|
my ($connect_string) = @_;
|
2009-04-06 19:40:13 +00:00
|
|
|
|
2009-04-07 17:17:30 +00:00
|
|
|
my ( $server, $username, $port );
|
|
|
|
|
|
|
|
logmsg( 3, 'split_hostname: connect_string=' . $connect_string );
|
2009-04-06 19:40:13 +00:00
|
|
|
|
|
|
|
$username = $config{user} if ( $config{user} );
|
|
|
|
|
2009-04-07 17:17:30 +00:00
|
|
|
if ( $connect_string =~ s/^(.*)@// ) {
|
2009-04-06 19:40:13 +00:00
|
|
|
$username = $1;
|
|
|
|
}
|
|
|
|
|
2009-04-07 17:17:30 +00:00
|
|
|
# cope with IPv6 addresses
|
|
|
|
|
|
|
|
# check for correct syntax of using [<IPv6 address>]
|
|
|
|
# See http://tools.ietf.org/html/rfc2732 for more details
|
|
|
|
if ( $connect_string =~ m/^\[([\w:]+)\](?::(\d+))?$/xsm ) {
|
|
|
|
logmsg( 3, 'connect_string contains IPv6 address' );
|
|
|
|
$server = $1;
|
|
|
|
$port = $2;
|
2009-04-06 19:40:13 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-04-07 17:17:30 +00:00
|
|
|
|
|
|
|
my $colon_count = $connect_string =~ tr/://;
|
|
|
|
|
|
|
|
# See if there are exactly 7 colons - if so, assume pure IPv6
|
|
|
|
if ( $colon_count == 7 ) {
|
|
|
|
$server = $connect_string;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
# if more than 1 but less than 8 colons and last octect is
|
|
|
|
# numbers only, warn about ambiguity
|
|
|
|
if ( $colon_count > 1
|
|
|
|
&& $colon_count < 8
|
|
|
|
&& $connect_string =~ m/:(\d+)$/ )
|
|
|
|
{
|
|
|
|
our $seen_error;
|
|
|
|
warn 'Potentially ambiguous IPv6 address/port definition: ',
|
|
|
|
$connect_string, $/;
|
|
|
|
warn 'Assuming it is an IPv6 address only.', $/;
|
|
|
|
$server = $connect_string;
|
|
|
|
if ( !$seen_error ) {
|
|
|
|
warn '*** See documenation for more information.', $/;
|
|
|
|
$seen_error = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
# split out port from end of connect string
|
|
|
|
# could have an invalid IPv6 address here, but the connect
|
2009-04-22 19:23:16 +00:00
|
|
|
# method will warn if it cannot connect anyhow
|
2009-04-07 17:17:30 +00:00
|
|
|
# However, this also catchs IPv4 addresses, possibly with ports
|
2009-06-02 14:40:27 +00:00
|
|
|
( $server, $port )
|
|
|
|
= $connect_string =~ m/^([\w.-]+)(?::(\d+))?$/xsm;
|
2009-04-06 19:40:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
$port ||= defined $options{port} ? $options{port} : q{};
|
2009-04-07 17:17:30 +00:00
|
|
|
$username ||= q{};
|
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
logmsg( 3, "username=$username, server=$server, port=$port" );
|
|
|
|
|
|
|
|
return ( $username, $server, $port );
|
|
|
|
}
|
|
|
|
|
2007-12-19 09:53:42 +00:00
|
|
|
sub check_host($) {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $host = shift;
|
2009-04-06 19:40:13 +00:00
|
|
|
if ( $host =~ m/:/ ) {
|
|
|
|
logmsg( 2, "Not resolving IPv6 address '$host'" );
|
2009-04-08 17:56:38 +00:00
|
|
|
return $host;
|
2009-04-06 19:40:13 +00:00
|
|
|
}
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $host =~ m/^(\d{1,3}\.?){4}$/ ) {
|
|
|
|
logmsg( 2, "Not resolving IP address '$host'" );
|
2009-04-08 17:56:38 +00:00
|
|
|
return $host;
|
2009-03-09 19:02:51 +00:00
|
|
|
}
|
|
|
|
if ( $config{method} eq "ssh" ) {
|
|
|
|
logmsg( 1, "Attempting name resolution via user ssh config file" );
|
|
|
|
if ( $ssh_hostnames{$host} ) {
|
2009-04-08 17:56:38 +00:00
|
|
|
return $host;
|
2009-03-09 19:02:51 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
logmsg( 1,
|
|
|
|
"Failed to check host (falling back to gethostbyname): $!" );
|
|
|
|
}
|
2007-12-19 09:53:42 +00:00
|
|
|
}
|
2009-07-22 12:16:47 +00:00
|
|
|
|
|
|
|
my $gethost_obj = gethostbyname($host);
|
|
|
|
return defined($gethost_obj) ? $gethost_obj->name() : $host;
|
2007-12-19 09:53:42 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub open_client_windows(@) {
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach (@_) {
|
|
|
|
next unless ($_);
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-04-07 17:17:30 +00:00
|
|
|
my ( $username, $server, $port ) = split_hostname($_);
|
2009-06-02 15:03:03 +00:00
|
|
|
my $given_server_name = $server;
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# see if we can find the hostname - if not, drop it
|
2009-04-08 17:56:38 +00:00
|
|
|
my $realname = check_host($server);
|
|
|
|
if ( !$realname ) {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $text = "WARNING: '$_' unknown";
|
2008-01-23 22:18:33 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if (%ssh_hostnames) {
|
|
|
|
$text
|
|
|
|
.= " (unable to resolve and not in user ssh config file)";
|
|
|
|
}
|
2008-01-23 22:18:33 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
warn( $text, $/ );
|
2009-04-03 19:51:04 +00:00
|
|
|
|
|
|
|
#next; # Debian bug 499935 - ignore warnings about hostname resolution
|
2009-03-09 19:02:51 +00:00
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
my $color = '';
|
|
|
|
if ( $config{terminal_colorize} ) {
|
|
|
|
my $c = pick_color($server);
|
|
|
|
if ( $config{terminal_bg_style} eq 'dark' ) {
|
|
|
|
$color = "-bg \\#000000 -fg $c";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$color = "-fg \\#000000 -bg $c";
|
|
|
|
}
|
|
|
|
}
|
2008-12-20 22:15:54 +00:00
|
|
|
|
2009-04-08 17:56:38 +00:00
|
|
|
my $count = q{};
|
2009-04-06 19:40:13 +00:00
|
|
|
while ( defined( $servers{ $server . q{ } . $count } ) ) {
|
|
|
|
$count++;
|
|
|
|
}
|
2009-04-08 17:56:38 +00:00
|
|
|
$server .= q{ } . $count;
|
2009-04-06 19:40:13 +00:00
|
|
|
|
2009-04-07 17:17:30 +00:00
|
|
|
$servers{$server}{connect_string} = $_;
|
2009-06-02 15:03:03 +00:00
|
|
|
$servers{$server}{givenname} = $given_server_name;
|
2009-04-08 17:56:38 +00:00
|
|
|
$servers{$server}{realname} = $realname;
|
2009-04-07 17:17:30 +00:00
|
|
|
$servers{$server}{username} = $username;
|
|
|
|
$servers{$server}{port} = $port || '';
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Working on server $server for $_" );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$servers{$server}{pipenm} = tmpnam();
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Set temp name to: $servers{$server}{pipenm}" );
|
|
|
|
mkfifo( $servers{$server}{pipenm}, 0600 )
|
|
|
|
or die("Cannot create pipe: $!");
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# NOTE: the pid is re-fetched from the xterm window (via helper_script)
|
|
|
|
# later as it changes and we need an accurate PID as it is widely used
|
|
|
|
$servers{$server}{pid} = fork();
|
|
|
|
if ( !defined( $servers{$server}{pid} ) ) {
|
|
|
|
die("Could not fork: $!");
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $servers{$server}{pid} == 0 ) {
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# this is the child
|
|
|
|
# Since this is the child, we can mark any server unresolved without
|
|
|
|
# affecting the main program
|
2009-04-08 17:56:38 +00:00
|
|
|
$servers{$server}{realname} .= "==" if ( !$realname );
|
2009-03-09 19:02:51 +00:00
|
|
|
my $exec
|
2009-04-07 17:17:30 +00:00
|
|
|
= "$config{terminal} $color $config{terminal_args} $config{terminal_allow_send_events} $config{terminal_title_opt} '$config{title}: $servers{$server}{connect_string}' -font $config{terminal_font} -e \"$^X\" \"-e\" '$helper_script' '$servers{$server}{pipenm}' '$servers{$server}{realname}' '$servers{$server}{username}' '$servers{$server}{port}'";
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Terminal exec line:\n$exec\n" );
|
|
|
|
exec($exec) == 0 or warn("Failed: $!");
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# Now all the windows are open, get all their window id's
|
|
|
|
foreach my $server ( keys(%servers) ) {
|
|
|
|
next if ( defined( $servers{$server}{active} ) );
|
|
|
|
|
|
|
|
# sleep for a moment to give system time to come up
|
|
|
|
select( undef, undef, undef, 0.1 );
|
|
|
|
|
|
|
|
# block on open so we get the text when it comes in
|
|
|
|
unless (
|
|
|
|
sysopen(
|
|
|
|
$servers{$server}{pipehl}, $servers{$server}{pipenm},
|
|
|
|
O_RDONLY
|
|
|
|
)
|
|
|
|
)
|
|
|
|
{
|
|
|
|
warn(
|
|
|
|
"Cannot open pipe for reading when talking to $server: $!\n");
|
|
|
|
}
|
|
|
|
else {
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# NOTE: read both the xterm pid and the window ID here
|
|
|
|
# get PID here as it changes from the fork above, and we need the
|
|
|
|
# correct PID
|
|
|
|
logmsg( 2, "Performing sysread" );
|
|
|
|
my $piperead;
|
|
|
|
sysread( $servers{$server}{pipehl}, $piperead, 100 );
|
|
|
|
( $servers{$server}{pid}, $servers{$server}{wid} )
|
|
|
|
= split( /:/, $piperead, 2 );
|
|
|
|
warn("Cannot determ pid of '$server' window\n")
|
|
|
|
unless $servers{$server}{pid};
|
|
|
|
warn("Cannot determ window ID of '$server' window\n")
|
|
|
|
unless $servers{$server}{wid};
|
|
|
|
logmsg( 2, "Done and closing pipe" );
|
|
|
|
|
|
|
|
close( $servers{$server}{pipehl} );
|
|
|
|
}
|
|
|
|
delete( $servers{$server}{pipehl} );
|
2006-09-06 18:03:56 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
unlink( $servers{$server}{pipenm} );
|
|
|
|
delete( $servers{$server}{pipenm} );
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$servers{$server}{active} = 1; # mark as active
|
|
|
|
$config{internal_activate_autoquit}
|
|
|
|
= 1; # activate auto_quit if in use
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "All client windows opened" );
|
|
|
|
$config{internal_total} = int( keys(%servers) );
|
2005-05-09 16:07:12 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub get_font_size() {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Fetching font size" );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# get atom name<->number relations
|
|
|
|
my $quad_width = $xdisplay->atom("QUAD_WIDTH");
|
|
|
|
my $pixel_size = $xdisplay->atom("PIXEL_SIZE");
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
my $font = $xdisplay->new_rsrc;
|
|
|
|
$xdisplay->OpenFont( $font, $config{terminal_font} );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
my %font_info;
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
eval { (%font_info) = $xdisplay->QueryFont($font); }
|
|
|
|
|| die( "Fatal: Unrecognised font used ($config{terminal_font}).\n"
|
|
|
|
. "Please amend \$HOME/.csshrc with a valid font (see man page).\n"
|
|
|
|
);
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$config{internal_font_width} = $font_info{properties}{$quad_width};
|
|
|
|
$config{internal_font_height} = $font_info{properties}{$pixel_size};
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( !$config{internal_font_width} || !$config{internal_font_height} ) {
|
|
|
|
die( "Fatal: Unrecognised font used ($config{terminal_font}).\n"
|
|
|
|
. "Please amend \$HOME/.csshrc with a valid font (see man page).\n"
|
|
|
|
);
|
|
|
|
}
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Done with font size" );
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2005-05-09 16:07:12 +00:00
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub show_console() {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Sending console to front" );
|
2005-11-28 19:47:37 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$config{internal_previous_state} = "mid-change";
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# fudge the counter to drop a redraw event;
|
|
|
|
$config{internal_map_count} -= 4;
|
2005-11-28 19:47:37 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$xdisplay->flush();
|
|
|
|
$windows{main_window}->update();
|
2005-11-28 19:47:37 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
select( undef, undef, undef, 0.2 ); #sleep for a mo
|
|
|
|
$windows{main_window}->withdraw;
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# Sleep for a moment to give WM time to bring console back
|
|
|
|
select( undef, undef, undef, 0.5 );
|
2009-08-11 18:01:06 +01:00
|
|
|
|
|
|
|
if ( $config{menu_send_autotearoff} ) {
|
|
|
|
$menus{send}->menu->tearOffMenu()->raise;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( $config{menu_host_autotearoff} ) {
|
|
|
|
$menus{hosts}->menu->tearOffMenu()->raise;
|
|
|
|
}
|
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$windows{main_window}->deiconify;
|
|
|
|
$windows{main_window}->raise;
|
|
|
|
$windows{main_window}->focus( -force );
|
|
|
|
$windows{text_entry}->focus( -force );
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$config{internal_previous_state} = "normal";
|
2006-09-06 18:03:56 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# fvwm seems to need this (Debian #329440)
|
|
|
|
$windows{main_window}->MapWindow;
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2005-05-17 09:54:17 +00:00
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
# leave function def open here so we can be flexible in how it called
|
2007-11-26 11:11:10 +00:00
|
|
|
sub retile_hosts {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $force = shift || "";
|
|
|
|
logmsg( 2, "Retiling windows" );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{window_tiling} ne "yes" && !$force ) {
|
|
|
|
logmsg( 3,
|
|
|
|
"Not meant to be tiling; just reshow windows as they were" );
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach my $server ( reverse( keys(%servers) ) ) {
|
|
|
|
$xdisplay->req( 'MapWindow', $servers{$server}{wid} );
|
|
|
|
}
|
|
|
|
$xdisplay->flush();
|
|
|
|
show_console();
|
|
|
|
return;
|
2006-07-24 19:12:54 +00:00
|
|
|
}
|
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# ALL SIZES SHOULD BE IN PIXELS for consistency
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Count is currently $config{internal_total}" );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{internal_total} == 0 ) {
|
2005-11-28 19:47:37 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# If nothing to tile, done bother doing anything, just show console
|
|
|
|
show_console();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
# work out terminal pixel size from terminal size & font size
|
|
|
|
# does not include any title bars or scroll bars - purely text area
|
|
|
|
$config{internal_terminal_cols}
|
|
|
|
= ( $config{terminal_size} =~ /(\d+)x.*/ )[0];
|
|
|
|
$config{internal_terminal_width}
|
|
|
|
= ( $config{internal_terminal_cols} * $config{internal_font_width} )
|
|
|
|
+ $config{terminal_decoration_width};
|
|
|
|
|
|
|
|
$config{internal_terminal_rows}
|
|
|
|
= ( $config{terminal_size} =~ /.*x(\d+)/ )[0];
|
|
|
|
$config{internal_terminal_height}
|
|
|
|
= ( $config{internal_terminal_rows} * $config{internal_font_height} )
|
|
|
|
+ $config{terminal_decoration_height};
|
|
|
|
|
|
|
|
# fetch screen size
|
|
|
|
$config{internal_screen_height} = $xdisplay->{height_in_pixels};
|
|
|
|
$config{internal_screen_width} = $xdisplay->{width_in_pixels};
|
|
|
|
|
|
|
|
# Now, work out how many columns of terminals we can fit on screen
|
|
|
|
$config{internal_columns} = int(
|
|
|
|
( $config{internal_screen_width}
|
|
|
|
- $config{screen_reserve_left}
|
|
|
|
- $config{screen_reserve_right}
|
|
|
|
) / (
|
|
|
|
$config{internal_terminal_width}
|
|
|
|
+ $config{terminal_reserve_left}
|
|
|
|
+ $config{terminal_reserve_right}
|
2005-06-24 16:32:04 +00:00
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# Work out the number of rows we need to use to fit everything on screen
|
|
|
|
$config{internal_rows} = int(
|
|
|
|
( $config{internal_total} / $config{internal_columns} ) + 0.999 );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Screen Columns: ", $config{internal_columns} );
|
|
|
|
logmsg( 2, "Screen Rows: ", $config{internal_rows} );
|
2006-09-06 18:03:56 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# Now adjust the height of the terminal to either the max given,
|
|
|
|
# or to get everything on screen
|
|
|
|
{
|
|
|
|
my $height = int(
|
|
|
|
( ( $config{internal_screen_height}
|
|
|
|
- $config{screen_reserve_top}
|
|
|
|
- $config{screen_reserve_bottom}
|
|
|
|
) - (
|
|
|
|
$config{internal_rows} * (
|
|
|
|
$config{terminal_reserve_top}
|
|
|
|
+ $config{terminal_reserve_bottom}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
) / $config{internal_rows}
|
|
|
|
);
|
|
|
|
|
|
|
|
logmsg( 2, "Terminal height=$height" );
|
|
|
|
|
|
|
|
$config{internal_terminal_height} = (
|
|
|
|
$height > $config{internal_terminal_height}
|
|
|
|
? $config{internal_terminal_height}
|
|
|
|
: $height
|
|
|
|
);
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-04-22 18:16:58 +00:00
|
|
|
dump_config("noexit") if ( $options{debug} > 1 );
|
2006-09-06 18:03:56 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# now we have the info, plot first window position
|
|
|
|
my @hosts;
|
|
|
|
my ( $current_x, $current_y, $current_row, $current_col ) = 0;
|
2007-11-26 11:11:10 +00:00
|
|
|
if ( $config{window_tiling_direction} =~ /right/i ) {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Tiling top left going bot right" );
|
|
|
|
@hosts = sort( keys(%servers) );
|
|
|
|
$current_x
|
|
|
|
= $config{screen_reserve_left} + $config{terminal_reserve_left};
|
|
|
|
$current_y
|
|
|
|
= $config{screen_reserve_top} + $config{terminal_reserve_top};
|
|
|
|
$current_row = 0;
|
2005-06-24 16:32:04 +00:00
|
|
|
$current_col = 0;
|
2007-11-26 11:11:10 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Tiling bot right going top left" );
|
|
|
|
@hosts = reverse( sort( keys(%servers) ) );
|
|
|
|
$current_x
|
|
|
|
= $config{screen_reserve_right}
|
|
|
|
- $config{internal_screen_width}
|
|
|
|
- $config{terminal_reserve_right}
|
|
|
|
- $config{internal_terminal_width};
|
|
|
|
$current_y
|
|
|
|
= $config{screen_reserve_bottom}
|
|
|
|
- $config{internal_screen_height}
|
|
|
|
- $config{terminal_reserve_bottom}
|
|
|
|
- $config{internal_terminal_height};
|
|
|
|
|
|
|
|
$current_row = $config{internal_rows} - 1;
|
|
|
|
$current_col = $config{internal_columns} - 1;
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# Unmap windows (hide them)
|
|
|
|
# Move windows to new locatation
|
|
|
|
# Remap all windows in correct order
|
|
|
|
foreach my $server (@hosts) {
|
|
|
|
logmsg( 3,
|
|
|
|
"x:$current_x y:$current_y, r:$current_row c:$current_col" );
|
|
|
|
|
|
|
|
$xdisplay->req( 'UnmapWindow', $servers{$server}{wid} );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{unmap_on_redraw} =~ /yes/i ) {
|
|
|
|
$xdisplay->req( 'UnmapWindow', $servers{$server}{wid} );
|
|
|
|
}
|
|
|
|
|
|
|
|
logmsg( 2, "Moving $server window" );
|
|
|
|
send_resizemove(
|
|
|
|
$servers{$server}{wid},
|
|
|
|
$current_x, $current_y,
|
|
|
|
$config{internal_terminal_width},
|
|
|
|
$config{internal_terminal_height}
|
|
|
|
);
|
|
|
|
|
|
|
|
$xdisplay->flush();
|
|
|
|
select( undef, undef, undef, 0.1 ); # sleep for a moment for the WM
|
|
|
|
|
|
|
|
if ( $config{window_tiling_direction} =~ /right/i ) {
|
|
|
|
|
|
|
|
# starting top left, and move right and down
|
|
|
|
$current_x
|
|
|
|
+= $config{terminal_reserve_left}
|
|
|
|
+ $config{terminal_reserve_right}
|
|
|
|
+ $config{internal_terminal_width};
|
|
|
|
|
|
|
|
$current_col += 1;
|
|
|
|
if ( $current_col == $config{internal_columns} ) {
|
|
|
|
$current_y
|
|
|
|
+= $config{terminal_reserve_top}
|
|
|
|
+ $config{terminal_reserve_bottom}
|
|
|
|
+ $config{internal_terminal_height};
|
|
|
|
$current_x = $config{screen_reserve_left}
|
|
|
|
+ $config{terminal_reserve_left};
|
|
|
|
$current_row++;
|
|
|
|
$current_col = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
# starting bottom right, and move left and up
|
|
|
|
|
|
|
|
$current_col -= 1;
|
|
|
|
if ( $current_col < 0 ) {
|
|
|
|
$current_row--;
|
|
|
|
$current_col = $config{internal_columns};
|
|
|
|
}
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# Now remap in right order to get overlaps correct
|
|
|
|
if ( $config{window_tiling_direction} =~ /right/i ) {
|
|
|
|
foreach my $server ( reverse(@hosts) ) {
|
|
|
|
logmsg( 2, "Setting focus on $server" );
|
|
|
|
$xdisplay->req( 'MapWindow', $servers{$server}{wid} );
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# flush every time and wait a moment (The WMs are so slow...)
|
|
|
|
$xdisplay->flush();
|
|
|
|
select( undef, undef, undef, 0.1 ); # sleep for a mo
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2009-03-09 19:02:51 +00:00
|
|
|
else {
|
|
|
|
foreach my $server (@hosts) {
|
|
|
|
logmsg( 2, "Setting focus on $server" );
|
|
|
|
$xdisplay->req( 'MapWindow', $servers{$server}{wid} );
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# flush every time and wait a moment (The WMs are so slow...)
|
|
|
|
$xdisplay->flush();
|
|
|
|
select( undef, undef, undef, 0.1 ); # sleep for a mo
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# and as a last item, set focus back onto the console
|
|
|
|
show_console();
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub capture_terminal() {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 0, "Stub for capturing a terminal window" );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
return if ( $options{debug} < 6 );
|
2007-11-28 22:11:03 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# should never see this - all experimental anyhow
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach my $server ( keys(%servers) ) {
|
|
|
|
foreach my $data ( keys( %{ $servers{$server} } ) ) {
|
|
|
|
print "server $server key $data is $servers{$server}{$data}\n";
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
#return;
|
|
|
|
|
|
|
|
my %atoms;
|
|
|
|
|
|
|
|
for my $atom ( $xdisplay->req( 'ListProperties', $servers{loki}{wid} ) ) {
|
|
|
|
$atoms{ $xdisplay->atom_name($atom) }
|
|
|
|
= $xdisplay->req( 'GetProperty', $servers{loki}{wid},
|
|
|
|
$atom, "AnyPropertyType", 0, 200, 0 );
|
|
|
|
|
|
|
|
print $xdisplay->atom_name($atom), " ($atom) => ";
|
|
|
|
print "join here\n";
|
|
|
|
print join(
|
|
|
|
"\n",
|
|
|
|
$xdisplay->req(
|
|
|
|
'GetProperty', $servers{loki}{wid},
|
|
|
|
$atom, "AnyPropertyType", 0, 200, 0
|
|
|
|
)
|
|
|
|
),
|
|
|
|
"\n";
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
print "list by number\n";
|
|
|
|
for my $atom ( 1 .. 90 ) {
|
|
|
|
print "$atom: ", $xdisplay->req( 'GetAtomName', $atom ), "\n";
|
|
|
|
print join(
|
|
|
|
"\n",
|
|
|
|
$xdisplay->req(
|
|
|
|
'GetProperty', $servers{loki}{wid},
|
|
|
|
$atom, "AnyPropertyType", 0, 200, 0
|
|
|
|
)
|
|
|
|
),
|
|
|
|
"\n";
|
|
|
|
}
|
|
|
|
print "\n";
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
print "size hints\n";
|
2005-06-24 16:32:04 +00:00
|
|
|
print join(
|
2009-03-09 19:02:51 +00:00
|
|
|
"\n",
|
|
|
|
$xdisplay->req(
|
|
|
|
'GetProperty', $servers{loki}{wid},
|
|
|
|
42, "AnyPropertyType", 0, 200, 0
|
|
|
|
)
|
|
|
|
),
|
|
|
|
"\n";
|
|
|
|
|
|
|
|
print "atom list by name\n";
|
|
|
|
foreach ( keys(%atoms) ) {
|
|
|
|
print "atom :$_: = $atoms{$_}\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
print "geom\n";
|
|
|
|
print join " ", $xdisplay->req( 'GetGeometry', $servers{loki}{wid} ), $/;
|
|
|
|
print "attrib\n";
|
|
|
|
print join " ",
|
|
|
|
$xdisplay->req( 'GetWindowAttributes', $servers{loki}{wid} ),
|
|
|
|
$/;
|
2005-05-20 12:47:37 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub toggle_active_state() {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Toggling active state of all hosts" );
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach my $svr ( sort( keys(%servers) ) ) {
|
|
|
|
$servers{$svr}{active} = not $servers{$svr}{active};
|
|
|
|
}
|
2006-07-24 19:12:54 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub close_inactive_sessions() {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Closing all inactive sessions" );
|
2007-11-26 11:06:36 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach my $svr ( sort( keys(%servers) ) ) {
|
|
|
|
terminate_host($svr) if ( !$servers{$svr}{active} );
|
|
|
|
}
|
|
|
|
build_hosts_menu();
|
2007-11-26 11:06:36 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub add_host_by_name() {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Adding host to menu here" );
|
2005-05-05 15:22:06 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$windows{host_entry}->focus();
|
|
|
|
my $answer = $windows{addhost}->Show();
|
2005-05-05 15:22:06 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $answer ne "Add" ) {
|
|
|
|
$menus{host_entry} = "";
|
|
|
|
return;
|
|
|
|
}
|
2005-06-09 16:03:26 +00:00
|
|
|
|
2009-06-04 17:26:16 +00:00
|
|
|
if ( $menus{host_entry} ) {
|
|
|
|
logmsg( 2, "host=", $menus{host_entry} );
|
|
|
|
open_client_windows(
|
|
|
|
resolve_names( split( /\s+/, $menus{host_entry} ) ) );
|
|
|
|
}
|
2005-05-20 12:47:37 +00:00
|
|
|
|
2009-06-04 17:26:16 +00:00
|
|
|
if ( $menus{listbox}->curselection() ) {
|
|
|
|
my @hosts = $menus{listbox}->get( $menus{listbox}->curselection() );
|
|
|
|
logmsg( 2, "host=", join( ' ', @hosts ) );
|
|
|
|
open_client_windows( resolve_names(@hosts) );
|
|
|
|
}
|
2005-06-09 16:03:26 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
build_hosts_menu();
|
|
|
|
$menus{host_entry} = "";
|
2005-05-20 12:47:37 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# retile, or bring console to front
|
|
|
|
if ( $config{window_tiling} eq "yes" ) {
|
|
|
|
retile_hosts();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
show_console();
|
|
|
|
}
|
2005-05-05 15:22:06 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub build_hosts_menu() {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Building hosts menu" );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# first, empty the hosts menu from the 4th entry on
|
|
|
|
my $menu = $menus{bar}->entrycget( 'Hosts', -menu );
|
2009-04-22 18:58:24 +00:00
|
|
|
my $host_menu_static_items = 5;
|
|
|
|
$menu->delete( $host_menu_static_items, 'end' );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 3, "Menu deleted" );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# add back the seperator
|
|
|
|
$menus{hosts}->separator;
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 3, "Parsing list" );
|
2009-04-22 18:58:24 +00:00
|
|
|
|
|
|
|
my $menu_item_counter = $host_menu_static_items;
|
2009-03-09 19:02:51 +00:00
|
|
|
foreach my $svr ( sort( keys(%servers) ) ) {
|
|
|
|
logmsg( 3, "Checking $svr and restoring active value" );
|
2009-04-22 18:58:24 +00:00
|
|
|
my $colbreak = 0;
|
|
|
|
if ( $menu_item_counter > $config{max_host_menu_items} ) {
|
|
|
|
$colbreak = 1;
|
|
|
|
$menu_item_counter = 1;
|
|
|
|
}
|
2009-03-09 19:02:51 +00:00
|
|
|
$menus{hosts}->checkbutton(
|
2009-04-22 18:58:24 +00:00
|
|
|
-label => $svr,
|
|
|
|
-variable => \$servers{$svr}{active},
|
|
|
|
-columnbreak => $colbreak,
|
2009-03-09 19:02:51 +00:00
|
|
|
);
|
2009-04-22 18:58:24 +00:00
|
|
|
$menu_item_counter++;
|
2009-03-09 19:02:51 +00:00
|
|
|
}
|
|
|
|
logmsg( 3, "Changing window title" );
|
|
|
|
change_main_window_title();
|
|
|
|
logmsg( 2, "Done" );
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2005-05-20 12:47:37 +00:00
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub setup_repeat() {
|
2009-03-09 19:02:51 +00:00
|
|
|
$config{internal_count} = 0;
|
|
|
|
|
|
|
|
# if this is too fast then we end up with queued invocations
|
|
|
|
# with no time to run anything else
|
|
|
|
$windows{main_window}->repeat(
|
|
|
|
500,
|
|
|
|
sub {
|
|
|
|
$config{internal_count} = 0
|
|
|
|
if ( $config{internal_count} > 60000 ); # reset if too high
|
|
|
|
$config{internal_count}++;
|
|
|
|
my $build_menu = 0;
|
2009-04-22 19:07:32 +00:00
|
|
|
logmsg( 5, "Running repeat (count=$config{internal_count})" );
|
2009-03-09 19:02:51 +00:00
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
#logmsg( 3, "Number of servers in hash is: ", scalar( keys(%servers) ) );
|
2009-03-09 19:02:51 +00:00
|
|
|
|
|
|
|
foreach my $svr ( keys(%servers) ) {
|
|
|
|
if ( defined( $servers{$svr}{pid} ) ) {
|
|
|
|
if ( !kill( 0, $servers{$svr}{pid} ) ) {
|
|
|
|
$build_menu = 1;
|
|
|
|
delete( $servers{$svr} );
|
|
|
|
logmsg( 0, "$svr session closed" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
warn("Lost pid of $svr; deleting\n");
|
|
|
|
delete( $servers{$svr} );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# get current number of clients
|
|
|
|
$config{internal_total} = int( keys(%servers) );
|
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
#logmsg( 3, "Number after tidy is: ", $config{internal_total} );
|
2009-03-09 19:02:51 +00:00
|
|
|
|
|
|
|
# get current number of clients
|
|
|
|
$config{internal_total} = int( keys(%servers) );
|
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
#logmsg( 3, "Number after tidy is: ", $config{internal_total} );
|
2009-03-09 19:02:51 +00:00
|
|
|
|
|
|
|
# If there are no hosts in the list and we are set to autoquit
|
|
|
|
if ( $config{internal_total} == 0
|
|
|
|
&& $config{auto_quit} =~ /yes/i )
|
|
|
|
{
|
|
|
|
|
|
|
|
# and some clients were actually opened...
|
|
|
|
if ( $config{internal_activate_autoquit} ) {
|
|
|
|
logmsg( 2, "Autoquitting" );
|
|
|
|
exit_prog;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# rebuild host menu if something has changed
|
|
|
|
build_hosts_menu() if ($build_menu);
|
|
|
|
|
|
|
|
# clean out text area, anyhow
|
|
|
|
$menus{entrytext} = "";
|
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
#logmsg( 3, "repeat completed" );
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2009-03-09 19:02:51 +00:00
|
|
|
);
|
|
|
|
logmsg( 2, "Repeat setup" );
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2005-05-09 16:07:12 +00:00
|
|
|
|
2008-02-26 20:46:35 +00:00
|
|
|
sub write_default_user_config() {
|
2009-03-09 19:02:51 +00:00
|
|
|
return if ( !$ENV{HOME} || -e "$ENV{HOME}/.csshrc" );
|
2008-02-26 20:46:35 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( open( CONFIG, ">", "$ENV{HOME}/.csshrc" ) ) {
|
|
|
|
foreach ( sort( keys(%config) ) ) {
|
2008-02-26 20:46:35 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# do not output internal vars
|
|
|
|
next if ( $_ =~ /^internal/ );
|
|
|
|
print CONFIG "$_=$config{$_}\n";
|
|
|
|
}
|
|
|
|
close(CONFIG);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logmsg( 1, "Unable to write default $ENV{HOME}/.csshrc file" );
|
2008-02-26 20:46:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-06-24 16:32:04 +00:00
|
|
|
### Window and menu definitions ###
|
2005-05-09 16:07:12 +00:00
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub create_windows() {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "create_windows: started" );
|
|
|
|
$windows{main_window} = MainWindow->new( -title => "ClusterSSH" );
|
|
|
|
$windows{main_window}->withdraw; # leave withdrawn until needed
|
|
|
|
|
|
|
|
if ( defined( $config{console_position} )
|
|
|
|
&& $config{console_position} =~ /[+-]\d+[+-]\d+/ )
|
|
|
|
{
|
|
|
|
$windows{main_window}->geometry( $config{console_position} );
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$menus{entrytext} = "";
|
|
|
|
$windows{text_entry} = $windows{main_window}->Entry(
|
|
|
|
-textvariable => \$menus{entrytext},
|
|
|
|
-insertborderwidth => 4,
|
|
|
|
-width => 25,
|
|
|
|
)->pack(
|
|
|
|
-fill => "x",
|
|
|
|
-expand => 1,
|
|
|
|
);
|
|
|
|
|
|
|
|
$windows{history} = $windows{main_window}->Scrolled(
|
|
|
|
"ROText",
|
|
|
|
-insertborderwidth => 4,
|
|
|
|
-width => $config{history_width},
|
|
|
|
-height => $config{history_height},
|
|
|
|
-state => 'normal',
|
|
|
|
-takefocus => 0,
|
2007-11-28 22:11:03 +00:00
|
|
|
);
|
2009-03-09 19:02:51 +00:00
|
|
|
$windows{history}->bindtags(undef);
|
2007-11-28 22:11:03 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{show_history} ) {
|
|
|
|
$windows{history}->pack(
|
|
|
|
-fill => "x",
|
|
|
|
-expand => 1,
|
|
|
|
);
|
|
|
|
}
|
2005-11-28 19:47:37 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$windows{main_window}->bind( '<Destroy>' => \&exit_prog );
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# remove all Paste events so we set them up cleanly
|
|
|
|
$windows{main_window}->eventDelete('<<Paste>>');
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# Set up paste events from scratch
|
|
|
|
if ( $config{key_paste} && $config{key_paste} ne "null" ) {
|
|
|
|
$windows{main_window}
|
|
|
|
->eventAdd( '<<Paste>>' => '<' . $config{key_paste} . '>' );
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{mouse_paste} && $config{mouse_paste} ne "null" ) {
|
|
|
|
$windows{main_window}
|
|
|
|
->eventAdd( '<<Paste>>' => '<' . $config{mouse_paste} . '>' );
|
|
|
|
}
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$windows{main_window}->bind(
|
|
|
|
'<<Paste>>' => sub {
|
|
|
|
logmsg( 2, "PASTE EVENT" );
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$menus{entrytext} = "";
|
|
|
|
my $paste_text = '';
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# SelectionGet is fatal if no selection is given
|
2009-06-04 17:26:16 +00:00
|
|
|
Tk::catch {
|
|
|
|
$paste_text = $windows{main_window}->SelectionGet;
|
|
|
|
};
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( !length($paste_text) ) {
|
|
|
|
warn("Got empty paste event\n");
|
|
|
|
return;
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "Got text :", $paste_text, ":" );
|
2007-11-28 22:11:03 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
update_display_text($paste_text);
|
2005-05-05 15:22:06 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# now sent it on
|
|
|
|
foreach my $svr ( keys(%servers) ) {
|
|
|
|
send_text( $svr, $paste_text )
|
|
|
|
if ( $servers{$svr}{active} == 1 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$windows{help} = $windows{main_window}->Dialog(
|
|
|
|
-popover => $windows{main_window},
|
|
|
|
-overanchor => "c",
|
|
|
|
-popanchor => "c",
|
|
|
|
-font => [
|
|
|
|
-family => "interface system",
|
|
|
|
-size => 10,
|
|
|
|
],
|
|
|
|
-text =>
|
|
|
|
"Cluster Administrator Console using SSH\n\nVersion: $VERSION.\n\n"
|
|
|
|
. "Bug/Suggestions to http://clusterssh.sf.net/",
|
|
|
|
);
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$windows{manpage} = $windows{main_window}->DialogBox(
|
|
|
|
-popanchor => "c",
|
|
|
|
-overanchor => "c",
|
|
|
|
-title => "Cssh Documentation",
|
|
|
|
-buttons => ['Close'],
|
|
|
|
);
|
2005-05-11 14:19:14 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
my $manpage = `pod2text -l -q=\"\" $0`;
|
|
|
|
$windows{mantext}
|
|
|
|
= $windows{manpage}->Scrolled( "Text", )->pack( -fill => 'both' );
|
|
|
|
$windows{mantext}->insert( 'end', $manpage );
|
|
|
|
$windows{mantext}->configure( -state => 'disabled' );
|
|
|
|
|
|
|
|
$windows{addhost} = $windows{main_window}->DialogBox(
|
|
|
|
-popover => $windows{main_window},
|
|
|
|
-popanchor => 'n',
|
|
|
|
-title => "Add Host(s) or Cluster(s)",
|
|
|
|
-buttons => [ 'Add', 'Cancel' ],
|
|
|
|
-default_button => 'Add',
|
|
|
|
);
|
2005-05-20 12:47:37 +00:00
|
|
|
|
2009-06-04 17:26:16 +00:00
|
|
|
if ( $config{max_addhost_menu_cluster_items}
|
|
|
|
&& scalar keys %clusters )
|
|
|
|
{
|
|
|
|
if ( scalar keys %clusters < $config{max_addhost_menu_cluster_items} )
|
|
|
|
{
|
|
|
|
$menus{listbox} = $windows{addhost}->Listbox(
|
|
|
|
-selectmode => 'extended',
|
|
|
|
-height => scalar keys %clusters,
|
|
|
|
)->pack();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$menus{listbox} = $windows{addhost}->Scrolled(
|
|
|
|
'Listbox',
|
|
|
|
-scrollbars => 'e',
|
|
|
|
-selectmode => 'extended',
|
|
|
|
-height => $config{max_addhost_menu_cluster_items},
|
|
|
|
)->pack();
|
|
|
|
}
|
|
|
|
$menus{listbox}->insert( 'end', sort keys %clusters );
|
|
|
|
}
|
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
$windows{host_entry} = $windows{addhost}->add(
|
|
|
|
'LabEntry',
|
|
|
|
-textvariable => \$menus{host_entry},
|
|
|
|
-width => 20,
|
|
|
|
-label => 'Host',
|
|
|
|
-labelPack => [ -side => 'left', ],
|
|
|
|
)->pack( -side => 'left' );
|
|
|
|
logmsg( 2, "create_windows: completed" );
|
|
|
|
}
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
sub capture_map_events() {
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
# pick up on console minimise/maximise events so we can do all windows
|
|
|
|
$windows{main_window}->bind(
|
|
|
|
'<Map>' => sub {
|
|
|
|
logmsg( 3, "Entering MAP" );
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
my $state = $windows{main_window}->state();
|
|
|
|
logmsg( 3,
|
|
|
|
"state=$state previous=$config{internal_previous_state}" );
|
|
|
|
logmsg( 3, "Entering MAP" );
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{internal_previous_state} eq $state ) {
|
|
|
|
logmsg( 3, "repeating the same" );
|
|
|
|
}
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{internal_previous_state} eq "mid-change" ) {
|
|
|
|
logmsg( 3, "dropping out as mid-change" );
|
|
|
|
return;
|
|
|
|
}
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 3,
|
|
|
|
"state=$state previous=$config{internal_previous_state}" );
|
2005-06-09 16:03:26 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{internal_previous_state} eq "iconic" ) {
|
|
|
|
logmsg( 3, "running retile" );
|
2005-06-09 16:03:26 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
retile_hosts();
|
2005-05-05 15:22:06 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 3, "done with retile" );
|
|
|
|
}
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:02:51 +00:00
|
|
|
if ( $config{internal_previous_state} ne $state ) {
|
|
|
|
logmsg( 3, "resetting prev_state" );
|
|
|
|
$config{internal_previous_state} = $state;
|
|
|
|
}
|
2006-07-24 19:12:54 +00:00
|
|
|
}
|
2009-03-09 19:02:51 +00:00
|
|
|
);
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-06-04 17:26:16 +00:00
|
|
|
# $windows{main_window}->bind(
|
|
|
|
# '<Unmap>' => sub {
|
|
|
|
# logmsg( 3, "Entering UNMAP" );
|
|
|
|
#
|
|
|
|
# my $state = $windows{main_window}->state();
|
|
|
|
# logmsg( 3,
|
|
|
|
# "state=$state previous=$config{internal_previous_state}" );
|
|
|
|
#
|
|
|
|
# if ( $config{internal_previous_state} eq $state ) {
|
|
|
|
# logmsg( 3, "repeating the same" );
|
|
|
|
# }
|
|
|
|
#
|
|
|
|
# if ( $config{internal_previous_state} eq "mid-change" ) {
|
|
|
|
# logmsg( 3, "dropping out as mid-change" );
|
|
|
|
# return;
|
|
|
|
# }
|
|
|
|
#
|
|
|
|
# if ( $config{internal_previous_state} eq "normal" ) {
|
|
|
|
# logmsg( 3, "withdrawing all windows" );
|
|
|
|
# foreach my $server ( reverse( keys(%servers) ) ) {
|
|
|
|
# $xdisplay->req( 'UnmapWindow', $servers{$server}{wid} );
|
|
|
|
# if ( $config{unmap_on_redraw} =~ /yes/i ) {
|
|
|
|
# $xdisplay->req( 'UnmapWindow',
|
|
|
|
# $servers{$server}{wid} );
|
|
|
|
# }
|
|
|
|
# }
|
|
|
|
# $xdisplay->flush();
|
|
|
|
# }
|
|
|
|
#
|
|
|
|
# if ( $config{internal_previous_state} ne $state ) {
|
|
|
|
# logmsg( 3, "resetting prev_state" );
|
|
|
|
# $config{internal_previous_state} = $state;
|
|
|
|
# }
|
|
|
|
# }
|
|
|
|
# );
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# for all key event, event hotkeys so there is only 1 key binding
|
2007-11-26 11:11:10 +00:00
|
|
|
sub key_event {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $event = $Tk::event->T;
|
|
|
|
my $keycode = $Tk::event->k;
|
|
|
|
my $keysymdec = $Tk::event->N;
|
|
|
|
my $keysym = $Tk::event->K;
|
|
|
|
my $state = $Tk::event->s || 0;
|
|
|
|
|
|
|
|
$menus{entrytext} = "";
|
|
|
|
|
|
|
|
logmsg( 3, "=========" );
|
|
|
|
logmsg( 3, "event =$event" );
|
|
|
|
logmsg( 3, "keysym =$keysym (state=$state)" );
|
|
|
|
logmsg( 3, "keysymdec=$keysymdec" );
|
|
|
|
logmsg( 3, "keycode =$keycode" );
|
|
|
|
logmsg( 3, "state =$state" );
|
|
|
|
logmsg( 3, "codetosym=$keycodetosym{$keysymdec}" )
|
|
|
|
if ( $keycodetosym{$keysymdec} );
|
|
|
|
logmsg( 3, "symtocode=$keysymtocode{$keysym}" );
|
|
|
|
logmsg( 3, "keyboard =$keyboardmap{ $keysym }" )
|
|
|
|
if ( $keyboardmap{$keysym} );
|
|
|
|
|
|
|
|
#warn("debug stop point here");
|
|
|
|
if ( $config{use_hotkeys} eq "yes" ) {
|
|
|
|
my $combo = $Tk::event->s . $Tk::event->K;
|
|
|
|
|
|
|
|
$combo =~ s/Mod\d-//;
|
|
|
|
|
|
|
|
logmsg( 3, "combo=$combo" );
|
|
|
|
|
|
|
|
foreach my $hotkey ( grep( /key_/, keys(%config) ) ) {
|
|
|
|
my $key = $config{$hotkey};
|
|
|
|
next if ( $key eq "null" ); # ignore disabled keys
|
|
|
|
|
|
|
|
logmsg( 3, "key=:$key:" );
|
|
|
|
if ( $combo =~ /^$key$/ ) {
|
|
|
|
if ( $event eq "KeyRelease" ) {
|
|
|
|
logmsg( 2, "Received hotkey: $hotkey" );
|
2009-08-18 21:13:36 +01:00
|
|
|
send_text_to_all_servers('%s')
|
2009-06-04 17:26:16 +00:00
|
|
|
if ( $hotkey eq "key_clientname" );
|
|
|
|
add_host_by_name()
|
|
|
|
if ( $hotkey eq "key_addhost" );
|
|
|
|
retile_hosts("force")
|
|
|
|
if ( $hotkey eq "key_retilehosts" );
|
|
|
|
show_history() if ( $hotkey eq "key_history" );
|
|
|
|
exit_prog() if ( $hotkey eq "key_quit" );
|
2009-03-09 19:02:51 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
|
|
|
}
|
2009-03-09 19:02:51 +00:00
|
|
|
|
|
|
|
# look for a <Control>-d and no hosts, so quit
|
2009-06-04 17:26:16 +00:00
|
|
|
exit_prog()
|
|
|
|
if ( $state =~ /Control/ && $keysym eq "d" and !%servers );
|
2009-03-09 19:02:51 +00:00
|
|
|
|
|
|
|
update_display_text( $keycodetosym{$keysymdec} )
|
|
|
|
if ( $event eq "KeyPress" && $keycodetosym{$keysymdec} );
|
|
|
|
|
|
|
|
# for all servers
|
|
|
|
foreach ( keys(%servers) ) {
|
|
|
|
|
|
|
|
# if active
|
|
|
|
if ( $servers{$_}{active} == 1 ) {
|
|
|
|
logmsg( 3,
|
|
|
|
"Sending event $event with code $keycode (state=$state) to window $servers{$_}{wid}"
|
|
|
|
);
|
|
|
|
|
|
|
|
$xdisplay->SendEvent(
|
|
|
|
$servers{$_}{wid},
|
|
|
|
0,
|
|
|
|
$xdisplay->pack_event_mask($event),
|
|
|
|
$xdisplay->pack_event(
|
|
|
|
'name' => $event,
|
|
|
|
'detail' => $keycode,
|
|
|
|
'state' => $state,
|
|
|
|
'time' => time(),
|
|
|
|
'event' => $servers{$_}{wid},
|
|
|
|
'root' => $xdisplay->root(),
|
|
|
|
'same_screen' => 1,
|
|
|
|
)
|
|
|
|
) || warn("Error returned from SendEvent: $!");
|
|
|
|
}
|
2005-06-24 16:32:04 +00:00
|
|
|
}
|
2009-03-09 19:02:51 +00:00
|
|
|
$xdisplay->flush();
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
sub create_menubar() {
|
2009-03-09 19:02:51 +00:00
|
|
|
logmsg( 2, "create_menubar: started" );
|
|
|
|
$menus{bar} = $windows{main_window}->Menu;
|
|
|
|
$windows{main_window}->configure( -menu => $menus{bar} );
|
|
|
|
|
|
|
|
$menus{file} = $menus{bar}->cascade(
|
|
|
|
-label => 'File',
|
|
|
|
-menuitems => [
|
|
|
|
[ "command",
|
|
|
|
"Show History",
|
|
|
|
-command => \&show_history,
|
|
|
|
-accelerator => $config{key_history},
|
|
|
|
],
|
|
|
|
[ "command",
|
|
|
|
"Exit",
|
|
|
|
-command => \&exit_prog,
|
|
|
|
-accelerator => $config{key_quit},
|
|
|
|
]
|
|
|
|
],
|
|
|
|
-tearoff => 0,
|
|
|
|
);
|
|
|
|
|
|
|
|
$menus{hosts} = $menus{bar}->cascade(
|
|
|
|
-label => 'Hosts',
|
|
|
|
-tearoff => 1,
|
|
|
|
-menuitems => [
|
|
|
|
[ "command",
|
|
|
|
"Retile Windows",
|
|
|
|
-command => \&retile_hosts,
|
|
|
|
-accelerator => $config{key_retilehosts},
|
|
|
|
],
|
2008-02-26 20:46:35 +00:00
|
|
|
|
|
|
|
# [ "command", "Capture Terminal", -command => \&capture_terminal, ],
|
2009-03-09 19:02:51 +00:00
|
|
|
[ "command",
|
|
|
|
"Toggle active state",
|
|
|
|
-command => \&toggle_active_state,
|
|
|
|
],
|
|
|
|
[ "command",
|
|
|
|
"Close inactive sessions",
|
|
|
|
-command => \&close_inactive_sessions,
|
|
|
|
],
|
|
|
|
[ "command",
|
|
|
|
"Add Host(s) or Cluster(s)",
|
|
|
|
-command => \&add_host_by_name,
|
|
|
|
-accelerator => $config{key_addhost},
|
|
|
|
],
|
|
|
|
'',
|
|
|
|
],
|
|
|
|
);
|
|
|
|
|
2009-08-24 22:23:41 +01:00
|
|
|
$menus{send} = $menus{bar}->cascade(
|
|
|
|
-label => 'Send',
|
|
|
|
-tearoff => 1,
|
|
|
|
);
|
|
|
|
|
|
|
|
populate_send_menu();
|
2009-03-09 19:02:51 +00:00
|
|
|
|
|
|
|
$menus{help} = $menus{bar}->cascade(
|
|
|
|
-label => 'Help',
|
|
|
|
-menuitems => [
|
|
|
|
[ 'command', "About", -command => sub { $windows{help}->Show } ],
|
|
|
|
[ 'command', "Documentation",
|
|
|
|
-command => sub { $windows{manpage}->Show }
|
|
|
|
],
|
|
|
|
],
|
|
|
|
-tearoff => 0,
|
|
|
|
);
|
|
|
|
|
|
|
|
#$windows{main_window}->bind(
|
|
|
|
#'<Key>' => \&key_event,
|
|
|
|
#);
|
|
|
|
$windows{main_window}->bind( '<KeyPress>' => \&key_event, );
|
|
|
|
$windows{main_window}->bind( '<KeyRelease>' => \&key_event, );
|
|
|
|
logmsg( 2, "create_menubar: completed" );
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2009-08-24 22:23:41 +01:00
|
|
|
sub populate_send_menu_entries_from_xml {
|
|
|
|
my ( $menu, $menu_xml ) = @_;
|
2009-08-18 21:13:36 +01:00
|
|
|
|
|
|
|
foreach my $menu_ref ( @{ $menu_xml->{menu} } ) {
|
|
|
|
if ( $menu_ref->{menu} ) {
|
2009-08-24 22:23:41 +01:00
|
|
|
$menus{ $menu_ref->{title} }
|
|
|
|
= $menu->cascade( -label => $menu_ref->{title}, );
|
2009-09-17 19:07:29 +01:00
|
|
|
populate_send_menu_entries_from_xml( $menus{ $menu_ref->{title} },
|
|
|
|
$menu_ref, );
|
2009-08-24 22:23:41 +01:00
|
|
|
if ( $menu_ref->{detach} && $menu_ref->{detach} =~ m/y/i ) {
|
|
|
|
$menus{ $menu_ref->{title} }->menu->tearOffMenu()->raise;
|
|
|
|
}
|
2009-08-18 21:13:36 +01:00
|
|
|
}
|
|
|
|
else {
|
2009-08-24 22:23:41 +01:00
|
|
|
my $command = undef;
|
|
|
|
my $accelerator = undef;
|
2009-08-18 21:13:36 +01:00
|
|
|
if ( $menu_ref->{command} ) {
|
2009-08-24 22:23:41 +01:00
|
|
|
$command = sub {
|
|
|
|
send_text_to_all_servers( $menu_ref->{command}[0] );
|
|
|
|
};
|
2009-08-18 21:13:36 +01:00
|
|
|
}
|
|
|
|
if ( $menu_ref->{accelerator} ) {
|
2009-08-24 22:23:41 +01:00
|
|
|
$accelerator = $menu_ref->{accelerator};
|
2009-08-18 21:13:36 +01:00
|
|
|
}
|
2009-08-24 22:23:41 +01:00
|
|
|
$menu->command(
|
|
|
|
-label => $menu_ref->{title},
|
|
|
|
-command => $command,
|
|
|
|
-accelerator => $accelerator,
|
|
|
|
);
|
2009-08-18 21:13:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-24 22:23:41 +01:00
|
|
|
return;
|
2009-08-18 21:13:36 +01:00
|
|
|
}
|
|
|
|
|
2009-08-24 22:23:41 +01:00
|
|
|
sub populate_send_menu {
|
|
|
|
|
|
|
|
# my @menu_items = ();
|
2009-08-18 21:13:36 +01:00
|
|
|
if ( !-r $config{send_menu_xml_file} ) {
|
|
|
|
logmsg( 2, 'Using default send menu' );
|
|
|
|
|
2009-08-24 22:23:41 +01:00
|
|
|
$menus{send}->command(
|
|
|
|
-label => 'Hostname',
|
|
|
|
-command => [ \&send_text_to_all_servers, '%s' ],
|
|
|
|
-accelerator => $config{key_clientname},
|
|
|
|
);
|
2009-08-18 21:13:36 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
logmsg(
|
|
|
|
2,
|
|
|
|
'Using xml send menu definition from ',
|
|
|
|
$config{send_menu_xml_file}
|
|
|
|
);
|
|
|
|
|
|
|
|
eval { require XML::Simple; };
|
|
|
|
die 'Cannot load XML::Simple - has it been installed? ', $@ if ($@);
|
|
|
|
|
|
|
|
my $xml = XML::Simple->new( ForceArray => 1, );
|
2009-09-17 19:07:29 +01:00
|
|
|
my $menu_xml = $xml->XMLin( $config{send_menu_xml_file} );
|
|
|
|
|
|
|
|
logmsg( 3, 'xml send menu: ', $/, $xml->XMLout($menu_xml) );
|
2009-08-18 21:13:36 +01:00
|
|
|
|
2009-09-17 19:07:29 +01:00
|
|
|
if ( $menu_xml->{detach} && $menu_xml->{detach} =~ m/y/i ) {
|
|
|
|
$menus{send}->menu->tearOffMenu()->raise;
|
|
|
|
}
|
2009-08-18 21:13:36 +01:00
|
|
|
|
2009-09-17 19:07:29 +01:00
|
|
|
populate_send_menu_entries_from_xml( $menus{send}, $menu_xml );
|
2009-08-18 21:13:36 +01:00
|
|
|
}
|
|
|
|
|
2009-08-24 22:23:41 +01:00
|
|
|
return;
|
2009-08-18 21:13:36 +01:00
|
|
|
}
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
### main ###
|
|
|
|
|
|
|
|
# Note: getopts returned "" if it finds any options it doesnt recognise
|
|
|
|
# so use this to print out basic help
|
2009-06-04 17:26:16 +00:00
|
|
|
pod2usage( -verbose => 1 )
|
|
|
|
if ( !GetOptions( \%options, @options_spec ) );
|
2009-04-21 20:14:00 +00:00
|
|
|
pod2usage( -verbose => 1 ) if ( $options{'?'} || $options{help} );
|
2009-04-22 18:16:58 +00:00
|
|
|
pod2usage( -verbose => 2 ) if ( $options{H} || $options{man} );
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
if ( $options{version} ) {
|
2009-03-09 19:02:51 +00:00
|
|
|
print "Version: $VERSION\n";
|
|
|
|
exit 0;
|
2005-04-25 14:57:28 +00:00
|
|
|
}
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
$options{debug} ||= 0;
|
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
# only get xdisplay if we got past usage and help stuff
|
|
|
|
$xdisplay = X11::Protocol->new();
|
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
if ( !$xdisplay ) {
|
2009-03-09 19:02:51 +00:00
|
|
|
die("Failed to get X connection\n");
|
2006-07-24 19:12:54 +00:00
|
|
|
}
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
# catch and reap any zombies
|
2007-11-26 11:11:10 +00:00
|
|
|
sub REAPER {
|
2009-03-09 19:02:51 +00:00
|
|
|
my $kid;
|
|
|
|
do {
|
|
|
|
$kid = waitpid( -1, WNOHANG );
|
|
|
|
logmsg( 2, "REAPER currently returns: $kid" );
|
|
|
|
} until ( $kid == -1 || $kid == 0 );
|
2005-04-26 11:43:10 +00:00
|
|
|
}
|
2005-04-25 14:57:28 +00:00
|
|
|
$SIG{CHLD} = \&REAPER;
|
|
|
|
|
2009-04-22 18:16:58 +00:00
|
|
|
if ( $options{d} && $options{D} ) {
|
2009-04-21 20:14:00 +00:00
|
|
|
$options{debug} += 3;
|
2009-04-22 18:16:58 +00:00
|
|
|
logmsg( 0, 'NOTE: -d and -D are deprecated - use "--debug 3" instead' );
|
|
|
|
}
|
|
|
|
elsif ( $options{d} ) {
|
2009-04-21 20:14:00 +00:00
|
|
|
$options{debug} += 1;
|
2009-04-22 18:16:58 +00:00
|
|
|
logmsg( 0, 'NOTE: -d is deprecated - use "--debug 1" instead' );
|
|
|
|
}
|
|
|
|
elsif ( $options{D} ) {
|
2009-04-21 20:14:00 +00:00
|
|
|
$options{debug} += 2;
|
2009-04-22 18:16:58 +00:00
|
|
|
logmsg( 0, 'NOTE: -D is deprecated - use "--debug 2" instead' );
|
2009-04-21 20:14:00 +00:00
|
|
|
}
|
2007-11-26 11:11:10 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
# restrict to max level
|
2009-04-22 18:16:58 +00:00
|
|
|
$options{debug} = 4 if ( $options{debug} && $options{debug} > 4 );
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2007-11-26 11:11:10 +00:00
|
|
|
logmsg( 2, "VERSION: $VERSION" );
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
load_config_defaults();
|
2005-05-05 15:22:06 +00:00
|
|
|
load_configfile();
|
2009-04-21 20:14:00 +00:00
|
|
|
|
|
|
|
dump_config() if ( $options{'output-config'} );
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2008-01-23 22:18:33 +00:00
|
|
|
check_ssh_hostnames();
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
evaluate_commands() if ( $options{evaluate} );
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
load_keyboard_map();
|
|
|
|
|
|
|
|
get_clusters();
|
|
|
|
|
2009-06-02 14:40:27 +00:00
|
|
|
if (@ARGV) {
|
|
|
|
@servers = resolve_names(@ARGV);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ( $clusters{default} ) {
|
|
|
|
@servers = resolve_names( split( /\s+/, $clusters{default} ) );
|
|
|
|
}
|
|
|
|
}
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
create_windows();
|
|
|
|
create_menubar();
|
|
|
|
|
|
|
|
change_main_window_title();
|
|
|
|
|
2005-11-28 19:47:37 +00:00
|
|
|
logmsg( 2, "Capture map events" );
|
|
|
|
capture_map_events();
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
setup_helper_script();
|
|
|
|
open_client_windows(@servers);
|
|
|
|
|
2005-11-28 19:47:37 +00:00
|
|
|
# Check here if we are tiling windows. Here instead of in func so
|
2005-05-05 15:22:06 +00:00
|
|
|
# can be tiled from console window if wanted
|
2007-11-26 11:11:10 +00:00
|
|
|
if ( $config{window_tiling} eq "yes" ) {
|
2009-03-09 19:02:51 +00:00
|
|
|
retile_hosts();
|
2007-11-26 11:11:10 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-03-09 19:02:51 +00:00
|
|
|
show_console();
|
2005-11-28 19:47:37 +00:00
|
|
|
}
|
2005-05-05 15:22:06 +00:00
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
build_hosts_menu();
|
|
|
|
|
2005-06-24 16:32:04 +00:00
|
|
|
logmsg( 2, "Sleeping for a mo" );
|
2005-11-28 19:47:37 +00:00
|
|
|
select( undef, undef, undef, 0.5 );
|
2005-04-26 11:43:10 +00:00
|
|
|
|
2005-06-24 16:32:04 +00:00
|
|
|
logmsg( 2, "Sorting focus on console" );
|
2005-04-25 14:57:28 +00:00
|
|
|
$windows{text_entry}->focus();
|
2005-04-26 11:43:10 +00:00
|
|
|
|
2005-11-28 19:47:37 +00:00
|
|
|
logmsg( 2, "Marking main window as user positioned" );
|
2007-11-26 11:11:10 +00:00
|
|
|
$windows{main_window}->positionfrom('user')
|
2009-03-09 19:02:51 +00:00
|
|
|
; # user puts it somewhere, leave it there
|
2005-06-24 16:32:04 +00:00
|
|
|
|
|
|
|
logmsg( 2, "Setting up repeat" );
|
2005-04-26 11:43:10 +00:00
|
|
|
setup_repeat();
|
|
|
|
|
2008-02-26 20:46:35 +00:00
|
|
|
logmsg( 2, "Writing default user configuration" );
|
|
|
|
write_default_user_config();
|
|
|
|
|
2005-05-20 12:47:37 +00:00
|
|
|
# Start event loop
|
2005-06-24 16:32:04 +00:00
|
|
|
logmsg( 2, "Starting MainLoop" );
|
2005-04-25 14:57:28 +00:00
|
|
|
MainLoop();
|
|
|
|
|
|
|
|
# make sure we leave program in an expected way
|
2005-11-28 19:47:37 +00:00
|
|
|
exit_prog();
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-03 19:50:07 +00:00
|
|
|
# man/perldoc/pod page
|
2005-04-25 14:57:28 +00:00
|
|
|
__END__
|
2009-03-09 19:56:27 +00:00
|
|
|
|
|
|
|
=pod
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=head1 NAME
|
|
|
|
|
2009-04-03 19:45:52 +00:00
|
|
|
cssh, crsh, ctel - Cluster administration tool
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
S<< cssh [options] [[user@]<server>[:port]|<tag>] [...] >>
|
|
|
|
S<< crsh [options] [[user@]<server>[:port]|<tag>] [...] >>
|
2009-04-06 19:40:13 +00:00
|
|
|
S<< ctel [options] [<server>[:port]|<tag>] [...] >>
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
The command opens an administration console and an xterm to all specified
|
|
|
|
hosts. Any text typed into the administration console is replicated to
|
|
|
|
all windows. All windows may also be typed into directly.
|
|
|
|
|
|
|
|
This tool is intended for (but not limited to) cluster administration where
|
|
|
|
the same configuration or commands must be run on each node within the
|
|
|
|
cluster. Performing these commands all at once via this tool ensures all
|
|
|
|
nodes are kept in sync.
|
|
|
|
|
|
|
|
Connections are opened via ssh so a correctly installed and configured
|
|
|
|
ssh installation is required. If, however, the program is called by "crsh"
|
2007-10-25 12:08:15 +00:00
|
|
|
then the rsh protocol is used (and the communications channel is insecure),
|
|
|
|
or by "ctel" then telnet is used.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
Extra caution should be taken when editing system files such as
|
|
|
|
/etc/inet/hosts as lines may not necessarily be in the same order. Assuming
|
|
|
|
line 5 is the same across all servers and modifying that is dangerous.
|
|
|
|
Better to search for the specific line to be changed and double-check before
|
|
|
|
changes are committed.
|
|
|
|
|
|
|
|
=head2 Further Notes
|
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
Please also see L<KNOWN BUGS>.
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=over
|
|
|
|
|
|
|
|
=item *
|
|
|
|
|
|
|
|
The dotted line on any sub-menu is a tear-off, i.e. click on it
|
|
|
|
and the sub-menu is turned into its own window.
|
|
|
|
|
|
|
|
=item *
|
|
|
|
|
|
|
|
Unchecking a hostname on the Hosts sub-menu will unplug the host from the
|
|
|
|
cluster control window, so any text typed into the console is not sent to
|
|
|
|
that host. Re-selecting it will plug it back in.
|
|
|
|
|
|
|
|
=item *
|
|
|
|
|
2009-04-15 21:47:41 +00:00
|
|
|
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">).
|
|
|
|
|
|
|
|
=item *
|
|
|
|
|
|
|
|
If the terminals overlap too much see the C<terminal_reserve_XXXXX>
|
|
|
|
options in the F<csshrc> file (see L<"FILES">).
|
|
|
|
|
|
|
|
=item *
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
If the code is called as crsh instead of cssh (i.e. a symlink called
|
|
|
|
crsh points to the cssh file or the file is renamed) rsh is used as the
|
2006-07-24 19:12:54 +00:00
|
|
|
communications protocol instead of ssh.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2005-06-09 16:03:26 +00:00
|
|
|
=item *
|
|
|
|
|
2007-10-25 12:08:15 +00:00
|
|
|
If the code is called as ctel instead of cssh (i.e. a symlink called
|
|
|
|
ctel points to the cssh file or the file is renamed) telnet is used as the
|
|
|
|
communications protocol instead of ssh.
|
|
|
|
|
|
|
|
=item *
|
|
|
|
|
2005-06-09 16:03:26 +00:00
|
|
|
When using cssh on a large number of systems to connect back to a single
|
|
|
|
system (e.g. you issue a command to the cluster to scp a file from a given
|
|
|
|
location) and when these connections require authentication (i.e. you are
|
|
|
|
going to authenticate with a password), the sshd daemon at that location
|
|
|
|
may refuse connects after the number specified by MaxStartups in
|
|
|
|
sshd_config is exceeded. (If this value is not set, it defaults to 10.)
|
|
|
|
This is expected behavior; sshd uses this mechanism to prevent DoS attacks
|
|
|
|
from unauthenticated sources. Please tune sshd_config and reload the SSH
|
|
|
|
daemon, or consider using the ~/.ssh/authorized_keys mechanism for
|
|
|
|
authentication if you encounter this problem.
|
|
|
|
|
2005-11-28 19:47:37 +00:00
|
|
|
=item *
|
|
|
|
|
2007-11-26 11:06:36 +00:00
|
|
|
If client windows fail to open, try running:
|
|
|
|
|
|
|
|
C<< cssh -e {single host name} >>
|
|
|
|
|
|
|
|
This will test the mechanisms used to open windows to hosts. This could
|
|
|
|
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).
|
2005-11-28 19:47:37 +00:00
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=back
|
|
|
|
|
|
|
|
=head1 OPTIONS
|
|
|
|
|
2005-06-09 16:03:26 +00:00
|
|
|
Some of these options may also be defined within the configuration file.
|
|
|
|
Default options are shown as appropriate.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
=over
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --action,-a '<command>'
|
2009-04-15 17:35:22 +00:00
|
|
|
|
|
|
|
Run the command in each session, i.e. C<-a 'vi /etc/hosts'> to drop straight
|
|
|
|
into a vi session. NOTE: not all communications methods support this (ssh
|
|
|
|
and rsh should, telnet will not).
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --cluster-file,-c <file>
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:56:27 +00:00
|
|
|
Use supplied file as additional cluster file (see also L<"FILES">)
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --config-file,-C <file>
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:56:27 +00:00
|
|
|
Use supplied file as additional configuration file (see also L<"FILES">)
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
=item -d
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
DEPRECATED. See '--debug'.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
=item -D
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
DEPRECATED. See '--debug'.
|
|
|
|
|
|
|
|
=item --debug [number].
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
Enable debugging. Either a level can be provided or the option can be
|
|
|
|
repeated multiple times. Maximum level is 4.
|
|
|
|
|
|
|
|
=item --evaluate,-e [user@]<hostname>[:port]
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-03-09 19:56:27 +00:00
|
|
|
Display and evaluate the terminal and connection arguments so display any
|
|
|
|
potential errors. The <hostname> is required to aid the evaluation.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --tile,-g|--no-tile,-G
|
2005-05-03 13:58:38 +00:00
|
|
|
|
2005-11-28 19:47:37 +00:00
|
|
|
Enable|Disable window tiling (overriding the config file)
|
2005-05-03 13:58:38 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --help,-h|-?
|
2005-06-09 16:03:26 +00:00
|
|
|
|
2009-03-09 19:56:27 +00:00
|
|
|
Show basic help text, and exit
|
2005-06-09 16:03:26 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --man,-H
|
2008-02-26 20:05:54 +00:00
|
|
|
|
2009-03-09 19:56:27 +00:00
|
|
|
Show full help test (the man page), and exit
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --username,-l $LOGNAME
|
2005-06-09 16:03:26 +00:00
|
|
|
|
|
|
|
Specify the default username to use for connections (if different from the
|
2007-12-17 19:05:16 +00:00
|
|
|
currently logged in user). B<NOTE:> will be overridden by <user>@<host>
|
2005-06-09 16:03:26 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --options,-o "-x -o ConnectTimeout=10" - for ssh connections
|
2005-06-09 16:03:26 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --options,-o "" - for rsh connections
|
2005-06-09 16:03:26 +00:00
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
Specify arguments to be passed to ssh or rsh when making the connection.
|
|
|
|
|
2007-12-17 19:05:16 +00:00
|
|
|
B<NOTE:> any "generic" change to the method (i.e. specifying the ssh port to use)
|
2006-07-24 19:12:54 +00:00
|
|
|
should be done in the medium's own config file (see L<ssh_config> and
|
|
|
|
F<$HOME/.ssh/config>).
|
2005-06-09 16:03:26 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --port,-p <port>
|
2009-03-10 09:37:53 +00:00
|
|
|
|
|
|
|
Specify an alternate port for connections.
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --autoquit,-q|--no-autoquit,-Q
|
2009-03-09 19:56:27 +00:00
|
|
|
|
|
|
|
Enable|Disable automatically quiting after the last client window has closed
|
|
|
|
(overriding the config file)
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --show-history,-s
|
2007-11-28 22:11:03 +00:00
|
|
|
|
|
|
|
IN BETA: Show history within console window. This code is still being
|
|
|
|
worked upon, but may help some users.
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --term-args,-t ""
|
2005-06-09 16:03:26 +00:00
|
|
|
|
|
|
|
Specify arguments to be passed to terminals being used
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --title,-T "CSSH"
|
2005-06-13 13:56:24 +00:00
|
|
|
|
2009-03-09 19:56:27 +00:00
|
|
|
Specify the initial part of the title used in the console and client windows
|
2005-06-13 13:56:24 +00:00
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --output-config,-u
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-03-09 19:56:27 +00:00
|
|
|
Output the current configuration in the same format used by the
|
|
|
|
F<$HOME/.csshrc> file.
|
|
|
|
|
2009-04-21 20:14:00 +00:00
|
|
|
=item --version,-v
|
2009-03-09 19:56:27 +00:00
|
|
|
|
|
|
|
Show version information and exit
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=back
|
|
|
|
|
|
|
|
=head1 ARGUMENTS
|
|
|
|
|
|
|
|
The following arguments are support:
|
|
|
|
|
|
|
|
=over
|
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
=item [user@]<hostname>[:port] ...
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
Open an xterm to the given hostname and connect to the administration
|
2006-07-24 19:12:54 +00:00
|
|
|
console. An optional port number can be used if sshd is not listening
|
|
|
|
on standard port (e.g not listening on port 22) and ssh_config cannot be used.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
=item <tag> ...
|
|
|
|
|
|
|
|
Open a series of xterms defined by <tag> within either /etc/clusters or
|
2005-06-09 16:03:26 +00:00
|
|
|
F<$HOME/.csshrc> (see L<"FILES">).
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
=head1 KEY SHORTCUTS
|
|
|
|
|
|
|
|
The following key shortcuts are available within the console window, and all
|
|
|
|
of them may be changed via the configuration files.
|
|
|
|
|
|
|
|
=over
|
|
|
|
|
|
|
|
=item Control-q
|
|
|
|
|
|
|
|
Quit the program and close all connections and windows
|
|
|
|
|
|
|
|
=item Control-+
|
|
|
|
|
2009-04-22 19:23:16 +00:00
|
|
|
Open the 'Add Host(s) or Cluster(s)' dialogue box. Mutiple host or cluster
|
|
|
|
names can be entered, separated by spaces.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
=item Alt-n
|
|
|
|
|
2009-06-02 15:03:03 +00:00
|
|
|
Paste in the hostname part of the specific connection string to each
|
|
|
|
client, minus any username or port, i.e.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
C<< scp /etc/hosts server:files/<Alt-n>.hosts >>
|
|
|
|
|
2009-04-22 19:23:16 +00:00
|
|
|
would replace the <Alt-n> with the client's name in each window
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2005-11-28 19:47:37 +00:00
|
|
|
=item Alt-r
|
|
|
|
|
|
|
|
Retile all the client windows
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=back
|
|
|
|
|
2009-03-09 19:22:36 +00:00
|
|
|
=head1 EXAMPLES
|
|
|
|
|
|
|
|
=over
|
|
|
|
|
|
|
|
=item Open up a session to 3 servers
|
|
|
|
|
|
|
|
S<$ cssh server1 server2 server3>
|
|
|
|
|
|
|
|
=item Open up a session to a cluster of servers identified by the tag 'farm1'
|
|
|
|
and give the controlling window a specific title, where the cluster is defined
|
|
|
|
in one of the default configuration files
|
|
|
|
|
|
|
|
S<$ cssh -T 'Web Farm Cluster 1' farm1>
|
|
|
|
|
|
|
|
=item Connect to different servers using different login names. NOTE: this can
|
|
|
|
also be achieved by setting up appropriate options in the F<.ssh/config> file.
|
|
|
|
Do not close cssh when last terminal exits.
|
|
|
|
|
|
|
|
S<$ cssh -Q user1@server1 admin@server2>
|
|
|
|
|
|
|
|
=item Open up a cluster defined in a non-default configuration file
|
|
|
|
|
|
|
|
S<$ cssh -c $HOME/cssh.config db_cluster>
|
|
|
|
|
2009-03-10 09:37:53 +00:00
|
|
|
=item Use telnet on port 2022 instead of ssh
|
2009-03-09 19:22:36 +00:00
|
|
|
|
2009-04-15 21:47:41 +00:00
|
|
|
S<$ ctel -p 2022 server1 server2>
|
2009-03-09 19:22:36 +00:00
|
|
|
|
|
|
|
=item Use rsh instead of ssh
|
|
|
|
|
2009-04-15 21:47:41 +00:00
|
|
|
S<$ crsh server1 server2>
|
2009-03-09 19:22:36 +00:00
|
|
|
|
|
|
|
=back
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=head1 FILES
|
|
|
|
|
|
|
|
=over
|
|
|
|
|
2009-08-18 21:13:36 +01:00
|
|
|
=item F</etc/clusters>
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
This file contains a list of tags to server names mappings. When any name
|
2006-12-19 13:02:02 +00:00
|
|
|
is used on the command line it is checked to see if it is a tag.
|
|
|
|
If it is a tag, then the tag is replaced with the list of servers. The
|
|
|
|
formated is as follows:
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
S<< <tag> [user@]<server> [user@]<server> [...] >>
|
|
|
|
|
2006-12-19 13:02:02 +00:00
|
|
|
i.e.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2006-12-19 13:02:02 +00:00
|
|
|
# List of servers in live
|
|
|
|
live admin1@server1 admin2@server2 server3 server4
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2006-12-19 13:02:02 +00:00
|
|
|
All comments (marked by a #) and blank lines are ignored. Tags may be
|
|
|
|
nested, but be aware of recursive tags which are not checked for.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2006-12-19 13:02:02 +00:00
|
|
|
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.
|
2006-07-24 19:12:54 +00:00
|
|
|
|
2009-06-02 14:40:27 +00:00
|
|
|
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.
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=item F</etc/csshrc> & F<$HOME/.csshrc>
|
|
|
|
|
|
|
|
This file contains configuration overrides - the defaults are as marked.
|
|
|
|
Default options are overwritten first by the global file, and then by the
|
|
|
|
user file.
|
|
|
|
|
2007-12-17 19:05:16 +00:00
|
|
|
B<NOTE:> values for entries do not need to be quoted unless it is required
|
|
|
|
for passing arguments, i.e.
|
|
|
|
|
|
|
|
terminal_allow_send_events="-xrm '*.VT100.allowSendEvents:true'"
|
|
|
|
|
|
|
|
should be written as
|
|
|
|
|
|
|
|
terminal_allow_send_events=-xrm '*.VT100.allowSendEvents:true'
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=over
|
|
|
|
|
|
|
|
=item always_tile = yes
|
|
|
|
|
|
|
|
Setting to anything other than C<yes> does not perform window tiling (see also -G).
|
|
|
|
|
|
|
|
=item auto_quit = yes
|
|
|
|
|
|
|
|
Automatically quit after the last client window closes. Set to anything
|
|
|
|
other than "yes" to disable. Can be overridden by C<-Q> on the command line.
|
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
=item clusters = <blank>
|
|
|
|
|
|
|
|
Define a number of cluster tags in addition to (or to replace) tags defined
|
|
|
|
in the F</etc/clusters> file. The format is:
|
|
|
|
|
|
|
|
clusters = <tag1> <tag2> <tag3>
|
|
|
|
<tag1> = host1 host2 host3
|
|
|
|
<tag2> = user@host4 user@host5 host6
|
|
|
|
<tag3> = <tag1> <tag2>
|
|
|
|
|
|
|
|
As with the F</etc/clusters> file, be sure not to create recursivly nested tags.
|
|
|
|
|
2006-12-19 13:02:02 +00:00
|
|
|
=item comms = ssh
|
|
|
|
|
|
|
|
Sets the default communication method (initially taken from the name of
|
|
|
|
program, but can be overridden here).
|
|
|
|
|
2005-06-24 16:32:04 +00:00
|
|
|
=item console_position = <null>
|
|
|
|
|
|
|
|
Set the initial position of the console - if empty then let the window manager
|
|
|
|
decide. Format is '+<x>+<y>', i.e. '+0+0' is top left hand corner of the screen,
|
|
|
|
'+0-70' is bottom left hand side of screen (more or less).
|
|
|
|
|
2006-12-19 13:02:02 +00:00
|
|
|
=item extra_cluster_file = <null>
|
2005-11-28 19:47:37 +00:00
|
|
|
|
2006-12-19 13:02:02 +00:00
|
|
|
Define an extra cluster file in the format of F</etc/clusters>. Multiple
|
|
|
|
files can be specified, seperated by commas. Both ~ and $HOME are acceptable
|
|
|
|
as a to reference the users home directory, i.e.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2006-12-19 13:02:02 +00:00
|
|
|
extra_cluster_file = ~/clusters, $HOME/clus
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2007-12-19 09:53:42 +00:00
|
|
|
=item ignore_host_errors
|
2005-06-13 13:56:24 +00:00
|
|
|
|
2007-12-19 09:53:42 +00:00
|
|
|
THIS OPTION IS DEPRECATED. It has been left in so current systems continue
|
|
|
|
to function as expected.
|
2005-06-13 13:56:24 +00:00
|
|
|
|
2009-04-22 19:07:32 +00:00
|
|
|
=item key_addhost = Control-Shift-plus
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
Default key sequence to open AddHost menu. See below notes on shortcuts.
|
|
|
|
|
|
|
|
=item key_clientname = Alt-n
|
|
|
|
|
|
|
|
Default key sequence to send cssh client names to client. See below notes
|
|
|
|
on shortcuts.
|
|
|
|
|
2006-12-19 13:02:02 +00:00
|
|
|
=item key_paste = Control-v
|
|
|
|
|
|
|
|
Default key sequence to paste text into the console window. See below notes
|
|
|
|
on shortcuts.
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=item key_quit = Control-q
|
|
|
|
|
|
|
|
Default key sequence to quit the program (will terminate all open windows).
|
|
|
|
See below notes on shortcuts.
|
|
|
|
|
2005-05-05 15:22:06 +00:00
|
|
|
=item key_retilehosts = Alt-r
|
|
|
|
|
|
|
|
Default key sequence to retile host windows. See below notes on shortcuts.
|
|
|
|
|
2009-06-04 17:26:16 +00:00
|
|
|
=item max_addhost_menu_cluster_items = 6
|
|
|
|
|
|
|
|
Maximum number of entries in the 'Add Host' menu cluster list before
|
|
|
|
scrollbars are used
|
|
|
|
|
2009-04-22 18:58:24 +00:00
|
|
|
=item max_host_menu_items = 30
|
|
|
|
|
|
|
|
Maximum number of hosts to put into the host menu before starting a new column
|
|
|
|
|
2009-08-11 18:01:06 +01:00
|
|
|
=item menu_host_autotearoff = 0
|
|
|
|
|
|
|
|
=item menu_send_autotearoff = 0
|
|
|
|
|
|
|
|
When set to non-0 will automatically tear-off the host or send menu at
|
|
|
|
program start
|
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
=item mouse_paste = Button-2 (middle mouse button)
|
|
|
|
|
|
|
|
Default key sequence to paste text into the console window using the mouse.
|
|
|
|
See below notes on shortcuts.
|
|
|
|
|
2006-12-19 13:02:02 +00:00
|
|
|
=item rsh_args = <blank>
|
|
|
|
|
|
|
|
=item ssh_args = "-x -o ConnectTimeout=10"
|
|
|
|
|
|
|
|
Sets any arguments to be used with the communication method (defaults to ssh
|
|
|
|
arguments).
|
|
|
|
|
2007-12-17 19:05:16 +00:00
|
|
|
B<NOTE:> The given defaults are based on OpenSSH, not commercial ssh software.
|
2006-12-19 13:02:02 +00:00
|
|
|
|
2007-12-17 19:05:16 +00:00
|
|
|
B<NOTE:> Any "generic" change to the method (i.e. specifying the ssh port to use)
|
2006-12-19 13:02:02 +00:00
|
|
|
should be done in the medium's own config file (see L<ssh_config> and
|
|
|
|
F<$HOME/.ssh/config>).
|
|
|
|
|
2009-04-15 21:47:41 +00:00
|
|
|
=item screen_reserve_top = 0
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-15 21:47:41 +00:00
|
|
|
=item screen_reserve_bottom = 60
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2005-05-05 15:22:06 +00:00
|
|
|
=item screen_reserve_left = 0
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2005-05-05 15:22:06 +00:00
|
|
|
=item screen_reserve_right = 0
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
Number of pixels from the screen side to reserve when calculating screen
|
|
|
|
geometry for tiling. Setting this to something like 50 will help keep cssh
|
|
|
|
from positioning windows over your window manager's menu bar if it draws one
|
|
|
|
at that side of the screen.
|
|
|
|
|
|
|
|
=item rsh = /path/to/rsh
|
|
|
|
|
2006-12-19 13:02:02 +00:00
|
|
|
=item ssh = /path/to/ssh
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
Depending on the value of comms, set the path of the communication binary.
|
|
|
|
|
|
|
|
=item terminal = /path/to/terminal
|
|
|
|
|
|
|
|
Path to the x-windows terminal used for the client.
|
|
|
|
|
|
|
|
=item terminal_args = <blank>
|
|
|
|
|
|
|
|
Arguments to use when opening terminal windows. Otherwise takes defaults
|
|
|
|
from F<$HOME/.Xdefaults> or $<$HOME/.Xresources> file.
|
|
|
|
|
2005-05-05 15:22:06 +00:00
|
|
|
=item terminal_font = 6x13
|
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
Font to use in the terminal windows. Use standard X font notation.
|
2005-05-05 15:22:06 +00:00
|
|
|
|
2009-04-15 21:47:41 +00:00
|
|
|
=item terminal_reserve_top = 5
|
2005-05-05 15:22:06 +00:00
|
|
|
|
|
|
|
=item terminal_reserve_bottom = 0
|
|
|
|
|
2009-04-15 21:47:41 +00:00
|
|
|
=item terminal_reserve_left = 5
|
2005-05-05 15:22:06 +00:00
|
|
|
|
|
|
|
=item terminal_reserve_right = 0
|
|
|
|
|
|
|
|
Number of pixels from the terminal side to reserve when calculating screen
|
|
|
|
geometry for tiling. Setting these will help keep cssh from positioning
|
2009-04-15 21:47:41 +00:00
|
|
|
windows over your scroll and title bars or otherwise overlapping the windows
|
|
|
|
too much.
|
2005-05-05 15:22:06 +00:00
|
|
|
|
2008-12-22 16:11:14 +00:00
|
|
|
=item terminal_colorize = 1
|
|
|
|
|
|
|
|
If set to 1 (the default), then "-bg" and "-fg" arguments will be added
|
|
|
|
to the terminal invocation command-line. The terminal will be colored
|
|
|
|
in a pseudo-random way based on the host name; while the color of a terminal
|
|
|
|
is not easily predicted, it will always be the same color for a given host
|
|
|
|
name. After a while, you will recognize hosts by their characteristic
|
|
|
|
terminal color.
|
|
|
|
|
|
|
|
=item terminal_bg_style = dark
|
|
|
|
|
|
|
|
If set to dark, the the terminal background will be set to black and
|
|
|
|
the foreground to the pseudo-random color. If set to light, then the
|
|
|
|
foreground will be black and the background the pseudo-random color. If
|
|
|
|
terminal_colorize is zero, then this option has no effect.
|
|
|
|
|
2005-05-05 15:22:06 +00:00
|
|
|
=item terminal_size = 80x24
|
|
|
|
|
|
|
|
Initial size of terminals to use (note: the number of lines (24) will be
|
|
|
|
decreased when resizing terminals for tiling, not the number of characters (80))
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=item terminal_title_opt = -T
|
|
|
|
|
|
|
|
Option used with C<terminal> to set the title of the window
|
|
|
|
|
2007-11-28 22:18:41 +00:00
|
|
|
=item terminal_allow_send_events = -xrm '*.VT100.allowSendEvents:true'
|
2005-04-25 14:57:28 +00:00
|
|
|
|
|
|
|
Option required by the terminal to allow XSendEvents to be received
|
|
|
|
|
|
|
|
=item title = cssh
|
|
|
|
|
|
|
|
Title of windows to use for both the console and terminals.
|
|
|
|
|
2006-09-06 18:03:56 +00:00
|
|
|
=item unmap_on_redraw = no
|
|
|
|
|
|
|
|
Tell Tk to use the UnmapWindow request before redrawing terminal windows.
|
|
|
|
This defaults to "no" as it causes some problems with the FVWM window
|
|
|
|
manager. If you are experiencing problems with redraws, you can set it to
|
|
|
|
"yes" to allow the window to be unmapped before it is repositioned.
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=item use_hotkeys = yes
|
|
|
|
|
|
|
|
Setting to anything other than C<yes> will disable all hotkeys.
|
|
|
|
|
|
|
|
=item user = $LOGNAME
|
|
|
|
|
|
|
|
Sets the default user for running commands on clients.
|
|
|
|
|
2005-05-03 13:58:38 +00:00
|
|
|
=item window_tiling = yes
|
|
|
|
|
|
|
|
Perform window tiling (set to C<no> to disable)
|
|
|
|
|
2005-05-05 15:22:06 +00:00
|
|
|
=item window_tiling_direction = right
|
|
|
|
|
|
|
|
Direction to tile windows, where "right" means starting top left and moving
|
2005-11-28 19:47:37 +00:00
|
|
|
right and then down, and anything else means starting bottom right and moving
|
|
|
|
left and then up
|
2005-05-05 15:22:06 +00:00
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=back
|
|
|
|
|
2007-12-17 19:05:16 +00:00
|
|
|
B<NOTE:> The key shortcut modifiers must be in the form "Control", "Alt", or
|
2005-06-09 16:03:26 +00:00
|
|
|
"Shift", i.e. with the first letter capitalised and the rest lower case. Keys
|
2008-02-26 20:05:54 +00:00
|
|
|
may also be disabled individually by setting to the word "null".
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-08-18 21:13:36 +01:00
|
|
|
=item F<$HOME/.csshrc_send_menu>
|
|
|
|
|
|
|
|
This (optional) file contains items to populate the send menu. The
|
|
|
|
default entry could be written as:
|
|
|
|
|
|
|
|
<send_menu>
|
|
|
|
<menu title="Hostname">
|
|
|
|
<command>%s</command>
|
|
|
|
<accelerator>ALT-n</accelerator>
|
|
|
|
</menu>
|
|
|
|
</send_menu>
|
|
|
|
|
|
|
|
Submenus can also be specified as follows:
|
|
|
|
|
|
|
|
<send_menu>
|
|
|
|
<menu title="Default Entries">
|
2009-08-24 22:23:41 +01:00
|
|
|
<detach>yes</detach>
|
2009-08-18 21:13:36 +01:00
|
|
|
<menu title="Hostname">
|
|
|
|
<command>%s</command>
|
|
|
|
<accelerator>ALT-n</accelerator>
|
|
|
|
</menu>
|
|
|
|
</menu>
|
|
|
|
</send_menu>
|
|
|
|
|
|
|
|
B<Caveats:>
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item There is currently no strict format checking of this file.
|
|
|
|
|
|
|
|
=item The format of the file may change in the future
|
|
|
|
|
|
|
|
=item If the file exists the default entry (Hostname) is not added
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
The following replacement macros are available:
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item %s
|
|
|
|
|
|
|
|
Hostname part of the specific connection string to each client, minus any
|
|
|
|
username or port
|
|
|
|
|
|
|
|
=item %u
|
|
|
|
|
|
|
|
Username part of the connection string to each client
|
|
|
|
|
|
|
|
=item %h
|
|
|
|
|
|
|
|
Hostname of server where cssh is being run from
|
|
|
|
|
|
|
|
=item %n
|
|
|
|
|
|
|
|
<RETURN> code
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
B<NOTE:> requires L<XML::Simple> to be installed
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=back
|
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
=head1 KNOWN BUGS
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
=over 4
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
=item 1.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
Catering for IPv6 addresses is minimal. This is due to a conflict
|
|
|
|
between IPv6 addresses and port numbers within the same
|
|
|
|
server definition since they both use the same seperator, i.e. is the
|
|
|
|
following just an IPv6 address, or an address + port number of 2323?
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
2001:db8::1428:2323
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
Exactly - I cannot tell either. the IPv6 address without a port is assumed
|
|
|
|
in those cases where it cannot be determined and a warning is issued.
|
|
|
|
|
|
|
|
Possible work arounds include:
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item a.
|
|
|
|
|
2009-04-07 17:17:30 +00:00
|
|
|
Use square brackets around the IPv6 address, i.e.
|
|
|
|
[2001:db8::1428]:2323
|
|
|
|
or
|
|
|
|
[2001:db8::1428:2323]
|
|
|
|
as appropriate so there is no ambiguity
|
|
|
|
|
|
|
|
=item b.
|
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
Use the full IPv6 address if also using a port number - the 8th colon
|
|
|
|
is assumed to be the port seperator.
|
|
|
|
|
2009-04-07 17:17:30 +00:00
|
|
|
=item c.
|
2009-04-06 19:40:13 +00:00
|
|
|
|
|
|
|
Define the IPv6 address in your /etc/hosts file, DNS or other name service
|
|
|
|
lookup mechanism and use the hostname instead of the address.
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
=item 2.
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
Swapping virtual desktops can a redraw of all the terminal windows. This
|
2006-07-24 19:12:54 +00:00
|
|
|
is due to a lack of distinction within Tk between switching desktops and
|
|
|
|
minimising/maximising windows. Until Tk can tell the difference between the
|
|
|
|
two events, there is no fix (apart from rewriting everything directly in X)
|
2005-04-25 14:57:28 +00:00
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
=back
|
|
|
|
|
|
|
|
Anyone with any good ideas to fix the above bugs is more than welcome to get
|
|
|
|
in touch and/or provide a patch.
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=head1 REPORTING BUGS
|
|
|
|
|
|
|
|
=over 2
|
|
|
|
|
|
|
|
=item *
|
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
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).
|
|
|
|
|
|
|
|
1. test the terminal window works with the options provided
|
|
|
|
|
|
|
|
2. test ssh works to a host with the configured arguments
|
|
|
|
|
|
|
|
Configuration options to watch for in ssh are
|
|
|
|
|
|
|
|
- Doesnt understand "-o ConnectTimeout=10" - remove the option
|
|
|
|
in the F<.csshrc> file
|
|
|
|
|
|
|
|
- OpenSSH-3.8 using untrusted ssh tunnels - use "-Y" instead of "-X"
|
|
|
|
or use "ForwardX11Trusted yes' in ssh_config (if you change the
|
|
|
|
default ssh options from -x to -X)
|
|
|
|
|
|
|
|
=item *
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
If you require support, please run the following commands
|
|
|
|
and post it on the web site in the support/problems forum:
|
|
|
|
|
|
|
|
C<< perl -V >>
|
|
|
|
|
|
|
|
C<< perl -MTk -e 'print $Tk::VERSION,$/' >>
|
|
|
|
|
|
|
|
C<< perl -MX11::Protocol -e 'print $X11::Protocol::VERSION,$/' >>
|
|
|
|
|
2006-07-24 19:12:54 +00:00
|
|
|
C<< cat /etc/csshrc $HOME/.csshrc >>
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=item *
|
|
|
|
|
|
|
|
Use the debug switches (-d, -D, or -dD) will turn on debugging output.
|
|
|
|
However, please only use this option with one host at a time,
|
|
|
|
i.e. "cssh -d <host>" due to the amount of output produced (in both main
|
|
|
|
and child windows).
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
=head1 SEE ALSO
|
|
|
|
|
|
|
|
L<http://clusterssh.sourceforge.net/>,
|
|
|
|
L<ssh>,
|
|
|
|
L<Tk::overview>,
|
|
|
|
L<X11::Protocol>,
|
|
|
|
L<perl>
|
|
|
|
|
2009-04-06 19:40:13 +00:00
|
|
|
=head1 AUTHOR
|
|
|
|
|
|
|
|
Duncan Ferguson
|
|
|
|
|
|
|
|
=head1 CREDITS
|
|
|
|
|
|
|
|
clusterssh is distributed under the GNU public license. See the file
|
|
|
|
F<LICENSE> for details.
|
|
|
|
|
|
|
|
A web site for comments, requests, bug reports and bug fixes/patches is
|
|
|
|
available at L<http://clusterssh.sourceforge.net/>
|
|
|
|
|
2005-04-25 14:57:28 +00:00
|
|
|
=cut
|