#!/bin/bash function get_ssh_param () { local session_name ssh_param session_name="${1:?}" ssh_param="${2:?}" # SSHtunnelUser -> ssh_user # SSHtunnelHost -> ssh_target_server # SSHtunnelHostPort -> ssh_target_port # SSHtunnelPort -> ssh_local_port # Host -> tunneled_target_host # Port -> tunneled_target_port local value value="$(grep -Pio -- '(?<=^Servers\\'"${session_name}"'\\'"${ssh_param}"'<\|\|\|>[[:digit:]]<\|\|\|>)[^\r\n\f]+' "${settings_file}")" if [[ ! "${value}" ]]; then case "${ssh_param}" in SSHtunnelUser) value="${USER}" ;; SSHtunnelHostPort) value='22' ;; Host) value='127.0.0.1' ;; *) return 1 ;; esac fi printf -- '%s' "${value}" } function local_port_is_free () { local local_port local_listeners local_port="${1:?}" local_listeners="$(ss --no-header -tln 'sport :'"${local_port}")" if [[ "${local_listeners}" ]]; then return 1 fi return 0 } function prep_tunnel () { local session_name session_name="${1:?}" local ssh_user ssh_target_server ssh_target_port ssh_local_port tunneled_target_host tunneled_target_port ssh_user="$(get_ssh_param "${session_name}" 'SSHtunnelUser')" ssh_target_server="$(get_ssh_param "${session_name}" 'SSHtunnelHost')" ssh_target_port="$(get_ssh_param "${session_name}" 'SSHtunnelHostPort')" ssh_local_port="$(get_ssh_param "${session_name}" 'SSHtunnelPort')" tunneled_target_host="$(get_ssh_param "${session_name}" 'Host')" tunneled_target_port="$(get_ssh_param "${session_name}" 'Port')" if [[ ! "${ssh_user}" ]] || \ [[ ! "${ssh_target_server}" ]] || \ [[ ! "${ssh_target_port}" ]] || \ [[ ! "${ssh_local_port}" ]] || \ [[ ! "${tunneled_target_host}" ]] || \ [[ ! "${tunneled_target_port}" ]]; then printf 'Session name\n\n %s\n\nUnable to set all necessary SSH vars, exiting 256 ...\n' "'${session_name}'" exit 256 fi printf '%s\n' 'Starting SSH tunnel ...' if local_port_is_free "${ssh_local_port}"; then set -xv ssh "${ssh_user}"'@'"${ssh_target_server}" \ -o 'ExitOnForwardFailure=yes' \ -o 'ConnectTimeout=2' \ -f \ -p "${ssh_target_port}" \ -N \ -L "${ssh_local_port}"':'"${tunneled_target_host}"':'"${tunneled_target_port}" && { set +xv printf -- 'Done!' local_port_is_free "${ssh_local_port}" } set +xv else printf -- '%s\n' \ 'Failed! Something is listening on local TCP port '"${ssh_local_port}"'.' \ 'Try ss --no-header -tlpn '"'"'sport :'"${ssh_local_port}"''"'"' to ID processes.' \ 'Exiting 256 ...' exit 256 fi } function main () { settings_file=~/'.heidisql/portable_settings.txt' if [[ ! -r "${settings_file}" ]]; then COMPREPLY="$(printf -- '%s' '')" return 1 fi prep_tunnel "${@}" } main "${@}"