aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2014-10-06 10:52:18 +0200
committerMartin Willi <martin@revosec.ch>2014-10-06 18:24:39 +0200
commit7dd06d274da5c0775e772f0d74e2f823f85b675b (patch)
tree89dc696de0d42061cce09b4814911c6cfe9336e8 /src
parent02e4dedce513c07da88b873acc6bd5e59dd867ae (diff)
downloadstrongswan-7dd06d274da5c0775e772f0d74e2f823f85b675b.tar.bz2
strongswan-7dd06d274da5c0775e772f0d74e2f823f85b675b.tar.xz
process: Add a wrapper to invoke a command under the system default shell
Diffstat (limited to 'src')
-rw-r--r--src/libstrongswan/tests/suites/test_process.c16
-rw-r--r--src/libstrongswan/utils/process.c77
-rw-r--r--src/libstrongswan/utils/process.h17
3 files changed, 110 insertions, 0 deletions
diff --git a/src/libstrongswan/tests/suites/test_process.c b/src/libstrongswan/tests/suites/test_process.c
index 7092f0650..c22c47294 100644
--- a/src/libstrongswan/tests/suites/test_process.c
+++ b/src/libstrongswan/tests/suites/test_process.c
@@ -176,6 +176,18 @@ START_TEST(test_env)
}
END_TEST
+START_TEST(test_shell)
+{
+ process_t *process;
+ int retval;
+
+ process = process_start_shell(NULL, NULL, NULL, NULL, "exit %d", 3);
+ ck_assert(process != NULL);
+ ck_assert(process->wait(process, &retval));
+ ck_assert_int_eq(retval, 3);
+}
+END_TEST
+
Suite *process_suite_create()
{
Suite *s;
@@ -201,5 +213,9 @@ Suite *process_suite_create()
tcase_add_test(tc, test_env);
suite_add_tcase(s, tc);
+ tc = tcase_create("shell");
+ tcase_add_test(tc, test_shell);
+ suite_add_tcase(s, tc);
+
return s;
}
diff --git a/src/libstrongswan/utils/process.c b/src/libstrongswan/utils/process.c
index 25e161b2c..233429447 100644
--- a/src/libstrongswan/utils/process.c
+++ b/src/libstrongswan/utils/process.c
@@ -13,11 +13,16 @@
* for more details.
*/
+/* vasprintf() */
+#define _GNU_SOURCE
#include "process.h"
+#include <library.h>
#include <utils/debug.h>
#include <fcntl.h>
+#include <stdio.h>
+#include <stdarg.h>
typedef struct private_process_t private_process_t;
@@ -218,6 +223,35 @@ process_t* process_start(char *const argv[], char *const envp[],
}
}
+/**
+ * See header
+ */
+process_t* process_start_shell(char *const envp[], int *in, int *out, int *err,
+ char *fmt, ...)
+{
+ char *argv[] = {
+ "/bin/sh",
+ "-c",
+ NULL,
+ NULL
+ };
+ process_t *process;
+ va_list args;
+ int len;
+
+ va_start(args, fmt);
+ len = vasprintf(&argv[2], fmt, args);
+ va_end(args);
+ if (len < 0)
+ {
+ return NULL;
+ }
+
+ process = process_start(argv, envp, in, out, err, TRUE);
+ free(argv[2]);
+ return process;
+}
+
#else /* WIN32 */
/**
@@ -511,4 +545,47 @@ process_t* process_start(char *const argv[], char *const envp[],
return &this->public;
}
+/**
+ * See header
+ */
+process_t* process_start_shell(char *const envp[], int *in, int *out, int *err,
+ char *fmt, ...)
+{
+ char path[MAX_PATH], *exe = "system32\\cmd.exe";
+ char *argv[] = {
+ path,
+ "/C",
+ NULL,
+ NULL
+ };
+ process_t *process;
+ va_list args;
+ int len;
+
+ len = GetSystemWindowsDirectory(path, sizeof(path));
+ if (len == 0 || len >= sizeof(path) - strlen(exe))
+ {
+ DBG1(DBG_LIB, "resolving Windows directory failed: 0x%08x",
+ GetLastError());
+ return NULL;
+ }
+ if (path[len + 1] != '\\')
+ {
+ strncat(path, "\\", sizeof(path) - len++);
+ }
+ strncat(path, exe, sizeof(path) - len);
+
+ va_start(args, fmt);
+ len = vasprintf(&argv[2], fmt, args);
+ va_end(args);
+ if (len < 0)
+ {
+ return NULL;
+ }
+
+ process = process_start(argv, envp, in, out, err, TRUE);
+ free(argv[2]);
+ return process;
+}
+
#endif /* WIN32 */
diff --git a/src/libstrongswan/utils/process.h b/src/libstrongswan/utils/process.h
index 62d2ce757..81719201c 100644
--- a/src/libstrongswan/utils/process.h
+++ b/src/libstrongswan/utils/process.h
@@ -77,4 +77,21 @@ struct process_t {
process_t* process_start(char *const argv[], char *const envp[],
int *in, int *out, int *err, bool close_all);
+/**
+ * Spawn a command in a shell child process.
+ *
+ * Same as process_start(), but passes a single command to a shell, such as
+ * "sh -c". See process_start() for I/O redirection notes.
+ *
+ * @param envp NULL terminated list of environment variables
+ * @param in pipe fd returned for redirecting data to child stdin
+ * @param out pipe fd returned to redirect child stdout data to
+ * @param err pipe fd returned to redirect child stderr data to
+ * @param fmt printf format string for command
+ * @param ... arguments for fmt
+ * @return process, NULL on failure
+ */
+process_t* process_start_shell(char *const envp[], int *in, int *out, int *err,
+ char *fmt, ...);
+
#endif /** PROCESS_H_ @}*/