glib/libglib/src/gspawn-symbian.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* gspawn-spawn.c - Process launching on Symbian
       
     2  *
       
     3  *  Copyright 2000 Red Hat, Inc.
       
     4  *  Copyright 2003 Tor Lillqvist
       
     5  * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
     6  *
       
     7  * GLib is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Lesser General Public License as
       
     9  * published by the Free Software Foundation; either version 2 of the
       
    10  * License, or (at your option) any later version.
       
    11  *
       
    12  * GLib is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Lesser General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Lesser General Public
       
    18  * License along with GLib; see the file COPYING.LIB.  If not, write
       
    19  * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    20  * Boston, MA 02111-1307, USA.
       
    21  */
       
    22 
       
    23 
       
    24 /* Define this to get some logging all the time */
       
    25 /* #define G_SPAWN_WIN32_DEBUG */
       
    26 
       
    27 
       
    28 
       
    29 /*This program is adapted to be used in the Symbian OS scenario*/
       
    30 
       
    31 #include <config.h>
       
    32 
       
    33 #include "glib.h"
       
    34 #include "gprintfint.h"
       
    35 #include "galias.h"
       
    36 
       
    37 #include <string.h>
       
    38 #include <stdlib.h>
       
    39 #include <stdio.h>
       
    40 
       
    41 #include <errno.h>
       
    42 #include <fcntl.h>
       
    43 
       
    44 #include "glibintl.h"
       
    45 
       
    46 #ifdef __SYMBIAN32__
       
    47 #include <sys/select.h>
       
    48 #include "glibbackend.h"
       
    49 #endif
       
    50 
       
    51 #ifdef __SYMBIAN32__
       
    52 #include <glib_wsd.h>
       
    53 #endif
       
    54 
       
    55 #if EMULATOR
       
    56 
       
    57 PLS(debug,gspawn_symbian,int)
       
    58 #define debug  (*FUNCTION_NAME(debug,gspawn_symbian)())
       
    59 
       
    60 #endif /* EMULATOR */
       
    61 
       
    62 #ifdef G_SPAWN_SYMBIAN_DEBUG
       
    63 #if !(EMULATOR)
       
    64   static int debug = 1;
       
    65 #endif /* EMULATOR */
       
    66   #define SETUP_DEBUG() /* empty */
       
    67 #else
       
    68 #if !(EMULATOR)
       
    69   static int debug = -1;
       
    70 #endif /* EMULATOR */
       
    71   #define SETUP_DEBUG()					\
       
    72     G_STMT_START					\
       
    73       {							\
       
    74 	if (debug == -1)				\
       
    75 	  {						\
       
    76 	    if (getenv ("G_SPAWN_WIN32_DEBUG") != NULL)	\
       
    77 	      debug = 1;				\
       
    78 	    else					\
       
    79 	      debug = 0;				\
       
    80 	  }						\
       
    81       }							\
       
    82     G_STMT_END
       
    83 #endif
       
    84 
       
    85 enum
       
    86 {
       
    87   CHILD_NO_ERROR,
       
    88   CHILD_CHDIR_FAILED,
       
    89   CHILD_SPAWN_FAILED,
       
    90 };
       
    91 
       
    92 enum {
       
    93   ARG_CHILD_ERR_REPORT = 1,
       
    94   ARG_STDIN,
       
    95   ARG_STDOUT,
       
    96   ARG_STDERR,
       
    97   ARG_WORKING_DIRECTORY,
       
    98   ARG_CLOSE_DESCRIPTORS,
       
    99   ARG_USE_PATH,
       
   100   ARG_WAIT,
       
   101   ARG_PROGRAM,
       
   102   ARG_COUNT = ARG_PROGRAM
       
   103 };
       
   104 
       
   105 
       
   106 static gchar *
       
   107 protect_argv_string (const gchar *string)
       
   108 {
       
   109   const gchar *p = string;
       
   110   gchar *retval, *q;
       
   111   gint len = 0;
       
   112   gboolean need_dblquotes = FALSE;
       
   113   while (*p)
       
   114     {
       
   115       if (*p == ' ' || *p == '\t')
       
   116 	need_dblquotes = TRUE;
       
   117       else if (*p == '"')
       
   118 	len++;
       
   119       else if (*p == '\\')
       
   120 	{
       
   121 	  const gchar *pp = p;
       
   122 	  while (*pp && *pp == '\\')
       
   123 	    pp++;
       
   124 	  if (*pp == '"')
       
   125 	    len++;
       
   126 	}
       
   127       len++;
       
   128       p++;
       
   129     }
       
   130   q = retval = g_malloc (len + need_dblquotes*2 + 1);
       
   131   p = string;
       
   132 
       
   133   if (need_dblquotes)
       
   134     *q++ = '"';
       
   135   
       
   136   while (*p)
       
   137     {
       
   138       if (*p == '"')
       
   139 	*q++ = '\\';
       
   140       else if (*p == '\\')
       
   141 	{
       
   142 	  const gchar *pp = p;
       
   143 	  while (*pp && *pp == '\\')
       
   144 	    pp++;
       
   145 	  if (*pp == '"')
       
   146 	    *q++ = '\\';
       
   147 	}
       
   148       *q++ = *p;
       
   149       p++;
       
   150     }
       
   151   
       
   152   if (need_dblquotes)
       
   153     *q++ = '"';
       
   154   *q++ = '\0';
       
   155 
       
   156   return retval;
       
   157 }
       
   158 
       
   159 static gint
       
   160 protect_argv (gchar  **argv,
       
   161 	      gchar ***new_argv)
       
   162 {
       
   163   gint i;
       
   164   gint argc = 0;
       
   165   
       
   166   while (argv[argc])
       
   167     ++argc;
       
   168   *new_argv = g_new (gchar *, argc+1);
       
   169 
       
   170   /* Quote each argv element if necessary, so that it will get
       
   171    * reconstructed correctly in the C runtime startup code.  Note that
       
   172    * the unquoting algorithm in the C runtime is really weird, and
       
   173    * rather different than what Unix shells do. See stdargv.c in the C
       
   174    * runtime sources (in the Platform SDK, in src/crt).
       
   175    *
       
   176    * Note that an new_argv[0] constructed by this function should
       
   177    * *not* be passed as the filename argument to a spawn* or exec*
       
   178    * family function. That argument should be the real file name
       
   179    * without any quoting.
       
   180    */
       
   181   for (i = 0; i < argc; i++)
       
   182     (*new_argv)[i] = protect_argv_string (argv[i]);
       
   183 
       
   184   (*new_argv)[argc] = NULL;
       
   185 
       
   186   return argc;
       
   187 }
       
   188 
       
   189 #if EMULATOR
       
   190 
       
   191 PLS(quark,g_spawn_error_quark ,GQuark)
       
   192 #define quark (*FUNCTION_NAME(quark,g_spawn_error_quark )())
       
   193 
       
   194 #endif /* EMULATOR */
       
   195 
       
   196 EXPORT_C GQuark
       
   197 g_spawn_error_quark (void)
       
   198 {
       
   199   #if !(EMULATOR)
       
   200   static GQuark quark = 0;
       
   201   #endif /* EMULATOR */
       
   202   if (quark == 0)
       
   203     quark = g_quark_from_static_string ("g-exec-error-quark");
       
   204   return quark;
       
   205 }
       
   206 
       
   207 #if EMULATOR
       
   208 #undef quark
       
   209 #endif /* EMULATOR */
       
   210 
       
   211 EXPORT_C gboolean
       
   212 g_spawn_async (const gchar          *working_directory,
       
   213 		    gchar               **argv,
       
   214 		    gchar               **envp,
       
   215 		    GSpawnFlags           flags,
       
   216 		    GSpawnChildSetupFunc  child_setup,
       
   217 		    gpointer              user_data,
       
   218 		    GPid                 *child_handle,
       
   219 		    GError              **error)
       
   220 {
       
   221   g_return_val_if_fail (argv != NULL, FALSE);
       
   222   
       
   223   return g_spawn_async_with_pipes (working_directory,
       
   224 					argv, envp,
       
   225 					flags,
       
   226 					child_setup,
       
   227 					user_data,
       
   228 					child_handle,
       
   229 					NULL, NULL, NULL,
       
   230 					error);
       
   231 }
       
   232 
       
   233 static gboolean
       
   234 utf8_charv_to_wcharv (char     **utf8_charv,
       
   235 		      wchar_t ***wcharv,
       
   236 		      int       *error_index,
       
   237 		      GError   **error)
       
   238 {
       
   239   wchar_t **retval = NULL;
       
   240 
       
   241   *wcharv = NULL;
       
   242   if (utf8_charv != NULL)
       
   243     {
       
   244       int n = 0, i;
       
   245 
       
   246       while (utf8_charv[n])
       
   247 		n++;
       
   248       retval = g_new (wchar_t *, n + 1);
       
   249             
       
   250 
       
   251       for (i = 0; i < n; i++)
       
   252 	{
       
   253 	  retval[i] = g_utf8_to_utf16 (utf8_charv[i], -1, NULL, NULL, error);
       
   254 	  if (retval[i] == NULL)
       
   255 	    {
       
   256 	      if (error_index)
       
   257 		*error_index = i;
       
   258 	      while (i)
       
   259 		g_free (retval[--i]);
       
   260 	      g_free (retval);
       
   261 	      return FALSE;
       
   262 	    }
       
   263 	}
       
   264 	    
       
   265       retval[n] = NULL;
       
   266     }
       
   267   *wcharv = retval;
       
   268   return TRUE;
       
   269 }
       
   270 
       
   271 static gboolean
       
   272 utf8_charv_to_cp_charv (char   **utf8_charv,
       
   273 			gchar ***cp_charv,
       
   274 			int     *error_index,
       
   275 			GError **error)
       
   276 {
       
   277   char **retval = NULL;
       
   278 
       
   279   *cp_charv = NULL;
       
   280   if (utf8_charv != NULL)
       
   281     {
       
   282       int n = 0, i;
       
   283 
       
   284       while (utf8_charv[n])
       
   285 		n++;
       
   286       retval = g_new (char *, n + 1);
       
   287 
       
   288       for (i = 0; i < n; i++)
       
   289 	{
       
   290 	  retval[i] = g_locale_from_utf8 (utf8_charv[i], -1, NULL, NULL, error);
       
   291 	  if (retval[i] == NULL)
       
   292 	    {
       
   293 	      if (error_index)
       
   294 		*error_index = i;
       
   295 	      while (i)
       
   296 		g_free (retval[--i]);
       
   297 	      g_free (retval);
       
   298 	      return FALSE;
       
   299 	    }
       
   300 	}
       
   301       retval[n] = NULL;
       
   302     }
       
   303 
       
   304   *cp_charv = retval;
       
   305   return TRUE;
       
   306 }
       
   307 
       
   308 static gboolean
       
   309 do_spawn_directly (gint                 *exit_status,
       
   310 		   gboolean		 do_return_handle,
       
   311 		   GSpawnFlags           flags,
       
   312 		   gchar               **argv,
       
   313 		   char                **envp,
       
   314 		   char                **protected_argv,
       
   315 		   GSpawnChildSetupFunc  child_setup,
       
   316 		   gpointer              user_data,
       
   317 		   GPid                 *child_handle,
       
   318 		   GError              **error)     
       
   319 {
       
   320   const int mode = (exit_status == NULL) ? P_NOWAIT : P_WAIT;
       
   321   char **new_argv;
       
   322   int rc = -1;
       
   323   int saved_errno;
       
   324   GError *conv_error = NULL;
       
   325   gint conv_error_index;
       
   326   
       
   327   char *cpargv0, **cpargv, **cpenvp;
       
   328 
       
   329   /*
       
   330   if G_SPAWN_FILE_AND_ARGV_ZERO is specified all the argv except the first
       
   331   ie argv[0] is passed to the child. if the flag is not specified all the 
       
   332   arguements are passed to the child including the the argv[0]
       
   333   */
       
   334   new_argv = (flags & G_SPAWN_FILE_AND_ARGV_ZERO) ? protected_argv + 1 : protected_argv; 
       
   335       
       
   336   cpargv0 = g_locale_from_utf8 (argv[0], -1, NULL, NULL, &conv_error);
       
   337   if (cpargv0 == NULL)
       
   338   {
       
   339   	g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
       
   340 		       "Invalid program name: %s",
       
   341 		       conv_error->message);
       
   342 	g_error_free (conv_error);
       
   343 
       
   344 	return FALSE;
       
   345   }
       
   346 
       
   347   if  (!utf8_charv_to_cp_charv (new_argv, &cpargv, &conv_error_index, &conv_error))
       
   348   {
       
   349 	g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
       
   350 		       "Invalid string in argument vector at %d: %s",
       
   351 		       conv_error_index, conv_error->message);
       
   352 	g_error_free (conv_error);
       
   353 	g_free (cpargv0);
       
   354 
       
   355 	return FALSE;
       
   356   }
       
   357 
       
   358   if (!utf8_charv_to_cp_charv (envp, &cpenvp, NULL, &conv_error))
       
   359   {
       
   360 	g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
       
   361 		       "Invalid string in environment: %s",
       
   362 		       conv_error->message);
       
   363 	g_error_free (conv_error);
       
   364 	g_free (cpargv0);
       
   365 	g_strfreev (cpargv);
       
   366 
       
   367 	return FALSE;
       
   368   }
       
   369 
       
   370   if (child_setup)
       
   371   	(* child_setup) (user_data);
       
   372   
       
   373   if (flags & G_SPAWN_SEARCH_PATH)
       
   374 	if (cpenvp != NULL)
       
   375 	  rc = spawnvpe (mode, cpargv0, (const char **) cpargv, (const char **) cpenvp);
       
   376 	else
       
   377 	  rc = spawnvp (mode, cpargv0, (const char **) cpargv);
       
   378   else
       
   379 	if (envp != NULL)
       
   380 	  rc = spawnve (mode, cpargv0, (const char **) cpargv, (const char **) cpenvp);
       
   381 	else
       
   382 	  rc = spawnv (mode, cpargv0, (const char **) cpargv);
       
   383 
       
   384   g_free (cpargv0);
       
   385   g_strfreev (cpargv);
       
   386   g_strfreev (cpenvp);
       
   387   
       
   388 
       
   389   saved_errno = errno;
       
   390 
       
   391   if (rc == -1 && saved_errno != 0)
       
   392     {
       
   393       g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
       
   394 		   _("Failed to execute child process (%s)"),
       
   395 		   g_strerror (saved_errno));
       
   396       return FALSE;
       
   397     }
       
   398 
       
   399   if (exit_status == NULL)
       
   400     {
       
   401       if (child_handle && do_return_handle)
       
   402 	  	*child_handle = (GPid) rc;
       
   403       else
       
   404       	{
       
   405 	  	CloseHandle ((HANDLE) rc);
       
   406 	  	if (child_handle)
       
   407 	    	*child_handle = 0;
       
   408 	  	}
       
   409     }
       
   410   else
       
   411     *exit_status = rc;
       
   412 
       
   413   return TRUE;
       
   414 }
       
   415 
       
   416 #if EMULATOR
       
   417 
       
   418 PLS(warned_about_child_setup ,do_spawn_with_pipes,gboolean)
       
   419 #define warned_about_child_setup (*FUNCTION_NAME(warned_about_child_setup,do_spawn_with_pipes)())
       
   420 
       
   421 #endif /* EMULATOR */
       
   422 
       
   423 
       
   424 static gboolean
       
   425 do_spawn_with_pipes (gint                 *exit_status,
       
   426 		     gboolean		   do_return_handle,
       
   427 		     const gchar          *working_directory,
       
   428 		     gchar               **argv,
       
   429 		     char                **envp,
       
   430 		     GSpawnFlags           flags,
       
   431 		     GSpawnChildSetupFunc  child_setup,
       
   432 		     gpointer              user_data,
       
   433 		     GPid                 *child_handle,
       
   434 		     gint                 *standard_input,
       
   435 		     gint                 *standard_output,
       
   436 		     gint                 *standard_error,
       
   437 		     gint		  *err_report,
       
   438 		     GError              **error)     
       
   439 {
       
   440   char **protected_argv;
       
   441   int rc = -1;
       
   442   int argc;
       
   443   gboolean retval;
       
   444 
       
   445   #if !(EMULATOR)
       
   446   static gboolean warned_about_child_setup = FALSE;
       
   447   #endif /* EMULATOR */
       
   448   
       
   449   GError *conv_error = NULL;
       
   450     
       
   451   SETUP_DEBUG();
       
   452 
       
   453   if (child_setup && !warned_about_child_setup)
       
   454     {
       
   455       warned_about_child_setup = TRUE;
       
   456       g_warning ("passing a child setup function to the g_spawn functions is pointless and dangerous on Win32");
       
   457     }
       
   458 
       
   459   argc = protect_argv (argv, &protected_argv);
       
   460 
       
   461   retval =
       
   462 	do_spawn_directly (exit_status, do_return_handle, flags,
       
   463 			   argv, envp, protected_argv,
       
   464 			   child_setup, user_data, child_handle,
       
   465 			   error);
       
   466       g_strfreev (protected_argv);
       
   467    
       
   468    if(standard_input)
       
   469    	*standard_input = -1;
       
   470    if(standard_output)
       
   471    	*standard_output = -1;
       
   472    if(standard_error)
       
   473    	*standard_error = -1;
       
   474    
       
   475    return retval;  
       
   476 }
       
   477 
       
   478 #if EMULATOR
       
   479 #undef warned_about_child_setup 
       
   480 #endif /* EMULATOR */
       
   481 
       
   482 EXPORT_C gboolean
       
   483 g_spawn_sync (const gchar          *working_directory,
       
   484 		   gchar               **argv,
       
   485 		   gchar               **envp,
       
   486 		   GSpawnFlags           flags,
       
   487 		   GSpawnChildSetupFunc  child_setup,
       
   488 		   gpointer              user_data,
       
   489 		   gchar               **standard_output,
       
   490 		   gchar               **standard_error,
       
   491 		   gint                 *exit_status,
       
   492 		   GError              **error)     
       
   493 {
       
   494   gint outpipe = -1;
       
   495   gint errpipe = -1;
       
   496   gint reportpipe = -1;
       
   497   gint outindex = -1;
       
   498   gint errindex = -1;
       
   499   GString *outstr = NULL;
       
   500   GString *errstr = NULL;
       
   501   gint status;
       
   502   
       
   503   g_return_val_if_fail (argv != NULL, FALSE);
       
   504   g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
       
   505   g_return_val_if_fail (standard_output == NULL ||
       
   506                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
       
   507   g_return_val_if_fail (standard_error == NULL ||
       
   508                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
       
   509   
       
   510   /* Just to ensure segfaults if callers try to use
       
   511    * these when an error is reported.
       
   512    */
       
   513   if (standard_output)
       
   514     *standard_output = NULL;
       
   515 
       
   516   if (standard_error)
       
   517     *standard_error = NULL;
       
   518   
       
   519   if (!do_spawn_with_pipes (&status,
       
   520 			    FALSE,
       
   521 			    working_directory,
       
   522 			    argv,
       
   523 			    envp,
       
   524 			    flags,
       
   525 			    child_setup,
       
   526 			    user_data,
       
   527 			    NULL,
       
   528 			    NULL,
       
   529 			    standard_output ? &outpipe : NULL,
       
   530 			    standard_error ? &errpipe : NULL,
       
   531 			    &reportpipe,
       
   532 			    error))
       
   533     return FALSE;
       
   534 
       
   535     if (exit_status)
       
   536     	*exit_status = status;
       
   537     return TRUE;
       
   538 }
       
   539 
       
   540 EXPORT_C gboolean
       
   541 g_spawn_async_with_pipes (const gchar          *working_directory,
       
   542 			       gchar               **argv,
       
   543 			       gchar               **envp,
       
   544 			       GSpawnFlags           flags,
       
   545 			       GSpawnChildSetupFunc  child_setup,
       
   546 			       gpointer              user_data,
       
   547 			       GPid                 *child_handle,
       
   548 			       gint                 *standard_input,
       
   549 			       gint                 *standard_output,
       
   550 			       gint                 *standard_error,
       
   551 			       GError              **error)
       
   552 {
       
   553   g_return_val_if_fail (argv != NULL, FALSE);
       
   554   g_return_val_if_fail (standard_output == NULL ||
       
   555                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
       
   556   g_return_val_if_fail (standard_error == NULL ||
       
   557                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
       
   558   /* can't inherit stdin if we have an input pipe. */
       
   559   g_return_val_if_fail (standard_input == NULL ||
       
   560                         !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
       
   561   
       
   562   return do_spawn_with_pipes (NULL,
       
   563 			      (flags & G_SPAWN_DO_NOT_REAP_CHILD),
       
   564 			      working_directory,
       
   565 			      argv,
       
   566 			      envp,
       
   567 			      flags,
       
   568 			      child_setup,
       
   569 			      user_data,
       
   570 			      child_handle,
       
   571 			      standard_input,
       
   572 			      standard_output,
       
   573 			      standard_error,
       
   574 			      NULL,
       
   575 			      error);
       
   576 }
       
   577 
       
   578 EXPORT_C gboolean
       
   579 g_spawn_command_line_sync (const gchar  *command_line,
       
   580 				gchar       **standard_output,
       
   581 				gchar       **standard_error,
       
   582 				gint         *exit_status,
       
   583 				GError      **error)
       
   584 {
       
   585   gboolean retval;
       
   586   gchar **argv = 0;
       
   587 
       
   588   g_return_val_if_fail (command_line != NULL, FALSE);
       
   589   
       
   590   if (!g_shell_parse_argv (command_line,
       
   591                            NULL, &argv,
       
   592                            error))
       
   593     return FALSE;
       
   594   
       
   595   retval = g_spawn_sync (NULL,
       
   596 			      argv,
       
   597 			      NULL,
       
   598 			      G_SPAWN_SEARCH_PATH,
       
   599 			      NULL,
       
   600 			      NULL,
       
   601 			      standard_output,
       
   602 			      standard_error,
       
   603 			      exit_status,
       
   604 			      error);
       
   605   g_strfreev (argv);
       
   606 
       
   607   return retval;
       
   608 }
       
   609 
       
   610 EXPORT_C gboolean
       
   611 g_spawn_command_line_async (const gchar *command_line,
       
   612 				 GError     **error)
       
   613 {
       
   614   gboolean retval;
       
   615   gchar **argv = 0;
       
   616 
       
   617   g_return_val_if_fail (command_line != NULL, FALSE);
       
   618 
       
   619   if (!g_shell_parse_argv (command_line,
       
   620                            NULL, &argv,
       
   621                            error))
       
   622     return FALSE;
       
   623   
       
   624   retval = g_spawn_async (NULL,
       
   625 			       argv,
       
   626 			       NULL,
       
   627 			       G_SPAWN_SEARCH_PATH,
       
   628 			       NULL,
       
   629 			       NULL,
       
   630 			       NULL,
       
   631 			       error);
       
   632   g_strfreev (argv);
       
   633 
       
   634   return retval;
       
   635 }
       
   636 
       
   637 EXPORT_C void
       
   638 g_spawn_close_pid (GPid pid)
       
   639 {
       
   640     CloseHandle (pid);
       
   641 }
       
   642 
       
   643 #define __G_SPAWN_C__
       
   644 #include "galiasdef.c"