]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
spawn: move argument parser from iptv_pipe
authorJaroslav Kysela <perex@perex.cz>
Mon, 1 Dec 2014 15:37:12 +0000 (16:37 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 1 Dec 2014 16:03:28 +0000 (17:03 +0100)
src/input/mpegts/iptv/iptv_pipe.c
src/spawn.c
src/spawn.h

index 15839a0e6f9e0147d7435ce0388890fda740bae9..65be0ed2104cb61ec28504c5a150eac019fe8f15 100644 (file)
  * 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
index 7775f2c152631ae4a7e612de7125b4c40d0355bc..91a09eab8f741cfdb0544a4616d9e5be507283a1 100644 (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).
index e6be04afa30500a15b38e472d5cd8400a84f2319..1554a74943212d521c923fd9b8a24289c0fcd392 100644 (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);