X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FObject%2FRemote%2FConnector%2FLocalSudo.pm;h=aa19ced3fbcbc1dcef95ba9c093af24235cb68f1;hb=aa052874c2efdb5837fd42ae2f924d6f05b49c71;hp=6eed5e6dd04b75955c5407e2ad35dcdbe8f833b3;hpb=dac97b35627e705e87c7b9130b1c60d8ef217334;p=scpubgit%2FObject-Remote.git diff --git a/lib/Object/Remote/Connector/LocalSudo.pm b/lib/Object/Remote/Connector/LocalSudo.pm index 6eed5e6..aa19ced 100644 --- a/lib/Object/Remote/Connector/LocalSudo.pm +++ b/lib/Object/Remote/Connector/LocalSudo.pm @@ -9,23 +9,22 @@ extends 'Object::Remote::Connector::Local'; has password_callback => (is => 'ro'); sub _sudo_perl_command { - my ($self, $stderr_fdno, $target_user) = @_; + my ($self, $target_user) = @_; return 'sudo', '-S', '-u', $target_user, '-p', "[sudo] password please\n", 'perl', '-MPOSIX=dup2', - '-e', 'print STDERR "GO\n"; dup2(shift(@ARGV), 2); exec(@ARGV);', - $stderr_fdno, $self->_perl_command($target_user); + '-e', 'print STDERR "GO\n"; exec(@ARGV);', + $self->_perl_command($target_user); } sub _start_perl { my $self = shift; - open my $stderr_dup, '>&', \*STDERR or die "Couldn't dup STDERR: $!"; my $sudo_stderr = gensym; my $pid = open3( my $foreign_stdin, my $foreign_stdout, $sudo_stderr, - $self->_sudo_perl_command(fileno($stderr_dup), @_) + $self->_sudo_perl_command(@_) ) or die "open3 failed: $!"; chomp(my $line = <$sudo_stderr>); if ($line eq "GO") { @@ -36,14 +35,32 @@ sub _start_perl { unless $cb; print $foreign_stdin $cb->($line, @_), "\n"; chomp($line = <$sudo_stderr>); - die "sent password and expected newline from sudo, got ${line}" - if $line; - chomp($line = <$sudo_stderr>); - die "sent password but next line was ${line}" - unless $line eq "GO"; + if ($line and $line ne 'GO') { + die "sent password and expected newline from sudo, got ${line}"; + } + elsif (not $line) { + chomp($line = <$sudo_stderr>); + die "sent password but next line was ${line}" + unless $line eq "GO"; + } } else { die "Got inexplicable line ${line} trying to sudo"; }; + Object::Remote->current_loop + ->watch_io( + handle => $sudo_stderr, + on_read_ready => sub { + if (sysread($sudo_stderr, my $buf, 1024) > 0) { + print STDERR $buf; + } else { + Object::Remote->current_loop + ->unwatch_io( + handle => $sudo_stderr, + on_read_ready => 1 + ); + } + } + ); return ($foreign_stdin, $foreign_stdout, $pid); };