Added code for `--retry-input' in question()

This commit is contained in:
0xfadead 2024-09-15 19:54:41 +02:00 committed by someordinaryidiot#
parent aeeaa3524c
commit b3521680fd

View file

@ -1710,6 +1710,14 @@ static int question(short preset, const char *format, va_list args)
FILE *stream; FILE *stream;
int fd_in = fileno(stdin); int fd_in = fileno(stdin);
va_list args_copy;
int format_len;
/* No need to initialize:
* the other calls also print a termination character */
char prompt_cache_stack[256];
char *prompt_cache = prompt_cache_stack;
size_t prompt_cache_size = sizeof(prompt_cache_stack);
if(config->noconfirm) { if(config->noconfirm) {
stream = stdout; stream = stdout;
} else { } else {
@ -1717,12 +1725,63 @@ static int question(short preset, const char *format, va_list args)
stream = stderr; stream = stderr;
} }
/* Cache prompt, because we can't call v*printf() multiple times
* on the same arguments. */
/* Copy args so we can retry when the buffer is too small */
va_copy(args_copy, args);
/* Don't ask me why v*printf() returns an Integer instead of a long */
format_len = vsnprintf(
prompt_cache,
prompt_cache_size,
format, args);
/* Something has gone wrong */
if (format_len < 1) {
pm_printf(ALPM_LOG_ERROR, _("vsnprintf failure: Failed to cache prompt: %s\n"), strerror(errno));
return 0;
}
/* Buffer is too small */
if ((size_t)format_len + 1 > prompt_cache_size) {
prompt_cache = malloc(format_len + 1);
prompt_cache_size = format_len + 1;
if (prompt_cache == 0) {
pm_printf(ALPM_LOG_ERROR, _("malloc failure: could not allocate %i bytes\n"), format_len + 1);
va_end(args_copy);
return 0;
}
format_len = vsnprintf(prompt_cache, prompt_cache_size, format, args_copy);
/* Something has gone wrong */
if (format_len < 1) {
pm_printf(ALPM_LOG_ERROR, _("vsnprintf failure: Failed to cache prompt: %s\n"), strerror(errno));
va_end(args_copy);
return 0;
}
/* Just in case */
if ((size_t)format + 1 != prompt_cache_size) {
pm_printf(ALPM_LOG_ERROR, _("vsnprintf failure: Failed to cache prompt: Required size: %zu -> %i bytes\n"), prompt_cache_size, format_len + 1);
va_end(args_copy);
return 0;
}
}
/* We can free the args-copy now */
va_end(args_copy);
/* Prompt the user at least once before exiting */
do {
/* ensure all text makes it to the screen before we prompt the user */ /* ensure all text makes it to the screen before we prompt the user */
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
fputs(config->colstr.colon, stream); fputs(config->colstr.colon, stream);
vfprintf(stream, format, args); fputs(prompt_cache, stream);
if(preset) { if(preset) {
fprintf(stream, " %s ", _("[Y/n]")); fprintf(stream, " %s ", _("[Y/n]"));
@ -1756,8 +1815,12 @@ static int question(short preset, const char *format, va_list args)
return 1; return 1;
} else if(mbscasecmp(response, _("N")) == 0 || mbscasecmp(response, _("NO")) == 0) { } else if(mbscasecmp(response, _("N")) == 0 || mbscasecmp(response, _("NO")) == 0) {
return 0; return 0;
} else
/* Emulate same behaviour as multiselect_question() and select_question() */
fprintf(stream, _("invalid input: prompt requires `%s' or `%s'\n\n"), _("Y"), _("N"));
} }
} } while (config->retry_input);
return 0; return 0;
} }