diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2007-01-16 17:01:31 +0000 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@nokia.com> | 2007-01-16 17:01:31 +0000 |
commit | a9cf92a289a833ed3785ccbaae306cbbcd8af7bc (patch) | |
tree | a6605b614d50f3824666e257e5a6f192a0a0c2ce /hcid/dbus-service.c | |
parent | 18a13b29f55177bf663c69a651b7b54ed80b2b6b (diff) |
Support for adding and removing .service files in /etc/bluetooth
Diffstat (limited to 'hcid/dbus-service.c')
-rw-r--r-- | hcid/dbus-service.c | 147 |
1 files changed, 85 insertions, 62 deletions
diff --git a/hcid/dbus-service.c b/hcid/dbus-service.c index e060938e..bb9bc336 100644 --- a/hcid/dbus-service.c +++ b/hcid/dbus-service.c @@ -37,6 +37,7 @@ #include "hcid.h" #include "dbus.h" +#include "notify.h" #include "dbus-common.h" #include "dbus-error.h" #include "dbus-manager.h" @@ -125,6 +126,9 @@ static void service_free(struct service *service) if (!service) return; + if (service->filename) + free(service->filename); + if (service->object_path) free(service->object_path); @@ -735,16 +739,18 @@ static const DBusObjectPathVTable services_vtable = { .unregister_function = NULL }; -int register_service(char *path, struct service *service) +static int register_service(struct service *service) { - char obj_path[PATH_MAX], *slash; + char obj_path[PATH_MAX], *suffix; DBusConnection *conn = get_dbus_connection(); DBusMessage *signal; - path[strlen(path) - strlen(SERVICE_SUFFIX)] = '\0'; - slash = strrchr(path, '/'); + snprintf(obj_path, sizeof(obj_path) - 1, "/org/bluez/service_%s", + service->filename); - snprintf(obj_path, sizeof(obj_path) - 1, "/org/bluez/service_%s", slash + 1); + /* Don't include the .service part in the path */ + suffix = strstr(obj_path, SERVICE_SUFFIX); + *suffix = '\0'; debug("Registering service object: exec=%s, name=%s (%s)", service->exec, service->name, obj_path); @@ -755,7 +761,7 @@ int register_service(char *path, struct service *service) service->object_path = strdup(obj_path); - services = g_slist_append(services, strdup(obj_path)); + services = g_slist_append(services, service); signal = dbus_message_new_signal(BASE_PATH, MANAGER_INTERFACE, "ServiceAdded"); @@ -771,51 +777,23 @@ int register_service(char *path, struct service *service) return 0; } -int unregister_service(const char *sender, const char *path) +static int unregister_service(struct service *service) { - struct service *service; + DBusMessage *signal; DBusConnection *conn = get_dbus_connection(); - GSList *l; - - debug("Unregistering service object: %s", path); - - if (dbus_connection_get_object_path_data(conn, path, (void *) &service)) { - /* No data assigned to this path or it is not the owner */ - if (!service || strcmp(sender, service->bus_name)) - return -EPERM; - - if (service->records) - unregister_service_records(service->records); - service_free(service); - } + debug("Unregistering service object: %s", service->object_path); - if (!dbus_connection_unregister_object_path(conn, path)) + if (!dbus_connection_unregister_object_path(conn, service->object_path)) return -ENOMEM; - name_listener_remove(conn, sender, (name_cb_t) service_exit, service); - - l = g_slist_find_custom(services, path, (GCompareFunc) strcmp); - if (l) { - void *p = l->data; - services = g_slist_remove(services, l->data); - free(p); - } - - return 0; -} - -static void release_service(struct service *service) -{ - DBusMessage *signal; - signal = dbus_message_new_signal(BASE_PATH, MANAGER_INTERFACE, "ServiceRemoved"); if (signal) { dbus_message_append_args(signal, DBUS_TYPE_STRING, &service->object_path, DBUS_TYPE_INVALID); - send_message_and_unref(get_dbus_connection(), signal); + send_message_and_unref(conn, signal); } if (service->records) @@ -850,33 +828,16 @@ static void release_service(struct service *service) if (service->shutdown_timer) g_timeout_remove(service->shutdown_timer); + services = g_slist_remove(services, service); + service_free(service); } void release_services(DBusConnection *conn) { - GSList *l = services; - struct service *service; - const char *path; - debug("release_services"); - while (l) { - path = l->data; - - l = l->next; - - if (dbus_connection_get_object_path_data(conn, path, (void *) &service)) { - if (!service) - continue; - - release_service(service); - } - - dbus_connection_unregister_object_path(conn, path); - } - - g_slist_foreach(services, (GFunc) free, NULL); + g_slist_foreach(services, (GFunc) unregister_service, NULL); g_slist_free(services); services = NULL; } @@ -909,15 +870,19 @@ void append_available_services(DBusMessageIter *array_iter) { GSList *l; - for (l = services; l != NULL; l = l->next) + for (l = services; l != NULL; l = l->next) { + struct service *service = l->data; + dbus_message_iter_append_basic(array_iter, - DBUS_TYPE_STRING, &l->data); + DBUS_TYPE_STRING, &service->object_path); + } } static struct service *create_service(const char *file) { GKeyFile *keyfile; struct service *service; + const char *slash; service = malloc(sizeof(struct service)); if (!service) { @@ -948,6 +913,14 @@ static struct service *create_service(const char *file) goto failed; } + slash = strrchr(file, '/'); + if (!slash) { + error("No slash in service file path!?"); + goto failed; + } + + service->filename = strdup(slash + 1); + service->descr = g_key_file_get_string(keyfile, SERVICE_GROUP, "Description", NULL); @@ -964,6 +937,54 @@ failed: return NULL; } +static gint service_filename_cmp(struct service *service, const char *filename) +{ + return strcmp(service->filename, filename); +} + +static void service_notify(int action, const char *name, void *user_data) +{ + GSList *l; + struct service *service; + size_t len; + char fullpath[PATH_MAX]; + + len = strlen(name); + if (len < (strlen(SERVICE_SUFFIX) + 1)) + return; + + if (strcmp(name + (len - strlen(SERVICE_SUFFIX)), SERVICE_SUFFIX)) + return; + + switch (action) { + case NOTIFY_CREATE: + debug("%s was created", name); + snprintf(fullpath, sizeof(fullpath) - 1, "%s/%s", CONFIGDIR, name); + service = create_service(fullpath); + if (!service) { + error("Unable to read %s", fullpath); + break; + } + + register_service(service); + + break; + case NOTIFY_DELETE: + debug("%s was deleted", name); + l = g_slist_find_custom(services, name, + (GCompareFunc) service_filename_cmp); + if (l) + unregister_service(l->data); + break; + case NOTIFY_MODIFY: + debug("%s was modified", name); + break; + default: + debug("Unknown notify action %d", action); + break; + } +} + int init_services(const char *path) { DIR *d; @@ -995,11 +1016,13 @@ int init_services(const char *path) continue; } - register_service(full_path, service); + register_service(service); } closedir(d); + notify_add(path, service_notify, NULL); + return 0; } |