summaryrefslogtreecommitdiffstats
path: root/src/Applet/Applet.cpp
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-09-18 15:07:11 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-09-18 15:07:11 +0200
commit43fe926f20bd427e96a22081deace10752bb4533 (patch)
tree64a3a9950ad659ad3ff193df2916d05e31fa085c /src/Applet/Applet.cpp
parent73c3f5fba688d9359dbf79f70b8759aee2857e41 (diff)
downloadabrt-43fe926f20bd427e96a22081deace10752bb4533.tar.gz
abrt-43fe926f20bd427e96a22081deace10752bb4533.tar.xz
abrt-43fe926f20bd427e96a22081deace10752bb4533.zip
abrt-applet: remove dbus-c++ glue. -50k of code
text data bss dec hex filename 70529 2144 1528 74201 121d9 abrt.t0/UNPACKED/usr/bin/abrt-applet 22116 1688 376 24180 5e74 abrt.t1/UNPACKED/usr/bin/abrt-applet Also, we do not use dbus-c++ anymore, which is 200k of code Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'src/Applet/Applet.cpp')
-rw-r--r--src/Applet/Applet.cpp249
1 files changed, 205 insertions, 44 deletions
diff --git a/src/Applet/Applet.cpp b/src/Applet/Applet.cpp
index cf58c7da..a75a1425 100644
--- a/src/Applet/Applet.cpp
+++ b/src/Applet/Applet.cpp
@@ -17,95 +17,256 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "CCApplet.h"
#include <iostream>
#include <dbus/dbus-shared.h>
-
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
#if HAVE_CONFIG_H
#include <config.h>
#endif
-
#if HAVE_LOCALE_H
#include <locale.h>
#endif
-
#if ENABLE_NLS
#include <libintl.h>
#define _(S) gettext(S)
#else
#define _(S) (S)
#endif
+#include "abrtlib.h"
+#include "abrt_dbus.h"
+#include "DBusCommon.h"
+#include "CCApplet.h"
+
-//@@global applet object
-CApplet *applet;
+static CApplet* applet;
-static void
-crash_notify_cb(const char* progname)
+
+static void Crash(DBusMessage* signal)
{
- const char *message = _("A crash in package %s has been detected!");
-#ifdef DEBUG
- std::cerr << "Application " << progname << " has crashed!" << std::endl;
-#endif
- //applet->AddEvent(uid, std::string(progname));
+ int r;
+ DBusMessageIter in_iter;
+ if (!dbus_message_iter_init(signal, &in_iter))
+ {
+ /* signal has no parameters */
+ error_msg("dbus signal %s: parameter type mismatch", __func__);
+ return;
+ }
+ const char* progname;
+ r = load_val(&in_iter, progname);
+ if (r != ABRT_DBUS_MORE_FIELDS)
+ {
+ error_msg("dbus signal %s: parameter type mismatch", __func__);
+ return;
+ }
+ const char* uid_str;
+ r = load_val(&in_iter, uid_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;
+ uid_t uid_num = atoi(uid_str);
+
+ if (uid_num != getuid())
+ return;
+
+ const char* message = _("A crash in package %s has been detected");
+ //applet->AddEvent(uid, progname);
applet->SetIconTooltip(message, progname);
applet->ShowIcon();
applet->CrashNotify(message, progname);
}
-static void
-quota_exceed_cb(const char* str)
+static void QuotaExceed(DBusMessage* signal)
{
+ int r;
+ DBusMessageIter in_iter;
+ if (!dbus_message_iter_init(signal, &in_iter))
+ {
+ /* signal has no parameters */
+ error_msg("dbus signal %s: parameter type mismatch", __func__);
+ return;
+ }
+ 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;
applet->ShowIcon();
applet->CrashNotify("%s", str);
}
-int main(int argc, char **argv)
+static void NameOwnerChanged(DBusMessage* signal)
+{
+ int r;
+ DBusMessageIter in_iter;
+ if (!dbus_message_iter_init(signal, &in_iter))
+ {
+ /* signal has no parameters */
+ error_msg("dbus signal %s: parameter type mismatch", __func__);
+ return;
+ }
+ 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;
+ }
+
+ if (new_owner[0])
+ applet->Enable(_("ABRT service has been started"));
+ else
+ applet->Disable(_("ABRT service is not running"));
+}
+
+static DBusHandlerResult handle_message(DBusConnection* conn, DBusMessage* msg, void* user_data)
+{
+ const char* member = dbus_message_get_member(msg);
+ 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)
{
- setlocale(LC_ALL,"");
+ 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)
+{
+ /* I18n */
+ setlocale(LC_ALL, "");
#if ENABLE_NLS
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
- /* need to be thread safe */
+ /* Need to be thread safe */
g_thread_init(NULL);
gdk_threads_init();
gdk_threads_enter();
- gtk_init(&argc,&argv);
- /* prevent zombies when we spawn abrt-gui */
- signal(SIGCHLD, SIG_IGN);
- /* move to the DBusClient::connect */
- DBus::Glib::BusDispatcher dispatcher;
- /* this should bind the dispatcher with mainloop */
- dispatcher.attach(NULL);
- DBus::default_dispatcher = &dispatcher;
- DBus::Connection session = DBus::Connection::SessionBus();
- //FIXME: possible race, but the dbus-c++ API won't let us check return value of request_name :(
- if(session.has_name("com.redhat.abrt.applet"))
+ /* Parse options */
+ int opt;
+ while ((opt = getopt(argc, argv, "dv")) != -1)
{
- //applet is already running
- std::cerr << _("Applet is already running.") << std::endl;
- return -1;
- }
- else
- {
- //applet is not running, so claim the name on the session bus
- session.request_name("com.redhat.abrt.applet");
+ 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);
+ 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");
- DBus::Connection conn = DBus::Connection::SystemBus();
- applet = new CApplet(conn, session, CC_DBUS_PATH, CC_DBUS_NAME);
- applet->ConnectCrashHandler(crash_notify_cb);
- applet->ConnectQuotaExceedHandler(quota_exceed_cb);
- if(!conn.has_name(CC_DBUS_NAME))
+ /* Initialize GUI stuff.
+ * Note: inside CApplet ctor, libnotify hooks session dbus
+ * to glib main loop */
+ applet = new CApplet;
+ /* 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 disabled icon if daemon is not running */
+ if (!dbus_bus_name_has_owner(system_conn, CC_DBUS_NAME, &err))
{
- std::cout << _("ABRT service is not running") << std::endl;
- applet->Disable(_("ABRT service is not running"));
+ const char* msg = _("ABRT service is not running");
+ puts(msg);
+ applet->Disable(msg);
}
+ /* Enter main loop */
gtk_main();
+
gdk_threads_leave();
delete applet;
return 0;