From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.2 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, T_SCC_BODY_TEXT_LINE shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id E22641F406 for ; Sun, 12 Nov 2023 13:12:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org; s=selector1; t=1699794754; bh=0ZGrFm8S7zhUxZ1efh5URgPMyIz82RK/BwlyJKjJQLA=; h=From:To:Subject:Date:From; b=Lgezv5enGJn8MLMp7b8xRDrDwsPPk5JfTu7ZmpxInaeBuZrL+cAN4gA8+ImYTnste d9cPpXr7FSg+VYsSFSqpJG81NgoUjLC2tALp8xbr4DS0cBSQTKjZ2A70ogTdKKJnYh QLmT/Fu1NIJXPEMd0x6FAMZ8kJ7EkrRF2XZ1N4oE= From: Eric Wong To: meta@public-inbox.org Subject: [PATCH] lei: don't read --stdin terminals from daemon Date: Sun, 12 Nov 2023 13:12:33 +0000 Message-Id: <20231112131233.718614-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: 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 | 33 +-------------------------------- lib/PublicInbox/LEI.pm | 10 +++++++++- 2 files changed, 10 insertions(+), 33 deletions(-) diff --git a/lib/PublicInbox/InputPipe.pm b/lib/PublicInbox/InputPipe.pm index 232f20e8..ee5bda59 100644 --- a/lib/PublicInbox/InputPipe.pm +++ b/lib/PublicInbox/InputPipe.pm @@ -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); diff --git a/lib/PublicInbox/LEI.pm b/lib/PublicInbox/LEI.pm index 681044c8..77acb5a1 100644 --- a/lib/PublicInbox/LEI.pm +++ b/lib/PublicInbox/LEI.pm @@ -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;