|
Packit |
76ec6a |
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
Packit |
76ec6a |
/* Procman - dialogs
|
|
Packit |
76ec6a |
* Copyright (C) 2001 Kevin Vandersloot
|
|
Packit |
76ec6a |
*
|
|
Packit |
76ec6a |
* This program is free software; you can redistribute it and/or
|
|
Packit |
76ec6a |
* modify it under the terms of the GNU General Public License
|
|
Packit |
76ec6a |
* as published by the Free Software Foundation; either version 2
|
|
Packit |
76ec6a |
* of the License, or (at your option) any later version.
|
|
Packit |
76ec6a |
*
|
|
Packit |
76ec6a |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
76ec6a |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
76ec6a |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
76ec6a |
* GNU General Public License for more details.
|
|
Packit |
76ec6a |
*
|
|
Packit |
76ec6a |
* You should have received a copy of the GNU Library General Public
|
|
Packit |
76ec6a |
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
76ec6a |
*
|
|
Packit |
76ec6a |
*/
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#include <config.h>
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#include <glib/gi18n.h>
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#include <signal.h>
|
|
Packit |
76ec6a |
#include <string.h>
|
|
Packit |
76ec6a |
#include <stdio.h>
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#include "procdialogs.h"
|
|
Packit |
76ec6a |
#include "proctable.h"
|
|
Packit |
76ec6a |
#include "prettytable.h"
|
|
Packit |
76ec6a |
#include "procactions.h"
|
|
Packit |
76ec6a |
#include "util.h"
|
|
Packit |
76ec6a |
#include "gsm_gnomesu.h"
|
|
Packit |
76ec6a |
#include "gsm_gksu.h"
|
|
Packit |
76ec6a |
#include "gsm_pkexec.h"
|
|
Packit |
76ec6a |
#include "cgroups.h"
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static GtkDialog *renice_dialog = NULL;
|
|
Packit |
76ec6a |
static gint new_nice_value = 0;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static void
|
|
Packit |
76ec6a |
kill_dialog_button_pressed (GtkDialog *dialog, gint id, gpointer data)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
struct ProcActionArgs *kargs = static_cast<ProcActionArgs*>(data);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_widget_destroy (GTK_WIDGET (dialog));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (id == GTK_RESPONSE_OK)
|
|
Packit |
76ec6a |
kill_process (kargs->app, kargs->arg_value);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
g_free (kargs);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
procdialog_create_kill_dialog (GsmApplication *app, int signal)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
GtkMessageDialog *kill_alert_dialog;
|
|
Packit |
76ec6a |
GtkWidget *confirm_button;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gchar *primary, *secondary, *button_text;
|
|
Packit |
76ec6a |
struct ProcActionArgs *kargs;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
kargs = g_new(ProcActionArgs, 1);
|
|
Packit |
76ec6a |
kargs->app = app;
|
|
Packit |
76ec6a |
kargs->arg_value = signal;
|
|
Packit |
76ec6a |
gint selected_count = gtk_tree_selection_count_selected_rows (app->selection);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if ( selected_count == 1 ) {
|
|
Packit |
76ec6a |
ProcInfo *selected_process = NULL;
|
|
Packit |
76ec6a |
// get the last selected row
|
|
Packit |
76ec6a |
gtk_tree_selection_selected_foreach (app->selection, get_last_selected,
|
|
Packit |
76ec6a |
&selected_process);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
std::string *process_name = &selected_process->name;
|
|
Packit |
76ec6a |
std::string short_process_name = process_name->substr(0, process_name->find(" "));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
switch (signal) {
|
|
Packit |
76ec6a |
case SIGKILL:
|
|
Packit |
76ec6a |
/*xgettext: primary alert message for killing single process*/
|
|
Packit |
76ec6a |
primary = g_strdup_printf (_("Are you sure you want to kill the selected process “%s” (PID: %u)?"),
|
|
Packit |
76ec6a |
short_process_name.c_str(),
|
|
Packit |
76ec6a |
selected_process->pid);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
case SIGTERM:
|
|
Packit |
76ec6a |
/*xgettext: primary alert message for ending single process*/
|
|
Packit |
76ec6a |
primary = g_strdup_printf (_("Are you sure you want to end the selected process “%s” (PID: %u)?"),
|
|
Packit |
76ec6a |
short_process_name.c_str(),
|
|
Packit |
76ec6a |
selected_process->pid);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
default: // SIGSTOP
|
|
Packit |
76ec6a |
/*xgettext: primary alert message for stopping single process*/
|
|
Packit |
76ec6a |
primary = g_strdup_printf (_("Are you sure you want to stop the selected process “%s” (PID: %u)?"),
|
|
Packit |
76ec6a |
short_process_name.c_str(),
|
|
Packit |
76ec6a |
selected_process->pid);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
} else {
|
|
Packit |
76ec6a |
switch (signal) {
|
|
Packit |
76ec6a |
case SIGKILL:
|
|
Packit |
76ec6a |
/*xgettext: primary alert message for killing multiple processes*/
|
|
Packit |
76ec6a |
primary = g_strdup_printf (ngettext("Are you sure you want to kill the selected process?",
|
|
Packit |
76ec6a |
"Are you sure you want to kill the %d selected processes?", selected_count),
|
|
Packit |
76ec6a |
selected_count);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
case SIGTERM:
|
|
Packit |
76ec6a |
/*xgettext: primary alert message for ending multiple processes*/
|
|
Packit |
76ec6a |
primary = g_strdup_printf (ngettext("Are you sure you want to end the selected process?",
|
|
Packit |
76ec6a |
"Are you sure you want to end the %d selected processes?", selected_count),
|
|
Packit |
76ec6a |
selected_count);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
default: // SIGSTOP
|
|
Packit |
76ec6a |
/*xgettext: primary alert message for stopping multiple processes*/
|
|
Packit |
76ec6a |
primary = g_strdup_printf (ngettext("Are you sure you want to stop the selected process?",
|
|
Packit |
76ec6a |
"Are you sure you want to stop the %d selected processes?", selected_count),
|
|
Packit |
76ec6a |
selected_count);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
switch (signal) {
|
|
Packit |
76ec6a |
case SIGKILL:
|
|
Packit |
76ec6a |
/*xgettext: secondary alert message*/
|
|
Packit |
76ec6a |
secondary = _("Killing a process may destroy data, break the "
|
|
Packit |
76ec6a |
"session or introduce a security risk. "
|
|
Packit |
76ec6a |
"Only unresponsive processes should be killed.");
|
|
Packit |
76ec6a |
button_text = ngettext("_Kill Process", "_Kill Processes", selected_count);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
case SIGTERM:
|
|
Packit |
76ec6a |
/*xgettext: secondary alert message*/
|
|
Packit |
76ec6a |
secondary = _("Ending a process may destroy data, break the "
|
|
Packit |
76ec6a |
"session or introduce a security risk. "
|
|
Packit |
76ec6a |
"Only unresponsive processes should be ended.");
|
|
Packit |
76ec6a |
button_text = ngettext("_End Process", "_End Processes", selected_count);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
default: // SIGSTOP
|
|
Packit |
76ec6a |
/*xgettext: secondary alert message*/
|
|
Packit |
76ec6a |
secondary = _("Stopping a process may destroy data, break the "
|
|
Packit |
76ec6a |
"session or introduce a security risk. "
|
|
Packit |
76ec6a |
"Only unresponsive processes should be stopped.");
|
|
Packit |
76ec6a |
button_text = ngettext("_Stop Process", "_Stop Processes", selected_count);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
kill_alert_dialog = GTK_MESSAGE_DIALOG (gtk_message_dialog_new (GTK_WINDOW (app->main_window),
|
|
Packit |
76ec6a |
static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
|
|
Packit |
76ec6a |
GTK_MESSAGE_WARNING,
|
|
Packit |
76ec6a |
GTK_BUTTONS_NONE,
|
|
Packit |
76ec6a |
"%s",
|
|
Packit |
76ec6a |
primary));
|
|
Packit |
76ec6a |
g_free (primary);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_message_dialog_format_secondary_text (kill_alert_dialog,
|
|
Packit |
76ec6a |
"%s",
|
|
Packit |
76ec6a |
secondary);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_dialog_add_button (GTK_DIALOG (kill_alert_dialog),
|
|
Packit |
76ec6a |
_("_Cancel"), GTK_RESPONSE_CANCEL);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
confirm_button = gtk_dialog_add_button (GTK_DIALOG (kill_alert_dialog),
|
|
Packit |
76ec6a |
button_text, GTK_RESPONSE_OK);
|
|
Packit |
76ec6a |
gtk_style_context_add_class (gtk_widget_get_style_context (confirm_button),
|
|
Packit |
76ec6a |
GTK_STYLE_CLASS_DESTRUCTIVE_ACTION);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_dialog_set_default_response (GTK_DIALOG (kill_alert_dialog),
|
|
Packit |
76ec6a |
GTK_RESPONSE_CANCEL);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
g_signal_connect (G_OBJECT (kill_alert_dialog), "response",
|
|
Packit |
76ec6a |
G_CALLBACK (kill_dialog_button_pressed), kargs);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_widget_show_all (GTK_WIDGET (kill_alert_dialog));
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static void
|
|
Packit |
76ec6a |
renice_scale_changed (GtkAdjustment *adj, gpointer data)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
GtkLabel *label = GTK_LABEL (data);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
new_nice_value = int(gtk_adjustment_get_value (adj));
|
|
Packit |
76ec6a |
gchar* text = g_strdup(procman::get_nice_level_with_priority (new_nice_value));
|
|
Packit |
76ec6a |
gtk_label_set_text (label, text);
|
|
Packit |
76ec6a |
g_free(text);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static void
|
|
Packit |
76ec6a |
renice_dialog_button_pressed (GtkDialog *dialog, gint id, gpointer data)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
GsmApplication *app = static_cast<GsmApplication *>(data);
|
|
Packit |
76ec6a |
if (id == 100) {
|
|
Packit |
76ec6a |
if (new_nice_value == -100)
|
|
Packit |
76ec6a |
return;
|
|
Packit |
76ec6a |
renice(app, new_nice_value);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_widget_destroy (GTK_WIDGET (dialog));
|
|
Packit |
76ec6a |
renice_dialog = NULL;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
procdialog_create_renice_dialog (GsmApplication *app)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
ProcInfo *info;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
GtkLabel *label;
|
|
Packit |
76ec6a |
GtkLabel *priority_label;
|
|
Packit |
76ec6a |
GtkAdjustment *renice_adj;
|
|
Packit |
76ec6a |
GtkBuilder *builder;
|
|
Packit |
76ec6a |
gchar *text;
|
|
Packit |
76ec6a |
gchar *dialog_title;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (renice_dialog)
|
|
Packit |
76ec6a |
return;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_tree_selection_selected_foreach (app->selection, get_last_selected,
|
|
Packit |
76ec6a |
&info;;
|
|
Packit |
76ec6a |
gint selected_count = gtk_tree_selection_count_selected_rows (app->selection);
|
|
Packit |
76ec6a |
if (!info)
|
|
Packit |
76ec6a |
return;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
builder = gtk_builder_new();
|
|
Packit |
76ec6a |
gtk_builder_add_from_resource (builder, "/org/gnome/gnome-system-monitor/data/renice.ui", NULL);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
renice_dialog = GTK_DIALOG (gtk_builder_get_object (builder, "renice_dialog"));
|
|
Packit |
76ec6a |
if ( selected_count == 1 ) {
|
|
Packit |
76ec6a |
dialog_title = g_strdup_printf (_("Change Priority of Process “%s” (PID: %u)"),
|
|
Packit |
76ec6a |
info->name.c_str(), info->pid);
|
|
Packit |
76ec6a |
} else {
|
|
Packit |
76ec6a |
dialog_title = g_strdup_printf (ngettext("Change Priority of the selected process", "Change Priority of %d selected processes", selected_count),
|
|
Packit |
76ec6a |
selected_count);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_window_set_title (GTK_WINDOW(renice_dialog), dialog_title);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
g_free (dialog_title);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_dialog_set_default_response (GTK_DIALOG (renice_dialog), 100);
|
|
Packit |
76ec6a |
new_nice_value = -100;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
renice_adj = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "renice_adj"));
|
|
Packit |
76ec6a |
gtk_adjustment_configure( GTK_ADJUSTMENT(renice_adj), info->nice, RENICE_VAL_MIN, RENICE_VAL_MAX, 1, 1, 0);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
new_nice_value = 0;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
priority_label = GTK_LABEL (gtk_builder_get_object (builder, "priority_label"));
|
|
Packit |
76ec6a |
gtk_label_set_label (priority_label, procman::get_nice_level_with_priority (info->nice));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
text = g_strconcat("<small>", _("Note:"), " ",
|
|
Packit |
76ec6a |
_("The priority of a process is given by its nice value. A lower nice value corresponds to a higher priority."),
|
|
Packit |
76ec6a |
"</small>", NULL);
|
|
Packit |
76ec6a |
label = GTK_LABEL (gtk_builder_get_object (builder, "note_label"));
|
|
Packit |
76ec6a |
gtk_label_set_label (label, _(text));
|
|
Packit |
76ec6a |
gtk_label_set_line_wrap (label, TRUE);
|
|
Packit |
76ec6a |
g_free (text);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
g_signal_connect (G_OBJECT (renice_dialog), "response",
|
|
Packit |
76ec6a |
G_CALLBACK (renice_dialog_button_pressed), app);
|
|
Packit |
76ec6a |
g_signal_connect (G_OBJECT (renice_adj), "value_changed",
|
|
Packit |
76ec6a |
G_CALLBACK (renice_scale_changed), priority_label);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_window_set_transient_for (GTK_WINDOW (renice_dialog), GTK_WINDOW (GsmApplication::get()->main_window));
|
|
Packit |
76ec6a |
gtk_widget_show_all (GTK_WIDGET (renice_dialog));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_builder_connect_signals (builder, NULL);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
g_object_unref (G_OBJECT (builder));
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static char *
|
|
Packit |
76ec6a |
procman_action_to_command(ProcmanActionType type,
|
|
Packit |
76ec6a |
gint pid,
|
|
Packit |
76ec6a |
gint extra_value)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
switch (type) {
|
|
Packit |
76ec6a |
case PROCMAN_ACTION_KILL:
|
|
Packit |
76ec6a |
return g_strdup_printf("kill -s %d %d", extra_value, pid);
|
|
Packit |
76ec6a |
case PROCMAN_ACTION_RENICE:
|
|
Packit |
76ec6a |
return g_strdup_printf("renice %d %d", extra_value, pid);
|
|
Packit |
76ec6a |
default:
|
|
Packit |
76ec6a |
g_assert_not_reached();
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/*
|
|
Packit |
76ec6a |
* type determines whether if dialog is for killing process or renice.
|
|
Packit |
76ec6a |
* type == PROCMAN_ACTION_KILL, extra_value -> signal to send
|
|
Packit |
76ec6a |
* type == PROCMAN_ACTION_RENICE, extra_value -> new priority.
|
|
Packit |
76ec6a |
*/
|
|
Packit |
76ec6a |
gboolean
|
|
Packit |
76ec6a |
procdialog_create_root_password_dialog(ProcmanActionType type,
|
|
Packit |
76ec6a |
GsmApplication *app,
|
|
Packit |
76ec6a |
gint pid,
|
|
Packit |
76ec6a |
gint extra_value)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
char * command;
|
|
Packit |
76ec6a |
gboolean ret = FALSE;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
command = procman_action_to_command(type, pid, extra_value);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
procman_debug("Trying to run '%s' as root", command);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (procman_has_pkexec())
|
|
Packit |
76ec6a |
ret = gsm_pkexec_create_root_password_dialog(command);
|
|
Packit |
76ec6a |
else if (procman_has_gksu())
|
|
Packit |
76ec6a |
ret = gsm_gksu_create_root_password_dialog(command);
|
|
Packit |
76ec6a |
else if (procman_has_gnomesu())
|
|
Packit |
76ec6a |
ret = gsm_gnomesu_create_root_password_dialog(command);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
g_free(command);
|
|
Packit |
76ec6a |
return ret;
|
|
Packit |
76ec6a |
}
|