Vbox source code used in libvirt.git is LGPLv2-only.  If linked
into libvirt.so, then we are legally forbidden from linking an app
against both that libvirt.so and any GPLv3 code, such as libreadline.
While we'd like to fix libvirt.so to be LGPLv2+ in the future,
regardless of whether vbox support was compiled in (by moving
vbox support into libvirtd, which can afford to be [L]GPLv2-only),
that is a more invasive change; this is a simpler approach that
fixes the issue for the libvirt package, even though it doesn't
help other GPLv3 apps that want to use libvirt.

* configure.ac (VIRSH_LIBS): Prefer the weaker libedit if
vbox code is enabled.
* tools/virsh.c (vshReadlineInit, vshReadlineDeinit, main): Make
history code conditional on actual readline library.
(vshShowVersion): Document which library is in use.
* libvirt.spec.in (Requires): Use correct library.

Signed-off-by: Eric Blake <ebl...@redhat.com>
---
 configure.ac    | 15 ++++++++++++++-
 libvirt.spec.in |  8 ++++++++
 tools/virsh.c   | 21 ++++++++++++++++-----
 3 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index 3feed8b..b2cebf0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1406,7 +1406,20 @@ fi
 AM_CONDITIONAL([WITH_PHYP],[test "$with_phyp" = "yes"])

 dnl virsh libraries
-VIRSH_LIBS="$VIRSH_LIBS $READLINE_LIBS"
+dnl Use of vbox in libvirt.so renders that library LGPLv2-only, which
+dnl is incompatible with GPLv3 readline.  If that is the case, we must
+dnl use libedit or nothing; libedit supports readline() but not history.
+if test "x$with_vbox" != xno; then
+    if test "x$with_edit" = xyes; then
+        VIRSH_LIBS="$VIRSH_LIBS $EDIT_LIBS"
+        READLINE_CFLAGS="$READLINE_CFLAGS $EDIT_CFLAGS -DUSE_EDITLINE"
+    fi
+else
+    if test "x$lv_use_readline" = xyes; then
+        VIRSH_LIBS="$VIRSH_LIBS $READLINE_LIBS"
+        READLINE_CFLAGS="$READLINE_CFLAGS -DUSE_READLINE_HISTORY"
+    fi
+fi
 AC_SUBST([VIRSH_LIBS])

 dnl check if the network driver should be compiled
diff --git a/libvirt.spec.in b/libvirt.spec.in
index ae1bd21..56ef277 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -406,7 +406,11 @@ BuildRequires: xen-devel
 BuildRequires: libxml2-devel
 BuildRequires: xhtml1-dtds
 BuildRequires: libxslt
+%if %{with_vbox}
+BuildRequires: libedit-devel
+%else
 BuildRequires: readline-devel
+%endif
 BuildRequires: ncurses-devel
 BuildRequires: gettext
 BuildRequires: libtasn1-devel
@@ -1017,7 +1021,11 @@ capabilities of XEN
 %package client
 Summary: Client side library and utilities of the libvirt library
 Group: Development/Libraries
+%if %{with_vbox}
+Requires: libedit
+%else
 Requires: readline
+%endif
 Requires: ncurses
 # So remote clients can access libvirt over SSH tunnel
 # (client invokes 'nc' against the UNIX socket on the server)
diff --git a/tools/virsh.c b/tools/virsh.c
index ac86608..56bc239 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -47,7 +47,9 @@
 #include <libxml/xpath.h>
 #include <libxml/xmlsave.h>

-#ifdef HAVE_READLINE_READLINE_H
+#if USE_EDITLINE
+# include <readline.h>
+#elif USE_READLINE
 # include <readline/readline.h>
 # include <readline/history.h>
 #endif
@@ -2627,16 +2629,19 @@ vshReadlineCompletion(const char *text, int start,


 static int
-vshReadlineInit(vshControl *ctl)
+vshReadlineInit(vshControl *ctl ATTRIBUTE_UNUSED)
 {
-    char *userdir = NULL;
+    char name[] = "virsh";

     /* Allow conditional parsing of the ~/.inputrc file. */
-    rl_readline_name = "virsh";
+    rl_readline_name = name;

     /* Tell the completer that we want a crack first. */
     rl_attempted_completion_function = vshReadlineCompletion;

+# if USE_READLINE_HISTORY
+    char *userdir = NULL;
+
     /* Limit the total size of the history buffer */
     stifle_history(500);

@@ -2663,6 +2668,7 @@ vshReadlineInit(vshControl *ctl)
     VIR_FREE(userdir);

     read_history(ctl->historyfile);
+# endif /* USE_READLINE_HISTORY */

     return 0;
 }
@@ -2670,6 +2676,7 @@ vshReadlineInit(vshControl *ctl)
 static void
 vshReadlineDeinit(vshControl *ctl)
 {
+# if USE_READLINE_HISTORY
     if (ctl->historyfile != NULL) {
         if (virFileMakePathWithMode(ctl->historydir, 0755) < 0 &&
             errno != EEXIST) {
@@ -2680,6 +2687,7 @@ vshReadlineDeinit(vshControl *ctl)
             write_history(ctl->historyfile);
         }
     }
+# endif /* USE_READLINE_HISTORY */

     VIR_FREE(ctl->historydir);
     VIR_FREE(ctl->historyfile);
@@ -2955,6 +2963,9 @@ vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED)
 #ifdef USE_READLINE
     vshPrint(ctl, " Readline");
 #endif
+#ifdef USE_READLINE_HISTORY
+    vshPrint(ctl, " History");
+#endif
 #ifdef WITH_DRIVER_MODULES
     vshPrint(ctl, " Modular");
 #endif
@@ -3228,7 +3239,7 @@ main(int argc, char **argv)
             if (ctl->cmdstr == NULL)
                 break;          /* EOF */
             if (*ctl->cmdstr) {
-#if USE_READLINE
+#if USE_READLINE_HISTORY
                 add_history(ctl->cmdstr);
 #endif
                 if (vshCommandStringParse(ctl, ctl->cmdstr))
-- 
1.8.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to