summaryrefslogtreecommitdiffstats
path: root/src/Common/Backends
diff options
context:
space:
mode:
authorMatthias Schiffer <matthias@gamezock.de>2008-10-07 00:25:14 +0200
committerMatthias Schiffer <matthias@gamezock.de>2008-10-07 00:25:14 +0200
commit3bb4da8601bd4d6de56d57507faf7fa115a15037 (patch)
treeabda8e58057911e3da566768c1556a3432527fc5 /src/Common/Backends
parent426d60a6992259ca80431c59e916073cc31f5261 (diff)
downloadmad-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.cpp108
-rw-r--r--src/Common/Backends/SystemBackendPosix.h11
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>());
};
}