diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 5afdeb19..0102256e 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -11,6 +11,8 @@ #include #ifndef WIN32 #include "sys/signal.h" +#include +#include #else #include #include @@ -25,6 +27,8 @@ using namespace log4cxx; using namespace Transport; +static LoggerPtr logger = log4cxx::Logger::getLogger("Spectrum"); + Swift::SimpleEventLoop *eventLoop_ = NULL; static void spectrum_sigint_handler(int sig) { @@ -163,6 +167,7 @@ int main(int argc, char **argv) #ifndef WIN32 if (!no_daemon) { + // create directories try { boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir")); } @@ -179,8 +184,10 @@ int main(int argc, char **argv) std::cerr << "Can't create service.pidfile directory " << boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() << ".\n"; return 1; } + + // daemonize daemonize(CONFIG_STRING(&config, "service.working_dir").c_str(), CONFIG_STRING(&config, "service.pidfile").c_str()); - } + } #endif if (CONFIG_STRING(&config, "logging.config").empty()) { @@ -195,6 +202,34 @@ int main(int argc, char **argv) log4cxx::PropertyConfigurator::configure(CONFIG_STRING(&config, "logging.config")); } +#ifndef WIN32 + if (!CONFIG_STRING(&config, "service.group").empty()) { + struct group *gr; + if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) { + LOG4CXX_ERROR(logger, "Invalid service.group name " << CONFIG_STRING(&config, "service.group")); + return 1; + } + + if (((setgid(gr->gr_gid)) != 0) || (initgroups(CONFIG_STRING(&config, "service.user").c_str(), gr->gr_gid) != 0)) { + LOG4CXX_ERROR(logger, "Failed to set service.group name " << CONFIG_STRING(&config, "service.group") << " - " << gr->gr_gid << ":" << strerror(errno)); + return 1; + } + } + + if (!CONFIG_STRING(&config, "service.user").empty()) { + struct passwd *pw; + if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) { + LOG4CXX_ERROR(logger, "Invalid service.user name " << CONFIG_STRING(&config, "service.user")); + return 1; + } + + if ((setuid(pw->pw_uid)) != 0) { + LOG4CXX_ERROR(logger, "Failed to set service.user name " << CONFIG_STRING(&config, "service.user") << " - " << pw->pw_uid << ":" << strerror(errno)); + return 1; + } + } +#endif + Swift::SimpleEventLoop eventLoop; Swift::BoostNetworkFactories *factories = new Swift::BoostNetworkFactories(&eventLoop); diff --git a/spectrum/src/sample2.cfg b/spectrum/src/sample2.cfg index 0f4b5651..10347f9e 100644 --- a/spectrum/src/sample2.cfg +++ b/spectrum/src/sample2.cfg @@ -2,6 +2,10 @@ # 1 if Spectrum should run in server mode. server_mode = 1 +# The name of user/group Spectrum runs as. +#user=spectrum +#group=spectrum + # JID of Spectrum instance. jid = localhost diff --git a/src/config.cpp b/src/config.cpp index f171697e..7b717c1a 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -50,6 +50,8 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ("service.server", value()->default_value(""), "Server to connect to") ("service.password", value()->default_value(""), "Password used to auth the server") ("service.port", value()->default_value(0), "Port the server is listening on") + ("service.user", value()->default_value(""), "The name of user Spectrum runs as.") + ("service.group", value()->default_value(""), "The name of group Spectrum runs as.") ("service.backend", value()->default_value("libpurple_backend"), "Backend") ("service.protocol", value()->default_value(""), "Protocol") ("service.pidfile", value()->default_value("/var/run/spectrum2/spectrum2.pid"), "Full path to pid file")