Re-instate internal xmltv search routine (will try to use external tv_find_grabbers), remove use of fixed path for find script and make spawn calls search path if required.

This commit is contained in:
Adam Sutton 2012-08-09 15:48:41 +01:00
parent ec3bb46252
commit 71dc6bff73
3 changed files with 111 additions and 27 deletions

View file

@ -38,7 +38,8 @@
#include "epggrab.h"
#include "epggrab/private.h"
#define XMLTV_FIND_GRABBERS "/usr/bin/tv_find_grabbers"
#define XMLTV_FIND "tv_find_grabbers"
#define XMLTV_GRAB "tv_grab_"
static epggrab_channel_tree_t _xmltv_channels;
static epggrab_module_t *_xmltv_module;
@ -527,30 +528,66 @@ static void _xmltv_load_grabbers ( void )
size_t i, outlen, p, n;
char *outbuf;
char name[1000];
char *tmp, *path;
/* Load data */
outlen = spawn_and_store_stdout(XMLTV_FIND_GRABBERS, NULL, &outbuf);
if ( outlen < 1 ) {
tvhlog(LOG_ERR, "xmltv", "%s failed", XMLTV_FIND_GRABBERS);
return;
}
outlen = spawn_and_store_stdout(XMLTV_FIND, NULL, &outbuf);
/* Process */
p = n = i = 0;
while ( i < outlen ) {
if ( outbuf[i] == '\n' || outbuf[i] == '\0' ) {
outbuf[i] = '\0';
sprintf(name, "XMLTV: %s", &outbuf[n]);
epggrab_module_int_create(NULL, &outbuf[p], name, 3, &outbuf[p],
if ( outlen ) {
p = n = i = 0;
while ( i < outlen ) {
if ( outbuf[i] == '\n' || outbuf[i] == '\0' ) {
outbuf[i] = '\0';
sprintf(name, "XMLTV: %s", &outbuf[n]);
epggrab_module_int_create(NULL, &outbuf[p], name, 3, &outbuf[p],
NULL, _xmltv_parse, NULL, NULL);
p = n = i + 1;
} else if ( outbuf[i] == '|' ) {
outbuf[i] = '\0';
n = i + 1;
p = n = i + 1;
} else if ( outbuf[i] == '|' ) {
outbuf[i] = '\0';
n = i + 1;
}
i++;
}
i++;
free(outbuf);
/* Internal search */
} else if ((tmp = getenv("PATH"))) {
tvhlog(LOG_DEBUG, "epggrab", "using internal grab search");
char bin[256];
char desc[] = "--description";
char *argv[] = {
NULL,
desc,
NULL
};
path = strdup(tmp);
tmp = strtok(path, ":");
while (tmp) {
DIR *dir;
struct dirent *de;
struct stat st;
if ((dir = opendir(tmp))) {
while ((de = readdir(dir))) {
if (strstr(de->d_name, XMLTV_GRAB) != de->d_name) continue;
snprintf(bin, sizeof(bin), "%s/%s", tmp, de->d_name);
if (lstat(bin, &st)) continue;
if (!(st.st_mode & S_IEXEC)) continue;
if (!S_ISREG(st.st_mode)) continue;
if ((outlen = spawn_and_store_stdout(bin, argv, &outbuf))) {
if (outbuf[outlen-1] == '\n') outbuf[outlen-1] = '\0';
snprintf(name, sizeof(name), "XMLTV: %s", outbuf);
epggrab_module_int_create(NULL, bin, name, 3, bin,
NULL, _xmltv_parse, NULL, NULL);
free(outbuf);
}
}
}
closedir(dir);
tmp = strtok(NULL, ":");
}
free(path);
}
free(outbuf);
}
void xmltv_init ( void )

View file

@ -18,6 +18,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -26,6 +27,7 @@
#include <assert.h>
#include <syslog.h>
#include <fcntl.h>
#include <dirent.h>
#include "tvheadend.h"
#include "file.h"
@ -43,6 +45,38 @@ typedef struct spawn {
const char *name;
} spawn_t;
/*
* Search PATH for executable
*/
static int
_find_exec ( const char *name, char *out, size_t len )
{
int ret = 0;
char bin[512];
char *path, *tmp;
DIR *dir;
struct dirent *de;
struct stat st;
if (!(path = getenv("PATH"))) return 0;
path = strdup(path);
tmp = strtok(path, ":");
while (tmp && !ret) {
if (!(dir = opendir(tmp))) continue;
while ((de = readdir(dir))) {
if (strstr(de->d_name, name) != de->d_name) continue;
snprintf(bin, sizeof(bin), "%s/%s", tmp, de->d_name);
if (lstat(bin, &st)) continue;
if (!S_ISREG(st.st_mode) || !(st.st_mode & S_IEXEC)) continue;
strncpy(out, bin, len);
ret = 1;
break;
}
closedir(dir);
tmp = strtok(NULL, ":");
}
free(path);
return ret;
}
/**
* The reaper is called once a second to finish of any pending spawns
@ -118,18 +152,21 @@ spawn_enq(const char *name, int pid)
*/
int
spawn_and_store_stdout(const char *prog, char *const argv[], char **outp)
spawn_and_store_stdout(const char *prog, char *argv[], char **outp)
{
pid_t p;
int fd[2], f;
const char *local_argv[2];
char bin[256];
const char *local_argv[2] = { NULL, NULL };
if(argv == NULL) {
local_argv[0] = prog;
local_argv[1] = NULL;
argv = (void *)local_argv;
if (*prog != '/' && *prog != '.') {
if (!_find_exec(prog, bin, sizeof(bin))) return -1;
prog = bin;
}
if(!argv) argv = (void *)local_argv;
if (!argv[0]) argv[0] = (char*)prog;
pthread_mutex_lock(&fork_lock);
if(pipe(fd) == -1) {
@ -188,9 +225,19 @@ spawn_and_store_stdout(const char *prog, char *const argv[], char **outp)
* The function will return the size of the buffer
*/
int
spawnv(const char *prog, char *const argv[])
spawnv(const char *prog, char *argv[])
{
pid_t p;
char bin[256];
const char *local_argv[2] = { NULL, NULL };
if (*prog != '/' && *prog != '.') {
if (!_find_exec(prog, bin, sizeof(bin))) return -1;
prog = bin;
}
if(!argv) argv = (void *)local_argv;
if (!argv[0]) argv[0] = (char*)prog;
p = fork();

View file

@ -19,9 +19,9 @@
#ifndef SPAWN_H
#define SPAWN_H
int spawn_and_store_stdout(const char *prog, char *const argv[], char **outp);
int spawn_and_store_stdout(const char *prog, char *argv[], char **outp);
int spawnv(const char *prog, char *const argv[]);
int spawnv(const char *prog, char *argv[]);
void spawn_reaper(void);