From 89295b6bec0ea4eae5af3b09bf0df74a51b60e94 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 9 Dec 2010 18:11:04 +0100 Subject: convert Applet.cpp to C. Needed only one change: dbus' load_val -> load_charp Signed-off-by: Denys Vlasenko --- src/applet/Applet.cpp | 303 ------------------------------------------------- src/applet/Makefile.am | 2 +- src/applet/applet.c | 303 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 304 insertions(+), 304 deletions(-) delete mode 100644 src/applet/Applet.cpp create mode 100644 src/applet/applet.c (limited to 'src') diff --git a/src/applet/Applet.cpp b/src/applet/Applet.cpp deleted file mode 100644 index 4ce497cf..00000000 --- a/src/applet/Applet.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com) - Copyright (C) 2009 RedHat inc. - - 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., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#if HAVE_LOCALE_H -# include -#endif -#include -#include -#include -#include "abrtlib.h" -#include "abrt_dbus.h" -#include "dbus_common.h" -#include "applet_gtk.h" - - -static struct applet* applet = NULL; - - -static void Crash(DBusMessage* signal) -{ - int r; - DBusMessageIter in_iter; - dbus_message_iter_init(signal, &in_iter); - - /* 1st param: package */ - const char* package_name; - r = load_val(&in_iter, package_name); - - /* 2nd param: crash_id */ - if (r != ABRT_DBUS_MORE_FIELDS) - { - error_msg("dbus signal %s: parameter type mismatch", __func__); - return; - } - const char* crash_id = NULL; - r = load_val(&in_iter, crash_id); - - /* 3rd param: dir */ -//dir parameter is not used for now, use is planned in the future - if (r != ABRT_DBUS_MORE_FIELDS) - { - error_msg("dbus signal %s: parameter type mismatch", __func__); - return; - } - const char* dir = NULL; - r = load_val(&in_iter, dir); - - /* Optional 4th param: uid */ - const char* uid_str = NULL; - if (r == ABRT_DBUS_MORE_FIELDS) - { - r = load_val(&in_iter, uid_str); - } - if (r != ABRT_DBUS_LAST_FIELD) - { - error_msg("dbus signal %s: parameter type mismatch", __func__); - return; - } - - if (uid_str != NULL) - { - char *end; - errno = 0; - unsigned long uid_num = strtoul(uid_str, &end, 10); - if (errno || *end != '\0' || uid_num != getuid()) - { - return; - } - } - - const char* message = _("A crash in the %s package has been detected"); - if (package_name[0] == '\0') - message = _("A crash has been detected"); - //applet->AddEvent(uid, package_name); - set_icon_tooltip(applet, message, package_name); - show_icon(applet); - - /* If this crash seems to be repeating, do not annoy user with popup dialog. - * (The icon in the tray is not suppressed) - */ - static time_t last_time = 0; - static char* last_package_name = NULL; - static char* last_crash_id = NULL; - time_t cur_time = time(NULL); - if (last_package_name && strcmp(last_package_name, package_name) == 0 - && last_crash_id && strcmp(last_crash_id, crash_id) == 0 - && (unsigned)(cur_time - last_time) < 2 * 60 * 60 - ) { - log_msg("repeated crash in %s, not showing the notification", package_name); - return; - } - last_time = cur_time; - free(last_package_name); - last_package_name = xstrdup(package_name); - free(last_crash_id); - last_crash_id = xstrdup(crash_id); - - show_crash_notification(applet, crash_id, message, package_name); -} - -static void QuotaExceed(DBusMessage* signal) -{ - int r; - DBusMessageIter in_iter; - dbus_message_iter_init(signal, &in_iter); - const char* str; - r = load_val(&in_iter, str); - if (r != ABRT_DBUS_LAST_FIELD) - { - error_msg("dbus signal %s: parameter type mismatch", __func__); - return; - } - - //if (m_pSessionDBus->has_name("com.redhat.abrt.gui")) - // return; - show_icon(applet); - show_msg_notification(applet, "%s", str); -} - -static void NameOwnerChanged(DBusMessage* signal) -{ - int r; - DBusMessageIter in_iter; - dbus_message_iter_init(signal, &in_iter); - const char* name; - r = load_val(&in_iter, name); - if (r != ABRT_DBUS_MORE_FIELDS) - { - error_msg("dbus signal %s: parameter type mismatch", __func__); - return; - } - - /* We are only interested in (dis)appearances of our daemon */ - if (strcmp(name, "com.redhat.abrt") != 0) - return; - - const char* old_owner; - r = load_val(&in_iter, old_owner); - if (r != ABRT_DBUS_MORE_FIELDS) - { - error_msg("dbus signal %s: parameter type mismatch", __func__); - return; - } - const char* new_owner; - r = load_val(&in_iter, new_owner); - if (r != ABRT_DBUS_LAST_FIELD) - { - error_msg("dbus signal %s: parameter type mismatch", __func__); - return; - } - -// hide icon if it's visible - as NM and don't show it, if it's not - if (!new_owner[0]) - hide_icon(applet); -} - -static DBusHandlerResult handle_message(DBusConnection* conn, DBusMessage* msg, void* user_data) -{ - const char* member = dbus_message_get_member(msg); - - VERB1 log("%s(member:'%s')", __func__, member); - - int type = dbus_message_get_type(msg); - if (type != DBUS_MESSAGE_TYPE_SIGNAL) - { - log("The message is not a signal. ignoring"); - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (strcmp(member, "NameOwnerChanged") == 0) - NameOwnerChanged(msg); - else if (strcmp(member, "Crash") == 0) - Crash(msg); - else if (strcmp(member, "QuotaExceed") == 0) - QuotaExceed(msg); - - return DBUS_HANDLER_RESULT_HANDLED; -} - -//TODO: move to abrt_dbus.cpp -static void die_if_dbus_error(bool error_flag, DBusError* err, const char* msg) -{ - if (dbus_error_is_set(err)) - { - error_msg("dbus error: %s", err->message); - /*dbus_error_free(&err); - why bother, we will exit in a microsecond */ - error_flag = true; - } - if (!error_flag) - return; - error_msg_and_die("%s", msg); -} - -int main(int argc, char** argv) -{ - const char * app_name = "abrt-gui"; - /* I18n */ - setlocale(LC_ALL, ""); -#if ENABLE_NLS - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); -#endif - - /* Need to be thread safe */ - g_thread_init(NULL); - gdk_threads_init(); - gdk_threads_enter(); - - /* Parse options */ - int opt; - while ((opt = getopt(argc, argv, "dv")) != -1) - { - switch (opt) - { - case 'v': - g_verbose++; - break; - default: - error_msg_and_die( - "Usage: abrt-applet [-v]\n" - "\nOptions:" - "\n\t-v\tVerbose" - ); - } - } - gtk_init(&argc, &argv); - - /* Prevent zombies when we spawn abrt-gui */ - signal(SIGCHLD, SIG_IGN); - - /* Initialize our (dbus_abrt) machinery: hook _system_ dbus to glib main loop. - * (session bus is left to be handled by libnotify, see below) */ - DBusError err; - dbus_error_init(&err); - DBusConnection* system_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - die_if_dbus_error(system_conn == NULL, &err, "Can't connect to system dbus"); - attach_dbus_conn_to_glib_main_loop(system_conn, NULL, NULL); - if (!dbus_connection_add_filter(system_conn, handle_message, NULL, NULL)) - error_msg_and_die("Can't add dbus filter"); - /* which messages do we want to be fed to handle_message()? */ - //signal sender=org.freedesktop.DBus -> path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged - // string "com.redhat.abrt" - // string "" - // string ":1.70" - dbus_bus_add_match(system_conn, "type='signal',member='NameOwnerChanged'", &err); - die_if_dbus_error(false, &err, "Can't add dbus match"); - //signal sender=:1.73 -> path=/com/redhat/abrt; interface=com.redhat.abrt; member=Crash - // string "coreutils-7.2-3.fc11" - // string "0" - dbus_bus_add_match(system_conn, "type='signal',path='/com/redhat/abrt'", &err); - die_if_dbus_error(false, &err, "Can't add dbus match"); - - /* Initialize GUI stuff. - * Note: inside CApplet ctor, libnotify hooks session dbus - * to glib main loop */ - applet = applet_new(app_name); - /* dbus_abrt cannot handle more than one bus, and we don't really need to. - * The only thing we want to do is to announce ourself on session dbus */ - DBusConnection* session_conn = dbus_bus_get(DBUS_BUS_SESSION, &err); - die_if_dbus_error(session_conn == NULL, &err, "Can't connect to session dbus"); - int r = dbus_bus_request_name(session_conn, - "com.redhat.abrt.applet", - /* flags */ DBUS_NAME_FLAG_DO_NOT_QUEUE, &err); - die_if_dbus_error(r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER, &err, - "Problem connecting to dbus, or applet is already running"); - - /* show the warning in terminal, as nm-applet does */ - if (!dbus_bus_name_has_owner(system_conn, ABRTD_DBUS_NAME, &err)) - { - const char* msg = _("ABRT service is not running"); - puts(msg); - } - - /* dbus_bus_request_name can already read some data. Thus while dbus fd hasn't - * any data anymore, dbus library can buffer a message or two. - * If we don't do this, the data won't be processed until next dbus data arrives. - */ - int cnt = 10; - while (dbus_connection_dispatch(system_conn) != DBUS_DISPATCH_COMPLETE && --cnt) - continue; - - /* Enter main loop */ - gtk_main(); - - gdk_threads_leave(); - applet_destroy(applet); - return 0; -} diff --git a/src/applet/Makefile.am b/src/applet/Makefile.am index 294f0fed..cd4a643f 100644 --- a/src/applet/Makefile.am +++ b/src/applet/Makefile.am @@ -2,7 +2,7 @@ bin_PROGRAMS = abrt-applet #test-report abrt_applet_SOURCES = \ - Applet.cpp \ + applet.c \ applet_gtk.h applet_gtk.c abrt_applet_CPPFLAGS = \ -I$(srcdir)/../include/report -I$(srcdir)/../include \ diff --git a/src/applet/applet.c b/src/applet/applet.c new file mode 100644 index 00000000..37c5f386 --- /dev/null +++ b/src/applet/applet.c @@ -0,0 +1,303 @@ +/* + Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com) + Copyright (C) 2009 RedHat inc. + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#if HAVE_LOCALE_H +# include +#endif +#include +#include +#include +#include "abrtlib.h" +#include "abrt_dbus.h" +#include "dbus_common.h" +#include "applet_gtk.h" + + +static struct applet* applet = NULL; + + +static void Crash(DBusMessage* signal) +{ + int r; + DBusMessageIter in_iter; + dbus_message_iter_init(signal, &in_iter); + + /* 1st param: package */ + const char* package_name = NULL; + r = load_charp(&in_iter, &package_name); + + /* 2nd param: crash_id */ + if (r != ABRT_DBUS_MORE_FIELDS) + { + error_msg("dbus signal %s: parameter type mismatch", __func__); + return; + } + const char* crash_id = NULL; + r = load_charp(&in_iter, &crash_id); + + /* 3rd param: dir */ +//dir parameter is not used for now, use is planned in the future + if (r != ABRT_DBUS_MORE_FIELDS) + { + error_msg("dbus signal %s: parameter type mismatch", __func__); + return; + } + const char* dir = NULL; + r = load_charp(&in_iter, &dir); + + /* Optional 4th param: uid */ + const char* uid_str = NULL; + if (r == ABRT_DBUS_MORE_FIELDS) + { + r = load_charp(&in_iter, &uid_str); + } + if (r != ABRT_DBUS_LAST_FIELD) + { + error_msg("dbus signal %s: parameter type mismatch", __func__); + return; + } + + if (uid_str != NULL) + { + char *end; + errno = 0; + unsigned long uid_num = strtoul(uid_str, &end, 10); + if (errno || *end != '\0' || uid_num != getuid()) + { + return; + } + } + + const char* message = _("A crash in the %s package has been detected"); + if (package_name[0] == '\0') + message = _("A crash has been detected"); + //applet->AddEvent(uid, package_name); + set_icon_tooltip(applet, message, package_name); + show_icon(applet); + + /* If this crash seems to be repeating, do not annoy user with popup dialog. + * (The icon in the tray is not suppressed) + */ + static time_t last_time = 0; + static char* last_package_name = NULL; + static char* last_crash_id = NULL; + time_t cur_time = time(NULL); + if (last_package_name && strcmp(last_package_name, package_name) == 0 + && last_crash_id && strcmp(last_crash_id, crash_id) == 0 + && (unsigned)(cur_time - last_time) < 2 * 60 * 60 + ) { + log_msg("repeated crash in %s, not showing the notification", package_name); + return; + } + last_time = cur_time; + free(last_package_name); + last_package_name = xstrdup(package_name); + free(last_crash_id); + last_crash_id = xstrdup(crash_id); + + show_crash_notification(applet, crash_id, message, package_name); +} + +static void QuotaExceed(DBusMessage* signal) +{ + int r; + DBusMessageIter in_iter; + dbus_message_iter_init(signal, &in_iter); + const char* str = NULL; + r = load_charp(&in_iter, &str); + if (r != ABRT_DBUS_LAST_FIELD) + { + error_msg("dbus signal %s: parameter type mismatch", __func__); + return; + } + + //if (m_pSessionDBus->has_name("com.redhat.abrt.gui")) + // return; + show_icon(applet); + show_msg_notification(applet, "%s", str); +} + +static void NameOwnerChanged(DBusMessage* signal) +{ + int r; + DBusMessageIter in_iter; + dbus_message_iter_init(signal, &in_iter); + const char* name = NULL; + r = load_charp(&in_iter, &name); + if (r != ABRT_DBUS_MORE_FIELDS) + { + error_msg("dbus signal %s: parameter type mismatch", __func__); + return; + } + + /* We are only interested in (dis)appearances of our daemon */ + if (strcmp(name, "com.redhat.abrt") != 0) + return; + + const char* old_owner = NULL; + r = load_charp(&in_iter, &old_owner); + if (r != ABRT_DBUS_MORE_FIELDS) + { + error_msg("dbus signal %s: parameter type mismatch", __func__); + return; + } + const char* new_owner = NULL; + r = load_charp(&in_iter, &new_owner); + if (r != ABRT_DBUS_LAST_FIELD) + { + error_msg("dbus signal %s: parameter type mismatch", __func__); + return; + } + +// hide icon if it's visible - as NM and don't show it, if it's not + if (!new_owner[0]) + hide_icon(applet); +} + +static DBusHandlerResult handle_message(DBusConnection* conn, DBusMessage* msg, void* user_data) +{ + const char* member = dbus_message_get_member(msg); + + VERB1 log("%s(member:'%s')", __func__, member); + + int type = dbus_message_get_type(msg); + if (type != DBUS_MESSAGE_TYPE_SIGNAL) + { + log("The message is not a signal. ignoring"); + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (strcmp(member, "NameOwnerChanged") == 0) + NameOwnerChanged(msg); + else if (strcmp(member, "Crash") == 0) + Crash(msg); + else if (strcmp(member, "QuotaExceed") == 0) + QuotaExceed(msg); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +//TODO: move to abrt_dbus.cpp +static void die_if_dbus_error(bool error_flag, DBusError* err, const char* msg) +{ + if (dbus_error_is_set(err)) + { + error_msg("dbus error: %s", err->message); + /*dbus_error_free(&err); - why bother, we will exit in a microsecond */ + error_flag = true; + } + if (!error_flag) + return; + error_msg_and_die("%s", msg); +} + +int main(int argc, char** argv) +{ + const char * app_name = "abrt-gui"; + /* I18n */ + setlocale(LC_ALL, ""); +#if ENABLE_NLS + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); +#endif + + /* Need to be thread safe */ + g_thread_init(NULL); + gdk_threads_init(); + gdk_threads_enter(); + + /* Parse options */ + int opt; + while ((opt = getopt(argc, argv, "dv")) != -1) + { + switch (opt) + { + case 'v': + g_verbose++; + break; + default: + error_msg_and_die( + "Usage: abrt-applet [-v]\n" + "\nOptions:" + "\n\t-v\tVerbose" + ); + } + } + gtk_init(&argc, &argv); + + /* Prevent zombies when we spawn abrt-gui */ + signal(SIGCHLD, SIG_IGN); + + /* Initialize our (dbus_abrt) machinery: hook _system_ dbus to glib main loop. + * (session bus is left to be handled by libnotify, see below) */ + DBusError err; + dbus_error_init(&err); + DBusConnection* system_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + die_if_dbus_error(system_conn == NULL, &err, "Can't connect to system dbus"); + attach_dbus_conn_to_glib_main_loop(system_conn, NULL, NULL); + if (!dbus_connection_add_filter(system_conn, handle_message, NULL, NULL)) + error_msg_and_die("Can't add dbus filter"); + /* which messages do we want to be fed to handle_message()? */ + //signal sender=org.freedesktop.DBus -> path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged + // string "com.redhat.abrt" + // string "" + // string ":1.70" + dbus_bus_add_match(system_conn, "type='signal',member='NameOwnerChanged'", &err); + die_if_dbus_error(false, &err, "Can't add dbus match"); + //signal sender=:1.73 -> path=/com/redhat/abrt; interface=com.redhat.abrt; member=Crash + // string "coreutils-7.2-3.fc11" + // string "0" + dbus_bus_add_match(system_conn, "type='signal',path='/com/redhat/abrt'", &err); + die_if_dbus_error(false, &err, "Can't add dbus match"); + + /* Initialize GUI stuff. + * Note: inside CApplet ctor, libnotify hooks session dbus + * to glib main loop */ + applet = applet_new(app_name); + /* dbus_abrt cannot handle more than one bus, and we don't really need to. + * The only thing we want to do is to announce ourself on session dbus */ + DBusConnection* session_conn = dbus_bus_get(DBUS_BUS_SESSION, &err); + die_if_dbus_error(session_conn == NULL, &err, "Can't connect to session dbus"); + int r = dbus_bus_request_name(session_conn, + "com.redhat.abrt.applet", + /* flags */ DBUS_NAME_FLAG_DO_NOT_QUEUE, &err); + die_if_dbus_error(r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER, &err, + "Problem connecting to dbus, or applet is already running"); + + /* show the warning in terminal, as nm-applet does */ + if (!dbus_bus_name_has_owner(system_conn, ABRTD_DBUS_NAME, &err)) + { + const char* msg = _("ABRT service is not running"); + puts(msg); + } + + /* dbus_bus_request_name can already read some data. Thus while dbus fd hasn't + * any data anymore, dbus library can buffer a message or two. + * If we don't do this, the data won't be processed until next dbus data arrives. + */ + int cnt = 10; + while (dbus_connection_dispatch(system_conn) != DBUS_DISPATCH_COMPLETE && --cnt) + continue; + + /* Enter main loop */ + gtk_main(); + + gdk_threads_leave(); + applet_destroy(applet); + return 0; +} -- cgit