-
-
Save soraxas/5ce8029b3a1fd02af7fbd5d30381e517 to your computer and use it in GitHub Desktop.
copy to clipboard
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
_scs_col="\e[0;32m" | |
_wrn_col='\e[1;31m' | |
_trn_col='\e[0;33m' | |
_res_col='\e[0m' | |
# set -x | |
stderr_color() { | |
color_code="$1" | |
shift | |
printf -- "${color_code}%s${_res_col}" "$@" >&2 | |
} | |
info() { | |
stderr_color "${_scs_col}" "$@" | |
} | |
error() { | |
stderr_color "${_wrn_col}" "$@" | |
} | |
stderr_endline() { | |
printf -- "\n" >&2 | |
} | |
println() { | |
printf -- "%s\n" "$@" | |
} | |
remote_hostname="localhost" | |
remote_port="15756" | |
inside_ssh() { | |
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then | |
return 0 | |
fi | |
# many other tests omitted | |
case $(ps -o comm= -p "$PPID") in | |
sshd|*/sshd) | |
return 0 | |
;; | |
esac | |
return 1 | |
} | |
help() { | |
printf '%s\n' "$(basename "$0"): Copies a string to the clipboard." >&2 | |
printf '%s\n' "" >&2 | |
printf '%s\n' "Usage: $(basename "$0") <string>" >&2 | |
printf '%s\n' " echo <string> | cb" >&2 | |
printf '\n' >&2 | |
printf '\t%s\n' "If a pipe exists, this script copy the piped inputs" >&2 | |
printf '\t%s\n' "to system clipboard. Otherwise, the given argument" >&2 | |
printf '\t%s\n' "will be copied instead." >&2 | |
printf '\n' >&2 | |
printf '%s\n' "Options:" >&2 | |
printf '\t%s\t%s\n' "--help " "display help message" >&2 | |
printf '\t%s\t%s\n' "-r, --hostname" "set remote address to listen to in remote netcat mode (default: $remote_hostname)" >&2 | |
printf '\t%s\t%s\n' "-p, --port" "set remote port to listen to in remote netcat mode (default: $remote_port)" >&2 | |
printf '\t%s\t%s\n' "-r, --remote" "set role to remote listener. This will make $(basename $0) listens input from netcat" >&2 | |
printf '\t%s\t%s\n' "--remote-sender" "set role to remote sender. This is not necessary as the script auto detect being inside ssh." >&2 | |
} | |
raw_send_text_via_socket() ( | |
# exec 3<>/dev/tcp/localhost/5556; cat >&3; cat <&3; exec 3<&- | |
# The following version closes on EOF | |
exec 3<>/dev/tcp/"$remote_hostname"/"$remote_port"; cat >&3; exec 3<&- | |
) | |
EOL=$(echo '\00\07\01\00') | |
if [ "$#" != 0 ]; then | |
set -- "$@" "$EOL" | |
while [ "$1" != "$EOL" ]; do | |
opt="$1"; shift | |
case "$opt" in | |
--help) | |
help | |
exit | |
;; | |
-h|--hostname) | |
remote_hostname="$1" | |
shift | |
;; | |
-p|--port) | |
remote_hostname="$1" | |
shift | |
;; | |
--remote-sender) | |
remote_mode="sender" | |
;; | |
--remote-listener|--remote|-r) | |
remote_mode="listener" | |
;; | |
--*=*) # convert '--name=arg' to '--name' 'arg' | |
set -- "${opt%%=*}" "${opt#*=}" "$@";; | |
-[!-]?*) # convert '-abc' to '-a' '-b' '-c' | |
# shellcheck disable=SC2046 # we want word splitting | |
set -- $(echo "${opt#-}" | sed 's/\(.\)/ -\1/g') "$@";; | |
--) # process remaining arguments as positional | |
while [ "$1" != "$EOL" ]; do set -- "$@" "$1"; shift; done;; | |
-*) | |
echo "Error: Unsupported flag '$opt'" >&2 | |
exit 1 | |
;; | |
*) | |
# set back any unused args | |
set -- "$@" "$opt" | |
esac | |
done | |
shift # remove the EOL token | |
fi | |
# auto select ssh mode | |
if [ -z "$remote_mode" ] && inside_ssh; then | |
info ">> Detected inside ssh, setting current role as remote sender." | |
stderr_endline | |
remote_mode="sender" | |
fi | |
_get_input_local() { | |
# If no tty, data should be available on stdin | |
if [ -t 0 ]; then | |
# echo running interactivelly | |
if [ "$#" -lt 1 ]; then | |
# If no input, print usage message. | |
error 'No argunment given.' | |
stderr_endline | |
help | |
exit 1 | |
fi | |
input="$@" | |
else | |
input="$(tee)" | |
# while read line; do | |
# input="$input\n$line" | |
# done | |
fi | |
if [ -z "$input" ]; then | |
error 'Empty input from stdin.' | |
stderr_endline | |
exit 1 | |
fi | |
println "$input" | |
} | |
_get_input_remote() { | |
nc -cl "$remote_hostname" -p "$remote_port" | |
# the previous command might returns non zero status | |
true | |
} | |
get_input() { | |
if [ "$remote_mode" = "listener" ]; then | |
info "Listening to remote @ $remote_hostname:$remote_port..." | |
stderr_endline | |
_get_input_remote | |
else | |
_get_input_local "$@" | |
fi | |
} | |
_get_receiver_local() { | |
# Check that xclip is installed. | |
if command -v pbcopy >/dev/null 2>&1; then | |
cb="pbcopy" | |
params="" | |
elif command -v xsel >/dev/null 2>&1; then | |
cb="xsel" | |
params="--clipboard" | |
elif command -v xclip >/dev/null 2>&1; then | |
cb="xclip" | |
params="-selection c" | |
else | |
error "You must have 'xsel' or 'xclip' installed." | |
stderr_endline | |
exit 1 | |
fi | |
# Check if user is NOT Root (because Root cannot access User's xorg server) | |
if [ "$USER" = "root" ]; then | |
error "You must be regular user (non-root) to copy to clipboard." | |
stderr_endline | |
exit 1 | |
fi | |
"$cb" $params # allows params to split on space | |
} | |
_get_receiver_remote() { | |
if command -v nc >/dev/null 2>&1; then | |
nc -c "$remote_hostname" "$remote_port" | |
elif command -v telnet >/dev/null 2>&1; then | |
# sleep to wait for telnet to first connects. It's a heuristic. | |
{ sleep .5; printf '%s\n' "$(tee)"; } | telnet "$remote_hostname" "$remote_port" | |
else | |
# use raw socket | |
raw_send_text_via_socket | |
fi | |
status="$?" | |
if [ "$status" -ne 0 ]; then | |
error "Error in opening port. If you are in ssh session, have you " | |
stderr_endline | |
error " (1) open port with '-R $remote_port:localhost:$remote_port', and " | |
stderr_endline | |
error " (2) starts a local $(basename $0) process with '$(basename $0) -r'?" | |
stderr_endline | |
stderr_endline | |
error " (tip): You can use ssh escape sequence ~C and then type the previous command" | |
stderr_endline | |
error " to amend a ssh session without closing it." | |
stderr_endline | |
exit 1 | |
fi | |
} | |
get_receiver() { | |
set -o pipefail | |
if [ "$remote_mode" = "sender" ]; then | |
info "Sending to remote @ $remote_hostname:$remote_port..." | |
stderr_endline | |
_get_receiver_remote | |
else | |
_get_receiver_local | |
fi | |
} | |
# if [ -n "$remote_mode" ]; then | |
# echo hi | raw_send_text_via_socket | |
# exit | |
# fi | |
input="$(get_input "$@")" | |
# echo "in4 $input" | |
status="$?" | |
if [ "$status" -ne 0 ]; then | |
exit "$status" | |
fi | |
# Copy input to clipboard | |
printf -- '%s' "$input" | get_receiver | |
status="$?" | |
if [ "$status" -ne 0 ]; then | |
exit "$status" | |
fi | |
# Truncate text for status | |
if [ ${#input} -gt 80 ]; then | |
input="$(printf -- "%s$_trn_col..." "$(echo "$input" | head -c80)")" | |
fi | |
# Print status. | |
stderr_color "${_scs_col}" "Copied to clipboard: " | |
stderr_color "" "$input" | |
stderr_endline | |
# alias h2cb='fc -ln -1 | tail --lines=2 | head --lines=1 | cb' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment