diff --git a/INSTALL.md b/INSTALL.md
index babe44cf2a082dba687c0c844ebc7450cd006708..118124cc206080c0808704a9cb8822288dba8fc3 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -62,3 +62,7 @@ options as necessary.
 ## Out-of-tree builds
 
 obarun.org packages do not support out-of-tree builds. They are small, so it does not cost much to duplicate the entire source tree if parallel builds are needed.
+
+## Dbus support
+
+The 66-dbus-broker-launch tool is built if you give the `--enable-dbus=<implementation>` flag to configure. There are two supported values for `<implementation>: basu and elogind. You should install the relevant header and library files for your chosen implementation before building the 66-dbus-broker-launch.
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 1bf7c348cc4587ceb769118e11d53888724f80cd..0221bc2ccaf6b6b5accd453c758c548fc2096133 100644
--- a/Makefile
+++ b/Makefile
@@ -103,11 +103,21 @@ install-ns-rule: $(RULE_TARGET:examples/rule/%=$(DESTDIR)$(ns_rule)/%)
 
 $(DESTDIR)$(datarootdir)/doc/$(package)/$(version)/%.html: doc/$(version)/html/%.html
 	$(INSTALL) -D -m 644 $< $@ && \
-	sed -e 's,%%service_admconf%%,/etc/66/conf,g' $< > $@
+	sed -e 's,%%dbus_system_service%%,$(dbus_system_service),g' \
+		-e 's,%%dbus_session_service%%,$(dbus_session_service),g' \
+		-e 's,%%dbus_system_name%%,$(dbus_system_name),g' \
+		-e 's,%%dbus_session_name%%,$(dbus_session_name),g' \
+		-e 's,%%datarootdir%%,$(datarootdir),g' \
+		-e 's,%%ns_rule%%,$(ns_rule),g' $< > $@
 
 $(DESTDIR)$(mandir)/man1/%.1: doc/man/man1/%.1
 	$(INSTALL) -D -m 644 $< $@ && \
-	sed -e 's,%%service_admconf%%,/etc/66/conf,g' $< > $@
+	sed -e 's,%%dbus_system_service%%,$(dbus_system_service),g' \
+		-e 's,%%dbus_session_service%%,$(dbus_session_service),g' \
+		-e 's,%%dbus_system_name%%,$(dbus_system_name),g' \
+		-e 's,%%dbus_session_name%%,$(dbus_session_name),g' \
+		-e 's,%%datarootdir%%,$(datarootdir),g' \
+		-e 's,%%ns_rule%%,$(ns_rule),g' $< > $@
 
 $(DESTDIR)$(datadir)/%: src/etc/%
 	exec $(INSTALL) -D -m 644 $< $@
diff --git a/README.md b/README.md
index a17d00f61432adf7b2b230b1d03f77fc3a57eb8f..0af8831e032965d0ce1cf8573fb4a8946b52ffdb 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
 ![GitLabl Build Status](https://git.obarun.org/Obarun/66-tools/badges/master/pipeline.svg)
 
-66-tools - Helpers tools to accomplish various and repetitive tasks in service scripts administration common tasks
+66-tools: A set of helper tools designed to simplify and automate various repetitive tasks commonly encountered in service script administration. These tools also provide additional functionalities to enhance service management.
+
 ====
 
 Some utilities are language [execline](https://skarnet.org/software/execline) specific (usually named with `execl-` prefix) where other can be used on classic shell.
@@ -28,7 +29,7 @@ Contact information
   https://web.obarun.org/
 
 * XMPP Channel:
-  obarun@xmpp.obarun.org
+  obarun@conference.xmpp.obarun.org
 
 Supports the project
 ---------------------
diff --git a/configure b/configure
index 92b89039b26fd38f076572c58a52c7ec9b6fbcc9..37e08a6d9b6f0b6fbcd35f21c87c692254a7dce7 100755
--- a/configure
+++ b/configure
@@ -9,47 +9,52 @@ Usage: $0 [OPTION]... [TARGET]
 Defaults for the options are specified in brackets.
 System types:
 
-  --target=TARGET               configure to run on target TARGET [detected]
-  --host=TARGET                 same as --target
+  --target=TARGET                 configure to run on target TARGET [detected]
+  --host=TARGET                   same as --target
 
 Installation directories:
 
-  --prefix=PREFIX               main installation prefix [/]
-  --exec-prefix=EPREFIX         installation prefix for executable files [PREFIX]
+  --prefix=PREFIX                 main installation prefix [/]
+  --exec-prefix=EPREFIX           installation prefix for executable files [PREFIX]
 
 Fine tuning of the installation directories:
 
-  --dynlibdir=DIR               shared library files [PREFIX/lib]
-  --bindir=BINDIR               user executables [EPREFIX/bin]
-  --libexecdir=DIR              package-scoped executables [EPREFIX/libexec]
-  --libdir=DIR                  static library files [PREFIX/lib/$package]
-  --includedir=DIR              C header files [PREFIX/include]
-  --datarootdir=DATAROOTDIR     read-only architecture-independent data root [PREFIX/share]
-  --mandir=DIR                  man documentation [$datarootdir/man]
-  --with-ns-rule=DIR            66-ns rule installation directory [DATAROOTDIR/66/script/ns]
+  --dynlibdir=DIR                 shared library files [PREFIX/lib]
+  --bindir=BINDIR                 user executables [EPREFIX/bin]
+  --libexecdir=DIR                package-scoped executables [EPREFIX/libexec]
+  --libdir=DIR                    static library files [PREFIX/lib/$package]
+  --includedir=DIR                C header files [PREFIX/include]
+  --datarootdir=DATAROOTDIR       read-only architecture-independent data root [PREFIX/share]
+  --mandir=DIR                    man documentation [$datarootdir/man]
+  --with-ns-rule=DIR              66-ns rule installation directory [DATAROOTDIR/66/script/ns]
 
  If no --prefix option is given, by default libdir (but not dynlibdir) will be
  /usr/lib/$package, and includedir will be /usr/include.
 
 Dependencies:
 
-  --with-sysdeps=DIR            use sysdeps in DIR [PREFIX/lib/skalibs/sysdeps]
-  --with-include=DIR            add DIR to the list of searched directories for headers
-  --with-lib=DIR                add DIR to the list of searched directories for static libraries
-  --with-dynlib=DIR             add DIR to the list of searched directories for shared libraries
+  --with-sysdeps=DIR              use sysdeps in DIR [PREFIX/lib/skalibs/sysdeps]
+  --with-include=DIR              add DIR to the list of searched directories for headers
+  --with-lib=DIR                  add DIR to the list of searched directories for static libraries
+  --with-dynlib=DIR               add DIR to the list of searched directories for shared libraries
 
  If no --prefix option is given, by default sysdeps will be fetched from
  /usr/lib/skalibs/sysdeps.
 
 Optional features:
-
-  --enable-shared               build shared libraries [disabled]
-  --disable-static              do not build static libraries [enabled]
-  --disable-allstatic           do not prefer linking against static libraries [enabled]
-  --enable-static-libc          make entirely static binaries [disabled]
-  --disable-all-pic             do not build executables and static libs as PIC [enabled]
-  --enable-absolute-paths       do not rely on PATH to access this package's binaries,
+  --enable-shared                 build shared libraries [enabled]
+  --disable-static                do not build static libraries [enabled]
+  --disable-allstatic             do not prefer linking against static libraries [enabled]
+  --enable-static-libc            make entirely static binaries [disabled]
+  --disable-all-pic               do not build executables and static libs as PIC [enabled]
+  --enable-absolute-paths         do not rely on PATH to access this package's binaries,
                                   hardcode absolute BINDIR/foobar paths instead [disabled]
+Dbus support:
+  --enable-dbus=basu|elogind      build 66-dbus-broker-launch program with basu or elogind [disabled]
+  --with-dbus-system-service-dir=DIR   directory of system service [DATAROOTDIR/dbus-1/system-services]
+  --with-dbus-session-service-dir=DIR  directory of session service [DATAROOTDIR/dbus-1/services]
+  --with-dbus-system-name=NAME    name of the dbus system socket[system_bus_socket]
+  --with-dbus-session-name=NAME   name of the dbus session socket[dbus]
 EOF
 exit 0
 }
@@ -148,20 +153,24 @@ sysdeps='$prefix/lib/skalibs/sysdeps'
 datarootdir='$prefix/share'
 mandir='$datarootdir/man'
 ns_rule='$datarootdir/66/script/ns'
+dbus_session_service='$datarootdir/dbus-1/services'
+dbus_system_service='$datarootdir/dbus-1/system-services'
+dbus_system_name='system_bus_socket'
+dbus_session_name='bus'
 manualsysdeps=false
-shared=false
-static=true
-allpic=true
-abspath=false
-home=
-allstatic=true
+shared=true
+static=false
+allpic=false
+allstatic=false
 evenmorestatic=false
+abspath=false
 addincpath=''
 addlibspath=''
 addlibdpath=''
 vpaths=''
 vpathd=''
 build=
+dbus=
 
 for arg ; do
   case "$arg" in
@@ -192,6 +201,13 @@ for arg ; do
     --disable-all-pic|--enable-all-pic=no) allpic=false ;;
     --enable-absolute-paths|--enable-absolute-paths=yes) abspath=true ;;
     --disable-absolute-paths|--enable-absolute-paths=no) abspath=false ;;
+    --enable-dbus=basu) dbus=basu ;;
+    --enable-dbus=elogind) dbus=elogind ;;
+    --disable-dbus|--disable-dbus=no|--disable-dbus=none) dbus= ;;
+    --with-dbus-system-service-dir=*) dbus_system_service=${arg#*=} ;;
+    --with-dbus-session-service-dir=*) dbus_session_service=${arg#*=} ;;
+    --with-dbus-system-name=*) dbus_system_name=${arg#*=} ;;
+    --with-dbus-session-name=*) dbus_session_name=${arg#*=} ;;
     --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;;
     --host=*|--target=*) target=${arg#*=} ;;
     --build=*) build=${arg#*=} ;;
@@ -221,7 +237,8 @@ fi
 stripdir prefix
 for i in exec_prefix dynlibdir libexecdir \
          bindir libdir includedir sysdeps \
-         datarootdir mandir ns_rule ; do
+         datarootdir mandir ns_rule \
+         dbus_system_service dbus_session_service; do
   eval tmp=\${$i}
   eval $i=$tmp
   stripdir $i
@@ -353,14 +370,6 @@ else
   LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibdpath}"
 fi
 
-if test -z "$vpaths" ; then
-  while read dep ; do
-    base=$(basename $dep)
-    vpaths="$vpaths /usr/lib/$base"
-    addlibspath="$addlibspath -L/usr/lib/$base"
-  done < package/deps-build
-fi
-
 echo "Creating config.mak..."
 cmdline=$(quote "$0")
 for i ; do cmdline="$cmdline $(quote "$i")" ; done
@@ -369,6 +378,7 @@ cat << EOF
 # This file was generated by:
 # $cmdline
 # Any changes made here will be lost if configure is re-run.
+
 target := $target
 package := $package
 prefix := $prefix
@@ -381,14 +391,19 @@ includedir := $includedir
 datarootdir := $datarootdir
 mandir := $mandir
 ns_rule := $ns_rule
+dbus_system_service := $dbus_system_service
+dbus_session_service := $dbus_session_service
+dbus_system_name := $dbus_system_name
+dbus_session_name := $dbus_session_name
 sysdeps := $sysdeps
 version := $version
-home := $home
+
 SPAWN_LIB := ${spawn_lib}
 SOCKET_LIB := ${socket_lib}
 SYSCLOCK_LIB := ${sysclock_lib}
 TIMER_LIB := ${timer_lib}
 UTIL_LIB := ${util_lib}
+
 CC := $CC_AUTO
 CPPFLAGS_AUTO := $CPPFLAGS_AUTO
 CPPFLAGS := $CPPFLAGS $CPPFLAGS_POST
@@ -399,6 +414,7 @@ LDFLAGS := $LDFLAGS $LDFLAGS_POST
 LDFLAGS_SHARED := $LDFLAGS_SHARED
 LDFLAGS_NOSHARED := $LDFLAGS_NOSHARED
 CROSS_COMPILE := $cross
+
 vpath lib%.a$vpaths
 vpath lib%.so$vpathd
 EOF
@@ -423,6 +439,11 @@ if $allpic ; then
 else
   echo "STATIC_LIBS_ARE_PIC :="
 fi
+if test -n $dbus ; then
+  echo "DBUS_IMPL := $dbus"
+else
+  echo "DBUS_IMPL :="
+fi
 
 exec 1>&3 3>&-
 echo "  ... done."
@@ -446,6 +467,18 @@ else
 fi
 echo "#define ${package_macro_name}_LIBEXECPREFIX \"$libexecdir/\""
 echo "#define ${package_macro_name}_NSRULE \"$ns_rule/\""
+echo "#define ${package_macro_name}_DBS_SYSTEM_SERVICE \"$dbus_system_service/\""
+echo "#define ${package_macro_name}_DBS_SESSION_SERVICE \"$dbus_session_service/\""
+echo "#define ${package_macro_name}_DBS_SYSTEM_NAME \"$dbus_system_name\""
+echo "#define ${package_macro_name}_DBS_SESSION_NAME \"$dbus_session_name\""
+echo "#undef ${package_macro_name}_USE_BASU"
+echo "#undef ${package_macro_name}_USE_ELOGIND"
+if test "basu" = "$dbus" ; then
+  echo "#define ${package_macro_name}_USE_BASU"
+elif test "elogind" = "$dbus" ; then
+  echo "#define ${package_macro_name}_USE_ELOGIND"
+fi
+
 echo
 echo "#endif"
 exec 1>&3 3>&-
diff --git a/doc/66-dbus-launch.md b/doc/66-dbus-launch.md
new file mode 100644
index 0000000000000000000000000000000000000000..22927051569b99f8cad58a1e0da25aaa6c79d412
--- /dev/null
+++ b/doc/66-dbus-launch.md
@@ -0,0 +1,146 @@
+title: The 66-tools Suite: 66-dbus-launch
+author: Eric Vidal <eric@obarun.org>
+
+[66-tools](index.html)
+
+[Software](https://web.obarun.org/software)
+
+[obarun.org](https://web.obarun.org)
+
+# 66-dbus-launch
+
+*66-dbus-launch* is a tool for launching, supervising, and reacting to [dbus-broker](https://github.com/bus1/dbus-broker) events emitted by relevant D-Bus signals.
+
+## Interface
+
+```
+    66-dbus-launch [ -h ] [ -z ] [ -v verbosity ] [ -d notif ]
+```
+
+*66-dbus-launch* acts as a launcher for the [dbus-broker](https://github.com/bus1/dbus-broker), spawning and managing a D-Bus Message Bus.
+
+On receiving D-Bus or kernel signals, the launcher executes tasks based on the signal received(see [Execution tasks](#execution-tasks)).
+Each instance of *66-dbus-launch* manages exactly one message bus. Each message bus is independent.
+
+When started by a regular user, *66-dbus-launch* will drop privileges before executing [dbus-broker](https://github.com/bus1/dbus-broker). The launcher only manages services and environments for the process owner, meaning a user launcher cannot manage root services or environments and vice versa.
+
+This program is only built if the `--enable-dbus=` option is passed during compilation (see [Build Requirements](#build-requirements)).
+
+## Exit codes
+
+- *0* success
+- *100* wrong usage
+- *111* system call failed
+
+## Options
+
+- **-h** : prints this help.
+
+- **-z** : enable color. If *66-dbus-launch* is not launched from a terminal, the color is automatically disabled and the option has no effect.
+
+- **-v** *verbosity*: increases/decreases the verbosity of the command.
+    * *0*: only print error messages.
+    * *1*: also, print informative messages. This is the default.
+    * *2*: also, print warning messages.
+    * *3*: also, print tracing messages.
+    * *4*: also, print function name and line code of the messages.
+    * *5*: also, display the sequence of the current process function by function.
+    *verbosity* are also propagated to the *66* command invocation to activate or desactivate a service.
+
+- **-d** *notif* : notify readiness on file descriptor *notif*. Has no effect when launched from a terminal. Notification occurs before entering the [loop](#running-time), ensuring that both the broker and launcher are fully synchronized.
+
+## Execution Tasks
+
+### Start Time
+
+At startup, 66-dbus-launch performs the following tasks:
+
+- Creates, binds, and listens to a socket at `/run/dbus/%%dbus_system_name%%` or `/run/user/UID/%%dbus_session_name%%`, depending on the process owner. The socket name can be customized at compile time with `--with-dbus-system-name=NAME` and `--with-dbus-session-name=NAME`.
+
+- Sets the `DBUS_SYSTEM_BUS_ADDRESS=unix:path=/run/dbus/%%dbus_system_name%%` and `DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/UID/%%dbus_session_name%%` environment variables according to the owner of the process.
+
+- For each D-Bus service file found in `%%dbus_system_service%%` or `%%dbus_session_service%%`, it reads, parses, translates, and writes a corresponding 66 frontend file. An example:
+
+    ```
+    [Main]
+    Type = classic
+    Description "org.freedesktop.Consolekit.dbus dbus service"
+    User = ( root )
+    Version = 0.0.1
+    InTree = dbus
+    MaxDeath = 5
+    TimeoutStart = 3000
+    TimeoutStop = 3000
+
+    [Start]
+    Execute = (
+        execl-envfile -l ${ImportFile}
+        /usr/bin/console-kit-daemon --nodaemon
+    )
+
+    [Environment]
+    ImportFile=/etc/66/environment/0000-dbus
+    ```
+
+It ensures that you use the latest *D-Bus* file declarations by overwriting any existing frontend files with the same name.
+
+- Creates an unbound socket pair and forks the command `/usr/bin/dbus-broker --controller FD --machine-id MachineId`, with *FD* being the file descriptor of the connected socket's standard input. If `/etc/machine-id` is unreadable, it defaults to `00000000000000000000000000000001`. For regular users, privileges are dropped before execution.
+
+- Notifies readiness (if -`d` is used) and enters a loop, listening and supervising the broker.
+
+### Running time
+
+*66-dbus-launch* responds to kernel signals. A `SIGHUP` signal triggers a reading, parsing, translating and writting process.
+Synchronization of services can also be manually triggered via `66 reload dbus` or `66 signal -s HUP dbus`.
+It also synchronizes the available list of services between the launcher and the broke as follows:
+- If a *D-Bus* service file is removed, the launcher deactivates from the broker, executes `66 remove <service>`, and erases the corresponding *66* frontend file.
+- If a new *D-Bus* service is found, the launcher triggers the reading, parsing, translating and writting process, and activates the service in the broker.
+- For an existing service with the same name, the launcher executes `66 parse -f <service>` to ensure the latest *D-Bus* service declaration is used. Note that the service need to restarted for any changes to take effect.
+
+*66-dbus-launch* reacts on D-Bus signals:
+
+- Activation requested invoke a `66 start <service>` command.
+- A `org.freedesktop.DBus.UpdateActivationEnvironment()` request trigger the update environment variables, writing them by default to `/etc/66/environment/0000-dbus` or `$HOME/.66/environment/0000-dbus`, depending on ownership. The file is overwritten for each update. You can also use the [dbus-update-activation-environment](https://dbus.freedesktop.org/doc/dbus-update-activation-environment.1.html) program to trigger this update. Note that you may need to define the `DBUS_SESSION_BUS_ADDRESS` before launching the *dbus-update-activation-environment* program. For root, use `DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/%%dbus_system_name%%`, and for regular user, use `DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/UID/%%dbus_session_name%%`.
+
+- A `org.freedesktop.DBus.ReloadConfig()` request triggers the same process as a `SIGHUP` signal.
+
+### Stop time
+
+Stopping the launcher invokes a `66 tree free dbus` command, as each service frontend file declares [`InTree=dbus`](#start-time).
+
+As the frontend file of each service declare `InTree=dbus`, stopping the launcher invoke a `66 tree free dbus` command. This behavior may change in the future. For now, this reduce the surface of attack and guarantee you to always use a fresh installation of the service.
+
+## Example of 66-dbus-launch frontend file for 66
+
+The following frontend file can be used to start a 66-dbus-launch daemon, either as root or as a regular user, by setting `User=(root)` or `User=(user)` in the example below:
+
+```
+[Main]
+Type=classic
+Description="Dbus-broker launcher for @U account"
+User=(root)
+Version=0.0.1
+TimeoutStart=3000
+TimeoutStop=3000
+MaxDeath=5
+Notify=3
+
+[Start]
+Execute=(66-dbus-launch -d3 -v${Verbosity})
+
+[Environment]
+Verbosity=!3
+```
+
+By default, the frontend file can be installed at `%%datarootdir%%/66/service` (for root) and `%%datarootdir%%/66/service/user` (for regular users).
+
+## Build requirements
+
+- The `--enable-dbus=` option is required at compile time, with either `basu` or `elogind` as the provider of `sd_bus` functions. The use of the `sd_bus` library may change at any time without warning.
+
+- For the runtime, the system must have [dbus-broker](https://github.com/bus1/dbus-broker) installed for *66-dbus-launch* to function properly.
+
+## Caveats
+
+[dbus-broker](https://github.com/bus1/dbus-broker)'s policy API isn't yet stable, allowing broad access for now.
+Currently, *66-dbus-launch* doesn't handle configuration files for D-Bus (e.g., `/usr/share/dbus-1/{system,session}.conf`).
\ No newline at end of file
diff --git a/doc/66-ns.md b/doc/66-ns.md
index b3b7a646363ac3166d00ea55f797c4c9db47bb3b..ab0a455d24c5f70a79ea7156d5fd750a432c4b9b 100644
--- a/doc/66-ns.md
+++ b/doc/66-ns.md
@@ -39,11 +39,13 @@ or
 
 - **-z** : enable color. If *66-ns* is not launched from a terminal, the color is automatically disabled and the option has no effect.
 
-- **-v** *verbosity* : increases/decreases the verbosity of the command.
-    * *1* : only print error messages. This is the default.
-    * *2* : also print warning messages.
-    * *3* : also print tracing messages.
-    * *4* : also print debugging messages.
+- **-v** *verbosity*: increases/decreases the verbosity of the command.
+    * *0*: only print error messages.
+    * *1*: also, print informative messages. This is the default.
+    * *2*: also, print warning messages.
+    * *3*: also, print tracing messages.
+    * *4*: also, print function name and line code of the messages.
+    * *5*: also, display the sequence of the current process function by function.
 
 - **-d** *notif* : notify readiness on file descriptor *notif*. If *66-ns* is launched from a terminal, the option has no effect. The notification happens right before the launch of *prog*. This guarantees you that the namespace is completely configured and ready to use. This notification **does not** guarantee you that *prog* was started successfully. This is important to keep in mind mostly when you use *66-ns* for a service supervision.
 
diff --git a/doc/66-yeller.md b/doc/66-yeller.md
index 348c1e185f39e5102cbfdc8fc56f5f86005b607e..3035e1d90bb3b0c7f2e4b15ff0589f5454068a6f 100644
--- a/doc/66-yeller.md
+++ b/doc/66-yeller.md
@@ -37,7 +37,7 @@ author: Eric Vidal <eric@obarun.org>
 
 - **-1** *file* : redirects *stream_1* to *file*. The file is opened for appending and created if it doesn't exist.
 
-- **-2** *file* : redirects *stream_2* to *file*. The file is opened for appending and created if it doesn't exist. 
+- **-2** *file* : redirects *stream_2* to *file*. The file is opened for appending and created if it doesn't exist.
 
 - **-z** : enable color. If the *stream_1* does not point to a terminal, the color is automatically disabled and the option has no effects.
 
@@ -47,10 +47,13 @@ author: Eric Vidal <eric@obarun.org>
 
 - **-p** *prog* : use *prog* as the program name to display. By default *66-yeller* tries to find the name of the calling process by reading and parsing the `/proc/<pid>/comm` file. This option tells to *66-yeller* to use *prog* as the default program name to display.
 
-- **-v** *verbosity* : increases/decreases the verbosity of the command.
-    * *1* : prints error and information messages. This is the default.
-    * *2* : also prints warning messages.
-    * *3* : also prints tracing messages.
+- **-v** *verbosity*: increases/decreases the verbosity of the command.
+    * *0*: only print error messages.
+    * *1*: also, print informative messages. This is the default.
+    * *2*: also, print warning messages.
+    * *3*: also, print tracing messages.
+    * *4*: also, print function name and line code of the messages.
+    * *5*: also, display the sequence of the current process function by function.
 
 - **-i** : does not write the informative message.
 
@@ -113,7 +116,7 @@ author: Eric Vidal <eric@obarun.org>
 
 ## Environment variables
 
-The following environment variable can be set to configure the default *66-yeller* behavior. The corresponding options set at commandline overwrite the environment variable. 
+The following environment variable can be set to configure the default *66-yeller* behavior. The corresponding options set at commandline overwrite the environment variable.
 
 - ### PROG
 
@@ -241,7 +244,7 @@ Reads *msg* from stdin:
 Reads message from stdin. Does not display informative message and the system time. Uses double output and redirects *stream_2* to `myfile`
 
 ```
-	% ls -la /tmp | 66-yeller -cdi2 /tmp/myfile -S /tmp contents "->"  
+	% ls -la /tmp | 66-yeller -cdi2 /tmp/myfile -S /tmp contents "->"
 	/tmp contents -> total 844K
 	/tmp contents -> drwxrwxrwt  6 root   root   240 May 18 09:40 ./
 	/tmp contents -> drwxr-xr-x 19 root   root  4.0K May 16 09:13 ../
@@ -257,15 +260,15 @@ Use *66-yeller* in a `sh` script called `script.sh` with a pre-defined behavior
 	export VERBOSITY=2
 	export DOUBLE_OUTPUT=1
 	export REDIRFD_2=/tmp/my_awesome_script.log
-	
+
 	set -e
-	
+
 	if ! [ -e /etc/66/init.conf ]; then
 		66-yeller -f "file /etc/66/init.conf doesn't exist"
 	else
 		cat /etc/66/init.conf | 66-yeller -Sic "%y->%n "
 	fi
-	
+
 	if ! [ -e /etc/66/toto.conf ]; then
 		66-yeller -f "file /etc/66/toto.conf doesn't exist"
 	else
@@ -301,5 +304,5 @@ Use *66-yeller* in a `sh` script called `script.sh` with a pre-defined behavior
 	-> RESCAN=0
 	-> ISHELL=/etc/66/ishell
 	2020-05-18 10:03:28.94 my_awesome_script: fatal: file /etc/66/toto.conf doesn't exist
-	
+
 ```
diff --git a/doc/index.md b/doc/index.md
index 8120f9169ecbae7461a951a205d3b3a2d8bd48f2..9435ee3d980d97e50382b1291be2f367866a3a94 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -7,13 +7,13 @@ author: Eric Vidal <eric@obarun.org>
 
 # What is 66-tools
 
-Sixty-six-tools is a collection of helpers tools to accomplish various and repetitive tasks in service scripts. Some utilities are language [execline](https://skarnet.org/software/execline) specific (usually named with `execl-` prefix) where other can be used on classic shell.
+Sixty-six-tools is a set of helper tools designed to simplify and automate various repetitive tasks commonly encountered in service script administration. These tools also provide additional functionalities to enhance service management.
 
 ## Installation
 
 ### Requirements
 
-Please refer to the [INSTALL.md](https://framagit.org/Obarun/66-tools) file for details.
+Please refer to the [INSTALL.md](https://git.obarun.org/Obarun/66-tools) file for details.
 
 ### Licensing
 
@@ -48,3 +48,5 @@ See [changes](upgrade.html) between version.
 - [66-which](66-which.html)
 
 - [66-yeller](66-yeller.html)
+
+- [66-dbus-launch](66-dbus-launch.html)
diff --git a/doc/make-html.sh b/doc/make-html.sh
index 79b8bc6506bca51e01ac125bd22d06b037f62ebd..7a2ea361d0318d6c0c0c6da321c2af0c75d59597 100755
--- a/doc/make-html.sh
+++ b/doc/make-html.sh
@@ -1,6 +1,6 @@
 #!/bin/sh -e
 
-html='66-clock 66-getenv 66-gnwenv 66-olexec 66-which 66-writenv 66-yeller execl-cmdline execl-subuidgid execl-toc 66-ns index upgrade'
+html='66-clock 66-dbus-launch 66-getenv 66-gnwenv 66-olexec 66-which 66-writenv 66-yeller execl-cmdline execl-subuidgid execl-toc 66-ns index upgrade'
 
 version=${1}
 
diff --git a/doc/make-man.sh b/doc/make-man.sh
index 4b3c1a6c44951939db8eedaea00eb78ec35d2b77..c1a8f780b4fe9fdd2ab400b7bc132f3423584655 100755
--- a/doc/make-man.sh
+++ b/doc/make-man.sh
@@ -1,6 +1,6 @@
 #!/bin/sh -e
 
-man1='66-clock 66-getenv 66-gnwenv 66-olexec 66-which 66-writenv 66-yeller execl-cmdline execl-subuidgid execl-toc 66-ns'
+man1='66-clock 66-dbus-launch 66-getenv 66-gnwenv 66-olexec 66-which 66-writenv 66-yeller execl-cmdline execl-subuidgid execl-toc 66-ns'
 
 mkdir -p doc/man/man1
 
diff --git a/package/deps.mak b/package/deps.mak
index f2b0d43fad6ec02037a7460d37ba5eeb500972fc..9c2927ad92a72d4a59e1a955079eb9d6f68cbb4d 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -2,36 +2,87 @@
 # This file has been generated by tools/gen-deps.sh
 #
 
-src/66-tools/66-clock.o src/66-tools/66-clock.lo: src/66-tools/66-clock.c
-src/66-tools/66-getenv.o src/66-tools/66-getenv.lo: src/66-tools/66-getenv.c
-src/66-tools/66-gnwenv.o src/66-tools/66-gnwenv.lo: src/66-tools/66-gnwenv.c
-src/66-tools/66-ns.o src/66-tools/66-ns.lo: src/66-tools/66-ns.c src/include/66-tools/config.h
-src/66-tools/66-olexec.o src/66-tools/66-olexec.lo: src/66-tools/66-olexec.c
-src/66-tools/66-which.o src/66-tools/66-which.lo: src/66-tools/66-which.c
-src/66-tools/66-writenv.o src/66-tools/66-writenv.lo: src/66-tools/66-writenv.c
-src/66-tools/66-yeller.o src/66-tools/66-yeller.lo: src/66-tools/66-yeller.c
-src/66-tools/execl-cmdline.o src/66-tools/execl-cmdline.lo: src/66-tools/execl-cmdline.c
-src/66-tools/execl-subuidgid.o src/66-tools/execl-subuidgid.lo: src/66-tools/execl-subuidgid.c
-src/66-tools/execl-toc.o src/66-tools/execl-toc.lo: src/66-tools/execl-toc.c
+ifneq ($(strip $(DBUS_IMPL)),)
+src/66-dbus-launch/dbus.h: src/include/66-tools/config.h
+endif
+ifneq ($(strip $(DBUS_IMPL)),)
+src/66-dbus-launch/launcher.h: src/66-dbus-launch/dbus.h src/66-dbus-launch/macro.h
+endif
+ifneq ($(strip $(DBUS_IMPL)),)
+endif
+ifneq ($(strip $(DBUS_IMPL)),)
+src/66-dbus-launch/policy.h: src/66-dbus-launch/dbus.h
+endif
+ifneq ($(strip $(DBUS_IMPL)),)
+src/66-dbus-launch/service.h: src/66-dbus-launch/launcher.h
+endif
+ifneq ($(strip $(DBUS_IMPL)),)
+src/66-dbus-launch/util.h: src/66-dbus-launch/launcher.h
+endif
+src/66-clock/66-clock.o src/66-clock/66-clock.lo: src/66-clock/66-clock.c
+ifneq ($(strip $(DBUS_IMPL)),)
+src/66-dbus-launch/66-dbus-launch.o src/66-dbus-launch/66-dbus-launch.lo: src/66-dbus-launch/66-dbus-launch.c src/66-dbus-launch/dbus.h src/66-dbus-launch/launcher.h src/66-dbus-launch/service.h src/66-dbus-launch/util.h
+endif
+ifneq ($(strip $(DBUS_IMPL)),)
+src/66-dbus-launch/dbus.o src/66-dbus-launch/dbus.lo: src/66-dbus-launch/dbus.c src/include/66-tools/config.h src/66-dbus-launch/dbus.h src/66-dbus-launch/launcher.h src/66-dbus-launch/service.h
+endif
+ifneq ($(strip $(DBUS_IMPL)),)
+src/66-dbus-launch/launcher.o src/66-dbus-launch/launcher.lo: src/66-dbus-launch/launcher.c src/include/66-tools/config.h src/66-dbus-launch/dbus.h src/66-dbus-launch/launcher.h src/66-dbus-launch/macro.h src/66-dbus-launch/policy.h src/66-dbus-launch/service.h src/66-dbus-launch/util.h
+endif
+ifneq ($(strip $(DBUS_IMPL)),)
+src/66-dbus-launch/policy.o src/66-dbus-launch/policy.lo: src/66-dbus-launch/policy.c src/66-dbus-launch/dbus.h src/66-dbus-launch/policy.h
+endif
+ifneq ($(strip $(DBUS_IMPL)),)
+src/66-dbus-launch/service.o src/66-dbus-launch/service.lo: src/66-dbus-launch/service.c src/include/66-tools/config.h src/66-dbus-launch/dbus.h src/66-dbus-launch/launcher.h src/66-dbus-launch/service.h src/66-dbus-launch/util.h
+endif
+ifneq ($(strip $(DBUS_IMPL)),)
+src/66-dbus-launch/util.o src/66-dbus-launch/util.lo: src/66-dbus-launch/util.c src/66-dbus-launch/launcher.h src/66-dbus-launch/service.h
+endif
+src/66-getenv/66-getenv.o src/66-getenv/66-getenv.lo: src/66-getenv/66-getenv.c
+src/66-gnwenv/66-gnwenv.o src/66-gnwenv/66-gnwenv.lo: src/66-gnwenv/66-gnwenv.c
+src/66-ns/66-ns.o src/66-ns/66-ns.lo: src/66-ns/66-ns.c src/include/66-tools/config.h
+src/66-olexec/66-olexec.o src/66-olexec/66-olexec.lo: src/66-olexec/66-olexec.c
+src/66-userd/66-userd.o src/66-userd/66-userd.lo: src/66-userd/66-userd.c
+src/66-which/66-which.o src/66-which/66-which.lo: src/66-which/66-which.c
+src/66-writenv/66-writenv.o src/66-writenv/66-writenv.lo: src/66-writenv/66-writenv.c
+src/66-yeller/66-yeller.o src/66-yeller/66-yeller.lo: src/66-yeller/66-yeller.c
+src/execl-cmdline/execl-cmdline.o src/execl-cmdline/execl-cmdline.lo: src/execl-cmdline/execl-cmdline.c
+src/execl-subuidgid/execl-subuidgid.o src/execl-subuidgid/execl-subuidgid.lo: src/execl-subuidgid/execl-subuidgid.c
+src/execl-toc/execl-toc.o src/execl-toc/execl-toc.lo: src/execl-toc/execl-toc.c
+
 66-clock: EXTRA_LIBS := -loblibs -lskarnet
-66-clock: src/66-tools/66-clock.o 
+66-clock: src/66-clock/66-clock.o 
+ifneq ($(strip $(DBUS_IMPL)),)
+ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
+lib66dbusbroker.a.xyzzy: src/66-dbus-launch/dbus.o src/66-dbus-launch/launcher.o src/66-dbus-launch/policy.o src/66-dbus-launch/service.o src/66-dbus-launch/util.o
+else
+lib66dbusbroker.a.xyzzy: src/66-dbus-launch/dbus.lo src/66-dbus-launch/launcher.lo src/66-dbus-launch/policy.lo src/66-dbus-launch/service.lo src/66-dbus-launch/util.lo
+endif
+endif
+ifneq ($(strip $(DBUS_IMPL)),)
+66-dbus-launch: EXTRA_LIBS := -l66 -loblibs -lskarnet ${DBUS_LIB}
+66-dbus-launch: src/66-dbus-launch/66-dbus-launch.o lib66dbusbroker.a.xyzzy
+endif
 66-getenv: EXTRA_LIBS := -loblibs -lskarnet
-66-getenv: src/66-tools/66-getenv.o 
+66-getenv: src/66-getenv/66-getenv.o 
 66-gnwenv: EXTRA_LIBS := -loblibs -lskarnet
-66-gnwenv: src/66-tools/66-gnwenv.o 
+66-gnwenv: src/66-gnwenv/66-gnwenv.o 
 66-ns: EXTRA_LIBS := -loblibs -lskarnet
-66-ns: src/66-tools/66-ns.o 
+66-ns: src/66-ns/66-ns.o 
 66-olexec: EXTRA_LIBS := -loblibs -lskarnet
-66-olexec: src/66-tools/66-olexec.o 
+66-olexec: src/66-olexec/66-olexec.o 
+66-userd: EXTRA_LIBS := -l66 -loblibs
+66-userd: src/66-userd/66-userd.o
 66-which: EXTRA_LIBS := -loblibs -lskarnet
-66-which: src/66-tools/66-which.o 
+66-which: src/66-which/66-which.o 
 66-writenv: EXTRA_LIBS := -loblibs -lskarnet
-66-writenv: src/66-tools/66-writenv.o
+66-writenv: src/66-writenv/66-writenv.o
 66-yeller: EXTRA_LIBS := -loblibs -lskarnet
-66-yeller: src/66-tools/66-yeller.o 
+66-yeller: src/66-yeller/66-yeller.o 
 execl-cmdline: EXTRA_LIBS := -loblibs -lexecline -lskarnet
-execl-cmdline: src/66-tools/execl-cmdline.o
+execl-cmdline: src/execl-cmdline/execl-cmdline.o
 execl-subuidgid: EXTRA_LIBS := -loblibs -lexecline -lskarnet
-execl-subuidgid: src/66-tools/execl-subuidgid.o ${LIBEXECLINE}
+execl-subuidgid: src/execl-subuidgid/execl-subuidgid.o
 execl-toc: EXTRA_LIBS := -loblibs -lexecline -lskarnet
-execl-toc: src/66-tools/execl-toc.o
+execl-toc: src/execl-toc/execl-toc.o
+INTERNAL_LIBS := lib66dbusbroker.a.xyzzy
diff --git a/package/modes b/package/modes
index bf6c289471b90020dbca5f5e965e5aabb3ed37cd..d850b566bb37cd918102921998bc1b8f0c7f2f86 100644
--- a/package/modes
+++ b/package/modes
@@ -9,3 +9,4 @@
 execl-cmdline   0755
 execl-subuidgid 0755
 execl-toc       0755
+66-dbus-launch  0755
\ No newline at end of file
diff --git a/package/targets.mak b/package/targets.mak
index 0c8ee0d66afdb75b7f7806e7e0175b2477034360..a615100b3e5f2400ff7d242c827192c570c5ba77 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -15,3 +15,23 @@ RULE_TARGET := $(shell find examples/rule -type f)
 
 LIBEXEC_TARGETS :=
 
+LIB_DEFS :=
+
+ifneq ($(DBUS_IMPL),)
+
+BIN_TARGETS += 66-dbus-launch
+
+ifeq ($(DBUS_IMPL),basu)
+
+DBUS_LIB := -lbasu
+
+else ifeq ($(DBUS_IMPL),elogind)
+
+DBUS_LIB := -lelogind
+
+else
+
+DBUS_LIB := $(error invalid DBUS_IMPL. Please configure with --enable-dbus=basu or --enable-dbus=elogind.)
+
+endif
+endif
\ No newline at end of file
diff --git a/src/66-tools/66-clock.c b/src/66-clock/66-clock.c
similarity index 100%
rename from src/66-tools/66-clock.c
rename to src/66-clock/66-clock.c
diff --git a/src/66-tools/deps-exe/66-clock b/src/66-clock/deps-exe/66-clock
similarity index 100%
rename from src/66-tools/deps-exe/66-clock
rename to src/66-clock/deps-exe/66-clock
diff --git a/src/66-dbus-launch/66-dbus-launch.c b/src/66-dbus-launch/66-dbus-launch.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee4b636d07e8cff35b9270b84d94e36370e9dbc0
--- /dev/null
+++ b/src/66-dbus-launch/66-dbus-launch.c
@@ -0,0 +1,165 @@
+/*
+ * 66-dbus-broker-launch.c
+ *
+ * Copyright (c) 2018-2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "service.h"
+#include "launcher.h"
+#include "util.h"
+#include "dbus.h"
+
+#include <oblibs/log.h>
+#include <oblibs/io.h>
+
+#include <skalibs/tai.h>
+#include <skalibs/iopause.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/types.h>
+#include <skalibs/selfpipe.h>
+#include <skalibs/buffer.h>
+#include <skalibs/sig.h>
+
+#define USAGE "66-dbus-launch [ -h ] [ -z ] [ -v verbosity ] [ -d notif ]"
+
+static inline void info_help (void)
+{
+    static char const *help =
+        "66-dbus-launch <options> prog\n"
+        "\n"
+        "options:\n"
+        "   -h: print this help\n"
+        "   -z: use color\n"
+        "   -v: increase/decrease verbosity\n"
+		"   -d: notify readiness on file descriptor notif\n"
+        "\n"
+        ;
+
+    if (buffer_putsflush(buffer_1, help) < 0)
+        log_dieusys(LOG_EXIT_SYS, "write to stdout") ;
+}
+
+static int notifier_isvalid(const char *str)
+{
+	unsigned int u ;
+
+	if (!uint0_scan(str, &u))
+		log_usage(USAGE) ;
+
+	if (u < 3)
+		log_die(LOG_EXIT_USER, "file descriptor must be 3 or more") ;
+
+	if (fcntl(u, F_GETFD) < 0)
+		log_diesys(LOG_EXIT_USER, "invalid file descriptor") ;
+
+	return u ;
+}
+
+int main(int argc, char const *const *argv)
+{
+	unsigned int notif = 0 ;
+	int r, istty ;
+	struct service_s *hservice = NULL ;
+	dbs_cleanup_(launcher_freep) launcher_t *launcher = 0 ;
+
+	log_color = &log_color_disable ;
+	istty = isatty(1) ;
+
+	set_clock_enable(1) ;
+
+	PROG = "66-dbus-launch" ;
+	{
+		subgetopt l = SUBGETOPT_ZERO ;
+		for (;;) {
+			int opt = subgetopt_r(argc, argv, "hzv:d:", &l) ;
+            if (opt == -1)
+				break ;
+            switch (opt) {
+				case 'h':
+                    info_help() ;
+					return 0 ;
+				case 'z':
+                    log_color = !istty ? &log_color_disable : &log_color_enable ;
+                    break ;
+                case 'v':
+                    if (!uint0_scan(l.arg, &VERBOSITY))
+                        log_usage(USAGE) ;
+                    break ;
+				case 'd':
+                    notif = notifier_isvalid(l.arg) ;
+					break ;
+				default:
+                    log_usage(USAGE) ;
+			}
+		}
+		argc -= l.ind ; argv += l.ind ;
+	}
+
+	if (!fd_sanitize())
+		log_dieusys(LOG_EXIT_SYS, "sanitize standards I/O") ;
+
+	/** bind and listen dbus socket */
+	int socket = dbs_socket_bind() ;
+
+	if (dbs_setenv_dbus_address() < 0)
+		log_dieusys(LOG_EXIT_SYS, "set ", !getuid() ? "DBUS_SYSTEM_BUS_ADDRESS" : "DBUS_SESSION_BUS_ADDRESS") ;
+
+	if (!fd_ensure_open(notif, notif))
+		log_dieusys(LOG_EXIT_SYS, "reverse fd for notification") ;
+
+	int spfd = selfpipe_init() ;
+	if (spfd < 0)
+        log_dieusys(LOG_EXIT_SYS, "selfpipe_init") ;
+
+	if (!selfpipe_trap(SIGCHLD) ||
+        !selfpipe_trap(SIGINT) ||
+		!selfpipe_trap(SIGQUIT) ||
+        !selfpipe_trap(SIGHUP) ||
+        !selfpipe_trap(SIGTERM) ||
+        !sig_altignore(SIGPIPE))
+            log_dieusys(LOG_EXIT_SYS, "selfpipe_trap") ;
+
+	/** populate launcher struct */
+	r = launcher_new(&launcher, &hservice, socket, spfd) ;
+	if (r < 0)
+		log_dieu(LOG_EXIT_SYS, "make new launcher") ;
+
+	r = service_load(launcher) ;
+	if (r <= 0)
+		log_dieu(LOG_EXIT_SYS, "collect service") ;
+
+	r = launcher_run(launcher) ;
+	if (r < 0)
+		log_dieu(LOG_EXIT_SYS, "run launcher") ;
+
+	// notify right before the loop
+	if (notif) {
+		write(notif, "\n", 1) ;
+		close(notif) ;
+	}
+
+	r = launcher_loop(launcher) ;
+	if (r < 0)
+		log_dieu(LOG_EXIT_SYS, "loop launcher") ;
+
+	selfpipe_finish() ;
+	/** tear down all services from tree dbus */
+	service_discard_tree() ;
+
+	return 0 ;
+}
diff --git a/src/66-dbus-launch/DCO b/src/66-dbus-launch/DCO
new file mode 100644
index 0000000000000000000000000000000000000000..0cdce0c397f01a8749cf6052289e9275ddd8652e
--- /dev/null
+++ b/src/66-dbus-launch/DCO
@@ -0,0 +1,37 @@
+Developer Certificate of Origin
+Version 1.1
+
+Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
+1 Letterman Drive
+Suite D4700
+San Francisco, CA, 94129
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+
+Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+(a) The contribution was created in whole or in part by me and I
+    have the right to submit it under the open source license
+    indicated in the file; or
+
+(b) The contribution is based upon previous work that, to the best
+    of my knowledge, is covered under an appropriate open source
+    license and I have the right under that license to submit that
+    work with modifications, whether created in whole or in part
+    by me, under the same open source license (unless I am
+    permitted to submit under a different license), as indicated
+    in the file; or
+
+(c) The contribution was provided directly to me by some other
+    person who certified (a), (b) or (c) and I have not modified
+    it.
+
+(d) I understand and agree that this project and the contribution
+    are public and that a record of the contribution (including all
+    personal information I submit with it, including my sign-off) is
+    maintained indefinitely and may be redistributed consistent with
+    this project or the open source license(s) involved.
\ No newline at end of file
diff --git a/src/66-dbus-launch/dbus.c b/src/66-dbus-launch/dbus.c
new file mode 100644
index 0000000000000000000000000000000000000000..900fe97c923e1f2ab0ac3b1e55984397fd3ac97f
--- /dev/null
+++ b/src/66-dbus-launch/dbus.c
@@ -0,0 +1,168 @@
+/*
+ * dbus.c
+ *
+ * Copyright (c) 2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include "dbus.h"
+#include "launcher.h"
+#include "service.h"
+
+#include <oblibs/log.h>
+#include <oblibs/io.h>
+#include <oblibs/string.h>
+#include <oblibs/stack.h>
+#include <oblibs/socket.h>
+
+#include <skalibs/types.h>
+
+#include <66/config.h>
+
+#include <66-tools/config.h>
+
+const sd_bus_vtable launcher_vtable[] = {
+	SD_BUS_VTABLE_START(0),
+	SD_BUS_METHOD("ReloadConfig", NULL, NULL, launcher_on_reload_config, 0),
+	SD_BUS_VTABLE_END
+} ;
+
+sd_bus *dbs_close_unref(sd_bus *bus)
+{
+	log_flow() ;
+	/** It is not sufficient to simply call sd_bus_unref(), as messages
+	* in the bus' queues may pin the bus itself. Also,
+	* sd_bus_flush_close_unref() is not always appropriate as it would
+	* block in poll waiting for messages to be flushed to the socket.
+	*
+	* In some cases all we really want to do is close the socket and
+	* release all the memory, ignoring whether or not it has been
+	* flushed to the kernel (typically in error paths). */
+	if (!bus)
+		return NULL ;
+
+	sd_bus_flush(bus) ;
+	//sd_bus_close(bus) ;
+
+	return sd_bus_unref(bus) ;
+}
+
+void dbs_get_socket_path(char *path)
+{
+	log_flow() ;
+
+	uid_t uid = getuid() ;
+
+	if (!uid) {
+		auto_strings(path, "/run/dbus/", SS_TOOLS_DBS_SYSTEM_NAME) ;
+	} else {
+		char ustr[UID_FMT] ;
+		ustr[uid_fmt(ustr, uid)] = 0 ;
+		auto_strings(path, "/run/user/", ustr, "/", SS_TOOLS_DBS_SESSION_NAME) ;
+	}
+}
+
+int dbs_get_socket_unix_path(char *path)
+{
+	_alloc_stk_(s, SS_MAX_PATH) ;
+	dbs_get_socket_path(s.s) ;
+	s.len = strlen(s.s) ;
+	if (!stack_insert(&s, 0, "unix:path="))
+		log_warnusys_return(DBS_EXIT_FATAL, "stack insert") ;
+
+	auto_strings(path, s.s) ;
+
+	return 1 ;
+}
+
+int dbs_socket_bind(void)
+{
+	log_flow() ;
+
+	_alloc_stk_(path, SS_MAX_PATH) ;
+	dbs_get_socket_path(path.s) ;
+
+	unlink(path.s) ;
+
+	close(0) ;
+	int fd = socket_open(SOCK_NONBLOCK|SOCK_CLOEXEC) ;
+	if (fd < 0)
+		log_dieusys(LOG_EXIT_SYS, "create socket") ;
+
+	mode_t m = umask(0000) ;
+	if (socket_bind(fd, path.s) < 0) {
+		close(fd) ;
+		log_dieusys(LOG_EXIT_SYS, "bind socket: ", path.s) ;
+	}
+	umask(m) ;
+
+	if (socket_listen(fd, SOCK_BACKLOG) < 0) {
+		close(fd) ;
+		log_dieusys(LOG_EXIT_SYS, "listen socket: ", path.s) ;
+	}
+
+	return fd ;
+}
+
+int dbs_setenv_dbus_address(void)
+{
+	/** bus_set_address_user and bus_set_address_system rely
+	 * on this environment variable*/
+
+	uid_t uid = getuid() ;
+	char *path = 0 ;
+	_alloc_stk_(stk, SS_MAX_PATH) ;
+
+	if (!uid) {
+
+		path = getenv("DBUS_SYSTEM_BUS_ADDRESS") ;
+
+		if (!path) {
+
+			if (dbs_get_socket_unix_path(stk.s) < 0)
+				log_warnusys_return(DBS_EXIT_FATAL, "get dbus socket path") ;
+
+			if (setenv("DBUS_SYSTEM_BUS_ADDRESS", stk.s, 1) < 0)
+				log_warnusys_return(DBS_EXIT_FATAL, "set DBUS_SYSTEM_BUS_ADDRESS=", stk.s, " environment variable") ;
+
+			return 1 ;
+		}
+
+		if (setenv("DBUS_SYSTEM_BUS_ADDRESS", path, 1) < 0)
+			log_warnusys_return(DBS_EXIT_FATAL, "set DBUS_SYSTEM_BUS_ADDRESS=", path, " environment variable") ;
+
+	} else {
+
+		path = getenv("DBUS_SESSION_BUS_ADDRESS") ;
+
+		if (!path) {
+
+			if (dbs_get_socket_unix_path(stk.s) < 0)
+			log_warnusys_return(DBS_EXIT_FATAL, "get dbus socket path") ;
+
+			if (setenv("DBUS_SESSION_BUS_ADDRESS", stk.s, 1) < 0)
+				log_warnusys_return(DBS_EXIT_FATAL, "set DBUS_SESSION_BUS_ADDRESS=", stk.s, " environment variable") ;
+
+			return 1 ;
+		}
+
+		if (setenv("DBUS_SESSION_BUS_ADDRESS", path, 1) < 0)
+			log_warnusys_return(DBS_EXIT_FATAL, "set DBUS_SESSION_BUS_ADDRESS=", path, " environment variable") ;
+	}
+
+	return 1 ;
+}
\ No newline at end of file
diff --git a/src/66-dbus-launch/dbus.h b/src/66-dbus-launch/dbus.h
new file mode 100644
index 0000000000000000000000000000000000000000..d5026c419f5b1c5863b05230f4e88c4a735f5de8
--- /dev/null
+++ b/src/66-dbus-launch/dbus.h
@@ -0,0 +1,44 @@
+/*
+ * dbus.h
+ *
+ * Copyright (c) 2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#ifndef DBS_DBUS_H_INCLUDE
+#define DBS_DBUS_H_INCLUDE
+
+#include <66-tools/config.h>
+
+#ifdef SS_TOOLS_USE_BASU
+#include <basu/sd-bus.h>
+#include <basu/sd-bus-vtable.h>
+#else
+#ifdef SS_TOOLS_USE_ELOGIND
+#include <elogind/sd-bus.h>
+#include <elogind/sd-bus-vtable.h>
+#else
+
+#error No sd_bus backend configured
+
+#endif
+#endif
+
+#define MACHINEID 32 // https://www.freedesktop.org/software/systemd/man/latest/machine-id.html
+
+extern const sd_bus_vtable launcher_vtable[] ;
+extern sd_bus *dbs_close_unref(sd_bus *bus) ;
+extern void dbs_get_socket_path(char *store) ;
+extern int dbs_get_socket_unix_path(char *store) ;
+extern int dbs_socket_bind(void) ;
+extern int dbs_setenv_dbus_address(void) ;
+
+#endif
+
diff --git a/src/66-dbus-launch/deps-exe/66-dbus-launch b/src/66-dbus-launch/deps-exe/66-dbus-launch
new file mode 100644
index 0000000000000000000000000000000000000000..a80668d7ad5575ebb751bab985c041bbce6cecfc
--- /dev/null
+++ b/src/66-dbus-launch/deps-exe/66-dbus-launch
@@ -0,0 +1,5 @@
+lib66dbusbroker.a.xyzzy
+-l66
+-loblibs
+-lskarnet
+${DBUS_LIB}
diff --git a/src/66-dbus-launch/deps-lib/66dbusbroker b/src/66-dbus-launch/deps-lib/66dbusbroker
new file mode 100644
index 0000000000000000000000000000000000000000..93a02a9c157674b009fb0eaf189400cc3dbabcc8
--- /dev/null
+++ b/src/66-dbus-launch/deps-lib/66dbusbroker
@@ -0,0 +1,8 @@
+dbus.o
+launcher.o
+policy.o
+service.o
+util.o
+-l66
+-loblibs
+-lskarnet
diff --git a/src/66-dbus-launch/launcher.c b/src/66-dbus-launch/launcher.c
new file mode 100644
index 0000000000000000000000000000000000000000..d3df776398b1ee5808b45be6ed7751c3f8bf6a6d
--- /dev/null
+++ b/src/66-dbus-launch/launcher.c
@@ -0,0 +1,477 @@
+/*
+ * launcher.c
+ *
+ * Copyright (c) 2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <grp.h>
+#include <sys/prctl.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/socket.h>
+
+#include "launcher.h"
+#include "dbus.h"
+#include "service.h"
+#include "util.h"
+#include "policy.h"
+#include "macro.h"
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+#include <oblibs/stack.h>
+#include <oblibs/sastr.h>
+#include <oblibs/files.h>
+#include <oblibs/io.h>
+
+#include <skalibs/iopause.h>
+#include <skalibs/selfpipe.h>
+
+#include <66-tools/config.h>
+
+#include <66/constants.h>
+#include <66/config.h>
+
+launcher_t *launcher_free(launcher_t *launcher)
+{
+	log_flow() ;
+
+	if (!launcher)
+		return NULL ;
+	close(launcher->fd_dbus) ;
+    dbs_close_unref(launcher->bus_controller) ;
+    dbs_close_unref(launcher->bus_regular) ;
+	service_hash_free(launcher->hservice) ;
+	close(launcher->fd_controller_in) ;
+	close(launcher->fd_controller_out) ;
+	free(launcher) ;
+	return NULL ;
+}
+
+int launcher_new(launcher_t_ref *plauncher, struct service_s **hservice, int socket, int sfpd)
+{
+	log_flow() ;
+
+	dbs_cleanup_(launcher_freep) launcher_t *launcher = NULL ;
+
+	launcher = calloc(1, sizeof(*launcher)) ;
+	if (!launcher)
+		log_warn_return(DBS_EXIT_FATAL, "launcher") ;
+
+	launcher->fd_dbus = socket ;
+	launcher->spfd = sfpd ;
+	launcher->fd_controller_in= -1 ;
+	launcher->fd_controller_out= -1 ;
+	launcher->uid = getuid() ;
+	launcher->gid = getgid() ;
+	launcher->nservice = 1 ;
+	launcher_get_machine_id(launcher) ;
+
+	launcher->hservice = hservice ;
+
+	*plauncher = launcher ;
+	launcher = NULL ;
+
+	return 1 ;
+}
+
+int launcher_run(launcher_t *launcher)
+{
+	int r, controller[2] ;
+
+	if (socketpair(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, controller) < 0)
+		log_warnu_return(DBS_EXIT_FATAL, "socketpair") ;
+
+	launcher->fd_controller_in = controller[0] ;
+	launcher->fd_controller_out = controller[1] ;
+
+	if (pipe(launcher->sync) < 0)
+		log_warnu_return(DBS_EXIT_FATAL, "pipe") ;
+
+	r = launcher_fork(launcher) ;
+	if (r < 0)
+		return r ;
+
+	r = launcher_setup(launcher) ;
+	if (r < 0)
+		log_warnu_return(r, "setup launcher") ;
+
+	return 1 ;
+}
+
+int launcher_fork(launcher_t *launcher)
+{
+	int r ;
+	pid_t pid = fork();
+	if (pid == -1)
+		log_warnusys_return(DBS_EXIT_FATAL, "fork") ;
+
+	if (pid == 0) {
+
+		close(launcher->sync[0]) ;
+		selfpipe_finish() ;
+		close(launcher->fd_controller_in) ;
+
+		launcher_run_broker(launcher) ;
+	}
+
+	close(launcher->fd_controller_out) ;
+
+	launcher->bpid = pid ;
+
+	{
+		// synchronize with child
+		close(launcher->sync[1]) ;
+		int dummy ;
+		do r = read(launcher->sync[0], &dummy, 1) ;
+		while ((r < 0) && (errno == EINTR)) ;
+		if (r < 0)
+			log_warnu_return(DBS_EXIT_FATAL, "synchronize with child") ;
+		close(launcher->sync[0]) ;
+	}
+
+	return 1 ;
+}
+
+int launcher_setup(launcher_t *launcher)
+{
+	log_flow() ;
+
+	int r ;
+	if (sd_bus_new(&launcher->bus_controller) < 0)
+	 	log_warn_return(DBS_EXIT_FATAL, "sd_bus_new") ;
+
+	if (sd_bus_set_fd(launcher->bus_controller, launcher->fd_controller_in, launcher->fd_controller_in) < 0)
+		log_warnu_return(DBS_EXIT_FATAL, "set the file descriptors to use for bus communication") ;
+
+	if (sd_bus_add_object_vtable(launcher->bus_controller, NULL, "/org/bus1/DBus/Controller", "org.bus1.DBus.Controller", launcher_vtable, launcher) < 0)
+		log_warnusys_return(DBS_EXIT_FATAL, "sd_bus_add_object_vtable") ;
+
+	if (sd_bus_start(launcher->bus_controller) < 0)
+		log_warnusys_return(DBS_EXIT_FATAL, "sd_bus_start") ;
+
+	if (sd_bus_add_filter(launcher->bus_controller, NULL, launcher_on_message, launcher) < 0)
+		log_warnusys_return(DBS_EXIT_FATAL, "sd_bus_add_filter") ;
+
+	if (!launcher_add_listener(launcher))
+		log_warnsys("AddListener failed") ;
+
+	if (launcher_connect(launcher) < 0)
+	 	log_warnusys_return(DBS_EXIT_FATAL, "connect to dbus socket") ;
+
+	service_sync_launcher_broker(launcher) ;
+
+	r = launcher_drop_permissions(launcher) ;
+	if (r < 0)
+		log_warnusys_return(DBS_EXIT_FATAL, "drop permissions") ;
+
+	return 1 ;
+}
+
+int launcher_connect(launcher_t *launcher)
+{
+	log_flow() ;
+
+	if (launcher->uid) {
+		if (sd_bus_open_user(&launcher->bus_regular) < 0)
+			log_warnusys_return(DBS_EXIT_FATAL, "set user dbus address") ;
+	} else {
+		if (sd_bus_open_system(&launcher->bus_regular) < 0)
+			log_warnusys_return(DBS_EXIT_FATAL, "set system dbus address") ;
+	}
+
+	return 1  ;
+}
+
+int launcher_run_broker(launcher_t *launcher)
+{
+	log_flow() ;
+
+	int r, flags ;
+	char fd[INT_FMT] ;
+	fd[int_fmt(fd, launcher->fd_controller_out)] = 0 ;
+
+	const char *const nargv[] = {
+		"/usr/bin/dbus-broker",
+		"--controller",
+		fd,
+		"--machine-id",
+		launcher->machineid,
+		// "--max-matches", "1000000",
+        // "--max-objects", "1000000",
+        // "--max-bytes", "1000000000",
+		0
+	} ;
+
+	r = launcher_drop_permissions(launcher) ;
+	if (r < 0){
+		log_warnusys("drop permissions") ;
+		goto exit ;
+	}
+
+	// die if parent process exit
+	if (prctl(PR_SET_PDEATHSIG, SIGTERM)) {
+		log_warnusys("prctl") ;
+		goto exit ;
+	}
+
+	flags = fcntl(launcher->fd_controller_out, F_GETFD) ;
+    if (flags < 0) {
+		log_warnusys("get flags of fd_controller_out") ;
+		goto exit ;
+	}
+
+	if (fcntl(launcher->fd_controller_out, F_SETFD, flags & ~FD_CLOEXEC) < 0){
+		log_warnusys("remove FD_CLOEXEC flag on fd_controller_out") ;
+		goto exit ;
+	}
+
+	{
+		// synchronize with parent
+		do r = write(launcher->sync[1], "\n", 1) ;
+		while (r < 0 && (errno = EINTR)) ;
+		if (r < 0) {
+			log_warnusys("synchronize with parent") ;
+			goto exit ;
+		}
+		close(launcher->sync[1]) ;
+	}
+
+	execve(nargv[0], (char *const *) nargv, (char *const *) environ) ;
+	log_warnusys_return(DBS_EXIT_FATAL, "exec dbus-broker") ;
+
+	exit:
+		_exit(1) ;
+}
+
+int launcher_add_listener(launcher_t *launcher)
+{
+	log_flow() ;
+
+	sd_bus_message *m = NULL ;
+
+	if (sd_bus_message_new_method_call(launcher->bus_controller,
+									   &m,
+									   NULL,
+									   "/org/bus1/DBus/Broker",
+									   "org.bus1.DBus.Broker",
+									   "AddListener") < 0)
+		log_warnusys_return(DBS_EXIT_WARN, "call method org.bus1.DBus.Broker") ;
+
+	if (sd_bus_message_append(m, "oh", "/org/bus1/DBus/Listener/0", launcher->fd_dbus) < 0)
+		log_warnusys_return(DBS_EXIT_WARN, "append message") ;
+
+	if (policy(m) < 0)
+		log_warnusys_return(DBS_EXIT_WARN, "export policy") ;
+
+	sd_bus_error error = SD_BUS_ERROR_NULL ;
+	if (sd_bus_call(launcher->bus_controller, m, 0, &error, NULL) < 0)
+		log_warnu_return(DBS_EXIT_WARN, "sd_bus_call failed: ", error.name," ", error.message) ;
+
+	sd_bus_message_unref(m) ;
+
+	return 1 ;
+}
+
+int launcher_loop(launcher_t *launcher)
+{
+	int r ;
+	tain deadline = tain_infinite_relative ;
+
+	iopause_fd x[2] = {
+		{ .fd = launcher->spfd, .events = IOPAUSE_READ, .revents = 0 },
+		{ .fd = launcher->fd_controller_in, .events = IOPAUSE_READ, .revents = 0 }
+	} ;
+
+	tain_now_set_stopwatch_g() ;
+    tain_add_g(&deadline, &deadline) ;
+
+	for (;;) {
+
+		r = iopause_g(x, 2, &deadline) ;
+        if (r < 0)
+            log_warnusys_return(DBS_EXIT_FATAL, "iopause") ;
+        if (!r)
+			// never reached
+            log_warnusys_return(DBS_EXIT_FATAL, "timeout") ;
+
+		if (x[1].revents & IOPAUSE_READ) {
+
+			do r = sd_bus_process(launcher->bus_controller, NULL) ;
+			while (r < 0 && errno == EINTR) ;
+			if (r < 0)
+				log_warnusys_return(DBS_EXIT_FATAL, "process bus");
+			if (r > 0) /* we processed a request, try to process another one, right-away */
+				continue ;
+		}
+
+		if (x[0].revents & IOPAUSE_READ) {
+
+			r = handle_signal(launcher, launcher->bpid) ;
+			if (r == DBS_EXIT_MAIN)
+				break ;
+			if (r == DBS_EXIT_FATAL)
+				return DBS_EXIT_FATAL ;
+			continue ;
+        }
+	}
+
+	return 1 ;
+}
+
+// https://github.com/bus1/dbus-broker/blob/main/src/launch/launcher.c#L491
+int launcher_on_message(sd_bus_message *m, void *userdata, sd_bus_error *error)
+{
+	log_flow() ;
+
+	launcher_t *launcher = userdata ;
+
+	const char *obj_path ;
+	int suffix ;
+
+	obj_path = sd_bus_message_get_path(m) ;
+
+	if (!obj_path)
+		return 0 ;
+
+	suffix = str_start_with(obj_path, "/org/bus1/DBus/Name/") ;
+
+	if (!suffix) {
+
+		if (sd_bus_message_is_signal(m, "org.bus1.DBus.Name", "Activate")) {
+
+			uint64_t serial;
+			int r = sd_bus_message_read(m, "t", &serial);
+
+			_alloc_stk_(stk, strlen(obj_path) + 1) ;
+
+			if (!ob_basename(stk.s, obj_path))
+				log_warnu_return(DBS_EXIT_WARN, "get basename of: ", obj_path) ;
+
+			r = service_activate(launcher, atoi(stk.s)) ;
+
+			if (r != 0)
+				sd_bus_call_method(launcher->bus_controller, NULL, obj_path, "org.bus1.DBus.Name", "Reset", NULL, NULL, "t", serial) ;
+
+		}
+
+	} else if (!strcmp(obj_path, "/org/bus1/DBus/Broker")) {
+
+		if (sd_bus_message_is_signal(m, "org.bus1.DBus.Broker", "SetActivationEnvironment"))
+			launcher_update_environment(launcher, m) ;
+	}
+
+	return 0 ;
+}
+
+int launcher_on_reload_config(sd_bus_message *message, void *userdata, sd_bus_error *error)
+{
+	log_flow() ;
+
+    launcher_t *launcher = userdata ;
+	log_info("config reload requested") ;
+	service_reload(launcher) ;
+	return sd_bus_reply_method_return(message, NULL) ;
+}
+
+// https://github.com/bus1/dbus-broker/blob/main/src/launch/launcher.c#L459
+void launcher_update_environment(launcher_t *launcher, sd_bus_message *m)
+{
+	log_flow() ;
+
+	char home[SS_MAX_PATH_LEN + strlen(SS_ENVIRONMENT_USERDIR) + 9] ;
+	_alloc_sa_(sa) ;
+
+	memset(home, 0, sizeof(char) * SS_MAX_PATH_LEN + strlen(SS_ENVIRONMENT_USERDIR) + 9) ;
+
+	log_info("environment update requested") ;
+
+	int r = sd_bus_message_enter_container(m, 'a', "{ss}") ;
+	if (r != 1) {
+		log_warnusys("enter in container") ;
+		goto exit ;
+	}
+
+	while (!sd_bus_message_at_end(m, false)) {
+
+		const char *key, *value;
+
+		r = sd_bus_message_read(m, "{ss}", &key, &value);
+		if (r < 0) {
+			log_warnusys("read environment key=value pair") ;
+			goto exit ;
+		}
+
+		if (!auto_stra(&sa, key, "=", value, "\n")) {
+			log_warnusys("stralloc") ;
+			goto exit ;
+		}
+	}
+
+	if (!service_environ_file_name(home, launcher))
+		goto exit ;
+
+	log_trace("write environment file: ", home) ;
+	if (!file_write_unsafe_g(home, sa.s))
+		log_warnusys("write file: ", home) ;
+
+	exit:
+		r = sd_bus_message_exit_container(m) ;
+		if (r != 1)
+			log_warnusys("exit from container") ;
+}
+
+void launcher_get_machine_id(launcher_t *launcher)
+{
+	log_flow() ;
+
+	int fd = io_open("/etc/machine-id", O_RDONLY) ;
+	if (fd < 0) {
+		memcpy(launcher->machineid, "00000000000000000000000000000001", 32) ;
+        goto exit ;
+    }
+
+    int r = io_read(launcher->machineid, fd, 32) ;
+    if (r < 0)
+        memcpy(launcher->machineid, "00000000000000000000000000000001", 32) ;
+
+    exit:
+	    r = 32 ;
+	    close(fd) ;
+
+        launcher->machineid[r + 1] = 0 ;
+}
+
+int launcher_drop_permissions(launcher_t *launcher)
+{
+	if (launcher->uid > 0) {
+		/*
+		* For compatibility to dbus-daemon, this must be
+		* non-fatal.
+		*/
+		setgroups(0, NULL) ;
+
+		if (setgid(launcher->gid) < 0)
+			log_warnusys_return(DBS_EXIT_FATAL, "setgid") ;
+
+		if (setuid(launcher->uid) < 0)
+			log_warnusys_return(DBS_EXIT_FATAL, "setuid") ;
+	}
+
+	return 1 ;
+}
+
+
diff --git a/src/66-dbus-launch/launcher.h b/src/66-dbus-launch/launcher.h
new file mode 100644
index 0000000000000000000000000000000000000000..0cd8acd949d3f19273c0939432e8268a889a29a0
--- /dev/null
+++ b/src/66-dbus-launch/launcher.h
@@ -0,0 +1,66 @@
+/*
+ * launcher.h
+ *
+ * Copyright (c) 2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#ifndef DBS_LAUNCHER_H_INCLUDE
+#define DBS_LAUNCHER_H_INCLUDE
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "dbus.h"
+#include "macro.h"
+
+/** Avoid circular dependency with service.h header file*/
+struct service_s ;
+
+typedef struct launcher_s launcher_t, *launcher_t_ref ;
+struct launcher_s
+{
+	int fd_dbus ; // fd of the dbus socket
+	int fd_controller_in ; // fd to pass to the broker
+	int fd_controller_out ; // fd to pass to the broker
+	char machineid[MACHINEID + 2] ; // machine id string
+	uid_t uid ; // uid of the owner of the process
+	gid_t gid ; // gid of the owner of the process
+	sd_bus *bus_controller ;
+	sd_bus *bus_regular ;
+	pid_t bpid ; // pid of the broker
+	int sync[2] ; // synchronization between parent and child
+	int spfd ; // fd to trap signal
+	uint32_t nservice ; // counter for struct service_s -> id, never reset
+	struct service_s **hservice ;
+} ;
+
+#define LAUNCHER_ZERO { 0, 0, 0, {0}, -1, -1, NULL, NULL, -1, {0}, 0, 1, NULL } ;
+
+extern launcher_t *launcher_free(launcher_t *launcher) ;
+
+DBS_DEFINE_CLEANUP(launcher_t *, launcher_free) ;
+
+extern int launcher_new(launcher_t_ref *launcher, struct service_s **hservice, int socket, int spfd) ;
+extern int launcher_setup(launcher_t *launcher) ;
+extern int launcher_run_broker(launcher_t *launcher) ;
+extern int launcher_add_listener(launcher_t *launcher) ;
+extern int launcher_on_message(sd_bus_message *m, void *userdata, sd_bus_error *error) ;
+extern int launcher_on_reload_config(sd_bus_message *message, void *userdata, sd_bus_error *error) ;
+extern void launcher_update_environment(launcher_t *launcher, sd_bus_message *m) ;
+extern void launcher_get_machine_id(launcher_t *launcher) ;
+extern int launcher_drop_permissions(launcher_t *launcher) ;
+extern int launcher_run(launcher_t *launcher) ;
+extern int launcher_fork(launcher_t *launcher) ;
+extern int launcher_loop(launcher_t *launcher) ;
+extern int launcher_connect(launcher_t *launcher) ;
+
+#endif
+
diff --git a/src/66-dbus-launch/macro.h b/src/66-dbus-launch/macro.h
new file mode 100644
index 0000000000000000000000000000000000000000..c9810d73de35d506bbc1f1dc6bc7ed645f9e8152
--- /dev/null
+++ b/src/66-dbus-launch/macro.h
@@ -0,0 +1,30 @@
+/*
+ * macro.h
+ *
+ * Copyright (c) 2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+#ifndef DBS_MACRO_H_INCLUDE
+#define DBS_MACRO_H_INCLUDE
+
+#define dbs_cleanup_(func) __attribute__((__cleanup__(func)))
+
+#define DBS_DEFINE_CLEANUP(_type, _func)			\
+	static inline void _func ## p(_type *p) {   \
+		if (*p)                                 \
+		    _func(*p) ;                 		\
+	} struct force_semicolon
+
+#define DBS_EXIT_FATAL -1
+#define DBS_EXIT_WARN 0
+#define DBS_EXIT_MAIN 0
+#define DBS_EXIT_CHILD 1
+
+#endif
\ No newline at end of file
diff --git a/src/66-dbus-launch/policy.c b/src/66-dbus-launch/policy.c
new file mode 100644
index 0000000000000000000000000000000000000000..31ecacfeb6e8ac739d9bfb65389d568eb702625a
--- /dev/null
+++ b/src/66-dbus-launch/policy.c
@@ -0,0 +1,92 @@
+/*
+ * policy.c
+ *
+ * Copyright (c) 2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "dbus.h"
+#include "policy.h"
+
+#include <oblibs/log.h>
+
+/*
+ * At the moment, we just allow everything
+ * The syntax of the policy is not stable yet: refer to
+ * https://github.com/bus1/dbus-broker/blob/main/docs/dbus-broker.rst
+ * dbus-broker/src/launch/policy.c and
+ * dbus-broker/src/bus/policy.c
+ *
+ * For Type format https://man.archlinux.org/man/sd_bus_message_append.3.en
+ */
+
+static void policy_export_connect(sd_bus_message *m)
+{
+    sd_bus_message_append(m, "bt", true, POLICY_PRIORITY_DEFAULT) ;
+}
+
+static void policy_export_own(sd_bus_message *m)
+{
+    sd_bus_message_open_container(m, 'a', "(btbs)") ;
+    sd_bus_message_open_container(m, 'r', "btbs") ;
+    sd_bus_message_append(m, "btbs", true, POLICY_PRIORITY_DEFAULT, true, "") ;
+    sd_bus_message_close_container(m) ;
+    sd_bus_message_close_container(m) ;
+}
+
+static void policy_export_xmit(sd_bus_message *m)
+{
+    sd_bus_message_open_container(m, 'a', "(btssssuutt)") ;
+    sd_bus_message_open_container(m, 'r', "btssssuutt") ;
+    sd_bus_message_append(m, "btssssuutt", true, POLICY_PRIORITY_DEFAULT, "", "", "", "", 0, 0, UINT64_C(0), (uint64_t) - 1) ;
+    sd_bus_message_close_container(m) ;
+    sd_bus_message_close_container(m) ;
+}
+
+int policy(sd_bus_message *m)
+{
+    log_flow() ;
+
+    int r;
+    r = sd_bus_message_open_container(m, 'v', "(" POLICY_T ")") ;
+    r = sd_bus_message_open_container(m, 'r', POLICY_T) ;
+    r = sd_bus_message_open_container(m, 'a', "(u(" POLICY_T_BATCH "))") ;
+    r = sd_bus_message_open_container(m, 'r', "u(" POLICY_T_BATCH ")") ;
+    r = sd_bus_message_append(m, "u", (uint32_t) - 1) ;
+    r = sd_bus_message_open_container(m, 'r', POLICY_T_BATCH) ;
+    policy_export_connect(m) ;
+    policy_export_own(m) ;
+    policy_export_xmit(m) ;
+    policy_export_xmit(m) ;
+
+    r = sd_bus_message_close_container(m) ;
+    r = sd_bus_message_close_container(m) ;
+    r = sd_bus_message_close_container(m) ;
+
+    r = sd_bus_message_open_container(m, 'a', "(buu(" POLICY_T_BATCH "))") ;
+    r = sd_bus_message_close_container(m) ;
+
+    r = sd_bus_message_open_container(m, 'a', "(ss)") ;
+    r = sd_bus_message_close_container(m) ;
+
+    r = sd_bus_message_append(m, "b", false) ;
+
+    /** From a cursory reading of the source code, it seems this is
+     * only relevant if you're using MAC. Until the policy API gets
+     * stabilized, using this field doesn't make sense.*/
+    r = sd_bus_message_append(m, "s", "n/a") ;
+    r = sd_bus_message_close_container(m) ;
+    r = sd_bus_message_close_container(m) ;
+
+    return r ;
+}
diff --git a/src/66-dbus-launch/policy.h b/src/66-dbus-launch/policy.h
new file mode 100644
index 0000000000000000000000000000000000000000..869e8e90e7eff49b6384710fea88ad6c2820a555
--- /dev/null
+++ b/src/66-dbus-launch/policy.h
@@ -0,0 +1,38 @@
+/*
+ * policy.h
+ *
+ * Copyright (c) 2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#ifndef DBS_POLICY_H_INCLUDE
+#define DBS_POLICY_H_INCLUDE
+
+#include "dbus.h"
+
+#define POLICY_T_BATCH                                                          \
+                "bt"                                                            \
+                "a(btbs)"                                                       \
+                "a(btssssuutt)"                                                 \
+                "a(btssssuutt)"
+
+#define POLICY_T                                                                \
+                "a(u(" POLICY_T_BATCH "))"                                      \
+                "a(buu(" POLICY_T_BATCH "))"                                    \
+                "a(ss)"                                                         \
+                "b"                                                             \
+                "s"
+
+#define POLICY_PRIORITY_DEFAULT (UINT64_C(1))
+
+extern int policy(sd_bus_message *m);
+
+#endif
+
diff --git a/src/66-dbus-launch/service.c b/src/66-dbus-launch/service.c
new file mode 100644
index 0000000000000000000000000000000000000000..384009988b88e6d88a303d954647f212eb3caa06
--- /dev/null
+++ b/src/66-dbus-launch/service.c
@@ -0,0 +1,574 @@
+/*
+ * service.c
+ *
+ * Copyright (c) 2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "launcher.h"
+#include "service.h"
+#include "dbus.h"
+#include "util.h"
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+#include <oblibs/sastr.h>
+#include <oblibs/stack.h>
+#include <oblibs/environ.h>
+#include <oblibs/files.h>
+#include <oblibs/types.h>
+
+#include <skalibs/types.h>
+
+#include <66/hash.h>
+#include <66/utils.h>
+#include <66/config.h>
+#include <66/constants.h>
+
+#include <66-tools/config.h>
+
+void service_hash_free(struct service_s **hservice)
+{
+	log_flow() ;
+
+	struct service_s *c, *tmp ;
+	HASH_ITER(hh, *hservice, c, tmp) {
+		HASH_DEL(*hservice, c) ;
+		free(c) ;
+	}
+}
+
+struct service_s *service_search_byname(struct service_s **hservice, const char *name)
+{
+	log_flow() ;
+
+	struct service_s *h ;
+	HASH_FIND_STR(*hservice, name, h) ;
+	return h ;
+}
+
+struct service_s *service_search_byid(struct service_s **hservice, int id)
+{
+	log_flow() ;
+
+	struct service_s *c, *tmp ;
+
+	HASH_ITER(hh, *hservice, c, tmp)
+		if (c->id == id)
+			return c ;
+
+	return NULL ;
+}
+
+int service_get_list(stralloc *sa, launcher_t *launcher)
+{
+	log_flow() ;
+
+	char const *exclude[1] = { 0 } ;
+	const char *path = 0 ;
+
+	if (launcher->uid > 0) {
+		path = SS_TOOLS_DBS_SESSION_SERVICE ;
+	} else {
+		path = SS_TOOLS_DBS_SYSTEM_SERVICE ;
+	}
+
+	if (!sastr_dir_get(sa, path, exclude, S_IFREG))
+        log_warnu_return(DBS_EXIT_FATAL, "get services from: ", path) ;
+
+	return 1 ;
+}
+
+void service_add_hash(launcher_t *launcher, struct service_s *service)
+{
+	log_flow() ;
+
+	struct service_s *h = service_search_byname(launcher->hservice, service->name) ;
+
+	char *name __attribute__((unused)) = service->name ;
+
+	if (h == NULL) {
+		service->state = 0 ;
+		FLAGS_SET(service->state, DBS_SERVICE_INSERT) ;
+		service->id = launcher->nservice++ ;
+		HASH_ADD_STR(*launcher->hservice, name, service) ;
+	}
+}
+
+void service_remove_hash(launcher_t *launcher, const char *name)
+{
+	log_flow() ;
+
+	struct service_s *h = service_search_byname(launcher->hservice, name) ;
+
+	if (h != NULL) {
+		HASH_DEL(*launcher->hservice, h) ;
+		free(h) ;
+	}
+}
+
+int service_environ_file_name(char *store, launcher_t *launcher)
+{
+	log_flow() ;
+
+	if (launcher->uid > 0) {
+
+		if (!set_ownerhome_stack_byuid(store, launcher->uid))
+			log_warnusys_return(DBS_EXIT_WARN, "set home directory") ;
+
+		auto_string_builder(store, strlen(store), (char const *[]){ SS_ENVIRONMENT_USERDIR, DBS_ENVIRONMENTFILE, NULL }) ;
+
+	} else {
+
+		auto_strings(store, SS_ENVIRONMENT_ADMDIR, DBS_ENVIRONMENTFILE) ;
+	}
+
+	return 1 ;
+}
+
+int service_parse(struct service_s *service, const char *path)
+{
+	log_flow() ;
+
+	/** We cannot use the environ_parse_file directly
+	 * due of the section [D-BUS Service] at start of the file.
+	 * Hack it commenting it. */
+	ssize_t len = file_get_size(path) ;
+	size_t pos = 0 ;
+	_alloc_stk_(file, len + 1) ;
+	_alloc_stk_(contents, len + 1) ;
+
+	log_trace("parsing service: ", path) ;
+
+	if (!stack_read_file(&file, path))
+		log_warnu_return(DBS_EXIT_WARN, "read file: ", path) ;
+
+	size_t seclen = str_contain(file.s, DBS_SERVICE_SECTION) ;
+	if (seclen < 0)
+		log_warnu_return(DBS_EXIT_WARN, "get section " DBS_SERVICE_SECTION) ;
+
+	seclen++ ; // remove '\n' character
+
+	if (!environ_trim(&contents, file.s + seclen))
+		log_warnu_return(DBS_EXIT_WARN, "trim environment file: ", path) ;
+
+	FOREACH_STK(&contents, pos) {
+
+		char *line = contents.s + pos ;
+
+		_alloc_stk_(key, strlen(line) + 1) ;
+		_alloc_stk_(val, strlen(line) + 1) ;
+
+		if (!environ_get_key(&key, line))
+			log_warnu_return(DBS_EXIT_WARN, "get key from line: ", line, " at file: ", path) ;
+
+		if (!environ_get_value(&val, line))
+			log_warnu_return(DBS_EXIT_WARN, "get value from line: ", line, " at file: ", path) ;
+
+		if (!strcmp(key.s, "Name")) {
+			auto_strings(service->name, val.s) ;
+		} else if (!strcmp(key.s, "Exec")) {
+			auto_strings(service->exec, val.s) ;
+		} else if (!strcmp(key.s, "User")) {
+			auto_strings(service->user, val.s) ;
+		}
+	}
+	return 1 ;
+}
+
+int service_frontend_path(char *store, launcher_t *launcher, const char *service)
+{
+	if (launcher->uid > 0) {
+
+		if (!set_ownerhome_stack_byuid(store, launcher->uid))
+			log_warnu_return(DBS_EXIT_WARN, "set home directory") ;
+
+		auto_string_builder(store, strlen(store), (char const *[]){ SS_SERVICE_USERDIR, service, DBS_SERVICE_SUFFIX, NULL}) ;
+
+	} else {
+
+		auto_strings(store, SS_SERVICE_ADMDIR, service, DBS_SERVICE_SUFFIX) ;
+	}
+
+	return 1 ;
+}
+
+int service_resolve_path(char *store, launcher_t *launcher, const char *service)
+{
+	if (launcher->uid > 0) {
+
+		if (!set_ownerhome_stack_byuid(store, launcher->uid))
+			log_warnu_return(DBS_EXIT_WARN, "set home directory") ;
+
+		auto_string_builder(store, strlen(store), (char const *[]){ SS_USER_DIR, SS_SYSTEM, SS_RESOLVE, SS_SERVICE, service, DBS_SERVICE_SUFFIX, NULL}) ;
+
+	} else {
+
+		auto_strings(store, SS_SYSTEM_DIR, SS_SYSTEM, SS_RESOLVE, SS_SERVICE, service, DBS_SERVICE_SUFFIX) ;
+	}
+
+	return 1 ;
+}
+
+int service_write_frontend(launcher_t *launcher, struct service_s *service)
+{
+	log_flow() ;
+
+	_alloc_sa_(sa) ;
+
+	char efile[SS_MAX_PATH_LEN + strlen(SS_ENVIRONMENT_USERDIR) + DBS_ENVIRONMENTFILE_LEN + 1] ;
+	const char *suid = 0 ;
+
+	if (launcher->uid) {
+		suid = "user" ;
+	} else {
+		suid = "root" ;
+	}
+
+	if (!service_environ_file_name(efile, launcher))
+		log_warnu_return(DBS_EXIT_WARN, "get environment file path") ;
+
+	if (!auto_stra(&sa,
+		"[Main]\n",
+		"Type = classic\n",
+		"Description = \"", service->name, " dbus service\"\n",
+		"User = ( ", suid, " )\n",
+		"Version = 0.0.1\n",
+		"InTree = dbus\n",
+		"MaxDeath = 5\n"
+		"TimeoutStart = 3000\n",
+		"TimeoutStop = 3000\n\n",
+		"[Start]\n"))
+
+	if (*service->user) {
+		if (!auto_stra(&sa, "RunAs = ", service->user,"\n"))
+			log_warnu_return(DBS_EXIT_FATAL, "stralloc") ;
+	}
+
+	if (!auto_stra(&sa, "Execute = (\n",
+		"	execl-envfile -l ${ImportFile}\n",
+		"	", service->exec, "\n",
+		")\n\n",
+		"[Environment]\n",
+		"ImportFile=", efile, "\n"))
+			log_warnu_return(DBS_EXIT_FATAL, "stralloc") ;
+
+	if (!service_frontend_path(service->frontend, launcher, service->name))
+		log_warnu_return(DBS_EXIT_WARN, "get frontend service file of service: ", service->name) ;
+
+	log_trace("write frontend file: ", service->frontend) ;
+	if (!file_write_unsafe_g(service->frontend, sa.s))
+		log_warnu_return(DBS_EXIT_WARN, "write file: ", service->frontend) ;
+
+	return 1 ;
+}
+
+int service_translate(launcher_t *launcher, const char *name)
+{
+	log_flow() ;
+
+	int r ;
+	const char *path = 0 ;
+
+	if (launcher->uid > 0) {
+		path = SS_TOOLS_DBS_SESSION_SERVICE ;
+	} else {
+		path = SS_TOOLS_DBS_SYSTEM_SERVICE ;
+	}
+
+	_alloc_stk_(file, strlen(path) + strlen(name) + 1) ;
+	auto_strings(file.s, path, name) ;
+
+	struct service_s *service ;
+	service = (struct service_s *)malloc(sizeof(*service)) ;
+	if (service == NULL)
+		log_warnu_return(DBS_EXIT_FATAL, "malloc") ;
+
+	memset(service, 0, sizeof(*service)) ;
+
+	r = service_parse(service, file.s) ;
+	if (!r)
+		log_warnu_return(DBS_EXIT_WARN, "parse service: ", file.s) ;
+
+	if (!*service->name || !*service->exec)
+		log_warnu_return(DBS_EXIT_FATAL, "missing mandatory field at file: ", file.s) ;
+
+	r = service_write_frontend(launcher, service) ;
+	if (!r)
+		log_warnu_return(DBS_EXIT_FATAL, "write frontend file of service: ", service->name) ;
+
+	service_add_hash(launcher, service) ;
+
+	return 1 ;
+}
+
+int service_load(launcher_t *launcher)
+{
+	log_flow() ;
+
+	int r ;
+	size_t pos = 0 ;
+	_alloc_sa_(sa) ;
+
+	if (service_get_list(&sa, launcher) < 0)
+		return DBS_EXIT_FATAL ;
+
+	FOREACH_SASTR(&sa, pos) {
+
+		r = service_translate(launcher, sa.s + pos) ;
+		if (r == DBS_EXIT_FATAL)
+			return r ;
+	}
+
+	return 1 ;
+}
+
+void service_handle_state(stralloc *list, launcher_t *launcher)
+{
+	log_flow() ;
+
+	size_t pos = 0 ;
+	struct service_s *hash ;
+	struct service_s *c, *tmp ;
+
+	/** compare for service to add */
+	FOREACH_SASTR(list, pos) {
+
+		size_t len = strlen(list->s + pos) ;
+		_alloc_stk_(name, len) ;
+		ssize_t r = get_rlen_until(list->s + pos, '.', len) ;
+
+		if (r < 0){
+			log_warn("invalid D-Bus service file name: ", list->s + pos) ;
+			continue ;
+		}
+		auto_strings(name.s, list->s + pos) ;
+		name.s[r] = 0 ;
+
+		hash = service_search_byname(launcher->hservice, name.s) ;
+
+		if (hash == NULL) {
+			/** Nothing to do with the exit code */
+			service_translate(launcher, name.s) ;
+		} else {
+			FLAGS_SET(hash->state, DBS_SERVICE_PARSE) ;
+		}
+	}
+
+	/** compare for service to remove */
+	HASH_ITER(hh, *launcher->hservice, c, tmp) {
+
+		size_t len = strlen(c->name) ;
+		_alloc_stk_(name, len + 9) ;
+		auto_strings(name.s, c->name, ".service") ;
+
+		if (sastr_cmp(list, name.s) < 0) {
+			c->state = 0 ;
+			FLAGS_SET(c->state, DBS_SERVICE_DELETE) ;
+		} else {
+			FLAGS_SET(c->state, DBS_SERVICE_OK) ;
+		}
+	}
+}
+
+void service_sync_launcher_broker(launcher_t *launcher)
+{
+	log_flow() ;
+
+	int r;
+	struct service_s *c, *tmp ;
+
+	HASH_ITER(hh, *launcher->hservice, c, tmp) {
+
+		if (FLAGS_ISSET(c->state, DBS_SERVICE_OK)) {
+
+			if (FLAGS_ISSET(c->state, DBS_SERVICE_PARSE))
+				service_reactivate(c) ;
+			continue ;
+		}
+
+		char fmt[SIZE_FMT] ;
+		size_t ilen = size_fmt(fmt, c->id) ;
+		fmt[ilen] = 0 ;
+		_alloc_stk_(path, strlen("/org/bus1/DBus/Name/") + ilen + 1) ;
+		auto_strings(path.s, "/org/bus1/DBus/Name/", fmt) ;
+
+		if (FLAGS_ISSET(c->state, DBS_SERVICE_INSERT)) {
+
+			r = sd_bus_call_method(launcher->bus_controller, NULL, "/org/bus1/DBus/Broker", "org.bus1.DBus.Broker", "AddName", NULL, NULL, "osu", path.s, c->name, 0) ;
+			if (r < 0) {
+				errno = -r ;
+				log_warnusys("org.bus1.DBus.AddName") ;
+				continue ;
+			}
+
+			log_info("add service name: ", c->name, " (", path.s, ")") ;
+
+			if (FLAGS_ISSET(c->state, DBS_SERVICE_PARSE))
+				service_reactivate(c) ;
+
+			c->state = 0 ;
+			FLAGS_SET(c->state, DBS_SERVICE_OK) ;
+
+		} else if (FLAGS_ISSET(c->state, DBS_SERVICE_DELETE)) {
+
+			r = sd_bus_call_method(launcher->bus_controller, NULL, path.s, "org.bus1.DBus.Name", "Release", NULL, NULL, "") ;
+			if (r < 0) {
+				errno = -r ;
+				log_warnusys("org.bus1.DBus.Name.Release") ;
+				continue ;
+			}
+
+			log_info( "freed service: ", c->name, " (", path.s, ")") ;
+
+			service_discard(launcher, c) ;
+
+		} else {
+			/* unreachable */
+			char fmt[UINT_FMT] ;
+			fmt[uint_fmt(fmt, c->state)] = 0 ;
+			log_warn("bug: service ", c->name, " (", path.s, ") in invalid state ", fmt);
+		}
+	}
+
+	log_info("service selection synchronized successfully") ;
+}
+
+int service_reload(launcher_t *launcher)
+{
+	log_flow() ;
+
+	_alloc_sa_(sa) ;
+
+	service_get_list(&sa, launcher) ;
+
+	service_handle_state(&sa, launcher) ;
+
+	service_sync_launcher_broker(launcher) ;
+
+	return 1 ;
+}
+
+int service_activate(launcher_t *launcher, int id)
+{
+	log_flow() ;
+
+	struct service_s *s = service_search_byid(launcher->hservice, id) ;
+
+	_alloc_stk_(name, strlen(s->name) + DBS_SERVICE_SUFFIX_LEN) ;
+	auto_strings(name.s, s->name, DBS_SERVICE_SUFFIX) ;
+
+	char fmt[INT_FMT] ;
+	fmt[int_fmt(fmt, VERBOSITY)] = 0 ;
+
+	log_info("activation requested for service: ", name.s) ;
+
+	if (s) {
+
+		char *nargv[] = {
+			"66",
+			"-v",
+			fmt,
+			"start",
+			name.s,
+			0
+		} ;
+
+		return sync_spawn(nargv) ;
+	}
+	log_warnu_return(DBS_EXIT_FATAL, "find service: ", name.s, " -- ignoring activation request") ;
+}
+
+int service_reactivate(struct service_s *service)
+{
+	log_flow() ;
+
+	_alloc_stk_(name, strlen(service->name) + DBS_SERVICE_SUFFIX_LEN) ;
+	auto_strings(name.s, service->name, DBS_SERVICE_SUFFIX) ;
+
+	char fmt[INT_FMT] ;
+	fmt[int_fmt(fmt, VERBOSITY)] = 0 ;
+
+	log_info("reactivation requested for service: ", name.s) ;
+
+	char *nargv[] = {
+		"66",
+		"-v",
+		fmt,
+		"parse",
+		"-f",
+		name.s,
+		0
+	} ;
+
+	return sync_spawn(nargv) ;
+}
+
+int service_deactivate(struct service_s *service)
+{
+	log_flow() ;
+
+	_alloc_stk_(name, strlen(service->name) + DBS_SERVICE_SUFFIX_LEN) ;
+	auto_strings(name.s, service->name, DBS_SERVICE_SUFFIX) ;
+
+	char fmt[INT_FMT] ;
+	fmt[int_fmt(fmt, VERBOSITY)] = 0 ;
+
+	log_info("deactivation requested for service: ", name.s) ;
+
+	char *nargv[] = {
+		"66",
+		"-v",
+		fmt,
+		"remove",
+		name.s,
+		0
+	} ;
+
+	return sync_spawn(nargv) ;
+}
+
+void service_discard(launcher_t *launcher, struct service_s *service)
+{
+	log_flow() ;
+
+	/** nothing to do with the exit code,
+	 * we are on stop process */
+	service_deactivate(service) ;
+	unlink(service->frontend) ;
+	service_remove_hash(launcher, service->name) ;
+}
+
+void service_discard_tree(void)
+{
+	log_flow() ;
+
+	char fmt[INT_FMT] ;
+	fmt[int_fmt(fmt, VERBOSITY)] = 0 ;
+
+	char *nargv[] = {
+		"66",
+		"-T3000",
+		"-v",
+		fmt,
+		"tree",
+		"free",
+		"dbus",
+		0
+	} ;
+
+	sync_spawn(nargv) ;
+}
\ No newline at end of file
diff --git a/src/66-dbus-launch/service.h b/src/66-dbus-launch/service.h
new file mode 100644
index 0000000000000000000000000000000000000000..54f752a15aff873ecaf27ad9fbfdadec43c553e8
--- /dev/null
+++ b/src/66-dbus-launch/service.h
@@ -0,0 +1,83 @@
+/*
+ * service.h
+ *
+ * Copyright (c) 2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#ifndef DBS_SERVICE_H_INCLUDE
+#define DBS_SERVICE_H_INCLUDE
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "launcher.h"
+
+#include <skalibs/stralloc.h>
+
+#include <66/hash.h>
+#include <66/constants.h>
+#include <66/config.h>
+
+#define DBS_ENVIRONMENTFILE "0000-dbus"
+#define DBS_ENVIRONMENTFILE_LEN (sizeof DBS_ENVIRONMENTFILE - 1)
+#define DBS_SERVICE_SUFFIX ".dbus"
+#define DBS_SERVICE_SUFFIX_LEN (sizeof DBS_SERVICE_SUFFIX - 1)
+#define DBS_SERVICE_SECTION "[D-BUS Service]"
+#define DBS_SERVICE_SECTION_LEN (sizeof DBS_SERVICE_SECTION - 1)
+
+#define DBS_SERVICE_OK (1 << 1)
+#define DBS_SERVICE_INSERT (1 << 2)
+#define DBS_SERVICE_PARSE (1 << 3)
+#define DBS_SERVICE_DELETE (1 << 4)
+
+struct service_s {
+	char name[SS_MAX_SERVICE_NAME + 1] ;
+	char exec[1024 + 1] ;
+	char user[1024 + 1] ;
+	char frontend[SS_MAX_PATH_LEN + 1] ;
+	size_t id ;
+	uint8_t state ;
+	UT_hash_handle hh ;
+} ;
+
+#define SERVICE_ZERO { {0}, {0}, {0}, {0}, 0, 0, NULL }
+
+extern void service_hash_free(struct service_s **hservice) ;
+extern struct service_s *service_search_byname(struct service_s **hservice, const char *name) ;
+extern struct service_s *service_search_byid(struct service_s **hservice, int id) ;
+extern int service_get_list(stralloc *sa, launcher_t *launcher) ;
+extern void service_add_hash(launcher_t *launcher, struct service_s *service) ;
+extern void service_remove_hash(launcher_t *launcher, const char *name) ;
+extern int service_environ_owner_path(char *store, launcher_t *launcher) ;
+extern int service_environ_file_name(char *store, launcher_t *launcher) ;
+extern int service_parse(struct service_s *service, const char *path) ;
+extern int service_frontend_path(char *store, launcher_t *launcher, const char *service) ;
+extern int service_resolve_path(char *store, launcher_t *launcher, const char *service) ;
+extern int service_write_frontend(launcher_t *launcher, struct service_s *service) ;
+extern int service_translate(launcher_t *launcher, const char *name) ;
+extern int service_load(launcher_t *launcher) ;
+extern void service_handle_state(stralloc *sa, launcher_t *launcher) ;
+extern void service_sync_launcher_broker(launcher_t *launcher) ;
+extern int service_reload(launcher_t *launcher) ;
+extern int service_activate(launcher_t *launcher, int id) ;
+extern int service_reactivate(struct service_s *service) ;
+extern int service_deactivate(struct service_s *service) ;
+extern void service_discard(launcher_t *launcher, struct service_s *service) ;
+extern void service_discard_tree(void) ;
+
+
+
+
+
+
+
+#endif
+
diff --git a/src/66-dbus-launch/util.c b/src/66-dbus-launch/util.c
new file mode 100644
index 0000000000000000000000000000000000000000..8ead50d1cf7db5e24ede2e00632b0c3b443fd82e
--- /dev/null
+++ b/src/66-dbus-launch/util.c
@@ -0,0 +1,140 @@
+/*
+ * util.c
+ *
+ * Copyright (c) 2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <spawn.h>
+#include <signal.h>
+#include <stddef.h>
+
+#include "launcher.h"
+#include "service.h"
+
+#include <oblibs/log.h>
+
+#include <skalibs/selfpipe.h>
+#include <skalibs/djbunix.h>
+
+extern char **environ;
+
+int fdmove(int to, int from) {
+
+	log_flow() ;
+
+	int r ;
+	if (to == from) return 0 ;
+	do r = dup2(from, to) ;
+	while ((r == -1) && (errno == EINTR)) ;
+	if (r < 0) return r ;
+	close(from) ;
+	return 0 ;
+}
+
+/**
+ * make a proper environment
+ *
+*/
+
+pid_t async_spawn(char **cmd)
+{
+	log_flow() ;
+	pid_t p ;
+	if ((errno = posix_spawnp(&p, cmd[0], NULL, NULL, cmd, environ)))
+		return 0 ;
+	return p ;
+}
+
+int spawn_wait(pid_t p)
+{
+	log_flow() ;
+
+	int r, wstat ;
+
+	do r = waitpid(p, &wstat, 0) ;
+	while (r < 0 && errno == EINTR) ;
+
+	if (r < 0)
+		return DBS_EXIT_FATAL ;
+
+	if (WIFEXITED(wstat) && WEXITSTATUS(wstat) == 0)
+		return 0 ;
+	else
+		return WIFSIGNALED(wstat) ? 128 + WTERMSIG(wstat) : WEXITSTATUS(wstat) ;
+
+}
+
+int sync_spawn(char **cmd)
+{
+	log_flow() ;
+
+	pid_t p = async_spawn(cmd) ;
+	if (p == 0)
+		return DBS_EXIT_FATAL ;
+
+	return spawn_wait(p) ;
+}
+
+static int compute_exit(int wstat)
+{
+	log_flow() ;
+
+    if (WIFEXITED(wstat) && WEXITSTATUS(wstat) == 0)
+        return DBS_EXIT_MAIN ;
+
+    return WIFSIGNALED(wstat) ? 128 + WTERMSIG(wstat) : WEXITSTATUS(wstat) ;
+}
+
+int handle_signal(launcher_t *launcher, pid_t ppid)
+{
+	int ok = DBS_EXIT_MAIN, wstat ;
+	pid_t cpid ;
+
+    for (;;) {
+		int r = selfpipe_read() ;
+
+		switch (r) {
+
+            case -1 : log_dieusys(LOG_EXIT_ZERO, "selfpipe_read") ;
+            case 0 : return DBS_EXIT_MAIN ;
+			case SIGHUP:
+				log_info("caught SIGHUP signal, reloading services and configuration") ;
+				service_reload(launcher) ;
+				return DBS_EXIT_CHILD ;
+			case SIGTERM:
+            case SIGINT:
+            case SIGQUIT:
+				return DBS_EXIT_MAIN ;
+            case SIGCHLD:
+				/** We can have multiple pid as long as we spawn
+				 * a process to start a service. */
+				for (;;) {
+
+					cpid = wait_nohang(&wstat) ;
+
+					if (cpid < 0) {
+						if (errno == ECHILD) break ;
+						else log_warnusys_return(DBS_EXIT_FATAL,"wait for children") ;
+					} else if (!cpid) return DBS_EXIT_CHILD ;
+
+					/** launcher */
+					if (cpid == ppid)
+						return compute_exit(wstat) ;
+				}
+                break ;
+			default : log_warn("unexpected data in selfpipe") ; return DBS_EXIT_WARN ;
+		}
+    }
+
+    return ok ;
+}
diff --git a/src/66-dbus-launch/util.h b/src/66-dbus-launch/util.h
new file mode 100644
index 0000000000000000000000000000000000000000..b0504dfd8a730e5130b0b4755d3cf4cd9951a2c2
--- /dev/null
+++ b/src/66-dbus-launch/util.h
@@ -0,0 +1,29 @@
+/*
+ * util.h
+ *
+ * Copyright (c) 2024 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#ifndef DBS_UTILS_H_INCLUDE
+#define DBS_UTILS_H_INCLUDE
+
+#include <sys/types.h>
+
+#include "launcher.h"
+
+extern int fdmove(int to, int from) ;
+extern pid_t async_spawn(char **cmd) ;
+extern int spawn_wait(pid_t p) ;
+extern int sync_spawn(char **cmd) ;
+extern int handle_signal(launcher_t *launcher, pid_t ppid) ;
+
+#endif
+
diff --git a/src/66-tools/66-getenv.c b/src/66-getenv/66-getenv.c
similarity index 100%
rename from src/66-tools/66-getenv.c
rename to src/66-getenv/66-getenv.c
diff --git a/src/66-tools/deps-exe/66-getenv b/src/66-getenv/deps-exe/66-getenv
similarity index 100%
rename from src/66-tools/deps-exe/66-getenv
rename to src/66-getenv/deps-exe/66-getenv
diff --git a/src/66-tools/66-gnwenv.c b/src/66-gnwenv/66-gnwenv.c
similarity index 99%
rename from src/66-tools/66-gnwenv.c
rename to src/66-gnwenv/66-gnwenv.c
index a1e3e45216be01ddda0c6d076cbd93f2e6f874fb..e75a723b6de09b629553e11421c53d78d0713b56 100644
--- a/src/66-tools/66-gnwenv.c
+++ b/src/66-gnwenv/66-gnwenv.c
@@ -147,6 +147,3 @@ int main (int argc, char const *const *argv, char const *const *envp)
 
     xmexec_f (newargv, v, r) ;
 }
-
-
-
diff --git a/src/66-tools/deps-exe/66-gnwenv b/src/66-gnwenv/deps-exe/66-gnwenv
similarity index 100%
rename from src/66-tools/deps-exe/66-gnwenv
rename to src/66-gnwenv/deps-exe/66-gnwenv
diff --git a/src/66-tools/66-ns.c b/src/66-ns/66-ns.c
similarity index 100%
rename from src/66-tools/66-ns.c
rename to src/66-ns/66-ns.c
diff --git a/src/66-tools/deps-exe/66-ns b/src/66-ns/deps-exe/66-ns
similarity index 100%
rename from src/66-tools/deps-exe/66-ns
rename to src/66-ns/deps-exe/66-ns
diff --git a/src/66-tools/66-olexec.c b/src/66-olexec/66-olexec.c
similarity index 100%
rename from src/66-tools/66-olexec.c
rename to src/66-olexec/66-olexec.c
diff --git a/src/66-tools/deps-exe/66-olexec b/src/66-olexec/deps-exe/66-olexec
similarity index 100%
rename from src/66-tools/deps-exe/66-olexec
rename to src/66-olexec/deps-exe/66-olexec
diff --git a/src/66-tools/66-which.c b/src/66-which/66-which.c
similarity index 100%
rename from src/66-tools/66-which.c
rename to src/66-which/66-which.c
diff --git a/src/66-tools/deps-exe/66-which b/src/66-which/deps-exe/66-which
similarity index 100%
rename from src/66-tools/deps-exe/66-which
rename to src/66-which/deps-exe/66-which
diff --git a/src/66-tools/66-writenv.c b/src/66-writenv/66-writenv.c
similarity index 100%
rename from src/66-tools/66-writenv.c
rename to src/66-writenv/66-writenv.c
diff --git a/src/66-tools/deps-exe/66-writenv b/src/66-writenv/deps-exe/66-writenv
similarity index 100%
rename from src/66-tools/deps-exe/66-writenv
rename to src/66-writenv/deps-exe/66-writenv
diff --git a/src/66-tools/66-yeller.c b/src/66-yeller/66-yeller.c
similarity index 100%
rename from src/66-tools/66-yeller.c
rename to src/66-yeller/66-yeller.c
diff --git a/src/66-tools/deps-exe/66-yeller b/src/66-yeller/deps-exe/66-yeller
similarity index 100%
rename from src/66-tools/deps-exe/66-yeller
rename to src/66-yeller/deps-exe/66-yeller
diff --git a/src/66-tools/deps-exe/execl-cmdline b/src/execl-cmdline/deps-exe/execl-cmdline
similarity index 100%
rename from src/66-tools/deps-exe/execl-cmdline
rename to src/execl-cmdline/deps-exe/execl-cmdline
diff --git a/src/66-tools/execl-cmdline.c b/src/execl-cmdline/execl-cmdline.c
similarity index 100%
rename from src/66-tools/execl-cmdline.c
rename to src/execl-cmdline/execl-cmdline.c
diff --git a/src/66-tools/deps-exe/execl-subuidgid b/src/execl-subuidgid/deps-exe/execl-subuidgid
similarity index 66%
rename from src/66-tools/deps-exe/execl-subuidgid
rename to src/execl-subuidgid/deps-exe/execl-subuidgid
index 5cc2d0d427f119f144618797d709a4f8582e24af..18e65f48bab6f524c217e6c7e81e6f5953d27e7f 100644
--- a/src/66-tools/deps-exe/execl-subuidgid
+++ b/src/execl-subuidgid/deps-exe/execl-subuidgid
@@ -1,4 +1,3 @@
 -loblibs
 -lexecline
 -lskarnet
-${LIBEXECLINE}
diff --git a/src/66-tools/execl-subuidgid.c b/src/execl-subuidgid/execl-subuidgid.c
similarity index 100%
rename from src/66-tools/execl-subuidgid.c
rename to src/execl-subuidgid/execl-subuidgid.c
diff --git a/src/66-tools/deps-exe/execl-toc b/src/execl-toc/deps-exe/execl-toc
similarity index 68%
rename from src/66-tools/deps-exe/execl-toc
rename to src/execl-toc/deps-exe/execl-toc
index 0a747e65ed5eebf7d606c8da7461147709baa6b7..18e65f48bab6f524c217e6c7e81e6f5953d27e7f 100644
--- a/src/66-tools/deps-exe/execl-toc
+++ b/src/execl-toc/deps-exe/execl-toc
@@ -1,4 +1,3 @@
 -loblibs
 -lexecline
 -lskarnet
-${LIBEXECLINE}
\ No newline at end of file
diff --git a/src/66-tools/execl-toc.c b/src/execl-toc/execl-toc.c
similarity index 100%
rename from src/66-tools/execl-toc.c
rename to src/execl-toc/execl-toc.c
diff --git a/tools/gen-deps.sh b/tools/gen-deps.sh
index 7601b5db576203597bccf73f43a7191a8fbf0379..831d991030d980544afaa4dfb6d393af19fb7a5c 100755
--- a/tools/gen-deps.sh
+++ b/tools/gen-deps.sh
@@ -7,7 +7,10 @@ echo '# This file has been generated by tools/gen-deps.sh'
 echo '#'
 echo
 
+internal_libs=
+
 for dir in src/include/${package} src/* ; do
+
   for file in $(ls -1 $dir | grep -- \\.h$) ; do
     {
       grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ;
@@ -23,11 +26,19 @@ for dir in src/include/${package} src/* ; do
           deps="$deps src/include-local/$dep"
         fi
       done
+      dbus=$(echo ${dir} | cut -d '/' -f2)
+      if test ${dbus} = "66-dbus-launch"; then
+        echo 'ifneq ($(strip $(DBUS_IMPL)),)'
+      fi
       if test -n "$deps" ; then
         echo "${dir}/${file}:${deps}"
       fi
+      if test ${dbus} = "66-dbus-launch"; then
+        echo 'endif'
+      fi
     }
   done
+
 done
 
 for dir in src/* ; do
@@ -46,12 +57,20 @@ for dir in src/* ; do
           deps="$deps src/include-local/$dep"
         fi
       done
+      dbus=$(echo ${dir} | cut -d '/' -f2)
+      if test ${dbus} = "66-dbus-launch"; then
+        echo 'ifneq ($(strip $(DBUS_IMPL)),)'
+      fi
       o=$(echo $file | sed s/\\.c$/.o/)
       lo=$(echo $file | sed s/\\.c$/.lo/)
       echo "${dir}/${o} ${dir}/${lo}:${deps}"
+      if test ${dbus} = "66-dbus-launch"; then
+        echo 'endif'
+      fi
     }
   done
 done
+echo
 
 for dir in $(ls -1 src | grep -v ^include) ; do
   for file in $(ls -1 src/$dir/deps-lib) ; do
@@ -64,13 +83,25 @@ for dir in $(ls -1 src | grep -v ^include) ; do
         deps="$deps src/$dir/$dep"
       fi
     done < src/$dir/deps-lib/$file
+    dbus=$(echo ${dir} | cut -d '/' -f2)
+      if test ${dbus} = "66-dbus-launch"; then
+        echo 'ifneq ($(strip $(DBUS_IMPL)),)'
+      fi
     echo 'ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)'
     echo "lib${file}.a.xyzzy:$deps"
     echo else
     echo "lib${file}.a.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')"
     echo endif
-    echo "lib${file}.so.xyzzy: EXTRA_LIBS :=$libs"
-    echo "lib${file}.so.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')"
+    if grep -E "^LIB_DEFS [+:]=" package/targets.mak | grep -qF "$file" ; then
+      echo "lib${file}.so.xyzzy: EXTRA_LIBS :=$libs"
+      echo "lib${file}.so.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')"
+    else
+      internal_libs="$internal_libs lib${file}.a.xyzzy"
+    fi
+    dbus=$(echo ${dir} | cut -d '/' -f2)
+      if test ${dbus} = "66-dbus-launch"; then
+        echo 'endif'
+      fi
   done
 
   for file in $(ls -1 src/$dir/deps-exe) ; do
@@ -86,7 +117,16 @@ for dir in $(ls -1 src | grep -v ^include) ; do
         deps="$deps $dep"
       fi
     done < src/$dir/deps-exe/$file
+    dbus=$(echo ${dir} | cut -d '/' -f2)
+    if test ${dbus} = "66-dbus-launch"; then
+      echo 'ifneq ($(strip $(DBUS_IMPL)),)'
+    fi
     echo "$file: EXTRA_LIBS :=$libs"
     echo "$file: src/$dir/$file.o$deps"
+    dbus=$(echo ${dir} | cut -d '/' -f2)
+    if test ${dbus} = "66-dbus-launch"; then
+      echo 'endif'
+    fi
   done
 done
+echo "INTERNAL_LIBS :=$internal_libs"
diff --git a/tools/install.sh b/tools/install.sh
index 89f94289129eb8afb5a25c7d41a4a23566ae2983..e96dd7b7796925d9a9ae319c1fe76a2fa62bef44 100755
--- a/tools/install.sh
+++ b/tools/install.sh
@@ -1,19 +1,21 @@
 #!/bin/sh
 
 usage() {
-  echo "usage: $0 [-D] [-l] [-m mode] src dst" 1>&2
+  echo "usage: $0 [ -D ] [ -l ] [ -m mode ] [ -O owner:group ] src dst" 1>&2
   exit 1
 }
 
 mkdirp=false
 symlink=false
 mode=0755
+og=
 
-while getopts Dlm: name ; do
+while getopts Dlm:O: name ; do
   case "$name" in
     D) mkdirp=true ;;
     l) symlink=true ;;
     m) mode=$OPTARG ;;
+    O) og=$OPTARG ;;
     ?) usage ;;
   esac
 done
@@ -46,7 +48,10 @@ if $symlink ; then
   ln -s "$src" "$tmp"
 else
   cat < "$1" > "$tmp"
-  chmod "$mode" "$tmp"
+  if test -n "$og" ; then
+    chown -- "$og" "$tmp"
+  fi
+  chmod -- "$mode" "$tmp"
 fi
 
 mv -f "$tmp" "$dst"