If users {net-,pool-,}edit but make a mistake in XML all changes are permanently lost. However, if virsh is running in interactive mode we can as user if he wants to re-edit the file and correct the mistakes. --- tools/console.c | 40 +++++++++++++++++++++++++--------------- tools/console.h | 1 + tools/virsh.c | 41 +++++++++++++++++++++++++++++++++++------ 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/tools/console.c b/tools/console.c index 34fde05..90e54e3 100644 --- a/tools/console.c +++ b/tools/console.c @@ -298,13 +298,36 @@ vshGetEscapeChar(const char *s) return *s; } +int vshMakeStdinRaw(struct termios *ttyattr, bool report_errors) { + struct termios rawattr; + + if (tcgetattr(STDIN_FILENO, ttyattr) < 0) { + if (report_errors) + VIR_ERROR(_("unable to get tty attributes: %s"), + strerror(errno)); + return -1; + } + + rawattr = *ttyattr; + cfmakeraw(&rawattr); + + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) { + if (report_errors) + VIR_ERROR(_("unable to set tty attributes: %s"), + strerror(errno)); + return -1; + } + + return 0; +} + int vshRunConsole(virDomainPtr dom, const char *dev_name, const char *escape_seq, unsigned int flags) { int ret = -1; - struct termios ttyattr, rawattr; + struct termios ttyattr; void (*old_sigquit)(int); void (*old_sigterm)(int); void (*old_sigint)(int); @@ -317,21 +340,8 @@ int vshRunConsole(virDomainPtr dom, result in it being echoed back already), and also ensure Ctrl-C, etc is blocked, and misc other bits */ - if (tcgetattr(STDIN_FILENO, &ttyattr) < 0) { - VIR_ERROR(_("unable to get tty attributes: %s"), - strerror(errno)); - return -1; - } - - rawattr = ttyattr; - cfmakeraw(&rawattr); - - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) { - VIR_ERROR(_("unable to set tty attributes: %s"), - strerror(errno)); + if (vshMakeStdinRaw(&ttyattr, true) < 0) goto resettty; - } - /* Trap all common signals so that we can safely restore the original terminal settings on STDIN before the diff --git a/tools/console.h b/tools/console.h index 2b5440c..97c97cd 100644 --- a/tools/console.h +++ b/tools/console.h @@ -30,6 +30,7 @@ int vshRunConsole(virDomainPtr dom, const char *escape_seq, unsigned int flags); +int vshMakeStdinRaw(struct termios *ttyattr, bool report_errors); # endif /* !WIN32 */ #endif /* __VIR_CONSOLE_H__ */ diff --git a/tools/virsh.c b/tools/virsh.c index dd9292a..3537e2e 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -33,6 +33,7 @@ #include <signal.h> #include <poll.h> #include <strings.h> +#include <termios.h> #include <libxml/parser.h> #include <libxml/tree.h> @@ -15806,11 +15807,14 @@ cmdEdit (vshControl *ctl, const vshCmd *cmd) { bool ret = false; virDomainPtr dom = NULL; + virDomainPtr dom_edited = NULL; char *tmp = NULL; char *doc = NULL; char *doc_edited = NULL; char *doc_reread = NULL; unsigned int flags = VIR_DOMAIN_XML_SECURE | VIR_DOMAIN_XML_INACTIVE; + int c = 0; + struct termios ttyattr; if (!vshConnectionUsability(ctl, ctl->conn)) goto cleanup; @@ -15828,6 +15832,7 @@ cmdEdit (vshControl *ctl, const vshCmd *cmd) tmp = editWriteToTempFile (ctl, doc); if (!tmp) goto cleanup; +reedit: /* Start the editor. */ if (editFile (ctl, tmp) == -1) goto cleanup; @@ -15858,19 +15863,43 @@ cmdEdit (vshControl *ctl, const vshCmd *cmd) } /* Everything checks out, so redefine the domain. */ - virDomainFree (dom); - dom = virDomainDefineXML(ctl->conn, doc_edited); - if (!dom) - goto cleanup; + dom_edited = virDomainDefineXML(ctl->conn, doc_edited); + if (!dom_edited) { + /* Redefine failed. If we are in interactive mode ask user + * if he wants to re-edit the XML. */ + if (!ctl->imode || + vshMakeStdinRaw(&ttyattr, false) < 0) + goto cleanup; + + virshReportError(ctl); + + while (true) { + vshPrint(ctl, "\rFailed. Try again? (y/Y/n/N) [Y]:"); + c = getchar(); + c = c_toupper(c); + if (c == '\n' || c == '\r' || c == 'Y' || c == 'N') + break; + } + + tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr); + + if (c == 'N') + goto cleanup; + + vshPrint(ctl, "\r\n"); + goto reedit; + } vshPrint (ctl, _("Domain %s XML configuration edited.\n"), virDomainGetName(dom)); ret = true; - cleanup: +cleanup: if (dom) - virDomainFree (dom); + virDomainFree(dom); + if (dom_edited) + virDomainFree(dom_edited); VIR_FREE(doc); VIR_FREE(doc_edited); -- 1.7.8.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list