// Spectre 2 // // Douglas Thrift // // $Id$ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Matcher/Matcher.hpp" // XXX: Menes' linker is linking too much namespace Spectre2 { bool debug(false); } ext::String pid("spectre.pid"); inline int usage(int code = 0) { api::Cerr << "Usage: " << api::GetExecutablePath().GetName() << " start|stop|restart|reload|status [...]" << ios::NewLine; return code; } inline pid_t process() { api::FileReader fin(pid); return lexical_cast(ios::ReadLine(fin)); } void start(const app::ArgumentList& args); void stop(); inline void restart(const app::ArgumentList& args) { stop(); start(args); } void reload(); void status(); struct Spectre2Control : public app::Application { virtual int Run(const app::ArgumentList& args) { enum Command { Start, Stop, Restart, Reload, Status } command; if (!args.IsEmpty()) { const ext::String& arg(args.First()); if (arg == "start") command = Start; else if (arg == "stop") command = Stop; else if (arg == "restart") command = Restart; else if (arg == "reload") command = Reload; else if (arg == "status") command = Status; else return usage(1); _foreach (app::ArgumentList, arg, args) { Matcher matcher("^-pid=(.*)$"); if (*arg == matcher) pid = matcher[1]; } } else return usage(); switch (command) { case Start: start(args); break; case Stop: stop(); break; case Restart: restart(args); break; case Reload: reload(); break; case Status: status(); } return 0; } } spectreControl; void start(const app::ArgumentList& args) { api::Cout << "Starting Spectre daemon ... " << ios::Flush; if (pid_t process = api::Posix::CheckError(::fork())) { api::Cout << "started." << ios::NewLine; } else { _L argv; argv.Reserve(args.GetSize()); _foreach (app::ArgumentList, arg, args) argv.InsertLast(arg->NullTerminate()); ext::String command(api::GetExecutablePath().GetParent() + "Spectre2"); argv.First() = command.NullTerminate(); api::Posix::CheckError(::execv(command.NullTerminate(), const_cast(argv.NullTerminate()))); } } void stop() { api::Cout << "Stopping Spectre daemon ... " << ios::Flush; try { pid_t id(process()); api::Posix::CheckError(::kill(id, SIGTERM)); // XXX: somehow wait for it to terminate api::Cout << "stopped." << ios::NewLine; } catch (ext::Exception) { api::Cout << "failed." << ios::NewLine; } } void reload() { api::Cout << "Reloading Spectre daemon ... " << ios::Flush; try { api::Posix::CheckError(::kill(id, SIGUSR1)); api::Cout << "reloaded." << ios::NewLine; } catch (ext::Exception) { api::Cout << "failed." << ios::NewLine; } } void status() { }