[GRASS-SVN] r40547 - grass/branches/develbranch_6/lib/gis
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue Jan 19 02:34:45 EST 2010
Author: glynn
Date: 2010-01-19 02:34:44 -0500 (Tue, 19 Jan 2010)
New Revision: 40547
Modified:
grass/branches/develbranch_6/lib/gis/spawn.c
Log:
Sync spawn.c to 7.0
Modified: grass/branches/develbranch_6/lib/gis/spawn.c
===================================================================
--- grass/branches/develbranch_6/lib/gis/spawn.c 2010-01-19 07:32:53 UTC (rev 40546)
+++ grass/branches/develbranch_6/lib/gis/spawn.c 2010-01-19 07:34:44 UTC (rev 40547)
@@ -26,6 +26,8 @@
#ifndef __MINGW32__
#include <sys/wait.h>
+#else
+#include <windows.h>
#endif
#include <grass/config.h>
#include <grass/gis.h>
@@ -56,187 +58,428 @@
* \return process status on success
*/
-#ifdef __MINGW32__
+struct redirect
+{
+ int dst_fd;
+ int src_fd;
+ const char *file;
+ int mode;
+};
-int G_spawn(const char *command, ...)
+struct signal
{
- va_list va;
+ int which;
+ int action;
+ int signum;
+ int valid;
+#ifndef __MINGW32__
+ struct sigaction old_act;
+ sigset_t old_mask;
+#endif
+};
+
+struct binding
+{
+ const char *var;
+ const char *val;
+};
+
+struct spawn
+{
const char *args[MAX_ARGS];
- int num_args = 0;
+ 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;
+};
- va_start(va, command);
+static void parse_arglist(struct spawn *sp, va_list va);
+static void parse_argvec(struct spawn *sp, const char **va);
- for (num_args = 0; num_args < MAX_ARGS;) {
- const char *arg = va_arg(va, const char *);
+#ifdef __MINGW32__
- args[num_args++] = arg;
- if (!arg)
- break;
- }
+struct buffer {
+ char *str;
+ size_t len;
+ size_t size;
+};
- va_end(va);
+static const int INCREMENT = 50;
- if (num_args >= MAX_ARGS) {
- G_warning(_("Too many arguments"));
- return -1;
+static void clear(struct buffer *b)
+{
+ b->len = 0;
+ b->str[b->len] = '\0';
+}
+
+static void init(struct buffer *b)
+{
+ b->str = G_malloc(1);
+ b->size = 1;
+ clear(b);
+}
+
+static char *release(struct buffer *b)
+{
+ char *p = b->str;
+
+ b->str = NULL;
+ b->size = 0;
+ b->len = 0;
+
+ return p;
+}
+
+static void finish(struct buffer *b)
+{
+ if (b->str)
+ G_free(b->str);
+ release(b);
+}
+
+static void ensure(struct buffer *b, size_t n)
+{
+ if (b->size <= b->len + n + 1) {
+ b->size = b->len + n + INCREMENT;
+ b->str = G_realloc(b->str, b->size);
}
+}
- G_debug(3, "spawning '%s' ...", command);
+static void append(struct buffer *b, const char *str)
+{
+ size_t n = strlen(str);
- return _spawnvp(_P_WAIT, command, args);
+ ensure(b, n);
+ memcpy(&b->str[b->len], str, n);
+ b->len += n;
+ b->str[b->len] = '\0';
}
-#else
+static void append_char(struct buffer *b, char c)
+{
+ ensure(b, 1);
+ b->str[b->len] = c;
+ b->len++;
+ b->str[b->len] = '\0';
+}
-int G_spawn(const char *command, ...)
+static void escape_arg(struct buffer *result, const char *arg)
{
- va_list va;
- char *args[MAX_ARGS];
- int num_args = 0;
- struct sigaction act, intr, quit;
- sigset_t block, oldmask;
- int status = -1;
- pid_t pid;
+ struct buffer buf;
+ int quote, j;
- va_start(va, command);
+ init(&buf);
- for (num_args = 0; num_args < MAX_ARGS;) {
- char *arg = va_arg(va, char *);
+ quote = arg[0] == '\0' || strchr(arg, ' ') || strchr(arg, '\t');
- args[num_args++] = arg;
- if (!arg)
+ if (quote)
+ append_char(result, '\"');
+
+ for (j = 0; arg[j]; j++) {
+ int c = arg[j];
+ int k;
+
+ switch (c) {
+ case '\\':
+ append_char(&buf, '\\');
break;
+ case '\"':
+ for (k = 0; k < buf.len; k++)
+ append(result, "\\\\");
+ clear(&buf);
+ append(result, "\\\"");
+ break;
+ default:
+ if (buf.len > 0) {
+ append(result, buf.str);
+ clear(&buf);
+ }
+ append_char(result, c);
+ }
}
- va_end(va);
+ if (buf.len > 0)
+ append(result, buf.str);
- if (num_args >= MAX_ARGS) {
- G_warning(_("Too many arguments"));
- return -1;
+ if (quote) {
+ append(result, buf.str);
+ append_char(result, '\"');
}
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_RESTART;
+ finish(&buf);
+}
- act.sa_handler = SIG_IGN;
- if (sigaction(SIGINT, &act, &intr) < 0)
- goto error_1;
- if (sigaction(SIGQUIT, &act, &quit) < 0)
- goto error_2;
+static char *check_program(const char *pgm, const char *dir, const char *ext)
+{
+ char pathname[GPATH_MAX];
- sigemptyset(&block);
- sigaddset(&block, SIGCHLD);
- if (sigprocmask(SIG_BLOCK, &block, &oldmask) < 0)
- goto error_3;
+ sprintf(pathname, "%s%s%s%s", dir, *dir ? "\\" : "", pgm, ext);
+ return access(pathname, 0) == 0
+ ? G_store(pathname)
+ : NULL;
+}
- G_debug(3, "forking '%s' ...", command);
+static char *find_program_ext(const char *pgm, const char *dir, char **pathext)
+{
+ char *result;
+ int i;
- pid = fork();
+ if (result = check_program(pgm, dir, ""), result)
+ return result;
- if (pid < 0) {
- G_warning(_("Unable to create a new process"));
- goto error_4;
+ for (i = 0; pathext[i]; i++) {
+ const char *ext = pathext[i];
+ if (result = check_program(pgm, dir, ext), result)
+ return result;
}
- if (pid == 0) {
- sigaction(SIGINT, &intr, NULL);
- sigaction(SIGQUIT, &quit, NULL);
+ return NULL;
+}
- execvp(command, args);
- G_warning(_("Unable to execute command"));
- _exit(127);
+static char *find_program_dir_ext(const char *pgm, char **path, char **pathext)
+{
+ char *result = NULL;
+ int i;
+
+ if (strchr(pgm, '\\') || strchr(pgm, '/')) {
+ if (result = find_program_ext(pgm, "", pathext), result)
+ return result;
}
else {
- pid_t n;
+ if (result = find_program_ext(pgm, ".", pathext), result)
+ return result;
- do
- n = waitpid(pid, &status, 0);
- while (n == (pid_t) - 1 && errno == EINTR);
+ for (i = 0; path[i]; i++) {
+ const char *dir = path[i];
+ if (result = find_program_ext(pgm, dir, pathext), result)
+ return result;
+ }
+ }
- if (n != pid)
- status = -1;
+ return NULL;
+}
+
+static char *find_program(const char *pgm)
+{
+ char **path = G_tokenize(getenv("PATH"), ";");
+ char **pathext = G_tokenize(getenv("PATHEXT"), ";");
+ char *result = find_program_dir_ext(pgm, path, pathext);
+ G_free_tokens(path);
+ G_free_tokens(pathext);
+ return result;
+}
+
+static char *make_command_line(int shell, const char *cmd, const char **argv)
+{
+ struct buffer result;
+ int i;
+
+ init(&result);
+
+ if (shell) {
+ const char *comspec = getenv("COMSPEC");
+ append(&result, comspec ? comspec : "cmd.exe");
+ append(&result, " /c ");
+ escape_arg(&result, cmd);
}
- error_4:
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
- error_3:
- sigaction(SIGQUIT, &quit, NULL);
- error_2:
- sigaction(SIGINT, &intr, NULL);
- error_1:
- return status;
+ for (i = shell ? 1 : 0; argv[i]; i++) {
+ if (result.len > 0)
+ append_char(&result, ' ');
+ escape_arg(&result, argv[i]);
+ }
+
+ return release(&result);
}
-#endif /*__MINGW32__*/
+static char *make_environment(const char **envp)
+{
+ struct buffer result;
+ int i;
-struct redirect
+ init(&result);
+
+ for (i = 0; envp[i]; i++) {
+ const char *env = envp[i];
+
+ append(&result, env);
+ append_char(&result, '\0');
+ }
+
+ return release(&result);
+}
+
+static HANDLE get_handle(int fd)
{
- int dst_fd;
- int src_fd;
- const char *file;
- int mode;
-};
+ HANDLE h1, h2;
-struct signal
+ if (fd < 0)
+ return INVALID_HANDLE_VALUE;
+
+ h1 = (HANDLE) _get_osfhandle(fd);
+ if (!DuplicateHandle(GetCurrentProcess(), h1,
+ GetCurrentProcess(), &h2,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ return INVALID_HANDLE_VALUE;
+
+ return h2;
+}
+
+static int win_spawn(const char *cmd, const char **argv, const char **envp,
+ const char *cwd, HANDLE handles[3], int background,
+ int shell)
{
- int which;
- int action;
- int signum;
- int valid;
-#ifndef __MINGW32__
- struct sigaction old_act;
- sigset_t old_mask;
-#endif
-};
+ char *args = make_command_line(shell, cmd, argv);
+ char *env = make_environment(envp);
+ char *program = shell ? NULL : find_program(cmd);
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ BOOL result;
+ DWORD exitcode;
-struct binding
+ if (!shell) {
+ G_debug(3, "win_spawn: program = %s", program);
+
+ if (!program) {
+ G_free(args);
+ G_free(env);
+ return -1;
+ }
+ }
+
+ G_debug(3, "win_spawn: args = %s", args);
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+
+ si.dwFlags |= STARTF_USESTDHANDLES;
+ si.hStdInput = handles[0];
+ si.hStdOutput = handles[1];
+ si.hStdError = handles[2];
+
+ result = CreateProcess(
+ program, /* lpApplicationName */
+ args, /* lpCommandLine */
+ NULL, /* lpProcessAttributes */
+ NULL, /* lpThreadAttributes */
+ 1, /* bInheritHandles */
+ 0, /* dwCreationFlags */
+ env, /* lpEnvironment */
+ cwd, /* lpCurrentDirectory */
+ &si, /* lpStartupInfo */
+ &pi /* lpProcessInformation */
+ );
+
+ G_free(args);
+ G_free(env);
+ G_free(program);
+
+ if (!result) {
+ G_warning(_("CreateProcess() failed: error = %d"), GetLastError());
+ return -1;
+ }
+
+ if (!background) {
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ if (!GetExitCodeProcess(pi.hProcess, &exitcode))
+ return -1;
+ return (int) exitcode;
+ }
+
+ return pi.dwProcessId;
+}
+
+static void do_redirects(struct redirect *redirects, int num_redirects, HANDLE handles[3])
{
- const char *var;
- const char *val;
-};
+ int i;
-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;
+ for (i = 0; i < 3; i++)
+ handles[i] = get_handle(i);
-#ifdef __MINGW32__
+ for (i = 0; i < num_redirects; i++) {
+ struct redirect *r = &redirects[i];
-static void do_redirects(struct redirect *redirects, int num_redirects)
+ if (r->dst_fd < 0 || r->dst_fd > 2) {
+ G_warning(_("G_spawn: unable to redirect descriptor %d"), r->dst_fd);
+ continue;
+ }
+
+ if (r->file) {
+ r->src_fd = open(r->file, r->mode, 0666);
+
+ if (r->src_fd < 0) {
+ G_warning(_("G_spawn: unable to open file %s"), r->file);
+ _exit(127);
+ }
+
+ handles[r->dst_fd] = get_handle(r->src_fd);
+
+ close(r->src_fd);
+
+ }
+ else if (r->src_fd >= 0) {
+ handles[r->dst_fd] = get_handle(r->src_fd);
+ }
+ else
+ handles[r->dst_fd] = INVALID_HANDLE_VALUE;
+ }
+}
+
+static void add_binding(const char **env, int *pnum, const struct binding *b)
{
- if (num_redirects > 0)
- G_fatal_error
- ("G_spawn_ex: redirection not (yet) supported on Windows");
+ char *str = G_malloc(strlen(b->var) + strlen(b->val) + 2);
+ int n = *pnum;
+ int i;
+
+ sprintf(str, "%s=%s", b->var, b->val);
+
+ for (i = 0; i < n; i++)
+ if (G_strcasecmp(env[i], b->var) == 0) {
+ env[i] = str;
+ return;
+ }
+
+ env[n++] = str;
+ *pnum = n;
}
-static char **do_bindings(char **env, struct binding *bindings,
- int num_bindings)
+static const char **do_bindings(const struct binding *bindings, int num_bindings)
{
- if (num_bindings > 0)
- G_fatal_error
- ("G_spawn_ex: redirection not (yet) supported on Windows");
+ const char **newenv;
+ int i, n;
- return env;
+ for (i = 0; _environ[i]; i++)
+ ;
+ n = i;
+
+ newenv = G_malloc((num_bindings + n + 1) * sizeof(char *));
+
+ for (i = 0; i < n; i++)
+ newenv[i] = _environ[i];
+
+ for (i = 0; i < num_bindings; i++)
+ add_binding(newenv, &n, &bindings[i]);
+
+ return newenv;
}
-static int do_spawn(const char *command)
+static int do_spawn(struct spawn *sp, const char *command)
{
- char **env;
+ HANDLE handles[3];
+ const char **env;
int status;
- do_redirects(redirects, num_redirects);
- env = do_bindings(_environ, bindings, num_bindings);
+ do_redirects(sp->redirects, sp->num_redirects, handles);
+ env = do_bindings(sp->bindings, sp->num_bindings);
- status =
- spawnvpe(background ? _P_NOWAIT : _P_WAIT, command, args, env);
+ status = win_spawn(command, sp->args, env, sp->directory, handles, sp->background, 1);
- if (!background && status < 0)
+ if (!sp->background && status < 0)
G_warning(_("Unable to execute command"));
return status;
@@ -244,13 +487,13 @@
#else /* __MINGW32__ */
-static int undo_signals(struct signal *signals, int num_signals, int which)
+static int undo_signals(const struct signal *signals, int num_signals, int which)
{
int error = 0;
int i;
for (i = num_signals - 1; i >= 0; i--) {
- struct signal *s = &signals[i];
+ const struct signal *s = &signals[i];
if (s->which != which)
continue;
@@ -377,60 +620,59 @@
}
}
-static void do_bindings(struct binding *bindings, int num_bindings)
+static void do_bindings(const struct binding *bindings, int num_bindings)
{
int i;
for (i = 0; i < num_bindings; i++) {
- struct binding *b = &bindings[i];
- static char *str = NULL;
+ const struct binding *b = &bindings[i];
+ 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);
putenv(str);
}
}
-static int do_spawn(const char *command)
+static int do_spawn(struct spawn *sp, const char *command)
{
int status = -1;
pid_t pid;
- if (!do_signals(signals, num_signals, SST_PRE))
+ if (!do_signals(sp->signals, sp->num_signals, SST_PRE))
return status;
pid = fork();
if (pid < 0) {
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;
}
if (pid == 0) {
- if (!undo_signals(signals, num_signals, SST_PRE))
+ if (!undo_signals(sp->signals, sp->num_signals, SST_PRE))
_exit(127);
- if (!do_signals(signals, num_signals, SST_CHILD))
+ if (!do_signals(sp->signals, sp->num_signals, SST_CHILD))
_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);
}
- 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"));
_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;
else {
pid_t n;
@@ -443,171 +685,158 @@
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;
}
#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)++)
-static void parse_argvec(const char **va)
+static void parse_argvec(struct spawn *sp, const char **va)
{
for (;;) {
const char *arg = NEXT_ARG(va, const char *);
const char *var, *val;
- switch ((int)arg) {
- case 0:
- args[num_args++] = NULL;
+ if (!arg) {
+ sp->args[sp->num_args++] = NULL;
break;
- case ((int)SF_REDIRECT_FILE):
- redirects[num_redirects].dst_fd = NEXT_ARG(va, int);
+ }
+ else if (arg == SF_REDIRECT_FILE) {
+ 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++;
- break;
- case ((int)SF_REDIRECT_DESCRIPTOR):
- redirects[num_redirects].dst_fd = NEXT_ARG(va, int);
- redirects[num_redirects].src_fd = NEXT_ARG(va, int);
+ sp->num_redirects++;
+ }
+ else if (arg == SF_REDIRECT_DESCRIPTOR) {
+ 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++;
- break;
- case ((int)SF_CLOSE_DESCRIPTOR):
- redirects[num_redirects].dst_fd = NEXT_ARG(va, int);
+ sp->redirects[sp->num_redirects].file = NULL;
+ sp->num_redirects++;
+ }
+ else if (arg == SF_CLOSE_DESCRIPTOR) {
+ sp->redirects[sp->num_redirects].dst_fd = NEXT_ARG(va, int);
- redirects[num_redirects].src_fd = -1;
- redirects[num_redirects].file = NULL;
- num_redirects++;
- break;
- 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->redirects[sp->num_redirects].src_fd = -1;
+ sp->redirects[sp->num_redirects].file = NULL;
+ sp->num_redirects++;
+ }
+ else if (arg == SF_SIGNAL) {
+ 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++;
- break;
- case ((int)SF_VARIABLE):
+ sp->signals[sp->num_signals].valid = 0;
+ sp->num_signals++;
+ }
+ else if (arg == SF_VARIABLE) {
var = NEXT_ARG(va, const char *);
val = getenv(var);
- args[num_args++] = val ? val : "";
- break;
- case ((int)SF_BINDING):
- bindings[num_bindings].var = NEXT_ARG(va, const char *);
- bindings[num_bindings].val = NEXT_ARG(va, const char *);
+ sp->args[sp->num_args++] = val ? val : "";
+ }
+ else if (arg == SF_BINDING) {
+ sp->bindings[sp->num_bindings].var = NEXT_ARG(va, const char *);
+ sp->bindings[sp->num_bindings].val = NEXT_ARG(va, const char *);
- num_bindings++;
- break;
- case ((int)SF_BACKGROUND):
- background = 1;
- break;
- case ((int)SF_DIRECTORY):
- directory = NEXT_ARG(va, const char *);
+ sp->num_bindings++;
+ }
+ else if (arg == SF_BACKGROUND) {
+ sp->background = 1;
+ }
+ else if (arg == SF_DIRECTORY) {
+ sp->directory = NEXT_ARG(va, const char *);
- break;
- case ((int)SF_ARGVEC):
- parse_argvec(NEXT_ARG(va, const char **));
-
- break;
- default:
- args[num_args++] = arg;
- break;
}
-
- if (!arg)
- break;
+ else if (arg == SF_ARGVEC) {
+ parse_argvec(sp, NEXT_ARG(va, const char **));
+ }
+ else
+ sp->args[sp->num_args++] = arg;
}
}
-static void parse_arglist(va_list va)
+static void parse_arglist(struct spawn *sp, va_list va)
{
for (;;) {
const char *arg = va_arg(va, const char *);
const char *var, *val;
- switch ((int)arg) {
- case 0:
- args[num_args++] = NULL;
+ if (!arg) {
+ sp->args[sp->num_args++] = NULL;
break;
- case ((int)SF_REDIRECT_FILE):
- redirects[num_redirects].dst_fd = va_arg(va, int);
+ }
+ else if (arg == SF_REDIRECT_FILE) {
+ 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++;
- break;
- case ((int)SF_REDIRECT_DESCRIPTOR):
- redirects[num_redirects].dst_fd = va_arg(va, int);
- redirects[num_redirects].src_fd = va_arg(va, int);
+ sp->num_redirects++;
+ }
+ else if (arg == SF_REDIRECT_DESCRIPTOR) {
+ 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++;
- break;
- case ((int)SF_CLOSE_DESCRIPTOR):
- redirects[num_redirects].dst_fd = va_arg(va, int);
+ sp->redirects[sp->num_redirects].file = NULL;
+ sp->num_redirects++;
+ }
+ else if (arg == SF_CLOSE_DESCRIPTOR) {
+ sp->redirects[sp->num_redirects].dst_fd = va_arg(va, int);
- redirects[num_redirects].src_fd = -1;
- redirects[num_redirects].file = NULL;
- num_redirects++;
- break;
- 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->redirects[sp->num_redirects].src_fd = -1;
+ sp->redirects[sp->num_redirects].file = NULL;
+ sp->num_redirects++;
+ }
+ else if (arg == SF_SIGNAL) {
+ 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++;
- break;
- case ((int)SF_VARIABLE):
+ sp->signals[sp->num_signals].valid = 0;
+ sp->num_signals++;
+ }
+ else if (arg == SF_VARIABLE) {
var = va_arg(va, char *);
val = getenv(var);
- args[num_args++] = val ? val : "";
- break;
- case ((int)SF_BINDING):
- bindings[num_bindings].var = va_arg(va, const char *);
- bindings[num_bindings].val = va_arg(va, const char *);
+ sp->args[sp->num_args++] = val ? val : "";
+ }
+ else if (arg == SF_BINDING) {
+ sp->bindings[sp->num_bindings].var = va_arg(va, const char *);
+ sp->bindings[sp->num_bindings].val = va_arg(va, const char *);
- num_bindings++;
- break;
- case ((int)SF_BACKGROUND):
- background = 1;
- break;
- case ((int)SF_DIRECTORY):
- directory = va_arg(va, const char *);
-
- break;
- case ((int)SF_ARGVEC):
- parse_argvec(va_arg(va, const char **));
-
- break;
- default:
- args[num_args++] = arg;
- break;
+ sp->num_bindings++;
}
-
- if (!arg)
- break;
+ else if (arg == SF_BACKGROUND) {
+ sp->background = 1;
+ }
+ else if (arg == SF_DIRECTORY) {
+ sp->directory = va_arg(va, const char *);
+ }
+ else if (arg == SF_ARGVEC) {
+ parse_argvec(sp, va_arg(va, const char **));
+ }
+ else
+ sp->args[sp->num_args++] = arg;
}
}
@@ -623,11 +852,13 @@
*/
int G_vspawn_ex(const char *command, const char **args)
{
- begin_spawn();
+ struct spawn sp;
- parse_argvec(args);
+ begin_spawn(&sp);
- return do_spawn(command);
+ parse_argvec(&sp, args);
+
+ return do_spawn(&sp, command);
}
/**
@@ -642,13 +873,54 @@
int G_spawn_ex(const char *command, ...)
{
+ struct spawn sp;
va_list va;
- begin_spawn();
+ begin_spawn(&sp);
va_start(va, command);
- parse_arglist(va);
+ parse_arglist(&sp, va);
va_end(va);
- return do_spawn(command);
+ return do_spawn(&sp, command);
}
+
+/**
+ * \brief Spawn new process based on <b>command</b>.
+ *
+ * \param[in] command
+ * \return -1 on error
+ * \return process status on success
+ */
+
+int G_spawn(const char *command, ...)
+{
+ const char *args[MAX_ARGS];
+ int num_args = 0, i;
+ va_list va;
+ int status = -1;
+
+ va_start(va, command);
+
+ for (i = 0; ; i++) {
+ const char *arg = va_arg(va, const char *);
+ args[num_args++] = arg;
+ if (!arg)
+ break;
+ }
+
+ va_end(va);
+
+ status = G_spawn_ex(
+ command,
+#ifndef __MINGW32__
+ SF_SIGNAL, SST_PRE, SSA_IGNORE, SIGINT,
+ SF_SIGNAL, SST_PRE, SSA_IGNORE, SIGQUIT,
+ SF_SIGNAL, SST_PRE, SSA_BLOCK, SIGCHLD,
+#endif
+ SF_ARGVEC, args,
+ NULL);
+
+ return status;
+}
+
More information about the grass-commit
mailing list