[comp.sources.amiga] v90i262: BTNtape 1.0 - SCSI-direct tape handler, Part01/02

amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (10/05/90)

Submitted-by: <DrBob@cup.portal.com>
Posting-number: Volume 90, Issue 262
Archive-name: devices/btntape-1.0/part01

BTNtape is a "Better Than Nothing" SCSI tape device handler.  It provides
flat-file access to a SCSI tape drive from application programs using
simple DOS calls to Read() and Write().  It can also be used with the Amiga
TAR utility for disk backups.  Files may span multiple tape volumes
and may start at any tape block.  This handler requires a "SCSI-direct"
compatible hard disk driver.  It is known to work with a 3-M MCD-40 tape
drive on the CBM 2091 controller, the CBM 2090A with an ST506 hard drive,
and the Supra 4x4, and may also work with others (refer to the docs).
Included is a monitoring program which prints useful information
about handler activities, including error sense data.
Includes ANSI C source code.


#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 2)."
# Contents:  MakeFile formattape lmkfile mountlist pktstuff.c
#   sense.codes tape-handle.uu tape.c tape.h tapeio.c tapemon
#   tapemon/tapemon.c tapemon/tapemon.doc tapemon/tapemon.lmk
#   tapemon/tapemon.uu tplink.h
# Wrapped by tadguy@abcfd20 on Thu Oct  4 19:41:24 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MakeFile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MakeFile'\"
else
echo shar: Extracting \"'MakeFile'\" \(192 characters\)
sed "s/^X//" >'MakeFile' <<'END_OF_FILE'
X# Aztec C makefile
XOBJECT   = tape.o  tapeio.o  pktstuff.o
X
Xtape-handler: $(OBJECT)
X   ln +Q -o tape-handler -w +a -g +s $(OBJECT) -lc
X
X$(OBJECT):   tape.h
X   cc -m0b -so -sb -we -bs $*.c
X
X
X
X
END_OF_FILE
if test 192 -ne `wc -c <'MakeFile'`; then
    echo shar: \"'MakeFile'\" unpacked with wrong size!
fi
# end of 'MakeFile'
fi
if test -f 'formattape' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'formattape'\"
else
echo shar: Extracting \"'formattape'\" \(618 characters\)
sed "s/^X//" >'formattape' <<'END_OF_FILE'
X04 80 20 00 03 80
X
XThis is the raw command string for formatting cartridges with a 3M MCD-40.
XTo start a format operation, enter this from the CLI:
X
X      type formattape to tape:$$RAWCMD$$
X
XThe $$RAWCMD$$ must be in upper case.  This file must be smaller than
Xa tape block.  Everything in the file after the first line is ignored.
X
XThe bytes have the following meanings:
X
Xbyte 0 = 04 = the SCSI Format_Unit command
Xbyte 1 = 80 = immediate command execution
Xbyte 2 = 20 = condition tape before format
Xbyte 3 = 00 = reserved
Xbyte 4 = 00 = interleave (00,02-07 are valid values)
Xbyte 5 = 80 = no retries,  80 = retries
X
END_OF_FILE
if test 618 -ne `wc -c <'formattape'`; then
    echo shar: \"'formattape'\" unpacked with wrong size!
fi
# end of 'formattape'
fi
if test -f 'lmkfile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'lmkfile'\"
else
echo shar: Extracting \"'lmkfile'\" \(455 characters\)
sed "s/^X//" >'lmkfile' <<'END_OF_FILE'
X# LATTICE MAKEFILE FOR BTN-TAPE
X
X# Compile with -d to create the window version
X#FLAGS= -v -y -b1 -mat -cakfsu -d
XCFLAGS= -v -y -b1 -mat -cakfsu
X
XLIBS=LIB:lc.lib+LIB:amiga.lib
X
Xtape-handler: tape.o tapeio.o pktstuff.o
X   blink FROM tape.o+tapeio.o+pktstuff.o TO $@ SC SD LIB $(LIBS)
X
Xtape.o : tape.c tape.h tplink.h
X    LC $(CFLAGS) tape.c
X
Xtapeio.o : tapeio.c tape.h
X    LC $(CFLAGS) tapeio.c
X
Xpktstuff.o : pktstuff.c tape.h
X    LC $(CFLAGS) pktstuff.c
X
END_OF_FILE
if test 455 -ne `wc -c <'lmkfile'`; then
    echo shar: \"'lmkfile'\" unpacked with wrong size!
fi
# end of 'lmkfile'
fi
if test -f 'mountlist' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mountlist'\"
else
echo shar: Extracting \"'mountlist'\" \(222 characters\)
sed "s/^X//" >'mountlist' <<'END_OF_FILE'
XTAPE:   Handler   = L:tape-handler
X        Startup   = "4/1/8192/1/0/yourscsi.device"  /* change for yours! */
X        Stacksize = 4000
X        Priority  = 5
X        GlobVec   = -1
X        Mount     = 1   /* optional */
X#
END_OF_FILE
if test 222 -ne `wc -c <'mountlist'`; then
    echo shar: \"'mountlist'\" unpacked with wrong size!
fi
# end of 'mountlist'
fi
if test -f 'pktstuff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pktstuff.c'\"
else
echo shar: Extracting \"'pktstuff.c'\" \(1768 characters\)
sed "s/^X//" >'pktstuff.c' <<'END_OF_FILE'
X/* misc.c  - support routines - Phillip Lindsay (C) Commodore 1986
X *  You may freely distribute this source and use it for Amiga Development -
X *  as long as the Copyright notice is left intact.
X *
X * 30-SEP-86
X */
X
X#include <exec/types.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <exec/ports.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include "tape.h"
X
X#if defined AZTEC_C
X  #include <functions.h>
X#elif defined LATTICE
X  #include <proto/exec.h>
X#endif
X
X
X/* returnpkt() - packet support routine
X * here is the guy who sends the packet back to the sender...
X * (I modeled this just like the BCPL routine [so its a little redundant] )
X */
X
Xvoid returnpkt(
X   struct DosPacket *packet,
X   ULONG  res1,
X   ULONG  res2)
X{
X struct Message *mess;
X struct MsgPort *replyport;
X struct Process *myproc;
X
X packet->dp_Res1          = res1;
X packet->dp_Res2          = res2;
X replyport                = packet->dp_Port;
X mess                     = packet->dp_Link;
X myproc                   = (struct Process *) FindTask(0L);
X packet->dp_Port          = &myproc->pr_MsgPort;
X mess->mn_Node.ln_Name    = (char *) packet;
X mess->mn_Node.ln_Succ    = NULL;
X mess->mn_Node.ln_Pred    = NULL;
X
X PutMsg(replyport,mess);
X}
X
X
X/*
X * taskwait() ... Waits for a message to arrive at your port and
X *   extracts the packet address which is returned to you.
X */
X
Xstruct DosPacket *taskwait(void)
X{
X struct Process *myproc;
X struct MsgPort *myport;
X struct Message *mymess;
X
X myproc = (struct Process *) FindTask(0L);
X myport = &myproc->pr_MsgPort;
X
X WaitPort(myport); /* wait for packet */
X mymess = (struct Message *) GetMsg(myport);
X
X/* give them the pointer to the packet */
Xreturn((struct DosPacket *) mymess->mn_Node.ln_Name);
X}
X
X/* end of misc.c */
END_OF_FILE
if test 1768 -ne `wc -c <'pktstuff.c'`; then
    echo shar: \"'pktstuff.c'\" unpacked with wrong size!
fi
# end of 'pktstuff.c'
fi
if test -f 'sense.codes' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sense.codes'\"
else
echo shar: Extracting \"'sense.codes'\" \(1279 characters\)
sed "s/^X//" >'sense.codes' <<'END_OF_FILE'
X/* Extended Sense codes provided by the 3-M MCD-403 drive
X
X   1 - RECOVERED ERROR
X
X   2 - NOT READY
X             04 Drive Not Ready
X             A7 Logical Load Failure
X             A8 Cartridge Autoloading
X             B0 No Cartridge in Drive
X
X   3 - MEDIUM ERROR
X             10 ID CRC
X             11 Unrecovered Read error of data blocks
X             15 Seek Positioning error
X             19 Defect List error
X             31 Medium Format corrupted
X             32 No Defect Spare Location Available
X
X   4 - HARDWARE ERROR
X             08 Logical Unit Communication Failure
X             10 ID CRC
X             15 Seek Positioning error
X             42 Power On Diagnostic Failure
X
X   5 - ILLEGAL REQUEST
X             20 Invalid Command Operation Code
X             21 Illegal Logical Block Address
X             24 Illegal field in CDB
X             26 Invalid field in Parameter List
X
X   6 - UNIT ATTENTION
X             28 Medium Changed
X             29 Power On or Reset or Bus Device Reset occured
X             2A Mode Select Parameters changed
X
X   7 - DATA PROTECT
X             27 Write Protected
X
X   8 - BLANK CHECK (unformatted tape)
X
X   9 - VENDOR UNIQUE
X
X   B - ABORTED COMMAND
X             47 Message Parity Error Message
X             48 Initiator Detected Error
X*/
END_OF_FILE
if test 1279 -ne `wc -c <'sense.codes'`; then
    echo shar: \"'sense.codes'\" unpacked with wrong size!
fi
# end of 'sense.codes'
fi
if test -f 'tape-handle.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tape-handle.uu'\"
else
echo shar: Extracting \"'tape-handle.uu'\" \(10238 characters\)
sed "s/^X//" >'tape-handle.uu' <<'END_OF_FILE'
Xbegin 644 tape-handler
XM```#\P`````````"``````````$```9^````>````^D```9^3E7_B$CG!SI)(
XM^0````!P`#M`_XX[0/^00_H'GG``+'@`!$ZN_=@I0`%0D\E.KO[:)D!.N@\<)
XM)$`@*@`<(@#E@2X`0?H'ABM(_]I!^@>**TC_WBM!_^9![`%^*TC_[D'M_\(KG
XM2/_J0>W_VBE(`60G2`!8("H`&.6`($!#Z``!*4D!>A`1*T'_SG(BL`%F'E*LV
XM`7H@;`%Z2AAF_%.(D>P!>B`((FP!>M/`0BG__T*G80`([BM`_\)(>``!80`(<
XMXBP`2'@``6$`"-@J`$AX``%A``C.*4`!;$AX``%A``C".4`!>$AX__]A``BV#
XM3^\`&"M`_[(@+`%L(@5.NA%:*4`!<"M`_[8@;?^R$!!R)+`!9@XI?`$`````^
XM"%*M_[)@#G(KL`%F"$*L`7!2K?^R*VW_LO_B(`8`@``!```O0``<(#P```%6`
XM(B\`'"QX``1.KO\Z*T#_QDJ`9AQ(>`!G0J<O"DZZ#8XB;`%0+'@`!$ZN_F)@U
XM``8\(&W_QBE(`51#Z``@*4D!6$/H`$`I20%<0J="ITZZ$:9(>``P+P!.NA)H<
XM3^\`$"E``6`@;?^R("W_PB)L`6!R`"QX``1.KOY$2H!G*DAX`-)"IR\*3KH-/
XM)B)L`5`L>``$3J[^8B)M_\8@/````59.KO\N8``%QD'K`%PB;?_.(T@`""\J4
XM`!!(>/__+PI.N@SN3^\`#'#_+'@`!$ZN_K8;0/^-#```_V<,<@`2`'`!XZ`KB
XM0/_R0J=A``9@6$].N@T>)$`@*@`(7X!G``4*4X!G``467X!G``4F<D.0@6<`Y
XM`RY;@&<`!`0$@````Y9G#E.`9PI3@&<``G)@``482FW_D&<22'@`RD*G+PI.U
XMN@QP3^\`#&"H(`8`@``!```O0``<("W_MB(O`!PL>``$3J[_.BE````@!@"`5
XM``$``"]``!P@+?^V(B\`'$ZN_SHI0``$2JP``&<$2H!F+"\M_[9A``9L2'@`^
XM9T*G+PI.N@P02'H%$$AL`7Y.N@\N80`&_$_O`!A@`/\X<``B*@`<Y8$@04/H6
XM``$I20%Z.T#_ECM`_Y([0/^4(&P!>A`0<CJP`6<&4JP!>F#N(&P!>E*(<`E#M
XM^@3D$ABR&5;(__IF#'`!.T#_ECM`_Y)@1"!L`7H0*``!<BJP`68(.WP``?^25
XM8"YR`!(`0>P`30@P``(8`&<>(&P!>E*(0J="IR\(3KH5!$_O``PI0`%H.WP`!
XM`?^20J=A``3X6$]*;?^29PAP`"M`_YI@%G``+P`O`$AX``-.N@:23^\`#"M`&
XM_YI*@&<B+P!A``3(+JW_MF$`!71(>`#:0J<O"DZZ"QA/[P`08`#^4'``+P`OC
XM`$AX``5.N@963^\`#$J`9P@@/'____]@%G``(&P!6!`H``+A@'(`$B@``X"!:
XM4H`I0`%T(@5.N@XV+P`O!2\L`71(>@/Z2&P!?DZZ#>AA``6V3^\`%#M\``'_J
XMD'``.4``#$*M_Z(K;?^V_YX[0/^8.T#_CDIM_Y)F"C`L`7A(P"E``6@O+`%H$
XM2'H#PDAL`7Y.N@VB80`%<$_O``P,J@```^T`"&8Z.WP``?^4<``O`"\`2'@`X
XM`4ZZ!:9/[P`,(BP!;-.L`6@K0/^:9A1P`2\`+P`O`$ZZ!8A/[P`,*T#_FB\J9
XM`!!(>/__+PI.N@H>3^\`#&``_59*;?^09V)*;?^.9S9*;?^69Q@P+?^82,!"M
XMIR\`2'@`!$ZZ!49/[P`,8#`P+?^82,!"IR\`2'@``DZZ!2Y/[P`,8!A*;``,<
XM9Q)P`"\`+P!(>``&3KH%%$_O``Q";?^0+RW_MF$`!`!83R\J`!!(>/__+PI.!
XMN@F@3^\`#$IM_Y1F""`L`6S1K`%H+RP!:$AZ`MQ(;`%^3KH,J&$`!'9/[P`,\
XM8`#\LDJM_YIG%"\M_YIA``,`6$]P_R5``!Q@``"N*VH`&/^N*VH`'/^J2JW_!
XMJF<``)I*K?^>9D@@+`%LT:P!:#`M_YA(P'(!+P$O`"\!3KH$>$_O``PK0/^:<
XM9Q`O`&$``K!83W#_)4``'&!>"&T``/^9("W_MG(`*T#_GBM!_Z(@+?^>(BW_<
XMJK*`;@(@`3(M_YA(P>6!0>P``"!P&`#1[?^B*T#_IB)M_ZY@`A+84X!D^B`M<
XM_Z:1K?^JT:W_HI&M_Y[1K?^N8`#_8B\J`!@O*@`<+PI.N@B>3^\`#&``^]8KE
XM:@`8_ZXK:@`<_ZI*K?^J9P``Q"`M_YXB+?^JLH!M?#(M_YA(P>6!0>P``"!PS
XM&`#1[?^B(FW_KF`"$-E3@&3Z,"W_F$C`2'@``2\`2'@``DZZ`Y9/[P`,*T#_R
XMFF<0+P!A``'.6$]P_R5``!Q@:"`L`6S1K`%H("W_GI&M_ZK1K?^N<``K;?^VG
XM_YX(;0``_YE";?^.*T#_HF``_W(P+?^82,#E@$'L```@<`@`T>W_HB)M_ZY@D
XM`A#94X%D^B`M_ZJ1K?^>T:W_HD*M_ZH[?``!_XY@`/\X+RH`$"\J`!PO"DZZ@
XM![)/[P`,8`#ZZD*G+P<O"DZZ!Z!/[P`,8`#ZV"\J`!`O*@`4+PI.N@>*3^\`P
XM#&``^L(O*@`02'C__R\*3KH'=$_O``Q@`/JL2'@`T4*G+PI.N@=@+JH`"$AZ?
XM`,)(;`%^3KH*>F$``DA/[P`48`#ZA$SM7.#_;$Y=3G5I;G1U:71I;VXN;&EBR
XM<F%R>0!487!E2&%N9&QE<@`M0E1.5$%012!6,2XP(%)!4BU397`@,3`@,3DYD
XM,`!#86XG="!G970@;65M;W)Y(&9O<B!T87!E(&)U9F9E<G,*```D)%)!5T--`
XM1"0D```E9"`J("5D(#T@)60*`$]P96YE9"!A="!B;&]C:R`E9`H`0VQO<V5D@
XM(&%T(&)L;V-K("5D"@!5;G-U<'!O<G1E9%]0:W0])60*`&EO7T5R<F]R/25DA
XM("!396YS93TE6"PE,#)8"@`O`$CG`0A)^0`````N+P`,<``@;`%8$4``#"!L=
XM`5@10``"X(=F$G``+P`O`"\`3KH!BD_O``Q@3G`MOH!F2'``+P`O`"\`3KH!B
XM<D_O``P@;`%8$!`B``(!`'!*`68,`@``#R!L`5@10``"$"@``B!L`6010``D\
XM(&P!6!`H``P@;`%D$4``)7``(&P!6!`H``)R`!(H``PO`2\`+P=(>O]&2&P!H
XM?DZZ".IA``"X3^\`%$S?$(!.=4CG`0I)^0`````N+P`02FP`#&<2<``O`"\`3
XM2'@`!DZZ`.1/[P`,2JP``&<.(FP``"`'+'@`!$ZN_RY*K``$9PXB;``$(`<L!
XM>``$3J[_+I'(*4@`!"E(``!,WU"`3G5(YP$82?D`````/B\`$DI'9P1P`&`$[
XM("P!>B9`2'K^SB\+3KH&"E!/*4`!>G#_OD!F!B`L`7I@$$*G0J<O+`%Z3KH.>
XMI$_O``Q,WQB`3G5(YP`*2?D`````(&P!9$JH`"!G/")H`"`@*``<+'@`!$ZN'
XM_KP@;`%D("@`&$ZN_L(B;`%D(FD`("!L`60@*``<3J[^O"!L`60@*``83J[^[
XMPDS?4`!.=0``3E7_]$CG+PI)^0`````N+0`(+"T`#!HM`!-*;``,9S8B;`%@P
XM+'@`!$ZN_B9P`#E```P@;`%@2B@`'V<:<@`2*``?X8%T`")L`5P4*0`5TH(@.
XM`6```U!P!KZ`9@9P`&```T0@;`%<(6P!5``,(&P!7#%\``8`$'``(&P!7!%`8
XM`!4B;`%@,WP`'``<(&P!8"%L`5P`*'(6(&P!8"%!`"0@;`%@$4``'Q%\``$`0
XM'G@`<`:X0&P,(&P!5-#$0A!21&#N(`<,@`````9D``)PT$`P.P`&3OL`!`%LQ
XM``H`F@$N`>@!L"`L`6C0K`%LL*P!=&4$80`#5"!L`500O``(("P!:"(`X(ETF
XM`$8"PH(@;`%4$4$``G``1@#`K`%H(&P!5!%```,@+`%L(&P!5!%```0@!N6`[
XM0>P``")L`5PBL`@`(&P!7"%L`7``!"!L`5P1?``!`!0O+`%L+RP!:$AZ`E!(0
XM;`%^3KH&<DZZ_D!/[P`08``!RB`L`6C0K`%LL*P!=&4$80`"Q"!L`500O``*@
XM("P!:"(`X(ET`!0!<@!&`<2!(&P!5!%"``)P`$8`P*P!:"!L`5010``#("P!*
XM;"!L`5010``$(`;E@$'L```B,`@`@JP`""!L`5P@@2%L`7``!"!L`5Q"*``4=
XM+RP!;"\L`6A(>@'42&P!?DZZ!=Y.NOVL3^\`$&```38@;`%4$+P``2`&Y8!!1
XM[```(FP!7"*P"``@;`%<0J@`!"!L`5Q"*``42'H!K$AL`7Y.N@6>3KK];%!/,
XM8```^"!L`500O``#(&P!5!%\`!P`!'`<(&P!7"%```0@;`%<(*P!6"!L`5P1X
XM?``!`!1(>@%T2&P!?DZZ!5I.NOTH4$]@``"T(&P!5!"\`"5P""!L`5PA0``$:
XM(&P!7""L`5@@;`%<$7P``0`42'H!0DAL`7Y.N@4@3KK\[E!/8'IX`"`&Y8!!M
XM[```*W`(`/_\(&W__!`0<@JP`6<T<""X0&PN(`121")L`532P$AX`!!(;?_\+
XM+P@O20`H3KH+1$_O``QR`$8!P($@;P`<$(!@P"!L`5P@K`%8(&P!7$*H``0@2
XM;`%<0B@`%$AZ`-!(;`%^3KH$I$ZZ_')03TH%9B8B;`%@+'@`!$ZN_CAP`"!LQ
XM`6`0*``?X8!R`")L`5P2*0`5T(%@0"\L`6!.N@PV6$\@;`%@2B@`'V<6<``0?
XM*``?X8!R`"!L`5P2*``5T(%@%B!L`6`0*``>"````&8&.7P``0`,<`!,WU#TQ
XM3EU.=5)E861I;F<@8FQO8VL@)60@*B`E9`H``%=R:71I;F<@8FQO8VL@)60@1
XM*B`E9`H``%)E=VEN9&EN9PH``%-E;G-E.@``0V%P86-I='DZ`%)A=R!C;VUMD
XM86YD"@``("!%3U0Z($EN<V5R="!N97AT('1A<&4`0V]N=&EN=64``%%U:70`%
XM`%1I;64@9F]R(&$@;F5W('1A<&4*```O#$GY`````'``+P`O`$AX``9A`/NF(
XM2'K_TDAL`7Y.N@-P3KK[/DAX`#)(>`#Z<``O`"\`2&P`.$AL`"1(;``00J=.[
XMN@3Z3^\`-$J`9Q(P+`%X2,`I0`%H0J=.NOFF6$\H7TYU``!.5?_T2.<#.DGYA
XM`````"9M``@N+0`,+"T`$"='``PG1@`0*VL`!/_X)%.3R2QX``1.KO[:($!#E
XMZ`!<)TD`!"5+``J3R22))4D`!"M`__0@;?_X(DI.KOZ23-]<P$Y=3G5.5?_T2
XM2.<`.DGY`````)/)+'@`!$ZN_MHF0$7K`%P@2DZN_H`@2DZN_HP@0"`H``I,'
XMWUP`3EU.=4CG(#`F;P`0)$M*$F<D<``0$D'L`$T(,``!"`!G"G(`$@!T()*"-
XM8`1R`!(`%(%2BF#8(`M,WPP$3G4``````````'!A3E7_]$CG`3`F;P`@(`MG(
XM(B!++RT`#"\(*4@!T$ZZ`9)03RX`(&P!T")(T\<K2?_X8!`@;`'02A!F!'``C
XM8$(K2/_X)&W_^"\M``PO"DZZ`7Y03RX`2C)X`&<:0C)X`"!*T<=%Z``!+RT`V
XM#"\*3KH!0E!/+@`@2M''*4@!T"`M__A,WPR`3EU.=2`O``@@;P`$3E7_]")/[
XM<@I.N@)`!D$`,!+!2H!F\"`)$.&_R6;Z0A"0CTY=3G4``"`O``@@;P`$3E7_=
XM]")/(@`"00`'!D$`,!+!YHAF\"`)$.&_R6;Z0A"0CTY=3G4``#`Q,C,T-38W<
XM.#EA8F-D968@+P`((&\`!$/O``0R``)!``\2^Q#<Z(AF\B`)(@]8@1#ALHEFP
XM^D(0D(%.=4Y5__A(YP$P)F\`'"1O`"!^`$H39RHK2O_\(&W__$H09PP0$+`32
XM9P92K?_\8.P@;?_\2A!F!"`'8`A2AU*+8-(@!TS?#(!.74YU3E7_^$CG`3`FB
XM;P`<)&\`('X`2A-G(BM*__P@;?_\2A!G$!`0L!-F!"`'8`Y2K?_\8.A2AU*+%
XM8-H@!TS?#(!.74YU2.<`,"9O``PD;P`0+PHO"V$`_V)03TS?#`!.=4CG`#`F\
XM;P`,)&\`$"\*+PMAD%!/3-\,`$YU```@;P`$(DAR`'``+P(,$``K9P8,$``MH
XM9@)22!`8!```,&T2#```"6X,)`'E@=*"TH'2@&#F#!$`+68"1($D'R`(4X`@+
XM;P`(((&0B4YU+P<N+P`(4JP!V"`'(&P!U!#`*4@!U"X?3G5.50``2.<`,"9OK
XM`!`D;P`40JP!V"E+`=1(;0`0+PI(>O_&3KH%Q"!L`=1"$"`L`=A,[0P`__A._
XM74YU2.<P`"0`)@%(0DA#Q,'&P,#!U$-(0D)"T(),WP`,3G5*@&H``!Y$@$J!]
XM:@``#$2!80``($2!3G5A```81(!$@4YU2H%J```,1(%A```&1(!.=2\"2$$TK
XM`68``")(0$A!2$(T`&<```:$P3`"2$`T`(3!,`)(0C(")!].=2\#=A`,00"`X
XM9```!N&944,,00@`9```!NF964,,02``9```!N6954-*06L```;CF5-#-`#FJ
XMJ$A"0D+FJDA#@,$V`#`"-`-(0<3!D()D```(4T/0@63^<@`R`TA#Y[A(0,%!A
XM)A\D'TYU2.<#,B9O`!@N+P`<</\L>``$3J[^MBP`#`8`_V8$<`!@9G`B(CP`I
XM`0`!3J[_.B1`(`IF"G``$`9.KOZP8$@E2P`*(`<50``)%7P`!``(0BH`#A5&^
XM``^3R4ZN_MHE0``0(`MG"")*3J[^GF`:0>H`&"5(`!1!Z@`4)4@`'$*J`!@5Q
XM?``"`"`@"DS?3,!.=0``2.<P,BQL`5`@;P`8(F\`'"1O`"`F;P`D("\`*"(O$
XM`"PD+P`P)B\`-$ZN_J1,WTP,3G4``````````'!A2.<!,B9O`!0N+P`8(`MF^
XM!'``8"P@!R(\``$``2QX``1.KO\Z)$`@"F<4%7P`!0`(0BH`"25+``X@!S5`:
XM`!(@"DS?3(!.=0``3E7_Q$CG)S`F;P!<)&\`8'X`?`!Z`'``&WP`(/_[<@`KX
XM0?_V=/\K0O_R0>W_T!M`__$;0/_\*T'_Y"M!_^@K2/_,2A-G+'``$!,$0``@L
XM9Q170&<444!G"%5`9A9^`6`.?`%@"GH!8`8;?``!__Q2BV#0$!-R,+`!9@92G
XMBQM!__MP*K`39@P@4EB2*U#_]E*+8`Y(;?_V+PM.NOS.4$_7P!`3<BZP`68BO
XM4HMP*K`39@P@4EB2*U#_\E*+8`Y(;?_R+PM.NORD4$_7P!`3<FRP`68*&WP`V
XM`?_Q4HM@"')HL`%F`E*+$!MR`!(`&T#_\`1!`%AG``%^!$$`"V<``@I306<DD
XM!$$`"V<``1)306<``5!706<``;I506<``.1706<``5)@``'X2BW_\6<((%)8\
XMDB`08`8@4EB2(!`K0/_L;`IR`42M_^PK0?_H2JW_Z&<$<"U@"DH&9P1P*V`"J
XM<"`;0/_0<``0!B(M_^B"@'``$`6"@&<(4JW_S%*M_^0O+?_L+RW_S$ZZ^H)0<
XM3RM`_\@@+?_R2H!J!G(!*T'_\B`M_\@B+?_RDH!([0`"_\1O-"!M_\PB2-/!B
XM+P`O"2\(3KH"4D_O``QP`!`M__LB+?_$(&W_S&`"$,!3@63Z("W_\BM`_\C1Z
XMK?_D0>W_T"M(_\Q*!V<``3`;?``@__M@``$F2BW_\6<((%)8DB`08`8@4EB20
XM(!`K0/_L8`#_9$HM__%G""!26)(@$&`&(%)8DB`0*T#_[$HM__QG$B!M_\P0&
XM_``P<@$K0?_D*TC_S"\`+RW_S$ZZ^>903RM`_\A@`/\R&WP`,/_[("W_\DJ`4
XM:@9P""M`__)*+?_Q9P@@4EB2(!!@!B!26)(@$"M`_^Q*+?_\9Q8@;?_,$/P`!
XM,!#\`'AR`BM!_^0K2/_,+P`O+?_,3KKYRE!/*T#_R'!8L"W_\&8`_M!(;?_0S
XM3KKX=EA/8`#^PB!26)(B4"M)_\QF"$'Z`-@K2/_,(&W_S$H89OQ3B)'M_\PKT
XM2/_D("W_\DJ`:R:QP&\B*T#_Y&`<<`$K0/_D(%)8DB`0&T#_T$(M_]%@!G``:
XM8```C"`M_^0B+?_VLH!L"'0`*T+_]F`$D:W_]DH'9S93K?_D;1AP`"!M_\P0A
XM&"\`*TC_S"!M`!!.D%A/8.)3K?_V;4AP`!`M__LO`"!M`!!.D%A/8.A3K?_V(
XM;1)P`!`M__LO`"!M`!!.D%A/8.A3K?_D;1AP`"!M_\P0&"\`*TC_S"!M`!!.O
XMD%A/8.(@"TS?#.1.74YU``!.5?_T2.<!,"9O`"`D;P`D*VT`$/_V'AI*!V<T0
XM<"6^`&8BL!)F!%**8!HO"TAM__8O"F$`_!9/[P`,*T#_^F<$)$!@TG``$`<O2
XM`$Z36$]@QDS?#(!.74YU```@;P`$(F\`""`O``QO%K/(90S1P-/`$R!3@&;Z5
XM3G42V%.`9OI.=0``+SP`````2.=X,"!O`"`B;P`D("\`*"E\``````'<)$@,Z
XM$``@9@122&#V)D@,````;0P,```D;@8,```!9@9P`&```/@,$``M9@A2+P`8R
XM4DA@"`P0`"MF`E)(#````&8><`H,$``P9CAP"%)(#!``6&<&#!``>&8H<!!2F
XM2&`B#```$&8<#!``,&86#"@`>``!9@142&`*#"@`6``!9@)42$*!0H(,$```!
XM9P``7!00#`(`,&U2#`(`.6X&!`(`,&`."((`!0P"`$%M/`0"`#>T`&XT*`%GM
XM("8!QL!(1,C`2$1K#@Q$``!F"-:$900B`V`&'WP``0`9TH)D```('WP``0`9<
XM4DA@G@@O````&&<"1($(+P```!EG```B*7P````B`=P(+P```!AF```*(CQ_N
XM____8`8B/(````"S_`````!G"K?(9@0BBF`"(H@@`4S?#!Y8CTYU````````B
XM``!P82)O``0O#BQI`!1.KO_B+%].=0`````#[`````D````!```/6@``#OH`A
XM``Z.```*3@``"?(```FD```)1@``")(````*`````````_`````"7T)E9VEN(
XM24\``!GD`````````_(```/J````>````````````````````````0$```8`W
XM`P````````Y,```````!`0``!@`#````````#F0```````$!```&``,`````E
XM```.;@``````("`@("`@("`@*"@H*"@@("`@("`@("`@("`@("`@("!($!`0<
XM$!`0$!`0$!`0$!`0A(2$A(2$A(2$A!`0$!`0$!"!@8&!@8$!`0$!`0$!`0$!H
XM`0$!`0$!`0$!`1`0$!`0$(*"@H*"@@("`@("`@("`@("`@("`@("`@("$!`0.
XM$"`@("`@("`@("`H*"@H*"`@("`@("`@("`@("`@("`@($@0$!`0$!`0$!`0`
XM$!`0$!"$A(2$A(2$A(2$$!`0$!`0$(&!@8&!@0$!`0$!`0$!`0$!`0$!`0$!_
XM`0$!$!`0$!`0@H*"@H*"`@("`@("`@("`@("`@("`@("`@(0$!`0(```````W
XM`````````````````````````````````````````````````````````````
XM`````````````````````````````````````````````````````````````
XM`````````````````````````````````````````````````````````````
XG`````````````^P````#`````````$0````P````'`````````/RW
X``
Xend
Xsize 7284
END_OF_FILE
if test 10238 -ne `wc -c <'tape-handle.uu'`; then
    echo shar: \"'tape-handle.uu'\" unpacked with wrong size!
fi
# end of 'tape-handle.uu'
fi
if test -f 'tape.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tape.c'\"
else
echo shar: Extracting \"'tape.c'\" \(16555 characters\)
sed "s/^X//" >'tape.c' <<'END_OF_FILE'
X/****     BTNtape Handler for SCSI tape drives        ****/
X/**** Author: Bob Rethemeyer  (DrBob@cup.portal.com)  ****/
X
X#define TVERSION "-BTNTAPE V1.0 RAR-" ## __DATE__
X
X/*  (c) Copyright 1990, Robert Rethemeyer.
X *  This software may be freely distributed and redistributed,
X *  for non-commercial purposes, provided this notice is included.
X *-----------------------------------------------------------------------
X *  BTNtape is an AmigaDOS device handler to make a simple DOS TAPE: device.
X *  It converts DOS packets for the device into I/O requests to a
X *  "SCSI-direct" compatible device driver.  It is based on "my.handler"
X *  by Phillip Lindsay and a SCSI-direct program by Robert Mitchell.
X *  Source is ANSI C compliant.  Compile with Lattice v5 or Manx v5.
X *
X *  This handler works in conjunction with the accompanying TapeMon program.
X *----------------------------------------------------------------------------
X * Install this handler in your L: directory.
X * Make a devs:mountlist entry similar to this:
X *
X *   TAPE:  Handler   = L:tape-handler
X *          Stacksize = 4000
X *          Priority  = 5     (use 11 for Supra)
X *          GlobVec   = -1
X *          Startup   = "4/5/8192/1/0/yourscsi.device"
X *                    ( unit/BufMemType/blocksize/Buffers/Reserved/Driver )
X *   #
X * Then use "MOUNT TAPE:" to make the device known to DOS.
X *
X * This handler can circumvent the "write phase" problem in the CBM 2090A
X * driver.  To invoke the circumvention, prefix the name of the driver
X * in the Startup mountlist parameter with a dollar sign ("$").
X * Example:    Startup = "4/5/8192/1/0/$hddisk.device"
X *
X * This handler can circumvent a byte count problem in the Supra v1.10
X * driver.  To invoke the circumvention, prefix the name of the driver
X * in the Startup mountlist parameter with a plus sign ("+").
X * Example:    Startup = "4/5/8192/1/0/+supradirect.device"
X *
X * ----------------------------------------------------------------------------
X */
X
X#include <exec/types.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <exec/ports.h>
X#include <exec/tasks.h>
X#include <exec/libraries.h>
X#include <exec/io.h>
X#include <exec/memory.h>
X#include <devices/scsidisk.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <libraries/filehandler.h>
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X#include <limits.h>
X
X#if defined AZTEC_C
X  #include <functions.h>
X#elif defined LATTICE
X  #include <proto/exec.h>
X#endif
X
X#include "tape.h"
X#include "tplink.h"
X
Xstruct things {  /* a collection of things we will have to alloc */
X         UBYTE cmdbuff[32];
X         UBYTE snsarea[32];
X         struct SCSICmd scsicmd;
X         UBYTE pad[256];  /* SCSICmd may be larger than include? */
X         } ;
X
X/*======== Global data */
X
Xstruct IntuitionBase *IntuitionBase;
XUBYTE           *cdb;          /* pointer to tape command buffer */
XUBYTE           *sns;          /* pointer to sense data buffer   */
Xstruct SCSICmd  *cmd;          /* pointer to scsidirect command  */
Xstruct IOStdReq *ior;          /* pointer to io request structure*/
XUBYTE           *TapeBuff[2]   /* pointers to 2 tape buffers     */
X                            ={NULL,NULL};
Xstruct tplink   *linktp;       /* pointer to link structure      */
XULONG  blknum;                 /* block number for io operation  */
XULONG  numblks;                /* number of blocks per io operation */
XULONG  rwlen;                  /* bytes in a tape read/write     */
XULONG  bugmask = 0;            /* 2090A bug circumvention        */
Xlong   tpsize;                 /* tape size in blocks            */
Xshort  reserved;               /* number of reserved blocks at BOT */
Xshort  inprog = FALSE;         /* io operation in progress flag  */
Xchar   *z;                     /* scratch                        */
Xchar   dbb[80];                /* buffer for monitor messages    */
X
X#define RAWNAME "$$RAWCMD$$"
X#define RAWLEN 10
X
X/***********************  Main program  ********************************/
X#ifdef AZTEC_C
X  #pragma intfunc(_main())
X#endif
Xvoid _main(void)
X{
X struct tplink         tpl;         /* structure to link hndlr & mon     */
X struct Process        *myproc;     /* ptr to handler's process struct   */
X struct DosPacket      *mypkt;      /* ptr to dos packet sent            */
X struct DeviceNode     *mynode;     /* ptr to devnode passed in pkt Arg3 */
X ULONG                  dvnode;     /* ptr to devnode passed in pkt Arg3 */
X struct things         *xarea;      /* ptr to dynamic misc. areas        */
X ULONG                 unit;        /* device SCSI unit address          */
X ULONG                 bufmemtype;  /* type of mem for dynamic buffers   */
X ULONG                 blksize;     /* bytes per tape block              */
X ULONG                 TBSize;      /* bytes in a tape buffer            */
X char                  *driver;     /* name of SCSI device driver        */
X UBYTE                 *dptr;       /* ptr to next byte in dos buffer    */
X long                  dcnt;        /* count of dos packet bytes to move */
X long                  mcnt;        /* count of bytes to move            */
X long                  Boff;        /* current offset in tape buffer     */
X long                  rem;         /* bytes remaining in tape buffer    */
X long                  x;           /* scratch                           */
X short                 Bn;          /* current buffer number, 0 or 1     */
X short                 raw;         /* raw command mode flag             */
X short                 rdmode;      /* flag indicating open for reading  */
X short                 norw;        /* no-rewind flag                    */
X short                 open= FALSE; /* tape file open flag               */
X short                 dirty=FALSE; /* buffer has unwritten data in it   */
X BYTE                  acksig;      /* monitor acknowledge signal number */
X
X/*======== Startup */
X
X IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
X myproc  = (struct Process *) FindTask(0L);          /* find this process */
X mypkt = taskwait();                           /* wait for startup packet */
X /* packet: Arg1=BSTR to name, Arg2=BSTR to startup string, Arg3=BPTR devnode*/
X mynode = (struct DeviceNode *) BADDR(mypkt->dp_Arg3);
X dvnode = (ULONG) mypkt->dp_Arg3;
X
X/*======== Create linkage for the tape monitor:  install pointer to tplink
X  ======== structure in the free pointer of the task block, so the tape
X  ======== monitor can find it after FindTask().
X*/
X tpl.keyword = "TapeHandler";
X tpl.version = TVERSION;
X tpl.devnode = (void *)mynode;
X tpl.dbb     = dbb;
X tpl.unit    = &unit;
X linktp = &tpl;
X ((struct Task *)myproc)->tc_UserData = (APTR) linktp;
X
X/*======== Extract info from mountlist Startup parameter. It may be
X  ======== enclosed in quotes, and each item is separated by a single '/'
X*/
X z = (char *)BADDR(mypkt->dp_Arg2)+1 ;  /* Arg2= BSTR to mountlist 'Startup'*/
X if(z[0]=='\"')  {                      /* remove quotes if any */
X     z++;
X     z[strlen(z)-1]= '\0' ;
X }
X unit       = Nextnum(0);
X bufmemtype = Nextnum(1);
X blksize    = Nextnum(1);
X numblks    = Nextnum(1);
X reserved   = Nextnum(1);
X driver     = (char *) Nextnum(-1);
X rwlen = TBSize = numblks * blksize;   /* size of a tape buffer */
X
X/*======== Kludges to work around various SCSIdirect driver software problems */
X
X if (driver[0] == '$') {               /* Activate 2090A bug circumvention */
X     bugmask = 0x01000000;            /* if driver name starts with '$'   */
X     driver++ ;
X }
X else if (driver[0] == '+') {          /* Activate Supra bug circumvention */
X     rwlen = 0;                       /* if driver name starts with '+'   */
X     driver++ ;
X }
X tpl.driver  = driver;
X
X/*======== Allocate some memory for non-data buffers */
X
X if( !(xarea = (struct things *)
X           AllocMem(sizeof(struct things), bufmemtype | MEMF_CLEAR) ))
X           { returnpkt(mypkt,DOSFALSE,ERROR_NO_FREE_STORE);
X             CloseLibrary((struct Library *)IntuitionBase);
X             return;
X           }
X cdb = &xarea->cmdbuff[0];
X sns = &xarea->snsarea[0];
X cmd = &xarea->scsicmd;
X ior = (struct IOStdReq *) CreateExtIO( CreatePort(0,0),
X                                         sizeof(struct IOStdReq));
X
X/*======== Open the SCSIdirect device */
X
X if ( OpenDevice(driver,unit,(struct IORequest *)ior,0L)  )  {
X    returnpkt(mypkt,DOSFALSE,ERROR_INVALID_COMPONENT_NAME);
X    CloseLibrary((struct Library *)IntuitionBase);
X    FreeMem(xarea,sizeof(struct things));
X    return;
X }
X mynode->dn_Task = &myproc->pr_MsgPort;    /* install handler taskid */
X returnpkt(mypkt,DOSTRUE,mypkt->dp_Res2);  /* reply to initial packet */
X
X/*======== Allocate the signal that TapeMon will
X  ======== use to acknowledge MPR requests.
X*/
X acksig = AllocSignal(-1);
X if(acksig != -1) tpl.handsig = 1UL << acksig;
X /* else { monitor will not attempt to signal us } */
X
X DoSense(0);
X
X/* =========== The main packet processing loop =============== */
X
X for (;;)  {
X   mypkt = taskwait();          /* wait for a packet */
X   switch(mypkt->dp_Type) {
X
X     case ACTION_FINDINPUT:  /*----------- Open() ------------*/
X     case ACTION_FINDOUTPUT:
X          if(open) returnpkt(mypkt,DOSFALSE,ERROR_OBJECT_IN_USE);
X          else {
X             TapeBuff[0] = (UBYTE *) AllocMem(TBSize, bufmemtype | MEMF_CLEAR);
X             TapeBuff[1] = (UBYTE *) AllocMem(TBSize, bufmemtype | MEMF_CLEAR);
X             if (!TapeBuff[0] || !TapeBuff[1]) {
X                  FreeStuff(TBSize);
X                  returnpkt(mypkt,DOSFALSE,ERROR_NO_FREE_STORE);
X                  MPR0("Can't get memory for tape buffers\n")
X             }
X             else {
X                  /* Detect open modes: raw command, continue, goto-block */
X                  raw=norw=rdmode=FALSE;
X                  for( z=(char *)BADDR(mypkt->dp_Arg3)+1 ; z[0]!=':' ; z++ );
X                  if(!memcmp(z+1,RAWNAME,RAWLEN)) raw=norw=TRUE;
X                  else if( z[1] == '*' ) norw=TRUE;
X                  else if( isdigit((int)z[1]) ) {
X                         blknum = (ULONG) strtol(z+1,NULL,0);
X                         norw=TRUE;
X                         }
X
X                  DoSense(0);  /* eat tape-change status */
X                  if(norw) x=0;
X                  else x=TapeIO(TREWIND,0,CTLWAIT);
X                  if(x) {
X                     DoSense(x);
X                     FreeStuff(TBSize);
X                     returnpkt(mypkt,DOSFALSE,ERROR_DEVICE_NOT_MOUNTED);
X                  }
X                  else {
X                     tpsize = TapeIO(RDCAP,0,CTLWAIT) ? /* get tape capacity in sns */
X                                LONG_MAX : ((sns[2] << 8) | sns[3]) + 1;
X                     MPR3("%d * %d = %d\n", tpsize,blksize,tpsize*blksize)
X                     open=TRUE;
X                     dirty=FALSE;
X                     inprog=FALSE;
X                     Boff=0;
X                     Bn=0;
X                     rem = TBSize;
X                     if(!norw) blknum = reserved;
X                     MPR1("Opened at block %d\n",blknum)
X                     if (mypkt->dp_Type==ACTION_FINDINPUT)  {
X                        rdmode=TRUE;
X                        x= TapeIO(TREAD,0,CTLWAIT);      /* fill 1st buffer   */
X                        blknum += numblks;
X                        if(!x) x=TapeIO(TREAD,1,CTLIMM); /* start reading 2nd */
X                     }
X                     returnpkt(mypkt,DOSTRUE,mypkt->dp_Res2);
X                  }
X             }
X          }
X          break;
X
X     case ACTION_END:        /*----------- Close() -----------*/
X          if(open) {
X            if(dirty) {
X               if(raw) TapeIO(RAWCMD,Bn,CTLWAIT);  /* send user command */
X               else    TapeIO(TWRITE,Bn,CTLWAIT);  /* write last block */
X            }
X            else if(inprog) TapeIO(TFINISH,0,CTLWAIT); /* wait for last one */
X            open=FALSE;
X            FreeStuff(TBSize);
X          }
X          returnpkt(mypkt,DOSTRUE,mypkt->dp_Res2);
X          if(!rdmode) blknum += numblks;
X          MPR1("Closed at block %d\n",blknum)
X          break;
X
X     case ACTION_READ:       /*----------- Read() ------------*/
X          if(x) {
X              DoSense(x);
X              mypkt->dp_Arg3 = -1;
X              goto RDERR;
X          }
X          dptr = (UBYTE *) mypkt->dp_Arg2;
X          dcnt =           mypkt->dp_Arg3;
X          while(dcnt)   {
X            if(!rem)     {
X               blknum += numblks;   /* start reading next buffer */
X               if(x=TapeIO(TREAD,Bn,CTLIMM))  {
X                   DoSense(x);
X                   mypkt->dp_Arg3 = -1;
X                   goto RDERR;
X               }
X               Bn ^= 1;             /* switch to other (filled) buffer */
X               rem = TBSize;
X               Boff = 0;
X            }
X            mcnt = (dcnt>rem) ? rem : dcnt;
X            memcpy (dptr, &TapeBuff[Bn][Boff], mcnt);
X            dcnt -= mcnt ;
X            Boff += mcnt ;
X            rem  -= mcnt ;
X            dptr += mcnt ;
X          }
X          RDERR:
X          returnpkt(mypkt,mypkt->dp_Arg3,mypkt->dp_Arg2);
X          break;
X
X     case ACTION_WRITE:      /*----------- Write() -----------*/
X          dptr = (UBYTE *) mypkt->dp_Arg2;
X          dcnt =           mypkt->dp_Arg3;
X          while (dcnt)    {
X            if (dcnt >= rem) {
X               memcpy (&TapeBuff[Bn][Boff], dptr, rem);
X               if( x=TapeIO(TWRITE,Bn,CTLIMM) ) {
X                       DoSense(x);
X                       mypkt->dp_Arg3 = -1;
X                       goto WRTERR;
X               }
X               blknum += numblks;
X               dcnt -= rem;
X               dptr += rem;
X               Boff  = 0;
X               rem   = TBSize;
X               Bn   ^= 1;
X               dirty = FALSE;
X            }
X            else {
X               memcpy (&TapeBuff[Bn][Boff], dptr, dcnt);
X               rem  -= dcnt;
X               Boff += dcnt;
X               dcnt  = 0;
X               dirty = TRUE;
X            }
X          }
X          WRTERR:
X          returnpkt(mypkt,mypkt->dp_Arg3,mypkt->dp_Res2);
X          break;
X
X     case ACTION_CURRENT_VOLUME:
X          returnpkt(mypkt,dvnode,DOSFALSE);
X          break;
X
X     case ACTION_LOCATE_OBJECT:  /* lock */
X          returnpkt(mypkt,mypkt->dp_Arg1,mypkt->dp_Res2);
X          break;
X
X     case ACTION_FREE_LOCK:      /* unlock */
X          returnpkt(mypkt,DOSTRUE,mypkt->dp_Res2);
X          break;
X
X     default:    /* say what? */
X          returnpkt(mypkt,DOSFALSE,ERROR_ACTION_NOT_KNOWN);
X          MPR1("Unsupported_Pkt=%d\n",mypkt->dp_Type)
X
X     } /* end of switch */
X } /* end of loop */
X} /* end of _main() */
X
X/**************************************************************************/
X
Xvoid DoSense(long x)
X{
X   sns[2] = sns[12] = 0;
X   x=x>>8;
X   if(x==0) TapeIO(TSENSE,0,CTLWAIT);
X   else if(x==HFERR_BadStatus)  {
X       TapeIO(TSENSE,0,CTLWAIT);
X       if(!(sns[0] & 0x70)) sns[2]=sns[0] & 0x0f; /* non-extended sense */
X       linktp->sense = sns[2];    /* keep last error info */
X       linktp->xsense = sns[12];
X   }
X   MPR3("io_Error=%d  Sense=%X,%02X\n", x, sns[2], sns[12])
X   return;
X}
X
X/**************************************************************************/
X
Xvoid FreeStuff(ULONG bs)
X{
X   if(inprog) TapeIO(TFINISH,0,CTLWAIT); /* just in case */
X   if(TapeBuff[0]) FreeMem(TapeBuff[0],bs);
X   if(TapeBuff[1]) FreeMem(TapeBuff[1],bs);
X   TapeBuff[0] = TapeBuff[1] = NULL;
X   return;
X}
X
X/**************************************************************************/
X/* Nextnum parses and returns the next number in the startup string */
X
XULONG Nextnum(short kk)            /* kk=0 for first number */
X{                                  /* kk=1 for other numbers */
Xchar *zz;                          /* kk=-1 for pointer to last token */
X   zz = (kk) ? NULL : z;
X   z = strtok(zz,"/");
X   if(kk==-1) return( (ULONG) z);
X   else       return( (ULONG) strtol(z,NULL,0) );
X}
X
X/**************************************************************************
X   MonPrint requests that the TapeMon program print the message in 'dbb'.
X    Since this handler cannot do DOS I/O, it must beg the TapeMon program,
X    possibly running in a CLI somewhere, to do the printf for it.  If the
X    TapeMon is running, it will have installed a pointer to its task in
X    the link structure, and we can Signal() it.
X*/
X
Xvoid MonPrint(void)
X{
X   if(linktp->montask)  {
X      Signal(linktp->montask, linktp->monsig);
X      Wait  (linktp->handsig);
X      Signal(linktp->montask, linktp->monsig);
X      Wait  (linktp->handsig);
X   }
X   return;
X}
X
END_OF_FILE
if test 16555 -ne `wc -c <'tape.c'`; then
    echo shar: \"'tape.c'\" unpacked with wrong size!
fi
# end of 'tape.c'
fi
if test -f 'tape.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tape.h'\"
else
echo shar: Extracting \"'tape.h'\" \(1152 characters\)
sed "s/^X//" >'tape.h' <<'END_OF_FILE'
X/* BTNtape include file, version 1.0 */
X
X/* Operations supported by TapeIO */
X#define TSENSE  0    /* issue sense */
X#define TREAD   1    /* read blocks */
X#define TWRITE  2    /* write blocks */
X#define TREWIND 3    /* rewind (rezero) tape */
X#define RAWCMD  4    /* send user scsi command to tape */
X#define RDCAP   5    /* read capacity */
X#define TFINISH 6    /* wait for last operation to finish */
X
X/* these control how fast TapeIO returns to the caller */
X#define CTLWAIT 0    /* return when operation is done */
X#define CTLIMM  1    /* return immediately */
X
X/* inline message print functions */
X#define MPR0(XYZ)           sprintf(dbb,XYZ);           MonPrint();
X#define MPR1(XYZ,V1)        sprintf(dbb,XYZ,V1);        MonPrint();
X#define MPR2(XYZ,V1,V2)     sprintf(dbb,XYZ,V1,V2);     MonPrint();
X#define MPR3(XYZ,V1,V2,V3)  sprintf(dbb,XYZ,V1,V2,V3);  MonPrint();
X
X/* function prototypes */
Xvoid _main(void);
Xvoid   DoSense(long);
Xvoid   FreeStuff(ULONG);
XULONG  Nextnum(short);
Xvoid   MonPrint(void);
Xlong   TapeIO(int,int,UBYTE);
Xvoid   NewTape(void);
Xvoid   returnpkt(struct DosPacket *, ULONG, ULONG);
Xstruct DosPacket *taskwait(void);
END_OF_FILE
if test 1152 -ne `wc -c <'tape.h'`; then
    echo shar: \"'tape.h'\" unpacked with wrong size!
fi
# end of 'tape.h'
fi
if test -f 'tapeio.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tapeio.c'\"
else
echo shar: Extracting \"'tapeio.c'\" \(6492 characters\)
sed "s/^X//" >'tapeio.c' <<'END_OF_FILE'
X/*
X**  TapeIO: performs operations to the tape unit via SCSI-direct for BTNtape
X**     Version 1.0  09/10/90
X**
X**   (c) Copyright 1990 Robert Rethemeyer.
X**     This code is freely distributable and redistributable,
X**     for non-commercial purposes, provided this notice is included.
X**
X**   This code was derived from programs written by Robert Mitchell.
X*/
X
X#include <exec/types.h>
X#include <exec/io.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <devices/scsidisk.h>
X#include <intuition/intuition.h>
X#include <stdio.h>
X#include <string.h>
X
X#if defined AZTEC_C
X  #include <functions.h>
X#elif defined LATTICE
X  #include <proto/exec.h>
X  #include <proto/intuition.h>
X#endif
X
X#include "tape.h"
X#include "tplink.h"
X
X/* the following SCSI commands are defined for the 3M MCD-403 tape unit */
X#define CMD_TEST_UNIT_READY         0x00
X#define CMD_REZERO                  0x01
X#define CMD_REQUEST_SENSE           0x03
X#define CMD_FORMAT_UNIT             0x04
X#define CMD_SEND_SYSTEM_DATA        0x05
X#define CMD_RECEIVE_SYSTEM_DATA     0x06
X#define CMD_REASSIGN_BLOCKS         0x07
X#define CMD_SCSI_READ               0x08
X#define CMD_VERIFY_UNIT             0x09
X#define CMD_SCSI_WRITE              0x0a
X#define CMD_SEEK                    0x0b
X#define CMD_READ_SCSI_DEFECT        0x0d
X#define CMD_READ_CONTROLLER_INFO    0x0e
X#define CMD_WRITE_CONTROLLER_INFO   0x0f
X#define CMD_DRIVE_PASS_THRU         0x10
X#define CMD_READ_DRIVE_LINES        0x11
X#define CMD_INQUIRY                 0x12
X#define CMD_READ_QIC100_INFO        0x13
X#define CMD_WRITE_QIC100_INFO       0x14
X#define CMD_MODE_SELECT             0x15
X#define CMD_RESERVE                 0x16
X#define CMD_RELEASE                 0x17
X#define CMD_READ_QIC100_DEFECT      0x19
X#define CMD_MODE_SENSE              0x1a
X#define CMD_LOAD_UNLOAD             0x1b
X#define CMD_READ_DIAG_RESULT        0x1c
X#define CMD_SEND_DIAG               0x1d
X#define CMD_READ_CAPACITY           0x25
X#define CMD_READ_EXTENDED           0x28
X#define CMD_WRITE_EXTENDED          0x2a
X#define CMD_SEEK_EXTENDED           0x2b
X#define CMD_READ_SCSI_DEFECT_DATA   0x37
X#define CMD_WRITE_BUFFER            0x3b
X#define CMD_READ_BUFFER             0x3c
X
X#define CBLEN 6
Xextern          UBYTE  *cdb;
Xextern          UBYTE  *sns;
Xextern struct SCSICmd  *cmd;
Xextern          UBYTE  *TapeBuff[2];
Xextern struct IOStdReq *ior;
Xextern          ULONG  blknum;
Xextern          ULONG  numblks;
Xextern          ULONG  rwlen;
Xextern          ULONG  bugmask;
Xextern          long   tpsize;
Xextern struct tplink   *linktp;
Xextern          short  inprog;
Xextern          char   dbb[80];
X
X
Xlong TapeIO(int toper, int bn, UBYTE ctl)
X{
X char *z;
X short i;
X
X  if(inprog) { WaitIO((struct IORequest *)ior);
X               inprog = FALSE;
X               if(ior->io_Error)
X                 return((long)((ior->io_Error << 8) + cmd->scsi_Status));
X             }
X  if(toper == TFINISH) return(0L);
X  cmd->scsi_Command = cdb;
X  cmd->scsi_CmdLength = CBLEN;
X  cmd->scsi_Status = 0;
X  ior->io_Command = HD_SCSICMD;
X  ior->io_Data = (APTR) cmd;
X  ior->io_Length = sizeof(struct SCSICmd);
X  ior->io_Error = 0;
X  ior->io_Flags = IOF_QUICK;
X  for (i=0 ; i<CBLEN; i++) cdb[i] = 0x00;
X
X  switch(toper) {
X  case TREAD:
X    if((blknum+numblks)>=tpsize) NewTape();
X    cdb[0] = CMD_SCSI_READ;
X    cdb[2] = (UBYTE) ( (blknum >> 8) & 0x00ff);
X    cdb[3] = (UBYTE) (blknum & 0x00ff);
X    cdb[4] = (UBYTE) numblks ;
X    cmd->scsi_Data = (UWORD *) TapeBuff[bn];
X    cmd->scsi_Length = rwlen;
X    cmd->scsi_Flags = SCSIF_READ;
X    MPR2("Reading block %d * %d\n",blknum,numblks)
X    break;
X
X  case TWRITE:
X    if((blknum+numblks)>=tpsize) NewTape();
X    cdb[0] = CMD_SCSI_WRITE;
X    cdb[2] = (UBYTE)(blknum >> 8) & 0x00ff;
X    cdb[3] = (UBYTE)(blknum & 0x00ff);
X    cdb[4] = (UBYTE) numblks ;
X /* cmd->scsi_Data = (UWORD *) TapeBuff[bn]; */      /* 2090A bug fix */
X    cmd->scsi_Data = (UWORD *) ((ULONG) TapeBuff[bn] | bugmask);
X    cmd->scsi_Length = rwlen;
X    cmd->scsi_Flags = SCSIF_WRITE;
X    MPR2("Writing block %d * %d\n",blknum,numblks)
X    break;
X
X  case TREWIND:
X    cdb[0] = CMD_REZERO;
X    cmd->scsi_Data = (UWORD *) TapeBuff[bn];
X    cmd->scsi_Length = 0;
X    cmd->scsi_Flags  = 0;
X    MPR0("Rewinding\n")
X    break;
X
X  case TSENSE:
X    cdb[0] = CMD_REQUEST_SENSE;
X    cdb[4] = 28;  /* extended sense */
X    cmd->scsi_Length = 28;
X    cmd->scsi_Data = (UWORD *) sns;
X    cmd->scsi_Flags = SCSIF_READ;
X    MPR0("Sense:")
X    break;
X
X  case RDCAP:
X    cdb[0] = CMD_READ_CAPACITY;
X    cmd->scsi_Length = 8;
X    cmd->scsi_Data = (UWORD *) sns;
X    cmd->scsi_Flags = SCSIF_READ;
X    MPR0("Capacity:")
X    break;
X
X  case RAWCMD:    /* Convert hex in tape buffer to bytes in command buffer. */
X    i = 0;        /* Bytes are specified by hex digit pairs sep. by blanks  */
X    z = (char *)TapeBuff[bn];   /* terminated by newline */
X    while(z[0]!='\n' && i<32)  cdb[i++] = (UBYTE) 0xff & strtol(z,&z,16);
X    cmd->scsi_Data = (UWORD *) sns;
X    cmd->scsi_Length = 0;
X    cmd->scsi_Flags  = 0;
X    MPR0("Raw command\n")
X    break;
X
X  }
X  if(ctl == CTLWAIT) {
X         DoIO ((struct IORequest *)ior);    /* start sync io */
X         return((long)((ior->io_Error << 8) + cmd->scsi_Status));
X         }
X  else               {
X         BeginIO((struct IORequest *)ior);  /* start async io */
X         if(ior->io_Error)
X                  return((long)((ior->io_Error << 8) + cmd->scsi_Status));
X         if( !(ior->io_Flags & IOF_QUICK) )  inprog = TRUE;
X         return(0L);
X         }
X}
X
X/**************************************************************************
X*  NewTape()   Displays a requester asking user to insert a new tape.
X*/
X
Xvoid NewTape(void)
X{
X extern ULONG  blknum;
X extern short  reserved;
X extern void   DoSense();
X
X static struct IntuiText reqtext[] = {
X     { AUTOFRONTPEN,AUTOBACKPEN,AUTODRAWMODE,AUTOLEFTEDGE,AUTOTOPEDGE,AUTOITEXTFONT,
X        "  EOT: Insert next tape", AUTONEXTTEXT },
X     { AUTOFRONTPEN,AUTOBACKPEN,AUTODRAWMODE,AUTOLEFTEDGE,AUTOTOPEDGE,AUTOITEXTFONT,
X        "Continue", AUTONEXTTEXT },
X     { AUTOFRONTPEN,AUTOBACKPEN,AUTODRAWMODE,AUTOLEFTEDGE,AUTOTOPEDGE,AUTOITEXTFONT,
X        "Quit", AUTONEXTTEXT }
X  };
X
X TapeIO(TFINISH,0,CTLWAIT);   /* yeeks, recursion! */
X MPR0("Time for a new tape\n")
X if( AutoRequest(NULL,&reqtext[0],&reqtext[1],&reqtext[2],NULL,NULL,250,50) ) {
X      blknum=reserved;  /* reset block number for new tape */
X      DoSense(0);      /* eat tape change status (recursion again) */
X      }
X return;
X}
END_OF_FILE
if test 6492 -ne `wc -c <'tapeio.c'`; then
    echo shar: \"'tapeio.c'\" unpacked with wrong size!
fi
# end of 'tapeio.c'
fi
if test ! -d 'tapemon' ; then
    echo shar: Creating directory \"'tapemon'\"
    mkdir 'tapemon'
fi
if test -f 'tapemon/tapemon.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tapemon/tapemon.c'\"
else
echo shar: Extracting \"'tapemon/tapemon.c'\" \(3861 characters\)
sed "s/^X//" >'tapemon/tapemon.c' <<'END_OF_FILE'
X/**
X *  TapeMon:  a monitor program for the BTNtape handler.
X */
X#define MVERSION  "TapeMon V1.0"
X/*
X *  (c) Copyright 1990  Robert Rethemeyer
X *   This software may be freely distributed and redistributed,
X *   for non-commercial purposes, provided this notice is included.
X *------------------------------------------------------------
X *   Run TapeMon from a CLI to receive informational messages
X *   from the BTN-Tape handler process.  To terminate the
X *   monitor program, break the CLI using control-C or BREAK.
X */
X#include <exec/types.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <exec/ports.h>
X#include <exec/tasks.h>
X#include <exec/execbase.h>
X#include <libraries/dos.h>
X#include <stdlib.h>
X#include <stdio.h>
X#include <string.h>
X#include "/tplink.h"
X
X#if defined AZTEC_C
X  #include <functions.h>
X#elif defined LATTICE
X  #include <proto/exec.h>
X  #include <proto/dos.h>
X#endif
X
Xextern struct DosLibrary *DOSBase;
X
Xvoid main(int,char *[]);
Xvoid main(int argc, char *argv[])
X{
X struct Task    *tapeproc;
X struct tplink  *linktp;
X char *tapename;
X ULONG x;
X short run = 1;
X BYTE  signum;
X BYTE  oldpri;
X
X   printf("*** BTN-Tape Handler & Monitor ***\n(c) Copyright 1990 Robert Rethemeyer\n");
X
X   if(argc > 1) tapename = argv[1];
X   else         tapename = "TAPE";
X   if (!(tapeproc = FindTask(tapename)))  {
X         printf("Process %s not found...\n (be sure to use caps, no ':')\n",tapename);
X         exit(30);
X   }
X   if (!(linktp = (struct tplink *) tapeproc->tc_UserData))  {
X         printf("No linkage structure...\n wrong process, or\n handler not active yet?\n");
X         exit(31);
X   }
X   printf("%s: Proc %X DevNode %X\n",tapename,tapeproc,linktp->devnode);
X
X   if (strcmp(linktp->keyword,"TapeHandler"))  {
X         printf("Process %s doesn't look like BTN-Tape\n",tapename);
X         exit(32);
X   }
X
X   if (linktp->montask)  {
X         printf("There is already a TapeMon running\n");
X         exit(33);
X   }
X
X   if (!linktp->handsig) {
X          printf("Handler has no signal\n");
X          exit(34);
X   }
X
X   signum = AllocSignal(-1);
X   if (signum == -1)  {
X         printf("Unable to allocate signal for TapeMon\n");
X         exit(35);
X   }
X   linktp->monsig  = 1UL << signum;      /* give mask to tape handler */
X   linktp->montask = FindTask(0);        /* tell it where I am also   */
X   printf("%s Unit %X\n",linktp->driver,*(linktp->unit));
X   if(linktp->sense)
X       printf("Last sense= %X,%02X\n",linktp->sense,linktp->xsense);
X   printf("Use ^C to terminate TapeMon\n%s\n",linktp->version);
X
X   /* Set the monitor priority to the same as that of the handler */
X   oldpri = SetTaskPri (linktp->montask, (long)tapeproc->tc_Node.ln_Pri);
X
X   /* The main loop.  Wait for a signal from the handler, then print the
X      contents of dbb.  Some extra handshaking must then be done to sync
X      the two processes and prevent races.  If a control-C occurs during
X      a Wait, then finish whatever was in progress before ending the loop.
X   */
X
X   while(run)  {
X     x=Wait(linktp->monsig | SIGBREAKF_CTRL_C);   /* Wait for req from hndlr */
X     if  (x & SIGBREAKF_CTRL_C) run = 0;
X     if(!(x & linktp->monsig) ) continue;
X
X     printf(" %s",linktp->dbb);                   /* print handler's message */
X     Signal(tapeproc, linktp->handsig);           /* tell it we are 'done'   */
X
X     x=Wait(linktp->monsig | SIGBREAKF_CTRL_C);   /* Wait for ack of 'done'  */
X     if  (x & SIGBREAKF_CTRL_C) run = 0;
X     if(!(x & linktp->monsig) ) Wait(linktp->monsig);
X
X     Signal(tapeproc, linktp->handsig);           /* Ack his ack */
X   }
X
X   /* Clean up and exit */
X
X   SetTaskPri(linktp->montask, (long) oldpri);   /* restore priority */
X   linktp->montask = NULL;                      /* break link with handler */
X   linktp->monsig  = 0;
X   FreeSignal((ULONG)signum);
X   printf("TapeMon terminated\n");
X   exit(0);
X}
END_OF_FILE
if test 3861 -ne `wc -c <'tapemon/tapemon.c'`; then
    echo shar: \"'tapemon/tapemon.c'\" unpacked with wrong size!
fi
# end of 'tapemon/tapemon.c'
fi
if test -f 'tapemon/tapemon.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tapemon/tapemon.doc'\"
else
echo shar: Extracting \"'tapemon/tapemon.doc'\" \(3964 characters\)
sed "s/^X//" >'tapemon/tapemon.doc' <<'END_OF_FILE'
X****    TapeMon:  a monitor program for BTNtape handler           ****
X****       Version 1.0   09/10/90                                 ****
X****       Freeware by Bob Rethemeyer   (DrBob@cup.portal.com)    ****
X****      (c) Copyright 1990  Robert Rethemeyer                   ****
X
XTapeMon is an optional companion program to the BTNtape SCSIdirect
Xtape handler.  Since the handler cannot directly inform you of what
Xit is doing,  TapeMon, running in a separate CLI, communicates with
Xthe handler and prints information for you.  Think of it as a window
Xinto the handler.
X
XTo run TapeMon, bring up a separate CLI window.  Enter "TapeMon" or
X"TapeMon name", where name is the name of the handler device process.
XIf you do not enter the name, the monitor will default to using "TAPE".
XIf you do enter the name, it must be in uppercase letters, and must
Xnot have an ending colon.
X
XThe handler must be loaded and running for TapeMon to work.  Otherwise
Xit prints a message and immediately quits.  If you have mounted the
Xtape handler but not accessed the tape yet, the handler is not yet loaded,
Xand TapeMon will give up.  To avoid this, invoke TapeMon after starting
Xtape access, or use "Mount = 1" in your mountlist entry.
X
XOnce the handler is loaded and running, you may invoke or terminate
Xthe monitor at any time (but only one TapeMon may run at a time).
XTo terminate the monitor, enter control-C from the TapeMon CLI window,
Xor send a BREAK command from another CLI.
X
XIf the handler encounters a tape error, it remembers the data returned
Xby SENSE.  When TapeMon is started, it prints the retained sense data.
XSo if you weren't running TapeMon at the time an error occurs, you can
Xstill see the sense data by starting TapeMon after the fact.
X
XThe following summarizes the messages from the handler/monitor:
X
X  Opened at block x         printed when the TAPE: file is opened by DOS.
X                            x is the first block number of the file.
X
X  Closed at block x         printed when the TAPE: file is closed by DOS.
X                            x is the next available block.
X
X  Writing block x * n       printed when a tape write is started by the
X                            handler. x = starting block, n = number of blocks
X
X  Reading block x * n       printed when a tape read is started by the handler.
X
X  Unsupported_pkt= x        printed when DOS sends a packet which the handler
X                            rejects.  Example: 25 for the INFO command.
X
X  Rewinding                 printed when handler starts a tape rewind
X
X  Raw command               printed when handler receives a raw command request
X
X  Last sense= x,yy          retained sense data printed at TapeMon startup
X
X  Sense: io_Error= z  Sense= x,yy    printed when the handler issues SENSE
X                                     to the tape drive.  z is the Amiga
X                                     error code returned by the scsi driver,
X                                     n is the basic sense code returned by
X                                     the drive, and yy is the extended sense.
X
X  Capacity: xxxx * yyyy = zzzzzzzz   prints the capacity of the tape volume.
X                                     x is the number of blocks on the tape,
X                                     y is the size of a block, and z is the
X                                     total volume capacity in bytes.
X
X  Can't get memory for tape buffers   printed for Open() attempts when not
X                                      enough memory is available for buffers.
X
X  Time for a new tape                printed when EOT requester displayed
X
X
XHOW IT WORKS
X
XTapeMon works by finding the tape handler process and locating a common
Xdata structure attached to it.  The monitor waits for signals from the
Xhandler.  The handler detects the presence of the monitor and signals
Xit when a message needs to be printed.  A break signal causes the monitor
Xto disconnect itself from the handler and terminate.
X
END_OF_FILE
if test 3964 -ne `wc -c <'tapemon/tapemon.doc'`; then
    echo shar: \"'tapemon/tapemon.doc'\" unpacked with wrong size!
fi
# end of 'tapemon/tapemon.doc'
fi
if test -f 'tapemon/tapemon.lmk' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tapemon/tapemon.lmk'\"
else
echo shar: Extracting \"'tapemon/tapemon.lmk'\" \(231 characters\)
sed "s/^X//" >'tapemon/tapemon.lmk' <<'END_OF_FILE'
X# LATTICE MAKEFILE FOR TAPE MONITOR
X
XCFLAGS= -b1 -mat -cakfsu
X
XLIBS=LIB:lc.lib+LIB:amiga.lib
X
Xtapemon : tapemon.o
X   blink FROM LIB:c.o+tapemon.o TO $@ SC SD LIB $(LIBS)
X
Xtapemon.o : tapemon.c /tplink.h
X    LC $(CFLAGS) tapemon.c
X
END_OF_FILE
if test 231 -ne `wc -c <'tapemon/tapemon.lmk'`; then
    echo shar: \"'tapemon/tapemon.lmk'\" unpacked with wrong size!
fi
# end of 'tapemon/tapemon.lmk'
fi
if test -f 'tapemon/tapemon.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tapemon/tapemon.uu'\"
else
echo shar: Extracting \"'tapemon/tapemon.uu'\" \(10953 characters\)
sed "s/^X//" >'tapemon/tapemon.uu' <<'END_OF_FILE'
Xbegin 644 tapemon
XM```#\P`````````"``````````$```;T```!(0```^D```;T2.=^_B1()`!)_
XM^0`````L>``$1_D```(<<@`@/````)I@`B;!4<C__"E/`EPI3@)40JP"6'``?
XM(CP``#``3J[^SD/Z`5IP`$ZN_=@I0`.P9@9P9&```/PF;@$4*6L`F`)02JL`#
XMK&=H(`^0KP`X!H````"`*4`"("!K`*S1R-'((F@`$-/)T\D@`G(`$ADI20)D$
XMT(%2@$)G4H`"0/_^G\!5@$)W"``@`E.`U($?L@``(`!3@E'(__8?O``@(`!3>
XM@A^Q(``@`%'*__@B3R\)8'(I:P`Z`B!P?U*`T:P"($'K`%Q.KOZ`0>L`7$ZNU
XM_HPI0`)8+P`D0"`J`"1G$BQL`[`@0"(H```I00)03J[_@B(J`"!G&B0\```#%
XM[4ZN_^(I0`)@9PKEB"!`)V@`"`"D(&P"6"\(2&P"'"!H`"0I:``$`F1.N@1RB
XM3KH3VG``8`0@+P`$+P`@+`)(9P0@0$Z03KH.LBQX``0B;`.P3J[^8DZZ!$A*U
XMK`)89QHB+`)@9P1.KO_<+'@`!$ZN_WPB;`)83J[^AB`?+FP"7$S??WY.=61OU
XM<RYL:6)R87)Y`$Y5_^R_[`(@90`(9DCG#S(N+0`(>@%(>@(>3KH#]%A/<`&^)
XM@&\,(&T`#"MH``3_]&`(0?H"2BM(__0B;?_T+'@`!$ZN_MHF0"`+9A@O+?_T/
XM2'H",DZZ!"9(>``>3KH+/D_O``PD:P!8(`IF$DAZ`DY.N@.>2'@`'TZZ"R)0)
XM3R\J``PO"R\M__1(>@)X3KH)P$_O`!`@4D/Z`H(0&+`99@9*`&;V9Q@O+?_T<
XM2'H">DZZ`\Q(>``@3KH*Y$_O``Q*J@`@9Q)(>@*(3KH#1DAX`"%.N@K*4$]*%
XMJ@`89A)(>@*43KH#+DAX`").N@JR4$]P_RQX``1.KOZV*``,!`#_9A)(>@*(2
XM3KH#"DAX`"-.N@J.4$]P`!`$<@'AH25!`!R3R2QX``1.KO[:)4``("!J`!`O8
XM$"\J``A(>@)Z3KH)$D_O``Q**@`D9QQP`!`J`"1R`!(J`"4O`2\`2'H"9$ZZG
XM"/!/[P`,+RH`!$AZ`FI.N@,.4$]P`!`K``DB:@`@+'@`!$ZN_M0;0/_L2D5G7
XM<"`J`!P`0!``+'@`!$ZN_L(L``@&``QG`GH`(`;`J@`<9]HO*@`42'H"0$ZZ9
XM`L103R)+("H`&"QX``1.KOZ\("H`'`!`$`!.KO["+``(!@`,9P)Z`"`&(BH`?
XM',"!9@8@`4ZN_L(B2R`J`!A.KOZ\8(QP`!`M_^PB:@`@+'@`!$ZN_M1"J@`@=
XM0JH`''``$`1.KOZP2'H!V$ZZ`>Q"ETZZ"7),[4SP_]!.74YU*BHJ($)43BU47
XM87!E($AA;F1L97(@)B!-;VYI=&]R("HJ*@JI($-O<'ER:6=H="`Q.3DP(%)O@
XM8F5R="!2971H96UE>65R"@``5$%010``4')O8V5S<R`E<R!N;W0@9F]U;F0N-
XM+BX*("AB92!S=7)E('1O('5S92!C87!S+"!N;R`G.B<I"@!.;R!L:6YK86=E'
XM('-T<G5C='5R92XN+@H@=W)O;F<@<')O8V5S<RP@;W(*(&AA;F1L97(@;F]TW
XM(&%C=&EV92!Y970_"@``)7,Z(%!R;V,@)5@@1&5V3F]D92`E6`H`5&%P94AA9
XM;F1L97(`4')O8V5S<R`E<R!D;V5S;B=T(&QO;VL@;&EK92!"5$XM5&%P90H`?
XM`%1H97)E(&ES(&%L<F5A9'D@82!487!E36]N(')U;FYI;F<*`$AA;F1L97(@4
XM:&%S(&YO('-I9VYA;`H``%5N86)L92!T;R!A;&QO8V%T92!S:6=N86P@9F]RE
XM(%1A<&5-;VX*```E<R!5;FET("58"@!,87-T('-E;G-E/2`E6"PE,#)8"@``>
XM57-E(%Y#('1O('1E<FUI;F%T92!487!E36]N"B5S"@`@)7,`5&%P94UO;B!T:
XM97)M:6YA=&5D"@!.=4YU2.<#$"9O`!`@2TH89OQ3B)'++`A^`!X;2H=G,E.LJ
XM`$9M%B!L`#Y#Z``!*4D`/B`'$(!R`!(`8-P@!W(`$@!(;``Z+P%.N@%V4$\BO
XM`&#&2&P`.DAX__].N@%D4$\@!DS?",!.=0```````'!A3E7_W$CG#S`F;P!$0
XM?`!![0`,*TC_\AX;2@=G``$*<"6^`&8``,P>&W``$`=R&%U!:P``B+![$`AF?
XM]$[[$`0`9&```%``>&```!H`<&```!0`<V````(@;?_R)%@K2/_R8$H@;?_R6
XM*!@K2/_R1>W_['H'2H5K%B`$<@_`@4'Z`,#1P!204XKHA%.%8.9"+?_M8!H@$
XM;?_R*!@K2/_R+P1(;?_E3KH1.%!/1>W_Y2\*3KK^Y%A/W(!@`/]>4H93K`!&4
XM;1@@;``^0^@``2E)`#X@!Q"`<@`2`&``_SYP`!`'2&P`.B\`3KH`:E!/(@!@Z
XM`/\H4H93K`!&;1@@;``^0^@``2E)`#X@!Q"`<@`2`&``_PAP`!`'2&P`.B\`U
XM3KH`-%!/(@!@`/[R2&P`.DAX__].N@`@(`9,[0SP_\1.74YU,#$R,S0U-C<X!
XM.4%#1$5&````3E7_[$CG+Q`N+P`T)F\`."@'<#'`JP`89P9P_V```G`(*P`'A
XM`!I6P$0`2(!(P"P`2JL`%&8``(0(*P`"`!MF>G``)T``#'+_OH%G``)"+PM.9
XMN@^*6$]*@&<,".L`!0`;</]@``(J".L``0`;2@9G#B`K`!0B`$2!)T$`#&`([
XM("L`%"=```Q3JP`,;18@:P`$0^@``2=)``0@!Q"`<@`2`&`2(`=R`!(`+PLO/
XM`6$`_U)03R(`(`%@``'6""L``@`;9UAP_[Z`9@9P`&```<(@!QM`__]*!F<B@
XM<@J^@68<<@(O`4AZ`;(O*P`<*T'_\$ZZ"$Q/[P`,*@!@&G(!+P%(;?__+RL`A
XM'"M!__!.N@@P3^\`#"H`?O]@``#@".L``0`;2@9G4G#_OH!G3%2K``QR"KZ!F
XM9B8@:P`$0^@``2=)``00O``-(BL`#$J!:PHO"R\`80#^KE!/4JL`#"!K``1#=
XMZ``!)TD`!"`'$(`B*P`,2H%K``$<?O\@*P`$D*L`$"M`__!G<@@K``8`&F=26
XM2'@``D*G+RL`'$ZZ`R!/[P`,*T#_[$H&9SA3K?_L;3)"IR\M_^PO*P`<3KH#6
XM`$AX``%(;?_]+RL`'$ZZ#^Q/[P`82JP"-&8*$"W__7(:L`%GR"\M__`O*P`0W
XM+RL`'$ZZ!U!/[P`,*@!@`GH`</^Z@&8(".L`!0`;8`RZK?_P9P8(ZP`$`!M*:
XM!F<.(BL`%"0!1((G0@`,8!@(*P`"`!MG"'(`)T$`#&`((BL`%"=!``P@:P`0Q
XM)T@`!+Z`9RY3JP`,;18@:P`$0^@``2=)``0@!Q"`<@`2`&`2(`=R`!(`+PLO#
XM`6$`_9!03R(`<##`JP`89P1P_V`,</^X@&8$<`!@`B`$3-\(]$Y=3G4-"@``,
XM``````````!P82YL`EQ.N@]Z2'D````43KH#'```````````<&%(YR`P)F\`[
XM$"1+2A)G)'``$!)![`")"#```0@`9PIR`!(`=""2@F`$<@`2`!2!4HI@V"`+(
XM3-\,!$YU``````````!P84Y5__A(YP,P)F\`("1O`"0N+P`H($I*&&;\4XB16
XMRBP(($M*&&;\4XB1RR`((DO3P"M)__B\AV,"+`<@!B!*8`(2V%.`9/H@;?_XC
XM0C!H`"`+3-\,P$Y=3G4@+P`((&\`!$Y5__0B3W(*3KH$4`9!`#`2P4J`9O`@]
XM"1#AO\EF^D(0D(].74YU```@+P`((&\`!$Y5__0B3R(``D$`!P9!`#`2P>:(6
XM9O`@"1#AO\EF^D(0D(].74YU```P,3(S-#4V-S@Y86)C9&5F("\`""!O``1#&
XM[P`$,@`"00`/$OL0W.B(9O(@"2(/6($0X;*)9OI"$)"!3G4@;P`$(DAR`'``\
XM+P(,$``K9P8,$``M9@)22!`8!```,&T2#```"6X,)`'E@=*"TH'2@&#F#!$`!
XM+68"1($D'R`(4X`@;P`(((&0B4YU+P<N+P`(4JP#J%.L`$9M%B!L`#Y#Z``!N
XM*4D`/B`'$(!R`!(`8!0@!W(`$@!(;``Z+P%.NON(4$\B`"X?3G5.50``+PLF'
XM;P`,0JP#J$AM``PO"TAZ_ZQ.N@BV2&P`.DAX__].NOM8("P#J"9M__Q.74YU\
XM``!(YP\0+B\`&"PO`!PJ+P`@+P=.N@.$6$\F0"`+9@1P_V`>+P4O!B\K``1.<
XMN@&@3^\`#"@`2JP"-&<$</]@`B`$3-\(\$YU``````````!P84CG`S`N+P`4C
XM2H=N!G``8```I'`(OH!D`BX`(`=6@"X``D?__$7L`!`F4B`+9T`@*P`$L(=MP
XM,K"'9@P@4R2(GZP`%"`+8&X@*P`$D(=R"+"!918@2]'')(@D2"23)4``!)^LD
XM`!0@"V!,)$LF4V"\(`<B+`"$T(%3@$ZZ`@HB+`"$3KH!XBP`4(8@!E:`+``")
XM1O_\+P9.N@,N6$\F0"`+9Q(O!B\+3KH+%BZ'80#_5%!/8`)P`$S?#,!.=0``,
XM````````````````2.<#$"XO`!!'[``8(`MG-`@K``(`&V8H""L``0`;9R`@4
XM*P`$D*L`$"P`2H9G$B\&+RL`$"\K`!Q.N@,R3^\`#"938,@O!TZZ"B!83TS?F
XM",!.=0``2.<W$"XO`!PF;P`@+"\`)$JL`DQG!$ZZ#=A"K`(T(@<D"R8&+&P#-
XML$ZN_]`J`'#_NH!F#DZN_WPI0`(T<`4I0`.L(`5,WPCL3G4`````````````L
XM`````````````'!A2.<_`"XO`!PL+P`@*B\`)$JL`DQG!$ZZ#7A"K`(T(`53(
XM@"(')`8F`"QL`[!.KO^^*`!P_[B`9@Y.KO]\*4`"-'`6*4`#K"`%#(`````"G
XM9Q8,@`````%G"$J`9A@@!F`4(`30AF`.(@=T`'8`+&P#L$ZN_[Y,WP#\3G4`$
XM`$CG-Q`N+P`<)F\`("PO`"1*K`),9P1.N@S\0JP"-"(')`LF!BQL`[!.KO_6F
XM*@!P_[J`9@Y.KO]\*4`"-'`%*4`#K"`%3-\([$YU```O!RXO``A*K`),9P1.)
XMN@RZ(@<L;`.P3J[_W'``+A].=4CG,``D`"8!2$)(0\3!QL#`P=1#2$)"0M""-
XM3-\`#$YU2H!J```>1(!*@6H```Q$@6$``"!$@4YU80``&$2`1(%.=4J!:@``9
XM#$2!80``!D2`3G4O`DA!-`%F```B2$!(04A"-`!G```&A,$P`DA`-`"$P3`"<
XM2$(R`B0?3G4O`W80#$$`@&0```;AF5%##$$(`&0```;IF5E##$$@`&0```;E:
XMF55#2D%K```&XYE30S0`YJA(0D)"YJI(0X#!-@`P`C0#2$'$P9""9```"%-#L
XMT(%D_G(`,@-(0^>X2$#!028?)!].=2\'+B\`"'``*4`"-$J':R*^K```;!P@S
XM!^>`0>P":$JP"`!G#B`'YX!![`)HT<`@"&`(<`DI0`.L<``N'TYU````````3
XM``````````!(YP`R)FP#M"`+9Q0D4R)+("L`""QX``1.KO\N)DI@Z)'(*4@#=
XMN"E(`[1,WTP`3G5(YP$R+B\`%'`,WH`@!W(`+'@`!$ZN_SHF0"`+9@1P`&`Z"
XM)T<`"$7L`[0@:@`$)T@`!)'()HA*DF8")(M*J@`$9P8B:@`$(HLE2P`$2JP`E
XM!&8$*4L`!$'K``P@"$S?3(!.=0``````````````````2.<',"XO`!@F;P`<,
XM+"\`("\'3KK_`%A/)$`@"F8$</]@-@@J``,``V<02'@``D*G+P=.NOM(3^\`U
XM#"\&+PLO*@`$3KK\I$_O``PJ`$JL`C1G!'#_8`(@!4S?#.!.=0``3E7_Q$CGP
XM)S`F;P!<)&\`8'X`?`!Z`'``&WP`(/_[<@`K0?_V=/\K0O_R0>W_T!M`__$;7
XM0/_\*T'_Y"M!_^@K2/_,2A-G+'``$!,$0``@9Q170&<444!G"%5`9A9^`6`.-
XM?`%@"GH!8`8;?``!__Q2BV#0$!-R,+`!9@92BQM!__MP*K`39@P@4EB2*U#_B
XM]E*+8`Y(;?_V+PM.NOG"4$_7P!`3<BZP`68B4HMP*K`39@P@4EB2*U#_\E*+K
XM8`Y(;?_R+PM.NOF84$_7P!`3<FRP`68*&WP``?_Q4HM@"')HL`%F`E*+$!MRY
XM`!(`&T#_\`1!`%AG``%^!$$`"V<``@I306<D!$$`"V<``1)306<``5!706<`6
XM`;I506<``.1706<``5)@``'X2BW_\6<((%)8DB`08`8@4EB2(!`K0/_L;`IR9
XM`42M_^PK0?_H2JW_Z&<$<"U@"DH&9P1P*V`"<"`;0/_0<``0!B(M_^B"@'``@
XM$`6"@&<(4JW_S%*M_^0O+?_L+RW_S$ZZ^#I03RM`_\@@+?_R2H!J!G(!*T'_!
XM\B`M_\@B+?_RDH!([0`"_\1O-"!M_\PB2-/!+P`O"2\(3KH&HD_O``QP`!`M0
XM__LB+?_$(&W_S&`"$,!3@63Z("W_\BM`_\C1K?_D0>W_T"M(_\Q*!V<``3`;8
XM?``@__M@``$F2BW_\6<((%)8DB`08`8@4EB2(!`K0/_L8`#_9$HM__%G""!22
XM6)(@$&`&(%)8DB`0*T#_[$HM__QG$B!M_\P0_``P<@$K0?_D*TC_S"\`+RW_K
XMS$ZZ]YY03RM`_\A@`/\R&WP`,/_[("W_\DJ`:@9P""M`__)*+?_Q9P@@4EB2*
XM(!!@!B!26)(@$"M`_^Q*+?_\9Q8@;?_,$/P`,!#\`'AR`BM!_^0K2/_,+P`O>
XM+?_,3KKW@E!/*T#_R'!8L"W_\&8`_M!(;?_03KKV7EA/8`#^PB!26)(B4"M)[
XM_\QF"$'Z`-@K2/_,(&W_S$H89OQ3B)'M_\PK2/_D("W_\DJ`:R:QP&\B*T#_E
XMY&`<<`$K0/_D(%)8DB`0&T#_T$(M_]%@!G``8```C"`M_^0B+?_VLH!L"'0`D
XM*T+_]F`$D:W_]DH'9S93K?_D;1AP`"!M_\P0&"\`*TC_S"!M`!!.D%A/8.)3C
XMK?_V;4AP`!`M__LO`"!M`!!.D%A/8.A3K?_V;1)P`!`M__LO`"!M`!!.D%A/#
XM8.A3K?_D;1AP`"!M_\P0&"\`*TC_S"!M`!!.D%A/8.(@"TS?#.1.74YU``!.S
XM5?_T2.<!,"9O`"`D;P`D*VT`$/_V'AI*!V<T<"6^`&8BL!)F!%**8!HO"TAMA
XM__8O"F$`_!9/[P`,*T#_^F<$)$!@TG``$`<O`$Z36$]@QDS?#(!.74YU``!.G
XM5?_P2.<A,B9O`"P,K````"`#^FP``(80$W(@L`%G#'()L`%G!G(*L`%F!%*+T
XM8.A*$V=H("P#^N6`4JP#^D'L!`+1P"1(<"*P$V8F4HLDBTH39PIP(K`39P12:
XMBV#R2A-F#$AX``%.N@(D6$]@GD(;8)HDBTH39Q@0$W(@L`%G$'()L`%G"G(*8
XML`%G!%*+8.1*$V8"8`9"&V``_W)*K`/Z9@8@;`)88`1![`0"*4@#_DJL`_IF]
XM?$/Z`21-[`/`+-DLV2S9+-D\D2)L`E@@:0`D2'@`*"\H``1(;`/`3KKT>D_O^
XM``PL;`.P0>P#P"(()#P```/N3J[_XBE``FPI0`)T<A`I00)P*4`"?"E!`GCEC
XM@"M`__`L>``$D\E.KO[:(&W_\")`(V@`"`"D?@`K0/_T8"HL;`.P3J[_RBE`F
XM`FQ.KO_$*4`"=$'Z`*8B""0\```#[4ZN_^(I0`)\?A`@!P!`@`&!K`)H(`<`?
XM0(`"@:P"<`"L``"``P)X2JP`@&<$<`!@!B`\``"``"X`0JP`-"`'`$```2E`^
XM`#!P`2E``%8@!P!```(I0`!2<`(I0`!X(`<`0`"`*4``=$'Z`W8I2`),+RP#L
XM_B\L`_I.NNJ^0I=.NO943.U,A/_<3EU.=6-O;CHQ,"\Q,"\S,C`O.#`O`"H`B
XM````````````````2.<P,BQO`#@@;P`8(F\`'"1O`"`F;P`D("\`*"(O`"PD\
XM+P`P)B\`-$ZN_J1,WTP,3G4``"\+)F\`"$JK`!1G#`@K``,`&V8$<`!@-B\L[
XM`8Q.NO4.6$\G0``$)T``$$J`9@IP#"E``ZQP_V`6)VP!C``4<//!JP`8<``G&
XM0``,)T``""9?3G4``````````'!A2.<'`"XO`!`@+```4X`L`$I&:S`@!DC`;
XMYX!![`)H*C`(`$H%9QH(!0`$9A0@!DC`YX!![`)H+S`(!$ZZ]MA83U-&8,PO#
XM!TZZZ5A83TS?`.!.=0``("\`""!O``1.5?_T(D]L!A#\`"U$@'(*3KKW&`9!_
XM`#`2P4J`9O`0X;_)9OI"$"`(3EV0KP`$3G5.5?_H2.<!,BXO`#1*AVX&</]@X
XM``#2<`B^@&0"+@`@!U:`+@`"1__\)&T`""`M``C0A]^L`!1![``0)E`K0/_P\
XM*TC_]"`+9P``D"!+("L`!-'`*TC_[")M__"WR6,0)(LE1P`$+&W_]"R*<`!@3
XM>+?)9AHL4R2.("L`!"(`TH<E00`$+&W_]"R*<`!@6K7(9`B?K``4</]@3K7(K
XM9BQ*DV<.(%.SR&,(GZP`%'#_8#C?JP`$2I-G#K/39@H@*0`$T:L`!":1<`!@-
XM'BM+__0K;?_L_^@F4V``_VX@;?_T((I"DB5'``1P`$S?3(!.74YU``!(YP<P@
XM+B\`&"9O`!PL+P`@+P=.NO:(6$\D0"`*9@1P_V`>+P8O"R\J``1.NO4@3^\`0
XM#"H`2JP"-&<$</]@`B`%3-\,X$YU```@;P`$(F\`""`O``QO%K/(90S1P-/`Y
XM$R!3@&;Z3G42V%.`9OI.=0``3E7_J$CG`0(L>``$0_H`CG``3J[]V"M`_ZAFQ
XM"DAX`!1.NOWR6$]^`"!L`F0>*/__(`=#[?^P8`(2V%.`9/I"-7BP0>W_L"E(@
XM`9PO+?^H2'@`*$AX`/IP`"\`+P!(;`&X<@`O`4AL`:0O`4ZZ_1A(>``43KK]>
XMH$SM0(#_H$Y=3G4J*B!3=&%C:R!/=F5R9FQO=R`J*@``15A)5```:6YT=6ET/
XM:6]N+FQI8G)A<GD```````````!P84Y5_YA(YS,"?@`@;`)D'BC__W!/OH!OX
XM`BX`(`=#[?^O8`(2V%.`9/I"-7BO+'@`!)/)3J[^VBM`_Z8@0$JH`*QG4B(HY
XM`*SE@2)!+"D`.$CM``+_GDJ&9@0L*`"@2H9G-"QL`[`B!D'Z`+(D"'8+3J[_W
XMT"!'4H<@"!N\``H(KRQL`[`B!B8'0>W_KR0(3J[_T'#_8%(L>``$0_H`C'``%
XM3J[]V"M`_YIF!'#_8#I![?^O*4@!["\M_YI(>``\2'@`^G``+P`O`$AL`@A(!
XM;`'T2&P!X$*G3KK[]D_O`"13@&<$</]@`G``3-]`S$Y=3G4J*B!5<V5R($%BT
XM;W)T(%)E<75E<W1E9"`J*@``0T].5$E.544``$%"3U)4`"HJ*B!"<F5A:SH@5
XM`&EN='5I=&EO;BYL:6)R87)Y`"\'<``B/```,``L>``$3J[^SBX``H<``#``1
XM2H=G($JL`DQG&B!L`DQ.D$J`9@)@#D*L`DQ(>``43KK[ZEA/+A].=6&\3G4`)
XM`````^P````"`````0```!0````*`````````_(```/J````AP```"@`````A
XM`````````````````````````#H`````````````````````````````````Z
XM``````````!<````````````````````````````````````````````````<
XM``````````````````````````````````````````"`````!```("`@("`@$
XM("`@*"@H*"@@("`@("`@("`@("`@("`@("!($!`0$!`0$!`0$!`0$!`0A(2$L
XMA(2$A(2$A!`0$!`0$!"!@8&!@8$!`0$!`0$!`0$!`0$!`0$!`0$!`1`0$!`0V
XM$(*"@H*"@@("`@("`@("`@("`@("`@("`@("$!`0$"`@("`@("`@("`H*"@HD
XM*"`@("`@("`@("`@("`@("`@($@0$!`0$!`0$!`0$!`0$!"$A(2$A(2$A(2$(
XM$!`0$!`0$(&!@8&!@0$!`0$!`0$!`0$!`0$!`0$!`0$!$!`0$!`0@H*"@H*"V
XM`@("`@("`@("`@("`@("`@("`@(0$!`0(````````@#__P````X`#@``````D
XM`````````/__````!``$````````&A@```&0__\````$``0````````:+@``7
XM``#__P````X`#@```````!L^`````/__````!``$``````````````',__\`$
XM```$``0````````;6@````#__P````0`!````````!MD`````````^P````%V
XM`````````A0```(````!V````<0```&P````!`````$```'P```!M````#H`,
X+```8`````````_(`-
X``
Xend
Xsize 7796
END_OF_FILE
if test 10953 -ne `wc -c <'tapemon/tapemon.uu'`; then
    echo shar: \"'tapemon/tapemon.uu'\" unpacked with wrong size!
fi
# end of 'tapemon/tapemon.uu'
fi
if test -f 'tplink.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tplink.h'\"
else
echo shar: Extracting \"'tplink.h'\" \(771 characters\)
sed "s/^X//" >'tplink.h' <<'END_OF_FILE'
X/* Structure shared by BTNtape and TapeMon.  Version 1.0 */
X
Xstruct tplink {
X                char   *keyword;     /* name "TapeHandler" */
X                char   *version;     /* version string     */
X                char   *driver;      /* scsi driver name   */
X                void   *devnode;     /* device node address*/
X                ULONG  *unit;        /* scsi unit number   */
X                char   *dbb;         /* message from handler */
X                ULONG   handsig;     /* handler sig mask   */
X                ULONG   monsig;      /* monitor sig mask   */
X         struct Task   *montask;     /* monitor task ptr   */
X                UBYTE  sense;        /* last sense         */
X                UBYTE  xsense;       /* last extended sense*/
X       };
END_OF_FILE
if test 771 -ne `wc -c <'tplink.h'`; then
    echo shar: \"'tplink.h'\" unpacked with wrong size!
fi
# end of 'tplink.h'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.