From: Baptiste Daroussin Date: Mon, 24 Oct 2022 11:36:14 +0000 (+0200) Subject: utils: add 2 wrappers around posix_spawn X-Git-Tag: RELEASE_1_4_0a1~64 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=12ed25df2f3babfee42389c962edeaae0160db1b;p=thirdparty%2Fmlmmj.git utils: add 2 wrappers around posix_spawn the goal here it to avoid code duplication around fork and execvp --- diff --git a/include/utils.h b/include/utils.h index 4648e1e2..7e4b4bd8 100644 --- a/include/utils.h +++ b/include/utils.h @@ -26,3 +26,5 @@ char *lowercase(const char *); intmax_t strtoim(const char *np, intmax_t minval, intmax_t maxval, const char **errpp); uintmax_t strtouim(const char *, uintmax_t, uintmax_t, const char **); +void exec_or_die(const char *arg, ...); +int exec_and_wait(const char *arg, ...); diff --git a/src/utils.c b/src/utils.c index 7644dc48..0a6eef6b 100644 --- a/src/utils.c +++ b/src/utils.c @@ -20,13 +20,20 @@ * IN THE SOFTWARE. */ -#include +#include + #include +#include #include +#include +#include +#include #include "xmalloc.h" #include "utils.h" +extern char **environ; + intmax_t strtoim(const char *np, intmax_t minval, intmax_t maxval, const char **errpp) { @@ -104,3 +111,62 @@ lowercase(const char *address) } return (loweraddress); } + +void +exec_or_die(const char *arg, ...) +{ + va_list ap; + const char **argv; + int n; + + va_start(ap, arg); + n = 1; + while (va_arg(ap, char *) != NULL) + n++; + va_end(ap); + argv = xmalloc((n +1) * sizeof(argv)); + va_start(ap, arg); + argv[0] = arg; + n = 1; + while ((argv[n] = va_arg(ap, char *)) != NULL) + n++; + va_end(ap); + execvp(argv[0], (char *const *)argv); + err(EXIT_FAILURE, "Execution failed for '%s'", argv[0]); +} + +int +exec_and_wait(const char *arg, ...) +{ + va_list ap; + const char **argv; + int n; + pid_t p; + int pstat; + + va_start(ap, arg); + n = 1; + while (va_arg(ap, char *) != NULL) + n++; + va_end(ap); + argv = xmalloc((n +1) * sizeof(argv)); + va_start(ap, arg); + argv[0] = arg; + n = 1; + while ((argv[n] = va_arg(ap, char *)) != NULL) + n++; + va_end(ap); + + if (0 != posix_spawnp(&p, argv[0], NULL, NULL, + (char *const *) argv, environ)) { + warn("Execution failed for '%s'", argv[0]); + return (-1); + } + while (waitpid(p, &pstat, 0) == -1) { + if (errno != EINTR) + warn("Could not wait for the execution of '%s'", argv[0]); + return (-1); + } + + return (WEXITSTATUS(pstat)); +} diff --git a/tests/mlmmj.c b/tests/mlmmj.c index c81695ac..f277f69e 100644 --- a/tests/mlmmj.c +++ b/tests/mlmmj.c @@ -53,6 +53,8 @@ ATF_TC_WITHOUT_HEAD(mygetline); ATF_TC_WITHOUT_HEAD(init_sock); ATF_TC_WITHOUT_HEAD(genmsgid); ATF_TC_WITHOUT_HEAD(lowercase); +ATF_TC_WITHOUT_HEAD(exec_or_die); +ATF_TC_WITHOUT_HEAD(exec_and_wait); #ifndef NELEM #define NELEM(array) (sizeof(array) / sizeof((array)[0])) @@ -256,6 +258,35 @@ ATF_TC_BODY(genmsgid, tc) free(test); } +ATF_TC_BODY(exec_or_die, tc) +{ + pid_t p = atf_utils_fork(); + if (p == 0) { + exec_or_die("/usr/bin/nopenope", NULL); + } + atf_utils_wait(p, 1, "", "mlmmj: Execution failed for '/usr/bin/nopenope': No such file or directory\n"); + p = atf_utils_fork(); + if (p == 0) { + exec_or_die("/usr/bin/true", (char *)NULL); + } + atf_utils_wait(p, 0, "", ""); + p = atf_utils_fork(); + if (p == 0) { + exec_or_die("/bin/echo", "a", (char *)NULL); + } + atf_utils_wait(p, 0, "a\n", ""); +} + +ATF_TC_BODY(exec_and_wait, tc) +{ + int val = exec_and_wait("/usr/bin/nopenope", NULL); + ATF_REQUIRE_EQ(val, -1); + val = exec_and_wait("/usr/bin/true", NULL); + ATF_REQUIRE_EQ(val, 0); + val = exec_and_wait("/usr/bin/false", NULL); + ATF_REQUIRE_EQ(val, 1); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, random_int); @@ -266,6 +297,8 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, lowercase); ATF_TP_ADD_TC(tp, init_sock); ATF_TP_ADD_TC(tp, genmsgid); + ATF_TP_ADD_TC(tp, exec_or_die); + ATF_TP_ADD_TC(tp, exec_and_wait); return (atf_no_error()); }