]> granicus.if.org Git - icinga2/commitdiff
Implement support for libedit
authorGunnar Beutner <gunnar@beutner.name>
Tue, 17 Mar 2015 09:42:46 +0000 (10:42 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Tue, 17 Mar 2015 14:05:47 +0000 (15:05 +0100)
fixes #8776

13 files changed:
CMakeLists.txt
INSTALL.md
config.h.cmake
icinga-app/CMakeLists.txt
icinga-app/icinga2.cmake [new file with mode: 0644]
icinga2.spec
lib/base/console.cpp
lib/base/console.hpp
lib/cli/CMakeLists.txt
lib/cli/consolecommand.cpp
lib/cli/editline.hpp [new file with mode: 0644]
third-party/cmake/FindEditline.cmake [new file with mode: 0644]
third-party/cmake/FindTermcap.cmake [new file with mode: 0644]

index 1ef5d5733e183d479a6f01f34450c633ebbdc2f1..1a9ce720a62c5536ba36c8bcf2e6c56a8f3f0ef5 100644 (file)
@@ -100,6 +100,12 @@ if(NOT YAJL_FOUND)
   set(YAJL_LIBRARIES "yajl")
 endif()
 
+find_package(Editline)
+set(HAVE_EDITLINE "${EDITLINE_FOUND}")
+
+find_package(Termcap)
+set(HAVE_TERMCAP "${TERMCAP_FOUND}")
+
 include_directories(
   ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/lib
   ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/lib
@@ -108,7 +114,7 @@ include_directories(
 #set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
 
 if(APPLE)
-  set(CMAKE_INSTALL_NAME_DIR "@executable_path/../lib/icinga2")
+  set(CMAKE_INSTALL_NAME_DIR "@executable_path/..")
   set(CMAKE_MACOSX_RPATH 0)
 endif(APPLE)
 
index 82a89c3c9fb4b475d9187c9ea352c349ba5da156..f3fe5ba1401d14d8590596c6abde5964bed8ba7b 100644 (file)
@@ -32,6 +32,9 @@ parentheses):
 * optional: PostgreSQL (postgresql-devel on RHEL, libpq-dev on Debian); set CMake
             variable `ICINGA2_WITH_PGSQL` to `OFF` to disable this module
 * optional: YAJL (yajl-devel on RHEL, libyajl-dev on Debian)
+* optional: libedit (libedit-devel on RHEL, libedit-dev on Debian)
+* optional: Termcap (libtermcap-devel on RHEL, libtermcap-dev on Debian) - only required
+            if libedit doesn't already link against termcap/ncurses
 
 Note: RHEL5 ships an ancient flex version. Updated packages are available for
 example from the repoforge buildtools repository.
index 24c38ef27258c9d12469b3c7b0642bfb3b0a269b..521fcb96f6bc15884f167ab0261d33a23558968a 100644 (file)
@@ -9,6 +9,7 @@
 #cmakedefine HAVE_LIBEXECINFO
 #cmakedefine HAVE_CXXABI_H
 #cmakedefine HAVE_NICE
+#cmakedefine HAVE_EDITLINE
 
 #cmakedefine ICINGA2_UNITY_BUILD
 
index cbeb7a3c6b938118f35b086258530d8e0bee0a34..43ca460d502ea4a31ee68b884467683a930621df 100644 (file)
@@ -33,9 +33,23 @@ set_target_properties (
   OUTPUT_NAME icinga2
 )
 
+if(WIN32)
+  set(InstallPath "${CMAKE_INSTALL_SBINDIR}")
+else()
+  configure_file(icinga2.cmake ${CMAKE_CURRENT_BINARY_DIR}/icinga2 @ONLY)
+
+  install(
+    FILES ${CMAKE_CURRENT_BINARY_DIR}/icinga2
+    DESTINATION ${CMAKE_INSTALL_SBINDIR}
+    PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+  )
+
+  set(InstallPath "${CMAKE_INSTALL_LIBDIR}/icinga2/sbin")
+endif()
+
 install(
   TARGETS icinga-app
-  RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
+  RUNTIME DESTINATION ${InstallPath}
 )
 
 install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/log/icinga2\")")
diff --git a/icinga-app/icinga2.cmake b/icinga-app/icinga2.cmake
new file mode 100644 (file)
index 0000000..11ca36c
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+ICINGA2_BIN=@CMAKE_INSTALL_FULL_LIBDIR@/icinga2/sbin/icinga2
+
+if test "x`uname -s`" = "xLinux"; then
+  libedit_line=`ldd $ICINGA2_BIN 2>&1 | grep libedit`
+  if test $? -eq 0; then
+    libedit_path=`echo $libedit_line | cut -f3 -d' '`
+    if test -n "$libedit_path"; then
+      libdir=`dirname -- $libedit_path`
+      for libreadline_path in $libdir/libreadline.so*; do
+        break
+      done
+      if test -n "$libreadline_path"; then
+        export LD_PRELOAD="$libreadline_path:$LD_PRELOAD"
+      fi
+    fi
+  fi
+fi
+
+exec $ICINGA2_BIN $@
index 567afaf0794d7c39f35e7013c0e629f99b1c87cf..d2439c5183347f67eb7e4a387a59855389a687db 100644 (file)
@@ -90,6 +90,8 @@ Recommends:    monitoring-plugins
 BuildRequires: libyajl-devel
 %endif
 %endif
+BuildRequires: libedit-devel
+BuildRequires: ncurses-devel
 BuildRequires: openssl-devel
 BuildRequires: gcc-c++
 BuildRequires: libstdc++-devel
@@ -453,6 +455,8 @@ exit 0
 %exclude %{_libdir}/%{name}/libdb_ido_pgsql*
 %dir %{_libdir}/%{name}
 %{_libdir}/%{name}/*.so*
+%dir %{_libdir}/%{name}/sbin
+%{_libdir}/%{name}/sbin/%{name}
 %{_datadir}/%{name}
 %exclude %{_datadir}/%{name}/include
 %{_mandir}/man8/%{name}.8.gz
index 2a157d8eee7f76514d87397717522f6d03b7a95f..7fa9de0aedb2f52dfdb2474cad904ebd3fca63a4 100644 (file)
@@ -27,10 +27,6 @@ INITIALIZE_ONCE(&Console::DetectType);
 
 static ConsoleType l_ConsoleType = Console_Dumb;
 
-ConsoleColorTag::ConsoleColorTag(int color)
-       : m_Color(color), m_ConsoleType(-1)
-{ }
-
 ConsoleColorTag::ConsoleColorTag(int color, ConsoleType consoleType)
        : m_Color(color), m_ConsoleType(consoleType)
 { }
index ba295f52f52970dad3cc81275bbeaea9f1826b1d..93ea44900b3b577b1a9d5cc8c656b005e26b8ab0 100644 (file)
@@ -56,6 +56,8 @@ enum ConsoleColor
 
 enum ConsoleType
 {
+       Console_Autodetect = -1,
+
        Console_Dumb,
 #ifndef _WIN32
        Console_VT100,
@@ -67,8 +69,7 @@ enum ConsoleType
 class I2_BASE_API ConsoleColorTag
 {
 public:
-       ConsoleColorTag(int color);
-       ConsoleColorTag(int color, ConsoleType consoleType);
+       ConsoleColorTag(int color, ConsoleType consoleType = Console_Autodetect);
 
        friend I2_BASE_API std::ostream& operator<<(std::ostream& fp, const ConsoleColorTag& cct);
 
index 052822c099ce5ff47fabca58cdb1c084d6e37233..eb2073fe39c95ff1b6681c96252540029fafd2bb 100644 (file)
@@ -38,6 +38,16 @@ add_library(cli SHARED ${cli_SOURCES})
 
 target_link_libraries(cli ${Boost_LIBRARIES} base config remote)
 
+if(EDITLINE_FOUND)
+  target_link_libraries(cli ${EDITLINE_LIBRARIES})
+  include_directories(${EDITLINE_INCLUDE_DIR})
+endif()
+
+if(TERMCAP_FOUND)
+  target_link_libraries(cli ${TERMCAP_LIBRARIES})
+  include_directories(${TERMCAP_INCLUDE_DIR})
+endif()
+
 set_target_properties (
   cli PROPERTIES
   INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR}/icinga2
index c78708b81adb22acb72807559dfdb83c06e4b4b5..227ab6be5cd7b376438578806313d5c5b750a0e6 100644 (file)
@@ -26,7 +26,9 @@
 #include "base/utility.hpp"
 #include "base/networkstream.hpp"
 #include <iostream>
-
+#ifdef HAVE_EDITLINE
+#include "cli/editline.hpp"
+#endif /* HAVE_EDITLINE */
 
 using namespace icinga;
 namespace po = boost::program_options;
@@ -84,20 +86,44 @@ int ConsoleCommand::Run(const po::variables_map& vm, const std::vector<std::stri
                std::string command;
 
 incomplete:
-
-               std::cout << ConsoleColorTag(Console_ForegroundCyan)
-                   << fileName
-                   << ConsoleColorTag(Console_ForegroundRed);
+#ifdef HAVE_EDITLINE
+               ConsoleType console_type = Console_VT100;
+               std::ostringstream promptbuf;
+               std::ostream& os = promptbuf;
+#else /* HAVE_EDITLINE */
+               ConsoleType console_type = Console_Autodetect;
+               std::ostream& os = std::cout;
+#endif /* HAVE_EDITLINE */
+
+               os << ConsoleColorTag(Console_ForegroundCyan, console_type)
+                  << fileName
+                  << ConsoleColorTag(Console_ForegroundRed, console_type);
 
                if (!continuation)
-                       std::cout << " => ";
+                       os << " => ";
                else
-                       std::cout << " .. ";
+                       os << " .. ";
+
+               os << ConsoleColorTag(Console_Normal, console_type);
+
+#ifdef HAVE_EDITLINE
+               String prompt = promptbuf.str();
+
+               char *cline;
+               cline = readline(prompt.CStr());
+
+               if (!cline)
+                       break;
+
+               add_history(cline);
 
-               std::cout << ConsoleColorTag(Console_Normal);
+               std::string line = cline;
 
+               free(cline);
+#else /* HAVE_EDITLINE */
                std::string line;
                std::getline(std::cin, line);
+#endif /* HAVE_EDITLINE */
 
                if (!command.empty())
                        command += "\n";
diff --git a/lib/cli/editline.hpp b/lib/cli/editline.hpp
new file mode 100644 (file)
index 0000000..141991f
--- /dev/null
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org)    *
+ *                                                                            *
+ * 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; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#ifndef EDITLINE_H
+#define EDITLINE_H
+
+extern "C" {
+
+char *readline(const char *prompt);
+int add_history(const char *line);
+
+}
+
+#endif /* EDITLINE_H */
diff --git a/third-party/cmake/FindEditline.cmake b/third-party/cmake/FindEditline.cmake
new file mode 100644 (file)
index 0000000..eb84e4b
--- /dev/null
@@ -0,0 +1,86 @@
+# Copyright (c) 2014, Matthias Vallentin
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 
+#     1. Redistributions of source code must retain the above copyright
+#        notice, this list of conditions and the following disclaimer.
+# 
+#     2. Redistributions in binary form must reproduce the above copyright
+#        notice, this list of conditions and the following disclaimer in the
+#        documentation and/or other materials provided with the distribution.
+# 
+#     3. Neither the name of the copyright holder nor the names of its
+#        contributors may be used to endorse or promote products derived from
+#        this software without specific prior written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# Tries to find editline headers and libraries
+#
+# Usage of this module as follows:
+#
+#     find_package(Editline)
+#
+# Variables used by this module, they can change the default behaviour and need
+# to be set before calling find_package:
+#
+#  EDITLINE_ROOT_DIR  Set this variable to the root installation of
+#                     editline if the module has problems finding
+#                     the proper installation path.
+#
+# Variables defined by this module:
+#
+#  EDITLINE_FOUND              System has Editline libs/headers
+#  EDITLINE_LIBRARIES          The Editline libraries
+#  EDITLINE_INCLUDE_DIR        The location of Editline headers
+#  EDITLINE_VERSION            The full version of Editline
+#  EDITLINE_VERSION_MAJOR      The version major of Editline
+#  EDITLINE_VERSION_MINOR      The version minor of Editline
+
+find_path(EDITLINE_INCLUDE_DIR
+  NAMES histedit.h
+  HINTS ${EDITLINE_ROOT_DIR}/include)
+
+if (EDITLINE_INCLUDE_DIR)
+  file(STRINGS ${EDITLINE_INCLUDE_DIR}/histedit.h editline_header REGEX "^#define.LIBEDIT_[A-Z]+.*$")
+
+  string(REGEX REPLACE ".*#define.LIBEDIT_MAJOR[ \t]+([0-9]+).*" "\\1" EDITLINE_VERSION_MAJOR "${editline_header}")
+  string(REGEX REPLACE ".*#define.LIBEDIT_MINOR[ \t]+([0-9]+).*" "\\1" EDITLINE_VERSION_MINOR "${editline_header}")
+
+  set(EDITLINE_VERSION_MAJOR ${EDITLINE_VERSION_MAJOR} CACHE STRING "" FORCE)
+  set(EDITLINE_VERSION_MINOR ${EDITLINE_VERSION_MINOR} CACHE STRING "" FORCE)
+  set(EDITLINE_VERSION ${EDITLINE_VERSION_MAJOR}.${EDITLINE_VERSION_MINOR}
+    CACHE STRING "" FORCE)
+endif ()
+
+find_library(EDITLINE_LIBRARIES
+  NAMES edit
+  HINTS ${EDITLINE_ROOT_DIR}/lib)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(
+  Editline
+  DEFAULT_MSG
+  EDITLINE_LIBRARIES
+  EDITLINE_INCLUDE_DIR)
+
+mark_as_advanced(
+  EDITLINE_ROOT_DIR
+  EDITLINE_LIBRARIES
+  EDITLINE_INCLUDE_DIR
+  EDITLINE_VERSION
+  EDITLINE_VERSION_MAJOR
+  EDITLINE_VERSION_MINOR
+  )
diff --git a/third-party/cmake/FindTermcap.cmake b/third-party/cmake/FindTermcap.cmake
new file mode 100644 (file)
index 0000000..ba7c97b
--- /dev/null
@@ -0,0 +1,68 @@
+# Copyright (c) 2014, Matthias Vallentin
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 
+#     1. Redistributions of source code must retain the above copyright
+#        notice, this list of conditions and the following disclaimer.
+# 
+#     2. Redistributions in binary form must reproduce the above copyright
+#        notice, this list of conditions and the following disclaimer in the
+#        documentation and/or other materials provided with the distribution.
+# 
+#     3. Neither the name of the copyright holder nor the names of its
+#        contributors may be used to endorse or promote products derived from
+#        this software without specific prior written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# Tries to find termcap headers and libraries
+#
+# Usage of this module as follows:
+#
+#     find_package(Termcap)
+#
+# Variables used by this module, they can change the default behaviour and need
+# to be set before calling find_package:
+#
+#  TERMCAP_ROOT_DIR  Set this variable to the root installation of
+#                     termcap if the module has problems finding
+#                     the proper installation path.
+#
+# Variables defined by this module:
+#
+#  TERMCAP_FOUND              System has Termcap libs/headers
+#  TERMCAP_LIBRARIES          The Termcap libraries
+#  TERMCAP_INCLUDE_DIR        The location of Termcap headers
+
+find_path(TERMCAP_INCLUDE_DIR
+  NAMES termcap.h
+  HINTS ${TERMCAP_ROOT_DIR}/include)
+
+find_library(TERMCAP_LIBRARIES
+  NAMES termcap ncurses
+  HINTS ${TERMCAP_ROOT_DIR}/lib)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(
+  Termcap
+  DEFAULT_MSG
+  TERMCAP_LIBRARIES
+  TERMCAP_INCLUDE_DIR)
+
+mark_as_advanced(
+  TERMCAP_ROOT_DIR
+  TERMCAP_LIBRARIES
+  TERMCAP_INCLUDE_DIR
+  )