[GRASS-SVN] r40453 - in grass/trunk: include lib/gis

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Jan 14 19:49:23 EST 2010


Author: glynn
Date: 2010-01-14 19:49:22 -0500 (Thu, 14 Jan 2010)
New Revision: 40453

Modified:
   grass/trunk/include/spawn.h
   grass/trunk/lib/gis/spawn.c
Log:
G_spawn* updates:
 Use shell on Windows
 Eliminate spawnv*-based implementations
 Implement G_spawn() atop G_spawn_ex()
 Add SF_ARGLIST


Modified: grass/trunk/include/spawn.h
===================================================================
--- grass/trunk/include/spawn.h	2010-01-14 22:01:18 UTC (rev 40452)
+++ grass/trunk/include/spawn.h	2010-01-15 00:49:22 UTC (rev 40453)
@@ -23,6 +23,7 @@
 #define SF_BACKGROUND			((const char *) 7)
 #define SF_DIRECTORY			((const char *) 8)
 #define SF_ARGVEC			((const char *) 9)
+#define SF_ARGLIST			((const char *) 10)
 
 enum signal_action
 {
@@ -41,7 +42,7 @@
 };
 
 extern int G_spawn(const char *command, ...);
+extern int G_vspawn_ex(const char *command, const char **args);
 extern int G_spawn_ex(const char *command, ...);
-extern int G_vspawn_ex(const char *command, const char **args);
 
 #endif

Modified: grass/trunk/lib/gis/spawn.c
===================================================================
--- grass/trunk/lib/gis/spawn.c	2010-01-14 22:01:18 UTC (rev 40452)
+++ grass/trunk/lib/gis/spawn.c	2010-01-15 00:49:22 UTC (rev 40453)
@@ -24,17 +24,11 @@
 #include <errno.h>
 #include <sys/types.h>
 
-#define USE_CREATE_PROCESS 1
-
 #ifndef __MINGW32__
 #include <sys/wait.h>
 #else
-#ifdef USE_CREATE_PROCESS
 #include <windows.h>
-#else
-typedef void *HANDLE;
 #endif
-#endif
 #include <grass/config.h>
 #include <grass/gis.h>
 #include <grass/glocale.h>
@@ -64,12 +58,6 @@
  * \return process status on success
  */
 
-#ifdef __MINGW32__
-
-#else
-
-#endif /*__MINGW32__*/
-
 struct redirect
 {
     int dst_fd;
@@ -110,10 +98,11 @@
     const char *directory;
 };
 
+static void parse_arglist(struct spawn *sp, va_list va);
+static void parse_argvec(struct spawn *sp, const char **va);
+
 #ifdef __MINGW32__
 
-#ifdef USE_CREATE_PROCESS
-
 struct buffer {
     char *str;
     size_t len;
@@ -225,51 +214,6 @@
     finish(&buf);
 }
 
-static const char *escaped(const char *arg)
-{
-    struct buffer result;
-
-    if (!arg)
-	return NULL;
-
-    init(&result);
-    escape_arg(&result, arg);
-    return release(&result);
-}
-
-static char *make_command_line(const char **argv)
-{
-    struct buffer result;
-    int i;
-
-    init(&result);
-
-    for (i = 0; argv[i]; i++) {
-	if (result.len > 0)
-	    append_char(&result, ' ');
-	escape_arg(&result, argv[i]);
-    }
-
-    return release(&result);
-}
-
-static char *make_environment(const char **envp)
-{
-    struct buffer result;
-    int i;
-
-    init(&result);
-
-    for (i = 0; envp[i]; i++) {
-	const char *env = envp[i];
-
-	append(&result, env);
-	append_char(&result, '\0');
-    }
-
-    return release(&result);
-}
-
 static char *check_program(const char *pgm, const char *dir, const char *ext)
 {
     char pathname[GPATH_MAX];
@@ -330,6 +274,46 @@
     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);
+    }
+
+    for (i = shell ? 1 : 0; argv[i]; i++) {
+	if (result.len > 0)
+	    append_char(&result, ' ');
+	escape_arg(&result, argv[i]);
+    }
+
+    return release(&result);
+}
+
+static char *make_environment(const char **envp)
+{
+    struct buffer result;
+    int i;
+
+    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)
 {
     HANDLE h1, h2;
@@ -347,25 +331,29 @@
 }
 
 static int win_spawn(const char *cmd, const char **argv, const char **envp,
-		     const char *cwd, HANDLE handles[3], int background)
+		     const char *cwd, HANDLE handles[3], int background,
+		     int shell)
 {
-    char *args = make_command_line(argv);
+    char *args = make_command_line(shell, cmd, argv);
     char *env = make_environment(envp);
-    char *program = find_program(cmd);
+    char *program = shell ? NULL : find_program(cmd);
     STARTUPINFO si;
     PROCESS_INFORMATION pi;
     BOOL result;
     DWORD exitcode;
 
-    G_debug(3, "win_spawn: program = %s", program);
-    G_debug(3, "win_spawn: args = %s", args);
+    if (!shell) {
+	G_debug(3, "win_spawn: program = %s", program);
 
-    if (!program) {
-	G_free(args);
-	G_free(env);
-	return -1;
+	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);
 
@@ -442,17 +430,6 @@
     }
 }
 
-#else
-
-static void do_redirects(struct redirect *redirects, int num_redirects, HANDLE handles[3])
-{
-    if (num_redirects > 0)
-	G_fatal_error
-	    ("G_spawn_ex: redirection not (yet) supported on Windows");
-}
-
-#endif
-
 static void add_binding(const char **env, int *pnum, const struct binding *b)
 {
     char *str = G_malloc(strlen(b->var) + strlen(b->val) + 2);
@@ -500,11 +477,7 @@
     do_redirects(sp->redirects, sp->num_redirects, handles);
     env = do_bindings(sp->bindings, sp->num_bindings);
 
-#ifdef USE_CREATE_PROCESS
-    status = win_spawn(command, sp->args, env, sp->directory, handles, sp->background);
-#else
-    status = spawnvpe(sp->background ? _P_NOWAIT : _P_WAIT, command, sp->args, env);
-#endif
+    status = win_spawn(command, sp->args, env, sp->directory, handles, sp->background, 1);
 
     if (!sp->background && status < 0)
 	G_warning(_("Unable to execute command"));
@@ -512,46 +485,6 @@
     return status;
 }
 
-int G_spawn(const char *command, ...)
-{
-    va_list va;
-    char *program = find_program(command);
-    const char *args[MAX_ARGS];
-    int num_args = 0;
-    int result, i;
-
-    va_start(va, command);
-
-    for (num_args = 0; num_args < MAX_ARGS;) {
-	const char *arg = va_arg(va, const char *);
-
-	args[num_args++] = escaped(arg);
-	if (!arg)
-	    break;
-	G_debug(3, "argv[%d]='%s'", num_args-1, args[num_args-1]);
-    }
-
-    va_end(va);
-
-    if (num_args >= MAX_ARGS) {
-	G_warning(_("Too many arguments"));
-	result = -1;
-    }
-    else {
-	G_debug(3, "spawning '%s' ...", program);
-	result = _spawnvp(_P_WAIT, program, args);
-	G_debug(3, "result = %d", result);
-	if (result < 0)
-	    G_debug(3, "error: %s", strerror(errno));
-    }
-
-    G_free(program);
-    for (i = 0; i < num_args; i++)
-	G_free((char *) args[i]);
-
-    return result;
-}
-
 #else /* __MINGW32__ */
 
 static int undo_signals(const struct signal *signals, int num_signals, int which)
@@ -758,85 +691,6 @@
     return status;
 }
 
-int G_spawn(const char *command, ...)
-{
-    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;
-
-    va_start(va, command);
-
-    for (num_args = 0; num_args < MAX_ARGS;) {
-	char *arg = va_arg(va, char *);
-
-	args[num_args++] = arg;
-	if (!arg)
-	    break;
-    }
-
-    va_end(va);
-
-    if (num_args >= MAX_ARGS) {
-	G_warning(_("Too many arguments"));
-	return -1;
-    }
-
-    sigemptyset(&act.sa_mask);
-    act.sa_flags = SA_RESTART;
-
-    act.sa_handler = SIG_IGN;
-    if (sigaction(SIGINT, &act, &intr) < 0)
-	goto error_1;
-    if (sigaction(SIGQUIT, &act, &quit) < 0)
-	goto error_2;
-
-    sigemptyset(&block);
-    sigaddset(&block, SIGCHLD);
-    if (sigprocmask(SIG_BLOCK, &block, &oldmask) < 0)
-	goto error_3;
-
-    G_debug(3, "forking '%s' ...", command);
-
-    pid = fork();
-
-    if (pid < 0) {
-	G_warning(_("Unable to create a new process"));
-	goto error_4;
-    }
-
-    if (pid == 0) {
-	sigaction(SIGINT, &intr, NULL);
-	sigaction(SIGQUIT, &quit, NULL);
-
-	execvp(command, args);
-	G_warning(_("Unable to execute command"));
-	_exit(127);
-    }
-    else {
-	pid_t n;
-
-	do
-	    n = waitpid(pid, &status, 0);
-	while (n == (pid_t) - 1 && errno == EINTR);
-
-	if (n != pid)
-	    status = -1;
-    }
-
-  error_4:
-    sigprocmask(SIG_SETMASK, &oldmask, NULL);
-  error_3:
-    sigaction(SIGQUIT, &quit, NULL);
-  error_2:
-    sigaction(SIGINT, &intr, NULL);
-  error_1:
-    return status;
-}
-
 #endif /* __MINGW32__ */
 
 static void begin_spawn(struct spawn *sp)
@@ -914,6 +768,9 @@
 	else if (arg == SF_ARGVEC) {
 	    parse_argvec(sp, NEXT_ARG(va, const char **));
 	}
+	else if (arg == SF_ARGLIST) {
+	    parse_arglist(sp, NEXT_ARG(va, va_list));
+	}
 	else
 	    sp->args[sp->num_args++] = arg;
     }
@@ -981,6 +838,9 @@
 	else if (arg == SF_ARGVEC) {
 	    parse_argvec(sp, va_arg(va, const char **));
 	}
+	else if (arg == SF_ARGLIST) {
+	    parse_arglist(sp, va_arg(va, va_list));
+	}
 	else
 	    sp->args[sp->num_args++] = arg;
     }
@@ -1031,3 +891,33 @@
     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, ...)
+{
+    va_list va;
+    int status = -1;
+
+    va_start(va, command);
+
+    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_ARGLIST, va,
+	NULL);
+
+    va_end(va);
+
+    return status;
+}
+



More information about the grass-commit mailing list