LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Slackware (https://www.linuxquestions.org/questions/slackware-14/)
-   -   Slackware ash bug (https://www.linuxquestions.org/questions/slackware-14/slackware-ash-bug-4175613499/)

orbea 09-09-2017 11:46 AM

Slackware ash bug
 
When using 'ash-0.4.0-x86_64-2' included in Slackware current to test compatibilty with scripts I discovered the following issue.

Consider this example.

Code:

#!/bin/ash

set -eu

word='test - オウムのジャングル'
test='test - オウムのジャングル keep this'

type="${test#"$word"}"

printf %s\\n "word = $word"
printf %s\\n "test = $test"
printf %s\\n "type = $type"
exit

Expected output should be:

Code:

word = test - オウムのジャングル
test = test - オウムのジャングル keep this
type =  keep this

However with the slackware ash fails to remove $word from $test.
Code:

word = test - オウムのジャングル
test = test - オウムのジャングル keep this
type = test - オウムのジャングル keep this

Now this happens because $word and $test contain the kana 'の', if this character is removed the test script will work correctly with the Slackware ash, but for my purposes I can not assume what letters or characters $word and $test may or may not contain...

The frustrating part is that other ash implementations do not have this problem including the busybox and freebsd ash nor do related shells like dash or yash.

For bonus, consider this more advanced usage which will result in an infinite loop with the Slackware ash...

Code:

#!/bin/ash

set -eu

word='test - オウムのジャングル'
new=

while [ "$word" != '' ]; do
  first="${word%%"${word#?}"}"
  word="${word#"$first"}"
  new="${new}$first"
  printf %s\\n "first = $first"
  printf %s\\n "word = $word"
  printf %s\\n "new = $new"
done

exit

This should save the first letter, remove everything else from the $word variable and then recreate the string in the $new variable. This could be useful if you wanted to replace certain characters without requiring any binaries or any bashisms.

Darth Vader 09-09-2017 12:10 PM

I am not sure that the Slackware installer and/or the (generated) initrd are supposed to support Japanese or any Asian languages...

Long story short, I thought that the ASH is a mini-shell, limited like hell.

PS. In fact, it is (still) used (the ASH) in the installer?

orbea 09-09-2017 12:21 PM

I am not testing the installer, I use it because I am interested in writing portable scripts that work anywhere. Other ash implementations do not have this problem either...

volkerdi 09-09-2017 12:46 PM

Yes, the Slackware version of ash is severely limited, and there are no longer any scripts in Slackware (in the installer or elsewhere) that use it. Since it seems that dash is the designated successor to ash on Linux systems, perhaps the solution is to switch to that?

orbea 09-09-2017 12:55 PM

Dash would work, but another possible idea is to simply change to a different ash implementation which is not quite as limited. The ash in busybox or freebsd seem better maintained for example. I understand the Slackware ash was derived from a netbsd version, but I am not sure what status their current sh is in? Although it may not be your direct concern I wonder how far spread this particular ash is beyond just Slackware?

Didier Spaier 09-09-2017 12:56 PM

I don't think that ash be able to process UTF-8 encoded files.

ash-0.40 shipped in Slackware-current is more that 16 years old... While there has been a proposal for processing UTF-8 in a shell in 1992, I don't think there have been many implementations before 2003.

@Orbea: to test compatibility (assuming that you want that your script be portable, i.e. doesn't need any extension beyond what is specified by POSIX), you could use dash (available from SBo) or just bash in POSIX mode (bash --posix).

@Darth Vader: the Slackware installer uses bash and I don't think it can work as-is with another shell.

PS Sorry, I typed too slow... And anyway all ash implementations are very limited and I don't think any be POSIX compliant. So yes, if it is to be replaced in Slackware dash looks like a good candidate.

Darth Vader 09-09-2017 01:09 PM

Didier, thanks for details, my French friend! :D

@orbea

I think you make a dramatic huge confusion, because looks like today, the shell so called ASH is basically a modular Bash framework: https://github.com/ash-shell/ash

Read: something like a Bash on steroids.

So, looks like the modern ASH is NOT the same with our 16 years old junk... ;)

PS. I wonder, why we do not send in retirement this really old pal, if it is not used anymore?

orbea 09-09-2017 01:17 PM

I find the easiest way to test compatibility is to actually try the shells, using dash or bash --posix doesn't teach things like how in ksh 'type' is an alias to 'whence -v' nor will it reveal silent exits in a more limited shell where you left undefined behavior. :)

Anyways, my main intent was to record this somewhere public and given that this seems to be specific to the ash used by Slackware this seemed to be the best place.

orbea 09-09-2017 01:21 PM

@Darth Vader: You should realize your link has nothing to do with the Almquist Shell (Ash) despite the misleading name.

https://en.wikipedia.org/wiki/Almquist_shell
https://github.com/ash-shell/ash/issues/41

Darth Vader 09-09-2017 01:25 PM

Thanks, I figured out already... ;)

Also, looks like today the old ASH is called for real DASH:

http://gondor.apana.org.au/~herbert/dash/

Latest source being: http://gondor.apana.org.au/~herbert/...h-0.5.9.tar.gz (2016-06-06)

So, I suspect that the other distros use this DASH, eventually symlinked as /bin/ash ...

orbea 09-11-2017 12:50 AM

I found a way to work around this issue, but it will still get that one kana wrong... I guess its truly hopeless with this old shell. :)

To get the first letter.
Code:

#!/bin/ash

set -eu

first='test - オウムのジャングル'

while [ "${#first}" -gt 1 ]; do
  first="${first%?}"
done

printf %s\\n "first = $first"

exit

To recreate the word.
Code:

#!/bin/ash

set -eu

word='test - オウムのジャングル'
new=

printf %s\\n "word = $word"

while [ "$word" != '' ]; do
  first="$word"
  word="${word#?}"
  while [ "${#first}" -gt 1 ]; do
    first="${first%?}"
  done
  new="${new}$first"
done

printf %s\\n "new = $new"

exit

Output:
Code:

word = test - オウムのジャングル
new = test - オウムãジャングル


Darth Vader 09-11-2017 01:19 AM

@orbea

BUT, the question is: is not BASH present in any honorable distribution?

Make sense for you to insist on mini-shells?

orbea 09-11-2017 01:29 AM

Can you please go be rude somewhere else? This thread has nothing to do with bash nor have you left a single useful reply.

orbea 09-11-2017 01:23 PM

Actually there is a work around, considering that the Slackware ash does not have printf as a builtin and that it falls back to the GNU printf in coreutils which does not have this bug this can be done.

Code:

#!/bin/ash

set -eu

word='test - オウムのジャングル'
test='test - オウムのジャングル keep this'

type="$(printf %s "${test#"$word"}")"

printf %s\\n "word = $word"
printf %s\\n "test = $test"
printf %s\\n "type = $type"
exit

Or:
Code:

#!/bin/ash

set -eu

word='test - オウムのジャングル'
new=

while [ "$word" != '' ]; do
  first="$(printf %s "${word%"${word#?}"}")"
  word="$(printf %s "${word#?}")"
  new="${new}$first"
  printf %s\\n "first = $first"
  printf %s\\n "word = $word"
  printf %s\\n "new = $new"
done

exit

I have also tested bash, dash, ksh, ksh-openbsd, mksh, pdksh, posh, yash and zsh where this continues to work.

Richard Cranium 09-11-2017 03:16 PM

Quote:

Originally Posted by Darth Vader (Post 5757500)
@orbea

BUT, the question is: is not BASH present in any honorable distribution?

Make sense for you to insist on mini-shells?

If you exec a shell in a loop, it can make a difference.

The last time someone checked, you can knock a measurable amount of time off of boot startup by using dash in the Slackware init scripts versus bash.


All times are GMT -5. The time now is 03:07 AM.