penguin/utils

my env utils

commit 84e8bbc4c566664da694c61a061c689e41ceb9a5

author斟酌 鵬兄 <tgckpg@gmail.com>
date2026-07-20T12:27:39Z
subjectAdded clipboard server
commit 84e8bbc4c566664da694c61a061c689e41ceb9a5
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2026-07-20T12:27:39Z

    Added clipboard server
---
 bash/dist/rbashrc                |  2 +-
 bash/dist/rbashrc.asc            | 10 ++--
 bash/dist/sources.list           |  1 +
 bash/sources/42_clipboard_server | 99 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 106 insertions(+), 6 deletions(-)

diff --git a/bash/dist/rbashrc b/bash/dist/rbashrc
index 43ad6ef..be686c0 100755
--- a/bash/dist/rbashrc
+++ b/bash/dist/rbashrc
@@ -18,7 +18,7 @@ RBASH_CONFIG="$RBASH_HOME/config"
 RBASH_ENV="$RBASH_HOME/env"
 RBASH_MERGED="$RBASH_CACHE_DIR/merged"
 RBASH_BIN="$RBASH_HOME/bin"
-RBASH_SOURCES_SUM="53c4c6eaceb4526d0940873d22ff9978f8eb49d23b6431a5cf814893e086bb23"
+RBASH_SOURCES_SUM="d92990747fccac0f0dff1c9bbfddcb26d592514cbdb5667dd7d96a727eeb99ee"
 
 
 # ---- rbash: bash/core/00_env.bash ----
diff --git a/bash/dist/rbashrc.asc b/bash/dist/rbashrc.asc
index 774203b..2bf3c29 100644
--- a/bash/dist/rbashrc.asc
+++ b/bash/dist/rbashrc.asc
@@ -1,8 +1,8 @@
 -----BEGIN PGP SIGNATURE-----
 
-iJEEABYKADkWIQR8HpSNhBJUxWnt+97Vz1+xz60nwwUCakzH+RsUgAAAAAAEAA5t
-YW51MiwyLjUrMS4xMiwwLDMACgkQ1c9fsc+tJ8OgegD/cmVsnne+vp67XFOigKRB
-jPWPdbROVndkYmG4DyqLKVIA/jocAoCry9fe6hY8Iv8FvWjFViyF1d6oCQ+SY4I/
-qMYB
-=zzsS
+iJEEABYKADkWIQR8HpSNhBJUxWnt+97Vz1+xz60nwwUCal4UHRsUgAAAAAAEAA5t
+YW51MiwyLjUrMS4xMiwwLDMACgkQ1c9fsc+tJ8O4gQD+IQqcafpgcckOfljmR3lO
+xjLOAXsO5McFX6opCBSZgxkA/19heZtnLv3LfhUdzB2hImKf2YnPIOfvEWW5yWpz
+2k4A
+=VxQF
 -----END PGP SIGNATURE-----
diff --git a/bash/dist/sources.list b/bash/dist/sources.list
index 29e7d06..c5f9743 100644
--- a/bash/dist/sources.list
+++ b/bash/dist/sources.list
@@ -13,4 +13,5 @@ b5a488efc0558e2b795a1558e2c91a8aeecc3fd441d437aff3a4749d5eb0bdfc  sources/23_win
 5dbc166ce1b051b54d244ef5dc6b52dfbff03965e9abb0ed891d441dffbf8a76  sources/31_git-utils
 c9c270376844e7c7e3c48b1e86c2ce3e7824dde64e8724c17c5fc95910abd11c  sources/40_go-command
 c0e8ef70466063907b5ed9e52c13532b0019b8cb5975d020899804549a76a37f  sources/41_pivot-command
+e2af033a486bde23c6ee0a1a161d1cc0f279026dde048af1baead4b1bacb661a  sources/42_clipboard_server
 d02be2a68e8bd1f7e5adacbdd0bdc4f426aabfa1a57709270b673617db6c5352  sources/60_diagnostics
diff --git a/bash/sources/42_clipboard_server b/bash/sources/42_clipboard_server
new file mode 100644
index 0000000..e9a57bf
--- /dev/null
+++ b/bash/sources/42_clipboard_server
@@ -0,0 +1,99 @@
+# macOS clipboard receiver for SSH reverse forwarding.
+
+SSH_CLIPBOARD_DIR="${SSH_CLIPBOARD_DIR:-$HOME/.cache}"
+SSH_CLIPBOARD_SOCKET="${SSH_CLIPBOARD_SOCKET:-$SSH_CLIPBOARD_DIR/ssh-clipboard.sock}"
+SSH_CLIPBOARD_PIDFILE="${SSH_CLIPBOARD_PIDFILE:-$SSH_CLIPBOARD_DIR/ssh-clipboard.pid}"
+SSH_CLIPBOARD_LOG="${SSH_CLIPBOARD_LOG:-$SSH_CLIPBOARD_DIR/ssh-clipboard.log}"
+
+# This path is created on the remote host.
+# Override it when the remote username differs from the local username.
+SSH_CLIPBOARD_REMOTE_SOCKET="${SSH_CLIPBOARD_REMOTE_SOCKET:-/tmp/ssh-clipboard-client.sock}"
+
+function clipboard_server_running {
+	local pid
+
+	[[ -f "$SSH_CLIPBOARD_PIDFILE" ]] || return 1
+
+	read -r pid < "$SSH_CLIPBOARD_PIDFILE"
+
+	[[ "$pid" =~ ^[0-9]+$ ]] || return 1
+	kill -0 "$pid" 2>/dev/null
+}
+
+function init_clipboard_server {
+	case "$OSTYPE" in
+		darwin*)
+			command -v socat >/dev/null 2>&1 || {
+				echo "clipboard server: socat is not installed" >&2
+				echo "Install it with: brew install socat" >&2
+				return 1
+			}
+
+			[[ -x /usr/bin/pbcopy ]] || {
+				echo "clipboard server: /usr/bin/pbcopy was not found" >&2
+				return 1
+			}
+
+			if clipboard_server_running; then
+				return 0
+			fi
+
+			mkdir -p "$SSH_CLIPBOARD_DIR"
+			chmod 700 "$SSH_CLIPBOARD_DIR"
+
+			rm -f "$SSH_CLIPBOARD_SOCKET" "$SSH_CLIPBOARD_PIDFILE"
+
+			(
+				umask 077
+
+				socat \
+					"UNIX-LISTEN:$SSH_CLIPBOARD_SOCKET,fork,mode=600" \
+					EXEC:/usr/bin/pbcopy \
+					>>"$SSH_CLIPBOARD_LOG" 2>&1 &
+
+				echo "$!" > "$SSH_CLIPBOARD_PIDFILE"
+			)
+			;;
+
+		cygwin*)
+			echo "clipboard server: Cygwin support is not implemented" >&2
+			return 1
+			;;
+
+		*)
+			echo "clipboard server: $OSTYPE is not supported" >&2
+			return 1
+			;;
+	esac
+}
+
+function stop_clipboard_server {
+	local pid
+
+	if clipboard_server_running; then
+		read -r pid < "$SSH_CLIPBOARD_PIDFILE"
+		kill "$pid" 2>/dev/null || true
+	fi
+
+	rm -f "$SSH_CLIPBOARD_SOCKET" "$SSH_CLIPBOARD_PIDFILE"
+}
+
+function clipboard_server_config {
+	cat <<EOF
+RemoteForward $SSH_CLIPBOARD_REMOTE_SOCKET $SSH_CLIPBOARD_SOCKET
+StreamLocalBindUnlink yes
+ExitOnForwardFailure yes
+EOF
+}
+
+function sshc {
+	init_clipboard_server || return
+
+	command ssh \
+		-o StreamLocalBindUnlink=yes \
+		-o ExitOnForwardFailure=yes \
+		-R "$SSH_CLIPBOARD_REMOTE_SOCKET:$SSH_CLIPBOARD_SOCKET" \
+		"$@"
+}
+
+init_clipboard_server