penguin/utils

my env utils

commit 446448f28235b24692f61475f0803804557a0ed7

author斟酌 鵬兄 <tgckpg@gmail.com>
date2026-08-14T07:34:56Z
subjectAdded pbpaste
commit 446448f28235b24692f61475f0803804557a0ed7
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2026-08-14T07:34:56Z

    Added pbpaste
---
 bash/dist/rbashrc                |   2 +-
 bash/dist/rbashrc.asc            |  10 +--
 bash/dist/sources.list           |   2 +-
 bash/sources/42_clipboard_server | 136 ++++++++++++++++++++++++++++++++-------
 4 files changed, 119 insertions(+), 31 deletions(-)

diff --git a/bash/dist/rbashrc b/bash/dist/rbashrc
index bdc5eea..d5623ad 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="61835cc27d7685e8c77479d6e129da27876e67750ae33b84bbd304ae94b3d327"
+RBASH_SOURCES_SUM="c7b59b606495091d7995fe38dd132890af9e9cefa342b3e35dc92f7ce4dae3ef"
 
 
 # ---- rbash: bash/core/00_env.bash ----
diff --git a/bash/dist/rbashrc.asc b/bash/dist/rbashrc.asc
index 32d4ca0..1fa7e4d 100644
--- a/bash/dist/rbashrc.asc
+++ b/bash/dist/rbashrc.asc
@@ -1,8 +1,8 @@
 -----BEGIN PGP SIGNATURE-----
 
-iJEEABYKADkWIQR8HpSNhBJUxWnt+97Vz1+xz60nwwUCamBLnRsUgAAAAAAEAA5t
-YW51MiwyLjUrMS4xMiwwLDMACgkQ1c9fsc+tJ8PzHgEAyhtngzSz/8tTukR7oMsw
-lSX0bmNExmi0IDvmS3PacS4A/A7nVaPtWnAFP0lKIDeJu0rbRNlY0hAjHP/MBIIh
-KKcN
-=HQN4
+iJEEABYKADkWIQR8HpSNhBJUxWnt+97Vz1+xz60nwwUCan7FAhsUgAAAAAAEAA5t
+YW51MiwyLjUrMS4xMiwwLDMACgkQ1c9fsc+tJ8MRAAD8DSxV2gCyyhicV9pmhCnQ
+AHyPJ8wLyanxixxLGIduBM4BAIJq2iILLTdpNEx6zmasVusLr1N+Crq0KYoibbcX
+ZokH
+=zX0d
 -----END PGP SIGNATURE-----
diff --git a/bash/dist/sources.list b/bash/dist/sources.list
index 1a0841c..66b6af8 100644
--- a/bash/dist/sources.list
+++ b/bash/dist/sources.list
@@ -13,5 +13,5 @@ b5a488efc0558e2b795a1558e2c91a8aeecc3fd441d437aff3a4749d5eb0bdfc  sources/23_win
 5dbc166ce1b051b54d244ef5dc6b52dfbff03965e9abb0ed891d441dffbf8a76  sources/31_git-utils
 c9c270376844e7c7e3c48b1e86c2ce3e7824dde64e8724c17c5fc95910abd11c  sources/40_go-command
 c0e8ef70466063907b5ed9e52c13532b0019b8cb5975d020899804549a76a37f  sources/41_pivot-command
-9218459bd0245a83afa467d71437a6a8cebb387c89fc33551f857a351074eeb0  sources/42_clipboard_server
+6815db1a12f540804a4ddb592905b43f53aca494d835e9e4afe3854db7f22416  sources/42_clipboard_server
 d02be2a68e8bd1f7e5adacbdd0bdc4f426aabfa1a57709270b673617db6c5352  sources/60_diagnostics
diff --git a/bash/sources/42_clipboard_server b/bash/sources/42_clipboard_server
index 247c0ae..2b64c6c 100644
--- a/bash/sources/42_clipboard_server
+++ b/bash/sources/42_clipboard_server
@@ -1,17 +1,22 @@
 SSH_CLIPBOARD_DIR="${SSH_CLIPBOARD_DIR:-$HOME/.cache}"
-SSH_CLIPBOARD_SOCKET="${SSH_CLIPBOARD_SOCKET:-$SSH_CLIPBOARD_DIR/ssh-clipboard.sock}"
+
+SSH_CLIPBOARD_COPY_SOCKET="${SSH_CLIPBOARD_COPY_SOCKET:-$SSH_CLIPBOARD_DIR/ssh-clipboard-copy.sock}"
+SSH_CLIPBOARD_PASTE_SOCKET="${SSH_CLIPBOARD_PASTE_SOCKET:-$SSH_CLIPBOARD_DIR/ssh-clipboard-paste.sock}"
+
 SSH_CLIPBOARD_PIDFILE="${SSH_CLIPBOARD_PIDFILE:-$SSH_CLIPBOARD_DIR/ssh-clipboard.pid}"
+SSH_CLIPBOARD_PASTE_PIDFILE="${SSH_CLIPBOARD_PASTE_PIDFILE:-$SSH_CLIPBOARD_DIR/ssh-clipboard-paste.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="/tmp/ssh-clipboard-client.sock"
+# These paths are created on the remote host.
+SSH_CLIPBOARD_REMOTE_COPY_SOCKET="/tmp/ssh-clipboard-copy-client.sock"
+SSH_CLIPBOARD_REMOTE_PASTE_SOCKET="/tmp/ssh-clipboard-paste-client.sock"
+
 
 function clipboard_server_running {
 	local pid
 
-	if [ -n "${SSH_CLIPBOARD_REMOTE_SOCKET:-}" ] &&
-		[ -S "$SSH_CLIPBOARD_REMOTE_SOCKET" ]; then
+	if [ -n "${SSH_CLIPBOARD_REMOTE_COPY_SOCKET:-}" ] &&
+		[ -S "$SSH_CLIPBOARD_REMOTE_COPY_SOCKET" ]; then
 		return 0
 	fi
 
@@ -23,41 +28,63 @@ function clipboard_server_running {
 	kill -0 "$pid" 2>/dev/null
 }
 
+
 function init_clipboard_server {
 	if clipboard_server_running; then
 		return 0
 	fi
+
+	command -v socat >/dev/null 2>&1 || {
+		echo "clipboard server: socat is not installed" >&2
+		return 1
+	}
+
 	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
+			[[ -x /usr/bin/pbcopy ]] || {
+				echo "clipboard server: /usr/bin/pbcopy was not found" >&2
 				return 1
 			}
 
-			[[ -x /usr/bin/pbcopy ]] || {
-				echo "clipboard server: /usr/bin/pbcopy was not found" >&2
+			[[ -x /usr/bin/pbpaste ]] || {
+				echo "clipboard server: /usr/bin/pbpaste was not found" >&2
 				return 1
 			}
 
 			mkdir -p "$SSH_CLIPBOARD_DIR"
 			chmod 700 "$SSH_CLIPBOARD_DIR"
 
-			rm -f "$SSH_CLIPBOARD_SOCKET" "$SSH_CLIPBOARD_PIDFILE"
+			rm -f \
+				"$SSH_CLIPBOARD_COPY_SOCKET" \
+				"$SSH_CLIPBOARD_PASTE_SOCKET" \
+				"$SSH_CLIPBOARD_PIDFILE" \
+				"$SSH_CLIPBOARD_PASTE_PIDFILE"
 
 			(
 				umask 077
 
+				# Remote -> local clipboard
 				socat \
-					"UNIX-LISTEN:$SSH_CLIPBOARD_SOCKET,fork,mode=600" \
+					"UNIX-LISTEN:$SSH_CLIPBOARD_COPY_SOCKET,fork,mode=600" \
 					EXEC:/usr/bin/pbcopy \
 					>>"$SSH_CLIPBOARD_LOG" 2>&1 &
 
 				echo "$!" > "$SSH_CLIPBOARD_PIDFILE"
+
+				# Local clipboard -> remote
+				socat \
+					"UNIX-LISTEN:$SSH_CLIPBOARD_PASTE_SOCKET,fork,mode=600" \
+					EXEC:/usr/bin/pbpaste \
+					>>"$SSH_CLIPBOARD_LOG" 2>&1 &
+
+				echo "$!" > "$SSH_CLIPBOARD_PASTE_PIDFILE"
 			)
 			;;
 
 		cygwin*)
+			# Eventually:
+			#   copy  -> cat > /dev/clipboard
+			#   paste -> cat /dev/clipboard
 			echo "clipboard server: Cygwin support is not implemented" >&2
 			return 1
 			;;
@@ -69,45 +96,60 @@ function init_clipboard_server {
 	esac
 }
 
+
 function stop_clipboard_server {
 	local pid
 
-	if clipboard_server_running; then
+	if [[ -f "$SSH_CLIPBOARD_PIDFILE" ]]; then
 		read -r pid < "$SSH_CLIPBOARD_PIDFILE"
-		kill "$pid" 2>/dev/null || true
+		[[ "$pid" =~ ^[0-9]+$ ]] && kill "$pid" 2>/dev/null || true
+	fi
+
+	if [[ -f "$SSH_CLIPBOARD_PASTE_PIDFILE" ]]; then
+		read -r pid < "$SSH_CLIPBOARD_PASTE_PIDFILE"
+		[[ "$pid" =~ ^[0-9]+$ ]] && kill "$pid" 2>/dev/null || true
 	fi
 
-	rm -f "$SSH_CLIPBOARD_SOCKET" "$SSH_CLIPBOARD_PIDFILE"
+	rm -f \
+		"$SSH_CLIPBOARD_COPY_SOCKET" \
+		"$SSH_CLIPBOARD_PASTE_SOCKET" \
+		"$SSH_CLIPBOARD_PIDFILE" \
+		"$SSH_CLIPBOARD_PASTE_PIDFILE"
 }
 
+
 function clipboard_server_config {
 	cat <<EOF
-RemoteForward $SSH_CLIPBOARD_REMOTE_SOCKET $SSH_CLIPBOARD_SOCKET
+RemoteForward $SSH_CLIPBOARD_REMOTE_COPY_SOCKET $SSH_CLIPBOARD_COPY_SOCKET
+RemoteForward $SSH_CLIPBOARD_REMOTE_PASTE_SOCKET $SSH_CLIPBOARD_PASTE_SOCKET
 StreamLocalBindUnlink yes
 ExitOnForwardFailure yes
 EOF
 }
 
+
 function sshc {
 	init_clipboard_server || return
 
 	echo "-- ssh with clipboard server"
 
 	command ssh \
-		-R "$SSH_CLIPBOARD_REMOTE_SOCKET:$SSH_CLIPBOARD_SOCKET" \
+		-R "$SSH_CLIPBOARD_REMOTE_COPY_SOCKET:$SSH_CLIPBOARD_COPY_SOCKET" \
+		-R "$SSH_CLIPBOARD_REMOTE_PASTE_SOCKET:$SSH_CLIPBOARD_PASTE_SOCKET" \
 		"$@"
 }
 
+
 function pbcopy {
-	if [ -n "${SSH_CLIPBOARD_REMOTE_SOCKET:-}" ] &&
-		[ -S "$SSH_CLIPBOARD_REMOTE_SOCKET" ]; then
+	if [ -n "${SSH_CLIPBOARD_REMOTE_COPY_SOCKET:-}" ] &&
+		[ -S "$SSH_CLIPBOARD_REMOTE_COPY_SOCKET" ]; then
 
 		command -v socat >/dev/null 2>&1 || {
 			echo "pbcopy: socat is required for the remote clipboard" >&2
 			return 1
 		}
 
-		socat - "UNIX-CONNECT:$SSH_CLIPBOARD_REMOTE_SOCKET"
+		socat - "UNIX-CONNECT:$SSH_CLIPBOARD_REMOTE_COPY_SOCKET"
 		return $?
 	fi
 
@@ -120,6 +162,11 @@ function pbcopy {
 				return 1
 			fi
 			;;
+
+		cygwin*)
+			cat > /dev/clipboard
+			;;
+
 		*)
 			echo "pbcopy: no remote clipboard socket is available" >&2
 			return 1
@@ -127,16 +174,57 @@ function pbcopy {
 	esac
 }
 
+
+function pbpaste {
+	if [ -n "${SSH_CLIPBOARD_REMOTE_PASTE_SOCKET:-}" ] &&
+		[ -S "$SSH_CLIPBOARD_REMOTE_PASTE_SOCKET" ]; then
+
+		command -v socat >/dev/null 2>&1 || {
+			echo "pbpaste: socat is required for the remote clipboard" >&2
+			return 1
+		}
+
+		socat - "UNIX-CONNECT:$SSH_CLIPBOARD_REMOTE_PASTE_SOCKET"
+		return $?
+	fi
+
+	case "$OSTYPE" in
+		darwin*)
+			if [ -x /usr/bin/pbpaste ]; then
+				/usr/bin/pbpaste
+			else
+				echo "pbpaste: /usr/bin/pbpaste was not found" >&2
+				return 1
+			fi
+			;;
+
+		cygwin*)
+			cat /dev/clipboard
+			;;
+
+		*)
+			echo "pbpaste: no remote clipboard socket is available" >&2
+			return 1
+			;;
+	esac
+}
+
+
 function cleanup_ssh_clipboard {
 	[ -n "${SSH_CONNECTION:-}" ] || return
-	[ -S "$SSH_CLIPBOARD_REMOTE_SOCKET" ] || return
-	rm -f -- "$SSH_CLIPBOARD_REMOTE_SOCKET"
+
+	[ -S "$SSH_CLIPBOARD_REMOTE_COPY_SOCKET" ] &&
+		rm -f -- "$SSH_CLIPBOARD_REMOTE_COPY_SOCKET"
+
+	[ -S "$SSH_CLIPBOARD_REMOTE_PASTE_SOCKET" ] &&
+		rm -f -- "$SSH_CLIPBOARD_REMOTE_PASTE_SOCKET"
 }
 
+
 if [ -z "${SSH_CONNECTION:-}" ] && init_clipboard_server; then
 	alias ssh='sshc'
 fi
 
 if [ -n "${SSH_CONNECTION:-}" ]; then
 	trap cleanup_ssh_clipboard EXIT HUP TERM
-fi
+fi
\ No newline at end of file