diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 5037e6d0cc64a3e7fc6d9d1236372a471e88c2cc..fb52de18f119e45d77adc0b4ed156c84f44be72d 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -8,9 +8,11 @@ #include "transport/userregistration.h" #include "transport/networkpluginserver.h" #include "transport/admininterface.h" +#include "transport/statsresponder.h" #include "transport/util.h" #include "Swiften/EventLoop/SimpleEventLoop.h" #include +#include #ifndef WIN32 #include "sys/signal.h" #include @@ -122,6 +124,7 @@ int main(int argc, char **argv) boost::program_options::variables_map vm; bool no_daemon = false; std::string config_file; + std::string jid; #ifndef WIN32 @@ -135,11 +138,14 @@ int main(int argc, char **argv) return -1; } #endif - boost::program_options::options_description desc("Usage: spectrum [OPTIONS] \nAllowed options"); + boost::program_options::options_description desc(std::string("Spectrum version: ") + SPECTRUM_VERSION + "\nUsage: spectrum [OPTIONS] \nAllowed options"); desc.add_options() ("help,h", "help") ("no-daemonize,n", "Do not run spectrum as daemon") + ("no-debug,d", "Create coredumps on crash") + ("jid,j", boost::program_options::value(&jid)->default_value(""), "Specify JID of transport manually") ("config", boost::program_options::value(&config_file)->default_value(""), "Config file") + ("version,v", "Shows Spectrum version") ; try { @@ -149,7 +155,10 @@ int main(int argc, char **argv) options(desc).positional(p).run(), vm); boost::program_options::notify(vm); - + if (vm.count("version")) { + std::cout << SPECTRUM_VERSION << "\n"; + return 0; + } if(vm.count("help")) { @@ -177,31 +186,46 @@ int main(int argc, char **argv) return 1; } - if (!config.load(vm["config"].as())) { + if (!config.load(vm["config"].as(), jid)) { std::cerr << "Can't load configuration file.\n"; return 1; } -#ifndef WIN32 - if (!no_daemon) { - // create directories - try { - boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir")); - } - catch (...) { - std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n"; + // create directories + try { + boost::filesystem::create_directories( + boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() + ); + } + catch (...) { + std::cerr << "Can't create service.pidfile directory " << boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() << ".\n"; + return 1; + } + // create directories + try { + boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir")); + } + catch (...) { + std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n"; + return 1; + } + + if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) { + struct group *gr; + if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) { + std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n"; return 1; } - try { - boost::filesystem::create_directories( - boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() - ); - } - catch (...) { - std::cerr << "Can't create service.pidfile directory " << boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() << ".\n"; + struct passwd *pw; + if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) { + std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n"; return 1; } + chown(CONFIG_STRING(&config, "service.working_dir").c_str(), pw->pw_uid, gr->gr_gid); + } +#ifndef WIN32 + if (!no_daemon) { // daemonize daemonize(CONFIG_STRING(&config, "service.working_dir").c_str(), CONFIG_STRING(&config, "service.pidfile").c_str()); // removeOldIcons(CONFIG_STRING(&config, "service.working_dir") + "/icons"); @@ -231,6 +255,46 @@ int main(int argc, char **argv) p.setProperty("pid", pid); p.setProperty("jid", jid); #endif + + std::string dir; + BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) { + if (boost::ends_with(prop, ".File")) { + dir = p.get(prop); + boost::replace_all(dir, "${jid}", jid); + break; + } + } + + if (!dir.empty()) { + // create directories + try { + boost::filesystem::create_directories( + boost::filesystem::path(dir).parent_path().string() + ); + } + catch (...) { + std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ".\n"; + return 1; + } + +#ifndef WIN32 + if (!CONFIG_STRING(&config, "service.group").empty() && !CONFIG_STRING(&config, "service.user").empty()) { + struct group *gr; + if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) { + std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n"; + return 1; + } + struct passwd *pw; + if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) { + std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n"; + return 1; + } + chown(dir.c_str(), pw->pw_uid, gr->gr_gid); + } + +#endif + } + log4cxx::PropertyConfigurator::configure(p); } @@ -242,12 +306,12 @@ int main(int argc, char **argv) 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")); + std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n"; 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)); + std::cerr << "Failed to set service.group name " << CONFIG_STRING(&config, "service.group") << " - " << gr->gr_gid << ":" << strerror(errno) << "\n"; return 1; } } @@ -255,17 +319,22 @@ int main(int argc, char **argv) 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")); + std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n"; 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)); + std::cerr << "Failed to set service.user name " << CONFIG_STRING(&config, "service.user") << " - " << pw->pw_uid << ":" << strerror(errno) << "\n"; return 1; } } setrlimit(RLIMIT_CORE, &limit); } + + struct rlimit limit; + limit.rlim_max = RLIM_INFINITY; + limit.rlim_cur = RLIM_INFINITY; + setrlimit(RLIMIT_CORE, &limit); #endif Swift::SimpleEventLoop eventLoop; @@ -313,6 +382,8 @@ int main(int argc, char **argv) NetworkPluginServer plugin(&transport, &config, &userManager, &ftManager); AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend); + StatsResponder statsResponder(&transport, &userManager, &plugin, storageBackend); + statsResponder.start(); eventLoop_ = &eventLoop;