From: Franck Bui Date: Wed, 2 Nov 2016 12:51:02 +0000 (+0100) Subject: core: rework ask_for_confirmation() X-Git-Tag: v234~813^2~11 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3b20f877ade5599dab124474055d2e56c3dcdb15;p=platform%2Fupstream%2Fsystemd.git core: rework ask_for_confirmation() Now the reponses are handled by ask_for_confirmation() as well as the report of any errors occuring during the process of retrieving the confirmation response. One benefit of this is that there's no need to open/close the console one more time when reporting error/status messages. The caller now just needs to care about the return values whose meanings are: - don't execute and pretend that the command failed - don't execute and pretend that the command succeeed - positive answer, execute the command Also some slight code reorganization and introduce write_confirm_error() and write_confirm_error_fd(). write_confim_message becomes unneeded. --- diff --git a/src/core/execute.c b/src/core/execute.c index 43a0a5c..8b09f71 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -669,21 +669,27 @@ static int setup_confirm_stdio(const char *vc, int *_saved_stdin, int *_saved_st return 0; } -_printf_(2, 3) static int write_confirm_message(const char *vc, const char *format, ...) { +static void write_confirm_error_fd(int err, int fd) { + assert(err < 0); + + if (err == -ETIMEDOUT) + dprintf(fd, "Confirmation question timed out, assuming positive response.\n"); + else { + errno = -err; + dprintf(fd, "Couldn't ask confirmation: %m, assuming positive response.\n"); + } +} + +static void write_confirm_error(int err, const char *vc) { _cleanup_close_ int fd = -1; - va_list ap; - assert(format); + assert(vc); fd = open_terminal(vc, O_WRONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) - return fd; - - va_start(ap, format); - vdprintf(fd, format, ap); - va_end(ap); + return; - return 0; + write_confirm_error_fd(err, fd); } static int restore_confirm_stdio(int *saved_stdin, int *saved_stdout) { @@ -708,22 +714,48 @@ static int restore_confirm_stdio(int *saved_stdin, int *saved_stdout) { return r; } -static int ask_for_confirmation(const char *vc, char *response, char **argv) { +enum { + CONFIRM_PRETEND_FAILURE = -1, + CONFIRM_PRETEND_SUCCESS = 0, + CONFIRM_EXECUTE = 1, +}; + +static int ask_for_confirmation(const char *vc, const char *cmdline) { int saved_stdout = -1, saved_stdin = -1, r; - _cleanup_free_ char *line = NULL; + char c; + /* For any internal errors, assume a positive response. */ r = setup_confirm_stdio(vc, &saved_stdin, &saved_stdout); - if (r < 0) - return r; - - line = exec_command_line(argv); - if (!line) - return -ENOMEM; + if (r < 0) { + write_confirm_error(r, vc); + return CONFIRM_EXECUTE; + } - r = ask_char(response, "yns", "Execute %s? [Yes, No, Skip] ", line); + r = ask_char(&c, "yns", "Execute %s? [Yes, No, Skip] ", cmdline); + if (r < 0) { + write_confirm_error_fd(r, STDOUT_FILENO); + r = CONFIRM_EXECUTE; + goto restore_stdio; + } + + switch (c) { + case 'n': + printf("Failing execution.\n"); + r = CONFIRM_PRETEND_SUCCESS; + break; + case 's': + printf("Skipping execution.\n"); + r = CONFIRM_PRETEND_FAILURE; + break; + case 'y': + r = CONFIRM_EXECUTE; + break; + default: + assert_not_reached("Unhandled choice"); + } +restore_stdio: restore_confirm_stdio(&saved_stdin, &saved_stdout); - return r; } @@ -2311,21 +2343,22 @@ static int exec_child( if (params->confirm_spawn) { const char *vc = params->confirm_spawn; - char response; - - r = ask_for_confirmation(vc, &response, argv); - if (r == -ETIMEDOUT) - write_confirm_message(vc, "Confirmation question timed out, assuming positive response.\n"); - else if (r < 0) - write_confirm_message(vc, "Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-r)); - else if (response == 's') { - write_confirm_message(vc, "Skipping execution.\n"); + _cleanup_free_ char *cmdline = NULL; + + cmdline = exec_command_line(argv); + if (!cmdline) { + *exit_status = EXIT_CONFIRM; + return -ENOMEM; + } + + r = ask_for_confirmation(vc, cmdline); + if (r != CONFIRM_EXECUTE) { + if (r == CONFIRM_PRETEND_SUCCESS) { + *exit_status = EXIT_SUCCESS; + return 0; + } *exit_status = EXIT_CONFIRM; return -ECANCELED; - } else if (response == 'n') { - write_confirm_message(vc, "Failing execution.\n"); - *exit_status = 0; - return 0; } }