view release on metacpan or search on metacpan
lib/App/ClusterSSH.pm view on Meta::CPAN
srand($color);
my $ans = '\\#';
$ans .= $components[ int( 4 * rand() ) ];
$ans .= $components[ int( 4 * rand() ) ];
$ans .= $components[ int( 4 * rand() ) ];
return $ans;
}
# close a specific host session
sub terminate_host($) {
my ( $self, $svr ) = @_;
$self->debug( 2, "Killing session for $svr" );
if ( !$servers{$svr} ) {
$self->debug( 2, "Session for $svr not found" );
return;
}
$self->debug( 2, "Killing process $servers{$svr}{pid}" );
kill( 9, $servers{$svr}{pid} ) if kill( 0, $servers{$svr}{pid} );
delete( $servers{$svr} );
return $self;
}
# catch_all exit routine that should always be used
sub exit_prog() {
my ($self) = @_;
$self->debug( 3, "Exiting via normal routine" );
if ( $self->config->{external_command_pipe}
&& -e $self->config->{external_command_pipe} )
{
close( $self->{external_command_pipe_fh} )
or warn(
"Could not close pipe "
. $self->config->{external_command_pipe} . ": ",
lib/App/ClusterSSH.pm view on Meta::CPAN
system($comms_command);
$run_command = "$terminal_command '$comms_command'";
print STDERR $run_command, $/;
system($run_command);
$self->exit_prog;
}
sub load_keyboard_map() {
my ($self) = @_;
# 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
lib/App/ClusterSSH.pm view on Meta::CPAN
# don't know these two key combs yet...
#$keyboardmap{ $keycodetosym { $keyboard[$_][4] } } = $_ + $min;
#$keyboardmap{ $keycodetosym { $keyboard[$_][5] } } = $_ + $min;
#print "$_ => $keyboardmap{$_}\n" foreach(sort(keys(%keyboardmap)));
#print "keysymtocode: $keysymtocode{o}\n";
#die;
}
sub get_keycode_state($) {
my ( $self, $keysym ) = @_;
$keyboardmap{$keysym} =~ m/^(\D+)(\d+)$/;
my ( $state, $code ) = ( $1, $2 );
$self->debug( 2, "keyboardmap=:", $keyboardmap{$keysym}, ":" );
$self->debug( 2, "state=$state, code=$code" );
SWITCH: for ($state) {
/^n$/ && do {
$state = 0;
lib/App/ClusterSSH.pm view on Meta::CPAN
};
die("Should never reach here");
}
$self->debug( 2, "returning state=:$state: code=:$code:" );
return ( $state, $code );
}
sub resolve_names(@) {
my ( $self, @servers ) = @_;
$self->debug( 2, 'Resolving cluster names: started' );
foreach (@servers) {
my $dirty = $_;
my $username = q{};
$self->debug( 3, 'Checking tag ', $_ );
if ( $dirty =~ s/^(.*)@// ) {
$username = $1;
lib/App/ClusterSSH.pm view on Meta::CPAN
$self->debug( 2, 'Resolving cluster names: completed' );
return (@servers);
}
sub remove_repeated_servers {
my %all = ();
@all{@_} = 1;
return ( keys %all );
}
sub change_main_window_title() {
my ($self) = @_;
my $number = keys(%servers);
$windows{main_window}->title( $self->config->{title} . " [$number]" );
}
sub show_history() {
my ($self) = @_;
if ( $self->config->{show_history} ) {
$windows{history}->packForget();
$windows{history}->selectAll();
$windows{history}->deleteSelected();
$self->config->{show_history} = 0;
}
else {
$windows{history}->pack(
-fill => "x",
-expand => 1,
);
$self->config->{show_history} = 1;
}
}
sub update_display_text($) {
my ( $self, $char ) = @_;
return if ( !$self->config->{show_history} );
$self->debug( 2, "Dropping :$char: into display" );
SWITCH: {
foreach ($char) {
/^Return$/ && do {
$windows{history}->insert( 'end', "\n" );
lib/App/ClusterSSH.pm view on Meta::CPAN
$text =~ s!$macro_newline!\n!xsmg;
}
{
my $macro_version = $self->config->{macro_version};
$text =~ s/$macro_version/$VERSION/xsmg;
}
return $text;
}
sub send_text($@) {
my $self = shift;
my $svr = shift;
my $text = join( "", @_ );
$self->debug( 2, "servers{$svr}{wid}=$servers{$svr}{wid}" );
$self->debug( 3, "Sending to '$svr' text:$text:" );
$text = $self->substitute_macros( $svr, $text );
foreach my $char ( split( //, $text ) ) {
lib/App/ClusterSSH.pm view on Meta::CPAN
sub send_text_to_all_servers {
my $self = shift;
my $text = join( '', @_ );
foreach my $svr ( keys(%servers) ) {
$self->send_text( $svr, $text )
if ( $servers{$svr}{active} == 1 );
}
}
sub send_variable_text_to_all_servers($&) {
my ( $self, $code ) = @_;
foreach my $svr ( keys(%servers) ) {
$self->send_text( $svr, $code->($svr) )
if ( $servers{$svr}{active} == 1 );
}
}
sub send_resizemove($$$$$) {
my ( $self, $win, $x_pos, $y_pos, $x_siz, $y_siz ) = @_;
$self->debug( 3,
"Moving window $win to x:$x_pos y:$y_pos (size x:$x_siz y:$y_siz)" );
#$self->debug( 2, "resize move normal: ", $xdisplay->atom('WM_NORMAL_HINTS') );
#$self->debug( 2, "resize move size: ", $xdisplay->atom('WM_SIZE_HINTS') );
# set the window to have "user" set size & position, rather than "program"
$xdisplay->req(
lib/App/ClusterSSH.pm view on Meta::CPAN
$win,
'x' => $x_pos,
'y' => $y_pos,
'width' => $x_siz,
'height' => $y_siz,
);
#$xdisplay->flush(); # dont flush here, but after all tiling worked out
}
sub open_client_windows(@) {
my $self = shift;
foreach (@_) {
next unless ($_);
my $server_object = App::ClusterSSH::Host->parse_host_string($_);
my $username = $server_object->get_username();
$username = $self->config->{user}
if ( !$username && $self->config->{user} );
my $port = $server_object->get_port();
lib/App/ClusterSSH.pm view on Meta::CPAN
$servers{$server}{active} = 1; # mark as active
$self->config->{internal_activate_autoquit}
= 1; # activate auto_quit if in use
}
$self->debug( 2, "All client windows opened" );
$self->config->{internal_total} = int( keys(%servers) );
return $self;
}
sub get_font_size() {
my ($self) = @_;
$self->debug( 2, "Fetching font size" );
# get atom name<->number relations
my $quad_width = $xdisplay->atom("QUAD_WIDTH");
my $pixel_size = $xdisplay->atom("PIXEL_SIZE");
my $font = $xdisplay->new_rsrc;
my $terminal_font = $self->config->{terminal_font};
$xdisplay->OpenFont( $font, $terminal_font );
lib/App/ClusterSSH.pm view on Meta::CPAN
{
die( "Fatal: Unrecognised font used ($terminal_font).\n"
. "Please amend \$HOME/.clusterssh/config with a valid font (see man page).\n"
);
}
$self->debug( 2, "Done with font size" );
return $self;
}
sub show_console() {
my ($self) = shift;
$self->debug( 2, "Sending console to front" );
$self->config->{internal_previous_state} = "mid-change";
# fudge the counter to drop a redraw event;
$self->config->{internal_map_count} -= 4;
$xdisplay->flush();
$windows{main_window}->update();
lib/App/ClusterSSH.pm view on Meta::CPAN
$self->config->{internal_previous_state} = "normal";
# fvwm seems to need this (Debian #329440)
$windows{main_window}->MapWindow;
return $self;
}
# set the first argument to the second if the first is undefined
# the equivalent of //= but works in older Perls (e.g. 5.8)
sub slash_slash_equal(\$$) {
if ( !defined( ${ $_[0] } ) ) {
${ $_[0] } = $_[1];
}
return ${ $_[0] };
}
# leave function def open here so we can be flexible in how it's called
sub retile_hosts {
lib/App/ClusterSSH.pm view on Meta::CPAN
# flush every time and wait a moment (The WMs are so slow...)
$xdisplay->flush();
select( undef, undef, undef, 0.1 ); # sleep for a mo
}
}
# and as a last item, set focus back onto the console
return $self->show_console();
}
sub capture_terminal() {
my ($self) = @_;
$self->debug( 0, "Stub for capturing a terminal window" );
return if ( $self->options->debug_level < 6 );
# should never see this - all experimental anyhow
foreach my $server ( keys(%servers) ) {
foreach my $data ( keys( %{ $servers{$server} } ) ) {
print "server $server key $data is $servers{$server}{$data}\n";
lib/App/ClusterSSH.pm view on Meta::CPAN
}
print "geom\n";
print join " ", $xdisplay->req( 'GetGeometry', $servers{loki}{wid} ), $/;
print "attrib\n";
print join " ",
$xdisplay->req( 'GetWindowAttributes', $servers{loki}{wid} ),
$/;
}
sub toggle_active_state() {
my ($self) = @_;
$self->debug( 2, "Toggling active state of all hosts" );
foreach my $svr ( sort( keys(%servers) ) ) {
$servers{$svr}{active} = not $servers{$svr}{active};
}
}
sub set_all_active() {
my ($self) = @_;
$self->debug( 2, "Setting all hosts to be active" );
foreach my $svr ( keys(%servers) ) {
$servers{$svr}{active} = 1;
}
}
sub set_half_inactive() {
my ($self) = @_;
$self->debug( 2, "Setting approx half of all hosts to inactive" );
my (@keys) = keys(%servers);
$#keys /= 2;
foreach my $svr (@keys) {
$servers{$svr}{active} = 0;
}
}
sub close_inactive_sessions() {
my ($self) = @_;
$self->debug( 2, "Closing all inactive sessions" );
foreach my $svr ( sort( keys(%servers) ) ) {
$self->terminate_host($svr) if ( !$servers{$svr}{active} );
}
$self->build_hosts_menu();
}
sub add_host_by_name() {
my ($self) = @_;
$self->debug( 2, "Adding host to menu here" );
$windows{host_entry}->focus();
my $answer = $windows{addhost}->Show();
if ( !$answer || $answer ne "Add" ) {
$menus{host_entry} = "";
return;
}
lib/App/ClusterSSH.pm view on Meta::CPAN
if ( $self->config->{window_tiling} eq "yes" ) {
return $self->retile_hosts();
}
else {
return $self->show_console();
}
}
# attempt to re-add any hosts that have been closed since we started
# the session - either through errors or deliberate log-outs
sub re_add_closed_sessions() {
my ($self) = @_;
$self->debug( 2, "add closed sessions" );
return if ( scalar(@dead_hosts) == 0 );
my @new_hosts = @dead_hosts;
# clear out the list in case open fails
@dead_hosts = qw//;
lib/App/ClusterSSH.pm view on Meta::CPAN
# retile, or bring console to front
if ( $self->config->{window_tiling} eq "yes" ) {
return $self->retile_hosts();
}
else {
return $self->show_console();
}
}
sub build_hosts_menu() {
my ($self) = @_;
return if ( $self->config->{hide_menu} );
$self->debug( 2, "Building hosts menu" );
# first, empty the hosts menu from the last static entry + 1 on
my $menu = $menus{bar}->entrycget( 'Hosts', -menu );
$menu->delete( $host_menu_static_items, 'end' );
lib/App/ClusterSSH.pm view on Meta::CPAN
-variable => \$servers{$svr}{active},
-columnbreak => $colbreak,
);
$menu_item_counter++;
}
$self->debug( 3, "Changing window title" );
$self->change_main_window_title();
$self->debug( 2, "Done" );
}
sub setup_repeat() {
my ($self) = @_;
$self->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 {
$self->config->{internal_count} = 0
if ( $self->config->{internal_count} > 60000 )
lib/App/ClusterSSH.pm view on Meta::CPAN
#$self->debug( 3, "repeat completed" );
}
);
$self->debug( 2, "Repeat setup" );
return $self;
}
### Window and menu definitions ###
sub create_windows() {
my ($self) = @_;
$self->debug( 2, "create_windows: started" );
$windows{main_window}
= MainWindow->new( -title => "ClusterSSH", -class => 'cssh', );
$windows{main_window}->withdraw; # leave withdrawn until needed
if ( defined( $self->config->{console_position} )
&& $self->config->{console_position} =~ /[+-]\d+[+-]\d+/ )
{
$windows{main_window}->geometry( $self->config->{console_position} );
lib/App/ClusterSSH.pm view on Meta::CPAN
-width => 20,
-label => 'Host',
-labelPack => [ -side => 'left', ],
-class => 'cssh',
)->pack( -side => 'left' );
$self->debug( 2, "create_windows: completed" );
return $self;
}
sub capture_map_events() {
my ($self) = @_;
# pick up on console minimise/maximise events so we can do all windows
$windows{main_window}->bind(
'<Map>' => sub {
$self->debug( 3, "Entering MAP" );
my $state = $windows{main_window}->state();
$self->debug(
3,
lib/App/ClusterSSH.pm view on Meta::CPAN
'same_screen' => 1,
)
) || warn("Error returned from SendEvent: $!");
}
}
$xdisplay->flush();
return $self;
}
sub create_menubar() {
my ($self) = @_;
$self->debug( 2, "create_menubar: started" );
$menus{bar} = $windows{main_window}->Menu();
$windows{main_window}->configure( -menu => $menus{bar}, )
unless $self->config->{hide_menu};
$menus{file} = $menus{bar}->cascade(
-label => 'File',
-menuitems => [
lib/App/ClusterSSH/Host.pm view on Meta::CPAN
$self->read_ssh_file( $self->{ssh_config} );
$self->debug( 5, 'Have the following ssh hostnames' );
$self->debug( 5, ' "', $_, '"' )
foreach ( sort keys %ssh_hostname_for );
}
return $self;
}
sub read_ssh_file($$) {
my ($self) = shift;
my ($filename) = glob(shift);
$self->debug( 3, 'Reading SSH file: ', $filename );
$ssh_configs_read{$filename} = 1;
if ( open( my $ssh_config_fh, '<', $filename ) ) {
while ( my $line = <$ssh_config_fh> ) {
chomp $line;