--- gksu-2.0.2/gksu/gksu.c-orig 2010-12-16 03:43:51.275486079 -0600
+++ gksu-2.0.2/gksu/gksu.c 2010-12-16 03:46:11.151315385 -0600
@@ -9,6 +9,8 @@
#include <string.h>
#include <getopt.h>
#include <locale.h>
+#include <dlfcn.h>
+#include <link.h>
#include <glib.h>
#include <glib/gstdio.h>
@@ -27,6 +29,9 @@
gboolean print_pass = FALSE;
gboolean force_grab = FALSE;
gboolean prompt = FALSE;
+gboolean elevated_privilege = TRUE;
+gboolean elevated_role = TRUE;
+
enum
{
SUDO_MODE,
@@ -40,10 +45,14 @@ struct option long_opts[] = {
*/
{"help", no_argument, NULL, 'h'},
{"login", no_argument, NULL, 'l'},
+#ifndef __sun
{"preserv-env", no_argument, NULL, 'k'},
{"preserve-env", no_argument, NULL, 'k'},
+#endif
{"user", required_argument, NULL, 'u'},
+#ifndef __sun
{"print-pass", no_argument, NULL, 'p'},
+#endif
{"message", required_argument, NULL, 'm'},
{"title", required_argument, NULL, 't'},
{"icon", required_argument, NULL, 'i'},
@@ -55,6 +64,8 @@ struct option long_opts[] = {
{"prompt", optional_argument, NULL, 'P'},
{"desktop", required_argument, NULL, 'D'},
{"description", required_argument, NULL, 'D'},
+ {"elevated-privilege", no_argument, NULL, 'p'},
+ {"elevated-role", no_argument, NULL, 'r'},
{0, 0, 0, 0}
};
@@ -106,12 +117,14 @@ help (gchar *cmdname)
" Replace the standard message shown to ask for\n"
" password for the argument passed to the option.\n"
" Only use this if --description does not suffice.\n"),
+#ifndef __sun
N_("\n"),
N_(" --print-pass, -p\n"
" Ask gksu to print the password to stdout, just\n"
" like ssh-askpass. Useful to use in scripts with\n"
" programs that accept receiving the password on\n"
" stdin.\n"),
+#endif
N_("\n"),
N_(" --sudo-mode, -S\n"
" Make GKSu use sudo instead of su, as if it had been\n"
@@ -119,6 +132,13 @@ help (gchar *cmdname)
N_(" --su-mode, -w\n"
" Make GKSu use su, instead of using libgksu's\n"
" default.\n"),
+#ifdef __sun
+ N_("\n"),
+ N_(" --elevated-privilege, -p\n"
+ " attempt to elevate user's privilege\n"),
+ N_(" --elevated-role, -r\n"
+ " attempt to elevate user's role\n"),
+#endif
};
help_trans = g_strconcat(_(help_text[0]), _(help_text[1]),
@@ -157,6 +177,14 @@ gk_dialog (GtkMessageType type, gchar *f
gtk_window_set_resizable (GTK_WINDOW(diag_win), FALSE);
gtk_widget_show_all (diag_win);
+
+ // we "raise" the window because there is a race here for
+ // focus-follow-mouse and auto-raise WMs that may put the window
+ // in the background and confuse users
+ gtk_window_set_keep_above(GTK_WINDOW (diag_win), TRUE);
+ // reset cursor
+ gdk_window_set_cursor(diag_win->window, gdk_cursor_new(GDK_LEFT_PTR));
+
gtk_dialog_run (GTK_DIALOG(diag_win));
g_free (msg);
@@ -271,10 +299,12 @@ show_hide_advanced (GtkWidget *button, g
else
gksu_context_set_login_shell (context, FALSE);
+#ifndef __sun
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(check_presenv)))
gksu_context_set_keep_env (context, TRUE);
else
gksu_context_set_keep_env (context, FALSE);
+#endif
gtk_widget_destroy (dialog);
}
@@ -334,8 +364,15 @@ fill_with_user_list(GtkWidget *combobox)
endpwent();
}
+static gboolean
+focus_out_cb (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
+{
+ gtk_window_present (GTK_WINDOW(widget));
+ return TRUE;
+}
+
void
-request_command_and_user (GksuContext *context)
+request_command_and_user (GksuContext *context, gchar *command)
{
GtkWidget *dialog;
GtkWidget *hbox;
@@ -347,7 +384,12 @@ request_command_and_user (GksuContext *c
GtkWidget *entry_cmd;
GtkWidget *label_user;
- GtkWidget *combo_user;
+ GtkWidget *entry_user;
+
+ AtkObject *atk_user_label;
+ AtkObject *atk_user_entry;
+ AtkObject *atk_command_label;
+ AtkObject *atk_command_entry;
/* advanced stuff */
GtkWidget *advanced_button;
@@ -362,6 +404,11 @@ request_command_and_user (GksuContext *c
GTK_STOCK_OK,
GTK_RESPONSE_OK,
NULL);
+
+ /* make sure that our window will always have the focus */
+ g_signal_connect (G_OBJECT(dialog), "focus-out-event",
+ G_CALLBACK(focus_out_cb), NULL);
+
gtk_dialog_set_has_separator (GTK_DIALOG(dialog), FALSE);
/* horizontal box */
@@ -385,14 +432,44 @@ request_command_and_user (GksuContext *c
dialog);
gtk_box_pack_start (GTK_BOX(lvbox), entry_cmd, TRUE, TRUE, 0);
+ if (command)
+ {
+ gtk_entry_set_text (GTK_ENTRY (entry_cmd), command);
+ gtk_editable_set_editable (GTK_EDITABLE (entry_cmd), FALSE);
+ gtk_widget_set_sensitive (entry_cmd, FALSE);
+ }
+
+ atk_command_label = gtk_widget_get_accessible (label_cmd);
+ atk_command_entry = gtk_widget_get_accessible (entry_cmd);
+ atk_object_add_relationship (atk_command_label, ATK_RELATION_LABEL_FOR,
+ atk_command_entry);
+ atk_object_add_relationship (atk_command_entry, ATK_RELATION_LABELLED_BY,
+ atk_command_label);
+
/* user name */
- label_user = gtk_label_new (_("As user:"));
+ /* SUN_BRANDING label */
+ label_user = gtk_label_new (_("As user or role:"));
gtk_label_set_justify (GTK_LABEL(label_user), GTK_JUSTIFY_LEFT);
gtk_box_pack_start (GTK_BOX(lvbox), label_user, TRUE, TRUE, 0);
- combo_user = gtk_combo_box_new_text ();
- fill_with_user_list (combo_user);
- gtk_box_pack_start (GTK_BOX(lvbox), combo_user, TRUE, TRUE, 0);
+ entry_user = gtk_entry_new ();
+ gtk_signal_connect (GTK_OBJECT(entry_user), "activate",
+ GTK_SIGNAL_FUNC(response_ok_cb),
+ dialog);
+
+ if (context->user)
+ {
+ gtk_entry_set_text (GTK_ENTRY (entry_user), context->user);
+ }
+
+ atk_user_label = gtk_widget_get_accessible (label_user);
+ atk_user_entry = gtk_widget_get_accessible (entry_user);
+ atk_object_add_relationship (atk_user_label, ATK_RELATION_LABEL_FOR,
+ atk_user_entry);
+ atk_object_add_relationship (atk_user_entry, ATK_RELATION_LABELLED_BY,
+ atk_user_label);
+
+ gtk_box_pack_start (GTK_BOX(lvbox), entry_user, TRUE, TRUE, 0);
/* right vertical box */
rvbox = gtk_vbox_new (FALSE, 2);
@@ -430,18 +507,14 @@ request_command_and_user (GksuContext *c
g_free (tmp);
}
- tmp = gtk_combo_box_get_active_text (GTK_COMBO_BOX(combo_user));
+ tmp = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry_user)));
if (tmp)
{
gksu_context_set_user (context, tmp);
g_free (tmp);
}
- if (!strcmp (gksu_context_get_user (context), ""))
- {
- gk_dialog (GTK_MESSAGE_ERROR, _("Missing command to run."));
- }
- else
+ if (strcmp (gksu_context_get_user (context), ""))
{
gtk_widget_destroy (dialog);
break;
@@ -465,7 +538,7 @@ main (int argc, char **argv)
int c = 0;
- setlocale (LC_ALL, "");
+ setlocale (6, "");
bindtextdomain(PACKAGE_NAME, LOCALEDIR);
bind_textdomain_codeset (PACKAGE_NAME, "UTF-8");
textdomain(PACKAGE_NAME);
@@ -502,7 +575,13 @@ main (int argc, char **argv)
gtk_init (&newargc, &newargv);
context = gksu_context_new ();
- while ((c = getopt_long(newargc, newargv, "?hu:lpm:kt:i:gdsSwP::aD:", long_opts, NULL))
+ /*
+ * First character is + since we want gksu to accept all arguments after the
+ * first operand as part of the operand. So you can run
+ * "gksu -u root command -x". Without the "+", getopt_long incorrectly
+ * treats the "-x" as a gksu argument rather than a command argument.
+ */
+ while ((c = getopt_long(newargc, newargv, "+?hu:lpm:kt:i:gdsSwP::aD:", long_opts, NULL))
!= EOF)
{
switch (c)
@@ -525,14 +604,20 @@ main (int argc, char **argv)
gksu_context_set_login_shell (context, TRUE);
break;
case 'p':
+#ifndef __sun
print_pass = TRUE;
+#else
+ gksu_context_set_elevated_privilege (context, FALSE);
+#endif
break;
case 'm':
gksu_context_set_message (context, optarg);
break;
+#ifndef __sun
case 'k':
gksu_context_set_keep_env (context, TRUE);
break;
+#endif
case 'g':
gksu_context_set_grab (context, FALSE);
@@ -565,6 +650,9 @@ main (int argc, char **argv)
case 'w':
run_mode = SU_MODE;
break;
+ case 'r':
+ gksu_context_set_elevated_role (context, FALSE);
+ break;
case 'P':
prompt = TRUE;
@@ -646,9 +734,14 @@ main (int argc, char **argv)
return 0;
}
+ if (gksu_context_get_pfexec_mode (context))
+ {
+ gksu_context_set_need_pipe (context, FALSE);
+ }
+
/* now we can begin to care about a command */
if (newargc <= optind)
- request_command_and_user (context); /* previously known as gksuexec */
+ request_command_and_user (context, NULL); /* previously known as gksuexec */
else
{
gchar *command = g_strdup (newargv[optind]);
@@ -693,7 +786,27 @@ main (int argc, char **argv)
g_free (command);
command = tmp;
}
- gksu_context_set_command (context, command);
+
+ context->command = g_strdup (command);
+
+ if (strcmp (g_get_user_name (), "root") == 0)
+ {
+ /* If root, just use pfexec */
+ context->pfexec_mode = TRUE;
+ context->user = g_strdup ("root");
+ }
+ else if (run_mode != SUDO_MODE)
+ {
+ if (gksu_context_try_need_password (context))
+ {
+ request_command_and_user (context, command);
+ }
+ }
+ else
+ {
+ request_command_and_user (context, command);
+ }
+
g_free (command);
}
@@ -714,7 +827,8 @@ main (int argc, char **argv)
return 1;
}
- if (pwentry->pw_uid == geteuid ())
+ /* If in pfexec mode, process in gksu_sudo_fuller */
+ if (!gksu_context_get_pfexec_mode (context) && pwentry->pw_uid == geteuid ())
{
gint retval = g_spawn_command_line_sync (gksu_context_get_command (context),
NULL, NULL, NULL, NULL);
@@ -722,18 +836,6 @@ main (int argc, char **argv)
}
}
- {
- gint count = 0;
-
- for (count = 0; count < 3; count++)
- {
- if (error) /* wrong password was given */
- {
- gksu_context_set_alert (context, _("<b>Incorrect password... try again.</b>"));
- g_error_free (error);
- error = NULL;
- }
-
if (run_mode == SUDO_MODE)
gksu_sudo_fuller (context,
NULL, NULL,
@@ -753,18 +855,25 @@ main (int argc, char **argv)
NULL, NULL,
&exit_status,
&error);
- if ((error == NULL) || (error->code != GKSU_ERROR_WRONGPASS))
- break;
- }
- }
if (error && (error->code != GKSU_ERROR_CANCELED))
{
+ char *msg;
+
+ if (context->alert != NULL)
+ {
+ msg = context->alert;
+ }
+ else
+ {
+ msg = error->message;
+ }
+
gk_dialog (GTK_MESSAGE_ERROR,
_("<b>Failed to run %s as user %s.</b>\n\n%s"),
gksu_context_get_command (context),
gksu_context_get_user (context),
- error->message);
+ msg);
return 3;
}