As there's no working sftp program included with lsh yet, I wrote a
rcp/scp-like program. It's called "lcp", and it should work with
almost any rsh/scp program, including lsh and lshg. It currently needs
bash on the remote end, but it does *not* need any other programs to
be installed, which I think is neat.
Improvements are welcome, in particular the quote function could be
improved, and it would be nice if it worked with a plain old /bin/sh.
The entire script is included below.
Happy hacking!
/Niels
#! /bin/sh
# rcp-like copying program. Requires bash on the remote machine, but
# no other special programs.
# lsh, an implementation of the ssh protocol
#
# Copyright (C) 2001 Niels Möller
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
set -e
verbose=no
dry_run=no
force=no
function werror () {
if [ $verbose == yes ] ; then
echo 1>&2 "$@"
fi
}
function usage () {
echo "Usage: lcp [OPTIONS] SOURCE DESTINATION"
echo
echo "Both SOURCE and DESTINATION can be files on remote machines."
echo "Valid file specifications are:"
echo
echo " file"
echo " machine:file"
echo " user@machine:file"
echo
echo "Valid options are:"
echo
echo " --help display this message"
echo " -f, --force overwrite existing files"
echo " -v, --verbose display commands before they are executed"
echo " -n, --dry-run don't execute any commands. Implies -v"
}
# This could be improved, e.g. by inserting a backslash
# before each character.
function quote () {
echo '"'"$1"'"'
}
# Splits an argument of the form [[user@]host:]file
function split_spec () {
host=''
user=''
file="$1"
case "$file" in
*:*)
host=${1%:*}
file=${1#*:}
case "$host" in
*@*)
user=${host%@*}
host=${host#*@}
;;
esac
;;
esac
}
# Arguments USER HOST FILE
function read_src () {
local user="${1:+-l}$1"
local host="$2"
local file="$3"
if [ -z "$host" ]; then
werror "From: cat "`quote "$file"`
if [ $dry_run == no ] ; then
cat "$file"
fi
else
file=`quote "$file"`
werror "From: " ${LCP_SSH:-lsh} $user "$host" cat "$file"
if [ $dry_run == no ] ; then
${LCP_SSH:-lsh} $user "$host" cat "$file"
fi
fi
}
# Arguments USER HOST FILE SRC_FILE
function write_dst () {
local user="${1:+-l}$1"
local host="$2"
local file="$3"
local src_file=`quote "$4"`
if [ -z "$host" ]; then
werror "To: cat >"`quote "$file"`
if [ $dry_run == no ] ; then
cat > "$file"
fi
else
file=`quote "$file"`
command="$set_clobber ; if [ -d $file ] ; then cat > $file/$src_file ; else cat >
$file ; fi"
werror "To: " ${LCP_SSH:-lsh} $user "$host" "bash -c '$command'"
if [ $dry_run == no ] ; then
${LCP_SSH:-lsh} $user "$host" bash -c "'$command'"
fi
fi
}
function foo ()
{
split_spec "$1"
echo user: `quote "$user"`
echo host: `quote "$host"`
echo file: `quote "$file"`
}
while [ $# -ge 1 ]; do
case "$1" in
--usage|--help)
usage
exit 1;
;;
-v|--verbose)
verbose=yes
;;
-n|--dry-run)
dry_run=yes
verbose=yes
;;
-f|--force)
force=yes
;;
--)
shift
if [ $# != 2 ] ; then
usage
exit 1
fi
break
;;
-*)
echo "lcp: unrecognized option \`$1'"
echo "Try \`lcp --help' or \`lcp --usage' for more information."
exit 1;
;;
*)
break
;;
esac
shift
done
if [ $# != 2 ] ; then
usage
exit 1
fi
split_spec "$1"
src_user="$user"
src_host="$host"
src_file="$file"
split_spec "$2"
dst_user="$user"
dst_host="$host"
dst_file="$file"
# echo dry_run: $dry_run
# echo verbose: $verbose
if [ $force == yes ] ; then
set_clobber='set +C'
else
# noclobber
set_clobber='set -C'
fi
$set_clobber
if [ $dry_run == yes ] ; then
read_src "$src_user" "$src_host" "$src_file"
write_dst "$dst_user" "$dst_host" "$dst_file" "$src_file"
else
read_src "$src_user" "$src_host" "$src_file" \
| write_dst "$dst_user" "$dst_host" "$dst_file" "$src_file"
fi