On 10/9/23 09:46, Richard W.M. Jones wrote:
Hi Eric, a couple of POSIX questions for you from nbdkit.
The first question is from an AUR comment on nbdkit:
https://aur.archlinux.org/packages/nbdkit#comment-937381
I think there's a bash-ism in the logscript parameter in this test:
https://gitlab.com/nbdkit/nbdkit/-/blame/master/tests/test-log-script-inf...
I believe it is happening in the $(( .. )) expression. How do we
write that so it'll work in a posix shell?
(I'm not Eric, but curious! :) )
Here I think we should just explicitly insist on bash. Shell arrays are
a bash-specific feature, and the extent array is deeply ingrained. See
especially commit df63b23b6280 ("log: Use strict shell quoting for every
parameter displayed in the log file.", 2021-01-04). In particular the
assignment
extents=(0x0 0x8000 "hole,zero" 0x8000 0x8000 "")
turns "extents" into an array variable.
In the bug tracker, comment
<
https://aur.archlinux.org/packages/nbdkit#comment-937375> says, "Thus
this is an upstream issue; their scripts are calling sh when they should
be calling bash". I think that's correct; for logscript=..., we should
require /bin/bash in the manual, and execute the script with /bin/bash
explicitly, not just system().
- - -
Secondly while looking into this I was trying variations on:
$ POSIXLY_CORRECT=1 ./nbdkit -fv data '1 2 3' --run 'nbdinfo $uri'
This doesn't actually cause bash to emulate a posix shell, but it does
uncover a different bug:
nbdkit: error: raw|base64|data parameter must be specified exactly once
This seems to be happening because getopt_long in wrapper.c behaves
somehow differently parsing when POSIXLY_CORRECT is set. However I
couldn't work out exactly why.
https://gitlab.com/nbdkit/nbdkit/-/blob/master/wrapper.c?ref_type=heads#L278
I guess the wrapper ought to work if POSIXLY_CORRECT is set (?)
IIRC, POSIXLY_CORRECT makes getopt() stop parsing options when the first
non-option argument (i.e., first operand) is reached. So "-f" and
"-v"
are taken as options, then the two arguments "data" and '1 2 3' are
taken as operands, and then "--run" and the rest are taken as operands
as well.
I think the following loop is relevant:
/* Are there any non-option arguments? */
if (optind < argc) {
/* Ensure any further parameters can never be parsed as options by
* real nbdkit.
*/
passthru ("--");
/* The first non-option argument is the plugin name. If it is a
* short name then rewrite it.
*/
if (is_short_name (argv[optind])) {
const char *language;
/* Plugins written in scripting languages. */
if (is_script_plugin (argv[optind], &language)) {
passthru_format ("%s/plugins/%s/.libs/nbdkit-%s-plugin." SOEXT,
builddir, language, language);
passthru_format ("%s/plugins/%s/nbdkit-%s-plugin",
builddir, argv[optind], argv[optind]);
}
/* Otherwise normal plugins written in C or other languages that
* compile to .so files.
*/
else {
passthru_format ("%s/plugins/%s/.libs/nbdkit-%s-plugin." SOEXT,
builddir, argv[optind], argv[optind]);
}
++optind;
}
/* Everything else is passed through without rewriting. */
while (optind < argc) {
passthru (argv[optind]);
++optind;
}
}
With POSIXLY_CORRECT set, the "Everything else is passed through without
rewriting" logic extends to "--run" etc. I'm not sure how that would
lead to the specific error message, though.
Laszlo
Rich.