summaryrefslogtreecommitdiffstats
path: root/src/mandi_daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mandi_daemon.c')
-rw-r--r--src/mandi_daemon.c269
1 files changed, 269 insertions, 0 deletions
diff --git a/src/mandi_daemon.c b/src/mandi_daemon.c
new file mode 100644
index 0000000..6c67d88
--- /dev/null
+++ b/src/mandi_daemon.c
@@ -0,0 +1,269 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include <time.h>
+#include <unistd.h>
+
+#include <dbus/dbus.h>
+#include <errno.h>
+
+#include "plugin.h"
+
+#define MANDI_DAEMON_SERVICE PLUGIN_ROOT_INTF
+
+typedef struct {
+ DBusConnection *bus;
+ DBusWatch *bus_read_watch;
+ int bus_read_fd;
+} mandi_daemon_t;
+
+extern plugin_t wpa_supplicant_plugin;
+extern plugin_t ifw_plugin;
+plugin_t *plugins[] = {
+ &wpa_supplicant_plugin,
+ &ifw_plugin,
+ NULL,
+};
+
+static mandi_daemon_t *mandi_daemon_p; /* global variable used in signal handlers only */
+static void sigquit(int signum);
+static int mandi_daemon_init(mandi_daemon_t *daemon);
+static void mandi_daemon_exit(mandi_daemon_t *daemon, int exit_code);
+static void mandi_daemon_handle_dbus(mandi_daemon_t *daemon);
+static int mandi_daemon_acquire_service(mandi_daemon_t *daemon);
+static int mandi_daemon_init_watch(mandi_daemon_t *daemon);
+static dbus_bool_t mandi_daemon_add_watch(DBusWatch *watch, void *data);
+static void mandi_daemon_toggle_watch(DBusWatch *watch, void *data);
+static void mandi_daemon_remove_watch(DBusWatch *watch, void *data);
+static DBusConnection *mandi_daemon_get_system_bus();
+static int mandi_daemon_init_path(mandi_daemon_t *daemon, plugin_t *plugin);
+static void mandi_daemon_object_path_unregister(DBusConnection *connection, void *user_data);
+static DBusHandlerResult mandi_daemon_object_path_handle_message(DBusConnection *connection, DBusMessage *message, void *user_data);
+
+int main(int argc, char **argv)
+{
+ mandi_daemon_t mandi_daemon;
+
+ /* set up signal handlers to exit nicely when needed */
+ mandi_daemon_p = &mandi_daemon;
+ signal(SIGINT, sigquit);
+ signal(SIGTERM, sigquit);
+ signal(SIGQUIT, sigquit);
+
+ mandi_daemon_init(&mandi_daemon);
+
+ if (getopt(argc, argv, "d") == 'd') {
+ daemon(0, 0);
+ }
+
+ printf("Monitoring daemon waiting for events ...\n");
+
+ while (1) {
+ int num_fds;
+ fd_set read_fds;
+ plugin_t **ptr;
+ plugin_t *plugin;
+
+ FD_ZERO(&read_fds);
+ FD_SET(mandi_daemon.bus_read_fd, &read_fds);
+ num_fds = mandi_daemon.bus_read_fd + 1;
+ for (ptr = plugins; *ptr; ptr++) {
+ plugin = *ptr;
+ if (plugin->fd >= 0) {
+ FD_SET(plugin->fd, &read_fds);
+ if (plugin->fd + 1 > num_fds) {
+ num_fds = plugin->fd + 1;
+ }
+ }
+ }
+
+ if (select(num_fds, &read_fds, NULL, NULL, NULL) > 0) {
+ if (FD_ISSET(mandi_daemon.bus_read_fd, &read_fds)) {
+ mandi_daemon_handle_dbus(&mandi_daemon);
+ }
+ for (ptr = plugins; *ptr; ptr++) {
+ plugin = *ptr;
+ if (plugin->fd >= 0 && FD_ISSET(plugin->fd, &read_fds)) {
+ plugin->handle_incoming(plugin, mandi_daemon.bus);
+ }
+ }
+ } else {
+ fprintf(stderr, "unhandled error in select(): %s\n", strerror(errno));
+
+ }
+ }
+
+ mandi_daemon_exit(&mandi_daemon, EXIT_SUCCESS);
+ return 0;
+}
+
+static void sigquit(int signum) {
+ printf("SIGINT, SIGTERM or SIGQUIT catched, trying to exit nicely\n");
+ mandi_daemon_exit(mandi_daemon_p, EXIT_SUCCESS);
+}
+
+static int mandi_daemon_init(mandi_daemon_t *daemon) {
+ plugin_t **ptr;
+ plugin_t *plugin;
+
+ daemon->bus = mandi_daemon_get_system_bus();
+ if (!daemon->bus) {
+ mandi_daemon_exit(daemon, EXIT_FAILURE);
+ }
+
+ if (mandi_daemon_init_watch(daemon) != 0) {
+ fprintf(stderr, "unable to init DBus watch\n");
+ mandi_daemon_exit(daemon, EXIT_FAILURE);
+ }
+
+ if (mandi_daemon_acquire_service(daemon) != 0) {
+ fprintf(stderr, "unable to init DBus service\n");
+ mandi_daemon_exit(daemon, EXIT_FAILURE);
+ }
+
+ for (ptr = plugins; *ptr; ptr++) {
+ plugin = *ptr;
+ if (plugin->init(plugin, daemon->bus) != 0) {
+ fprintf(stderr, "unable to init \"%s\" plugin\n", plugin->name);
+ mandi_daemon_exit(daemon, EXIT_FAILURE);
+ }
+
+ mandi_daemon_init_path(daemon, plugin);
+ }
+
+ return 0;
+}
+
+static void mandi_daemon_exit(mandi_daemon_t *daemon, int exit_code) {
+ plugin_t **ptr;
+ plugin_t *plugin;
+ for (ptr = plugins; *ptr; ptr++) {
+ plugin = *ptr;
+ plugin->deinit(plugin, daemon->bus);
+ }
+ /* unregister dbus */
+ exit(exit_code);
+}
+
+static void mandi_daemon_handle_dbus(mandi_daemon_t *daemon) {
+ dbus_watch_handle(daemon->bus_read_watch, DBUS_WATCH_READABLE);
+ dbus_connection_dispatch(daemon->bus);
+}
+
+int mandi_daemon_acquire_service(mandi_daemon_t *daemon) {
+ DBusError error;
+ dbus_error_init(&error);
+
+ if (dbus_bus_acquire_service(daemon->bus, MANDI_DAEMON_SERVICE, 0, &error) == -1) {
+ fprintf(stderr, "dbus_bus_acquire_service(): %s\n", error.message);
+ fprintf(stderr, "Make sure a DBus policy allows you to acquire this service.\n");
+ dbus_error_free(&error);
+ return -1;
+ }
+ dbus_connection_dispatch(daemon->bus);
+
+ dbus_error_free(&error);
+ return 0;
+}
+
+/* get fds to be watched */
+static int mandi_daemon_init_watch(mandi_daemon_t *daemon) {
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ if (dbus_connection_set_watch_functions(daemon->bus,
+ mandi_daemon_add_watch,
+ mandi_daemon_toggle_watch,
+ mandi_daemon_remove_watch,
+ (void *) daemon,
+ NULL) == FALSE) {
+ fprintf(stderr, "dbus_connection_set_watch_functions(): %s\n", error.message);
+ dbus_error_free(&error);
+ return -1;
+ }
+ dbus_connection_dispatch(daemon->bus);
+
+ dbus_error_free(&error);
+ return 0;
+}
+
+static dbus_bool_t mandi_daemon_add_watch(DBusWatch *watch, void *data) {
+ mandi_daemon_t *daemon = (mandi_daemon_t *) data;
+ if (dbus_watch_get_flags(watch) & DBUS_WATCH_READABLE) {
+ fprintf(stderr, "mandi_daemon_add_watch(): READABLE\n");
+ daemon->bus_read_watch = watch;
+ daemon->bus_read_fd = dbus_watch_get_fd(daemon->bus_read_watch);
+ }
+ /* do nothing for WRITABLE watch, we dispatch when needed */
+ return TRUE;
+}
+
+static void mandi_daemon_toggle_watch(DBusWatch *watch, void *data) {
+ fprintf(stderr, "mandi_daemon_toggle_watch()\n");
+ /* FIXME : do we need to do something here ? */
+}
+
+static void mandi_daemon_remove_watch(DBusWatch *watch, void *data) {
+ if (dbus_watch_get_flags(watch) & DBUS_WATCH_READABLE) {
+ fprintf(stderr, "mandi_daemon_remove_watch(): READABLE\n");
+ /* FIXME : do we need to do something here ? */
+ }
+}
+
+/* set a connection to the system bus */
+static DBusConnection *mandi_daemon_get_system_bus() {
+ DBusConnection *bus;
+ DBusError error;
+ dbus_error_init(&error);
+
+ bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ if (!bus) {
+ fprintf(stderr, "Failed to connect to the D-BUS daemon: %s\n", error.message);
+ dbus_error_free(&error);
+ return NULL;
+ }
+
+ dbus_error_free(&error);
+ return bus;
+}
+
+static int mandi_daemon_init_path(mandi_daemon_t *daemon, plugin_t *plugin) {
+ struct DBusObjectPathVTable object_path_vtable = {
+ mandi_daemon_object_path_unregister,
+ mandi_daemon_object_path_handle_message,
+ NULL, NULL, NULL, NULL
+ };
+
+ DBusError error;
+ dbus_error_init(&error);
+
+ if (dbus_connection_register_object_path(daemon->bus, plugin->path, &object_path_vtable, plugin) == FALSE) {
+ fprintf(stderr, "dbus_connection_register_object_path(): not enough memory\n");
+ dbus_error_free(&error);
+ return -1;
+ }
+ dbus_connection_dispatch(daemon->bus);
+
+ dbus_error_free(&error);
+ return 0;
+}
+
+static void mandi_daemon_object_path_unregister(DBusConnection *connection, void *user_data) {
+}
+
+static DBusHandlerResult mandi_daemon_object_path_handle_message(DBusConnection *connection, DBusMessage *message, void *user_data) {
+ plugin_t *plugin = (plugin_t *) user_data;
+
+ printf("handling method call '%s' on interface '%s'\n",
+ dbus_message_get_member(message),
+ dbus_message_get_interface(message));
+
+ return plugin->handle_message(connection, message, plugin);
+}