// Spectre 2 // // Douglas Thrift // // $Id$ #include "Mounter.hpp" #include "Unmounter.hpp" #include #include #include #include int Main(const app::Options& options) { api::Path config(Spectre2::prefix + "/etc/spectre.xml"); enum Mode { none, pid = 1, fork } mode(none); _foreach (const app::ArgumentList, arg, app::GetArguments()) { Matcher matcher; if (*arg == matcher("^-config=(.*)$")) config = matcher[1]; else if (*arg == "-pid") mode = pid; else if (*arg == "-fork") mode = fork; else if (*arg == "-D") Spectre2::debug = true; else if (*arg != matcher("^--.*$")) { api::Cerr << "Usage: " << Spectre2::program << " [-config=config] [-pid|-fork] [-D]" << ios::NewLine; return 1; } } if (!config.Exists()) { api::Cerr << Spectre2::program << ": configuration file " << config.GetPath() << " does not exist." << ios::NewLine; return 2; } switch (mode) { case pid: try { _H document(xml::Parse(config.GetPath())); api::FileReader in(*document/"spectre"/"pid"); ios::ReadToWrite(in, api::Cout); } catch (const api::Error&) { return 1; } break; case fork: if (api::Posix::CheckError(::fork())) return 0; default: { Spectre2 spectre(config); } } return 0; } extern "C" { void reload(int signal, ::siginfo_t* info, void* uap); void stop(int signal, ::siginfo_t* info, void* uap); } Spectre2::Spectre2(const api::Path& config) { { _H document(xml::Parse(config.GetPath())); _H spectre(*document/"spectre"); pid = *spectre/"pid"; } { api::FileWriter out(pid); ios::FormatWriter fout(out); fout << ::getpid() << ios::NewLine; } Daemon daemon_(config); daemon = &daemon_; { struct ::sigaction action; action.sa_sigaction = reload; action.sa_flags = SA_SIGINFO; api::Posix::CheckError(::sigemptyset(&action.sa_mask)); api::Posix::CheckError(::sigaction(SIGUSR1, &action, NULL)); action.sa_sigaction = stop; api::Posix::CheckError(::sigaction(SIGINT, &action, NULL)); api::Posix::CheckError(::sigaction(SIGTERM, &action, NULL)); } } Spectre2::~Spectre2() { api::Posix::CheckError(::unlink(pid.NullTerminate())); } ext::String Spectre2::program(api::GetExecutablePath().GetName()), Spectre2::prefix(_Spectre2_prefix_), Spectre2::root(_Spectre2_root_), Spectre2::mount(_Spectre2_mount_), Spectre2::umount(_Spectre2_umount_); bool Spectre2::debug(false); Daemon* Spectre2::daemon; extern "C" { void reload(int signal, ::siginfo_t* info, void* uap) { if (Spectre2::debug) api::Cout << "Reload" << ios::NewLine; Spectre2::daemon->reload(); } void stop(int signal, ::siginfo_t* info, void* uap) { if (Spectre2::debug) api::Cout << "Stop" << ios::NewLine; Spectre2::daemon->stop(); } }