[libvirt] [PATCH 7/9] Make handling of monitor prompts more general.

Miloslav Trmač mitr at redhat.com
Tue Jul 21 11:12:03 UTC 2009


---
 src/qemu_driver.c |   87 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 73 insertions(+), 14 deletions(-)

diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index f2be27f..12079f8 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -87,6 +87,12 @@ static void qemuDriverUnlock(struct qemud_driver *driver)
     virMutexUnlock(&driver->lock);
 }
 
+/* Return -1 for error, 0 for success */
+typedef int qemudMonitorExtraPromptHandler(const virDomainObjPtr vm,
+                                           const char *buf,
+                                           const char *prompt,
+                                           void *data);
+
 static void qemuDomainEventFlush(int timer, void *opaque);
 static void qemuDomainEventQueue(struct qemud_driver *driver,
                                  virDomainEventPtr event);
@@ -111,6 +117,12 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom);
 static int qemudMonitorCommand(const virDomainObjPtr vm,
                                const char *cmd,
                                char **reply);
+static int qemudMonitorCommandWithHandler(const virDomainObjPtr vm,
+                                          const char *cmd,
+                                          const char *extraPrompt,
+                                          qemudMonitorExtraPromptHandler extraHandler,
+                                          void *handlerData,
+                                          char **reply);
 static int qemudMonitorCommandExtra(const virDomainObjPtr vm,
                                     const char *cmd,
                                     const char *extra,
@@ -2014,15 +2026,15 @@ qemuMonitorDiscardPendingData(virDomainObjPtr vm) {
 
 
 static int
-qemudMonitorCommandExtra(const virDomainObjPtr vm,
-                         const char *cmd,
-                         const char *extra,
-                         const char *extraPrompt,
-                         char **reply) {
+qemudMonitorCommandWithHandler(const virDomainObjPtr vm,
+                               const char *cmd,
+                               const char *extraPrompt,
+                               qemudMonitorExtraPromptHandler extraHandler,
+                               void *handlerData,
+                               char **reply) {
     int size = 0;
     char *buf = NULL;
     size_t cmdlen = strlen(cmd);
-    size_t extralen = extra ? strlen(extra) : 0;
 
     qemuMonitorDiscardPendingData(vm);
 
@@ -2061,14 +2073,20 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm,
 
         /* Look for QEMU prompt to indicate completion */
         if (buf) {
-            if (extra) {
-                if (strstr(buf, extraPrompt) != NULL) {
-                    if (safewrite(vm->monitor, extra, extralen) != extralen)
-                        return -1;
-                    if (safewrite(vm->monitor, "\r", 1) != 1)
-                        return -1;
-                    extra = NULL;
-                }
+            char *foundPrompt;
+
+            if (extraPrompt &&
+                (foundPrompt = strstr(buf, extraPrompt)) != NULL) {
+                char *promptEnd;
+
+                if (extraHandler(vm, buf, foundPrompt, handlerData) < 0)
+                    return -1;
+                /* Discard output so far, necessary to detect whether
+                   extraPrompt appears again.  We don't need the output between
+                   original command and this prompt anyway. */
+                promptEnd = foundPrompt + strlen(extraPrompt);
+                memmove(buf, promptEnd, strlen(promptEnd)+1);
+                size -= promptEnd - buf;
             } else if ((tmp = strstr(buf, QEMU_CMD_PROMPT)) != NULL) {
                 char *commptr = NULL, *nlptr = NULL;
                 /* Preserve the newline */
@@ -2106,6 +2124,47 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm,
     return -1;
 }
 
+struct extraHandlerData
+{
+    const char *reply;
+    bool first;
+};
+
+static int
+qemudMonitorCommandSimpleExtraHandler(const virDomainObjPtr vm,
+                                      const char *buf ATTRIBUTE_UNUSED,
+                                      const char *prompt ATTRIBUTE_UNUSED,
+                                      void *data_)
+{
+    struct extraHandlerData *data = data_;
+    size_t len;
+
+    if (!data->first)
+        return 0;
+    len = strlen(data->reply);
+    if (safewrite(vm->monitor, data->reply, len) != len)
+        return -1;
+    if (safewrite(vm->monitor, "\r", 1) != 1)
+        return -1;
+    data->first = false;
+    return 0;
+}
+
+static int
+qemudMonitorCommandExtra(const virDomainObjPtr vm,
+                         const char *cmd,
+                         const char *extra,
+                         const char *extraPrompt,
+                         char **reply) {
+    struct extraHandlerData data;
+
+    data.reply = extra;
+    data.first = true;
+    return qemudMonitorCommandWithHandler(vm, cmd, extraPrompt,
+                                          qemudMonitorCommandSimpleExtraHandler,
+                                          &data, reply);
+}
+
 static int
 qemudMonitorCommand(const virDomainObjPtr vm,
                     const char *cmd,
-- 
1.6.2.5




More information about the libvir-list mailing list