From: Gunnar Beutner Date: Tue, 17 Mar 2015 09:42:46 +0000 (+0100) Subject: Implement support for libedit X-Git-Tag: v2.4.0~814 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=37736caa5c6da877118e7c4b5c584c55f9ed8ec4;p=icinga2 Implement support for libedit fixes #8776 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ef5d5733..1a9ce720a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/INSTALL.md b/INSTALL.md index 82a89c3c9..f3fe5ba14 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -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. diff --git a/config.h.cmake b/config.h.cmake index 24c38ef27..521fcb96f 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -9,6 +9,7 @@ #cmakedefine HAVE_LIBEXECINFO #cmakedefine HAVE_CXXABI_H #cmakedefine HAVE_NICE +#cmakedefine HAVE_EDITLINE #cmakedefine ICINGA2_UNITY_BUILD diff --git a/icinga-app/CMakeLists.txt b/icinga-app/CMakeLists.txt index cbeb7a3c6..43ca460d5 100644 --- a/icinga-app/CMakeLists.txt +++ b/icinga-app/CMakeLists.txt @@ -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 index 000000000..11ca36c45 --- /dev/null +++ b/icinga-app/icinga2.cmake @@ -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 $@ diff --git a/icinga2.spec b/icinga2.spec index 567afaf07..d2439c518 100644 --- a/icinga2.spec +++ b/icinga2.spec @@ -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 diff --git a/lib/base/console.cpp b/lib/base/console.cpp index 2a157d8ee..7fa9de0ae 100644 --- a/lib/base/console.cpp +++ b/lib/base/console.cpp @@ -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) { } diff --git a/lib/base/console.hpp b/lib/base/console.hpp index ba295f52f..93ea44900 100644 --- a/lib/base/console.hpp +++ b/lib/base/console.hpp @@ -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); diff --git a/lib/cli/CMakeLists.txt b/lib/cli/CMakeLists.txt index 052822c09..eb2073fe3 100644 --- a/lib/cli/CMakeLists.txt +++ b/lib/cli/CMakeLists.txt @@ -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 diff --git a/lib/cli/consolecommand.cpp b/lib/cli/consolecommand.cpp index c78708b81..227ab6be5 100644 --- a/lib/cli/consolecommand.cpp +++ b/lib/cli/consolecommand.cpp @@ -26,7 +26,9 @@ #include "base/utility.hpp" #include "base/networkstream.hpp" #include - +#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 "; + 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 index 000000000..141991fe4 --- /dev/null +++ b/lib/cli/editline.hpp @@ -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 index 000000000..eb84e4bb3 --- /dev/null +++ b/third-party/cmake/FindEditline.cmake @@ -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 index 000000000..ba7c97b00 --- /dev/null +++ b/third-party/cmake/FindTermcap.cmake @@ -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 + )