1 package Object::Remote::Connector::LocalSudo;
7 extends 'Object::Remote::Connector::Local';
9 has password_callback => (is => 'ro');
11 sub _sudo_perl_command {
12 my ($self, $target_user) = @_;
14 'sudo', '-S', '-u', $target_user, '-p', "[sudo] password please\n",
15 'perl', '-MPOSIX=dup2',
16 '-e', 'print STDERR "GO\n"; exec(@ARGV);',
17 $self->_perl_command($target_user);
22 my $sudo_stderr = gensym;
27 $self->_sudo_perl_command(@_)
28 ) or die "open3 failed: $!";
29 chomp(my $line = <$sudo_stderr>);
31 # started already, we're good
32 } elsif ($line =~ /\[sudo\]/) {
33 my $cb = $self->password_callback;
34 die "sudo sent ${line} but we have no password callback"
36 print $foreign_stdin $cb->($line, @_), "\n";
37 chomp($line = <$sudo_stderr>);
38 if ($line and $line ne 'GO') {
39 die "sent password and expected newline from sudo, got ${line}";
42 chomp($line = <$sudo_stderr>);
43 die "sent password but next line was ${line}"
47 die "Got inexplicable line ${line} trying to sudo";
49 Object::Remote->current_loop
51 handle => $sudo_stderr,
52 on_read_ready => sub {
53 if (sysread($sudo_stderr, my $buf, 1024) > 0) {
56 Object::Remote->current_loop
58 handle => $sudo_stderr,
64 return ($foreign_stdin, $foreign_stdout, $pid);
69 push @Object::Remote::Connection::Guess, sub {
71 # username followed by @
72 if (defined and !ref and /^ ([^\@]*?) \@ $/x) {
73 return __PACKAGE__->new->connect($1);