spawn: move argument parser from iptv_pipe

This commit is contained in:
Jaroslav Kysela 2014-12-01 16:37:12 +01:00
parent bd20a5393c
commit bb31907761
3 changed files with 91 additions and 73 deletions

View file

@ -32,88 +32,30 @@
* Connect UDP/RTP
*/
static int
iptv_pipe_start ( iptv_mux_t *im, const char *_raw, const url_t *url )
iptv_pipe_start ( iptv_mux_t *im, const char *raw, const url_t *url )
{
char *argv[64], *envp[32], *f, *raw, *s, *p, *a;
int i = 1, rd;
char **argv = NULL, **envp = NULL;
const char *replace[] = { "${service_name}", im->mm_iptv_svcname ?: "", NULL };
int rd;
pid_t pid;
if (strncmp(_raw, "pipe://", 7))
return -1;
if (strncmp(raw, "pipe://", 7))
goto err;
s = raw = tvh_strdupa(_raw + 7);
if (spawn_parse_args(&argv, 64, raw + 7, replace))
goto err;
argv[0] = NULL;
if (spawn_parse_args(&envp, 64, im->mm_iptv_env ?: "", NULL))
goto err;
while (*s && *s != ' ')
s++;
if (*s == ' ') {
*(char *)s = '\0';
s++;
}
while (*s && i < ARRAY_SIZE(argv) - 1) {
f = s;
while (*s && *s != ' ') {
while (*s && *s != ' ' && *s != '\\')
s++;
if (*s == '\\') {
memmove(s, s + 1, strlen(s));
if (*s)
s++;
}
}
if (f != s) {
if (*s) {
*(char *)s = '\0';
s++;
}
p = strstr(f, "${service_name}");
if (p) {
a = alloca(strlen(f) + strlen(im->mm_iptv_svcname ?: ""));
*p = '\0';
strcpy(a, f);
strcat(a, im->mm_iptv_svcname ?: "");
strcat(a, p + 15);
f = a;
}
argv[i++] = f;
}
}
argv[i] = NULL;
s = im->mm_iptv_env ? tvh_strdupa(im->mm_iptv_env) : (char *)"";
i = 0;
while (*s && i < ARRAY_SIZE(envp) - 1) {
f = s;
while (*s && *s != '=')
s++;
if (*s != '=')
break;
while (*s && *s != ' ') {
while (*s && *s != ' ' && *s != '\\')
s++;
if (*s == '\\') {
memmove(s, s + 1, strlen(s));
if (*s)
s++;
}
}
if (f != s) {
if (*s) {
*s = '\0';
s++;
}
envp[i++] = f;
}
}
envp[i] = NULL;
if (spawn_and_give_stdout(raw, argv, envp, &rd, &pid, 1)) {
if (spawn_and_give_stdout(argv[0], argv, envp, &rd, &pid, 1)) {
tvherror("iptv", "Unable to start pipe '%s' (wrong executable?)", raw);
return -1;
goto err;
}
spawn_free_args(argv);
spawn_free_args(envp);
fcntl(rd, F_SETFD, fcntl(rd, F_GETFD) | FD_CLOEXEC);
fcntl(rd, F_SETFL, fcntl(rd, F_GETFL) | O_NONBLOCK);
@ -125,6 +67,13 @@ iptv_pipe_start ( iptv_mux_t *im, const char *_raw, const url_t *url )
if (url)
iptv_input_mux_started(im);
return 0;
err:
if (argv)
spawn_free_args(argv);
if (envp)
spawn_free_args(envp);
return -1;
}
static void

View file

@ -324,6 +324,71 @@ spawn_enq(const char *name, int pid)
}
/**
*
*/
int
spawn_parse_args(char ***argv, int argc, const char *cmd, const char **replace)
{
char *s, *f, *p, *a;
const char **r;
int i = 0, l;
if (!argv || !cmd)
return -1;
s = tvh_strdupa(cmd);
*argv = calloc(argc, sizeof(char *));
while (*s && i < argc - 1) {
f = s;
while (*s && *s != ' ') {
while (*s && *s != ' ' && *s != '\\')
s++;
if (*s == '\\') {
memmove(s, s + 1, strlen(s));
if (*s)
s++;
}
}
if (f != s) {
if (*s) {
*(char *)s = '\0';
s++;
}
for (r = replace; r && *r; r += 2) {
p = strstr(f, *r);
if (p) {
l = strlen(*r);
a = malloc(strlen(f) + strlen(r[1]) + 1);
*p = '\0';
strcpy(a, f);
strcat(a, r[1]);
strcat(a, p + l);
*argv[i++] = f;
break;
}
}
if (r && *r)
continue;
(*argv)[i++] = strdup(f);
}
}
(*argv)[i] = NULL;
return 0;
}
/**
*
*/
void
spawn_free_args(char **argv)
{
char **a = argv;
for (; *a; a++)
free(*a);
free(argv);
}
/**
* Execute the given program and return its standard output as file-descriptor (pipe).

View file

@ -25,6 +25,10 @@ void spawn_error ( const char *fmt, ... );
int find_exec ( const char *name, char *out, size_t len );
int spawn_parse_args(char ***argv, int argc, const char *cmd, const char **replace);
void spawn_free_args(char **argv);
int spawn_and_give_stdout(const char *prog, char *argv[], char *envp[],
int *rd, pid_t *pid, int redir_stderr);