diff --git a/config.h.cmake b/config.h.cmake
index e8a7bdcba..c461e029f 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -21,7 +21,7 @@
#define ICINGA_INCLUDECONFDIR "${CMAKE_INSTALL_FULL_DATADIR}/icinga2/include"
#define ICINGA_USER "${ICINGA2_USER}"
#define ICINGA_GROUP "${ICINGA2_GROUP}"
-
+#define ICINGA_SYSCONFIGFILE "${ICINGA2_SYSCONFIGFILE}"
#define ICINGA_BUILD_HOST_NAME "${ICINGA2_BUILD_HOST_NAME}"
#define ICINGA_BUILD_COMPILER_NAME "${ICINGA2_BUILD_COMPILER_NAME}"
#define ICINGA_BUILD_COMPILER_VERSION "${ICINGA2_BUILD_COMPILER_VERSION}"
diff --git a/doc/17-language-reference.md b/doc/17-language-reference.md
index 196cc2e54..01aba61d0 100644
--- a/doc/17-language-reference.md
+++ b/doc/17-language-reference.md
@@ -389,8 +389,8 @@ ObjectsPath |**Read-write.** Contains the path of the Icinga 2 objects f
PidPath |**Read-write.** Contains the path of the Icinga 2 PID file. Defaults to RunDir + "/icinga2/icinga2.pid".
Vars |**Read-write.** Contains a dictionary with global custom attributes. Not set by default.
NodeName |**Read-write.** Contains the cluster node name. Set to the local hostname by default.
-RunAsUser |**Read-write.** Defines the user the Icinga 2 daemon is running as. Used in the `init.conf` configuration file.
-RunAsGroup |**Read-write.** Defines the group the Icinga 2 daemon is running as. Used in the `init.conf` configuration file.
+RunAsUser |**Read-write.** Defines the user the Icinga 2 daemon is running as. Set in the Icinga 2 sysconfig.
+RunAsGroup |**Read-write.** Defines the group the Icinga 2 daemon is running as. Set in the Icinga 2 sysconfig.
PlatformName |**Read-only.** The name of the operating system, e.g. "Ubuntu".
PlatformVersion |**Read-only.** The version of the operating system, e.g. "14.04.3 LTS".
PlatformKernel |**Read-only.** The name of the operating system kernel, e.g. "Linux".
@@ -407,9 +407,9 @@ Variable |Description
--------------------|-------------------
EventEngine |**Read-write.** The name of the socket event engine, can be `poll` or `epoll`. The epoll interface is only supported on Linux.
AttachDebugger |**Read-write.** Whether to attach a debugger when Icinga 2 crashes. Defaults to `false`.
-RLimitFiles |**Read-write.** Defines the resource limit for RLIMIT_NOFILE that should be set at start-up. Value cannot be set lower than the default `16 * 1024`. 0 disables the setting. Used in the `init.conf` configuration file.
-RLimitProcesses |**Read-write.** Defines the resource limit for RLIMIT_NPROC that should be set at start-up. Value cannot be set lower than the default `16 * 1024`. 0 disables the setting. Used in the `init.conf` configuration file.
-RLimitStack |**Read-write.** Defines the resource limit for RLIMIT_STACK that should be set at start-up. Value cannot be set lower than the default `256 * 1024`. 0 disables the setting. Used in the `init.conf` configuration file.
+RLimitFiles |**Read-write.** Defines the resource limit for RLIMIT_NOFILE that should be set at start-up. Value cannot be set lower than the default `16 * 1024`. 0 disables the setting. Set in Icinga 2 sysconfig.
+RLimitProcesses |**Read-write.** Defines the resource limit for RLIMIT_NPROC that should be set at start-up. Value cannot be set lower than the default `16 * 1024`. 0 disables the setting. Set in Icinga 2 sysconfig.
+RLimitStack |**Read-write.** Defines the resource limit for RLIMIT_STACK that should be set at start-up. Value cannot be set lower than the default `256 * 1024`. 0 disables the setting. Set in Icinga 2 sysconfig.
## Apply
diff --git a/etc/CMakeLists.txt b/etc/CMakeLists.txt
index bce13366b..bffca3016 100644
--- a/etc/CMakeLists.txt
+++ b/etc/CMakeLists.txt
@@ -15,8 +15,6 @@
# along with this program; if not, write to the Free Software Foundation
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-configure_file(icinga2/init.conf.cmake ${CMAKE_CURRENT_BINARY_DIR}/icinga2/init.conf @ONLY)
-
if(NOT WIN32)
configure_file(icinga2/constants.conf.cmake ${CMAKE_CURRENT_BINARY_DIR}/icinga2/constants.conf @ONLY)
endif()
@@ -25,8 +23,6 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
configure_file(logrotate.d/icinga2.cmake ${CMAKE_CURRENT_BINARY_DIR}/logrotate.d/icinga2 @ONLY)
endif()
-install_if_not_exists(${CMAKE_CURRENT_BINARY_DIR}/icinga2/init.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2)
-
if(NOT WIN32)
install_if_not_exists(${CMAKE_CURRENT_BINARY_DIR}/icinga2/constants.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2)
install_if_not_exists(icinga2/icinga2.conf ${CMAKE_INSTALL_SYSCONFDIR}/icinga2)
diff --git a/etc/icinga2/init.conf.cmake b/etc/icinga2/init.conf.cmake
deleted file mode 100644
index 9f57bca82..000000000
--- a/etc/icinga2/init.conf.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * This file is read by Icinga 2 before the main
- * configuration file (icinga2.conf) is processed.
- */
-
-const RunAsUser = "@ICINGA2_USER@"
-const RunAsGroup = "@ICINGA2_GROUP@"
diff --git a/etc/initsystem/icinga2.init.d.cmake b/etc/initsystem/icinga2.init.d.cmake
index 080fb2779..bc41ccf67 100644
--- a/etc/initsystem/icinga2.init.d.cmake
+++ b/etc/initsystem/icinga2.init.d.cmake
@@ -31,16 +31,14 @@ if [ ! -e $ICINGA2_CONFIG_FILE ]; then
exit 6
fi
-ICINGA2_USER=`$DAEMON variable get --current RunAsUser`
-if [ $? != 0 ]; then
- echo "Could not fetch RunAsUser variable. Error '$ICINGA2_USER'. Exiting."
- exit 6
+if [ ! $ICINGA2_USER ]; then
+ echo "Could not fetch \$ICINGA2_USER. Exiting."
+ exit 6
fi
-ICINGA2_GROUP=`$DAEMON variable get --current RunAsGroup`
-if [ $? != 0 ]; then
- echo "Could not fetch RunAsGroup variable. Error '$ICINGA2_GROUP'. Exiting."
- exit 6
+if [ ! $ICINGA2_GROUP ]; then
+ echo "Could not fetch \$ICINGA2_GROUP. Exiting."
+ exit 6
fi
getent passwd $ICINGA2_USER >/dev/null 2>&1 || (echo "Icinga user '$ICINGA2_USER' does not exist. Exiting." && exit 6)
@@ -49,14 +47,14 @@ getent group $ICINGA2_COMMAND_GROUP >/dev/null 2>&1 || (echo "Icinga command gro
# Get function from functions library
if [ -f /etc/rc.d/init.d/functions ]; then
- . /etc/rc.d/init.d/functions
+ . /etc/rc.d/init.d/functions
elif [ -f /etc/init.d/functions ]; then
- . /etc/init.d/functions
+ . /etc/init.d/functions
fi
# Load extra environment variables
if [ -f /etc/default/icinga2 ]; then
- . /etc/default/icinga2
+ . /etc/default/icinga2
fi
# Start Icinga 2
@@ -74,34 +72,33 @@ start() {
# Restart Icinga 2
stop() {
- printf "Stopping Icinga 2: "
+ printf "Stopping Icinga 2: "
- if [ ! -e $ICINGA2_PID_FILE ]; then
- echo "The PID file '$ICINGA2_PID_FILE' does not exist."
- if [ "x$1" = "xnofail" ]; then
+ if [ ! -e $ICINGA2_PID_FILE ]; then
+ echo "The PID file '$ICINGA2_PID_FILE' does not exist."
+ if [ "x$1" = "xnofail" ]; then
return
else
exit 7
fi
- fi
+ fi
pid=`cat $ICINGA2_PID_FILE`
-
- if kill -INT $pid >/dev/null 2>&1; then
+
+ if icinga2 internal signal -s SIGINT -p $pid >/dev/null 2>&1; then
for i in 1 2 3 4 5 6 7 8 9 10; do
- if ! kill -CHLD $pid >/dev/null 2>&1; then
+ if ! icinga2 internal signal -s SIGCHLD -p $pid >/dev/null 2>&1; then
break
fi
printf '.'
-
sleep 3
done
fi
- if kill -CHLD $pid >/dev/null 2>&1; then
- kill -KILL $pid
- fi
+ if icinga2 internal signal -s SIGCHLD -p $pid >/dev/null 2>&1; then
+ icinga2 internal signal -s SIGKILL -p $pid >/dev/null 2>&1
+ fi
echo "Done"
}
@@ -116,21 +113,21 @@ checkconfig() {
printf "Checking configuration: "
if ! $DAEMON daemon -c $ICINGA2_CONFIG_FILE -C > $ICINGA2_STARTUP_LOG 2>&1; then
- if [ "x$1" = "x" ]; then
+ if [ "x$1" = "x" ]; then
cat $ICINGA2_STARTUP_LOG
echo "Icinga 2 detected configuration errors. Check '$ICINGA2_STARTUP_LOG' for details."
- exit 1
- else
+ exit 1
+ else
echo "Not "$1"ing Icinga 2 due to configuration errors. Check '$ICINGA2_STARTUP_LOG' for details."
- if [ "x$2" = "xfail" ]; then
- exit 1
- fi
- fi
- fi
-
+ if [ "x$2" = "xfail" ]; then
+ exit 1
+ fi
+ fi
+ fi
+
echo "Done"
# no arguments requires full output
- if [ "x$1" = "x" ]; then
+ if [ "x$1" = "x" ]; then
cat $ICINGA2_STARTUP_LOG
fi
}
@@ -145,7 +142,7 @@ status() {
fi
pid=`cat $ICINGA2_PID_FILE`
- if kill -CHLD $pid >/dev/null 2>&1; then
+ if icinga2 internal signal -s SIGCHLD -p $pid >/dev/null 2>&1; then
echo "Running"
else
echo "Not running"
@@ -157,33 +154,34 @@ status() {
case "$1" in
start)
checkconfig start fail
- start
- ;;
+ start
+ ;;
stop)
- stop
- ;;
+ stop
+ ;;
status)
- status
- ;;
+ status
+ ;;
restart)
checkconfig restart fail
- stop nofail
- start
- ;;
+ stop nofail
+ start
+ ;;
condrestart)
- status > /dev/null 2>&1 || exit 0
- checkconfig restart fail
- stop nofail
- start
- ;;
+ status > /dev/null 2>&1 || exit 0
+ checkconfig restart fail
+ stop nofail
+ start
+ ;;
reload)
reload
- ;;
+ ;;
checkconfig)
checkconfig
- ;;
+ ;;
*)
- echo "Usage: $0 {start|stop|restart|reload|checkconfig|status}"
- exit 3
+ echo "Usage: $0 {start|stop|restart|reload|checkconfig|status}"
+ exit 3
esac
+
exit 0
diff --git a/etc/initsystem/icinga2.sysconfig.cmake b/etc/initsystem/icinga2.sysconfig.cmake
index e7fa54baf..7daf305be 100644
--- a/etc/initsystem/icinga2.sysconfig.cmake
+++ b/etc/initsystem/icinga2.sysconfig.cmake
@@ -3,9 +3,10 @@ ICINGA2_CONFIG_FILE=@CMAKE_INSTALL_FULL_SYSCONFDIR@/icinga2/icinga2.conf
ICINGA2_RUN_DIR=@ICINGA2_RUNDIR@
ICINGA2_STATE_DIR=@CMAKE_INSTALL_FULL_LOCALSTATEDIR@
ICINGA2_PID_FILE=$ICINGA2_RUN_DIR/icinga2/icinga2.pid
-ICINGA2_ERROR_LOG=@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/log/icinga2/error.log
-ICINGA2_STARTUP_LOG=@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/log/icinga2/startup.log
-ICINGA2_LOG=@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/log/icinga2/icinga2.log
+ICINGA2_LOG_DIR=@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/log/icinga2
+ICINGA2_ERROR_LOG=$ICINGA2_LOG_DIR/error.log
+ICINGA2_STARTUP_LOG=$ICINGA2_LOG_DIR/startup.log
+ICINGA2_LOG=$ICINGA2_LOG_DIR/icinga2.log
ICINGA2_CACHE_DIR=$ICINGA2_STATE_DIR/cache/icinga2
ICINGA2_USER=@ICINGA2_USER@
ICINGA2_GROUP=@ICINGA2_GROUP@
diff --git a/etc/initsystem/prepare-dirs b/etc/initsystem/prepare-dirs
index 5d67d476d..44b8343a8 100644
--- a/etc/initsystem/prepare-dirs
+++ b/etc/initsystem/prepare-dirs
@@ -13,49 +13,42 @@ else
fi
-ICINGA2_USER=`$DAEMON variable get --current RunAsUser`
-if [ $? != 0 ]; then
- echo "Could not fetch RunAsUser variable. Error '$ICINGA2_USER'. Exiting."
- exit 6
+if [ ! $ICINGA2_USER ]; then
+ echo "Could not fetch \$ICINGA2_USER. Exiting."
+ exit 6
fi
-ICINGA2_GROUP=`$DAEMON variable get --current RunAsGroup`
-if [ $? != 0 ]; then
- echo "Could not fetch RunAsGroup variable. Error '$ICINGA2_GROUP'. Exiting."
- exit 6
+if [ ! $ICINGA2_GROUP ]; then
+ echo "Could not fetch \$ICINGA2_GROUP. Exiting."
+ exit 6
fi
getent passwd $ICINGA2_USER >/dev/null 2>&1 || (echo "Icinga user '$ICINGA2_USER' does not exist. Exiting." && exit 6)
getent group $ICINGA2_GROUP >/dev/null 2>&1 || (echo "Icinga group '$ICINGA2_GROUP' does not exist. Exiting." && exit 6)
getent group $ICINGA2_COMMAND_GROUP >/dev/null 2>&1 || (echo "Icinga command group '$ICINGA2_COMMAND_GROUP' does not exist. Exiting." && exit 6)
-mkdir -p $(dirname -- $ICINGA2_PID_FILE)
-chown $ICINGA2_USER:$ICINGA2_COMMAND_GROUP $(dirname -- $ICINGA2_PID_FILE)
-if [ -f $ICINGA2_PID_FILE ]; then
- chown $ICINGA2_USER:$ICINGA2_GROUP $ICINGA2_PID_FILE
+if [ ! -e "$ICINGA2_RUN_DIR"/icinga2 ]; then
+ mkdir "$ICINGA2_RUN_DIR"/icinga2
+ mkdir "$ICINGA2_RUN_DIR"/icinga2/cmd
+ chmod 755 "$ICINGA2_RUN_DIR"/icinga2
+ chmod 2750 "$ICINGA2_RUN_DIR"/icinga2/cmd
+ chown -R $ICINGA2_USER:$ICINGA2_COMMAND_GROUP "$ICINGA2_RUN_DIR"/icinga2
fi
-mkdir -p $(dirname -- $ICINGA2_ERROR_LOG)
-chown $ICINGA2_USER:$ICINGA2_COMMAND_GROUP $(dirname -- $ICINGA2_ERROR_LOG)
-chmod 750 $(dirname -- $ICINGA2_ERROR_LOG)
-if [ -f $ICINGA2_ERROR_LOG ]; then
- chown $ICINGA2_USER:$ICINGA2_COMMAND_GROUP $ICINGA2_ERROR_LOG
-fi
-if [ -f $ICINGA2_LOG ]; then
- chown $ICINGA2_USER:$ICINGA2_COMMAND_GROUP $ICINGA2_LOG
+# Could be undefined in installations where sysconf is not overridden on upgrade
+if [ -z "$ICINGA2_LOG_DIR" ]; then
+ $ICINGA2_LOG_DIR=$(dirname -- "$ICINGA2_LOG")
fi
-mkdir -p $ICINGA2_RUN_DIR/icinga2/cmd
-chown $ICINGA2_USER:$ICINGA2_COMMAND_GROUP $ICINGA2_RUN_DIR/icinga2/cmd
+test -e "$ICINGA2_LOG_DIR" || install -m 750 -o $ICINGA2_USER -g $ICINGA2_COMMAND_GROUP -d "$ICINGA2_LOG_DIR"
+
if type restorecon >/dev/null 2>&1; then
- restorecon -R $ICINGA2_RUN_DIR/icinga2/
+ restorecon -R "$ICINGA2_RUN_DIR"/icinga2/
fi
-chmod 2750 $ICINGA2_RUN_DIR/icinga2/cmd
# Add a fallback if the user did not specify this directory in the sysconfig file
if [ -z "$ICINGA2_CACHE_DIR" ]; then
- ICINGA2_CACHE_DIR=$ICINGA2_STATE_DIR/cache/icinga2
+ ICINGA2_CACHE_DIR="$ICINGA2_STATE_DIR"/cache/icinga2
fi
-mkdir -p $ICINGA2_CACHE_DIR
-chown $ICINGA2_USER:$ICINGA2_GROUP $ICINGA2_CACHE_DIR
-chmod 750 $ICINGA2_CACHE_DIR
+
+test -e "$ICINGA2_CACHE_DIR" || install -m 750 -o $ICINGA2_USER -g $ICINGA2_COMMAND_GROUP -d "$ICINGA2_CACHE_DIR"
diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp
index ef6627818..af8a1dda9 100644
--- a/icinga-app/icinga.cpp
+++ b/icinga-app/icinga.cpp
@@ -143,6 +143,7 @@ static int Main()
#endif /* _WIN32 */
Application::DeclarePrefixDir(ICINGA_PREFIX);
+ Application::DeclareSysconfigFile(ICINGA_SYSCONFIGFILE);
Application::DeclareSysconfDir(ICINGA_SYSCONFDIR);
Application::DeclareRunDir(ICINGA_RUNDIR);
Application::DeclareLocalStateDir(ICINGA_LOCALSTATEDIR);
@@ -153,13 +154,63 @@ static int Main()
#endif /* _WIN32 */
Application::DeclareZonesDir(Application::GetSysconfDir() + "/icinga2/zones.d");
- Application::DeclareRunAsUser(ICINGA_USER);
- Application::DeclareRunAsGroup(ICINGA_GROUP);
-#ifdef __linux__
- Application::DeclareRLimitFiles(Application::GetDefaultRLimitFiles());
- Application::DeclareRLimitProcesses(Application::GetDefaultRLimitProcesses());
- Application::DeclareRLimitStack(Application::GetDefaultRLimitStack());
-#endif /* __linux__ */
+
+ String icingaUser = Utility::GetFromSysconfig("ICINGA2_USER");
+ if (icingaUser.IsEmpty())
+ icingaUser = ICINGA_USER;
+
+ String icingaGroup = Utility::GetFromSysconfig("ICINGA2_GROUP");
+ if (icingaGroup.IsEmpty())
+ icingaGroup = ICINGA_GROUP;
+
+ Application::DeclareRunAsUser(icingaUser);
+ Application::DeclareRunAsGroup(icingaGroup);
+
+#ifdef RLIMIT_NOFILE
+ String rLimitFiles = Utility::GetFromSysconfig("ICINGA2_RLIMIT_FILES");
+ if (rLimitFiles.IsEmpty())
+ Application::DeclareRLimitFiles(Application::GetDefaultRLimitFiles());
+ else {
+ try {
+ Application::DeclareRLimitFiles(Convert::ToLong(rLimitFiles));
+ } catch (const std::invalid_argument& ex) {
+ std::cout
+ << "Error while parsing \"ICINGA2_RLIMIT_FILES\" from sysconfig: " << ex.what() << '\n';
+ return EXIT_FAILURE;
+ }
+ }
+#endif /* RLIMIT_NOFILE */
+
+#ifdef RLIMIT_NPROC
+ String rLimitProcesses = Utility::GetFromSysconfig("ICINGA2_RLIMIT_PROCESSES");
+ if (rLimitProcesses.IsEmpty())
+ Application::DeclareRLimitProcesses(Application::GetDefaultRLimitProcesses());
+ else {
+ try {
+ Application::DeclareRLimitProcesses(Convert::ToLong(rLimitProcesses));
+ } catch (const std::invalid_argument& ex) {
+ std::cout
+ << "Error while parsing \"ICINGA2_RLIMIT_PROCESSES\" from sysconfig: " << ex.what() << '\n';
+ return EXIT_FAILURE;
+ }
+ }
+#endif /* RLIMIT_NPROC */
+
+#ifdef RLIMIT_STACK
+ String rLimitStack = Utility::GetFromSysconfig("ICINGA2_RLIMIT_STACK");
+ if (rLimitStack.IsEmpty())
+ Application::DeclareRLimitStack(Application::GetDefaultRLimitStack());
+ else {
+ try {
+ Application::DeclareRLimitStack(Convert::ToLong(rLimitStack));
+ } catch (const std::invalid_argument& ex) {
+ std::cout
+ << "Error while parsing \"ICINGA2_RLIMIT_STACK\" from sysconfig: " << ex.what() << '\n';
+ return EXIT_FAILURE;
+ }
+ }
+#endif /* RLIMIT_STACK */
+
Application::DeclareConcurrency(std::thread::hardware_concurrency());
Application::DeclareMaxConcurrentChecks(Application::GetDefaultMaxConcurrentChecks());
@@ -175,21 +226,6 @@ static int Main()
ScriptGlobal::Set("BuildCompilerName", ICINGA_BUILD_COMPILER_NAME);
ScriptGlobal::Set("BuildCompilerVersion", ICINGA_BUILD_COMPILER_VERSION);
- String initconfig = Application::GetSysconfDir() + "/icinga2/init.conf";
-
- if (Utility::PathExists(initconfig)) {
- std::unique_ptr expression;
- try {
- expression = ConfigCompiler::CompileFile(initconfig);
-
- ScriptFrame frame(true);
- expression->Evaluate(frame);
- } catch (const std::exception& ex) {
- Log(LogCritical, "config", DiagnosticInformation(ex));
- return EXIT_FAILURE;
- }
- }
-
if (!autocomplete)
Application::SetResourceLimits();
diff --git a/lib/base/application.cpp b/lib/base/application.cpp
index 7c552eaeb..1c1aa6776 100644
--- a/lib/base/application.cpp
+++ b/lib/base/application.cpp
@@ -1326,6 +1326,27 @@ void Application::DeclareStatePath(const String& path)
ScriptGlobal::Set("StatePath", path);
}
+/**
+ * Retrives the path of the sysconfig file.
+ *
+ * @returns The path.
+ */
+String Application::GetSysconfigFile(void)
+{
+ return ScriptGlobal::Get("SysconfigFile");
+}
+
+/**
+ * Sets the path of the sysconfig file.
+ *
+ * @param path The new path.
+ */
+void Application::DeclareSysconfigFile(const String& path)
+{
+ if (!ScriptGlobal::Exists("SysconfigFile"))
+ ScriptGlobal::Set("SysconfigFile", path);
+}
+
/**
* Retrieves the path for the modified attributes file.
*
diff --git a/lib/base/application.hpp b/lib/base/application.hpp
index ecdb1e92b..03d83599b 100644
--- a/lib/base/application.hpp
+++ b/lib/base/application.hpp
@@ -106,7 +106,10 @@ public:
static String GetIncludeConfDir();
static void DeclareIncludeConfDir(const String& path);
- static String GetStatePath();
+ static String GetSysconfigFile(void);
+ static void DeclareSysconfigFile(const String& path);
+
+ static String GetStatePath(void);
static void DeclareStatePath(const String& path);
static String GetModAttrPath();
diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp
index f9cf18cdb..6869e353d 100644
--- a/lib/base/utility.cpp
+++ b/lib/base/utility.cpp
@@ -1935,3 +1935,35 @@ String Utility::GetIcingaDataPath()
}
#endif /* _WIN32 */
+
+String Utility::GetFromSysconfig(const String& env)
+{
+#ifndef _WIN32
+ String sysconf = Application::GetSysconfigFile();
+ if (sysconf.IsEmpty())
+ return "";
+
+ String cmdInner = ". " + EscapeShellArg(sysconf) + " 2>&1 >/dev/null;echo \"$" + env + "\"";
+ String cmd = "sh -c " + EscapeShellArg(cmdInner);
+
+ FILE *fp = popen(cmd.CStr(), "r");
+
+ if (!fp)
+ return "";
+
+ char line[1024];
+ String out;
+
+ if (fgets(line, sizeof(line), fp))
+ out = line;
+ else
+ return "";
+
+ pclose(fp);
+
+ return out.Trim();
+#else
+ //TODO: Figure out how to do this on windows
+ return "";
+#endif /* _WIN32 */
+}
diff --git a/lib/base/utility.hpp b/lib/base/utility.hpp
index dd542c30a..97bb834b8 100644
--- a/lib/base/utility.hpp
+++ b/lib/base/utility.hpp
@@ -147,6 +147,8 @@ public:
static String GetIcingaDataPath();
#endif /* _WIN32 */
+ static String GetFromSysconfig(const String& env);
+
#ifdef I2_DEBUG
static void SetTime(double);
static void IncrementTime(double);
diff --git a/lib/cli/CMakeLists.txt b/lib/cli/CMakeLists.txt
index bb2c75f47..258597dec 100644
--- a/lib/cli/CMakeLists.txt
+++ b/lib/cli/CMakeLists.txt
@@ -30,6 +30,7 @@ set(cli_SOURCES
featureenablecommand.cpp featureenablecommand.hpp
featurelistcommand.cpp featurelistcommand.hpp
featureutility.cpp featureutility.hpp
+ internalsignalcommand.cpp internalsignalcommand.hpp
nodesetupcommand.cpp nodesetupcommand.hpp
nodeutility.cpp nodeutility.hpp
nodewizardcommand.cpp nodewizardcommand.hpp
diff --git a/lib/cli/internalsignalcommand.cpp b/lib/cli/internalsignalcommand.cpp
new file mode 100644
index 000000000..3e196728d
--- /dev/null
+++ b/lib/cli/internalsignalcommand.cpp
@@ -0,0 +1,84 @@
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
+ * *
+ * 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. *
+ ******************************************************************************/
+
+#include "cli/internalsignalcommand.hpp"
+#include "base/logger.hpp"
+#include
+
+using namespace icinga;
+namespace po = boost::program_options;
+
+REGISTER_CLICOMMAND("internal/signal", InternalSignalCommand);
+
+String InternalSignalCommand::GetDescription() const
+{
+ return "Send signal as Icinga user";
+}
+
+String InternalSignalCommand::GetShortDescription() const
+{
+ return "Send signal as Icinga user";
+}
+
+ImpersonationLevel InternalSignalCommand::GetImpersonationLevel() const
+{
+ return ImpersonateIcinga;
+}
+
+bool InternalSignalCommand::IsHidden() const
+{
+ return true;
+}
+
+void InternalSignalCommand::InitParameters(boost::program_options::options_description& visibleDesc,
+ boost::program_options::options_description& hiddenDesc) const
+{
+ visibleDesc.add_options()
+ ("pid,p", po::value(), "Target PID")
+ ("sig,s", po::value(), "Signal (POSIX string) to send")
+ ;
+}
+
+/**
+ * The entry point for the "internal signal" CLI command.
+ *
+ * @returns An exit status.
+ */
+int InternalSignalCommand::Run(const boost::program_options::variables_map& vm, const std::vector& ap) const
+{
+#ifndef _WIN32
+ String signal = vm["sig"].as();
+
+ /* Thank POSIX */
+ if (signal == "SIGKILL")
+ return kill(vm["pid"].as(), SIGKILL);
+ if (signal == "SIGINT")
+ return kill(vm["pid"].as(), SIGINT);
+ if (signal == "SIGCHLD")
+ return kill(vm["pid"].as(), SIGCHLD);
+ if (signal == "SIGHUP")
+ return kill(vm["pid"].as(), SIGHUP);
+
+ Log(LogCritical, "cli") << "Unsupported signal \"" << signal << "\"";
+#else
+ Log(LogCritical, "cli", "Unsupported action on Windows.");
+#endif /* _Win32 */
+ return 1;
+}
+
diff --git a/lib/cli/internalsignalcommand.hpp b/lib/cli/internalsignalcommand.hpp
new file mode 100644
index 000000000..44830ccd9
--- /dev/null
+++ b/lib/cli/internalsignalcommand.hpp
@@ -0,0 +1,50 @@
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
+ * *
+ * 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 INTERNALSIGNALCOMMAND_H
+#define INTERNALSIGNALCOMMAND_H
+
+#include "cli/clicommand.hpp"
+
+namespace icinga
+{
+
+/**
+ * The "internal signal" command.
+ *
+ * @ingroup cli
+ */
+class InternalSignalCommand final : public CLICommand
+{
+public:
+ DECLARE_PTR_TYPEDEFS(InternalSignalCommand);
+
+ String GetDescription() const override;
+ String GetShortDescription() const override;
+ ImpersonationLevel GetImpersonationLevel() const override;
+ bool IsHidden() const override;
+ void InitParameters(boost::program_options::options_description& visibleDesc,
+ boost::program_options::options_description& hiddenDesc) const override;
+ int Run(const boost::program_options::variables_map& vm, const std::vector& ap) const override;
+
+};
+
+}
+
+#endif /* INTERNALSIGNALCOMMAND_H */