Re: Failing shell code under busybox 1.36.1 that worked with 1.31.1

2024-02-26 Thread Denys Vlasenko
On Thu, Feb 15, 2024 at 9:52 AM David Leonard
 wrote:
> > _result="$_result '${_p//'/'\"'\"'}'"
>
> Busybox ash has a CONFIG_ASH_BASH_COMPAT config to get this ${var//...}
> replacement behaviour.  And, in bash, the ' in the pattern section is treated
> as a quote start. To give the ' a literal meaning, use \'
> eg ${_p//\'/..repl..}
>
> In current busybox ash you will run into a bug where quotes aren't
> handled in the pattern, and even loses the rest of the word, as you
> observed. That is, given this script:
>
> var="don't g/o"
> echo "${var/'/'o}!"
> echo "${var/\'/\'o}!"
>
> bash outputs:
>
> don't g!(pattern="/o" repl="")
> don'ot g/o! (pattern="'", repl="'o")
>
> and busybox ash outputs:
>
> don't g/o   (pattern=?, repl=?, NOTE: lost !)
> don'ot g/o! (pattern="'", repl="'o")
>
> Here's a patch to make ash a little bit closer to bash.

Thank you, applied (with some changes, but the same idea).
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Failing shell code under busybox 1.36.1 that worked with 1.31.1

2024-02-16 Thread Harvey
BTW, do we have to propose this patch somewhere else or is this already 
the right place?


Greetings
Harvey

Am 15.02.24 um 22:48 schrieb Harvey:

David,

I can confirm that your patch solves my problem without any further need 
to change the shell code. Now V 1.36.1 acts in the same way as V 1.31.1 
did. Thank you so mutch! Maybe this is candidate to merge ;)


Greetings
Harvey

Am 15.02.24 um 09:45 schrieb David Leonard:



    _result="$_result '${_p//'/'\"'\"'}'"


Busybox ash has a CONFIG_ASH_BASH_COMPAT config to get this ${var//...}
replacement behaviour.  And, in bash, the ' in the pattern section is 
treated

as a quote start. To give the ' a literal meaning, use \'
eg ${_p//\'/..repl..}

In current busybox ash you will run into a bug where quotes aren't
handled in the pattern, and even loses the rest of the word, as you
observed. That is, given this script:

 var="don't g/o"
 echo "${var/'/'o}!"
 echo "${var/\'/\'o}!"

bash outputs:

 don't g!    (pattern="/o" repl="")
 don'ot g/o!    (pattern="'", repl="'o")

and busybox ash outputs:

 don't g/o    (pattern=?, repl=?, NOTE: lost !)
 don'ot g/o!    (pattern="'", repl="'o")

Here's a patch to make ash a little bit closer to bash.

--- a/shell/ash.c
+++ b/shell/ash.c
@@ -7058,6 +7058,7 @@ subevalvar(char *start, char *str, int strloc,
  */
 repl = NULL;
 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
+   int quoted = 0;
 /* Find '/' and replace with NUL */
 repl = start;
 /* The pattern can't be empty.
@@ -7073,6 +7074,11 @@ subevalvar(char *start, char *str, int strloc,
 repl = NULL;
 break;
 }
+   /* Handle quoted patterns */
+   if ((unsigned char)*repl == CTLQUOTEMARK)
+   quoted ^= 1;
+   if (quoted)
+   goto literal;
 if (*repl == '/') {
 *repl = '\0';
 break;
@@ -7084,6 +7090,7 @@ subevalvar(char *start, char *str, int strloc,
 /* Handle escaped slashes, e.g. "${v/\//_}" 
(they are CTLESC'ed by this point) */

 if ((unsigned char)*repl == CTLESC && repl[1])
 repl++;
+   literal:
 repl++;
 }
 }

new file mode 100644
index 0..23aecb5ae
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash_repl_quoted.right
@@ -0,0 +1,3 @@
+ab.
+axb.
+x/b.
new file mode 100644
index 0..d2ba39578
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash_repl_quoted.tests
@@ -0,0 +1,4 @@
+v=a/b
+echo "${v/'/'}."
+echo "${v/'/'/x}."
+echo "${v/'a'/x}."



On Wed, 14 Feb 2024, Harvey wrote:


Sorry, posted the wrong version of the pack_args() funtion:
I have payed with possible solutions for so long that I forgot the
restore the original before posting  -blush-

Here is the original version:


# Packs arguments into a single string.
#
# Input:
#   $1 = name of variable receiving the arguments in such a way that
#    (re)evaluating them provides the original arguments
#   $2... = arguments
# Example:
#   func() {
# local args
# pack_args args "$@"
# send_rpc func_impl "$args"
#   }
#   # (in another process) > #   receive_rpc() {
# local func="$1"
# local args="$2"
# eval $func "$args"
#   }
pack_args()
{
    local _p _resvar=$1 _result= _value
    shift
    for _p
    do
    _result="$_result '${_p//'/'\"'\"'}'"
    done
    eval $_resvar=\${_result\# }
}


Harvey

Am 14.02.24 um 19:06 schrieb Harvey:

Hello,

I am part of the team of a small router distribution called fli4l:
https://www.fli4l.de/doku.php?id=start.

We use buildroot to generate our images. Due to a hardware crash and 
the
leaving of our main developer we are facing the dead of our project. 
But

there are still some people left and at least we want to try to keep it
alive 😉

That said - the first we have to try is the update of our buildroot
base. A lot of work is already done and but we struggle with the 
busybox

update, especially with the ash shell contained. When updating to
Version 1.36.1 we are facing script failures in places that did work
until busybox 1.31.1.

I have tried to debug the code and it seems that the error is contained
in a helper include for string handling.

The code is:

# Packs arguments into a single string.
#
# Input:
#   $1 = name of variable receiving the arguments in such a way that
#    (re)evaluating them provides the original argu

RE: Failing shell code under busybox 1.36.1 that worked with 1.31.1

2024-02-15 Thread 'David Leonard'



Well, I also tried adding support for bash's ${var@Q} (which I think is the
 most readable way to solve quoting) but it seems I really don't understand
how ash's subevalvar() works after all :)


./busybox ash -xvc 'v="ab cd"; echo "(${v@Q})"'
+ v='ab cd'
ash: vstransform:str='Q'
ash: vstransform:startp='ab cd'
+ echo ''"'"'a'"'"'ab cd'"'"')'
'a'ab cd')





diff --git a/shell/ash.c b/shell/ash.c
index ae1b79f37..8d5d6146d 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -222,6 +222,8 @@
 #define IF_BASH_PATTERN_SUBST   IF_ASH_BASH_COMPAT
 #defineBASH_SUBSTR  ENABLE_ASH_BASH_COMPAT
 #define IF_BASH_SUBSTR  IF_ASH_BASH_COMPAT
+#defineBASH_PARAM_TRANSFORM ENABLE_ASH_BASH_COMPAT
+#define IF_BASH_PARAM_TRANSFORM IF_ASH_BASH_COMPAT
 /* BASH_TEST2: [[ EXPR ]]
  * Status of [[ support:
  *   && and || work as they should
@@ -574,6 +576,7 @@ var_end(const char *var)
return var;
 }

+static int hasmeta(const char *);

 /*  Parser data */

@@ -868,6 +871,9 @@ out2str(const char *p)
 #define VSREPLACE   0xd /* ${var/pattern/replacement} */
 #define VSREPLACEALL0xe /* ${var//pattern/replacement} */
 #endif
+#if BASH_PARAM_TRANSFORM
+#define VSTRANSFORM 0xf /* ${var@operator} */
+#endif

 static const char dolatstr[] ALIGN1 = {
CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
@@ -7262,6 +7268,20 @@ subevalvar(char *start, char *str, int strloc,
repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
);

+#if BASH_PARAM_TRANSFORM
+   if (subtype == VSTRANSFORM) {
+   bb_error_msg("vstransform:str='%s'", str);
+   if (strcmp(str, "Q") != 0)
+   goto out1;
+   bb_error_msg("vstransform:startp='%s'", startp);
+   char *quoted = single_quote(startp);
+   int len = strlen(quoted);
+   memmove(startp, quoted, len);
+   loc = startp + len;
+   goto out;
+   }
+#endif /* BASH_PARAM_TRANSFORM */
+
 #if BASH_PATTERN_SUBST
workloc = expdest - (char *)stackblock();
if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
@@ -7432,7 +7452,7 @@ subevalvar(char *start, char *str, int strloc,
  out:
amount = loc - expdest;
STADJUST(amount, expdest);
-#if BASH_PATTERN_SUBST
+#if BASH_PATTERN_SUBST || BASH_PARAM_TRANSFORM
  out1:
 #endif
/* Remove any recorded regions beyond start of variable */
@@ -7671,6 +7691,9 @@ evalvar(char *p, int flag)
 #if BASH_PATTERN_SUBST
case VSREPLACE:
case VSREPLACEALL:
+#endif
+#if BASH_PARAM_TRANSFORM
+   case VSTRANSFORM:
 #endif
break;
default:
@@ -12989,6 +13012,13 @@ parsesub: {
goto badsub;
subtype++; /* VSREPLACEALL */
break;
+#endif
+#if BASH_PARAM_TRANSFORM
+   case '@':
+   /* ${v@operator} */
+   subtype = VSTRANSFORM;
+               newsyn = BASESYNTAX;
+           break;
 #endif
}
} else {


On Thu, 15 Feb 2024, David Laight wrote:


From: David Leonard

Sent: 15 February 2024 08:46
To: Harvey 
Cc: busybox@busybox.net
Subject: Re: Failing shell code under busybox 1.36.1 that worked with 1.31.1



_result="$_result '${_p//'/'\"'\"'}'"


Busybox ash has a CONFIG_ASH_BASH_COMPAT config to get this ${var//...}
replacement behaviour.  And, in bash, the ' in the pattern section is treated
as a quote start. To give the ' a literal meaning, use \'
eg ${_p//\'/..repl..}

...

It is probably safer to the quotes into variables.
Then the syntax analysis won't get messed up.

So something like:
sq="'"
qsq='"'"'"'"'

then
"${_p/$sg/$qsq}"

is probably ok and maybe more readable.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, 
UK
Registration No: 1397386 (Wales)


___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Failing shell code under busybox 1.36.1 that worked with 1.31.1

2024-02-15 Thread Harvey

David,

I can confirm that your patch solves my problem without any further need 
to change the shell code. Now V 1.36.1 acts in the same way as V 1.31.1 
did. Thank you so mutch! Maybe this is candidate to merge ;)


Greetings
Harvey

Am 15.02.24 um 09:45 schrieb David Leonard:



    _result="$_result '${_p//'/'\"'\"'}'"


Busybox ash has a CONFIG_ASH_BASH_COMPAT config to get this ${var//...}
replacement behaviour.  And, in bash, the ' in the pattern section is 
treated

as a quote start. To give the ' a literal meaning, use \'
eg ${_p//\'/..repl..}

In current busybox ash you will run into a bug where quotes aren't
handled in the pattern, and even loses the rest of the word, as you
observed. That is, given this script:

 var="don't g/o"
 echo "${var/'/'o}!"
 echo "${var/\'/\'o}!"

bash outputs:

 don't g!    (pattern="/o" repl="")
 don'ot g/o!    (pattern="'", repl="'o")

and busybox ash outputs:

 don't g/o    (pattern=?, repl=?, NOTE: lost !)
 don'ot g/o!    (pattern="'", repl="'o")

Here's a patch to make ash a little bit closer to bash.

--- a/shell/ash.c
+++ b/shell/ash.c
@@ -7058,6 +7058,7 @@ subevalvar(char *start, char *str, int strloc,
  */
     repl = NULL;
     if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
+   int quoted = 0;
     /* Find '/' and replace with NUL */
     repl = start;
     /* The pattern can't be empty.
@@ -7073,6 +7074,11 @@ subevalvar(char *start, char *str, int strloc,
     repl = NULL;
     break;
     }
+   /* Handle quoted patterns */
+   if ((unsigned char)*repl == CTLQUOTEMARK)
+   quoted ^= 1;
+   if (quoted)
+   goto literal;
     if (*repl == '/') {
     *repl = '\0';
     break;
@@ -7084,6 +7090,7 @@ subevalvar(char *start, char *str, int strloc,
     /* Handle escaped slashes, e.g. "${v/\//_}" 
(they are CTLESC'ed by this point) */

     if ((unsigned char)*repl == CTLESC && repl[1])
     repl++;
+   literal:
     repl++;
     }
     }

new file mode 100644
index 0..23aecb5ae
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash_repl_quoted.right
@@ -0,0 +1,3 @@
+ab.
+axb.
+x/b.
new file mode 100644
index 0..d2ba39578
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash_repl_quoted.tests
@@ -0,0 +1,4 @@
+v=a/b
+echo "${v/'/'}."
+echo "${v/'/'/x}."
+echo "${v/'a'/x}."



On Wed, 14 Feb 2024, Harvey wrote:


Sorry, posted the wrong version of the pack_args() funtion:
I have payed with possible solutions for so long that I forgot the
restore the original before posting  -blush-

Here is the original version:


# Packs arguments into a single string.
#
# Input:
#   $1 = name of variable receiving the arguments in such a way that
#    (re)evaluating them provides the original arguments
#   $2... = arguments
# Example:
#   func() {
# local args
# pack_args args "$@"
# send_rpc func_impl "$args"
#   }
#   # (in another process) > #   receive_rpc() {
# local func="$1"
# local args="$2"
# eval $func "$args"
#   }
pack_args()
{
    local _p _resvar=$1 _result= _value
    shift
    for _p
    do
    _result="$_result '${_p//'/'\"'\"'}'"
    done
    eval $_resvar=\${_result\# }
}


Harvey

Am 14.02.24 um 19:06 schrieb Harvey:

Hello,

I am part of the team of a small router distribution called fli4l:
https://www.fli4l.de/doku.php?id=start.

We use buildroot to generate our images. Due to a hardware crash and the
leaving of our main developer we are facing the dead of our project. But
there are still some people left and at least we want to try to keep it
alive 😉

That said - the first we have to try is the update of our buildroot
base. A lot of work is already done and but we struggle with the busybox
update, especially with the ash shell contained. When updating to
Version 1.36.1 we are facing script failures in places that did work
until busybox 1.31.1.

I have tried to debug the code and it seems that the error is contained
in a helper include for string handling.

The code is:

# Packs arguments into a single string.
#
# Input:
#   $1 = name of variable receiving the arguments in such a way that
#    (re)evaluating them provides the original arguments
#   $2... = arguments
# Example:
#   func() {
# local args
# pack_args args "$@"
# send_rpc func_impl "$args"
#   }
#   # (in another 

RE: Failing shell code under busybox 1.36.1 that worked with 1.31.1

2024-02-15 Thread David Laight
From: David Leonard
> Sent: 15 February 2024 08:46
> To: Harvey 
> Cc: busybox@busybox.net
> Subject: Re: Failing shell code under busybox 1.36.1 that worked with 1.31.1
> 
> 
> > _result="$_result '${_p//'/'\"'\"'}'"
> 
> Busybox ash has a CONFIG_ASH_BASH_COMPAT config to get this ${var//...}
> replacement behaviour.  And, in bash, the ' in the pattern section is treated
> as a quote start. To give the ' a literal meaning, use \'
> eg ${_p//\'/..repl..}
...

It is probably safer to the quotes into variables.
Then the syntax analysis won't get messed up.

So something like:
sq="'"
qsq='"'"'"'"'

then
"${_p/$sg/$qsq}"

is probably ok and maybe more readable.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, 
UK
Registration No: 1397386 (Wales)
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


RE: Failing shell code under busybox 1.36.1 that worked with 1.31.1

2024-02-15 Thread David Laight
From: Harvey
> Sent: 14 February 2024 18:18
> Sorry, posted the wrong version of the pack_args() funtion:
> I have payed with possible solutions for so long that I forgot the
> restore the original before posting  -blush-
> 
> Here is the original version:
> 
> 
> # Packs arguments into a single string.
> #
> # Input:
> #   $1 = name of variable receiving the arguments in such a way that
> #(re)evaluating them provides the original arguments
> #   $2... = arguments
> # Example:
> #   func() {
> # local args
> # pack_args args "$@"
> # send_rpc func_impl "$args"
> #   }
> #   # (in another process)
> #   receive_rpc() {
> # local func="$1"
> # local args="$2"
> # eval $func "$args"
> #   }
> pack_args()
> {
>  local _p _resvar=$1 _result= _value
>  shift
>  for _p
>  do
>  _result="$_result '${_p//'/'\"'\"'}'"
>  done
>  eval $_resvar=\${_result\# }
> }

Try just splitting the quoting of the final '
Just adding "" before it might be enough.
Failing that add it on the next line.

Probably easier than trying to find the bug in ash.
(been there, done that...)

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, 
UK
Registration No: 1397386 (Wales)
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Failing shell code under busybox 1.36.1 that worked with 1.31.1

2024-02-15 Thread David Leonard



_result="$_result '${_p//'/'\"'\"'}'"


Busybox ash has a CONFIG_ASH_BASH_COMPAT config to get this ${var//...}
replacement behaviour.  And, in bash, the ' in the pattern section is treated
as a quote start. To give the ' a literal meaning, use \'
eg ${_p//\'/..repl..}

In current busybox ash you will run into a bug where quotes aren't
handled in the pattern, and even loses the rest of the word, as you
observed. That is, given this script:

var="don't g/o"
echo "${var/'/'o}!"
echo "${var/\'/\'o}!"

bash outputs:

don't g!(pattern="/o" repl="")
don'ot g/o! (pattern="'", repl="'o")

and busybox ash outputs:

don't g/o   (pattern=?, repl=?, NOTE: lost !)
don'ot g/o! (pattern="'", repl="'o")

Here's a patch to make ash a little bit closer to bash.

--- a/shell/ash.c
+++ b/shell/ash.c
@@ -7058,6 +7058,7 @@ subevalvar(char *start, char *str, int strloc,
 */
repl = NULL;
if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
+   int quoted = 0;
/* Find '/' and replace with NUL */
repl = start;
/* The pattern can't be empty.
@@ -7073,6 +7074,11 @@ subevalvar(char *start, char *str, int strloc,
repl = NULL;
break;
}
+   /* Handle quoted patterns */
+   if ((unsigned char)*repl == CTLQUOTEMARK)
+   quoted ^= 1;
+   if (quoted)
+   goto literal;
if (*repl == '/') {
*repl = '\0';
break;
@@ -7084,6 +7090,7 @@ subevalvar(char *start, char *str, int strloc,
/* Handle escaped slashes, e.g. "${v/\//_}" (they are 
CTLESC'ed by this point) */
if ((unsigned char)*repl == CTLESC && repl[1])
repl++;
+   literal:
repl++;
}
}

new file mode 100644
index 0..23aecb5ae
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash_repl_quoted.right
@@ -0,0 +1,3 @@
+ab.
+axb.
+x/b.
new file mode 100644
index 0..d2ba39578
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash_repl_quoted.tests
@@ -0,0 +1,4 @@
+v=a/b
+echo "${v/'/'}."
+echo "${v/'/'/x}."
+echo "${v/'a'/x}."



On Wed, 14 Feb 2024, Harvey wrote:


Sorry, posted the wrong version of the pack_args() funtion:
I have payed with possible solutions for so long that I forgot the
restore the original before posting  -blush-

Here is the original version:


# Packs arguments into a single string.
#
# Input:
#   $1 = name of variable receiving the arguments in such a way that
#(re)evaluating them provides the original arguments
#   $2... = arguments
# Example:
#   func() {
# local args
# pack_args args "$@"
# send_rpc func_impl "$args"
#   }
#   # (in another process) > #   receive_rpc() {
# local func="$1"
# local args="$2"
# eval $func "$args"
#   }
pack_args()
{
local _p _resvar=$1 _result= _value
shift
for _p
do
_result="$_result '${_p//'/'\"'\"'}'"
done
eval $_resvar=\${_result\# }
}


Harvey

Am 14.02.24 um 19:06 schrieb Harvey:

Hello,

I am part of the team of a small router distribution called fli4l:
https://www.fli4l.de/doku.php?id=start.

We use buildroot to generate our images. Due to a hardware crash and the
leaving of our main developer we are facing the dead of our project. But
there are still some people left and at least we want to try to keep it
alive 😉

That said - the first we have to try is the update of our buildroot
base. A lot of work is already done and but we struggle with the busybox
update, especially with the ash shell contained. When updating to
Version 1.36.1 we are facing script failures in places that did work
until busybox 1.31.1.

I have tried to debug the code and it seems that the error is contained
in a helper include for string handling.

The code is:

# Packs arguments into a single string.
#
# Input:
#   $1 = name of variable receiving the arguments in such a way that
#    (re)evaluating them provides the original arguments
#   $2... = arguments
# Example:
#   func() {
# local args
# pack_args args "$@"
# send_rpc func_impl "$args"
#   }
#   # (in another process)
#   receive_rpc() {
# local func="$1"
# local args="$2"
# eval $func "$args"
#   }
pack_args()
{
     local _p _resvar=$1 _result= _value
     shift
     for _p
     do
     _result="$_result '${_p//'/'\"'\"'}''"
  

Re: Failing shell code under busybox 1.36.1 that worked with 1.31.1

2024-02-14 Thread Steffen Nurpmeso
Hello.

Harvey wrote in
 <031f00da-4016-4311-b397-1c04e373d...@gmx.de>:
 |Sorry, posted the wrong version of the pack_args() funtion:
 |I have payed with possible solutions for so long that I forgot the
 |restore the original before posting  -blush-
 |
 |Here is the original version:
 |
 |
 |# Packs arguments into a single string.
 |#
 |# Input:
 |#   $1 = name of variable receiving the arguments in such a way that
 |#(re)evaluating them provides the original arguments
 |#   $2... = arguments

Dunno about yours, but Robert Elz (kre) did such in a way that is
portable to any shell i tried it with (// is definitely not
portable); with only slight changes of mine, as attached.

 |# Example:
 |#   func() {
 |# local args
 |# pack_args args "$@"
 |# send_rpc func_impl "$args"
 |#   }
 |#   # (in another process)
 |#   receive_rpc() {
 |# local func="$1"
 |# local args="$2"
 |# eval $func "$args"
 |#   }
 |pack_args()
 |{
 | local _p _resvar=$1 _result= _value
 | shift
 | for _p
 | do
 | _result="$_result '${_p//'/'\"'\"'}'"
 | done
 | eval $_resvar=\${_result\# }
 |}

--steffen
|
|Der Kragenbaer,The moon bear,
|der holt sich munter   he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)
#!/bin/sh -
#@ Round trip quote strings in POSIX shell.  For example
#@   set -- x 'a \ b' "foo'" "\\'b\\a\\r\\" Aä
#@   printf "%s: <%s><%s><%s><%s><%s>\n" "$#" "${1}" "${2}" "${3}" "$4" "$5"
#@   saved_parameters=`quote_rndtrip "$@"`
#@   eval "set -- $saved_parameters"
#@   printf "%s: <%s><%s><%s><%s><%s>\n" "$#" "${1}" "${2}" "${3}" "$4" "$5"
#
# 2017 Robert Elz (kre).
# 2017 - 2022 Steffen Nurpmeso .
# Public Domain

# Though slower use a subshell version instead of properly restoring $IFS
# and flags, as elder shells may not be able to properly restore flags via
# "set +o" as later standardized in POSIX, and it seems overkill to handle
# all possible forms of output "set +o" may or may not actually generate.
quote__rndtrip() (
	case "$1" in
	*\'*) ;;
	*) printf "'%s'" "$1"; return 0;;
	esac
	a="$1" s= e=
	while case "$a" in
		\'*) a=${a#?}; s="${s}'";;
		*\') a=${a%?}; e="${e}'";;
		'') printf "${s}${e}"; exit 0;;
		*) false;;
		esac
	do
		continue
	done
	IFS=\'
	set -f
	set -- $a
	r="${1}"
	shift
	for a
	do
		r="${r}'\\''${a}"
	done
	printf "${s}'%s'${e}" "${r}"
	exit 0
)

quote_rndtrip() (
	j=
	for i
	do
		[ -n "$j" ] && printf ' '
		j=' '
		quote__rndtrip "$i"
	done
)

quote_string() (
	j=
	for i
	do
		[ -n "$j" ] && printf '\\ '
		j=' '
		quote__rndtrip "$i"
	done
)

# s-sht-mode
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Failing shell code under busybox 1.36.1 that worked with 1.31.1

2024-02-14 Thread Harvey

Sorry, posted the wrong version of the pack_args() funtion:
I have payed with possible solutions for so long that I forgot the
restore the original before posting  -blush-

Here is the original version:


# Packs arguments into a single string.
#
# Input:
#   $1 = name of variable receiving the arguments in such a way that
#(re)evaluating them provides the original arguments
#   $2... = arguments
# Example:
#   func() {
# local args
# pack_args args "$@"
# send_rpc func_impl "$args"
#   }
#   # (in another process)
#   receive_rpc() {
# local func="$1"
# local args="$2"
# eval $func "$args"
#   }
pack_args()
{
local _p _resvar=$1 _result= _value
shift
for _p
do
_result="$_result '${_p//'/'\"'\"'}'"
done
eval $_resvar=\${_result\# }
}


Harvey

Am 14.02.24 um 19:06 schrieb Harvey:

Hello,

I am part of the team of a small router distribution called fli4l:
https://www.fli4l.de/doku.php?id=start.

We use buildroot to generate our images. Due to a hardware crash and the
leaving of our main developer we are facing the dead of our project. But
there are still some people left and at least we want to try to keep it
alive 😉

That said - the first we have to try is the update of our buildroot
base. A lot of work is already done and but we struggle with the busybox
update, especially with the ash shell contained. When updating to
Version 1.36.1 we are facing script failures in places that did work
until busybox 1.31.1.

I have tried to debug the code and it seems that the error is contained
in a helper include for string handling.

The code is:

# Packs arguments into a single string.
#
# Input:
#   $1 = name of variable receiving the arguments in such a way that
#    (re)evaluating them provides the original arguments
#   $2... = arguments
# Example:
#   func() {
# local args
# pack_args args "$@"
# send_rpc func_impl "$args"
#   }
#   # (in another process)
#   receive_rpc() {
# local func="$1"
# local args="$2"
# eval $func "$args"
#   }
pack_args()
{
     local _p _resvar=$1 _result= _value
     shift
     for _p
     do
     _result="$_result '${_p//'/'\"'\"'}''"
     done
     eval $_resvar=\${_result\# }
}


The debug trace (using set -x) in V1.31.1 looks like this:

+ pack_args exit_trap_0 sync_unlock_all_resources
+ local _p '_resvar=exit_trap_0' '_result=' _value
+ shift
+ _result=' '"'"'sync_unlock_all_resources'"'"
+ eval 'exit_trap_0=${_result#' '}'
+ exit_trap_0=''"'"'sync_unlock_all_resources'"'"
+ exit_trap_num=1
+ return 0


while in V1.36.1 it looks like this:

+ pack_args exit_trap_0 sync_unlock_all_resources
+ local _p '_resvar=exit_trap_0' '_result=' _value
+ shift
+ _result=' '"'"'sync_unlock_all_resources'
    missing quote
+ eval 'exit_trap_0=${_result#' '}'
+ exit_trap_0=''"'"'sync_unlock_all_resources'
   missing quote
+ exit_trap_num=1
+ return 0

The eval line then fails with 'Unterminated quoted string'

Unfortunately I can't tell where the difference lies.

I hope someone can help or at least point me in the right direction.

Greetings
Harvey
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox