]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
profile: generate shell + command OSC events
authorLennart Poettering <lennart@poettering.net>
Thu, 30 Jan 2025 14:09:21 +0000 (15:09 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 27 Feb 2025 14:13:15 +0000 (15:13 +0100)
meson.build
profile.d/80-systemd-osc-context.sh [new file with mode: 0644]
profile.d/meson.build
tmpfiles.d/20-systemd-osc-context.conf.in [new file with mode: 0644]
tmpfiles.d/meson.build

index e87c8ea2ecdd7b61b38251ae74cea6e599c47f4b..0865c861ecf4dce4c9e784894609066cba1849e1 100644 (file)
@@ -233,6 +233,7 @@ if shellprofiledir == ''
         shellprofiledir = sysconfdir / 'profile.d'
 endif
 conf.set10('LINK_SHELL_EXTRA_DROPIN', shellprofiledir != 'no' and not shellprofiledir.startswith('/usr/'))
+conf.set10('LINK_OSC_CONTEXT_DROPIN', shellprofiledir != 'no' and not shellprofiledir.startswith('/usr/'))
 conf.set('SHELLPROFILEDIR', shellprofiledir, description : 'shell profile directory')
 
 memory_accounting_default = get_option('memory-accounting-default')
diff --git a/profile.d/80-systemd-osc-context.sh b/profile.d/80-systemd-osc-context.sh
new file mode 100644 (file)
index 0000000..59af2e1
--- /dev/null
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# shellcheck shell=bash
+# shellcheck disable=SC2016
+# shellcheck disable=SC1003
+
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+__systemd_osc_context_escape() {
+    # Escape according to the OSC 8003 spec. Since this requires shelling out
+    # to 'sed' we'll only do it where it's strictly necessary, and skip it when
+    # processing strings we are pretty sure we won't need it for, such as
+    # uuids, id128, hostnames, usernames, since they all come with syntax
+    # requirements that exclude \ and ; anyway. This hence primarily is about
+    # escaping the current working directory.
+    echo "$1" | sed -e 's/\\/\\x5x/g' -e 's/;/\\x3b/g'
+}
+
+__systemd_osc_context_common() {
+    printf ";user=%s;hostname=%s;machineid=%s;bootid=%s;pid=%s" "$USER" "$HOSTNAME" "$(</etc/machine-id)" "$(</proc/sys/kernel/random/boot_id)" "$$"
+}
+
+__systemd_osc_context_precmdline() {
+    local systemd_exitstatus="$?"
+
+    # Close previous command
+    if [ -n "${systemd_osc_context_cmd_id:-}" ]; then
+        if [ "$systemd_exitstatus" -ge 127 ]; then
+            printf "\033]8003;end=%s;exit=interrupt;signal=%s\033\\" "$systemd_osc_context_cmd_id" $((systemd_exitstatus-127))
+        elif [ "$systemd_exitstatus" -ne 0 ]; then
+            printf "\033]8003;end=%s;exit=failure;status=%s\033\\" "$systemd_osc_context_cmd_id" $((systemd_exitstatus))
+        else
+            printf "\033]8003;end=%s;exit=success\033\\" "$systemd_osc_context_cmd_id"
+        fi
+    fi
+
+    # Prepare a context ID for this shell if we have none
+    if [ -z "${systemd_osc_context_shell_id:-}" ]; then
+        read -r systemd_osc_context_shell_id </proc/sys/kernel/random/uuid
+    fi
+
+    # Create or update the shell session
+    printf "\033]8003;start=%s%s;type=shell;cwd=%s\033\\" "$systemd_osc_context_shell_id" "$(__systemd_osc_context_common)" "$(__systemd_osc_context_escape "$PWD")"
+
+    # Prepare cmd id for next command
+    read -r systemd_osc_context_cmd_id </proc/sys/kernel/random/uuid
+}
+
+if [[ -n "${BASH_VERSION:-}" ]]; then
+    # Whenever a new prompt is shown close the previous command, and prepare new command
+    PROMPT_COMMAND+=(__systemd_osc_context_precmdline)
+
+    # PS0 is shown right after a prompt completed, but before the command is executed
+    PS0='\033]8003;start=$systemd_osc_context_cmd_id$(__systemd_osc_context_common);type=command;cwd=$(__systemd_osc_context_escape "$PWD")\033\\'"${PS0:-}"
+fi
index b87dc18eaa5aa2dd407a5f7b7a96f42b6a0df800..fa03ed0ab03dfd9e40b2f318d1cce01249352663 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 install_data('70-systemd-shell-extra.sh', install_dir : shellprofiledir.startswith('/usr/') ? shellprofiledir : libexecdir / 'profile.d')
+install_data('80-systemd-osc-context.sh', install_dir : shellprofiledir.startswith('/usr/') ? shellprofiledir : libexecdir / 'profile.d')
 
 if conf.get('LINK_SHELL_EXTRA_DROPIN') == 1
         install_emptydir(shellprofiledir)
@@ -8,3 +9,10 @@ if conf.get('LINK_SHELL_EXTRA_DROPIN') == 1
         meson.add_install_script(sh, '-c',
                 ln_s.format(libexecdir / 'profile.d' / '70-systemd-shell-extra.sh', shellprofiledir / '70-systemd-shell-extra.sh'))
 endif
+
+if conf.get('LINK_OSC_CONTEXT_DROPIN') == 1
+        install_emptydir(shellprofiledir)
+
+        meson.add_install_script(sh, '-c',
+                ln_s.format(libexecdir / 'profile.d' / '80-systemd-osc-context.sh', shellprofiledir / '80-systemd-osc-context.sh'))
+endif
diff --git a/tmpfiles.d/20-systemd-osc-context.conf.in b/tmpfiles.d/20-systemd-osc-context.conf.in
new file mode 100644 (file)
index 0000000..dc39f9a
--- /dev/null
@@ -0,0 +1,12 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+# See tmpfiles.d(5) for details.
+
+{% if LINK_OSC_CONTEXT_DROPIN %}
+L$ {{SHELLPROFILEDIR}}/80-systemd-osc-context.sh - - - - {{LIBEXECDIR}}/profile.d/80-systemd-osc-context.sh
+{% endif %}
index 19eb6d9c990a61b8726856ed1833350251837e28..db58a9817a1b6ea65f7a15fd51506aa3d42f4656 100644 (file)
@@ -31,6 +31,7 @@ endforeach
 
 in_files = [
         ['20-systemd-shell-extra.conf',   'LINK_SHELL_EXTRA_DROPIN'],
+        ['20-systemd-osc-context.conf',   'LINK_OSC_CONTEXT_DROPIN'],
         ['20-systemd-ssh-generator.conf', 'ENABLE_SSH_PROXY_CONFIG'],
         ['20-systemd-stub.conf',          'ENABLE_EFI'],
         ['20-systemd-userdb.conf',        'ENABLE_SSH_USERDB_CONFIG'],