.ENABL LC
 ; library-created 3/5/80 - for WHT-SM c runtime
        .title SND
        .enabl lc
        .psect SND
        .enabl ama
	.nlist sym
        .mcall qiow$,dir$,fdop$r,finit$,fsrsz$,nmblk$,fdbk$r,qiow$s
        .mcall fdat$r,fdrc$r,read$,wait$,close$,exst$s,alun$,gmcr$
        .mcall gtsk$s,mrkt$s,cmkt$s
        flun=2 
        fev=20. 
        cr=15
        esc=33
        good=1
        bad=4
begin:   
namep:  .word 0                         ;temp cell
puic:   .word 0                         ;owner uic
uic:    .word 0                         ;uic of file
len:    .word 0                         ;length of file name
name:   .blkb 16.*3+20                  ;file name is input here
         
buf:    .blkb 16.                       ;put packet buffer
code:   .word                           ; is 16 bytes,2 bytes=code,2bytes=cksum
sum:    .word 0                         ; this is the checksum
        .blkb 6.                        ;safety - so we don't clobber anything
ack:    .byte 'A,'A                     ;ack/nack buffer (goes back)
newline: .byte 12,15,0,0                ;newline output string
ios:    .word 0,0                       ;2 word qio status block
i:      .word 0                         ;index
j:      .word 0                         ;index
        .word 0                         ;spare
p:      .word ffdb                      ;pointer into fdb/block buffer
fsize:  .word 0				;size of the file in blocks
bnum:   .word 0,0                       ;block number double prec
bios:   .word 0,0                       ;block i/o status block
dsw:    .word 0                         ;save dsw on get mcr line
alun:   alun$  3,TI,0
alunb:  alun$  1,CM 0
kill:   qiow$ io.kil ,1                     ;kill i/o
inabo:  qiow$ io.ral ,1,7,,ios,,<buf,2>     ;input qio on abort code
in:     qiow$ io.ral ,1,7,,ios,,<ack,1>     ;input qio
insy:   qiow$ io.ral ,1,7,,ios,,<buf,1,0>   ;input sync
out:    qiow$ io.wal ,1,7,,ios,,<buf,20.,0> ;output qio
osync:  qiow$ io.wal ,1,7,,ios,,<osy,4,0>   ;output qio
osy:    .ascii /SSSS/                           ;output sync
gmcr:   gmcr$
	.MCALL CSI$
	CSI$
	.EVEN
CSIBLK:: .BLKB C.SIZE
ffdb:
;FDB lun B/R,[block]
       .mcall fdop$a,fdat$a,fdbdf$,fdrc$a,fdbk$a
       fdbdf$
       fdop$a flun,csiblk+c.dsds
       fdat$a r.fix,,512.
       fdrc$a fd.rwm
       fdbk$a block,512.
block:  .blkb   512.                    ;block buffer
dfnb:   nmblk$ ,,,sy                    ;defaults to current uic, and sy
stat:   .blkw 5                         ;statistics block (for contiguous attr)
        .even
 
start:     
        finit$ 
        dir$ #alun                      ;lun for ti:
        dir$ #alunb                     ;lun for communications
        mov #begin,r0                   ;for debugging
        mov #ffdb,r1
        mov #p,r2
        mov #ios,r3
        mov #in-buf,r4
        nop 
        nop 
         
         
        dir$ #gmcr
        mov $dsw,dsw
	TST dsw		;IS dsw LT #0
	BGE SND1	;Not if GE
usage:
        br SND6
SND5=.
	.ascii ~Send Usage: Send filename~
SND4=.
	.even
SND6=.
        qiow$s #io.wvb,#3,#15. ,, ,, <#<SND5>,#<SND4-SND5>,#<40>>
	        exst$s #bad
	JMP SND7
SND1=.			; 
 
                mov dsw,r1              ;length computation
	MOV #gmcr+g.mcrb+3,r0	;Init loop index
SND8=.
	CMP r0,#gmcr+g.mcrb+79.	;done loop?
	BHI SND9	;yes if HI
	CMPB (r0),#esc		;IS (r0) = #esc
	BNE SND16	;Not if NE
	BR SND14		;condition met
SND16=.
	CMPB (r0),#cr		;IS (r0) = #cr
	BNE SND13	;Not if NE
SND14=.
	BR SND11		;condition met
SND13=.
	CMPB (r0),#40		;IS (r0) = #40
	BNE SND10	;Not if NE
SND11=.
	JMP SND9		;break 
SND10=.			; 
SND12=.
		        dec r1
	INC r0
	JMP SND8		;back to top
SND9=.
	CMPB (r0),#esc		;IS (r0) = #esc
	BNE SND22	;Not if NE
	BR SND20		;condition met
SND22=.
	CMPB (r0),#cr		;IS (r0) = #cr
	BNE SND19	;Not if NE
SND20=.
badfil:
        br SND27
SND26=.
	.ascii ~Bad file name~
SND25=.
	.even
SND27=.
        qiow$s #io.wvb,#3,#15. ,, ,, <#<SND26>,#<SND25-SND26>,#<40>>
                     jmp usage
SND19=.			; 
SND21=.
                sub #4, r1              ;don't include blank or uic
	BGT SND28	;Not if GT
	                br badfil
SND28=.			; 
SND30=.
                inc r0                  ;point past blank
                mov r1,len              ;the length of file is in r1
                mov r0,namep            ;and the name starts at r0
SND7=.			; 
SND3=.
         
        mov namep,r0
        mov #name,r1
        mov len,r2
SND31=.
        movb (r0)+,(r1)+
        sob r2,SND31
         
;FILE addr-of-string len-str
	.MCALL CSI$1,CSI$2
	CSI$1 #CSIBLK,#name,len
	BCS SND32
        CSI$2   ,OUTPUT
SND32=.
	BCC SND33	;Not if CC
            jmp badfil
SND33=.			; 
SND35=.
        mov #block,r0                   ;use scratch buffer
        gtsk$s r0                       ;get task info
        mov block+g.tsdu,puic           ;protection uic
        mov block+g.tspc,uic            ;default uic (might be file uic)
	CMPB gmcr+g.mcrb,#1		;IS gmcr+g.mcrb = #1
	BNE SND36	;Not if NE
            movb gmcr+g.mcrb+1,uic      ;yes, so -
            movb gmcr+g.mcrb+2,uic+1    ;copy from command line
SND36=.			; 
SND38=.
        mov uic,r1
        mov @#.fsrpt,r0                 ;do this ourselves so we can use
        mov r1,102(r0)                  ;fcs res
        clr 24(r0)                      ;this is what module rwfsr2 does
        mov #stat,ffdb+f.stbk           ;set up to return statistics
;OPEN fdb rd/wrt/upd/mod
	.mcall open$
	open$ #ffdb,#fo.rd
	BCC SND39	;Not if CC
            call putl
        br SND44
SND43=.
	.ascii ~Cannot open file - Fcs error code (octal) = ~
SND42=.
	.even
SND44=.
        qiow$s #io.wvb,#3,#15. ,, ,, <#<SND43>,#<SND42-SND43>,#<0>>
            mov f.err+FFDB,r0
            call putn8b
            call putl
            exst$s #bad
SND39=.			; 
SND41=.
	TST stat+2		;IS stat+2 NE #0
	BEQ SND48	;Not if EQ
	BR SND46		;condition met
SND48=.
	TST stat		;IS stat NE #0
	BEQ SND45	;Not if EQ
SND46=.
        neg len                         ;send negative file length = contig.
SND45=.			; 
SND47=.
        nop
        nop
        mov ffdb+f.dspt,r2              ;get data set descripter pointer
        add #4,r2                       ;address of string descripter
	TST (r2)		;IS (r2) NE #0
	BEQ SND51	;Not if EQ
                mov #uic,r3             ;output the uic here
	        call .ascpp
SND51=.			; 
SND53=.
	CMPB puic+1,uic+1		;IS puic+1 NE uic+1
	BEQ SND54	;Not if EQ
	CMPB puic+1,#10		;IS puic+1 HI #10
	BLOS SND57	;Not if LOS
        br SND62
SND61=.
	.ascii ~LOGIN uic group must match FILE uic group to send file~
SND60=.
	.even
SND62=.
        qiow$s #io.wvb,#3,#15. ,, ,, <#<SND61>,#<SND60-SND61>,#<40>>
              exst$s #bad
SND57=.			; 
SND59=.
SND54=.			; 
SND56=.
        dir$ #osync                     ;output sync
        call sync                       ;sync on receiver too
        call putfdb                     ;output the fdb part
        call putnam                     ;output the file name
         
        mov #ffdb,r1                    ;now prepare the fdb
        mov f.efbk+2(r1),fsize          ;save file size
	TST f.ffby(r1)		;IS f.ffby(r1) = #0
	BNE SND63	;Not if NE
	TST fsize		;IS fsize GT #0
	BLE SND66	;Not if LE
	BR SND69	;Here IF fsize GT #0    
SND66=.
	BR SND63		;Here if not
SND69=.
	        dec fsize
SND63=.			; 
SND65=.
         
        call putfil
        call closeit
         
         
          exst$s #good
         
         
closeit: 
        close$ #ffdb
        rts pc
         
putfil:  
	MOV #1,bnum+2	;Init loop index
SND70=.
	CMP bnum+2,fsize	;done loop?
	BGT SND71	;yes if GT
            read$ #ffdb,#block,#512.,#bnum,#fev,#bios
            wait$ 
            call putblk
	INC bnum+2
	JMP SND70		;back to top
SND71=.
        rts pc
putfdb:  
        mov #ffdb,p                    ;point at input
	MOV #1,j	;Init loop index
SND72=.
	CMP j,#7	;done loop?
	BGT SND73	;yes if GT
        mov p,r0
        mov #buf,r1
        mov #16.,r2
SND74=.
        movb (r0)+,(r1)+
        sob r2,SND74
            call putp                   ;put a packet out
            add #16.,p                  ;update to next area going out
	INC j
	JMP SND72		;back to top
SND73=.
        rts pc
putnam:  
         
        mov #puic,p                 ;point at input
	MOV #1,j	;Init loop index
SND75=.
	CMP j,#3	;done loop?
	BGT SND76	;yes if GT
        mov p,r0
        mov #buf,r1
        mov #16.,r2
SND77=.
        movb (r0)+,(r1)+
        sob r2,SND77
            call putp               ;put a packet out
            add #16.,p              ;update to next area going out
	INC j
	JMP SND75		;back to top
SND76=.
        rts pc
         
putblk:  
         
        mov #block,p                ;point at input
	MOV #1,j	;Init loop index
SND78=.
	CMP j,#32.	;done loop?
	BGT SND79	;yes if GT
        mov p,r0
        mov #buf,r1
        mov #16.,r2
SND80=.
        movb (r0)+,(r1)+
        sob r2,SND80
            call putp               ;put out packet
            add #16.,p              ;update to next area going out
	INC j
	JMP SND78		;back to top
SND79=.
        rts pc
putp:        
            clr sum
	MOV #buf,i	;Init loop index
SND81=.
	CMP i,#buf+17.	;done loop?
	BHI SND82	;yes if HI
                add @i,sum
	ADD #2,i
	JMP SND81		;back to top
SND82=.
                 
SND83=.
            dir$ #out
            dir$ #in
	CMPB ack,#'A		;IS ack = #'A
	BNE SND85	;Not if NE
	JMP SND84		;break 
SND85=.			; 
SND87=.
	CMPB ack,#'F		;IS ack = #'F
	BNE SND88	;Not if NE
                jmp abort
SND88=.			; 
SND90=.
        br SND93
SND92=.
	.ascii ~Checksum error reported, retrying~
SND91=.
	.even
SND93=.
        qiow$s #io.wvb,#3,#15. ,, ,, <#<SND92>,#<SND91-SND92>,#<40>>
	JMP SND83		;Repeat loop
SND84=.
l2:      
        return 
abort:
        dir$ #inabo
        call putl
        br SND96
SND95=.
	.ascii ~Unrecoverable error on other machine - code = ~
SND94=.
	.even
SND96=.
        qiow$s #io.wvb,#3,#15. ,, ,, <#<SND95>,#<SND94-SND95>,#<0>>
        mov buf,r0
        call putn8b
        call putl
        exst$s #bad
putstr:
        mov r0,r2
1$:     tstb(r0)+
        bne 1$
	MOV r0,r1
	SUB r2,r1
        dec r1
        qiow$s #io.wvb,#3,#7,,#ios,,<r2,r1,#0>
        rts pc
putl:
        mov #newline,r0
        call putstr
        rts pc
putn8:
        mov r0,r1
        mov #block,r0
        mov #1,r2
        call $cbomg
        clrb (r0)
        mov #block,r0
        call putstr
        rts pc
putn8b:
        mov r0,r1
        mov #block,r0
        clr r2
        call $cbomg
        clrb (r0)
        mov #block,r0
        call putstr
        rts pc
sync:
        mrkt$s ,#20.,#2,#timout            ;marktime for ast
        clr r2
SND97=.
	        clrb buf
	        dir$ #insy
	CMPB buf,#'R		;IS buf = #'R
	BNE SND99	;Not if NE
		        inc r2
	JMP SND102
SND99=.			; 
		        clr r2
SND102=.			; 
SND101=.
	CMP r2,#4		;IS r2 GE #4
	BLT SND103	;Not if LT
	JMP SND98		;break 
SND103=.			; 
SND105=.
	JMP SND97		;Repeat loop
SND98=.
        cmkt$s
        rts pc
timout:
	        dir$ #kill
        br SND108
SND107=.
	.ascii ~Initialization failure (time-out)~
SND106=.
	.even
SND108=.
        qiow$s #io.wvb,#3,#15. ,, ,, <#<SND107>,#<SND106-SND107>,#<40>>
                exst$s #bad
        fsrsz$   1
        .end start
