Files

62 lines
1.8 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
// Package sessionbus selects the same desktop session bus as GLib clients,
// including Python Cthulhu and I38lock, without changing the process environment.
package sessionbus
/*
#cgo pkg-config: gio-2.0
#include <gio/gio.h>
*/
import "C"
import (
"context"
"fmt"
"log/slog"
"time"
"unsafe"
"github.com/godbus/dbus/v5"
)
func sessionAddress() (string, error) {
var nativeError *C.GError
address := C.g_dbus_address_get_for_bus_sync(C.G_BUS_TYPE_SESSION, nil, &nativeError)
if nativeError != nil {
defer C.g_error_free(nativeError)
return "", fmt.Errorf("resolve desktop session bus: %s", C.GoString(nativeError.message))
}
if address == nil {
return "", fmt.Errorf("resolve desktop session bus: no address")
}
defer C.g_free(C.gpointer(unsafe.Pointer(address)))
return C.GoString(address), nil
}
// Connect uses GLib's session address discovery and godbus's private connection.
// Bus IDs let debug logs identify mismatched buses without exposing addresses.
func Connect(logger *slog.Logger, component string) (*dbus.Conn, error) {
address, err := sessionAddress()
if err != nil {
return nil, err
}
connection, err := dbus.Connect(address)
if err != nil {
return nil, err
}
if logger != nil && logger.Enabled(context.Background(), slog.LevelDebug) {
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
var busID string
if err := connection.BusObject().CallWithContext(ctx, "org.freedesktop.DBus.GetId", 0).Store(&busID); err != nil {
logger.Debug("query session bus identity", "component", component, "error", err)
} else {
logger.Debug("connected to session bus", "component", component, "bus_id", busID)
}
}
return connection, nil
}