Changes for gsh version 2.0d5:

Add quotes around null parameters from the command line so they will be
parsed properly (resolves PR#84).

Output piped to an unfound command caused gsh to terminate, due to an
interface change to the GNO 2.0.6 version of getpgrp(2): it now returns the
process group of the caller.  To get the process group number for the
pid passed as a parameter pid, the call has to be made to _getpgrp(2).
In addition to fixing invoke.asm, updates were also made in jobs.asm.

When directory stack is full, pushd, reports a new error message: 'pushd:
Directory stack full'.  (Previously, 50 pushds would cause a crash.)

When parameter passed to "pushd +n" is <= 0, report a new error message:
'pushd: Invalid number'. (Previously, tried to chdir to the parameter.)

When a command appends to stderr (e.g., echo test >>&/tmp/err), stdin was
closed, due to errappend being defined as pipefds+2 rather than pipefds+4
in cmd.asm.

When there was an error reading stdin, gsh went into an infinite loop of
beeping and requesting more input. Changed getchar (in stdio.asm) and
GetCmdLine (in edit.asm) to report the error and terminate.

Code in cmd.asm set and reset handler for signal SIGSTOP (17). This makes
no sense, since there cannot be a handler for SIGSTOP. This was changed
to set and reset signal SIGTSTP (18) since that handler is used by gsh.

The error message "specify a command before redirecting" was never
caught by the invoke() subroutine because the next higher routine,
command(), checked for argv==0 before calling invoke(). The error
message was moved into command().
This commit is contained in:
tribby 1998-10-26 17:04:51 +00:00
parent 0c8ae50cfc
commit 963a33c4bf
13 changed files with 830 additions and 557 deletions

View File

@ -1,27 +1,40 @@
Last updated: July 5, 1998 By: Dave Tribby
Last updated: Oct. 25, 1998 By: Dave Tribby
For more bug reports, see also http://www.gno.org/~gno/bugs.html
For more bug reports, see http://www.gno.org/~gno/bugs.html
Completed items are reported in file UpdateLog.
Gsh requires the v2.0.4 ltermcap to link. Termcap has changed in v2.0.6,
and gsh should be updated to reflect this.
Executing the following exec file often results in a hang:
# Create exec file
set tmpcmd=/tmp/testcmds
echo "echo Sourcing $tmpcmd" > $tmpcmd
echo "/bin/ps -l" >> $tmpcmd
chtyp -l exec $tmpcmd
# Source that file; usually doesn't return
source $tmpcmd
Allow redirection of built-in commands' I/O even if they aren't forked.
Rather than have each built-in command always be either forked or
non-forked, check dynamically and only fork when it's really necessary
(background or piped).
Identify limits built into gsh and how they can be changed; for example,
size of $PATH <= 256; max programs in hash table = 256.
Allow redirection of built-in commands' I/O even if they aren't forked.
When a background process finishes and there's text in the input buffer,
the next keypress correctly reprints the edit line but the key itself does
not get put in the buffer.
running a process in the background from inside a script (not 'source',
Running a process in the background from inside a script (not 'source',
but executing the script as a command) causes the shell to wait for that
background process to end - not exactly what we want.
usage for alias and hash
Usage for alias and hash
Gsh requires the v2.0.4 ltermcap to link. A new version of the termcap
library is proposed for GNO v2.0.6, and gsh may require updates.
job control monitor for defunct processes when waiting.

View File

@ -1,7 +1,51 @@
GSH 2.0 UPDATES
^^^^^^^^^^^^^^^
Oct 10 98 [dmt] Found race condition: when forked process completes
quickly, the parent process may not ever receive its completion
signal. Fix: ensure process exists by calling kill(pid,0)
and checking status before calling pwait (cmd.asm).
Change calls to set and reset handler for signal 17 (SIGSTOP)
to do it for signal 18 (SIGTSTP) (17 can't be caught; 18 is).
Oct 7 98 [dmt] Check for directory stack full in pushd, and report
new error message: 'pushd: Directory stack full'. (Previously,
50 pushds would cause a crash.)
Check for parameter in pushd "+n" <=0, and report a new error
message: 'pushd: Invalid number'. (Previously, tried to chdir
to the parameter.)
Oct 6 98 [dmt] Before calling pwait (to wait for child process) in
cmd.asm, enable the child status signal handler; change it
back to its previous state after the pwait call. This partially
fixes the problem of the shell waiting forever when a shell
exec file sources another exec file that contains a command
that causes a fork.
command() checked for argv==0 before calling invoke(), but
invoke() also checks. Move invoke()'s error message ("specify
a command before redirecting.") into command().
Sep 27 98 [dmt] Add quotes around null parameters on the command line
so they are parsed by the target command (PR#84)
Sep 25 98 [dmt] If a command appends to stdout (echo test >>&/tmp/err),
then stdin gets closed. This was due to errappend being
defined as pipefds+2 rather than pipefds+4 in cmd.asm.
Sep 23 98 [dmt] If there is an error reading stdin, gsh would go into
an infinite loop of beeping and requesting more input. Changed
getchar (in stdio.asm) and GetCmdLine (in edit.asm) to report
the error and terminate.
Sep 9 98 [dmt] Output piped to an unfound command caused gsh to
terminate. This was due to an interface change to getpgrp(2):
it now returns the process group of the caller. To get the
process group number of the parameter pid, the call has to
be made to _getpgrp(2). This change was made in invoke.asm to
fix the bug. Additional updates were made in jobs.asm.
Sep 7 98 [dmt] Changes to this point checked-in to master archive.
Released as version 2.0d4
Sep 7 98 [dmt] In "gettoken" (cmd.asm), decrement buf (pointer to
command line) when EOL is reached; otherwise if the character
@ -37,6 +81,7 @@ Aug 4 98 [dmt] Fixed defects in wordmatch (edit.asm) related to
Aug 3 98 [dmt] Entabbed all the asm files (saved >36,000 bytes).
Aug 3 98 [dmt] Changes to this point checked-in to master archive.
Released as version 2.0d3
Aug 2 98 [dmt] Remove alloc256/free256 and associated data. Replace
with fixed 64-byte buffer for command filename (hash.asm)
@ -74,6 +119,7 @@ Jul 20 98 [dmt] Changed expand.asm to use InitWildcardGS and
NextWildcardGS instead of their obsolete counterparts.
Jul 20 98 [dmt] Changes up to this point checked-in to master archive.
Released as version 2.0d3
Jul 19 98 [dmt] Changed edit.asm to use ReadIndexedGS, InitWildcardGS,
NextWildcardGS, instead of their obsolete counterparts.
@ -133,6 +179,7 @@ Jul 5 98 [dmt] Changed default order for copying files in $PATH dirs
pathname to ExpandPathGS.
Jun 29 98 [dmt] Changes up to this point checked-in to master archive.
Released as version 2.0d2
Jun 28 98 [dmt] Added InitVar routine to shellvar.asm to read values
of all environment variables tracked in vardata.

View File

@ -6,7 +6,7 @@
* Jawaid Bazyar
* Tim Meekins
*
* $Id: builtin.asm,v 1.6 1998/09/08 16:53:05 tribby Exp $
* $Id: builtin.asm,v 1.7 1998/10/26 17:04:49 tribby Exp $
*
**************************************************************************
*
@ -1284,32 +1284,6 @@ Usage dc c'Usage: ',h'00'
END
**************************************************************************
*
* FST descriptions
*
**************************************************************************
FSTData DATA
FSTtable dc a4'fst0,fst1,fst2,fst3,fst4,fst5,fst6,fst7,fst8'
dc a4'fst0,fsta,fstb,fstc,fstd'
fst0 dc c'[Unknown]',h'00'
fst1 dc c'ProDOS',h'00'
fst2 dc c'DOS 3.3',h'00'
fst3 dc c'DOS 3.2',h'00'
fst4 dc c'Pascal',h'00'
fst5 dc c'MFS',h'00'
fst6 dc c'HFS',h'00'
fst7 dc c'Lisa (get real)',h'00'
fst8 dc c'CP/M',h'00'
fsta dc c'MS-DOS',h'00'
fstb dc c'High Sierra',h'00'
fstc dc c'ISO 9660',h'00'
fstd dc c'AppleShare',h'00'
END
**************************************************************************
*

View File

@ -6,7 +6,7 @@
* Jawaid Bazyar
* Tim Meekins
*
* $Id: cmd.asm,v 1.6 1998/09/08 16:53:07 tribby Exp $
* $Id: cmd.asm,v 1.7 1998/10/26 17:04:49 tribby Exp $
*
**************************************************************************
*
@ -28,17 +28,21 @@
*
* command subroutine (4:waitpid,2:inpipe,2:jobflag,2:inpipe2,
* 4:pipesem,4:stream)
* Called by execute to act on a single command
* Returns next token in Accumulator
*
* argfree subroutine (2:argc,4:argv)
*
* ShellExec subroutine (4:path,2:argc,4:argv,2:jobflag)
* Reads and executes commands from an exec file.
* Returns completion status in Accumulator
*
* execute subroutine (4:cmdline,2:jobflag)
* Interpret a command line.
* Returns completion status in Accumulator
*
* system Defined for libc; interface in <stdlib.h>
* User interface to execute commands via shell
* int system (char *command)
*
**************************************************************************
@ -52,6 +56,8 @@ dummycmd start ; ends up in .root
SIGINT gequ 2
SIGSTOP gequ 17
SIGTSTP gequ 18
SIGCHLD gequ 20
;
; TOKENS used by the parser
;
@ -328,12 +334,12 @@ errstr2 dc c"gsh: Missing ending '.",h'0d00'
command START
pipefds equ 1
errappend equ pipefds+2
errappend equ pipefds+4
errfile equ errappend+2
srcfile equ errfile+4
dstfile equ srcfile+4
count equ dstfile+4
argv equ count+2
needq equ dstfile+4
argv equ needq+2
word equ argv+4
cmdline equ word+4
pid equ cmdline+4
@ -366,33 +372,35 @@ end equ waitpid+4
lda #0 Initialize to null C string.
sta [cmdline]
jsl alloc1024
jsl alloc1024 Allocate memory for token.
sta word
stx word+2
ph4 #MAXARG*4
ph4 #MAXARG*4 Allocate argv parameter pointer array
~NEW
sta argv
stx argv+2
stz srcfile
stz argc Argument count = 0
stz srcfile Clear I/O redirection pointers
stz srcfile+2
stz dstfile
stz dstfile+2
stz errfile
stz errfile+2
stz argc
stz pipefds
stz pipefds+2
lda #-3
sta [waitpid]
loop pei (word+2)
loop pei (word+2) Get next token from input stream.
pei (word)
pei (stream+2)
pei (stream)
jsl gettoken
sta token
sta token Jump to appropriate token handler.
asl a
tax
jmp (toktbl,x)
@ -443,23 +451,33 @@ word2 lda argc ;Copy word to argv[argc]
pei (temp)
jsr copycstr
stz count ;count illegal characters in word
ldy #0
illword lda [word],y
;
; Determine whether parameter needs surrounding quotes
;
stz needq
lda [word] If this is a null parameter,
and #$FF
beq appword
if2 @a,eq,#' ',incword
if2 @a,eq,#'&',incword
if2 @a,eq,#'|',incword
if2 @a,eq,#'<',incword
if2 @a,eq,#'>',incword
if2 @a,eq,#';',incword
bra nextword
incword inc count
nextword iny
bra illword
beq qneeded it needs to be quoted.
ldy #0
chkchar if2 @a,eq,#' ',qneeded
if2 @a,eq,#'&',qneeded
if2 @a,eq,#'|',qneeded
if2 @a,eq,#'<',qneeded
if2 @a,eq,#'>',qneeded
if2 @a,eq,#';',qneeded
iny Not special character.
lda [word],y Get next character in parameter.
and #$FF
beq appword Done if null character.
bra chkchar
appword pei (word+2) ;append word to current command line
qneeded inc needq Quotes needed.
;
; Append word to command line (optionally, with quotes)
;
appword anop
pei (word+2)
pei (word)
pei (cmdline+2)
pei (cmdline)
@ -470,35 +488,35 @@ appword pei (word+2) ;append word to current command line
lda #' '
sta [cmdline],y
iny
nospace lda count
nospace lda needq If special char is in parameter,
beq noquote
lda [word]
and #$FF
cmp #'"'
cmp #'"' and it doesn't start with '"',
bne doquote
stz count
stz needq
bra noquote
doquote lda #'"'
doquote lda #'"' add a '"' at start.
sta [cmdline],y
iny
inc count
noquote pei (cmdline+2)
add2 @y,cmdline,@a
pha
jsr copycstr
lda count
jsr copycstr Copy the parameter.
lda needq If quote was added at start,
beq noquote2
pei (cmdline+2)
pei (cmdline)
jsr cstrlen
tay
lda #'"'
lda #'"' add another at end.
sta [cmdline],y
iny
lda #0
sta [cmdline],y
noquote2 inc argc ;increment argument count
goloop jmp loop
;
; Parse a '<' token
;
@ -579,76 +597,95 @@ tok_semi anop
tok_nl anop
tok_eof anop
lda argc
lda argc If number of arguments == 0,
bne nonnull
lda #0
sta [waitpid]
lda #T_NULL
lda srcfile If any of the file pointers
ora srcfile+2 are != NULL,
ora dstfile
ora dstfile+2
ora errfile
ora errfile+2
beq nulldone
ldx #^spcmdstr print error message:
lda #spcmdstr specify a command before redirecting.
jsr errputs
nulldone lda #0 Clear the waitpid
sta [waitpid] and return as if
lda #T_NULL nothing were parsed.
jmp exit
nonnull asl2 a ;terminate the argv list
tay
nonnull asl2 a Terminate the argv list
tay with a null poiner.
lda #0
sta [argv],y
iny2
sta [argv],y
;
; see if there is a conflict between >,>> with |
; See if there is a conflict between > or >> and |
;
lda token
if2 @a,ne,#T_BAR,runit
lda dstfile
ora dstfile+2
beq bar2
lda #err08 ;> or >> conflicts with |
lda #err08 Yes: there is a conflict!
jmp error
bar2 clc
tdc
adc #pipefds
bar2 clc Calculate 32-bit address
tdc of direct page variable
adc #pipefds pipefds in X and A.
ldx #0
pipe @xa
;what if pipes return errors?
pipe @xa Allocate 2 file descriptor pipe
; >> NOTE: what if pipes return errors?
runit pei (argc)
pei (argv+2)
;
; Call invoke param size:name
;
runit pei (argc) 2: argc
pei (argv+2) 4: argv
pei (argv)
pei (srcfile+2)
pei (srcfile+2) 4: sfile
pei (srcfile)
pei (dstfile+2)
pei (dstfile+2) 4: dfile
pei (dstfile)
pei (errfile+2)
pei (errfile+2) 4: efile
pei (errfile)
pei (append)
pei (errappend)
pei (append) 2: app
pei (errappend) 2: eapp
ldx #0
if2 token,ne,#T_AMP,run2
inx
inx 2: bg
run2 phx
pei (cmdline+2)
pei (cmdline+2) 4: cline
pei (cmdline)
pei (jobflag)
pei (inpipe)
pei (pipefds+2)
pei (inpipe2)
pei (pipefds)
pei (pipesem+2)
pei (jobflag) 2: jobflag
pei (inpipe) 2: pipein (param passed in)
pei (pipefds+2) 2: pipeout (allocated: read end)
pei (inpipe2) 2: pipein2 (param passed in)
pei (pipefds) 2: pipeout2 (allocated: write end)
pei (pipesem+2) 4: pipesem (param passed in)
pei (pipesem)
jsl invoke
sta pid
cmp #-1
beq exit
if2 token,ne,#T_BAR,run3 If next token is "|",
pei (waitpid+2) recursively call command.
; If next token is "|", recursively call command.
if2 token,ne,#T_BAR,run3
pei (waitpid+2) 4: waitpid
pei (waitpid)
pei (pipefds)
pei (jobflag)
pei (pipefds+2)
pei (pipesem+2)
pei (pipefds) 2: inpipe
pei (jobflag) 2: jobflag
pei (pipefds+2) 2: inpipe2
pei (pipesem+2) 4: pipesem
pei (pipesem)
pei (stream+2)
pei (stream+2) 4: stream
pei (stream)
jsl command
bra exit
@ -728,6 +765,7 @@ err06 dc c'gsh: Extra ''>&'' or ''>>&'' encountered.',h'0d00'
err07 dc c'gsh: No file specified for ''>&'' or ''>>&''.',h'0d00'
err08 dc c'gsh: ''|'' conflicts with ''>'' or ''>>''.',h'0d00'
err09 dc c'gsh: ''|'' conflicts with ''<''.',h'0d00'
spcmdstr dc c'gsh: Specify a command before redirecting.',h'0d00'
END
@ -766,7 +804,7 @@ free2 pei (argv+2)
**************************************************************************
*
* Interpret a shell script
* Read and execute commands from an exec file (shell script)
* This is overly complicated so that it can be run concurrently.
*
**************************************************************************
@ -802,7 +840,7 @@ end equ path+4
lock mutex
;
; Set the variables 0..argc
; Set the environment variables $0 ... argc
;
lda argc Get number of variables.
jeq vars_set If 0, there are none to set.
@ -853,39 +891,49 @@ set_value anop
jcc parmloop stay in loop.
;
; Variables have all been set
; $0 ... $n environment variables have all been set
;
vars_set unlock mutex
ph4 #4 ;Close parms
;
; Allocate memory for GS/OS calls
;
ph4 #4 CloseGS parms
~NEW
sta CRec
stx CRec+2
ph4 #10 ;Open parms
ph4 #10 OpenGS parameter block
~NEW
sta ORec
stx ORec+2
ph4 #12 ;NewLine parms
ph4 #12 NewLineGS parameter block
~NEW
sta NRec
stx NRec+2
ph4 #16 ;Read parms
ph4 #16 ReadGS parameter block
~NEW
sta RRec
stx RRec+2
ph4 #1000 ;data buffer
ph4 #1000 Data buffer (1000 bytes)
~NEW
sta data
stx data+2
pei (path+2) ;Convert filename to GS/OS string
pei (path)
;
; Set parameters in OpenGS parameter block
;
lda #3 Number of parameters = 3.
sta [ORec]
pei (path+2) Convert exec file
pei (path) pathname to GS/OS string
jsr c2gsstr
ldy #4
ldy #4 Store in PB, offset bytes 4-7.
sta [ORec],y
sta ptr
iny2
@ -893,86 +941,105 @@ vars_set unlock mutex
sta [ORec],y
sta ptr+2
ldy #8
lda #1 ;Read access only
lda #1 Read access only
ldy #8 Store in PB, offset bytes 8-9.
sta [ORec],y
lda #3 ;Open the file
sta [ORec]
pei (ORec+2)
pei (ORec+2) OpenGS(ORec)
pei (ORec)
ph2 #$2010 ;OPEN
ph2 #$2010
jsl $E100B0
bcc ok
sta ErrError
bcc ok If there was an error,
sta ErrError print a message
ErrorGS Err
jmp done
awshit sta ErrError
ErrorGS Err
jmp almostdone
ok ldy #2 Copy file ref num
lda [ORec],y from OpenGS PB into
sta [NRec],y NewLineGS PB,
sta [RRec],y ReadGS PB,
sta [CRec],y and CloseGS PB.
ok ldy #2 ;Copy file ref num
lda [ORec],y
sta [NRec],y
sta [RRec],y
sta [CRec],y
lda #4 ;Do NewLine
;
; Set parameters in NewLineGS parameter block
;
lda #4 Number of parameters = 4.
sta [NRec]
ldy #4
lda #$7F
sta [NRec],y
iny2
lda #1
sta [NRec],y
iny2
lda #NLTable
ldy #4 enableMask
lda #$7F = $7F (each input character
sta [NRec],y is ANDed with this mask)
iny2 numChars
lda #1 = 1 (number of newline chars
sta [NRec],y contained in newline char table)
iny2 newlineTable pointer
lda #NLTable = NLTable
sta [NRec],y
iny2
lda #^NLTable
sta [NRec],y
pei (NRec+2)
pei (NRec)
ph2 #$2011 ;NEWLINE
jsl $E100B0
bcs awshit
lda #4 ;Set up read parm
pei (NRec+2) NewLineGS(NRec)
pei (NRec)
ph2 #$2011
jsl $E100B0
bcc ok2 If there was an error,
sta ErrError print a message
ErrorGS Err
jmp close_ex
;
; Set up ReadGS parameter block
;
ok2 lda #4 Number of parameters = 4
sta [RRec]
tay
lda data
tay dataBuffer (offset 4)
lda data = data
sta [RRec],y
iny2
lda data+2
sta [RRec],y
iny2
lda #1000
iny2 requestCount (offset 4)
lda #999 = 999 (save 1 byte for \0)
sta [RRec],y
iny2
lda #0
sta [RRec],y
;
; Read lines from the exec file
;
ReadLoop anop
pei (RRec+2)
pei (RRec+2) ReadGS(RRec)
pei (RRec)
ph2 #$2012 ;READ
ph2 #$2012
jsl $E100B0
bcs almostdone
ldy #12
bcs close_ex Check for error
ldy #12 Get transferCount
lda [RRec],y
tay
lda #0
tay Store null byte
lda #0 at end of buffer.
sta [data],y
lda varecho
beq noecho
lda varecho If $ECHO environment
beq noecho variable is set,
ldx data+2
lda data
jsr puts
jsr newline
noecho lda [data]
and #$FF
if2 @a,eq,#'#',ReadLoop
jsr puts print the line
jsr newline and a newline.
noecho lda [data] If first character
and #$FF in data buffer is
if2 @a,eq,#'#',ReadLoop "#", read next line.
* call execute: subroutine (4:cmdline,2:jobflag)
pei (data+2)
@ -981,20 +1048,23 @@ noecho lda [data]
jsl execute
sta status
lda exit_requested
bne almostdone
bra ReadLoop
lda exit_requested If exit not requested,
bne close_ex
bra ReadLoop stay in read loop.
almostdone anop
stz exit_requested
lda #1
;
; Close the exec file
;
close_ex anop
lda #1 Number of parameters = 1.
sta [CRec]
pei (CRec+2)
pei (CRec+2) CloseGS(CRec)
pei (CRec)
ph2 #$2014 ;CLOSE
ph2 #$2014
jsl $E100B0
stz exit_requested Clear the "exit gsh" flag.
done pei (CRec+2)
done pei (CRec+2) Free the parameter blocks,
pei (CRec)
jsl nullfree
pei (NRec+2)
@ -1006,15 +1076,17 @@ done pei (CRec+2)
pei (ORec+2)
pei (ORec)
jsl nullfree
pei (data+2)
pei (data+2) data buffer,
pei (data)
jsl nullfree
pei (ptr+2)
pei (ptr+2) and path name.
pei (ptr)
jsl nullfree
;
; Restore stack and return to caller
;
exit1a anop
lda space+1
sta end-2
lda space
@ -1028,7 +1100,8 @@ exit1a anop
lda status Pass back status value.
rtl
NLTable dc h'0d'
NLTable dc h'0d' Newline Table
; Parameter block for shell ErrorGS call (p 393 in ORCA/M manual)
Err dc i2'1' pCount
@ -1135,7 +1208,7 @@ find_end anop
lda [cmdstrt],y Get next character.
and #$FF If at end of string,
beq found_end all done looking.
; Check for special characters
; Check for special quote characters
cmp #"'"
beq s_quote
cmp #'"'
@ -1267,9 +1340,9 @@ loop pea 0 ;Bank 0 waitpid (hi)
clc
adc #pid
pha waitpid (low)
pea 0 inpipe
pea 0 inpipe = 0
pei (jobflag) jobflag
pea 0 inpipe2
pea 0 inpipe2 = 0
pea 0 ;Bank 0 pipesem (hi)
tdc
clc
@ -1283,51 +1356,64 @@ loop pea 0 ;Bank 0 waitpid (hi)
jsl command
sta term
bmi noerrexit
jmi noerrexit
lda pid
beq nowait
jeq donewait
cmp #-1
beq noerrexit
jeq noerrexit
lda jobflag
beq jobwait
jeq jobwait
signal (#SIGINT,#0)
phx
pha
signal (#SIGSTOP,#0)
signal (#SIGTSTP,#0)
phx
pha
otherwait ldx #0
otherwait anop
ldx #0
clc
tdc
adc #waitstatus
wait @xa
wait @xa Wait for child completion.
cmp pid
bne otherwait
lda waitstatus
and #$FF
cmp #$7F
cmp #$7F Check for WSTOPPED status.
beq otherwait
lda waitstatus
jsr setstatus
pla
plx
signal (#SIGSTOP,@xa)
signal (#SIGTSTP,@xa)
pla
plx
signal (#SIGINT,@xa)
bra nowait
bra donewait
jobwait jsl pwait
sta waitstatus
jobwait anop
signal (#SIGCHLD,#pchild) Ensure child sig handler active.
phx Save address of previous sig handler.
pha
kill (pid,#0) If child no longer exists,
beq wait4job
pei pid
jsl removejentry Remove it from the list.
bra setwstat
wait4job jsl pwait Otherwise, wait for it.
setwstat stz waitstatus
pla Restore previous child completion
plx signal handler.
signal (#SIGCHLD,@xa)
; If command detected EOF terminator, all done
nowait if2 term,eq,#T_EOF,noerrexit
donewait if2 term,eq,#T_EOF,noerrexit
lda [exebuf] If not at end of line,
and #$FF
beq exit
@ -1405,11 +1491,11 @@ space equ retval+2
ina return 1 to caller.
;
; Let execute(str) do the work
; Let execute(str,1) do the work
;
makecall pei (str+2)
pei (str)
ph2 #1 ;tells execute we're called by system
ph2 #1 jobflag=1 says we're called by system
jsl execute
;
; Set status and go back to the caller

View File

@ -6,7 +6,7 @@
* Jawaid Bazyar
* Tim Meekins
*
* $Id: dir.asm,v 1.6 1998/09/08 16:53:07 tribby Exp $
* $Id: dir.asm,v 1.7 1998/10/26 17:04:50 tribby Exp $
*
**************************************************************************
*
@ -25,11 +25,11 @@
*
* InitDStack
*
* dirs
* dirs built-in command
*
* pushd
* pushd built-in command
*
* popd
* popd built-in command
*
* path2tilde
*
@ -88,6 +88,7 @@ space equ arg+4
beq showshort
dec a
bne using
ldy #4
lda [argv],y
sta arg
@ -108,12 +109,12 @@ using ldx #^usingstr
jsr errputs
bra exit
showlong jsl dotods
showlong jsl dotods Set top of stack to current directory.
pea 0
jsl showdir
bra exit
showshort jsl dotods
showshort jsl dotods Set top of stack to current directory.
pea 1
jsl showdir
@ -144,46 +145,52 @@ space equ arg+4
subroutine (4:argv,2:argc),space
lda argc
dec a
beq xchange
dec a
bne usage
lda argc Get number of arguments.
dec a If no parameters,
beq xchange exchange top two dirs on stack.
dec a If > 1 parameter,
bne usage print usage string.
ldy #4
lda [argv],y
sta arg
ldy #4 Move parameter pointer from
lda [argv],y argv array to direct
sta arg page variable "arg".
ldy #6
lda [argv],y
sta arg+2
lda [arg]
and #$FF
cmp #'+'
beq rotate
jmp godir
lda [arg] If first character
and #$FF of parameter is
cmp #'+' "+",
beq rotate do the rotate;
jmp godir else push the directory.
;
; More than one parameter provided; print usage string and exit.
;
usage ldx #^usagestr
lda #usagestr
jsr errputs
jmp exit
jmp prerrmsg
xchange lda tods
bne xgoodie
ldx #^err1
lda #err1
jsr errputs
jmp exit
xgoodie jsl dotods
;
; Either no parameter or "+" provided; exchange directory stack entries.
;
xchange lda tods Get index to top of dir stack.
bne xgoodie If 0,
ldx #^err1 print error message
lda #err1 "No other directory"
jmp prerrmsg
xgoodie jsl dotods Set top of stack to current directory.
lda tods
dec a
asl a
asl a
tax
tax X = offset to tos-1.
lda tods
asl a
asl a
tay
lda dirstack,x
tay Y = offset to tos.
lda dirstack,x Swap tos-1 and tos.
pha
lda dirstack,y
sta dirstack,x
@ -195,29 +202,36 @@ xgoodie jsl dotods
sta dirstack+2,x
pla
sta dirstack+2,y
jmp gototop
jmp gototop chdir to the new tos.
;
; Parameter = +n; do the rotate
;
rotate add4 arg,#1,p
pei (p+2)
pei (p)
jsr cstrlen
tax
Dec2Int (p,@x,#0),@a
sta count
cmp #0
beq godir
lda tods
beq roterr
lda count
cmp tods
Dec2Int (p,@x,#0),@a Convert parameter to decimal
sta count and store in count.
cmp #0 If parameter is 0
beq badnum or negative,
bmi badnum report "invalid number".
cmp tods If count >= tos,
beq rotloop
bcc rotloop
roterr ldx #^err2
lda #err2
jsr errputs
jmp exit
roterr ldx #^err2 Print error message:
lda #err2 Directory stack not that deep
jmp prerrmsg
badnum ldx #^errbadnum Print error message:
lda #errbadnum Invalid number
jmp prerrmsg
;
; Loop to rotate entries in directory stack
;
rotloop lda tods
dec a
asl a
@ -244,25 +258,9 @@ nextrot pla
sta dirstack+2
dec count
bne rotloop
bra gototop
godir jsl dotods
pei (arg+2)
pei (arg)
jsl gotodir
bne exit
inc tods
lda tods
asl a
asl a
tay
lda #0
sta dirstack,y
sta dirstack+2,y
jsl dotods
bra done
;
; chdir to the top-of-stack directory
;
gototop lda tods
asl a
asl a
@ -272,17 +270,50 @@ gototop lda tods
lda dirstack,y
pha
jsl gotodir
bra done All done.
done lda varpushdsil
;
; Parameter = directory name; add it to the stack
;
godir anop
lda tods
cmp #MAXD-1 If index >= maximum,
bcc stackok
ldx #^errfull print error message.
lda #errfull
prerrmsg jsr errputs
bra exit
stackok anop
jsl dotods Set top of stack to current directory.
pei (arg+2)
pei (arg)
jsl gotodir chdir to the parameter directory.
bne exit
inc tods Bump the top of stack pointer.
lda tods
asl a
asl a
tay
lda #0
sta dirstack,y
sta dirstack+2,y
jsl dotods Set top of stack to current directory.
done lda varpushdsil If $PUSHDSILENT not defined,
bne exit
pea 1
jsl showdir
jsl showdir show the directory stack.
exit return 2:#0
usagestr dc c'usage: pushd [+n | dir]',h'0d00'
err1 dc c'pushd: No other directory',h'0d00'
err2 dc c'pushd: Directory stack not that deep',h'0d00'
errfull dc c'pushd: Directory stack full',h'0d00'
errbadnum dc c'pushd: Invalid number',h'0d00'
END
@ -348,7 +379,7 @@ pluserr ldx #^err2
jsr errputs
bra exit
doplus jsl dotods
doplus jsl dotods Set top of stack to current directory.
sub2 tods,count,@a
asl a
asl a
@ -502,35 +533,39 @@ space equ idx+2
subroutine (2:flag),space
lda tods
asl a
asl a
lda tods Get directory stack index.
asl a Multiply by four to
asl a get byte offset (idx).
sta idx
loop lda flag
loop lda flag If parameter == 1,
beq long
ldy idx
lda dirstack+2,y
lda dirstack+2,y print entry
pha
lda dirstack,y
pha
jsl path2tilde
phx
jsl path2tilde but first substitute "~"
phx for home directory.
pha
jsr puts
jsl nullfree
bra next
long ldy idx
lda dirstack+2,y
long ldy idx else,
lda dirstack+2,y print full entry.
tax
lda dirstack,y
jsr puts
next lda #' '
next lda #' ' Print a space.
jsr putchar
lda idx
lda idx If idx != 0,
beq done
sub2 idx,#4,idx
bra loop
sub2 idx,#4,idx idx = idx -4
bra loop handle next entry.
done jsr newline
@ -555,7 +590,7 @@ space equ idx+2
subroutine (0:dummy),space
lda tods Get index number.
asl a Multiply by four
asl a Multiply index by four
asl a to get byte offset.
sta idx Store in idx
tay and Y-register.

View File

@ -6,7 +6,7 @@
* Jawaid Bazyar
* Tim Meekins
*
* $Id: edit.asm,v 1.6 1998/09/08 16:53:08 tribby Exp $
* $Id: edit.asm,v 1.7 1998/10/26 17:04:50 tribby Exp $
*
**************************************************************************
*
@ -121,23 +121,33 @@ nextchar jsr cursoron
jsr flush
jsr getchar
sta 4
ldx signalled
ldx signalled If signal was received,
beq nextchar2
jsr cmdsig
; bra cmdloop
jsr cmdsig acknowledge it.
nextchar2 jsr cursoroff
lda 4
cmp #-1
lda 4 Get results of getchar.
cmp #-1 EOF?
beq eof
cmp #4 ;CTL-D
bne findcmd
cmp #4 CTL-D? (treated same as EOF)
beq eof
cmp #$FF00 Error?
bcc findcmd
and #$00FF
sta ErrError
ErrorGS Err yes--print error code.
bra reterr
;
; Parameter block for shell ErrorGS call (p 393 in ORCA/M manual)
;
Err dc i2'1' pCount
ErrError ds 2 Error number
eof ldx cmdlen
bne findcmd
lda varignore
bne findcmd
jsr cursoron
reterr jsr cursoron
ioctl (#1,#TIOCSETP,#oldsgtty)
ioctl (#1,#TIOCSETK,#oldttyk)
ioctl (#1,#TIOCSLTC,#oldltc)
@ -243,6 +253,7 @@ cmdov2 lda insertflag
cmp #0
bne cmdov2a
rts
cmdov2a ldx #0
cmdov3 if2 @y,eq,cmdlen,cmdov4
lda cmdline,y

View File

@ -66,13 +66,13 @@
MEND
********************
* getpgrp
* _getpgrp
********************
MACRO
&lab getpgrp &a1
&lab _getpgrp &a1
&lab ph2 &a1
case on
jsl getpgrp
jsl _getpgrp
case off
MEND

View File

@ -1,7 +1,7 @@
/*
* Resources for version and comment
*
* $Id: gsh.rez,v 1.5 1998/09/08 16:53:09 tribby Exp $
* $Id: gsh.rez,v 1.6 1998/10/26 17:04:50 tribby Exp $
*/
#define PROG "gsh"
@ -16,7 +16,7 @@
resource rVersion (1, purgeable3) {
{ 2, 0, 0, /* Version 2.0.0 */
development, /* development|alpha|beta|final|release */
4 }, /* non-final release number */
5 }, /* non-final release number */
verUS, /* Country */
PROG, /* Program name */
DESC

View File

@ -6,7 +6,7 @@
* Jawaid Bazyar
* Tim Meekins
*
* $Id: invoke.asm,v 1.7 1998/09/08 16:53:10 tribby Exp $
* $Id: invoke.asm,v 1.8 1998/10/26 17:04:50 tribby Exp $
*
**************************************************************************
*
@ -28,7 +28,7 @@
* returns with carry set/clear to indicate failure/success
*
* invoke 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:eapp,2:bg,4:cline,2:jobflag,2:pipein,2:pipeout,
* 2:pipein2,2:pipeout2,4:pipesem)
* return 2:rtnval
*
@ -225,117 +225,111 @@ p equ 0
biflag equ p+4
ptr equ biflag+2
rtnval equ ptr+4 Return pid, -1 (error), or 0 (no fork)
dir equ rtnval+2
space equ dir+4
cpath equ rtnval+2
space equ cpath+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
subroutine (2:argc,4:argv,4:sfile,4:dfile,4:efile,2:app,2:eapp,2:bg,4:cline,2:jobflag,2:pipein,2:pipeout,2:pipein2,2:pipeout2,4:pipesem),space
ld2 -1,rtnval
stz biflag ;not a built-in
stz biflag Clear built-in flag.
lda argc Get number of arguments.
bne chknull If != 0 continue with processing.
lda sfile If any of the file pointers
ora sfile+2 are != NULL,
ora dfile
ora dfile+2
ora efile
ora efile+2
beq nulldone
ldx #^spcmdstr print error message:
lda #spcmdstr ' specify a command before redirecting.'
jsr errputs
nulldone jmp done
lda argc If number of arguments == 0,
bne chknull nothing to do. (Shouldn't happen
nulldone jmp done because invoke checks argc==0).
;
; Check for null command
;
chknull ldy #2 Move command line
chknull ldy #2 Move 1st argument
lda [argv] pointer to
sta dir dir (4 bytes).
sta cpath cpath (4 bytes).
lda [argv],y
sta dir+2 If pointer == NULL
ora dir
sta cpath+2 If pointer == NULL
ora cpath
beq nulldone all done.
lda [dir] If first character == '\0',
lda [cpath] If first character == '\0',
and #$FF
beq nulldone all done.
;
; check for file
; Check command: is it builtin, in hash table, etc?
;
checkfile anop
pei (dir+2)
pei (dir)
jsl IsBuiltin ;check builtin first
cmp #-1
pei (cpath+2) IsBuiltin returns
pei (cpath) 0 if forked built-in
jsl IsBuiltin 1 if non-forked built-in
cmp #-1 -1 if not a built-in
jne trybuiltin
;
; Command is not listed in the built-in table. See if it was hashed
pei (dir+2)
pei (dir)
;
pei (cpath+2)
pei (cpath)
ph4 hash_table
ph4 #hash_paths
jsl search
cmp #0
bne changeit
cpx #0
beq skip
beq noentry
changeit sta dir
stx dir+2
changeit sta cpath Use full path from
stx cpath+2 hash table.
skip lock mutex2
pei (dir+2)
pei (dir)
;
; Get information about the command's filename
;
noentry lock info_mutex
pei (cpath+2)
pei (cpath)
jsr c2gsstr
sta GRecPath
sta ptr
stx GRecPath+2
stx ptr+2
GetFileInfo GRec
unlock mutex2
jcs notfound
; File type $B5 is a GS/OS Shell application (EXE)
unlock info_mutex
jcs notfound If error getting info, print error.
; Is file type $B5: GS/OS Shell application (EXE)?
if2 GRecFileType,eq,#$B5,doExec
; File type $B3 is a GS/OS application (S16)
; Is file type $B3: GS/OS application (S16)?
if2 @a,eq,#$B3,doExec
ldx vardirexec
ldx vardirexec If $NODIREXEC isn't set, and
bne ft02
cmp #$0F
jeq doDir Target is a directory; change to it.
jeq doDir file is a directory: change to it.
; File type $B0 is a source code file (SRC)
; Is file type $B0: source code file (SRC)?
ft02 if2 @a,ne,#$B0,badfile
; Type $B0, Aux $00000006 is a shell command file (EXEC)
if2 GRecAuxType,ne,#6,badfile
if2 GRecAuxType+2,ne,#0,badfile
jmp doShell
badfile ldx dir+2
lda dir
;
; Command file is not an appropriate type
;
badfile ldx cpath+2
lda cpath
jsr errputs
ldx #^err1 Print error message:
lda #err1 'Not executable.'
jsr errputs
free pei (ptr+2)
pei (ptr)
free pei (ptr+2) Free memory used to hold
pei (ptr) GS/OS string with path.
jsl nullfree
jmp done
;
; launch an executable
;
*
* ---------------------------------------------------------------
*
* Launch an executable (EXE or S16 file)
doExec pei (ptr+2)
pei (ptr)
jsl nullfree
@ -344,11 +338,13 @@ doExec pei (ptr+2)
jsr postfork
jmp done
invoke0 phk
plb
;
; make a copy of cmd
; Forked shell starts here...
;
invoke0 phk Make sure data bank register
plb is the same as program bank.
;
; Make copies of command line (cline) and path (cpath) for child
;
pha
pha
@ -362,7 +358,7 @@ invoke0 phk
lda [1],y ;This is the UserID!
and #$F0FF
pha
ph4 _cmd
ph4 _cline
jsr cstrlen
inc a
ply
@ -371,7 +367,7 @@ invoke0 phk
NewHandle (@xa,@y,#$4018,#0),1
ply
ldx #0
PtrToHand (_cmd,1,@xy)
PtrToHand (_cline,1,@xy)
ldy #2
lda [1],y
tax
@ -379,10 +375,8 @@ invoke0 phk
pld
ply
ply
phx ;_cmd
phx ;_cline
pha
;
; make a copy of dir
;
pha
pha
@ -396,7 +390,7 @@ invoke0 phk
lda [1],y ;This is the UserID!
and #$F0FF
pha
ph4 _dir
ph4 _cpath
jsr cstrlen
inc a
ply
@ -405,7 +399,7 @@ invoke0 phk
NewHandle (@xa,@y,#$4018,#0),1
ply
ldx #0
PtrToHand (_dir,1,@xy)
PtrToHand (_cpath,1,@xy)
ldy #2
lda [1],y
tax
@ -413,24 +407,32 @@ invoke0 phk
pld
ply
ply
phx ;_dir
phx ;_cpath
pha
jsl infork
bcs invoke1
;
; Call _execve(_cpath,_cline) to replace forked shell with executable file
;
case on
jsl _execve For 2.0.6: call _execve, not execve
case off
rtl
;
; Error reported by infork; clean up stack and return to caller
;
invoke1 pla
pla
pla
pla
rtl
;
; Next command is a directory name, so change to that directory
;
*
* ---------------------------------------------------------------
*
* Next command is a directory name, so change to that directory
doDir lock cdmutex
mv4 GRecPath,PRecPath
SetPrefix PRec
@ -438,10 +440,13 @@ doDir lock cdmutex
stz rtnval Return value: no fork done.
jmp free
;
; Next command is a shell command file: fork a shell script
;
doShell inc biflag ;don't free argv...
*
* ---------------------------------------------------------------
*
* Next command is a shell command file: fork a shell script
doShell anop
inc biflag ;don't free argv...
jsr prefork
* int fork2(void *subr, int stack, int prio, char *name, word argc, ...)
@ -458,26 +463,32 @@ doShell inc biflag ;don't free argv...
jsl fork2
case off
* fork #exec0
jsr postfork
jmp free
exec0 ph2 _argc ;for argfree
;
; Forked shell starts here...
;
exec0 anop
ph2 _argc ;for argfree
ph4 _argv
ph4 _dir ;for shellexec
ph4 _cpath ShellExec parameters
ph2 _argc
ph4 _argv
jsl infork
bcs exec0c
signal (#SIGCHLD,#0)
PushVariablesGS NullPB
pea 1
pea 1 jobflag = 1
jsl ShellExec
jsl argfree
PopVariablesGS NullPB
rtl
;
; Error reported by infork; clean up stack and return to caller
;
exec0c pla
pla
pla
@ -511,8 +522,8 @@ trybuiltin inc biflag It's a built-in. Which type?
;
; Control transfers here for a forked built-in command
;
forkbuiltin cop $7F Give palloc a chance
forkbuiltin anop
cop $7F Give palloc a chance
ph2 _argc
ph4 _argv
jsl infork
@ -520,12 +531,15 @@ forkbuiltin cop $7F Give palloc a chance
jsl builtin
rtl
;
; Error reported by infork; clean up stack and return to caller
;
fork0c pla
pla
pla
rtl
* ---------------------------------------------------------------
;
; It's a non-forked builtin
@ -558,46 +572,59 @@ notfound pei (ptr+2)
lda pipein
beq notfound0
; Input being piped into a command that was not found.
ssignal _semaphore
sdelete _semaphore
mv4 pjoblist,p
ldy #16 ;p_jobid
lda [p],y
getpgrp @a
lda [p],y Get forked process's pid.
_getpgrp @a Get forked process's group number.
eor #$FFFF
inc a
kill (@a,#9)
kill (@a,#9) Kill all processes in that group.
sigpause #0
notfound0 anop
done cop $7F
lda biflag
lda biflag If built-in flag is clear,
bne skipfrarg
pei (argc)
pei (argc) free arguments.
pei (argv+2)
pei (argv)
jsl argfree
skipfrarg pei (cmd+2)
pei (cmd)
skipfrarg pei (cline+2) Free command-line.
pei (cline)
jsl nullfree
return 2:rtnval
* ---------------------------------------------------------------
*
* Support routines
*
* ---------------------------------------------------------------
;
; Tasks to do just before forking
;
; stuff to do just before forking
;
prefork lock mutex
prefork lock fork_mutex Lock the fork mutual exclusion.
SetInGlobals (#$FF,#00)
;
; Move essential parameters from stack to mutual-exclusion protected memory
;
mv4 sfile,_sfile
mv4 dfile,_dfile
mv4 efile,_efile
mv2 app,_app
mv2 eapp,_eapp
mv4 cmd,_cmd
mv4 dir,_dir
mv4 cline,_cline
mv4 cpath,_cpath
mv2 argc,_argc
mv4 argv,_argv
mv2 pipein,_pipein
@ -608,73 +635,87 @@ prefork lock mutex
mv2 jobflag,_jobflag
lda [pipesem]
sta _semaphore
lda pipesem
sta putsem+1
lda pipesem+1
lda pipesem Set address of
sta putsem+1 semaphone in
lda pipesem+1 LDA instruction.
sta putsem+2
rts
* ---------------------------------------------------------------
;
; stuff to do right after forking
; Tasks the parent process does right after forking
;
postfork sta rtnval
lda pipein
lda pipein If pipein != 0,
beq postfork2
sta CloseRef
Close CloseParm
postfork2 lda pipeout
Close CloseParm close pipein.
postfork2 lda pipeout If pipeout != 0,
beq postfork3
sta CloseRef
Close CloseParm
postfork3 lda rtnval
Close CloseParm close pipeout.
postfork3 lda rtnval If return value == -1,
cmp #-1
bne postfork4
ldx #^deadstr Print error message:
lda #deadstr 'Cannot fork (too many processes?)'
ldx #^deadstr Print error message:
lda #deadstr 'Cannot fork (too many processes?)'
jsr errputs
unlock mutex
jmp done
unlock fork_mutex Unlock the fork mutual exclusion.
jmp postfork6 Return to caller.
postfork4 ldx jobflag
dex
beq postfork5
pha
beq postfork5 If jobflag == 1,
pha
pei (bg)
pei (cmd+2)
pei (cmd)
lda pipein
pei (cline+2)
pei (cline)
lda pipein if pipein == 0,
bne postfork4a
jsl palloc
bra postfork5
postfork4a jsl pallocpipe
postfork5 lda >mutex ;DANGER!!!!! Assumes knowledge of
jsl palloc palloc(0,cline)
bra postfork5 else
postfork4a jsl pallocpipe pallocpipe(0,cline)
postfork5 anop
;
; Wait for fork mutual exclusion lock to clear (cleared by infork)
;
lda >fork_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
;
; Startup tasks by forked process
;
infork phk Make sure data bank register
plb is the same as program bank.
lda _jobflag If jobflag == 0,
bne infork0b
Open ttyopen
jcs doneinfork
jcs errinfork
lda _pipein
bne invoke0a
tcnewpgrp ttyref
invoke0a settpgrp ttyref
lda _bg ;if in background then reset tty to
bne infork0a If not in pipeline,
tcnewpgrp ttyref allocate new process group.
infork0a settpgrp ttyref Set current process to have proc group.
lda _bg If in background,
and #$FF
beq invoke0b ;to the shell process group
tctpgrp (gshtty,gshpid)
beq infork0b
tctpgrp (gshtty,gshpid) reset tty to the shell process group.
invoke0b ph4 _sfile
infork0b ph4 _sfile Redirect I/O
ph4 _dfile
ph4 _efile
ph2 _app
@ -684,40 +725,58 @@ invoke0b ph4 _sfile
ph2 _pipein2
ph2 _pipeout2
jsl redirect
jcs doneinfork
jcs errinfork
unlock mutex
unlock fork_mutex
;
; Wait on appropriate pipe semaphores
;
lda _pipein
bne invoke0c
bne infork0c
lda _pipeout
beq invoke0d
screate #0
putsem sta >$FFFFFF
swait @a
bra invoke0d
invoke0c lda _pipeout
bne invoke0d
waitsemy lda _semaphore
beq clean_exit
;
; _pipein == 0 && _pipeout != 0
;
screate #0 Create a semaphore with count=0.
putsem sta >$FFFFFF Store semaphore number in pipesem.
swait @a Block on semaphore until ssignal.
bra clean_exit
infork0c lda _pipeout
bne clean_exit
;
; _pipein != 0 && _pipeout != 0
;
waitsemy lda _semaphore While _semaphore == 0,
bne goodsemy
cop $7F
cop $7F allow other processes to run.
bra waitsemy
goodsemy ssignal _semaphore
sdelete _semaphore
invoke0d anop
goodsemy ssignal _semaphore Release _semaphore
sdelete _semaphore and delete it.
clean_exit anop
clc
bra indone
;
; Arrive at "errinfork" if ttyopen or redirect didn't work.
;
errinfork unlock fork_mutex
; sec Note: carry already set
doneinfork unlock mutex
sec
indone rtl
indone rtl Return to caller; status in carry.
mutex key
mutex2 key
cdmutex key
fork_mutex key Mutual exclusion for forking
info_mutex key Mutual exclusion for GetFileInfo
cdmutex key Mutual exclusion for SetPrefix
;
; Variables protected by fork_mutex (set by parent, used by child process)
;
_argc dc i2'0'
_argv dc i4'0'
_sfile dc i4'0'
@ -725,8 +784,8 @@ _dfile dc i4'0'
_efile dc i4'0'
_app dc i2'0'
_eapp dc i2'0'
_cmd dc i4'0'
_dir dc i4'0'
_cline dc i4'0'
_cpath dc i4'0'
_pipein dc i2'0'
_pipeout dc i2'0'
_pipein2 dc i2'0'
@ -735,10 +794,12 @@ _bg dc i2'0'
_jobflag dc i2'0'
_semaphore dc i2'0'
;
; String constants
;
str dc c'[0]',h'0d00'
err1 dc c': Not executable.',h'0d00'
err2 dc c': Command not found.',h'0d00'
spcmdstr dc c'Specify a command before redirecting.',h'0d00'
deadstr dc c'Cannot fork (too many processes?)',h'0d00' ;try a spoon
@ -759,6 +820,7 @@ CloseRef dc i2'0'
Err dc i2'0'
; Parameter block for opening tty
ttyopen dc i2'2'
ttyref dc i2'0'
dc i4'ttyname'

View File

@ -6,7 +6,7 @@
* Jawaid Bazyar
* Tim Meekins
*
* $Id: jobs.asm,v 1.6 1998/09/08 16:53:10 tribby Exp $
* $Id: jobs.asm,v 1.7 1998/10/26 17:04:50 tribby Exp $
*
**************************************************************************
*
@ -96,55 +96,73 @@ end equ space+3
phd
tcd
getpid
getpid Get process ID.
sta waitpid
waitloop ldx #%0000000000001010
;
; Start of loop that waits for child processes to complete
;
waitloop anop
; Block signals 15 (SIGTERM), 18 (SIGTSTP), and 20 (SIGCHLD):
; Bit 3 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
; Num 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1
; X/A 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ldx #%0000000000001010
lda #%0100000000000000
sigblock @xa
sta oldsig
sta oldsig Save the previous signal mask.
stx oldsig+2
lda pjoblist
lock plistmutex Ensure list doesn't change.
lda pjoblist Start pointer at head of job list.
ldx pjoblist+2
loop sta p
loop sta p Save job entry pointer in p.
stx p+2
ora p+2
beq done
ldy #p_flags
ora p+2 If pointer is 0,
beq done all done.
ldy #p_flags Get entry's job status flags.
lda [p],y
and #PFOREGND+PRUNNING
cmp #PFOREGND+PRUNNING
bne loop2
ldy #p_pid
bne getnext
ldy #p_pid Get entry's process ID.
lda [p],y
cmp waitpid
beq loop2
beq getnext
; check if the process is actually running..if it is not, report to the
; user that a stale process was detected and remove it from job control.
sigsetmask oldsig
sigpause #0
bra waitloop
loop2 ldy #p_next+2
unlock plistmutex
sigsetmask oldsig Restore previous signal mask.
sigpause #0 Wait for a signal to arrive.
bra waitloop Start searching the entire list.
getnext ldy #p_next+2 Get pointer to next entry
lda [p],y
tax
ldy #p_next
lda [p],y
bra loop
bra loop and stay in loop.
done sigsetmask oldsig
;
; Arrive here when p == 0
;
done unlock plistmutex
sigsetmask oldsig Restore previous signal mask.
pld
tsc
pld Reset direct page and
tsc stack pointers.
clc
adc #end-4
tcs
rtl
rtl Return to caller.
END
@ -205,7 +223,9 @@ end equ pid+2
phd
tcd
ldx #%0000000000001000
lock plistmutex Ensure list doesn't change.
ldx #%0000000000001000 Block SIGCHILD signals.
lda #%0000000000000000
sigblock @xa
phx
@ -284,6 +304,8 @@ in02 anop
sta [pp],y
jsr copycstr
unlock plistmutex
lda bg
beq noprint
pei (pp+2)
@ -294,7 +316,7 @@ in02 anop
noprint anop
case on
jsl sigsetmask
jsl sigsetmask Restore signal mask.
case off
lda space
@ -340,6 +362,8 @@ end equ pid+2
phd
tcd
lock plistmutex Ensure list doesn't change.
ldx #%0000000000001000
lda #%0000000000000000
sigblock @xa
@ -423,6 +447,8 @@ addit ldy #p_friends
lda pp+2
sta [p],y
unlock plistmutex
case on
jsl sigsetmask
case off
@ -486,7 +512,7 @@ end equ code+2
;
; search for the job that has finished.
;
search lda pjoblist
lda pjoblist
ldx pjoblist+2
lookloop sta p
stx p+2
@ -554,10 +580,11 @@ kill ldy #p_flags
jsr setstatus
bra zap
zap0 inc signalled
zap ldy #p_index
lda [p],y
zap ldy #p_pid Remove the job entry
lda [p],y by referring to its pid.
pha
jsl removejob
jsl removejentry
ldy #p_flags
lda [p],y
bit #PFOREGND
@ -578,9 +605,11 @@ done anop
rtl
;--------------------------------------------------------------------
;
; Set $status return variable
;
setstatus ENTRY
xba Isolate status
@ -631,21 +660,21 @@ valstat_text dc c'000' Text (up to three digits)
;====================================================================
;
; remove a job
; remove an entry in the job list, based on process number
;
;====================================================================
removejob START
removejentry START
using pdata
p equ 1
prev equ p+4
space equ prev+4
jobnum equ space+3
end equ jobnum+2
pid equ space+3 process id
end equ pid+2
; subroutine (2:jobnum),space
; subroutine (2:pid),space
tsc
sec
@ -656,40 +685,43 @@ end equ jobnum+2
stz prev
stz prev+2
lock plistmutex Ensure list doesn't change.
lda pjoblist
ldx pjoblist+2
loop sta p
loop sta p Get next entry in job list.
stx p+2
ora p+2
jeq done
ldy #p_index
ora p+2 If null pointer,
jeq done all done.
ldy #p_pid Get job/pid number in entry.
lda [p],y
cmp jobnum
cmp pid If it's not the one we're looking for,
beq gotit
lda p
lda p Set prev to this entry.
sta prev
stx prev+2
ldy #p_next+2
lda [p],y
lda [p],y Set X/A to next entry.
tax
ldy #p_next
lda [p],y
bra loop
bra loop Check next entry.
;
; adjust linked list pointers
; Entry found: adjust linked list pointers
;
gotit ora2 prev,prev+2,@a
gotit ora2 prev,prev+2,@a If prev != NULL,
beq gotit2
ldy #p_next
ldy #p_next prev->next = p->next
lda [p],y
sta [prev],y
ldy #p_next+2
lda [p],y
sta [prev],y
bra gotit3
gotit2 ldy #p_next
lda [p],y
gotit2 ldy #p_next else
lda [p],y pjoblist = p->next
sta pjoblist
ldy #p_next+2
lda [p],y
@ -698,12 +730,11 @@ gotit2 ldy #p_next
; free the node (may want to check currjob and prevjob pointers)
;
gotit3 anop
ldy #p_flags
ldy #p_flags If PFOREGND status bit is set,
lda [p],y
and #PFOREGND
bne gotit3c
jsr newline
jsr newline Print the job entry
ldy #p_flags
lda #0
sta [p],y
@ -712,36 +743,37 @@ gotit3 anop
pea 0
pea 0
jsl pprint
gotit3c anop
ldy #p_command+2
lda [p],y
gotit3c anop
ldy #p_command+2 Free memory used to hold
lda [p],y command string.
pha
dey2
lda [p],y
pha
jsl nullfree
lda pcurrent
lda pcurrent If pcurrent != p
eor pcurrent+2
eor p
eor p+2
bne gotit3a
mv4 pprevious,pcurrent
stz pprevious
mv4 pprevious,pcurrent pcurrent = pprevious
stz pprevious pprevious = NULL
stz pprevious+2
lda prev
lda prev If prev != pcurrent,
eor prev+2
eor pcurrent
eor pcurrent+2
beq gotit3a
mv4 prev,pprevious
gotit3a lda pprevious
mv4 prev,pprevious pprevious = prev
gotit3a lda pprevious If pprevious != p,
eor pprevious+2
eor p
eor p+2
bne gotit3b
stz pprevious
stz pprevious pprevious == NULL
stz pprevious+2
gotit3b anop
@ -751,18 +783,19 @@ gotit4 ldy #p_friends
ldy #p_friends+2
lda [p],y
pha
pei (p+2)
pei (p+2) Free memory used to hold entry.
pei (p)
jsl nullfree
pla
sta P+2
pla p = p->p_friends
sta p+2
pla
sta p
ora p+2
beq gotit5
ldy #p_command+2
lda [p],y
beq gotit5 If p != NULL,
ldy #p_command+2 Free memory used to
lda [p],y hold text of command
pha
ldy #p_command
lda [p],y
@ -772,7 +805,7 @@ gotit4 ldy #p_friends
gotit5 anop
;
; find maximum job number
; find maximum job number and set pmaxindex
;
stz prev
lda pjoblist
@ -792,9 +825,11 @@ skipmax ldy #p_next+2
ldy #p_next
lda [p],y
bra fmaxloop
gotmax mv2 prev,pmaxindex
done anop
unlock plistmutex
lda space+1
sta end-2
lda space
@ -1215,7 +1250,6 @@ dofg1 lda [p],y
lda [p],y
bit #PSTOPPED
beq dofg2
; lda [p],y
eor #PSTOPPED
sta [p],y
pei (p+2)
@ -1225,7 +1259,7 @@ dofg1 lda [p],y
jsl pprint
ldy #p_jobid
lda [p],y
getpgrp @a
_getpgrp @a
eor #$FFFF
inc a
kill (@a,#SIGCONT)
@ -1313,26 +1347,20 @@ loop ora2 p,p+2,@a
dofg ldy #p_flags
lda [p],y
bit #PRUNNING
; cmp #PRUNNING
; bne dofg1
beq dofg1
ldx #^err02
lda #err02
bra puterr
dofg1 anop
; lda [p],y
dofg1 anop note: Y = #p_flags, A = [p],y
ora #PRUNNING
sta [p],y
bit #PFOREGND
beq dobg0
; lda [p],y
eor #PFOREGND
sta [p],y
dobg0 anop
; lda [p],y
bit #PSTOPPED
beq dofg2
; lda [p],y
eor #PSTOPPED
sta [p],y
tctpgrp (gshtty,gshpid)
@ -1343,7 +1371,7 @@ dobg0 anop
jsl pprint
ldy #p_jobid
lda [p],y
getpgrp @a
_getpgrp @a
eor #$FFFF
inc a
kill (@a,#SIGCONT)
@ -1411,6 +1439,7 @@ getit2 ldy #4+2
sta pid
cmp #-1
jeq nojob
mv4 pjoblist,p
loop ora2 p,p+2,@a
jeq nojob
@ -1437,7 +1466,7 @@ dofg ldy #p_flags
dofg1 tctpgrp (gshtty,gshpid)
ldy #p_jobid
lda [p],y
getpgrp @a
_getpgrp @a
eor #$FFFF
inc a
kill (@a,#SIGSTOP)
@ -1731,6 +1760,8 @@ done return 2:pid
pdata DATA
plistmutex key Mutual exclusion for job list
pwaitsem dc i2'0'
pjoblist dc i4'0' ;job list

View File

@ -6,7 +6,7 @@
* Jawaid Bazyar
* Tim Meekins
*
* $Id: shell.asm,v 1.6 1998/09/08 16:53:13 tribby Exp $
* $Id: shell.asm,v 1.7 1998/10/26 17:04:51 tribby Exp $
*
**************************************************************************
*
@ -225,10 +225,10 @@ didit anop
pha
lda [p]
pha
ph2 CmdArgc
pei (p+2)
ph2 CmdArgc argc
pei (p+2) argv
pei (p)
pea 0
pea 0 jobflag = 0
jsl ShellExec
jmp done1
@ -238,9 +238,9 @@ cmdskip lda ExecFlag
;
; The -e flag is set: execute remaining arguments as a command and exit.
;
ph4 ExecCmd
ph2 #0
jsl Execute
ph4 ExecCmd cmdline
ph2 #0 jobflag = 0
jsl execute
jmp done1
;
@ -289,8 +289,8 @@ gnoloop entry
jsr newlineX
jsr flush
ph4 #cmdline
ph2 #0
ph4 #cmdline execute(cmdline,0)
ph2 #0 jobflag = 0
jsl execute
lda exit_requested

View File

@ -6,7 +6,7 @@
* Jawaid Bazyar
* Tim Meekins
*
* $Id: stdio.asm,v 1.5 1998/09/08 16:53:14 tribby Exp $
* $Id: stdio.asm,v 1.6 1998/10/26 17:04:51 tribby Exp $
*
**************************************************************************
*
@ -300,8 +300,12 @@ getchar START
readloop Read inReadParm
bcc okread
ldy #-1 ;return EOF on ALL errors
jmp done2
ldy #-1 Return EOF if error code
cmp #$4C is "EOF encountered".
beq go_done2
ora #$FF00 For all other errors,
tay hi-byte is $FF, low-byte is error.
go_done2 jmp done2
okread stz inindex
lda insize

View File

@ -6,7 +6,7 @@
* Jawaid Bazyar
* Tim Meekins
*
* $Id: term.asm,v 1.6 1998/09/08 16:53:14 tribby Exp $
* $Id: term.asm,v 1.7 1998/10/26 17:04:51 tribby Exp $
*
**************************************************************************
*
@ -149,8 +149,11 @@ ok jsl nullfree Free buffer allocated by getenv.
sta termok
mv4 areabuf,area
;
; Get addresses of termcap strings
;
tgetstr (#isid,#area)
jsr puts
jsr puts Send initialization string to term.
tgetstr (#leid,#area)
sta lecap
stx lecap+2
@ -187,7 +190,10 @@ ok jsl nullfree Free buffer allocated by getenv.
tgetstr (#usid,#area)
sta uscap
stx uscap+2
;
; Bind keyboard characters
;
tgetstr (#klid,#area)
phx
pha
@ -223,23 +229,27 @@ ok jsl nullfree Free buffer allocated by getenv.
termname gsstr 'term'
error1 dc c'Error reading termcap file!',h'0d0d00'
error2 dc c'Termcap entry not found for ',h'00'
isid dc c'is',h'00'
leid dc c'le',h'00'
ndid dc c'nd',h'00'
veid dc c've',h'00'
viid dc c'vi',h'00'
vsid dc c'vs',h'00'
blid dc c'bl',h'00'
clid dc c'cl',h'00'
soid dc c'so',h'00'
seid dc c'se',h'00'
klid dc c'kl',h'00'
krid dc c'kr',h'00'
kuid dc c'ku',h'00'
kdid dc c'kd',h'00'
cdid dc c'cd',h'00'
ueid dc c'ue',h'00'
usid dc c'us',h'00'
;
; Termcap identification strings
;
isid dc c'is',h'00' Initialization
leid dc c'le',h'00' Out of keypad transmit mode
ndid dc c'nd',h'00' Non-destructive space
veid dc c've',h'00' Normal cursor visible
viid dc c'vi',h'00' Cursor unvisible
vsid dc c'vs',h'00' Standout cursor
blid dc c'bl',h'00' Bell
clid dc c'cl',h'00' Clear screen and home cursor
soid dc c'so',h'00' Begin standout mode
seid dc c'se',h'00' End standout mode
cdid dc c'cd',h'00' Clear to end of display
ueid dc c'ue',h'00' End underscore mode
usid dc c'us',h'00' Begin underscore mode
klid dc c'kl',h'00' Left arrow key
krid dc c'kr',h'00' Right arrow key
kuid dc c'ku',h'00' Up key
kdid dc c'kd',h'00' Down key
sgtty anop
dc i1'0'