diff --git a/HISTORY b/HISTORY index 4aefe90..b339021 100644 --- a/HISTORY +++ b/HISTORY @@ -177,3 +177,7 @@ VDR Plugin 'iptv' Revision History - Optimized reading from UDP sockets. - Fixed ProvidesChannel method. + +2012-07-10: Version 1.0.1 + +- Added FreeBSD support (Thanks to Jürgen Lock). diff --git a/Makefile b/Makefile index d41acd1..c7b78bf 100644 --- a/Makefile +++ b/Makefile @@ -5,9 +5,15 @@ # Debugging on/off #IPTV_DEBUG = 1 +# Default shell for EXT protocol +#IPTV_EXTSHELL = /bin/bash + # Strip debug symbols? Set eg. to /bin/true if not STRIP = strip +# Install command +INSTALL = cp --remove-destination + # The official name of this plugin. # This name will be used in the '-P...' option of VDR to load the plugin. # By default the main source file also carries this name. @@ -60,6 +66,10 @@ ifdef IPTV_DEBUG DEFINES += -DDEBUG endif +ifdef IPTV_EXTSHELL +DEFINES += -DEXTSHELL='"$(IPTV_EXTSHELL)"' +endif + ifneq ($(strip $(GITTAG)),) DEFINES += -DGITVERSION='"-GIT-$(GITTAG)"' endif @@ -123,7 +133,7 @@ libvdr-$(PLUGIN).so: $(OBJS) ifndef IPTV_DEBUG @$(STRIP) $@ endif - @cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION) + @$(INSTALL) $@ $(LIBDIR)/$@.$(APIVERSION) dist: $(I18Npo) clean @-rm -rf $(TMPDIR)/$(ARCHIVE) diff --git a/common.h b/common.h index c3728f9..7586358 100644 --- a/common.h +++ b/common.h @@ -39,13 +39,14 @@ #define SECTION_FILTER_TABLE_SIZE 7 #define ERROR_IF_FUNC(exp, errstr, func, ret) \ - do { \ - if (exp) { \ - char tmp[64]; \ - error(errstr": %s", strerror_r(errno, tmp, sizeof(tmp))); \ - func; \ - ret; \ - } \ + do { \ + if (exp) { \ + char tmp[64]; \ + strerror_r(errno, tmp, sizeof(tmp)); \ + error(errstr": %s", tmp); \ + func; \ + ret; \ + } \ } while (0) diff --git a/iptv.c b/iptv.c index aa95b1c..ed12f10 100644 --- a/iptv.c +++ b/iptv.c @@ -21,7 +21,7 @@ #define GITVERSION "" #endif - const char VERSION[] = "1.0.0" GITVERSION; + const char VERSION[] = "1.0.1" GITVERSION; static const char DESCRIPTION[] = trNOOP("Experience the IPTV"); class cPluginIptv : public cPlugin { diff --git a/protocolext.c b/protocolext.c index a5a3086..ee54d30 100644 --- a/protocolext.c +++ b/protocolext.c @@ -19,6 +19,10 @@ #include "config.h" #include "protocolext.h" +#ifndef EXTSHELL +#define EXTSHELL "/bin/bash" +#endif + cIptvProtocolExt::cIptvProtocolExt() : pid(-1), scriptFile(""), @@ -56,7 +60,9 @@ void cIptvProtocolExt::ExecuteScript(void) // Execute the external script cString cmd = cString::sprintf("%s %d %d", *scriptFile, scriptParameter, streamPort); debug("cIptvProtocolExt::ExecuteScript(child): %s\n", *cmd); - if (execl("/bin/bash", "sh", "-c", *cmd, (char *)NULL) == -1) { + // Create a new session for a process group + ERROR_IF_RET(setsid() == -1, "setsid()", _exit(-1)); + if (execl(EXTSHELL, "sh", "-c", *cmd, (char *)NULL) == -1) { error("Script execution failed: %s", *cmd); _exit(-1); } @@ -75,27 +81,36 @@ void cIptvProtocolExt::TerminateScript(void) if (pid > 0) { const unsigned int timeoutms = 100; unsigned int waitms = 0; - siginfo_t waitStatus; bool waitOver = false; - // signal and wait for termination - int retval = kill(pid, SIGINT); + // Signal and wait for termination + int retval = killpg(pid, SIGINT); ERROR_IF_RET(retval < 0, "kill()", waitOver = true); while (!waitOver) { retval = 0; waitms += timeoutms; if ((waitms % 2000) == 0) { error("Script '%s' won't terminate - killing it!", *scriptFile); - kill(pid, SIGKILL); + killpg(pid, SIGKILL); } // Clear wait status to make sure child exit status is accessible + // and wait for child termination +#ifdef __FreeBSD__ + int waitStatus = 0; + retval = waitpid(pid, &waitStatus, WNOHANG); +#else // __FreeBSD__ + siginfo_t waitStatus; memset(&waitStatus, '\0', sizeof(waitStatus)); - // Wait for child termination retval = waitid(P_PID, pid, &waitStatus, (WNOHANG | WEXITED)); +#endif // __FreeBSD__ ERROR_IF_RET(retval < 0, "waitid()", waitOver = true); // These are the acceptable conditions under which child exit is // regarded as successful +#ifdef __FreeBSD__ + if (retval > 0 && (WIFEXITED(waitStatus) || WIFSIGNALED(waitStatus))) { +#else // __FreeBSD__ if (!retval && waitStatus.si_pid && (waitStatus.si_pid == pid) && ((waitStatus.si_code == CLD_EXITED) || (waitStatus.si_code == CLD_KILLED))) { +#endif // __FreeBSD__ debug("Child (%d) exited as expected\n", pid); waitOver = true; } diff --git a/sectionfilter.h b/sectionfilter.h index 7176180..28247aa 100644 --- a/sectionfilter.h +++ b/sectionfilter.h @@ -8,6 +8,9 @@ #ifndef __IPTV_SECTIONFILTER_H #define __IPTV_SECTIONFILTER_H +#ifdef __FreeBSD__ +#include +#endif // __FreeBSD__ #include #include "common.h" diff --git a/socket.c b/socket.c index 6e33ff6..cd5f697 100644 --- a/socket.c +++ b/socket.c @@ -57,9 +57,11 @@ bool cIptvSocket::OpenSocket(const int Port, const bool isUdp) // Allow multiple sockets to use the same PORT number ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0, "setsockopt(SO_REUSEADDR)", CloseSocket(), return false); +#ifndef __FreeBSD__ // Allow packet information to be fetched ERROR_IF_FUNC(setsockopt(socketDesc, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0, "setsockopt(IP_PKTINFO)", CloseSocket(), return false); +#endif // __FreeBSD__ // Bind socket memset(&sockAddr, '\0', sizeof(sockAddr)); sockAddr.sin_family = AF_INET; @@ -180,11 +182,13 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen) else break; if (len > 0) { +#ifndef __FreeBSD__ // Process auxiliary received data and validate source address for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) { if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) { struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg); if ((i->ipi_addr.s_addr == streamAddr) || (INADDR_ANY == streamAddr)) { +#endif // __FreeBSD__ if (BufferAddr[0] == TS_SYNC_BYTE) return len; else if (len > 3) { @@ -215,9 +219,11 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen) return (len - headerlen); } } +#ifndef __FreeBSD__ } } } +#endif // __FreeBSD__ } } while (len > 0); ERROR_IF_RET(len < 0 && errno != EAGAIN, "recvmsg()", return -1); diff --git a/socket.h b/socket.h index b912a27..7cec2cf 100644 --- a/socket.h +++ b/socket.h @@ -9,6 +9,9 @@ #define __IPTV_SOCKET_H #include +#ifdef __FreeBSD__ +#include +#endif // __FreeBSD__ class cIptvSocket { private: