summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Common/Backends/SystemBackendPosix.cpp108
-rw-r--r--src/Common/Backends/SystemBackendPosix.h11
-rw-r--r--src/Common/ConfigManager.cpp2
-rw-r--r--src/Common/SystemBackend.cpp9
-rw-r--r--src/Common/SystemBackend.h18
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);
};