1 # This program is free software; you can redistribute it and/or modify
2 # it under the terms of the GNU General Public License as published by
3 # the Free Software Foundation; either version 2 of the License, or
4 # (at your option) any later version.
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # GNU Library General Public License for more details.
11 # You should have received a copy of the GNU General Public License
12 # along with this program; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 # See the COPYING file for license information.
17 # Copyright (c) 2006, 2007, 2008 Guillaume Chazarain <guichaz@gmail.com>
25 from gsh
import remote_dispatcher
26 from gsh
import display_names
27 from gsh
.terminal_size
import terminal_size
30 """Iterator over all the remote_dispatcher instances"""
31 return sorted([i
for i
in asyncore
.socket_map
.itervalues() if
32 isinstance(i
, remote_dispatcher
.remote_dispatcher
)],
33 key
=lambda i
: i
.display_name
)
35 def count_awaited_processes():
36 """Return a tuple with the number of awaited processes and the total
40 for i
in all_instances():
43 if i
.state
is not remote_dispatcher
.STATE_IDLE
:
48 """For each remote shell determine if its terminated"""
49 instances_found
= False
50 for i
in all_instances():
51 instances_found
= True
52 if i
.state
not in (remote_dispatcher
.STATE_TERMINATED
,
53 remote_dispatcher
.STATE_DEAD
):
55 return instances_found
57 def update_terminal_size():
58 """Propagate the terminal size to the remote shells accounting for the
59 place taken by the longest name"""
60 w
, h
= terminal_size()
61 w
= max(w
- display_names
.max_display_name_length
- 2, min(w
, 10))
62 # python bug http://python.org/sf/1112949 on amd64
64 bug
= struct
.unpack('i', struct
.pack('I', termios
.TIOCSWINSZ
))[0]
65 packed_size
= struct
.pack('HHHH', h
, w
, 0, 0)
67 for i
in all_instances():
68 if i
.enabled
and i
.term_size
!= term_size
:
69 i
.term_size
= term_size
70 fcntl
.ioctl(i
.fd
, bug
, packed_size
)
72 def format_info(info_list
):
73 """Turn a 2-dimension list of strings into a 1-dimension list of strings
74 with correct spacing"""
77 nr_columns
= len(info_list
[0])
80 for i
in xrange(nr_columns
):
81 max_lengths
.append(max([len(str(info
[i
])) for info
in info_list
]))
82 for info_id
in xrange(len(info_list
)):
83 info
= info_list
[info_id
]
84 for str_id
in xrange(len(info
) - 1):
85 # Don't justify the last column (i.e. the last printed line)
86 # as it can get much longer in some shells than in others
87 orig_str
= str(info
[str_id
])
88 indent
= max_lengths
[str_id
] - len(orig_str
)
89 info
[str_id
] = orig_str
+ indent
* ' '
90 info_list
[info_id
] = ' '.join(info
) + '\n'
92 def create_remote_dispatchers(hosts
):
94 for i
, host
in enumerate(hosts
):
95 if remote_dispatcher
.options
.interactive
:
96 last_message
= 'Started %d/%d remote processes\r' % (i
, len(hosts
))
97 sys
.stdout
.write(last_message
)
100 remote_dispatcher
.remote_dispatcher(host
)
106 sys
.stdout
.write(' ' * len(last_message
) + '\r')