]> Sergey Matveev's repositories - public-inbox.git/blobdiff - script/lei
lei_xsearch: transfer 4 FDs internally, drop IO::FDPass
[public-inbox.git] / script / lei
index 5e30f4d7dec277d2ac7d0f0ccff12670126a6d66..5c32ab88d07ff7ce39d3b5b5cba7f59467d09e34 100755 (executable)
@@ -6,16 +6,28 @@ use v5.10.1;
 use Socket qw(AF_UNIX SOCK_STREAM pack_sockaddr_un);
 use PublicInbox::CmdIPC4;
 my $narg = 4;
+my $recv_cmd = PublicInbox::CmdIPC4->can('recv_cmd4');
 my $send_cmd = PublicInbox::CmdIPC4->can('send_cmd4') // do {
-       require PublicInbox::CmdIPC1; # 2nd choice
-       $narg = 1;
-       PublicInbox::CmdIPC1->can('send_cmd1');
-} // do {
        require PublicInbox::Spawn; # takes ~50ms even if built *sigh*
        $narg = 4;
+       $recv_cmd = PublicInbox::Spawn->can('recv_cmd4');
        PublicInbox::Spawn->can('send_cmd4');
 };
 
+sub exec_cmd {
+       my ($fds, $argc, @argv) = @_;
+       my %env = map { split(/=/, $_, 2) } splice(@argv, $argc);
+       my @m = (*STDIN{IO}, '<&=',  *STDOUT{IO}, '>&=',
+               *STDERR{IO}, '>&=');
+       for my $fd (@$fds) {
+               my ($old_io, $mode) = splice(@m, 0, 2);
+               open($old_io, $mode, $fd) or die "open $mode$fd: $!";
+       }
+       %ENV = (%ENV, %env);
+       exec(@argv);
+       die "exec: @argv: $!";
+}
+
 my ($sock, $pwd);
 if ($send_cmd && eval {
        my $path = do {
@@ -60,19 +72,24 @@ Falling back to (slow) one-shot mode
                $pwd = $cwd;
        }
        1;
-}) { # (Socket::MsgHdr|IO::FDPass|Inline::C), $sock, $pwd are all available:
+}) { # (Socket::MsgHdr|Inline::C), $sock, $pwd are all available:
        local $ENV{PWD} = $pwd;
-       my $buf = join("\0", $$, scalar(@ARGV), @ARGV);
+       my $buf = join("\0", scalar(@ARGV), @ARGV);
        while (my ($k, $v) = each %ENV) { $buf .= "\0$k=$v" }
        $buf .= "\0\0";
        select $sock;
        $| = 1; # unbuffer selected $sock
        $send_cmd->($sock, [ 0, 1, 2 ], $buf, 0);
-       while ($buf = <$sock>) {
-               $buf =~ /\Aexit=([0-9]+)\n\z/ and exit($1 + 0);
-               die $buf;
+       while (my (@fds) = $recv_cmd->($sock, $buf, 4096 * 33)) {
+               if ($buf =~ /\Aexit=([0-9]+)\n\z/) {
+                       exit($1);
+               } elsif ($buf =~ /\Aexec (.+)\n\z/) {
+                       exec_cmd(\@fds, split(/\0/, $1));
+               } else {
+                       die $buf;
+               }
        }
-} else { # for systems lacking Socket::MsgHdr, IO::FDPass or Inline::C
+} else { # for systems lacking Socket::MsgHdr or Inline::C
        warn $@ if $@;
        require PublicInbox::LEI;
        PublicInbox::LEI::oneshot(__PACKAGE__);