mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-11-18 19:09:31 +00:00
6269a8ca25
Fixed several mutual exclusion problems, including a particularly nasty one that would cause gsh to loop forever inside the memory manager. (You could identify this one by the "BRA (-23)" at the bottom of the infinite loop.) Fixed the string vector print routine to properly handle all numbers of entries in the hash table. Previously, it would always print duplicate entries if there were < 6 commands hashed, and would sometimes print duplicates (depending on previous contents of an internal table) for other numbers of commands. gsh would wait on background processes started from an exec file (executed, not sourced). Now the exec file does not wait on the process, but the background process is not associated with the parent shell after the exec file terminates. Made gsh globbing work more like csh: if none of the requested patterns are found, print "No match" and exit. At startup, if /etc/glogin, $HOME/glogin, or $HOME/gshrc does not exist, don't report a "file not found" error message. (PR#100)
1970 lines
33 KiB
NASM
1970 lines
33 KiB
NASM
************************************************************************
|
|
*
|
|
* The GNO Shell Project
|
|
*
|
|
* Developed by:
|
|
* Jawaid Bazyar
|
|
* Tim Meekins
|
|
*
|
|
* $Id: builtin.asm,v 1.9 1998/12/31 18:29:11 tribby Exp $
|
|
*
|
|
**************************************************************************
|
|
*
|
|
* BUILTIN.ASM
|
|
* By Tim Meekins
|
|
* Modified by Dave Tribby for GNO 2.0.6
|
|
*
|
|
* Builtin command searching and execution.
|
|
*
|
|
* Note: text set up for tabs at col 16, 22, 41, 49, 57, 65
|
|
* | | | | | |
|
|
* ^ ^ ^ ^ ^ ^
|
|
**************************************************************************
|
|
*
|
|
* Interfaces defined in this file:
|
|
*
|
|
* builtin subroutine (2:argc,4:argv)
|
|
* Returns completion status in Accumulator
|
|
*
|
|
* IsBuiltin subroutine (4:name)
|
|
* return 2:tbl
|
|
*
|
|
* Remainder are interfaces to builtin commands with interface
|
|
* subroutine (4:argv,2:argc)
|
|
* returns status in accumulator
|
|
* cd (chdir is entry as an alternate name)
|
|
* clear
|
|
* echo
|
|
* pwd
|
|
* which
|
|
* prefix
|
|
* rehash (unhash is entry as an alternate name)
|
|
* exit
|
|
* setdebug
|
|
* psbi (command name is "ps")
|
|
* hashbi (command name is "hash")
|
|
* source
|
|
* cmdbi (command name is "commands")
|
|
*
|
|
**************************************************************************
|
|
|
|
mcopy /obj/gno/bin/gsh/builtin.mac
|
|
|
|
dummybuiltin start ; ends up in .root
|
|
end
|
|
|
|
setcom 60
|
|
|
|
p_next gequ 0 ;next in global proclist
|
|
p_friends gequ p_next+4 ;next in job list
|
|
p_flags gequ p_friends+4 ;various job status flags
|
|
p_reason gequ p_flags+2 ;reason for entering this state
|
|
p_index gequ p_reason+2 ;job index
|
|
p_pid gequ p_index+2 ;process id
|
|
p_jobid gequ p_pid+2 ;process id of job leader
|
|
p_command gequ p_jobid+2 ;command (how job invoked)
|
|
p_space gequ p_command+4 ;space for structure
|
|
|
|
**************************************************************************
|
|
*
|
|
* Find and execute a builtin command
|
|
*
|
|
**************************************************************************
|
|
|
|
builtin START
|
|
|
|
using BuiltinData
|
|
|
|
val equ 1
|
|
file equ val+2
|
|
tbl equ file+4
|
|
space equ tbl+4
|
|
argv equ space+3
|
|
argc equ argv+4
|
|
end equ argc+2
|
|
|
|
; subroutine (2:argc,4:argv),space
|
|
|
|
tsc
|
|
sec
|
|
sbc #space-1
|
|
tcs
|
|
phd
|
|
tcd
|
|
|
|
ldy #2
|
|
lda [argv]
|
|
sta file
|
|
lda [argv],y
|
|
sta file+2
|
|
ld4 builtintbl,tbl
|
|
ld2 -1,val
|
|
lda argc
|
|
beq done
|
|
|
|
loop ldy #2
|
|
lda [tbl]
|
|
ora [tbl],y
|
|
beq done
|
|
lda [tbl],y
|
|
pha
|
|
lda [tbl]
|
|
pha
|
|
pei (file+2)
|
|
pei (file)
|
|
jsr cmpcstr
|
|
beq foundit
|
|
bpl done
|
|
add2 tbl,#10,tbl
|
|
bra loop
|
|
;
|
|
; Found the command handler address. Since we don't have a "jsl [tbl],y"
|
|
; instruction, after pushing parameters on the stack we will push the
|
|
; return address, then the command's address - 1 (2 bytes only, since it's
|
|
; in the current bank). An rts will take us to the command handler, and a
|
|
; rtl at the end of the handler will bring us back.
|
|
;
|
|
foundit anop
|
|
pei (argv+2) Push parameters (3 words)
|
|
pei (argv)
|
|
pei (argc)
|
|
phk Push return address (high byte)
|
|
per return-1 Push return address (low bytes)
|
|
ldy #4 Get address of builtin handler
|
|
lda [tbl],y (16 bytes; assume in this bank)
|
|
dec a subtract 1 so rts will take us there
|
|
pha
|
|
rts Go to builtin handler routine.
|
|
;
|
|
; Return from handler to this location
|
|
;
|
|
return sta val Save return status.
|
|
|
|
;
|
|
; Free the argv array
|
|
;
|
|
ph4 #0 (no path)
|
|
pei (argc)
|
|
pei (argv+2)
|
|
pei (argv)
|
|
jsl argfree
|
|
|
|
done ldy val Y-reg = return value.
|
|
|
|
lda space
|
|
sta end-3
|
|
lda space+1
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
clc
|
|
adc #end-4
|
|
tcs
|
|
|
|
tya Accumulator = return value.
|
|
|
|
rtl
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* Is it a built-in?
|
|
*
|
|
* Return value is: -1 if not a built-in, 0 if forked built-in,
|
|
* 1 if non-forked built-in.
|
|
*
|
|
**************************************************************************
|
|
|
|
IsBuiltin START
|
|
|
|
using BuiltinData
|
|
|
|
tbl equ 0
|
|
space equ tbl+4
|
|
|
|
subroutine (4:name),space
|
|
|
|
ld4 builtintbl,tbl
|
|
builtinloop ldy #2
|
|
lda [tbl]
|
|
ora [tbl],y
|
|
beq nofile
|
|
lda [tbl],y
|
|
pha
|
|
lda [tbl]
|
|
pha
|
|
pei (name+2)
|
|
pei (name)
|
|
jsr cmpcstr
|
|
beq foundit
|
|
bpl nofile
|
|
add2 tbl,#10,tbl
|
|
bra builtinloop
|
|
foundit ldy #8 Get the fork/nofork flag
|
|
lda [tbl],y and use it as return value.
|
|
bra foundbuiltin
|
|
|
|
nofile lda #-1 Set not-found return value.
|
|
foundbuiltin sta tbl
|
|
|
|
return 2:tbl
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* Builtin data
|
|
*
|
|
**************************************************************************
|
|
|
|
BuiltinData DATA
|
|
;
|
|
; First address is a pointer to the name, the second is a pointer to the
|
|
; command. Third value is fork flag (0 to fork, 1 for no fork).
|
|
; TABLE MUST BE SORTED BY COMMAND NAME.
|
|
;
|
|
builtintbl dc a4'aliasname,alias',i2'0'
|
|
dc a4'bgname,bg',i2'1'
|
|
dc a4'bindkeyname,bindkey',i2'0'
|
|
dc a4'cdname,cd',i2'1'
|
|
dc a4'chdirname,chdir',i2'1'
|
|
dc a4'clearname,clear',i2'1' Changed to unforked
|
|
dc a4'cmdname,cmdbi',i2'0'
|
|
dc a4'dirsname,dirs',i2'0'
|
|
dc a4'echoname,echo',i2'0'
|
|
dc a4'editname,edit',i2'1'
|
|
dc a4'exitname,exit',i2'1'
|
|
dc a4'exportname,export',i2'1'
|
|
dc a4'fgname,fg',i2'1'
|
|
dc a4'hashname,hashbi',i2'0'
|
|
dc a4'hname,PrintHistory',i2'0'
|
|
dc a4'jobsname,jobs',i2'1'
|
|
dc a4'killname,kill',i2'1'
|
|
dc a4'popdname,popd',i2'1'
|
|
dc a4'pfxname,prefix',i2'1'
|
|
dc a4'psname,psbi',i2'0'
|
|
dc a4'pushdname,pushd',i2'1'
|
|
dc a4'pwdname,pwd',i2'1'
|
|
dc a4'rehashname,rehash',i2'1'
|
|
dc a4'setname,set',i2'0'
|
|
dc a4'setbugname,setdebug',i2'0'
|
|
dc a4'setenvname,setenv',i2'0'
|
|
dc a4'sourcename,source',i2'1' Changed to unforked
|
|
dc a4'stopname,stop',i2'1'
|
|
dc a4'tsetname,tset',i2'1'
|
|
dc a4'unaliasname,unalias',i2'1'
|
|
dc a4'unhashname,unhash',i2'1'
|
|
dc a4'unsetname,unset',i2'1'
|
|
dc a4'whichname,which',i2'0'
|
|
dc i4'0,0'
|
|
|
|
aliasname dc c'alias',h'00'
|
|
bgname dc c'bg',h'00'
|
|
bindkeyname dc c'bindkey',h'00'
|
|
chdirname dc c'chdir',h'00'
|
|
cdname dc c'cd',h'00'
|
|
clearname dc c'clear',h'00'
|
|
cmdname dc c'commands',h'00'
|
|
dirsname dc c'dirs',h'00'
|
|
echoname dc c'echo',h'00'
|
|
editname dc c'edit',h'00'
|
|
exitname dc c'exit',h'00'
|
|
exportname dc c'export',h'00'
|
|
fgname dc c'fg',h'00'
|
|
hashname dc c'hash',h'00'
|
|
hname dc c'history',h'00'
|
|
jobsname dc c'jobs',h'00'
|
|
killname dc c'kill',h'00'
|
|
pfxname dc c'prefix',h'00'
|
|
popdname dc c'popd',h'00'
|
|
psname dc c'ps',h'00'
|
|
pushdname dc c'pushd',h'00'
|
|
pwdname dc c'pwd',h'00'
|
|
rehashname dc c'rehash',h'00'
|
|
setbugname dc c'setdebug',h'00'
|
|
setname dc c'set',h'00'
|
|
setenvname dc c'setenv',h'00'
|
|
sourcename dc c'source',h'00'
|
|
stopname dc c'stop',h'00'
|
|
tsetname dc c'tset',h'00'
|
|
unaliasname dc c'unalias',h'00'
|
|
unhashname dc c'unhash',h'00'
|
|
unsetname dc c'unset',h'00'
|
|
whichname dc c'which',h'00'
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* CD: builtin command
|
|
* syntax: cd [pathname]
|
|
*
|
|
* Changes the current prefix to pathname. If no pathname then set to $HOME
|
|
*
|
|
**************************************************************************
|
|
|
|
cd START
|
|
chdir ENTRY
|
|
|
|
dpg equ 1 Direct page pointer.
|
|
buf equ dpg+4 Buffer address to be freed.
|
|
status equ buf+4 Status returned from command.
|
|
space equ status+2
|
|
argc equ space+3
|
|
argv equ argc+2
|
|
end equ argv+4
|
|
|
|
; subroutine (4:argv,2:argc),space
|
|
|
|
tsc
|
|
sec
|
|
sbc #space-1
|
|
tcs
|
|
phd
|
|
tcd
|
|
|
|
lock cdmutex
|
|
|
|
stz buf Clear the pointer to
|
|
stz buf+2 allocated buffer.
|
|
|
|
stz status Assume good status.
|
|
|
|
lda argc Number of parameters
|
|
dec a determines type of cd...
|
|
beq cdhome either to $HOME
|
|
dec a or to the directory
|
|
jeq paramcd on the command line.
|
|
|
|
;
|
|
; Illegal parameters: print usage string
|
|
;
|
|
showusage inc status Return status = 1.
|
|
lda [argv]
|
|
tax
|
|
ldy #2
|
|
lda [argv],y
|
|
stx argv
|
|
sta argv+2
|
|
lda [argv],y
|
|
and #$FF
|
|
beq cdusage
|
|
ldx #^Usage2 Print chdir usage
|
|
lda #Usage2
|
|
jsr errputs
|
|
jmp exit
|
|
cdusage ldx #^Usage Print cd usage
|
|
lda #Usage
|
|
jsr errputs
|
|
jmp exit
|
|
|
|
;
|
|
; Set prefix to $home
|
|
;
|
|
cdhome anop
|
|
ph4 #home Get value of $HOME
|
|
jsl getenv
|
|
sta buf If GS/OS result buffer
|
|
stx buf+2 wasn't allocated,
|
|
ora buf+2
|
|
jeq exit there's no more to do.
|
|
|
|
clc Calculate address
|
|
lda buf of GS/OS input string
|
|
adc #2 (2 bytes from start of
|
|
sta PRecPath result buffer).
|
|
sta GRecPath
|
|
lda buf+2
|
|
adc #0
|
|
sta PRecPath+2
|
|
sta GRecPath+2
|
|
|
|
bra getinfo
|
|
|
|
;
|
|
; Set prefix to path specified on command line
|
|
;
|
|
paramcd anop
|
|
|
|
ldy #4
|
|
lda [argv],y
|
|
sta dpg
|
|
iny2
|
|
lda [argv],y
|
|
sta dpg+2
|
|
|
|
lda [dpg]
|
|
and #$FF
|
|
if2 @a,ne,#'-',setprefix
|
|
jmp showusage
|
|
|
|
setprefix pei (dpg+2)
|
|
pei (dpg)
|
|
jsr c2gsstr
|
|
sta PRecPath
|
|
sta GRecPath
|
|
sta buf
|
|
stx PRecPath+2
|
|
stx GRecPath+2
|
|
stx buf+2
|
|
|
|
;
|
|
; Get file information to determine whether target is a valid directory
|
|
;
|
|
getinfo GetFileInfo GRec
|
|
bcc ok
|
|
ohshit sta ErrError
|
|
ErrorGS Err
|
|
inc status Return status = 1.
|
|
bra done
|
|
|
|
ok if2 GRecFT,eq,#$F,ok2
|
|
ldx dpg+2
|
|
lda dpg
|
|
jsr errputs
|
|
ldx #^direrr
|
|
lda #direrr
|
|
jsr errputs
|
|
inc status Return status = 1.
|
|
bra done
|
|
|
|
;
|
|
; Everything looks OK. Set prefix 0 to the indicated value
|
|
;
|
|
ok2 SetPrefix PRec
|
|
bcs ohshit
|
|
|
|
;
|
|
; Deallocate buffer (if necessary), unlock mutex, cleanup stack, and leave
|
|
;
|
|
done ph4 buf
|
|
jsl nullfree
|
|
|
|
exit unlock cdmutex
|
|
|
|
ldy status Put return status in Y-reg
|
|
|
|
lda space
|
|
sta end-3
|
|
lda space+1
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
clc
|
|
adc #end-4
|
|
tcs
|
|
|
|
tya Put return status in Accumulator.
|
|
|
|
rtl
|
|
|
|
cdmutex key Mutual exclusion key
|
|
|
|
; Parameter block for GS/OS SetPrefix call
|
|
PRec dc i'2' pCount
|
|
dc i'0' prefixNum (0 = current directory)
|
|
PRecPath ds 4 Pointer to input prefix path
|
|
|
|
; Parameter block for GS/OS GetFileInfo call
|
|
GRec dc i'3' pCount
|
|
GRecPath ds 4 Pointer to input pathname
|
|
GRecAcc ds 2 access (result)
|
|
GRecFT ds 2 fileType (result)
|
|
|
|
home gsstr 'home' Env variable name
|
|
|
|
; Parameter block for shell ErrorGS call (p 393 in ORCA/M manual)
|
|
Err dc i2'1' pCount
|
|
ErrError ds 2 Error number
|
|
|
|
Usage dc c'Usage: cd [pathname]',h'0d00'
|
|
Usage2 dc c'Usage: chdir [pathname]',h'0d00'
|
|
dirErr dc c': Not a directory',h'0d00'
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* CLEAR: builtin command
|
|
* syntax: clear
|
|
*
|
|
* clears the screen
|
|
*
|
|
**************************************************************************
|
|
|
|
clear START
|
|
|
|
space equ 1
|
|
argc equ space+3
|
|
argv equ argc+2
|
|
end equ argv+4
|
|
|
|
; subroutine (4:argv,2:argc),space
|
|
|
|
tsc
|
|
phd
|
|
tcd
|
|
|
|
lda argc
|
|
dec a
|
|
beq clearit
|
|
|
|
ldx #^Usage
|
|
lda #Usage
|
|
jsr errputs
|
|
ldy #1 Return status = 1.
|
|
bra exit
|
|
|
|
clearit jsr clearscrn
|
|
jsr flush
|
|
ldy #0 Return status = 0.
|
|
|
|
exit lda space
|
|
sta end-3
|
|
lda space+1
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
clc
|
|
adc #end-4
|
|
tcs
|
|
|
|
tya
|
|
|
|
rtl
|
|
|
|
Usage dc c'Usage: clear',h'0d00'
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* ECHO: builtin command
|
|
* syntax: echo [-n] [text][...]
|
|
*
|
|
* Echo displays to stdout what is on the command (except -n).
|
|
*
|
|
* If '-n' specified then don't print newline.
|
|
*
|
|
**************************************************************************
|
|
|
|
echo START
|
|
|
|
val equ 1
|
|
nl equ val+2 flag: was -n option set?
|
|
ptr equ nl+2
|
|
status equ ptr+4
|
|
space equ status+2
|
|
argc equ space+3
|
|
argv equ argc+2
|
|
end equ argv+4
|
|
|
|
; subroutine (4:argv,2:argc),space
|
|
|
|
* Add space on stack for local variables
|
|
|
|
tsc
|
|
sec
|
|
sbc #space-1
|
|
tcs
|
|
phd
|
|
tcd
|
|
|
|
stz status Clear return status.
|
|
stz nl Clear the -n flag.
|
|
dec argc Decrement argument counter.
|
|
jeq done Done if no more arguments.
|
|
|
|
ldy #4
|
|
lda [argv],y Set ptr to
|
|
sta ptr point to the
|
|
iny2 text of the
|
|
lda [argv],y first
|
|
sta ptr+2 argument.
|
|
ldy #1
|
|
lda [ptr] Get first
|
|
and #$FF character.
|
|
if2 @a,ne,#'-',loop If != '-', handle as regular param.
|
|
|
|
|
|
; First argument begins with "-"; only legal value is -n
|
|
|
|
lda [ptr],y Get second
|
|
and #$FF character.
|
|
if2 @a,eq,#'n',gotn If != 'n', it's a bad one.
|
|
|
|
showusage ldx #^Usage Incorrect parameter usage:
|
|
lda #Usage display the usage string.
|
|
jsr errputs
|
|
inc status Return status = 1.
|
|
jmp exit
|
|
|
|
gotn iny
|
|
lda [ptr],y Get third
|
|
and #$FF character.
|
|
bne showusage If != 0, it's a bad one.
|
|
inc nl Set the -n flag.
|
|
add2 argv,#4,argv Bump argument pointer.
|
|
dec argc Decrement argument counter.
|
|
jeq done Done if no more arguments.
|
|
|
|
;
|
|
; Beginning of main processing loop of echo parameters.
|
|
;
|
|
loop add2 argv,#4,argv Bump argument pointer.
|
|
ldy #2
|
|
lda [argv],y Set ptr to argv (next argument)
|
|
sta ptr+2
|
|
lda [argv]
|
|
sta ptr
|
|
putloop lda [ptr] Get first
|
|
and #$FF character.
|
|
cmp #0 If 0,
|
|
jeq doneput done with this argument.
|
|
cmp #'\' If != "\"
|
|
jne putit go save in print buffer.
|
|
incad ptr Escape character found; point
|
|
lda [ptr] to the next
|
|
and #$FF character.
|
|
beq doneput If 0, done with this argument.
|
|
if2 @a,ne,#'b',esc02 Check for escape codes: "b"
|
|
ldx #1
|
|
jsr moveleft moveleft
|
|
bra didit
|
|
esc02 if2 @a,ne,#'f',esc03 "f"
|
|
jsr clearscrn clearscreen
|
|
bra didit
|
|
esc03 if2 @a,ne,#'n',esc04 "n"
|
|
lda #13 print newline
|
|
bra putit
|
|
esc04 if2 @a,ne,#'r',esc05 "r"
|
|
lda #13 print newline
|
|
bra putit
|
|
esc05 if2 @a,ne,#'t',esc06 "t"
|
|
lda #9 print tab
|
|
bra putit
|
|
esc06 if2 @a,ne,#'0',putit "0"
|
|
stz val decode numeric value
|
|
ldy #1
|
|
escloop lda [ptr],y
|
|
and #$FF
|
|
beq putval
|
|
if2 @a,cc,#'0',putval
|
|
if2 @a,cs,#'9'+1,putval
|
|
sub2 @a,#'0',@a
|
|
pha
|
|
lda val
|
|
asl2 a
|
|
adc val
|
|
asl a
|
|
adc 1,s
|
|
sta val
|
|
pla
|
|
incad ptr
|
|
bra escloop
|
|
|
|
putval lda val Get numeric escape code.
|
|
|
|
putit jsr putchar Save character in accumulator.
|
|
didit incad ptr Point to next char in arg
|
|
jmp putloop and go process it.
|
|
|
|
doneput dec argc Decrement argument counter.
|
|
beq done Done if no more arguments.
|
|
bmi done (or if there were no arguments!)
|
|
lda #' ' Add a blank
|
|
jsr putchar between arguments.
|
|
jmp loop Get next argument.
|
|
|
|
done lda nl If "-n" flag isn't set,
|
|
bne exit
|
|
jsr newline add a newline.
|
|
|
|
exit jsr flush Print the buffer.
|
|
ldy status
|
|
|
|
* Clear parameters from stack and return from subroutine.
|
|
|
|
lda space
|
|
sta end-3
|
|
lda space+1
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
clc
|
|
adc #end-4
|
|
tcs
|
|
|
|
tya
|
|
|
|
rtl
|
|
|
|
Usage dc c'Usage: echo [-n] [strings...]',h'0d00'
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* PWD: builtin command
|
|
* syntax: pwd
|
|
*
|
|
* print the working directory.
|
|
*
|
|
**************************************************************************
|
|
|
|
pwd START
|
|
|
|
ptr equ 1
|
|
space equ ptr+4
|
|
argc equ space+3
|
|
argv equ argc+2
|
|
end equ argv+4
|
|
|
|
; subroutine (4:argv,2:argc),space
|
|
|
|
tsc
|
|
sec
|
|
sbc #space-1
|
|
tcs
|
|
phd
|
|
tcd
|
|
|
|
dec argc If an argument was provided,
|
|
beq wait
|
|
|
|
ldx #^Usage print the usage string.
|
|
lda #Usage
|
|
jsr errputs
|
|
ldy #1 Return status = 1.
|
|
bra exit
|
|
|
|
wait pea 0
|
|
jsl getpfxstr Get value of prefix 0.
|
|
sta ptr
|
|
stx ptr+2
|
|
|
|
ora ptr+2 If NULL pointer returned,
|
|
beq done an error was reported.
|
|
|
|
ldy #2 If length of returned
|
|
lda [ptr],y GS/OS string is 0,
|
|
beq freebuf an error was reported.
|
|
|
|
lda ptr X/A = address of
|
|
clc text (four bytes
|
|
adc #4 beyond start).
|
|
bcc doputs
|
|
inx
|
|
doputs jsr puts Print the c-string
|
|
jsr newline and add a newline.
|
|
|
|
freebuf ph4 ptr Free the buffer.
|
|
jsl nullfree
|
|
|
|
done ldy #0 Return status = 0.
|
|
|
|
exit lda space Deallocate stack space
|
|
sta end-3 and return to the caller.
|
|
lda space+1
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
clc
|
|
adc #end-4
|
|
tcs
|
|
|
|
tya Return status.
|
|
|
|
rtl
|
|
|
|
Usage dc c'Usage: pwd',h'0d00'
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* WHICH: builtin command
|
|
* syntax: which [command ...]
|
|
*
|
|
* displays the location of command
|
|
*
|
|
**************************************************************************
|
|
|
|
which START
|
|
|
|
using hashdata
|
|
|
|
ptr equ 1
|
|
sptr equ ptr+4
|
|
file equ sptr+4
|
|
status equ file+4
|
|
space equ status+2
|
|
argc equ space+3
|
|
argv equ argc+2
|
|
end equ argv+4
|
|
|
|
; subroutine (4:argv,2:argc),space
|
|
|
|
tsc
|
|
sec
|
|
sbc #space-1
|
|
tcs
|
|
phd
|
|
tcd
|
|
|
|
stz status Clear return status.
|
|
;
|
|
; Display usage if no argument
|
|
;
|
|
if2 argc,ge,#2,loop
|
|
ldx #^whicherr
|
|
lda #whicherr
|
|
jsr errputs
|
|
inc status Return status = 1
|
|
jmp exit
|
|
;
|
|
; loop through each argument
|
|
;
|
|
loop add2 argv,#4,argv
|
|
dec argc
|
|
jeq exit
|
|
|
|
lda [argv]
|
|
sta file
|
|
ldy #2
|
|
lda [argv],y
|
|
sta file+2
|
|
|
|
;
|
|
; see if it's an alias
|
|
;
|
|
pei (file+2)
|
|
pei (file)
|
|
jsl findalias
|
|
sta ptr
|
|
stx ptr+2
|
|
ora ptr+2
|
|
beq chkbuiltin
|
|
ldx #^aliasstr
|
|
lda #aliasstr
|
|
jsr puts
|
|
ldx ptr+2
|
|
lda ptr
|
|
jsr puts
|
|
jmp nextarg
|
|
;
|
|
; was it a built-in?
|
|
;
|
|
chkbuiltin pei (file+2)
|
|
pei (file)
|
|
jsl IsBuiltin
|
|
cmp #-1
|
|
beq tryhash
|
|
foundbuiltin ldx #^builtstr
|
|
lda #builtstr
|
|
jsr puts
|
|
jmp nextarg
|
|
;
|
|
; See if it was hashed
|
|
;
|
|
tryhash pei (file+2)
|
|
pei (file)
|
|
ph4 hash_table
|
|
ph4 #hash_paths
|
|
jsl search
|
|
cmp #0
|
|
bne foundhash
|
|
cpx #0
|
|
beq thispfx
|
|
;
|
|
; It was hashed, so say so.
|
|
;
|
|
foundhash sta sptr
|
|
stx sptr+2
|
|
jsr puts
|
|
pei (sptr+2) Free memory allocated
|
|
pei (sptr) by search to hold full path.
|
|
jsl nullfree
|
|
jmp nextarg
|
|
;
|
|
; It must be in the current prefix, so check it out.
|
|
;
|
|
thispfx lock whichmutex
|
|
;
|
|
; check for existence of file
|
|
;
|
|
pei (file+2)
|
|
pei (file)
|
|
jsr c2gsstr
|
|
sta GRecPath
|
|
stx GRecPath+2
|
|
sta ptr
|
|
stx ptr+2
|
|
|
|
GetFileInfo GRec
|
|
bcs nofile
|
|
;
|
|
; we found the file, so display the cwd
|
|
;
|
|
showcwd pei (ptr+2)
|
|
pei (ptr)
|
|
jsl nullfree
|
|
|
|
pea 0
|
|
jsl getpfxstr Get value of prefix 0.
|
|
sta ptr
|
|
stx ptr+2
|
|
|
|
ora ptr+2 If NULL pointer returned,
|
|
beq donecwd an error was reported.
|
|
|
|
ldy #2 If length of returned
|
|
lda [ptr],y GS/OS string is 0,
|
|
beq freebuf an error was reported.
|
|
|
|
lda ptr X/A = address of
|
|
clc text (four bytes
|
|
adc #4 beyond start).
|
|
bcc doputs
|
|
inx
|
|
doputs jsr puts Print the directory name.
|
|
|
|
ldx file+2 Print the file name.
|
|
lda file
|
|
jsr puts
|
|
|
|
freebuf ph4 ptr Free the buffer.
|
|
jsl nullfree
|
|
stz ptr
|
|
stz ptr+2
|
|
bra donecwd
|
|
;
|
|
; No such command
|
|
;
|
|
nofile ldx #^cantdoit
|
|
lda #cantdoit
|
|
jsr puts
|
|
donecwd unlock whichmutex
|
|
pei (ptr+2)
|
|
pei (ptr)
|
|
jsl nullfree
|
|
;
|
|
; Go try the next file.
|
|
;
|
|
nextarg jsr newline
|
|
jmp loop
|
|
|
|
exit ldy status
|
|
lda space
|
|
sta end-3
|
|
lda space+1
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
clc
|
|
adc #end-4
|
|
tcs
|
|
|
|
tya
|
|
|
|
rtl
|
|
|
|
whicherr dc c'Usage: which [file ...]',h'0d00'
|
|
builtstr dc c'Shell Built-in Command',h'00'
|
|
cantdoit dc c'Command Not Found',h'00'
|
|
aliasstr dc c'Aliased as ',h'00'
|
|
|
|
whichmutex key
|
|
|
|
GRec dc i'4'
|
|
GRecPath ds 4
|
|
ds 2
|
|
GRecFileType ds 2
|
|
GRecAuxType ds 4
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* PREFIX: builtin command
|
|
* syntax: prefix [num [prefix]]
|
|
*
|
|
* sets prefix number num to prefix or print list of all prefixes
|
|
*
|
|
**************************************************************************
|
|
|
|
prefix START
|
|
|
|
dir equ 1
|
|
numstr equ dir+4
|
|
pfxnum equ numstr+4
|
|
status equ pfxnum+2
|
|
space equ status+2
|
|
argc equ space+3
|
|
argv equ argc+2
|
|
end equ argv+4
|
|
|
|
; subroutine (4:argv,2:argc),space
|
|
|
|
tsc
|
|
sec
|
|
sbc #space-1
|
|
tcs
|
|
phd
|
|
tcd
|
|
|
|
lock prefixmutex
|
|
|
|
stz status Clear return status.
|
|
lda argc Get number of arguments.
|
|
dec a
|
|
beq showall If no parameters, show all prefixes.
|
|
dec a
|
|
jeq showone If one, show one.
|
|
dec a
|
|
jeq setprefix If two, set a prefix.
|
|
|
|
ldx #^usage
|
|
lda #usage
|
|
jsr errputs
|
|
jmp badstat
|
|
|
|
; -------------------------------------------------------------------
|
|
;
|
|
; No parameters provided: show all the prefixes
|
|
;
|
|
showall anop
|
|
lda #$FFFF
|
|
sta pfxnum First prefix # will be 0.
|
|
|
|
pha Get the boot volume string.
|
|
jsl getpfxstr
|
|
sta dir
|
|
stx dir+2
|
|
|
|
ora dir+2 If NULL pointer returned,
|
|
beq bumppfx an error was reported.
|
|
|
|
ldx #^bootstr
|
|
lda #bootstr
|
|
bra printid Jump into the loop
|
|
|
|
allloop lda pfxnum
|
|
pha
|
|
jsl getpfxstr
|
|
sta dir
|
|
stx dir+2
|
|
|
|
ora dir+2 If NULL pointer returned,
|
|
beq bumppfx an error was reported.
|
|
|
|
ldy #2 Get length word.
|
|
lda [dir],y
|
|
beq nextall If zero, do the next prefix.
|
|
Int2Dec (pfxnum,#pfxstr,#2,#0)
|
|
ldx #^pfxstr
|
|
lda #pfxstr
|
|
printid jsr puts
|
|
ldx dir+2
|
|
lda dir X/A = address of
|
|
clc text (four bytes
|
|
adc #4 beyond start).
|
|
bcc doputs2
|
|
inx
|
|
doputs2 jsr puts Print the directory name
|
|
jsr newline
|
|
|
|
nextall ph4 dir Free the GS/OS result buffer
|
|
jsl nullfree allocated for pathname.
|
|
bumppfx inc pfxnum Bump the prefix number.
|
|
if2 pfxnum,cc,#32,allloop
|
|
jmp done
|
|
|
|
; -------------------------------------------------------------------
|
|
;
|
|
; One parameter provided: show a single prefix
|
|
;
|
|
showone ldy #1*4+2 Put pointer to
|
|
lda [argv],y first command
|
|
sta numstr+2 argument in
|
|
pha numstr, and
|
|
dey2 also on stack
|
|
lda [argv],y as parameter.
|
|
sta numstr
|
|
pha
|
|
jsr cstrlen Get length of argument.
|
|
tax
|
|
|
|
Dec2Int (numstr,@x,#0),@a Convert to integer.
|
|
cmp #32 If prefix num >= 32,
|
|
bcc getpfx
|
|
jsr newline just print blank line.
|
|
jmp done
|
|
|
|
getpfx pha Get that prefix value.
|
|
jsl getpfxstr
|
|
sta dir
|
|
stx dir+2
|
|
|
|
ora dir+2 If NULL pointer returned,
|
|
jeq done an error was reported.
|
|
|
|
Int2Dec (pfxnum,#pfxstr,#2,#0)
|
|
|
|
ldy #2 Get length word.
|
|
lda [dir],y
|
|
beq donewline If zero, just print newline.
|
|
ldx dir+2
|
|
lda dir X/A = address of
|
|
clc text (four bytes
|
|
adc #4 beyond start).
|
|
bcc doputs3
|
|
inx
|
|
doputs3 jsr puts Print the directory name
|
|
donewline jsr newline
|
|
ph4 dir Free the GS/OS result buffer
|
|
jsl nullfree allocated for pathname.
|
|
jmp done
|
|
|
|
; -------------------------------------------------------------------
|
|
;
|
|
; Two parameters provided: set a prefix
|
|
;
|
|
setprefix ldy #1*4+2 Put pointer to
|
|
lda [argv],y first command
|
|
sta numstr+2 argument (prefix
|
|
pha num) in numstr, and
|
|
dey2 also on stack
|
|
lda [argv],y as parameter.
|
|
sta numstr
|
|
pha
|
|
jsr cstrlen Get length of argument.
|
|
tax
|
|
|
|
Dec2Int (numstr,@x,#0),PRecNum Convert to integer string.
|
|
|
|
lda PRecNum
|
|
cmp #32 If prefix num >= 32,
|
|
bcs done nothing to do.
|
|
|
|
ldy #2*4+2 Put pointer to
|
|
lda [argv],y second command
|
|
pha argument (value)
|
|
dey2 on stack as parameter.
|
|
lda [argv],y
|
|
pha
|
|
jsr c2gsstr Convert to GS string.
|
|
|
|
sta GRecPath Store in GetFileInfo
|
|
stx GRecPath+2 parameter block and
|
|
sta PRecPath SetPrefix p.b.
|
|
stx PRecPath+2
|
|
|
|
;
|
|
; Get file information to determine whether target is a valid directory
|
|
;
|
|
GetFileInfo GRec
|
|
bcc ok
|
|
sta ErrError
|
|
ErrorGS Err
|
|
bra done
|
|
|
|
ok if2 GRecFT,eq,#$F,ok2 If filetype != $F,
|
|
ldx #^direrr print error message
|
|
lda #direrr 'Not a directory'
|
|
jsr errputs
|
|
badstat inc status Return status = 1.
|
|
bra done
|
|
|
|
ok2 SetPrefix PRec Set the prefix.
|
|
bcc finish If error flag set,
|
|
ldx #^errorstr print error message
|
|
lda #errorstr 'could not set prefix,
|
|
jsr errputs pathname may not exist.'
|
|
inc status Return status = 1.
|
|
|
|
; -------------------------------------------------------------------
|
|
;
|
|
; All done: cleanup and return
|
|
;
|
|
finish ph4 PRecPath Free the name string buffer.
|
|
jsl nullfree
|
|
|
|
;
|
|
; Exit through here if PRecPath wasn't used
|
|
;
|
|
done unlock prefixmutex
|
|
|
|
ldy status
|
|
|
|
lda space
|
|
sta end-3
|
|
lda space+1
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
clc
|
|
adc #end-4
|
|
tcs
|
|
|
|
tya
|
|
|
|
rtl
|
|
|
|
prefixmutex key
|
|
|
|
errorstr dc c'prefix: could not set prefix, pathname may not exist.'
|
|
dc h'0d00'
|
|
usage dc c'Usage: prefix prefixnum prefixname',h'0d00'
|
|
bootstr dc c' *: ',h'00'
|
|
pfxstr dc c'00: ',h'00'
|
|
dirErr dc c'prefix: Not a directory',h'0d00'
|
|
|
|
;
|
|
; Parameter block for GS/OS GetFileInfo call
|
|
;
|
|
GRec dc i'3' pCount
|
|
GRecPath ds 4 Pointer to input pathname
|
|
GRecAcc ds 2 access (result)
|
|
GRecFT ds 2 fileType (result)
|
|
|
|
;
|
|
; Parameter buffer for SetPrefix GS/OS call
|
|
;
|
|
PRec dc i'2' pCount
|
|
PRecNum dc i'0' prefix number
|
|
PRecPath ds 4 pointer to GS/OS string with value
|
|
|
|
;
|
|
; Parameter block for shell ErrorGS call (p 393 in ORCA/M manual)
|
|
;
|
|
Err dc i2'1' pCount
|
|
ErrError ds 2 Error number
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* REHASH: builtin command
|
|
* syntax: rehash
|
|
*
|
|
* rehashes the path
|
|
*
|
|
**************************************************************************
|
|
*
|
|
* UNHASH: builtin command
|
|
* syntax: unhash
|
|
*
|
|
* turns off command hashing
|
|
*
|
|
**************************************************************************
|
|
|
|
rehash START
|
|
unhash ENTRY
|
|
|
|
status equ 0
|
|
space equ status+2
|
|
|
|
subroutine (4:argv,2:argc),space
|
|
|
|
stz status
|
|
|
|
lda argc
|
|
dec a
|
|
beq doit
|
|
|
|
ldx #^Usage
|
|
lda #Usage
|
|
jsr errputs
|
|
ldy #2
|
|
lda [argv],y
|
|
tax
|
|
lda [argv]
|
|
jsr errputs
|
|
lda #13
|
|
jsr errputchar
|
|
inc status Return status = 1.
|
|
bra exit
|
|
|
|
doit jsr dispose_hash ;remove old table
|
|
lda [argv]
|
|
tax
|
|
ldy #2
|
|
lda [argv],y
|
|
sta argv+2
|
|
stx argv
|
|
lda [argv]
|
|
and #$FF
|
|
jsr tolower
|
|
if2 @a,eq,#'u',exit ;if 'rehash' do the hashing.
|
|
jsl hashpath ;hash the path
|
|
|
|
exit return 2:status
|
|
|
|
Usage dc c'Usage: ',h'00'
|
|
|
|
END
|
|
|
|
|
|
**************************************************************************
|
|
*
|
|
* EXIT: builtin command
|
|
* syntax: exit
|
|
*
|
|
* exit gsh
|
|
*
|
|
**************************************************************************
|
|
|
|
exit START
|
|
|
|
using global
|
|
|
|
space equ 0
|
|
|
|
subroutine (4:argv,2:argc),space
|
|
|
|
inc exit_requested
|
|
|
|
return 2:#0
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* SETDEBUG: builtin command
|
|
* syntax: setdebug (val | [+|-]flag)
|
|
*
|
|
* sets debugging in kernel
|
|
*
|
|
**************************************************************************
|
|
|
|
setdebug START
|
|
|
|
arg equ 0
|
|
newdebug equ arg+4
|
|
mode equ newdebug+2
|
|
status equ mode+2
|
|
space equ status+2
|
|
|
|
subroutine (4:argv,2:argc),space
|
|
|
|
stz status
|
|
|
|
lda argc
|
|
dec a
|
|
bne ok
|
|
showusage ldx #^usage
|
|
lda #usage
|
|
jsr errputs
|
|
inc status Return status = 1.
|
|
jmp return
|
|
|
|
ok stz mode
|
|
mv2 globaldebug,newdebug
|
|
dec argc
|
|
add2 argv,#4,argv
|
|
loop lda [argv]
|
|
sta arg
|
|
ldy #2
|
|
lda [argv],y
|
|
sta arg+2
|
|
lda [arg]
|
|
and #$FF
|
|
if2 @a,eq,#'-',turnoff
|
|
if2 @a,eq,#'+',turnon
|
|
ldx mode
|
|
bne showusage
|
|
ldx argc
|
|
dex
|
|
bne showusage
|
|
if2 @a,cc,#'0',showusage
|
|
if2 @a,cs,#'9'+1,showusage
|
|
pei (arg+2)
|
|
pei (arg)
|
|
jsr cstrlen
|
|
tax
|
|
Dec2Int (arg,@x,#0),@a
|
|
sta newdebug
|
|
jmp done
|
|
|
|
turnoff jsr findflag
|
|
eor #$FFFF
|
|
and newdebug
|
|
bra turnnext
|
|
turnon jsr findflag
|
|
ora newdebug
|
|
turnnext sta newdebug
|
|
ld2 1,mode
|
|
add2 argv,#4,argv
|
|
dec argc
|
|
beq done
|
|
jmp loop
|
|
|
|
done setdebug newdebug
|
|
mv2 newdebug,globaldebug
|
|
return return 2:status
|
|
|
|
findflag incad arg
|
|
ldy #0
|
|
findloop phy
|
|
lda nametbl,y
|
|
ora nametbl+2,y
|
|
beq nofind
|
|
lda nametbl+2,y
|
|
pha
|
|
lda nametbl,y
|
|
pha
|
|
pei (arg+2)
|
|
pei (arg)
|
|
jsr cmpcstr
|
|
beq foundit
|
|
pla
|
|
add2 @a,#4,@y
|
|
bra findloop
|
|
|
|
foundit pla
|
|
lsr a
|
|
tax
|
|
lda bittbl,x
|
|
rts
|
|
|
|
nofind pla
|
|
ldx arg+2
|
|
lda arg
|
|
jsr errputs
|
|
ldx #^errstr
|
|
lda #errstr
|
|
jsr errputs
|
|
lda #-1
|
|
pla ;rts address
|
|
jmp showusage
|
|
|
|
usage dc c'Usage: setdebug (value | [+|-]flag ... )',h'0d0d'
|
|
dc c'Flags: gsostrace - Trace GS/OS calls',h'0d'
|
|
dc c' gsosblocks - Trace GS/OS parameter blocks',h'0d'
|
|
dc c' gsoserrors - Trace GS/OS errors',h'0d'
|
|
dc c' pathtrace - Trace GS/OS pathnames',h'0d'
|
|
dc c' sigtrace - Trace signals',h'0d'
|
|
dc c' systrace - Trace system calls',h'0d'
|
|
* >> Next line is temporary
|
|
dc c' breakpoint - Coded brk instructions',h'0d'
|
|
dc h'00'
|
|
|
|
errstr dc c': Unknown flag',h'0d0d00'
|
|
|
|
nametbl dc a4'str01,str02,str03,str04,str05,str06,str07,0'
|
|
str01 dc c'gsostrace',h'00'
|
|
str02 dc c'pathtrace',h'00'
|
|
str03 dc c'gsoserrors',h'00'
|
|
str04 dc c'sigtrace',h'00'
|
|
str05 dc c'systrace',h'00'
|
|
str06 dc c'gsosblocks',h'00'
|
|
* >> Next line is temporary; Also: remove str07 in nametbl
|
|
str07 dc c'breakpoint',h'00'
|
|
|
|
bittbl dc i2'%000001'
|
|
dc i2'%000010'
|
|
dc i2'%000100'
|
|
dc i2'%001000'
|
|
dc i2'%010000'
|
|
dc i2'%100000'
|
|
* >> Next line is temporary
|
|
dc i2'%10000000'
|
|
|
|
* >> Next line is temporary
|
|
check4debug ENTRY
|
|
|
|
globaldebug dc i2'0'
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* PS: builtin command
|
|
* syntax: ps
|
|
*
|
|
* display process status
|
|
*
|
|
**************************************************************************
|
|
|
|
psbi START
|
|
|
|
using pdata
|
|
|
|
myuid equ 0
|
|
t equ myuid+2
|
|
ps2 equ t+4
|
|
pr2 equ ps2+4
|
|
pr equ pr2+4
|
|
ps equ pr+4
|
|
status equ ps+4
|
|
space equ status+2
|
|
|
|
subroutine (4:argv,2:argc),space
|
|
|
|
stz status
|
|
|
|
lda argc
|
|
dec a
|
|
beq ok
|
|
showusage ldx #^usage
|
|
lda #usage
|
|
jsr errputs
|
|
inc status Return status = 1.
|
|
jmp return
|
|
|
|
ok getuid
|
|
sta myuid
|
|
kvm_open
|
|
sta ps
|
|
stx ps+2
|
|
ora2 @a,ps+2,@a
|
|
bne ok2
|
|
ldx #^kvmerrstr
|
|
lda #kvmerrstr
|
|
jsr errputs
|
|
inc status Return status = 1.
|
|
jmp done
|
|
|
|
ok2 ldx #^header
|
|
lda #header
|
|
jsr puts
|
|
|
|
loop kvmnextproc ps
|
|
sta pr
|
|
stx pr+2
|
|
ora2 @a,pr+2,@a
|
|
jeq done
|
|
|
|
ldy #94 ;ps->p_uid
|
|
lda [pr],y
|
|
cmp myuid
|
|
jne skip
|
|
|
|
ldy #2
|
|
lda [ps],y ;ps->pid
|
|
Int2Dec (@a,#pidstr,#4,#0)
|
|
ldx #^pidstr
|
|
lda #pidstr
|
|
jsr puts
|
|
|
|
ldy #2
|
|
lda [pr],y ;pr->processState
|
|
cmp #9
|
|
bcc okstate
|
|
lda #9
|
|
okstate asl a
|
|
asl a
|
|
asl a
|
|
tax
|
|
ldy #8
|
|
putstate lda statetbl,x
|
|
phx
|
|
phy
|
|
jsr putchar
|
|
ply
|
|
plx
|
|
inx
|
|
dey
|
|
bne putstate
|
|
|
|
ldy #6
|
|
lda [pr],y ;pr->ttyID
|
|
beq ttnul
|
|
cmp #3
|
|
bne ttnum
|
|
lda #'c'
|
|
jsr putchar
|
|
lda #'o'
|
|
bra showuser
|
|
ttnul lda #'n'
|
|
jsr putchar
|
|
lda #'u'
|
|
bra showuser
|
|
ttnum ldy #0
|
|
ttnumlup cmp #10
|
|
bcc ttnum0
|
|
sec
|
|
sbc #10
|
|
iny
|
|
bra ttnumlup
|
|
ttnum0 pha
|
|
tya
|
|
clc
|
|
adc #'0'
|
|
jsr putchar
|
|
pla
|
|
clc
|
|
adc #'0'
|
|
showuser jsr putchar
|
|
|
|
ldy #4
|
|
lda [pr],y ;pr->userID
|
|
Int2Hex (@a,#userstr+1,#4)
|
|
ldx #^userstr
|
|
lda #userstr
|
|
jsr puts
|
|
|
|
ldy #94
|
|
lda [pr],y ;pr->puid
|
|
Int2Hex (@a,#puidstr,#4)
|
|
ldx #^puidstr
|
|
lda #puidstr
|
|
jsr puts
|
|
|
|
ldy #50
|
|
lda [pr],y ;pr->ticks
|
|
tax
|
|
iny2
|
|
lda [pr],y
|
|
LongDivide (@ax,#60),(@ax,@yy)
|
|
LongDivide (@xa,#60),(t,@ax)
|
|
Long2Dec (@xa,#timestr+4,#2,#0)
|
|
Long2Dec (t,#timestr,#3,#0)
|
|
lda timestr+4
|
|
and #$FF
|
|
cmp #' '
|
|
bne time0
|
|
short a
|
|
lda #'0'
|
|
sta timestr+4
|
|
long a
|
|
time0 ldx #^timestr
|
|
lda #timestr
|
|
jsr puts
|
|
|
|
ldy #34
|
|
lda [pr],y ;pr->args
|
|
tax
|
|
iny2
|
|
lda [pr],y
|
|
jne goodcmd
|
|
cpx #0
|
|
jne goodcmd
|
|
|
|
lda pjoblist ;check for name in job list
|
|
ldx pjoblist+2
|
|
|
|
jobloop sta pr2
|
|
stx pr2+2
|
|
|
|
ora pr2+2
|
|
beq childof
|
|
ldy #p_pid
|
|
lda [pr2],y
|
|
ldy #2
|
|
cmp [ps],y ;ps->pid
|
|
bne loop2
|
|
|
|
ldy #p_command+2
|
|
lda [pr2],y
|
|
tax
|
|
ldy #p_command
|
|
lda [pr2],y
|
|
jsr puts
|
|
bra next
|
|
|
|
loop2 ldy #p_next+2
|
|
lda [pr2],y
|
|
tax
|
|
ldy #p_next
|
|
lda [pr2],y
|
|
bra jobloop
|
|
|
|
childof ldx #^forkstr
|
|
lda #forkstr
|
|
jsr puts
|
|
kvm_open
|
|
sta ps2
|
|
stx ps2+2
|
|
lda [pr]
|
|
tay
|
|
kvmgetproc (ps2,@y)
|
|
sta pr2
|
|
stx pr2+2
|
|
kvm_close ps2
|
|
ldy #34
|
|
lda [pr2],y ;pr2->args
|
|
tax
|
|
iny2
|
|
lda [pr2],y
|
|
bne goodcmd
|
|
cpx #0
|
|
bne goodcmd
|
|
|
|
ldx #^forkstr2
|
|
lda #forkstr2
|
|
jsr puts
|
|
bra next
|
|
|
|
goodcmd tay
|
|
txa
|
|
tyx
|
|
clc
|
|
adc #8
|
|
jsr puts
|
|
|
|
next jsr newline
|
|
skip jmp loop
|
|
|
|
done kvm_close ps
|
|
|
|
return return 2:status
|
|
|
|
usage dc c'Usage: ps',h'0d00'
|
|
kvmerrstr dc c'ps: error in kvm_open()',h'0d00'
|
|
header dc c' ID STATE TT MMID UID TIME COMMAND',h'0d00'
|
|
pidstr dc c'0000 ',h'00'
|
|
userstr dc c' 0000 ',h'00'
|
|
puidstr dc c'0000 ',h'00'
|
|
timestr dc c'000:00 ',h'00'
|
|
forkstr dc c'forked child of ',h'00'
|
|
forkstr2 dc c'an unknown process',h'00'
|
|
|
|
test1 dc c'getuid = $'
|
|
test1a dc c'0000',h'0d00'
|
|
|
|
statetbl dc c'defunct '
|
|
dc c'running '
|
|
dc c'ready '
|
|
dc c'blocked '
|
|
dc c'ready '
|
|
dc c'suspend '
|
|
dc c'waiting '
|
|
dc c'waiting '
|
|
dc c'paused '
|
|
dc c'unknown '
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* HASH: builtin command
|
|
* syntax: hash
|
|
*
|
|
* display hashed commands
|
|
*
|
|
**************************************************************************
|
|
|
|
hashbi START
|
|
|
|
using hashdata
|
|
|
|
sv equ 0
|
|
q equ sv+4
|
|
p equ q+4
|
|
status equ p+4
|
|
space equ status+2
|
|
|
|
subroutine (4:argv,2:argc),space
|
|
|
|
stz status
|
|
|
|
lda argc
|
|
dec a
|
|
beq dohash
|
|
|
|
ldx #^Usage
|
|
lda #Usage
|
|
jsr errputs
|
|
inc status Return status = 1.
|
|
bra exit
|
|
|
|
dohash ph2 t_size Get size of hash table.
|
|
jsl sv_alloc Allocate a string vector array.
|
|
sta sv
|
|
stx sv+2
|
|
|
|
lda hash_table If no hash table
|
|
ora hash_table+2 has been allocated,
|
|
beq exit exit.
|
|
|
|
mv4 hash_table,p Move address to dir pg variable.
|
|
lda hash_numexe Get the number of executable files.
|
|
beq doneadd Done if 0.
|
|
;
|
|
; loop through every hashed file and add it the string vector
|
|
;
|
|
ldy #0 Y is index into the next entry.
|
|
ldx t_size X is the number of entries left.
|
|
beq doneadd
|
|
addloop lda [p],y Get next hash table entry.
|
|
sta q
|
|
iny
|
|
iny
|
|
lda [p],y
|
|
sta q+2
|
|
iny
|
|
iny
|
|
ora q If this entry isn't used,
|
|
beq skip skip to the next one.
|
|
|
|
phy Hold the Y and X regs on stack.
|
|
phx
|
|
pei (sv+2) Insert string in table entry
|
|
pei (sv) into the string vector.
|
|
clc
|
|
lda q
|
|
adc #2 (Note: tn_name in hash.asm == 2)
|
|
tax
|
|
lda q+2
|
|
adc #0
|
|
pha
|
|
phx
|
|
pea 1 (allocflag: 1 = allocate memory)
|
|
jsl sv_add
|
|
plx Restore X and Y regs from stack.
|
|
ply
|
|
skip dex
|
|
bne addloop
|
|
;
|
|
; Files have all been added to the string vector
|
|
;
|
|
doneadd anop
|
|
|
|
pei (sv+2)
|
|
pei (sv)
|
|
jsl sv_sort Sort the string vector.
|
|
|
|
pei (sv+2)
|
|
pei (sv)
|
|
jsl sv_colprint Print the string vector in columns.
|
|
|
|
pei (sv+2)
|
|
pei (sv)
|
|
jsl sv_dispose Dispose of the string vector memory.
|
|
|
|
exit return 2:status
|
|
|
|
usage dc c'Usage: hash',h'0d00'
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* SOURCE: builtin command
|
|
* syntax: source file [arguments...]
|
|
*
|
|
* executes a shell file w/o pushing environment
|
|
*
|
|
**************************************************************************
|
|
|
|
source START
|
|
|
|
retval equ 0
|
|
space equ retval+2
|
|
|
|
subroutine (4:argv,2:argc),space
|
|
|
|
dec argc If no filename was provided,
|
|
bne ok
|
|
|
|
ldx #^usage Print usage string.
|
|
lda #usage
|
|
jsr errputs
|
|
lda #1 Return error status.
|
|
sta retval
|
|
bra exit
|
|
|
|
ok stz retval
|
|
|
|
add2 argv,#4,argv
|
|
|
|
* ShellExec subroutine (4:path,2:argc,4:argv,2:jobflag)
|
|
|
|
ldy #2 path is filename argument
|
|
lda [argv],y
|
|
pha
|
|
lda [argv]
|
|
pha
|
|
pei (argc) reuse argc
|
|
pei (argv+2) reuse argv
|
|
pei (argv)
|
|
pea 0 jobflag = 0
|
|
jsl ShellExec
|
|
sta retval
|
|
|
|
exit return 2:retval
|
|
|
|
usage dc c'usage: source file [arguments...]',h'0d00'
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* COMMANDS: builtin command
|
|
* syntax: commands
|
|
*
|
|
* display builtin commands
|
|
*
|
|
**************************************************************************
|
|
|
|
cmdbi START
|
|
|
|
using BuiltinData
|
|
|
|
sv equ 0
|
|
status equ sv+4
|
|
space equ status+2
|
|
|
|
subroutine (4:argv,2:argc),space
|
|
|
|
stz status
|
|
|
|
lda argc
|
|
dec a
|
|
beq docmds
|
|
|
|
ldx #^Usage
|
|
lda #Usage
|
|
jsr errputs
|
|
inc status Return status = 1.
|
|
bra exit
|
|
|
|
docmds ph2 #50
|
|
jsl sv_alloc
|
|
|
|
sta sv
|
|
stx sv+2
|
|
|
|
ldx #0
|
|
;
|
|
; loop through every hashed file and add it the string vector
|
|
;
|
|
addloop lda builtintbl,x
|
|
ora builtintbl+2,x
|
|
beq doneadd
|
|
phx
|
|
pei (sv+2)
|
|
pei (sv)
|
|
lda builtintbl+2,x
|
|
pha
|
|
lda builtintbl,x
|
|
pha
|
|
pea 1
|
|
jsl sv_add
|
|
pla
|
|
clc
|
|
adc #10
|
|
tax
|
|
bra addloop
|
|
doneadd anop
|
|
|
|
pei (sv+2)
|
|
pei (sv)
|
|
jsl sv_sort
|
|
pei (sv+2)
|
|
pei (sv)
|
|
jsl sv_colprint
|
|
|
|
pei (sv+2)
|
|
pei (sv)
|
|
jsl sv_dispose
|
|
|
|
exit return 2:status
|
|
|
|
usage dc c'Usage: commands',h'0d00'
|
|
|
|
END
|