Commit d7060aff by Edward Thomson

process: provide cmdline-handling and execv style

Provide both cmdline-style handling (passing it to the shell on POSIX,
or directly to CreateProcess on win32) and execv style (passing it
directly to execv on POSIX, and mangling it into a single command-line
on win32).
parent 23424f43
...@@ -43,7 +43,8 @@ typedef struct { ...@@ -43,7 +43,8 @@ typedef struct {
/** /**
* Create a new process. The command to run should be specified as the * Create a new process. The command to run should be specified as the
* element of the `arg` array. * element of the `arg` array, execv-style. This should be the full path
* to the command to run, the PATH is not obeyed.
* *
* This function will add the given environment variables (in `env`) * This function will add the given environment variables (in `env`)
* to the current environment. Operations on environment variables * to the current environment. Operations on environment variables
...@@ -67,8 +68,36 @@ extern int git_process_new( ...@@ -67,8 +68,36 @@ extern int git_process_new(
size_t env_len, size_t env_len,
git_process_options *opts); git_process_options *opts);
/**
* Create a new process. The command to run should be specified as the
* `cmdline` option - which is the full text of the command line as it
* would be specified or run by a user. The command to run will be
* looked up in the PATH.
*
* On Unix, this will be executed by the system's shell (`/bin/sh`)
* and may contain _Bourne-style_ shell quoting rules. On Windows,
* this will be passed to `CreateProcess`, and similarly, may
* contain _Windows-style_ shell quoting rules.
*
* This function will add the given environment variables (in `env`)
* to the current environment. Operations on environment variables
* are not thread safe, so you may not modify the environment during
* this call. You can avoid this by setting `exclude_env` in the
* options and providing the entire environment yourself.
*/
extern int git_process_new_from_cmdline(
git_process **out,
const char *cmdline,
const char **env,
size_t env_len,
git_process_options *opts);
#ifdef GIT_WIN32 #ifdef GIT_WIN32
extern int git_process__appname(
git_str *out,
const char *cmdline);
/* Windows path parsing is tricky; this helper function is for testing. */ /* Windows path parsing is tricky; this helper function is for testing. */
extern int git_process__cmdline( extern int git_process__cmdline(
git_str *out, git_str *out,
......
...@@ -146,6 +146,19 @@ int git_process_new( ...@@ -146,6 +146,19 @@ int git_process_new(
return 0; return 0;
} }
extern int git_process_new_from_cmdline(
git_process **out,
const char *cmdline,
const char **env,
size_t env_len,
git_process_options *opts)
{
const char *args[] = { "/bin/sh", "-c", cmdline };
return git_process_new(out,
args, ARRAY_SIZE(args), env, env_len, opts);
}
#define CLOSE_FD(fd) \ #define CLOSE_FD(fd) \
if (fd >= 0) { \ if (fd >= 0) { \
close(fd); \ close(fd); \
......
...@@ -162,30 +162,29 @@ done: ...@@ -162,30 +162,29 @@ done:
return ret < 0 ? -1 : 0; return ret < 0 ? -1 : 0;
} }
int git_process_new( static int process_new(
git_process **out, git_process **out,
const char **args, const char *appname,
size_t args_len, const char *cmdline,
const char **env, const char **env,
size_t env_len, size_t env_len,
git_process_options *opts) git_process_options *opts)
{ {
git_process *process; git_process *process;
git_str cmdline = GIT_STR_INIT; int error = 0;
int error;
GIT_ASSERT_ARG(out && args && args_len > 0);
*out = NULL; *out = NULL;
process = git__calloc(1, sizeof(git_process)); process = git__calloc(1, sizeof(git_process));
GIT_ERROR_CHECK_ALLOC(process); GIT_ERROR_CHECK_ALLOC(process);
if ((error = git_process__cmdline(&cmdline, args, args_len)) < 0) if (appname &&
git_utf8_to_16_alloc(&process->appname, appname) < 0) {
error = -1;
goto done; goto done;
}
if (git_utf8_to_16_alloc(&process->appname, args[0]) < 0 || if (git_utf8_to_16_alloc(&process->cmdline, cmdline) < 0) {
git_utf8_to_16_alloc(&process->cmdline, cmdline.ptr) < 0) {
error = -1; error = -1;
goto done; goto done;
} }
...@@ -211,6 +210,40 @@ done: ...@@ -211,6 +210,40 @@ done:
else else
*out = process; *out = process;
return error;
}
int git_process_new_from_cmdline(
git_process **out,
const char *cmdline,
const char **env,
size_t env_len,
git_process_options *opts)
{
GIT_ASSERT_ARG(out && cmdline);
return process_new(out, NULL, cmdline, env, env_len, opts);
}
int git_process_new(
git_process **out,
const char **args,
size_t args_len,
const char **env,
size_t env_len,
git_process_options *opts)
{
git_str cmdline = GIT_STR_INIT;
int error;
GIT_ASSERT_ARG(out && args && args_len > 0);
if ((error = git_process__cmdline(&cmdline, args, args_len)) < 0)
goto done;
error = process_new(out, args[0], cmdline.ptr, env, env_len, opts);
done:
git_str_dispose(&cmdline); git_str_dispose(&cmdline);
return error; return error;
} }
......
...@@ -10,8 +10,10 @@ static git_str result; ...@@ -10,8 +10,10 @@ static git_str result;
cl_assert_equal_s(expected, result.ptr); \ cl_assert_equal_s(expected, result.ptr); \
git_str_dispose(&result); \ git_str_dispose(&result); \
} while(0) } while(0)
#endif #endif
void test_process_win32__cmdline_is_whitespace_delimited(void) void test_process_win32__cmdline_is_whitespace_delimited(void)
{ {
#ifdef GIT_WIN32 #ifdef GIT_WIN32
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment