diff mbox

command substitutions in $PS4

Message ID 20141117214931.GA4601@chaz.gmail.com (mailing list archive)
State RFC
Delegated to: Herbert Xu
Headers show

Commit Message

Stephane Chazelas Nov. 17, 2014, 9:49 p.m. UTC
Hello.

[tested on current git head
f6d4def4e27b13fab174e948b94cd10550d3e10e]

Command substitution doesn't seem to work in $PS4 (used for
xtrace prompt):

$ PS4='$(date +%T)> ' dash -xc :
dash: 1: Syntax error: end of file unexpected (expecting ")")

And with the old syntax:

$ PS4='`date +%T`> ' dash -xc :
> :

And with more than one command:

$ PS4='`date +%T`> ' dash -xc ':;:'
> :

dash doesn't return and seems to go in a forking loop,
presumably because the `date` there triggers another PS4
expansion and so on recursively

If I prevent the recursion with:


$ PS4='`date +%T`> ' ./src/dash -xc ':;sleep 1; date'
> :
21:43:47> sleep 1
21:43:48> date
Mon Nov 17 21:43:48 GMT 2014

The command substitution still fails upon the first expansion
only. I quickly gave up trying to find out why as I found the
code there hard to follow.

Comments

Jilles Tjoelker Nov. 30, 2014, 8:42 p.m. UTC | #1
On Mon, Nov 17, 2014 at 09:49:32PM +0000, Stephane Chazelas wrote:
> [tested on current git head
> f6d4def4e27b13fab174e948b94cd10550d3e10e]

> Command substitution doesn't seem to work in $PS4 (used for
> xtrace prompt):

> $ PS4='$(date +%T)> ' dash -xc :
> dash: 1: Syntax error: end of file unexpected (expecting ")")

> And with the old syntax:

> $ PS4='`date +%T`> ' dash -xc :
> > :

> And with more than one command:

> $ PS4='`date +%T`> ' dash -xc ':;:'
> > :

> dash doesn't return and seems to go in a forking loop,
> presumably because the `date` there triggers another PS4
> expansion and so on recursively

> If I prevent the recursion with:

> --- a/src/eval.c
> +++ b/src/eval.c
> @@ -776,7 +776,15 @@ evalcommand(union node *cmd, int flags)
>  		int sep;
>  
>  		out = &preverrout;
> +
> +		/*
> +		 * reset xflag temporarily for command substitutions performed
> +		 * upon $PS4 expansion
> +		 */
> +		xflag = 0;
>  		outstr(expandstr(ps4val()), out);
> +		xflag = 1;
> +
>  		sep = 0;
>  		sep = eprintlist(out, varlist.list, sep);
>  		eprintlist(out, arglist.list, sep);

> $ PS4='`date +%T`> ' ./src/dash -xc ':;sleep 1; date'
> > :
> 21:43:47> sleep 1
> 21:43:48> date
> Mon Nov 17 21:43:48 GMT 2014

> The command substitution still fails upon the first expansion
> only. I quickly gave up trying to find out why as I found the
> code there hard to follow.

In FreeBSD sh, I have disabled command substitution in PS4 (POSIX does
not require it anyway). It is treated as a syntax error.

Talking about syntax errors, dash has a problem there as well. If there
is a syntax error in PS4 and set -x is enabled, it will not execute any
simple commands (assignments to PS4 cause an error and are subsequently
reverted). FreeBSD sh prints the error messages and subsequently uses
the raw unexpanded text.
diff mbox

Patch

--- a/src/eval.c
+++ b/src/eval.c
@@ -776,7 +776,15 @@  evalcommand(union node *cmd, int flags)
 		int sep;
 
 		out = &preverrout;
+
+		/*
+		 * reset xflag temporarily for command substitutions performed
+		 * upon $PS4 expansion
+		 */
+		xflag = 0;
 		outstr(expandstr(ps4val()), out);
+		xflag = 1;
+
 		sep = 0;
 		sep = eprintlist(out, varlist.list, sep);
 		eprintlist(out, arglist.list, sep);