#!/bin/sh
#
# 	@(#)sfetch	1.7 02/12/96 Felix Hassine
# 	@(#)sfetch	1.7 02/12/96 Christian Boissat
#
#	SFETCH SCRIPT FILE
#
#  Copyright (C) 1993 by CERN CN-SW/DC
#  All rights reserved
# 
#
# purpose:
#	copy a file from a remote site using FTP or RCP
# 	Returns 0 in case of success, 1 otherwise
#
# syntax:
#	sfetch local_path -t text [-v] [-u user] [-f mode]
#
# Restriction:
#	On a machine where a 'fetch' is already available
#	with its name specified by variable CRAYFETCH, that
#	fetch is executed. 
#
# Example:
#	sfetch myfile -t cernvm:profile.exec -u acher -f ascii
#	that will fetch the file profile.exec
#			 in account acher
#			 on machine cernvm
#			 in mode ascii for transfer
#			 and put it in the local file myfile
#
# sfetch supports syntax such as:
#	sfetch myfile -t 'vxcern::disk$user:[user]outfile' OR
#	sfetch myfile -t 'vxcern:disk$user:[user]outfile'
#
# Warning! Syntax such as: sfetch . -t 'vxcrna:sys$login:login.com'
# will work only if the current Unix id is the same as the VMS id 
# on the remote machine. Otherwise new id has to be specified with 
# the option -u.
#
#      We can also fetch files such as:
# sfetch newname -t'vxcrna:disk$c3:[user.subdir1.subdir2...]filename' -u user 
# OR 
# sfetch newname -t'vxcrna::disk$c3:[user.subdir1.subdir2...]filename' -u user 
#
# but then the -u user is obsolete as the disk & the user have already been 
# specified in the text.
#
# For fetching a file from its home directory on a machines running vms you can
# use the following syntax:
# sfetch  newname -t'vxcrna:filename' -u user 
#
# If the configuration file is correctly set with a line such as
# nodeX		protocol  	vms
#
# then a syntax such as:
# 	sfetch newfile -t vxcrna:file -u user.subdir 
# is also valid.
#
# this script file is to be executed in an environment
# containing the file specified in variable CFFILE.
#
# Retries on failure:
#-------------------
# if the file /etc/shift.conf has the lines:
# SFETCH SFETCHRETRY 10
# SFETCH SFETCHSLEEP 60
# then when a failure occurs, the command will be retried for 10 times
# and the process will be suspended 60 seconds between 2 retries.
# If no entry is found for these both parameters, no retry is done.
#
# A user can avoid the retries by typing the command:
# setenv NORETRY yes 
# before the sfetch is performed
#
# Its format: 
#	nodename	protocol
#
# example:
#	shift1		rcp
#
#
###############################################################
#
# Setting variables
#
LOGFILE="/tmp/sfetch.log"
#
VMSSYNTAX="FALSE"
SHIFTCONF="/etc/shift.conf"
TMPFILE="/tmp/sfetch.$$"
CFFILE="/etc/sfetch.cf" 
CRAYFETCH="/usr/bin/fetch"
CRAYACQUIRE="/usr/bin/acquire"
CRAY=$CRAYFETCH
#
trap "rm -f $TMPFILE; exit 1" 1 2 15
#
if [ "$PROGNAME" != "sacquire" ]; then
	PROGNAME="sfetch"
else
	CRAY=$CRAYACQUIRE
fi
VERBOSE="FALSE"
FOUND1="FALSE"
FOUND2="FALSE"
NOCFFILE="FALSE"
MACHINE=""
RETRY=0
SLEEP=0

log () {
	echo "$PROGNAME: $*"
	if [ -w $LOGFILE ]; then
		echo "$PROGNAME: $*" >> $LOGFILE
		echo \
"`date '+%y/%m/%d %H:%M:%S'` [$$] >>> Sfetch: command failed." >> $LOGFILE
	fi
}

verbose() {
	if [ "x$VERBOSE" = "xTRUE" ]; then
		echo "$PROGNAME: $*"
	fi
	if [ -w $LOGFILE ]; then
		echo "$PROGNAME: $*" >> $LOGFILE
	fi
}

usage() {
	log " $PROGNAME local_path -t text [-v] [-u user] [-f mode]"
}
if [ ! -f $CFFILE ]; then
	verbose "Configuration file $CFFILE not found"
	NOCFFILE="TRUE"
fi
#
if [ -f $CRAY ]; then
#
# fetch or acquire exists, no parsing required.
#
	verbose "$CRAY detected. Executing :$CRAY $*"
	$CRAY $*
	if [ -w $LOGFILE ]; then
		echo \
"`date '+%y/%m/%d %H:%M:%S'` [$$] >>> Sfetch: command successful." >> $LOGFILE
	fi
	exit 0
else
#
# fetch does not exist
#
# Checking arguments
# 
	if [ $# -le 2 ]; then
		usage
		exit 1
	elif [ `echo $1|sed '/^[^-]/p' | wc -l ` -eq 2 ]; then
		LOCPATH=$1
		shift
	else 
		usage
		log "$1 is not a valid local path"
		exit 1
	fi
	
	set -- `getopt u:f:t:v $*`
	while [ $# -gt 0 ]; do
	case $1 in
		-u) if [ "x$2" != "x" ]; then
			U=$2;shift;shift
		    else
			log "User uncorrectly specified"
			usage
			exit 1
		    fi ;;

		-v) VERBOSE="TRUE"; shift ;;
		-t|-text) if [ "x$2" != "x" ]; then
				TEXT=$2; shift; shift 
			  else
				log "Target not specified."
				exit 1 	
			  fi ;;
		  
		-f) if [ "x$2" != "x" ]; then
			MODE=$2; shift; shift 
		    else
			log "Transfert mode uncorrectly specified"
			exit 1
		    fi ;;
		-\?|-help) usage; exit 1 ;;
		
		--)
		   break;;

		*) log "invalid option $1."
		   usage
		   exit 1 ;;
   	 esac
	done
#
# Checking that logfile is not already there
#
i=0
if [ -f $TMPFILE ]; then
	while [ -f $TMPFILE"."$i ]; do
		i=`expr $i + 1`
	done
	TMPFILE=$TMPFILE.$i
fi
#verbose "Log file is $TMPFILE"
#
# setting up Default variables:
#
	DEFAULT_PROTOCOL="rcp"
	DEFAULT_MODE="ASCII"
	DEFAULT_MACHINE="shift"
	if [ "x$USER" != "x" ]; then
		DEFAULT_USER=$USER
	else
		DEFAULT_USER=$LOGNAME
	fi
if [ -w $LOGFILE ]; then
	echo \
"`date '+%y/%m/%d %H:%M:%S'` [$$] Fetching file for $DEFAULT_USER." >> $LOGFILE
fi
#
# Replacing variable by default values if required
#
	if [ "x$U" = "x" ]; then
		U=$DEFAULT_USER
		verbose "User : $U"
	fi
	if [ "x$TEXT" = "x" ]; then
		log "text has not been specified"
		exit 1
	fi
	if [ "x$MODE" = "x" ]; then 
		verbose "Mode: $DEFAULT_MODE"
		MODE=$DEFAULT_MODE
	fi
#
	verbose "text=$TEXT"
	verbose "Local Path=$LOCPATH"
	verbose "Transfer_mode=$MODE"
	if [ `echo "'$TEXT'" | sed '/:.*:/p' | wc -l ` -ge 2 ]; then
#
#       We are targetting a VMS machine
#
		VMSSYNTAX="TRUE"
		verbose "Syntax is VMS-like"
		TEXT=`echo $TEXT | tr -s ':' ':'`
		verbose "TEXT is $TEXT"
		IFS=":"
		set $TEXT
		IFS=" "
		MACHINE=$1
		FILE="$2:$3"
	elif [ `echo "$TEXT" | sed '/^[a-zA-Z].*:[~a-zA-Z/0-9.].*/p' | wc -l` -eq 2 ]; then
		IFS=":"
		set $TEXT
		IFS=" "
		MACHINE=$1
		FILE=$2
	elif [ `echo "$TEXT" | sed '/^[a-zA-Z].*:/p' | wc -l` -eq 2 ]; then
		log "Error: File name has not been correctly specified."
		exit 1	
	elif [ `echo "$TEXT" | sed '/:[a-zA-Z/0-9.~].*/p' | wc -l` -eq 2 ]; then
		log "Error: machine name has not been specified"
		exit 1
	else
		MACHINE=$DEFAULT_MACHINE
		FILE=$TEXT
	fi
		verbose "Machine has been set to $MACHINE"
		verbose "File has been set to $FILE"
#
# Making FILEN variable to specify local file name
#
		if [ -f $LOCPATH ]; then
			FILEN=$LOCPATH
			verbose "local file name is: $FILEN"
		elif [ -d $LOCPATH -a $VMSSYNTAX != "TRUE" ]; then
			IFS="/"
			set $FILE
			IFS=" "
			eval FILEN=\${$#}
			FILEN=$LOCPATH"/"$FILEN
			verbose "local file name is: $FILEN"
		else
			FILEN=$LOCPATH
			verbose "local file name is: $FILEN"
		fi
#
# Checking that this file is not write-protected
#
if [ "$PROGNAME" = "sacquire" ]; then
	if [ -f "$FILEN" ]; then
		verbose "File $FILEN exists. $PROGNAME exits."
		if [ -w $LOGFILE ]; then
			echo \
"`date '+%y/%m/%d %H:%M:%S'` [$$] >>> Sfetch: command successful." >> $LOGFILE
		fi
		exit 0
	fi
else
	if [ -f "$FILEN" -a ! -w "$FILEN" ]; then
		log "File $FILEN exists and is write-protected. $PROGNAME failed."
		exit 1
	fi
fi
#
# Checking that user has write permission
# on current directory
#
if [ -d $LOCPATH -a ! -w $LOCPATH ]; then
		log "You have no permission to write on $LOCPATH"
		exit 1
else
# LOCAPTH represents a file name given with a path:
		IFS="/"
		set $LOCPATH
		IFS=" "
		a=`expr $# - 1`
fi
if [ $a -gt 0 ]; then
in=1
eval WHDIR=\${$in}
		while [ $in -lt $a ]; do
			in=`expr $in + 1`
			eval TEMP=\${$in}
			WHDIR="$WHDIR/"$TEMP
		done
#
# the LOCAPTH is starting by a slash
#
if [ `echo $LOCPATH | sed '/^\//p' | wc -l` -eq 2 ]; then
		WHDIR="/"$WHDIR
else
		WHDIR=`pwd`/$WHDIR
fi
#
# The LOCPATH is just a file name to be
# interpreted relative to present directory
#
else
	WHDIR=`pwd`
fi
#
# Authorize sfetch or not
#
		 verbose "Whole TARGET Directory is : $WHDIR"
	if [ -d $WHDIR -a ! -w $WHDIR ]; then
		log "You have no permission to write on $WHDIR"
		exit 1
	elif [ ! -d $WHDIR ]; then
		log "Directory $WHDIR does not exist. Create it first"
		exit 1
	else
		verbose "Write into directory $WHDIR"
	fi
		
#
# Transfer mode
#
	case $MODE in
		TB|BB|binary|BINARY|bin)	TRANSMODE=binary ;;
		TC|TR|asc|ascii|ASCII) 		TRANSMODE=ascii;;
		*)  				TRANSMODE=ascii;;
	esac
#
# Reading the config files
#
	IFS="
"
	if [ "x$NOCFFILE" != "xTRUE" ]; then
		for F in `cat $CFFILE | grep "^[^#]" | tr -s "	" " "`
		do 
			IFS=" "
			set $F
			if [ "x$MACHINE" = "x$1" ]; then
				TRANSPROTOCOL=$2
				OPTION=$3
				verbose "Transfer protocol = $TRANSPROTOCOL"
				if [ "x$OPTION" != "x" ]; then
					verbose "Option : $OPTION"
				fi
				FOUND1="TRUE"
			fi
		done
	fi

	IFS="
"
	for G in `cat $SHIFTCONF | grep "^NET" | tr -s "	" " "`
	do
		IFS=" "
		set $G
		if [ "x$MACHINE" = "x$2" ]; then
				TARGETMACHINE=$3
				verbose "Target Machine = $TARGETMACHINE"
				FOUND2="TRUE"
		fi
	done
	IFS=" "
	if [ "x$FOUND1" != "xTRUE" ]; then
		verbose "Warning: Using default protocol: $DEFAULT_PROTOCOL."
		TRANSPROTOCOL=$DEFAULT_PROTOCOL
	fi
	if [ "x$FOUND2" != "xTRUE" ]; then
		verbose "Using default machine name as target: $MACHINE."
		TARGETMACHINE=$MACHINE	
	fi

if [ "x$NORETRY" != "xyes" ]; then
	SFLIN=`grep "SFETCHRETRY" $SHIFTCONF| tr -s "	" " "`
	if [ "x$SFLIN" != "x" ]; then 
		set $SFLIN
		RETRY=$3
		verbose "Number of retries: $RETRY"
	fi
	SFLIN=`grep "SFETCHSLEEP" $SHIFTCONF | tr -s "	" " "`
	if [ "x$SFLIN" != "x" ]; then
		set $SFLIN
		SLEEP=$3
		verbose "Sleep $SLEEP seconds before retrying sfetch"
	fi
fi
#
# START TRANSFER
#
	case $TRANSPROTOCOL in
#
# ftp is mainly for VM machine in CERN environment
#
		ftp|FTP)
			if [ "x$LOCPATH" = "x." ]; then
				LOCPATH=$FILE
			fi
			verbose "Executing : ftp $TARGETMACHINE "
			verbose "{ user anonymous , $TRANSMODE , cd $U , get $FILE $LOCPATH, quit } "
			ftp -n $TARGETMACHINE <<-AAA 2>&1 | egrep -v "^Name|^Ultra" > $TMPFILE
			user anonymous
			$TRANSMODE
			cd $U
			get $FILE $LOCPATH
			quit
			AAA
			j=1
			if [ $RETRY -gt 0 -a $SLEEP -gt 0 ]; then
				while [ -s $TMPFILE -a $j -lt $RETRY ]
				do
					log "`cat $TMPFILE`"
					verbose "Retry number $j"
					j=`expr $j + 1`
					sleep $SLEEP
					ftp -n $TARGETMACHINE <<-AAA 2>&1 | egrep -v "^Name|^Ultra" > $TMPFILE
					user anonymous
					$TRANSMODE
					cd $U
					get $FILE $LOCPATH
					quit
					AAA
				done
			fi
			if [ -s $TMPFILE ]; then
				log "`cat $TMPFILE`"; rm -f $TMPFILE
				exit 1
			else
				if [ -w $LOGFILE ]; then
					echo \
"`date '+%y/%m/%d %H:%M:%S'` [$$] >>> Sfetch: command successful." >> $LOGFILE
				fi
				rm -f $TMPFILE
				exit 0
			fi
			;;
		rcp|RCP)

		if [ "x$OPTION" = "xvms" -a "x$VMSSYNTAX" = "xFALSE" ]; then
			verbose "Executing : rcp $TARGETMACHINE:'sys\$login_device':[$U]$FILE $LOCPATH"
			j=1
			rcp $TARGETMACHINE:'sys$login_device':[$U]$FILE $LOCPATH > $TMPFILE 2>&1
			rc=$?
			if [ $RETRY -gt 0 -a $SLEEP -gt 0 ]; then
				while [ -s $TMPFILE -a $j -lt $RETRY ]
				do
					log "`cat $TMPFILE`"
					verbose "Retry number $j"
					j=`expr $j + 1`
					sleep $SLEEP
					rcp $TARGETMACHINE:'sys$login_device':[$U]$FILE $LOCPATH > $TMPFILE 2>&1
					rc=$?
				done
			fi
		else
			verbose "Executing : rcp $U@$TARGETMACHINE:$FILE $LOCPATH"
			j=1
			rcp $U@$TARGETMACHINE:$FILE $LOCPATH > $TMPFILE 2>&1
			rc=$?
			if [ $RETRY -gt 0 -a $SLEEP -gt 0 ]; then
				while [ -s $TMPFILE -a $j -lt $RETRY ]
				do
					log "`cat $TMPFILE`"
					verbose "Retry number $j"
					j=`expr $j + 1`
					sleep $SLEEP
					rcp $U@$TARGETMACHINE:$FILE $LOCPATH > $TMPFILE 2>&1
					rc=$?
				done
			fi
		fi
#
# rcp does not return an error status
# Detecting whether the output is null or not is more reliable to
# guess if an error occured.
#
			if [ $rc != 0 -o -s $TMPFILE ]; then
				log "`cat $TMPFILE`"; rm -f $TMPFILE
				exit 1
			else
				if [ -w $LOGFILE ]; then
					echo \
"`date '+%y/%m/%d %H:%M:%S'` [$$] >>> Sfetch: command successful." >> $LOGFILE
				fi
				rm -f $TMPFILE
				exit 0
			fi
			;;
		*)
			log "Error detected in configuration file: $CFFILE"
			log "$TRANSPROTOCOL unknown"
			exit 1
			;;
	esac
#
# End of if [ -f $CRAY ]
#
fi
# EOF
