static void add_identities(GtkComboBox *combo, GList *identities)
{
	GList *p;
	GtkCellRenderer *column;
	GtkListStore *store;

	store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_OBJECT);
	for (p = identities; p != NULL; p = p->next) {
		gchar *str = NULL;
		PolkitIdentity *id = (PolkitIdentity *)p->data;
		if(POLKIT_IS_UNIX_USER(id)) {
			uid_t uid = polkit_unix_user_get_uid(POLKIT_UNIX_USER(id));
			struct passwd *pwd = getpwuid(uid);
			str = g_strdup(pwd->pw_name);
		} else if(POLKIT_IS_UNIX_GROUP(id)) {
			gid_t gid = polkit_unix_group_get_gid(POLKIT_UNIX_GROUP(id));
			struct group *grp = getgrgid(gid);
			str = g_strdup_printf(_("Group: %s"), grp->gr_name);
		} else {
			str = polkit_identity_to_string(id);
		}
		gtk_list_store_insert_with_values(store, NULL, -1,
						  0, str,
						  1, id,
						  -1);
		g_free(str);
	}
	gtk_combo_box_set_model(combo, GTK_TREE_MODEL(store));
	g_object_unref(store);

	column = gtk_cell_renderer_text_new();
	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), column, TRUE);
	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), column,
				       "text", 0, NULL);
}
static void
auth_request_initiate (AuthRequest *request)
{
    gchar **user_names;
    GPtrArray *p;
    GList *l;

    p = g_ptr_array_new ();
    for (l = request->identities; l != NULL; l = l->next)
    {
        if (POLKIT_IS_UNIX_USER (l->data))
        {
            PolkitUnixUser *user = POLKIT_UNIX_USER (l->data);
            gint uid;
            gchar buf[4096];
            struct passwd pwd;
            struct passwd *ppwd;

            uid = polkit_unix_user_get_uid (user);
            if (getpwuid_r (uid, &pwd, buf, sizeof (buf), &ppwd) == 0)
            {
                if (!g_utf8_validate (pwd.pw_name, -1, NULL))
                {
                    g_warning ("Invalid UTF-8 in username for uid %d. Skipping", uid);
                }
                else
                {
                    g_ptr_array_add (p, g_strdup (pwd.pw_name));
                }
            }
            else
            {
                g_warning ("Error looking up user name for uid %d", uid);
            }
        }
        else
        {
            g_warning ("Unsupporting identity of GType %s", g_type_name (G_TYPE_FROM_INSTANCE (l->data)));
        }
    }
    g_ptr_array_add (p, NULL);
    user_names = (gchar **) g_ptr_array_free (p, FALSE);
    g_signal_emit (request->agent,
                   signals[INITIATE_SIGNAL],
                   0, /* detail */
                   request->action_id,
                   request->message,
                   request->icon_name,
                   request->cookie,
                   user_names);
    g_strfreev (user_names);
}
static gint
compare_users (gconstpointer a, gconstpointer b)
{
	char *user;
	int ret;

	if (POLKIT_IS_UNIX_USER (a))
		user = g_strdup (polkit_unix_user_get_name (POLKIT_UNIX_USER (a)));
	else
		user = polkit_identity_to_string (POLKIT_IDENTITY (a));

	ret = g_strcmp0 ((const char *) user, (const char *) b);
	g_free (user);
	return ret;
}
static void
cockpit_polkit_agent_initiate_authentication (PolkitAgentListener *listener,
                                              const gchar *action_id,
                                              const gchar *message,
                                              const gchar *icon_name,
                                              PolkitDetails *details,
                                              const gchar *cookie,
                                              GList *identities,
                                              GCancellable *cancellable,
                                              GAsyncReadyCallback callback,
                                              gpointer user_data)
{
  CockpitPolkitAgent *self = COCKPIT_POLKIT_AGENT (listener);
  PolkitIdentity *identity = NULL;
  GSimpleAsyncResult *result = NULL;
  GString *unsupported = NULL;
  ReauthorizeCaller *caller;
  gchar *string;
  uid_t uid;
  GList *l;

  const gchar *argv[] = {
    PACKAGE_LIBEXEC_DIR "/cockpit-polkit",
    cookie,
    NULL,
  };

  g_debug ("polkit is requesting authentication");

  result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
                                      cockpit_polkit_agent_initiate_authentication);

  uid = getuid ();

  unsupported = g_string_new ("");
  for (l = identities; l != NULL; l = g_list_next (l))
    {
      if (POLKIT_IS_UNIX_USER (l->data))
        {
          if (polkit_unix_user_get_uid (l->data) == uid)
            {
              identity = g_object_ref (l->data);
              break;
            }
        }

      string = polkit_identity_to_string (l->data);
      g_string_append_printf (unsupported, "%s ", string);
      g_free (string);
    }

  if (!identity)
    {
      g_message ("cannot reauthorize identity(s): %s", unsupported->str);
      g_simple_async_result_set_error (result, POLKIT_ERROR, POLKIT_ERROR_FAILED,
                                       "Reauthorization not supported for identity");
      g_simple_async_result_complete_in_idle (result);
      goto out;
    }

  string = polkit_identity_to_string (identity);
  g_message ("Reauthorizing %s", string);
  g_free (string);

  caller = g_new0 (ReauthorizeCaller, 1);
  caller->cookie = g_strdup (cookie);
  caller->helper = cockpit_pipe_spawn (argv, NULL, NULL, COCKPIT_PIPE_FLAGS_NONE);
  caller->read_sig = g_signal_connect (caller->helper, "read", G_CALLBACK (on_helper_read), caller);
  caller->close_sig = g_signal_connect (caller->helper, "close", G_CALLBACK (on_helper_close), caller);

  caller->cancellable = g_object_ref (cancellable);
  caller->cancel_sig = g_cancellable_connect (cancellable, G_CALLBACK (on_cancelled), caller, NULL);

  caller->result = g_object_ref (result);
  caller->self = self;

  g_hash_table_replace (self->callers, caller->cookie, caller);

  g_debug ("cockpit-polkit helper starting");

out:
  if (unsupported)
    g_string_free (unsupported, TRUE);
  g_object_unref (result);
  if (identity)
    g_object_unref (identity);
}
static void
initiate_authentication (PolkitAgentListener  *listener,
                         const char           *action_id,
                         const char           *message,
                         const char           *icon_name,
                         PolkitDetails        *details,
                         const char           *cookie,
                         GList                *identities,
                         GCancellable         *cancellable,
                         GAsyncReadyCallback   callback,
                         gpointer              user_data)
{
	NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (listener);
	GSimpleAsyncResult *simple;
	PolkitIdentity *identity;

	simple = g_simple_async_result_new (G_OBJECT (listener),
	                                    callback,
	                                    user_data,
	                                    initiate_authentication);
	if (priv->active_session != NULL) {
		g_simple_async_result_set_error (simple,
		                                 POLKIT_ERROR,
		                                 POLKIT_ERROR_FAILED,
		                                 _("An authentication session is already underway."));
		g_simple_async_result_complete_in_idle (simple);
		g_object_unref (simple);
		return;
	}

	/* Choose identity */
	identity = choose_identity (identities);

	priv->active_session = polkit_agent_session_new (identity, cookie);
	g_signal_connect (priv->active_session,
	                  "completed",
	                  G_CALLBACK (on_completed),
	                  listener);
	g_signal_connect (priv->active_session,
	                  "request",
	                  G_CALLBACK (on_request),
	                  listener);
	g_signal_connect (priv->active_session,
	                  "show-info",
	                  G_CALLBACK (on_show_info),
	                  listener);
	g_signal_connect (priv->active_session,
	                  "show-error",
	                  G_CALLBACK (on_show_error),
	                  listener);

	priv->action_id = g_strdup (action_id);
	priv->message = g_strdup (message);
	priv->icon_name = g_strdup (icon_name);
	if (POLKIT_IS_UNIX_USER (identity))
		priv->identity = g_strdup (polkit_unix_user_get_name (POLKIT_UNIX_USER (identity)));
	else
		priv->identity = polkit_identity_to_string (identity);

	priv->simple = simple;
	priv->cancellable = g_object_ref (cancellable);
	priv->cancel_id = g_cancellable_connect (cancellable,
	                                         G_CALLBACK (on_cancelled),
	                                         listener,
	                                         NULL);

	polkit_agent_session_initiate (priv->active_session);
}
static void initiate_authentication(PolkitAgentListener  *listener,
                                    const gchar          *action_id,
                                    const gchar          *message,
                                    const gchar          *icon_name,
                                    PolkitDetails        *details,
                                    const gchar          *cookie,
                                    GList                *identities,
                                    GCancellable         *cancellable,
                                    GAsyncReadyCallback   callback,
                                    gpointer              user_data)
{
    GtkBuilder* b = gtk_builder_new();
    GtkWidget *icon, *msg, *detail, *id_hbox;
    GList* l;
    DlgData* data = g_slice_new0(DlgData);
    DEBUG("init_authentication");
    DEBUG("action_id = %s", action_id);
#ifdef G_ENABLE_DEBUG
    char** p;
    for(p = polkit_details_get_keys(details);*p;++p)
        DEBUG("%s: %s", *p, polkit_details_lookup(details, *p));
#endif
    data->listener = (LXPolkitListener*)listener;
    data->result = g_simple_async_result_new(listener, callback, user_data, initiate_authentication);

    data->action_id = g_strdup(action_id);
    data->cancellable = (GCancellable*)g_object_ref(cancellable);
    data->callback = callback;
    data->user_data = user_data;
    data->cookie = g_strdup(cookie);

    /* create the dialog, load from GtkBuilder ui definition file. */
    gtk_builder_add_from_file(b, PACKAGE_UI_DIR "/lxpolkit.ui", NULL);
    data->dlg = (GtkWidget*)gtk_builder_get_object(b, "dlg");
    icon = (GtkWidget*)gtk_builder_get_object(b, "icon");
    msg = (GtkWidget*)gtk_builder_get_object(b, "msg");
    detail = (GtkWidget*)gtk_builder_get_object(b, "detail");
    id_hbox = (GtkWidget*)gtk_builder_get_object(b, "id_hbox");
    data->id = (GtkWidget*)gtk_builder_get_object(b, "id");
    data->request = (GtkWidget*)gtk_builder_get_object(b, "request");
    data->request_label = (GtkWidget*)gtk_builder_get_object(b, "request_label");
    g_object_unref(b);

    g_signal_connect(data->dlg, "response", G_CALLBACK(on_dlg_response), data);
    g_signal_connect(cancellable, "cancelled", G_CALLBACK(on_cancelled), data);

    gtk_dialog_set_alternative_button_order(GTK_DIALOG(data->dlg), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL);
    gtk_dialog_set_default_response(GTK_DIALOG(data->dlg), GTK_RESPONSE_OK);
    gtk_window_set_icon_name(GTK_WINDOW(data->dlg), GTK_STOCK_DIALOG_AUTHENTICATION);

    /* set dialog icon */
    if(icon_name && *icon_name)
        gtk_image_set_from_icon_name(GTK_IMAGE(icon), icon_name, GTK_ICON_SIZE_DIALOG);
    else
        gtk_image_set_from_stock(GTK_IMAGE(icon), GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG);

    /* set message prompt */
    gtk_label_set_text(GTK_LABEL(msg), message);

    /* create combo box for user selection */
    if( identities )
    {
        GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_OBJECT);
        g_signal_connect(data->id, "changed", G_CALLBACK(on_user_changed), data);
        for(l = identities; l; l=l->next)
        {
            PolkitIdentity* id = (PolkitIdentity*)l->data;
            char* name;
            if(POLKIT_IS_UNIX_USER(id))
            {
                struct passwd* pwd = getpwuid(polkit_unix_user_get_uid(POLKIT_UNIX_USER(id)));
                gtk_list_store_insert_with_values(store, NULL, -1, 0, pwd->pw_name, 1, id, -1);
            }
            else if(POLKIT_IS_UNIX_GROUP(id))
            {
                struct group* grp = getgrgid(polkit_unix_group_get_gid(POLKIT_UNIX_GROUP(id)));
                char* str = g_strdup_printf(_("Group: %s"), grp->gr_name);
                gtk_list_store_insert_with_values(store, NULL, -1, 0, str, 1, id, -1);
                g_free(str);
            }
            else
            {
                /* FIXME: what's this? */
                char* str = polkit_identity_to_string(id);
                gtk_list_store_insert_with_values(store, NULL, -1, 0, str, 1, id, -1);
                g_free(str);
            }
        }
        gtk_combo_box_set_model(data->id, GTK_TREE_MODEL(store));
        g_object_unref(store);
        /* select the fist user in the list */
        gtk_combo_box_set_active(data->id, 0);
    }
    else
    {
        DEBUG("no identities list, is this an error?");
        gtk_widget_hide(id_hbox);
        g_simple_async_result_complete_in_idle(data->result);
        dlg_data_free(data);
        return;
    }
    gtk_window_present(GTK_WINDOW(data->dlg));
}