mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
conf: fix context.exec args parsing
The 'args' can be either JSON array, or a string. If a string it should not be parsed as JSON for a second time, but instead split at whitespaces.
This commit is contained in:
parent
51b3778f7c
commit
b80d115140
1 changed files with 62 additions and 23 deletions
|
|
@ -945,9 +945,10 @@ static char **pw_strv_insert_at(char **strv, int len, int pos, const char *str)
|
||||||
|
|
||||||
n = realloc(strv, sizeof(char*) * (len + 2));
|
n = realloc(strv, sizeof(char*) * (len + 2));
|
||||||
if (n == NULL) {
|
if (n == NULL) {
|
||||||
free(strv);
|
pw_free_strv(strv);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
strv = n;
|
strv = n;
|
||||||
|
|
||||||
memmove(strv+pos+1, strv+pos, sizeof(char*) * (len+1-pos));
|
memmove(strv+pos+1, strv+pos, sizeof(char*) * (len+1-pos));
|
||||||
|
|
@ -955,15 +956,16 @@ static char **pw_strv_insert_at(char **strv, int len, int pos, const char *str)
|
||||||
return strv;
|
return strv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_exec(struct pw_context *context, const char *path, const char *args)
|
static int do_exec(struct pw_context *context, char *const *argv)
|
||||||
{
|
{
|
||||||
int pid, res;
|
int pid, res;
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
char **arg;
|
char buf[1024];
|
||||||
int n_args;
|
char *const *p;
|
||||||
|
struct spa_strbuf s;
|
||||||
|
|
||||||
/* Double fork to avoid zombies; we don't want to set SIGCHLD handler */
|
/* Double fork to avoid zombies; we don't want to set SIGCHLD handler */
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
|
@ -975,23 +977,16 @@ static int do_exec(struct pw_context *context, const char *path, const char *arg
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
arg = pw_strv_parse(args, strlen(args), INT_MAX, &n_args);
|
spa_strbuf_init(&s, buf, sizeof(buf));
|
||||||
if (arg == NULL) {
|
for (p = argv; *p; ++p)
|
||||||
pw_log_error("error parsing arguments: %m");
|
spa_strbuf_append(&s, " '%s'", *p);
|
||||||
goto done;
|
|
||||||
}
|
pw_log_info("exec%s", s.buffer);
|
||||||
arg = pw_strv_insert_at(arg, n_args, 0, path);
|
res = execvp(argv[0], argv);
|
||||||
if (arg == NULL) {
|
|
||||||
pw_log_error("error constructing arguments: %m");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
pw_log_info("exec %s '%s'", path, args);
|
|
||||||
res = execvp(path, arg);
|
|
||||||
pw_free_strv(arg);
|
|
||||||
|
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
res = -errno;
|
res = -errno;
|
||||||
pw_log_error("execvp error '%s': %m", path);
|
pw_log_error("execvp error '%s': %m", argv[0]);
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -1016,6 +1011,36 @@ done:
|
||||||
* }
|
* }
|
||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static char **make_exec_argv(const char *path, const char *value, int len)
|
||||||
|
{
|
||||||
|
char **argv = NULL;
|
||||||
|
int n_args;
|
||||||
|
|
||||||
|
if (spa_json_is_container(value, len)) {
|
||||||
|
if (!spa_json_is_array(value, len)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
argv = pw_strv_parse(value, len, INT_MAX, &n_args);
|
||||||
|
} else {
|
||||||
|
spa_autofree char *s = calloc(1, len + 1);
|
||||||
|
if (!s)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (spa_json_parse_stringn(value, len, s, len + 1) < 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
argv = pw_split_strv(s, " \t", INT_MAX, &n_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!argv)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return pw_strv_insert_at(argv, n_args, 0, path);
|
||||||
|
}
|
||||||
|
|
||||||
static int parse_exec(void *user_data, const char *location,
|
static int parse_exec(void *user_data, const char *location,
|
||||||
const char *section, const char *str, size_t len)
|
const char *section, const char *str, size_t len)
|
||||||
{
|
{
|
||||||
|
|
@ -1034,7 +1059,9 @@ static int parse_exec(void *user_data, const char *location,
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((r = spa_json_enter_object(&it[1], &it[2])) > 0) {
|
while ((r = spa_json_enter_object(&it[1], &it[2])) > 0) {
|
||||||
char *path = NULL, *args = NULL;
|
char *path = NULL;
|
||||||
|
const char *args_val = "[]";
|
||||||
|
int args_len = 2;
|
||||||
bool have_match = true;
|
bool have_match = true;
|
||||||
|
|
||||||
while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
|
while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
|
||||||
|
|
@ -1053,13 +1080,13 @@ static int parse_exec(void *user_data, const char *location,
|
||||||
} else if (spa_streq(key, "args")) {
|
} else if (spa_streq(key, "args")) {
|
||||||
if (spa_json_is_container(val, l))
|
if (spa_json_is_container(val, l))
|
||||||
l = spa_json_container_len(&it[2], val, l);
|
l = spa_json_container_len(&it[2], val, l);
|
||||||
args = (char*)val;
|
args_val = val;
|
||||||
spa_json_parse_stringn(val, l, args, l+1);
|
args_len = l;
|
||||||
} else if (spa_streq(key, "condition")) {
|
} else if (spa_streq(key, "condition")) {
|
||||||
if (!spa_json_is_array(val, l)) {
|
if (!spa_json_is_array(val, l)) {
|
||||||
pw_log_warn("expected array for condition in '%.*s'",
|
pw_log_warn("expected array for condition in '%.*s'",
|
||||||
(int)len, str);
|
(int)len, str);
|
||||||
break;
|
goto next;
|
||||||
}
|
}
|
||||||
spa_json_enter(&it[2], &it[3]);
|
spa_json_enter(&it[2], &it[3]);
|
||||||
have_match = find_match(&it[3], &context->properties->dict, true);
|
have_match = find_match(&it[3], &context->properties->dict, true);
|
||||||
|
|
@ -1072,11 +1099,23 @@ static int parse_exec(void *user_data, const char *location,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (path != NULL) {
|
if (path != NULL) {
|
||||||
res = do_exec(context, path, args);
|
char **argv = make_exec_argv(path, args_val, args_len);
|
||||||
|
|
||||||
|
if (!argv) {
|
||||||
|
pw_log_warn("expected array or string for args in '%.*s'",
|
||||||
|
(int)len, str);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = do_exec(context, argv);
|
||||||
|
pw_free_strv(argv);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
break;
|
break;
|
||||||
d->count++;
|
d->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
pw_log_warn("malformed object array in '%.*s'", (int)len, str);
|
pw_log_warn("malformed object array in '%.*s'", (int)len, str);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue