diff options
Diffstat (limited to 'src/mandi_daemon.c')
-rw-r--r-- | src/mandi_daemon.c | 269 |
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); +} |