diff options
author | Matthias Schiffer <matthias@gamezock.de> | 2008-10-07 00:25:14 +0200 |
---|---|---|
committer | Matthias Schiffer <matthias@gamezock.de> | 2008-10-07 00:25:14 +0200 |
commit | 3bb4da8601bd4d6de56d57507faf7fa115a15037 (patch) | |
tree | abda8e58057911e3da566768c1556a3432527fc5 /src/Common/Backends | |
parent | 426d60a6992259ca80431c59e916073cc31f5261 (diff) | |
download | mad-3bb4da8601bd4d6de56d57507faf7fa115a15037.tar mad-3bb4da8601bd4d6de56d57507faf7fa115a15037.zip |
execWithOutput zum Posix-Backend hinzugef?gt; FS-Info angefangen
Diffstat (limited to 'src/Common/Backends')
-rw-r--r-- | src/Common/Backends/SystemBackendPosix.cpp | 108 | ||||
-rw-r--r-- | src/Common/Backends/SystemBackendPosix.h | 11 |
2 files changed, 108 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>()); }; } |