|
@@ -191,16 +191,19 @@ struct binding
|
|
const char *val;
|
|
const char *val;
|
|
};
|
|
};
|
|
|
|
|
|
-static const char *args[MAX_ARGS];
|
|
|
|
-static int num_args;
|
|
|
|
-static struct redirect redirects[MAX_REDIRECTS];
|
|
|
|
-static int num_redirects;
|
|
|
|
-static struct signal signals[MAX_SIGNALS];
|
|
|
|
-static int num_signals;
|
|
|
|
-static struct binding bindings[MAX_BINDINGS];
|
|
|
|
-static int num_bindings;
|
|
|
|
-static int background;
|
|
|
|
-static const char *directory;
|
|
|
|
|
|
+struct spawn
|
|
|
|
+{
|
|
|
|
+ const char *args[MAX_ARGS];
|
|
|
|
+ int num_args;
|
|
|
|
+ struct redirect redirects[MAX_REDIRECTS];
|
|
|
|
+ int num_redirects;
|
|
|
|
+ struct signal signals[MAX_SIGNALS];
|
|
|
|
+ int num_signals;
|
|
|
|
+ struct binding bindings[MAX_BINDINGS];
|
|
|
|
+ int num_bindings;
|
|
|
|
+ int background;
|
|
|
|
+ const char *directory;
|
|
|
|
+};
|
|
|
|
|
|
#ifdef __MINGW32__
|
|
#ifdef __MINGW32__
|
|
|
|
|
|
@@ -380,54 +383,53 @@ static void do_bindings(struct binding *bindings, int num_bindings)
|
|
|
|
|
|
for (i = 0; i < num_bindings; i++) {
|
|
for (i = 0; i < num_bindings; i++) {
|
|
struct binding *b = &bindings[i];
|
|
struct binding *b = &bindings[i];
|
|
- static char *str = NULL;
|
|
|
|
|
|
+ char *str = G_malloc(strlen(b->var) + strlen(b->val) + 2);
|
|
|
|
|
|
- str = G_realloc(str, strlen(b->var) + strlen(b->val) + 2);
|
|
|
|
sprintf(str, "%s=%s", b->var, b->val);
|
|
sprintf(str, "%s=%s", b->var, b->val);
|
|
putenv(str);
|
|
putenv(str);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static int do_spawn(const char *command)
|
|
|
|
|
|
+static int do_spawn(struct spawn *sp, const char *command)
|
|
{
|
|
{
|
|
int status = -1;
|
|
int status = -1;
|
|
pid_t pid;
|
|
pid_t pid;
|
|
|
|
|
|
- if (!do_signals(signals, num_signals, SST_PRE))
|
|
|
|
|
|
+ if (!do_signals(sp->signals, sp->num_signals, SST_PRE))
|
|
return status;
|
|
return status;
|
|
|
|
|
|
pid = fork();
|
|
pid = fork();
|
|
if (pid < 0) {
|
|
if (pid < 0) {
|
|
G_warning(_("Unable to create a new process"));
|
|
G_warning(_("Unable to create a new process"));
|
|
- undo_signals(signals, num_signals, SST_PRE);
|
|
|
|
|
|
+ undo_signals(sp->signals, sp->num_signals, SST_PRE);
|
|
|
|
|
|
return status;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
if (pid == 0) {
|
|
if (pid == 0) {
|
|
- if (!undo_signals(signals, num_signals, SST_PRE))
|
|
|
|
|
|
+ if (!undo_signals(sp->signals, sp->num_signals, SST_PRE))
|
|
_exit(127);
|
|
_exit(127);
|
|
|
|
|
|
- if (!do_signals(signals, num_signals, SST_CHILD))
|
|
|
|
|
|
+ if (!do_signals(sp->signals, sp->num_signals, SST_CHILD))
|
|
_exit(127);
|
|
_exit(127);
|
|
|
|
|
|
- if (directory)
|
|
|
|
- if (chdir(directory) < 0) {
|
|
|
|
- G_warning(_("Unable to change directory to %s"), directory);
|
|
|
|
|
|
+ if (sp->directory)
|
|
|
|
+ if (chdir(sp->directory) < 0) {
|
|
|
|
+ G_warning(_("Unable to change directory to %s"), sp->directory);
|
|
_exit(127);
|
|
_exit(127);
|
|
}
|
|
}
|
|
|
|
|
|
- do_redirects(redirects, num_redirects);
|
|
|
|
- do_bindings(bindings, num_bindings);
|
|
|
|
|
|
+ do_redirects(sp->redirects, sp->num_redirects);
|
|
|
|
+ do_bindings(sp->bindings, sp->num_bindings);
|
|
|
|
|
|
- execvp(command, (char **)args);
|
|
|
|
|
|
+ execvp(command, (char **)sp->args);
|
|
G_warning(_("Unable to execute command"));
|
|
G_warning(_("Unable to execute command"));
|
|
_exit(127);
|
|
_exit(127);
|
|
}
|
|
}
|
|
|
|
|
|
- do_signals(signals, num_signals, SST_POST);
|
|
|
|
|
|
+ do_signals(sp->signals, sp->num_signals, SST_POST);
|
|
|
|
|
|
- if (background)
|
|
|
|
|
|
+ if (sp->background)
|
|
status = (int)pid;
|
|
status = (int)pid;
|
|
else {
|
|
else {
|
|
pid_t n;
|
|
pid_t n;
|
|
@@ -440,27 +442,27 @@ static int do_spawn(const char *command)
|
|
status = -1;
|
|
status = -1;
|
|
}
|
|
}
|
|
|
|
|
|
- undo_signals(signals, num_signals, SST_POST);
|
|
|
|
- undo_signals(signals, num_signals, SST_PRE);
|
|
|
|
|
|
+ undo_signals(sp->signals, sp->num_signals, SST_POST);
|
|
|
|
+ undo_signals(sp->signals, sp->num_signals, SST_PRE);
|
|
|
|
|
|
return status;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
#endif /* __MINGW32__ */
|
|
#endif /* __MINGW32__ */
|
|
|
|
|
|
-static void begin_spawn(void)
|
|
|
|
|
|
+static void begin_spawn(struct spawn *sp)
|
|
{
|
|
{
|
|
- num_args = 0;
|
|
|
|
- num_redirects = 0;
|
|
|
|
- num_signals = 0;
|
|
|
|
- num_bindings = 0;
|
|
|
|
- background = 0;
|
|
|
|
- directory = NULL;
|
|
|
|
|
|
+ sp->num_args = 0;
|
|
|
|
+ sp->num_redirects = 0;
|
|
|
|
+ sp->num_signals = 0;
|
|
|
|
+ sp->num_bindings = 0;
|
|
|
|
+ sp->background = 0;
|
|
|
|
+ sp->directory = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
#define NEXT_ARG(var, type) ((type) *(var)++)
|
|
#define NEXT_ARG(var, type) ((type) *(var)++)
|
|
|
|
|
|
-static void parse_argvec(const char **va)
|
|
|
|
|
|
+static void parse_argvec(struct spawn *sp, const char **va)
|
|
{
|
|
{
|
|
for (;;) {
|
|
for (;;) {
|
|
const char *arg = NEXT_ARG(va, const char *);
|
|
const char *arg = NEXT_ARG(va, const char *);
|
|
@@ -468,64 +470,64 @@ static void parse_argvec(const char **va)
|
|
|
|
|
|
switch ((int)arg) {
|
|
switch ((int)arg) {
|
|
case 0:
|
|
case 0:
|
|
- args[num_args++] = NULL;
|
|
|
|
|
|
+ sp->args[sp->num_args++] = NULL;
|
|
break;
|
|
break;
|
|
case ((int)SF_REDIRECT_FILE):
|
|
case ((int)SF_REDIRECT_FILE):
|
|
- redirects[num_redirects].dst_fd = NEXT_ARG(va, int);
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].dst_fd = NEXT_ARG(va, int);
|
|
|
|
|
|
- redirects[num_redirects].src_fd = -1;
|
|
|
|
- redirects[num_redirects].mode = NEXT_ARG(va, int);
|
|
|
|
- redirects[num_redirects].file = NEXT_ARG(va, const char *);
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].src_fd = -1;
|
|
|
|
+ sp->redirects[sp->num_redirects].mode = NEXT_ARG(va, int);
|
|
|
|
+ sp->redirects[sp->num_redirects].file = NEXT_ARG(va, const char *);
|
|
|
|
|
|
- num_redirects++;
|
|
|
|
|
|
+ sp->num_redirects++;
|
|
break;
|
|
break;
|
|
case ((int)SF_REDIRECT_DESCRIPTOR):
|
|
case ((int)SF_REDIRECT_DESCRIPTOR):
|
|
- redirects[num_redirects].dst_fd = NEXT_ARG(va, int);
|
|
|
|
- redirects[num_redirects].src_fd = NEXT_ARG(va, int);
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].dst_fd = NEXT_ARG(va, int);
|
|
|
|
+ sp->redirects[sp->num_redirects].src_fd = NEXT_ARG(va, int);
|
|
|
|
|
|
- redirects[num_redirects].file = NULL;
|
|
|
|
- num_redirects++;
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].file = NULL;
|
|
|
|
+ sp->num_redirects++;
|
|
break;
|
|
break;
|
|
case ((int)SF_CLOSE_DESCRIPTOR):
|
|
case ((int)SF_CLOSE_DESCRIPTOR):
|
|
- redirects[num_redirects].dst_fd = NEXT_ARG(va, int);
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].dst_fd = NEXT_ARG(va, int);
|
|
|
|
|
|
- redirects[num_redirects].src_fd = -1;
|
|
|
|
- redirects[num_redirects].file = NULL;
|
|
|
|
- num_redirects++;
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].src_fd = -1;
|
|
|
|
+ sp->redirects[sp->num_redirects].file = NULL;
|
|
|
|
+ sp->num_redirects++;
|
|
break;
|
|
break;
|
|
case ((int)SF_SIGNAL):
|
|
case ((int)SF_SIGNAL):
|
|
- signals[num_signals].which = NEXT_ARG(va, int);
|
|
|
|
- signals[num_signals].action = NEXT_ARG(va, int);
|
|
|
|
- signals[num_signals].signum = NEXT_ARG(va, int);
|
|
|
|
|
|
+ sp->signals[sp->num_signals].which = NEXT_ARG(va, int);
|
|
|
|
+ sp->signals[sp->num_signals].action = NEXT_ARG(va, int);
|
|
|
|
+ sp->signals[sp->num_signals].signum = NEXT_ARG(va, int);
|
|
|
|
|
|
- signals[num_signals].valid = 0;
|
|
|
|
- num_signals++;
|
|
|
|
|
|
+ sp->signals[sp->num_signals].valid = 0;
|
|
|
|
+ sp->num_signals++;
|
|
break;
|
|
break;
|
|
case ((int)SF_VARIABLE):
|
|
case ((int)SF_VARIABLE):
|
|
var = NEXT_ARG(va, const char *);
|
|
var = NEXT_ARG(va, const char *);
|
|
|
|
|
|
val = getenv(var);
|
|
val = getenv(var);
|
|
- args[num_args++] = val ? val : "";
|
|
|
|
|
|
+ sp->args[sp->num_args++] = val ? val : "";
|
|
break;
|
|
break;
|
|
case ((int)SF_BINDING):
|
|
case ((int)SF_BINDING):
|
|
- bindings[num_bindings].var = NEXT_ARG(va, const char *);
|
|
|
|
- bindings[num_bindings].val = NEXT_ARG(va, const char *);
|
|
|
|
|
|
+ sp->bindings[sp->num_bindings].var = NEXT_ARG(va, const char *);
|
|
|
|
+ sp->bindings[sp->num_bindings].val = NEXT_ARG(va, const char *);
|
|
|
|
|
|
- num_bindings++;
|
|
|
|
|
|
+ sp->num_bindings++;
|
|
break;
|
|
break;
|
|
case ((int)SF_BACKGROUND):
|
|
case ((int)SF_BACKGROUND):
|
|
- background = 1;
|
|
|
|
|
|
+ sp->background = 1;
|
|
break;
|
|
break;
|
|
case ((int)SF_DIRECTORY):
|
|
case ((int)SF_DIRECTORY):
|
|
- directory = NEXT_ARG(va, const char *);
|
|
|
|
|
|
+ sp->directory = NEXT_ARG(va, const char *);
|
|
|
|
|
|
break;
|
|
break;
|
|
case ((int)SF_ARGVEC):
|
|
case ((int)SF_ARGVEC):
|
|
- parse_argvec(NEXT_ARG(va, const char **));
|
|
|
|
|
|
+ parse_argvec(sp, NEXT_ARG(va, const char **));
|
|
|
|
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
- args[num_args++] = arg;
|
|
|
|
|
|
+ sp->args[sp->num_args++] = arg;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -534,7 +536,7 @@ static void parse_argvec(const char **va)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static void parse_arglist(va_list va)
|
|
|
|
|
|
+static void parse_arglist(struct spawn *sp, va_list va)
|
|
{
|
|
{
|
|
for (;;) {
|
|
for (;;) {
|
|
const char *arg = va_arg(va, const char *);
|
|
const char *arg = va_arg(va, const char *);
|
|
@@ -542,64 +544,64 @@ static void parse_arglist(va_list va)
|
|
|
|
|
|
switch ((int)arg) {
|
|
switch ((int)arg) {
|
|
case 0:
|
|
case 0:
|
|
- args[num_args++] = NULL;
|
|
|
|
|
|
+ sp->args[sp->num_args++] = NULL;
|
|
break;
|
|
break;
|
|
case ((int)SF_REDIRECT_FILE):
|
|
case ((int)SF_REDIRECT_FILE):
|
|
- redirects[num_redirects].dst_fd = va_arg(va, int);
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].dst_fd = va_arg(va, int);
|
|
|
|
|
|
- redirects[num_redirects].src_fd = -1;
|
|
|
|
- redirects[num_redirects].mode = va_arg(va, int);
|
|
|
|
- redirects[num_redirects].file = va_arg(va, const char *);
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].src_fd = -1;
|
|
|
|
+ sp->redirects[sp->num_redirects].mode = va_arg(va, int);
|
|
|
|
+ sp->redirects[sp->num_redirects].file = va_arg(va, const char *);
|
|
|
|
|
|
- num_redirects++;
|
|
|
|
|
|
+ sp->num_redirects++;
|
|
break;
|
|
break;
|
|
case ((int)SF_REDIRECT_DESCRIPTOR):
|
|
case ((int)SF_REDIRECT_DESCRIPTOR):
|
|
- redirects[num_redirects].dst_fd = va_arg(va, int);
|
|
|
|
- redirects[num_redirects].src_fd = va_arg(va, int);
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].dst_fd = va_arg(va, int);
|
|
|
|
+ sp->redirects[sp->num_redirects].src_fd = va_arg(va, int);
|
|
|
|
|
|
- redirects[num_redirects].file = NULL;
|
|
|
|
- num_redirects++;
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].file = NULL;
|
|
|
|
+ sp->num_redirects++;
|
|
break;
|
|
break;
|
|
case ((int)SF_CLOSE_DESCRIPTOR):
|
|
case ((int)SF_CLOSE_DESCRIPTOR):
|
|
- redirects[num_redirects].dst_fd = va_arg(va, int);
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].dst_fd = va_arg(va, int);
|
|
|
|
|
|
- redirects[num_redirects].src_fd = -1;
|
|
|
|
- redirects[num_redirects].file = NULL;
|
|
|
|
- num_redirects++;
|
|
|
|
|
|
+ sp->redirects[sp->num_redirects].src_fd = -1;
|
|
|
|
+ sp->redirects[sp->num_redirects].file = NULL;
|
|
|
|
+ sp->num_redirects++;
|
|
break;
|
|
break;
|
|
case ((int)SF_SIGNAL):
|
|
case ((int)SF_SIGNAL):
|
|
- signals[num_signals].which = va_arg(va, int);
|
|
|
|
- signals[num_signals].action = va_arg(va, int);
|
|
|
|
- signals[num_signals].signum = va_arg(va, int);
|
|
|
|
|
|
+ sp->signals[sp->num_signals].which = va_arg(va, int);
|
|
|
|
+ sp->signals[sp->num_signals].action = va_arg(va, int);
|
|
|
|
+ sp->signals[sp->num_signals].signum = va_arg(va, int);
|
|
|
|
|
|
- signals[num_signals].valid = 0;
|
|
|
|
- num_signals++;
|
|
|
|
|
|
+ sp->signals[sp->num_signals].valid = 0;
|
|
|
|
+ sp->num_signals++;
|
|
break;
|
|
break;
|
|
case ((int)SF_VARIABLE):
|
|
case ((int)SF_VARIABLE):
|
|
var = va_arg(va, char *);
|
|
var = va_arg(va, char *);
|
|
|
|
|
|
val = getenv(var);
|
|
val = getenv(var);
|
|
- args[num_args++] = val ? val : "";
|
|
|
|
|
|
+ sp->args[sp->num_args++] = val ? val : "";
|
|
break;
|
|
break;
|
|
case ((int)SF_BINDING):
|
|
case ((int)SF_BINDING):
|
|
- bindings[num_bindings].var = va_arg(va, const char *);
|
|
|
|
- bindings[num_bindings].val = va_arg(va, const char *);
|
|
|
|
|
|
+ sp->bindings[sp->num_bindings].var = va_arg(va, const char *);
|
|
|
|
+ sp->bindings[sp->num_bindings].val = va_arg(va, const char *);
|
|
|
|
|
|
- num_bindings++;
|
|
|
|
|
|
+ sp->num_bindings++;
|
|
break;
|
|
break;
|
|
case ((int)SF_BACKGROUND):
|
|
case ((int)SF_BACKGROUND):
|
|
- background = 1;
|
|
|
|
|
|
+ sp->background = 1;
|
|
break;
|
|
break;
|
|
case ((int)SF_DIRECTORY):
|
|
case ((int)SF_DIRECTORY):
|
|
- directory = va_arg(va, const char *);
|
|
|
|
|
|
+ sp->directory = va_arg(va, const char *);
|
|
|
|
|
|
break;
|
|
break;
|
|
case ((int)SF_ARGVEC):
|
|
case ((int)SF_ARGVEC):
|
|
- parse_argvec(va_arg(va, const char **));
|
|
|
|
|
|
+ parse_argvec(sp, va_arg(va, const char **));
|
|
|
|
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
- args[num_args++] = arg;
|
|
|
|
|
|
+ sp->args[sp->num_args++] = arg;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -620,11 +622,13 @@ static void parse_arglist(va_list va)
|
|
*/
|
|
*/
|
|
int G_vspawn_ex(const char *command, const char **args)
|
|
int G_vspawn_ex(const char *command, const char **args)
|
|
{
|
|
{
|
|
- begin_spawn();
|
|
|
|
|
|
+ struct spawn sp;
|
|
|
|
+
|
|
|
|
+ begin_spawn(&sp);
|
|
|
|
|
|
- parse_argvec(args);
|
|
|
|
|
|
+ parse_argvec(&sp, args);
|
|
|
|
|
|
- return do_spawn(command);
|
|
|
|
|
|
+ return do_spawn(&sp, command);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -639,13 +643,14 @@ int G_vspawn_ex(const char *command, const char **args)
|
|
|
|
|
|
int G_spawn_ex(const char *command, ...)
|
|
int G_spawn_ex(const char *command, ...)
|
|
{
|
|
{
|
|
|
|
+ struct spawn sp;
|
|
va_list va;
|
|
va_list va;
|
|
|
|
|
|
- begin_spawn();
|
|
|
|
|
|
+ begin_spawn(&sp);
|
|
|
|
|
|
va_start(va, command);
|
|
va_start(va, command);
|
|
- parse_arglist(va);
|
|
|
|
|
|
+ parse_arglist(&sp, va);
|
|
va_end(va);
|
|
va_end(va);
|
|
|
|
|
|
- return do_spawn(command);
|
|
|
|
|
|
+ return do_spawn(&sp, command);
|
|
}
|
|
}
|