libobs: Add os_process_pipe_create2

This new API uses the os_process_args_t object rather than a string for
more safe and sane command line argument handling.
This commit is contained in:
derrod
2024-01-14 04:17:53 +01:00
committed by Lain
parent e885d25f5b
commit 9bc3082402
3 changed files with 88 additions and 6 deletions

View File

@@ -31,14 +31,14 @@ struct os_process_pipe {
FILE *err_file;
};
os_process_pipe_t *os_process_pipe_create(const char *cmd_line,
const char *type)
os_process_pipe_t *os_process_pipe_create_internal(const char *bin, char **argv,
const char *type)
{
struct os_process_pipe process_pipe = {0};
struct os_process_pipe *out;
posix_spawn_file_actions_t file_actions;
if (!cmd_line || !type) {
if (!bin || !argv || !type) {
return NULL;
}
@@ -94,9 +94,8 @@ os_process_pipe_t *os_process_pipe_create(const char *cmd_line,
STDERR_FILENO);
int pid;
char *argv[4] = {"sh", "-c", (char *)cmd_line, NULL};
int ret = posix_spawn(&pid, "/bin/sh", &file_actions, NULL, argv, NULL);
int ret = posix_spawn(&pid, bin, &file_actions, NULL,
(char *const *)argv, NULL);
posix_spawn_file_actions_destroy(&file_actions);
@@ -127,6 +126,23 @@ os_process_pipe_t *os_process_pipe_create(const char *cmd_line,
return out;
}
os_process_pipe_t *os_process_pipe_create(const char *cmd_line,
const char *type)
{
if (!cmd_line)
return NULL;
char *argv[3] = {"-c", (char *)cmd_line, NULL};
return os_process_pipe_create_internal("/bin/sh", argv, type);
}
os_process_pipe_t *os_process_pipe_create2(const os_process_args_t *args,
const char *type)
{
char **argv = os_process_args_get_argv(args);
return os_process_pipe_create_internal(argv[0], argv, type);
}
int os_process_pipe_destroy(os_process_pipe_t *pp)
{
int ret = 0;

View File

@@ -19,6 +19,7 @@
#include "platform.h"
#include "bmem.h"
#include "dstr.h"
#include "pipe.h"
struct os_process_pipe {
@@ -145,6 +146,69 @@ error:
return NULL;
}
static inline void add_backslashes(struct dstr *str, size_t count)
{
while (count--)
dstr_cat_ch(str, '\\');
}
os_process_pipe_t *os_process_pipe_create2(const os_process_args_t *args,
const char *type)
{
struct dstr cmd_line = {0};
/* Convert list to command line as Windows does not have any API that
* allows us to just pass argc/argv. */
char **argv = os_process_args_get_argv(args);
/* Based on Python subprocess module implementation. */
while (*argv) {
size_t bs_count = 0;
const char *arg = *argv;
bool needs_quotes = strlen(arg) == 0 ||
strstr(arg, " ") != NULL ||
strstr(arg, "\t") != NULL;
if (cmd_line.len)
dstr_cat_ch(&cmd_line, ' ');
if (needs_quotes)
dstr_cat_ch(&cmd_line, '"');
while (*arg) {
if (*arg == '\\') {
bs_count++;
} else if (*arg == '"') {
add_backslashes(&cmd_line, bs_count * 2);
dstr_cat(&cmd_line, "\\\"");
bs_count = 0;
} else {
if (bs_count) {
add_backslashes(&cmd_line, bs_count);
bs_count = 0;
}
dstr_cat_ch(&cmd_line, *arg);
}
arg++;
}
if (bs_count)
add_backslashes(&cmd_line, bs_count);
if (needs_quotes) {
add_backslashes(&cmd_line, bs_count);
dstr_cat_ch(&cmd_line, '"');
}
argv++;
}
os_process_pipe_t *ret = os_process_pipe_create(cmd_line.array, type);
dstr_free(&cmd_line);
return ret;
}
int os_process_pipe_destroy(os_process_pipe_t *pp)
{
int ret = 0;

View File

@@ -30,6 +30,8 @@ typedef struct os_process_args os_process_args_t;
EXPORT os_process_pipe_t *os_process_pipe_create(const char *cmd_line,
const char *type);
EXPORT os_process_pipe_t *os_process_pipe_create2(const os_process_args_t *args,
const char *type);
EXPORT int os_process_pipe_destroy(os_process_pipe_t *pp);
EXPORT size_t os_process_pipe_read(os_process_pipe_t *pp, uint8_t *data,