#!/usr/bin/ksh
# Written By	: Kynan Dent
# Written On	: 06/08/04
VERSION=1.0
# Function		: This is an alternative for the "amtape BACKUP_NAME show" command
#               as blank tapes cause the whole thing to go into a tail spin. If
#               it runs across an unlabelled tape it will label it as a monthly
#               if the -label flag has been set.
#               Tape library data is output to stdout in the following format:
#               

# check the command line for arguments
while getopts :dl:ns ARG
do
	case $ARG in
    l)
			# labelling on
			LABEL_PREFIX=BACKUP-NAME-`date +%Y%M`
      LABEL_SUFFIX="a"
      if [ $OPTARG = "s" ];then
      		SUSPICIOUS="ON"
      elif [ $OPTARG != "n" ];then
				USAGE="please explain"
			fi
      ;;
    d)
      if [ -z "$DEBUG" ];then
        DEBUG="ON"
      else
        DEBUG="REALLY ON"
      fi
      ;;
    \?|:)
    	USAGE="please explain"
      ;;
  esac
done

if [ -n "$USAGE" ];then
	cat<<EOF
Usage: `basename $0` [-l<n|s>] [-d[d]]

  -l<n|s>  label  If blank tapes are encountered they are labelled.  The label
                  BACKUP-NAME-YYYYMMa is applied to the first blank tape, the
                  letter at the end is incremented for each blank tape so the 
                  next blank tape would be BACKUP-NAME-YYYYMMb and so on. The
                  -l option MUST be accompanied by either n for normal mode or
                  s for suspicious mode.  In normal mode any blank tapes will 
                  be labelled.  In suspicious mode only tapes in slots 15 and 
                  16 will be labelled.  The default mode (without -l specified)
                  is to report the presence of blank tapes, no labelling will
                  happen.

  -d[d]    debug  Output detailing what is going on is sent to STDOUT. If a 
                  second d is specified then set -x is turned on as well.
Example:
  To run `basename $0` in suspicious mode with standard debugging
  `basename $0` -ls -d

EOF
	return 1
fi

if [ "$DEBUG" = "REALLY ON" ];then
	set -x
fi

# first things first - make sure there are no other amanda processes running
PROCS=`ps -ef | grep amanda | grep -v $$`
if [ -n "$PROCS" ];then
	# something else might be using the tape drive, bail out
cat<<EOF
Another amanda process was found running!
To prevent possible problems this script will not run.
EOF
	return 2 
fi

# assorted variables
BACKUP_TYPE="BACKUP_NAME"
MAX_SLOTS=18
CUR_SLOT=0
KEEP_LOOPING=0

# file locations
BASE_DIR="/opt/local/amanda/etc/$BACKUP_TYPE/"
STATUS_FILE="${BASE_DIR}tape0-status"
SLOT_FILE="${BASE_DIR}tape0-slot"

# zero out the status file and grab the new file size (which should be 0 now)
cat /dev/null > $STATUS
STATUS_SIZE=`ls -l $STATUS_FILE | awk '{print $5}'`
[ -n "$DEBUG" ] && echo "STATUS_SIZE=$STATUS_SIZE"

echo "Started scanning on `date`"
while [ $KEEP_LOOPING -eq 0 ]
do
	# is there a process running?
	if [ -z "$SCAN_PROC" ];then
		# no - kick off a tape change
		/opt/local/amanda/sbin/amtape $BACKUP_TYPE slot $CUR_SLOT > /dev/null 2>&1 &
		SCAN_PROC=$!
		[ -n "$DEBUG" ] && echo "Kicked off amtape $BACKUP_TYPE slot $CUR_SLOT (pid=$SCAN_PROC)"
	else
		# make sure the process is still out there
		[ -n "$DEBUG" ] && echo "Looking for PID $SCAN_PROC..."
		ps -e | /usr/xpg4/bin/grep -qe "^ *$SCAN_PROC"
		if [ $? = 0 ];then
			# still there - check the slot file
			[ -n "$DEBUG" ] && echo "Found $SCAN_PROC, checking $STATUS_FILE"
			NEW_SIZE=`ls -l $STATUS_FILE | awk '{print $5}'`
			# there can be a size diff of 1155 bytes - this is output everytime the
			# robot does something without screwing up
			ACCEPTABLE_SIZE=$(($STATUS_SIZE+1156))
			if [ $STATUS_SIZE -ne $NEW_SIZE ] && [ $NEW_SIZE -gt $ACCEPTABLE_SIZE ];then
				[ -n "$DEBUG" ] && echo "$STATUS_FILE was $STATUS_SIZE, now $NEW_SIZE!"
				[ -n "$DEBUG" ] && echo "Killing pids..."
				# kill the procs and try again. Have to kill the amtape process and
				# the /opt/local/amanda/libexec/chg-scsi process which is actually 
				# doing the work and writing to the error file
				#SCSI_PID=`echo \`fuser $STATUS_FILE 2>/dev/null\``
				SCSI_PID=`ps -eo pid,ppid,args | egrep "${SCAN_PROC}.*scsi" | awk '{print $1}'`
				for PROC_TO_KILL in $SCAN_PROC $SCSI_PID
				do
					kill $PROC_TO_KILL
					LOOP_COUNT=0
					# wait for it to die
					while [ $PROC_TO_KILL -ne 0 ]
					do
						LOOP_COUNT=$(($LOOP_COUNT+1))
						ps -e | /usr/xpg4/bin/grep -q $PROC_TO_KILL
						if [ $? = 1 ];then
							PROC_TO_KILL=0
						else
							if [ $LOOP_COUNT -eq 10 ];then
								# hmm, doesn't want to die
								kill -9 $PROC_TO_KILL
								PROC_TO_KILL=0
							else
								sleep 1
							fi #[ $LOOP_COUNT -eq 10 ]
						fi #[ $? = 1 ]
					done #while [ $PROC_TO_KILL -ne 0 ]
				done #for PROC_TO_KILL in $SCAN_PROC $SCSI_PID
				# do a scsi reset, to be sure, to be sure - first the L20
				/usr/local/bin/cdrecord dev=2,0,0 -reset > /dev/null 2>&1
				sleep 5
				# now the DLT7000
				/usr/local/bin/cdrecord dev=2,1,0 -reset > /dev/null 2>&1
				sleep 5
				# clean out the err file and reset the status file size again
				cat /dev/null > $STATUS_FILE
				STATUS_SIZE=`ls -l $STATUS_FILE | awk '{print $5}'`
				SCAN_PROC=""
				# all done, the next iteration will start up amtape again
				[ -n "$DEBUG" ] && echo "Done...Going back to try again."
			else
				# give it a chance to do something useful
				sleep 10
			fi #[ $STATUS_SIZE -ne $NEW_SIZE ] && [ $NEW_SIZE -ne $ACCEPTABLE_SIZE ]
		else
			# hmmm, amtape process has disappeared, hopefully it finished nicely.
			# try to get the label
			# First, check for a tape.  This is what comes back if there is a tape in the drive:
			#Quantum DLT8000 tape drive:
			#   sense key(0x12)= EOF   residual= 0   retries= 0
			#   file no= 0   block no= 0
			#
			# and this is with no tape:
			#
			#/dev/rmt/0: no tape loaded or drive offline
			[ -n "$DEBUG" ] && echo "Scan finished, checking tape..."
			SCAN_PROC=""
			mt -f /dev/rmt/0 status >/dev/null 2>&1
			RETVAL=$?
			if [ $RETVAL -eq 0 ];then
				# get the label
				LABEL=`dd if=/dev/rmt/0 bs=32k 2>/dev/null | tr -d '\014' | head -1`
				# blank tape?
				if [ -z "$LABEL" ];then
					echo "Physical Slot=$CUR_SLOT:BLANK tape in slot"
					# are we meant to be labelling?
					if [ -n "$LABEL_PREFIX" ];then
						# yes, are we in suspicious mode?
						if [ -z "$SUSPICIOUS" ];then
							# no - just label the tape
							echo "Labeling blank tape in slot $CUR_SLOT as ${LABEL_PREFIX}${LABEL_SUFFIX}"
							amlabel BACKUP-NAME ${LABEL_PREFIX}${LABEL_SUFFIX}
						elif [ $CUR_SLOT -eq 15 ] || [ $CUR_SLOT -eq 16 ]; then
							# yes, we are suspicious and the tape is in the right slot so label the tape
							echo "Labeling blank tape in slot $CUR_SLOT as ${LABEL_PREFIX}${LABEL_SUFFIX}"
							amlabel BACKUP_NAME ${LABEL_PREFIX}${LABEL_SUFFIX}
						else
							echo "Blank tape in slot $CUR_SLOT has NOT been labeled, I only expect blank tapes in slot 15 and 16"
						fi

						# increment the suffix, should only ever reach 'b' but
						# better safe than sorry
						LABEL_SUFFIX=`perl -e 'print ord($ARGV[0]), "\n"' $LABEL_SUFFIX`
						LABEL_SUFFIX=$(($LABEL_SUFFIX+1))
						LABEL_SUFFIX=`perl -e 'printf "%c\n", $ARGV[0]' $LABEL_SUFFIX`
					fi
				else
					# print the slot number and the tape label
					TYPE=`echo $LABEL | sed 's/.*\(BACKUP-NAME.*\)$/\1/'`
					echo "Physical Slot=$CUR_SLOT:Label=`echo $LABEL | cut -f4 -d' '` label $TYPE"
				fi #[ -z "$LABEL" ]
			else
				echo "Physical Slot=$CUR_SLOT:No tape in slot"
			fi #[ $RETVAL -eq 0 ]
			# now increment the slot number for the next amtape run
			CUR_SLOT=`cat $SLOT_FILE`
			if [ "$CUR_SLOT" = "$MAX_SLOTS" ];then
				# we're done
				KEEP_LOOPING=1
				#echo 0>$SLOT_FILE
			else
				CUR_SLOT=$(($CUR_SLOT+1))
			fi
			[ -n "$DEBUG" ] && echo "Slot changed to $CUR_SLOT..."
		fi #[ $? = 0 ]
	fi #[ -z "$SCAN_PROC" ]
done #[ $KEEP_LOOPING -eq 0 ]
echo "Scanning completed on `date`"
return 0