#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2.1).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2007-05-18 17:01 PDT by <amandabackup@paddy.zmanda.com>.
# Source directory was `/var/lib/amanda'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#  40722 -rwxr-xr-x /usr/lib/amanda/chg-zd-mtx
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
  shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
  shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
  shar_touch='touch -am $3$4$5$6$2 "$8"'
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
#
if mkdir _sh00379; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= /usr/lib/amanda/chg-zd-mtx ==============
if test ! -d '/usr'; then
  $echo 'x -' 'creating directory' '/usr'
  mkdir '/usr'
fi
if test ! -d '/usr/lib'; then
  $echo 'x -' 'creating directory' '/usr/lib'
  mkdir '/usr/lib'
fi
if test ! -d '/usr/lib/amanda'; then
  $echo 'x -' 'creating directory' '/usr/lib/amanda'
  mkdir '/usr/lib/amanda'
fi
if test -f '/usr/lib/amanda/chg-zd-mtx' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING '/usr/lib/amanda/chg-zd-mtx' '(file already exists)'
else
  $echo 'x -' extracting '/usr/lib/amanda/chg-zd-mtx' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > '/usr/lib/amanda/chg-zd-mtx' &&
#!/bin/sh 
#
# Exit Status:
# 0 Alles Ok
# 1 Illegal Request
# 2 Fatal Error
#
# Contributed by Eric DOUTRELEAU <Eric.Doutreleau@int-evry.fr>
# This is supposed to work with Zubkoff/Dandelion version of mtx
#
# Modified by Joe Rhett <jrhett@isite.net>
# to work with MTX 1.2.9 by Eric Lee Green http://mtx.sourceforge.net
#
# Modified by Jason Hollinden <jhollind@sammg.com> on 13-Feb-2001
# to work with MTX 1.2.10, >9 slots, has barcode support, and works with
# multiple configs at once.
# NOTE:  Only tested the 2 additions with an ADIC Scalar 100.
X
################################################################################
# Here are the things you need to do and know to configure this script:
#
#   * Figure out what the robot device name is and what the tape drive
#     device name is.  They will be different!
#
#     You cannot send robot commands to a tape drive and vice versa.
#     Both should respond to "mtx -f /dev/... inquiry".  Hopefully,
#     that output will make it obvious which is which.
#
#     For instance, here is what mtx has to say about my current robot:
#
#       Product Type: Medium Changer
#       Vendor ID: 'ATL     '
#       Product ID: 'ACL2640 206     '
#       Revision: '2A5A'
#       Attached Changer: No
#
#     and here is what it says about a tape drive:
#
#       Product Type: Tape Drive
#       Vendor ID: 'Quantum '
#       Product ID: 'DLT4000         '
#       Revision: 'CD50'
#       Attached Changer: No
#
#     Note the "Product Type" value makes it clear which is which.
#
#     If it is not obvious, "mf -f /dev/... rewind" should be happy when
#     talking to a (loaded) tape drive but the changer should give some
#     kind of error.  Similarly, "mtx -f /dev/... status" should show good
#     results with the changer but fail with a tape drive device name.
#
#     Once you have this figured out, set "changerdev" in amanda.conf
#     to the changer device and "tapedev" to the tape device.
#
#   * Find out what the first and last storage slots are.  Running
#     "mtx -f /dev/... status" should give you something like this
#     (although the output will vary widely based on the version of mtx
#     and the specifics of your robot):
#
#	  Storage Changer /dev/changer:1 Drives, 9 Slots ( 0 Import/Export )
#	Data Transfer Element 0:Empty
#	      Storage Element 1:Full :VolumeTag=SR0001
#	      Storage Element 2:Full :VolumeTag=SR0002
#	      Storage Element 3:Full :VolumeTag=SR0003
#	      Storage Element 4:Full :VolumeTag=SR0004
#	      Storage Element 5:Full :VolumeTag=SR0005
#	      Storage Element 6:Full :VolumeTag=SR0006
#	      Storage Element 7:Full :VolumeTag=SR0007
#	      Storage Element 8:Full :VolumeTag=SR0008
#	      Storage Element 9:Full :VolumeTag=SR0009
#	      Storage Element 10 IMPORT/EXPORT:Full :VolumeTag=SR0009
#
#     This says the first storage slot (element) is "1" and the last
#     is "9".  If you allocate the entire robot to Amanda, you do not need
#     to set the "firstslot" or "lastslot" configuration file variables --
#     the script will compute these values for you.
#
#     You do not have to allocate all of the slots for Amanda use,
#     but whatever slots you use must be contiguous (i.e. 4 through 9
#     in the above would be OK but 1, 2, 5, 6, 9 would not).  The one
#     exception to this is that if one of the slots contains a cleaning
#     cartridge, it may be in any slot (Amanda will just skip over it if
#     it is between firstslot and lastslot).
#
#   * Speaking of cleaning cartridges, if you have a storage slot dedicated
#     to one, figure out what slot it is in.  That slot number will go in
#     the "cleanslot" variable.
#
#     Also, decide if you want the changer script to automatically run
#     the cleaning tape through the drive after every so many mounts,
#     and how many mounts you want to do between cleanings.  If you
#     want the script to do this, set the "autoclean" variable to 1 and
#     the "autocleancount" to the number of mounts between cleanings.
#     If you do not want to do automatic cleanings (including not having
#     a cleaning cartridge in the robot), set "autoclean" to 0.
#
#     Note that only a count of mounts is used to determine when it is
#     time to clean.  The script does not try to detect if the drive is
#     requesting cleaning, or how much the drive was used on a given
#     mount.
#
#   * If you tell Amanda about a cleaning cartridge, whether for automatic
#     operation or manual (amtape <config> clean), you must also tell
#     the script how long it takes to run the cleaning cycle.  It is
#     impossible for the script to determine when the cleaning operation
#     is done, so the "cleancycle" variable is the number of seconds
#     the longest cleaning operation takes (you'll just have to figure
#     this out by watching it a few times, or maybe finding it in a tape
#     drive hardware manual).  The script will sleep for this length of
#     time whenever the cleaning tape is referenced.  The default is 120
#     seconds (two minutes).
#
#   * Figure out the drive slot number.  By default, it is set to 0.
#     In the example above, the tape drive ("Data Transfer Element")
#     is in slot 0. If your drive slot is not 0, you
#     need to set the drive slot number with the "driveslot" variable.
#
#   * Figure out whether your robot has a barcode reader and whether
#     your version of mtx supports it.  If you see "VolumeTag" entries
#     in the "mtx -f /dev/xxx status" output you did above, you have
#     a reader and mtx can work with it, so you may set the "havereader"
#     variable to 1.  The default is 0 (do not use a reader).
#
#   * Pick any tape to load and then determine if the robot can put it
#     away directly or whether an "offline" must be done first.
#
#     With the tape still mounted and ready, try to put the tape away
#     with "mtx".  If you get some kind of error, which is the most
#     common response, try "mt -f /dev/... offline", wait for the drive
#     to unload and make sure the robot takes no action on its own to
#     store the tape.  Assuming it does not, try the "mtx" command again
#     to store the tape.
#
#     If you had to issue the "mt -f /dev/... offline" before you could
#     use "mtx" to store the tape, set the "offline_before_unload"
#     variable to 1.  If "mtx" unloaded the drive and put the tape away
#     all by itself, set it to 0.
#
#   * Some drives and robots require a small delay between unloading the
#     tape and instructing the robot to move it back to storage.
#     For instance, if you try to grab the tape too soon on an ATL robot
#     with DLT tape drives, it will rip the leader out of the drive and
#     require sincerely painful hardware maintenance.
#
#     If you need a little delay, set the "unloadpause" variable to
#     the number of seconds to wait before trying to take a tape from
#     a drive back to storage.  The default is 0.
#
#   * Some drives also require a short pause after loading, or the drive
#     will return an I/O error during a test to see if it's online (which
#     this script uses "mt rewind" to test).  My drives don't recover from
#     this, and must be reloaded before they will come online after failing
#     such a test.  For this reason there is an "initial_poll_delay"
#     variable which will pause for a certain number of seconds before
#     looping through the online test for the first time.  The default is 0.
####
X
####
# Now you are ready to set up the variables in the changer configuration
# file.
#
# All variables are in "changerfile".conf where "changerfile" is set
# in amanda.conf.  For example, if amanda.conf has:
#
#	changerfile="/etc/amanda/Dailyset1/CHANGER"
#    or changerfile="/etc/amanda/Dailyset1/CHANGER.conf"
#
# the variables must be in "/etc/amanda/Dailyset1/CHANGER.conf".
# The ".conf" is appended only if it's not there".
#
# If "changerfile" is a relative path, it is relative to the directory
# that contains amanda.conf.  That also happens to be the directory Amanda
# makes current before running this script.
#
# Here is a commented out example file with all the variables and showing
# their default value (if any):
####
# firstslot=?		    #### First storage slot (element) -- required
# lastslot=?		    #### Last storage slot (element) -- required
# cleanslot=-1		    #### Slot with cleaner tape -- default is "-1"
#			    #### Set negative to indicate no cleaner available
# driveslot=0		    #### Drive slot number.  Defaults to 0
#			    #### Use the 'Data Transfer Element' you want
#
#   # Do you want to clean the drive after a certain number of accesses?
#   # NOTE - This is unreliable, since 'accesses' aren't 'uses', and we
#   #        have no reliable way to count this.  A single amcheck could
#   #        generate as many accesses as slots you have, plus 1.
#   # ALSO NOTE - many modern tape loaders handle this automatically.
#
# autoclean=0		    #### Set to '1' or greater to enable
#
# autocleancount=99	    #### Number of access before a clean.
#
# havereader=0		    #### If you have a barcode reader, set to 1.
#
# offline_before_unload=0   #### Does your robot require an
#			    #### 'mt offline' before mtx unload?
#
# poll_drive_ready=NN	    #### Time (seconds) between tests to see if
#			    #### the tape drive has gone ready (default: 3).
#
# max_drive_wait=NN	    #### Maximum time (seconds) to wait for the
#			    #### tape drive to become ready (default: 120).
#
# initial_poll_delay=NN	    #### initial delay after load before polling for
#			    #### readiness
#
####
X
####
# Now it is time to test the setup.  Do all of the following in the
# directory that contains the amanda.conf file, and do all of it as
# the Amanda user.
#
#   * Run this:
#
#       .../chg-zd-mtx -info
#       echo $?             #### (or "echo $status" if you use csh/tcsh)
#
#     You should get a single line from the script like this (the actual
#     numbers will vary):
#
#       5 9 1 1
#
#     The first number (5) is the "current" slot.  This may or may not be
#     the slot actually loaded at the moment (if any).  It is the slot
#     Amanda will try to use next.
#
#     The second number (9) is the number of slots.
#
#     The third number will always be "1" and indicates the changer is
#     capable of going backward.
#
#     The fourth number is optional.  If you set $havereader to 1, it
#     will be "1", otherwise it will not be present.
#
#     The exit code ($? or $status) should be zero.
#
#   * Run this:
#
#       .../chg-zd-mtx -reset
#       echo $?
#
#     The script should output a line like this:
#
#       1 /dev/rmt/0mn
#
#     The number at the first should match $firstslot.  The device name
#     after that should be your tape device.
#
#     The exit code ($? or $status) should be zero.
#
#   * Run this:
#
#       .../chg-zd-mtx -slot next
#       echo $?
#
#     The script should output a line like this:
#
#       2 /dev/rmt/0mn
#
#     The number at the first should be one higher than $firstslot.
#     The device name after that should be your tape device.
#
#     The exit code ($? or $status) should be zero.
#
#   * Run this:
#
#       .../chg-zd-mtx -slot current
#       echo $?
#
#     Assuming the tape is still loaded from the previous test, the
#     robot should not move and the script should report the same thing
#     the previous command did.
#
#   * If you continue to run "-slot next" commands, the robot should load
#     each tape in turn then wrap back around to the first when it
#     reaches $lasttape.  If $cleanslot is within the $firstslot to
#     $lastslot range, the script will skip over that entry.
#
#   * Finally, try some of the amtape commands and make sure they work:
#
#       amtape <config> reset
#       amtape <config> slot next
#       amtape <config> slot current
#
#   * If you set $havereader non-zero, now would be a good time to create
#     the initial barcode database:
#
#       amtape <config> update
####
X
################################################################################
# To debug this script, first look in /tmp/amanda.  The script
# uses one of two log files there, depending on what version of Amanda
# is calling it.  It may be chg-zd-mtx.YYYYMMDD*.debug, or it may be
# changer.debug.driveN where 'N' is the drive number.
#
# If the log file does not help, try running the script, **as the Amanda
# user**, in the amanda.conf directory with whatever set of args the log
# said were used when you had a problem.  If nothing else useful shows up
# in the output, try running the script with the DEBUG environment variable
# set non-null, e.g.:
#
#	env DEBUG=yes .../chg-zd-mtx ...
################################################################################
X
# source utility functions and values from configure
exec_prefix=/usr/local
libexecdir=${exec_prefix}/libexec
X. ${libexecdir}/chg-lib.sh
X
test -n "$DEBUG" && set -x
TMPDIR="/tmp/amanda"
DBGDIR="/tmp/amanda"
X
# support simultaneous development with and without gettext
function _() {
X	fmt="$1"
X	shift
X	printf "$fmt" $*
}
X
argv0=$0
myname=`expr "$argv0" : '.*/\(.*\)'`
X
config=`pwd 2>/dev/null`
config=`expr "$config" : '.*/\(.*\)'`
X
###
# Functions to write a new log file entry and append more log information.
###
X
ds=`date '+%H:%M:%S' 2>/dev/null`
if [ $? -eq 0  -a  -n "$ds" ]; then
X	logprefix=`echo "$ds" | sed 's/./ /g'`
else
X	logprefix=""
fi
X
LogAppend() {
X	if [ -z "$logprefix" ]; then
X		echo "$@" >> $DBGFILE
X	else
X		echo "$logprefix" "$@" >> $DBGFILE
X	fi
}
X
Log() {
X	if [ -z "$logprefix" ]; then
X		echo "===" "`date`" "===" >> $DBGFILE
X		echo "$@" >> $DBGFILE
X	else
X		ds=`date '+%H:%M:%S' 2>/dev/null`
X		echo "$ds" "$@" >> $DBGFILE
X	fi
}
X
###
# Common exit function.
#
#   $1 = exit code
#   $2 = slot result
#   $3 = additional information (error message, tape devive, etc)
###
X
internal_call=0
Exit() {
X	if [ $internal_call -gt 0 ]; then
X		call_type=Return
X	else
X		call_type=Exit
X	fi
X	code=$1
X	shift
X	exit_slot=$1
X	shift
X	exit_answer="$@"
X	Log $call_type "($code) -> $exit_slot $@"
X	echo "$exit_slot" "$@"
X	if [ $call_type = Return ]; then
X		return $code
X	fi
X	amgetconf$SUF dbclose.$argv0:$DBGFILE > /dev/null 2>&1
X	exit $code
}
X
###
# Function to run another command and log it.
###
X
Run() {
X	Log `_ 'Running: %s' "$@"`
X	rm -f $stdout $stderr
X	"$@" > $stdout 2> $stderr
X	exitcode=$?
X	Log `_ 'Exit code: %s' "$exitcode"`
X	if [ -s $stdout ]
X	then
X		LogAppend Stdout:
X		cat $stdout >> $DBGFILE
X	fi
X	if [ -s $stderr ]
X	then
X		LogAppend Stderr:
X		cat $stderr >> $DBGFILE
X	fi
X	cat $stdout
X	cat $stderr 1>&2
X	return $exitcode
}
X
###
# Return success if the arg is numeric.
###
X
IsNumeric() {
X	test -z "$1" && return 1
X	x="`expr "$1" : '\([-0-9][0-9]*\)' 2>/dev/null`"
X	return `expr X"$1" != X"$x"`
}
X
###
# Run $MTX status unless the previous output is still valid.
###
X
mtx_status_valid=0
get_mtx_status() {
X	test -n "$DEBUG" && set -x
X	if [ $mtx_status_valid -ne 0 ]; then
X		return 0
X	fi
X	rm -f $mtx_status
X	Run $MTX status > $mtx_status 2>&1
X	status=$?
X	if [ $status -eq 0 ]; then
X		mtx_status_valid=1
X	fi
X	return $status
}
X
###
# Determine the slot currently loaded.  Set $loadedslot to the slot
# currently loaded, or "-1", and $loadedbarcode to the corresponding
# barcode (or nothing).
###
X
get_loaded_info() {
X	test -n "$DEBUG" && set -x
X	get_mtx_status
X
X	set x `sed -n '
/^Data Transfer Element:Empty/                          {
X    s/.*/-1/p
X    q
}
/^Data Transfer Element '$driveslot':Empty/             {
X    s/.*/-1/p
X    q
}
/^Data Transfer Element:Full (Storage Element \([0-9][0-9]*\) Loaded):VolumeTag *= *\([^     ]*\)/               {
X    s/.*(Storage Element \([0-9][0-9]*\) Loaded):VolumeTag *= *\([^     ]*\)/\1 \2/p
X    q
}
/^Data Transfer Element '$driveslot':Full (Storage Element \([0-9][0-9]*\) Loaded):VolumeTag *= *\([^     ]*\)/  {
X    s/.*(Storage Element \([0-9][0-9]*\) Loaded):VolumeTag *= *\([^     ]*\)/\1 \2/p
X    q
}
/^Data Transfer Element '$driveslot':Full (Unknown Storage Element Loaded):VolumeTag *= *\([^     ]*\)/	{
X    s/.*:VolumeTag *= *\([^     ]*\)/-2 \1/p
X    q
}
/^Data Transfer Element:Full (Storage Element \([0-9][0-9]*\) Loaded)/                           {
X    s/.*(Storage Element \([0-9][0-9]*\) Loaded).*/\1/p
X    q
}
/^Data Transfer Element '$driveslot':Full (Storage Element \([0-9][0-9]*\) Loaded)/              {
X    s/.*Storage Element \([0-9][0-9]*\) Loaded.*/\1/p
X    q
}
/^Data Transfer Element '$driveslot':Full (Unknown Storage Element Loaded)/	{
X    s/.*/-2/p
X    q
}
' < $mtx_status 2>&1`
X	shift					# get rid of the "x"
X	loadedslot=$1
X	loadedbarcode=$2
X	if [ -z "$loadedslot" ]; then
X		Exit 2 \
X		    `_ '<none>'` \
X		    "could not determine current slot, are you sure your drive slot is $driveslot"
X		return $?			# in case we are internal
X	fi
X
X	#Use the current slot if it's empty and we don't know which slot is loaded'
X	if [ $loadedslot -eq -2 ]; then
X		set x `sed -n '
{
X    /^.*Storage Element '$currentslot':Empty/ {
X	s/.*Storage Element \([0-9][0-9]*\):Empty/\1/p
X        q
X    }
X    /^.*Storage Element '$currentslot':Full/ {
X	s/.*Storage Element \([0-9][0-9]*\):Full/-2/p
X        q
X    }
X    /^.*Storage Element '$currentslot' IMPORT\/EXPORT:Empty/ {
X	s/.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Empty/\1/p
X        q
X    }
X    /^.*Storage Element '$currentslot' IMPORT\/EXPORT:Full/ {
X	s/.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Full/-2/p
X        q
X    }
}
' < $mtx_status 2>& 1`
X		shift				# get rid of the "x"
X		loadedslotx=$1
X		if [ ! -z $loadedslotx ]; then
X			loadedslot=$loadedslotx
X		fi
X	fi
X
X	#Use the first empty slot if we don't know which slot is loaded'
X	if [ $loadedslot -eq -2 ]; then
X		set x `sed -n '
{
X    /^.*Storage Element \([0-9][0-9]*\):Empty/ {
X	s/.*Storage Element \([0-9][0-9]*\):Empty/\1/p
X        q
X    }
X    /^.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Empty/ {
X	s/.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Empty/\1/p
X        q
X    }
}
' < $mtx_status 2>& 1`
X		shift				# get rid of the "x"
X		loadedslot=$1
X	fi
X
X	if IsNumeric "$loadedslot" ; then
X		:
X	else
X		Exit 2 \
X		     `_ '<none>'` \
X		     "currently loaded slot ($loadedslot) not numeric"
X		return $?			# in case we are internal
X	fi
X	Log       `_ 'STATUS   -> currently loaded slot = %s' "$loadedslot"`
X	LogAppend `_ '         -> currently loaded barcode = "%s"' "$loadedbarcode"`
}
X
###
# Get a list of slots between $firstslot and $lastslot, if they are set.
# If they are not set, set them to the first and last slot seen on the
# assumption the entire robot is to be used (???).
###
X
slot_list=
get_slot_list() {
X	test -n "$DEBUG" && set -x
X	if [ -n "$slot_list" ]; then
X		return
X	fi
X	get_mtx_status
X	slot_list=`sed -n '
/^Data Transfer Element:Full (Storage Element \([0-9][0-9]*\) Loaded)/ {
X    s/.*(Storage Element \([0-9][0-9]*\) Loaded).*/\1/p
}
/^Data Transfer Element '$driveslot':Full (Storage Element \([0-9][0-9]*\) Loaded)/ {
X    s/.*Storage Element \([0-9][0-9]*\) Loaded.*/\1/p
}
/^Data Transfer Element '$driveslot':Full (Unknown Storage Element Loaded)/ {
X    : loop
X    n
X    /^.*Storage Element \([0-9][0-9]*\):Full/ {
X        s/.*Storage Element \([0-9][0-9]*\):Full.*/\1/p
X        b loop
X    }
X    /^.*Storage Element \([0-9][0-9]*\):Empty/ {
X	s/.*Storage Element \([0-9][0-9]*\):Empty/\1/p
X    }
}
/^.*Storage Element \([0-9][0-9]*\):Full/ {
X    s/.*Storage Element \([0-9][0-9]*\):Full.*/\1/p
}
/^.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Full/ {
X    s/.*Storage Element \([0-9][0-9]*\) IMPORT\/EXPORT:Full.*/\1/p
}
' < $mtx_status 2>&1 | grep -v "^${cleanslot}\$" | sort -n`
X	slot_list=`echo $slot_list`		# remove the newlines
X	if [ $firstslot -lt 0 -o $lastslot -lt 0 ]; then
X		last=$lastslot
X		for slot in $slot_list; do
X			if [ $firstslot -lt 0 ]; then
X				Log `_ 'SLOTLIST -> firstslot set to %s' "$slot"`
X				firstslot=$slot
X			fi
X			if [ $lastslot -lt 0 ]; then
X				last=$slot
X			fi
X		done
X		if [ $lastslot -lt 0 -a $last -ge 0 ]; then
X			Log `_ 'SLOTLIST -> lastslot set to %s' "$last"`
X			lastslot=$last
X		fi
X		if [ $firstslot -lt 0 ]; then
X			Exit 2 \
X			     `_ '<none>'` \
X			     `_ 'cannot determine first slot'`
X			return $?		# in case we are internal
X		elif [ $lastslot -lt 0 ]; then
X			Exit 2 \
X			     `_ '<none>'` \
X			     `_ 'cannot determine last slot'`
X			return $?		# in case we are internal
X		fi
X	fi
X	amanda_slot_list=
X	for slot in $slot_list; do
X		if [ $slot -ge $firstslot -a $slot -le $lastslot ]; then
X			amanda_slot_list="$amanda_slot_list $slot"
X		fi
X	done
X	if [ -z "$amanda_slot_list" ]; then
X		Exit 2 \
X		     `_ '<none>'` \
X		     "no slots available"
X		return $?			# in case we are internal
X	fi
X	slot_list="$amanda_slot_list"
}
X
# Paths
prefix=/usr/local
exec_prefix=/usr/local
sbindir=${exec_prefix}/sbin
libexecdir=${exec_prefix}/libexec
X
# try to hit all the possibilities here
PATH=$sbindir:$libexecdir:/usr/bin:/bin:/usr/sbin:/sbin:/usr/ucb:/usr/local/bin
export PATH
X
USE_VERSION_SUFFIXES="no"
if test "$USE_VERSION_SUFFIXES" = "yes"; then
X	SUF="-2.5.2b1"
else
X	SUF=
fi
X
DBGFILE=`amgetconf$SUF dbopen.$argv0 2>/dev/null`
if [ -z "$DBGFILE" ]
then
X	DBGFILE=/dev/null			# will try this again below
fi
X
changerfile=`amgetconf$SUF changerfile 2>/dev/null`
if [ -z "$changerfile" ]; then
X	Exit 2 \
X	     `_ '<none>'` \
X	     "changerfile must be specified in amanda.conf"
fi
X
tape=`amgetconf$SUF tapedev 2>/dev/null`
if [ -z "$tape" ]; then
X	Exit 2 \
X	     `_ '<none>'` \
X	     "tapedev may not be empty"
elif [ $tape = "/dev/null" -o `expr "$tape" : 'null:'` -eq 5 ]; then
X	Exit 2 \
X	     `_ '<none>'` \
X	     "tapedev ($tape) may not be the null device"
fi
TAPE=`amgetconf$SUF changerdev 2>/dev/null`
if [ -z "$TAPE" ]; then
X	Exit 2 \
X	     `_ '<none>'` \
X	     "changerdev may not be empty"
elif [ $TAPE = "/dev/null" ]; then
X	Exit 2 \
X	     `_ '<none>'` \
X	     "changerdev ($TAPE) may not be the null device"
fi
export TAPE					# for mtx command
X
CHANGER=$TAPE
export CHANGER					# for mtx command
X
#### Set up the various config files.
X
conf_match=`expr "$changerfile" : .\*\.conf\$`
if [ $conf_match -ge 6 ]; then
X	configfile=$changerfile
X	changerfile=`echo $changerfile | sed 's/.conf$//g'`
else
X	configfile=$changerfile.conf
fi
X
if [ ! -e $configfile ]; then
X	Exit 2 \
X	     `_ '<none>'` \
X	     "configuration file \"$configfile\" doesn't exist"
fi
if [ ! -f $configfile ]; then
X	Exit 2 \
X	     `_ '<none>'` \
X	     "configuration file \"$configfile\" is not a file"
fi
X
cleanfile=$changerfile-clean
accessfile=$changerfile-access
slotfile=$changerfile-slot
labelfile=$changerfile-barcodes
[ ! -s $cleanfile ] && echo 0 > $cleanfile
[ ! -s $accessfile ] && echo 0 > $accessfile
[ ! -s $slotfile ] && echo -1 > $slotfile
[ ! -f $labelfile ] && > $labelfile
cleancount=`cat $cleanfile`
accesscount=`cat $accessfile`
X
test -z "$MT" && Exit 2 "<none>" "No mt command defined"
test ! -f "$MT" && Exit 2 "<none>" "mt command ($MT) doesn't exist"
test -z "$MTX" && Exit 2 "<none>" "No mtx command defined"
test ! -f "$MTX" && Exit 2 "<none>" "mtx command ($MTX) doesn't exist"
X
#### Dig out of the config file what is needed
X
varlist=
varlist="$varlist firstslot"
varlist="$varlist lastslot"
varlist="$varlist cleanslot"
varlist="$varlist cleancycle"
varlist="$varlist OFFLINE_BEFORE_UNLOAD"	# old name
varlist="$varlist offline_before_unload"
varlist="$varlist unloadpause"
varlist="$varlist AUTOCLEAN"			# old name
varlist="$varlist autoclean"
varlist="$varlist autocleancount"
varlist="$varlist havereader"
varlist="$varlist driveslot"
varlist="$varlist poll_drive_ready"
varlist="$varlist initial_poll_delay"
varlist="$varlist max_drive_wait"
X
for var in $varlist
do
X	val="`cat $configfile 2>/dev/null | sed -n '
# Ignore comment lines (anything starting with a #).
/^[ 	]*#/d
# Find the first var=val line in the file, print the value and quit.
/^[ 	]*'$var'[ 	]*=[ 	]*\([^ 	][^ 	]*\).*/	{
X	s/^[ 	]*'$var'[ 	]*=[ 	]*\([^ 	][^ 	]*\).*/\1/p
X	q
}
'`"
X	eval $var=\"$val\"
done
X
# Deal with driveslot first so we can get DBGFILE set if we are still
# using the old amgetconf.
X
if [ -z "$driveslot" ]; then
X	driveslot=0;
fi
X
# Get DBGFILE set if it is not already.
X
if [ $DBGFILE = /dev/null ]; then
X	if [ -d "$DBGDIR" ]; then
X		DBGFILE=$DBGDIR/changer.debug.drive$driveslot
X	else
X		DBGFILE=/dev/null
X	fi
X	Log `_ '=== Start %s ===' "\`date\`"`
fi
if [ -z "$driveslot" ]; then
X	Exit 2 \
X	     `_ '<none>'` \
X	     `_ 'cannot determine drive slot from %s' "$tape"`
fi
X
stdout=$TMPDIR/$myname.1.$$
stderr=$TMPDIR/$myname.2.$$
mtx_status=$TMPDIR/$myname.status.$$
trap "rm -f $stdout $stderr $mtx_status" 0	# exit cleanup
X
Log `_ 'Using config file %s' "$configfile"`
X
# Log the argument list.
X
Log `_ "Arg info:"`
LogAppend "\$# = $#"
i=0
LogAppend "\$$i = \"$argv0\""
for arg in "$@"; do
X	i=`expr $i + 1`
X	LogAppend "\$$i = \"$arg\""
done
X
# Set the default config values for those not in the file.  Log the
# results and make sure each is valid (numeric).
X
firstslot=${firstslot:-'-1'}				# default: mtx status
lastslot=${lastslot:-'-1'}				# default: mtx status
cleanslot=${cleanslot:-'-1'}				# default: -1
cleancycle=${cleancycle:-'120'}				# default: two minutes
if [ -z "$offline_before_unload" -a -n "$OFFLINE_BEFORE_UNLOAD" ]; then
X	offline_before_unload=$OFFLINE_BEFORE_UNLOAD	# (old name)
fi
offline_before_unload=${offline_before_unload:-'0'}	# default: 0
unloadpause=${unloadpause:-'0'}				# default: 0
if [ -z "$autoclean" -a -n "$AUTOCLEAN" ]; then
X	autoclean=$AUTOCLEAN				# (old name)
fi
autoclean=${autoclean:-'0'}				# default: 0
autocleancount=${autocleancount:-'99'}			# default: 99
havereader=${havereader:-'0'}				# default: 0
poll_drive_ready=${poll_drive_ready:-'3'}		# default: three seconds
initial_poll_delay=${initial_poll_delay:-'0'}		# default: zero zeconds
max_drive_wait=${max_drive_wait:-'120'}			# default: two minutes
X
get_slot_list
X
Log `_ "Config info:"`
for var in $varlist; do
X	if [ $var = "OFFLINE_BEFORE_UNLOAD" ]; then
X		continue			# old name
X	elif [ $var = "AUTOCLEAN" ]; then
X		continue			# old name
X	fi
X	eval val=\"'$'$var\"
X	if [ -z "$val" ]; then
X		Exit 2 \
X		     `_ '<none>'` \
X		     `_ '%s missing in %s' "$var" "$configfile"`
X	fi
X	if IsNumeric "$val" ; then
X		:
X	else
X		Exit 2 \
X		     `_ '<none>'` \
X		     `_ '%s (%s) not numeric in %s' "$var" "$val" "$configfile"`
X	fi
X	LogAppend $var = \"$val\"
done
X
# Run the rest of the config file sanity checks.
X
if [ $firstslot -gt $lastslot ]; then
X	Exit 2 \
X	     `_ '<none>'` \
X	     `_ 'firstslot (%s) greater than lastslot (%s) in %s' "$firstslot" "$lastslot" "$configfile"`
fi
if [ $autoclean -ne 0 -a $cleanslot -lt 0 ]; then
X	Exit 2 \
X	     `_ '<none>'` \
X	     `_ 'autoclean set but cleanslot not valid (%s)' "$cleanslot"`
fi
X
# Set up the current slot
X
currentslot=`cat $slotfile`
if IsNumeric "$currentslot" ; then
X	if [ $currentslot -lt $firstslot ]; then
X		Log `_ 'SETUP    -> current slot %s less than %s ... resetting to %s' "$currentslot" "$firstslot" "$firstslot"`
X		currentslot=$firstslot
X	elif [ $currentslot -gt $lastslot ]; then
X		Log `_ 'SETUP    -> current slot %s greater than %s ... resetting to %s' "$currentslot" "$lastslot" "$lastslot"`
X		currentslot=$lastslot
X	fi
else
X	Log `_ 'SETUP    -> contents of %s (%s) invalid, setting current slot to first slot (%s)' "$slotfile" "$currentslot" "$firstslot"`
X	currentslot=$firstslot
fi
X
found_current=0
first_slot_in_list=-1
next_slot_after_current=-1
for slot in $slot_list; do
X	if [ $first_slot_in_list -lt 0 ]; then
X		first_slot_in_list=$slot	# in case $firstslot is missing
X	fi
X	if [ $slot -eq $currentslot ]; then
X		found_current=1
X		break
X	elif [ $slot -gt $currentslot ]; then
X		next_slot_after_current=$slot	# $currentslot is missing
X		break
X	fi
done
if [ $found_current -eq 0 ]; then
X	if [ $next_slot_after_current -lt 0 ]; then
X		new_currentslot=$first_slot_in_list
X	else
X		new_currentslot=$next_slot_after_current
X	fi
X	Log `_ 'WARNING  -> current slot %s not available, setting current slot to next slot (%s)' "$currentslot" "$new_currentslot"`
X	currentslot=$new_currentslot
fi
X
# More routines.
X
###
# Eject the current tape and put it away.
###
X
eject() {
X	test -n "$DEBUG" && set -x
X	Log `_ 'EJECT    -> ejecting tape from %s' "$tape"`
X	get_loaded_info 
X	if [ $loadedslot -gt 0 ]; then
X		Log `_ 'EJECT    -> moving tape from drive %s to storage slot %s' "$driveslot" "$loadedslot"`
X		if [ $offline_before_unload -ne 0 ]; then
X			Run $MT $MTF $tape offline > /dev/null 2>&1
X		fi
X		sleep $unloadpause
X		result=`Run $MTX unload $loadedslot $driveslot 2>&1`
X		status=$?
X		Log `_ '         -> status %s, result "%s"' "$status" "$result"`
X		mtx_status_valid=0
X		if [ $status -ne 0 ]; then
X			answer="$result"
X			code=2
X		else
X			answer="$tape"
X			code=0
X		fi
X	else
X		answer=`_ 'Drive was not loaded'`
X		code=1
X	fi
X	Exit $code "$loadedslot" "$answer"
X	return $?				# in case we are internal
}
X
###
# Reset the robot back to the first slot.
###
X
reset() {
X	test -n "$DEBUG" && set -x
X	Log `_ 'RESET    -> loading tape from slot %s to drive %s (%s)' "$firstslot" "$driveslot" "$tape"`
X	# Call loadslot without doing it as an internal and let it finish
X	# things up.
X	loadslot $firstslot
X	# NOTREACHED
X	Exit 2 `_ '<none>'` `_ 'reset: should not get here'`
X	return $?				# in case we are internal
}
X
###
# Unload the current tape (if necessary) and load a new one (unless
# "advance").  If no tape is loaded, get the value of "current" from
# $slotfile.
###
X
loadslot() {
X	test -n "$DEBUG" && set -x
X	if [ $# -lt 1 ]; then
X		Exit 2 `_ '<none>'` `_ 'Missing -slot argument'`
X		return $?			# in case we are internal
X	fi
X	whichslot=$1
X	Log `_ 'LOADSLOT -> load drive %s (%s) from slot %s' "$driveslot" "$tape" "$whichslot"`
X
X	numeric=`echo $whichslot | sed 's/[^0-9]//g'`
X	case $whichslot in
X	current|prev|next|advance)
X		find_slot=$currentslot
X		;;
X	first)
X		find_slot=$firstslot
X		;;
X	last)
X		find_slot=$lastslot
X		;;
X	$numeric)
X		find_slot=$numeric
X		;;
X	clean)
X		find_slot=$cleanslot
X		;;
X	*)
X		Exit 2 `_ '<none>'` `_ 'Illegal slot: "%s"' "$whichslot"`
X		return $?			# in case we are internal
X		;;
X	esac
X
X	# Find the requested slot in the slot list.  By loading the "set"
X	# command with multiple copies, we guarantee that if the slot is
X	# found, we can look both forward and backward without running
X	# off the end.	Putting $cleanslot at the end allows us to find
X	# that slot since it is not in $slot_list.
X	get_slot_list
X	set x $slot_list $slot_list $slot_list $cleanslot
X	shift					# get rid of the "x"
X	prev_slot=$1
X	shift
X	while [ $# -gt 0 ]; do
X		if [ $1 -eq $find_slot ]; then
X			break
X		fi
X		prev_slot=$1
X		shift
X	done
X	if [ $# -le 0 ]; then
X		Exit 2 \
X		     `_ '<none>'` \
X		     `_ 'Cannot find slot %s in slot list (%s)' "$find_slot " "$slot_list"`
X		return $?			# in case we are internal
X	fi
X
X	# Determine the slot to load.
X	case $whichslot in
X	next|advance)
X		shift
X		loadslot=$1
X		;;
X	prev)
X		loadslot=$prev_slot
X		;;
X	*)
X		loadslot=$find_slot
X	esac
X
X	# If the desired slot is already loaded, we are done.  Only update
X	# current slot if this is not the cleaning slot.
X	get_loaded_info
X	if [ $loadslot = $loadedslot ]; then
X		if [ $loadslot -ne $cleanslot ]; then
X			rm -f $slotfile
X			echo $loadslot > $slotfile
X		fi
X		Exit 0 "$loadedslot" "$tape"
X		return $?			# in case we are internal
X	fi
X	if [ $loadedslot -eq -2 ]; then
X		Exit 0 "$loadedslot" "$tape"
X		return $?			# in case we are internal
X        fi
X
X	# If we are loading the cleaning tape, bump the cleaning count
X	# and reset the access count.  Otherwise, bump the access count
X	# and see if it is time to do a cleaning.
X	if [ $loadslot = $cleanslot ]; then
X		rm -f $cleanfile $accessfile
X		expr $cleancount + 1 > $cleanfile
X		echo 0 > $accessfile
X	else
X		rm -f $accessfile
X		expr $accesscount + 1 > $accessfile
X		if [ $autoclean -ne 0 -a $accesscount -gt $autocleancount ]
X		then
X			internal_call=`expr $internal_call + 1`
X			loadslot clean > /dev/null 2>&1
X			status=$?
X			internal_call=`expr $internal_call - 1`
X			if [ $status -ne 0 ]; then
X				Exit $status "$loadslot" "$exit_answer"
X				return $?	# in case we are internal
X			fi
X
X			# Slot $cleanslot might contain an ordinary tape
X			# rather than a cleaning tape.  A cleaning tape
X			# *MIGHT* auto-eject; an ordinary tape does not.
X			# We therefore have to read the status again to
X			# check what actually happened.
X			mtx_status_valid=0
X			get_loaded_info
X		fi
X	fi
X
X	# Unload whatever tape is in the drive.
X	internal_call=`expr $internal_call + 1`
X	eject > /dev/null 2>&1
X	status=$?
X	internal_call=`expr $internal_call - 1`
X	if [ $status -gt 1 ]; then
X		Exit $status "$exit_slot" "$exit_answer"
X		return $?			# in case we are internal
X	fi
X
X	# If we were doing an "advance", we are done.
X	if [ $whichslot = advance ]; then
X		if [ $loadslot -ne $cleanslot ]; then
X			rm -f $slotfile
X			echo $loadslot > $slotfile
X		fi
X		Exit 0 "$loadslot" "/dev/null"
X		return $?			# in case we are internal
X	fi
X
X	# Load the tape, finally!
X	Log `_ "LOADSLOT -> loading tape from slot %s to drive %s (%s)" "$loadslot" "$driveslot" "$tape"`
X	result=`Run $MTX load $loadslot $driveslot 2>&1`
X	status=$?
X	Log `_ '         -> status %s, result "%s"' "$status" "$result"`
X	mtx_status_valid=0
X	if [ $status -ne 0 ]; then
X		Exit 2 "$loadslot" "$result"
X		return $?			# in case we are internal
X	fi
X
X	###
X	# Cleaning tapes never go "ready", so instead we just sit here
X	# for "long enough" (as determined empirically by the user),
X	# then return success.
X	###
X	if [ $loadslot -eq $cleanslot ]; then
X		Run sleep $cleancycle
X		Exit 0 "$loadslot" "$tape"
X		return $?			# in case we are internal
X	fi
X
X	###
X	# Wait for the drive to go online.
X	###
X	waittime=0
X	ready=0
X	sleep $initial_poll_delay
X	while [ $waittime -lt $max_drive_wait ]; do
X		result=`Run $MT $MTF $tape rewind 2>&1`
X		if [ $? -eq 0 ]; then
X			ready=1
X			break
X		fi
X		sleep $poll_drive_ready
X		waittime=`expr $waittime + $poll_drive_ready`
X	done
X	if [ $ready -eq 0 ]; then
X		Exit 2 "$loadslot" `_ 'Drive not ready after %s seconds, rewind said "%s"' "$max_drive_wait" "$result"`
X		return $?			# in case we are internal
X	fi
X
X	if [ $loadslot -ne $cleanslot ]; then
X		rm -f $slotfile
X		echo $loadslot > $slotfile
X	fi
X	Exit 0 "$loadslot" "$tape"
X	return $?				# in case we are internal
}
X
###
# Return information about how the changer is configured and the current
# state of the robot.
###
X
info() {
X	test -n "$DEBUG" && set -x
X	get_loaded_info
X	get_slot_list
X	Log       `_ 'INFO     -> first slot: %s' "$firstslot"`
X	LogAppend `_ '         -> current slot: %s' "$currentslot"`
X	LogAppend `_ '         -> loaded slot: %s' "$loadedslot"`
X	LogAppend `_ '         -> last slot: %s' "$lastslot"`
X	LogAppend `_ '         -> slot list: %s' "$slot_list"`
X	LogAppend `_ '         -> can go backwards: 1'`
X	LogAppend `_ '         -> havereader: %s' "$havereader"`
X
X        ###
X	# Check if a barcode reader is configured or not.  If so, it
X	# passes the 4th item in the echo back to amtape signifying it
X	# can search based on barcodes.
X	###
X	reader=
X        if [ $havereader -eq 1 ]; then
X		reader=1
X        fi
X
X	if [ $currentslot -lt $firstslot -o $currentslot -gt $lastslot ]; then
X		currentslot=$firstslot		# what "current" will get
X	fi
X	numslots=`expr $lastslot - $firstslot + 1`
X	Exit 0 "$currentslot" "$numslots 1 $reader"
X	return $?				# in case we are internal
}
X
###
# Read the labelfile and scan for a particular entry.
###
X
read_labelfile() {
X	labelfile_entry_found=0
X	labelfile_label=
X	labelfile_barcode=
X
X	lbl_search=$1
X	bc_search=$2
X
X	line=0
X	while read lbl bc junk; do
X		line=`expr $line + 1`
X		if [ -z "$lbl" -o -z "$bc" -o -n "$junk" ]; then
X			Log       `_ 'ERROR    -> Line %s malformed: %s %s %s' "$line" "$lbl" "$bc" "$junk"`
X			LogAppend `_ '         -> Remove %s and run "%s %s update"' "$labelfile" "$sbindir/amtape" "$config"`
X			Exit 2 \
X			     `_ '<none>'` \
X			     `_ 'Line %s malformed in %s: %s %s %s' "$line" "$labelfile" "$lbl" "$bc" "$junk"`
X			return $?		# in case we are internal
X		fi
X		if [ $lbl = "$lbl_search" -o $bc = "$bc_search" ]; then
X			if [ $labelfile_entry_found -ne 0 ]; then
X				Log       `_ 'ERROR    -> Duplicate entries: %s line %s' "$labelfile" "$line"`
X				LogAppend `_ '         -> Remove $labelfile and run "$sbindir/amtape $config update"' "$labelfile" "$sbindir/amtape" "$config"`
X				Exit 2 \
X				     `_ '<none>'` \
X				     `_ 'Duplicate entries: %s line %s' "$labelfile" "$line"`
X				return $?	# in case we are internal
X			fi
X			labelfile_entry_found=1
X			labelfile_label=$lbl
X			labelfile_barcode=$bc
X		fi
X	done
}
X
###
# Adds the label and barcode for the currently loaded tape to the
# barcode file.  Return an error if the database is messed up.
###
X
addlabel() {
X	test -n "$DEBUG" && set -x
X	if [ $# -lt 1 ]; then
X		Exit 2 `_ '<none>'` `_ 'Missing -label argument'`
X		return $?			# in case we are internal
X	fi
X        tapelabel=$1
X	if [ $havereader -eq 0 ]; then
X		Exit 2 `_ '<none>'` `_ 'Not configured with barcode reader'`
X		return $?			# in case we are internal
X	fi
X        get_loaded_info
X	if [ $loadedslot -lt 0 ]; then
X		Exit 1 `_ '<none>'` `_ 'No tape currently loaded'`
X		return $?			# in case we are internal
X	fi
X	Log       `_ 'LABEL    -> Adding label "%s" with barcode "%s" for slot %s into %s' "$tapelabel" "$loadedbarcode" "$loadedslot" "$labelfile"`
X	read_labelfile "$tapelabel" "$loadedbarcode" < $labelfile
X	if [ $labelfile_entry_found -ne 0 ]; then
X		lf_val=
X		if [ "$labelfile_barcode" != "$loadedbarcode" ]; then
X			lf_type=label
X			lf_val=$tapelabel
X			val_type=barcode
X			old_val=$labelfile_barcode
X			new_val=$loadedbarcode
X		elif [ "$labelfile_label" != "$tapelabel" ]; then
X			lf_type=barcode
X			lf_val=$loadedbarcode
X			val_type=label
X			old_val=$labelfile_label
X			new_val=$tapelabel
X		fi
X		if [ -n "$lf_val" ]; then
X			LogAppend `_ 'ERROR    -> !!! Label database corrupted !!!'`
X			LogAppend `_ '         -> "%s" conflicts with new %s "%s" for %s "%s"' "$old_val" "$val_type" "$new_val" "$lf_type" "$lf_val"`
X			Exit 2 \
X			     `_ '<none>'` \
X			     `_ '%s: "%s" conflicts with new %s "%s" for %s "%s"' "$tapelabel" "$old_val" "$val_type" "$new_val" "$lf_type" "$lf_val"`
X			return $?		# in case we are internal
X		fi
X		LogAppend `_ "         -> already synced"`
X	else
X		echo "$tapelabel $loadedbarcode" >> $labelfile
X		LogAppend `_ '         -> appended %s entry: %s %s' "$labelfile" "$tapelabel" "$loadedbarcode"`
X	fi
X	Exit 0 "$loadedslot" "$tape"
X	return $?				# in case we are internal
}
X
###
# Look for a label in the barcode file.  If found, locate the slot it's
# in by looking for the barcode in the mtx output, then load that tape.
###
X
searchtape() {
X	test -n "$DEBUG" && set -x
X	if [ $# -lt 1 ]; then
X		Exit 2 `_ '<none>'` `_ 'Missing -search argument'`
X		return $?			# in case we are internal
X	fi
X        tapelabel=$1
X	if [ $havereader -eq 0 ]; then
X		Exit 2 `_ '<none>'` `_ 'Not configured with barcode reader'`
X		return $?			# in case we are internal
X	fi
X	Log `_ 'SEARCH   -> Hunting for label "%s"' "$tapelabel"`
X	read_labelfile "$tapelabel" "" < $labelfile
X	if [ $labelfile_entry_found -eq 0 ]; then
X		LogAppend `_ '         -> !!! label "%s" not found in %s !!!' "$tapelabel" "$labelfile"`
X		LogAppend `_ '         -> Remove $labelfile and run "%s %s update"' "$labelfile" "$sbindir/amtape" "$config"`
X		Exit 2 \
X		     `_ '<none>'` \
X		     `_ '%s: label "%s" not found in %s' "$tapelabel" "$tapelabel" "$labelfile"`
X		return $?			# in case we are internal
X	fi
X	LogAppend `_ '         -> barcode is "%s"' "$labelfile_barcode"`
X	get_mtx_status
X	foundslot=`sed -n '
/VolumeTag *= *'$labelfile_barcode' *$/			{
X	s/.*Storage Element \([0-9][0-9]*\).*/\1/p
X	q
}
' < $mtx_status`
X	LogAppend `_ '         -> foundslot is %s' "$foundslot"`
X	if [ -z "$foundslot" ]; then
X		LogAppend `_ 'ERROR    -> !!! Could not find slot for barcode "%s"!!!' "$labelfile_barcode"`
X		LogAppend `_ '         -> Remove %s and run "%s %s update"' "$labelfile" "$sbindir/amtape" "$config"`
X		Exit 2 \
X		     `_ '<none>'` \
X		     `_ 'barcode "%s" not found in mtx status output' "$labelfile_barcode"`
X		return $?			# in case we are internal
X	fi
X	# Call loadslot without doing it as an internal and let it finish
X	# things up.
X	loadslot $foundslot
X	# NOTREACHED
X	Exit 2 `_ '<none>'` `_ 'searchtape: should not get here'`
X	return $?				# in case we are internal
}
X
###
# Program invocation begins here
###
X
if [ $# -lt 1 ]; then
X	Exit 2 `_ '<none>'` `_ 'Usage: %s -command args' "$myname"`
fi
cmd=$1
shift
case "$cmd" in
-slot)
X	loadslot "$@"
X	;;
-info)
X	info "$@"
X	;;
-reset)
X	reset "$@"
X	;;
-eject)
X	eject "$@"
X	;;
-label) 
X	addlabel "$@"
X	;;
-search)
X	searchtape "$@"
X	;;
-clean)
X	loadslot clean
X	;;
*)
X	Exit 2 `_ '<none>'` `_ 'unknown option: %s' "$cmd"`
X	;;
esac
X
Exit 2 `_ '<none>'` `_ '%s: should not get here' "$myname"`
SHAR_EOF
  (set 20 07 05 18 16 58 05 '/usr/lib/amanda/chg-zd-mtx'; eval "$shar_touch") &&
  chmod 0755 '/usr/lib/amanda/chg-zd-mtx' ||
  $echo 'restore of' '/usr/lib/amanda/chg-zd-mtx' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo '/usr/lib/amanda/chg-zd-mtx:' 'MD5 check failed'
17e7984e073f30a9865b4645b1ce3be5  /usr/lib/amanda/chg-zd-mtx
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < '/usr/lib/amanda/chg-zd-mtx'`"
    test 40722 -eq "$shar_count" ||
    $echo '/usr/lib/amanda/chg-zd-mtx:' 'original size' '40722,' 'current size' "$shar_count!"
  fi
fi
rm -fr _sh00379
exit 0

