Index: configure.in
===================================================================
--- configure.in	(revision 2210)
+++ configure.in	(working copy)
@@ -33,10 +33,41 @@
 PCRECPP_REQUIRED=6.4
 GTKMM_REQUIRED=2.8
 LIBXML_REQUIRED=2.0
+POLKIT_GNOME_REQUIRED=0.7
+POLKIT_DBUS_REQUIRED=0.7
+DBUS_GLIB_REQUIRED=0.71
+DBUS_REQUIRED=1.1.2
 
 PKG_CHECK_MODULES(PROCMAN, glib-2.0 >= $GLIB_REQUIRED gconf-2.0 >= $GCONF_REQUIRED libgtop-2.0 >= $LIBGTOP_REQUIRED libwnck-1.0 >= $LIBWNCK_REQUIRED gtk+-2.0 >= $GTK_REQUIRED gnome-vfs-2.0 >= $GNOME_VFS_REQUIRED gnome-icon-theme >= $GNOME_ICON_THEME_REQUIRED gtkmm-2.4 >= $GTKMM_REQUIRED libxml-2.0 >= $LIBXML_REQUIRED)
 
+# PolicyKit detection; defaults to 'auto' (use it if it's available)
+#
+POLKIT_GNOME_CFLAGS=
+POLKIT_GNOME_LIBS=
+POLKIT_DBUS_CFLAGS=
+POLKIT_DBUS_LIBS=
+AC_ARG_ENABLE(polkit, AS_HELP_STRING([--enable-polkit],[Enable PolicyKit support (auto)]),enable_polkit=$enableval,enable_polkit=auto)
+if test "x$enable_polkit" = "xno" ; then
+   HAVE_POLKIT=no
+else
+   HAVE_POLKIT=no
+   PKG_CHECK_MODULES(POLKIT_GNOME, polkit-gnome >= $POLKIT_GNOME_REQUIRED dbus-1 >= $DBUS_REQUIRED, HAVE_POLKIT=yes, HAVE_POLKIT=no)
 
+   if test "x$enable_polkit" = "xyes" -a "x$HAVE_POLKIT" = "xno" ; then
+     AC_MSG_ERROR(PolicyKit support explicity enabled but not available)
+   fi
+
+   if test "x$HAVE_POLKIT" = "xyes" ; then
+      AC_DEFINE(HAVE_POLKIT, 1, [Defined if PolicyKit support is enabled])
+      PKG_CHECK_MODULES(POLKIT_DBUS, polkit-dbus >= $POLKIT_DBUS_REQUIRED dbus-glib-1 >= $DBUS_GLIB_REQUIRED gobject-2.0)
+    fi
+fi
+AM_CONDITIONAL(HAVE_POLKIT, test "x$HAVE_POLKIT" = "xyes")
+AC_SUBST(POLKIT_GNOME_CFLAGS)
+AC_SUBST(POLKIT_GNOME_LIBS)
+AC_SUBST(POLKIT_DBUS_CFLAGS)
+AC_SUBST(POLKIT_DBUS_LIBS)
+
 AC_ARG_ENABLE([pcrecpp], AS_HELP_STRING([--enable-pcrecpp], [Enable pcrecpp. You really want this ! (but default: disabled)]), [enable_pcrecpp=$enableval], [enable_pcrecpp=no])
 
 if test "x$enable_pcrecpp" = "xyes" ; then
@@ -113,6 +144,7 @@
 	CFLAGS:			${CFLAGS}
 	CXXFLAGS:		${CXXFLAGS}
 	pcrecpp:		${enable_pcrecpp}
+        PolicyKit support:      ${HAVE_POLKIT}
 	Maintainer mode:	${USER_MAINTAINER_MODE}
 	Languages:		${ALL_LINGUAS}
 "
Index: src/procman.h
===================================================================
--- src/procman.h	(revision 2210)
+++ src/procman.h	(working copy)
@@ -32,6 +32,11 @@
 
 #include <map>
 
+#ifdef HAVE_POLKIT
+#  include <dbus/dbus-glib.h>
+#  include <polkit-gnome/polkit-gnome.h>
+#endif
+
 typedef struct _ProcConfig ProcConfig;
 struct ProcInfo;
 struct ProcData;
@@ -197,7 +202,19 @@
 	GtkWidget	*app;
 	GtkUIManager	*menu;
 
+#ifdef HAVE_POLKIT
+        DBusGProxy *mechanism_proxy;
 
+        PolKitAction *pk_action_kill;
+        PolKitAction *pk_action_change_priority;
+        PolKitAction *pk_action_increase_own_priority;
+
+        PolKitGnomeAction *sigstop_action;
+        PolKitGnomeAction *sigcont_action;
+        PolKitGnomeAction *sigterm_action;
+        PolKitGnomeAction *sigkill_action;
+#endif
+
 	/* cached username */
 	GStringChunk	*users;
 
Index: src/procman.cpp
===================================================================
--- src/procman.cpp	(revision 2210)
+++ src/procman.cpp	(working copy)
@@ -33,6 +33,10 @@
 #include <glibtop/close.h>
 #include <glibtop/loadavg.h>
 
+#ifdef HAVE_POLKIT
+#  include <dbus/dbus-glib.h>
+#endif
+
 #include "load-graph.h"
 #include "procman.h"
 #include "interface.h"
@@ -55,9 +59,36 @@
     disk_timeout(0),
     cpu_total_time(1),
     cpu_total_time_last(1)
-{ }
+{
+#ifdef HAVE_POLKIT
+        GError *error;
+        DBusGConnection *bus;
 
+        error = NULL;
+        bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (bus == NULL) {
+                g_warning ("Couldn't connect to system bus: %s", error->message);
+                g_error_free (error);
+                this->mechanism_proxy = NULL;        
+        } else {
+                this->mechanism_proxy = dbus_g_proxy_new_for_name (bus,
+                                                                   "org.gnome.SystemMonitor.Mechanism",
+                                                                   "/",
+                                                                   "org.gnome.SystemMonitor.Mechanism");
+        }
 
+        this->pk_action_kill = polkit_action_new ();
+        polkit_action_set_action_id (this->pk_action_kill, "org.gnome.system-monitor.kill");
+
+        this->pk_action_change_priority = polkit_action_new ();
+        polkit_action_set_action_id (this->pk_action_change_priority, "org.gnome.system-monitor.change-priority");
+
+        this->pk_action_increase_own_priority = polkit_action_new ();
+        polkit_action_set_action_id (this->pk_action_increase_own_priority, "org.gnome.system-monitor.increase-own-priority");
+#endif
+}
+
+
 ProcData* ProcData::get_instance()
 {
   static ProcData instance;
Index: src/interface.cpp
===================================================================
--- src/interface.cpp	(revision 2210)
+++ src/interface.cpp	(working copy)
@@ -30,6 +30,10 @@
 #include <gdk/gdkkeysyms.h>
 #include <math.h>
 
+#ifdef HAVE_POLKIT
+#  include <polkit-gnome/polkit-gnome.h>
+#endif
+
 #include "procman.h"
 #include "callbacks.h"
 #include "interface.h"
@@ -57,6 +61,7 @@
 	  N_("Quit the program"), G_CALLBACK (cb_app_exit) },
 
 
+#ifndef HAVE_POLKIT
 	{ "StopProcess", NULL, N_("_Stop Process"), "<control>S",
 	  N_("Stop process"), G_CALLBACK(cb_kill_sigstop) },
 	{ "ContProcess", NULL, N_("_Continue Process"), "<control>C",
@@ -66,6 +71,7 @@
 	  N_("Force process to finish normally"), G_CALLBACK (cb_end_process) },
 	{ "KillProcess", NULL, N_("_Kill Process"), "<control>K",
 	  N_("Force process to finish immediately"), G_CALLBACK (cb_kill_process) },
+#endif
 	{ "ChangePriority", NULL, N_("_Change Priority..."), "<control>R",
 	  N_("Change the order of priority of process"), G_CALLBACK (cb_renice) },
 	{ "Preferences", GTK_STOCK_PREFERENCES, NULL, NULL,
@@ -180,10 +186,14 @@
 	hbox2 = gtk_hbox_new (FALSE, 0);
 	gtk_box_pack_start (GTK_BOX (vbox1), hbox2, FALSE, FALSE, 0);
 	
+#ifdef HAVE_POLKIT
+	procdata->endprocessbutton = polkit_gnome_action_create_button (procdata->sigterm_action);
+#else
 	procdata->endprocessbutton = gtk_button_new_with_mnemonic (_("End _Process"));
-	gtk_box_pack_end (GTK_BOX (hbox2), procdata->endprocessbutton, FALSE, FALSE, 0);
 	g_signal_connect (G_OBJECT (procdata->endprocessbutton), "clicked",
 			  G_CALLBACK (cb_end_process_button_pressed), procdata);
+#endif
+	gtk_box_pack_end (GTK_BOX (hbox2), procdata->endprocessbutton, FALSE, FALSE, 0);
 	
 	
 	/* create popup_menu */
@@ -704,6 +714,45 @@
 					    G_CALLBACK(cb_radio_processes),
 					    procdata);
 
+#ifdef HAVE_POLKIT
+        procdata->sigstop_action = polkit_gnome_action_new_default ("StopProcess", 
+                                                                    NULL, 
+                                                                    _("_Stop Process"), 
+                                                                    _("Stop process"));
+        g_object_set (procdata->sigstop_action, "auth-label", _("_Stop Process..."), NULL);
+        g_signal_connect (procdata->sigstop_action, "activate", G_CALLBACK (cb_kill_sigstop), procdata);
+        gtk_action_group_add_action_with_accel (procdata->action_group, 
+                                                GTK_ACTION (procdata->sigstop_action), 
+                                                "<control>S");
+
+        procdata->sigcont_action = polkit_gnome_action_new_default ("ContProcess", 
+                                                                    NULL, 
+                                                                    _("_Continue Process"), 
+                                                                    _("Continue process"));
+        g_object_set (procdata->sigcont_action, "auth-label", _("_Continue Process..."), NULL);
+        g_signal_connect (procdata->sigcont_action, "activate", G_CALLBACK (cb_kill_sigcont), procdata);
+        gtk_action_group_add_action_with_accel (procdata->action_group, GTK_ACTION (procdata->sigcont_action), 
+                                                "<control>C");
+
+        procdata->sigterm_action = polkit_gnome_action_new_default ("EndProcess", 
+                                                                    NULL, 
+                                                                    _("End _Process"), 
+                                                                    _("Force process to finish normally"));
+        g_object_set (procdata->sigterm_action, "auth-label", _("End _Process..."), NULL);
+        g_signal_connect (procdata->sigterm_action, "activate", G_CALLBACK (cb_end_process), procdata);
+        gtk_action_group_add_action_with_accel (procdata->action_group, GTK_ACTION (procdata->sigterm_action), 
+                                                "<control>E");
+
+        procdata->sigkill_action = polkit_gnome_action_new_default ("KillProcess", 
+                                                                    NULL, 
+                                                                    _("_Kill Process"), 
+                                                                    _("Force process to finish immediately"));
+        g_object_set (procdata->sigkill_action, "auth-label", _("_Kill Process..."), NULL);
+        g_signal_connect (procdata->sigkill_action, "activate", G_CALLBACK (cb_kill_process), procdata);
+        gtk_action_group_add_action_with_accel (procdata->action_group, GTK_ACTION (procdata->sigkill_action), 
+                                                "<control>K");
+#endif
+
 	gtk_ui_manager_insert_action_group (procdata->uimanager,
 	                                    procdata->action_group,
 	                                    0);
@@ -711,7 +760,6 @@
 	menubar = gtk_ui_manager_get_widget (procdata->uimanager, "/MenuBar");
 	gtk_box_pack_start (GTK_BOX (main_box), menubar, FALSE, FALSE, 0);
 
-
 	/* create the main notebook */
 	notebook = gtk_notebook_new ();
   	gtk_box_pack_start (GTK_BOX (main_box), 
@@ -807,23 +855,53 @@
 	processes_sensitivity = (data->config.current_tab == PROCMAN_TAB_PROCESSES);
 	selected_sensitivity = (processes_sensitivity && data->selected_process != NULL);
 
+#ifndef HAVE_POLKIT
 	if(data->endprocessbutton) {
 		/* avoid error on startup if endprocessbutton
 		   has not been built yet */
 		gtk_widget_set_sensitive(data->endprocessbutton, selected_sensitivity);
 	}
+#endif
 
 	for (i = 0; i != G_N_ELEMENTS(processes_actions); ++i) {
 		action = gtk_action_group_get_action(data->action_group,
 						     processes_actions[i]);
-		gtk_action_set_sensitive(action, processes_sensitivity);
+		gtk_action_set_sensitive(action, selected_sensitivity);
 	}
 
 	for (i = 0; i != G_N_ELEMENTS(selected_actions); ++i) {
 		action = gtk_action_group_get_action(data->action_group,
 						     selected_actions[i]);
-		gtk_action_set_sensitive(action, selected_sensitivity);
+#ifdef HAVE_POLKIT
+                if (POLKIT_GNOME_IS_ACTION (action)) {
+                        polkit_gnome_action_set_sensitive (POLKIT_GNOME_ACTION (action), processes_sensitivity);
+                } else {
+                        gtk_action_set_sensitive(action, processes_sensitivity);
+                }
+#else
+		gtk_action_set_sensitive(action, processes_sensitivity);
+#endif
 	}
+
+#ifdef HAVE_POLKIT
+        /* update the PolicyKit actions */
+        if (data->selected_process != NULL) {
+                ProcInfo *pi = data->selected_process;
+                PolKitAction *pk_action;
+
+                /* TODO: multiple processes may be selected; consider all of them */
+
+                if (pi->uid == getuid ()) {
+                        pk_action = NULL;
+                } else {
+                        pk_action = data->pk_action_kill;
+                }
+                g_object_set (data->sigstop_action, "polkit-action", pk_action, NULL);
+                g_object_set (data->sigcont_action, "polkit-action", pk_action, NULL);
+                g_object_set (data->sigterm_action, "polkit-action", pk_action, NULL);
+                g_object_set (data->sigkill_action, "polkit-action", pk_action, NULL);
+        }
+#endif
 }
 
 static void		
Index: src/procdialogs.cpp
===================================================================
--- src/procdialogs.cpp	(revision 2210)
+++ src/procdialogs.cpp	(working copy)
@@ -35,6 +35,11 @@
 #include "procman_gnomesu.h"
 #include "procman_gksu.h"
 
+#ifdef HAVE_POLKIT
+#  include "gnome-system-monitor-mechanism-client-glue.h"
+#  include <polkit-gnome/polkit-gnome.h>
+#endif
+
 static GtkWidget *renice_dialog = NULL;
 static GtkWidget *prefs_dialog = NULL;
 static gint new_nice_value = 0;
@@ -121,29 +126,89 @@
 		return _("(Very Low Priority)");
 }
 
+typedef struct {
+        GtkWidget *priority_label;
+        ProcData *procdata;
+#ifdef HAVE_POLKIT
+        PolKitGnomeAction *renice_action;
+#endif
+} ReniceClosure;
+
+#ifdef HAVE_POLKIT
 static void
+_renice_compute_polkit_action (ReniceClosure *rc)
+{
+        if (rc->procdata->selected_process != NULL) {
+                ProcInfo *pi = rc->procdata->selected_process;
+
+                if (pi->uid == getuid ()) {
+                        if (new_nice_value < pi->nice) {
+                                GValue v;
+                                GValueArray *va;
+
+                                g_warning ("foo");
+
+                                memset (&v, 0, sizeof (GValue));
+                                g_value_init (&v, G_TYPE_POINTER);
+                                g_value_set_pointer (&v, rc->procdata->pk_action_change_priority);
+                                va = g_value_array_new (1);
+                                g_value_array_prepend (va, &v);
+
+                                g_object_set (rc->renice_action, 
+                                              "polkit-action", 
+                                              rc->procdata->pk_action_increase_own_priority,
+                                              "polkit-action-sufficient", 
+                                              va,
+                                              NULL);
+
+                                g_value_array_free (va);
+                                goto out;
+                        } 
+                } else {
+                        g_object_set (rc->renice_action, 
+                                      "polkit-action", 
+                                      rc->procdata->pk_action_change_priority, NULL);
+                        goto out;
+                }
+        }
+
+        g_object_set (rc->renice_action, "polkit-action", NULL, NULL);
+
+out:
+        ;
+}
+#endif
+
+static void
 renice_scale_changed (GtkAdjustment *adj, gpointer data)
 {
-	GtkWidget *label = GTK_WIDGET (data);
-	
+        ReniceClosure *rc = (ReniceClosure *) data;
+
 	new_nice_value = int(adj->value);
-	gtk_label_set_text (GTK_LABEL (label), get_nice_level (new_nice_value));		
-	
+	gtk_label_set_text (GTK_LABEL (rc->priority_label), get_nice_level (new_nice_value));		
+#ifdef HAVE_POLKIT
+        _renice_compute_polkit_action (rc);
+#endif
 }
 
 static void
 renice_dialog_button_pressed (GtkDialog *dialog, gint id, gpointer data)
 {
-	ProcData *procdata = static_cast<ProcData*>(data);
-	
+        ReniceClosure *rc = (ReniceClosure *) data;
+
 	if (id == 100) {
 		if (new_nice_value == -100)
 			return;		
-		renice(procdata, new_nice_value);
+		renice (rc->procdata, new_nice_value);
 	}
 	
 	gtk_widget_destroy (GTK_WIDGET (dialog));
 	renice_dialog = NULL;
+
+#ifdef HAVE_POLKIT
+        g_object_unref (G_OBJECT (rc->renice_action));
+#endif
+        g_free (rc);
 }
 
 void
@@ -153,22 +218,28 @@
 	GtkWidget *dialog = NULL;
 	GtkWidget *dialog_vbox;
 	GtkWidget *vbox;
-	GtkWidget *hbox;
   	GtkWidget *label;
   	GtkWidget *priority_label;
   	GtkWidget *table;
   	GtkObject *renice_adj;
   	GtkWidget *hscale;
 	GtkWidget *button;
+#ifndef HAVE_POLKIT
+	GtkWidget *hbox;
 	GtkWidget *align;
 	GtkWidget *icon;
+#endif
   	gchar *text;
+        ReniceClosure *rc;
 
 	if (renice_dialog)
 		return;
 		
 	if (!info)
 		return;
+
+        rc = g_new0 (ReniceClosure, 1);
+        rc->procdata = procdata;
 		
 	dialog = gtk_dialog_new_with_buttons (_("Change Priority"), NULL,
 				              GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -178,7 +249,20 @@
 	gtk_window_set_resizable (GTK_WINDOW (renice_dialog), FALSE);
 	gtk_dialog_set_has_separator (GTK_DIALOG (renice_dialog), FALSE);
 	gtk_container_set_border_width (GTK_CONTAINER (renice_dialog), 5);
-  	
+
+#ifdef HAVE_POLKIT
+        rc->renice_action = polkit_gnome_action_new_default ("ReniceProcessButton", 
+                                                             NULL,
+                                                             _("Change _Priority"),
+                                                             NULL);
+        g_object_set (rc->renice_action, 
+                      "auth-label", _("Change _Priority..."), 
+                      "yes-icon-name", GTK_STOCK_OK, 
+                      NULL);
+
+        button = polkit_gnome_action_create_button (rc->renice_action);
+	GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+#else  	
 	button = gtk_button_new ();
 	GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
 		
@@ -195,7 +279,9 @@
 	gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
 	gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
+#endif
 	gtk_dialog_add_action_widget (GTK_DIALOG (renice_dialog), button, 100);
+
   	gtk_dialog_set_default_response (GTK_DIALOG (renice_dialog), 100);
   	new_nice_value = -100;
   	  
@@ -236,15 +322,17 @@
 	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
     	gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 	g_free (text);
+
+        rc->priority_label = priority_label;
+        new_nice_value = info->nice;
+        _renice_compute_polkit_action (rc);
 	
 	g_signal_connect (G_OBJECT (dialog), "response",
-  			  G_CALLBACK (renice_dialog_button_pressed), procdata);
+  			  G_CALLBACK (renice_dialog_button_pressed), rc);
   	g_signal_connect (G_OBJECT (renice_adj), "value_changed",
-  			    G_CALLBACK (renice_scale_changed), priority_label);
+                          G_CALLBACK (renice_scale_changed), rc);
   	
     	gtk_widget_show_all (dialog);
-    	
-    	
 }
 
 static void
Index: src/callbacks.cpp
===================================================================
--- src/callbacks.cpp	(revision 2210)
+++ src/callbacks.cpp	(working copy)
@@ -36,25 +36,21 @@
 #include "disks.h"
 #include "lsof.h"
 
-
 void
 cb_kill_sigstop(GtkAction *action, gpointer data)
 {
 	ProcData * const procdata = static_cast<ProcData*>(data);
 
-	/* no confirmation */
+        /* no confirmation */
 	kill_process (procdata, SIGSTOP);
 }
 
-
-
-
 void
 cb_kill_sigcont(GtkAction *action, gpointer data)
 {
 	ProcData * const procdata = static_cast<ProcData*>(data);
 
-	/* no confirmation */
+        /* no confirmation */
 	kill_process (procdata, SIGCONT);
 }
 
@@ -208,11 +204,13 @@
 
 
 
+#ifndef HAVE_POLKIT
 void
 cb_end_process_button_pressed (GtkButton *button, gpointer data)
 {
 	kill_process_helper(static_cast<ProcData*>(data), SIGTERM);
 }
+#endif
 
 
 static void change_gconf_color(GConfClient *client, const char *key,
Index: src/procactions.cpp
===================================================================
--- src/procactions.cpp	(revision 2210)
+++ src/procactions.cpp	(working copy)
@@ -31,6 +31,10 @@
 #include "procdialogs.h"
 #include "callbacks.h"
 
+#ifdef HAVE_POLKIT
+#  include "gnome-system-monitor-mechanism-client-glue.h"
+#  include <polkit-gnome/polkit-gnome.h>
+#endif
 
 static void
 renice_single_process (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
@@ -48,6 +52,10 @@
 	if (!info)
 		return;
 
+        /* docs for getpriority suggest clearing errno before the call
+         * since -1 is a legitimate return value */
+        errno = 0; 
+
 	error = setpriority (PRIO_PROCESS, info->pid, args->nice_value);
 
 	/* success */
@@ -55,6 +63,28 @@
 
 	saved_errno = errno;
 
+#ifdef HAVE_POLKIT
+        /* need to be root */
+        if (errno == EPERM || errno == EACCES) {
+                GError *error = NULL;
+
+                if (!org_gnome_SystemMonitor_Mechanism_renice (args->procdata->mechanism_proxy, 
+                                                               info->pid, 
+                                                               args->nice_value,
+                                                               &error)) {
+                        /* TODO: Handle "require privileges" */
+                        error_msg = g_strdup_printf (
+                                _("Cannot renice process with pid %d to nice value %d: "
+                                  "%s"),
+                                info->pid, args->nice_value, error->message);
+                        g_error_free (error);
+                } else {
+                        return;
+                }
+        } else {
+                return;
+        }
+#else
 	/* need to be root */
 	if(errno == EPERM || errno == EACCES) {
 		gboolean success;
@@ -69,10 +99,11 @@
 			saved_errno = errno;
 		}
 	}
+#endif
 
 	/* failed */
 	error_msg = g_strdup_printf (
-		_("Cannot change the priority of process with pid %d to %d.\n"
+		_("Cannot change the priority of process with pid %d to %d: "
 		  "%s"),
 		info->pid, args->nice_value, g_strerror(saved_errno));
 
@@ -135,6 +166,28 @@
 
 	saved_errno = errno;
 
+#ifdef HAVE_POLKIT
+        /* need to be root */
+        if (errno == EPERM) {
+                GError *error = NULL;
+
+                if (!org_gnome_SystemMonitor_Mechanism_kill (args->procdata->mechanism_proxy, 
+                                                             info->pid, 
+                                                             args->signal,
+                                                             &error)) {
+                        /* TODO: Handle "require privileges" */
+                        error_msg = g_strdup_printf (
+                                _("Cannot kill process with pid %d with signal %d.\n"
+                                  "%s"),
+                                info->pid, args->signal, error->message);
+                        g_error_free (error);
+                } else {
+                        return;
+                }
+        } else {
+                return;
+        }
+#else
 	/* need to be root */
 	if(errno == EPERM) {
 		gboolean success;
@@ -149,12 +202,12 @@
 			saved_errno = errno;
 		}
 	}
-
 	/* failed */
 	error_msg = g_strdup_printf (
 		_("Cannot kill process with pid %d with signal %d.\n"
 		  "%s"),
 		info->pid, args->signal, g_strerror(saved_errno));
+#endif
 
 	dialog = gtk_message_dialog_new (
 		NULL,
@@ -188,3 +241,4 @@
 					   procdata);
 	proctable_update_all (procdata);
 }
+
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision 2210)
+++ src/Makefile.am	(working copy)
@@ -5,7 +5,9 @@
 	-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
 	-DDATADIR=\""$(datadir)"\" \
 	@PROCMAN_CFLAGS@ \
-	@PCRECPP_CFLAGS@
+	@PCRECPP_CFLAGS@ \
+	@POLKIT_DBUS_CFLAGS@ \
+	@POLKIT_GNOME_CFLAGS@
 
 bin_PROGRAMS = gnome-system-monitor
 
@@ -35,10 +37,14 @@
 	iconthemewrapper.cpp iconthemewrapper.h \
 	e_date.c e_date.h
 
+if HAVE_POLKIT
+gnome_system_monitor_SOURCES += gnome-system-monitor-mechanism-client-glue.h
+endif
 
-gnome_system_monitor_LDADD = @PROCMAN_LIBS@ @PCRECPP_LIBS@ libbacon.la
 
+gnome_system_monitor_LDADD = @PROCMAN_LIBS@ @PCRECPP_LIBS@ @POLKIT_GNOME_LIBS@ libbacon.la
 
+
 noinst_LTLIBRARIES = libbacon.la
 libbacon_la_SOURCES = \
 	bacon-message-connection.c \
@@ -52,8 +58,44 @@
 schema_DATA = $(schema_ins:.schemas.in=.schemas)
 @INTLTOOL_SCHEMAS_RULE@
 
+######################################################################
+if HAVE_POLKIT
+
+polkit_policydir = $(datadir)/PolicyKit/policy
+dist_polkit_policy_DATA = org.gnome.system-monitor.policy
+# You will need a recent intltool or the patch from this bug http://bugzilla.gnome.org/show_bug.cgi?id=462312
+@INTLTOOL_POLICY_RULE@
+
+gnome-system-monitor-mechanism-client-glue.h: gnome-system-monitor-mechanism.xml Makefile.am
+	dbus-binding-tool --prefix=gnome_system_monitor_mechanism --mode=glib-client --output=gnome-system-monitor-mechanism-client-glue.h gnome-system-monitor-mechanism.xml
+
+gnome-system-monitor-mechanism-glue.h: gnome-system-monitor-mechanism.xml Makefile.am
+	dbus-binding-tool --prefix=gnome_system_monitor_mechanism --mode=glib-server --output=gnome-system-monitor-mechanism-glue.h gnome-system-monitor-mechanism.xml
+
+dbusconfdir = $(sysconfdir)/dbus-1/system.d
+dbusconf_DATA = org.gnome.SystemMonitor.Mechanism.conf
+
+org.gnome.SystemMonitor.Mechanism.service : org.gnome.SystemMonitor.Mechanism.service.in Makefile.am
+	sed -e s_libexecdir_$(libexecdir)_ org.gnome.SystemMonitor.Mechanism.service.in > org.gnome.SystemMonitor.Mechanism.service
+
+dbussyssvcdir = $(datadir)/dbus-1/system-services
+dbussyssvc_DATA = org.gnome.SystemMonitor.Mechanism.service
+
+libexec_PROGRAMS = gnome-system-monitor-mechanism
+gnome_system_monitor_mechanism_SOURCES = 					      \
+						gnome-system-monitor-mechanism-glue.h \
+	gnome-system-monitor-mechanism.c
+
+gnome_system_monitor_mechanism_CFLAGS = $(POLKIT_DBUS_CFLAGS)
+gnome_system_monitor_mechanism_LDADD = $(POLKIT_DBUS_LIBS)
+endif
+######################################################################
+
+
 EXTRA_DIST = \
-	$(schema_ins)
+	$(schema_ins) \
+	org.gnome.system-monitor.policy.in \
+	org.gnome.system-monitor.service.in
 
 CLEANFILES = \
 	$(schema_DATA)
Index: po/POTFILES.in
===================================================================
--- po/POTFILES.in	(revision 2210)
+++ po/POTFILES.in	(working copy)
@@ -6,6 +6,7 @@
 src/defaulttable.h
 src/disks.cpp
 src/e_date.c
+src/gnome-system-monitor.policy.in
 src/gnome-system-monitor.schemas.in
 src/interface.cpp
 src/load-graph.cpp
--- /dev/null	2007-12-21 05:01:42.582083906 -0500
+++ src/org.gnome.system-monitor.policy.in	2007-12-04 20:59:31.000000000 -0500
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<!-- 
+Policy definitions for gnome-system-monitor
+
+Copyright (c) 2007 David Zeuthen <david@fubar.dk>
+
+NOTE: If you make changes to this file, make sure to validate the file
+using the polkit-policy-file-validate(1) tool. Changes made to this
+file are instantly applied.
+-->
+
+<policyconfig>
+
+  <vendor>The GNOME Project</vendor>
+  <vendor_url>http://online.gnome.org/application?id=gnome-system-monitor</vendor_url>
+  <icon_name>utilities-system-monitor</icon_name>
+
+  <action id="org.gnome.system-monitor.change-priority">
+    <_description>Change priority of a process owned by another user</_description>
+    <_message>Changing the priority of a process owned by another user requires privileges</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.gnome.system-monitor.increase-own-priority">
+    <_description>Increase the priority of a processes</_description>
+    <_message>Increasing the priority of one of your own processes requires privileges</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_self_keep_always</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.gnome.system-monitor.kill">
+    <_description>Kill a process owned by another user</_description>
+    <_message>Killing a process owned by another user requires privileges</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin</allow_active>
+    </defaults>
+  </action>
+  
+</policyconfig>
--- /dev/null	2007-12-21 05:01:42.582083906 -0500
+++ src/gnome-system-monitor-mechanism.c	2007-12-04 23:09:55.000000000 -0500
@@ -0,0 +1,640 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david@fubar.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <polkit-dbus/polkit-dbus.h>
+
+static gboolean no_exit = FALSE;
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+#define GNOME_SYSTEM_MONITOR_TYPE_MECHANISM         (gnome_system_monitor_mechanism_get_type ())
+#define GNOME_SYSTEM_MONITOR_MECHANISM(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GNOME_SYSTEM_MONITOR_TYPE_MECHANISM, GnomeSystemMonitorMechanism))
+#define GNOME_SYSTEM_MONITOR_MECHANISM_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GNOME_SYSTEM_MONITOR_TYPE_MECHANISM, GnomeSystemMonitorMechanismClass))
+#define GNOME_SYSTEM_MONITOR_IS_MECHANISM(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNOME_SYSTEM_MONITOR_TYPE_MECHANISM))
+#define GNOME_SYSTEM_MONITOR_IS_MECHANISM_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GNOME_SYSTEM_MONITOR_TYPE_MECHANISM))
+#define GNOME_SYSTEM_MONITOR_MECHANISM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GNOME_SYSTEM_MONITOR_TYPE_MECHANISM, GnomeSystemMonitorMechanismClass))
+
+typedef struct GnomeSystemMonitorMechanismPrivate GnomeSystemMonitorMechanismPrivate;
+
+typedef struct
+{
+        GObject        parent;
+        GnomeSystemMonitorMechanismPrivate *priv;
+} GnomeSystemMonitorMechanism;
+
+typedef struct
+{
+        GObjectClass   parent_class;
+} GnomeSystemMonitorMechanismClass;
+
+typedef enum
+{
+        GNOME_SYSTEM_MONITOR_MECHANISM_ERROR_GENERAL,
+        GNOME_SYSTEM_MONITOR_MECHANISM_ERROR_NOT_PRIVILEGED,
+        GNOME_SYSTEM_MONITOR_MECHANISM_NUM_ERRORS
+} GnomeSystemMonitorMechanismError;
+
+#define GNOME_SYSTEM_MONITOR_MECHANISM_ERROR gnome_system_monitor_mechanism_error_quark ()
+
+GType gnome_system_monitor_mechanism_error_get_type (void);
+#define GNOME_SYSTEM_MONITOR_MECHANISM_TYPE_ERROR (gnome_system_monitor_mechanism_error_get_type ())
+
+
+GQuark                     gnome_system_monitor_mechanism_error_quark         (void);
+GType                      gnome_system_monitor_mechanism_get_type            (void);
+GnomeSystemMonitorMechanism *gnome_system_monitor_mechanism_new                 (void);
+
+/* exported methods */
+gboolean gnome_system_monitor_mechanism_kill (GnomeSystemMonitorMechanism  *mechanism,
+                                              int                           pid,
+                                              int                           sig,
+                                              DBusGMethodInvocation        *context);
+
+gboolean gnome_system_monitor_mechanism_renice (GnomeSystemMonitorMechanism  *mechanism,
+                                                int                           pid,
+                                                int                           nice_value,
+                                                DBusGMethodInvocation        *context);
+
+/*--------------------------------------------------------------------------------------------------------------*/
+#include "gnome-system-monitor-mechanism-glue.h"
+
+static gboolean
+do_exit (gpointer user_data)
+{
+        g_debug ("Exiting due to inactivity");
+        exit (1);
+        return FALSE;
+}
+
+static void
+reset_killtimer (void)
+{
+        static guint timer_id = 0;
+
+        if (no_exit)
+                return;
+
+        if (timer_id > 0) {
+                g_source_remove (timer_id);
+        }
+        g_debug ("Setting killtimer to 30 seconds...");
+        timer_id = g_timeout_add (30 * 1000, do_exit, NULL);
+}
+
+struct GnomeSystemMonitorMechanismPrivate
+{
+        DBusGConnection *system_bus_connection;
+        DBusGProxy      *system_bus_proxy;
+        PolKitContext   *pol_ctx;
+};
+
+static void     gnome_system_monitor_mechanism_class_init  (GnomeSystemMonitorMechanismClass *klass);
+static void     gnome_system_monitor_mechanism_init        (GnomeSystemMonitorMechanism      *seat);
+static void     gnome_system_monitor_mechanism_finalize    (GObject     *object);
+
+G_DEFINE_TYPE (GnomeSystemMonitorMechanism, gnome_system_monitor_mechanism, G_TYPE_OBJECT)
+
+#define GNOME_SYSTEM_MONITOR_MECHANISM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNOME_SYSTEM_MONITOR_TYPE_MECHANISM, GnomeSystemMonitorMechanismPrivate))
+
+GQuark
+gnome_system_monitor_mechanism_error_quark (void)
+{
+        static GQuark ret = 0;
+
+        if (ret == 0) {
+                ret = g_quark_from_static_string ("gnome_system_monitor_mechanism_error");
+        }
+
+        return ret;
+}
+
+
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+gnome_system_monitor_mechanism_error_get_type (void)
+{
+        static GType etype = 0;
+        
+        if (etype == 0)
+        {
+                static const GEnumValue values[] =
+                        {
+                                ENUM_ENTRY (GNOME_SYSTEM_MONITOR_MECHANISM_ERROR_GENERAL, "GeneralError"),
+                                ENUM_ENTRY (GNOME_SYSTEM_MONITOR_MECHANISM_ERROR_NOT_PRIVILEGED, "NotPrivileged"),
+                                { 0, 0, 0 }
+                        };
+                
+                g_assert (GNOME_SYSTEM_MONITOR_MECHANISM_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
+                
+                etype = g_enum_register_static ("GnomeSystemMonitorMechanismError", values);
+        }
+        
+        return etype;
+}
+
+
+static GObject *
+gnome_system_monitor_mechanism_constructor (GType                  type,
+                                            guint                  n_construct_properties,
+                                            GObjectConstructParam *construct_properties)
+{
+        GnomeSystemMonitorMechanism      *mechanism;
+        GnomeSystemMonitorMechanismClass *klass;
+
+        klass = GNOME_SYSTEM_MONITOR_MECHANISM_CLASS (g_type_class_peek (GNOME_SYSTEM_MONITOR_TYPE_MECHANISM));
+
+        mechanism = GNOME_SYSTEM_MONITOR_MECHANISM (
+                G_OBJECT_CLASS (gnome_system_monitor_mechanism_parent_class)->constructor (type,
+                                                                                           n_construct_properties,
+                                                                                           construct_properties));
+        
+        return G_OBJECT (mechanism);
+}
+
+static void
+gnome_system_monitor_mechanism_class_init (GnomeSystemMonitorMechanismClass *klass)
+{
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->constructor = gnome_system_monitor_mechanism_constructor;
+        object_class->finalize = gnome_system_monitor_mechanism_finalize;
+
+        g_type_class_add_private (klass, sizeof (GnomeSystemMonitorMechanismPrivate));
+
+        dbus_g_object_type_install_info (GNOME_SYSTEM_MONITOR_TYPE_MECHANISM, &dbus_glib_gnome_system_monitor_mechanism_object_info);
+
+        dbus_g_error_domain_register (GNOME_SYSTEM_MONITOR_MECHANISM_ERROR, NULL, GNOME_SYSTEM_MONITOR_MECHANISM_TYPE_ERROR);
+
+}
+
+static void
+gnome_system_monitor_mechanism_init (GnomeSystemMonitorMechanism *mechanism)
+{
+        mechanism->priv = GNOME_SYSTEM_MONITOR_MECHANISM_GET_PRIVATE (mechanism);
+
+}
+
+static void
+gnome_system_monitor_mechanism_finalize (GObject *object)
+{
+        GnomeSystemMonitorMechanism *mechanism;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GNOME_SYSTEM_MONITOR_IS_MECHANISM (object));
+
+        mechanism = GNOME_SYSTEM_MONITOR_MECHANISM (object);
+
+        g_return_if_fail (mechanism->priv != NULL);
+
+        g_object_unref (mechanism->priv->system_bus_proxy);
+
+        G_OBJECT_CLASS (gnome_system_monitor_mechanism_parent_class)->finalize (object);
+}
+
+static gboolean
+pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
+{
+        int fd;
+        PolKitContext *pk_context = user_data;
+        fd = g_io_channel_unix_get_fd (channel);
+        polkit_context_io_func (pk_context, fd);
+        return TRUE;
+}
+
+static int 
+pk_io_add_watch (PolKitContext *pk_context, int fd)
+{
+        guint id = 0;
+        GIOChannel *channel;
+        channel = g_io_channel_unix_new (fd);
+        if (channel == NULL)
+                goto out;
+        id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context);
+        if (id == 0) {
+                g_io_channel_unref (channel);
+                goto out;
+        }
+        g_io_channel_unref (channel);
+out:
+        return id;
+}
+
+static void 
+pk_io_remove_watch (PolKitContext *pk_context, int watch_id)
+{
+        g_source_remove (watch_id);
+}
+
+static gboolean
+register_mechanism (GnomeSystemMonitorMechanism *mechanism)
+{
+        GError *error = NULL;
+
+        mechanism->priv->pol_ctx = polkit_context_new ();
+        polkit_context_set_io_watch_functions (mechanism->priv->pol_ctx, pk_io_add_watch, pk_io_remove_watch);
+        if (!polkit_context_init (mechanism->priv->pol_ctx, NULL)) {
+                g_critical ("cannot initialize libpolkit");
+                goto error;
+        }
+
+        error = NULL;
+        mechanism->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (mechanism->priv->system_bus_connection == NULL) {
+                if (error != NULL) {
+                        g_critical ("error getting system bus: %s", error->message);
+                        g_error_free (error);
+                }
+                goto error;
+        }
+
+        dbus_g_connection_register_g_object (mechanism->priv->system_bus_connection, "/", 
+                                             G_OBJECT (mechanism));
+
+        mechanism->priv->system_bus_proxy = dbus_g_proxy_new_for_name (mechanism->priv->system_bus_connection,
+                                                                      DBUS_SERVICE_DBUS,
+                                                                      DBUS_PATH_DBUS,
+                                                                      DBUS_INTERFACE_DBUS);
+
+        reset_killtimer ();
+
+        return TRUE;
+
+error:
+        return FALSE;
+}
+
+
+GnomeSystemMonitorMechanism *
+gnome_system_monitor_mechanism_new (void)
+{
+        GObject *object;
+        gboolean res;
+
+        object = g_object_new (GNOME_SYSTEM_MONITOR_TYPE_MECHANISM, NULL);
+
+        res = register_mechanism (GNOME_SYSTEM_MONITOR_MECHANISM (object));
+        if (! res) {
+                g_object_unref (object);
+                return NULL;
+        }
+
+        return GNOME_SYSTEM_MONITOR_MECHANISM (object);
+}
+
+static PolKitCaller *
+get_caller_from_context (GnomeSystemMonitorMechanism *mechanism, DBusGMethodInvocation *context)
+{
+        const char *sender;
+        GError *error;
+        DBusError dbus_error;
+        PolKitCaller *pk_caller;
+
+        sender = dbus_g_method_get_sender (context);
+        dbus_error_init (&dbus_error);
+        pk_caller = polkit_caller_new_from_dbus_name (
+                dbus_g_connection_get_connection (mechanism->priv->system_bus_connection),
+                sender, 
+                &dbus_error);
+        if (pk_caller == NULL) {
+                error = g_error_new (GNOME_SYSTEM_MONITOR_MECHANISM_ERROR,
+                                     GNOME_SYSTEM_MONITOR_MECHANISM_ERROR_GENERAL,
+                                     "Error getting information about caller: %s: %s",
+                                     dbus_error.name, dbus_error.message);
+                dbus_error_free (&dbus_error);
+                dbus_g_method_return_error (context, error);
+                g_error_free (error);
+                return NULL;
+        }
+
+        return pk_caller;
+}
+
+/* note, we take ownership of the passed PolKitCaller object */
+static gboolean
+_check_polkit_for_action_for_caller (GnomeSystemMonitorMechanism *mechanism, 
+                                     DBusGMethodInvocation *context,
+                                     PolKitCaller *pk_caller, 
+                                     const char *action,
+                                     const char *action_secondary)
+{
+        GError *error;
+        PolKitAction *pk_action;
+        PolKitResult pk_result;
+
+        error = NULL;
+
+        pk_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_action, action);
+        pk_result = polkit_context_is_caller_authorized (mechanism->priv->pol_ctx, 
+                                                         pk_action, 
+                                                         pk_caller, 
+                                                         TRUE, 
+                                                         NULL);
+        if (pk_result != POLKIT_RESULT_YES) {
+                polkit_action_set_action_id (pk_action, action_secondary);
+                pk_result = polkit_context_is_caller_authorized (mechanism->priv->pol_ctx, 
+                                                                 pk_action, 
+                                                                 pk_caller, 
+                                                                 TRUE, 
+                                                                 NULL);
+        }
+        polkit_action_unref (pk_action);
+        polkit_caller_unref (pk_caller);
+
+        if (pk_result != POLKIT_RESULT_YES) {
+                error = g_error_new (GNOME_SYSTEM_MONITOR_MECHANISM_ERROR,
+                                     GNOME_SYSTEM_MONITOR_MECHANISM_ERROR_NOT_PRIVILEGED,
+                                     "%s %s <-- (action, result)",
+                                     action,
+                                     polkit_result_to_string_representation (pk_result));
+                dbus_g_method_return_error (context, error);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
+static gboolean
+_check_polkit_for_action (GnomeSystemMonitorMechanism *mechanism, 
+                          DBusGMethodInvocation *context, 
+                          const char *action,
+                          const char *action_secondary)
+{
+        PolKitCaller *pk_caller;
+
+        /* Check that caller is privileged */
+        if ((pk_caller = get_caller_from_context (mechanism, context)) == NULL)
+                return FALSE;
+
+        return _check_polkit_for_action_for_caller (mechanism, context, pk_caller, action, action_secondary);
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+/* exported methods */
+
+gboolean
+gnome_system_monitor_mechanism_kill (GnomeSystemMonitorMechanism  *mechanism,
+                                     int                           pid,
+                                     int                           sig,
+                                     DBusGMethodInvocation        *context)
+{
+        reset_killtimer ();
+
+        if (!_check_polkit_for_action (mechanism, context, "org.gnome.system-monitor.kill", NULL))
+                return FALSE;
+
+        g_debug ("Sending signal %d to pid %d", sig, pid);
+
+        if (kill (pid, sig) != 0) {
+                GError *error;
+                error = g_error_new (GNOME_SYSTEM_MONITOR_MECHANISM_ERROR,
+                                     GNOME_SYSTEM_MONITOR_MECHANISM_ERROR_GENERAL,
+                                     "Error sending signal %d to pid %d: %m", sig, pid);
+                g_warning ("Error: %s", error->message);
+                dbus_g_method_return_error (context, error);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        dbus_g_method_return (context);
+        return TRUE;
+}
+
+gboolean
+gnome_system_monitor_mechanism_renice (GnomeSystemMonitorMechanism  *mechanism,
+                                       int                           pid,
+                                       int                           nice_value,
+                                       DBusGMethodInvocation        *context)
+{
+        uid_t caller_uid;
+        uid_t process_uid;
+        PolKitCaller *pk_caller;
+        char *procpath;
+        struct stat statbuf;
+        const char *action_id;
+        const char *action_id_secondary;
+
+        reset_killtimer ();
+
+        /* Hmm; is there a better way to do this? This may be Linux specific.. */
+        procpath = g_strdup_printf ("/proc/%d", pid);
+        if (stat (procpath, &statbuf) != 0) {
+                GError *error;
+                error = g_error_new (GNOME_SYSTEM_MONITOR_MECHANISM_ERROR,
+                                     GNOME_SYSTEM_MONITOR_MECHANISM_ERROR_GENERAL,
+                                     "Error figuring out uid for pid %d", pid);
+                g_warning ("Error: %s", error->message);
+                dbus_g_method_return_error (context, error);
+                g_error_free (error);
+                g_free (procpath);
+                return FALSE;
+        }
+        g_free (procpath);
+        process_uid = statbuf.st_uid;
+
+        pk_caller = get_caller_from_context (mechanism, context);
+        if (pk_caller == NULL)
+                return FALSE;
+
+        if (!polkit_caller_get_uid (pk_caller, &caller_uid)) {
+                GError *error;
+                error = g_error_new (GNOME_SYSTEM_MONITOR_MECHANISM_ERROR,
+                                     GNOME_SYSTEM_MONITOR_MECHANISM_ERROR_GENERAL,
+                                     "Error figuring out uid of caller");
+                g_warning ("Error: %s", error->message);
+                dbus_g_method_return_error (context, error);
+                g_error_free (error);
+                polkit_caller_unref (pk_caller);
+                return FALSE;
+        }
+
+        if (caller_uid == process_uid) {
+                /* we need either .increase-own-priority or .change-priority */
+                action_id = "org.gnome.system-monitor.increase-own-priority";
+                action_id_secondary = "org.gnome.system-monitor.change-priority";
+        } else {
+                action_id = "org.gnome.system-monitor.change-priority";
+                action_id_secondary = NULL;
+        }
+
+        if (!_check_polkit_for_action_for_caller (mechanism, context, pk_caller, action_id, action_id_secondary)) {
+                return FALSE;
+        }
+
+        g_debug ("Renicing pid %d (owned by uid %d) to priority %d on behalf of uid %d (action_id=%s)", 
+                 pid, process_uid, nice_value, caller_uid, action_id);
+
+        errno = 0;
+        if (setpriority (PRIO_PROCESS, pid, nice_value) != 0) {
+                GError *error;
+                error = g_error_new (GNOME_SYSTEM_MONITOR_MECHANISM_ERROR,
+                                     GNOME_SYSTEM_MONITOR_MECHANISM_ERROR_GENERAL,
+                                     "Error renicing pid %d to priority %d: %m", pid, nice_value);
+                g_warning ("Error: %s", error->message);
+                dbus_g_method_return_error (context, error);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        dbus_g_method_return (context);
+        return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+#define BUS_NAME "org.gnome.SystemMonitor.Mechanism"
+
+static gboolean
+acquire_name_on_proxy (DBusGProxy *bus_proxy)
+{
+        GError     *error;
+        guint       result;
+        gboolean    res;
+        gboolean    ret;
+
+        ret = FALSE;
+
+        if (bus_proxy == NULL) {
+                goto out;
+        }
+
+        error = NULL;
+	res = dbus_g_proxy_call (bus_proxy,
+                                 "RequestName",
+                                 &error,
+                                 G_TYPE_STRING, BUS_NAME,
+                                 G_TYPE_UINT, 0,
+                                 G_TYPE_INVALID,
+                                 G_TYPE_UINT, &result,
+                                 G_TYPE_INVALID);
+        if (! res) {
+                if (error != NULL) {
+                        g_warning ("Failed to acquire %s: %s", BUS_NAME, error->message);
+                        g_error_free (error);
+                } else {
+                        g_warning ("Failed to acquire %s", BUS_NAME);
+                }
+                goto out;
+	}
+
+ 	if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+                if (error != NULL) {
+                        g_warning ("Failed to acquire %s: %s", BUS_NAME, error->message);
+                        g_error_free (error);
+                } else {
+                        g_warning ("Failed to acquire %s", BUS_NAME);
+                }
+                goto out;
+        }
+
+        ret = TRUE;
+
+ out:
+        return ret;
+}
+
+int
+main (int argc, char **argv)
+{
+        GMainLoop                    *loop;
+        GnomeSystemMonitorMechanism  *mechanism;
+        DBusGProxy                   *bus_proxy;
+        DBusGConnection              *connection;
+        int                           ret;
+        GError                       *error;
+        GOptionContext      *context;
+        static GOptionEntry entries []   = {
+                { "no-exit", 0, 0, G_OPTION_ARG_NONE, &no_exit, N_("Don't exit after 30 seconds of inactivity"), NULL },
+                { NULL }
+        };
+
+        ret = 1;
+
+        g_type_init ();
+
+        context = g_option_context_new (_("PolicyKit GNOME session daemon"));
+        g_option_context_add_main_entries (context, entries, NULL);
+        g_option_context_parse (context, &argc, &argv, NULL);
+        g_option_context_free (context);
+
+
+        error = NULL;
+        connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (connection == NULL) {
+                g_warning ("Couldn't connect to system bus: %s", error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+	bus_proxy = dbus_g_proxy_new_for_name (connection,
+                                               DBUS_SERVICE_DBUS,
+                                               DBUS_PATH_DBUS,
+                                               DBUS_INTERFACE_DBUS);
+        if (bus_proxy == NULL) {
+                g_warning ("Could not construct bus_proxy object; bailing out");
+                goto out;
+        }
+
+        if (!acquire_name_on_proxy (bus_proxy) ) {
+                g_warning ("Could not acquire name; bailing out");
+                goto out;
+        }
+
+        mechanism = gnome_system_monitor_mechanism_new ();
+
+        if (mechanism == NULL) {
+                goto out;
+        }
+
+        loop = g_main_loop_new (NULL, FALSE);
+
+        g_main_loop_run (loop);
+
+        g_object_unref (mechanism);
+        g_main_loop_unref (loop);
+        ret = 0;
+
+out:
+        return ret;
+}
--- /dev/null	2007-12-21 05:01:42.582083906 -0500
+++ src/gnome-system-monitor-mechanism.xml	2007-10-21 12:32:38.000000000 -0400
@@ -0,0 +1,15 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/">
+  <interface name="org.gnome.SystemMonitor.Mechanism">
+    <method name="Kill">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg name="pid" direction="in" type="i"/>
+      <arg name="signal" direction="in" type="i"/>
+    </method>
+    <method name="Renice">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg name="pid" direction="in" type="i"/>
+      <arg name="nice_value" direction="in" type="i"/>
+    </method>
+  </interface>
+</node>
--- /dev/null	2007-12-21 05:01:42.582083906 -0500
+++ src/org.gnome.SystemMonitor.Mechanism.conf	2007-10-30 19:45:18.000000000 -0400
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
+
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <!-- Only root can own the service -->
+  <policy user="root">
+    <allow own="org.gnome.SystemMonitor.Mechanism"/>
+  </policy>
+</busconfig>
--- /dev/null	2007-12-21 05:01:42.582083906 -0500
+++ src/org.gnome.SystemMonitor.Mechanism.service.in	2007-12-04 20:52:03.000000000 -0500
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.gnome.SystemMonitor.Mechanism
+Exec=libexecdir/gnome-system-monitor-mechanism
+User=root
