Blame src/shell/killev.c

Packit 15f964
/*
Packit 15f964
 * killev.c
Packit 15f964
 *
Packit 15f964
 * This program is free software; you can redistribute it and/or modify it
Packit 15f964
 * under the terms of the GNU Lesser General Public License as published by
Packit 15f964
 * the Free Software Foundation.
Packit 15f964
 *
Packit 15f964
 * This program is distributed in the hope that it will be useful, but
Packit 15f964
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 15f964
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit 15f964
 * for more details.
Packit 15f964
 *
Packit 15f964
 * You should have received a copy of the GNU Lesser General Public License
Packit 15f964
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit 15f964
 *
Packit 15f964
 *
Packit 15f964
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
Packit 15f964
 *
Packit 15f964
 */
Packit 15f964
Packit 15f964
#include "evolution-config.h"
Packit 15f964
Packit 15f964
#include <signal.h>
Packit 15f964
#include <stdlib.h>
Packit 15f964
#include <unistd.h>
Packit 15f964
#include <sys/wait.h>
Packit 15f964
Packit 15f964
#include <gio/gio.h>
Packit 15f964
#include <glib/gi18n.h>
Packit 15f964
Packit 15f964
#include <libedataserver/libedataserver.h>
Packit 15f964
Packit 15f964
/* Seconds to wait after asking Evolution to terminate gracefully.
Packit 15f964
 * If the process has not terminated before the timeout expires,
Packit 15f964
 * then we get violent. */
Packit 15f964
#define EVOLUTION_SHUTDOWN_TIMEOUT 5
Packit 15f964
Packit 15f964
static GPid evolution_pid;
Packit 15f964
static GMainLoop *main_loop;
Packit 15f964
Packit 15f964
static void
Packit 15f964
file_monitor_changed_cb (GFileMonitor *monitor,
Packit 15f964
                         GFile *file,
Packit 15f964
                         GFile *not_used,
Packit 15f964
                         GFileMonitorEvent event_type)
Packit 15f964
{
Packit 15f964
	if (event_type != G_FILE_MONITOR_EVENT_DELETED)
Packit 15f964
		return;
Packit 15f964
Packit 15f964
	g_print ("Evolution process exited normally\n");
Packit 15f964
Packit 15f964
	g_main_loop_quit (main_loop);
Packit 15f964
}
Packit 15f964
Packit 15f964
static gboolean
Packit 15f964
evolution_not_responding_cb (gpointer user_data)
Packit 15f964
{
Packit 15f964
	g_print ("No response from Evolution -- killing the process\n");
Packit 15f964
Packit 15f964
	/* Kill the process. */
Packit 15f964
	kill ((pid_t) evolution_pid, SIGTERM);
Packit 15f964
Packit 15f964
	g_main_loop_quit (main_loop);
Packit 15f964
Packit 15f964
	return FALSE;
Packit 15f964
}
Packit 15f964
Packit 15f964
static gboolean
Packit 15f964
get_evolution_pid (GFile *file)
Packit 15f964
{
Packit 15f964
	gint64 v_int64;
Packit 15f964
	gchar *contents = NULL;
Packit 15f964
	gboolean success = FALSE;
Packit 15f964
Packit 15f964
	/* Try to read Evolution's PID from its .running file. */
Packit 15f964
Packit 15f964
	if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, NULL))
Packit 15f964
		goto exit;
Packit 15f964
Packit 15f964
	/* Try to extract an integer value from the string. */
Packit 15f964
	v_int64 = g_ascii_strtoll (contents, NULL, 10);
Packit 15f964
	if (!(v_int64 > 0 && v_int64 < G_MAXINT64))
Packit 15f964
		goto exit;
Packit 15f964
Packit 15f964
	/* XXX Probably not portable. */
Packit 15f964
	evolution_pid = (GPid) v_int64;
Packit 15f964
Packit 15f964
	success = TRUE;
Packit 15f964
Packit 15f964
exit:
Packit 15f964
	g_free (contents);
Packit 15f964
Packit 15f964
	return success;
Packit 15f964
}
Packit 15f964
Packit 15f964
gint
Packit 15f964
main (gint argc,
Packit 15f964
      gchar **argv)
Packit 15f964
{
Packit 15f964
	GFile *pid_file = NULL;
Packit 15f964
	GFileMonitor *monitor;
Packit 15f964
	const gchar *user_config_dir;
Packit 15f964
	gchar *filename;
Packit 15f964
	gint retval = EXIT_SUCCESS;
Packit 15f964
	GError *error = NULL;
Packit 15f964
Packit 15f964
	bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR);
Packit 15f964
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
Packit 15f964
	textdomain (GETTEXT_PACKAGE);
Packit 15f964
Packit 15f964
	user_config_dir = e_get_user_config_dir ();
Packit 15f964
	filename = g_build_filename (user_config_dir, ".running", NULL);
Packit 15f964
	pid_file = g_file_new_for_path (filename);
Packit 15f964
	g_free (filename);
Packit 15f964
Packit 15f964
	if (!get_evolution_pid (pid_file)) {
Packit 15f964
		g_printerr ("Could not find Evolution's process ID\n");
Packit 15f964
		retval = EXIT_FAILURE;
Packit 15f964
		goto kill;
Packit 15f964
	}
Packit 15f964
Packit 15f964
	if (g_getenv ("DISPLAY") == NULL)
Packit 15f964
		goto kill;
Packit 15f964
Packit 15f964
	/* Play it safe here and bail if something goes wrong.  We don't
Packit 15f964
	 * want to just skip to the killing if we can't ask Evolution to
Packit 15f964
	 * terminate gracefully.  Despite our name we actually want to
Packit 15f964
	 * -avoid- killing Evolution if at all possible. */
Packit 15f964
	if (!g_spawn_command_line_async ("evolution --quit", &error)) {
Packit 15f964
		g_printerr ("%s\n", error->message);
Packit 15f964
		g_error_free (error);
Packit 15f964
		retval = EXIT_FAILURE;
Packit 15f964
		goto kill;
Packit 15f964
	}
Packit 15f964
Packit 15f964
	/* Now we set up a monitor on Evolution's .running file.
Packit 15f964
	 * If Evolution is still responsive it will delete this
Packit 15f964
	 * file just before terminating and we'll be notified. */
Packit 15f964
	monitor = g_file_monitor_file (pid_file, 0, NULL, &error);
Packit 15f964
	if (error != NULL) {
Packit 15f964
		g_printerr ("%s\n", error->message);
Packit 15f964
		g_error_free (error);
Packit 15f964
		retval = EXIT_FAILURE;
Packit 15f964
		goto kill;
Packit 15f964
	}
Packit 15f964
Packit 15f964
	g_signal_connect (
Packit 15f964
		monitor, "changed",
Packit 15f964
		G_CALLBACK (file_monitor_changed_cb), NULL);
Packit 15f964
Packit 15f964
	e_named_timeout_add_seconds (
Packit 15f964
		EVOLUTION_SHUTDOWN_TIMEOUT,
Packit 15f964
		evolution_not_responding_cb, NULL);
Packit 15f964
Packit 15f964
	/* Start the clock. */
Packit 15f964
Packit 15f964
	main_loop = g_main_loop_new (NULL, TRUE);
Packit 15f964
	g_main_loop_run (main_loop);
Packit 15f964
	g_main_loop_unref (main_loop);
Packit 15f964
Packit 15f964
	g_object_unref (monitor);
Packit 15f964
Packit 15f964
kill:
Packit 15f964
#ifdef KILL_PROCESS_COMMAND
Packit 15f964
#ifdef KILL_PROCESS_COMMAND_ARGS
Packit 15f964
#define KILL_CMD KILL_PROCESS_COMMAND " " KILL_PROCESS_COMMAND_ARGS
Packit 15f964
#else
Packit 15f964
#define KILL_CMD KILL_PROCESS_COMMAND
Packit 15f964
#endif
Packit 15f964
#ifndef KILL_PROCESS_COMMAND_ARG_EXACT
Packit 15f964
#define KILL_PROCESS_COMMAND_ARG_EXACT ""
Packit 15f964
#endif
Packit 15f964
	if (system (KILL_CMD " " KILL_PROCESS_COMMAND_ARG_EXACT " -TERM evolution 2> /dev/null") == -1)
Packit 15f964
		g_warning ("%s: Failed to execute: '%s'", G_STRFUNC, KILL_PROCESS_COMMAND);
Packit 15f964
	if (system (KILL_CMD " -TERM evolution-alarm-notify 2> /dev/null") == -1)
Packit 15f964
		g_warning ("%s: Failed to execute: '%s'", G_STRFUNC, KILL_PROCESS_COMMAND);
Packit 15f964
	if (system (KILL_CMD " -TERM evolution-source-registry 2> /dev/null") == -1)
Packit 15f964
		g_warning ("%s: Failed to execute: '%s'", G_STRFUNC, KILL_PROCESS_COMMAND);
Packit 15f964
	if (system (KILL_CMD " -TERM evolution-addressbook-factory 2> /dev/null") == -1)
Packit 15f964
		g_warning ("%s: Failed to execute: '%s'", G_STRFUNC, KILL_PROCESS_COMMAND);
Packit 15f964
	if (system (KILL_CMD " -TERM evolution-calendar-factory 2> /dev/null") == -1)
Packit 15f964
		g_warning ("%s: Failed to execute: '%s'", G_STRFUNC, KILL_PROCESS_COMMAND);
Packit 15f964
#undef KILL_CMD
Packit 15f964
#else
Packit 15f964
	g_printerr ("No \"kill\" command available.\n");
Packit 15f964
#endif
Packit 15f964
Packit 15f964
	g_clear_object (&pid_file);
Packit 15f964
Packit 15f964
	return retval;
Packit 15f964
}