mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-22 14:43:55 +08:00
echo: Don't interpret and print options
A weird interaction between grouped short options and our weird option parsing that puts unknown options back: ``` echo "-n foo" ``` would see the `-n`, turn off printing newlines, interpret the " " as another grouped short option, see that there is no short option for space and put the entire token back on the arguments pile. So it would print "-n foo" *without a newline*. Fix this by keeping an old state of the options around and reverting it when putting options back. The alternative is *probably* to forbid the " " short option in wgetopt, then check if an option group contains it and error out, but this should only really be a problem in `echo` because that is, AFAICT, the only thing that puts the options back. Fixes #7614
This commit is contained in:
parent
3c3d09b65f
commit
1dd776ec99
|
@ -28,6 +28,8 @@ static int parse_cmd_opts(echo_cmd_opts_t &opts, int *optind, int argc, wchar_t
|
|||
wchar_t *cmd = argv[0];
|
||||
int opt;
|
||||
wgetopter_t w;
|
||||
echo_cmd_opts_t oldopts = opts;
|
||||
int oldoptind = 0;
|
||||
while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, nullptr)) != -1) {
|
||||
switch (opt) {
|
||||
case 'n': {
|
||||
|
@ -51,6 +53,7 @@ static int parse_cmd_opts(echo_cmd_opts_t &opts, int *optind, int argc, wchar_t
|
|||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
case '?': {
|
||||
opts = oldopts;
|
||||
*optind = w.woptind - 1;
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
|
@ -58,6 +61,17 @@ static int parse_cmd_opts(echo_cmd_opts_t &opts, int *optind, int argc, wchar_t
|
|||
DIE("unexpected retval from wgetopt_long");
|
||||
}
|
||||
}
|
||||
|
||||
// Super cheesy: We keep an old copy of the option state around,
|
||||
// so we can revert it in case we get an argument like
|
||||
// "-n foo".
|
||||
// We need to keep it one out-of-date so we can ignore the *last* option.
|
||||
// (this might be an issue in wgetopt, but that's a whole other can of worms
|
||||
// and really only occurs with our weird "put it back" option parsing)
|
||||
if (w.woptind == oldoptind + 2) {
|
||||
oldopts = opts;
|
||||
oldoptind = w.woptind;
|
||||
}
|
||||
}
|
||||
|
||||
*optind = w.woptind;
|
||||
|
|
|
@ -475,3 +475,12 @@ echo $status
|
|||
builtin --query echo
|
||||
echo $status
|
||||
#CHECK: 0
|
||||
|
||||
# Check that echo doesn't interpret options *and print them*
|
||||
# at the start of quoted args:
|
||||
echo '-ne \tart'
|
||||
# CHECK: -ne \tart
|
||||
echo '-n art'
|
||||
echo banana
|
||||
# CHECK: -n art
|
||||
# CHECK: banana
|
||||
|
|
Loading…
Reference in New Issue
Block a user