/**
 * terminal_client_append_exec_options:
 * @builder: a #GVariantBuilder of #GVariantType "a{sv}"
 * @working_directory: (allow-none): the cwd, or %NULL
 * @shell:
 *
 * Appends the environment and the working directory to @builder.
 */
void 
terminal_client_append_exec_options (GVariantBuilder *builder,
                                     const char      *working_directory,
                                     gboolean         shell)
{
  gs_strfreev char **envv;

  envv = g_get_environ ();
  envv = g_environ_unsetenv (envv, "COLORTERM");
  envv = g_environ_unsetenv (envv, "COLUMNS");
  envv = g_environ_unsetenv (envv, "DESKTOP_STARTUP_ID");
  envv = g_environ_unsetenv (envv, "DISPLAY");
  envv = g_environ_unsetenv (envv, "GIO_LAUNCHED_DESKTOP_FILE_PID");
  envv = g_environ_unsetenv (envv, "GIO_LAUNCHED_DESKTOP_FILE");
  envv = g_environ_unsetenv (envv, "GNOME_DESKTOP_ICON");
  envv = g_environ_unsetenv (envv, "LINES");
  envv = g_environ_unsetenv (envv, "PWD");
  envv = g_environ_unsetenv (envv, "TERM");
  envv = g_environ_unsetenv (envv, "WINDOWID");

  g_variant_builder_add (builder, "{sv}",
                         "environ",
                         g_variant_new_bytestring_array ((const char * const *) envv, -1));

  if (working_directory)
    g_variant_builder_add (builder, "{sv}", 
                           "cwd", g_variant_new_bytestring (working_directory));

  if (shell)
    g_variant_builder_add (builder, "{sv}",
                           "shell",
                           g_variant_new_boolean (TRUE));
}
/* FIXME: make this async */
static gboolean
create_terminal (ExecData *data /* transfer full */)
{
  TerminalFactory *factory;
  TerminalReceiver *receiver;
  GError *error = NULL;
  GVariantBuilder builder;
  char *object_path;
  char startup_id[32];
  char **argv;
  int argc;

  factory = terminal_factory_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
                                                     G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
                                                     G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
                                                     TERMINAL_APPLICATION_ID,
                                                     TERMINAL_FACTORY_OBJECT_PATH,
                                                     NULL /* cancellable */,
                                                     &error);
  if (factory == NULL) {
    g_dbus_error_strip_remote_error (error);
    g_printerr ("Error constructing proxy for %s:%s: %s\n",
                TERMINAL_APPLICATION_ID, TERMINAL_FACTORY_OBJECT_PATH,
                error->message);
    g_error_free (error);
    exec_data_free (data);
    return FALSE;
  }

  g_snprintf (startup_id, sizeof (startup_id), "_TIME%u", data->timestamp);

  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));

  terminal_client_append_create_instance_options (&builder,
                                                  data->display,
                                                  startup_id,
                                                  NULL /* geometry */,
                                                  NULL /* role */,
                                                  NULL /* use default profile */,
                                                  NULL /* title */,
                                                  TRUE, /* active */
                                                  FALSE /* maximised */,
                                                  FALSE /* fullscreen */);

  if (!terminal_factory_call_create_instance_sync
         (factory,
          g_variant_builder_end (&builder),
          &object_path,
          NULL /* cancellable */,
          &error)) {
    g_dbus_error_strip_remote_error (error);
    g_printerr ("Error creating terminal: %s\n", error->message);
    g_error_free (error);
    g_object_unref (factory);
    exec_data_free (data);
    return FALSE;
  }

  g_object_unref (factory);

  receiver = terminal_receiver_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
                                                       G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
                                                       G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
                                                       TERMINAL_APPLICATION_ID,
                                                       object_path,
                                                       NULL /* cancellable */,
                                                       &error);
  if (receiver == NULL) {
    g_dbus_error_strip_remote_error (error);
    g_printerr ("Failed to create proxy for terminal: %s\n", error->message);
    g_error_free (error);
    g_free (object_path);
    exec_data_free (data);
    return FALSE;
  }

  g_free (object_path);

  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));

  terminal_client_append_exec_options (&builder,
                                       data->path,
                                       NULL, 0, /* FD array */
                                       TRUE /* shell */);

  if (data->info == FILE_INFO_SFTP &&
      data->remote) {
    argv = ssh_argv (data->uri, data->run_in_mc, &argc);
  } else if (data->run_in_mc) {
    argv = mc_argv (&argc);
  } else {
    argv = NULL; argc = 0;
  }

  if (!terminal_receiver_call_exec_sync (receiver,
                                         g_variant_builder_end (&builder),
                                         g_variant_new_bytestring_array ((const char * const *) argv, argc),
                                         NULL /* in FD list */,
                                         NULL /* out FD list */,
                                         NULL /* cancellable */,
                                         &error)) {
    g_dbus_error_strip_remote_error (error);
    g_printerr ("Error: %s\n", error->message);
    g_error_free (error);
    g_strfreev (argv);
    g_object_unref (receiver);
    exec_data_free (data);
    return FALSE;
  }

  g_strfreev (argv);

  exec_data_free (data);

  g_object_unref (receiver);

  return TRUE;
}
Esempio n. 3
0
/**
 * handle_options:
 * @app:
 * @options: a #TerminalOptions
 * @allow_resume: whether to merge the terminal configuration from the
 *   saved session on resume
 * @error: a #GError to fill in
 *
 * Processes @options. It loads or saves the terminal configuration, or
 * opens the specified windows and tabs.
 *
 * Returns: %TRUE if @options could be successfully handled, or %FALSE on
 *   error
 */
static gboolean
handle_options (TerminalFactory *factory,
                TerminalOptions *options,
                GError **error)
{
  GList *lw;
  GError *err;

#if 0
  gdk_screen = terminal_app_get_screen_by_display_name (options->display_name,
                                                        options->screen_number);
#endif

  /* Make sure we open at least one window */
  terminal_options_ensure_window (options);

  for (lw = options->initial_windows;  lw != NULL; lw = lw->next)
    {
      InitialWindow *iw = lw->data;
      GList *lt;
      guint window_id;

      g_assert (iw->tabs);

      window_id = 0;

      /* Now add the tabs */
      for (lt = iw->tabs; lt != NULL; lt = lt->next)
        {
          InitialTab *it = lt->data;
          GVariantBuilder builder;
          char *object_path, *p;
          TerminalReceiver *receiver;
          char **argv;
          int argc;

          err = NULL;

          g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));

          terminal_client_append_create_instance_options (&builder,
                                                          options->display_name,
                                                          options->startup_id,
                                                          iw->geometry,
                                                          iw->role,
                                                          it->profile ? it->profile : options->default_profile,
                                                          it->title ? it->title : options->default_title,
                                                          iw->start_maximized,
                                                          iw->start_fullscreen);

          if (window_id)
            g_variant_builder_add (&builder, "{sv}",
                                   "window-id", g_variant_new_uint32 (window_id));

          /* Restored windows shouldn't demand attention; see bug #586308. */
          if (iw->source_tag == SOURCE_SESSION)
            g_variant_builder_add (&builder, "{sv}",
                                   "present-window", g_variant_new_boolean (FALSE));
          if (options->zoom_set || it->zoom_set)
            g_variant_builder_add (&builder, "{sv}",
                                   "zoom", g_variant_new_double (it->zoom_set ? it->zoom : options->zoom));
          if (iw->force_menubar_state)
            g_variant_builder_add (&builder, "{sv}",
                                   "show-menubar", g_variant_new_boolean (iw->menubar_state));
#if 0
          if (it->active)
            terminal_window_switch_screen (window, screen);
#endif

          if (!terminal_factory_call_create_instance_sync 
                 (factory,
                  g_variant_builder_end (&builder),
                  &object_path,
                  NULL /* cancellable */,
                  &err)) {
            g_dbus_error_strip_remote_error (err);
            g_printerr ("Error creating terminal: %s\n", err->message);
            g_error_free (err);

            /* Continue processing the remaining options! */
            continue;
          }

          p = strstr (object_path, "/window/");
          if (p) {
            char *end = NULL;
            guint64 value;

            errno = 0;
            p += strlen ("/window/");
            value = g_ascii_strtoull (p, &end, 10);
            if (errno == 0 && end != p && *end == '/')
              window_id = (guint) value;
          }

          receiver = terminal_receiver_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
                                                               G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
                                                               G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
                                                               options->server_app_id ? options->server_app_id
                                                                                      : TERMINAL_APPLICATION_ID,
                                                               object_path,
                                                               NULL /* cancellable */,
                                                               &err);
          if (receiver == NULL) {
            g_dbus_error_strip_remote_error (err);
            g_printerr ("Failed to create proxy for terminal: %s\n", err->message);
            g_error_free (err);
            g_free (object_path);

            /* Continue processing the remaining options! */
            continue;
          }
          g_free (object_path);

          g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));

          argv = it->exec_argv ? it->exec_argv : options->exec_argv,
          argc = argv ? g_strv_length (argv) : 0;

          terminal_client_append_exec_options (&builder,
                                               it->working_dir ? it->working_dir 
                                                               : options->default_working_dir,
                                               argc == 0);

          if (!terminal_receiver_call_exec_sync (receiver,
                                                 g_variant_builder_end (&builder),
                                                 g_variant_new_bytestring_array ((const char * const *) argv, argc),
                                                 NULL /* infdlist */, NULL /* outfdlist */,
                                                NULL /* cancellable */,
                                                &err)) {
            g_dbus_error_strip_remote_error (err);
            g_printerr ("Error: %s\n", err->message);
            g_error_free (err);
          }

          g_object_unref (receiver);
        }
    }

  return TRUE;
}
Esempio n. 4
0
/**
 * g_dbus_gvalue_to_gvariant:
 * @gvalue: A #GValue to convert to a #GVariant
 * @type: A #GVariantType
 *
 * Converts a #GValue to a #GVariant of the type indicated by the @type
 * parameter.
 *
 * The conversion is using the following rules:
 *
 * - #G_TYPE_STRING: 's', 'o', 'g' or 'ay'
 * - #G_TYPE_STRV: 'as', 'ao' or 'aay'
 * - #G_TYPE_BOOLEAN: 'b'
 * - #G_TYPE_UCHAR: 'y'
 * - #G_TYPE_INT: 'i', 'n'
 * - #G_TYPE_UINT: 'u', 'q'
 * - #G_TYPE_INT64 'x'
 * - #G_TYPE_UINT64: 't'
 * - #G_TYPE_DOUBLE: 'd'
 * - #G_TYPE_VARIANT: Any #GVariantType
 *
 * This can fail if e.g. @gvalue is of type #G_TYPE_STRING and @type
 * is ['i'][G-VARIANT-TYPE-INT32:CAPS]. It will also fail for any #GType
 * (including e.g. #G_TYPE_OBJECT and #G_TYPE_BOXED derived-types) not
 * in the table above.
 *
 * Note that if @gvalue is of type #G_TYPE_VARIANT and its value is
 * %NULL, the empty #GVariant instance (never %NULL) for @type is
 * returned (e.g. 0 for scalar types, the empty string for string types,
 * '/' for object path types, the empty array for any array type and so on).
 *
 * See the g_dbus_gvariant_to_gvalue() function for how to convert a
 * #GVariant to a #GValue.
 *
 * Returns: A #GVariant (never floating) of #GVariantType @type holding
 *     the data from @gvalue or %NULL in case of failure. Free with
 *     g_variant_unref().
 *
 * Since: 2.30
 */
GVariant *
g_dbus_gvalue_to_gvariant (const GValue       *gvalue,
                           const GVariantType *type)
{
  GVariant *ret;
  const gchar *s;
  const gchar * const *as;
  const gchar *empty_strv[1] = {NULL};

  g_return_val_if_fail (gvalue != NULL, NULL);
  g_return_val_if_fail (type != NULL, NULL);

  ret = NULL;

  /* @type can easily be e.g. "s" with the GValue holding a GVariant - for example this
   * can happen when using the org.gtk.GDBus.C.ForceGVariant annotation with the
   * gdbus-codegen(1) tool.
   */
  if (G_VALUE_TYPE (gvalue) == G_TYPE_VARIANT)
    {
      ret = g_value_dup_variant (gvalue);
    }
  else
    {
      switch (g_variant_type_peek_string (type)[0])
        {
        case G_VARIANT_CLASS_BOOLEAN:
          ret = g_variant_ref_sink (g_variant_new_boolean (g_value_get_boolean (gvalue)));
          break;

        case G_VARIANT_CLASS_BYTE:
          ret = g_variant_ref_sink (g_variant_new_byte (g_value_get_uchar (gvalue)));
          break;

        case G_VARIANT_CLASS_INT16:
          ret = g_variant_ref_sink (g_variant_new_int16 (g_value_get_int (gvalue)));
          break;

        case G_VARIANT_CLASS_UINT16:
          ret = g_variant_ref_sink (g_variant_new_uint16 (g_value_get_uint (gvalue)));
          break;

        case G_VARIANT_CLASS_INT32:
          ret = g_variant_ref_sink (g_variant_new_int32 (g_value_get_int (gvalue)));
          break;

        case G_VARIANT_CLASS_UINT32:
          ret = g_variant_ref_sink (g_variant_new_uint32 (g_value_get_uint (gvalue)));
          break;

        case G_VARIANT_CLASS_INT64:
          ret = g_variant_ref_sink (g_variant_new_int64 (g_value_get_int64 (gvalue)));
          break;

        case G_VARIANT_CLASS_UINT64:
          ret = g_variant_ref_sink (g_variant_new_uint64 (g_value_get_uint64 (gvalue)));
          break;

        case G_VARIANT_CLASS_DOUBLE:
          ret = g_variant_ref_sink (g_variant_new_double (g_value_get_double (gvalue)));
          break;

        case G_VARIANT_CLASS_STRING:
          s = g_value_get_string (gvalue);
          if (s == NULL)
            s = "";
          ret = g_variant_ref_sink (g_variant_new_string (s));
          break;

        case G_VARIANT_CLASS_OBJECT_PATH:
          s = g_value_get_string (gvalue);
          if (s == NULL)
            s = "/";
          ret = g_variant_ref_sink (g_variant_new_object_path (s));
          break;

        case G_VARIANT_CLASS_SIGNATURE:
          s = g_value_get_string (gvalue);
          if (s == NULL)
            s = "";
          ret = g_variant_ref_sink (g_variant_new_signature (s));
          break;

        case G_VARIANT_CLASS_ARRAY:
          switch (g_variant_type_peek_string (type)[1])
            {
            case G_VARIANT_CLASS_BYTE:
              s = g_value_get_string (gvalue);
              if (s == NULL)
                s = "";
              ret = g_variant_ref_sink (g_variant_new_bytestring (s));
              break;

            case G_VARIANT_CLASS_STRING:
              as = g_value_get_boxed (gvalue);
              if (as == NULL)
                as = empty_strv;
              ret = g_variant_ref_sink (g_variant_new_strv (as, -1));
              break;

            case G_VARIANT_CLASS_OBJECT_PATH:
              as = g_value_get_boxed (gvalue);
              if (as == NULL)
                as = empty_strv;
              ret = g_variant_ref_sink (g_variant_new_objv (as, -1));
              break;

            case G_VARIANT_CLASS_ARRAY:
              switch (g_variant_type_peek_string (type)[2])
                {
                case G_VARIANT_CLASS_BYTE:
                  as = g_value_get_boxed (gvalue);
                  if (as == NULL)
                    as = empty_strv;
                  ret = g_variant_ref_sink (g_variant_new_bytestring_array (as, -1));
                  break;

                default:
                  ret = g_value_dup_variant (gvalue);
                  break;
                }
              break;

            default:
              ret = g_value_dup_variant (gvalue);
              break;
            }
          break;

        case G_VARIANT_CLASS_HANDLE:
        case G_VARIANT_CLASS_VARIANT:
        case G_VARIANT_CLASS_MAYBE:
        case G_VARIANT_CLASS_TUPLE:
        case G_VARIANT_CLASS_DICT_ENTRY:
          ret = g_value_dup_variant (gvalue);
          break;
        }
    }

  /* Could be that the GValue is holding a NULL GVariant - in that case,
   * we return an "empty" GVariant instead of a NULL GVariant
   */
  if (ret == NULL)
    {
      GVariant *untrusted_empty;
      untrusted_empty = g_variant_new_from_data (type, NULL, 0, FALSE, NULL, NULL);
      ret = g_variant_ref_sink (g_variant_get_normal_form (untrusted_empty));
      g_variant_unref (untrusted_empty);
    }

  g_assert (!g_variant_is_floating (ret));

  return ret;
}