gno/bin/gsh/invoke.asm

710 lines
11 KiB
NASM

***********************************************************************
*
* The GNO Shell Project
*
* Developed by:
* Jawaid Bazyar
* Tim Meekins
*
**************************************************************************
*
* INVOKE.ASM
* By Tim Meekins
*
* Command invocation routines.
*
**************************************************************************
mcopy m/invoke.mac
keep o/invoke.mac
SIGINT gequ 2
SIGKILL gequ 9
SIGTERM gequ 15
SIGSTOP gequ 17
SIGTSTP gequ 18
SIGCONT gequ 19
SIGCHLD gequ 20
SIGTTIN gequ 21
SIGTTOU gequ 22
**************************************************************************
*
* Redirect
*
**************************************************************************
redirect START
space equ 1
pipeout2 equ space+3
pipein2 equ pipeout2+2
pipeout equ pipein2+2
pipein equ pipeout+2
eapp equ pipein+2
app equ eapp+2
efile equ app+2
dfile equ efile+4
sfile equ dfile+4
end equ sfile+4
; subroutine (4:sfile,4:dfile,4:efile,2:app,2:eapp,2:pipein,2:pipeout,2:pipein2,2:pipeout2),space
tsc
phd
tcd
;
; standard input
;
ora2 sfile,sfile+2,@a
beq execa
pei (sfile+2) ;for c2pstr
pei (sfile)
pei (sfile+2)
pei (sfile)
jsr cstrlen
inc a
pea 0
pha
jsl ~NEW
sta RedirectFile
stx RedirectFile+2
phx
pha
jsr c2pstr
stz RedirectDev
stz RedirectApp
Redirect RedirectParm
php
ph4 RedirectFile
jsl nullfree
plp
bcc execa
ldx #^err1
lda #err1
jmp badbye
;
; standard output
;
execa ora2 dfile,dfile+2,@a
beq execb
pei (dfile+2) ;for c2pstr
pei (dfile)
pei (dfile+2)
pei (dfile)
jsr cstrlen
inc a
pea 0
pha
jsl ~NEW
sta RedirectFile
stx RedirectFile+2
phx
pha
jsr c2pstr
ld2 1,RedirectDev
mv2 app,RedirectApp
Redirect RedirectParm
php
ph4 RedirectFile
jsl nullfree
plp
bcc execb
ldx #^err2
lda #err2
jmp badbye
;
; standard error
;
execb ora2 efile,efile+2,@a
beq execc
pei (efile+2) ;for c2pstr
pei (efile)
pei (efile+2)
pei (efile)
jsr cstrlen
inc a
pea 0
pha
jsl ~NEW
sta RedirectFile
stx RedirectFile+2
phx
pha
jsr c2pstr
ld2 2,RedirectDev
mv2 eapp,RedirectApp
Redirect RedirectParm
php
ph4 RedirectFile
jsl nullfree
plp
bcc execc
ldx #^err3
lda #err3
jmp badbye
;
; is input piped in?
;
execc lda pipein
beq execd
dup2 (pipein,#1)
mv2 pipein2,CloseRef
Close CloseParm
ldx #0
lda pipein
SetInputDevice (#3,@xa)
;
; is output piped?
;
execd lda pipeout
beq exece
dup2 (pipeout,#2)
mv2 pipeout2,CloseRef
Close CloseParm
ldx #0
lda pipeout
SetOutputDevice (#3,@xa)
exece anop
goodbye ldy #0
bra exit
badbye jsr errputs
cop $7F ; get out of the way
ldy #1
exit lda space
sta end-3
lda space+1
sta end-2
pld
tsc
clc
adc #end-4
tcs
cpy #1
rtl
RedirectParm anop
RedirectDev ds 2
RedirectApp ds 2
RedirectFile ds 4
CloseParm dc i'1'
CloseRef dc i'0'
err1 dc c'gsh: Error redirecting standard input.',h'0d00'
err2 dc c'gsh: Error redirecting standard output.',h'0d00'
err3 dc c'gsh: Error redirecting standard error.',h'0d00'
END
**************************************************************************
*
* Invoke a command (PHASE 0)
*
**************************************************************************
invoke START
using hashdata
using vardata
using global
using pdata
p equ 0
biflag equ p+4
ptr equ biflag+2
val equ ptr+4
dir equ val+2
space equ dir+4
subroutine (2:argc,4:argv,4:sfile,4:dfile,4:efile,2:app,2:eapp,2:bg,4:cmd,2:jobflag,2:pipein,2:pipeout,2:pipein2,2:pipeout2,4:pipesem),space
ld2 -1,val
stz biflag ;not a built-in
lda argc
bne chknull
lda sfile
ora sfile+2
ora dfile
ora dfile+2
ora efile
ora efile+2
beq nulldone
ldx #^hehstr
lda #hehstr
jsr errputs
nulldone jmp done
;
; Check for null command
;
chknull ldy #2
lda [argv]
sta dir
lda [argv],y
sta dir+2
ora dir
beq gonull
lda [dir]
and #$FF
bne checkfile
gonull jmp done
;
; check for file
;
checkfile anop
pei (dir+2)
pei (dir)
jsl IsBuiltin ;check builtin first
cmp #-1
jne trybuiltin
pei (dir+2)
pei (dir)
ph4 hash_table
ph4 #hash_paths
jsl search
cmp #0
bne changeit
cpx #0
beq skip
changeit sta dir
stx dir+2
skip lock mutex2
pei (dir+2)
pei (dir)
jsr c2gsstr
sta GRecPath
sta ptr
stx GRecPath+2
stx ptr+2
GetFileInfo GRec
unlock mutex2
jcs notfound
if2 GRecFileType,eq,#$B5,doExec
if2 @a,eq,#$B3,doExec
ldx vardirexec
bne ft02
cmp #$0F
jeq doDir
ft02 if2 @a,ne,#$B0,badfile
if2 GRecAuxType,ne,#6,badfile
if2 GRecAuxType+2,ne,#0,badfile
jmp doShell
badfile ldx dir+2
lda dir
jsr errputs
ldx #^err1
lda #err1
jsr errputs
free pei (ptr+2)
pei (ptr)
jsl nullfree
jmp done
;
; launch an executable
;
doExec pei (ptr+2)
pei (ptr)
jsl nullfree
jsr prefork
fork #invoke0
jsr postfork
jmp done
invoke0 phk
plb
;
; make a a copy of cmd
;
pha
pha
tsc
phd
tcd
ldx #0
tsc
FindHandle @xa,1
ldy #6
lda [1],y ;This is the UserID!
and #$F0FF
pha
ph4 _cmd
jsr cstrlen
inc a
ply
pha
ldx #0
NewHandle (@xa,@y,#$4018,#0),1
ply
ldx #0
PtrToHand (_cmd,1,@xy)
ldy #2
lda [1],y
tax
lda [1]
pld
ply
ply
phx ;_cmd
pha
;
; make a a copy of dir
;
pha
pha
tsc
phd
tcd
ldx #0
tsc
FindHandle @xa,1
ldy #6
lda [1],y ;This is the UserID!
and #$F0FF
pha
ph4 _dir
jsr cstrlen
inc a
ply
pha
ldx #0
NewHandle (@xa,@y,#$4018,#0),1
ply
ldx #0
PtrToHand (_dir,1,@xy)
ldy #2
lda [1],y
tax
lda [1]
pld
ply
ply
phx ;_dir
pha
jsl infork
bcs invoke1
case on
jsl execve
case off
rtl
invoke1 pla
pla
pla
pla
rtl
;
; do path (it was a directory entry so change to that directory)
;
doDir lock cdmutex
mv4 GRecPath,PRecPath
SetPrefix PRec
unlock cdmutex
stz val
jmp free
;
; fork a shell script
;
doShell inc biflag ;don't free argv...
jsr prefork
* int fork2(void *subr, int stack, int prio, char *name, word argc, ...)
pea 0
ldy #2
lda [argv],y
pha
lda [argv]
pha
pea 0
pea 1024
ph4 #exec0
case on
jsl fork2
case off
* fork #exec0
jsr postfork
jmp free
exec0 ph2 _argc ;for argfree
ph4 _argv
ph4 _dir ;for shellexec
ph2 _argc
ph4 _argv
jsl infork
bcs exec0c
signal (#SIGCHLD,#0)
PushVariables 0
pea 1
jsl ShellExec
jsl argfree
PopVariables 0
rtl
exec0c pla
pla
pla
pla
pla
pla
pla
pla
rtl
;
; file not found, so try a builtin.
;
trybuiltin inc biflag ;it's a built-in
cmp #1
beq noforkbuiltin
jsr prefork
fork #forkbuiltin
jsr postfork
jmp done
forkbuiltin cop $7F ;give palloc a chance
ph2 _argc
ph4 _argv
jsl infork
bcs fork0c
jsl builtin
rtl
fork0c pla
pla
pla
rtl
noforkbuiltin anop
pei (argc)
pei (argv+2)
pei (argv)
jsl builtin
stz val
bra done
notfound pei (ptr+2)
pei (ptr)
jsl nullfree
ldy #2
lda [argv],y
tax
lda [argv]
jsr errputs
ldx #^err2
lda #err2
jsr errputs
lda pipein
beq notfound0
ssignal _semaphore
sdelete _semaphore
mv4 pjoblist,p
ldy #16 ;p_jobid
lda [p],y
getpgrp @a
eor #$FFFF
inc a
kill (@a,#9)
sigpause #0
notfound0 anop
done cop $7F
lda biflag
bne skipfrarg
pei (argc)
pei (argv+2)
pei (argv)
jsl argfree
skipfrarg pei (cmd+2)
pei (cmd)
jsl nullfree
return 2:val
;
;
; stuff to do just before forking
;
prefork lock mutex
SetInGlobals (#$FF,#00)
mv4 sfile,_sfile
mv4 dfile,_dfile
mv4 efile,_efile
mv2 app,_app
mv2 eapp,_eapp
mv4 cmd,_cmd
mv4 dir,_dir
mv2 argc,_argc
mv4 argv,_argv
mv2 pipein,_pipein
mv2 pipeout,_pipeout
mv2 pipein2,_pipein2
mv2 pipeout2,_pipeout2
mv2 bg,_bg
mv2 jobflag,_jobflag
lda [pipesem]
sta _semaphore
lda pipesem
sta putsem+1
lda pipesem+1
sta putsem+2
rts
;
; stuff to do right after forking
;
postfork sta val
lda pipein
beq postfork2
sta CloseRef
Close CloseParm
postfork2 lda pipeout
beq postfork3
sta CloseRef
Close CloseParm
postfork3 lda val
cmp #-1
bne postfork4
ldx #^deadstr
lda #deadstr
jsr errputs
unlock mutex
jmp done
postfork4 ldx jobflag
dex
beq postfork5
pha
pei (bg)
pei (cmd+2)
pei (cmd)
lda pipein
bne postfork4a
jsl palloc
bra postfork5
postfork4a jsl pallocpipe
postfork5 lda >mutex ;DANGER!!!!! Assumes knowledge of
beq postfork6 ;lock/unlock structure!!!!!!!!
cop $7F
bra postfork5
postfork6 rts
;
; stuff to do in fork
;
infork phk
plb
lda _jobflag
bne invoke0b
Open ttyopen
jcs doneinfork
lda _pipein
bne invoke0a
tcnewpgrp ttyref
invoke0a settpgrp ttyref
lda _bg ;if in background then reset tty to
and #$FF
beq invoke0b ;to the shell process group
tctpgrp (gshtty,gshpid)
invoke0b ph4 _sfile
ph4 _dfile
ph4 _efile
ph2 _app
ph2 _eapp
ph2 _pipein
ph2 _pipeout
ph2 _pipein2
ph2 _pipeout2
jsl redirect
jcs doneinfork
unlock mutex
lda _pipein
bne invoke0c
lda _pipeout
beq invoke0d
screate #0
putsem sta >$FFFFFF
swait @a
bra invoke0d
invoke0c lda _pipeout
bne invoke0d
waitsemy lda _semaphore
bne goodsemy
cop $7F
bra waitsemy
goodsemy ssignal _semaphore
sdelete _semaphore
invoke0d anop
clc
bra indone
doneinfork unlock mutex
sec
indone rtl
mutex key
mutex2 key
cdmutex key
_argc dc i2'0'
_argv dc i4'0'
_sfile dc i4'0'
_dfile dc i4'0'
_efile dc i4'0'
_app dc i2'0'
_eapp dc i2'0'
_cmd dc i4'0'
_dir dc i4'0'
_pipein dc i2'0'
_pipeout dc i2'0'
_pipein2 dc i2'0'
_pipeout2 dc i2'0'
_bg dc i2'0'
_jobflag dc i2'0'
_semaphore dc i2'0'
str dc c'[0]',h'0d00'
err1 dc c': Not executable.',h'0d00'
err2 dc c': Command not found.',h'0d00'
hehstr dc c'heh heh, next time you''ll need to specify a command '
dc c'before redirecting.',h'0d00'
deadstr dc c'Cannot fork (too many processes?)',h'0d00' ;try a spoon
GRec dc i'4'
GRecPath ds 4
ds 2
GRecFileType ds 2
GRecAuxType ds 4
PRec dc i'2'
PRecNum dc i'0'
PRecPath ds 4
CloseParm dc i2'1'
CloseRef dc i2'0'
Err dc i2'0'
ttyopen dc i2'2'
ttyref dc i2'0'
dc i4'ttyname'
ttyname gsstr '.tty'
END