From 3bb4da8601bd4d6de56d57507faf7fa115a15037 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 7 Oct 2008 00:25:14 +0200 Subject: execWithOutput zum Posix-Backend hinzugef?gt; FS-Info angefangen --- src/Common/Backends/SystemBackendPosix.cpp | 108 ++++++++++++++++++++++++++--- src/Common/Backends/SystemBackendPosix.h | 11 +++ src/Common/ConfigManager.cpp | 2 + src/Common/SystemBackend.cpp | 9 +++ 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 #include + +#include #include #include #include +#include + +#include namespace Mad { namespace Common { namespace Backends { SystemBackendPosix SystemBackendPosix::backend; + std::map > SystemBackendPosix::processes; +std::map, 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& > &callback) { + // TODO Process df output + + callback(std::vector()); +} + +bool SystemBackendPosix::fsInfo(const sigc::slot& > &callback) { + std::vector 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, 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& resultHandler, const std::string &filename, const std::vector &argv, const std::vector &env) { - pid_t pid; +std::pair SystemBackendPosix::makeArgs(const std::string &filename, const std::vector &argv, const std::vector &env) { char **argvp, **envp; if(argv.empty()) { @@ -102,29 +143,74 @@ bool SystemBackendPosix::exec(const sigc::slot& resultHandler, const envp[env.size()] = 0; } + return std::make_pair(argvp, envp); +} + +void SystemBackendPosix::destroyArgs(std::pair 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 &resultHandler, const std::string &filename, const std::vector &argv, const std::vector &env) { + pid_t pid; + std::pair 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 &resultHandler, const std::string &filename, const std::vector &argv, const std::vector &env) { + pid_t pid; + std::pair 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 > processes; + static std::map, int> > processesWithOutput; static void setChildHandler(); static void childHandler(int); + static std::pair makeArgs(const std::string &filename, const std::vector &argv, const std::vector &env); + static void destroyArgs(std::pair args); + SystemBackendPosix() { setChildHandler(); } + void fsInfoCallback(int, const std::string &output, const sigc::slot& > &callback); + protected: + virtual bool fsInfo(const sigc::slot& > &callback); + virtual bool doShutdown(const sigc::slot &callback) {return exec(sigc::hide(callback), "/sbin/halt");} virtual bool doReboot(const sigc::slot &callback) {return exec(sigc::hide(callback), "/sbin/reboot");} @@ -64,6 +72,9 @@ class SystemBackendPosix : public SystemBackend { static bool exec(const sigc::slot &resultHandler, const std::string &filename, const std::vector &argv = std::vector(), const std::vector &env = std::vector()); + + static bool execWithOutput(const sigc::slot &resultHandler, const std::string &filename, const std::vector &argv = std::vector(), + const std::vector &env = std::vector()); }; } 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 #include @@ -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& > &callback) { + for(std::set::iterator backend = backends.begin(); backend != backends.end(); ++backend) { + if((*backend)->fsInfo(callback)) + return true; + } + + return false; +} + bool SystemBackend::shutdown(const sigc::slot &callback) { for(std::set::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 +#include +#include + #include namespace Mad { @@ -39,6 +42,15 @@ class SystemBackend { static std::set 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& >&) { + return false; + } + virtual bool doShutdown(const sigc::slot&) {return false;} virtual bool doReboot(const sigc::slot&) {return false;} @@ -76,6 +92,8 @@ class SystemBackend { static bool getMemoryInfo(const sigc::slot &callback); static bool getLoadInfo(const sigc::slot &callback); + static bool getFSInfo(const sigc::slot& > &callback); + static bool shutdown(const sigc::slot &callback); static bool reboot(const sigc::slot &callback); }; -- cgit v1.2.3