NetBSD Problem Report #52458

From www@NetBSD.org  Thu Aug  3 01:22:43 2017
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id A80B17A20E
	for <gnats-bugs@gnats.NetBSD.org>; Thu,  3 Aug 2017 01:22:43 +0000 (UTC)
Message-Id: <20170803012242.D37F87A26E@mollari.NetBSD.org>
Date: Thu,  3 Aug 2017 01:22:42 +0000 (UTC)
From: idleroux@fastmail.fm
Reply-To: idleroux@fastmail.fm
To: gnats-bugs@NetBSD.org
Subject: \n in prompt breaks history mechanism in /bin/sh
X-Send-Pr-Version: www-1.0

>Number:         52458
>Category:       bin
>Synopsis:       \n in prompt breaks history mechanism in /bin/sh
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kre
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Aug 03 01:25:00 +0000 2017
>Closed-Date:    Wed Aug 09 11:12:34 +0000 2017
>Last-Modified:  Wed Aug 09 11:12:34 +0000 2017
>Originator:     Ian D. Leroux
>Release:        NetBSD 8.99.1 amd64
>Organization:
>Environment:
NetBSD scrameustache.unrouted.net 8.99.1 NetBSD 8.99.1 (GENERIC) #3: Sun Jul 30 17:08:46 EDT 2017  idleroux@scrameustache.unrouted.net:/build/src/sys/arch/amd64/compile/obj/GENERIC amd64
>Description:
In /bin/sh with command-line editing enabled (either with 'set -o vi' or 'set -o emacs', or one of the equivalent commands), one can normally cycle back through previously entered commands one by one using 'k' in vi command mode, or Ctrl-P (or up-arrow) in emacs mode.

However, if $PS1 contains a newline, the commands are not recorded separately but rather as a single block of text, and attempting to go back to a previous command reloads the entire command history as a single  script, rather than as a series of individually selectable commands.

The problem was introduced recently, in that a system from 2017-06-18 does not exhibit this behavior, while one from 2017-07-30 does.
>How-To-Repeat:
/bin/sh
PS1='
$ '
# run a few example commands, e.g.
ls
date
uname
# now attempt to view history,
# either with ESC-k in vi mode or with Ctrl-P in emacs mode,
# and note that all preceding commands appear as a block.
>Fix:

>Release-Note:

>Audit-Trail:

Responsible-Changed-From-To: bin-bug-people->kre
Responsible-Changed-By: kre@NetBSD.org
Responsible-Changed-When: Thu, 03 Aug 2017 06:45:44 +0000
Responsible-Changed-Why:
I am looking into this PR


State-Changed-From-To: open->analyzed
State-Changed-By: kre@NetBSD.org
State-Changed-When: Sat, 05 Aug 2017 10:44:46 +0000
State-Changed-Why:
This is understood now ... the problem occurred with the PS1 expansion
code (etc.)   That works by treating the prompt (PS1 etc) as an input
string, "reading" it (as if we were inside double quotes, or a here
document that needs expanding) parsing the "line" read, expanding it
(much as if it were an arg on a command line) - then the expanded prompt
is eventually output.   Normally (no \n in the prompt) there's no issue
with any of that, but when there is a \n, the shell needs to make sure
no prompt is emitted, so it just turned the prompting off (this is
a variable with 3 states, "off" "use PS1" and "use PS2").

That by itself would all be fine, but it turns out that the shell
decides after it has read each line, whether to add that line to
the history list as a new entry, or whether to append it to the last
one, by looking to see which prompt it just used, if it was PS1,
then this is a new command line, if it was PS2, then we are continuing
the previous entry (a continuation of the command).   (This only
occurs when reading from the terminal, so prompting would generally
be on - note that PS1='' does not turn off prompting, it simply causes
there to be no characters to output in the prompt when it is issued...)

Where it got complicated was where when the prompt was being re-read
to be expanded, and contained a \n (which normally would be the time
for a new (PS2) prompt to be issued) prompting was turned off.  So,
after the prompt had been issued, instead of the variable saying "PS1
needed (or really, here, just used)" (which is what it had said) it now
says "no prompt" - then when the shell comes to add the line just read
to the history, the prompt did not say "PS1" so it assumed it must have
been "PS2", and appended the line to the previous event instead of making
a new one.

This can be fixed in either of two ways (I tested both, separately).

First, rather than testing "if PS1, new entry, else, append" change it to,
"If not PS2, new entry, else, append" (or if you like, "If PS2, append,
else new entry" which is the same thing with more code churn.)

Alternatively, when the prompt is being expanded, save, and then
restore, the "which prompt" variable, so after the expansion is
done, the state is unchanged.

I will do both ... (better safe!)

While here, I noticed a (semi-related) other bug though, empty
lines are not added to history.   That's fine (and a good thing)
if you're sitting at PS1, and just banging the return key to
avoid the screen saver (or something similar), it is OK, though
probably not really correct, in a command like

	ls |


	wc

where the empty lines did not get added to the history event,
but which does not really matter, as what did get added:

	ls |
	wc

means the same thing, but is completely broken when the command is

	echo 'abc


	def'

where the history would say

	echo 'abc
	def'

which is not the same thing at all.   This is an old bug, which has
been around for a long time, but which can be fixed in a very similar
way to the above ... if the prompt used is PS2, then we will enter
empty lines into the history event (append them) just the same way as
lines that contain something (nb: here, by "empty" I mean a line containing
nothing but the terminating \n, and that \n will be appended to the
history event.)


From: "Robert Elz" <kre@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/52458 CVS commit: src/bin/sh
Date: Sat, 5 Aug 2017 11:33:05 +0000

 Module Name:	src
 Committed By:	kre
 Date:		Sat Aug  5 11:33:05 UTC 2017

 Modified Files:
 	src/bin/sh: input.c parser.c

 Log Message:
 PR bin/52458

 Avoid mangling history when editing is enabled, and the prompt contains a \n

 Also, allow empty input lines into history when they are being appended to
 a previous (partial) command (but not when they would just make an empty entry).

 For all the gory details, see the PR.

 Note nothing here actually makes prompts containing \n work correctly
 when editing is enabled, that's a libedit issue, which will be addressed
 some other time.


 To generate a diff of this commit:
 cvs rdiff -u -r1.60 -r1.61 src/bin/sh/input.c
 cvs rdiff -u -r1.142 -r1.143 src/bin/sh/parser.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Ian D. Leroux" <idleroux@fastmail.fm>
To: gnats-bugs@NetBSD.org
Cc: kre@NetBSD.org, netbsd-bugs@netbsd.org, gnats-admin@netbsd.org
Subject: Re: bin/52458 (\n in prompt breaks history mechanism in /bin/sh)
Date: Sat, 5 Aug 2017 08:31:25 -0400

 Thanks for the thorough explanation of the bug.

 On Sat,  5 Aug 2017 10:44:46 +0000 (UTC) kre@NetBSD.org wrote:
 > This can be fixed in either of two ways (I tested both, separately).
 > 
 > First, rather than testing "if PS1, new entry, else, append" change
 > it to, "If not PS2, new entry, else, append" (or if you like, "If
 > PS2, append, else new entry" which is the same thing with more code
 > churn.)

 Note that this, on its own, would break if I put a '\n' in PS2.  That's
 unlikely to be a problem in practice (I routinely use a newline in PS1,
 but I've never heard of anyone putting one in PS2 and it seems like a
 silly idea).

 > Alternatively, when the prompt is being expanded, save, and then
 > restore, the "which prompt" variable, so after the expansion is
 > done, the state is unchanged.

 That sounds like a more general fix.

 Thanks,

 --
 IDL

From: "Ian D. Leroux" <idleroux@fastmail.fm>
To: gnats-bugs@NetBSD.org
Cc: "Robert Elz" <kre@netbsd.org>, kre@NetBSD.org, gnats-admin@netbsd.org,
 netbsd-bugs@netbsd.org
Subject: Re: PR/52458 CVS commit: src/bin/sh
Date: Sat, 5 Aug 2017 18:35:47 -0400

 On Sat,  5 Aug 2017 22:05:01 +0000 (UTC) "Robert Elz" <kre@netbsd.org>
 wrote:
 >  Avoid mangling history when editing is enabled, and the prompt
 > contains a \n 

 Thanks!

 --
 IDL

State-Changed-From-To: analyzed->feedback
State-Changed-By: kre@NetBSD.org
State-Changed-When: Sat, 05 Aug 2017 23:39:48 +0000
State-Changed-Why:
Can this be considered done now ... if it is OK, I will request
a pullup to -8

Nothing here actually makes \n's in prompts work as one might expect
when libedit is in use.


From: "Ian D. Leroux" <idleroux@fastmail.fm>
To: gnats-bugs@NetBSD.org
Cc: kre@NetBSD.org, netbsd-bugs@netbsd.org, gnats-admin@netbsd.org
Subject: Re: bin/52458 (\n in prompt breaks history mechanism in /bin/sh)
Date: Sat, 5 Aug 2017 19:45:35 -0400

 On Sat,  5 Aug 2017 23:39:49 +0000 (UTC) kre@NetBSD.org wrote:
 > Can this be considered done now ... if it is OK, I will request
 > a pullup to -8

 Yes, this PR can be closed.  The libedit problem(s) is, as you said,
 another battle for another day.

 --
 IDL

State-Changed-From-To: feedback->pending-pullups
State-Changed-By: kre@NetBSD.org
State-Changed-When: Sun, 06 Aug 2017 00:18:03 +0000
State-Changed-Why:
pullup-8 #199


From: "Soren Jacobsen" <snj@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/52458 CVS commit: [netbsd-8] src/bin/sh
Date: Wed, 9 Aug 2017 05:35:19 +0000

 Module Name:	src
 Committed By:	snj
 Date:		Wed Aug  9 05:35:19 UTC 2017

 Modified Files:
 	src/bin/sh [netbsd-8]: input.c parser.c

 Log Message:
 Pull up following revision(s) (requested by kre in ticket #199):
 	bin/sh/input.c: revision 1.61
 	bin/sh/parser.c: revision 1.143
 PR bin/52458
 Avoid mangling history when editing is enabled, and the prompt contains a \n
 Also, allow empty input lines into history when they are being appended to
 a previous (partial) command (but not when they would just make an empty entry)
 .
 For all the gory details, see the PR.
 Note nothing here actually makes prompts containing \n work correctly
 when editing is enabled, that's a libedit issue, which will be addressed
 some other time.


 To generate a diff of this commit:
 cvs rdiff -u -r1.56.2.1 -r1.56.2.2 src/bin/sh/input.c
 cvs rdiff -u -r1.132.2.1 -r1.132.2.2 src/bin/sh/parser.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: pending-pullups->closed
State-Changed-By: kre@NetBSD.org
State-Changed-When: Wed, 09 Aug 2017 11:12:34 +0000
State-Changed-Why:
Completed.


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.