our
$VERSION
=
'1.16.0'
;
@EXPORT
=
qw(net_ssh2_exec net_ssh2_exec_output net_ssh2_shell_exec)
;
our
$READ_STDERR
= 1;
our
$EXEC_AND_SLEEP
= 0;
sub
net_ssh2_exec {
my
(
$ssh
,
$cmd
,
$base
,
$option
) =
@_
;
my
$chan
=
$ssh
->channel;
if
( !Rex::Config->get_no_tty ) {
$chan
->pty(
"xterm"
);
$chan
->pty_size( 4000, 80 );
}
$chan
->blocking(1);
$chan
->
exec
(
$cmd
);
my
$in
;
my
$in_err
=
""
;
my
$rex_int_conf
= Rex::Commands::get(
"rex_internals"
) || {};
my
$buffer_size
= 1024;
if
(
exists
$rex_int_conf
->{read_buffer_size} ) {
$buffer_size
=
$rex_int_conf
->{read_buffer_size};
}
my
@lines
;
my
$last_line
;
my
$current_line
=
""
;
while
(
my
$len
=
$chan
->
read
(
my
$buf
,
$buffer_size
) ) {
$in
.=
$buf
;
$current_line
.=
$buf
;
if
(
$buf
=~ m/\n/ms ) {
@lines
=
split
( /\n/,
$current_line
);
unshift
@lines
,
$last_line
if
(
$last_line
);
$last_line
=
pop
@lines
;
for
my
$line
(
@lines
) {
$line
=~ s/[\r\n]//gms;
$line
.=
"\n"
;
$base
->execute_line_based_operation(
$line
,
$option
) &&
goto
END_READ;
}
$current_line
=
""
;
}
}
my
@lines_err
;
my
$last_line_err
=
""
;
while
(
my
$len
=
$chan
->
read
(
my
$buf_err
,
$buffer_size
, 1 ) ) {
$in_err
.=
$buf_err
;
@lines_err
=
split
( /\n/,
$buf_err
);
unshift
@lines_err
,
$last_line_err
if
(
$last_line_err
);
$last_line_err
=
pop
@lines_err
;
for
my
$line
(
@lines_err
) {
$line
=~ s/[\r\n]//gms;
$line
.=
"\n"
;
$base
->execute_line_based_operation(
$line
,
$option
) &&
goto
END_READ;
}
}
END_READ:
$chan
->send_eof;
my
$wait_c
= 0;
my
$wait_max
=
$rex_int_conf
->{ssh2_channel_closewait_max} || 500;
while
( !
$chan
->
eof
) {
Rex::Logger::debug(
"Waiting for eof on ssh channel."
);
sleep
0.002;
$wait_c
++;
if
(
$wait_c
>=
$wait_max
) {
Rex::Logger::debug(
"Rex::Helper::SSH2::net_ssh2_exec: force closing channel for command: $cmd"
);
last
;
}
}
$chan
->wait_closed;
$? =
$chan
->exit_status;
if
( !Rex::Config->get_no_tty ) {
$in
=~ s/\r//g
if
$in
;
$in_err
=~ s/\r//g
if
$in_err
;
}
if
(
wantarray
) {
return
(
$in
,
$in_err
);
}
return
$in
;
}
sub
net_ssh2_exec_output {
my
(
$ssh
,
$cmd
,
$callback
) =
@_
;
my
$chan
=
$ssh
->channel;
$chan
->blocking(1);
$chan
->
exec
(
$cmd
);
while
(1) {
my
$buf
;
my
$buf_err
;
$chan
->
read
(
$buf
, 15 );
$chan
->
read
(
$buf_err
, 15 );
if
(
$callback
) {
&$callback
(
$buf
,
$buf_err
);
}
else
{
print
$buf
;
print
$buf_err
;
}
last
unless
$buf
;
}
$chan
->
close
;
$? =
$chan
->exit_status;
}
1;