diff --git a/Makefile.obexd b/Makefile.obexd
index 74dd977..b59cfaf 100644
--- a/Makefile.obexd
+++ b/Makefile.obexd
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 \
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) \
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
#include "gdbus/gdbus.h"
#include "obexd/src/log.h"
+#include "obexd/src/logind.h"
#include "obexd/src/obexd.h"
#include "transfer.h"
.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;
return 0;
}
-void pbap_exit(void)
+static void pbap_exit_cb(void)
{
DBG("");
}
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
#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
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)
return obex_transport_driver_register(&driver);
}
-static void bluetooth_exit(void)
+static void bluetooth_exit_cb(void)
{
GSList *l;
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
+// 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
+/* 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
#include "../client/manager.h"
#include "log.h"
+#include "logind.h"
#include "obexd.h"
#include "server.h"
__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);