summaryrefslogtreecommitdiff
path: root/extpipe.cpp
diff options
context:
space:
mode:
authorJochen Dolze <vdr@dolze.de>2010-12-29 16:54:30 +0100
committerJochen Dolze <vdr@dolze.de>2010-12-29 16:54:30 +0100
commit83cf2436ce3f2ed9ce4e0a0847b10d5144907061 (patch)
tree5cde43e0da488ac42c1b4c757a8054cfe410d588 /extpipe.cpp
downloadvdr-plugin-xmltv2vdr-83cf2436ce3f2ed9ce4e0a0847b10d5144907061.tar.gz
vdr-plugin-xmltv2vdr-83cf2436ce3f2ed9ce4e0a0847b10d5144907061.tar.bz2
First commit
Diffstat (limited to 'extpipe.cpp')
-rw-r--r--extpipe.cpp131
1 files changed, 131 insertions, 0 deletions
diff --git a/extpipe.cpp b/extpipe.cpp
new file mode 100644
index 0000000..c596226
--- /dev/null
+++ b/extpipe.cpp
@@ -0,0 +1,131 @@
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <vdr/tools.h>
+#include <vdr/thread.h>
+#include "extpipe.h"
+
+
+
+cExtPipe::cExtPipe(void)
+{
+ pid = -1;
+ f = NULL;
+}
+
+cExtPipe::~cExtPipe()
+{
+ int status;
+ Close(status);
+}
+
+bool cExtPipe::Open(const char *Command, const char *Mode)
+{
+ int fd[2];
+
+ if (pipe(fd) < 0)
+ {
+ LOG_ERROR;
+ return false;
+ }
+ if ((pid = fork()) < 0) // fork failed
+ {
+ LOG_ERROR;
+ close(fd[0]);
+ close(fd[1]);
+ return false;
+ }
+
+ const char *mode = "w";
+ int iopipe = 0;
+
+ if (pid > 0) // parent process
+ {
+ if (strcmp(Mode, "r") == 0)
+ {
+ mode = "r";
+ iopipe = 1;
+ }
+ close(fd[iopipe]);
+ if ((f = fdopen(fd[1 - iopipe], mode)) == NULL)
+ {
+ LOG_ERROR;
+ close(fd[1 - iopipe]);
+ }
+ return f != NULL;
+ }
+ else // child process
+ {
+ int iofd = STDOUT_FILENO;
+ if (strcmp(Mode, "w") == 0)
+ {
+ mode = "r";
+ iopipe = 1;
+ iofd = STDIN_FILENO;
+ }
+ close(fd[iopipe]);
+ if (dup2(fd[1 - iopipe], iofd) == -1) // now redirect
+ {
+ LOG_ERROR;
+ close(fd[1 - iopipe]);
+ _exit(-1);
+ }
+ else
+ {
+ int MaxPossibleFileDescriptors = getdtablesize();
+ for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++)
+ close(i); //close all dup'ed filedescriptors
+ if (execl("/bin/sh", "sh", "-c", Command, NULL) == -1)
+ {
+ LOG_ERROR_STR(Command);
+ close(fd[1 - iopipe]);
+ _exit(-1);
+ }
+ }
+ _exit(0);
+ }
+}
+
+int cExtPipe::Close(int &status)
+{
+ int ret = -1;
+
+ if (f)
+ {
+ fclose(f);
+ f = NULL;
+ }
+
+ if (pid > 0)
+ {
+ int i = 5;
+ while (i > 0)
+ {
+ ret = waitpid(pid, &status, WNOHANG);
+ if (ret < 0)
+ {
+ if (errno != EINTR && errno != ECHILD)
+ {
+ LOG_ERROR;
+ break;
+ }
+ }
+ else if (ret == pid)
+ break;
+ i--;
+ cCondWait::SleepMs(100);
+ }
+ if (!i)
+ {
+ kill(pid, SIGKILL);
+ ret = -1;
+ }
+ else if (ret == -1 || !WIFEXITED(status))
+ ret = -1;
+ pid = -1;
+ }
+
+ return ret;
+}