process: Add a wrapper to invoke a command under the system default shell
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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_ @}*/
|
||||
|
||||
Reference in New Issue
Block a user