From patchwork Tue Jan 3 06:15:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Herbert Xu X-Patchwork-Id: 13087209 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9E373C3DA7D for ; Tue, 3 Jan 2023 06:16:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230124AbjACGQD (ORCPT ); Tue, 3 Jan 2023 01:16:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57572 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230107AbjACGQD (ORCPT ); Tue, 3 Jan 2023 01:16:03 -0500 Received: from formenos.hmeau.com (helcar.hmeau.com [216.24.177.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 24FD0C42 for ; Mon, 2 Jan 2023 22:16:01 -0800 (PST) Received: from loth.rohan.me.apana.org.au ([192.168.167.2]) by formenos.hmeau.com with smtp (Exim 4.94.2 #2 (Debian)) id 1pCaac-00DMOt-CY; Tue, 03 Jan 2023 14:15:59 +0800 Received: by loth.rohan.me.apana.org.au (sSMTP sendmail emulation); Tue, 03 Jan 2023 14:15:58 +0800 Date: Tue, 3 Jan 2023 14:15:58 +0800 From: Herbert Xu To: =?utf-8?b?0L3QsNCx?= Cc: dash@vger.kernel.org, harald@gigawatt.nl Subject: [v3 PATCH] input: Read standard input byte-wise Message-ID: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <42d2b629549d8be07d14acb6cdd7d0f853ed1a6e.1670979949.git.nabijaczleweli@nabijaczleweli.xyz> X-Newsgroups: apana.lists.os.linux.dash Precedence: bulk List-ID: X-Mailing-List: dash@vger.kernel.org наб wrote: > > POSIX Issue 7, XCU, sh, STDIN says: Your patch breaks history support since that relies on there being a whole line in the input buffer. This works for me: ---8<--- POSIX Issue 7, XCU, sh, STDIN says: When the shell is using standard input and it invokes a command that also uses standard input, the shell shall ensure that the standard input file pointer points directly after the command it has read when the command begins execution. It shall not read ahead in such a manner that any characters intended to be read by the invoked command are consumed by the shell (whether interpreted by the shell or not) or that characters that are not read by the invoked command are not seen by the shell. I.e. sh < Signed-off-by: Herbert Xu diff --git a/src/input.c b/src/input.c index ec075f5..43c9161 100644 --- a/src/input.c +++ b/src/input.c @@ -159,6 +159,17 @@ int pgetc(void) return __pgetc(); } +static int stdin_clear_nonblock(void) +{ + int flags = fcntl(0, F_GETFL, 0); + + if (flags >= 0) { + flags &=~ O_NONBLOCK; + flags = fcntl(0, F_SETFL, flags); + } + + return flags; +} static int preadfd(void) @@ -195,22 +206,38 @@ retry: } else #endif + if (parsefile->fd) nr = read(parsefile->fd, buf, IBUFSIZ - 1); + else { + unsigned len = IBUFSIZ - 1; + + nr = 0; + + do { + int err; + err = read(0, buf, 1); + if (err <= 0) { + if (nr) + break; + + nr = err; + if (errno != EWOULDBLOCK) + break; + if (stdin_clear_nonblock() < 0) + break; + + out2str("sh: turning off NDELAY mode\n"); + goto retry; + } + + nr++; + } while (!IS_DEFINED_SMALL && *buf++ != '\n' && --len); + } if (nr < 0) { if (errno == EINTR) goto retry; - if (parsefile->fd == 0 && errno == EWOULDBLOCK) { - int flags = fcntl(0, F_GETFL, 0); - if (flags >= 0 && flags & O_NONBLOCK) { - flags &=~ O_NONBLOCK; - if (fcntl(0, F_SETFL, flags) >= 0) { - out2str("sh: turning off NDELAY mode\n"); - goto retry; - } - } - } } return nr; } diff --git a/src/input.h b/src/input.h index 8c39f33..8830b66 100644 --- a/src/input.h +++ b/src/input.h @@ -34,6 +34,12 @@ * @(#)input.h 8.2 (Berkeley) 5/4/95 */ +#ifdef SMALL +#define IS_DEFINED_SMALL 1 +#else +#define IS_DEFINED_SMALL 0 +#endif + /* PEOF (the end of file marker) is defined in syntax.h */ enum {