prototype of dumm GUI
parent
e8a680d94a
commit
a47486b5e4
|
@ -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!])])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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**)¤t))
|
||||
enumerator = this->ifaces->create_enumerator(this->ifaces);
|
||||
while (enumerator->enumerate(enumerator, (void**)¤t))
|
||||
{
|
||||
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();
|
||||
|
|
|
@ -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
|
||||
|
|
207
src/dumm/dumm.c
207
src/dumm/dumm.c
|
@ -23,6 +23,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
#include "dumm.h"
|
||||
|
||||
|
@ -31,11 +32,6 @@
|
|||
#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 iterator_t* create_guest_iterator(private_dumm_t *this)
|
||||
static enumerator_t* create_guest_enumerator(private_dumm_t *this)
|
||||
{
|
||||
return this->guests->create_iterator(this->guests, TRUE);
|
||||
return this->guests->create_enumerator(this->guests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of dumm_t.delete_guest.
|
||||
*/
|
||||
static void delete_guest(private_dumm_t *this, guest_t *guest)
|
||||
{
|
||||
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 iterator_t* create_bridge_iterator(private_dumm_t *this)
|
||||
static enumerator_t* create_bridge_enumerator(private_dumm_t *this)
|
||||
{
|
||||
return this->bridges->create_iterator(this->bridges, TRUE);
|
||||
return this->bridges->create_enumerator(this->bridges);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of dumm_t.delete_bridge.
|
||||
*/
|
||||
static void delete_bridge(private_dumm_t *this, bridge_t *bridge)
|
||||
{
|
||||
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**)¤t))
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -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 iterator over bridge_t's
|
||||
* @return enumerator over bridge_t's
|
||||
*/
|
||||
iterator_t* (*create_bridge_iterator)(dumm_t *this);
|
||||
enumerator_t* (*create_bridge_enumerator)(dumm_t *this);
|
||||
|
||||
/**
|
||||
* @brief Delete a bridge.
|
||||
*
|
||||
* @param bridge bridge to destroy
|
||||
*/
|
||||
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);
|
||||
|
|
141
src/dumm/guest.c
141
src/dumm/guest.c
|
@ -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**)¤t))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,22 +188,10 @@ static char* write_arg(char **pos, size_t *left, char *format, ...)
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
this->pid = invoke(data, &this->public, args, i);
|
||||
if (!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->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;
|
||||
|
@ -340,22 +352,6 @@ static bool mount_unionfs(private_guest_t *this)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -17,11 +17,12 @@
|
|||
#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.
|
||||
*
|
||||
* @return iterator over iface_t's
|
||||
* @param iface interface to destroy
|
||||
*/
|
||||
iterator_t* (*create_iface_iterator)(guest_t *this);
|
||||
void (*destroy_iface)(guest_t *this, iface_t *iface);
|
||||
|
||||
/**
|
||||
* @brief Create an enumerator over all guest interfaces.
|
||||
*
|
||||
* @return enumerator over iface_t's
|
||||
*/
|
||||
enumerator_t* (*create_iface_enumerator)(guest_t *this);
|
||||
|
||||
/**
|
||||
* @brief Set the template COWFS overlay to use.
|
||||
|
|
|
@ -43,6 +43,42 @@ struct private_iface_t {
|
|||
mconsole_t *mconsole;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
1079
src/dumm/main.c
1079
src/dumm/main.c
File diff suppressed because it is too large
Load Diff
|
@ -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, ¬ify, sizeof(notify), 0, NULL, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
if (this->idle)
|
||||
{
|
||||
this->idle();
|
||||
}
|
||||
len = recvfrom(this->notify, ¬ify, 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);
|
||||
|
|
|
@ -42,14 +42,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
|
||||
*/
|
||||
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue