#!/bin/sh ######################################################################## # # # generic utiltiy modules # # (c) 2001 jannet it services # # contact@jannet.de # # # # $Id$ # # # This program is free software; permission to use, copy, modify, # # distribute, and sell this software and its documentation under the # # terms of the GNU Public license as published by the Free Software # # Foundation, either version 2 or any later version of the license, is # # hereby granted without fee, provided that (i) the above copyright # # notices and this permission notice appear in all copies of the # # software and related documentation, and (ii) the name of JanNet may # # not be used in any advertising or publicity relating to the software # # without the specific, prior written permission of JanNet. # # # # This program is distributed in the hope that it will be useful, but # # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- # # TABILITY 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 Founda- # # tion, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # ######################################################################## MYNAME=`basename $0` HOST=ftp.jannet.de CFG_FILE=$HOME/.uploadrc user=`whoami` method=rsync_ssh pw_ftp= pw_scp=$HOME/.ssh/identity pw_rsync= pw_rsync_ssh=$HOME/.ssh/identity file_mode= dir_mode= file_owner= file_group= test -f $CFG_FILE && . $CFG_FILE usage() { cat << EOT Unified Upload Interface Version '$Revision$' - '$Date$' (c) 2002 Jannet IT Services http://www.jannet.de usage: $MYNAME file [[password:[method:]user@]]]host:[target[:mode[:dirmode[:owner[.group]]]]] ... where "method" is one of "ftp", "scp", "rsync", "rsync_ssh". "password" may be a valid rsa private key file, too, if this makes sense with the chosen method. "file" may be a directory and a file. If it ends with a slash, it is treated as an existing directory and expands to its contents. "target" may be a directory and a file. + If it is an existing directory, it will be populated with "file", "file" will keep its name. + If it is not an existing directory, $MYNAME will take the path from target (i.e., skip everything following the last slash), and populate it with "file". - If there is a nonempty file name following the last slash, this will be the new file name. - If the last character of the target is a slash, the file name will be taken from "file". The default values for the optional parameters can be redefined in $CFG_FILE. Currently they are: user="$user" method="$method" pw_ftp="$pw_ftp" pw_scp="$pw_scp" pw_rsync="$pc_rsync" pw_rsync_ssh="$pw_rsync_ssh" file_mode="$file_mode" dir_mode="$dir_mode" file_owner="$file_owner" file_group="$file_group" EOT [ -n "$1" ] && exit $1 } parse_target() { target=$1 USER=`echo $target | sed -e '/@/ !d; s/@.*//; s/.*://'` test -n "$USER" && echo user="\"$USER\";" METHOD=`echo :$target | sed -e '/@/ !d; s/@.*//' | rev | cut -d: -f2 | rev` test -n "$METHOD" && echo method="\"$METHOD\";" PASSWD=`echo :$target | sed -e '/@/ !d; s/@.*//' | rev | cut -d: -f3 | rev` if [ -n "$PASSWD" ]; then echo passwd="\"$PASSWD\";" if [ -f "$PASSWD" ]; then echo IDENTITY="\"-i $PASSWD\"" fi echo pw_ftp="\"$PASSWD\";" echo pw_scp="\"$PASSWD\";" echo pw_rsync="\"$PASSWD\";" echo pw_rsync_ssh="\"$PASSWD\";" fi HOST=`echo $target | sed -e 's/.*@//' | cut -d: -f1` if [ -n "$HOST" ]; then echo host="\"$HOST\";" else PARSE_TARGET=FALSE return fi TARGET_FILE=`echo $target | sed -e 's/.*@//' | cut -d: -f2` if [ -n "$TARGET_FILE" ]; then echo target_file="\"$TARGET_FILE\";" else PARSE_TARGET=FALSE return fi FILE_MODE=`echo $target | sed -e 's/.*@//' | cut -d: -f3` test -n "$FILE_MODE" && echo file_mode="\"$FILE_MODE\";" DIR_MODE=`echo $target | sed -e 's/.*@//' | cut -d: -f4` test -n "$DIR_MODE" && echo dir_mode="\"$DIR_MODE\";" FILE_OWNER=`echo $target | sed -e 's/.*@//' | cut -d: -f5 | cut -d. -f1` test -n "$FILE_OWNER" && echo file_owner="\"$FILE_OWNER\";" FILE_GROUP=`echo $target | sed -e 's/.*@//' | cut -d: -f5 | cut -d. -f2` test -n "$FILE_GROUP" && echo file_group="\"$FILE_GROUP\";" echo "PARSE_TARGET=\"OK\";" } ssh_mkdir() { set -e dir=`echo $1 | sed -e 's/\/[^\/]*$//; s/\/*$//'` parts="`echo $dir | sed -e 's/\// /g'`" test -n "$dir_mode" && MODE="-m $dir_mode" cat << EOT | for part in $parts; do path="\$path/\$part" if [ ! -d \$path ]; then mkdir \$path || break test -n "$2" && chown "$2" \$path || break test -n "$3" && chgrp "$3" \$path || break test -n "$4" && chmod "$4" \$path || break fi if [ ! -d \$path ]; then echo "failed to create directory \$path, owner=\$file_owner, group=\$file_group, mode=\$dir_mode" exit 2 fi done EOT ssh -l $user $IDENTITY $host -C "SCRIPT=\`mktemp /tmp/$MYNAME""_XXXXXX\`; cat > \$SCRIPT; /bin/sh \$SCRIPT; rm \$SCRIPT" } # -- here we go test $# -lt 2 && usage 1 # -- get parameters from command line source=$1 shift # -- check run for t in $*; do # parse_target $t eval `parse_target $t` if [ "$PARSE_TARGET" != OK ]; then echo "Failed to parse target \"$t\"; exiting." parse_target $t exit 2 fi test "$METHOD" && method=$METHOD case $method in rsync_ssh) if [ "$user" != root ]; then if [ "$file_owner" -a "$file_owner" != "$user" ]; then echo "File owner \"$file_owner\" is only legal, if you log in as \"$user\" or as \"root\"." exit 1 fi fi if [ ! -d "$source" -a ! -f "$source" -a ! -L "$source" ]; then echo \"$source\" is neither a regular file, nor a directory, nor a link. Exiting. >&2 exit 1 fi;; *) echo "Support for method \"$method\" is not implemented." >&2 exit 1;; esac done # -- real run for t in $*; do eval `parse_target $t` test "$METHOD" && method=$METHOD case $method in rsync_ssh) ssh_mkdir $target_file $file_owner $file_group $dir_mode || break /usr/bin/rsync -az --links -e "/usr/bin/ssh -l $user $IDENTITY" $source $user@$host:$target_file ;; *) echo "Internal error: \"$method\" is not implemented." >&2 exit 1;; esac done