Add Windows-specific note to the gtk-doc comment.
[platform/upstream/glib.git] / glib / gspawn.c
index e283af6..33960e0 100644 (file)
@@ -20,6 +20,8 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include <config.h>
+
 #include "glib.h"
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/select.h>
 #endif /* HAVE_SYS_SELECT_H */
 
-#ifdef _
-#warning "FIXME remove gettext hack"
-#endif
-
-#define _(x) x
+#include "glibintl.h"
 
 static gint g_execute (const gchar  *file,
                        gchar **argv,
@@ -56,6 +54,7 @@ static gboolean fork_exec_with_pipes (gboolean              intermediate_child,
                                       gboolean              stdout_to_null,
                                       gboolean              stderr_to_null,
                                       gboolean              child_inherits_stdin,
+                                      gboolean              file_and_argv_zero,
                                       GSpawnChildSetupFunc  child_setup,
                                       gpointer              user_data,
                                       gint                 *child_pid,
@@ -75,19 +74,19 @@ g_spawn_error_quark (void)
 
 /**
  * g_spawn_async:
- * @working_directory: child's current working directory, or NULL to inherit parent's
+ * @working_directory: child's current working directory, or %NULL to inherit parent's
  * @argv: child's argument vector
- * @envp: child's environment, or NULL to inherit parent's
+ * @envp: child's environment, or %NULL to inherit parent's
  * @flags: flags from #GSpawnFlags
- * @child_setup: function to run in the child just before exec()
+ * @child_setup: function to run in the child just before <function>exec()</function>
  * @user_data: user data for @child_setup
- * @child_pid: return location for child process ID, or NULL
+ * @child_pid: return location for child process ID, or %NULL
  * @error: return location for error
  * 
  * See g_spawn_async_with_pipes() for a full description; this function
  * simply calls the g_spawn_async_with_pipes() without any pipes.
  * 
- * Return value: TRUE on success, FALSE if error is set
+ * Return value: %TRUE on success, %FALSE if error is set
  **/
 gboolean
 g_spawn_async (const gchar          *working_directory,
@@ -138,8 +137,8 @@ read_data (GString *str,
            gint     fd,
            GError **error)
 {
-  gint bytes;
-  gchar buf[4096];
+  gssize bytes;        
+  gchar buf[4096];    
 
  again:
   
@@ -170,29 +169,30 @@ read_data (GString *str,
 
 /**
  * g_spawn_sync:
- * @working_directory: child's current working directory, or NULL to inherit parent's
+ * @working_directory: child's current working directory, or %NULL to inherit parent's
  * @argv: child's argument vector
- * @envp: child's environment, or NULL to inherit parent's
+ * @envp: child's environment, or %NULL to inherit parent's
  * @flags: flags from #GSpawnFlags
- * @child_setup: function to run in the child just before exec()
+ * @child_setup: function to run in the child just before <function>exec()</function>
  * @user_data: user data for @child_setup
  * @standard_output: return location for child output 
  * @standard_error: return location for child error messages
- * @exit_status: child exit status, as returned by waitpid()
+ * @exit_status: child exit status, as returned by <function>waitpid()</function>
  * @error: return location for error
  *
  * Executes a child synchronously (waits for the child to exit before returning).
  * All output from the child is stored in @standard_output and @standard_error,
- * if those parameters are non-NULL. If @exit_status is non-NULL, the exit status
- * of the child is stored there as it would be by waitpid(); standard UNIX
- * macros such as WIFEXITED() and WEXITSTATUS() must be used to evaluate the
- * exit status. If an error occurs, no data is returned in @standard_output,
- * @standard_error, or @exit_status.
+ * if those parameters are non-%NULL. If @exit_status is non-%NULL, the exit 
+ * status of the child is stored there as it would be returned by 
+ * <function>waitpid()</function>; standard UNIX macros such as 
+ * <function>WIFEXITED()</function> and <function>WEXITSTATUS()</function> 
+ * must be used to evaluate the exit status. If an error occurs, no data is 
+ * returned in @standard_output, @standard_error, or @exit_status.
  * 
  * This function calls g_spawn_async_with_pipes() internally; see that function
  * for full details on the other parameters.
  * 
- * Return value: TRUE on success, FALSE if an error was set.
+ * Return value: %TRUE on success, %FALSE if an error was set.
  **/
 gboolean
 g_spawn_sync (const gchar          *working_directory,
@@ -241,6 +241,7 @@ g_spawn_sync (const gchar          *working_directory,
                              (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
                              (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
                              (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
+                             (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
                              child_setup,
                              user_data,
                              &pid,
@@ -404,69 +405,78 @@ g_spawn_sync (const gchar          *working_directory,
 
 /**
  * g_spawn_async_with_pipes:
- * @working_directory: child's current working directory, or NULL to inherit parent's
+ * @working_directory: child's current working directory, or %NULL to inherit parent's
  * @argv: child's argument vector
- * @envp: child's environment, or NULL to inherit parent's
+ * @envp: child's environment, or %NULL to inherit parent's
  * @flags: flags from #GSpawnFlags
- * @child_setup: function to run in the child just before exec()
+ * @child_setup: function to run in the child just before <function>exec()</function>
  * @user_data: user data for @child_setup
- * @child_pid: return location for child process ID, or NULL
- * @standard_input: return location for file descriptor to write to child's stdin, or NULL
- * @standard_output: return location for file descriptor to read child's stdout, or NULL
- * @standard_error: return location for file descriptor to read child's stderr, or NULL
+ * @child_pid: return location for child process ID, or %NULL
+ * @standard_input: return location for file descriptor to write to child's stdin, or %NULL
+ * @standard_output: return location for file descriptor to read child's stdout, or %NULL
+ * @standard_error: return location for file descriptor to read child's stderr, or %NULL
  * @error: return location for error
  *
  * Executes a child program asynchronously (your program will not
  * block waiting for the child to exit). The child program is
  * specified by the only argument that must be provided, @argv. @argv
- * should be a NULL-terminated array of strings, to be passed as the
+ * should be a %NULL-terminated array of strings, to be passed as the
  * argument vector for the child. The first string in @argv is of
  * course the name of the program to execute. By default, the name of
- * the program must be a full path; the PATH shell variable will only
- * be searched if you pass the %G_SPAWN_SEARCH_PATH flag.
+ * the program must be a full path; the <envar>PATH</envar> shell variable 
+ * will only be searched if you pass the %G_SPAWN_SEARCH_PATH flag.
  *
- * @envp is a NULL-terminated array of strings, where each string
+ * @envp is a %NULL-terminated array of strings, where each string
  * has the form <literal>KEY=VALUE</literal>. This will become
- * the child's environment. If @envp is NULL, the child inherits its
+ * the child's environment. If @envp is %NULL, the child inherits its
  * parent's environment.
  *
  * @flags should be the bitwise OR of any flags you want to affect the
  * function's behavior. The %G_SPAWN_DO_NOT_REAP_CHILD means that the
- * child will not be automatically reaped; you must call waitpid() or
- * handle SIGCHLD yourself, or the child will become a zombie.
+ * child will not be automatically reaped; you must call 
+ * <function>waitpid()</function> or handle %SIGCHLD yourself, or the 
+ * child will become a zombie.
  * %G_SPAWN_LEAVE_DESCRIPTORS_OPEN means that the parent's open file
  * descriptors will be inherited by the child; otherwise all
  * descriptors except stdin/stdout/stderr will be closed before
- * calling exec() in the child. %G_SPAWN_SEARCH_PATH means that
- * <literal>argv[0]</literal> need not be an absolute path, it
- * will be looked for in the user's PATH. %G_SPAWN_STDOUT_TO_DEV_NULL
- * means that the child's standad output will be discarded, instead
- * of going to the same location as the parent's standard output.
+ * calling <function>exec()</function> in the child. %G_SPAWN_SEARCH_PATH 
+ * means that <literal>argv[0]</literal> need not be an absolute path, it
+ * will be looked for in the user's <envar>PATH</envar>. 
+ * %G_SPAWN_STDOUT_TO_DEV_NULL means that the child's standad output will 
+ * be discarded, instead of going to the same location as the parent's 
+ * standard output.
  * %G_SPAWN_STDERR_TO_DEV_NULL means that the child's standard error
  * will be discarded. %G_SPAWN_CHILD_INHERITS_STDIN means that
  * the child will inherit the parent's standard input (by default,
  * the child's standard input is attached to /dev/null).
+ * %G_SPAWN_FILE_AND_ARGV_ZERO means that the first element of @argv is
+ * the file to execute, while the remaining elements are the
+ * actual argument vector to pass to the file. Normally
+ * g_spawn_async_with_pipes() uses @argv[0] as the file to execute, and
+ * passes all of @argv to the child.
  *
  * @child_setup and @user_data are a function and user data to be
  * called in the child after GLib has performed all the setup it plans
  * to perform (including creating pipes, closing file descriptors,
- * etc.) but before calling exec(). That is, @child_setup is called
- * just before calling exec() in the child. Obviously actions taken in
- * this function will only affect the child, not the parent. 
+ * etc.) but before calling <function>exec()</function>. That is, 
+ * @child_setup is called just before calling <function>exec()</function> 
+ * in the child. Obviously actions taken in this function will only affect 
+ * the child, not the parent. 
  *
- * If non-NULL, @child_pid will be filled with the child's process
+ * If non-%NULL, @child_pid will be filled with the child's process
  * ID. You can use the process ID to send signals to the child, or
- * to waitpid() if you specified the %G_SPAWN_DO_NOT_REAP_CHILD flag.
+ * to <function>waitpid()</function> if you specified the 
+ * %G_SPAWN_DO_NOT_REAP_CHILD flag.
  *
- * If non-NULL, the @standard_input, @standard_output, @standard_error
+ * If non-%NULL, the @standard_input, @standard_output, @standard_error
  * locations will be filled with file descriptors for writing to the child's
  * standard input or reading from its standard output or standard error.
  * The caller of g_spawn_async_with_pipes() must close these file descriptors
- * when they are no longer in use. If these parameters are NULL, the
+ * when they are no longer in use. If these parameters are %NULL, the
  * corresponding pipe won't be created.
  *
- * @error can be NULL to ignore errors, or non-NULL to report errors.
- * If an error is set, the function returns FALSE. Errors
+ * @error can be %NULL to ignore errors, or non-%NULL to report errors.
+ * If an error is set, the function returns %FALSE. Errors
  * are reported even if they occur in the child (for example if the
  * executable in <literal>argv[0]</literal> is not found). Typically
  * the <literal>message</literal> field of returned errors should be displayed
@@ -475,7 +485,7 @@ g_spawn_sync (const gchar          *working_directory,
  * If an error occurs, @child_pid, @standard_input, @standard_output,
  * and @standard_error will not be filled with valid values.
  * 
- * Return value: TRUE on success, FALSE if an error was set
+ * Return value: %TRUE on success, %FALSE if an error was set
  **/
 gboolean
 g_spawn_async_with_pipes (const gchar          *working_directory,
@@ -508,6 +518,7 @@ g_spawn_async_with_pipes (const gchar          *working_directory,
                                (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
                                (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
                                (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
+                               (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
                                child_setup,
                                user_data,
                                child_pid,
@@ -534,7 +545,15 @@ g_spawn_async_with_pipes (const gchar          *working_directory,
  * appropriate. Possible errors are those from g_spawn_sync() and those
  * from g_shell_parse_argv().
  * 
- * Return value: TRUE on success, FALSE if an error was set
+ * On Windows, please note the implications of g_shell_parse_argv()
+ * parsing @command_line. Space is a separator, and backslashes are
+ * special. Thus you cannot simply pass a @command_line consisting of
+ * a canonical Windows path, like "c:\\program files\\app\\app.exe",
+ * as the backslashes will be eaten, and the space will act as a
+ * separator. You need to enclose the path with single quotes, like
+ * "'c:\\program files\\app\\app.exe'".
+ *
+ * Return value: %TRUE on success, %FALSE if an error was set
  **/
 gboolean
 g_spawn_command_line_sync (const gchar  *command_line,
@@ -581,7 +600,9 @@ g_spawn_command_line_sync (const gchar  *command_line,
  * consider using g_spawn_async() directly if appropriate. Possible
  * errors are those from g_shell_parse_argv() and g_spawn_async().
  * 
- * Return value: TRUE on success, FALSE if error is set.
+ * The same concerns on Windows apply as for g_spawn_command_line_sync().
+ *
+ * Return value: %TRUE on success, %FALSE if error is set.
  **/
 gboolean
 g_spawn_command_line_async (const gchar *command_line,
@@ -768,6 +789,7 @@ do_exec (gint                  child_err_report_fd,
          gboolean              stdout_to_null,
          gboolean              stderr_to_null,
          gboolean              child_inherits_stdin,
+         gboolean              file_and_argv_zero,
          GSpawnChildSetupFunc  child_setup,
          gpointer              user_data)
 {
@@ -858,7 +880,9 @@ do_exec (gint                  child_err_report_fd,
       (* child_setup) (user_data);
     }
 
-  g_execute (argv[0], argv, envp, search_path);
+  g_execute (argv[0],
+             file_and_argv_zero ? argv + 1 : argv,
+             envp, search_path);
 
   /* Exec failed */
   write_err_and_exit (child_err_report_fd,
@@ -868,15 +892,15 @@ do_exec (gint                  child_err_report_fd,
 static gboolean
 read_ints (int      fd,
            gint*    buf,
-           gint     n_ints_in_buf,
-           gint    *n_ints_read,
+           gint     n_ints_in_buf,    
+           gint    *n_ints_read,      
            GError **error)
 {
-  gint bytes = 0;
+  gsize bytes = 0;    
   
   while (TRUE)
     {
-      gint chunk;
+      gssize chunk;    
 
       if (bytes >= sizeof(gint)*2)
         break; /* give up, who knows what happened, should not be
@@ -886,7 +910,7 @@ read_ints (int      fd,
     again:
       chunk = read (fd,
                     ((gchar*)buf) + bytes,
-                    sizeof(gint)*n_ints_in_buf - bytes);
+                    sizeof(gint) * n_ints_in_buf - bytes);
       if (chunk < 0 && errno == EINTR)
         goto again;
           
@@ -904,15 +928,11 @@ read_ints (int      fd,
         }
       else if (chunk == 0)
         break; /* EOF */
-      else
-        {
-          g_assert (chunk > 0);
-              
-          bytes += chunk;
-        }
+      else /* chunk > 0 */
+       bytes += chunk;
     }
 
-  *n_ints_read = bytes/4;
+  *n_ints_read = (gint)(bytes / sizeof(gint));
 
   return TRUE;
 }
@@ -927,6 +947,7 @@ fork_exec_with_pipes (gboolean              intermediate_child,
                       gboolean              stdout_to_null,
                       gboolean              stderr_to_null,
                       gboolean              child_inherits_stdin,
+                      gboolean              file_and_argv_zero,
                       GSpawnChildSetupFunc  child_setup,
                       gpointer              user_data,
                       gint                 *child_pid,
@@ -1025,6 +1046,7 @@ fork_exec_with_pipes (gboolean              intermediate_child,
                        stdout_to_null,
                        stderr_to_null,
                        child_inherits_stdin,
+                       file_and_argv_zero,
                        child_setup,
                        user_data);
             }
@@ -1053,6 +1075,7 @@ fork_exec_with_pipes (gboolean              intermediate_child,
                    stdout_to_null,
                    stderr_to_null,
                    child_inherits_stdin,
+                   file_and_argv_zero,
                    child_setup,
                    user_data);
         }
@@ -1062,7 +1085,7 @@ fork_exec_with_pipes (gboolean              intermediate_child,
       /* Parent */
       
       gint buf[2];
-      gint n_ints = 0;
+      gint n_ints = 0;    
 
       /* Close the uncared-about ends of the pipes */
       close_and_invalidate (&child_err_report_pipe[1]);
@@ -1082,7 +1105,8 @@ fork_exec_with_pipes (gboolean              intermediate_child,
               else if (errno == ECHILD)
                 ; /* do nothing, child already reaped */
               else
-                g_warning ("waitpid() should not fail in %s", __FUNCTION__);
+                g_warning ("waitpid() should not fail in "
+                          "'fork_exec_with_pipes'");
             }
         }
       
@@ -1112,7 +1136,8 @@ fork_exec_with_pipes (gboolean              intermediate_child,
               g_set_error (error,
                            G_SPAWN_ERROR,
                            exec_err_to_g_error (buf[1]),
-                           _("Failed to execute child process (%s)"),
+                           _("Failed to execute child process \"%s\" (%s)"),
+                           argv[0],
                            g_strerror (buf[1]));
 
               break;
@@ -1138,7 +1163,8 @@ fork_exec_with_pipes (gboolean              intermediate_child,
               g_set_error (error,
                            G_SPAWN_ERROR,
                            G_SPAWN_ERROR_FAILED,
-                           _("Unknown error executing child process"));
+                           _("Unknown error executing child process \"%s\""),
+                           argv[0]);
               break;
             }
 
@@ -1234,13 +1260,13 @@ script_execute (const gchar *file,
   {
     gchar **new_argv;
 
-    new_argv = g_new0 (gchar*, argc + 1);
+    new_argv = g_new0 (gchar*, argc + 2); /* /bin/sh and NULL */
     
     new_argv[0] = (char *) "/bin/sh";
     new_argv[1] = (char *) file;
-    while (argc > 1)
+    while (argc > 0)
       {
-       new_argv[argc] = argv[argc - 1];
+       new_argv[argc + 1] = argv[argc];
        --argc;
       }
 
@@ -1291,7 +1317,8 @@ g_execute (const gchar *file,
   else
     {
       gboolean got_eacces = 0;
-      char *path, *p, *name, *freeme;
+      const gchar *path, *p;
+      gchar *name, *freeme;
       size_t len;
       size_t pathlen;