2016-01-07 08:14:33 +00:00
|
|
|
#pragma once
|
2015-06-15 22:16:43 +00:00
|
|
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
|
|
|
namespace nall {
|
|
|
|
|
|
|
|
struct service {
|
|
|
|
inline explicit operator bool() const;
|
|
|
|
inline auto command(const string& name, const string& command) -> bool;
|
|
|
|
inline auto receive() -> string;
|
|
|
|
inline auto name() const -> string;
|
|
|
|
inline auto stop() const -> bool;
|
|
|
|
|
|
|
|
private:
|
|
|
|
shared_memory shared;
|
|
|
|
string _name;
|
|
|
|
bool _stop = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
service::operator bool() const {
|
|
|
|
return (bool)shared;
|
|
|
|
}
|
|
|
|
|
|
|
|
//returns true on new service process creation (false is not necessarily an error)
|
|
|
|
auto service::command(const string& name, const string& command) -> bool {
|
|
|
|
if(!name) return false;
|
|
|
|
if(!command) return print("[{0}] usage: {service} command\n"
|
|
|
|
"commands:\n"
|
|
|
|
" status : query whether service is running\n"
|
|
|
|
" start : start service if it is not running\n"
|
|
|
|
" stop : stop service if it is running\n"
|
|
|
|
" remove : remove semaphore lock if service crashed\n"
|
|
|
|
" {value} : send custom command to service\n"
|
|
|
|
"", format{name}), false;
|
|
|
|
|
|
|
|
if(shared.open(name, 4096)) {
|
|
|
|
if(command == "start") {
|
|
|
|
print("[{0}] already started\n", format{name});
|
|
|
|
} else if(command == "status") {
|
|
|
|
print("[{0}] running\n", format{name});
|
|
|
|
}
|
|
|
|
if(auto data = shared.acquire()) {
|
|
|
|
if(command == "stop") print("[{0}] stopped\n", format{name});
|
|
|
|
memory::copy(data, command.data(), min(command.size(), 4096));
|
|
|
|
shared.release();
|
|
|
|
}
|
|
|
|
if(command == "remove") {
|
|
|
|
shared.remove();
|
|
|
|
print("[{0}] removed\n", format{name});
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(command == "start") {
|
|
|
|
if(shared.create(name, 4096)) {
|
|
|
|
print("[{0}] started\n", format{name});
|
|
|
|
auto pid = fork();
|
|
|
|
if(pid == 0) {
|
|
|
|
signal(SIGHUP, SIG_IGN);
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
_name = name;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
shared.close();
|
|
|
|
} else {
|
|
|
|
print("[{0}] start failed ({1})\n", format{name, strerror(errno)});
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(command == "status") {
|
|
|
|
print("[{0}] stopped\n", format{name});
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto service::receive() -> string {
|
|
|
|
string command;
|
|
|
|
if(shared) {
|
|
|
|
if(auto data = shared.acquire()) {
|
|
|
|
if(*data) {
|
|
|
|
command.resize(4095);
|
2015-08-02 06:23:13 +00:00
|
|
|
memory::copy(command.get(), data, 4095);
|
2015-06-15 22:16:43 +00:00
|
|
|
memory::fill(data, 4096);
|
|
|
|
}
|
|
|
|
shared.release();
|
|
|
|
if(command == "remove") {
|
|
|
|
_stop = true;
|
|
|
|
return "";
|
|
|
|
} else if(command == "start") {
|
|
|
|
return "";
|
|
|
|
} else if(command == "status") {
|
|
|
|
return "";
|
|
|
|
} else if(command == "stop") {
|
|
|
|
_stop = true;
|
|
|
|
shared.remove();
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return command;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto service::name() const -> string {
|
|
|
|
return _name;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto service::stop() const -> bool {
|
|
|
|
return _stop;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|