prototype of dumm GUI
authorMartin Willi <martin@strongswan.org>
Mon, 28 Apr 2008 16:43:30 +0000 (16:43 -0000)
committerMartin Willi <martin@strongswan.org>
Mon, 28 Apr 2008 16:43:30 +0000 (16:43 -0000)
13 files changed:
configure.in
src/dumm/Makefile.am
src/dumm/bridge.c
src/dumm/bridge.h
src/dumm/dumm.c
src/dumm/dumm.h
src/dumm/guest.c
src/dumm/guest.h
src/dumm/iface.c
src/dumm/iface.h
src/dumm/main.c
src/dumm/mconsole.c
src/dumm/mconsole.h

index 30a9f28..9751651 100644 (file)
@@ -20,6 +20,7 @@ AC_INIT(strongSwan,4.2.2)
 AM_INIT_AUTOMAKE(tar-ustar)
 AC_C_BIGENDIAN
 AC_SUBST(confdir, '${sysconfdir}')
+PKG_PROG_PKG_CONFIG
 
 dnl =================================
 dnl  check --enable-xxx & --with-xxx
@@ -581,11 +582,17 @@ if test x$curl = xtrue; then
 fi
 
 if test x$xml = xtrue; then
-       PKG_CHECK_MODULES(xml, [libxml-2.0],, AC_MSG_ERROR([No libxml2 package information found]))
+       PKG_CHECK_MODULES(xml, [libxml-2.0])
        AC_SUBST(xml_CFLAGS)
        AC_SUBST(xml_LIBS)
 fi
 
+if test x$dumm = xtrue; then
+       PKG_CHECK_MODULES(gtk, [gtk+-2.0 vte])
+       AC_SUBST(gtk_CFLAGS)
+       AC_SUBST(gtk_LIBS)
+fi
+
 if test x$fast = xtrue; then
        AC_HAVE_LIBRARY([neo_cgi],[LIBS="$LIBS"],[AC_MSG_ERROR([ClearSilver library neo_cgi not found!])])
        AC_HAVE_LIBRARY([neo_utl],[LIBS="$LIBS"],[AC_MSG_ERROR([ClearSilver library neo_utl not found!])])
index 3356e7a..58d19f5 100644 (file)
@@ -1,12 +1,12 @@
 lib_LTLIBRARIES = libdumm.la
 ipsec_PROGRAMS = dumm
 
-libdumm_la_SOURCES = dumm.c dumm.h guest.c guest.h iface.c iface.h bridge.c bridge.h mconsole.c mconsole.h cowfs.h cowfs.c
+libdumm_la_SOURCES = dumm.c dumm.h guest.c guest.h iface.c iface.h \
+  bridge.c bridge.h mconsole.c mconsole.h cowfs.h cowfs.c
 dumm_SOURCES = main.c
 
-libdumm_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lpthread -lbridge -lfuse -lutil ${xml_LIBS}
-dumm_LDADD = -ldumm -lreadline
-
-INCLUDES = -I$(top_srcdir)/src/libstrongswan ${xml_CFLAGS}
+libdumm_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lbridge -lfuse -lutil
+dumm_LDADD = -ldumm ${gtk_LIBS}
 
+INCLUDES = -I$(top_srcdir)/src/libstrongswan ${gtk_CFLAGS}
 AM_CFLAGS = -D_FILE_OFFSET_BITS=64
index 1230dc0..73659ea 100644 (file)
@@ -31,6 +31,11 @@ struct private_bridge_t {
        /** list of attached interfaces */
        linked_list_t *ifaces;
 };
+
+/**
+ * defined in iface.c
+ */
+bool iface_control(char *name, bool up);
        
 /**
  * Implementation of bridge_t.get_name.
@@ -41,11 +46,11 @@ static char* get_name(private_bridge_t *this)
 }
 
 /**
- * Implementation of bridge_t.create_iface_iterator.
+ * Implementation of bridge_t.create_iface_enumerator.
  */
-static iterator_t* create_iface_iterator(private_bridge_t *this)
+static enumerator_t* create_iface_enumerator(private_bridge_t *this)
 {
-       return this->ifaces->create_iterator(this->ifaces, TRUE);
+       return this->ifaces->create_enumerator(this->ifaces);
 }
 
 /**
@@ -53,12 +58,12 @@ static iterator_t* create_iface_iterator(private_bridge_t *this)
  */
 static bool disconnect_iface(private_bridge_t *this, iface_t *iface)
 {
-       iterator_t *iterator;
+       enumerator_t *enumerator;
        iface_t *current;
        bool good = FALSE;
 
-       iterator = this->ifaces->create_iterator(this->ifaces, TRUE);
-       while (iterator->iterate(iterator, (void**)&current))
+       enumerator = this->ifaces->create_enumerator(this->ifaces);
+       while (enumerator->enumerate(enumerator, (void**)&current))
        {
                if (current == iface)
                {
@@ -80,7 +85,7 @@ static bool disconnect_iface(private_bridge_t *this, iface_t *iface)
                DBG1("iface '%s' not found on bridge '%s'", iface->get_hostif(iface),
                         this->name);
        }
-       iterator->destroy(iterator);
+       enumerator->destroy(enumerator);
        return good;
 }
 
@@ -120,6 +125,7 @@ static void destroy(private_bridge_t *this)
 {
        this->ifaces->invoke_function(this->ifaces, (linked_list_invoke_t)unregister);
        this->ifaces->destroy(this->ifaces);
+       iface_control(this->name, FALSE);
        if (br_del_bridge(this->name) != 0)
        {
                DBG1("deleting bridge '%s' from kernel failed: %m", this->name);
@@ -150,7 +156,7 @@ bridge_t *bridge_create(char *name)
        
        this = malloc_thing(private_bridge_t);
        this->public.get_name = (char*(*)(bridge_t*))get_name;
-       this->public.create_iface_iterator = (iterator_t*(*)(bridge_t*))create_iface_iterator;
+       this->public.create_iface_enumerator = (enumerator_t*(*)(bridge_t*))create_iface_enumerator;
        this->public.disconnect_iface = (bool(*)(bridge_t*, iface_t *iface))disconnect_iface;
        this->public.connect_iface = (bool(*)(bridge_t*, iface_t *iface))connect_iface;
        this->public.destroy = (void*)destroy;
@@ -161,6 +167,10 @@ bridge_t *bridge_create(char *name)
                free(this);
                return NULL;
        }
+       if (!iface_control(name, TRUE))
+       {
+               DBG1("bringing bridge '%s' up failed: %m", name);
+       }
 
        this->name = strdup(name);
        this->ifaces = linked_list_create();
index 6d28ed3..79a0a3a 100644 (file)
@@ -17,7 +17,7 @@
 #define BRIDGE_H
 
 #include <library.h>
-#include <utils/iterator.h>
+#include <utils/enumerator.h>
 
 typedef struct bridge_t bridge_t;
 
@@ -31,32 +31,32 @@ struct bridge_t {
        /**
         * @brief Get the name of the bridge.
         *
-        * @return                              name of the bridge
+        * @return                      name of the bridge
         */
        char* (*get_name)(bridge_t *this);
        
        /**
         * @brief Add an interface to a bridge.
         *
-        * @param iface                 interface to add
-        * @return                              TRUE if interface added
+        * @param iface         interface to add
+        * @return                      TRUE if interface added
         */
        bool (*connect_iface)(bridge_t *this, iface_t *iface);
        
        /**
         * @brief Remove an interface from a bridge.
         *
-        * @param iface                 interface to remove
-        * @return                              TRUE if interface removed
+        * @param iface         interface to remove
+        * @return                      TRUE if interface removed
         */
        bool (*disconnect_iface)(bridge_t *this, iface_t *iface);
        
        /**
-        * @brief Create an iterator over all interfaces.
+        * @brief Create an enumerator over all interfaces.
         *
-        * @return                              iterator over iface_t's
+        * @return                      enumerator over iface_t's
         */
-       iterator_t* (*create_iface_iterator)(bridge_t *this);   
+       enumerator_t* (*create_iface_enumerator)(bridge_t *this);       
        
        /**
         * @brief Destroy a bridge
index b9a2814..5db8eae 100644 (file)
@@ -23,6 +23,7 @@
 #include <errno.h>
 
 #include <debug.h>
+#include <utils/linked_list.h>
 
 #include "dumm.h"
 
 #define TEMPLATE_DIR "templates"
 #define TEMPLATE_DIR_DIR "diff"
 
-/**
- * instances of dumm, used to deliver signals
- */
-static linked_list_t *instances = NULL;
-
 typedef struct private_dumm_t private_dumm_t;
 
 struct private_dumm_t {
@@ -74,11 +70,31 @@ static guest_t* create_guest(private_dumm_t *this, char *name, char *kernel,
 }
 
 /**
- * Implementation of dumm_t.create_guest_iterator.
+ * Implementation of dumm_t.create_guest_enumerator.
+ */
+static enumerator_t* create_guest_enumerator(private_dumm_t *this)
+{
+       return this->guests->create_enumerator(this->guests);
+}
+
+/**
+ * Implementation of dumm_t.delete_guest.
  */
-static iterator_t* create_guest_iterator(private_dumm_t *this)
+static void delete_guest(private_dumm_t *this, guest_t *guest)
 {
-       return this->guests->create_iterator(this->guests, TRUE);
+       if (this->guests->remove(this->guests, guest, NULL))
+       {
+               char buf[512];
+               int len;
+               
+               len = snprintf(buf, sizeof(buf), "rm -Rf %s/%s",
+                                          this->guest_dir, guest->get_name(guest));
+               guest->destroy(guest);
+               if (len > 8 && len < 512)
+               {
+                       system(buf);
+               }
+       }
 }
 
 /**
@@ -97,11 +113,22 @@ static bridge_t* create_bridge(private_dumm_t *this, char *name)
 }
 
 /**
- * Implementation of dumm_t.create_bridge_iterator.
+ * Implementation of dumm_t.create_bridge_enumerator.
+ */
+static enumerator_t* create_bridge_enumerator(private_dumm_t *this)
+{
+       return this->bridges->create_enumerator(this->bridges);
+}
+
+/**
+ * Implementation of dumm_t.delete_bridge.
  */
-static iterator_t* create_bridge_iterator(private_dumm_t *this)
+static void delete_bridge(private_dumm_t *this, bridge_t *bridge)
 {
-       return this->bridges->create_iterator(this->bridges, TRUE);
+       if (this->bridges->remove(this->bridges, bridge, NULL))
+       {
+               bridge->destroy(bridge);
+       }
 }
 
 /**
@@ -109,26 +136,18 @@ static iterator_t* create_bridge_iterator(private_dumm_t *this)
  */
 static void clear_template(private_dumm_t *this)
 {
-       iterator_t *iterator, *ifaces;
+       enumerator_t *enumerator;
        guest_t *guest;
-       iface_t *iface;
 
        free(this->template);
        this->template = NULL;
 
-       iterator = this->guests->create_iterator(this->guests, TRUE);
-       while (iterator->iterate(iterator, (void**)&guest))
+       enumerator = this->guests->create_enumerator(this->guests);
+       while (enumerator->enumerate(enumerator, (void**)&guest))
        {
                guest->load_template(guest, NULL);
-               ifaces = guest->create_iface_iterator(guest);
-               while (ifaces->iterate(ifaces, (void**)&iface))
-               {
-                       ifaces->remove(ifaces);
-                       iface->destroy(iface);
-               }
-               ifaces->destroy(ifaces);
        }
-       iterator->destroy(iterator);
+       enumerator->destroy(enumerator);
 }
 
 /**
@@ -136,7 +155,7 @@ static void clear_template(private_dumm_t *this)
  */
 static bool load_template(private_dumm_t *this, char *name)
 {
-       iterator_t *iterator;
+       enumerator_t *enumerator;
        guest_t *guest;
        char dir[PATH_MAX];
        size_t len;
@@ -169,131 +188,36 @@ static bool load_template(private_dumm_t *this, char *name)
                        return FALSE;
                }
        }
-       iterator = this->guests->create_iterator(this->guests, TRUE);
-       while (iterator->iterate(iterator, (void**)&guest))
+       enumerator = this->guests->create_enumerator(this->guests);
+       while (enumerator->enumerate(enumerator, (void**)&guest))
        {
                if (!guest->load_template(guest, dir))
                {
-                       iterator->destroy(iterator);
+                       enumerator->destroy(enumerator);
                        clear_template(this);
                        return FALSE;
                }
        }
-       iterator->destroy(iterator);
+       enumerator->destroy(enumerator);
        return TRUE;
 }
 
 /**
- * signal handler 
- */
-void signal_handler(int sig, siginfo_t *info, void *ucontext)
-{
-       if (sig == SIGCHLD)
-       {
-               switch (info->si_code)
-               {
-                       case CLD_EXITED:
-                       case CLD_KILLED:
-                       case CLD_DUMPED:
-                       {
-                               private_dumm_t *this;
-                               guest_t *guest;
-                               iterator_t *iterator, *guests;
-                               
-                               iterator = instances->create_iterator(instances, TRUE);
-                               while (iterator->iterate(iterator, (void**)&this))
-                               {
-                                       if (this->destroying)
-                                       {
-                                               continue;
-                                       }
-                                       guests = this->guests->create_iterator(this->guests, TRUE);
-                                       while (guests->iterate(guests, (void**)&guest))
-                                       {
-                                               if (guest->get_pid(guest) == info->si_pid)
-                                               {
-                                                       guest->sigchild(guest);
-                                                       break;
-                                               }
-                                       }
-                                       guests->destroy(guests);
-                               }
-                               iterator->destroy(iterator);
-                               break;
-                       }
-                       default:
-                               break;
-               }
-
-       }
-       /* SIGHUP is currently just ignored */
-}
-
-/**
- * add a dumm instance
- */
-static void add_instance(private_dumm_t *this)
-{
-       if (instances == NULL)
-       {
-               struct sigaction action;
-               
-               instances = linked_list_create();
-               
-               memset(&action, 0, sizeof(action));
-               action.sa_sigaction = signal_handler;
-               action.sa_flags = SA_SIGINFO;
-               
-               if (sigaction(SIGCHLD, &action, NULL) != 0 ||
-                       sigaction(SIGHUP, &action, NULL) != 0)
-               {
-                       DBG1("installing signal handler failed!");
-               }
-       }
-       instances->insert_last(instances, this);
-}
-
-/**
- * remove a dumm instance
- */
-static void remove_instance(private_dumm_t *this)
-{
-       iterator_t *iterator;
-       private_dumm_t *current;
-       
-       iterator = instances->create_iterator(instances, TRUE);
-       while (iterator->iterate(iterator, (void**)&current))
-       {
-               if (current == this)
-               {
-                       iterator->remove(iterator);
-                       break;
-               }
-       }
-       iterator->destroy(iterator);
-       if (instances->get_count(instances) == 0)
-       {
-               instances->destroy(instances);
-               instances = NULL;
-       }
-}
-
-/**
  * Implementation of dumm_t.destroy
  */
 static void destroy(private_dumm_t *this)
 {
-       iterator_t *iterator;
+       enumerator_t *enumerator;
        guest_t *guest;
 
        this->bridges->destroy_offset(this->bridges, offsetof(bridge_t, destroy));
        
-       iterator = this->guests->create_iterator(this->guests, TRUE);
-       while (iterator->iterate(iterator, (void**)&guest))
+       enumerator = this->guests->create_enumerator(this->guests);
+       while (enumerator->enumerate(enumerator, (void**)&guest))
        {
-               guest->stop(guest);
+               guest->stop(guest, NULL);
        }
-       iterator->destroy(iterator);
+       enumerator->destroy(enumerator);
        
        this->destroying = TRUE;
        this->guests->destroy_offset(this->guests, offsetof(guest_t, destroy));
@@ -301,7 +225,6 @@ static void destroy(private_dumm_t *this)
        free(this->template_dir);
        free(this->template);
        free(this->dir);
-       remove_instance(this);
        free(this);
 }
 
@@ -329,7 +252,6 @@ static void load_guests(private_dumm_t *this)
                guest = guest_load(this->guest_dir, ent->d_name);
                if (guest)
                {
-                       DBG1("loaded guest '%s'", ent->d_name);
                        this->guests->insert_last(this->guests, guest);
                }
                else
@@ -349,20 +271,35 @@ dumm_t *dumm_create(char *dir)
        private_dumm_t *this = malloc_thing(private_dumm_t);
        
        this->public.create_guest = (guest_t*(*)(dumm_t*,char*,char*,char*,int))create_guest;
-       this->public.create_guest_iterator = (iterator_t*(*)(dumm_t*))create_guest_iterator;
+       this->public.create_guest_enumerator = (enumerator_t*(*)(dumm_t*))create_guest_enumerator;
+       this->public.delete_guest = (void(*)(dumm_t*,guest_t*))delete_guest;
        this->public.create_bridge = (bridge_t*(*)(dumm_t*, char *name))create_bridge;
-       this->public.create_bridge_iterator = (iterator_t*(*)(dumm_t*))create_bridge_iterator;
+       this->public.create_bridge_enumerator = (enumerator_t*(*)(dumm_t*))create_bridge_enumerator;
+       this->public.delete_bridge = (void(*)(dumm_t*,bridge_t*))delete_bridge;
        this->public.load_template = (bool(*)(dumm_t*, char *name))load_template;
        this->public.destroy = (void(*)(dumm_t*))destroy;
        
        this->destroying = FALSE;
-       if (*dir == '/' || getcwd(cwd, sizeof(cwd)) == 0)
+       
+       if (dir && *dir == '/')
        {
                this->dir = strdup(dir);
        }
        else
        {
-               asprintf(&this->dir, "%s/%s", cwd, dir);
+               if (getcwd(cwd, sizeof(cwd)) == NULL)
+               {
+                       free(this);
+                       return NULL;
+               }
+               if (dir)
+               {
+                       asprintf(&this->dir, "%s/%s", cwd, dir);
+               }
+               else
+               {
+                       this->dir = strdup(cwd);
+               }
        }
        this->template = NULL;
        asprintf(&this->guest_dir, "%s/%s", this->dir, GUEST_DIR);
@@ -370,8 +307,6 @@ dumm_t *dumm_create(char *dir)
        this->guests = linked_list_create();
        this->bridges = linked_list_create();
        
-       add_instance(this);
-       
        if (mkdir(this->guest_dir, PERME) < 0 && errno != EEXIST)
        {
                DBG1("creating guest directory '%s' failed: %m", this->guest_dir);
index 5414f99..6abf4fc 100644 (file)
@@ -19,7 +19,7 @@
 #include <signal.h>
 
 #include <library.h>
-#include <utils/linked_list.h>
+#include <utils/enumerator.h>
 
 #include "guest.h"
 #include "bridge.h"
@@ -30,8 +30,6 @@ typedef struct dumm_t dumm_t;
  * @brief dumm - Dynamic Uml Mesh Modeler
  *
  * Controls a group of UML guests and their networks.
- * Dumm catches SIGCHD and SIGHUP to trace UML child processes and the FUSE
- * filesystem. Do not overwrite these signal handlers!
  */
 struct dumm_t {
 
@@ -48,11 +46,18 @@ struct dumm_t {
                                                          char *master, int mem);
        
        /**
-        * @brief Create an iterator over all guests.
+        * @brief Create an enumerator over all guests.
         *
-        * @return                      iteraotor over guest_t's
+        * @return                      enumerator over guest_t's
         */
-       iterator_t* (*create_guest_iterator) (dumm_t *this);
+       enumerator_t* (*create_guest_enumerator) (dumm_t *this);
+       
+       /**
+        * @brief Delete a guest from disk.
+        *
+        * @param guest         guest to destroy
+        */
+       void (*delete_guest) (dumm_t *this, guest_t *guest);
        
        /**
         * @brief Create a new bridge.
@@ -63,11 +68,18 @@ struct dumm_t {
        bridge_t* (*create_bridge)(dumm_t *this, char *name);
        
        /**
-        * @brief Create an iterator over all bridges.
+        * @brief Create an enumerator over all bridges.
+        *
+        * @return                      enumerator over bridge_t's
+        */
+       enumerator_t* (*create_bridge_enumerator)(dumm_t *this);
+       
+       /**
+        * @brief Delete a bridge.
         *
-        * @return                      iterator over bridge_t's
+        * @param bridge        bridge to destroy
         */
-       iterator_t* (*create_bridge_iterator)(dumm_t *this);
+       void (*delete_bridge) (dumm_t *this, bridge_t *bridge);
        
        /**
         * @brief Loads a template, create a new one if it does not exist.
@@ -86,7 +98,7 @@ struct dumm_t {
 /**
  * @brief Create a group of UML hosts and networks.
  *
- * @param dir                  directory to create guests/load from
+ * @param dir                  directory to create guests/load from, NULL for cwd
  * @return                             created UML group, or NULL if failed.
  */
 dumm_t *dumm_create(char *dir);
index bbb59f4..58539b7 100644 (file)
@@ -63,8 +63,6 @@ struct private_guest_t {
        int pid;
        /** state of guest */
        guest_state_t state;
-       /** log file for console 0 */
-       int bootlog;
        /** FUSE cowfs instance */
        cowfs_t *cowfs;
        /** mconsole to control running UML */
@@ -94,7 +92,7 @@ static char* get_name(private_guest_t *this)
  */
 static iface_t* create_iface(private_guest_t *this, char *name)
 {
-       iterator_t *iterator;
+       enumerator_t *enumerator;
        iface_t *iface;
        
        if (this->state != GUEST_RUNNING)
@@ -103,17 +101,17 @@ static iface_t* create_iface(private_guest_t *this, char *name)
                return NULL;
        }
        
-       iterator = this->ifaces->create_iterator(this->ifaces, TRUE);
-       while (iterator->iterate(iterator, (void**)&iface))
+       enumerator = this->ifaces->create_enumerator(this->ifaces);
+       while (enumerator->enumerate(enumerator, (void**)&iface))
        {
                if (streq(name, iface->get_guestif(iface)))
                {
                        DBG1("guest '%s' already has an interface '%s'", this->name, name);
-                       iterator->destroy(iterator);
+                       enumerator->destroy(enumerator);
                        return NULL;
                }
        }
-       iterator->destroy(iterator);
+       enumerator->destroy(enumerator);
 
        iface = iface_create(this->name, name, this->mconsole);
        if (iface)
@@ -124,11 +122,32 @@ static iface_t* create_iface(private_guest_t *this, char *name)
 }
 
 /**
- * Implementation of guest_t.create_iface_iterator.
+ * Implementation of guest_t.destroy_iface.
  */
-static iterator_t* create_iface_iterator(private_guest_t *this)
+static void destroy_iface(private_guest_t *this, iface_t *iface)
 {
-       return this->ifaces->create_iterator(this->ifaces, TRUE);
+       enumerator_t *enumerator;
+       iface_t *current;
+       
+       enumerator = this->ifaces->create_enumerator(this->ifaces);
+       while (enumerator->enumerate(enumerator, (void**)&current))
+       {
+               if (current == iface)
+               {
+                       this->ifaces->remove_at(this->ifaces, enumerator);
+                       current->destroy(current);
+                       break;
+               }
+       }
+       enumerator->destroy(enumerator);
+}
+
+/**
+ * Implementation of guest_t.create_iface_enumerator.
+ */
+static enumerator_t* create_iface_enumerator(private_guest_t *this)
+{
+       return this->ifaces->create_enumerator(this->ifaces);
 }
        
 /**
@@ -170,21 +189,9 @@ static char* write_arg(char **pos, size_t *left, char *format, ...)
 }
 
 /**
- * Implementation of get_t.close_console.
- */
-static char* get_console(private_guest_t *this, int console)
-{
-       if (this->state == GUEST_RUNNING)
-       {
-               return this->mconsole->get_console_pts(this->mconsole, console);
-       }
-       return NULL;
-}
-
-/**
  * Implementation of guest_t.stop.
  */
-static void stop(private_guest_t *this)
+static void stop(private_guest_t *this, idle_function_t idle)
 {
        if (this->state != GUEST_STOPPED)
        {
@@ -192,23 +199,35 @@ static void stop(private_guest_t *this)
                this->ifaces->destroy_offset(this->ifaces, offsetof(iface_t, destroy));
                this->ifaces = linked_list_create();
                kill(this->pid, SIGINT);
-               waitpid(this->pid, NULL, 0);
-               this->state = GUEST_STOPPED;
+               while (this->state != GUEST_STOPPED)
+               {
+                       if (idle)
+                       {
+                               idle();
+                       }
+                       else
+                       {
+                               usleep(50000);
+                       }
+               }
        }
 }
 
 /**
  * Implementation of guest_t.start.
  */
-static bool start(private_guest_t *this)
+static bool start(private_guest_t *this, invoke_function_t invoke, void* data,
+                                 idle_function_t idle)
 {
        char buf[2048];
        char *notify;
        char *pos = buf;
-       char *args[16];
+       char *args[32];
        int i = 0;
        size_t left = sizeof(buf);
        
+       memset(args, 0, sizeof(args));
+       
        if (this->state != GUEST_STOPPED)
        {
                DBG1("unable to start guest in state %N", guest_state_names, this->state);
@@ -226,32 +245,20 @@ static bool start(private_guest_t *this)
        args[i++] = write_arg(&pos, &left, "umid=%s", this->name);
        args[i++] = write_arg(&pos, &left, "mem=%dM", this->mem);
        args[i++] = write_arg(&pos, &left, "mconsole=notify:%s", notify);
-       args[i++] = write_arg(&pos, &left, "con=pts");
-       args[i++] = write_arg(&pos, &left, "con0=none,fd:%d", this->bootlog);
-       args[i++] = NULL;
+       args[i++] = write_arg(&pos, &left, "con=null");
          
-       this->pid = fork();
-       switch (this->pid)
-       {
-               case 0: /* child,  */
-                       dup2(open("/dev/null", 0), 0);
-                       dup2(this->bootlog, 1);
-                       dup2(this->bootlog, 2);
-                       execvp(args[0], args);
-                       DBG1("starting UML kernel '%s' failed: %m", args[0]);
-                       exit(1);
-               case -1:
-                       this->state = GUEST_STOPPED;
-                       return FALSE;
-               default:
-                       break;
+       this->pid = invoke(data, &this->public, args, i);
+       if (!this->pid)
+       {
+               this->state = GUEST_STOPPED;
+               return FALSE;
        }
        /* open mconsole */
-       this->mconsole = mconsole_create(notify);
+       this->mconsole = mconsole_create(notify, idle);
        if (this->mconsole == NULL)
        {
                DBG1("opening mconsole at '%s' failed, stopping guest", buf);
-               stop(this);
+               stop(this, NULL);
                return FALSE;
        }
        
@@ -266,6 +273,7 @@ static bool load_template(private_guest_t *this, char *path)
 {
        char dir[PATH_MAX];
        size_t len;
+       iface_t *iface;
        
        if (path == NULL)
        {
@@ -285,7 +293,15 @@ static bool load_template(private_guest_t *this, char *path)
                        return FALSE;
                }
        }
-       return this->cowfs->set_overlay(this->cowfs, dir);
+       if (!this->cowfs->set_overlay(this->cowfs, dir))
+       {
+               return FALSE;
+       }
+       while (this->ifaces->remove_last(this->ifaces, (void**)&iface) == SUCCESS)
+       {
+               iface->destroy(iface);
+       }
+       return TRUE;
 }
 
 /**
@@ -293,10 +309,6 @@ static bool load_template(private_guest_t *this, char *path)
  */
 static void sigchild(private_guest_t *this)
 {
-       if (this->state != GUEST_STOPPING)
-       {       /* collect zombie if uml crashed */
-               waitpid(this->pid, NULL, WNOHANG);
-       }
        DESTROY_IF(this->mconsole);
        this->mconsole = NULL;
        this->state = GUEST_STOPPED;
@@ -341,22 +353,6 @@ static bool mount_unionfs(private_guest_t *this)
 }
 
 /**
- * open logfile for boot messages
- */
-static int open_bootlog(private_guest_t *this)
-{
-       int fd;
-       
-       fd = openat(this->dir, LOG_FILE, O_WRONLY | O_CREAT, PERM);
-       if (fd == -1)
-       {
-               DBG1("opening bootlog failed, using stdout");
-               return 1;
-       }
-       return fd;
-}
-
-/**
  * load memory configuration from file
  */
 int loadmem(private_guest_t *this)
@@ -402,12 +398,8 @@ bool savemem(private_guest_t *this, int mem)
  */
 static void destroy(private_guest_t *this)
 {
-       stop(this);
+       stop(this, NULL);
        umount_unionfs(this);
-       if (this->bootlog > 1)
-       {
-               close(this->bootlog);
-       }
        if (this->dir > 0)
        {
                close(this->dir);
@@ -430,10 +422,10 @@ static private_guest_t *guest_create_generic(char *parent, char *name,
        this->public.get_pid = (pid_t(*)(guest_t*))get_pid;
        this->public.get_state = (guest_state_t(*)(guest_t*))get_state;
        this->public.create_iface = (iface_t*(*)(guest_t*,char*))create_iface;
-       this->public.create_iface_iterator = (iterator_t*(*)(guest_t*))create_iface_iterator;
+       this->public.destroy_iface = (void(*)(guest_t*,iface_t*))destroy_iface;
+       this->public.create_iface_enumerator = (enumerator_t*(*)(guest_t*))create_iface_enumerator;
        this->public.start = (void*)start;
        this->public.stop = (void*)stop;
-       this->public.get_console = (char*(*)(guest_t*,int))get_console;
        this->public.load_template = (bool(*)(guest_t*, char *path))load_template;
        this->public.sigchild = (void(*)(guest_t*))sigchild;
        this->public.destroy = (void*)destroy;
@@ -464,7 +456,6 @@ static private_guest_t *guest_create_generic(char *parent, char *name,
        this->mconsole = NULL;
        this->ifaces = linked_list_create();
        this->mem = 0;
-       this->bootlog = open_bootlog(this);
        this->name = strdup(name);
        this->cowfs = NULL;
        
index 10b37aa..79a47fa 100644 (file)
 #define GUEST_H
 
 #include <library.h>
-#include <utils/iterator.h>
+#include <utils/enumerator.h>
 
 #include "iface.h"
 
 typedef enum guest_state_t guest_state_t;
+typedef struct guest_t guest_t;
 
 /**
  * @brief State of a guest (started, stopped, ...)
@@ -44,7 +45,26 @@ enum guest_state_t {
  */
 extern enum_name_t *guest_state_names;
 
-typedef struct guest_t guest_t;
+/**
+ * Invoke function which lauches the UML guest.
+ *
+ * Consoles are all set to NULL, you may change them by adding additional UML
+ * options to args before invocation.
+ *
+ * @param data         callback data
+ * @param guest                guest to start
+ * @param args         args to use for guest invocation, args[0] is kernel
+ * @param argc         number of elements in args
+ * @param idle         
+ * @return                     PID of child, 0 if failed
+ */
+typedef pid_t (*invoke_function_t)(void *data, guest_t *guest, 
+                                                                  char *args[], int argc);
+
+/**
+ * Idle function to pass to start().
+ */
+typedef void (*idle_function_t)(void);
 
 /**
  * @brief A guest is a UML instance running on the host.
@@ -75,27 +95,21 @@ struct guest_t {
        /**
         * @brief Start the guest.
         *
-        * @return              TRUE if guest successfully started
+        * @param invoke        UML guest invocation function
+        * @param data          data to pass back to invoke function
+        * @param idle          idle function to call while waiting on child
+        * @return                      TRUE if guest successfully started
         */
-       bool (*start) (guest_t *this);
+       bool (*start) (guest_t *this, invoke_function_t invoke, void *data,
+                                  idle_function_t idle);
        
        /**
         * @brief Kill the guest.
         *
-        * @return              TRUE if guest was running and killed
+        * @param idle          idle function to call while waiting to termination
+        * @return                      TRUE if guest was running and killed
         */
-       bool (*stop) (guest_t *this);
-       
-       /**
-        * @brief Get a console pts device.
-        *
-        * Every guest has 5 consoles, numbered from 1 to 5. These are associated
-        * to a unique pts device on the host. 
-        *
-        * @param console       console number to get (1-5)
-        * @return                      pts device file name, NULL if failed
-        */
-       char* (*get_console) (guest_t *this, int console);
+       bool (*stop) (guest_t *this, idle_function_t idle);
        
        /**
         * @brief Create a new interface in the current scenario.
@@ -106,11 +120,18 @@ struct guest_t {
        iface_t* (*create_iface)(guest_t *this, char *name);
        
        /**
-        * @brief Create an iterator over all guest interfaces.
+        * @brief Destroy an interface on guest.
+        *
+        * @param iface interface to destroy
+        */
+       void (*destroy_iface)(guest_t *this, iface_t *iface);
+       
+       /**
+        * @brief Create an enumerator over all guest interfaces.
         *
-        * @return              iterator over iface_t's
+        * @return              enumerator over iface_t's
         */
-       iterator_t* (*create_iface_iterator)(guest_t *this);
+       enumerator_t* (*create_iface_enumerator)(guest_t *this);
        
        /**
         * @brief Set the template COWFS overlay to use.
index 3c1bfc4..b78c10b 100644 (file)
@@ -44,6 +44,42 @@ struct private_iface_t {
 };
 
 /**
+ * bring an interface up or down
+ */
+bool iface_control(char *name, bool up)
+{
+       int s;
+       bool good = FALSE;
+       struct ifreq ifr;
+       
+       memset(&ifr, 0, sizeof(struct ifreq));
+       strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (!s)
+       {
+               return FALSE;
+       }
+       if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0)
+       {
+               if (up)
+               {
+                       ifr.ifr_flags |= IFF_UP;
+               }
+               else
+               {
+                       ifr.ifr_flags &= ~IFF_UP;
+               }
+               if (ioctl(s, SIOCSIFFLAGS, &ifr) == 0)
+               {
+                       good = TRUE;
+               }
+       }
+       close(s);
+       return good;
+}
+
+/**
  * Implementation of iface_t.get_guestif.
  */
 static char* get_guestif(private_iface_t *this)
@@ -74,7 +110,11 @@ static bool destroy_tap(private_iface_t *this)
 {
        struct ifreq ifr;
        int tap;
-
+       
+       if (!iface_control(this->hostif, FALSE))
+       {
+               DBG1("bringing iface down failed: %m");
+       }
        memset(&ifr, 0, sizeof(ifr));
        ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
        strncpy(ifr.ifr_name, this->hostif, sizeof(ifr.ifr_name) - 1);
@@ -165,6 +205,10 @@ iface_t *iface_create(char *guest, char *guestif, mconsole_t *mconsole)
                free(this);
                return NULL;
        }
+       if (!iface_control(this->hostif, TRUE))
+       {
+               DBG1("bringing iface '%s' up failed: %m", this->hostif);
+       }
        if (!this->mconsole->add_iface(this->mconsole, this->guestif, this->hostif))
        {
                DBG1("creating interface '%s' in guest failed", this->guestif);
index 59de99f..e04fe4e 100644 (file)
@@ -17,7 +17,7 @@
 #define IFACE_H
 
 #include <library.h>
-#include <utils/iterator.h>
+#include <utils/enumerator.h>
 
 #define TAP_DEVICE "/dev/net/tun"
 
@@ -53,10 +53,8 @@ struct iface_t {
        void (*set_bridge)(iface_t *this, bridge_t *bridge);
        
        /*
-       bool (*up) (iface_t *this);
-       bool (*down) (iface_t *this);
        bool (*add_addr) (iface_t *this, host_t *addr);
-       iterator_t* (*create_addr_iterator) (iface_t *this);
+       enumerator_t* (*create_addr_enumerator) (iface_t *this);
        */
        
        /**
index b996021..e8c7bf7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Martin Willi
+ * Copyright (C) 2008 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
  * for more details.
  */
 
-#define _GNU_SOURCE
+#include "dumm.h"
+
+#include <utils/linked_list.h>
 
-#include <stdio.h>
+#include <sys/types.h>
 #include <unistd.h>
-#include <getopt.h>
-#include <library.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-#include <dlfcn.h>
-#include <dirent.h>
 
-#include "dumm.h"
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <vte/vte.h>
+#include <vte/reaper.h>
 
 /**
- * global set of UMLs guests
+ * notebook page with vte and guest
  */
-dumm_t *dumm;
+typedef struct {
+       gint num;
+       GtkWidget *vte;
+       guest_t *guest;
+} page_t;
 
 /**
- * show usage information (program arguments)
+ * Main window
  */
-static void usage()
-{
-       printf("Usage:\n");
-       printf("  --dir|-d <path>            set working dir to <path>\n");
-       printf("  --help|-h                  show this help\n");
-}
+GtkWidget *window;
 
 /**
- * readline() wrapper
+ * notebook with guests, vtes
  */
-static char* get_line(char *format, ...)
-{
-       char *line = NULL;
-       char *prompt = "";
-       va_list args;
-       
-       va_start(args, format);
-       vasprintf(&prompt, format, args);
-       va_end(args);
-       
-       while (TRUE)
-       {
-               line = readline(prompt);
-               if (line == NULL)
-               {
-                       printf("quit\n");
-                       dumm->destroy(dumm);
-                       clear_history();
-                       exit(0);
-               }
-               if (*line == '\0')
-               {
-                       free(line);
-                       continue;
-               }
-               add_history(line);
-               break;
-       }
-       free(prompt);
-       return line;
-}
+GtkWidget *notebook;
+
+/**
+ * dumm context
+ */
+dumm_t *dumm;
+
+/**
+ * pages in notebook, page_t
+ */
+linked_list_t *pages;
 
 /**
- * get a guest by name
+ * handle guest termination, SIGCHILD
  */
-static guest_t* get_guest(char *name)
+static void child_exited(VteReaper *vtereaper, gint pid, gint status)
 {
-       iterator_t *iterator;
-       guest_t *guest = NULL;
+       enumerator_t *enumerator;
+       page_t *page;
        
-       iterator = dumm->create_guest_iterator(dumm);
-       while (iterator->iterate(iterator, (void**)&guest))
+       enumerator = pages->create_enumerator(pages);
+       while (enumerator->enumerate(enumerator, (void**)&page))
        {
-               if (streq(guest->get_name(guest), name))
+               if (page->guest->get_pid(page->guest) == pid)
                {
+                       page->guest->sigchild(page->guest);
+                       vte_terminal_feed(VTE_TERMINAL(page->vte),
+                                                         "\n\r--- guest terminated ---\n\r", -1);
                        break;
                }
-               guest = NULL;
        }
-       iterator->destroy(iterator);
-       return guest;
+       enumerator->destroy(enumerator);
 }
 
-/**
- * get a bridge by name
- */
-static bridge_t* get_bridge(char *name)
+static page_t* get_page(int num)
 {
-       iterator_t *iterator;
-       bridge_t *bridge = NULL;
+       enumerator_t *enumerator;
+       page_t *page, *found = NULL;
        
-       iterator = dumm->create_bridge_iterator(dumm);
-       while (iterator->iterate(iterator, (void**)&bridge))
+       enumerator = pages->create_enumerator(pages);
+       while (enumerator->enumerate(enumerator, (void**)&page))
        {
-               if (streq(bridge->get_name(bridge), name))
+               if (page->num == num)
                {
+                       found = page;
                        break;
                }
-               bridge = NULL;
        }
-       iterator->destroy(iterator);
-       return bridge;
+       enumerator->destroy(enumerator);
+       return found;
 }
 
 /**
- * get an interface by guest name
+ * Guest invocation callback
  */
-static iface_t* get_iface(char *name, char *ifname)
+static pid_t invoke(void *vte, guest_t *guest,
+                                       char *args[], int argc)
 {
-       iterator_t *guests, *ifaces;
-       guest_t *guest;
-       iface_t *iface;
-       
-       guests = dumm->create_guest_iterator(dumm);
-       while (guests->iterate(guests, (void**)&guest))
-       {
-               if (streq(guest->get_name(guest), name))
-               {
-                       iface = NULL;
-                       ifaces = guest->create_iface_iterator(guest);
-                       while (ifaces->iterate(ifaces, (void**)&iface))
-                       {
-                               if (streq(iface->get_guestif(iface), ifname))
-                               {
-                                       break;
-                               }
-                               iface = NULL;
-                       }
-                       ifaces->destroy(ifaces);
-                       if (iface)
-                       {
-                               break;
-                       }
-               }
-       }
-       guests->destroy(guests);
-       return iface;
+       args[argc] = "con0=fd:0,fd:1";
+       return vte_terminal_fork_command(VTE_TERMINAL(vte), args[0], args, NULL,
+                                                                        NULL, FALSE, FALSE, FALSE);
 }
 
-static void guest_addif_menu(guest_t *guest)
+void idle(void)
 {
-       char *name;
-       
-       name = get_line("interface name: ");
+       gtk_main_iteration_do(FALSE);
+       sched_yield();
+}
+
+static void start_guest()
+{
+       page_t *page;
        
-       if (!guest->create_iface(guest, name))
+       page = get_page(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
+       if (page && page->guest->get_state(page->guest) == GUEST_STOPPED)
        {
-               printf("creating interface failed\n");
+               vte_terminal_feed(VTE_TERMINAL(page->vte),
+                                                 "--- starting guest ---\n\r", -1);
+               page->guest->start(page->guest, invoke, VTE_TERMINAL(page->vte), idle);
        }
-       free(name);
 }
 
-static void guest_delif_menu(guest_t *guest)
+static void start_all_guests()
 {
-       char *name;
-       iface_t *iface;
-       iterator_t *iterator;
-       bool found = FALSE;
+       enumerator_t *enumerator;
+       page_t *page;
        
-       name = get_line("interface name: ");
-       
-       iterator = guest->create_iface_iterator(guest);
-       while (iterator->iterate(iterator, (void**)&iface))
+       enumerator = pages->create_enumerator(pages);
+       while (enumerator->enumerate(enumerator, (void**)&page))
        {
-               if (streq(iface->get_guestif(iface), name))
+               if (page->guest->get_state(page->guest) == GUEST_STOPPED)
                {
-                       iterator->remove(iterator);
-                       iface->destroy(iface);
-                       found = TRUE;
-                       break;
+                       vte_terminal_feed(VTE_TERMINAL(page->vte),
+                                                 "--- starting all guests ---\n\r", -1);
+                       page->guest->start(page->guest, invoke,
+                                                          VTE_TERMINAL(page->vte), idle);
                }
        }
-       iterator->destroy(iterator);
-       
-       if (!found)
-       {
-               printf("interface '%s' not found\n");
-       }
-       free(name);
+       enumerator->destroy(enumerator);
 }
 
-static void guest_console(guest_t *guest)
+static void stop_guest()
 {
-       int con;
+       page_t *page;
        
-       for (con = 1; con <= 6; con++)
+       page = get_page(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
+       if (page && page->guest->get_state(page->guest) == GUEST_RUNNING)
        {
-               char *pts = guest->get_console(guest, con);
-               if (pts)
-               {
-                       printf("%d: %s\n", con, pts);
-                       free(pts);
-               }
+               page->guest->stop(page->guest, idle);
        }
 }
 
-static void guest_menu(guest_t *guest)
+/**
+ * quit signal handler
+ */
+static void quit()
 {
-       while (TRUE)
+       enumerator_t *enumerator;
+       page_t *page;
+
+       dumm->load_template(dumm, NULL);
+       
+       enumerator = pages->create_enumerator(pages);
+       while (enumerator->enumerate(enumerator, &page))
        {
-               char *line = get_line("guest/%s# ", guest->get_name(guest));
-               
-               if (streq(line, "back"))
-               {
-                       free(line);
-                       break;
-               }
-               else if (streq(line, "start"))
-               {
-                       if (guest->start(guest))
-                       {
-                               printf("guest '%s' is running\n", guest->get_name(guest));
-                       }
-                       else
-                       {
-                               printf("failed to start guest '%s'\n", guest->get_name(guest));
-                       }
-               }
-               else if (streq(line, "stop"))
-               {
-                       printf("stopping guest '%s'...\n", guest->get_name(guest));
-                       guest->stop(guest);
-                       printf("guest '%s' is down\n", guest->get_name(guest));
-               }
-               else if (streq(line, "addif"))
-               {
-                       guest_addif_menu(guest);
-               }
-               else if (streq(line, "delif"))
-               {
-                       guest_delif_menu(guest);
+               if (page->guest->get_state(page->guest) != GUEST_STOPPED)
+               {                       
+                       page->guest->stop(page->guest, idle);
                }
-               else if (streq(line, "console"))
-               {
-                       guest_console(guest);
-               }
-               else
-               {
-                       printf("back|start|stop|addif|delif|console\n");
-               }
-               free(line);
        }
+       enumerator->destroy(enumerator);
+    gtk_main_quit();
 }
 
-static void guest_create_menu()
+static void error_dialog(char *msg)
 {
-       char *name, *kernel, *master, *mem;
-       guest_t *guest;
-       
-       name = get_line("guest name: ");
-       kernel = get_line("kernel image: ");
-       master = get_line("master filesystem: ");
-       mem = get_line("amount of memory in MB: ");
-       
-       guest = dumm->create_guest(dumm, name, kernel, master, atoi(mem));
-       if (guest)
-       {
-               printf("guest '%s' created\n", guest->get_name(guest));
-               guest_menu(guest);
-       }
-       else
-       {
-               printf("failed to create guest '%s'\n", name);
-       }
-       free(name);
-       free(kernel);
-       free(master);
-       free(mem);
+       GtkWidget *error;
+
+       error = gtk_message_dialog_new(GTK_WINDOW(window),
+                                                         GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
+                                                         GTK_BUTTONS_CLOSE, msg);
+       gtk_dialog_run(GTK_DIALOG(error));
+       gtk_widget_destroy(error);
 }
 
-static void guest_list_menu()
+static void create_switch()
 {
+       GtkWidget *dialog, *table, *label, *name;
+       bridge_t *bridge;
+       
+       dialog = gtk_dialog_new_with_buttons("Create new switch", GTK_WINDOW(window),
+                                                       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                                       GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+                                                       GTK_STOCK_NEW, GTK_RESPONSE_ACCEPT, NULL);
+       
+       table = gtk_table_new(1, 2, TRUE);
+       gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table);
+       
+       label = gtk_label_new("Switch name");
+       gtk_table_attach(GTK_TABLE(table), label,  0, 1, 0, 1, 0, 0, 0, 0);
+       gtk_widget_show(label);
+       
+       name = gtk_entry_new();
+       gtk_table_attach(GTK_TABLE(table), name, 1, 2, 0, 1,
+                                        GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
+       gtk_widget_show(name);
+       
+       gtk_widget_show(table);
+       
        while (TRUE)
        {
-               iterator_t *iterator;
-               guest_t *guest;
-               char *line = get_line("guest# ");
-               
-               if (streq(line, "back"))
-               {
-                       free(line);
-                       break;
-               }
-               else if (streq(line, "list"))
-               {
-                       iterator = dumm->create_guest_iterator(dumm);
-                       while (iterator->iterate(iterator, (void**)&guest))
-                       {
-                               printf("%s\n", guest->get_name(guest));
-                       }
-                       iterator->destroy(iterator);
-               }
-               else if (streq(line, "create"))
+               switch (gtk_dialog_run(GTK_DIALOG(dialog)))
                {
-                       guest_create_menu();
-               }
-               else
-               {
-                       guest = get_guest(line);
-                       if (guest)
-                       {
-                               guest_menu(guest);
-                       }
-                       else
-                       {
-                               printf("back|list|create|<guest>\n");
+                       case GTK_RESPONSE_ACCEPT:
+                       {                       
+                               if (streq(gtk_entry_get_text(GTK_ENTRY(name)), ""))
+                               {
+                                       continue;
+                               }
+                               bridge = dumm->create_bridge(dumm,
+                                                                       (char*)gtk_entry_get_text(GTK_ENTRY(name)));
+                               if (!bridge)
+                               {
+                                       error_dialog("creating bridge failed!");
+                                       continue;
+                               }
+                               break;
                        }
+                       default:
+                               break;
                }
-               free(line);
+               break;
        }
+       gtk_widget_destroy(dialog);
 }
 
-static void bridge_addif_menu(bridge_t *bridge)
+static void delete_switch()
 {
-       char *name, *ifname;
-       iface_t *iface;
-       
-       name = get_line("guest name: ");
-       ifname = get_line("interface name: ");
-       
-       iface = get_iface(name, ifname);
-       if (!iface)
-       {
-               printf("guest '%s' has no interface named '%s'\n", name, ifname);
-       }
-       else if (!bridge->connect_iface(bridge, iface))
-       {
-               printf("failed to add interface '%s' to bridge '%s'\n", ifname,
-                          bridge->get_name(bridge));
-       }
-       free(name);
-       free(ifname);
+
 }
 
-static void bridge_delif_menu(bridge_t *bridge)
+static void connect_guest()
 {
-       char *name, *ifname;
+       page_t *page;
+       GtkWidget *dialog, *table, *label, *name, *box;
+       bridge_t *bridge;
        iface_t *iface;
+       enumerator_t *enumerator;
        
-       name = get_line("guest name: ");
-       ifname = get_line("interface name: ");
-       
-       iface = get_iface(name, ifname);
-       if (!iface)
+       page = get_page(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
+       if (!page || page->guest->get_state(page->guest) != GUEST_RUNNING)
        {
-               printf("guest '%s' has no interface named '%s'\n", name, ifname);
+               return;
        }
-       else if (!bridge->disconnect_iface(bridge, iface))
+       
+       dialog = gtk_dialog_new_with_buttons("Connect guest", GTK_WINDOW(window),
+                                                       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                                       GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+                                                       GTK_STOCK_NEW, GTK_RESPONSE_ACCEPT, NULL);
+       
+       table = gtk_table_new(2, 2, TRUE);
+       gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table);
+       
+       label = gtk_label_new("Interface name");
+       gtk_table_attach(GTK_TABLE(table), label,  0, 1, 0, 1, 0, 0, 0, 0);
+       gtk_widget_show(label);
+       
+       name = gtk_entry_new();
+       gtk_table_attach(GTK_TABLE(table), name, 1, 2, 0, 1,
+                                        GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
+       gtk_widget_show(name);
+       
+       label = gtk_label_new("Connected switch");
+       gtk_table_attach(GTK_TABLE(table), label,  0, 1, 1, 2, 0, 0, 0, 0);
+       gtk_widget_show(label);
+       
+       box = gtk_combo_box_new_text();
+       gtk_table_attach(GTK_TABLE(table), box, 1, 2, 1, 2,
+                                        GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
+       enumerator = dumm->create_bridge_enumerator(dumm);
+       while (enumerator->enumerate(enumerator, &bridge))
        {
-               printf("failed to remove interface '%s' from bridge '%s'\n", ifname,
-                          bridge->get_name(bridge));
+               gtk_combo_box_append_text(GTK_COMBO_BOX(box), bridge->get_name(bridge));
        }
-       free(name);
-       free(ifname);
-}
-
-static void bridge_menu(bridge_t *bridge)
-{
+       enumerator->destroy(enumerator);
+       gtk_widget_show(box);
+       
+       gtk_widget_show(table);
+       
        while (TRUE)
        {
-               char *line = get_line("bridge/%s# ", bridge->get_name(bridge));
-               
-               if (streq(line, "back"))
+               switch (gtk_dialog_run(GTK_DIALOG(dialog)))
                {
-                       free(line);
-                       break;
-               }
-               else if (streq(line, "list"))
-               {
-                       iterator_t *iterator;
-                       iface_t *iface;
-
-                       iterator = bridge->create_iface_iterator(bridge);
-                       while (iterator->iterate(iterator, (void**)&iface))
-                       {
-                               printf("%s (%s)\n", iface->get_guestif(iface), iface->get_hostif(iface));
+                       case GTK_RESPONSE_ACCEPT:
+                       {                       
+                               if (streq(gtk_entry_get_text(GTK_ENTRY(name)), ""))
+                               {
+                                       continue;
+                               }
+                               
+                               iface = page->guest->create_iface(page->guest,
+                                                                       (char*)gtk_entry_get_text(GTK_ENTRY(name)));
+                               if (!iface)
+                               {
+                                       error_dialog("creating interface failed!");
+                                       continue;
+                               }
+                               enumerator = dumm->create_bridge_enumerator(dumm);
+                               while (enumerator->enumerate(enumerator, &bridge))
+                               {
+                                       if (!bridge->connect_iface(bridge, iface))
+                                       {
+                                               error_dialog("connecting interface failed!");
+                                       }
+                                       break;
+                               }
+                               enumerator->destroy(enumerator);
+                               break;
                        }
-                       iterator->destroy(iterator);
-               }
-               else if (streq(line, "addif"))
-               {
-                       bridge_addif_menu(bridge);
-               }
-               else if (streq(line, "delif"))
-               {
-                       bridge_delif_menu(bridge);
-               }
-               else
-               {
-                       printf("back|list|addif|delif\n");
+                       default:
+                               break;
                }
-               free(line);
+               break;
        }
+       gtk_widget_destroy(dialog);
 }
 
-static void bridge_create_menu()
+static void disconnect_guest()
 {
-       char *name;
-       bridge_t *bridge;
-       
-       name = get_line("bridge name: ");
-       
-       bridge = dumm->create_bridge(dumm, name);
-       if (bridge)
-       {
-               printf("bridge '%s' created\n", bridge->get_name(bridge));
-               bridge_menu(bridge);
-       }
-       else
-       {
-               printf("failed to create bridge '%s'\n", name);
-       }
-       free(name);
+
 }
 
-static void bridge_list_menu()
+static void delete_guest()
 {
-       while (TRUE)
+       page_t *page;
+       
+       page = get_page(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
+       if (page)
        {
-               iterator_t *iterator;
-               bridge_t *bridge;
-               char *line = get_line("bridge# ");
-               
-               if (streq(line, "back"))
-               {
-                       free(line);
-                       break;
-               }
-               else if (streq(line, "list"))
-               {
-                       iterator = dumm->create_bridge_iterator(dumm);
-                       while (iterator->iterate(iterator, (void**)&bridge))
-                       {
-                               printf("%s\n", bridge->get_name(bridge));
-                       }
-                       iterator->destroy(iterator);
-               }
-               else if (streq(line, "create"))
-               {
-                       bridge_create_menu();
-               }
-               else
-               {
-                       bridge = get_bridge(line);
-                       if (bridge)
-                       {
-                               bridge_menu(bridge);
-                       }
-                       else
-                       {
-                               printf("back|list|create|<bridge>\n");
-                       }
-               }
-               free(line);
+               page->guest->stop(page->guest, idle);
+               dumm->delete_guest(dumm, page->guest);
+               gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), page->num);
+               pages->remove(pages, page, NULL);
+               g_free(page);
        }
 }
 
-static void template_menu()
+/**
+ * create a new page for a guest
+ */
+static page_t* create_page(guest_t *guest)
 {
-       char *name;
-       
-       name = get_line("template name (or 'none'): ");
-       
-       dumm->load_template(dumm, streq(name, "none") ? NULL : name);
+       GtkWidget *label;
+       page_t *page;
        
-       free(name);
+       page = g_new(page_t, 1);
+       page->guest = guest;
+       page->vte = vte_terminal_new();
+       label = gtk_label_new(guest->get_name(guest));
+       page->num = gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+                                                                                page->vte, label);
+       gtk_widget_show(page->vte);
+       pages->insert_last(pages, page);
+       return page;
 }
 
-typedef bool (*uml_test_t)(dumm_t *dumm);
-
-static void test_menu()
+/**
+ * create a new guest
+ */
+static void create_guest()
 {
-       char *name;
-       void *handle;
-       struct dirent *ent;
-       DIR *dir;
-       uml_test_t test;
+       guest_t *guest;
+       GtkWidget *dialog, *table, *label, *name, *kernel, *master, *memory;
+       
+       dialog = gtk_dialog_new_with_buttons("Create new guest", GTK_WINDOW(window),
+                                                       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                                       GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+                                                       GTK_STOCK_NEW, GTK_RESPONSE_ACCEPT, NULL);
+       
+       table = gtk_table_new(4, 2, TRUE);
+       gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table);
+       
+       label = gtk_label_new("Guest name");
+       gtk_table_attach(GTK_TABLE(table), label,  0, 1, 0, 1, 0, 0, 0, 0);
+       gtk_widget_show(label);
+       
+       label = gtk_label_new("UML kernel");
+       gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, 0, 0, 0, 0);
+       gtk_widget_show(label);
+       
+       label = gtk_label_new("Master filesystem");
+       gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, 0, 0, 0, 0);
+       gtk_widget_show(label);
+       
+       label = gtk_label_new("Memory (MB)");
+       gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, 0, 0, 0, 0);
+       gtk_widget_show(label);
+       
+       name = gtk_entry_new();
+       gtk_table_attach(GTK_TABLE(table), name, 1, 2, 0, 1,
+                                        GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
+       gtk_widget_show(name);
+       
+       kernel = gtk_file_chooser_button_new("Select UML kernel image",
+                                                                                GTK_FILE_CHOOSER_ACTION_OPEN);
+       gtk_table_attach(GTK_TABLE(table), kernel, 1, 2, 1, 2,
+                                        GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
+       gtk_widget_show(kernel);
        
-       name = get_line("test name: ");
+       master = gtk_file_chooser_button_new("Select master filesystem",
+                                                                                GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+       gtk_table_attach(GTK_TABLE(table), master, 1, 2, 2, 3,
+                                        GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
+       gtk_widget_show(master);
        
-       dir = opendir("tests");
-       if (dir)
+       memory = gtk_spin_button_new_with_range(1, 4096, 1);
+       gtk_spin_button_set_digits(GTK_SPIN_BUTTON(memory), 0);
+       gtk_table_attach(GTK_TABLE(table), memory, 1, 2, 3, 4,
+                                        GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0, 0);
+       gtk_widget_show(memory);
+       
+       gtk_widget_show(table);
+       
+       while (TRUE)
        {
-               while ((ent = readdir(dir)))
+               switch (gtk_dialog_run(GTK_DIALOG(dialog)))
                {
-                       char buf[PATH_MAX];
-                       size_t len;
-                       
-                       len = strlen(ent->d_name);
-                       if (strlen(ent->d_name) < 4 || !streq(ent->d_name + len - 3, ".so"))
+                       case GTK_RESPONSE_ACCEPT:
                        {
-                               continue;
-                       }
+                               char *sname, *skernel, *smaster;
+                               page_t *page;
+                               
+                               sname = (char*)gtk_entry_get_text(GTK_ENTRY(name));
+                               skernel = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(kernel));
+                               smaster = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(master));
                        
-                       snprintf(buf, sizeof(buf), "%s/%s", "tests", ent->d_name);
-                       handle = dlopen(buf, RTLD_LAZY);
-                       if (!handle)
-                       {
-                               printf("failed to open test %s\n", ent->d_name);
-                               continue;
-                       }
-                       test = dlsym(handle, "test");
-                       if (test && dumm->load_template(dumm, ent->d_name))
-                       {
-                               printf("running test %s: ", ent->d_name);
-                               if (test(dumm))
+                               if (!sname[0] || !skernel || !smaster)
                                {
-                                       printf("success\n");
+                                       continue;
                                }
-                               else
+                               guest = dumm->create_guest(dumm, sname, skernel, smaster, 
+                                                       gtk_spin_button_get_value(GTK_SPIN_BUTTON(memory)));
+                               if (!guest)
                                {
-                                       printf("failed\n");
+                                       error_dialog("creating guest failed!");
+                                       continue;
                                }
+                               page = create_page(guest);
+                               gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page->num);
+                               break;
                        }
-                       else
-                       {
-                               printf("failed to open test %s\n", ent->d_name);
-                       }
-                       dlclose(handle);
+                       default:
+                               break;
                }
+               break;
        }
-       free(name);
-}
-
-/**
- * Signal handler 
- */
-void signal_action(int sig, siginfo_t *info, void *ucontext)
-{
-       dumm->destroy(dumm);
-       clear_history();
-       exit(0);
+       gtk_widget_destroy(dialog);
 }
 
 /**
@@ -553,84 +466,154 @@ void signal_action(int sig, siginfo_t *info, void *ucontext)
  */
 int main(int argc, char *argv[])
 {
-       struct sigaction action;
-       char *dir = ".";
+       GtkWidget *menubar, *menu, *menuitem, *vbox;
+       GtkWidget *dummMenu, *guestMenu, *switchMenu;
+       enumerator_t *enumerator;
+       guest_t *guest;
        
-       library_init(STRONGSWAN_CONF);
+       library_init(NULL);
+       gtk_init(&argc, &argv);
+       
+       pages = linked_list_create();
+       dumm = dumm_create(NULL);
 
-       while (TRUE)
-       {
-               struct option options[] = {
-                       {"dir", 1, 0, 0},
-                       {"help", 0, 0, 0},
-                       {0, 0, 0, 0}
-               };
-               
-               switch (getopt_long(argc, argv, "d:h", options, NULL)) 
-               {
-                       case -1:
-                               break;
-                       case 'd':
-                               dir = optarg;
-                               continue;
-                       case 'h':
-                               usage();
-                               return 0;
-                       default:
-                               usage();
-                               return 1;
-               }
-               break;
-       }
+       /* setup window */
+       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(quit), NULL);
+       gtk_window_set_title(GTK_WINDOW (window), "Dumm");
+       gtk_window_set_default_size(GTK_WINDOW (window), 1000, 500);
+       g_signal_connect(G_OBJECT(vte_reaper_get()), "child-exited",
+                                        G_CALLBACK(child_exited), NULL);
        
-       memset(&action, 0, sizeof(action));
-       action.sa_sigaction = signal_action;
-       action.sa_flags = SA_SIGINFO;
-       if (sigaction(SIGINT, &action, NULL) != 0 ||
-               sigaction(SIGQUIT, &action, NULL) != 0 ||
-               sigaction(SIGTERM, &action, NULL) != 0)
-       {
-               printf("signal handler setup failed: %m.\n");
-               return 1;
-       }
+       /* add vbox with menubar, notebook */
+       vbox = gtk_vbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(window), vbox);
+       menubar = gtk_menu_bar_new();
+       gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
+       notebook = gtk_notebook_new();
+       g_object_set(G_OBJECT(notebook), "homogeneous", TRUE, NULL);
+       gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_BOTTOM);
+    gtk_container_add(GTK_CONTAINER(vbox), notebook);
+
+       /* Dumm menu */
+       menu = gtk_menu_new();
+       dummMenu = gtk_menu_item_new_with_mnemonic("_Dumm");
+       gtk_menu_bar_append(GTK_MENU_BAR(menubar), dummMenu);
+       gtk_widget_show(dummMenu);
+       gtk_menu_item_set_submenu(GTK_MENU_ITEM(dummMenu), menu);
        
-       dumm = dumm_create(dir);
-       while (TRUE)
+       /* Dumm -> exit */
+       menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                                        G_CALLBACK(quit), NULL);
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+
+       /* Guest menu */
+       menu = gtk_menu_new();
+       guestMenu = gtk_menu_item_new_with_mnemonic("_Guest");
+       gtk_menu_bar_append(GTK_MENU_BAR(menubar), guestMenu);
+       gtk_widget_show(guestMenu);
+       gtk_menu_item_set_submenu(GTK_MENU_ITEM(guestMenu), menu);
+       
+       /* Guest -> new */
+       menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                                        G_CALLBACK(create_guest), NULL);
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+       
+       /* Guest -> delete */
+       menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_DELETE, NULL);
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                                        G_CALLBACK(delete_guest), NULL);
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+       
+       menuitem = gtk_separator_menu_item_new();
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+       
+       /* Guest -> start */
+       menuitem = gtk_menu_item_new_with_mnemonic("_Start");
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                                        G_CALLBACK(start_guest), NULL);
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+       
+       /* Guest -> startall */
+       menuitem = gtk_menu_item_new_with_mnemonic("Start _all");
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                                        G_CALLBACK(start_all_guests), NULL);
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+       
+       /* Guest -> stop */
+       menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_STOP, NULL);
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                                        G_CALLBACK(stop_guest), NULL);
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+       
+       menuitem = gtk_separator_menu_item_new();
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+       
+       /* Guest -> connect */
+       menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_CONNECT, NULL);
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                                        G_CALLBACK(connect_guest), NULL);
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+       
+       /* Guest -> disconnect */
+       menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_DISCONNECT, NULL);
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                                        G_CALLBACK(disconnect_guest), NULL);
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+
+       /* Switch menu */
+       menu = gtk_menu_new();
+       switchMenu = gtk_menu_item_new_with_mnemonic("_Switch");
+       gtk_menu_bar_append(GTK_MENU_BAR(menubar), switchMenu);
+       gtk_widget_show(switchMenu);
+       gtk_menu_item_set_submenu(GTK_MENU_ITEM(switchMenu), menu);
+       
+       /* Switch -> new */
+       menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                                        G_CALLBACK(create_switch), NULL);
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+       
+       /* Switch -> delete */
+       menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_DELETE, NULL);
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                                        G_CALLBACK(delete_switch), NULL);
+       gtk_menu_append(GTK_MENU(menu), menuitem);
+       gtk_widget_show(menuitem);
+       
+       /* show widgets */
+       gtk_widget_show(menubar);
+       gtk_widget_show(notebook);
+       gtk_widget_show(vbox);
+       gtk_widget_show(window);
+       
+       /* fill notebook with guests */
+       enumerator = dumm->create_guest_enumerator(dumm);
+       while (enumerator->enumerate(enumerator, (void**)&guest))
        {
-               char *line = get_line("# ");
-               
-               if (streq(line, "quit"))
-               {
-                       free(line);
-                       break;
-               }
-               else if (streq(line, "guest"))
-               {
-                       guest_list_menu();
-               }
-               else if (streq(line, "bridge"))
-               {
-                       bridge_list_menu();
-               }
-               else if (streq(line, "template"))
-               {
-                       template_menu();
-               }
-               else if (streq(line, "test"))
-               {
-                       test_menu();
-               }
-               else
-               {
-                       printf("quit|guest|bridge|template|test\n");
-               }
-               free(line);
+               create_page(guest);
        }
-       dumm->load_template(dumm, NULL);
+       enumerator->destroy(enumerator);
+       
+       gtk_main();
+       
        dumm->destroy(dumm);
+       pages->destroy_function(pages, g_free);
        
        library_deinit();
-       clear_history();
        return 0;
 }
 
index 25cb846..6d6d900 100644 (file)
@@ -44,6 +44,8 @@ struct private_mconsole_t {
        int notify;
        /** address of uml socket */
        struct sockaddr_un uml;
+       /** idle function */
+       void (*idle)(void);
 };
 
 /**
@@ -91,7 +93,7 @@ static int request(private_mconsole_t *this, char *command,
 {
        mconsole_request request;
        mconsole_reply reply;
-       int len, total = 0;
+       int len, total = 0, flags = 0;
        
        memset(&request, 0, sizeof(request));
        request.magic = MCONSOLE_MAGIC;
@@ -101,19 +103,41 @@ static int request(private_mconsole_t *this, char *command,
        *buf = '\0';
        (*size)--;
 
-       if (sendto(this->console, &request, sizeof(request), 0,
-               (struct sockaddr*)&this->uml, sizeof(this->uml)) < 0)
+       if (this->idle)
+       {
+               flags = MSG_DONTWAIT;
+       }
+       do
+       {
+               if (this->idle)
+               {
+                       this->idle();
+               }
+               len = sendto(this->console, &request, sizeof(request), flags,
+                                        (struct sockaddr*)&this->uml, sizeof(this->uml));
+       }
+       while (len < 0 && (errno == EINTR || errno == EAGAIN));
+       
+       if (len < 0)
        {
                snprintf(buf, *size, "sending mconsole command to UML failed: %m");
                return -1;
        }
        do 
        {
-               len = recv(this->console, &reply, sizeof(reply), 0);
+               len = recv(this->console, &reply, sizeof(reply), flags);
+               if (len < 0 && (errno == EINTR || errno == EAGAIN))
+               {
+                       if (this->idle)
+                       {
+                               this->idle();
+                       }
+                       continue;
+               }
                if (len < 0)
                {
                        snprintf(buf, *size, "receiving from mconsole failed: %m");
-               return -1;
+                       return -1;
                }
                if (len > 0)
                {
@@ -169,35 +193,6 @@ static bool del_iface(private_mconsole_t *this, char *guest)
        }
        return TRUE;
 }
-       
-/**
- * Implementation of mconsole_t.get_console_pts.
- */
-static char* get_console_pts(private_mconsole_t *this, int con)
-{
-       char buf[128];
-       char *pos;
-       int len;
-       
-       len = snprintf(buf, sizeof(buf), "config con%d", con);
-       if (len < 0 || len >= sizeof(buf))
-       {
-               return NULL;
-       }
-       len = sizeof(buf);
-       if (request(this, buf, buf, &len) != 0)
-       {
-               DBG1("getting console pts failed: %.*s", len, buf);
-               return NULL;
-       }
-       pos = memchr(buf, ':', len);
-       if (pos == NULL)
-       {
-               return NULL;
-       }
-       pos++;
-       return strndup(pos, len - (pos - buf));
-}
 
 /**
  * Poll until guest is ready
@@ -220,7 +215,14 @@ static bool wait_bootup(private_mconsole_t *this)
                {
                        return TRUE;
                }
-               usleep(50000);
+               if (this->idle)
+               {
+                       this->idle();
+               }
+               else
+               {
+                       usleep(50000);
+               }
        }
 }
 
@@ -241,7 +243,7 @@ static bool wait_for_notify(private_mconsole_t *this, char *nsock)
 {
        struct sockaddr_un addr;
        mconsole_notify notify;
-       int len;
+       int len, flags = 0;
 
        this->notify = socket(AF_UNIX, SOCK_DGRAM, 0);
        if (this->notify < 0)
@@ -258,10 +260,20 @@ static bool wait_for_notify(private_mconsole_t *this, char *nsock)
                close(this->notify);
                return FALSE;
        }
+       if (this->idle)
+       {
+               flags = MSG_DONTWAIT;
+       }
        do
        {
-               len = recvfrom(this->notify, &notify, sizeof(notify), 0, NULL, 0);
-       } while (len < 0 && errno == EINTR);
+               if (this->idle)
+               {
+                       this->idle();
+               }
+               len = recvfrom(this->notify, &notify, sizeof(notify), flags, NULL, 0);
+       }
+       while (len < 0 && (errno == EINTR || errno == EAGAIN));
+       
        if (len < 0 || len >= sizeof(notify))
        {
                DBG1("reading from mconsole notify socket failed: %m");
@@ -314,15 +326,16 @@ static bool setup_console(private_mconsole_t *this)
 /**
  * create the mconsole instance
  */
-mconsole_t *mconsole_create(char *notify)
+mconsole_t *mconsole_create(char *notify, void(*idle)(void))
 {
        private_mconsole_t *this = malloc_thing(private_mconsole_t);
        
        this->public.add_iface = (bool(*)(mconsole_t*, char *guest, char *host))add_iface;
        this->public.del_iface = (bool(*)(mconsole_t*, char *guest))del_iface;
-       this->public.get_console_pts = (char*(*)(mconsole_t*, int con))get_console_pts;
        this->public.destroy = (void*)destroy;
        
+       this->idle = idle;
+       
        if (!wait_for_notify(this, notify))
        {
                free(this);
index 53aaa1b..55ce15d 100644 (file)
@@ -43,14 +43,6 @@ struct mconsole_t {
        bool (*del_iface)(mconsole_t *this, char *guest);
        
        /**
-        * @brief Get the pts device file assigned to a console.
-        *
-        * @param con                   console number in guest
-        * @return                              allocated device string
-        */
-       char* (*get_console_pts)(mconsole_t *this, int con);
-       
-       /**
         * @brief Destroy the mconsole instance
         */
        void (*destroy) (mconsole_t *this);
@@ -63,9 +55,10 @@ struct mconsole_t {
  * to connect to the mconsole socket supplied in the received notification.
  *
  * @param notify                       unix notify socket path
+ * @param idle                         idle function to call while waiting for responses
  * @return                                     mconsole instance, or NULL if failed
  */
-mconsole_t *mconsole_create(char *notify);
+mconsole_t *mconsole_create(char *notify, void(*idle)(void));
 
 #endif /* MCONSOLE_H */