This ugly thing is a shell script to detect availability of the -q option for 'nc': debian and suse based distros need this flag to ensure the remote nc will exit on EOF, so it will go away when we close the tunnel. If it doesn't go away, a useless 'nc' process is left sitting on the remote host. Fedora's 'nc' doesn't have this option, so we can't blindly pass -q. More info here: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=564034 We also detect the -U option, since some nc versions don't support it, which has caused quite some user confusion. Connecting to a box and using the incorrect nc: virsh --connect qemu+ssh://root@debhost/system?netcat=/bin/nc.traditional error: server closed connection: /bin/nc.traditional: invalid option -- U nc -h for help openbsd nc is required error: failed to connect to the hypervisor Test with Fedora 12, RHEL 5.4, and Debian Lenny --- src/remote/remote_driver.c | 52 ++++++++++++++++++++++++++++++++++++++------ 1 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 7f92fd0..c3258d3 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -732,8 +732,49 @@ doRemoteOpen (virConnectPtr conn, } case trans_ssh: { - int j, nr_args = 6; + int j, nr_args = 0; + char *nc_command; + + const char *nc_bin = netcat ? netcat : "nc"; + const char *sock_path = (sockname ? sockname : + (flags & VIR_CONNECT_RO + ? LIBVIRTD_PRIV_UNIX_SOCKET_RO + : LIBVIRTD_PRIV_UNIX_SOCKET)); + + /* + * Build 'nc' command run on the remote host + * + * This ugly thing is a shell script to detect availability of + * the -q option for 'nc': debian and suse based distros need this + * flag to ensure the remote nc will exit on EOF, so it will go away + * when we close the tunnel. If it doesn't go away, a useless 'nc' + * process is left sitting on the remote host. + * + * Fedora's 'nc' doesn't have this option, and apparently defaults + * to the desired behavior. + */ + const char *nc_detect_template = ( + "NCOUT=$(%s -U 2>&1);" + "echo \"$NCOUT\" | grep -q 'invalid option';" + "if [ $? -eq 0 ] ; then" + " echo \"$NCOUT\" >&2;" + " echo openbsd 'nc' is required >&2;" + " exit 1;" + "fi;" + "" + "%s -q 2>&1 | grep -q 'requires an argument';" + "if [ $? -eq 0 ] ; then" + " CMD='-q 0';" + "else" + " CMD='';" + "fi;" + "%s $CMD -U %s;"); + + if (virAsprintf(&nc_command, nc_detect_template, + nc_bin, nc_bin, nc_bin, sock_path) < 0) + goto out_of_memory; + nr_args += 4; /* ssh $hostname $netcat_command NULL*/ if (username) nr_args += 2; /* For -l username */ if (no_tty) nr_args += 5; /* For -T -o BatchMode=yes -e none */ if (port) nr_args += 2; /* For -p port */ @@ -765,12 +806,9 @@ doRemoteOpen (virConnectPtr conn, cmd_argv[j++] = strdup ("none"); } cmd_argv[j++] = strdup (priv->hostname); - cmd_argv[j++] = strdup (netcat ? netcat : "nc"); - cmd_argv[j++] = strdup ("-U"); - cmd_argv[j++] = strdup (sockname ? sockname : - (flags & VIR_CONNECT_RO - ? LIBVIRTD_PRIV_UNIX_SOCKET_RO - : LIBVIRTD_PRIV_UNIX_SOCKET)); + + cmd_argv[j++] = nc_command; + cmd_argv[j++] = 0; assert (j == nr_args); for (j = 0; j < (nr_args-1); j++) -- 1.6.5.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list