/* * 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 . * * 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 #include #include #include #include #include #include #include #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 set working dir to \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|\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|\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; }