diff --git a/bin/gsh/To.Do b/bin/gsh/To.Do index d3b2d36..1461c4e 100644 --- a/bin/gsh/To.Do +++ b/bin/gsh/To.Do @@ -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. diff --git a/bin/gsh/UpdateLog b/bin/gsh/UpdateLog index f9f54ac..ae6fcf9 100644 --- a/bin/gsh/UpdateLog +++ b/bin/gsh/UpdateLog @@ -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. diff --git a/bin/gsh/builtin.asm b/bin/gsh/builtin.asm index eedf670..f0331bf 100644 --- a/bin/gsh/builtin.asm +++ b/bin/gsh/builtin.asm @@ -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 ************************************************************************** * diff --git a/bin/gsh/cmd.asm b/bin/gsh/cmd.asm index e304a9b..23f84e1 100644 --- a/bin/gsh/cmd.asm +++ b/bin/gsh/cmd.asm @@ -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 +* 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 diff --git a/bin/gsh/dir.asm b/bin/gsh/dir.asm index 1f39bf1..4f53707 100644 --- a/bin/gsh/dir.asm +++ b/bin/gsh/dir.asm @@ -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. diff --git a/bin/gsh/edit.asm b/bin/gsh/edit.asm index 9b0abe2..6cdba09 100644 --- a/bin/gsh/edit.asm +++ b/bin/gsh/edit.asm @@ -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 diff --git a/bin/gsh/gsh.mac b/bin/gsh/gsh.mac index 1ceca9f..fb7a2a1 100644 --- a/bin/gsh/gsh.mac +++ b/bin/gsh/gsh.mac @@ -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 diff --git a/bin/gsh/gsh.rez b/bin/gsh/gsh.rez index 2a6c3b5..6711a50 100644 --- a/bin/gsh/gsh.rez +++ b/bin/gsh/gsh.rez @@ -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 diff --git a/bin/gsh/invoke.asm b/bin/gsh/invoke.asm index 1660c47..0c2fb42 100644 --- a/bin/gsh/invoke.asm +++ b/bin/gsh/invoke.asm @@ -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' diff --git a/bin/gsh/jobs.asm b/bin/gsh/jobs.asm index b120f24..84e2c62 100644 --- a/bin/gsh/jobs.asm +++ b/bin/gsh/jobs.asm @@ -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 diff --git a/bin/gsh/shell.asm b/bin/gsh/shell.asm index 5ecfe28..7575ea9 100644 --- a/bin/gsh/shell.asm +++ b/bin/gsh/shell.asm @@ -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 diff --git a/bin/gsh/stdio.asm b/bin/gsh/stdio.asm index 1217191..1c31e7d 100644 --- a/bin/gsh/stdio.asm +++ b/bin/gsh/stdio.asm @@ -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 diff --git a/bin/gsh/term.asm b/bin/gsh/term.asm index c2e0f47..2adf695 100644 --- a/bin/gsh/term.asm +++ b/bin/gsh/term.asm @@ -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'