Add Windows-specific note to the gtk-doc comment.
[platform/upstream/glib.git] / glib / gspawn.c
index fd40617..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>
@@ -72,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,
@@ -135,8 +137,8 @@ read_data (GString *str,
            gint     fd,
            GError **error)
 {
-  gint bytes;
-  gchar buf[4096];
+  gssize bytes;        
+  gchar buf[4096];    
 
  again:
   
@@ -167,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,
@@ -402,44 +405,46 @@ 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,
@@ -453,23 +458,25 @@ g_spawn_sync (const gchar          *working_directory,
  * @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
@@ -478,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,
@@ -538,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,
@@ -585,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,
@@ -875,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
@@ -893,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;
           
@@ -911,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;
 }
@@ -1072,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]);
@@ -1123,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;
@@ -1149,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;
             }
 
@@ -1245,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;
       }