From cfb5bb250569f7bb2a33b6602ceccacb020783e0 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sun, 5 Feb 2023 23:52:25 +0100 Subject: [PATCH] builtin: correctly flush streams after running Rust builtin --- src/builtin.cpp | 72 ++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/builtin.cpp b/src/builtin.cpp index cf9f7f338..4679df0c3 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -82,8 +82,8 @@ #include "wutil.h" // IWYU pragma: keep static maybe_t try_get_rust_builtin(const wcstring &cmd); -static proc_status_t builtin_run_rust(parser_t &parser, io_streams_t &streams, - const wcstring_list_t &argv, RustBuiltin builtin); +static maybe_t builtin_run_rust(parser_t &parser, io_streams_t &streams, + const wcstring_list_t &argv, RustBuiltin builtin); /// Counts the number of arguments in the specified null-terminated array int builtin_count_args(const wchar_t *const *argv) { @@ -452,11 +452,6 @@ proc_status_t builtin_run(parser_t &parser, const wcstring_list_t &argv, io_stre if (argv.empty()) return proc_status_t::from_exit_code(STATUS_INVALID_ARGS); const wcstring &cmdname = argv.front(); - auto rust_builtin = try_get_rust_builtin(cmdname); - if (rust_builtin.has_value()) { - return builtin_run_rust(parser, streams, argv, *rust_builtin); - } - // We can be handed a keyword by the parser as if it was a command. This happens when the user // follows the keyword by `-h` or `--help`. Since it isn't really a builtin command we need to // handle displaying help for it here. @@ -465,38 +460,43 @@ proc_status_t builtin_run(parser_t &parser, const wcstring_list_t &argv, io_stre return proc_status_t::from_exit_code(STATUS_CMD_OK); } - if (const builtin_data_t *data = builtin_lookup(cmdname)) { + maybe_t builtin_ret; + + auto rust_builtin = try_get_rust_builtin(cmdname); + if (rust_builtin.has_value()) { + builtin_ret = builtin_run_rust(parser, streams, argv, *rust_builtin); + } else if (const builtin_data_t *data = builtin_lookup(cmdname)) { // Construct the permutable argv array which the builtin expects, and execute the builtin. null_terminated_array_t argv_arr(argv); - maybe_t builtin_ret = data->func(parser, streams, argv_arr.get()); - - // Flush our out and error streams, and check for their errors. - int out_ret = streams.out.flush_and_check_error(); - int err_ret = streams.err.flush_and_check_error(); - - // Resolve our status code. - // If the builtin itself produced an error, use that error. - // Otherwise use any errors from writing to out and writing to err, in that order. - int code = builtin_ret.has_value() ? *builtin_ret : 0; - if (code == 0) code = out_ret; - if (code == 0) code = err_ret; - - // The exit code is cast to an 8-bit unsigned integer, so saturate to 255. Otherwise, - // multiples of 256 are reported as 0. - if (code > 255) code = 255; - - // Handle the case of an empty status. - if (code == 0 && !builtin_ret.has_value()) { - return proc_status_t::empty(); - } - if (code < 0) { - FLOGF(warning, "builtin %ls returned invalid exit code %d", cmdname.c_str(), code); - } - return proc_status_t::from_exit_code(code); + builtin_ret = data->func(parser, streams, argv_arr.get()); + } else { + FLOGF(error, UNKNOWN_BUILTIN_ERR_MSG, cmdname.c_str()); + return proc_status_t::from_exit_code(STATUS_CMD_ERROR); } - FLOGF(error, UNKNOWN_BUILTIN_ERR_MSG, cmdname.c_str()); - return proc_status_t::from_exit_code(STATUS_CMD_ERROR); + // Flush our out and error streams, and check for their errors. + int out_ret = streams.out.flush_and_check_error(); + int err_ret = streams.err.flush_and_check_error(); + + // Resolve our status code. + // If the builtin itself produced an error, use that error. + // Otherwise use any errors from writing to out and writing to err, in that order. + int code = builtin_ret.has_value() ? *builtin_ret : 0; + if (code == 0) code = out_ret; + if (code == 0) code = err_ret; + + // The exit code is cast to an 8-bit unsigned integer, so saturate to 255. Otherwise, + // multiples of 256 are reported as 0. + if (code > 255) code = 255; + + // Handle the case of an empty status. + if (code == 0 && !builtin_ret.has_value()) { + return proc_status_t::empty(); + } + if (code < 0) { + FLOGF(warning, "builtin %ls returned invalid exit code %d", cmdname.c_str(), code); + } + return proc_status_t::from_exit_code(code); } /// Returns a list of all builtin names. @@ -542,5 +542,5 @@ static proc_status_t builtin_run_rust(parser_t &parser, io_streams_t &streams, rust_argv.emplace_back(arg.c_str()); } rust_run_builtin(parser, streams, rust_argv, builtin); - return proc_status_t{}; + return none(); }