Return a falsey status if the last -c command has a parse error

This makes `fish -c begin` fail with a status of 127 - it already
printed a syntax error so that was weird. (127 was the status for
syntax errors when piping to fish, so we stay consistent with that)

We allow multiple `-c` commands, and this will return the regular
status if the last `-c` succeeded.

This is fundamentally an extremely weird situation but this is the
simple targeted fix - we did nothing, unsuccessfully, so we should
fail.

Things to consider in future:

1. Return something better than 127 - that's the status for "unknown
command"!
2. Fail after a `-c` failed, potentially even checking all of them
before executing the first?

Fixes #9888

(cherry picked from commit a6c36a014c)
This commit is contained in:
Fabian Boehm 2023-07-12 17:59:43 +02:00
parent 4ba7855699
commit 72edd888f1
2 changed files with 27 additions and 1 deletions

View File

@ -258,6 +258,7 @@ static void read_init(parser_t &parser, const struct config_paths_t &paths) {
static int run_command_list(parser_t &parser, const std::vector<std::string> &cmds, static int run_command_list(parser_t &parser, const std::vector<std::string> &cmds,
const io_chain_t &io) { const io_chain_t &io) {
int retval = STATUS_CMD_OK;
for (const auto &cmd : cmds) { for (const auto &cmd : cmds) {
wcstring cmd_wcs = str2wcstring(cmd); wcstring cmd_wcs = str2wcstring(cmd);
// Parse into an ast and detect errors. // Parse into an ast and detect errors.
@ -273,14 +274,17 @@ static int run_command_list(parser_t &parser, const std::vector<std::string> &cm
parsed_source_ref_t ps = parsed_source_ref_t ps =
std::make_shared<parsed_source_t>(std::move(cmd_wcs), std::move(ast)); std::make_shared<parsed_source_t>(std::move(cmd_wcs), std::move(ast));
parser.eval(ps, io); parser.eval(ps, io);
retval = STATUS_CMD_OK;
} else { } else {
wcstring sb; wcstring sb;
parser.get_backtrace(cmd_wcs, errors, sb); parser.get_backtrace(cmd_wcs, errors, sb);
std::fwprintf(stderr, L"%ls", sb.c_str()); std::fwprintf(stderr, L"%ls", sb.c_str());
// XXX: Why is this the return for "unknown command"?
retval = STATUS_CMD_UNKNOWN;
} }
} }
return 0; return retval;
} }
/// Parse the argument list, return the index of the first non-flag arguments. /// Parse the argument list, return the index of the first non-flag arguments.

View File

@ -569,24 +569,46 @@ $fish -c 'echo \utest'
# CHECKERR: echo \utest # CHECKERR: echo \utest
# CHECKERR: ^~~~~^ # CHECKERR: ^~~~~^
echo $status
# CHECK: 127
$fish -c 'echo \c' $fish -c 'echo \c'
# CHECKERR: fish: Incomplete escape sequence '\c' # CHECKERR: fish: Incomplete escape sequence '\c'
# CHECKERR: echo \c # CHECKERR: echo \c
# CHECKERR: ^^ # CHECKERR: ^^
echo $status
# CHECK: 127
$fish -c 'echo \C' $fish -c 'echo \C'
# CHECK: C # CHECK: C
echo $status
# CHECK: 0
$fish -c 'echo \U' $fish -c 'echo \U'
# CHECKERR: fish: Incomplete escape sequence '\U' # CHECKERR: fish: Incomplete escape sequence '\U'
# CHECKERR: echo \U # CHECKERR: echo \U
# CHECKERR: ^^ # CHECKERR: ^^
echo $status
# CHECK: 127
$fish -c 'echo \x' $fish -c 'echo \x'
# CHECKERR: fish: Incomplete escape sequence '\x' # CHECKERR: fish: Incomplete escape sequence '\x'
# CHECKERR: echo \x # CHECKERR: echo \x
# CHECKERR: ^^ # CHECKERR: ^^
echo $status
# CHECK: 127
$fish -c begin
# CHECKERR: fish: Missing end to balance this begin
# CHECKERR: begin
# CHECKERR: ^~~~^
echo $status
# CHECK: 127
printf '%s\n' "#!/bin/sh" 'echo $0' > $tmpdir/argv0.sh printf '%s\n' "#!/bin/sh" 'echo $0' > $tmpdir/argv0.sh
chmod +x $tmpdir/argv0.sh chmod +x $tmpdir/argv0.sh
cd $tmpdir cd $tmpdir