$SIZE*LN$CNT> LT 3770; Insure we will fit in 1KW .psect $RODATA ,RO,D,LCL,REL,CON edikey::.byte 'S!200 ; If using simple minded XOR .byte 'Z!200 ; encryption. Otherwise build .byte '1!200 ; one at run time. .byte 'p!200 .byte '#!200 .byte 'x!200 .byte '7!200 .byte 'c!200 .byte '[!200 .byte '.!200 .byte 'a!200 .byte ':!200 .byte 'k!200 .byte 0 ; we will never get a NULL. prm:: .asciz /Cle$ / ; A prompt nulprm: .byte 0 .blkb 10 ; In case of patching? .even ; Please lastcn::.word LN$CNT ; Buffer count edisiz::.word LN$MAX ; $$BUFP = 0 ; Now generate command buffers lastli:: ; Start of buffer address table .rept LN$CNT ; Generate the structure $BADDR =EDIEND+; Compute the address .ASSUME $BADDR LT <143777-LN$SIZE> .word $BADDR ; Insert the address $$BUFP = $$BUFP+1 ; Move up .endr ; Next please .asect ; Local R/W data. You can NOT ; place data here that needs to be . = 1000 ; saved between commands. stklim::.blkw 300 ; A small stack stack:: .blkw 1 ; Top of it buf:: .blkb 200 ; A buffer for reading tmpbuf: .blkb 200 jobn: .blkw 1 ; Current job number regid: .blkw 1 ; Region id for dynamic region regnam: .blkw 2 ; Region name func: .blkw 1 ; Debugging vttype::.blkw 1 ; Terminal type curppn: .blkw 1 ; Current UIC prmadr: .blkw 1 .restore .sbttl Entry to the run time system .psect $CODE ,ro,i,lcl,rel,con ...CLE::mov #stack ,sp ; Insure sufficient stack space call init ; Start things up 10$: call leftm ; Insure cursor at left margin mov #buf ,-(sp) ; Read, edit and store a line mov prmadr ,-(sp) ; Stuff buffer address and a mov sp ,r5 ; promt. Point R5 to params. This call kbredi ; is because we use the editor with cmp (sp)+ ,(sp)+ ; Minitab and Kermit-11. Pop args. tst r1 ; Anyting there? beq 10$ ; No mov #buf ,r2 ; Remove trailing control chars add r1 ,r2 ; Point to end of the line 20$: cmpb -(r2) ,#40 ; Well? bhi 30$ ; No more sob r1 ,20$ ; Found one, keep looking br 10$ ; Nothing, ignore it. 30$: cmp r1 ,#1 ; One character? bne 40$ ; No cmpb buf ,#'$ ; Just a '$' command beq 10$ ; Yes, ignore 40$: mov #buf ,-(sp) ; No. Now comes the REAL KLUDGE. call chkbye ; Since we can't tell the exec to bcs 50$ ; delete the region when its creator call detreg ; disappers, we will try to catch call delreg ; the likely logout message and then 50$: mov #buf ,-(sp) ; detach and delete the region here. .TTECH ; Insure echoing. call docmd ; Generate and execute '$ commandline' jmp ...huh ; This can't happen. .even .sbttl Utility routines ; DOCMD ; ; Passed: 2(sp) Command line to build ; Return: If '$' is a valid CCL command, it never returns Docmd: mov r4 ,-(sp) ; Save it mov r3 ,-(sp) ; This one also mov 2+4(sp) ,r3 ; Get string address STRLEN r3 ; Get the length now mov r0 ,r2 ; Copy it beq 100$ ; Nothing to do. add #5 ,r2 ; Room for '$ ' and null. bic #1 ,r2 ; Insure even value sub r2 ,sp ; Allocate a buffer mov sp ,r4 ; And a pointer to it movb #'$ ,(r4)+ ; Insert DCL prefix movb #40 ,(r4)+ ; ... STRCPY r4 ,r3 ; Make a copy of the command mov sp ,r4 ; Reset buffer address CLRXRB ; Insure XRB is cleared out STRLEN r4 ; Get total length mov r0 ,XRB+XRLEN ; Length of the CCL command mov r0 ,XRB+XRBC ; Again mov r4 ,XRB+XRLOC ; String address .CCL ; Try it out PRINT #200$ ; Huh? This can't happen add r2 ,sp ; But it did. Restore the stack 100$: mov (sp)+ ,r3 ; Pop registers mov (sp)+ ,r4 ; Simple mov (sp)+ ,(sp) ; Move return address up return ; And exit 200$: .asciz /$ (DCL) CCL command failed/ .even .sbttl Get started ; INIT ; ; Passed: Nothing ; ; Init handles all initialization whenever a user enters the RTS. ; It does the following things: ; ; 1. Save current UIC. ; 2. Get terminal type, reject entry if not a VT1xx or VT2xx. ; 3. ChanCLE MAC[.050034]CLE .MAC[.050034]    X14|H [4;Ik(&'( k ߫H&P` \RrPP2PPzPP{PPPPP2P~\$\\TD 0D \~ hi) +\ ^( n ^( np\^txY\^ˀ\!kVk<\F˰<˴ˬ\VVkˤ1`@lP ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789<@<SЬTЬ UQS>?\\\\\\\\\`:#@'="\abcdefghi\\\\\\\jklmnopqr\\\\\\\~stuvwxyz\\\\\\\\\\\\\\\\\\\\\\{ABCDEFGHI\\\\\\}JKLMNOPQR\\\\\\\\STUVWXYZ\\\\\\0123456789\\\\\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~@ggh<i|o<m<4p<p<k|Zn<l fr rwx<x<x<x޺<w@]@@fjnr]Ze@@|> | |v<H|  |  |xz|  |zt f r   < &^ @&@'*/V,"?Lh:hmBmz|z{x`y~|fN|@@|@͂|@ ݃ƃ<ns<|Ŏ |️|ep|u|-@率|<ᄇ2ֻr||ZRM | ntB|xyvZw|J=|R>|J? nnaa|bddfS .PLAS ; Do it tstb FIRQB ; Did it work? bne 200$ ; No tst r5 ; First time here? beq 30$ ; No mov curppn ,@#edippn ; And save the current UIC please 30$: cmp curppn ,@#edippn ; Same UIC bne 40$ ; No, init the region then. tst r5 ; First time? beq 100$ ; No 40$: call inireg ; Yes, init things 100$: clr @#edipos ; Clear out cursor position clr @#edilen ; Clear length return ; Exit 200$: movb FIRQB ,r0 ; Dump the error code DECOUT r0 ; Do it PRINT #inierr ; Error text PRINT func ; Function jmp ...dcl ; Goto DCL .save .psect $RODATA ,D inierr: .asciz / was the init error. / unknown:.asciz /Unknown init failure/ $uurts: .asciz /Failed to create region/ $atrfq: .asciz /.PLAS ATRFQ failed/ $crafq: .asciz /.PLAS CRAFQ failed/ notvt: .ascii /??CLE-F CLE can only be used from VTxxx series terminals/ crlf: .byte CR,LF,0 .even .restore .enabl LSB inireg::mov #-1 ,@#edicmd ; Init the current command to -1 clr @#edists ; Clear status mov #LN$CNT ,r0 ; Number of buffers to clear mov #lastli ,r1 ; Address of list 10$: mov (r1)+ ,r2 ; Address of current buffer clrb @r2 ; Zap it sob r0 ,10$ ; Next please CLRFQB ; Use UU.SYS for a key movb #UU.SYS ,FIRQB+FQFUN ; Function incb FIRQB+5 ; Part one .UUO ; mov #FIRQB+2,r1 ; A pointer mov #34 ,r0 ; Size mov #$skey ,r2 ; ... 20$: movb (r1)+ ,(r2) ; Copy bne 30$ ; Ok incb (r2) ; Insure > 0 30$: bisb #200 ,(r2)+ ; Insure > 200 sob r0 ,20$ ; Next clrb @r2 ; .ASCIZ .DATE ; Get current stuff movb XRB+5 ,@#editim ; Save ticks till minute mov #$ENCKEY,-(sp) ; Inittialize keys clr -(sp) ; Get ENCODE key mov #200$ ,-(sp) ; Using time info call kinit ; Do it inc 2(sp) ; Get DECODE key next mov #$DECKEY,4(sp) ; Simple call kinit ; Again add #3*2 ,sp ; Pop stack. return ; Exit ; Since the tables in CLECRY.MAC are key dependent, we will ; use the old one and do the en/decryption based on the ticks ; to next second at region creation. .save .radix 10 .psect $PDATA ,D 200$: .byte 31, 41, 59, 26, 53, 58, 97, 93, 238, 46, 26, 43, 38, 32, 79 .even .radix 8 .restore .dsabl lsb .sbttl Detach, delete region Detreg::CLRFQB ; Always do this movb #DTRFQ ,FIRQB+4 ; .PLAS subfunction mov regid ,FIRQB+6 ; Region ID .PLAS ; Simple clc ; Always say it worked. return ; Exit Delreg::CLRFQB ; Ditto, insure no oddball defaults mov regnam+0,FIRQB+FQNAM1+0 ; Stuff the region name in mov regnam+2,FIRQB+FQNAM1+2 ; ...Stuff the region name in movb #24 ,FIRQB+4 ; UU.RTS subfunction, delete region movb #UU.RTS ,FIRQB+FQFUN ; .UUO function code .UUO ; Simple clc ; Always say it works return ; And exit .sbttl Utility routines Clrcns::return Read1c::CLRXRB ; Insure XRB is zapped .TTNCH ; No echo .TTDDT ; One shot ODT mode CLRXRB ; Insure XRB zapped clr -(sp) ; Allocate a buffer mov sp ,r1 ; A pointer mov r1 ,XRB+XRLOC ; Buffer address inc XRB+XRLEN ; One character size buffer mov #100000 ,XRB+XRTIME ; KMON read .READ ; Simple clr r0 ; Return the character next tstb FIRQB ; Errors? bne 100$ ; Yes, return a NULL tst XRB+XRBC ; No data????? beq 100$ ; Should never happen. bisb @r1 ,r0 ; No, return the data then. 100$: tst (sp)+ ; Pop the buffer and exit return ; Bye kbread::return ; No-op for hardcopy terminals ; TTYOUT ; ; Passed: 2(sp) .ASCIZ string address ; ; ; The entry point MOUT is present for compatibility with K11EDI ; having been assembled for Kermit-11 with the K11MAC.MAC include ; file. MOUT:: TTYOUT::mov r0 ,-(sp) ; Save R0 mov r1 ,-(sp) ; Save R1 mov 2+4(sp) ,r0 ; no length, assume .asciz 10$: tstb (r0)+ ; move along looking for a null bne 10$ ; none yet so far sub 2+4(sp) ,r0 ; get the length dec r0 ; off by one ble 100$ ; Nothing to do, exit 20$: mov #XRB ,r1 ; address of CLE MAC[.050034]CLE .MAC[.050034]    X14|H [4;Ik(&'( k ߫H&P` \RrPP2PPzPP{PPPPP2P~\$\\TD 0D \~ hi) +\ ^( n ^( np\^txY\^ˀ\!kVk<\F˰<˴ˬ\VVkˤ1`@lP ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789<@<SЬTЬ UQS>?\\\\\\\\\`:#@'="\abcdefghi\\\\\\\jklmnopqr\\\\\\\~stuvwxyz\\\\\\\\\\\\\\\\\\\\\\{ABCDEFGHI\\\\\\}JKLMNOPQR\\\\\\\\STUVWXYZ\\\\\\0123456789\\\\\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~@ggh<i|o<m<4p<p<k|Zn<l fr rwx<x<x<x޺<w@]@@fjnr]Ze@@|> | |v<H|  |  |xz|  |zt f r   < &^ @&@'*/V,"?Lh:hmBmz|z{x`y~|fN|@@|@͂|@ ݃ƃ<ns<|Ŏ |️|ep|u|-@率|<ᄇ2ֻr||ZRM | ntB|xyvZw|J=|R>|J? nnaa|bddf mov #$cbomg ,r3 ; Octal conversion br pcom Putdec: SAVE mov #$cbdmg ,r3 ; Decimal conversion Pcom: SAVE ; Save some more registers mov 10+2(sp),r1 ; The value sub #20 ,sp ; Create a buffer mov sp ,r0 ; The buffer movb #40 ,(r0)+ ; Stuff a blank in clr r2 ; Formatting options jsr pc ,@r3 ; Now format clrb @r0 ; Make it .ASCIZ now mov sp ,r0 ; Reset the buffer address PRINT r0 ; And dump the data add #20 ,sp ; Pop buffer UNSAVE ; Pop registers mov (sp)+ ,(sp) ; Move return address up return ; And exit Scanch::save ; save temps mov 6(sp) ,r2 ; get address of the string clr r0 ; initial found position 10$: tstb @r2 ; end of the string yet ? beq 90$ ; yes inc r0 ; no, pos := succ(pos) cmpb 4(sp) ,(r2)+ ; does the ch match the next one? bne 10$ ; no, try again br 100$ ; yes, exit loop 90$: clr r0 ; failure, return postion = 0 100$: unsave ; pop r2 mov @sp ,4(sp) ; move return address up cmp (sp)+ ,(sp)+ ; pop stack return ; and exit .sbttl RSX Syslib conversion routines $SAVRG::MOV R4,-(SP) MOV R3,-(SP) MOV R5,-(SP) MOV 6(SP),R5 CALL @(SP)+ MOV (SP)+,R3 MOV (SP)+,R4 MOV (SP)+,R5 RETURN $CBDMG::MOV #25012,-(SP) BR E00072 $CBDSG::MOV #25412,-(SP) BR E00072 $CBOMG::MOV #31010,-(SP) BR E00072 $CBOSG::MOV #31410,-(SP) BR E00072 $CBTMG::BIC #-400,R1 MOV #15010,-(SP) E00072: TST R2 BNE E00102 BIC #1000,(SP) E00102: MOV (SP)+,R2 $CBTA::JSR R5,$SAVRG MOVB R2,R5 CLRB R2 SWAB R2 ASR R2 BCC E00134 TST R1 BPL E00134 NEG R1 MOVB #55,(R0)+ E00134: MOV R0,R4 ROR R2 ROR R2 ROR R3 CLRB R3 BISB R2,R3 CLRB R2 BISB #60,R2 MOV R1,R0 E00160: MOV R0,R1 CLR R0 DIV R5,R0 CMP R1,#11 BLOS E00200 ADD #7,R1 E00200: ADD R2,R1 MOV R1,-(SP) DECB R3 BLE E00234 TST R0 BNE E00230 TST R2 BPL E00234 TST R3 BPL E00230 BIC #20,R2 E00230: CALL E00160 E00234: MOVB (SP)+,(R4)+ MOV R4,R0 RETURN .sbttl Get terminal type .enabl lsb ; Assume: Login.com did a $ SET TER/INQ ; ; INQTER ; ; Passed: Nothing ; Return: R0 = 0 if hardcopy ; R0 = 1 if VT1xx or VT2xx series Inqter::CLRFQB ; Clear out again movb #UU.TRM ,FIRQB+FQFUN ; Terminal char function mov #1+<400*377>,FIRQB+4 ; Subfunction 1, KB: .UUO ; Read chars tstb FIRQB ; Success? bne 90$ ; No mov #200$ ,r0 ; Yes, look for VT type term 10$: tstb @r0 ; End of list yet? beq 90$ ; Yes, return( TTY ) cmpb (r0)+ ,FIRQB+6 ; No, check for a match bne 10$ ; Not yet mov #VT100 ,r0 ; Yes, return(VT100) br 100$ ; Exit 90$: mov #TTY ,r0 ; Nothing 100$: return ; Exit .save .psect $RODATA ,D 200$: .byte 6. ; VT100 .byte 13. ; VT101 .byte 14. ; VT102 .byte 15. ; VT125 .byte 16. ; VT131 .byte 17. ; VT132 .byte 18. ; VT220 .byte 19. ; VT240 .byte 20. ; VT241 .byte 21. ; VT105 .byte 22. ; VK100 (gigi) .byte 23. ; RT02 .byte 0 ; End .even .restore .dsabl lsb .sbttl Try to catch LOGOUT or BYE commands ; This is a kludge. The problem is that we do not have a way ; to tell the EXEC at region creation time to get rid of the ; region when the creator process (your job) is removed (via ; UU.BYE or job kill). Ideally, one would like to be able to ; do so. But in the mean time, what we can do is to check for ; LIKELY logout strings, like LOG*OUT or BYE*, and if found ; detach and delete the region ourself. ; ; ; CHKBYE ; ; Passed: 2(sp) Command line address ; Return: C bit Cleared --> Logout command found ; C bit Set --> We did not find LOG*OUT or BYE? Chkbye::SAVE ; Save temps mov 2+<2*3>(sp),r1 ; Command line sub #LN$SIZE+2,sp ; Allocate a buffer mov sp ,r2 ; Point to it 10$: movb (r1)+ ,@r2 ; Copy command character beq 20$ ; Alldone cmpb @r2 ,#CR ; Carriage return? beq 20$ ; Yes, done cmpb @r2 ,#LF ; Line feed? beq 20$ ; Done cmpb @r2 ,#'A!40 ; Lower cCLE MAC[.050034]CLE .MAC[.050034]    X14|H [4;Ik(&'( k ߫H&P` \RrPP2PPzPP{PPPPP2P~\$\\TD 0D \~ hi) +\ ^( n ^( np\^txY\^ˀ\!kVk<\F˰<˴ˬ\VVkˤ1`@lP ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789<@<SЬTЬ UQS>?\\\\\\\\\`:#@'="\abcdefghi\\\\\\\jklmnopqr\\\\\\\~stuvwxyz\\\\\\\\\\\\\\\\\\\\\\{ABCDEFGHI\\\\\\}JKLMNOPQR\\\\\\\\STUVWXYZ\\\\\\0123456789\\\\\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~@ggh<i|o<m<4p<p<k|Zn<l fr rwx<x<x<x޺<w@]@@fjnr]Ze@@|> | |v<H|  |  |xz|  |zt f r   < &^ @&@'*/V,"?Lh:hmBmz|z{x`y~|fN|@@|@͂|@ ݃ƃ<ns<|Ŏ |️|ep|u|-@率|<ᄇ2ֻr||ZRM | ntB|xyvZw|J=|R>|J? nnaa|bddf #LN$SIZE+2,sp ; Yes, pop buffer and exit sec ; Done, no match. 100$: UNSAVE ; Pop registers and exit mov (sp)+ ,(sp) ; Move return address up return ; And now exit. .save .psect $RODATA .even log$li::.word LOG ,LOGO ,LOGOU ,LOGOUT ,BYE ,BYEF ,BYEI ,BYEY .word 0 log:: .asciz /LOG/ logo:: .asciz /LOGO/ logou:: .asciz /LOGOU/ logout::.asciz /LOGOUT/ bye:: .asciz /BYE/ byey:: .asciz /BYEY/ byef:: .asciz /BYEF/ byei:: .asciz /BYEI/ .even .restore .sbttl Encryption .iif ndf ,$$SIMPLE, $$SIMPLE = 1 .if ne ,$$SIMPLE .ift ; ENCRYPT ; ; Passed: ; 2(sp) String to do ; 4(sp) Key string ; Return: 2(sp) Output string ; ; This is simply an XOR encryption, which is trivial to break. ; It's better than nothing for now until I get a 'DES' routine ; or something similiar. It will prevent casual browsing. Decryp:: Encryp::SAVE ; Save all mov 2+<6*2>(sp),r5 ; Get pointer to string mov 4+<6*2>(sp),r4 ; Get pointer to key string mov #$skey ,r4 ; *** Override the key address *** STRLEN r4 ; Get length of the key mov r0 ,-(sp) ; Save the key length beq 100$ ; Nothing to do. clr r1 ; Offset into the key string 10$: clr r2 ; Copy the next character bisb @r5 ,r2 ; Get the character now. beq 100$ ; All done mov r4 ,r3 ; Key string add r1 ,r3 ; Point to current key char clr r0 ; Always avoid sign extension bisb @r3 ,r0 ; Get next key character xor r2 ,r0 ; Do the xor movb r0 ,(r5)+ ; And copy over the source inc r1 ; Next key character clr r0 ; Get remainder after division div (sp) ,r0 ; Do it br 10$ ; Next please 100$: clrb @r5 ; Insure .asciz tst (sp)+ ; Pop temp UNSAVE ; Pop all mov (sp) ,4(sp) ; Move return address up cmp (sp)+ ,(sp)+ return kinit: return .iff ; Use more advanced routine .enabl lsb Encryp:: Decryp:: 10$: mov r2 ,-(sp) mov sp ,r2 mov r3 ,-(sp) mov r4 ,-(sp) mov 6(r2) ,-(sp) mov 4(r2) ,r3 mov r3 ,-(sp) mov #LN$MAX ,r4 asr r4 asr r4 asr r4 20$: mov r3 ,(sp) movb editim ,r2 asr r2 asr r2 asr r2 inc r2 30$: call desalt sob r2 ,30$ add #10 ,r3 sob r4 ,20$ cmp (sp)+ ,(sp)+ mov (sp)+ ,r4 mov (sp)+ ,r3 mov (sp)+ ,r2 mov (sp) ,4(sp) cmp (sp)+ ,(sp)+ return .dsabl lsb .endc .sbttl Control C, Synch interupts and psuedo vector ...CC:: ; Control C things ...2CC::.TTECH ; Enable echoing .TTRST ; And reset other terminal stuff rti ; And dismiss the interupt .enabl lsb ...IOT::PRINT #210$ br ...DCL ..FPER:: ; Should never get here. ...BAD::movb FIRQB ,r2 ; Save exec's error code mov sp ,r3 ; Save stack PRINT #200$ ; Die PRINT #230$ ; Info OCTOUT r2 ; Error code OCTOUT @r3 ; PC OCTOUT 2(r3) ; PS PRINT #300$ ; CR/LF br ...dcl ; Exit ...HUH::PRINT #220$ ; A message br ...dcl ; And goto DCL ...DCL::CLRXRB ; Clear XRB out CLRFQB ; Ditto for the FIRQB mov #^RDCL ,FIRQB+FQNAM1 ; Go to DCL now mov #-1 ,FIRQB+FQEXT ; Make it the default .RTS ; Try to do this .EXIT ; Go away now. .save .psect $RODATA ,D 200$: .asciz /??CLE-F FP error or other trap/ 210$: .asciz /IOT trap/ 220$: .asciz /??CLE-F $ (DCL) CCL Command failed/ 230$: .asciz /Error code, PC and PS:/ 300$: .byte 15,12,0 .even .restore .psect .99998 .blkw 30 .psect .99999 ..psta::.word PF.KBM!PF.NER ; KBM and no error logging .rad50 /CLE/ ; Default 'runnable' extention .word 0 ; Reserved .word 1 ; 1 KW min size .word ..FPER ; FIS (an 11/40?) .word 0 ; Reserved .word 0 ; Reserved .word ...CLE ; 'New' user entry point .word ...CLE ; 'Run' entry .word ...BAD ; Junk .word ...BAD ; BPT .word ...IOT ; IOT .word ...BAD ; Non-exec EMT's .word ...BAD ; TRAP's .word ..FPER ; FPU errors .word ...CC ; Control C .word ...2CC ; Two of the things .word 1 ; P.SIZE, max size ..pend:: .end CLE MAC[.050034]CLE .MAC[.050034]<   X14|H [4;Ik(&'( k ߫H&P` \RrPP2PPzPP{PPPPP2P~\$\\TD 0D \~ hi) +\ ^( n ^( np\^txY\^ˀ\!kVk<\F˰<˴ˬ\VVkˤ1`@lP ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789<@<SЬTЬ UQS>