diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Common/Backends/SystemBackendPosix.cpp | 108 | ||||
-rw-r--r-- | src/Common/Backends/SystemBackendPosix.h | 11 | ||||
-rw-r--r-- | src/Common/ConfigManager.cpp | 2 | ||||
-rw-r--r-- | src/Common/SystemBackend.cpp | 9 | ||||
-rw-r--r-- | src/Common/SystemBackend.h | 18 |
5 files changed, 137 insertions, 11 deletions
diff --git a/src/Common/Backends/SystemBackendPosix.cpp b/src/Common/Backends/SystemBackendPosix.cpp index 3ddf67d..ca8b440 100644 --- a/src/Common/Backends/SystemBackendPosix.cpp +++ b/src/Common/Backends/SystemBackendPosix.cpp @@ -21,16 +21,23 @@ #include <cstdlib> #include <cstring> + +#include <fcntl.h> #include <signal.h> #include <spawn.h> #include <sys/wait.h> +#include <unistd.h> + +#include <sigc++/bind.h> namespace Mad { namespace Common { namespace Backends { SystemBackendPosix SystemBackendPosix::backend; + std::map<pid_t, sigc::slot<void, int> > SystemBackendPosix::processes; +std::map<pid_t, std::pair<sigc::slot<void, int, const std::string&>, int> > SystemBackendPosix::processesWithOutput; void SystemBackendPosix::setChildHandler() { @@ -53,6 +60,24 @@ SystemBackendPosix::~SystemBackendPosix() { sigaction(SIGCHLD, &action, 0); } + +void SystemBackendPosix::fsInfoCallback(int, const std::string &output, const sigc::slot<void, const std::vector<FSInfo>& > &callback) { + // TODO Process df output + + callback(std::vector<FSInfo>()); +} + +bool SystemBackendPosix::fsInfo(const sigc::slot<void, const std::vector<FSInfo>& > &callback) { + std::vector<std::string> argv; + + argv.push_back("/bin/df"); + argv.push_back("-P"); + argv.push_back("-k"); + + return execWithOutput(sigc::bind(sigc::mem_fun(this, &SystemBackendPosix::fsInfoCallback), callback), "/bin/df", argv); +} + + void SystemBackendPosix::childHandler(int) { int status; pid_t pid; @@ -64,13 +89,29 @@ void SystemBackendPosix::childHandler(int) { it->second(status); processes.erase(it); } + else { + std::map<pid_t, std::pair<sigc::slot<void, int, const std::string&>, int> >::iterator it2 = processesWithOutput.find(pid); + + if(it2 != processesWithOutput.end()) { + char buffer[1024]; + ssize_t n; + std::string output; + + while((n = read(it2->second.second, buffer, sizeof(buffer))) > 0) + output += std::string(buffer, n); + + close(it2->second.second); + + it2->second.first(status, output); + processesWithOutput.erase(it2); + } + } } setChildHandler(); } -bool SystemBackendPosix::exec(const sigc::slot<void, int>& resultHandler, const std::string &filename, const std::vector<std::string> &argv, const std::vector<std::string> &env) { - pid_t pid; +std::pair<char**, char**> SystemBackendPosix::makeArgs(const std::string &filename, const std::vector<std::string> &argv, const std::vector<std::string> &env) { char **argvp, **envp; if(argv.empty()) { @@ -102,29 +143,74 @@ bool SystemBackendPosix::exec(const sigc::slot<void, int>& resultHandler, const envp[env.size()] = 0; } + return std::make_pair(argvp, envp); +} + +void SystemBackendPosix::destroyArgs(std::pair<char**, char**> args) { + for(char **p = args.first; *p != 0; ++p) + std::free(*p); + + delete [] args.first; + + if(args.second != environ) { + for(char **p = args.second; *p != 0; ++p) + std::free(*p); + + delete [] args.second; + } +} + +bool SystemBackendPosix::exec(const sigc::slot<void, int> &resultHandler, const std::string &filename, const std::vector<std::string> &argv, const std::vector<std::string> &env) { + pid_t pid; + std::pair<char**, char**> args = makeArgs(filename, argv, env); + sigset_t set, oldset; sigemptyset(&set); sigaddset(&set, SIGCHLD); sigprocmask(SIG_BLOCK, &set, &oldset); - bool ret = (posix_spawnp(&pid, filename.c_str(), 0, 0, argvp, envp) == 0); + bool ret = (posix_spawnp(&pid, filename.c_str(), 0, 0, args.first, args.second) == 0); if(ret) processes.insert(std::make_pair(pid, resultHandler)); sigprocmask(SIG_SETMASK, &oldset, 0); - for(char **p = argvp; *p != 0; ++p) - std::free(*p); + destroyArgs(args); - delete [] argvp; + return ret; +} - if(envp != environ) { - for(char **p = envp; *p != 0; ++p) - std::free(*p); +bool SystemBackendPosix::execWithOutput(const sigc::slot<void, int, const std::string&> &resultHandler, const std::string &filename, const std::vector<std::string> &argv, const std::vector<std::string> &env) { + pid_t pid; + std::pair<char**, char**> args = makeArgs(filename, argv, env); - delete [] envp; - } + int saveStdout = dup(STDOUT_FILENO); + int pipeHandles[2]; + + pipe(pipeHandles); // TODO Better pipe handling + + fcntl(pipeHandles[0], F_SETFD, FD_CLOEXEC); + + sigset_t set, oldset; + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigprocmask(SIG_BLOCK, &set, &oldset); + + dup2(pipeHandles[1], STDOUT_FILENO); // set the new pipe as stdout + close(pipeHandles[1]); + + bool ret = (posix_spawnp(&pid, filename.c_str(), 0, 0, args.first, args.second) == 0); + + if(ret) + processesWithOutput.insert(std::make_pair(pid, std::make_pair(resultHandler, pipeHandles[0]))); + + dup2(saveStdout, STDOUT_FILENO); // restore old stdout + close(saveStdout); + + sigprocmask(SIG_SETMASK, &oldset, 0); + + destroyArgs(args); return ret; } diff --git a/src/Common/Backends/SystemBackendPosix.h b/src/Common/Backends/SystemBackendPosix.h index 4a2c572..b7f364a 100644 --- a/src/Common/Backends/SystemBackendPosix.h +++ b/src/Common/Backends/SystemBackendPosix.h @@ -38,16 +38,24 @@ class SystemBackendPosix : public SystemBackend { private: static SystemBackendPosix backend; static std::map<pid_t, sigc::slot<void, int> > processes; + static std::map<pid_t, std::pair<sigc::slot<void, int, const std::string&>, int> > processesWithOutput; static void setChildHandler(); static void childHandler(int); + static std::pair<char**, char**> makeArgs(const std::string &filename, const std::vector<std::string> &argv, const std::vector<std::string> &env); + static void destroyArgs(std::pair<char**, char**> args); + SystemBackendPosix() { setChildHandler(); } + void fsInfoCallback(int, const std::string &output, const sigc::slot<void, const std::vector<FSInfo>& > &callback); + protected: + virtual bool fsInfo(const sigc::slot<void, const std::vector<FSInfo>& > &callback); + virtual bool doShutdown(const sigc::slot<void> &callback) {return exec(sigc::hide(callback), "/sbin/halt");} virtual bool doReboot(const sigc::slot<void> &callback) {return exec(sigc::hide(callback), "/sbin/reboot");} @@ -64,6 +72,9 @@ class SystemBackendPosix : public SystemBackend { static bool exec(const sigc::slot<void, int> &resultHandler, const std::string &filename, const std::vector<std::string> &argv = std::vector<std::string>(), const std::vector<std::string> &env = std::vector<std::string>()); + + static bool execWithOutput(const sigc::slot<void, int, const std::string&> &resultHandler, const std::string &filename, const std::vector<std::string> &argv = std::vector<std::string>(), + const std::vector<std::string> &env = std::vector<std::string>()); }; } diff --git a/src/Common/ConfigManager.cpp b/src/Common/ConfigManager.cpp index c8aea47..6afeeef 100644 --- a/src/Common/ConfigManager.cpp +++ b/src/Common/ConfigManager.cpp @@ -20,6 +20,7 @@ #include "ConfigManager.h" #include "Util.h" #include "Backends/SystemBackendProc.h" +#include "Backends/SystemBackendPosix.h" #include <fstream> #include <stdexcept> @@ -97,6 +98,7 @@ bool ConfigManager::loadFile(const std::string &filename) { void ConfigManager::initBackends() { Backends::SystemBackendProc::registerBackend(); + Backends::SystemBackendPosix::registerBackend(); } } diff --git a/src/Common/SystemBackend.cpp b/src/Common/SystemBackend.cpp index 06a2898..2370b89 100644 --- a/src/Common/SystemBackend.cpp +++ b/src/Common/SystemBackend.cpp @@ -52,6 +52,15 @@ bool SystemBackend::getLoadInfo(const sigc::slot<void, unsigned long, unsigned l return false; } +bool SystemBackend::getFSInfo(const sigc::slot<void, const std::vector<FSInfo>& > &callback) { + for(std::set<SystemBackend*>::iterator backend = backends.begin(); backend != backends.end(); ++backend) { + if((*backend)->fsInfo(callback)) + return true; + } + + return false; +} + bool SystemBackend::shutdown(const sigc::slot<void> &callback) { for(std::set<SystemBackend*>::iterator backend = backends.begin(); backend != backends.end(); ++backend) { if((*backend)->doShutdown(callback)) diff --git a/src/Common/SystemBackend.h b/src/Common/SystemBackend.h index c8eee69..944f195 100644 --- a/src/Common/SystemBackend.h +++ b/src/Common/SystemBackend.h @@ -21,6 +21,9 @@ #define MAD_COMMON_SYSTEMBACKEND_H_ #include <set> +#include <string> +#include <vector> + #include <sigc++/signal.h> namespace Mad { @@ -39,6 +42,15 @@ class SystemBackend { static std::set<SystemBackend*, Compare> backends; + public: + struct FSInfo { + std::string fsName; + std::string mountedOn; + long long total; + long long used; + long long available; + }; + protected: SystemBackend() {} @@ -62,6 +74,10 @@ class SystemBackend { return false; } + virtual bool fsInfo(const sigc::slot<void, const std::vector<FSInfo>& >&) { + return false; + } + virtual bool doShutdown(const sigc::slot<void>&) {return false;} virtual bool doReboot(const sigc::slot<void>&) {return false;} @@ -76,6 +92,8 @@ class SystemBackend { static bool getMemoryInfo(const sigc::slot<void, unsigned long, unsigned long, unsigned long, unsigned long> &callback); static bool getLoadInfo(const sigc::slot<void, unsigned long, unsigned long, float, float, float> &callback); + static bool getFSInfo(const sigc::slot<void, const std::vector<FSInfo>& > &callback); + static bool shutdown(const sigc::slot<void> &callback); static bool reboot(const sigc::slot<void> &callback); }; |