]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
lei: don't read --stdin terminals from daemon
authorEric Wong <e@80x24.org>
Sun, 12 Nov 2023 13:12:33 +0000 (13:12 +0000)
committerEric Wong <e@80x24.org>
Mon, 13 Nov 2023 00:25:02 +0000 (00:25 +0000)
We must use a foreground process to read from terminals
on stdin, otherwise weird things like lost keystrokes and
EIO can happen.  So take advantage of ->send_exec_cmd to
spawn `cat' in the same way we spawn MUAs, pagers,
`git config --edit' and `git credential' from script/lei

lib/PublicInbox/InputPipe.pm
lib/PublicInbox/LEI.pm

index 232f20e85bf531e70a3c73500b595407c73c9524..ee5bda59781f91f6be329fdc11ba8ab13a29f607 100644 (file)
@@ -6,31 +6,6 @@ package PublicInbox::InputPipe;
 use v5.12;
 use parent qw(PublicInbox::DS);
 use PublicInbox::Syscall qw(EPOLLIN);
-use POSIX ();
-use Carp qw(croak carp);
-
-# I'm not sure what I'm doing w.r.t terminals.
-# FIXME needs non-interactive tests
-sub unblock_tty ($) {
-       my ($self) = @_;
-       my $fd = fileno($self->{sock});
-       my $t = POSIX::Termios->new;
-       $t->getattr($fd) or croak("tcgetattr($fd): $!");
-       return if $t->getlflag & POSIX::ICANON; # line-oriented, good
-
-       # make noncanonical mode TTYs behave like a O_NONBLOCK pipe.
-       # O_NONBLOCK itself isn't well-defined, here, so rely on VMIN + VTIME
-       my ($vmin, $vtime) = ($t->getcc(POSIX::VMIN), $t->getcc(POSIX::VTIME));
-       return if $vmin == 1 && $vtime == 0;
-
-       $t->setcc(POSIX::VMIN, 1); # 1 byte minimum
-       $t->setcc(POSIX::VTIME, 0); # no timeout
-       $t->setattr($fd, POSIX::TCSANOW) or croak("tcsetattr($fd): $!");
-
-       $t->setcc(POSIX::VMIN, $vmin);
-       $t->setcc(POSIX::VTIME, $vtime);
-       $self->{restore_termios} = $t;
-}
 
 sub consume {
        my ($in, $cb, @args) = @_;
@@ -41,18 +16,12 @@ sub consume {
                $self->requeue;
        } elsif (-p _ || -S _) { # O_NONBLOCK for sockets and pipes
                $in->blocking(0);
-       } elsif (-t $in) { # isatty(3) can't use `_' stat cache
-               unblock_tty($self);
        }
        $self;
 }
 
 sub close { # idempotent
        my ($self) = @_;
-       if (my $t = delete($self->{restore_termios})) {
-               my $fd = fileno($self->{sock} // return);
-               $t->setattr($fd, POSIX::TCSANOW) or carp("tcsetattr($fd): $!")
-       }
        $self->{-need_rq} ? delete($self->{sock}) : $self->SUPER::close
 }
 
@@ -67,7 +36,7 @@ sub event_step {
                        $self->{cb}->($self, @{$self->{args}}, '');
                        $self->close
                } elsif ($!{EAGAIN}) { # rely on EPOLLIN
-               } elsif ($!{EINTR}) { # rely on EPOLLIN for sockets/pipes/tty
+               } elsif ($!{EINTR}) { # rely on EPOLLIN for sockets/pipes
                        $self->requeue if $self->{-need_rq};
                } else { # another error
                        $self->{cb}->($self, @{$self->{args}}, undef);
index 681044c8dea9b0e62789a8808dd4f409f7f8055e..77acb5a15bd6c6aa8bc4757192b9453e19655b20 100644 (file)
@@ -1577,7 +1577,15 @@ sub _stdin_cb { # PublicInbox::InputPipe::consume callback for --stdin
 sub slurp_stdin {
        my ($lei, $cb) = @_;
        require PublicInbox::InputPipe;
-       PublicInbox::InputPipe::consume($lei->{0}, \&_stdin_cb, $lei, $cb);
+       my $in = $lei->{0};
+       if (-t $in) { # run cat via script/lei and read from it
+               $in = undef;
+               use autodie qw(pipe);
+               pipe($in, my $wr);
+               say { $lei->{2} } '# enter query, Ctrl-D when done';
+               send_exec_cmd($lei, [ $lei->{0}, $wr ], ['cat'], {});
+       }
+       PublicInbox::InputPipe::consume($in, \&_stdin_cb, $lei, $cb);
 }
 
 1;