[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Really include renamed console files. :-)



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID deff07c1b686479f117d18ed12334e94310e9f69
# Parent  ec1878b6956ea9eab2349fde6dccb7d814585ff4
Really include renamed console files. :-)
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r ec1878b6956e -r deff07c1b686 tools/console/Makefile
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/Makefile    Sun Aug  7 09:13:39 2005
@@ -0,0 +1,39 @@
+
+XEN_ROOT=../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+DAEMON_INSTALL_DIR = /usr/sbin
+CLIENT_INSTALL_DIR = /usr/libexec/xen
+
+INSTALL         = install
+INSTALL_PROG    = $(INSTALL) -m0755
+INSTALL_DIR     = $(INSTALL) -d -m0755
+
+CC       = gcc
+CFLAGS   = -Wall -Werror -g3
+
+CFLAGS  += -I $(XEN_XCS)
+CFLAGS  += -I $(XEN_LIBXC)
+CFLAGS  += -I $(XEN_XENSTORE)
+
+BIN      = xenconsoled xenconsole
+
+all: $(BIN)
+
+clean:
+       $(RM) *.a *.so *.o *.rpm $(BIN)
+       $(RM) client/*.o daemon/*.o
+
+xenconsoled: $(patsubst %.c,%.o,$(wildcard daemon/*.c))
+       $(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
+              -lxc -lxenstore
+
+xenconsole: $(patsubst %.c,%.o,$(wildcard client/*.c))
+       $(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
+             -lxc -lxenstore
+
+install: $(BIN)
+       $(INSTALL_DIR) -p $(DESTDIR)/$(DAEMON_INSTALL_DIR)
+       $(INSTALL_PROG) xenconsoled $(DESTDIR)/$(DAEMON_INSTALL_DIR)
+       $(INSTALL_DIR) -p $(DESTDIR)/$(CLIENT_INSTALL_DIR)
+       $(INSTALL_PROG) xenconsole $(DESTDIR)/$(CLIENT_INSTALL_DIR)
diff -r ec1878b6956e -r deff07c1b686 tools/console/client/main.c
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/client/main.c       Sun Aug  7 09:13:39 2005
@@ -0,0 +1,228 @@
+/*\
+ *  Copyright (C) International Business Machines  Corp., 2005
+ *  Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ *  Xen Console Daemon
+ *
+ *  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; under version 2 of the License.
+ * 
+ *  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.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+\*/
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <signal.h>
+#include <getopt.h>
+#include <sys/select.h>
+#include <err.h>
+#include <errno.h>
+#include <pty.h>
+
+#include "xc.h"
+#include "xs.h"
+
+#define ESCAPE_CHARACTER 0x1d
+
+static volatile sig_atomic_t received_signal = 0;
+
+static void sighandler(int signum)
+{
+       received_signal = 1;
+}
+
+static bool write_sync(int fd, const void *data, size_t size)
+{
+       size_t offset = 0;
+       ssize_t len;
+
+       while (offset < size) {
+               len = write(fd, data + offset, size - offset);
+               if (len < 1) {
+                       return false;
+               }
+               offset += len;
+       }
+
+       return true;
+}
+
+static void usage(const char *program) {
+       printf("Usage: %s [OPTION] DOMID\n"
+              "Attaches to a virtual domain console\n"
+              "\n"
+              "  -h, --help       display this help and exit\n"
+              , program);
+}
+
+/* don't worry too much if setting terminal attributes fail */
+static void init_term(int fd, struct termios *old)
+{
+       struct termios new_term;
+
+       if (tcgetattr(fd, old) == -1) {
+               return;
+       }
+
+       new_term = *old;
+       cfmakeraw(&new_term);
+
+       tcsetattr(fd, TCSAFLUSH, &new_term);
+}
+
+static void restore_term(int fd, struct termios *old)
+{
+       tcsetattr(fd, TCSAFLUSH, old);
+}
+
+static int console_loop(int xc_handle, domid_t domid, int fd)
+{
+       int ret;
+
+       do {
+               fd_set fds;
+
+               FD_ZERO(&fds);
+               FD_SET(STDIN_FILENO, &fds);
+               FD_SET(fd, &fds);
+
+               ret = select(fd + 1, &fds, NULL, NULL, NULL);
+               if (ret == -1) {
+                       if (errno == EINTR || errno == EAGAIN) {
+                               continue;
+                       }
+                       return -1;
+               }
+
+               if (FD_ISSET(STDIN_FILENO, &fds)) {
+                       ssize_t len;
+                       char msg[60];
+
+                       len = read(STDIN_FILENO, msg, sizeof(msg));
+                       if (len == 1 && msg[0] == ESCAPE_CHARACTER) {
+                               return 0;
+                       } 
+
+                       if (len == 0 || len == -1) {
+                               if (len == -1 &&
+                                   (errno == EINTR || errno == EAGAIN)) {
+                                       continue;
+                               }
+                               return -1;
+                       }
+
+                       if (!write_sync(fd, msg, len)) {
+                               perror("write() failed");
+                               return -1;
+                       }
+               }
+
+               if (FD_ISSET(fd, &fds)) {
+                       ssize_t len;
+                       char msg[512];
+
+                       len = read(fd, msg, sizeof(msg));
+                       if (len == 0 || len == -1) {
+                               if (len == -1 &&
+                                   (errno == EINTR || errno == EAGAIN)) {
+                                       continue;
+                               }
+                               return -1;
+                       }
+
+                       if (!write_sync(STDOUT_FILENO, msg, len)) {
+                               perror("write() failed");
+                               return -1;
+                       }
+               }
+       } while (received_signal == 0);
+
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       struct termios attr;
+       int domid;
+       int xc_handle;
+       char *sopt = "hf:pc";
+       int ch;
+       int opt_ind=0;
+       struct option lopt[] = {
+               { "help",    0, 0, 'h' },
+               { "file",    1, 0, 'f' },
+               { "pty",     0, 0, 'p' },
+               { "ctty",    0, 0, 'c' },
+               { 0 },
+
+       };
+       char *str_pty;
+       char path[1024];
+       int spty;
+       unsigned int len = 0;
+       struct xs_handle *xs;
+
+       while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
+               switch(ch) {
+               case 'h':
+                       usage(argv[0]);
+                       exit(0);
+                       break;
+               }
+       }
+       
+       if ((argc - optind) != 1) {
+               fprintf(stderr, "Invalid number of arguments\n");
+               fprintf(stderr, "Try `%s --help' for more information.\n", 
+                       argv[0]);
+               exit(EINVAL);
+       }
+       
+       domid = atoi(argv[optind]);
+
+       xs = xs_daemon_open();
+       if (xs == NULL) {
+               err(errno, "Could not contact XenStore");
+       }
+
+       xc_handle = xc_interface_open();
+       if (xc_handle == -1) {
+               err(errno, "xc_interface_open()");
+       }
+       
+       signal(SIGTERM, sighandler);
+
+       snprintf(path, sizeof(path), "/console/%d/tty", domid);
+       str_pty = xs_read(xs, path, &len);
+       if (str_pty == NULL) {
+               err(errno, "Could not read tty from store");
+       }
+       spty = open(str_pty, O_RDWR | O_NOCTTY);
+       if (spty == -1) {
+               err(errno, "Could not open tty `%s'", str_pty);
+       }
+       free(str_pty);
+
+       init_term(STDIN_FILENO, &attr);
+       console_loop(xc_handle, domid, spty);
+       restore_term(STDIN_FILENO, &attr);
+
+       return 0;
+ }
diff -r ec1878b6956e -r deff07c1b686 tools/console/daemon/io.c
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/daemon/io.c Sun Aug  7 09:13:39 2005
@@ -0,0 +1,343 @@
+/*\
+ *  Copyright (C) International Business Machines  Corp., 2005
+ *  Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ *  Xen Console Daemon
+ *
+ *  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; under version 2 of the License.
+ * 
+ *  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.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+\*/
+
+#define _GNU_SOURCE
+
+#include "utils.h"
+#include "io.h"
+
+#include "xc.h"
+#include "xs.h"
+#include "xen/io/domain_controller.h"
+#include "xcs_proto.h"
+
+#include <malloc.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/select.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <termios.h>
+
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+struct buffer
+{
+       char *data;
+       size_t size;
+       size_t capacity;
+       size_t max_capacity;
+};
+
+static void buffer_append(struct buffer *buffer, const void *data, size_t size)
+{
+       if ((buffer->capacity - buffer->size) < size) {
+               buffer->capacity += (size + 1024);
+               buffer->data = realloc(buffer->data, buffer->capacity);
+               if (buffer->data == NULL) {
+                       dolog(LOG_ERR, "Memory allocation failed");
+                       exit(ENOMEM);
+               }
+       }
+
+       memcpy(buffer->data + buffer->size, data, size);
+       buffer->size += size;
+
+       if (buffer->max_capacity &&
+           buffer->size > buffer->max_capacity) {
+               memmove(buffer->data + (buffer->size - buffer->max_capacity),
+                       buffer->data, buffer->max_capacity);
+               buffer->data = realloc(buffer->data, buffer->max_capacity);
+               buffer->capacity = buffer->max_capacity;
+       }
+}
+
+static bool buffer_empty(struct buffer *buffer)
+{
+       return buffer->size == 0;
+}
+
+static void buffer_advance(struct buffer *buffer, size_t size)
+{
+       size = MIN(size, buffer->size);
+       memmove(buffer->data, buffer + size, buffer->size - size);
+       buffer->size -= size;
+}
+
+struct domain
+{
+       int domid;
+       int tty_fd;
+       struct buffer buffer;
+       struct domain *next;
+};
+
+static struct domain *dom_head;
+
+static bool domain_is_valid(int domid)
+{
+       bool ret;
+       xc_dominfo_t info;
+
+       ret = (xc_domain_getinfo(xc, domid, 1, &info) == 1 &&
+              info.domid == domid);
+               
+       return ret;
+}
+
+static int domain_create_tty(struct domain *dom)
+{
+       char path[1024];
+       int master;
+
+       if ((master = getpt()) == -1 ||
+           grantpt(master) == -1 || unlockpt(master) == -1) {
+               dolog(LOG_ERR, "Failed to create tty for domain-%d",
+                     dom->domid);
+               master = -1;
+       } else {
+               const char *slave = ptsname(master);
+               struct termios term;
+               char *data;
+               unsigned int len;
+
+               if (tcgetattr(master, &term) != -1) {
+                       cfmakeraw(&term);
+                       tcsetattr(master, TCSAFLUSH, &term);
+               }
+
+               xs_mkdir(xs, "/console");
+               snprintf(path, sizeof(path), "/console/%d", dom->domid);
+               xs_mkdir(xs, path);
+               strcat(path, "/tty");
+
+               xs_write(xs, path, slave, strlen(slave), O_CREAT);
+
+               snprintf(path, sizeof(path), "/console/%d/limit", dom->domid);
+               data = xs_read(xs, path, &len);
+               if (data) {
+                       dom->buffer.max_capacity = strtoul(data, 0, 0);
+                       free(data);
+               }
+       }
+
+       return master;
+}
+
+static struct domain *create_domain(int domid)
+{
+       struct domain *dom;
+
+       dom = (struct domain *)malloc(sizeof(struct domain));
+       if (dom == NULL) {
+               dolog(LOG_ERR, "Out of memory %s:%s():L%d",
+                     __FILE__, __FUNCTION__, __LINE__);
+               exit(ENOMEM);
+       }
+
+       dom->domid = domid;
+       dom->tty_fd = domain_create_tty(dom);
+       dom->buffer.data = 0;
+       dom->buffer.size = 0;
+       dom->buffer.capacity = 0;
+       dom->buffer.max_capacity = 0;
+
+       dolog(LOG_DEBUG, "New domain %d", domid);
+
+       return dom;
+}
+
+static struct domain *lookup_domain(int domid)
+{
+       struct domain **pp;
+
+       for (pp = &dom_head; *pp; pp = &(*pp)->next) {
+               struct domain *dom = *pp;
+
+               if (dom->domid == domid) {
+                       return dom;
+               } else if (dom->domid > domid) {
+                       *pp = create_domain(domid);
+                       (*pp)->next = dom;
+                       return *pp;
+               }
+       }
+
+       *pp = create_domain(domid);
+       return *pp;
+}
+
+static void remove_domain(struct domain *dom)
+{
+       struct domain **pp;
+
+       dolog(LOG_DEBUG, "Removing domain-%d", dom->domid);
+
+       for (pp = &dom_head; *pp; pp = &(*pp)->next) {
+               struct domain *d = *pp;
+
+               if (dom->domid == d->domid) {
+                       *pp = d->next;
+                       if (d->buffer.data) {
+                               free(d->buffer.data);
+                       }
+                       free(d);
+                       break;
+               }
+       }
+}
+
+static void handle_tty_read(struct domain *dom)
+{
+       ssize_t len;
+       xcs_msg_t msg;
+
+       msg.type = XCS_REQUEST;
+       msg.u.control.remote_dom = dom->domid;
+       msg.u.control.msg.type = CMSG_CONSOLE;
+       msg.u.control.msg.subtype = CMSG_CONSOLE_DATA;
+       msg.u.control.msg.id = 1;
+
+       len = read(dom->tty_fd, msg.u.control.msg.msg, 60);
+       if (len < 1) {
+               close(dom->tty_fd);
+
+               if (domain_is_valid(dom->domid)) {
+                       dom->tty_fd = domain_create_tty(dom);
+               } else {
+                       remove_domain(dom);
+               }
+       } else if (domain_is_valid(dom->domid)) {
+               msg.u.control.msg.length = len;
+
+               if (!write_sync(xcs_data_fd, &msg, sizeof(msg))) {
+                       dolog(LOG_ERR, "Write to xcs failed: %m");
+               }
+       } else {
+               close(dom->tty_fd);
+               remove_domain(dom);
+       }
+}
+
+static void handle_tty_write(struct domain *dom)
+{
+       ssize_t len;
+
+       len = write(dom->tty_fd, dom->buffer.data, dom->buffer.size);
+       if (len < 1) {
+               close(dom->tty_fd);
+
+               if (domain_is_valid(dom->domid)) {
+                       dom->tty_fd = domain_create_tty(dom);
+               } else {
+                       remove_domain(dom);
+               }
+       } else {
+               buffer_advance(&dom->buffer, len);
+       }
+}
+
+static void handle_xcs_msg(int fd)
+{
+       xcs_msg_t msg;
+
+       if (!read_sync(fd, &msg, sizeof(msg))) {
+               dolog(LOG_ERR, "read from xcs failed! %m");
+       } else if (msg.type == XCS_REQUEST) {
+               struct domain *dom;
+
+               dom = lookup_domain(msg.u.control.remote_dom);
+               buffer_append(&dom->buffer,
+                             msg.u.control.msg.msg,
+                             msg.u.control.msg.length);
+       }
+}
+
+static void enum_domains(void)
+{
+       int domid = 0;
+       xc_dominfo_t dominfo;
+
+       while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
+               lookup_domain(dominfo.domid);
+               domid = dominfo.domid + 1;
+       }
+}
+
+void handle_io(void)
+{
+       fd_set readfds, writefds;
+       int ret;
+       int max_fd = -1;
+       int num_of_writes = 0;
+
+       do {
+               struct domain *d;
+               struct timeval tv = { 1, 0 };
+
+               FD_ZERO(&readfds);
+               FD_ZERO(&writefds);
+
+               FD_SET(xcs_data_fd, &readfds);
+               max_fd = MAX(xcs_data_fd, max_fd);
+
+               for (d = dom_head; d; d = d->next) {
+                       if (d->tty_fd != -1) {
+                               FD_SET(d->tty_fd, &readfds);
+                       }
+
+                       if (d->tty_fd != -1 && !buffer_empty(&d->buffer)) {
+                               FD_SET(d->tty_fd, &writefds);
+                       }
+
+                       max_fd = MAX(d->tty_fd, max_fd);
+               }
+
+               ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
+               if (tv.tv_sec == 1 && (++num_of_writes % 100) == 0) {
+                       /* FIXME */
+                       /* This is a nasty hack.  xcs does not handle the
+                          control channels filling up well at all.  We'll
+                          throttle ourselves here since we do proper
+                          queueing to give the domains a shot at pulling out
+                          the data.  Fixing xcs is not worth it as it's
+                          going away */
+                       tv.tv_usec = 1000;
+                       select(0, 0, 0, 0, &tv);
+               }
+               enum_domains();
+
+               if (FD_ISSET(xcs_data_fd, &readfds)) {
+                       handle_xcs_msg(xcs_data_fd);
+               }
+
+               for (d = dom_head; d; d = d->next) {
+                       if (FD_ISSET(d->tty_fd, &readfds)) {
+                               handle_tty_read(d);
+                       }
+
+                       if (FD_ISSET(d->tty_fd, &writefds)) {
+                               handle_tty_write(d);
+                       }
+               }
+       } while (ret > -1);
+}
diff -r ec1878b6956e -r deff07c1b686 tools/console/daemon/io.h
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/daemon/io.h Sun Aug  7 09:13:39 2005
@@ -0,0 +1,26 @@
+/*\
+ *  Copyright (C) International Business Machines  Corp., 2005
+ *  Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ *  Xen Console Daemon
+ *
+ *  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; under version 2 of the License.
+ * 
+ *  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.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+\*/
+
+#ifndef CONSOLED_IO_H
+#define CONSOLED_IO_H
+
+void handle_io(void);
+
+#endif
diff -r ec1878b6956e -r deff07c1b686 tools/console/daemon/main.c
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/daemon/main.c       Sun Aug  7 09:13:39 2005
@@ -0,0 +1,93 @@
+/*\
+ *  Copyright (C) International Business Machines  Corp., 2005
+ *  Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ *  Xen Console Daemon
+ *
+ *  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; under version 2 of the License.
+ * 
+ *  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.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+\*/
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "xc.h"
+#include "xen/io/domain_controller.h"
+#include "xcs_proto.h"
+
+#include "utils.h"
+#include "io.h"
+
+int main(int argc, char **argv)
+{
+       const char *sopts = "hVvi";
+       struct option lopts[] = {
+               { "help", 0, 0, 'h' },
+               { "version", 0, 0, 'V' },
+               { "verbose", 0, 0, 'v' },
+               { "interactive", 0, 0, 'i' },
+               { 0 },
+       };
+       bool is_interactive = false;
+       int ch;
+       int syslog_option = LOG_CONS;
+       int syslog_mask = LOG_WARNING;
+       int opt_ind = 0;
+
+       while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) {
+               switch (ch) {
+               case 'h':
+                       //usage(argv[0]);
+                       exit(0);
+               case 'V':
+                       //version(argv[0]);
+                       exit(0);
+               case 'v':
+                       syslog_option |= LOG_PERROR;
+                       syslog_mask = LOG_DEBUG;
+                       break;
+               case 'i':
+                       is_interactive = true;
+                       break;
+               case '?':
+                       fprintf(stderr,
+                               "Try `%s --help' for more information\n",
+                               argv[0]);
+                       exit(EINVAL);
+               }
+       }
+
+       if (geteuid() != 0) {
+               fprintf(stderr, "%s requires root to run.\n", argv[0]);
+               exit(EPERM);
+       }
+
+       openlog("xenconsoled", syslog_option, LOG_DAEMON);
+       setlogmask(syslog_mask);
+
+       if (!is_interactive) {
+               daemonize("/var/run/xenconsoled.pid");
+       }
+
+       xen_setup();
+
+       handle_io();
+
+       closelog();
+
+       return 0;
+}
diff -r ec1878b6956e -r deff07c1b686 tools/console/daemon/utils.c
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/daemon/utils.c      Sun Aug  7 09:13:39 2005
@@ -0,0 +1,251 @@
+/*\
+ *  Copyright (C) International Business Machines  Corp., 2005
+ *  Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ *  Xen Console Daemon
+ *
+ *  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; under version 2 of the License.
+ * 
+ *  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.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+\*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <string.h>
+
+#include "xc.h"
+#include "xen/io/domain_controller.h"
+#include "xcs_proto.h"
+
+#include "utils.h"
+
+struct xs_handle *xs;
+int xc;
+
+int xcs_ctrl_fd = -1;
+int xcs_data_fd = -1;
+
+bool _read_write_sync(int fd, void *data, size_t size, bool do_read)
+{
+       size_t offset = 0;
+       ssize_t len;
+
+       while (offset < size) {
+               if (do_read) {
+                       len = read(fd, data + offset, size - offset);
+               } else {
+                       len = write(fd, data + offset, size - offset);
+               }
+
+               if (len < 1) {
+                       if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
+                               return false;
+                       }
+               } else {
+                       offset += len;
+               }
+       }
+
+       return true;
+}
+
+static int open_domain_socket(const char *path)
+{
+       struct sockaddr_un addr;
+       int sock;
+       size_t addr_len;
+
+       if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
+               goto out;
+       }
+
+       addr.sun_family = AF_UNIX;
+       strcpy(addr.sun_path, path);
+       addr_len = sizeof(addr.sun_family) + strlen(XCS_SUN_PATH) + 1;
+
+       if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) {
+               goto out_close_sock;
+       }
+
+       return sock;
+
+ out_close_sock:
+       close(sock);
+ out:
+       return -1;
+}
+
+static void child_exit(int sig)
+{
+       while (waitpid(-1, NULL, WNOHANG) > 0);
+}
+
+void daemonize(const char *pidfile)
+{
+       pid_t pid;
+       int fd;
+       int len;
+       int i;
+       char buf[100];
+
+       if (getppid() == 1) {
+               return;
+       }
+
+       if ((pid = fork()) > 0) {
+               exit(0);
+       } else if (pid == -1) {
+               err(errno, "fork() failed");
+       }
+
+       setsid();
+
+       /* redirect fd 0,1,2 to /dev/null */
+       if ((fd = open("/dev/null",O_RDWR)) == -1) {
+               exit(1);
+       }
+
+       for (i = 0; i <= 2; i++) {
+               close(i);
+               dup2(fd, i);
+       }
+
+       close(fd);
+
+       umask(027);
+       chdir("/");
+
+       fd = open(pidfile, O_RDWR | O_CREAT);
+       if (fd == -1) {
+               exit(1);
+       }
+
+       if (lockf(fd, F_TLOCK, 0) == -1) {
+               exit(1);
+       }
+
+       len = sprintf(buf, "%d\n", getpid());
+       write(fd, buf, len);
+
+       signal(SIGCHLD, child_exit);
+       signal(SIGTSTP, SIG_IGN);
+       signal(SIGTTOU, SIG_IGN);
+       signal(SIGTTIN, SIG_IGN);
+}
+
+/* synchronized send/recv strictly for setting up xcs */
+/* always use asychronize callbacks any other time */
+static bool xcs_send_recv(int fd, xcs_msg_t *msg)
+{
+       bool ret = false;
+
+       if (!write_sync(fd, msg, sizeof(*msg))) {
+               dolog(LOG_ERR, "Write failed at %s:%s():L%d?  Possible bug.",
+                      __FILE__, __FUNCTION__, __LINE__);
+               goto out;
+       }
+
+       if (!read_sync(fd, msg, sizeof(*msg))) {
+               dolog(LOG_ERR, "Read failed at %s:%s():L%d?  Possible bug.",
+                      __FILE__, __FUNCTION__, __LINE__);
+               goto out;
+       }
+
+       ret = true;
+
+ out:
+       return ret;
+}
+
+bool xen_setup(void)
+{
+       int sock;
+       xcs_msg_t msg;
+       
+       xs = xs_daemon_open();
+       if (xs == NULL) {
+               dolog(LOG_ERR,
+                     "Failed to contact xenstore (%m).  Is it running?");
+               goto out;
+       }
+
+       xc = xc_interface_open();
+       if (xc == -1) {
+               dolog(LOG_ERR, "Failed to contact hypervisor (%m)");
+               goto out;
+       }
+
+       sock = open_domain_socket(XCS_SUN_PATH);
+       if (sock == -1) {
+               dolog(LOG_ERR, "Failed to contact xcs (%m).  Is it running?");
+               goto out_close_store;
+       }
+
+       xcs_ctrl_fd = sock;
+
+       sock = open_domain_socket(XCS_SUN_PATH);
+       if (sock == -1) {
+               dolog(LOG_ERR, "Failed to contact xcs (%m).  Is it running?");
+               goto out_close_ctrl;
+       }
+       
+       xcs_data_fd = sock;
+
+       memset(&msg, 0, sizeof(msg));
+       msg.type = XCS_CONNECT_CTRL;
+       if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
+               dolog(LOG_ERR, "xcs control connect failed.  Possible bug.");
+               goto out_close_data;
+       }
+
+       msg.type = XCS_CONNECT_DATA;
+       if (!xcs_send_recv(xcs_data_fd, &msg) || msg.result != XCS_RSLT_OK) {
+               dolog(LOG_ERR, "xcs data connect failed.  Possible bug.");
+               goto out_close_data;
+       }
+
+       /* Since the vast majority of control messages are console messages
+          it's just easier to ignore other messages that try to bind to 
+          a specific type. */
+       msg.type = XCS_MSG_BIND;
+       msg.u.bind.port = PORT_WILDCARD;
+       msg.u.bind.type = TYPE_WILDCARD;
+       if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
+               dolog(LOG_ERR, "xcs vind failed.  Possible bug.");
+               goto out_close_data;
+       }
+       
+       return true;
+
+ out_close_data:
+       close(xcs_ctrl_fd);
+       xcs_data_fd = -1;
+ out_close_ctrl:
+       close(xcs_ctrl_fd);
+       xcs_ctrl_fd = -1;
+ out_close_store:
+       xs_daemon_close(xs);
+ out:
+       return false;
+}
+
diff -r ec1878b6956e -r deff07c1b686 tools/console/daemon/utils.h
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/daemon/utils.h      Sun Aug  7 09:13:39 2005
@@ -0,0 +1,47 @@
+/*\
+ *  Copyright (C) International Business Machines  Corp., 2005
+ *  Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ *  Xen Console Daemon
+ *
+ *  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; under version 2 of the License.
+ * 
+ *  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.
+ * 
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+\*/
+
+#ifndef CONSOLED_UTILS_H
+#define CONSOLED_UTILS_H
+
+#include <stdbool.h>
+#include <syslog.h>
+#include <stdio.h>
+
+#include "xs.h"
+
+void daemonize(const char *pidfile);
+bool xen_setup(void);
+#define read_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, true)
+#define write_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, false)
+bool _read_write_sync(int fd, void *data, size_t size, bool do_read);
+
+extern int xcs_ctrl_fd;
+extern int xcs_data_fd;
+extern struct xs_handle *xs;
+extern int xc;
+
+#if 1
+#define dolog(val, fmt, ...) syslog(val, fmt, ## __VA_ARGS__)
+#else
+#define dolog(val, fmt, ...) fprintf(stderr, fmt "\n", ## __VA_ARGS__)
+#endif
+
+#endif
diff -r ec1878b6956e -r deff07c1b686 tools/console/testsuite/Makefile
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/testsuite/Makefile  Sun Aug  7 09:13:39 2005
@@ -0,0 +1,11 @@
+CFLAGS=-g -Wall
+CC=gcc
+LDFLAGS=-static
+
+all: console-dom0 console-domU procpipe
+
+console-dom0: console-dom0.o
+console-domU: console-domU.o
+procpipe: procpipe.o
+
+clean:; $(RM) *.o console-domU console-dom0 procpipe
diff -r ec1878b6956e -r deff07c1b686 tools/console/testsuite/README
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/testsuite/README    Sun Aug  7 09:13:39 2005
@@ -0,0 +1,29 @@
+ABOUT
+
+This tool uses two programs, one that lives in dom0 and one that lives in domU
+to verify that no data is lost.  dom0 and domU share a handshake with each
+other that they use to exchange a random seed.
+
+Both programs then generate a series of random numbers and then writes and
+reads the numbers via the console.  Because each side starts with the same seed
+they know what data the other side is generating and therefore what should be
+expected.
+
+RUNNNING
+
+console-domU should be installed within the guest image.  It must be launched
+from the client automatically.  I use a custom initrd image and put it in the
+/linuxrc.
+
+console-dom0 and console-domU will communicate with each other and stress the
+console code.  You can verify it at various levels by invoking it in different
+ways.  procpipe is used to connect the two.  I use the following command for
+testing:
+
+./procpipe ./console-dom0 'xm create -c /etc/xen/xmexample1'
+
+xmexample1 has no devices and no root set (this is what triggers /linuxrc).
+
+If it freezes, it probably means that console-domU is expecting more data from
+console-dom0 (which means that some data got dropped).  I'd like to add
+timeouts in the future to handle this more gracefully.
diff -r ec1878b6956e -r deff07c1b686 tools/console/testsuite/console-dom0.c
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/testsuite/console-dom0.c    Sun Aug  7 09:13:39 2005
@@ -0,0 +1,117 @@
+/* Written by Anthony Liguori <aliguori@xxxxxxxxxx> */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+static void generate_random_buffer(char *buffer, size_t size)
+{
+       int i;
+
+       for (i = 0; i < size; i++) {
+               buffer[i] = random() & 0xFF;
+       }
+}
+
+static void canonicalize(char *buffer)
+{
+       char *reader, *writer;
+
+       reader = writer = buffer;
+
+       while (*reader) {
+               *writer = *reader;
+               if (*reader != '\r') writer++;
+               reader++;
+       }
+       *writer = *reader;
+}
+
+int main(int argc, char **argv)
+{
+       char buffer[4096];
+       char *line;
+       unsigned int seed;
+       size_t size;
+       int runs;
+       unsigned long long total_bytes = 0;
+       struct termios term;
+
+       tcgetattr(STDIN_FILENO, &term);
+       cfmakeraw(&term);
+       tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
+
+       tcgetattr(STDOUT_FILENO, &term);
+       cfmakeraw(&term);
+       tcsetattr(STDOUT_FILENO, TCSAFLUSH, &term);
+
+       while ((line = fgets(buffer, sizeof(buffer), stdin))) {
+               canonicalize(line);
+
+               if (strcmp(line, "!!!XEN Test Begin!!!\n") == 0) {
+                       break;
+               } else {
+                       fprintf(stderr, "%s", line);
+               }
+       }
+
+       if (line == NULL) {
+               fprintf(stderr, "Client never sent start string.\n");
+               return 1;
+       }
+
+       seed = time(0);
+
+       printf("%u\n", seed); fflush(stdout);
+
+       fprintf(stderr, "Waiting for seed acknowledgement\n");
+       line = fgets(buffer, sizeof(buffer), stdin);
+       if (line == NULL) {
+               fprintf(stderr, "Client never acknowledge seed.\n");
+               return 1;
+       }
+
+       canonicalize(line);
+       if (strcmp(line, "Seed Okay.\n") != 0) {
+               fprintf(stderr, "Incorrect seed acknowledgement.\n");
+               fprintf(stderr, "[%s]", line);
+               return 1;
+       } else {
+               fprintf(stderr, "Processed seed.\n");
+       }
+
+       srandom(seed);
+
+       for (runs = (random() % 100000) + 4096; runs > 0; runs--) {
+
+               size = random() % 4096;
+
+               fprintf(stderr, "Writing %d bytes.\n", size);
+
+               generate_random_buffer(buffer, size);
+               fwrite(buffer, size, 1, stdout);
+               fflush(stdout);
+
+               do {
+                       line = fgets(buffer, sizeof(buffer), stdin);
+                       if (line == NULL) {
+                               fprintf(stderr, "Premature EOF from client.\n");
+                               return 1;
+                       }
+
+                       canonicalize(line);
+                       fprintf(stderr, "%s", line);
+               } while (strcmp(line, "Okay.\n") != 0);
+
+               total_bytes += size;
+       }
+
+       fprintf(stderr, "PASS: processed %llu byte(s).\n", total_bytes);
+
+       return 0;
+}
diff -r ec1878b6956e -r deff07c1b686 tools/console/testsuite/console-domU.c
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/testsuite/console-domU.c    Sun Aug  7 09:13:39 2005
@@ -0,0 +1,76 @@
+/* Written by Anthony Liguori <aliguori@xxxxxxxxxx> */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <termios.h>
+#include <unistd.h>
+
+static void canonicalize(char *buffer)
+{
+       char *reader, *writer;
+
+       reader = writer = buffer;
+
+       while (*reader) {
+               *writer = *reader;
+               if (*reader != '\r') writer++;
+               reader++;
+       }
+       *writer = *reader;
+}
+
+int main(int argc, char **argv)
+{
+       char buffer[4096];
+       char *line;
+       unsigned int seed;
+       size_t size;
+       int i;
+       int runs;
+       struct termios term;
+
+       tcgetattr(STDIN_FILENO, &term);
+       cfmakeraw(&term);
+       tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
+
+       tcgetattr(STDOUT_FILENO, &term);
+       cfmakeraw(&term);
+       tcsetattr(STDOUT_FILENO, TCSAFLUSH, &term);
+
+       printf("!!!XEN Test Begin!!!\n"); fflush(stdout);
+       line = fgets(buffer, sizeof(buffer), stdin);
+       if (line == NULL) {
+               printf("Failure\n"); fflush(stdout);
+               return 1;
+       }
+
+       canonicalize(line);
+       seed = strtoul(line, 0, 0);
+
+       printf("Seed Okay.\n"); fflush(stdout);
+
+       srandom(seed);
+
+       for (runs = (random() % 100000) + 4096; runs > 0; runs--) {
+               size = random() % 4096;
+
+               for (i = 0; i < size; i++) {
+                       int ch;
+                       int exp;
+
+                       ch = fgetc(stdin);
+                       exp = random() & 0xFF;
+                       if (ch != exp) {
+                               printf("Expected %d got %d\n",
+                                      exp, ch);
+                               fflush(stdout);
+                       }
+                       printf("Got %d/%d good bytes\n", i, size);
+               }
+               
+               printf("Okay.\n"); fflush(stdout);
+       }
+
+       return 0;
+}
diff -r ec1878b6956e -r deff07c1b686 tools/console/testsuite/procpipe.c
--- /dev/null   Sun Aug  7 09:12:55 2005
+++ b/tools/console/testsuite/procpipe.c        Sun Aug  7 09:13:39 2005
@@ -0,0 +1,133 @@
+/* Written by Anthony Liguori <aliguori@xxxxxxxxxx> */
+
+#include <stdio.h>
+#include <getopt.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <err.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define PACKAGE_NAME "procpipe"
+#define PACKAGE_VERSION "0.0.1"
+
+#define GPL_SHORT \
+"This is free software; see the source for copying conditions.  There is NO\n"\
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+#define PACKAGE_BUGS "aliguori@xxxxxxxxxx"
+#define PACKAGE_AUTHOR "Anthony Liguori"
+#define PACKAGE_OWNER "IBM, Corp."
+#define PACKAGE_LICENSE GPL_SHORT
+
+static void usage(const char *name)
+{
+       printf("Usage: %s [OPTIONS]\n"
+              "\n"
+              "  -h, --help      display this help and exit\n"
+              "  -V, --version   output version information and exit\n"
+              "\n"
+              "Report bugs to <%s>.\n"
+              , name, PACKAGE_BUGS);
+}
+
+static void version(const char *name)
+{
+       printf("%s (%s) %s\n"
+              "Written by %s.\n"
+              "\n"
+              "Copyright (C) 2005 %s.\n"
+              "%s\n"
+              , name, PACKAGE_NAME, PACKAGE_VERSION,
+              PACKAGE_AUTHOR, PACKAGE_OWNER, PACKAGE_LICENSE);
+}
+
+static pid_t exec(int stdout, int stdin, const char *cmd)
+{
+       pid_t pid;
+
+       pid = fork();
+       if (pid == 0) {
+               close(STDOUT_FILENO);
+               dup2(stdout, STDOUT_FILENO);
+               close(STDIN_FILENO);
+               dup2(stdin, STDIN_FILENO);
+
+               execlp("/bin/sh", "sh", "-c", cmd, NULL);
+       }
+
+       return pid;
+}
+
+int main(int argc, char **argv)
+{
+       int ch, opt_ind = 0;
+       const char *sopt = "hV";
+       struct option lopt[] = {
+               { "help", 0, 0, 'h' },
+               { "version", 0, 0, 'V' },
+               { 0 }
+       };
+       int host_stdout[2];
+       int host_stdin[2];
+       int res;
+       pid_t pid1, pid2;
+       int status;
+
+       while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
+               switch (ch) {
+               case 'h':
+                       usage(argv[0]);
+                       exit(0);
+               case 'V':
+                       version(argv[0]);
+                       exit(0);
+               case '?':
+                       errx(EINVAL, "Try `%s --help' for more information.",
+                            argv[0]);
+               }
+       }
+
+       if ((argc - optind) != 2) {
+               errx(EINVAL, "Two commands are required.\n"
+                    "Try `%s --help' for more information.", argv[0]);
+       }
+
+       res = pipe(host_stdout);
+       if (res == -1) {
+               err(errno, "pipe() failed");
+       }
+
+       res = pipe(host_stdin);
+       if (res == -1) {
+               err(errno, "pipe() failed");
+       }
+
+       pid1 = exec(host_stdout[1], host_stdin[0], argv[optind]);
+       if (pid1 == -1) {
+               err(errno, "exec(%s)", argv[optind]);
+       }
+
+       pid2 = exec(host_stdin[1], host_stdout[0], argv[optind + 1]);
+       if (pid2 == -1) {
+               err(errno, "exec(%s)", argv[optind + 1]);
+       }
+
+       waitpid(pid1, &status, 0);
+       if (WIFEXITED(status)) status = WEXITSTATUS(status);
+
+       if (status != 0) {
+               printf("Child exited with status %d\n", status);
+       }
+
+       waitpid(pid2, &status, 0);
+       if (WIFEXITED(status)) status = WEXITSTATUS(status);
+
+       if (status != 0) {
+               printf("Child2 exited with status %d\n", status);
+       }
+
+       return 0;
+}

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.