1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

display: yes no prompt improvement

Original code missed to catch all apperances of SIGINT.
Also enhance logging when running in shell without tty.
Accept this regex as valid input:
'^[ ^t]*([Yy]([Ee]([Ss]|)|)|[Nn]([Oo]|))[ ^t]*$'
This commit is contained in:
Zdenek Kabelac 2016-06-08 20:52:14 +02:00
parent cfdc87b623
commit 35612bd27c
2 changed files with 77 additions and 24 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.156 - Version 2.02.156 -
================================ ================================
Yes/No prompt accepts '^[ ^t]*([Yy]([Ee]([Ss]|)|)|[Nn]([Oo]|))[ ^t]*$'.
If available, also collect output from lsblk command when running lvmdump -s. If available, also collect output from lsblk command when running lvmdump -s.
Fix regression in blkdeactivate causing dm and md devices to be skipped. (2.02.155) Fix regression in blkdeactivate causing dm and md devices to be skipped. (2.02.155)

View File

@ -831,50 +831,102 @@ void display_name_error(name_error_t name_error)
* Prompt for y or n from stdin. * Prompt for y or n from stdin.
* Defaults to 'no' in silent mode. * Defaults to 'no' in silent mode.
* All callers should support --yes and/or --force to override this. * All callers should support --yes and/or --force to override this.
*
* Accepted are either _yes[] or _no[] strings or just their outset.
* When running without 'tty' stdin is printed to stderr.
* 'Yes' is accepted ONLY with '\n'.
*/ */
char yes_no_prompt(const char *prompt, ...) char yes_no_prompt(const char *prompt, ...)
{ {
int c = 0, ret = 0, cb = 0; /* Lowercase Yes/No strings */
static const char _yes[] = "yes";
static const char _no[] = "no";
const char *answer = NULL;
int c = silent_mode() ? EOF : 0;
int i, ret = 0, sig = 0;
char buf[12];
va_list ap; va_list ap;
sigint_allow(); sigint_allow();
do {
if (c == '\n' || !c) { for (;;) {
if (!ret) {
/* Show prompt */
va_start(ap, prompt); va_start(ap, prompt);
vfprintf(stderr, prompt, ap); vfprintf(stderr, prompt, ap);
va_end(ap); va_end(ap);
fflush(stderr); fflush(stderr);
if (silent_mode()) {
fputc('n', stderr); if (c == EOF)
ret = 'n';
break; break;
}
ret = 0; i = 0;
answer = NULL;
} }
nextchar:
if ((sig = sigint_caught()))
break; /* Check if already interrupted before getchar() */
if ((c = getchar()) == EOF) { if ((c = getchar()) == EOF) {
ret = 'n'; /* SIGINT */ /* SIGNAL or no chars on stdin (missing '\n') or ^D */
cb = 1; if (!i)
break; break; /* Just shown prompt,-> print [n]\n */
goto invalid; /* Note: c holds EOF */
} }
if ((i < (sizeof(buf) - 4)) && isprint(c))
buf[i++] = c;
c = tolower(c); c = tolower(c);
if ((c == 'y') || (c == 'n')) {
/* If both 'y' and 'n' given, begin again. */ if ((ret > 0) && (c == answer[0]))
if (ret && c != ret) answer++; /* Matching, next char */
ret = -1; else if (c == '\n') {
else if (feof(stdin))
ret = c; fputc('\n', stderr);
} if (ret > 0)
} while (ret < 1 || c != '\n'); break; /* Answered */
invalid:
if (i >= (sizeof(buf) - 4)) {
/* '...' for missing input */
i = sizeof(buf) - 1;
buf[i - 1] = buf[i - 2] = buf[i - 3] = '.';
}
buf[i] = 0;
log_warn("WARNING: Invalid input '%s'.", buf);
ret = 0; /* Otherwise refresh prompt */
} else if (!ret && (c == _yes[0])) {
ret = 'y';
answer = _yes + 1; /* Expecting 'Yes' */
} else if (!ret && (c == _no[0])) {
ret = 'n';
answer = _no + 1; /* Expecting 'No' */
} else if (!ret && isspace(c)) {
/* Ignore any whitespace before */
--i;
goto nextchar;
} else if ((ret > 0) && isspace(c)) {
/* Ignore any whitespace after */
while (*answer)
answer++; /* jump to end-of-word */
} else
ret = -1; /* Read till '\n' and refresh */
}
sigint_restore(); sigint_restore();
if (cb && !sigint_caught()) /* For other then Yes answer check there is really no interrupt */
fputc(ret, stderr); if (sig || sigint_caught()) {
stack;
if (c != '\n') ret = 'n';
fputc('\n', stderr); } else if (c == EOF) {
fputs("[n]\n", stderr);
ret = 'n';
} else
/* Not knowing if it's terminal, makes this hard.... */
log_verbose("Accepted input: [%c]", ret);
return ret; return ret;
} }