From: "Richard W.M. Jones" <rjones@redhat.com> Also if /dev/ttyS* is specified, make sure the serial port is set to raw mode. --- daemon/guestfsd.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 580315a..fe2bd79 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -41,6 +41,7 @@ #include <netinet/in.h> #include <errno.h> #include <assert.h> +#include <termios.h> #ifdef HAVE_PRINTF_H # include <printf.h> @@ -78,6 +79,7 @@ static dev_t root_device = 0; int verbose = 0; +static void makeraw (const char *channel, int fd); static int print_shell_quote (FILE *stream, const struct printf_info *info, const void *const *args); static int print_sysroot_shell_quote (FILE *stream, const struct printf_info *info, const void *const *args); #ifdef HAVE_REGISTER_PRINTF_SPECIFIER @@ -210,8 +212,6 @@ main (int argc, char *argv[]) printf ("could not read linux command line\n"); } - free (cmdline); - #ifndef WIN32 /* Make sure SIGPIPE doesn't kill us. */ struct sigaction sa; @@ -254,7 +254,22 @@ main (int argc, char *argv[]) copy_lvm (); /* Connect to virtio-serial channel. */ - int sock = open (VIRTIO_SERIAL_CHANNEL, O_RDWR|O_CLOEXEC); + char *channel, *p; + if (cmdline && (p = strstr (cmdline, "guestfs_channel=")) != NULL) { + p += 16; + channel = strndup (p, strcspn (p, " \n")); + } + else + channel = strdup (VIRTIO_SERIAL_CHANNEL); + if (!channel) { + perror ("strdup"); + exit (EXIT_FAILURE); + } + + if (verbose) + printf ("trying to open virtio-serial channel '%s'\n", channel); + + int sock = open (channel, O_RDWR|O_CLOEXEC); if (sock == -1) { fprintf (stderr, "\n" @@ -269,10 +284,19 @@ main (int argc, char *argv[]) "output to the libguestfs developers, either in a bug report\n" "or on the libguestfs redhat com mailing list.\n" "\n"); - perror (VIRTIO_SERIAL_CHANNEL); + perror (channel); exit (EXIT_FAILURE); } + /* If it's a serial-port like device then it probably has echoing + * enabled. Put it into complete raw mode. + */ + if (STRPREFIX (channel, "/dev/ttyS")) + makeraw (channel, sock); + + /* cmdline is not used after this point */ + free (cmdline); + /* Wait for udev devices to be created. If you start libguestfs, * especially with disks that contain complex (eg. mdadm) data * already, then it is possible for the 'mdadm' and LVM commands @@ -355,6 +379,25 @@ read_cmdline (void) return r; } +/* Try to make the socket raw, but don't fail if it's not possible. */ +static void +makeraw (const char *channel, int fd) +{ + struct termios tt; + + if (tcgetattr (fd, &tt) == -1) { + fprintf (stderr, "tcgetattr: "); + perror (channel); + return; + } + + cfmakeraw (&tt); + if (tcsetattr (fd, TCSANOW, &tt) == -1) { + fprintf (stderr, "tcsetattr: "); + perror (channel); + } +} + /* Return true iff device is the root device (and therefore should be * ignored from the point of view of user calls). */ -- 1.8.3.1