summaryrefslogtreecommitdiff
path: root/src/dumm/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dumm/main.c')
-rw-r--r--src/dumm/main.c632
1 files changed, 632 insertions, 0 deletions
diff --git a/src/dumm/main.c b/src/dumm/main.c
new file mode 100644
index 000000000..d6e142e24
--- /dev/null
+++ b/src/dumm/main.c
@@ -0,0 +1,632 @@
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.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"
+
+/**
+ * global set of UMLs guests
+ */
+dumm_t *dumm;
+
+/**
+ * show usage information (program arguments)
+ */
+static void usage()
+{
+ printf("Usage:\n");
+ printf(" --dir|-d <path> set working dir to <path>\n");
+ printf(" --help|-h show this help\n");
+}
+
+/**
+ * readline() wrapper
+ */
+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;
+}
+
+/**
+ * get a guest by name
+ */
+static guest_t* get_guest(char *name)
+{
+ iterator_t *iterator;
+ guest_t *guest = NULL;
+
+ iterator = dumm->create_guest_iterator(dumm);
+ while (iterator->iterate(iterator, (void**)&guest))
+ {
+ if (streq(guest->get_name(guest), name))
+ {
+ break;
+ }
+ guest = NULL;
+ }
+ iterator->destroy(iterator);
+ return guest;
+}
+
+/**
+ * get a bridge by name
+ */
+static bridge_t* get_bridge(char *name)
+{
+ iterator_t *iterator;
+ bridge_t *bridge = NULL;
+
+ iterator = dumm->create_bridge_iterator(dumm);
+ while (iterator->iterate(iterator, (void**)&bridge))
+ {
+ if (streq(bridge->get_name(bridge), name))
+ {
+ break;
+ }
+ bridge = NULL;
+ }
+ iterator->destroy(iterator);
+ return bridge;
+}
+
+/**
+ * get an interface by guest name
+ */
+static iface_t* get_iface(char *name, char *ifname)
+{
+ 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;
+}
+
+static void guest_addif_menu(guest_t *guest)
+{
+ char *name;
+
+ name = get_line("interface name: ");
+
+ if (!guest->create_iface(guest, name))
+ {
+ printf("creating interface failed\n");
+ }
+ free(name);
+}
+
+static void guest_delif_menu(guest_t *guest)
+{
+ char *name;
+ iface_t *iface;
+ iterator_t *iterator;
+ bool found = FALSE;
+
+ name = get_line("interface name: ");
+
+ iterator = guest->create_iface_iterator(guest);
+ while (iterator->iterate(iterator, (void**)&iface))
+ {
+ if (streq(iface->get_guestif(iface), name))
+ {
+ iterator->remove(iterator);
+ iface->destroy(iface);
+ found = TRUE;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ if (!found)
+ {
+ printf("interface '%s' not found\n");
+ }
+ free(name);
+}
+
+static void guest_console(guest_t *guest)
+{
+ int con;
+
+ for (con = 1; con <= 6; con++)
+ {
+ char *pts = guest->get_console(guest, con);
+ if (pts)
+ {
+ printf("%d: %s\n", con, pts);
+ free(pts);
+ }
+ }
+}
+
+static void guest_menu(guest_t *guest)
+{
+ while (TRUE)
+ {
+ 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);
+ }
+ else if (streq(line, "console"))
+ {
+ guest_console(guest);
+ }
+ else
+ {
+ printf("back|start|stop|addif|delif|console\n");
+ }
+ free(line);
+ }
+}
+
+static void guest_create_menu()
+{
+ 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);
+}
+
+static void guest_list_menu()
+{
+ 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"))
+ {
+ guest_create_menu();
+ }
+ else
+ {
+ guest = get_guest(line);
+ if (guest)
+ {
+ guest_menu(guest);
+ }
+ else
+ {
+ printf("back|list|create|<guest>\n");
+ }
+ }
+ free(line);
+ }
+}
+
+static void bridge_addif_menu(bridge_t *bridge)
+{
+ 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)
+{
+ 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->disconnect_iface(bridge, iface))
+ {
+ printf("failed to remove interface '%s' from bridge '%s'\n", ifname,
+ bridge->get_name(bridge));
+ }
+ free(name);
+ free(ifname);
+}
+
+static void bridge_menu(bridge_t *bridge)
+{
+ while (TRUE)
+ {
+ char *line = get_line("bridge/%s# ", bridge->get_name(bridge));
+
+ if (streq(line, "back"))
+ {
+ 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));
+ }
+ 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");
+ }
+ free(line);
+ }
+}
+
+static void bridge_create_menu()
+{
+ 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()
+{
+ while (TRUE)
+ {
+ 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);
+ }
+}
+
+static void template_menu()
+{
+ char *name;
+
+ name = get_line("template name (or 'none'): ");
+
+ dumm->load_template(dumm, streq(name, "none") ? NULL : name);
+
+ free(name);
+}
+
+typedef bool (*uml_test_t)(dumm_t *dumm);
+
+static void test_menu()
+{
+ char *name;
+ void *handle;
+ struct dirent *ent;
+ DIR *dir;
+ uml_test_t test;
+
+ name = get_line("test name: ");
+
+ dir = opendir("tests");
+ if (dir)
+ {
+ while ((ent = readdir(dir)))
+ {
+ 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"))
+ {
+ continue;
+ }
+
+ 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))
+ {
+ printf("success\n");
+ }
+ else
+ {
+ printf("failed\n");
+ }
+ }
+ else
+ {
+ printf("failed to open test %s\n", ent->d_name);
+ }
+ dlclose(handle);
+ }
+ }
+ free(name);
+}
+
+/**
+ * Signal handler
+ */
+void signal_action(int sig, siginfo_t *info, void *ucontext)
+{
+ dumm->destroy(dumm);
+ clear_history();
+ exit(0);
+}
+
+/**
+ * main routine, parses args and reads from console
+ */
+int main(int argc, char *argv[])
+{
+ struct sigaction action;
+ char *dir = ".";
+
+ 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;
+ }
+
+ 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;
+ }
+
+ dumm = dumm_create(dir);
+ while (TRUE)
+ {
+ 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);
+ }
+ dumm->load_template(dumm, NULL);
+ dumm->destroy(dumm);
+ clear_history();
+ return 0;
+}
+