From bb31907761e2ff25587d8ca49625cab1f4f81b85 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 1 Dec 2014 16:37:12 +0100 Subject: [PATCH] spawn: move argument parser from iptv_pipe --- src/input/mpegts/iptv/iptv_pipe.c | 95 +++++++------------------------ src/spawn.c | 65 +++++++++++++++++++++ src/spawn.h | 4 ++ 3 files changed, 91 insertions(+), 73 deletions(-) diff --git a/src/input/mpegts/iptv/iptv_pipe.c b/src/input/mpegts/iptv/iptv_pipe.c index 15839a0e..65be0ed2 100644 --- a/src/input/mpegts/iptv/iptv_pipe.c +++ b/src/input/mpegts/iptv/iptv_pipe.c @@ -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 diff --git a/src/spawn.c b/src/spawn.c index 7775f2c1..91a09eab 100644 --- a/src/spawn.c +++ b/src/spawn.c @@ -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). diff --git a/src/spawn.h b/src/spawn.h index e6be04af..1554a749 100644 --- a/src/spawn.h +++ b/src/spawn.h @@ -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);