Diff between 5b6c096fb859a70a0792b97ad7aca3190404a5a0 and 765356e80262a20c359ec7722a5590232442d0d3

Changed Files

File Additions Deletions Status
Makefile.obexd +10 -0 modified
obexd/client/pbap.c +14 -3 modified
obexd/plugins/bluetooth.c +12 -2 modified
obexd/src/logind.c +239 -0 added
obexd/src/logind.h +37 -0 added
obexd/src/main.c +4 -0 modified

Full Patch

diff --git a/Makefile.obexd b/Makefile.obexd
index 74dd977..b59cfaf 100644
--- a/Makefile.obexd
+++ b/Makefile.obexd
@@ -67,6 +67,7 @@ obexd_src_obexd_SOURCES = $(btio_sources) $(gobex_sources) \
 			obexd/src/main.c obexd/src/obexd.h \
 			obexd/src/plugin.h obexd/src/plugin.c \
 			obexd/src/log.h obexd/src/log.c \
+			obexd/src/logind.h obexd/src/logind.c \
 			obexd/src/manager.h obexd/src/manager.c \
 			obexd/src/obex.h obexd/src/obex.c obexd/src/obex-priv.h \
 			obexd/src/mimetype.h obexd/src/mimetype.c \
@@ -96,6 +97,8 @@ obexd_src_obexd_LDADD = lib/libbluetooth-internal.la \
 
 if EXTERNAL_PLUGINS
 obexd_src_obexd_LDFLAGS = $(AM_LDFLAGS) -Wl,--export-dynamic
+else
+obexd_src_obexd_LDFLAGS =
 endif
 
 obexd_src_obexd_CPPFLAGS = $(AM_CPPFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS) \
@@ -109,6 +112,13 @@ obexd-add-service-symlink:
 obexd-remove-service-symlink:
 endif
 
+if OBEX
+if SYSTEMD
+obexd_src_obexd_CPPFLAGS += -DSYSTEMD
+obexd_src_obexd_LDFLAGS += -lsystemd
+endif
+endif
+
 obexd_src_obexd_SHORTNAME = obexd
 
 obexd_builtin_files = obexd/src/builtin.h $(obexd_builtin_nodist)
diff --git a/obexd/client/pbap.c b/obexd/client/pbap.c
index 90f8bdc..51b5235 100644
--- a/obexd/client/pbap.c
+++ b/obexd/client/pbap.c
@@ -27,6 +27,7 @@
 #include "gdbus/gdbus.h"
 
 #include "obexd/src/log.h"
+#include "obexd/src/logind.h"
 #include "obexd/src/obexd.h"
 
 #include "transfer.h"
@@ -1454,13 +1455,13 @@ static struct obc_driver pbap = {
 	.remove = pbap_remove
 };
 
-int pbap_init(void)
+static int pbap_init_cb(void)
 {
 	int err;
 
 	DBG("");
 
-	conn = obex_get_dbus_connection();
+	conn = obex_setup_dbus_connection_private(NULL, NULL);
 	if (!conn)
 		return -EIO;
 
@@ -1481,7 +1482,7 @@ int pbap_init(void)
 	return 0;
 }
 
-void pbap_exit(void)
+static void pbap_exit_cb(void)
 {
 	DBG("");
 
@@ -1496,9 +1497,19 @@ void pbap_exit(void)
 	}
 
 	if (conn) {
+		dbus_connection_close(conn);
 		dbus_connection_unref(conn);
 		conn = NULL;
 	}
 
 	obc_driver_unregister(&pbap);
 }
+
+int pbap_init(void)
+{
+	return logind_register(pbap_init_cb, pbap_exit_cb);
+}
+void pbap_exit(void)
+{
+	return logind_unregister(pbap_init_cb, pbap_exit_cb);
+}
diff --git a/obexd/plugins/bluetooth.c b/obexd/plugins/bluetooth.c
index 8cf7189..7ff27a8 100644
--- a/obexd/plugins/bluetooth.c
+++ b/obexd/plugins/bluetooth.c
@@ -35,6 +35,7 @@
 #include "obexd/src/transport.h"
 #include "obexd/src/service.h"
 #include "obexd/src/log.h"
+#include "obexd/src/logind.h"
 
 #define BT_RX_MTU 32767
 #define BT_TX_MTU 32767
@@ -426,7 +427,7 @@ static const struct obex_transport_driver driver = {
 
 static unsigned int listener_id = 0;
 
-static int bluetooth_init(void)
+static int bluetooth_init_cb(void)
 {
 	connection = g_dbus_setup_private(DBUS_BUS_SYSTEM, NULL, NULL);
 	if (connection == NULL)
@@ -438,7 +439,7 @@ static int bluetooth_init(void)
 	return obex_transport_driver_register(&driver);
 }
 
-static void bluetooth_exit(void)
+static void bluetooth_exit_cb(void)
 {
 	GSList *l;
 
@@ -462,4 +463,13 @@ static void bluetooth_exit(void)
 	obex_transport_driver_unregister(&driver);
 }
 
+static int bluetooth_init(void)
+{
+	return logind_register(bluetooth_init_cb, bluetooth_exit_cb);
+}
+static void bluetooth_exit(void)
+{
+	return logind_unregister(bluetooth_init_cb, bluetooth_exit_cb);
+}
+
 OBEX_PLUGIN_DEFINE(bluetooth, bluetooth_init, bluetooth_exit)
diff --git a/obexd/src/logind.c b/obexd/src/logind.c
new file mode 100644
index 0000000..ff2bf32
--- /dev/null
+++ b/obexd/src/logind.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ *  Enable functionality only when the user is active
+ *
+ *  Copyright (C) 2007-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ */
+
+#ifdef SYSTEMD
+
+#include <assert.h>
+#include <errno.h>
+#include <poll.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <glib.h>
+
+#include <systemd/sd-login.h>
+
+#include "obexd/src/log.h"
+#include "obexd/src/logind.h"
+
+static sd_login_monitor * monitor;
+static int uid;
+static gboolean active = FALSE;
+static gboolean monitoring_enabled = TRUE;
+static guint event_source;
+
+struct callback_pair {
+	logind_init_cb init_cb;
+	logind_exit_cb exit_cb;
+};
+
+GSList *callbacks;
+
+static void call_init_cb(gpointer data, gpointer user_data)
+{
+	int res;
+
+	res = ((struct callback_pair *)data)->init_cb();
+	if (res)
+		*(int *)user_data = res;
+}
+static void call_exit_cb(gpointer data, gpointer user_data)
+{
+	((struct callback_pair *)data)->exit_cb();
+}
+
+static int update(void)
+{
+	char *state = NULL;
+	gboolean state_is_active;
+	int res;
+
+	res = sd_login_monitor_flush(monitor);
+	if (res < 0)
+		return res;
+	res = sd_uid_get_state(uid, &state);
+	state_is_active = g_strcmp0(state, "active");
+	free(state);
+	if (res < 0)
+		return res;
+
+	if (state_is_active) {
+		if (!active)
+			return 0;
+	} else {
+		res = sd_uid_get_seats(uid, 1, NULL);
+		if (res < 0)
+			return res;
+		if (active == !!res)
+			return 0;
+	}
+	active ^= TRUE;
+	res = 0;
+	g_slist_foreach(callbacks, active ? call_init_cb : call_exit_cb, &res);
+	return res;
+}
+
+static int check_event(void)
+{
+	int res;
+
+	res = sd_login_monitor_flush(monitor);
+	if (res < 0)
+		return res;
+	if (!monitoring_enabled)
+		return 0;
+	res = update();
+	if (res < 0)
+		return res;
+
+	return 0;
+}
+
+
+static gboolean event_handler(GIOChannel *source, GIOCondition condition,
+				gpointer data)
+{
+	int res;
+
+	res = check_event();
+	if (res) {
+		error("%s: %s", __func__, strerror(-res));
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static int logind_init(void)
+{
+	GIOChannel *channel;
+	int events;
+	int fd;
+	int res;
+
+	monitor = NULL;
+
+	DBG("");
+
+	if (!monitoring_enabled)
+		return 0;
+
+	uid = getuid();
+
+	res = sd_login_monitor_new("uid", &monitor);
+	if (res < 0) {
+		monitor = NULL;
+		goto FAIL;
+	}
+
+	// Check this after creating the monitor, in case of race conditions:
+	res = update();
+	if (res < 0)
+		goto FAIL;
+
+	events = res = sd_login_monitor_get_events(monitor);
+	if (res < 0)
+		goto FAIL;
+
+	fd = res = sd_login_monitor_get_fd(monitor);
+	if (res < 0)
+		goto FAIL;
+
+	channel = g_io_channel_unix_new(fd);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	event_source = g_io_add_watch(channel, events, event_handler, NULL);
+
+	g_io_channel_unref(channel);
+
+	return check_event();
+
+FAIL:
+	sd_login_monitor_unref(monitor);
+	monitoring_enabled = FALSE;
+	active = TRUE;
+	return res;
+}
+
+static void logind_exit(void)
+{
+	if (event_source) {
+		g_source_remove(event_source);
+		event_source = 0;
+	}
+	sd_login_monitor_unref(monitor);
+}
+
+static gint find_cb(gconstpointer a, gconstpointer b)
+{
+	return ((struct callback_pair *)a)->init_cb - (logind_init_cb)b;
+}
+
+int logind_register(logind_init_cb init_cb, logind_exit_cb exit_cb)
+{
+	struct callback_pair *cbs;
+
+	if (!monitoring_enabled)
+		return init_cb();
+	if (callbacks == NULL) {
+		int res;
+
+		res = logind_init();
+		if (res) {
+			error("logind_init(): %s - login detection disabled",
+				strerror(-res));
+			return init_cb();
+		}
+	}
+	cbs = g_new(struct callback_pair, 1);
+	cbs->init_cb = init_cb;
+	cbs->exit_cb = exit_cb;
+	callbacks = g_slist_prepend(callbacks, cbs);
+	return active ? init_cb() : 0;
+}
+void logind_unregister(logind_init_cb init_cb, logind_exit_cb exit_cb)
+{
+	GSList *cb_node;
+
+	if (!monitoring_enabled)
+		return exit_cb();
+	if (active)
+		exit_cb();
+	cb_node = g_slist_find_custom(callbacks, init_cb, find_cb);
+	if (cb_node != NULL)
+		callbacks = g_slist_delete_link(callbacks, cb_node);
+	if (callbacks == NULL)
+		logind_exit();
+}
+
+int logind_set(gboolean enabled)
+{
+	int res = 0;
+
+	if (monitoring_enabled == enabled)
+		return 0;
+
+	monitoring_enabled = enabled;
+	if (enabled) {
+		active = FALSE;
+		return update();
+	}
+
+	active = TRUE;
+	g_slist_foreach(callbacks, call_exit_cb, &res);
+	return res;
+}
+
+#endif
diff --git a/obexd/src/logind.h b/obexd/src/logind.h
new file mode 100644
index 0000000..eb3ff8d
--- /dev/null
+++ b/obexd/src/logind.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *  Enable functionality only when the user is active
+ *
+ *  Copyright (C) 2007-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ */
+
+typedef int (*logind_init_cb)(void);
+typedef void (*logind_exit_cb)(void);
+
+#ifdef SYSTEMD
+
+int logind_register(logind_init_cb init_cb, logind_exit_cb exit_cb);
+void logind_unregister(logind_init_cb init_cb, logind_exit_cb exit_cb);
+int logind_set(gboolean enabled);
+
+#else
+
+static inline int logind_register(logind_init_cb init_cb,
+					logind_exit_cb exit_cb)
+{
+	return init_cb();
+}
+static inline void logind_unregister(logind_init_cb init_cb,
+					logind_exit_cb exit_cb)
+{
+	return exit_cb();
+}
+static inline int logind_set(gboolean enabled)
+{
+	return 0;
+}
+
+#endif
diff --git a/obexd/src/main.c b/obexd/src/main.c
index ca95a70..df15097 100644
--- a/obexd/src/main.c
+++ b/obexd/src/main.c
@@ -35,6 +35,7 @@
 #include "../client/manager.h"
 
 #include "log.h"
+#include "logind.h"
 #include "obexd.h"
 #include "server.h"
 
@@ -283,6 +284,9 @@ int main(int argc, char *argv[])
 
 	__obex_log_init(option_debug, option_detach);
 
+	if (option_system_bus)
+		logind_set(FALSE);
+
 	DBG("Entering main loop");
 
 	main_loop = g_main_loop_new(NULL, FALSE);