process: Add a wrapper to invoke a command under the system default shell
authorMartin Willi <martin@revosec.ch>
Mon, 6 Oct 2014 08:52:18 +0000 (10:52 +0200)
committerMartin Willi <martin@revosec.ch>
Mon, 6 Oct 2014 16:24:39 +0000 (18:24 +0200)
src/libstrongswan/tests/suites/test_process.c
src/libstrongswan/utils/process.c
src/libstrongswan/utils/process.h

index 7092f06..c22c472 100644 (file)
@@ -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;
 }
index 25e161b..2334294 100644 (file)
  * 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 */
index 62d2ce7..8171920 100644 (file)
@@ -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_ @}*/