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 | |
| parent | 18a13b29f55177bf663c69a651b7b54ed80b2b6b (diff) | |
Support for adding and removing .service files in /etc/bluetooth
| -rw-r--r-- | hcid/dbus-service.c | 147 | ||||
| -rw-r--r-- | hcid/dbus-service.h | 1 | ||||
| -rw-r--r-- | hcid/main.c | 5 | 
3 files changed, 91 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;  } diff --git a/hcid/dbus-service.h b/hcid/dbus-service.h index 94fd580a..f0f66721 100644 --- a/hcid/dbus-service.h +++ b/hcid/dbus-service.h @@ -27,6 +27,7 @@  #define START_REPLY_TIMEOUT	5000  struct service { +	char *filename;  	char *object_path;  	DBusMessage *action;	/* Either Start or Stop method call */ diff --git a/hcid/main.c b/hcid/main.c index c7461c03..5da2216b 100644 --- a/hcid/main.c +++ b/hcid/main.c @@ -43,6 +43,7 @@  #include <bluetooth/hci_lib.h>  #include "glib-ectomy.h" +#include "notify.h"  #include "hcid.h"  #include "sdpd.h" @@ -757,6 +758,8 @@ int main(int argc, char *argv[])  	if (sdp)  		start_sdp_server(0, SDP_SERVER_COMPAT); +	notify_init(); +  	init_services(CONFIGDIR);  	/* Start event processor */ @@ -769,6 +772,8 @@ int main(int argc, char *argv[])  	hcid_dbus_exit(); +	notify_close(); +  	cleanup_sdp_session();  	g_main_loop_unref(event_loop); | 
