[kdbus] Add SipHash algorithm
[platform/upstream/glib.git] / glib / gspawn-win32-helper.c
index 7896941..76191f9 100644 (file)
 
 /* For _CrtSetReportMode, we don't want Windows CRT (2005 and later)
  * to terminate the process if a bad file descriptor is passed into
- * _get_osfhandle.  The newer MS CRT's are picky
- * on double close()'s and bad file descriptors.
+ * _get_osfhandle().  This is necessary because we use _get_osfhandle()
+ * to check the validity of the fd before we try to call close() on
+ * it as attempting to close an invalid fd will cause the Windows CRT
+ * to abort() this program internally.
+ *
+ * Please see http://msdn.microsoft.com/zh-tw/library/ks2530z6%28v=vs.80%29.aspx
+ * for an explanation on this.
  */
 #if (defined (_MSC_VER) && _MSC_VER >= 1400)
 #include <crtdbg.h>
@@ -59,8 +64,7 @@ write_err_and_exit (gint    fd,
 /* We build gspawn-win32-helper.exe as a Windows GUI application
  * to avoid any temporarily flashing console windows in case
  * the gspawn function is invoked by a GUI program. Thus, no main()
- * but a WinMain(). We do, however, still use argc and argv tucked
- * away in the global __argc and __argv by the C runtime startup code.
+ * but a WinMain().
  */
 
 /* Info peeked from mingw runtime's source code. __wgetmainargs() is a
@@ -161,13 +165,15 @@ protect_wargv (wchar_t  **wargv,
  * This is the (empty) invalid parameter handler
  * that is used for Visual C++ 2005 (and later) builds
  * so that we can use this instead of the system automatically
- * aborting the process, as the newer MS CRTs are more picky
- * about double close()'s and bad/invalid file descriptors.
+ * aborting the process.
  *
  * This is necessary as we use _get_oshandle() to check the validity
  * of the file descriptors as we close them, so when an invalid file
  * descriptor is passed into that function as we check on it, we get
  * -1 as the result, instead of the gspawn helper program aborting.
+ *
+ * Please see http://msdn.microsoft.com/zh-tw/library/ks2530z6%28v=vs.80%29.aspx
+ * for an explanation on this.
  */
 void myInvalidParameterHandler(
    const wchar_t * expression,
@@ -204,14 +210,11 @@ main (int ignored_argc, char **ignored_argv)
   gint argv_zero_offset = ARG_PROGRAM;
   wchar_t **new_wargv;
   int argc;
+  char **argv;
   wchar_t **wargv, **wenvp;
   _startupinfo si = { 0 };
   char c;
 
-  /* store up the file descriptors to close */
-  GSList *fd_toclose = NULL;
-  GSList *last_item = NULL;
-
 #if (defined (_MSC_VER) && _MSC_VER >= 1400)
   /* set up our empty invalid parameter handler */
   _invalid_parameter_handler oldHandler, newHandler;
@@ -222,28 +225,27 @@ main (int ignored_argc, char **ignored_argv)
   _CrtSetReportMode(_CRT_ASSERT, 0);
 #endif
 
-
-  g_assert (__argc >= ARG_COUNT);
-
   /* Fetch the wide-char argument vector */
   __wgetmainargs (&argc, &wargv, &wenvp, 0, &si);
 
-  /* We still have the system codepage args in __argv. We can look
-   * at the first args in which gspawn-win32.c passes us flags and
-   * fd numbers in __argv, as we know those are just ASCII anyway.
-   */
-  g_assert (argc == __argc);
+  g_assert (argc >= ARG_COUNT);
+
+  /* Convert unicode wargs to utf8 */
+  argv = g_new(char *, argc + 1);
+  for (i = 0; i < argc; i++)
+    argv[i] = g_utf16_to_utf8(wargv[i], -1, NULL, NULL, NULL);
+  argv[i] = NULL;
 
   /* argv[ARG_CHILD_ERR_REPORT] is the file descriptor number onto
    * which write error messages.
    */
-  child_err_report_fd = atoi (__argv[ARG_CHILD_ERR_REPORT]);
+  child_err_report_fd = atoi (argv[ARG_CHILD_ERR_REPORT]);
 
   /* Hack to implement G_SPAWN_FILE_AND_ARGV_ZERO. If
    * argv[ARG_CHILD_ERR_REPORT] is suffixed with a '#' it means we get
    * the program to run and its argv[0] separately.
    */
-  if (__argv[ARG_CHILD_ERR_REPORT][strlen (__argv[ARG_CHILD_ERR_REPORT]) - 1] == '#')
+  if (argv[ARG_CHILD_ERR_REPORT][strlen (argv[ARG_CHILD_ERR_REPORT]) - 1] == '#')
     argv_zero_offset++;
 
   /* argv[ARG_HELPER_SYNC] is the file descriptor number we read a
@@ -252,107 +254,93 @@ main (int ignored_argc, char **ignored_argv)
    * duplicate the process handle we sent it. Duplicating a handle
    * from another process works only if that other process exists.
    */
-  helper_sync_fd = atoi (__argv[ARG_HELPER_SYNC]);
+  helper_sync_fd = atoi (argv[ARG_HELPER_SYNC]);
 
   /* argv[ARG_STDIN..ARG_STDERR] are the file descriptor numbers that
    * should be dup2'd to 0, 1 and 2. '-' if the corresponding fd
    * should be left alone, and 'z' if it should be connected to the
    * bit bucket NUL:.
    */
-  if (__argv[ARG_STDIN][0] == '-')
+  if (argv[ARG_STDIN][0] == '-')
     ; /* Nothing */
-  else if (__argv[ARG_STDIN][0] == 'z')
+  else if (argv[ARG_STDIN][0] == 'z')
     {
       fd = open ("NUL:", O_RDONLY);
       if (fd != 0)
        {
          dup2 (fd, 0);
-         fd_toclose = g_slist_append (fd_toclose, GINT_TO_POINTER (fd));
+         close (fd);
        }
     }
   else
     {
-      fd = atoi (__argv[ARG_STDIN]);
+      fd = atoi (argv[ARG_STDIN]);
       if (fd != 0)
        {
          dup2 (fd, 0);
-         fd_toclose = g_slist_append (fd_toclose, GINT_TO_POINTER (fd));
+         close (fd);
        }
     }
 
-  if (__argv[ARG_STDOUT][0] == '-')
+  if (argv[ARG_STDOUT][0] == '-')
     ; /* Nothing */
-  else if (__argv[ARG_STDOUT][0] == 'z')
+  else if (argv[ARG_STDOUT][0] == 'z')
     {
       fd = open ("NUL:", O_WRONLY);
       if (fd != 1)
        {
          dup2 (fd, 1);
-         fd_toclose = g_slist_append (fd_toclose, GINT_TO_POINTER (fd));
+         close (fd);
        }
     }
   else
     {
-      fd = atoi (__argv[ARG_STDOUT]);
+      fd = atoi (argv[ARG_STDOUT]);
       if (fd != 1)
        {
          dup2 (fd, 1);
-         fd_toclose = g_slist_append (fd_toclose, GINT_TO_POINTER (fd));
+         close (fd);
        }
     }
 
-  if (__argv[ARG_STDERR][0] == '-')
+  if (argv[ARG_STDERR][0] == '-')
     ; /* Nothing */
-  else if (__argv[ARG_STDERR][0] == 'z')
+  else if (argv[ARG_STDERR][0] == 'z')
     {
       fd = open ("NUL:", O_WRONLY);
       if (fd != 2)
        {
          dup2 (fd, 2);
-         fd_toclose = g_slist_append (fd_toclose, GINT_TO_POINTER (fd));
+         close (fd);
        }
     }
   else
     {
-      fd = atoi (__argv[ARG_STDERR]);
+      fd = atoi (argv[ARG_STDERR]);
       if (fd != 2)
        {
          dup2 (fd, 2);
-         fd_toclose = g_slist_append (fd_toclose, GINT_TO_POINTER (fd));
+         close (fd);
        }
     }
 
-  /* __argv[ARG_WORKING_DIRECTORY] is the directory in which to run the
+  /* argv[ARG_WORKING_DIRECTORY] is the directory in which to run the
    * process.  If "-", don't change directory.
    */
-  if (__argv[ARG_WORKING_DIRECTORY][0] == '-' &&
-      __argv[ARG_WORKING_DIRECTORY][1] == 0)
+  if (argv[ARG_WORKING_DIRECTORY][0] == '-' &&
+      argv[ARG_WORKING_DIRECTORY][1] == 0)
     ; /* Nothing */
   else if (_wchdir (wargv[ARG_WORKING_DIRECTORY]) < 0)
     write_err_and_exit (child_err_report_fd, CHILD_CHDIR_FAILED);
 
-  /* __argv[ARG_CLOSE_DESCRIPTORS] is "y" if file descriptors from 3
+  /* argv[ARG_CLOSE_DESCRIPTORS] is "y" if file descriptors from 3
    *  upwards should be closed
    */
-  if (__argv[ARG_CLOSE_DESCRIPTORS][0] == 'y')
+  if (argv[ARG_CLOSE_DESCRIPTORS][0] == 'y')
     for (i = 3; i < 1000; i++) /* FIXME real limit? */
       if (i != child_err_report_fd && i != helper_sync_fd)
         if (_get_osfhandle (i) != -1)
-          fd_toclose = g_slist_append (fd_toclose, GINT_TO_POINTER (i));
-
-  /* ...so we won't get the nasty off-by-1 file descriptor leak */
-  fd_toclose = g_slist_append (fd_toclose, NULL);
-  last_item = g_slist_last (fd_toclose);
-
-  /* now close all the file descriptors as necessary */
-  if (fd_toclose != NULL && last_item != NULL)
-  {
-    for ( ; fd_toclose != last_item; fd_toclose = fd_toclose->next)
-      close (GPOINTER_TO_INT(fd_toclose->data));
-  }
-  g_slist_free (last_item);
-  g_slist_free (fd_toclose);
-
+          close (i);
 
   /* We don't want our child to inherit the error report and
    * helper sync fds.
@@ -360,16 +348,16 @@ main (int ignored_argc, char **ignored_argv)
   child_err_report_fd = dup_noninherited (child_err_report_fd, _O_WRONLY);
   helper_sync_fd = dup_noninherited (helper_sync_fd, _O_RDONLY);
 
-  /* __argv[ARG_WAIT] is "w" to wait for the program to exit */
-  if (__argv[ARG_WAIT][0] == 'w')
+  /* argv[ARG_WAIT] is "w" to wait for the program to exit */
+  if (argv[ARG_WAIT][0] == 'w')
     mode = P_WAIT;
   else
     mode = P_NOWAIT;
 
-  /* __argv[ARG_USE_PATH] is "y" to use PATH, otherwise not */
+  /* argv[ARG_USE_PATH] is "y" to use PATH, otherwise not */
 
-  /* __argv[ARG_PROGRAM] is executable file to run,
-   * __argv[argv_zero_offset]... is its argv. argv_zero_offset equals
+  /* argv[ARG_PROGRAM] is executable file to run,
+   * argv[argv_zero_offset]... is its argv. argv_zero_offset equals
    * ARG_PROGRAM unless G_SPAWN_FILE_AND_ARGV_ZERO was used, in which
    * case we have a separate executable name and argv[0].
    */
@@ -379,7 +367,7 @@ main (int ignored_argc, char **ignored_argv)
    */
   protect_wargv (wargv + argv_zero_offset, &new_wargv);
 
-  if (__argv[ARG_USE_PATH][0] == 'y')
+  if (argv[ARG_USE_PATH][0] == 'y')
     handle = _wspawnvp (mode, wargv[ARG_PROGRAM], (const wchar_t **) new_wargv);
   else
     handle = _wspawnv (mode, wargv[ARG_PROGRAM], (const wchar_t **) new_wargv);
@@ -394,5 +382,7 @@ main (int ignored_argc, char **ignored_argv)
 
   read (helper_sync_fd, &c, 1);
 
+  g_strfreev (argv);
+
   return 0;
 }