Exemple #1
0
static gchar *
spawn_dbus_daemon (const gchar *binary,
    const gchar *configuration,
    const gchar *listen_address,
    TestUser user,
    GPid *daemon_pid)
{
  GError *error = NULL;
  GString *address;
  gint address_fd;
  GPtrArray *argv;
#ifdef DBUS_UNIX
  const struct passwd *pwd = NULL;
#endif

  if (user != TEST_USER_ME)
    {
#ifdef DBUS_UNIX
      if (getuid () != 0)
        {
          g_test_skip ("cannot use alternative uid when not uid 0");
          return NULL;
        }

      switch (user)
        {
          case TEST_USER_ROOT:
            break;

          case TEST_USER_MESSAGEBUS:
            pwd = getpwnam (DBUS_USER);

            if (pwd == NULL)
              {
                gchar *message = g_strdup_printf ("user '%s' does not exist",
                    DBUS_USER);

                g_test_skip (message);
                g_free (message);
                return NULL;
              }

            break;

          case TEST_USER_OTHER:
            pwd = getpwnam (DBUS_TEST_USER);

            if (pwd == NULL)
              {
                gchar *message = g_strdup_printf ("user '%s' does not exist",
                    DBUS_TEST_USER);

                g_test_skip (message);
                g_free (message);
                return NULL;
              }

            break;

          default:
            g_assert_not_reached ();
        }
#else
      g_test_skip ("cannot use alternative uid on Windows");
      return NULL;
#endif
    }

  argv = g_ptr_array_new_with_free_func (g_free);
  g_ptr_array_add (argv, g_strdup (binary));
  g_ptr_array_add (argv, g_strdup (configuration));
  g_ptr_array_add (argv, g_strdup ("--nofork"));
  g_ptr_array_add (argv, g_strdup ("--print-address=1")); /* stdout */

  if (listen_address != NULL)
    g_ptr_array_add (argv, g_strdup (listen_address));

#ifdef DBUS_UNIX
  g_ptr_array_add (argv, g_strdup ("--systemd-activation"));
#endif

  g_ptr_array_add (argv, NULL);

  g_spawn_async_with_pipes (NULL, /* working directory */
      (gchar **) argv->pdata,
      NULL, /* envp */
      G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
#ifdef DBUS_UNIX
      child_setup, (gpointer) pwd,
#else
      NULL, NULL,
#endif
      daemon_pid,
      NULL, /* child's stdin = /dev/null */
      &address_fd,
      NULL, /* child's stderr = our stderr */
      &error);
  g_assert_no_error (error);

  g_ptr_array_free (argv, TRUE);

  address = g_string_new (NULL);

  /* polling until the dbus-daemon writes out its address is a bit stupid,
   * but at least it's simple, unlike dbus-launch... in principle we could
   * use select() here, but life's too short */
  while (1)
    {
      gssize bytes;
      gchar buf[4096];
      gchar *newline;

      bytes = read (address_fd, buf, sizeof (buf));

      if (bytes > 0)
        g_string_append_len (address, buf, bytes);

      newline = strchr (address->str, '\n');

      if (newline != NULL)
        {
          if ((newline > address->str) && ('\r' == newline[-1]))
            newline -= 1;
          g_string_truncate (address, newline - address->str);
          break;
        }

      g_usleep (G_USEC_PER_SEC / 10);
    }

  g_close (address_fd, NULL);

  return g_string_free (address, FALSE);
}
static gboolean
egg_desktop_file_launchv (EggDesktopFile *desktop_file,
			  GSList *documents, va_list args,
			  GError **error)
{
  EggDesktopFileLaunchOption option;
  GSList *translated_documents = NULL, *docs = NULL;
  char *command, **argv;
  int argc, i, screen_num;
  gboolean success, current_success;
  GdkDisplay *display;
  char *startup_id;

  GPtrArray   *env = NULL;
  char       **variables = NULL;
  GdkScreen   *screen = NULL;
  int          workspace = -1;
  const char  *directory = NULL;
  guint32      launch_time = (guint32)-1;
  GSpawnFlags  flags = G_SPAWN_SEARCH_PATH;
  GSpawnChildSetupFunc setup_func = NULL;
  gpointer     setup_data = NULL;

  GPid        *ret_pid = NULL;
  int         *ret_stdin = NULL, *ret_stdout = NULL, *ret_stderr = NULL;
  char       **ret_startup_id = NULL;

  if (documents && desktop_file->document_code == 0)
    {
      g_set_error (error, EGG_DESKTOP_FILE_ERROR,
		   EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
		   _("Application does not accept documents on command line"));
      return FALSE;
    }

  /* Read the options: technically it's incorrect for the caller to
   * NULL-terminate the list of options (rather than 0-terminating
   * it), but NULL-terminating lets us use G_GNUC_NULL_TERMINATED,
   * it's more consistent with other glib/gtk methods, and it will
   * work as long as sizeof (int) <= sizeof (NULL), and NULL is
   * represented as 0. (Which is true everywhere we care about.)
   */
  while ((option = va_arg (args, EggDesktopFileLaunchOption)))
    {
      switch (option)
	{
	case EGG_DESKTOP_FILE_LAUNCH_CLEARENV:
	  if (env)
	    g_ptr_array_free (env, TRUE);
	  env = g_ptr_array_new ();
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_PUTENV:
	  variables = va_arg (args, char **);
	  for (i = 0; variables[i]; i++)
	    env = array_putenv (env, variables[i]);
	  break;

	case EGG_DESKTOP_FILE_LAUNCH_SCREEN:
	  screen = va_arg (args, GdkScreen *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_WORKSPACE:
	  workspace = va_arg (args, int);
	  break;

	case EGG_DESKTOP_FILE_LAUNCH_DIRECTORY:
	  directory = va_arg (args, const char *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_TIME:
	  launch_time = va_arg (args, guint32);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_FLAGS:
	  flags |= va_arg (args, GSpawnFlags);
	  /* Make sure they didn't set any flags that don't make sense. */
	  flags &= ~G_SPAWN_FILE_AND_ARGV_ZERO;
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC:
	  setup_func = va_arg (args, GSpawnChildSetupFunc);
	  setup_data = va_arg (args, gpointer);
	  break;

	case EGG_DESKTOP_FILE_LAUNCH_RETURN_PID:
	  ret_pid = va_arg (args, GPid *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE:
	  ret_stdin = va_arg (args, int *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE:
	  ret_stdout = va_arg (args, int *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE:
	  ret_stderr = va_arg (args, int *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID:
	  ret_startup_id = va_arg (args, char **);
	  break;

	default:
	  g_set_error (error, EGG_DESKTOP_FILE_ERROR,
		       EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION,
		       _("Unrecognized launch option: %d"),
		       GPOINTER_TO_INT (option));
	  success = FALSE;
	  goto out;
	}
    }

  if (screen)
    {
      display = gdk_screen_get_display (screen);
      char *display_name = g_strdup (gdk_display_get_name (display));
      char *display_env = g_strdup_printf ("DISPLAY=%s", display_name);
      env = array_putenv (env, display_env);
      g_free (display_name);
      g_free (display_env);
    }
  else
    {
      display = gdk_display_get_default ();
      screen = gdk_display_get_default_screen (display);
    }
  screen_num = gdk_x11_screen_get_screen_number (screen);

  translated_documents = translate_document_list (desktop_file, documents);
  docs = translated_documents;

  success = FALSE;

  do
    {
      command = parse_exec (desktop_file, &docs, error);
      if (!command)
	goto out;

      if (!g_shell_parse_argv (command, &argc, &argv, error))
	{
	  g_free (command);
	  goto out;
	}
      g_free (command);

      startup_id = start_startup_notification (display, desktop_file,
					       argv[0], screen_num,
					       workspace, launch_time);
      if (startup_id)
	{
	  char *startup_id_env = g_strdup_printf ("DESKTOP_STARTUP_ID=%s",
						  startup_id);
	  env = array_putenv (env, startup_id_env);
	  g_free (startup_id_env);
	}

      if (env != NULL)
	g_ptr_array_add (env, NULL);

      current_success =
	g_spawn_async_with_pipes (directory,
				  argv,
				  env ? (char **)(env->pdata) : NULL,
				  flags,
				  setup_func, setup_data,
				  ret_pid,
				  ret_stdin, ret_stdout, ret_stderr,
				  error);
      g_strfreev (argv);

      if (startup_id)
	{
	  if (current_success)
	    {
	      set_startup_notification_timeout (display, startup_id);

	      if (ret_startup_id)
		*ret_startup_id = startup_id;
	      else
		g_free (startup_id);
	    }
	  else
	    g_free (startup_id);
	}
      else if (ret_startup_id)
	*ret_startup_id = NULL;

      if (current_success)
	{
	  /* If we successfully launch any instances of the app, make
	   * sure we return TRUE and don't set @error.
	   */
	  success = TRUE;
	  error = NULL;

	  /* Also, only set the output params on the first one */
	  ret_pid = NULL;
	  ret_stdin = ret_stdout = ret_stderr = NULL;
	  ret_startup_id = NULL;
	}
    }
  while (docs && current_success);

 out:
  if (env)
    {
      g_strfreev ((char **)env->pdata);
      g_ptr_array_free (env, FALSE);
    }
  free_document_list (translated_documents);

  return success;
}
Exemple #3
0
/* Spawns a process and puts the result into buffers while occasionally running busy_func.
 * The idea being that busy_func can do things to keep the gui alive while the function
 * blocks until the script terminates
 */
gboolean spawn_script(const gchar *wdir,
                      gchar **argv,
                      gchar **envp,
                      gchar *standard_input,
                      gchar **standard_output,
                      gchar **standard_error,
                      gint *exit_code,
                      GError **error,
                      int busy_func(void*),
                      void *busy_data)
{
    int nstdin, nstdout, nstderr;
    FILE *fstdin=NULL, *fstdout=NULL, *fstderr=NULL;
    GString *sstdout, *sstderr;
    GPid pid;
    gboolean ret;
    int c;
    GSpawnFlags sf;

    sf = 0;

    if (!(ret = g_spawn_async_with_pipes(wdir,
                                         argv,
                                         envp,
                                         sf, NULL, NULL,
                                         &pid,
                                         &nstdin,
                                         &nstdout,
                                         &nstderr,
                                         error))) {
        return ret;
    }

    if (!((fstdin  = fdopen(nstdin, "ab")) &&
            (fstdout = fdopen(nstdout, "rb")) &&
            (fstderr = fdopen(nstderr, "rb")))) {
        fprintf(stderr, "spawn_script fdopen failed\n");
        exit(1);
    }

    fprintf(fstdin, standard_input);
    fclose(fstdin);

    sstdout = g_string_new("");
    sstderr = g_string_new("");

    while ((c = fgetc(fstdout)) != EOF) {
        sstdout = g_string_append_c(sstdout, c);
        if (busy_func && !busy_func(busy_data)) {
            // terminate script and return
        }
    }

    while ((c = fgetc(fstderr)) != EOF) {
        sstderr = g_string_append_c(sstderr, c);
    }

    fclose(fstdout);
    fclose(fstderr);

    g_spawn_close_pid(pid);

    *standard_output = sstdout->str;
    *standard_error = sstderr->str;

    g_string_free(sstdout, FALSE);
    g_string_free(sstderr, FALSE); /* Frees struct, not character data */
    // *exit_code =

    return ret;
}
/* Spawn passwd backend
 * Returns: TRUE on success, FALSE otherwise and sets error appropriately */
static gboolean
spawn_passwd (PasswordDialog *pdialog, GError **error)
{
	gchar	*argv[2];
	gchar	*envp[1];
	gint	my_stdin, my_stdout, my_stderr;

	argv[0] = "/usr/bin/passwd";	/* Is it safe to rely on a hard-coded path? */
	argv[1] = NULL;

	envp[0] = NULL;					/* If we pass an empty array as the environment,
									 * will the childs environment be empty, and the
									 * locales set to the C default? From the manual:
									 * "If envp is NULL, the child inherits its
									 * parent'senvironment."
									 * If I'm wrong here, we somehow have to set
									 * the locales here.
									 */

	if (!g_spawn_async_with_pipes (NULL,						/* Working directory */
								   argv,						/* Argument vector */
								   envp,						/* Environment */
								   G_SPAWN_DO_NOT_REAP_CHILD,	/* Flags */
								   NULL,						/* Child setup */
								   NULL,						/* Data to child setup */
								   &pdialog->backend_pid,		/* PID */
								   &my_stdin,						/* Stdin */
								   &my_stdout,						/* Stdout */
								   &my_stderr,						/* Stderr */
								   error)) {					/* GError */

		/* An error occurred */
		free_passwd_resources (pdialog);

		return FALSE;
	}

	/* 2>&1 */
	if (dup2 (my_stderr, my_stdout) == -1) {
		/* Failed! */
		g_set_error (error,
					 PASSDLG_ERROR,
					 PASSDLG_ERROR_BACKEND,
					 "%s",
					 strerror (errno));

		/* Clean up */
		stop_passwd (pdialog);

		return FALSE;
	}

	/* Open IO Channels */
	pdialog->backend_stdin = g_io_channel_unix_new (my_stdin);
	pdialog->backend_stdout = g_io_channel_unix_new (my_stdout);

	/* Set raw encoding */
	/* Set nonblocking mode */
	if (g_io_channel_set_encoding (pdialog->backend_stdin, NULL, error) != G_IO_STATUS_NORMAL ||
		g_io_channel_set_encoding (pdialog->backend_stdout, NULL, error) != G_IO_STATUS_NORMAL ||
		g_io_channel_set_flags (pdialog->backend_stdin, G_IO_FLAG_NONBLOCK, error) != G_IO_STATUS_NORMAL ||
		g_io_channel_set_flags (pdialog->backend_stdout, G_IO_FLAG_NONBLOCK, error) != G_IO_STATUS_NORMAL ) {

		/* Clean up */
		stop_passwd (pdialog);
		return FALSE;
	}

	/* Turn off buffering */
	g_io_channel_set_buffered (pdialog->backend_stdin, FALSE);
	g_io_channel_set_buffered (pdialog->backend_stdout, FALSE);

	/* Add IO Channel watcher */
	pdialog->backend_stdout_watch_id = g_io_add_watch (pdialog->backend_stdout,
													   G_IO_IN | G_IO_PRI,
													   (GIOFunc) io_watch_stdout, pdialog);

	/* Add child watcher */
	pdialog->backend_child_watch_id = g_child_watch_add (pdialog->backend_pid, (GChildWatchFunc) child_watch_cb, pdialog);

	/* Success! */

	return TRUE;
}
Exemple #5
0
void GwSpawn::run()
{
  describe();
  // Working directory.
  const gchar *workingdirectory = NULL;
  if (!myworkingdirectory.empty())
    workingdirectory = myworkingdirectory.c_str();
  // Store arguments in argv.
  char *argv[myarguments.size() + 2];
  // I know these casts are ugly. To do: figure out a better way.
  argv[0] = (char *)myprogram.c_str();
  for (unsigned int i = 0; i < myarguments.size(); i++) {
    argv[i + 1] = (char *)myarguments[i].c_str();
  }
  // Terminate argv.
  argv[myarguments.size() + 1] = NULL;
  // Spawn flags.
  int flags = G_SPAWN_SEARCH_PATH;
  if (mydevnull) {
    flags |= (G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL);
  }
  // Possible pipes.
  gint standard_input_filedescriptor = 0;
  gint standard_output_filedescriptor;
  gint standard_error_filedescriptor;
  gint *standard_input_filedescriptor_pointer = NULL;
  gint *standard_output_filedescriptor_pointer = NULL;
  gint *standard_error_filedescriptor_pointer = NULL;
  gchar *standard_output = NULL;
  gchar *standard_error = NULL;
  gchar **standard_output_pointer = NULL;
  gchar **standard_error_pointer = NULL;
  if (myread) {
    standard_output_filedescriptor_pointer = &standard_output_filedescriptor;
    standard_error_filedescriptor_pointer = &standard_error_filedescriptor;
    standard_output_pointer = &standard_output;
    standard_error_pointer = &standard_error;
  }
  if (!mywrite.empty()) {
    standard_input_filedescriptor_pointer = &standard_input_filedescriptor;
  }
  // Spawn process.
  if (myasync) {
    result = g_spawn_async_with_pipes(workingdirectory, argv, NULL, (GSpawnFlags) flags, NULL, NULL, &pid, standard_input_filedescriptor_pointer, standard_output_filedescriptor_pointer, standard_error_filedescriptor_pointer, NULL);
    // Handle writing to stdin.
    if (standard_input_filedescriptor) {
      tiny_spawn_write(standard_input_filedescriptor, mywrite);
      close(standard_input_filedescriptor);
    }
  } else {
    result = g_spawn_sync(workingdirectory, argv, NULL, (GSpawnFlags) flags, NULL, NULL, standard_output_pointer, standard_error_pointer, &exitstatus, NULL);
  }
  // Handle case we didn't spawn the process.
  if (!result) {
    exitstatus = -1;
    ustring message = myprogram;
    message.append(_(" didn't spawn"));
    gw_critical(message);
    return;
  }
  // Handle progress function.
  if (myprogress || standard_input_filedescriptor) {
    ProgressWindow *progresswindow = NULL;
    if (myprogress)
      progresswindow = new ProgressWindow(mytext, myallowcancel);
    ustring filename = gw_build_filename("/proc", convert_to_string(pid));
    while (g_file_test(filename.c_str(), G_FILE_TEST_EXISTS)) {
      if (progresswindow) {
        progresswindow->pulse();
        if (progresswindow->cancel) {
          unix_kill(pid);
          cancelled = true;
        }
      }
      g_usleep(500000);
    }
    // Close pid.
    g_spawn_close_pid(pid);
    if (progresswindow) { delete progresswindow; }
  }
  // Handle reading the output.
  if (myread) {
    // In async mode we've got file descriptors, and in sync mode we have 
    // gchar * output.
    // If async mode, read the output and close the descriptors.
    if (myasync) {
      GIOChannel *channel_out = g_io_channel_unix_new(standard_output_filedescriptor);
      g_io_channel_read_to_end(channel_out, &standard_output, NULL, NULL);
      g_io_channel_shutdown(channel_out, false, NULL);
      GIOChannel *channel_err = g_io_channel_unix_new(standard_error_filedescriptor);
      g_io_channel_read_to_end(channel_err, &standard_error, NULL, NULL);
      g_io_channel_shutdown(channel_err, false, NULL);
    }
    ParseLine parse_out(standard_output);
    standardout = parse_out.lines;
    ParseLine parse_err(standard_error);
    standarderr = parse_err.lines;
    // Free data.
    if (standard_output)
      g_free(standard_output);
    if (standard_error)
      g_free(standard_error);
  }
}
static gint
nm_openconnect_start_openconnect_binary (NMOPENCONNECTPlugin *plugin,
                                         NMSettingVPN *s_vpn,
                                         GError **error)
{
	NMOPENCONNECTPluginPrivate *priv = NM_OPENCONNECT_PLUGIN_GET_PRIVATE (plugin);
	GPid	pid;
	const char **openconnect_binary = NULL;
	GPtrArray *openconnect_argv;
	GSource *openconnect_watch;
	gint	stdin_fd;
	const char *props_vpn_gw, *props_cookie, *props_cacert, *props_mtu, *props_gwcert, *props_proxy;
	
	/* Find openconnect */
	openconnect_binary = openconnect_binary_paths;
	while (*openconnect_binary != NULL) {
		if (g_file_test (*openconnect_binary, G_FILE_TEST_EXISTS))
			break;
		openconnect_binary++;
	}

	if (!*openconnect_binary) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             _("Could not find openconnect binary."));
		return -1;
	}

	/* The actual gateway to use (after redirection) comes from the auth
	   dialog, so it's in the secrets hash not the properties */
	props_vpn_gw = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GATEWAY);
	if (!props_vpn_gw || !strlen (props_vpn_gw) ) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             _("No VPN gateway specified."));
		return -1;
	}

	props_cookie = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_COOKIE);
	if (!props_cookie || !strlen (props_cookie)) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             _("No WebVPN cookie provided."));
		return -1;
	}
	props_gwcert = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GWCERT);

	props_cacert = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_CACERT);
	props_mtu = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_MTU);

	props_proxy = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_PROXY);

	openconnect_argv = g_ptr_array_new ();
	g_ptr_array_add (openconnect_argv, (gpointer) (*openconnect_binary));

	if (props_gwcert && strlen(props_gwcert)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--servercert");
		g_ptr_array_add (openconnect_argv, (gpointer) props_gwcert);
	} else if (props_cacert && strlen(props_cacert)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--cafile");
		g_ptr_array_add (openconnect_argv, (gpointer) props_cacert);
	}

	if (props_mtu && strlen(props_mtu)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--mtu");
		g_ptr_array_add (openconnect_argv, (gpointer) props_mtu);
	}

	if (props_proxy && strlen(props_proxy)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--proxy");
		g_ptr_array_add (openconnect_argv, (gpointer) props_proxy);
	}
		
	g_ptr_array_add (openconnect_argv, (gpointer) "--syslog");
	g_ptr_array_add (openconnect_argv, (gpointer) "--cookie-on-stdin");

	g_ptr_array_add (openconnect_argv, (gpointer) "--script");
	g_ptr_array_add (openconnect_argv, (gpointer) NM_OPENCONNECT_HELPER_PATH);

	priv->tun_name = create_persistent_tundev ();
	if (priv->tun_name) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--interface");
		g_ptr_array_add (openconnect_argv, (gpointer) priv->tun_name);
	}

	g_ptr_array_add (openconnect_argv, (gpointer) props_vpn_gw);

	if (debug)
		g_ptr_array_add (openconnect_argv, (gpointer) "--verbose");

	g_ptr_array_add (openconnect_argv, NULL);

	if (!g_spawn_async_with_pipes (NULL, (char **) openconnect_argv->pdata, NULL,
	                               G_SPAWN_DO_NOT_REAP_CHILD,
	                               openconnect_drop_child_privs, priv->tun_name,
	                               &pid, &stdin_fd, NULL, NULL, error)) {
		g_ptr_array_free (openconnect_argv, TRUE);
		g_warning ("openconnect failed to start.  error: '%s'", (*error)->message);
		return -1;
	}
	g_ptr_array_free (openconnect_argv, TRUE);

	g_message ("openconnect started with pid %d", pid);

	if (write(stdin_fd, props_cookie, strlen(props_cookie)) != strlen(props_cookie) ||
	    write(stdin_fd, "\n", 1) != 1) {
		g_warning ("openconnect didn't eat the cookie we fed it");
		return -1;
	}

	close(stdin_fd);

	NM_OPENCONNECT_PLUGIN_GET_PRIVATE (plugin)->pid = pid;
	openconnect_watch = g_child_watch_source_new (pid);
	g_source_set_callback (openconnect_watch, (GSourceFunc) openconnect_watch_cb, plugin, NULL);
	g_source_attach (openconnect_watch, NULL);
	g_source_unref (openconnect_watch);

	return 0;
}
Exemple #7
0
static gboolean
on_handle_stream_socket (CockpitWebServer *server,
                         const gchar *path,
                         GIOStream *io_stream,
                         GHashTable *headers,
                         GByteArray *input,
                         gpointer user_data)
{
  CockpitTransport *transport;
  const gchar *query = NULL;
  CockpitCreds *creds;
  int session_stdin = -1;
  int session_stdout = -1;
  GError *error = NULL;
  GPid pid = 0;

  gchar *value;
  gchar **env;
  gchar **argv;

  if (!g_str_has_prefix (path, "/cockpit/socket"))
    return FALSE;

  if (path[15] == '?')
    {
      query = path + 16;
    }
  else if (path[15] != '\0')
    {
      return FALSE;
    }

  if (service)
    {
      g_object_ref (service);
    }
  else
    {
      g_clear_object (&bridge);

      value = g_strdup_printf ("%d", server_port);
      env = g_environ_setenv (g_get_environ (), "COCKPIT_TEST_SERVER_PORT", value, TRUE);

      argv = g_strdupv (bridge_argv);
      if (query)
        argv[g_strv_length (argv) - 1] = g_strdup (query);

      g_spawn_async_with_pipes (NULL, argv, env,
                                G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
                                NULL, NULL, &pid, &session_stdin, &session_stdout, NULL, &error);

      g_strfreev (env);
      g_free (argv);
      g_free (value);

      if (error)
        {
          g_critical ("couldn't run bridge %s: %s", bridge_argv[0], error->message);
          return FALSE;
        }

      bridge = g_object_new (COCKPIT_TYPE_PIPE,
                             "name", "test-server-bridge",
                             "in-fd", session_stdout,
                             "out-fd", session_stdin,
                             "pid", pid,
                             NULL);

      creds = cockpit_creds_new (g_get_user_name (), "test",
                                 COCKPIT_CRED_CSRF_TOKEN, "myspecialtoken",
                                 NULL);

      transport = cockpit_pipe_transport_new (bridge);
      service = cockpit_web_service_new (creds, transport);
      cockpit_creds_unref (creds);
      g_object_unref (transport);

      /* Clear the pointer automatically when service is done */
      g_object_add_weak_pointer (G_OBJECT (service), (gpointer *)&service);
    }

  cockpit_web_service_socket (service, path, io_stream, headers, input);

  /* Keeps ref on itself until it closes */
  g_object_unref (service);

  return TRUE;
}
/* Spawn passwd backend
 * Returns: TRUE on success, FALSE otherwise and sets error appropriately */
static gboolean
spawn_passwd (PasswdHandler *passwd_handler, GError **error)
{
        gchar   *argv[2];
        gchar  **envp;
        gint    my_stdin, my_stdout, my_stderr;

        argv[0] = "/usr/bin/passwd";    /* Is it safe to rely on a hard-coded path? */
        argv[1] = NULL;

        envp = g_get_environ ();
        envp = g_environ_setenv (envp, "LC_ALL", "C", TRUE);

        if (!g_spawn_async_with_pipes (NULL,                            /* Working directory */
                                       argv,                            /* Argument vector */
                                       envp,                            /* Environment */
                                       G_SPAWN_DO_NOT_REAP_CHILD,       /* Flags */
                                       ignore_sigpipe,                  /* Child setup */
                                       NULL,                            /* Data to child setup */
                                       &passwd_handler->backend_pid,    /* PID */
                                       &my_stdin,                       /* Stdin */
                                       &my_stdout,                      /* Stdout */
                                       &my_stderr,                      /* Stderr */
                                       error)) {                        /* GError */

                /* An error occured */
                free_passwd_resources (passwd_handler);

                g_strfreev (envp);

                return FALSE;
        }

        g_strfreev (envp);

        /* 2>&1 */
        if (dup2 (my_stderr, my_stdout) == -1) {
                /* Failed! */
                g_set_error_literal (error,
                                     PASSWD_ERROR,
                                     PASSWD_ERROR_BACKEND,
                                     strerror (errno));

                /* Clean up */
                stop_passwd (passwd_handler);

                return FALSE;
        }

        /* Open IO Channels */
        passwd_handler->backend_stdin = g_io_channel_unix_new (my_stdin);
        passwd_handler->backend_stdout = g_io_channel_unix_new (my_stdout);

        /* Set raw encoding */
        /* Set nonblocking mode */
        if (g_io_channel_set_encoding (passwd_handler->backend_stdin, NULL, error) != G_IO_STATUS_NORMAL ||
                g_io_channel_set_encoding (passwd_handler->backend_stdout, NULL, error) != G_IO_STATUS_NORMAL ||
                g_io_channel_set_flags (passwd_handler->backend_stdin, G_IO_FLAG_NONBLOCK, error) != G_IO_STATUS_NORMAL ||
                g_io_channel_set_flags (passwd_handler->backend_stdout, G_IO_FLAG_NONBLOCK, error) != G_IO_STATUS_NORMAL ) {

                /* Clean up */
                stop_passwd (passwd_handler);
                return FALSE;
        }

        /* Turn off buffering */
        g_io_channel_set_buffered (passwd_handler->backend_stdin, FALSE);
        g_io_channel_set_buffered (passwd_handler->backend_stdout, FALSE);

        /* Add IO Channel watcher */
        passwd_handler->backend_stdout_watch_id = g_io_add_watch (passwd_handler->backend_stdout,
                                                                  G_IO_IN | G_IO_PRI,
                                                                  (GIOFunc) io_watch_stdout, passwd_handler);

        /* Add child watcher */
        passwd_handler->backend_child_watch_id = g_child_watch_add (passwd_handler->backend_pid, (GChildWatchFunc) child_watch_cb, passwd_handler);

        /* Success! */

        return TRUE;
}
Exemple #9
0
static BraseroBurnResult
brasero_process_start (BraseroJob *job, GError **error)
{
	BraseroProcessPrivate *priv = BRASERO_PROCESS_PRIVATE (job);
	BraseroProcess *process = BRASERO_PROCESS (job);
	int stdout_pipe, stderr_pipe;
	BraseroProcessClass *klass;
	BraseroBurnResult result;
	gboolean read_stdout;
	/* that's to make sure programs are not translated */
	gchar *envp [] = {	"LANG=C",
				"LANGUAGE=C",
				"LC_ALL=C",
				NULL};

	if (priv->pid)
		return BRASERO_BURN_RUNNING;

	/* ask the arguments for the program */
	result = brasero_process_ask_argv (job, error);
	if (result != BRASERO_BURN_OK)
		return result;

	if (priv->working_directory) {
		BRASERO_JOB_LOG (process, "Launching command in %s", priv->working_directory);
	}
	else {
		BRASERO_JOB_LOG (process, "Launching command");
	}

	klass = BRASERO_PROCESS_GET_CLASS (process);

	/* only watch stdout coming from the last object in the queue */
	read_stdout = (klass->stdout_func &&
		       brasero_job_get_fd_out (BRASERO_JOB (process), NULL) != BRASERO_BURN_OK);

	priv->process_finished = FALSE;
	priv->return_status = 0;

	if (!g_spawn_async_with_pipes (priv->working_directory,
				       (gchar **) priv->argv->pdata,
				       (gchar **) envp,
				       G_SPAWN_SEARCH_PATH|
				       G_SPAWN_DO_NOT_REAP_CHILD,
				       brasero_process_setup,
				       process,
				       &priv->pid,
				       NULL,
				       read_stdout ? &stdout_pipe : NULL,
				       &stderr_pipe,
				       error)) {
		return BRASERO_BURN_ERR;
	}

	/* error channel */
	priv->std_error = brasero_process_setup_channel (process,
							 stderr_pipe,
							&priv->io_err,
							(GIOFunc) brasero_process_read_stderr);

	if (read_stdout)
		priv->std_out = brasero_process_setup_channel (process,
							       stdout_pipe,
							       &priv->io_out,
							       (GIOFunc) brasero_process_read_stdout);

	return BRASERO_BURN_OK;
}
static gint
run_command (struct _CamelSExp *f,
             gint argc,
             struct _CamelSExpResult **argv,
             FilterMessageSearch *fms)
{
	CamelMimeMessage *message;
	CamelStream *stream;
	gint i;
	gint pipe_to_child;
	GPid child_pid;
	GError *error = NULL;
	GPtrArray *args;
	child_watch_data_t child_watch_data;
	GSource *source;
	GMainContext *context;

	if (argc < 1 || argv[0]->value.string[0] == '\0')
		return 0;

	args = g_ptr_array_new ();
	for (i = 0; i < argc; i++)
		g_ptr_array_add (args, argv[i]->value.string);
	g_ptr_array_add (args, NULL);

	if (!g_spawn_async_with_pipes (NULL,
				       (gchar **) args->pdata,
				       NULL,
				       G_SPAWN_DO_NOT_REAP_CHILD |
				       G_SPAWN_SEARCH_PATH |
				       G_SPAWN_STDOUT_TO_DEV_NULL |
				       G_SPAWN_STDERR_TO_DEV_NULL,
				       child_setup_func,
				       NULL,
				       &child_pid,
				       &pipe_to_child,
				       NULL,
				       NULL,
				       &error)) {
		g_ptr_array_free (args, TRUE);

		g_set_error (
			fms->error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("Failed to create child process '%s': %s"),
			argv[0]->value.string, error->message);
		g_error_free (error);
		return -1;
	}

	g_ptr_array_free (args, TRUE);

	message = camel_filter_search_get_message (fms, f);

	stream = camel_stream_fs_new_with_fd (pipe_to_child);
	camel_data_wrapper_write_to_stream_sync (
		CAMEL_DATA_WRAPPER (message), stream, fms->cancellable, NULL);
	camel_stream_flush (stream, fms->cancellable, NULL);
	g_object_unref (stream);

	context = g_main_context_new ();
	child_watch_data.loop = g_main_loop_new (context, FALSE);
	g_main_context_unref (context);

	source = g_child_watch_source_new (child_pid);
	g_source_set_callback (source, (GSourceFunc) child_watch, &child_watch_data, NULL);
	g_source_attach (source, g_main_loop_get_context (child_watch_data.loop));
	g_source_unref (source);

	g_main_loop_run (child_watch_data.loop);
	g_main_loop_unref (child_watch_data.loop);

#ifndef G_OS_WIN32
	if (WIFEXITED (child_watch_data.child_status))
		return WEXITSTATUS (child_watch_data.child_status);
	else
		return -1;
#else
	return child_watch_data.child_status;
#endif
}
Exemple #11
0
int main(
    int              argc,
    char            *argv[])
{

    glob_t                   gbuf;
    int                      grc, i;
    GString                 *cmd;
    GError                  *err = NULL;

    GMainLoop *loop;

    GPtrArray    *child_args     = NULL;

    /* parse options */
    parse_options(&argc, &argv);

    /* set up logging */
    if (!logc_setup(&err)) {
        air_opterr("%s", err->message);
    }

    if (fd_nextdir == NULL) {
        air_opterr("The --nextdir switch is required");
    }

    child_args = g_ptr_array_sized_new(64);
    for (i=1; i < argc; i++) {
        /* Double dash indicates end of filedaemon's arguments */
        if (!strncmp(argv[i], "--", strlen(argv[i])) )
            continue;
        g_ptr_array_add(child_args, g_strdup(argv[i]));
    }
    g_ptr_array_add(child_args, NULL);

    if (child_args->len > 1) {
        if (fd_faildir == NULL) {
            air_opterr("The --faildir switch is required");
        }
    }

    cmd  = g_string_new("");

    loop = g_main_loop_new(NULL, FALSE);

    /* We need an input glob */
    if (!fd_inspec) {
        air_opterr("Input glob must be specified");
    }

    /* If an output destination is provided, make sure it's a directory */
    if (fd_outspec && !g_file_test(fd_outspec, G_FILE_TEST_IS_DIR )) {
        air_opterr("Output is not a directory");
    }

    /* Options check out; daemonize */
    if (!fd_nodaemon) {
        if (!daemonize()) {
            goto end;
        }
    }

    while (1) {
        /* Evaluate glob expression */
        grc = glob(fd_inspec, 0, NULL, &gbuf);

        if (grc == GLOB_NOSPACE) {
            g_error("Out of memory: glob allocation failure");
        }
#ifdef GLOB_NOMATCH
        /* HaX0riffic! Simulate behavior without NOMATCH where we have it. */
        else if (grc == GLOB_NOMATCH) {
            gbuf.gl_pathc = 0;
            gbuf.gl_pathv = NULL;
        }
#endif

        /* Iterate over glob paths, enqueueing. */
        for (i = 0; i < gbuf.gl_pathc; i++) {
            char      **child_envp            = {NULL};
            GError     *child_err             = NULL;

            GString    *filename_in           = NULL;
            GString    *filename_out          = NULL;
            GString    *filename_lock         = NULL;

            GIOChannel *file_in               = NULL;
            GIOChannel *file_out              = NULL;

            GIOChannel *child_stdin           = NULL;
            gint        child_stdin_fd        = -1;

            GIOChannel *child_stdout          = NULL;
            gint        child_stdout_fd       = -1;

            GPid          child_pid;
            int         len;

            fd_read_data_t  read_data;
            fd_write_data_t write_data;

            filename_in = g_string_new(gbuf.gl_pathv[i]);

            /* Skip non-regular files */
            if (!g_file_test(filename_in->str, G_FILE_TEST_IS_REGULAR) ) {
                g_string_free(filename_in, TRUE);
                continue;
            }

            /* Skip lockfiles */
            if (!strcmp(".lock", filename_in->str
                        + strlen(filename_in->str) - 5))
            {
                g_string_free(filename_in, TRUE);
                continue;
            }

            /* Generate lock path */
            if (!filename_lock) filename_lock = g_string_new("");
            g_string_printf(filename_lock, "%s.lock", filename_in->str);

            /* Skip files locked at queue time */
            if (g_file_test(filename_lock->str, G_FILE_TEST_IS_REGULAR)) {
                g_debug("file %s is locked", filename_in->str);
                g_string_free(filename_in, TRUE);
                g_string_free(filename_lock, TRUE);
                continue;
            }

            if (child_args->len == 1) {
                /* Do move or delete */
                GString *destpath = g_string_new("");
                char    *dbase    = NULL;
                /* Calculate move destination path */
                dbase = g_path_get_basename(filename_in->str);

                g_string_printf(destpath, "%s/%s", fd_nextdir, dbase);
                if (dbase) free(dbase);
                /* Do link */
                g_message("moving %s -> %s", filename_in->str, fd_nextdir);
                if (link(filename_in->str, destpath->str) < 0)
                    g_critical(
                        "error moving input file to destination directory: %s",
                        strerror(errno));
                /* Do delete */
                if (unlink(filename_in->str) < 0) {
                    g_critical("error deleting input file");
                }
                g_string_free(destpath, TRUE);
                g_string_free(filename_in, TRUE);
                g_string_free(filename_lock, TRUE);
                continue;
            }

            if (fd_lock) {
                fd_lock_file(filename_in->str);
            }

            file_in = g_io_channel_new_file(filename_in->str, "r", &err);

            if (file_in == NULL) {
                g_critical("Cannot open input file!");
            }

            g_io_channel_set_encoding(file_in, NULL, &err);

            if (err) {
                g_critical("error setting input encoding!");
            }

            g_io_channel_set_buffer_size(file_in, fd_bufsize);

            filename_out = g_string_new("");

            if (fd_outspec == NULL) {
                g_string_printf(filename_out, "%s", gbuf.gl_pathv[i]);
            } else {
                g_string_printf(filename_out, "%s/%s", fd_outspec,
                                gbuf.gl_pathv[i]);
            }

            len  = filename_out->len;

            if (g_strrstr(filename_out->str, ".")) {
                while (len-- > 0
                       && !g_str_has_suffix(filename_out->str, ".") )
                {
                    g_string_set_size(filename_out, filename_out->len - 1);
                }
                g_string_set_size(filename_out, filename_out->len - 1);
            }
            if (fd_outext) {
                g_string_append_printf(filename_out, ".%s", fd_outext);
            } else {
                g_string_append(filename_out, ".out");
            }

            g_message("%d: %s -> %s", i, filename_in->str, filename_out->str);

            file_out = g_io_channel_new_file(filename_out->str, "w", &err);

            if (file_out == NULL) {
                g_error("Cannot open output file!");
            }

            g_io_channel_set_encoding(file_out, NULL, &err);

            if (err) {
                g_error("error setting output encoding!");
            }

            g_io_channel_set_buffer_size(file_out, fd_bufsize);

            if (!g_spawn_async_with_pipes(".",
                                          (gchar **) child_args->pdata,
                                          child_envp,
                                          G_SPAWN_SEARCH_PATH |
                                          G_SPAWN_DO_NOT_REAP_CHILD,
                                          NULL,
                                          NULL,
                                          &child_pid,
                                          &child_stdin_fd,
                                          &child_stdout_fd,
                                          NULL,
                                          &child_err))
            {
                g_error("error spawning process: %s",
                        (child_err && child_err->message ? child_err->
                         message : "unknown error"));
            }
            g_debug("spawned process %d", i);

            /* Watch for process exit status */
            g_child_watch_add(child_pid, on_child_exit, filename_in->str);

            child_stdin = g_io_channel_unix_new(child_stdin_fd);

            if (child_stdin == NULL) {
                g_error("Cannot open child stdin!");
            }

            g_io_channel_set_encoding(child_stdin, NULL, &err);

            if (err) {
                g_error("error setting child stdin encoding!");
            }

            g_io_channel_set_buffer_size(child_stdin, fd_bufsize);

            child_stdout = g_io_channel_unix_new(child_stdout_fd);

            if (child_stdout == NULL) {
                g_error("Cannot open child stdout!");
            }

            g_io_channel_set_encoding(child_stdout, NULL, &err);

            if (err) {
                g_error("error setting child stdout encoding!");
            }


            g_io_channel_set_buffer_size(child_stdout, fd_bufsize);


            write_data.infile = file_in;
            write_data.buf    = g_malloc(g_io_channel_get_buffer_size(file_in));

            if (write_data.buf == NULL) {
                g_error("error allocating file_in buffer");
            }

            if (!g_io_add_watch(child_stdin,  G_IO_OUT | G_IO_PRI | G_IO_HUP |
                                G_IO_ERR, write_to_child, &write_data))
                g_error("Cannot add watch on GIOChannel!");

            read_data.outfile = file_out;
            read_data.loop    = loop;
            read_data.buf     = g_malloc(g_io_channel_get_buffer_size(file_out));

            if (write_data.buf == NULL) {
                g_error("error allocating file_in buffer");
            }

            if (!g_io_add_watch(child_stdout, G_IO_IN | G_IO_PRI | G_IO_HUP |
                                G_IO_ERR, read_from_child, &read_data))
                g_error("Cannot add watch on GIOChannel!");

            g_main_loop_run(loop);

            if (fd_lock) {
                fd_unlock_file(filename_in->str);
            }

            if (read_data.buf) {
                g_free(read_data.buf);
            }
            if (write_data.buf) {
                g_free(write_data.buf);
            }

            g_string_free(filename_in, TRUE);
            g_string_free(filename_out, TRUE);
            g_string_free(filename_lock, TRUE);
        }
        sleep(fd_poll_delay);
    }

  end:

    return 0;
}
static gboolean
exec_skype()
{
#ifdef INSTANTBIRD
	return FALSE;
#else
	GError *error;
	
#ifdef USE_XVFB_SERVER	
	PurpleAccount *acct = NULL;
	int skype_stdin;
	gchar **skype_list;
	gchar *command;
	
	if (!getenv("SKYPEDISPLAY"))
		setenv("SKYPEDISPLAY", ":25", 0);
	unsetenv("DBUS_SESSION_BUS_ADDRESS");
	command = g_strconcat("Xvfb ",
				//"Xnest ", //Uncomment if using Xnest
				getenv("SKYPEDISPLAY"),
				" -ac -terminate -tst -xinerama",
				" -render -shmem -screen 0 320x240x16", //Dont use me if using Xnest
				NULL);
	if (g_spawn_command_line_async(command, NULL))
	{
		acct = skype_get_account(NULL);
		skype_debug_info("skype_x11", "acct: %d\n", acct);
		if (acct && acct->username && acct->username[0] != '\0' &&
			acct->password && acct->password[0] != '\0')
		{
			g_free(command);
			command = g_strconcat("skype --pipelogin -display ",
						getenv("SKYPEDISPLAY"),
						NULL);
			g_shell_parse_argv(command, NULL, &skype_list, NULL);
			if (g_spawn_async_with_pipes(NULL, skype_list, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &skype_stdin, NULL, NULL, NULL))
			{
				g_strfreev(skype_list);
				write(skype_stdin, acct->username, strlen(acct->username));
				write(skype_stdin, " ", 1);
				write(skype_stdin, acct->password, strlen(acct->password));
				write(skype_stdin, "\n", 1);
				fsync(skype_stdin);
				skype_debug_info("skype_x11", "pipelogin worked\n");
				g_free(command);
				return TRUE;
			}
			g_strfreev(skype_list);
		}
	}
	g_free(command);
#endif
	
	if (g_spawn_command_line_async("skype --disable-cleanlooks", &error))
	{
		return TRUE;
	} else {
		skype_debug_error("skype", "Could not start skype: %s\n", error->message);
		return FALSE;
	}
#endif
}
Exemple #13
0
int
main (int    argc,
      char **argv)
{
  const PangoViewer *view;
  gpointer instance;
  PangoContext *context;
  int run;
  int width, height;
  gpointer surface;
  
  g_type_init();
  setlocale (LC_ALL, "");
  parse_options (argc, argv);
  
  view = opt_viewer;

  g_assert (view->id);

  instance = view->create (view);
  context = view->get_context (instance);
  do_output (context, NULL, NULL, NULL, NULL, &width, &height);
  surface = view->create_surface (instance, width, height);
  for (run = 0; run < MAX(1,opt_runs); run++)
    view->render (instance, surface, context, width, height, NULL);

  if (opt_output)
    {
      if (!view->write)
	fail ("%s viewer backend does not support writing", view->name);
      else
	{
	  FILE *stream;

	  if (view->write_suffix && g_str_has_suffix (opt_output, view->write_suffix))
	    {
	      stream = g_fopen (opt_output, "wb");
	      if (!stream)
		fail ("Cannot open output file %s: %s\n",
		      opt_output, g_strerror (errno));
	    }
	  else
	    {
	      int fd;
	      const gchar *convert_argv[4] = {"convert", "-", "%s"};
	      GError *error;

	      convert_argv[2] = opt_output;
	      
	      if (!g_spawn_async_with_pipes (NULL, (gchar **)convert_argv, NULL,
					     G_SPAWN_SEARCH_PATH |
					     G_SPAWN_STDOUT_TO_DEV_NULL |
					     G_SPAWN_STDERR_TO_DEV_NULL,
					     NULL, NULL, NULL, &fd, NULL, NULL, &error))
		fail ("When running ImageMagick 'convert' command: %s\n", error->message);
	      stream = fdopen (fd, "wb");
	    }
	  view->write (instance, surface, stream, width, height);
	  fclose (stream);
	}
    }

  if (opt_display)
    {
      char *title;
      title = get_options_string ();

      if (view->display)
        {
	  gpointer window = NULL;
	  gpointer state = NULL;

	  if (view->create_window)
	    window = view->create_window (instance, title, width, height);

	  while (1)
	    {
	      state = view->display (instance, surface, window, width, height, state);
	      if (!state)
		break;

	      view->render (instance, surface, context, width, height, state);
	    }

	  if (view->destroy_window)
	    view->destroy_window (instance, window);
	}
      else
        {
	  int fd;
	  FILE *stream;
	  const gchar *display_argv[5] = {"display", "-title", "%s", "-"};
	  GError *error = NULL;
	  GPid pid;

	  if (!view->write)
	    fail ("%s viewer backend does not support displaying or writing", view->name);
	  display_argv[2] = title;
	  
	  if (!g_spawn_async_with_pipes (NULL, (gchar **)display_argv, NULL,
					 G_SPAWN_DO_NOT_REAP_CHILD |
					 G_SPAWN_SEARCH_PATH |
					 G_SPAWN_STDOUT_TO_DEV_NULL |
					 G_SPAWN_STDERR_TO_DEV_NULL,
					 NULL, NULL, &pid, &fd, NULL, NULL, &error))
	    fail ("When running ImageMagick 'display' command: %s\n", error->message);
	  stream = fdopen (fd, "wb");
	  view->write (instance, surface, stream, width, height);
	  fclose (stream);
#ifdef G_OS_UNIX
	  waitpid (pid, NULL, 0);
#endif
	  g_spawn_close_pid (pid);
	}

      g_free (title);
    }

  view->destroy_surface (instance, surface);
  g_object_unref (context);
  view->destroy (instance);
  finalize ();
  return 0;
}
Exemple #14
0
static void 
display_fortune_dialog (FishApplet *fish)
{
	GError      *error = NULL;
	gboolean     user_command;
	int          output;
	const char  *charset;
	int          argc;
	char       **argv;
	GdkScreen   *screen;
	char        *display;

	/* if there is still a pipe, close it */
	if (fish->source_id)
		g_source_remove (fish->source_id);
	fish->source_id = 0;
	fish_close_channel (fish);

	user_command = locate_fortune_command (fish, &argc, &argv);
	if (!argv)
		return;

	if (!fish->fortune_dialog) {
		GtkWidget *scrolled;
		GtkWidget *vbox;
		GdkScreen *screen;
		int        screen_width;
		int        screen_height;
      
		fish->fortune_dialog = 
			gtk_dialog_new_with_buttons (
				"", NULL, 0,
				_("_Speak again"), FISH_RESPONSE_SPEAK,
				_("_Close"), GTK_RESPONSE_CLOSE,
				NULL);

		gtk_window_set_icon_name (GTK_WINDOW (fish->fortune_dialog),
					  FISH_ICON);

		gtk_dialog_set_default_response (
			GTK_DIALOG (fish->fortune_dialog), GTK_RESPONSE_CLOSE);

		g_signal_connect (fish->fortune_dialog, "delete_event",
				  G_CALLBACK (delete_event), fish);
		g_signal_connect (fish->fortune_dialog, "response",
				  G_CALLBACK (handle_fortune_response), fish);

		gtk_window_set_wmclass (GTK_WINDOW (fish->fortune_dialog), "fish", "Fish");

		screen = gtk_widget_get_screen (GTK_WIDGET (fish));

		screen_width  = gdk_screen_get_width (screen);
		screen_height = gdk_screen_get_height (screen);

		gtk_window_set_default_size (GTK_WINDOW (fish->fortune_dialog),
					     MIN (600, screen_width  * 0.9),
					     MIN (350, screen_height * 0.9));

		fish->fortune_view = gtk_text_view_new ();
		gtk_text_view_set_editable (GTK_TEXT_VIEW (fish->fortune_view), FALSE);
		gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (fish->fortune_view), FALSE);
		gtk_text_view_set_left_margin (GTK_TEXT_VIEW (fish->fortune_view), 10);
		gtk_text_view_set_right_margin (GTK_TEXT_VIEW (fish->fortune_view), 10);
		fish->fortune_buffer =
			gtk_text_view_get_buffer (GTK_TEXT_VIEW (fish->fortune_view));

		gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (fish->fortune_buffer),
					    "monospace_tag", "family",
					    "Monospace", NULL);

		scrolled = gtk_scrolled_window_new (NULL, NULL);
		gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
						GTK_POLICY_AUTOMATIC,
						GTK_POLICY_AUTOMATIC);
		gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
						     GTK_SHADOW_IN);

		gtk_container_add (GTK_CONTAINER (scrolled), fish->fortune_view);

		fish->fortune_label = gtk_label_new ("");
		gtk_label_set_ellipsize (GTK_LABEL (fish->fortune_label),
					 PANGO_ELLIPSIZE_MIDDLE);
		fish->fortune_cmd_label = gtk_label_new ("");
		gtk_misc_set_alignment (GTK_MISC (fish->fortune_cmd_label),
					0, 0.5);

		vbox = gtk_dialog_get_content_area (GTK_DIALOG (fish->fortune_dialog));
		gtk_box_pack_start (GTK_BOX (vbox),
				    fish->fortune_label,
				    FALSE, FALSE, 6);

		gtk_box_pack_start (GTK_BOX (vbox),
				    scrolled,
				    TRUE, TRUE, 6);

		gtk_box_pack_start (GTK_BOX (vbox),
				    fish->fortune_cmd_label,
				    FALSE, FALSE, 6);

		update_fortune_dialog (fish);

		/* We don't show_all for the dialog since fortune_cmd_label
		 * might need to be hidden 
		 * The dialog will be shown with gtk_window_present later */
		gtk_widget_show (scrolled);
		gtk_widget_show (fish->fortune_view);
		gtk_widget_show (fish->fortune_label);
	}

	if (!user_command) {
		char *command;
		char * text;

		command = g_markup_printf_escaped ("<tt>%s</tt>", argv[0]);
		text = g_strdup_printf (_("The configured command is not "
					  "working and has been replaced by: "
					  "%s"), command);
		gtk_label_set_markup (GTK_LABEL (fish->fortune_cmd_label),
				      text);
		g_free (command);
		g_free (text);
		gtk_widget_show (fish->fortune_cmd_label);
	} else {
		gtk_widget_hide (fish->fortune_cmd_label);
	}

	clear_fortune_text (fish);

	screen = gtk_widget_get_screen (GTK_WIDGET (fish));
	display = gdk_screen_make_display_name (screen);

	g_spawn_async_with_pipes (NULL, /* working directory */
				  argv,
				  NULL, /* envp */
				  G_SPAWN_SEARCH_PATH|G_SPAWN_STDERR_TO_DEV_NULL,
				  set_environment,
				  &display,
				  NULL, /* child pid */
				  NULL, /* stdin */
				  &output,
				  NULL, /* stderr */
				  &error);

	g_free (display);

	if (error) {
		char *message;

		message = g_strdup_printf (_("Unable to execute '%s'\n\nDetails: %s"),
					   argv[0], error->message);
		something_fishy_going_on (fish, message);
		g_free (message);
		g_error_free (error);
		g_strfreev (argv);
		return;
	}

	fish->io_channel = g_io_channel_unix_new (output);
	/* set the correct encoding if the locale is not using UTF-8 */
	if (!g_get_charset (&charset))
		g_io_channel_set_encoding(fish->io_channel, charset, &error);
	if (error) {
		char *message;

		message = g_strdup_printf (_("Unable to read from '%s'\n\nDetails: %s"),
					   argv[0], error->message);
		something_fishy_going_on (fish, message);
		g_free (message);
		g_error_free (error);
		g_strfreev (argv);
		return;
	}

	g_strfreev (argv);

	fish->source_id = g_io_add_watch (fish->io_channel,
					  G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
					  fish_read_output, fish);

	gtk_window_set_screen (GTK_WINDOW (fish->fortune_dialog),
			       gtk_widget_get_screen (GTK_WIDGET (fish)));
	gtk_window_present (GTK_WINDOW (fish->fortune_dialog));
}
Exemple #15
0
/// Reads from espeak's stdout.
static gpointer
worker (WorkerData *data)
{
	// Spawn eSpeak
	GError *error = NULL;
	gint child_in, child_out;
	if (!g_spawn_async_with_pipes (NULL, data->cmdline, NULL,
		G_SPAWN_SEARCH_PATH, NULL, NULL,
		NULL, &child_in, &child_out, NULL, &error))
		g_error ("g_spawn() failed: %s", error->message);

	data->child_stdin = fdopen (child_in, "wb");
	if (!data->child_stdin)
		perror ("fdopen");

	FILE *child_stdout = fdopen (child_out, "rb");
	if (!child_stdout)
		perror ("fdopen");

	// Spawn a writer thread
	g_mutex_lock (data->dict_mutex);
	data->iterator = stardict_iterator_new (data->dict, data->start_entry);
	g_mutex_unlock (data->dict_mutex);

	GThread *writer = g_thread_new ("write worker",
		(GThreadFunc) worker_writer, data);

	// Read the output
	g_mutex_lock (data->remaining_mutex);
	guint32 remaining = data->remaining;
	g_mutex_unlock (data->remaining_mutex);

	data->output = NULL;
	gpointer *output_end = &data->output;
	while (remaining)
	{
		static gchar next[sizeof (gpointer)];
		GString *s = g_string_new (NULL);
		g_string_append_len (s, next, sizeof next);

		gint c;
		while ((c = fgetc (child_stdout)) != EOF && c != '\n')
			g_string_append_c (s, c);
		if (c == EOF)
			g_error ("eSpeak process died too soon");

		gchar *translation = g_string_free (s, FALSE);
		*output_end = translation;
		output_end = (gpointer *) translation;

		// We limit progress reporting so that
		// the mutex doesn't spin like crazy
		if ((--remaining & 255) != 0)
			continue;

		g_mutex_lock (data->remaining_mutex);
		data->remaining = remaining;
		g_cond_broadcast (data->remaining_cond);
		g_mutex_unlock (data->remaining_mutex);
	}

	if (fgetc (child_stdout) != EOF)
	{
		g_printerr ("Error: eSpeak has written more lines than it should. "
			"The output would be corrupt, aborting.\n");
		exit (EXIT_FAILURE);
	}

	fclose (child_stdout);
	return g_thread_join (writer);
}
Exemple #16
0
gboolean
ck_job_execute (CkJob   *job,
                GError **error)
{
        GError     *local_error;
        gboolean    res;
        GIOChannel *channel;
        int         standard_output;
        int         standard_error;
        int         argc;
        char      **argv;

        g_debug ("Executing %s", job->priv->command);
        local_error = NULL;
        if (! g_shell_parse_argv (job->priv->command, &argc, &argv, &local_error)) {
                g_debug ("Could not parse command: %s", local_error->message);
                g_propagate_error (error, local_error);
                return FALSE;
        }

        local_error = NULL;
        res = g_spawn_async_with_pipes (NULL,
                                        argv,
                                        NULL,
                                        G_SPAWN_DO_NOT_REAP_CHILD,
                                        NULL,
                                        NULL,
                                        &job->priv->child_pid,
                                        NULL,
                                        &standard_output,
                                        &standard_error,
                                        &local_error);

        g_strfreev (argv);
        if (! res) {
                g_debug ("Could not start command '%s': %s",
                          job->priv->command,
                          local_error->message);
                g_propagate_error (error, local_error);
                return FALSE;
        }

        /* output channel */
        channel = g_io_channel_unix_new (standard_output);
        g_io_channel_set_close_on_unref (channel, TRUE);
        g_io_channel_set_flags (channel,
                                g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK,
                                NULL);
        job->priv->out_watch_id = g_io_add_watch (channel,
                                                  G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
                                                  (GIOFunc)out_watch,
                                                  job);
        g_io_channel_unref (channel);

        /* error channel */
        channel = g_io_channel_unix_new (standard_error);
        g_io_channel_set_close_on_unref (channel, TRUE);
        g_io_channel_set_flags (channel,
                                g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK,
                                NULL);
        job->priv->err_watch_id = g_io_add_watch (channel,
                                                  G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
                                                  (GIOFunc)error_watch,
                                                  job);
        g_io_channel_unref (channel);

        return res;
}
Exemple #17
0
/**
 * connman_task_run:
 * @task: task structure
 * @function: exit callback
 * @user_data: optional exit user data
 * @fd: optional spawn with pipe
 *
 * Execute program specified by #task
 */
int connman_task_run(struct connman_task *task,
			connman_task_exit_t function, void *user_data,
			int *stdin_fd, int *stdout_fd, int *stderr_fd)
{
	GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD;
	bool result;
	char **argv, **envp;

	DBG("task %p", task);

	if (task->pid > 0)
		return -EALREADY;

	if (!stdout_fd)
		flags |= G_SPAWN_STDOUT_TO_DEV_NULL;

	if (!stderr_fd)
		flags |= G_SPAWN_STDERR_TO_DEV_NULL;

	task->exit_func = function;
	task->exit_data = user_data;

	if (g_ptr_array_index(task->argv, task->argv->len - 1))
		g_ptr_array_add(task->argv, NULL);

	if (task->envp->len == 0 ||
			g_ptr_array_index(task->envp, task->envp->len - 1)) {
		if (g_hash_table_size(task->notify) > 0) {
			const char *busname;
			char *str;

			busname = dbus_bus_get_unique_name(connection);
			str = g_strdup_printf("CONNMAN_BUSNAME=%s", busname);
			g_ptr_array_add(task->envp, str);

			str = g_strdup_printf("CONNMAN_INTERFACE=%s",
						CONNMAN_TASK_INTERFACE);
			g_ptr_array_add(task->envp, str);

			str = g_strdup_printf("CONNMAN_PATH=%s", task->path);
			g_ptr_array_add(task->envp, str);
		}

		g_ptr_array_add(task->envp, NULL);
	}

	argv = (char **) task->argv->pdata;
	envp = (char **) task->envp->pdata;

	result = g_spawn_async_with_pipes(NULL, argv, envp, flags,
					task_setup, task, &task->pid,
					stdin_fd, stdout_fd, stderr_fd, NULL);
	if (!result) {
		connman_error("Failed to spawn %s", argv[0]);
		return -EIO;
	}

	task->child_watch = g_child_watch_add(task->pid, task_died, task);

	return 0;
}
Exemple #18
0
int main(int argc, char** argv)
{
    GError *err = NULL;
    GMappedFile *map;
    char *buf = NULL, *pbuf = NULL, *data = NULL, *end;
    gsize len = 0;
    char *extract_path;

    gtk_init( &argc, &argv );

    /* load the executable file itself */
    map = g_mapped_file_new( argv[0], FALSE, NULL );
    if( !map )
        return 1;

    buf = g_mapped_file_get_contents(map);
    len = g_mapped_file_get_length( map );

    /* find the data */
    magic[0] = '_';

    for( pbuf = buf, end = buf + len - magic_len; G_LIKELY( pbuf < end ); ++pbuf )
    {
        if( G_UNLIKELY( 0 == memcmp( pbuf, magic, magic_len ) ) )
        {
            data = pbuf + magic_len + 1;
            break;
        }
    }

    if( G_UNLIKELY( ! data ) )
    {
        g_mapped_file_free( map );
        show_error( "檔案損毀,請重新下載。" );
        return 1;   /* error!  no data found */
    }

    len -= (data - buf);    /* skip ourself */

    extract_path = g_strconcat( "/tmp/Lazybuntu-", g_get_user_name(), NULL );
    g_mkdir_with_parents( extract_path, 0755 ); /* FIXME: is 0755 OK? */

    cmdv[3] = extract_path;
    if( g_spawn_async_with_pipes( NULL, cmdv, NULL, G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &std_in, NULL, NULL, &err ) )
    {
        int status = 0;
        write( std_in, data, len );
        close( std_in );
        waitpid( pid, &status, 0 );
        g_spawn_close_pid( pid );
    }
    else
    {
        show_error( err->message );   
        g_error_free( err );
    }
    g_mapped_file_free( map );

    g_chdir( extract_path );
    g_free( extract_path );
    g_chdir( "Lazybuntu" );
    execl( "Lazybuntu", NULL );

    show_error("錯誤,無法執行 Lazybuntu!");

    return 0;
}
static void
execute_current_command (ExecuteData *exec_data)
{
	FrProcess      *process = exec_data->process;
	FrCommandInfo  *info;
	GList          *scan;
	char          **argv;
	int             out_fd, err_fd;
	int             i = 0;
	GError         *error;

	debug (DEBUG_INFO, "%d/%d) ", process->priv->current_command, process->priv->n_comm);

	info = g_ptr_array_index (process->priv->comm, process->priv->current_command);

	argv = g_new (char *, g_list_length (info->args) + 1);
	for (scan = info->args; scan; scan = scan->next)
		argv[i++] = scan->data;
	argv[i] = NULL;

#ifdef DEBUG
	{
		int j;

		if (process->priv->use_standard_locale)
			g_print ("\tLC_MESSAGES=C\n");

		if (info->dir != NULL)
			g_print ("\tcd %s\n", info->dir);

		if (info->ignore_error)
			g_print ("\t[ignore error]\n");

		g_print ("\t");
		for (j = 0; j < i; j++)
			g_print ("%s ", argv[j]);
		g_print ("\n");
	}
#endif

	if (info->begin_func != NULL)
		(*info->begin_func) (info->begin_data);

	if (! g_spawn_async_with_pipes (info->dir,
					argv,
					NULL,
					(G_SPAWN_LEAVE_DESCRIPTORS_OPEN
					 | G_SPAWN_SEARCH_PATH
					 | G_SPAWN_DO_NOT_REAP_CHILD),
					child_setup,
					process,
					&process->priv->command_pid,
					NULL,
					&out_fd,
					&err_fd,
					&error))
	{
		exec_data->error = fr_error_new (FR_ERROR_SPAWN, 0, error);
		_fr_process_execute_complete_in_idle (exec_data);

		g_error_free (error);
		g_free (argv);
		return;
	}

	g_free (argv);

	fr_channel_data_set_fd (&process->out, out_fd, _fr_process_get_charset (process));
	fr_channel_data_set_fd (&process->err, err_fd, _fr_process_get_charset (process));

	process->priv->check_timeout = g_timeout_add (REFRESH_RATE,
					              check_child,
					              exec_data);
}
Exemple #20
0
Fichier : pty.c Projet : gbl/vte
/*
 * __vte_pty_spawn:
 * @pty: a #VtePty
 * @directory: the name of a directory the command should start in, or %NULL
 *   to use the cwd
 * @argv: child's argument vector
 * @envv: a list of environment variables to be added to the environment before
 *   starting the process, or %NULL
 * @spawn_flags: flags from #GSpawnFlags
 * @child_setup: function to run in the child just before exec()
 * @child_setup_data: user data for @child_setup
 * @child_pid: a location to store the child PID, or %NULL
 * @error: return location for a #GError, or %NULL
 *
 * Uses g_spawn_async() to spawn the command in @argv. The child's environment will
 * be the parent environment with the variables in @envv set afterwards.
 *
 * Enforces the vte_terminal_watch_child() requirements by adding
 * %G_SPAWN_DO_NOT_REAP_CHILD to @spawn_flags.
 *
 * Note that the %G_SPAWN_LEAVE_DESCRIPTORS_OPEN flag is not supported;
 * it will be cleared!
 *
 * If spawning the command in @working_directory fails because the child
 * is unable to chdir() to it, falls back trying to spawn the command
 * in the parent's working directory.
 *
 * Returns: %TRUE on success, or %FALSE on failure with @error filled in
 */
gboolean
__vte_pty_spawn (VtePty *pty,
                 const char *directory,
                 char **argv,
                 char **envv,
                 GSpawnFlags spawn_flags,
                 GSpawnChildSetupFunc child_setup,
                 gpointer child_setup_data,
                 GPid *child_pid /* out */,
                 GError **error)
{
	VtePtyPrivate *priv = pty->priv;
        VtePtyChildSetupData *data = &priv->child_setup_data;
	gboolean ret = TRUE;
        gboolean inherit_envv;
        char **envp2;
        gint i;
        GError *err = NULL;

        spawn_flags |= G_SPAWN_DO_NOT_REAP_CHILD;

        /* FIXMEchpe: Enforce this until I've checked our code to make sure
         * it doesn't leak out internal FDs into the child this way.
         */
        spawn_flags &= ~G_SPAWN_LEAVE_DESCRIPTORS_OPEN;

        inherit_envv = (spawn_flags & VTE_SPAWN_NO_PARENT_ENVV) == 0;
        spawn_flags &= ~VTE_SPAWN_NO_PARENT_ENVV;

        /* add the given environment to the childs */
        envp2 = __vte_pty_merge_environ (envv, inherit_envv);

        _VTE_DEBUG_IF (VTE_DEBUG_MISC) {
                g_printerr ("Spawing command:\n");
                for (i = 0; argv[i] != NULL; i++) {
                        g_printerr ("    argv[%d] = %s\n", i, argv[i]);
                }
                for (i = 0; envp2[i] != NULL; i++) {
                        g_printerr ("    env[%d] = %s\n", i, envp2[i]);
                }
                g_printerr ("    directory: %s\n",
                            directory ? directory : "(none)");
        }

	data->extra_child_setup = child_setup;
	data->extra_child_setup_data = child_setup_data;

        ret = g_spawn_async_with_pipes(directory,
                                       argv, envp2,
                                       spawn_flags,
                                       (GSpawnChildSetupFunc) vte_pty_child_setup,
                                       pty,
                                       child_pid,
                                       NULL, NULL, NULL,
                                       &err);
        if (!ret &&
            directory != NULL &&
            g_error_matches(err, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR)) {
                /* try spawning in our working directory */
                g_clear_error(&err);
                ret = g_spawn_async_with_pipes(NULL,
                                               argv, envp2,
                                               spawn_flags,
                                               (GSpawnChildSetupFunc) vte_pty_child_setup,
                                               pty,
                                               child_pid,
                                               NULL, NULL, NULL,
                                               &err);
        }

        g_strfreev (envp2);

	data->extra_child_setup = NULL;
	data->extra_child_setup_data = NULL;

        if (ret)
                return TRUE;

        g_propagate_error (error, err);
        return FALSE;
}
Exemple #21
0
/*
 * starts gdb, collects commands and start the first one
 */
static gboolean run(const gchar* file, const gchar* commandline, GList* env, GList *witer, GList *biter, const gchar* terminal_device, dbg_callbacks* callbacks)
{
	GError *err = NULL;
	const gchar *exclude[] = { "LANG", NULL };
	gchar **gdb_env = utils_copy_environment(exclude, "LANG", "C", NULL);
	gchar *working_directory = g_path_get_dirname(file);
	GList *lines, *iter;
	GList *commands = NULL;
	GString *command;
	int bp_index;
	queue_item *item;

	dbg_cbs = callbacks;

	/* spawn GDB */
	if (!g_spawn_async_with_pipes(working_directory, (gchar**)gdb_args, gdb_env,
				     GDB_SPAWN_FLAGS, NULL,
				     NULL, &gdb_pid, &gdb_in, &gdb_out, NULL, &err))
	{
		dbg_cbs->report_error(_("Failed to spawn gdb process"));
		g_free(working_directory);
		g_strfreev(gdb_env);
		return FALSE;
	}
	g_free(working_directory);
	g_strfreev(gdb_env);
	
	/* move gdb to it's own process group */
	setpgid(gdb_pid, 0);
	
	/* set handler for gdb process exit event */ 
	gdb_src_id = g_child_watch_add(gdb_pid, on_gdb_exit, NULL);

	/* create GDB GIO chanels */
	gdb_ch_in = g_io_channel_unix_new(gdb_in);
	gdb_ch_out = g_io_channel_unix_new(gdb_out);

	/* reading starting gdb messages */
	lines = read_until_prompt();
	for (iter = lines; iter; iter = iter->next)
	{
		gchar *unescaped = g_strcompress((gchar*)iter->data);
		if (strlen(unescaped))
		{
			colorize_message((gchar*)iter->data);
		}
	}
	g_list_foreach(lines, (GFunc)g_free, NULL);
	g_list_free(lines);

	/* add initial watches to the list */
	while (witer)
	{
		gchar *name = (gchar*)witer->data;

		variable *var = variable_new(name, VT_WATCH);
		watches = g_list_append(watches, var);
		
		witer = witer->next;
	}

	/* collect commands */

	/* loading file */
	command = g_string_new("");
	g_string_printf(command, "-file-exec-and-symbols \"%s\"", file);
	commands = add_to_queue(commands, _("~\"Loading target file.\\n\""), command->str, _("Error loading file"), FALSE);
	g_string_free(command, TRUE);

	/* setting asyncronous mode */
	commands = add_to_queue(commands, NULL, "-gdb-set target-async 1", _("Error configuring GDB"), FALSE);

	/* setting null-stop array printing */
	commands = add_to_queue(commands, NULL, "-interpreter-exec console \"set print null-stop\"", _("Error configuring GDB"), FALSE);

	/* enable pretty printing */
	commands = add_to_queue(commands, NULL, "-enable-pretty-printing", _("Error configuring GDB"), FALSE);

	/* set locale */
	command = g_string_new("");
	g_string_printf(command, "-gdb-set environment LANG=%s", g_getenv("LANG"));
	commands = add_to_queue(commands, NULL, command->str, NULL, FALSE);
	g_string_free(command, TRUE);

	/* set arguments */
	command = g_string_new("");
	g_string_printf(command, "-exec-arguments %s", commandline);
	commands = add_to_queue(commands, NULL, command->str, NULL, FALSE);
	g_string_free(command, TRUE);

	/* set passed evironment */
	iter = env;
	while (iter)
	{
		gchar *name, *value;

		name = (gchar*)iter->data;
		iter = iter->next;
		value = (gchar*)iter->data;

		command = g_string_new("");
		g_string_printf(command, "-gdb-set environment %s=%s", name, value);

		commands = add_to_queue(commands, NULL, command->str, NULL, FALSE);
		g_string_free(command, TRUE);

		iter = iter->next;
	}

	/* set breaks */
	bp_index = 1;
	while (biter)
	{
		breakpoint *bp = (breakpoint*)biter->data;
		GString *error_message = g_string_new("");

		command = g_string_new("");
		g_string_printf(command, "-break-insert -f \"\\\"%s\\\":%i\"", bp->file, bp->line);

		g_string_printf(error_message, _("Breakpoint at %s:%i cannot be set\nDebugger message: %s"), bp->file, bp->line, "%s");
		
		commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE);

		g_string_free(command, TRUE);

		if (bp->hitscount)
		{
			command = g_string_new("");
			g_string_printf(command, "-break-after %i %i", bp_index, bp->hitscount);
			commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE);
			g_string_free(command, TRUE);
		}
		if (strlen(bp->condition))
		{
			command = g_string_new("");
			g_string_printf (command, "-break-condition %i %s", bp_index, bp->condition);
			commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE);
			g_string_free(command, TRUE);
		}
		if (!bp->enabled)
		{
			command = g_string_new("");
			g_string_printf (command, "-break-disable %i", bp_index);
			commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE);
			g_string_free(command, TRUE);
		}

		g_string_free(error_message, TRUE);

		bp_index++;
		biter = biter->next;
	}

	/* set debugging terminal */
	command = g_string_new("-inferior-tty-set ");
	g_string_append(command, terminal_device);
	commands = add_to_queue(commands, NULL, command->str, NULL, FALSE);
	g_string_free(command, TRUE);

	/* connect read callback to the output chanel */
	gdb_id_out = g_io_add_watch(gdb_ch_out, G_IO_IN, on_read_async_output, commands);

	item = (queue_item*)commands->data;

	/* send message to debugger messages window */
	if (item->message)
	{
		dbg_cbs->send_message(item->message->str, "grey");
	}

	/* send first command */
	gdb_input_write_line(item->command->str);

	return TRUE;
}
Exemple #22
0
static gboolean
launch_test_binary (const char *binary,
                    guint       skip_tests)
{
  GTestLogBuffer *tlb;
  GSList *slist, *free_list = NULL;
  GError *error = NULL;
  int argc = 0;
  const gchar **argv;
  GPid pid = 0;
  gint report_pipe[2] = { -1, -1 };
  guint child_report_cb_id = 0;
  gboolean loop_pending;
  gint i = 0;

  if (pipe (report_pipe) < 0)
    {
      if (subtest_mode_fatal)
        g_error ("Failed to open pipe for test binary: %s: %s", binary, g_strerror (errno));
      else
        g_warning ("Failed to open pipe for test binary: %s: %s", binary, g_strerror (errno));
      return FALSE;
    }

  /* setup argc */
  for (slist = subtest_args; slist; slist = slist->next)
    argc++;
  /* argc++; */
  if (subtest_quiet)
    argc++;
  if (subtest_verbose)
    argc++;
  if (!subtest_mode_fatal)
    argc++;
  if (subtest_mode_quick)
    argc++;
  else
    argc++;
  if (subtest_mode_perf)
    argc++;
  if (gtester_list_tests)
    argc++;
  if (subtest_seedstr)
    argc++;
  argc++;
  if (skip_tests)
    argc++;
  for (slist = subtest_paths; slist; slist = slist->next)
    argc++;

  /* setup argv */
  argv = g_malloc ((argc + 2) * sizeof(gchar *));
  argv[i++] = binary;
  for (slist = subtest_args; slist; slist = slist->next)
    argv[i++] = (gchar*) slist->data;
  /* argv[i++] = "--debug-log"; */
  if (subtest_quiet)
    argv[i++] = "--quiet";
  if (subtest_verbose)
    argv[i++] = "--verbose";
  if (!subtest_mode_fatal)
    argv[i++] = "--keep-going";
  if (subtest_mode_quick)
    argv[i++] = "-m=quick";
  else
    argv[i++] = "-m=slow";
  if (subtest_mode_perf)
    argv[i++] = "-m=perf";
  if (gtester_list_tests)
    argv[i++] = "-l";
  if (subtest_seedstr)
    argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--seed=%s", subtest_seedstr));
  argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestLogFD=%u", report_pipe[1]));
  if (skip_tests)
    argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestSkipCount=%u", skip_tests));
  for (slist = subtest_paths; slist; slist = slist->next)
    argv[i++] = queue_gfree (&free_list, g_strdup_printf ("-p=%s", (gchar*) slist->data));
  argv[i++] = NULL;

  g_spawn_async_with_pipes (NULL, /* g_get_current_dir() */
                            (gchar**) argv,
                            NULL, /* envp */
                            G_SPAWN_DO_NOT_REAP_CHILD, /* G_SPAWN_SEARCH_PATH */
                            unset_cloexec_fdp, &report_pipe[1], /* pre-exec callback */
                            &pid,
                            NULL,       /* standard_input */
                            NULL,       /* standard_output */
                            NULL,       /* standard_error */
                            &error);
  g_slist_foreach (free_list, (void(*)(void*,void*)) g_free, NULL);
  g_slist_free (free_list);
  free_list = NULL;
  close (report_pipe[1]);

  if (!gtester_quiet)
    g_print ("(pid=%lu)\n", (unsigned long) pid);

  if (error)
    {
      close (report_pipe[0]);
      if (subtest_mode_fatal)
        g_error ("Failed to execute test binary: %s: %s", argv[0], error->message);
      else
        g_warning ("Failed to execute test binary: %s: %s", argv[0], error->message);
      g_clear_error (&error);
      g_free (argv);
      return FALSE;
    }
  g_free (argv);

  subtest_running = TRUE;
  subtest_io_pending = TRUE;
  tlb = g_test_log_buffer_new();
  if (report_pipe[0] >= 0)
    {
      ioc_report = g_io_channel_unix_new (report_pipe[0]);
      g_io_channel_set_flags (ioc_report, G_IO_FLAG_NONBLOCK, NULL);
      g_io_channel_set_encoding (ioc_report, NULL, NULL);
      g_io_channel_set_buffered (ioc_report, FALSE);
      child_report_cb_id = g_io_add_watch_full (ioc_report, G_PRIORITY_DEFAULT - 1, G_IO_IN | G_IO_ERR | G_IO_HUP, child_report_cb, tlb, NULL);
      g_io_channel_unref (ioc_report);
    }
  g_child_watch_add_full (G_PRIORITY_DEFAULT + 1, pid, child_watch_cb, NULL, NULL);

  loop_pending = g_main_context_pending (NULL);
  while (subtest_running ||     /* FALSE once child exits */
         subtest_io_pending ||  /* FALSE once ioc_report closes */
         loop_pending)          /* TRUE while idler, etc are running */
    {
      /* g_print ("LOOPSTATE: subtest_running=%d subtest_io_pending=%d\n", subtest_running, subtest_io_pending); */
      /* check for unexpected hangs that are not signalled on report_pipe */
      if (!subtest_running &&   /* child exited */
          subtest_io_pending && /* no EOF detected on report_pipe */
          !loop_pending)        /* no IO events pending however */
        break;
      g_main_context_iteration (NULL, TRUE);
      loop_pending = g_main_context_pending (NULL);
    }

  g_source_remove (child_report_cb_id);
  close (report_pipe[0]);
  g_test_log_buffer_free (tlb);

  return TRUE;
}
char *
netstatus_sysdeps_read_iface_statistics (const char *iface,
					 gulong     *in_packets,
					 gulong     *out_packets,
					 gulong     *in_bytes,
					 gulong     *out_bytes)
{
  GError  *error;
  char    *command_line;
  char   **argv;
  char    *error_message = NULL;
  int      pipe_out;

  g_return_val_if_fail (iface != NULL, NULL);
  g_return_val_if_fail (in_packets != NULL, NULL);
  g_return_val_if_fail (out_packets != NULL, NULL);
  g_return_val_if_fail (in_bytes != NULL, NULL);
  g_return_val_if_fail (out_bytes != NULL, NULL);

  *in_packets  = -1;
  *out_packets = -1;
  *in_bytes    = -1;
  *out_bytes   = -1;

  error = NULL;
  command_line = g_strdup_printf ("/usr/bin/netstat -n -I %s -b -f inet", iface);
  if (!g_shell_parse_argv (command_line, NULL, &argv, &error))
    {
      error_message = g_strdup_printf (_("Could not parse command line '%s': %s"),
				       command_line,
				       error->message);
      g_error_free (error);
      g_free (command_line);
      
      return error_message;
    }
  g_free (command_line);

  error = NULL;
  if (g_spawn_async_with_pipes (NULL,
				argv,
				NULL,
				0,
				NULL,
				NULL,
				NULL,
				NULL,
				&pipe_out,
				NULL,
				&error))
    {
      GIOChannel *channel;
      char       *buf;
      int         prx_idx, ptx_idx;
      int         brx_idx, btx_idx;

      channel = g_io_channel_unix_new (pipe_out);

      g_io_channel_read_line (channel, &buf, NULL, NULL, NULL);
      parse_header (buf, &prx_idx, &ptx_idx, &brx_idx, &btx_idx);
      g_free (buf);

      if (prx_idx == -1 || ptx_idx == -1 ||
	  brx_idx == -1 || btx_idx == -1)
	{
	  error_message = g_strdup (_("Could not parse 'netstat' output. Unknown format"));
	  goto error_shutdown;
	}

      g_io_channel_read_line (channel, &buf, NULL, NULL, NULL);

      if (!parse_stats (buf,
			prx_idx, ptx_idx, in_packets, out_packets,
			brx_idx, btx_idx, in_bytes, out_bytes))
	{
	  error_message = g_strdup_printf (_("Could not parse interface statistics from '%s'. "
					     "prx_idx = %d; ptx_idx = %d; brx_idx = %d; btx_idx = %d;"),
					   buf, prx_idx, ptx_idx, brx_idx, btx_idx);
	}
      else if (*in_packets == -1 || *out_packets == -1 || *in_bytes == -1 || *out_bytes == -1)
	{
	  error_message = g_strdup_printf ("Could not obtain information on interface '%s' from netstat",
					   iface);
	}

      g_free (buf);

    error_shutdown:
      g_io_channel_unref (channel);
      close (pipe_out);
    }
  else
    {
      error_message = g_strdup_printf ("Error running /usr/bin/netstat for '%s': %s", 
				       iface, error->message);
      g_error_free (error);
    }

  g_strfreev (argv);

  return error_message;
}
Exemple #24
0
/**
 * Execute synchronously an external command, read its output and invoke
 * a user-provided filter function on every line of it.
 */
int execute_shell_command(char **cmd, parse_cb_t cb_func, void *cb_arg)
{
    struct exec_ctx     ctx = { 0 };
    GPid                pid;
    GError             *err_desc = NULL;
    GSpawnFlags         flags = G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD;
    GIOChannel         *out_chan = NULL;
    GIOChannel         *err_chan = NULL;
    struct io_chan_arg  out_args;
    struct io_chan_arg  err_args;
    char               *log_cmd;
    int                 p_stdout;
    int                 p_stderr;
    bool                success;
    int                 rc = 0;

    ctx.gctx = g_main_context_new();
    g_main_context_push_thread_default(ctx.gctx);
    ctx.loop = g_main_loop_new(ctx.gctx, false);
    ctx.ref = 0;
    ctx.rc = 0;

    DisplayLog(LVL_DEBUG, TAG, "Spawning external command \"%s\"", cmd[0]);

    success = g_spawn_async_with_pipes(NULL,    /* Working dir */
                                       cmd, /* Parameters */
                                       NULL,    /* Environment */
                                       flags,   /* Execution directives */
                                       NULL,    /* Child setup function */
                                       NULL,    /* Child setup arg */
                                       &pid,    /* Child PID */
                                       NULL,    /* STDIN (unused) */
                                       cb_func ? &p_stdout : NULL,  /* STDOUT */
                                       cb_func ? &p_stderr : NULL,  /* STDERR */
                                       &err_desc);
    if (!success) {
        rc = -ECHILD;
        log_cmd = concat_cmd(cmd);
        DisplayLog(LVL_MAJOR, TAG, "Failed to execute \"%s\": %s",
                   log_cmd, err_desc->message);
        free(log_cmd);
        goto out_free;
    }

    /* register a watcher in the loop, thus increase refcount of our exec_ctx */
    ctx_incref(&ctx);
    g_child_watch_add_tothread(pid, watch_child_cb, &ctx);

    if (cb_func != NULL) {
        out_args.ident    = STDOUT_FILENO;
        out_args.cb       = cb_func;
        out_args.udata    = cb_arg;
        out_args.exec_ctx = &ctx;
        err_args.ident    = STDERR_FILENO;
        err_args.cb       = cb_func;
        err_args.udata    = cb_arg;
        err_args.exec_ctx = &ctx;

        out_chan = g_io_channel_unix_new(p_stdout);
        err_chan = g_io_channel_unix_new(p_stderr);

        /* instruct the refcount system to close the channels when unused */
        g_io_channel_set_close_on_unref(out_chan, true);
        g_io_channel_set_close_on_unref(err_chan, true);

        if ((rc = iochan_null_enc(out_chan)) ||
            (rc = iochan_null_enc(err_chan)))
            goto out_free;

        /* update refcount for the two watchers */
        ctx_incref(&ctx);
        ctx_incref(&ctx);

        g_io_add_watch_tothread(out_chan, G_IO_IN | G_IO_HUP,
                                readline_cb, &out_args);
        g_io_add_watch_tothread(err_chan, G_IO_IN | G_IO_HUP,
                                readline_cb, &err_args);
    }

    g_main_loop_run(ctx.loop);

 out_free:
    g_main_loop_unref(ctx.loop);
    g_main_context_pop_thread_default(ctx.gctx);
    g_main_context_unref(ctx.gctx);

    if (err_desc)
        g_error_free(err_desc);

    return rc ? rc : ctx.rc;
}
Exemple #25
0
GPid
storage_daemon_spawn_for_variant (StorageDaemon *daemon,
                                  const gchar **argv,
                                  const GVariantType *type,
                                  void (*callback) (GPid, GVariant *, GError *, gpointer),
                                  gpointer user_data)
{
  GError *error = NULL;
  struct VariantReaderData *data;
  gchar *prog = NULL;
  GPid pid;
  gint output_fd;
  gchar *cmd;

  /*
   * This is so we can override the location of storaged-lvm-helper
   * during testing.
   */

  if (!strchr (argv[0], '/'))
    {
      prog = storage_daemon_get_resource_path (daemon, TRUE, argv[0]);
      argv[0] = prog;
    }

  cmd = g_strjoinv (" ", (gchar **)argv);
  g_debug ("spawning for variant: %s", cmd);
  g_free (cmd);

  if (!g_spawn_async_with_pipes (NULL,
                                 (gchar **)argv,
                                 NULL,
                                 G_SPAWN_DO_NOT_REAP_CHILD,
                                 NULL,
                                 NULL,
                                 &pid,
                                 NULL,
                                 &output_fd,
                                 NULL,
                                 &error))
    {
      callback (0, NULL, error, user_data);
      g_error_free (error);
      return 0;
    }

  data = g_new0 (struct VariantReaderData, 1);

  data->type = type;
  data->callback = callback;
  data->user_data = user_data;

  data->pid = pid;
  data->output = g_byte_array_new ();
  data->output_channel = g_io_channel_unix_new (output_fd);
  g_io_channel_set_encoding (data->output_channel, NULL, NULL);
  g_io_channel_set_flags (data->output_channel, G_IO_FLAG_NONBLOCK, NULL);
  data->output_watch = g_io_add_watch (data->output_channel, G_IO_IN, variant_reader_child_output, data);

  g_child_watch_add_full (G_PRIORITY_DEFAULT_IDLE,
                          pid, variant_reader_watch_child, data, variant_reader_destroy);

  g_free (prog);
  return pid;
}
Exemple #26
0
static void exec_spawn_process (ExecCmd *e, GSpawnChildSetupFunc child_setup)
{
	/* Make sure that the args are null terminated */
	g_ptr_array_add(e->args, NULL);
	exec_print_cmd(e);
	gint std_out = 0, std_err = 0;
	GError *err = NULL;
	const GSpawnFlags flags = (GSpawnFlags) (G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN
			| G_SPAWN_DO_NOT_REAP_CHILD);
	if (g_spawn_async_with_pipes(NULL, (gchar**) e->args->pdata, NULL, flags, child_setup, e, &e->pid, NULL, &std_out,
			&std_err, &err)) {
		g_debug("exec_spawn_process - spawed process with pid [" FMT_PID "]\n", e->pid);

		if (!e->piped) {
			GIOChannel* const char_out = g_io_channel_unix_new(std_out);
			g_io_channel_set_encoding(char_out, NULL, NULL);
			g_io_channel_set_buffered(char_out, FALSE);
			g_io_channel_set_flags(char_out, G_IO_FLAG_NONBLOCK, NULL);
			guint const chan_out_id = g_io_add_watch(char_out,
					(GIOCondition)(G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI | G_IO_NVAL), exec_channel_callback,
					(gpointer) e);

			GIOChannel* const chan_err = g_io_channel_unix_new(std_err);
			g_io_channel_set_encoding(chan_err, NULL, NULL);
			g_io_channel_set_buffered(chan_err, FALSE);
			g_io_channel_set_flags(chan_err, G_IO_FLAG_NONBLOCK, NULL);
			guint const chan_err_id = g_io_add_watch(chan_err,
					(GIOCondition)(G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI | G_IO_NVAL), exec_channel_callback,
					(gpointer) e);

			while (exec_cmd_get_state(e) == RUNNING)
				gtk_main_iteration();

			g_source_remove(chan_out_id);
			g_source_remove(chan_err_id);
			g_io_channel_shutdown(char_out, FALSE, NULL);
			g_io_channel_unref(char_out);
			g_io_channel_shutdown(chan_err, FALSE, NULL);
			g_io_channel_unref(chan_err);
		} else {
			while ((waitpid(e->pid, &e->exit_code, WNOHANG) != -1) && (exec_cmd_get_state(e) == RUNNING))
				g_usleep(500000);
		}

		/* If the process was cancelled then we kill off the child */
		if (exec_cmd_get_state(e) == CANCELLED) {
			g_debug("exec_spawn_process - killing process with pid [" FMT_PID "]\n", e->pid);
			gint ret = kill(e->pid, SIGQUIT);
			g_debug("exec_spawn_process - SIGQUIT returned [%d]\n", ret);
			if (ret != 0) {
				ret = kill(e->pid, SIGTERM);
				g_debug("exec_spawn_process - SIGTERM returned [%d]\n", ret);
				if (ret != 0) {
					ret = kill(e->pid, SIGKILL);
					g_debug("exec_spawn_process - SIGKILL returned [%d]\n", ret);
				}
			}
		}

		/* Reap the child so we don't get a zombie */
		waitpid(e->pid, &e->exit_code, 0);
		g_spawn_close_pid(e->pid);
		close(std_out);
		close(std_err);

		exec_cmd_set_state(e, (e->exit_code == 0) ? COMPLETED : FAILED);
		g_debug("exec_spawn_process - child [" FMT_PID "] exitcode [%d]\n", e->pid, e->exit_code);
	} else {
		if (err != NULL)
			g_warning("exec_spawn_process - failed to spawn process [%d] [%s]\n", err->code, err->message);
		exec_cmd_set_state(e, FAILED);
		if (err != NULL)
			g_error_free(err);
	}
}
Exemple #27
0
		if (!spawn_parse_argv(command_line, &cl_argc, &cl_argv, error))
			return FALSE;

		if (argv)
			for (argc = 0; argv[argc]; argc++);

		full_argv = g_renew(gchar *, cl_argv, cl_argc + argc + 1);
		memcpy(full_argv + cl_argc, argv, argc * sizeof(gchar *));
		full_argv[cl_argc + argc] = NULL;
	}
	else
		full_argv = argv;

	spawned = g_spawn_async_with_pipes(working_directory, full_argv, envp,
		G_SPAWN_SEARCH_PATH | (child_pid ? G_SPAWN_DO_NOT_REAP_CHILD : 0), NULL, NULL,
		child_pid, stdin_fd, stdout_fd, stderr_fd, &gerror);

	if (!spawned)
	{
		gint en = 0;
		const gchar *message = gerror->message;

		/* try to cut glib citing of the program name or working directory: they may be long,
		   and only the caller knows whether they're UTF-8. We lose the exact chdir error. */
		switch (gerror->code)
		{
		#ifdef EACCES
			case G_SPAWN_ERROR_ACCES : en = EACCES; break;
		#endif
		#ifdef EPERM
Exemple #28
0
void
gvfs_udisks2_utils_spawn (guint                timeout_seconds,
                          GCancellable        *cancellable,
                          GAsyncReadyCallback  callback,
                          gpointer             user_data,
                          const gchar         *command_line_format,
                          ...)
{
  va_list var_args;
  SpawnData *data;
  GError *error;
  gint child_argc;
  gchar **child_argv = NULL;

  data = g_slice_new0 (SpawnData);
  data->simple = g_simple_async_result_new (NULL,
                                            callback,
                                            user_data,
                                            gvfs_udisks2_utils_spawn);
  data->main_context = g_main_context_get_thread_default ();
  if (data->main_context != NULL)
    g_main_context_ref (data->main_context);

  data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;

  va_start (var_args, command_line_format);
  data->command_line = g_strdup_vprintf (command_line_format, var_args);
  va_end (var_args);

  data->child_stdout = g_string_new (NULL);
  data->child_stderr = g_string_new (NULL);
  data->child_stdout_fd = -1;
  data->child_stderr_fd = -1;

  /* the life-cycle of SpawnData is tied to its GSimpleAsyncResult */
  g_simple_async_result_set_op_res_gpointer (data->simple, data, (GDestroyNotify) spawn_data_free);

  error = NULL;
  if (data->cancellable != NULL)
    {
      /* could already be cancelled */
      error = NULL;
      if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
        {
          g_simple_async_result_take_error (data->simple, error);
          g_simple_async_result_complete_in_idle (data->simple);
          g_object_unref (data->simple);
          goto out;
        }

      data->cancellable_handler_id = g_cancellable_connect (data->cancellable,
                                                            G_CALLBACK (on_cancelled),
                                                            data,
                                                            NULL);
    }

  error = NULL;
  if (!g_shell_parse_argv (data->command_line,
                           &child_argc,
                           &child_argv,
                           &error))
    {
      g_prefix_error (&error,
                      "Error parsing command-line `%s': ",
                      data->command_line);
      g_simple_async_result_take_error (data->simple, error);
      g_simple_async_result_complete_in_idle (data->simple);
      g_object_unref (data->simple);
      goto out;
    }

  error = NULL;
  if (!g_spawn_async_with_pipes (NULL, /* working directory */
                                 child_argv,
                                 NULL, /* envp */
                                 G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
                                 NULL, /* child_setup */
                                 NULL, /* child_setup's user_data */
                                 &(data->child_pid),
                                 NULL, /* gint *stdin_fd */
                                 &(data->child_stdout_fd),
                                 &(data->child_stderr_fd),
                                 &error))
    {
      g_prefix_error (&error,
                      "Error spawning command-line `%s': ",
                      data->command_line);
      g_simple_async_result_take_error (data->simple, error);
      g_simple_async_result_complete_in_idle (data->simple);
      g_object_unref (data->simple);
      goto out;
    }

  if (timeout_seconds > 0)
    {
      data->timeout_source = g_timeout_source_new_seconds (timeout_seconds);
      g_source_set_priority (data->timeout_source, G_PRIORITY_DEFAULT);
      g_source_set_callback (data->timeout_source, timeout_cb, data, NULL);
      g_source_attach (data->timeout_source, data->main_context);
      g_source_unref (data->timeout_source);
    }

  data->child_watch_source = g_child_watch_source_new (data->child_pid);
  g_source_set_callback (data->child_watch_source, (GSourceFunc) child_watch_cb, data, NULL);
  g_source_attach (data->child_watch_source, data->main_context);
  g_source_unref (data->child_watch_source);

  data->child_stdout_channel = g_io_channel_unix_new (data->child_stdout_fd);
  g_io_channel_set_flags (data->child_stdout_channel, G_IO_FLAG_NONBLOCK, NULL);
  data->child_stdout_source = g_io_create_watch (data->child_stdout_channel, G_IO_IN);
  g_source_set_callback (data->child_stdout_source, (GSourceFunc) read_child_stdout, data, NULL);
  g_source_attach (data->child_stdout_source, data->main_context);
  g_source_unref (data->child_stdout_source);

  data->child_stderr_channel = g_io_channel_unix_new (data->child_stderr_fd);
  g_io_channel_set_flags (data->child_stderr_channel, G_IO_FLAG_NONBLOCK, NULL);
  data->child_stderr_source = g_io_create_watch (data->child_stderr_channel, G_IO_IN);
  g_source_set_callback (data->child_stderr_source, (GSourceFunc) read_child_stderr, data, NULL);
  g_source_attach (data->child_stderr_source, data->main_context);
  g_source_unref (data->child_stderr_source);

 out:
  g_strfreev (child_argv);
}