#! /bin/csh -f
#
#    sendhome.com v0.95
#
#	Send your x-ray frames to a remote machine (home)
#	continuously, AS they are collected!
#
#						-James Holton 12-12-1901 :)
#
################################################################################
echo "$0  - a safe, secure, and backgroundable way to send files home     James Holton 12-12-1901"
echo ""
goto Setup
#
#    Routine (at bottom) to read command-line args
#
Help:
cat << EOF-help

usage: 
$0 /data/${user}/frames/first_001.img ${user}@remotehost.college.edu:/bigdisk/${user}/frames/ [no compress]

where:
/data/${user}/frames/		- the local directory containing frames
first_001.img			- the first (oldest) frame to send home
			  	  any frames newer than [first_001.img] will also be sent
${user}@remotehost.college.edu	- your login at home
/bigdisk/${user}/frames/		- the disk (at home) you want to put your frames on
                                  (remote directory will be created if it doesn't exist)

Other options:
no compress			- (optional) do not compress the files during transfer (usually 3x slower)
timeout 50			- set the connection time-out to 50 minutes
no timeout			- disable connection time-out (careful! might interfere with last file )

-----------
a log of files that were sent home will be kept in $sentlog

NOTE: things will probably go a lot faster if: 
	/bigdisk is pysically attached to remotehost.college.edu
        /data is pysically attached to the computer running sendhome

EOF-help

# exit is "Help" was not just displayed for fun...
#if($?BAD) 
exit 9

Return_from_Setup:
if("$rhost" == "") goto Help

###############################################################################
# preamble
###############################################################################
echo "logging sent files in $sentlog"
echo "sending ${minsize}-byte files"
echo -n "from ${framedir}  "
if("$firstfile" != "") echo -n "(starting with "\"$firstfile\"") "
if("$lastfile" != "")  echo -n "(finishing with "\"$lastfile\"") "
echo ""
echo "to   $rdir on ${ruser}@${rhost}"
if($?CLEAR) echo "local copy will be deleted once file has been sent."
onintr User_Interrupt
unset FINISHED

touch $sentlog

if($?BUNCHWISE) goto Bunchwise

###############################################################################
# start sending frames home
###############################################################################
echo "$framedir ext $minsize $timeout $lastfile $firstfile $sentlog" |\
nawk '{framedir=$1;minsize=$3;timeout=$4*60;lastfile=$5;firstfile=$6;\
	if(firstfile == "") sending=1;\
	cmd="ls -lLrt "framedir; while(1){new=0;\
	# keep listing the directory every 10 seconds \
	while(cmd | getline){\
	  # ignore entries before the first file \
	  if($NF == firstfile){sending=1};\
	  # pretend earlier entries were already sent \
	  if(! sending) sent[$NF]=1;\
          if((sending)&&($5>=minsize)&&(! sent[$NF])){\
		print $NF; fflush(); ++new; idle=0; \
		# keep an internal record of files we have sent \
		sent[$NF]=1;};\
	  # exit when we see a file called "exit" \
	  if($NF == lastfile){exit};\
	};\
	# idle timeout so last file send finishes \
	close(cmd); if(! new){system(" sleep 10 "); idle+=10};\
	if(idle > timeout) exit;}}' |\
(cd $framedir; tar c${B}${T}f - - ) | $compresser |\
ssh -x -k ${ruser}@${rhost} "if(! -e $rdir) mkdir -p $rdir; $decompress | (cd $rdir ; tar xv${B}f - )" |\
nawk -v clear=$?CLEAR -v framedir=$framedir -v sentlog=$sentlog '\
 {filename=""; for(i=1;i<=NF;++i){ word=$i; \
 if(! system("test -s " framedir "/" word)) filename=word; \
 word=substr($i,1,length($i)-1);\
 if(! system("test -s " framedir "/" word)) filename=word; \
 } if(filename=="") {print; next}}\
 clear!=0 && sentfile!=""{if(! system("rm -f " framedir "/" sentfile)) printf "deleted %s ", sentfile} \
 {print ""} \
 {printf "sending %s ", filename; print filename > sentlog} \
 {sentfile=filename} \
 END{if(clear !=0 && sentfile!="") if(! system("rm -f " framedir "/" sentfile)) printf "deleted %s ", sentfile; \
     print ""}' 

# user will only have to enter their remote password once

if(-e "${framedir}/$lastfile") then
    # the "exit" file was produced
    set FINISHED
    goto done
endif

# reaching here means the file-finder program timed out
goto Timed_out


Bunchwise:
###############################################################################
# make a list of at least $bunch_size files before initiating a send
# mainly for OSF1 users
echo "unimplemented! sorry."
exit 9

goto done
# user will have to enter their remote password once per bunch


Timed_out:
###############################################################################
echo "timeout: $timeout minutes"
set FINISHED

User_Interrupt:
###############################################################################
onintr done

echo "connection lost...."

# don't ask user questions if output is not a terminal
test -t 1
if($status) set DONT_ASK

echo "reconnect to ${rhost}? [Yes]"
echo -n "->"
if(! $?DONT_ASK) then
    set temp = "$<"
else
    set temp = "No"
    echo ""
endif
if("$temp" =~ [Nn]*) then
    goto done
endif


# re-discover first filename
set firstfile = ""

goto reconnect


###############################################################################
done:
###############################################################################
onintr

# don't ask user questions if output is not a terminal
test -t 1
if($status) set DONT_ASK

if(! $?FINISHED) then
    # extract last file sent from TAR log
    cat $sentlog |&\
    nawk 'BEGIN{RS=" "} {print}' |\
    nawk '/,$/{print substr($0,1,length($0)-1)} ! /,$/{print}' |\
    nawk 'NF==1' |\
    tail -1 >! ${tempfile}$$
    set firstfile = `tail -1 ${tempfile}$$`
    rm -f ${tempfile}$$ >& /dev/null
    if(-e "${framedir}/$firstfile") then
	echo ""
	echo "WARNING! remote $firstfile is incomplete! "
	echo ""
	echo "send it now? [Yes]"
	echo -n "->"
	if(! $?DONT_ASK) then
	    set temp = "$<"
	else
	    echo ""
	endif
	if("$temp" =~ [Nn]*) then
	    goto cleanup
	endif
	# do the standard send for one file
	echo "$firstfile" |\
	(cd $framedir; tar c${B}${T}f - - ) | $compresser |\
	ssh ${ruser}@${rhost} "$decompress | (cd $rdir ; tar xv${B}f - )" |&\
	nawk -v clear=$?CLEAR -v framedir=$framedir -v sentlog=$sentlog '\
	 NF==1{filename= $1} NF>1{filename = substr($2,1,length($2)-1)} \
	 {printf "sending %s", filename; print filename > sentlog} \
	 END{if(clear !=0){if(! system("rm -f " framedir "/" filename)) printf " deleted %s\n", filename;}}' 
	if(! $status) set FINISHED
    endif
endif

cleanup:
if($?FINISHED) then
    echo "done"
endif

exit


###############################################################################
# set-up routine (moved to bottom for clarity)
Setup:

if(! $?user) set user = `whoami`

# defaults (can be reset interdependently)
set timeout   = "60"		# max time since last new file appeared (minutes)
set framedir  = ""		# directory to send files from
set firstfile = ""		# first file (chronologically) to send
set lastfile  = "exit"		# last file (chronologically) to send
set minsize   = 10617344	# file must reach this size before being sent

set ruser     = ""		# remote username
set rhost     = ""		# remote computer name
set rdir      = ""		# send-to directory on remote computer

if($?CLEAR) unset CLEAR
#set CLEAR			# uncomment to delete files after they are sent

set tempfile  = ./tempfile
set sentlog   = ./sent_home.log
touch $sentlog >& /dev/null
if($status) then
    set sentlog = ~/sent_home.log
    set tempfile = ~/tempfile
endif
touch $sentlog >& /dev/null
if($status) then
    echo "ERROR!  unable to create sent-file log"
    echo "please make sure either "`pwd`" or ~$user is writable! "
    sleep 2
    set BAD
    goto Help
endif

# default: use compress (gzip is too slow)
# default: use gzip (compress has a stream size limit)
set compresser = "gzip --fast -c"
set decompress = "gunzip -c"

# machine-specific configurations
set machine = `uname`
set T = ""
#set B = "B"
set B = ""
if("$machine" =~ IRIX*) then
    set T="L"
endif
if("$machine" == "Linux") then
    set T="hT"
    alias nawk awk
endif
if("$machine" == "OSF1") then
    echo "ERROR: realtime file transmission is not possible on Digital Unix"
    echo "       this is because the OSF1 tar program is incapable of streaming"
    echo "       archives.  A workaround is being implemented, but is not yet"
    echo "       available. "
    echo ""
    echo " You will probably have better luck on an SGI or Linux box."
    echo ""
    set BUNCHWISE
    set bunch_size = 50
endif

# scan the command line
if($#argv == 0) goto Help
set i = 0
while ( $i < $#argv )
    @ i = ( $i + 1 )
    set arg = "$argv[$i]"

    # check for local directory specifier
    if(("$arg" =~ */*)&&("$arg" !~ *[@:]*)||(-e "$arg")) then
	if(-e "$arg") then
	    test -d $arg
	    if(! $status) then
		# just a directory
		set framedir = "$arg"
		continue
	    endif

	    test -c $arg
	    if(! $status) then
		# support tapes one day?
		continue
	    endif
	    
	    # must just be a regular file (or link)
	    if("$firstfile" == "") then
		set framedir  = `dirname  $arg`
		set firstfile = `basename $arg`
	    else
		# use last local filename given as a "last" file
		set lastfile = `basename $arg`
	    endif	    

	    continue
	else
	    if("$framedir" == "") then
		# no files specified yet
		set framedir = `dirname $arg`
		set prefix   = `basename $arg`
		set firstfile = `ls -lL $framedir | nawk '$5>1000000 && ! /dkc$/ {print $NF}' | egrep "^$prefix" | head -1`
		if(-e "${framedir}/$firstfile") then
		    continue
		endif
		# guess that wasn't anything
		set framedir = ""
		set firstfile = ""
		
		echo "WARNING: $arg does not exist! "
	    else
		# maybe this is a preemtive last file?
		if("$arg" =~ *.$ext) set lastfile = `basename $arg`
	    endif
	endif
    endif

    # check for remote file specifier
    if("$arg" =~ *[@:/]*) then
	# retrieve remote username
	set ruser = `echo $arg | nawk 'BEGIN{FS="@"} NF>1{print $1}'`
	if("$ruser" == "") set ruser = `whoami`

	# get the remote computer name
	set rhost = `echo $arg  | nawk 'BEGIN{FS="@"} {print $NF}' | nawk 'BEGIN{FS="[:/]"} {print $1}'`
	if("$rhost" != "") then
	    # get remote directory name
	    if("$arg" =~ *:*) then
		# everything after first colon is directory
		set rdir = `echo $arg | nawk 'BEGIN{FS="@"} {print $2}' | nawk '{print substr($0,index($0,":")+1)}'`
		set rdir = `echo $arg | nawk 'BEGIN{FS="@"} {print $2}' | nawk 'BEGIN{FS=":"} {print $2}'`
	    else
		# everything after first "/" is directory
		set rdir = `echo $arg | nawk '/[\/]/{print substr($0,index($0,"/"))}'`
	    endif
	else
	    echo "WARNING: did not understand $arg"
	    echo "         please use: user@host:directory"
	endif	
	continue
    endif

    # optional compression stuff
    if(("$arg" == "compress")||("$arg" == "-compress")) then
	set compresser = "compress -c"
	set decompress = "uncompress -c"
	if($?NO) then
	    # disable compression
	    set compresser = "cat"
	    set decompress = "cat"
	endif
	continue
    endif
    if(("$arg" == "gzip")||("$arg" == "-gzip")) then
	set compresser = "gzip --fast -c"
	set decompress = "gunzip -c"
	continue
    endif

    # ignore last sentlog
    if(("$arg" == "new")||("$arg" == "-new")) then
	echo "clearing $sentlog ..."
	echo -n "" >! $sentlog
    endif
    
    # delete files after sending them
    #if(("$arg" == "clear")||("$arg" == "delete")||("$arg" == "remove")) then
    if(("$arg" == "delete")) then
	if($?NO) then
	    unset CLEAR
	else
	    set CLEAR
	endif
    endif

    # negative logic (for next word)
    unset NO
    if(("$arg" == "no")||("$arg" == "-no")||("$arg" == "not")) then
	set NO
	continue
    endif
end

# default timeouts (relative speed of detectors)
if("$firstfile" =~ *.mar*) set timeout = 120
if("$firstfile" =~ *.img)  set timeout = 60
if("$firstfile" =~ *.osc)  set timeout = 200

# second pass
# scan the command line
set i = 0
while ( $i < $#argv )
    @ i = ( $i + 1 )
    set arg = "$argv[$i]"

    # manual setting of timeout
    if(("$arg" == "timeout")||("$arg" == "-timeout")) then
	if($?NO) then
	    # set timeout to 24 hours
	    set timeout = 1440
	else
	    @ j = ( $i + 1 )
	    if($j <= $#argv) then
		if("$argv[$j]" =~ [0-9]*) then
		    # user-specified timeout
		    set timeout = `echo $rgv[$j] | nawk '{print $1+0}'`
		endif
	    endif
	endif
    endif
    
    # negative logic (for next word)
    unset NO
    if(("$arg" == "no")||("$arg" == "-no")||("$arg" == "not")) then
	set NO
	continue
    endif
end

# defaults for bad or missing inputs
if(! -e "$framedir") then
    # default to current directory
    set framedir = "."
    set firstfile = ""
endif
if("$rhost" == "") then
    set temp = ""
    echo "where shall we send $firstfile ... etc. to? [${user}@home.college.edu:/bigdisk/${user}/frames]"
    echo ""
    echo -n "-> "
    if(! $?DONT_ASK) set temp = "$<"
    if(("$temp" =~ *[@:]*)) then
	set argv = ( $temp )
	goto Setup
    endif
    goto Help
endif
if("$rdir" == "") then
    echo "WARNING: files will be sent to ${ruser}@${rhost}'s HOME directory! "
    set rdir = "."
endif


# jump here to re-establish send where we left off
reconnect:

# check to see if we don't have a first filename yet
if(("${firstfile}" == "")||(! -e "${framedir}/$firstfile")) then
    # check for an old, aborted run
    if(-e "$sentlog") then
	# extract last file sent from TAR log
	cat $sentlog |&\
	nawk 'BEGIN{RS=" "} {print}' |\
	nawk '/,$/{print substr($0,1,length($0)-1)} ! /,$/{print}' |\
	tail -1 >! ${tempfile}$$
	set temp = `head -1 ${tempfile}$$`
	rm -f ${tempfile}$$ >& /dev/null
	if(-e "${framedir}/$temp") then
	    echo "reading $sentlog"
	    set firstfile = "$temp"
	endif
    endif
endif

# default to the first file in the directory
if(("${firstfile}" == "")||(! -e "${framedir}/$firstfile")) then
    set firstfile = `ls -lLrt $framedir | nawk -v size=$minsize '$5>=size{print $NF}' | head -1`
endif

# still nothing?
if(("${firstfile}" == "")||(! -e "${framedir}/$firstfile")) then
    # wait for something to appear
    set firstfile = ""

    # maybe just send the directory?
endif

# set the target frame size
if(("$firstfile" != "")&&(-e "${framedir}/$firstfile")) then
    set minsize = `ls -lL ${framedir}/${firstfile} | nawk '$5+0>0{print $5}'`
    # get filename extension too
    set ext = `echo $firstfile | nawk 'BEGIN{FS="."} {print $NF}'`
endif

goto Return_from_Setup


##################################
#  Future plans
#
# use cpio instead of tar?
# implement bunch-wise send
#
# checksum remote files after transfer (retransmit?)
# send directories?
#
#

