summaryrefslogtreecommitdiffstats
path: root/src/lib/process/daemon.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/process/daemon.cc')
-rw-r--r--src/lib/process/daemon.cc266
1 files changed, 266 insertions, 0 deletions
diff --git a/src/lib/process/daemon.cc b/src/lib/process/daemon.cc
new file mode 100644
index 0000000..c2589c9
--- /dev/null
+++ b/src/lib/process/daemon.cc
@@ -0,0 +1,266 @@
+// Copyright (C) 2014-2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <cc/data.h>
+#include <process/daemon.h>
+#include <process/log_parser.h>
+#include <exceptions/exceptions.h>
+#include <log/logger_name.h>
+#include <log/logger_support.h>
+#include <process/config_base.h>
+#include <process/redact_config.h>
+#include <util/filename.h>
+
+#include <functional>
+#include <sstream>
+#include <fstream>
+
+#include <errno.h>
+
+using namespace isc::data;
+namespace ph = std::placeholders;
+
+/// @brief provides default implementation for basic daemon operations
+///
+/// This file provides stub implementations that are expected to be redefined
+/// in derived classes (e.g. ControlledDhcpv6Srv)
+namespace isc {
+namespace process {
+
+bool Daemon::verbose_ = false;
+
+std::string Daemon::proc_name_("");
+
+std::string Daemon::default_logger_name_("kea");
+
+Daemon::Daemon()
+ : signal_set_(), config_file_(""),
+ pid_file_dir_(DATA_DIR), pid_file_(), am_file_author_(false),
+ exit_value_(EXIT_SUCCESS) {
+
+ // The pid_file_dir can be overridden via environment variable
+ // This is primarily intended to simplify testing
+ const char* const env = getenv("KEA_PIDFILE_DIR");
+ if (env) {
+ pid_file_dir_ = env;
+ }
+}
+
+Daemon::~Daemon() {
+ if (pid_file_ && am_file_author_) {
+ pid_file_->deleteFile();
+ }
+}
+
+void Daemon::cleanup() {
+}
+
+void Daemon::shutdown() {
+}
+
+void Daemon::configureLogger(const ConstElementPtr& log_config,
+ const ConfigPtr& storage) {
+
+ if (log_config) {
+ ConstElementPtr loggers = log_config->get("loggers");
+ if (loggers) {
+ LogConfigParser parser(storage);
+ parser.parseConfiguration(loggers, verbose_);
+ }
+ }
+}
+
+void
+Daemon::setVerbose(bool verbose) {
+ verbose_ = verbose;
+}
+
+bool
+Daemon::getVerbose() {
+ return (verbose_);
+}
+
+void Daemon::loggerInit(const char* name, bool verbose) {
+
+ setenv("KEA_LOGGER_DESTINATION", "stdout", 0);
+
+ // Initialize logger system
+ isc::log::initLogger(name, isc::log::DEBUG, isc::log::MAX_DEBUG_LEVEL,
+ NULL);
+
+ // Apply default configuration (log INFO or DEBUG to stdout)
+ isc::log::setDefaultLoggingOutput(verbose);
+}
+
+std::string Daemon::getVersion(bool /*extended*/) {
+ isc_throw(isc::NotImplemented, "Daemon::getVersion() called");
+}
+
+std::string
+Daemon::getConfigFile() const {
+ return (config_file_);
+}
+
+void
+Daemon::setConfigFile(const std::string& config_file) {
+ config_file_ = config_file;
+}
+
+void
+Daemon::checkConfigFile() const {
+ if (config_file_.empty()) {
+ isc_throw(isc::BadValue, "config file name is not set");
+ }
+
+ // Create Filename instance from the config_file_ pathname, and
+ // check the file name component.
+ isc::util::Filename file(config_file_);
+ if (file.name().empty()) {
+ isc_throw(isc::BadValue, "config file:" << config_file_
+ << " is missing file name");
+ }
+}
+
+std::string
+Daemon::getProcName() {
+ return (proc_name_);
+};
+
+void
+Daemon::setProcName(const std::string& proc_name) {
+ proc_name_ = proc_name;
+}
+
+std::string
+Daemon::getPIDFileDir() const {
+ return(pid_file_dir_);
+}
+
+void
+Daemon::setPIDFileDir(const std::string& pid_file_dir) {
+ pid_file_dir_ = pid_file_dir;
+}
+
+std::string
+Daemon::getPIDFileName() const {
+ if (pid_file_) {
+ return (pid_file_->getFilename());
+ }
+
+ return ("");
+};
+
+void
+Daemon::setPIDFileName(const std::string& pid_file_name) {
+ if (pid_file_) {
+ isc_throw(isc::InvalidOperation, "Daemon::setConfigFile"
+ " file name already set to:" << pid_file_->getFilename());
+ }
+
+ if (pid_file_name.empty()) {
+ isc_throw(isc::BadValue, "Daemon::setPIDFileName"
+ " file name may not be empty");
+ }
+
+ pid_file_.reset(new util::PIDFile(pid_file_name));
+};
+
+std::string
+Daemon::makePIDFileName() const {
+ if (config_file_.empty()) {
+ isc_throw(isc::InvalidOperation,
+ "Daemon::makePIDFileName config file name is not set");
+ }
+
+ // Create Filename instance from the config_file_ pathname, so we can
+ // extract the fname component.
+ isc::util::Filename file(config_file_);
+ if (file.name().empty()) {
+ isc_throw(isc::BadValue, "Daemon::makePIDFileName config file:"
+ << config_file_ << " is missing file name");
+ }
+
+ if (proc_name_.empty()) {
+ isc_throw(isc::InvalidOperation,
+ "Daemon::makePIDFileName process name is not set");
+ }
+
+ // Make the pathname for the PID file from the runtime directory,
+ // configuration name and process name.
+ std::ostringstream stream;
+ stream << pid_file_dir_ << "/" << file.name()
+ << "." << proc_name_ << ".pid";
+
+ return(stream.str());
+};
+
+void
+Daemon::createPIDFile(int pid) {
+ // If pid_file_ hasn't been instantiated explicitly, then do so
+ // using the default name.
+ if (!pid_file_) {
+ setPIDFileName(makePIDFileName());
+ }
+
+ // If we find a pre-existing file containing a live PID we bail.
+ int chk_pid = pid_file_->check();
+ if (chk_pid > 0) {
+ isc_throw(DaemonPIDExists, "Daemon::createPIDFile: PID: " << chk_pid
+ << " exists, PID file: " << getPIDFileName());
+ }
+
+ if (pid == 0) {
+ // Write the PID of the current process
+ pid_file_->write();
+ } else {
+ // Write the PID we were given
+ pid_file_->write(pid);
+ }
+
+ am_file_author_ = true;
+}
+
+size_t
+Daemon::writeConfigFile(const std::string& config_file,
+ ConstElementPtr cfg) const {
+ if (!cfg) {
+ isc_throw(Unexpected, "Can't write configuration: conversion to JSON failed");
+ }
+
+ std::ofstream out(config_file, std::ios::trunc);
+ if (!out.good()) {
+ isc_throw(Unexpected, "Unable to open file " + config_file + " for writing");
+ }
+
+ // Write the actual content using pretty printing.
+ prettyPrint(cfg, out);
+
+ size_t bytes = static_cast<size_t>(out.tellp());
+
+ out.close();
+
+ return (bytes);
+}
+
+std::list<std::list<std::string>>
+Daemon::jsonPathsToRedact() const {
+ static std::list<std::list<std::string>> const list;
+ return list;
+}
+
+isc::data::ConstElementPtr
+Daemon::redactConfig(isc::data::ConstElementPtr const& config) {
+ isc::data::ConstElementPtr result(config);
+ for (std::list<std::string>& json_path : jsonPathsToRedact()) {
+ result = isc::process::redactConfig(result, json_path);
+ }
+ return result;
+}
+
+} // namespace process
+} // namespace isc