gno/kern/gno/gsos.asm

2282 lines
37 KiB
NASM

* $Id: gsos.asm,v 1.1 1998/02/02 08:19:23 taubert Exp $
**************************************************************************
*
* The GNO Shell Project
*
* Developed by:
* Jawaid Bazyar
* Tim Meekins
* Derek Taubert
*
**************************************************************************
*
* GSOS.ASM
* By Tim Meekins
* and Jawaid Bazyar
* and Derek Taubert (modified socket stuff)
*
* This file contains routines for patching GS/OS to intercept Shell
* calls and do special things with certain GS/OS calls.
*
* taken over by JB on 6/18/91
* 10/29/91 - extensive modifications to better support the data structures
* of the fd (file descriptor) table
*
**************************************************************************
copy global.equates
mcopy m/gsos.mac
case on
copy inc/gsos.inc
copy inc/tty.inc
GSOStable START
dc a2'GNOStandard' ; $2001 Create
dc a2'GNOStandard' ; $2002 Destroy
dc a2'NotImpGS' ; $2003 OSShutDown
dc a2'GNOChangePath' ; $2004 ChangePath
dc a2'GNOStandard' ; $2005 SetFileInfo
dc a2'GNOStandard' ; $2006 GetFileInfo
dc a2'NotImpGS' ; $2007 JudgeName
dc a2'NotImpGS' ; $2008 Volume
dc a2'GNOSetPrefix' ; $2009 SetPrefix
dc a2'PGGetPrefix' ; $200A GetPrefix
dc a2'GNOStandard' ; $200B ClearBackupBit
dc a2'NotImpGS' ; $200C SetSysPrefs
dc a2'NotImpGS' ; $200D Null
dc a2'GNOExpandPath' ; $200E ExpandPath
dc a2'NotImpGS' ; $200F GetSysPrefs
dc a2'GNOOpen' ; $2010 Open
dc a2'GNONewLine' ; $2011 NewLine
dc a2'GNORdWr' ; $2012 Read
dc a2'GNORdWr' ; $2013 Write
dc a2'PGClose' ; $2014 Close
dc a2'GNORefCommon' ; $2015 Flush
dc a2'GNORefCommon' ; $2016 SetMark
dc a2'GNORefCommon' ; $2017 GetMark
dc a2'GNORefCommon' ; $2018 SetEOF
dc a2'GNORefCommon' ; $2019 GetEOF
dc a2'GNOSetLevel' ; $201A SetLevel
dc a2'GNOGetLevel' ; $201B GetLevel
dc a2'GNORefCommon' ; $201C GetDirEntry
dc a2'NotImpGS' ; $201D BeginSession
dc a2'NotImpGS' ; $201E EndSession
dc a2'NotImpGS' ; $201F SessionStatus
dc a2'GNOStandard' ; $2020 GetDevNumber
dc a2'NotImpGS' ; $2021
dc a2'NotImpGS' ; $2022
dc a2'NotImpGS' ; $2023
dc a2'NotImpGS' ; $2024 Format
dc a2'NotImpGS' ; $2025 EraseDisk
dc a2'NotImpGS' ; $2026 ResetCache
dc a2'GNOGetName' ; $2027 GetName
dc a2'NotImpGS' ; $2028 GetBootVol
dc a2'GNOQuit' ; $2029 Quit
dc a2'NotImpGS' ; $202A GetVersion
dc a2'NotImpGS' ; $202B GetFSTInfo
dc a2'NotImpGS' ; $202C DInfo
dc a2'NotImpGS' ; $202D DStatus
dc a2'NotImpGS' ; $202E DControl
dc a2'NotImpGS' ; $202F DRead
dc a2'NotImpGS' ; $2030 DWrite
dc a2'NotImpGS' ; $2031 BindInt
dc a2'NotImpGS' ; $2032 UnbindInt
dc a2'NotImpGS' ; $2033 FSTSpecific
dc a2'NotImpGS' ; $2034 AddNotifyProc
dc a2'NotImpGS' ; $2035 DelNotifyProc
dc a2'NotImpGS' ; $2036 DRename
dc a2'GNOGetStdRefNum' ; $2037 GetStdRefNum
dc a2'NotImpGS' ; $2038 GetRefNum
dc a2'GNOGetRefInfo' ; $2039 GetRefInfo
dc a2'NotImpGS' ; $203A SetStdRefNum
END
;
; Patch GS/OS
; This has been modified greatly to install itself through our special
; Permanent Init (PIF) file. This will allow us to do GSBug OS call traps
; properly
;
GSOSinfo DATA
storeHandle dc i4'0'
patchType dc i2'0' ; 0 = no gnobug, 1 = gnobug
gnobugPath str '*:system:system.setup:gnobug'
END
patchGSOS START
using GSOSinfo
handle equ 0
nextHandle equ 4
lookuid equ 8
;
location equ 0
attributes equ 4
userID equ 6
length equ 8
last equ 12
next equ 16
subroutine (0:foo),10
pha
ph4 #gnobugPath
_GetUserID
cmp #0
beq okay1
jmp reggalar
okay1 pla
sta lookuid
FindHandle #patchGSOS,handle
lb1 ldy #last
lda [handle],y
tax
iny2
ora [handle],y
beq lb1a
lda [handle],y
sta handle+2
stx handle
bra lb1
lb1a anop
lb2 lda handle
ora handle+2
jeq reggalar
ldy #next
lda [handle],y
sta nextHandle
iny2
lda [handle],y
sta nextHandle+2
ldy #userID
lda [handle],y
cmp lookuid
beq around1
jmp lb3
around1 anop
ldy #attributes
lda [handle],y
cmp #$C018 ; always, for PIF
beq around2
jmp lb3
lb3 mv4 nextHandle,handle
jmp lb2
around2 anop ; we've got the handle
lda [handle]
sta nextHandle
ldy #2
lda [handle],y
sta nextHandle+2
lda [nextHandle]
sta OldGSOS
lda [nextHandle],y
sta OldGSOS+2
iny2
lda [nextHandle],y
sta OldGSOSSt
iny2
lda [nextHandle],y
sta OldGSOSSt+2
lda #<OurGSOS
ldy #1
sta [nextHandle],y
lda #>OurGSOS
iny
sta [nextHandle],y
lda #<StackGSOS
ldy #5
sta [nextHandle],y
lda #>StackGSOS
iny
sta [nextHandle],y
mv4 nextHandle,storeHandle
lda #1
sta patchType
return
reggalar anop
pla
stz patchType
mv4 >$E100A8,OldGSOS
ld2 <OurGSOS,>$E100A8+1
ld2 >OurGSOS,>$E100A8+2
mv4 >$E100B0,OldGSOSSt
ld2 <StackGSOS,>$E100B0+1
ld2 >StackGSOS,>$E100B0+2
return
END
;
; UnPatch GS/OS
;
unpatchGSOS START
using GSOSinfo
patchPtr equ 0
subroutine (0:foo),4
lda patchType
beq oldType
mv4 storeHandle,patchPtr
ldy #2
lda OldGSOS
sta [patchPtr]
lda OldGSOS+2
sta [patchPtr],y
iny2
lda OldGSOSSt
sta [patchPtr],y
iny2
lda OldGSOSSt+2
sta [patchPtr],y
return
oldType anop
mv4 OldGSOS,>$E100A8
mv4 OldGSOSSt,>$E100B0
return
END
OurGSOS START
php ; these six bytes are where
phb ; the call info (cmdNum/pBlockPtr)
long ai
phy ; get stored
pha ;
pha ; p/b reg contents
pha ; y reg contents
pha ; a reg contents
lda 11,s ; copy p,b, and y further down
sta 5,s ; so we can pull them off
lda 9,s ; before the call
sta 3,s
short a
lda 15,s ; set data bank to pBlock's
pha ; bank (to use short-based)
plb ; stack indirect adressing
long a
ldy #1
lda (13,s),y ; cmdNum
sta 7,s
ldy #5 ; copy high word of pBlock
lda (13,s),y ; pointer
sta 11,s
ldy #3 ; low word of pBlock pointer
lda (13,s),y
sta 9,s
lda 13,s
clc
adc #6 ; set rtl address to point after
sta 13,s ; the call information
pla
ply
plb
plp
jsl StackGSOS
rtl
END
StackGSOS START
using KernelStruct
phb ;Save the data bank
php ;Save the proc status
long ai
phx
phy
phd
phk
plb
cld
ldx curProcInd
sta exitCode,x
lda gsosDebug
and #1
beq noDebug
ErrWriteChar #'('
ErrWriteChar #'$'
lda 12,s
jsr writeacc
lda gsosDebug
and #32
beq noDebug
ErrWriteChar #','
ErrWriteChar #'$'
lda 16,s
and #$00FF
jsr writeacc
lda 14,s
jsr writeacc
noDebug anop
* check here to see if it's one of the call groups we handle
lda 12,s
and #$FF00
cmp #0 ; P16?
beq ok
cmp #$2000 ; GS/OS?
beq ok
cmp #$0100 ; ORCA?
beq ok
pld ; nope, go to the real GS/OS entry
ply ; point
plx
plp
plb
* real stack entry point
OldGSOSSt ENTRY
dc i4'0'
brk 0
* real inline entry point
OldGSOS ENTRY
dc i4'0'
brk 0
ok anop
tsc
sec
sbc #$1F
tcd
dec a
tcs
lda 45
sta pBlock
lda 47
sta pBlock+2
lda 43
sta cmdNum
lda 41
sta 47
lda 40
sta 46
lda 38
sta 44
lda 36
sta 42
lda 34
sta 40
lda 32
sta 38
jsl incBusy
lda cmdNum
and #$FF00 ;Is it a shell command?
cmp #$0100
beq shellit
cmp #$0000 ; P16?
beq P16it
jmp GSOSit ; must be GS/OS then!
P16it anop
; create pointer to process entry for the current process
lda curProcInd
clc
adc #|CKernData
sta procEnt
lda #^CKernData
sta procEnt+2
lda cmdNum
and #$00FF ; mask off (nothing!)
cmp #$32+1
bcc rangeOK
jmp NotImpP16
rangeOK anop
asl a
tax
jmp (P16table-2,x)
GSOSit anop
; create pointer to process entry for the current process
lda curProcInd
clc
adc #|CKernData
sta procEnt
lda #^CKernData
sta procEnt+2
lda cmdNum
and #$00FF ; mask off $2000
cmp #$3A+1
bcc range
jmp NotImpGS
range anop
asl a
tax
jmp (GSOStable-2,x)
shellit anop
lda cmdNum
and #$40
bne orca2
lda #0
sta pCount
bra chkcmd
orca2 anop
lda [pBlock]
sta pCount
lda pBlock
clc
adc #2
sta pBlock
lda pBlock+2
adc #0
sta pBlock+2
chkcmd anop
lda cmdNum
and #$3F ;Strip entry type 2 [don't ask]
cmp #$20 ; new calls
bcs BadCommand
asl a
tax
jmp (ShellCallTbl-2,x)
; | p pstat from before call
; | acch
; | accl
; | p pstat containing cznv result of cmp #1
;
; Not a valid command
;
BadCommand anop
lda #1
; [6/29/91] removed all this duplicated code [jb]
;
; Return from a GSOS call
;
GSOSReturn ENTRY
ShellReturn ENTRY
sta $1E+6 ; neat trick coming up
tsc
clc
adc #$1E+6 ; so we can pull the result
tcs
; pla
jsl decBusy
; pha
lda >gsosDebug
and #1
beq noDebug1
lda >gsosDebug
and #4
beq noDebug2
lda 1,s
beq noDebug2 ; if no error, no message
ErrWriteChar #15
ErrWriteChar #'#' ; error codes get a # sign
ldy #1
lda 1,s ; the error number (incognito)
jsr writeacc ;
ErrWriteChar #14
noDebug2 anop
ErrWritechar #')'
ErrWriteChar #13
noDebug1 anop
pla
pld
ply
plx
; insert from here
pha
cmp #1
lda 1,s
php
short m
lda 1,s
and #%11000011
sta 1,s
lda 4,s
and #%00111100
ora 1,s
sta 4,s
pla
long m
lda 3,s
xba
sta 3,s ; swap two bytes around
pla
; to here
plb ; modifies the fucking P!
plp
rtl
* Amazing how I've finally managed to merge all this code! Augh!
NotImpGS ENTRY
NotImpP16 ENTRY
NotImp ENTRY
ph4 pBlock
ph2 cmdNum
jsl OldGSOSSt
jmp GSOSReturn
END
* New GetPrefix code
* instead of a handle, we'll use a small malloc'd record as follows:
PGGetPrefix START
using KernelStruct
pfxRec equ 10
pfxString equ 14
ldy #prefixh-CKernData ; copy the handle of the prefix rec
lda [procEnt],y ; out of the process table
sta pfxRec ; we dereference it later
iny2
lda [procEnt],y
sta pfxRec+2
lda cmdNum
and #$FF00
beq ok2
lda [pBlock]
cmp #2
beq ok1
lda #$04
jmp GSOSReturn
ok2 lda [pBlock]
bra lookuppfx
ok1 ldy #2
lda [pBlock],y
lookuppfx anop
inc a
asl a
asl a
tay
iny2
lda [pfxRec],y
sta pfxString+2
pha
dey2
lda [pfxRec],y
sta pfxString
pha
ora 3,s
bne notnull
pla
pla
ph4 #nullGSOS
ld4 nullGSOS,pfxString
notnull lda cmdNum
and #$FF00
beq p16vers
ldy #6
lda [pBlock],y
pha
ldy #4
lda [pBlock],y
pha
jsl copygs2res
jmp GSOSReturn
* for P16 calls, we need to condition the returned pathname somewhat
p16vers anop
lda [pfxString]
beq patherror ; length is zero, avoid major memtrashing
tay
iny
short m
* Scan the prefix for a slash; if one is present, return a null pathname
* because after processing ':'s to '/'s the pathname would be totally
* incorrect.
slashloop lda [pfxString],y
cmp #'/'
beq patherror
dey
cpy #2
bcs slashloop
long m
ldy #4
lda [pBlock],y
sta pfxString+2
pha
ldy #2
lda [pBlock],y
sta pfxString
pha
jsl copygs2p
lda [pfxString]
and #$00FF
tay
short m
fixloop lda [pfxString],y
cmp #':'
bne nofix
lda #'/'
sta [pfxString],y
nofix dey
bne fixloop
long m
lda #0
jmp GSOSReturn
patherror long m
pla ; remove input params
pla ; store a zero as length,
ldy #4 ; and don't return an error
lda [pBlock],y
sta pfxString+2
ldy #2
lda [pBlock],y
sta pfxString
lda #0
short m
sta [pfxString]
long m
jmp GSOSReturn
nullGSOS dc i2'0'
END
GNOSetPrefix START
using KernelStruct
pfxRec equ 10
pfxInd equ 14
pfxpCount equ 16
pfxpfxNum equ 18
pfxpathname equ 20
newPath equ 24
ldy #prefixh-CKernData ; copy the handle of the prefix rec
lda [procEnt],y ; out of the process table
sta pfxRec ; we dereference it later
iny2
lda [procEnt],y
sta pfxRec+2
lda [pBlock]
cmp #2
beq ok1
lda #$04
jmp GSOSReturn
ok1 anop
pea 1 ; don't do the named pfx expansion
ldy #2 ; push the prefix number
lda [pBlock],y
pha
ldy #6 ; push the path to be expanded
lda [pBlock],y
pha
ldy #4
lda [pBlock],y
pha
jsl gno_ExpandPath ; call our C routine
sta pfxpathname
stx pfxpathname+2 ; store result
cpx #$FFFF ; did an error occur?
bne noerr
jmp GSOSReturn
noerr anop
ldy #2
lda [pBlock],y
inc a
asl a
asl a
sta pfxInd
tay
iny2
lda [pfxRec],y
pha
dey2
lda [pfxRec],y
pha
ora 3,s
bne dodispose
pla
pla
bra nodispose
dodispose jsl ~NDISPOSE
nodispose lda [pfxpathname]
inc a
inc a
inc a
pea 0
pha
jsl ~NEW
sta newPath
stx newPath+2
ldy pfxInd ; copy the addr of the new mem into the
sta [pfxRec],y ; prefix record
iny2
txa
sta [pfxRec],y
ph4 pfxpathname ; copy the string
ph4 newPath
jsl copygsstr
lda [newPath]
inc a
tay
lda [newPath],y ; check to see if there's a
and #$00FF
cmp #':' ; separator at the end of the
beq alright
short m ; prefix, and if not, then
lda #':'
iny ; add one. Note that we alloced
sta [newPath],y ; one extra byte for this possibility
long m
dey
tya
sta [newPath]
alright lda #0
jmp GSOSReturn
END
GNOChangePath START
temp1 equ 10
temp2 equ 14
oldpathres equ 18
newmem equ 22
ldy #2
lda [pBlock],y
sta temp1
iny2
lda [pBlock],y
sta temp1+2
iny2
lda [pBlock],y
sta temp2
iny2
lda [pBlock],y
sta temp2+2
pea 0
pea 0
pushlong temp1
jsl gno_ExpandPath
cpx #$FFFF
bne noerr
jmp GSOSReturn
noerr phx
pha ; push source addr for copy
stx oldpathres+2
sta oldpathres
pea $0000
lda [oldpathres]
clc
adc #2
pha
jsl ~NEW
stx newmem+2
sta newmem
phx
pha ; push dest address
ldy #2
sta [pBlock],y
iny2
txa
sta [pBlock],y
dey2
ora [pBlock],y
beq memoryErr
jsl copygsstr ; copy the expanded path to temp
pea 0
pushword #0
pushlong temp2
jsl gno_ExpandPath
cpx #$FFFF
bne noerr1
ph4 newmem
jsl ~NDISPOSE
jmp GSOSReturn
noerr1 anop
ldy #6
sta [pBlock],y
iny2
txa
sta [pBlock],y
movelong pBlock,pb
lda cmdNum
sta cn
jsl OldGSOS
cn dc i2'0' ; set to same call # we are
pb dc i4'0'
pha ; return any error we get
pushlong newmem
jsl ~NDISPOSE
interdict anop
ldy #2
lda temp1
sta [pBlock],y
iny2
lda temp1+2
sta [pBlock],y
iny2
lda temp2
sta [pBlock],y
iny2
lda temp2+2
sta [pBlock],y
pla
jmp GSOSReturn
memoryErr pla
pla
pea $0054
bra interdict
END
GNOStandard START
oldpath equ 10
exppath equ 14
ldy #2
lda [pBlock],y
sta oldpath
iny2
lda [pBlock],y
sta oldpath+2
pea 0
pushword #0
pushlong oldpath
jsl gno_ExpandPath
cpx #$FFFF
bne noerr
jmp GSOSReturn
noerr anop
sta exppath
stx exppath+2
ph4 exppath
jsl findDevice
cmp #$FFFF
beq notdevice
lda #$0058 ; not a block device!
bra goaway
notdevice anop
ldy #2
lda exppath
sta [pBlock],y
ldy #4
lda exppath+2
sta [pBlock],y
ph4 pBlock
ph2 cmdNum
jsl OldGSOSSt
pha ; return any error we get
lda cmdNum
cmp #$2002
beq docff
cmp #$2005
bne noff
docff anop
ldx oldpath+2
lda oldpath
jsr checkFF
noff anop
ldy #2
lda oldpath
sta [pBlock],y
ldy #4
lda oldpath+2
sta [pBlock],y
pla
goaway jmp GSOSReturn
END
checkFF START
using KernelStruct
tay
lda gsosDebug ; don't print the path twice
pha
stz gsosDebug
pea 1
pea 0
phx ; pathname pointer
phy
jsl gno_ExpandPath ; expand it again, but this time
phx ; pointer to expanded pathname
pha
jsl FindFF
phx ; pointer to ff entry, if any
pha
ora 3,s ; null pointer means not in FF
beq noFF
jsl DeleteFF
goaway pla
sta gsosDebug
rts
noFF pla
pla
bra goaway
END
PcheckFF START
using KernelStruct
tay
lda gsosDebug ; don't print the path twice
pha
stz gsosDebug
pea 1
pea 0
phx ; pathname pointer
phy
jsl p16_ExpandPath ; expand it again, but this time
phx ; pointer to expanded pathname
pha
jsl FindFF
phx ; pointer to ff entry, if any
pha
ora 3,s ; null pointer means not in FF
beq noFF
jsl DeleteFF
goaway pla
sta gsosDebug
rts
noFF pla
pla
bra goaway
END
GNOOpen START
using KernelStruct
temp1 equ 10
files equ 14
fd equ 18
fdPtr equ 20
ttyn equ 24
* Save the old pathname so we can restore before we exit
ldy #4
lda [pBlock],y
sta temp1
iny2
lda [pBlock],y
sta temp1+2
ldy #openFiles-CKernData ; copy the handle of the prefix rec
lda [procEnt],y ; out of the process table
sta files ; we dereference it later
iny2
lda [procEnt],y
sta files+2
pea 0
pushword #0
pushlong temp1
jsl gno_ExpandPath
cpx #$FFFF
bne noerr
jmp GSOSReturn
noerr anop
phx
pha
phx
pha
jsl findDevice
cmp #$FFFF
jne openTTY
pla
plx
ldy #4 ; forgetting this is B A D (baaaad)
sta [pBlock],y
txa
iny2
sta [pBlock],y
movelong pBlock,pb
lda cmdNum
sta cn
ldy #FDTLevel ; open the file with the proper
lda [files],y ; GS/OS level
sta dolevel+2
ldy #FDTLevelMode
lda [files],y
sta dolevel+4
ph4 #dolevel
pea $201A ; SetLevelGS
jsl OldGSOSSt
jsl OldGSOS
cn dc i2'0' ; set to same call # we are
pb dc i4'0'
pha
cmp #0
jne error
; alloc a process file entry ONLY if GS/OS opened the file okay
lda [files] ; inc the number of open files,
inc a ; allocFD does not do this
sta [files]
pea 0 ; push the (dp) address of
tdc ; our local 'fd'
clc
adc #fd
pha
jsl allocFD
sta fdPtr
stx fdPtr+2
ldy #openFiles-CKernData
lda [procEnt],y
sta files
iny2
lda [procEnt],y
sta files+2
ldy #2
lda [pBlock],y
pha
pea FDgsos
jsl AddRefnum ; add to our tracking table
ldy #2 ; refNum returned by open
lda [pBlock],y
ldy #FDrefNum
sta [fdPtr],y ; and store the new refnum in the list
lda fd ; retreive the fd number and
ldy #2 ; return it in the pBlock
sta [pBlock],y
ldy #FDTLevel
lda [files],y
ldy #FDTLevelMode ; handle internal levels
ora [files],y
ldy #FDrefLevel
sta [fdPtr],y ; store file level with refnum
lda #0
sta 1,s ; no error! trick the stack
error anop
ldx temp1+2
lda temp1
jsr checkFF
ldy #4
lda temp1
sta [pBlock],y
iny2
lda temp1+2
sta [pBlock],y
pla
jmp GSOSReturn
* this should be common between P16/GSOS
openTTY anop
inc a
sta ttyn
pla
pla ; remove junk
pei (ttyn)
pea FDtty ; we're looking for this type
jsl FindRefnum
sta fdPtr
stx fdPtr+2 ; if fdptr==NULL, then there are
ora fdPtr+2 ; no references to this TTY
bne notfirst
* create a reference to this TTY
pei (ttyn)
pea FDtty
jsl AddRefnum
* since this is the first open on this TTY, reassign this process' controlling
* tty to this terminal. Also, make sure the terminal's process group is
* 0 (but not the process'- this allows the real controlling terminal to
* signal the process)
ldx curProcInd
lda ttyn
dec a
sta ttyID,x
lda ttyn
dec a
asl a
tax
stz ttyStruct,x
* here, call the Init routine in the Device Driver
lda ttyn
dec a ; 0-n device number
pha
ldy #t_open
jsl LineDiscDispatch
cmp #0
bne iserr ; open failed!
bra part2
notfirst anop
* should check here for exclusive access bit. If set, then the
* open call will fail (before we change any counts)
lda ttyn
jsl checkExclTTY
cpy #0
beq not_excl
lda #$50
bra iserr99 ; do NOT DecRefNum - we never inc'd it
iserr pha
pei (ttyn)
pea FDtty
jsl DecRefnum clean up after ourselves
pla
iserr99 jmp GSOSReturn ; the file is already open!
not_excl pei (ttyn)
pea FDtty
jsl IncRefnum ; tell 'em we're here to party!
part2 anop ; no errors-
pea 0
tdc
clc
adc #fd
pha ; push address of 'fd' (dp)
jsl allocFD
sta fdPtr
stx fdPtr+2
ora fdPtr+2
bne noerror9
lda #$42
bra iserr ; exit with error & cleanup
noerror9 anop
; re-dereference files since allocFD can modify it
ldy #openFiles-CKernData ; copy the handle of the prefix rec
lda [procEnt],y ; out of the process table
sta files ; we dereference it later
iny2
lda [procEnt],y
sta files+2
ldy #FDrefNum
lda ttyn
sta [fdPtr],y ; store device number
ldy #FDrefType
lda #FDtty
sta [fdPtr],y ; and file descriptor type
ldy #FDTLevel
lda [files],y ; and the file level
ldy #FDrefLevel
sta [fdPtr],y
lda #0
ldy #FDrefFlags ; no flags for TTYs yet!
sta [fdPtr],y
ldy #FDNLenableMask ; make sure newline mode is off
sta [fdPtr],y
ldy #FDTCount
lda [files],y
inc a
sta [files],y
lda fd ; retreive the fd number and
ldy #2 ; return it in the pBlock
sta [pBlock],y
lda [pBlock]
cmp #5
bcc ttybyebye
ldy #8
lda [pBlock],y
bne storeAccess
lda #3
storeAccess ldy #12
sta [pBlock],y
ttybyebye lda #0
jmp GSOSReturn
dolevel dc i2'2'
dc i2'0'
dc i2'0'
END
GNOSetLevel START
using KernelStruct
files equ 10
ldy #openFiles-CKernData ; copy the handle of the prefix rec
lda [procEnt],y ; out of the process table
sta files ; we dereference it later
iny2
lda [procEnt],y
sta files+2
lda [pBlock]
cmp #1
beq okay
cmp #2
beq okay1
lda #$04
bra error
okay anop
pea $8000 ; default to 'user' mode
bra okay2
okay1 anop
ldy #4 ; use the mode they passed us
lda [pBlock],y
and #$8000
pha
okay2 lda 1,s
bit #$8000
beq okay3
ldy #2
lda [pBlock],y
bit #$8000
beq okay3
pla
lda #$59
jmp GSOSReturn
okay3 ldy #2
lda [pBlock],y
ldy #FDTLevel
sta [files],y
pla
ldy #2 ; calculate the real file level
eor [pBlock],y
and #$8000
ldy #FDTLevelMode
sta [files],y
lda #0
error jmp GSOSReturn
END
GNOGetLevel START
using KernelStruct
files equ 10
ldy #openFiles-CKernData ; copy the handle of the prefix rec
lda [procEnt],y ; out of the process table
sta files ; we dereference it later
iny2
lda [procEnt],y
sta files+2
lda [pBlock]
cmp #1
beq okay
cmp #2
beq okay1
lda #$04
bra error
okay anop
pea $8000
bra okay2
okay1 anop
ldy #4
lda [pBlock],y ; levelmode is an input
and #$8000
pha
okay2 ldy #FDTLevel
lda [files],y
ldy #FDTLevelMode
ora [files],y
eor 1,s
ldy #2
sta [pBlock],y
pla
lda #0
error jmp GSOSReturn
END
GNOExpandPath START ; not to be confused with gno_EP
gep_flags equ 10
outPath equ 12
pathName equ 16
in_ind equ 20
out_ind equ 22
lda #0
sta gep_flags
lda [pBlock]
cmp #2
bcs okay
lda #4
jmp GSOSReturn
okay anop
beq okay1
ldy #$0A
lda [pBlock],y
sta gep_flags
okay1 anop
ldy #6
lda [pBlock],y
sta outPath
iny2
lda [pBlock],y
sta outPath+2
pea 1
pea $0000 ; prefix 0
ldy #4 ; push the old pathname ptr
lda [pBlock],y
pha
dey
dey
lda [pBlock],y ; on the stack and call C expandpath
pha
jsl gno_ExpandPath ; ha!
cpx #$FFFF
bne noerr
jmp GSOSReturn
noerr anop
sta pathName
stx pathName+2
ldy #6
lda [pBlock],y
sta outPath
iny2
lda [pBlock],y
sta outPath+2
lda [pathName]
clc
adc #4
cmp [outPath]
beq okay2
bcc okay2
ldy #2
sta [outPath],y
lda #$4F
jmp GSOSReturn
okay2 anop
lda [pathName]
ldy #2
sta [outPath],y
tax ; count down with X reg
beq noCopy
sty in_ind
lda #4
sta out_ind
short m
loop anop
ldy in_ind
lda [pathName],y
bit gep_flags+1 ; hi bit into 'N' preg bit
bpl noupper
cmp #'a'
bcc noupper
cmp #'z'+1
bcs noupper
sec
sbc #'a'-'A'
noupper anop
ldy out_ind
sta [outPath],y
long m
inc in_ind
inc out_ind
short m
dex
bne loop
noCopy anop
long m
lda #0
jmp GSOSReturn
END
GNOQuit START
using KernelStruct
ldx curProcInd
lda flags,x
ora #%00001000 ; FL_NORMTERM
sta flags,x
lda [pBlock]
cmp #2
bcs doFlags
pea 0
bra noFlags
doFlags ldy #6
lda [pBlock],y
pha
noFlags lda [pBlock]
cmp #1
bcs doPname
pea 0
pea 0
bra noPname
doPname ldy #4
lda [pBlock],y
pha
ldy #2
lda [pBlock],y
pha
ora 3,s
beq noPname
jsl gs2cstr
phx
pha ; push the coverted pathname
noPname anop
jsl CommonQuit
jmp GSOSReturn ; only returns on error
END
* Flush 2015 +2
* GetDirEntry 201C +2
* GetEOF 2019 +2 tty,pipe
* GetMark 2017 +2 tty,pipe
* GetRefInfo 2039 +2
* SetEOF 2018 +2 tty,pipe
* SetMark 2016 +2 tty,pipe
getFDptr START
using KernelStruct
files equ 0
subroutine (2:rn),4
lda rn
cmp #32 ; max # of open files
bcs invalidRN
ldx curProcInd
lda openFiles,x
sta files
lda openFiles+2,x
sta files+2
lda rn
asl a
asl a
asl a
asl a
sec
sbc #FDsize-FDTTable
clc
adc files
sta files
lda files+2
adc #0
sta files+2
goaway return 4:files
invalidRN stz files
stz files+2
bra goaway
END
mapRN START
using KernelStruct
files equ 0
retval equ 4
subroutine (2:rn),6
lda rn
cmp #32
bcs invalidRN
ldx curProcInd
lda openFiles,x
sta files
lda openFiles+2,x
sta files+2
lda rn
asl a
asl a
asl a
asl a
sec
sbc #FDsize-FDTTable
tay
lda [files],y
sta retval
goaway return 2:retval
invalidRN stz retval
bra goaway
END
* search the specified file descriptor table for the physical
* refnum specified. Returns 0 if the file wasn't found, or
* returns the refnum (index into table)
SearchFDTable START
rn equ 0
subroutine (4:fdptr,2:refnum),2
lda #0
sta rn
loop asl a
asl a
asl a
asl a
clc
adc #FDTTable ; don't forget the 6 bytes on top
tay
lda [fdptr],y
cmp refnum
bne nxt
iny
iny
lda [fdptr],y
cmp #FDgsos
beq gotit
nxt inc rn
lda rn
cmp #32
bcc loop
stz rn ; search failed, return 0
bra byebye
gotit inc rn ; rn + 1 is actual refnum
byebye return 2:rn
END
GNOGetRefInfo START
oldRN equ 10
fdPtr equ 12
ldy #2
lda [pBlock],y
beq badRef ; refnum 0 is BAD
sta oldRN
pha
jsl getFDptr
sta fdPtr
stx fdPtr+2
ora fdPtr+2
beq badRef
lda [fdPtr]
cmp #0
bne okay
badRef lda #$43
jmp GSOSReturn
okay anop
ldy #FDrefType
lda [fdPtr],y
cmp #FDgsos
beq typeOkay
cmp #FDpipe
beq notGSOS
ldy #FDrefNum
lda [fdPtr],y
dec a
asl a
asl a
tax
lda #3
ldy #4
sta [pBlock],y
lda [pBlock]
cmp #3
bcc gohome
lda >DeviceNames+2,x
pha
lda >DeviceNames,x
pha
ldy #8
lda [pBlock],y
pha
ldy #6
lda [pBlock],y
pha
jsl copygs2res
gohome lda #0
jmp GSOSReturn ; basically ignore the call. no harm
typeOkay lda [fdPtr]
ldy #2
sta [pBlock],y
ph4 pBlock
ph2 cmdNum
jsl OldGSOSSt
pha
lda oldRN
ldy #2
sta [pBlock],y
pla
jmp GSOSReturn
notGSOS lda #$58
jmp GSOSReturn
END
GNORefCommon START
oldRN equ 10
fdPtr equ 12
ldy #2
lda [pBlock],y
sta oldRN
pha
bne notzero
lda cmdNum
cmp #$2015
jeq FlushSpecial
pla
lda #$43
jmp GSOSReturn
notzero jsl getFDptr
sta fdPtr
stx fdPtr+2
lda [fdPtr]
cmp #0
bne okay
lda #$43
jmp GSOSReturn
okay anop
ldy #FDrefType
lda [fdPtr],y
cmp #FDgsos
beq typeOkay
jmp notGSOS
cmp #FDpipe
bne notGSOS
lda #0
jmp GSOSReturn ; basically ignore the call. no harm
typeOkay lda [fdPtr]
ldy #2
sta [pBlock],y
ph4 pBlock
ph2 cmdNum
jsl OldGSOSSt
pha
lda oldRN
ldy #2
sta [pBlock],y
pla
jmp GSOSReturn
notGSOS lda #$58
jmp GSOSReturn
* Special case this: Flush() is the only routine here which can accept
* zero as a legal refnum; it should flush all open files, and we pass
* the call _unmodified_ into GS/OS for this reason.
FlushSpecial anop
pla
ph4 pBlock
ph2 cmdNum
jsl OldGSOSSt
jmp GSOSReturn
END
GNONewLine START
oldRN equ 10
fdrec equ 12
trueRN equ 16
ldy #2
lda [pBlock],y
sta oldRN
pha
jsl getFDptr
sta fdrec
stx fdrec+2
ora fdrec+2
beq badRef ; bad refnum
ldy #FDrefNum
lda [fdrec],y
cmp #0
bne okay
badRef lda #$43
jmp GSOSReturn
okay anop
sta trueRN
ldy #FDrefType
lda [fdrec],y
cmp #FDgsos
bne nlPipe
lda trueRN
ldy #2
sta [pBlock],y
ph4 pBlock
ph2 cmdNum
jsl OldGSOSSt
pha
lda oldRN
ldy #2
sta [pBlock],y
pla
jmp GSOSReturn
nlPipe ldy #4
lda [pBlock],y
ldy #FDNLenableMask
sta [fdrec],y
beq noerror
ldy #6
lda [pBlock],y
ldy #FDNLnumChars
sta [fdrec],y
cmp #1
bcc doerror
cmp #256+1
bcs doerror
ldy #8
lda [pBlock],y
tax
iny2
lda [pBlock],y
ldy #FDNLtable+2
sta [fdrec],y
dey2
txa
sta [fdrec],y
ldy #FDrefFlags
lda [fdrec],y
and #%1111111111110111 ; ~rfP16NEWL
sta [fdrec],y
noerror lda #0
jmp GSOSReturn
doerror ldy #FDNLenableMask
lda #0
sta [fdrec],y
lda #$53
jmp GSOSReturn
END
GNORdWr START
using KernelStruct
files equ 10
fdrec equ 14
rn equ 18
ldx curProcInd
lda openFiles,x
sta files
lda openFiles+2,x
sta files+2
ldy #2
lda [pBlock],y
pha
sta rn
jsl getFDptr
sta fdrec
stx fdrec+2
ora fdrec+2
bne refIsOk
lda #$43
jmp GSOSReturn
refIsOk ldy #FDrefType
lda [fdrec],y
asl a
tax
jmp (rdwrtable,X)
rdwrtable dc i2'doGSOS'
dc i2'doPipe'
dc i2'doTTY'
dc i2'doSocket'
*******************
doGSOS anop
ldy #FDrefNum
lda [fdrec],y
ldy #2
sta [pBlock],y
ph4 pBlock
ph2 cmdNum
jsl OldGSOSSt
pha
ldy #2
lda rn
sta [pBlock],y
pla
jmp GSOSReturn
*******************
doPipe anop
jsl decBusy
; ph4 (pBlock)+2
lda pBlock
clc
adc #2
tay
lda pBlock+2
adc #0
pha
phy
ldy #FDrefNum
lda [fdrec],y
pha
lda cmdNum
cmp #$2012
beq pread
jsl pipeHiWrite
bra goback
pread ph4 fdrec ; we need this for newline
jsl pipeHiRead
goback anop
jsl incBusy
jmp GSOSReturn
*******************
doTTY anop
jsl decBusy
ldy #8
lda [pBlock],y
pha
ldy #6
lda [pBlock],y
pha
ldy #4
lda [pBlock],y
pha
lda cmdNum
cmp #$2012
beq tread
ldy #FDrefNum ; tty devId number
lda [fdrec],y
dec a
pha
ldy #t_write
jsl LineDiscDispatch
bra goaway2
tread ldy #FDrefNum ; the tty device ID number
lda [fdrec],y
dec a
pha
ldy #t_read
jsl LineDiscDispatch
goaway2 anop
phx
ldy #12
sta [pBlock],y ; to provide a way for TTYs to
lda #0 ; return EOF properly
ldy #14
sta [pBlock],y
jsl incBusy
pla
jmp GSOSReturn
*******************
doSocket anop
ldy #FDrefNum
lda [fdrec],y
pha
ph2 cmdNum
; ph4 pBlock
pei (pBlock+2)
lda pBlock
inc a
inc a
pha
jsl SOCKrdwr
jmp GSOSReturn
END
PGClose START
using KernelStruct
rn equ 10
files equ 12
fdptr equ 16
errno equ 20
cnt equ 22
level equ 24
stz errno
ldy #openFiles-CKernData ; get the address of the fd table
lda [procEnt],y
sta files
iny2
lda [procEnt],y
sta files+2
ldy #0
lda cmdNum
cmp #$0014 ; P16 refNum is at offset 0
beq whichOS
lda [pBlock]
cmp #1
beq pCountOkay
lda #$04
jmp GSOSReturn
pCountOkay ldy #2 ; GSOS refNum is at offset 2
whichOS lda [pBlock],y
sta rn
beq doClose0
pha
jsl getFDptr
stx fdptr+2
sta fdptr
ora fdptr+2
beq refIsBad
ph4 fdptr
jsl subClose
cmp #$43
beq dontdecr
pha
lda [files] ; decr the # of open files
dec a
sta [files]
pla
dontdecr jmp GSOSReturn
refIsBad lda #$43
jmp GSOSReturn
doClose0 anop
lda files
clc
adc #FDTTable
sta fdptr
lda files+2
adc #0
sta fdptr+2
ldy #FDTLevel ; calculate the actual
lda [files],y ; system level from the
ldy #FDTLevelMode ; user level setting
ora [files],y ; and the levelMode
sta level
lda [files] ; number of entries
sta cnt
loop anop
lda cnt
beq doneClose0
lda [fdptr] ; zero refNum means empty entry
beq nextEntry
; ldy #FDTLevel ; handle 'internal' file levels
; lda [files],y ; like System 6
; ldy #FDTLevelMode
; ora [files],y
; ldy #FDrefLevel
; cmp [fdptr],y
; bcs noclose
lda level ; our calculated level
ldy #FDTLevel
cmp [files],y ; 'global' file level
bcc noclose
ph4 fdptr
jsl subClose
cmp #0
beq noerror
sta errno
noerror anop
lda [files] ; decr the # of open files
dec a
sta [files]
noclose dec cnt
nextEntry lda fdptr
clc
adc #FDsize
sta fdptr
lda fdptr+2
adc #0
sta fdptr+2
bra loop
doneClose0 lda errno
jmp GSOSReturn
END
subClose START
CLpCount equ 0
CLrefNum equ 2
err equ 4
subroutine (4:fdptr),6
stz err
ldy #FDrefNum
lda [fdptr],y
bne validRN
lda #$43
sta err
jmp errorRet
validRN anop
ldy #FDrefType
lda [fdptr],y
asl a
tax
jmp (closetable,X)
closetable dc i2'subGSOS'
dc i2'subPipe'
dc i2'subTTY'
dc i2'subSocket'
*******************
subSocket anop
ldy #FDrefNum
lda [fdptr],y
pha
pea FDsocket
jsl DecRefnum
cmp #0 ; there are still more references
bne subSock1 ; to this file, don't close it!
ldy #FDrefNum
lda [fdptr],y
pha
jsl SOCKclose
sta err
subSock1 jmp goaway
*******************
subGSOS anop
ldy #FDrefNum
lda [fdptr],y
sta CLrefNum
pha
lda #1
sta CLpCount
pea FDgsos ; we know refType == gsos
jsl DecRefnum
cmp #0 ; there are still more references
bne goaway ; to this file, don't close it!
pea $0000 ; stack is always in bank 0!
phd
pea $2014 ; command number
jsl OldGSOSSt
sta err
jmp goaway
*******************
subPipe anop
ldy #FDrefNum
lda [fdptr],y
pha
ldy #FDrefFlags
lda [fdptr],y
pha
jsl decPipe
ldy #FDrefNum
lda [fdptr],y
pha
pea FDpipe
jsl DecRefnum
cmp #0
bne goaway
ldy #FDrefNum
lda [fdptr],y
pha
jsl disposePipe
goaway anop
lda #0
ldy #FDrefNum
sta [fdptr],y
ldy #FDrefType
sta [fdptr],y
errorRet anop
return 2:err
*******************
subTTY anop
ldy #FDrefNum
lda [fdptr],y
pha
pea FDtty
jsl DecRefnum
cmp #0
bne goaway
* Now, adjust the process group the terminal was in
ldy #FDrefNum
lda [fdptr],y
dec a
asl a
tax
lda ttyStruct,x
beq nopgrp ; no pgrp was set
dec a ; adjust, since pgrps start at
dec a ; number 2
asl a
tay
lda #0 ; zero the pgrp
sta ttyStruct,x
tyx
lda pgrpInfo,x ; decrement the pgrp count
dec a
sta pgrpInfo,x
nopgrp ldy #FDrefNum
lda [fdptr],y
dec a
pha
ldy #t_close ; shutdown the device driver
jsl LineDiscDispatch
bra goaway
END
GNOGetName START
using KernelStruct
pathptr equ 10
resptr equ 14
outind equ 18
inind equ 20
pathlen equ 22
* Note that forked processes will get the name of their parent
lda [pBlock]
beq pcerr
cmp #3
bcs pcerr
bra goaround
pcerr lda #4
jmp GSOSReturn
goaround anop
ldy #4
lda [pBlock],y
sta resptr+2
ldy #2
lda [pBlock],y
sta resptr
ldx curProcInd ; get the full pathname of
lda procUserID,x ; the process.
pha
pha ; space for tool call. ARGH!!!
pha
pea $1
_LGetPathname2
pl4 pathptr
lda [pathptr]
inc a
sta pathlen
tay
short m
loop lda [pathptr],y
cmp #':'
beq gotfname
dey
bra loop
gotfname long m
iny
sty inind
lda [pathptr] ; get length
sec
sbc inind ; length of filename
clc
adc #2 ; minus the length word
cmp [resptr] ; length of buffer?
beq okay ; <= is okay
bcs buffer2small
okay anop
ldy #2
sta [resptr],y ; store length of filename
ldy #4
sty outind
short m
cploop ldy inind
lda [pathptr],y
ldy outind
sta [resptr],y
ldy inind
cpy pathlen
bcs donecopy
long m
inc inind
inc outind
short m
bra cploop
donecopy long m
lda [pBlock]
cmp #1
beq done
ldx curProcInd
lda procUserID,x
ldy #6
sta [pBlock],y
done lda #0
jmp GSOSReturn
buffer2small ldy #2
sta [resptr],y
lda #$4F
jmp GSOSReturn ; buffer too small error
END
GNOGetStdRefNum START
lda [pBlock]
cmp #2
beq PCokay
lda #4
jmp GSOSReturn
PCokay ldy #2
lda [pBlock],y
cmp #10
bcc pfxerr
cmp #13
bcs pfxerr
sec
sbc #9
ldy #4
sta [pBlock],y
lda #0
jmp GSOSReturn
pfxerr lda #$53
jmp GSOSReturn
END