.title krtrme rms i/o for KERMIT-11 .ident /V04.64/ .library /LB:[1,1]RMSMAC.MLB/ ; /E64/ 05-May-96 John Santos ; ; From K11RMS.MAC. Name changed to avoid conflict with RT11 module. ; Moved RSTS/E versions of GETNXT, GETCR0, TGETCR here from KRTPAK ; Move messages to top. ; Add buffer for help file. ; grab the clock rate (ticks/second) from gtim$ in second ; Made packet buffer size = $ALLSIZ ; Remove unused code. Return file size on open/create ; Make rewind reset buffer pointers so it can be used for packet ; resizing. ; This appears to have never handled date xab's correctly. The ; fab's are all initialized to point to date xab's, but before ; opening any file, the xab pointers are changed to point to the ; protection xab. The prot XAB should be daisy chained to the end ; of the xab list. ; Brian Nelson 30-Nov-83 09:53:49 ; ; Copyright (C) 1983 Change Software, Inc. ; ; Edited by: ; RBD01 - Bob Denny 03-Mar-84 See KRTCMD for edit trails ; ; ; ******************************************************* ; * NOTES REGARDING DECnet (DAP) REMOTE FILE SUPPORT) * ; ******************************************************* ; ; The code here contains some magic for DECnet (DAP) remote file ; access. I have not been able to find documentation on the DAP ; support that is present in RMS-11 (V2). My current understanding ; of this, through experimentation, is as follows: ; ; 1. $PARSE fails with RMS status ER$UIN when given a file ; specification containing a node name, but seems to ; merge the input string and defaults into the expanded ; string buffer anyway. It also sets the file specification ; mask. I have assumed that the ER$UIN error is encountered ; in $PARSE after the merging of the default and input ; filespec information, and reflects the "fact" that RMS-11 ; (V2) DOES NOT SUPPORT WILDCARDING ON REMOTE FILE ACCESS. ; ; 2. Therefore, lookup() has been modified to return the ; expanded string if its second calling parameter (index) ; is zero (1st call) and there is either a node name or a ; quoted literal in the spec, no wildcards and the error ; is ER$UIN. ; ; 3. fparse() has been modified to accept if the error is ER$UIN, ; and if there are no wildcards and there is a node name present. ; The FB$FID bit is cleared, however, so that the original ; file spec string and the defaults will be used by $OPEN. ; ; 4. The "SY:" defaulting is not necessary, and in fact causes ; remote accesses to fail on VMS systems, where "SY:" has ; no conventional meaning. ; ; 5. The other routines which use $parse have been similarly ; modified to use the expanded string once only. ; ; 6. Finally, the NAMCVT routine in KRTM41 was changed to handle ; quoted sections in strings and node names. This was the ; hardest part of the DAP adaptation. ; ; I have to believe that $parse and friends act this way because remote ; wildcarding got "left out" at the last minute because of scheduling ; problems in the RMS group. The code I have added here should permit ; remote wildcarding when it is turned on by the RMS folks. ; ; Bob Denny 03-Mar-84 ; ; ; ; Please note that RSTS rms11 requires a real default device. I thus ; have to put my origional default for SY: back in for RSTS only. We ; will determine this at tkb time by defining a global called FU$DEF ; to be <> 0 in KRTE80.MAC and = 0 in KRTM41.MAC. ; ; ; Brian Nelson 16-Mar-84 17:34:19 ; ; BDN 17-Feb-87 08:57:48 Re-do the allocation of record buffers so ; can GBLDEF the size during TKB. This will ; allow the I/D space Kermit to handle much ; larger ascii records. ; define macros and things we want for KERMIT-11 .if ndf, krtinc .ift .if ndf, KRTINC .ift .include /IN:KRTMAC.MAC/ .endc .endc .iif ndf, krtinc, .error ; INCLUDE for IN:KRTMAC.MAC failed ; This is KRTRMS.MAC, the RMS11 version 2 i/o interface for ; Kermit on RSTS version 8, RSX11M+ v2.1 and RSX11M v4.1. It ; is, without a doubt, the worst part of Kermit due RMS11, ; but it's strong points are future uses and the RSX / RSTS ; transportability. An example of "future uses" is DECnet ; remote file access (DAP) support now present. ; ; ; close ( %val channel_number ) ; create( %loc filename, %val channel_number ,%val type ) ; getc ( %val channel_number ) ; getrec( %loc buffer , %val channel_number ,%val buffer_size ) ; { returns RSZ in R1} ; lookup( %loc in_filespec, %loc out_filename ) ; open ( %loc filename, %val channel_number ,%val type ) ; putc ( %val char , %val channel_number ) ; putrec( %loc buffer , %val record_size ,%val channel_number ) cr = 15 lf = 12 ff = 14 soh = 1 ; ; This isn't defined globally. (??) ; nb$nod = 400 ; Node in file or default string (FNB in NAM) .enabl gbl .sbttl messages .psect $pdata .even ; Make this <> 0 if you can't do CALFIP fu$dir::.word 0 ; style wildcarding on your non-standard ; RSTS system. Could cause side effects ; with remote decnet nodes. tlogda: .word 0,0 ; /46/ Returned data ln$mk1::.word 0 rme.01: .asciz "Failure to allocate record buffers" rme.02: .asciz "Failure to allocate command recall buffers" rme.03: .asciz "Breakpoint trap, " ; A message rme.04: .asciz " PC: " ; A header rme.05: .asciz " PSW: " ; ... rme.06: .byte CR,LF .ascii /Probable cause: Either RMSRES or an RMS satellite/ .asciz /resident library is not installed on this system./ rme.07: .asciz "Exiting due to control C interupt" ; /43/ .even .psect $code ,ro,i,lcl,rel,con .psect rmssup ,rw,d,lcl,rel,con .mcall fabof$ .mcall rabof$ .mcall xabof$ .mcall ifaof$ fabof$ RMS$L rabof$ RMS$L xabof$ RMS$L ifaof$ RMS$L .mcall fab$b ,fab$e ,rab$b ,rab$e .mcall xab$b ,xab$e .mcall nam$b ,nam$e .mcall $initif ,org$ .mcall pool$b ,pool$e ,p$bdb ,p$fab .mcall p$rabx ,p$idx ,p$buf .mcall $compar ,$fetch ,$store ,$rewin .mcall $close ,$creat ,$erase ,$open .mcall $connec ,$delet ,$discon,$find .mcall $get ,$put ,$updat ,$flush .mcall $read ,$write ,$off ,$set .mcall $testbits org$ SEQ, .psect rmssup ,rw,d,lcl,rel,con ; ORG$ macro needs .save/.restore .if ne ,0 ; Decide whether or not to use .ift ; dynamic space allocation by ; task extension or to use rmsbuf: pool$b ; static pools p$rab 6 ; plenty of record streams p$bdb 6 ; same goes for block buffers p$fab 4 ; up to 3 fabs (needed for search) p$buf 3072. ; for 2 files and directory i/o pool$e ; end of static pool .iff ; use task extension for space ; routine modifed from GSA example .mcall gsa$ ; from RMS v2.0 distribution. gsa$ gsa ; set our GSA address .globl gsa ; it may be global .endc ; to decide on pool allocation .psect rmssup ,rw,d,lcl,rel,con ; GSA$ macro needs .save/.restore .sbttl rms file access blocks facc = fb$get ! fb$put fab1: fab$b f$alq 0 ; initial allocation of 10 blocks f$fac facc ; allowed i/o operations f$fna nam1 ; name of the file f$fns 0 ; length of the filename f$fop fb$sup ; supercede old versions f$lch lun1 ; channel number to use f$org fb$seq ; seq f$rat fb$cr ; implied carriage control f$rfm fb$var ; variable length records f$xab datxb1 ; Date info fab$e fab1en: fab2: fab$b f$alq 0 ; initial allocation of 10 blocks f$fac facc ; allowed i/o operations f$fna nam2 ; name of the file f$fns 0 ; length of the filename f$fop fb$sup ; supercede old versions f$lch lun2 ; channel number to use f$org fb$seq ; seq f$rat fb$cr ; implied carriage control f$rfm fb$var ; variable length records f$xab datxb2 ; Date info fab$e fab2en: fab3: fab$b f$alq 0 ; initial allocation of 10 blocks f$fac facc ; allowed i/o operations f$fna nam3 ; name of the file f$fns 0 ; length of the filename f$fop fb$sup ; supercede old versions f$lch lun3 ; channel number to use f$org fb$seq ; seq f$rat fb$cr ; implied carriage control f$rfm fb$var ; variable length records f$xab datxb3 ; Date info fab$e fab3en: fab4: fab$b f$alq 0 ; initial allocation of 10 blocks f$fac facc ; allowed i/o operations f$fna nam4 ; name of the file f$fns 0 ; length of the filename f$fop fb$sup ; supercede old versions f$lch lun4 ; channel number to use f$org fb$seq ; seq f$rat fb$cr ; implied carriage control f$rfm fb$var ; variable length records f$xab datxb4 ; Date info fab$e .globl MAXSIZ .psect rmssup ,rw,d,lcl,rel,con sydisk::.ascii /SY:/ sylen == . - sydisk .even sydska == sydisk sydskl == sylen ; ;RBD01-- ; pointers to buffer and fabs ; ; While none of this is really needed since all this info is ; available in the FAB and RAB, I find it cleaner to do it ; this way and thus avoid having to look at the RMS control ; structures. fablst::.word 0 ,fab1 ,fab2 ,fab3 ,fab4 namlst::.word 0 ,nam1 ,nam2 ,nam3 ,nam4 namlen::.word 0 ,0 ,0 ,0 ,0 rablst::.word 0 ,rab1 ,rab2 ,rab3 ,rab4 buflst::.word ttbuf ,buf1 ,buf2 ,buf3 ,buf4 bufdef: .word ttbuf ,buf1 ,buf2 ,buf3 ,buf4 bufsiz: .word TTBSIZ ,MAXSIZ ,MAXSIZ ,MAXSIZ ,MAXSIZ bigbuf: .word bufx ,bufx ,bufx ,bufx ,bufx date.a::.word 0 ,0 ,0 ,0 ,0 ; /BBS/ date attribute filtyp::.word TERMINAL,TEXT ,TEXT ,TEXT ,TEXT bufp:: .word 0 ,0 ,0 ,0 ,0 bufs:: .word 0 ,0 ,0 ,0 ,0 mode:: .word 1 ,0 ,0 ,0 ,0 prot.a::.word 0 ,0 ,0 ,0 ,0 ; /BBS/ prot attribute sizof:: .word 0 ,0 ,0 ,0 ,0 ; size of file, blocks sizofh::.word 0 ,0 ,0 ,0 ,0 ; /E64/ high-word size time.a::.word 0 ,0 ,0 ,0 ,0 ; /BBS/ time attribute blknum::.word 0 ,0 ,0 ,0 ,0 itsopen:.word 0 ,0 ,0 ,0 ,0 FILSIZ == 40. BINLSIZ == 40*4 prewrk::.blkb 200. ; /E64/ prewind work buffer defdir::.blkb FILSIZ+2 ; default directory for send and rec dkname::.blkb FILSIZ+2 ; default directory for send and rec srcnam::.blkb FILSIZ+2 ; original send filespec filnam::.blkb FILSIZ+2 ; output from directory lookup routine asname::.blkb FILSIZ+2 ; for SEND file [as] file indnam::.blkb 40. ; /62/ current take or init file name ininam::.blkb 40. ; /62/ init file name for show file logfil::.blkb 40. $cmdbu::.blkb 120 $argbu::.blkb 120 bintyp::.word 10$ 10$: .rept BINLSIZE .byte 0 .endr status::.word 0 ; this is Kermit-11's error status reg totp.r::.word 10$ 10$: .rept 34 .word 0,0 .endr totp.s::.word 10$ 10$: .rept 34 .word 0,0 .endr ; this sets the default for creating text files df$rat::.word fb$cr df$rfm::.word fb$var en$siz::.word 0 ; for RT11 compatibilty namln1 = namlen+2 namln2 = namlen+4 namln3 = namlen+6 namln4 = namlen+10 nam1: .rept 100 .byte 0 .endr nam2: .rept 100 .byte 0 .endr nam3: .rept 100 .byte 0 .endr nam4: .rept 100 .byte 0 .endr .even packet::.blkb $ALLSIZ ; /E64/ From RT-11 version ;packet::.blkb MAXLNG+100 ; /51/ Moved. .even top: .LIMIT TTBSIZ == 40 ttbuf:: .blkb TTBSIZ+2 buf1: .iif df, MAXSIZ, .blkb MAXSIZ+2 ; /56/ Dynamic or static setup? buf2: .iif df, MAXSIZ, .blkb MAXSIZ+2 ; /56/ ... buf3: .iif df, MAXSIZ, .blkb MAXSIZ+2 ; /56/ .... buf4: .iif df, MAXSIZ, .blkb MAXSIZ+2 ; /56/ ..... bufx: .blkb 1002 ; one large buffer to share lun1 = 1 lun2 = 2 lun3 = 3 lun4 = 4 maxlun = lun4 .sbttl rms record access blocks rab1: rab$b ; define record access block r$fab fab1 ; associate a fab with this rab r$rac rb$seq ; access by keys r$rbf buf1 ; where to return the data r$ubf buf1 ; where to return the data rab$e ; end of record access block rab2: rab$b ; define record access block r$fab fab2 ; associate a fab with this rab r$rac rb$seq ; access by keys r$rbf buf2 ; where to return the data r$ubf buf2 ; where to return the data rab$e ; end of record access block rab3: rab$b ; define record access block r$fab fab3 ; associate a fab with this rab r$rac rb$seq ; access by keys r$rbf buf3 ; where to return the data r$ubf buf3 ; where to return the data rab$e ; end of record access block rab4: rab$b ; define record access block r$fab fab4 ; associate a fab with this rab r$rac rb$seq ; access by keys r$rbf buf4 ; where to return the data r$ubf buf4 ; where to return the data rab$e ; end of record access block proxab: xab$b XB$PRO ; file protection xab x$nxt 0 ; no more links x$pro 60. ; normal protection of <60> xab$e ; end of file protection xab datxb1: xab$b XB$DAT x$nxt 0 xab$e datxb2: xab$b XB$DAT x$nxt 0 xab$e datxb3: xab$b XB$DAT x$nxt 0 xab$e datxb4: xab$b XB$DAT x$nxt 0 xab$e .psect $code .sbttl Set up SST table to catch RMSRES missing .mcall SVTK$S,EXST$S,EXTK$S ; This code added /53/ .mcall GTSK$S ; Dynamic record buffer allocation and dynamic recall buffer ; allocation added /56/ .save ; Save current PSECT .psect RMSSUP ,D ; Switch to a data psect .even ; Insure this tbl: .word 0,0,norms ; Missing RMS gives a BPT trap .even .restore ; Pop old psect .enabl lsb Rmsini::mov #MAXSIZ ,r3 ; Allocate record buffers mov r3 ,O$MRS+fab1 ; Since we are allocating mov r3 ,O$MRS+fab2 ; the RMS record buffers at mov r3 ,O$MRS+fab3 ; run time we will can't mov r3 ,O$MRS+fab4 ; fill these fields in with mov r3 ,O$USZ+rab1 ; ...MAC mov r3 ,O$USZ+rab2 ; .... and so on mov r3 ,O$USZ+rab3 ; .... mov r3 ,O$USZ+rab4 ; .... ; .If df ,MAXSIZ ; Dynamic or static today? .Ift ; Static ; mov #buf1 ,r2 ; So get the preallocated buffers mov top+2 ,r4 ; .Iff ; Dynamic allocation ; ash #-<6-2> ,r3 ; We need 4 buffers, in 64 byte add #2 ,r3 ; chuncks. Add a safety margin EXTK$S r3 ; Ask for the memory bcs 110$ ; Oops, we will have to die. mov top+2 ,r2 ; The higest virtual address+2 add #2 ,r2 ; filled in by TKB via .LIMIT bic #1 ,r2 ; Insure even ; .Endc ; .If DF, Maxsiz ; mov #4 ,r0 ; Number of fields to update clr r3 ; Offset into BUFDEF and BUFLST 10$: mov r2 ,bufdef+2(r3) ; Insert a record buffer address mov r2 ,buflst+2(r3) ; Ditto for here also add #2 ,r3 ; Next please add #MAXSIZ+2,r2 ; Point to the next buffer sob r0 ,10$ ; And go do another .If ndf ,MAXSIZ ; Setup pointer for command line mov r2 ,r4 ; recall buffers if dynamic RMS .Endc ; buffer allocation was used ; Now for command line recall mov #LN$CNT ,r1 ; buffers. The count is defined ; in KRTMAC.MAC mov #*LN$CNT,r3 ; Total byte count for recall buffers ash #-6 ,r3 ; In 64 byte chunks add #/100,r3 ; Fix for truncation EXTK$S r3 ; Ask for it bcs 130$ ; No room, die (should never happen) mov #lastli ,r2 ; The pointer array 40$: mov r4 ,(r2)+ ; Insert the buffer address clrb @r4 ; Insure the buffer is zapped add #LN$MAX+2,r4 ; Get to the next one sob r1 ,40$ ; And loop ; ; Finally, our original purpose. SVTK$S #tbl,#3 ; Only want TBIT traps return ; Exit 110$: wrtall #rme.01 ; /E64/ br 200$ 130$: wrtall #rme.02 ; /E64/ 200$: EXST$S #EX$SEV ; Die... .dsabl lsb Norms: wrtall #rme.03 ; /E64/ mov (sp) ,r1 ; Dump PC and PS wrtall #rme.04 ; /E64/ OCTOUT R1 ; ... mov 2(sp) ,r1 ; PS wrtall #rme.05 ; /E64/ OCTOUT r1 ; ... cmp (sp) ,#140000 ; Perhaps RMSRES missing? blo 100$ ; No wrtall #rme.06 ; Dump the cause 100$: EXST$S #EX$SEV ; Die .globl LN$CNT .sbttl create sequential file .psect $code .even ; F C R E A T E and F O P E N ; ; fcreate( %loc filename; %val channel_number, %val type ,%val mb_count) ; fopen ( %loc filename; %val channel_number, %val type ,%val mb_count) ; ; input: @r5 filename address ; 2(r5) channel number ; 4(r5) val 'binary' or 'text' or 0 ; 6(r5) RMS multiblock count for the stream ; ; output: r0 rms error code ; ; Create a variable length sequential implied carriage control ; disk file. If 'type' is 'binary' then use read/write access ; to write a fixed 512 byte image file. If channel number is ; zero (0), then initialize buffer single character terminal ; output. It is always assumed that channel '0' implies writes ; to the attached console terminal. .enabl lsb open:: calls fopen ,<@r5,2(r5),4(r5),#0> return create::calls fcreate ,<@r5,2(r5),4(r5),#0> return append::calls fapnd ,<@r5,2(r5),4(r5),#0> return fopen:: save ; save registers call drpprv ; insure no privs are up now +MJG clr -(sp) ; flag for open not create br 5$ ; and try to do it fapnd:: save ; save registers +SSH call drpprv ; insure no privs +SSH mov #1,-(sp) ; flag for open / append +SSH br 5$ ; and try to do it +SSH fcreat::save ; save registers call drpprv ; insure no privs are up now +MJG tcreat: mov #-1 ,-(sp) ; flag for create 5$: $initif ; initialize rms i/o system if needed mov 2(r5) ,r0 ; get channel number please bne 10$ ; not channel zero, do it normally mov sp ,itsopen+0 ; flag it as having been initted mov sp ,mode+0 ; psuedo writing to the terminal clr bufp+0 ; initialize the terminal's buffer br 120$ ; pointer and exit 10$: asl r0 ; times 2 mov r0 ,r2 ; save it please mov namlst(r2),r1 ; get address of name block calls fparse ,<@r5,r1> ; parse and fill in defaults tst r0 ; did the parse succeed ? bne 120$ ; no, exit with RMS error in r0 strlen r1 ; get the expanded filename length mov r0 ,namlen(r2) ; and save the length mov r2 ,r0 ; get r0 back again please mov fablst(r0),r1 ; get the file access block mov @sp ,r2 ; pass create/open/append flag /SSH call settyp ; setup the FAB now mov r0 ,r2 ; save the channel number*2 tst @sp ; create or open or append /SSH bmi 30$ ; if negative then create /SSH $open r1 ; try to open existing file /SSH tst @sp ; opening for append ? +SSH beq 28$ ; no, go setup for read +SSH mov sp ,mode(r2) ; indicate open for writing +SSH clr bufp(r2) ; clear single char i/o pointer +SSH br 40$ ; continue with status check +SSH 28$: ; +SSH mov #-1 ,bufp(r2) ; init for buffer needing a read clr mode(r2) ; no writing please br 40$ ; check RMS status out now 30$: $creat r1 ; try hard to create the file mov sp ,mode(r2) ; open for writing clr bufp(r2) ; clear single character i/o pointer 40$: $fetch r0,sts,r1 ; get status back out please tst r0 ; if status > 0 then status = 0 bmi 130$ ; error if less than zero /SSH $fetch sizof(r2),alq0,r1 ; /E64/ get size (low word) $fetch sizofh(r2),alq1,r1 ; /E64/ get size (high word) mov sp ,itsopen(r2) ; /E64/ simple ; /E64/ ; /E64/ This is a crock to see if we can dredge up the file's creation ; /E64/ date and time without doing a directory lookup. RMS must have ; /E64/ done one, maybe the info is still there? ; /E64/ firqb=402 fqflag=24 fqpflg=26 mov firqb+fqflag,date.a(r2) ; /E64/ save creation date mov firqb+fqpflg,time.a(r2) ; /E64/ save creation time mov 2(r5) ,r0 ; connect access up now mov 6(r5) ,r1 ; and the multiblock count also mov (sp) ,r2 ; and the create/open/append opt +SSH call rmscon ; connect record stream up tst r0 ; if error > 0 then error = 0 bmi 120$ ; yep clr r0 ; error = 0 120$: tst (sp)+ ; pop open/create flag 125$: unsave ; pop registers we saved return ; and exit 130$: tst (sp)+ ; if error on open for append +SSH ble 125$ ; no, return with error +SSH br tcreat ; yes, try creating the file +SSH .globl drpprv ; +MJG .dsabl lsb .sbttl setup things for open/create in the FAB ; S E T T Y P ; ; input: r0 channel number times 2 ; r2 <> 0 implies create ; r5 --> open/create parameter list ; fbrw = fb$rea ! fb$wri settyp::save ; /E64/ mov fablst(r0),r1 clr blknum(r0) ; in case of read/write mode mov #MAXSIZ ,bufsiz(r0) ; default for the buffer size mov #text ,filtyp(r0) ; assume ascii text files for now mov bufdef(r0),buflst(r0) ; set a default record buffer also clr bufs(r0) ; clear single character i/o recsiz $fetch r3,XAB,r1 ; /E64/ point to name block $store #proxab,NXT,r3 ; /E64/ Get the protection out. $store namlen(r0),FNS,r1 $store #fb$seq,ORG,r1 ; insure sequential by default $store df$rat ,RAT,r1 ; implied carriage control $store df$rfm ,RFM,r1 ; and also variable length records $store #fb$get,FAC,r1 ; insure readonly please tst fu$def ; do we require a default device beq 1$ ; no $store #sydisk,DNA,r1 ; yes, stuff the correct def dev in $store #sylen ,DNS,r1 ; and the length of it also please 1$: tst r2 ; if creating or appending the file /SSH beq 10$ ; no /SSH $store #,FAC,r1 ; yes, get put access /SSH mov at$pro ,proxab+O$PRO ; /E64/ Protection explicity set? bne 10$ ; /59/ Yes $store #0,NXT,r3 ; /E64/ No, remove the protection XAB 10$: cmp 4(r5) ,#binary ; is this a binary file ? bne 100$ ; no, just exit mov #1000 ,bufsiz(r0) ; yes, fix it up for that mov bigbuf(r0),buflst(r0) ; setup a large i/o buffer please mov #binary ,filtyp(r0) ; please $store #0 ,RAT,r1 ; no cr/lf implied please $store #fb$fix ,RFM,r1 ; fixed length also $store #fb$rea ,FAC,r1 ; assume read only please tst r2 ; readonly ? beq 30$ ; yes $store #fbrw ,FAC,r1 ; read/write mode needed ? 30$: save ; /E64/ zero out the big buffer mov buflst(r0),r2 ; get the buffer address mov #1000 ,r3 ; 1000 (8) bytes please 40$: clrb (r2)+ ; simple sob r3 ,40$ ; next please unsave ; /E64/ pop registers we just used 100$: $store bufsiz(r0),MRS,r1 ; stuff max recordsize in please unsave ; /E64/ return .globl fu$def .globl AT$PRO ; /E64/ Protection mask .sbttl Preset a file I/O channel to desired block and offset ; /BBS/ ; P R E W I N D ; ; input: (r5) = lun ; 2(r5) = block number (count from zero) ; 4(r5) = byte offset in above block prewind::save mov @r5 ,r2 ; channel number please asl r2 ; word indexing mov 2(r5) ,blknum(r2) ; req'd block of the disk file mov rablst(r2),r1 ; get the record access buffer $store #RB$RFA,RAC,r1 ; RFA access $store #prewrk,UBF,r1 ; work buffer $store bufsiz(r2),USZ,r1 ; buffer size mov 2(r5),o$rfa+0(r1) ; use RFA mode please inc o$rfa+0(r1) ; count from 1 clr o$rfa+2(r1) ; second word is to have zero mov 4(r5),o$rfa+4(r1) ; offset $get r1 ; get next virtual block please $store #RB$SEQ,RAC,r1 ; SEQ access $fetch r0,STS,r1 ; get the return STATUS field tst r0 ; did it work ? blt 100$ ; no inc blknum(r2) ; next time read the next block mov 4(r5) ,r3 ; get a copy of required offset mov r3 ,bufp(r2) ; now preset offset in block $fetch r0,RSZ,r1 ; get the record size now sub r3 ,r0 ; don't count unused bytes.. mov r0 ,bufs(r2) ; save the record size clc br 110$ 100$: sec 110$: unsave return .sbttl close a file close:: save ; save registers we may have mov @r5 ,r0 ; get the lun asl r0 ; times 2 tst itsopen(r0) ; check for lun being open beq 90$ ; no, skip all this then clr itsopen(r0) ; not anymore please call flush ; dump out any remaining buffer mov @r5 ,r0 ; then disconnect the access stream beq 100$ ; terminal asl r0 ; channel number times 2 tst mode(r0) ; writing to it today? beq 10$ ; no calls atrfin ,<@r5> ; yes, perhaps do attribute things 10$: mov @r5 ,r0 ; then disconnect the access stream call rmsdis ; by doing a $disconnect mov @r5 ,r1 ; get the FAB for the file open on asl r1 ; the passed channel mov fablst(r1),r1 ; $close r1 ; try hard to close the file $fetch r0,sts,r1 ; get status back out please tst r0 ; if status > 0 then status = 0 blt 100$ ; error if less than zero 90$: clr r0 ; make > 0 status eq 0 100$: unsave return rewind::mov @r5 ,r0 beq 100$ asl r0 mov #-1 ,bufp(r0) ; flag a buffer reload is needed clr bufs(r0) ; nothing is in the buffer (size=0) clr blknum(r0) ; first block of the disk file mov rablst(r0),r0 $rewind r0 100$: clr r0 return .sbttl try to determine if a file needs binary xfer mode ; B I N F I L ; ; input: @r5 address of the filename ; 2(r5) lun ; output: r0 < 0 then RMS error ; r0 > 0 then the file is most likely binary binfil::save ; save registers we may use clr r4 ; nothing is open as of yet calls chkext ,<@r5> ; check file based on filetype tst r0 ; assume a binary file ? bne 100$ ; yep mov 2(r5) ,r2 ; get the lun asl r2 ; times 2 mov fablst(r2),r2 ; get the fab address now $fetch r3,XAB,r2 ; save the xab link address call getuic ; for RSTS, skip the protection XAB swab r0 ; if the user is not privledged cmpb r0 ,#1 ; since RMS uses the UU.LOK directive bne 5$ ; which may be patched to fail. $store #proxab,NXT,r3 ; /E64/ and stuff our own into it 5$: calls open ,<@r5,2(r5),#binary> tst r0 ; did the open work bmi 90$ ; no mov sp ,r4 ; flag that it's open mov #proxab ,r1 ; get the xab for the protection code $testbit #100,PRO,r1 ; if set, then it's executable bne 40$ ; assume it's binary $testbit #,ORG,r2; indexed or relative file ? bne 40$ ; yes, it must be sent as a binary file $compare #fb$stm,RFM,r2 ; stream ascii file ? beq 30$ ; yes, assume not binary then $testbit #FB$FTN,RAT,r2 ; /47/ Please not for Fortran files bne 30$ ; /47/ Ok $testbit #fb$cr,RAT,r2 ; implied carriage control ? bne 30$ ; yes, assume not 8 bit then br 40$ ; anything else is binary please 30$: clr -(sp) ; flag as most likely being ascii br 50$ ; bye 40$: mov #1 ,-(sp) ; flag as being binary and exit 50$: tst r4 ; ever opened up ? beq 60$ ; no calls close ,<2(r5)> ; close up 60$: mov (sp)+ ,r0 90$: $store #0,NXT,r3 ; /E64/ restore old xab links, if any 100$: unsave ; bye return .sbttl getatr return attributes for a file already open .mcall ifaof$ ; access the ifab for the fab ifaof$ rms$l ; get the ifab symbols defined ; /E64/ This appears to be unused ; ;getsiz::mov @r5 ,r1 ; return error in r0, size in r1 ; asl r1 ; lun times 2 ; mov fablst(r1),r1 ; fab for this file ; mov (r1),r1 ; get the size please ; clr r0 ; no errors ; return ; exit ; /E64/ This is bogus. There is only one protection XAB, which ; is used for all channels. In addition, the FAB XAB pointer never ; points to it here. It either points to the DAT XAB or nothing. ; Since changing the code to daisy-chain the PROT XAB to the DAT ; XAB, we should either follow the link (which won't work because ; the PROT XAB is only linked in for the duration of the OPEN call), ; or use the staticly allocated proxab. ;getpro::mov @r5 ,r0 ; size in r0 ; asl r0 ; lun times 2 ; mov fablst(r0),r0 ; fab for this file ; mov O$XAB(r0),r0 ; get the protection please getpro::mov #proxab ,r0 ; /E64/ point to protection xab mov O$PRO(r0),r0 ; ... return ; exit ; Getcdt Return time/date of creation, system (ie, RMS vs RT) dep. ; ; Passed: (r5) Channel number file is open on ; Return: R0 Zero if failure (internal error) else address of ; 64 byte Smithsonian date format Getcdt::mov @r5 ,r0 ; Channel beq 100$ ; Oops asl r0 ; Word offsets mov FABLST(r0),r0 ; Get the fab beq 100$ ; Impossible mov O$XAB(r0),r0 ; XAB address beq 100$ ; Nothing add #O$CDT ,r0 ; Point to 4word creation dat/tim 100$: return ; Exit Putcdt::mov @r5 ,r0 ; Channel beq 100$ ; Oops asl r0 ; Word offsets mov FABLST(r0),r0 ; Get the fab beq 100$ ; Impossible mov O$XAB(r0),r0 ; XAB address beq 100$ ; Nothing add #O$CDT ,r0 ; Point to 4word creation dat/tim mov 2(r5) ,r1 ; Data mov (r1)+ ,(r0)+ ; Copy it mov (r1)+ ,(r0)+ ; .Copy it mov (r1)+ ,(r0)+ ; ..Copy it mov (r1)+ ,(r0)+ ; ...Copy it 100$: return ; Exit getatr::save ; save these please mov @r5 ,r1 ; the channel number please asl r1 ; times two please mov fablst(r1),r1 ; simple mov o$ifi(r1),r1 ; and now we are at the ifab mov 2(r5) ,r2 ; where to copy the attributes to movb f$ratt(r1),(r2)+ ; stuff the input record attributes movb f$forg(r1),(r2)+ ; also stuff the input file org in mov f$rsiz(r1),(r2)+ ; and the input record size please mov f$hvbn(r1),(r2)+ ; and the input eof markers mov f$lvbn(r1),(r2)+ ; like hi and low virtual block mov f$heof(r1),(r2)+ ; and the high and low eof block mov f$leof(r1),(r2)+ ; numbers also mov f$ffby(r1),(r2)+ ; and, at last, the first free byte movb f$hdsz(r1),(r2)+ ; VFC header size next movb f$bksz(r1),(r2)+ ; and largest bucket size mov f$mrs(r1) ,(r2)+ ; the maximum record size mov f$deq(r1) ,(r2)+ ; and the default extenstion size mov f$rtde(r1),(r2)+ ; and the run time extentsion size unsave ; all done return putatr::save ; save these please mov @r5 ,r1 ; the channel number please asl r1 ; times two please mov fablst(r1),r1 ; simple mov o$ifi(r1),r1 ; and now we are at the ifab mov 2(r5) ,r2 ; where to get the attributes from movb (r2)+ ,f$ratt(r1) ; stuff the input record attributes movb (r2)+ ,f$forg(r1) ; also stuff the input file org in mov (r2)+ ,f$rsiz(r1) ; and the input record size please mov (r2)+ ,f$hvbn(r1) ; and the input eof markers mov (r2)+ ,f$lvbn(r1) ; like hi and low virtual block mov (r2)+ ,f$heof(r1) ; and the high and low eof block mov (r2)+ ,f$leof(r1) ; numbers also mov (r2)+ ,f$ffby(r1) ; and, at last, the first free byte movb (r2)+ ,f$hdsz(r1) ; VFC header size next movb (r2)+ ,f$bksz(r1) ; and largest bucket size mov (r2)+ ,f$mrs(r1) ; the maximum record size mov (r2)+ ,f$deq(r1) ; and the default extenstion size mov (r2)+ ,f$rtde(r1) ; and the run time extentsion size unsave ; all done return .sbttl connect record access block to file access block ; C O N N E C T ; ; connect( %val channel_number ) ; ; input: r0 channel number ; r1 multiblock count ; r2 create/open/append option flag +SSH ; output: r0 rms sts ; ; Connect a record access block to a file access block. ; Called only from OPEN and CREATE rmscon: mov r1 ,-(sp) ; the block count size mov r0 ,r1 ; get address of record access block asl r1 ; channel number times 2 mov rablst(r1),r1 ; address of a rab to use $store (sp)+,MBC,r1 ; the block buffer count $store #0,ROP,r1 ; assume no processing options +SSH tst r2 ; if appending to existing file +SSH ble 7$ ; no, leave options alone +SSH $store #rb$eof,ROP,r1 ; yes, set position to EOF option +SSH 7$: ; +SSH $conne r1 ; try hard to connect access up $fetch r0,sts,r1 ; get status back out please tst r0 ; if status > 0 then status = 0 blt 10$ ; error if less than zero clr r0 ; make > 0 status eq 0 10$: return .sbttl disconnect record access block from file access block ; R M S D I S ; ; input: r0 channel number ; r0 error sts ; rmsdis: mov r0 ,r1 asl r1 mov rablst(r1),r1 $discon r1 ; disconnect access stream from file $fetch r0,sts,r1 ; get status back out please tst r0 ; if status > 0 then status = 0 blt 10$ ; error if less than zero clr r0 ; make > 0 status eq 0 10$: return .sbttl read a record from a sequential file ; G E T R E C ; ; getrec( %loc buffer, %val channel_number, %val buf_siz ) ; ; input: @r5 address of user buffer, at least 80 bytes ; 2(r5) channel number ; 4(r5) buffer size ; ; output: r0 rms sts ; r1 record size ; ; Read the next record from a disk file, up to 4(r5) bytes ; in length. GETREC assumes text (stream ascii) file only. getrec::mov 2(r5) ,r0 ; get the channel number asl r0 ; times 2 to index into table mov rablst(r0),r1 ; get the record access buffer $store #0 ,RSZ,r1 $store @r5 ,UBF,r1 ; stuff a record buffer in $store 4(r5),USZ,r1 ; and a maximum record size cmp filtyp(r0),#binary ; a binary file today ? bne 10$ ; no, use normal get$ clr o$bkt+0(r1) ; use sequential mode please clr o$bkt+2(r1) ; both words are to have zero $read r1 ; get next virtual block please br 20$ ; get error code out now 10$: $get r1 ; read a record now 20$: $fetch r0,STS,r1 ; get the return STATUS field tst r0 ; did it work ? blt 100$ ; no clr r0 ; say no errors $fetch r1,RSZ,r1 ; get the record size now 100$: return .globl o$bkt .sbttl put a record to an rms sequential file ; P U T R E C ; ; putrec( %loc buffer, %val record_size, %val channel_number ) ; ; input: @r5 address of user buffer ; 2(r5) record size ; 4(r5) channel number ; ; output: r0 rms sts ; ; Write the next record to a disk file. putrec::mov r1 ,-(sp) mov 4(r5) ,r0 ; get the channel number bne 5$ ; if zero then assume TI: print @r5 ,2(r5) ; dump the buffer to ti: then br 100$ ; and exit 5$: asl r0 ; times 2 to index into table mov rablst(r0),r1 ; get the record access buffer $store @r5 ,RBF,r1 ; stuff a record buffer in $store 2(r5),RSZ,r1 ; and a current record size cmp filtyp(r0),#binary ; image mode today ? bne 10$ ; no $store #1000,RSZ,r1 ; yes, insure block write clr o$bkt+0(r1) ; yes, clear the VBN fields clr o$bkt+2(r1) ; yes, clear the VBN fields $write r1 ; simple br 20$ ; get the status and exit 10$: $put r1 ; write a record now /SSH 20$: $fetch r0,STS,r1 ; get the return STATUS field tst r0 ; did it work ? blt 99$ ; no clr r0 ; say no errors br 100$ 99$: mov r0,tmperr ; store error code for debugging 100$: mov (sp)+ ,r1 return .sbttl Get next file to send ; G E T N X T ; ; input: srcnam = possibly wildcarded file name ; index = 0 if this is the first time through ; output: filnam = next file to do ; r0 = if <>, error code getnxt::save calls lookup ,<#srcnam,#filnam> ; /62/ tst r0 ; did it work? beq 30$ ; yes cmp r0 ,#er$nmf ; no more files matching name? beq 10$ ; yes, we are all done then cmp r0 ,#er$fnf ; how about file not found? bne 20$ ; no, print the error message out 10$: tst index ; ya, but did any files match yet? bne 30$ ; yes, that's ok then mov #er$fnf ,r0 ; no, convert er$nmf to er$fnf 20$: mov r0 ,-(sp) ; save lookup error calls syserr , ; get the error text calls error ,<#3,#errtxt,#aspace,#filnam> ; /62/ include file name mov (sp)+ ,r0 ; restore saved error code from lookup 30$: unsave return .sbttl Get one character from a file ; G E T C ; ; getc(%val channel_number) ; ; input: (r5) = channel number ; output: r1 = character just read ; r0 = RMS error status getc:: mov @r5 ,r0 ; channel to use .br getcr0 ; /63/ dispatch to desired routine .sbttl Decide where to get the next character ; G E T C R 0 ; T G E T C R ; ; Passed: r0 = lun ; Return: r0 = if <>, error code (generally er$eof) ; r1 = character just read ; ; GETCR0 is the lowest level entry point called in Kermit to ; obtain the next character for a send function (even GETC ; calls it), where that may be a normal file transfer, or ; a server extended response. The main idea in altering it is ; so that a server dispatch routine can change the ; default (get from a file) to, say, get from an .asciz ; string in memory or switch to some other kind of ; get_next_character routine. This requires that the service ; routine insert its get_next_char routine address into the ; global GETCROUTINE and also reset it when the action is ; complete (by use of the textsrc macro sans an argument). getcr0::tst getcroutine ; /38/ is there a routine address set? beq fgetcr0 ; /63/ no, default to file reading jmp @getcroutine ; /63/ call currently defined routine tgetcr::tst tgetaddr ; /38/ have we ever been initted? beq 10$ ; /38/ no, return er$eof clr r1 ; /63/ avoid sign extension bisb @tgetaddr,r1 ; /63/ yes, get next character please beq 10$ ; /38/ nothing is left to do inc tgetaddr ; /38/ text_address++ clr r0 ; /38/ return(no_error) br 20$ 10$: mov #er$eof ,r0 ; /38/ return(end_of_file) clr getcroutine ; /62/ reset to file reading please 20$: return fgetcr0:save ; save temps mov r0 ,r2 ; channel number please asl r2 ; times 2 cmp bufp(r2),#-1 ; need to initialize the buffer? bne 10$ ; no calls getrec ,; yes, load it please tst r0 ; did the read work ? bne 100$ ; no, return rms error code clr bufp(r2) ; it worked. clear current pointer mov r1 ,bufs(r2) ; and save the record size br 30$ ; and goto common code 10$: cmp bufp(r2),#-2 ; flag to return ? bne 20$ ; no movb #cr ,r1 ; yes, return it in r1 mov #-3 ,bufp(r2) ; and setup for a nexttime clr r0 ; no error br 100$ ; bye 20$: cmp bufp(r2),#-3 ; flag to return a ? bne 30$ ; no movb #lf ,r1 ; yes, return in r1 mov #-1 ,bufp(r2) ; flag buffer reload next time clr r0 ; no error br 100$ 30$: tst bufs(r2) ; anything left to get in record? bne 40$ ; yes mov #-2 ,bufp(r2) ; no, flag for a next cmp filtyp(r2),#binary ; a binary file today ? bne 35$ ; yes, need data as is please mov #-1 ,bufp(r2) ; yes, flag for a read next 35$: mov r2 ,r0 ; channel number please asr r0 ; NOT times two call getcr0 ; call ourselves to do it br 100$ ; and exit 40$: mov buflst(r2),r3 ; get the address of the buffer add bufp(r2),r3 ; and point to the next character clr r1 ; to be returned in r1 bisb @r3 ,r1 ; simple inc bufp(r2) ; buffer.pointer := succ(buffer.pointer) dec bufs(r2) ; amountleft := pred( amountleft ) clr r0 ; no errors please 100$: unsave return .sbttl putc put a single character to an rms file ; P U T C ; ; input: @r5 the character to put ; 2(r5) the channel number to use ; ; Buffer single character i/o to internal disk buffer. ; Buffer is dumped if internal buffer is full or, for ; FB$VAR records (default for TEXT), a carraige return ; is found. For FB$VAR with FB$CR format, all carraige ; returns and line feeds are flushed as this record ; format will have them put back later. ; The local buffers are allocated in CREATE and OPEN. putc:: save ; simply save r1 and call putcr0 mov 2(r5) ,r1 ; to do it. putcr0 will be somewhat clr r0 ; faster to call directly due to the bisb @r5 ,r0 ; overhead involved in setting up an call putcr0 ; argument list. unsave ; pop saved r1 and exit return ; bye putcr0::save ; save registers we use mov r1 ,r2 ; channel number asl r2 ; times 2 of course cmp filtyp(r2),#binary ; is this a binary file today ? beq 5$ ; yes, don't dump buffer on cmpb r0 ,recdlm ; /56/ end of line time today ? beq 10$ ; yes, dump the record out 5$: cmp bufp(r2),bufsiz(r2) ; is the buffer full ? blo 20$ ; no, store some more characters in it 10$: movb r0 ,r3 ; yes, save the input character r0 calls putrec , ; yes, dump the buffer please clr bufp(r2) ; pointer := 0 tst r0 ; did it work ? bne 100$ ; no, die mov buflst(r2),r4 ; it worked. zero the buffer now mov bufsiz(r2),r0 ; get the buffer address and size 15$: clrb (r4)+ ; for i := 1 to bufsiz sob r0 ,15$ ; do buffer[i] := chr(0) movb r3 ,r0 ; ok, restore the old character 20$: cmp filtyp(r2),#binary ; once again, is this a binary file ? beq 30$ ; yes, ignore checks for and ^Z. cmp filtyp(r2),#terminal ; terminal file today ? beq 30$ ; yes, we want cr's and lf's cmpb r0 ,#lf ; we simply like to ignore line feeds beq 90$ ; bye cmpb r0 ,#'Z&37 ; control Z ? beq 90$ ; yes, ignore the control Z's please cmpb r0 ,#cr ; carraige return today ? beq 90$ ; yes, ignore it 30$: mov bufp(r2),r1 ; get the current buffer pointer add buflst(r2),r1 ; and point to a new home for the movb r0 ,@r1 ; the input character in r0 inc bufp(r2) ; pointer := succ( pointer ) 90$: clr r0 ; no errors 100$: unsave return .globl recdlm ; /56/ .sbttl flush flush: mov @r5 ,r0 ; get the internal channel number asl r0 ; times 2 for indexing tst bufp(r0) ; anything in the buffer beq 100$ ; no tst mode(r0) ; writing today ? beq 100$ ; no calls putrec , ; yes, dump it return 100$: clr r0 return .sbttl lookup do a filename lookup, wildcarding supported .enabl gbl ; L O O K U P ; ; input: (r5) address of input string ; 2(r5) address of output string ; ; output: r0 RMS error code ; ; ; clr index ;10$: calls lookup ,<#inbuf,#outbuf> ; tst r0 ; bne 100$ ; do something ; br 10$ .mcall $parse ,$search,$store ,$fetch ,$compare .mcall fab$b ,fab$e ,nam$b ,nam$e .mcall $off $testbits ;RBD01 .save .psect rmssup ,d fab: fab$b ; argument fab f$nam nam ; link to nam ;RBD01-- f$lch 1 ; a dummy channel for the i/o op fab$e nam: nam$b ; nam definition n$esa expstr ; exp str address n$ess 64. ; exp str length n$rsa resstr ; res str address n$rss 64. ; res str length nam$e expstr: .blkb 64. ; context must be preserved here resstr: .blkb 64. ; a temp place for the result .restore .sbttl the real work of lookup .psect $code lookup::save ; Save these please mov #fab ,r1 ; map the target fab ;RBD01-- tst fu$def ; do we really need a default device? beq 5$ ; no $store #sydisk,DNA,r1 ; yes, please stuff the def device name $store #sylen ,DNS,r1 ; and the length of it also please 5$: strlen #defdir ; anything in the Kermit default dir? tst r0 ; if <> then use it beq 10$ ; nothing there to use. Let system do it $store #defdir ,DNA,r1 ; something was there, stuff it in $store r0 ,DNS,r1 ; and the length of the default 10$: mov r1 ,r0 ; save it for later mov #nam ,r3 ; map the target nam tst index ; first time thru needs a parse bne 40$ ; not the first time clrb expstr ; clear the expanded name and clrb resstr ; the resultant string mov (r5) ,r4 ; point to the filename passed mov r4 ,r1 ; and save the pointer 20$: tstb (r1)+ ; and get the length of the name bne 20$ ; for an .asciz string sub r4 ,r1 ; compute the length of the string dec r1 ; which is off by one $store #lun.sr,lch,r0 ; channel number please $store r1,fns,r0 ; stuff the filename length $store r4,fna,r0 ; and the filename address $parse r0 ; parse the strings $fetch r4,sts,r0 ; get error codes cmp #ER$UIN,r4 ; Maybe a remote file spec? ;RBD01+ bne 30$ ; (no) $testbits #,fnb,r3 ; Anything wild? bne 90$ ; (wild remote files no good) $testbits #nb$nod,fnb,r3 ; Remote file? beq 90$ ; (ER$UIN with no node???) $off #nb$wch,fnb,r3 ; Make succeeding $search's act nice $fetch r0,esl,r3 ; Pass back expanded string $fetch r2,esa,r3 ; and skip the $search. br 70$ ;RBD01- 30$: tst r4 ; < 0 ? bmi 90$ ; yes, error ; This added edit 2.12 by BDN for those RSTS systems that totally ; disallow directory lookups by modify the executive for non-priv ; users. 40$: tst fu$dir ; in case george w. @ purdue beq 50$ ; needs this due to a hacked up exec $testbits #,fnb,r3 ; Anything wild? bne 50$ ; yes, let the $search go on tst index ; if no wildcarding and we have beq 45$ ; already been here then return mov #ER$NMF ,r4 ; no more files and exit br 90$ ; bye 45$: $fetch r0,esl,r3 ; no, skip the $search and get the $fetch r2,esa,r3 ; expanded string from $parse br 70$ ; and copy it over now ; End of option tp skip lookups for non-wildcarded filenames. 50$: $search r0 ; get a matching file $fetch r4,sts,r0 ; get error codes ; ;RBD01+ ; The following shouldn't have been necessary, as I ; banged off the NB$WCH bit above. But ... ; cmp r4,#ER$UIN ; Remote file hacking? bne 60$ ; (no) mov #ER$FNF,r4 ; Yes, no "more" files br 90$ ; and exit 60$: tst r4 ; < 0 ? ;RBD01- bmi 90$ ; yes, error $fetch r0,rsl,r3 ; get the string length $fetch r2,rsa,r3 ; get the string address 70$: mov 2(r5) ,r1 ; where to return the string 80$: movb (r2)+ ,(r1)+ ; copy it over sob r0 ,80$ ; for however the long it is clrb @r1 ; insure .asciz please clr r0 ; no errors inc index ; say we have at least one file br 100$ ; and exit 90$: mov r4 ,r0 ; error, return it please br 100$ ; exit 100$: unsave return .save .psect rendat ,rw,d,lcl,con,lcl .mcall $compare,$fetch ,$parse ,$search,$set ,$store .mcall fab$b ,nam$b ,$rename ; 24-Jan-86 14:01:48 Rename, Delete and GMCR code moved to overlay RNFAB1::FAB$B ; Old file name F$NAM RNNAM1 ; Link to RNNAM1 ;RBD01-- F$LCH 1 ; Channel 1 (a dummy, filled in later) FAB$E RNNAM1::NAM$B ; NAM definition NAM$E RNFAB2::FAB$B ; New file name F$NAM RNNAM2 ; Link to RNNAM2 ;RBD01-- F$LCH 1 ; a dummy channel FAB$E RNNAM2::NAM$B ; NAM definition NAM$E .restore .sbttl fparse parse filename and fill in with defaults .mcall $compar ,$fetch ,$off ,$parse ,$store .mcall tlog$s parfab = rnfab1 parnam = rnnam1 ; F P A R S E ; ; input: @r5 input filename, .asciz ; defdir the default directory name string to use ; ; output: 2(r5) expanded filename, .asciz, maximum length 63 bytes ; r0 error codes tlog:: clr r0 ; /46/ No errors return ; /46/ Exit Fparse::save ; /46/ save registers we may overwrite mov @r5 ,r4 ; /46/ Assume input from source mov #parfab ,r1 ; point to the fab we use ;RBD01-- $store #0,DNS,r1 ; /42/ PLEASE clear this OUT! tst fu$def ; do we need a default device string? beq 3$ ; no $store #sydisk,DNA,r1 ; yes, please put it where we need it $store #sylen ,DNS,r1 ; also, the length also 3$: strlen #defdir ; get the default directory spec tst r0 ; was anything there ? beq 4$ ; no $store #defdir,DNA,r1 ; yes, stuff that in for the default $store r0 ,DNS,r1 ; name string, and stuff the length. 4$: $store #lun.sr,LCH,r1 ; a channel number to use for $PARSE $off #fb$fid,FOP,r1 ; we want an implicit $SEARCH mov #parnam ,r2 ; also point to the NAME block sub #100 ,sp ; allocate result name string $store sp ,RSA,r2 ; set up the pointer to name string $store #100,RSS,r2 ; and set the size of the string sub #100 ,sp ; allocate result expanded name string $store sp ,ESA,r2 ; set up the pointer to expanded name $store #100,ESS,r2 ; and set the size of the string $store #ER$FNM ,STS,r1 ; preset a bad filename error strlen r4 ; /46/ get the length of the filename tst r0 ; anything left at all ? beq 90$ ; no, fake a bad filename please $store r0,FNS,r1 ; stuff the filename size in please $store r4,FNA,r1 ; /46/ stuff the filename address $parse r1 ; try to parse the filename now $compar #ER$UIN,sts,r1 ; Maybe a remote file spec? ;RBD01+ bne 5$ ; (no) $testb #,fnb,r2 ; Anything wild? bne 90$ ; (wild remote files no good) $testb #nb$nod,fnb,r2 ; Remote file? beq 90$ ; (ER$UIN with no node???) $off #nb$wch,fnb,r2 ; Make succeeding $search's act nice br 7$ ; Go ahead with it ;RBD01- 5$: $compar #0 ,STS,r1 ; did the parse of the name work ? blt 90$ ; no, exit and return STS in r0 7$: mov 2(r5) ,r1 ; where we will copy the name to movb o$esl(r2),r0 ; the length of the new name beq 30$ ; can't happen unless you fubar cmp r0 ,#77 ; truncate names that are too long blos 10$ ; it's ok mov #77 ,r0 ; too long, please set it to 63 (10) 10$: mov o$esa(r2),r2 ; where the name is coming from 20$: movb (r2)+ ,(r1)+ ; copy a byte at a time please sob r0 ,20$ ; next please 30$: clrb @r1 ; insure .asciz please clr r0 ; no errors please br 100$ ; bye 90$: $fetch r0,STS,r1 ; error from parse, return in r0 100$: add #200 ,sp ; pop local nameblock buffers 110$: unsave ; /46/ pop registers return ; bye .globl defdir ; F I X W I L D ; ; FIXWILD will replace % with ? for RSTS/E ; ; input: @r5 Address of string to process fixwil::nop ; in case we want to patch to 207 save ; save a register we use here mov @r5 ,r2 ; get the string address 10$: tstb @r2 ; done with the filename yet ? beq 100$ ; yes, exit cmpb @r2 ,#'% ; check for a % character bne 20$ ; no movb #'? ,@r2 ; yes, replace with question mark 20$: inc r2 ; next please br 10$ ; back again 100$: unsave ; pop r2 clr r0 ; no errors return ; bye iswild::save ; save a register we may use mov #parfab,r2 ; get a fab to use for this tst fu$def ; do we need a default device string? beq 5$ ; no $store #sydisk,DNA,r2 ; yes, please put it where we need it $store #sylen ,DNS,r2 ; also, the length also 5$: strlen #defdir ; get the default directory spec tst r0 ; was anything there ? beq 10$ ; no $store #defdir,DNA,r2 ; yes, stuff that in for the default $store r0 ,DNS,r2 ; name string, and stuff the length. 10$: $store @r5,FNA,r2 ; filename address strlen @r5 ; length $store r0,FNS,r2 ; into the FAB please $fetch r1,NAM,r2 ; get NAM block address clr O$ESA(r1) ; no expanded string address clr O$RSA(r1) ; no resultant string address clrb O$ESS(r1) ; no length fields either clrb O$RSS(r1) ; no length fields either $parse r2 ; parse the filename $fetch r0,STS,r2 ; get the status bmi 90$ ; exit on error please $testbi #NB$WVE!NB$WTY!NB$WNA!NB$WDI,FNB,r1 ; any wildcarding today ? beq 90$ ; no mov #1 ,r0 ; yes, return(true) br 100$ ; exit 90$: clr r0 100$: unsave ; pop reg and exit return ; exit .sbttl return current task size and return exec .mcall gtsk$s ,gtim$s second::save ; /43/ Get seconds past midnight sub #40 ,sp ; /43/ Used for reporting transfer mov sp ,r2 ; /43/ statistics gtim$s r2 ; /43/ One should really get the time mov g.ticp(r2),clkflg ; /E64/ grab the clock tick rate mov g.timi(r2),r3 ; /43/ in the 64 bit klunk format to mul #60. ,r3 ; /43/ avoid 24 hour rollover, but add g.tisc(r2),r3 ; /43/ I really think this is mov g.tihr(r2),r0 ; /43/ sufficient clr r1 ; /43/ multiply hour of day by 3600 mul #60.*60.,r0 ; /43/ which has to be 32 bits in add r3 ,r1 ; /43/ size, then add in minutes*60 adc r0 ; /43/ + seconds. add #40 ,sp ; /43/ Pop buffer and exit unsave ; /43/ Pop registers return ; /43/ Bye .sbttl gsa get space for i/o buffers ; Modified from sample GSA from RMS v2 distribution ; by Brian Nelson 05-Jan-84 10:22:06 ; ; ; Interface: ; Request space: ; R0 -> RMS/user Pool list head (maintained by RL/CQB) ; R1 := Amount of space requested (bytes) ; R2 := 0 (differentiates between request and release) ; ; Release space: ; R0 -> RMS Pool list head (maintained by RL/CQB) ; R1 := Amount of space to be released (bytes) ; R2 -> Base address (for release) ; ; ; Returns: ; C-Bit "set" if an error has occurred (failure) ; C-Bit "clear" if no error has occurred (success) ; .Mcall Extk$S .Sbttl Control block definitions .Psect GSA$$D,RW,D ; ; GSA internal data: ; ; GSABAS - Base address for the next memory allocation. ; Initially set to zero, it will be assigned ; the first address outside of the task's ; current address limits. ; GSAMIN - Decimal value reflecting the minimum size ; (in bytes) to extend the task in order to ; provide space to the pool. ; GSAREQ - Requested pool block number. If a request ; for the 'GSAMIN' fails, then the original ; allocation size will be attempted. If that ; fails, then there is no more memory left. ; GSABAS:: ; GSA base address .Word 000000 ; (for next allocation) GSAMIN:: ; Minimum allocation .Word 512./64. ; (in 32-word blocks) GSAREQ:: ; Size of this request .Word 000000 ; (if 'GSAMIN' extends fail) .Sbttl GSA Initialization code .Psect GSA$$I,RO,I .mcall extk$s ,gtsk$s GSAINI: Mov R0,-(SP) ; R0-2 will be used to Mov R1,-(SP) ; communicate with $INIDM Mov R2,-(SP) ; NOTE: $INIDM uses EXTSK. mov r0 ,-(sp) ; save r0 sub #40 ,sp ; check for 512 boundary mov sp ,r0 ; get the current task size and see gtsk$s r0 ; if we are at a boundary. if so, then mov g.tsts(r0),r0 ; extend a little bit to get INIDM to add #40 ,sp ; behave itself bic #^c777 ,r0 ; strip all the high crap cmp r0 ,#776 ; should we extend a little bit? blo 10$ ; no extk$s #1 ; yes, get 64 more bytes please 10$: mov (sp)+ ,r0 ; restore r0 Call $INIDM ; Initialize dynamic memory Mov R1,GSABAS ; Setup the "free" address Mov (SP)+,R2 ; Restore the registers Mov (SP)+,R1 ; Mov (SP)+,R0 ; Return ; And return to GSA .Sbttl GSA Mainline code .Psect GSA$$M,RO,I ; ; GSA Mainline ; ; Entry point is "GSA", with registers 0-2 loaded as ; described above. ; GSA:: gsax: ; ; First, determine if dynamic memory has been initialized. ; GSABAS (initially set to zero) will be non-zero if $INIDM ; has been called and the memory list initialized. On RSX ; based systems it is possible to install tasks with an ; extension (/INCREMENT). $INIDM will detect this and setup ; the first memory entry in the pool list. ; ; A point to note: If the RSX task has been installed with ; the non-checkpointable (/-CP) flag, then EXTKs will not ; return success. If it is necessary to install the task ; non-checkpointable, then the task should be installed with ; and increment value. ; Tst GSABAS ; Dynamic memory initialized? Bne 10$ ; Yes if NE, proceed Call GSAINI ; Otherwise, initialize pool 10$: Tst R1 ; Real memory? Bne 20$ ; Yes if NE, then process it Return ; Otherwise return with success 20$: Tst R2 ; Address specified? (release) Beq 30$ ; No if EQ, then it's a request Jmp $RLCB ; Otherwise it's a release; do it 30$: Mov R0,-(SP) ; save pool list head Mov R1,-(SP) ; save size of request Mov R2,-(SP) ; save entry flag Call $RQCB ; Try the allocation Bcc 70$ ; CC signifies success Mov 2(SP),R1 ; Obtain the request size Add #63.,R1 ; Round the request Asr R1 ; to a 32-word boundary Asr R1 ; Then convert the value Asr R1 ; to the number of Asr R1 ; 32-word blocks. Asr R1 Asr R1 Mov R1,GSAREQ ; Save the real size Cmp R1,GSAMIN ; Smaller than minimum? Bhi 40$ ; No if HI, use it as is Mov GSAMIN,R1 ; Otherwise use GSAMIN 40$: Extk$S R1 ; Extend the task Bcc 60$ ; CC if successful Cmp R1,GSAREQ ; Is this request? Blos 50$ ; Yes if LOS, the end Mov GSAREQ,R1 ; Otherwise try to use Br 40$ ; the actual request 50$: Sec ; Mark failure Br 70$ ; And exit 60$: Mov 4(SP),R0 ; Setup the PLH Asl R1 ; Convert the real Asl R1 ; size to the actual Asl R1 ; 16-bit size that Asl R1 ; was allocated. Asl R1 ; The virtual address Asl R1 ; should be after the Mov GSABAS,R2 ; task (which is now Add R1,GSABAS ; part of the task) Call GSAX ; Call ourself to release Mov (SP)+,R2 ; Restore our registers Mov (SP)+,R1 ; to the initial state Mov (SP)+,R0 ; upon entry, and reenter Br GSAX ; as if it's a new request 70$: Inc (SP)+ ; These won't alter the Bit (SP)+,(SP)+ ; C-bit, so status remains Return ; unchanged upon return .sbttl Corrected version of $INIDM ; Re-do $INIDM to use the actual task top address, not ; that which was stored by TKB from the .LIMIT directive. ; This is required because we have already done a EXTK$S. ; ; 17-Feb-87 07:11:21 BDN edit 3.56 .mcall GPRT$ ,GTSK$ ,DIR$ ,GTSK$S .Save .psect IMPURE ,d Limit: .Limit pdpb: GPRT$ tbuf tdpb: GTSK$ tbuf tbuf: .blkw 20 .Restore .Psect PURE$I ,RO,I,LCL,REL,CON ; Inidm ; ; Input: r0 Address of free code pool listhead ; Output: r0 First address in task ; r1 Address following task ; r2 Size of core pool $Inidm::DIR$ #tdpb ; We already did an EXTK$S so mov tbuf+G.TSTS,r2 ; want to use the CURRENT topmem add #3 ,r2 ; Round up to next 4 byte boundary bic #3 ,r2 ; ... mov r2 ,@r0 ; Set base address of pool EXTK$S #1 ; Ask for just a little bit more DIR$ #pdpb ; Get partition parameters mov $DSW ,r0 ; Save starting address of partition DIR$ #tdpb ; Get task parameters mov r2 ,-(sp) ; Save starting address clr (r2)+ ; Clear out first word mov tbuf+G.TSTS,(r2) ; Set physical size of task sub r0 ,(sp) ; Compute apparent size of task mov r0 ,r1 ; Copy base address add (r2) ,r1 ; Next address after task sub (sp)+ ,(r2) ; Set size of free pool mov (r2) ,r2 ; Get size return ; And exit .sbttl Increment status ; /BBS/ added this ; This kludge is provided because RT-11XM for some reason loses ; track of the status word's address, even when it's kept in the ; root, after calling c$dial results in a failed call four times. ; Then, it writes into RMON, trashing it and crashing everything. ; This is NOT any problem under TSX-Plus.. Billy Y. 24-Apr-91 incsts::inc status return .sbttl cctrap the control C trap cctrap::cmp cccnt ,#cc$max bhi 100$ CALL setcc inc cccnt return 100$: tst inserv beq 110$ call rstsrv 110$: tst infomsg ; /43/ beq 120$ ; /43/ wrtall #rme.07 ; /E64/ 120$: jmp c$exit .globl cccnt ,inserv ,rstsrv ,infomsg ; D I R E R $ ; ; called from DIRERR value macro direr$::mov r0 ,-(sp) ; direrr will select whether or not mov 4(sp) ,r0 ; to call rms error or FIP (or DIR) beq 10$ ; error based on whether the error CALLS syserr , ; code is < 0 (implies RMS) or > 0 wrtall #errtxt ; which implies either FIP (RSTS) .newline ; or a DIRECTIVE error (RSX). Thus 10$: mov (sp)+ ,r0 ; for RSX all error codes should be mov @sp ,2(sp) ; made > 0 for non RMS errors. tst (sp)+ ; error 0 is a no-op. return .sbttl Open and close the link device opentt::clr r0 ; /BBS/ preset to no error tst linksts ; already open? bne 100$ ; yes, ignore it then tst remote ; if remote beq 10$ ; then ttname := ourname tst inserv ; but not if we are a server beq 5$ ; and the line number has been tstb ttname ; set already bne 10$ ; 5$: calls gttnam ,<#ttname> ; get the terminal name here 10$: calls ttyini ,<#ter$pa> ; /E64/ init the link device tst r0 ; did it work? bne 100$ ; no mov sp ,linksts ; ya, flag it as being open 100$: return clostt::save call ttyfin ; close the link calls ttyrst ; /62/ reset the terminal clr linksts ; flag link is now closed unsave return .end