[PATCH 1/2] prompt.c: split up the password and non-password handling
From: Ævar Arnfjörð Bjarmason <hidden>
Date: 2021-11-02 16:48:19
Subsystem:
kernel build + files below scripts/ (unless maintained elsewhere), the rest · Maintainers:
Nathan Chancellor, Nicolas Schier, Linus Torvalds
Rather than pass PROMPT_ASKPASS and PROMPT_ECHO flags to git_prompt() let's split it up into git_prompt_echo() and git_prompt_noecho() functions, the latter only ever needs to be called from credential.c, and the same goes for the previous password-only codepath in git_prompt(), which is now exposed as a git_prompt_password(). Doing this paves the way towards addressing some of the issues brought up in 97387c8bdd9 (am: read interactive input from stdin, 2019-05-20). Signed-off-by: Ævar Arnfjörð Bjarmason <redacted> --- Makefile | 1 + builtin/bisect--helper.c | 5 ++- credential.c | 17 ++++++---- help.c | 2 +- prompt-password.c | 63 ++++++++++++++++++++++++++++++++++ prompt-password.h | 7 ++++ prompt.c | 73 ++++++---------------------------------- prompt.h | 7 ++-- 8 files changed, 97 insertions(+), 78 deletions(-) create mode 100644 prompt-password.c create mode 100644 prompt-password.h
diff --git a/Makefile b/Makefile
index 12be39ac497..e8815860e22 100644
--- a/Makefile
+++ b/Makefile@@ -967,6 +967,7 @@ LIB_OBJS += pretty.o LIB_OBJS += prio-queue.o LIB_OBJS += progress.o LIB_OBJS += promisor-remote.o +LIB_OBJS += prompt-password.o LIB_OBJS += prompt.o LIB_OBJS += protocol.o LIB_OBJS += protocol-caps.o
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 28a2e6a5750..30533a70b53 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c@@ -370,7 +370,7 @@ static int decide_next(const struct bisect_terms *terms, * translation. The program will only accept English input * at this point. */ - yesno = git_prompt(_("Are you sure [Y/n]? "), PROMPT_ECHO); + yesno = git_prompt_echo(_("Are you sure [Y/n]? ")); if (starts_with(yesno, "N") || starts_with(yesno, "n")) return -1; return 0;
@@ -838,8 +838,7 @@ static int bisect_autostart(struct bisect_terms *terms) * translation. The program will only accept English input * at this point. */ - yesno = git_prompt(_("Do you want me to do it for you " - "[Y/n]? "), PROMPT_ECHO); + yesno = git_prompt_echo(_("Do you want me to do it for you [Y/n]? ")); res = tolower(*yesno) == 'n' ? -1 : bisect_start(terms, empty_strvec, 0);
diff --git a/credential.c b/credential.c
index e7240f3f636..5509de382a5 100644
--- a/credential.c
+++ b/credential.c@@ -5,6 +5,7 @@ #include "run-command.h" #include "url.h" #include "prompt.h" +#include "prompt-password.h" #include "sigchain.h" #include "urlmatch.h"
@@ -169,11 +170,11 @@ static void credential_format(struct credential *c, struct strbuf *out) } } -static char *credential_ask_one(const char *what, struct credential *c, - int flags) +static char *credential_ask_one(struct credential *c, unsigned int password) { struct strbuf desc = STRBUF_INIT; struct strbuf prompt = STRBUF_INIT; + const char *what = password ? "Password" : "Username"; char *r; credential_describe(c, &desc);
@@ -182,7 +183,11 @@ static char *credential_ask_one(const char *what, struct credential *c, else strbuf_addf(&prompt, "%s: ", what); - r = git_prompt(prompt.buf, flags); + /* We'll try "askpass" for both usernames and passwords */ + r = git_prompt_askpass(prompt.buf); + if (!r) + r = password ? git_prompt_noecho(prompt.buf) + : git_prompt_echo(prompt.buf); strbuf_release(&desc); strbuf_release(&prompt);
@@ -192,11 +197,9 @@ static char *credential_ask_one(const char *what, struct credential *c, static void credential_getpass(struct credential *c) { if (!c->username) - c->username = credential_ask_one("Username", c, - PROMPT_ASKPASS|PROMPT_ECHO); + c->username = credential_ask_one(c, 0); if (!c->password) - c->password = credential_ask_one("Password", c, - PROMPT_ASKPASS); + c->password = credential_ask_one(c, 1); } int credential_read(struct credential *c, FILE *fp)
diff --git a/help.c b/help.c
index 973e47cdc30..6eebc26fbeb 100644
--- a/help.c
+++ b/help.c@@ -644,7 +644,7 @@ const char *help_unknown_cmd(const char *cmd) char *answer; struct strbuf msg = STRBUF_INIT; strbuf_addf(&msg, _("Run '%s' instead? (y/N)"), assumed); - answer = git_prompt(msg.buf, PROMPT_ECHO); + answer = git_prompt_echo(msg.buf); strbuf_release(&msg); if (!(starts_with(answer, "y") || starts_with(answer, "Y")))
diff --git a/prompt-password.c b/prompt-password.c
new file mode 100644
index 00000000000..5fa00363d6c
--- /dev/null
+++ b/prompt-password.c@@ -0,0 +1,63 @@ +#include "cache.h" +#include "prompt-password.h" +#include "strbuf.h" +#include "run-command.h" +#include "prompt.h" + +static char *do_askpass(const char *cmd, const char *prompt) +{ + struct child_process pass = CHILD_PROCESS_INIT; + const char *args[3]; + static struct strbuf buffer = STRBUF_INIT; + int err = 0; + + args[0] = cmd; + args[1] = prompt; + args[2] = NULL; + + pass.argv = args; + pass.out = -1; + + if (start_command(&pass)) + return NULL; + + strbuf_reset(&buffer); + if (strbuf_read(&buffer, pass.out, 20) < 0) + err = 1; + + close(pass.out); + + if (finish_command(&pass)) + err = 1; + + if (err) { + error("unable to read askpass response from '%s'", cmd); + strbuf_release(&buffer); + return NULL; + } + + strbuf_setlen(&buffer, strcspn(buffer.buf, "\r\n")); + + return buffer.buf; +} + +char *git_prompt_askpass(const char *prompt) +{ + const char *askpass; + char *r = NULL; + + askpass = getenv("GIT_ASKPASS"); + if (!askpass) + askpass = askpass_program; + if (!askpass) + askpass = getenv("SSH_ASKPASS"); + if (askpass && *askpass) + r = do_askpass(askpass, prompt); + + return r; +} + +char *git_prompt_noecho(const char *prompt) +{ + return git_prompt(prompt, 0); +}
diff --git a/prompt-password.h b/prompt-password.h
new file mode 100644
index 00000000000..84933d2b7c5
--- /dev/null
+++ b/prompt-password.h@@ -0,0 +1,7 @@ +#ifndef PROMPT_PASSWORD_H +#define PROMPT_PASSWORD_H + +char *git_prompt_askpass(const char *prompt); +char *git_prompt_noecho(const char *prompt); + +#endif
diff --git a/prompt.c b/prompt.c
index 5ded21a017f..458d6637506 100644
--- a/prompt.c
+++ b/prompt.c@@ -1,78 +1,27 @@ #include "cache.h" #include "config.h" -#include "run-command.h" #include "strbuf.h" #include "prompt.h" #include "compat/terminal.h" -static char *do_askpass(const char *cmd, const char *prompt) +char *git_prompt(const char *prompt, unsigned int echo) { - struct child_process pass = CHILD_PROCESS_INIT; - const char *args[3]; - static struct strbuf buffer = STRBUF_INIT; - int err = 0; - - args[0] = cmd; - args[1] = prompt; - args[2] = NULL; - - pass.argv = args; - pass.out = -1; - - if (start_command(&pass)) - return NULL; - - strbuf_reset(&buffer); - if (strbuf_read(&buffer, pass.out, 20) < 0) - err = 1; - - close(pass.out); - - if (finish_command(&pass)) - err = 1; + char *r = NULL; - if (err) { - error("unable to read askpass response from '%s'", cmd); - strbuf_release(&buffer); - return NULL; + if (git_env_bool("GIT_TERMINAL_PROMPT", 1)) { + r = git_terminal_prompt(prompt, echo); + if (!r) + die_errno("could not read"); + } else { + die("could not read terminal prompts disabled"); } - strbuf_setlen(&buffer, strcspn(buffer.buf, "\r\n")); - - return buffer.buf; + return r; } -char *git_prompt(const char *prompt, int flags) +char *git_prompt_echo(const char *prompt) { - char *r = NULL; - - if (flags & PROMPT_ASKPASS) { - const char *askpass; - - askpass = getenv("GIT_ASKPASS"); - if (!askpass) - askpass = askpass_program; - if (!askpass) - askpass = getenv("SSH_ASKPASS"); - if (askpass && *askpass) - r = do_askpass(askpass, prompt); - } - - if (!r) { - const char *err; - - if (git_env_bool("GIT_TERMINAL_PROMPT", 1)) { - r = git_terminal_prompt(prompt, flags & PROMPT_ECHO); - err = strerror(errno); - } else { - err = "terminal prompts disabled"; - } - if (!r) { - /* prompts already contain ": " at the end */ - die("could not read %s%s", prompt, err); - } - } - return r; + return git_prompt(prompt, 1); } int git_read_line_interactively(struct strbuf *line)
diff --git a/prompt.h b/prompt.h
index e294e93541c..f4d38178bc4 100644
--- a/prompt.h
+++ b/prompt.h@@ -1,11 +1,8 @@ #ifndef PROMPT_H #define PROMPT_H -#define PROMPT_ASKPASS (1<<0) -#define PROMPT_ECHO (1<<1) - -char *git_prompt(const char *prompt, int flags); - +char *git_prompt(const char *prompt, unsigned int echo); +char *git_prompt_echo(const char *prompt); int git_read_line_interactively(struct strbuf *line); #endif /* PROMPT_H */
--
2.33.1.1570.g069344fdd45