Often a command wants to be run in a shell with stdout placed in a string. This API mimics that of stdio's popen, running the given command (not argv array) with "/bin/sh -c" then appending the output from stdout to the buf argument. Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx> --- tools/lib/subcmd/Makefile | 32 +++++++++++++++++++++++++++++--- tools/lib/subcmd/run-command.c | 30 ++++++++++++++++++++++++++++++ tools/lib/subcmd/run-command.h | 14 ++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile index b87213263a5e..23174d013519 100644 --- a/tools/lib/subcmd/Makefile +++ b/tools/lib/subcmd/Makefile @@ -13,6 +13,7 @@ CC ?= $(CROSS_COMPILE)gcc LD ?= $(CROSS_COMPILE)ld AR ?= $(CROSS_COMPILE)ar +MKDIR = mkdir RM = rm -f MAKEFLAGS += --no-print-directory @@ -55,6 +56,17 @@ CFLAGS += -I$(srctree)/tools/include/ CFLAGS += $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) +LIBAPI_DIR = $(srctree)/tools/lib/api/ +ifneq ($(OUTPUT),) + LIBAPI_OUTPUT = $(abspath $(OUTPUT))/libapi +else + LIBAPI_OUTPUT = $(CURDIR)/libapi +endif +LIBAPI_DESTDIR = $(LIBAPI_OUTPUT) +LIBAPI_INCLUDE = $(LIBAPI_DESTDIR)/include +LIBAPI = $(LIBAPI_OUTPUT)/libapi.a +CFLAGS += -I$(LIBAPI_OUTPUT)/include + SUBCMD_IN := $(OUTPUT)libsubcmd-in.o ifeq ($(LP64), 1) @@ -76,7 +88,9 @@ include $(srctree)/tools/build/Makefile.include all: fixdep $(LIBFILE) -$(SUBCMD_IN): FORCE +prepare: $(LIBAPI) + +$(SUBCMD_IN): FORCE prepare @$(MAKE) $(build)=libsubcmd $(LIBFILE): $(SUBCMD_IN) @@ -113,10 +127,22 @@ install_headers: $(INSTALL_HDRS) install: install_lib install_headers -clean: +$(LIBAPI_OUTPUT): + $(Q)$(MKDIR) -p $@ + +$(LIBAPI): FORCE | $(LIBAPI_OUTPUT) + $(Q)$(MAKE) -C $(LIBAPI_DIR) O=$(LIBAPI_OUTPUT) \ + DESTDIR=$(LIBAPI_DESTDIR) prefix= \ + $@ install_headers + +$(LIBAPI)-clean: + $(call QUIET_CLEAN, libapi) + $(Q)$(RM) -r -- $(LIBAPI_OUTPUT) + +clean: $(LIBAPI)-clean $(call QUIET_CLEAN, libsubcmd) $(RM) $(LIBFILE); \ find $(or $(OUTPUT),.) -name \*.o -or -name \*.o.cmd -or -name \*.o.d | xargs $(RM) FORCE: -.PHONY: clean FORCE +.PHONY: clean FORCE prepare diff --git a/tools/lib/subcmd/run-command.c b/tools/lib/subcmd/run-command.c index 5cdac2162532..e90b285b6720 100644 --- a/tools/lib/subcmd/run-command.c +++ b/tools/lib/subcmd/run-command.c @@ -7,6 +7,7 @@ #include <linux/string.h> #include <errno.h> #include <sys/wait.h> +#include <api/strbuf.h> #include "subcmd-util.h" #include "run-command.h" #include "exec-cmd.h" @@ -227,3 +228,32 @@ int run_command_v_opt(const char **argv, int opt) prepare_run_command_v_opt(&cmd, argv, opt); return run_command(&cmd); } + +int run_command_strbuf(const char *cmd, struct strbuf *buf) +{ + const char *argv[4] = { + "/bin/sh", + "-c", + cmd, + NULL + }; + struct child_process child = { + .argv = argv, + .out = -1, + }; + int err; + ssize_t read_sz; + + err = start_command(&child); + if (err) + return err; + + read_sz = strbuf_read(buf, child.out, 0); + + err = finish_command(&child); + close(child.out); + if (read_sz < 0) + return (int)read_sz; + + return err; +} diff --git a/tools/lib/subcmd/run-command.h b/tools/lib/subcmd/run-command.h index 17d969c6add3..1f7a2af9248c 100644 --- a/tools/lib/subcmd/run-command.h +++ b/tools/lib/subcmd/run-command.h @@ -58,4 +58,18 @@ int run_command(struct child_process *); #define RUN_COMMAND_STDOUT_TO_STDERR 4 int run_command_v_opt(const char **argv, int opt); +struct strbuf; +/** + * run_command_strbuf() - Run cmd using /bin/sh and place stdout in strbuf. + * @cmd: The command to run by "/bin/sh -c". + * @buf: The strbuf appended to by reading stdout. + * + * Similar to popen with fread, run the given command reading the stdout output + * to buf. As with popen, stderr output goes to the current processes stderr but + * may be redirected in cmd by using "2>&1". + * + * Return: 0 on success or a negative error code on failure. + */ +int run_command_strbuf(const char *cmd, struct strbuf *buf); + #endif /* __SUBCMD_RUN_COMMAND_H */ -- 2.39.0.314.g84b9a713c41-goog