WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Really include renamed console files. :-)
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sun, 07 Aug 2005 05:12:10 -0400
Delivery-date: Sun, 07 Aug 2005 09:12:45 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Really include renamed console files. :-), Xen patchbot -unstable <=