NEW
  AUTO 3,1
*--------------------------------------
				.DUMMY
				.OR ZPTMP+8				7 Bytes
PS.Flags		.BS 1
PS.ArgV			.BS 2
PS.ArgSize		.BS 2
PS.NewPSPtr		.BS 2
				.ED
*/--------------------------------------
* # ExecL
* ## C / CSH
* `int execl(const char *cmdline, short int flags);`
* ## ASM
* `>PUSHW cmdline`
* `>PUSHB flags`
* `>SYSCALL execl`
* ## RETURN VALUE
* A = Child PSID
*\--------------------------------------
K.ExecL			>PULLB PS.Flags
				
				>LDYAI 256
				jsr K.GetMem
				bcs .99

				stx .90+1
				>STYA PS.ArgV
				>PUSHYA
				jsr K.Arg2ArgV			cmdline on stack, push buffer
				bcs .9

				jsr PS.Exec
.9				php
				pha
.90				lda #$ff				SELF MODIFIED
				jsr K.FreeMem
				pla
				plp
.99				rts
*/--------------------------------------
* # ExecV
* ## C / CSH
* `int execv(const char* argv[], short int flags);`
* ## ASM
* `>PUSHW argv`
* `>PUSHB flags`
* `>SYSCALL execv`
* ## RETURN VALUE
* A = Child PSID
*\--------------------------------------
K.ExecV			>PULLB PS.Flags
				>PULLW PS.ArgV
				
PS.Exec			jsr PS.CreateChild		A=PID,Child S.PS at PS.NewPSPtr,PS.Load.hMem
				bcs .9
				sta .8+1

				stz K.IOBuf				If !=0 after PS.Load, it's a script
				jsr PS.Load
				bcs .90

				jsr PS.AddArgV			K.IOBuf= /.../SHELL, K.Buf256=/.../SCRIPT
				bcc .8					or K.IOBuf= 0, K.Buf256=/.../BINFILE
.90				pha						save error code
				>PUSHBI 2
				lda .8+1
				jsr K.Kill
				pla						get back error code
				sec
				rts

.8				lda #$ff				SELF MODIFIED
*				clc
.9				rts
*/--------------------------------------
* # Fork
* ## C
* `short int fork();`
* ## ASM
* `>SYSCALL fork`
* ## RETURN VALUE
* A = Child PSID
*\--------------------------------------
K.Fork			clc
				rts
*--------------------------------------
* PS.CreateChild
*  in :
*  out :
*   A = PSID
*--------------------------------------
PS.CreateChild	ldx #0
				bra .2					Skip PS0
.1				lda PS.Table.PID,x
				beq .4					Found an empty slot
.2				inx
				cpx CORE.PSCount
				bne .1
				cpx #K.PS.MAX
				bne .3
				lda #E.OOH
				sec
				rts

.99				plx
				rts
.3				inc CORE.PSCount
.4				inc CORE.LastPSID		Get a PSID not already running
				beq .4					not = 0
				lda CORE.LastPSID
				jsr CORE.GetPS			Y=PS Index, X,A unmodified
				bcc .4					running...loop

				lda CORE.LastPSID
				sta PS.Table.PID,x
				phx						save PS Index
				>LDYAI S.PS
				jsr K.GetMem0			Blank Everything in this S.PS
				bcs .99
				>STYA PS.NewPSPtr
				txa
				plx
				sta PS.Table.hPS,x
				jsr Mem.SetOwner		Set Ownership

				lda PS.Flags
				and #S.PS.F.CLOSEONX
				sta (PS.NewPSPtr)

				lda CORE.LastPSID
				ldy #S.PS.PID
				sta (PS.NewPSPtr),y
				lda #S.PS.F.NOHUP
				bit PS.Flags
				beq .5
				lda PS.Table.hPS		Select PS0
				jsr K.GetMemPtr
				bra .6
.5				>LDYA pPs
.6				>STYA ZPPtr1
				ldy #S.PS.PID
				lda (ZPPtr1),y
				dey						#S.PS.PPID
				sta (PS.NewPSPtr),y

				ldy #S.PS.hCWD		copy hPREFIX...
				lda (ZPPtr1),y
				jsr K.GetMemPtr

				jsr K.StrDup
				bcs .9
				jsr Mem.SetOwner		Set Ownership

				txa
				ldy #S.PS.hCWD
				sta (PS.NewPSPtr),y

				ldy #S.PS.hENV
				lda (ZPPtr1),y
				
				jsr MEM.DupX			dup hENV from parent PS
				bcs .9

				ldy #S.PS.hENV
				sta (PS.NewPSPtr),y

				ldy #S.PS.hStdIn

.7				lda (ZPPtr1),y
				sta (PS.NewPSPtr),y
				iny
				cpy #S.PS.hStdErr+1
				bne .7
				ldy #S.PS.hSID
				lda (ZPPtr1),y
				sta (PS.NewPSPtr),y

				tax
				lda S.Table.hSession-1,x
				jsr MEM.GetMemByID
				jsr MEM.IncRefCnt

				lda #S.PS.F.HOLD
				bit PS.Flags
				beq .8
				ora (ZPPtr1)
				sta (ZPPtr1)			HOLD parent PS
				lda CORE.LastPSID
				ldy #S.PS.CPID
				sta (ZPPtr1),y
.8
*				lda #S.PS.S.INIT
*				ldy #S.PS.S 
*				sta (PS.NewPSPtr),y		Make this PS Init....

				lda CORE.LastPSID		Exit with A=PSID
				clc
				rts
.9				pha
				>PUSHBI 2
				lda	CORE.LastPSID
				jsr K.Kill
				pla
				sec
				rts
*--------------------------------------
PS.Load			ldy #$ff

.1				iny
				lda (PS.ArgV),y
				beq .2					no / in path...try search in PATH

				cmp #'/'
				bne .1

				>PUSHW PS.ArgV			found /, some path specified, no search
				>PUSHWI K.S.STAT
				>SYSCALL2 stat
				bcc .6					REAL path in K.Buf256

.99				rts

.2				>LDYA PS.ArgV

				jsr ENV.Search.PATH		Get fullpath in K.Buf256
				bcc .6

				>LDYA PS.ArgV
				jsr ENV.Search.CWD
				bcs .99

.6				lda K.S.STAT+S.STAT.P.TYPE
				cmp #S.FI.T.BIN
				bne .7
				jmp PS.LoadBIN

.7				cmp #S.FI.T.TXT
				beq PS.Load.SCRIPT

*				cmp #S.FI.T.SYS
*				bra *

PS.Load.IPATH	lda #E.BADPATH
				.HS 2C
PS.Load.IBIN	lda #E.IBIN
				sec
PS.Load.RTS		rts

PS.Load.SCRIPT	ldx #$ff

.10				inx						Save Script name in IOBuf
				lda K.Buf256,x
				sta K.IOBuf,x
				bne .10
				jsr PS.LoadGetHeader
				bcs PS.Load.RTS

				>PUSHWI PS.Load.ROOT
				>PUSHWI K.Buf256		K.Buf256 = "$ROOT"
				>SYSCALL2 GetEnv
				bcs PS.Load.IPATH

				ldx #$ff

.1				inx
				lda K.Buf256,x
				bne .1

				ldy #0

.3				lda K.IOBuf+128,y		Check HEADER= "#!/"
				cmp PS.Load.HEADER,y
				bne PS.Load.IBIN
				iny
				cpy #3
				bne .3

.4				iny
				inx
				lda K.IOBuf+128-1,y
				sta K.Buf256-1,x		K.Buf256 = "${ROOT}BIN/SHELL"
				beq .5

				eor #C.CR
				bne .4 
	
				sta K.Buf256-1,x		K.Buf256 = "${ROOT}BIN/SHELL\0"

.5				>PUSHWI K.Buf256
				>PUSHWI K.S.STAT
				>SYSCALL2 stat
				bcs PS.Load.RTS

				lda K.S.STAT+S.STAT.P.TYPE
				cmp #S.FI.T.BIN
				beq PS.LoadBIN
				jmp PS.Load.IBIN
*--------------------------------------
PS.LoadBIN		jsr BIN.Load			K.Buf256= "${ROOT}BIN/SH\0", K.IOBuf=/.../SCRIPT
				bcs .9

				>STYA ZPPtr4			save PTR to Code Segment
			
				phy
				ldy #S.PS.ZP.CODE+1
				sta (PS.NewPSPtr),y			save pCode HI...
				dey
				pla
				sta (PS.NewPSPtr),y			save pCode LO...
				txa
				ldy #S.PS.hCS
				sta (PS.NewPSPtr),y			save CS hMem in S.PS

*				jsr MEM.GetMemByID
*				jsr Mem.SetOwner		Set Ownership

				ldy #H.BIN.F			Get Bin S.PS.F
				lda (ZPPtr4),y
				beq .1
				ldy #S.PS.F				update PS S.PS.F
				ora (PS.NewPSPtr),y
				sta (PS.NewPSPtr),y

.1				ldy #H.BIN.DS.SIZE+1
				lda (ZPPtr4),y			Load DS.SIZE HI
				tax
				dey	
				ora (ZPPtr4),y

				beq .2					DS.SIZE=0...

				lda (ZPPtr4),y
				tay
				txa						Y,A = DS.SIZE
				ldx #S.MEM.F.INIT0+S.MEM.F.DATA
				jsr MEM.GetMem.YAX
				bcs .9

				phy
				ldy #S.PS.ZP.DATA+1
				sta (PS.NewPSPtr),y		save pData HI...
				dey
				pla
				sta (PS.NewPSPtr),y		save pData LO...

				txa
				ldy #S.PS.hDS
				sta (PS.NewPSPtr),y		save DS hMem in S.PS

				jsr Mem.SetOwner		Set Ownership

.2				ldy #H.BIN.SS.SIZE
				lda (ZPPtr4),y			Load SS.SIZE

				tay
				beq .3					SS.SIZE.LO=0, set as default $100

				lda #$ff				SS.SIZE.HI

.3				inc

				ldx #S.MEM.F.NOCROSS+S.MEM.F.STACK
				jsr MEM.GetMem.YAX
				bcs .9

				phy						save pStack base LO
				ldy #S.PS.ZP.STACK+1
				sta (PS.NewPSPtr),y		save pStack HI...

				ldy #S.PS.ZP.LOCAL+1
				sta (PS.NewPSPtr),y		save pLocal HI...

				pla						make pStack = Base...
				ldy #H.BIN.SS.SIZE		...plus Stack size
*				clc
				adc (ZPPtr4),y
				
				ldy #S.PS.ZP.STACK
				sta (PS.NewPSPtr),y

				txa
				ldy #S.PS.hSS
				sta (PS.NewPSPtr),y		save SS hMem in S.PS
				clc						Potentially CS from ADC (ZPPtr4),y
				jmp  Mem.SetOwner		Set Ownership
.9				rts
*--------------------------------------
PS.LoadGetHeader
				>PUSHWI K.IOBuf
				>PUSHBI	O.RDONLY
				>PUSHBI S.FI.T.TXT
				>PUSHWZ					Aux type
				>SYSCALL2 fopen
				bcs .9

				sta .1+1

				>PUSHWI 128
				>PUSHWI K.IOBuf+128
.1				lda #$ff				SELF MODIFIED
				>SYSCALL2 fread
				php
				pha
				lda .1+1
				>SYSCALL2 fclose
				pla
				plp
.9				rts
*--------------------------------------
PS.Load.ROOT	.AZ "ROOT"
PS.Load.HEADER	.AZ "#!/"
*--------------------------------------
* K.Buf256= /.../SHELL, K.IOBuf=/.../SCRIPT
* - or - 
* K.Buf256=/.../BINFILE,K.IOBuf=0 
* Buf256+IOBUF(?)+PS.ArgV[1,...] -> #S.PS.hARGV
*--------------------------------------
PS.AddArgV		ldy #$ff				In both cases, remove ARGV[0]

.60				iny
				lda (PS.ArgV),y
				bne .60

				tya
				sec
				adc PS.ArgV
				sta PS.ArgV
				bcc .70

				inc PS.ArgV+1			Skip old ARGV[0] = scriptename

.70				>LDYAI K.Buf256
				jsr K.strlen

				>STYA PS.ArgSize

				lda K.IOBuf				is there a /BIN/SHELL ?
				beq .10

				>LDYAI K.IOBuf
				jsr K.strlen
				jsr PS.AddYAp12ArgSize

.10				ldx #0					For now, 0 args...
				lda K.IOBuf
				beq .11					+1 for scriptpath

				inx

.11				>LDYA PS.ArgV
				>STYA ZPPtr1

.1				lda (ZPPtr1)
				beq .4

				inx

				ldy #0

.2				iny
				lda (ZPPtr1),y
				bne .2

*				lda #0
				jsr PS.AddYAp12ArgSize
				jsr SHARED.AddYp1ToPtr1
				bra .1

.4				txa
				ldy #S.PS.ARGC
				sta (PS.NewPSPtr),y

				>LDYA PS.ArgSize		Add 1 for ending 0
				iny
				bne .5
				inc

.5				iny						Add ONE MORE ?????!!!!
				bne .51
				inc

.51				jsr K.GetMem
				bcs .9

				>STYA ZPPtr2			Target Buffer
				txa
				ldy #S.PS.hARGV
				sta (PS.NewPSPtr),y

				>LDYAI K.Buf256
				jsr PS.AddYAToStrV
				lda K.IOBuf
				beq .6

				>LDYAI K.IOBuf
				jsr PS.AddYAToStrV

.6				>LDYA PS.ArgV
				>STYA ZPPtr1

.7				lda (ZPPtr1)
				sta (ZPPtr2)
				beq .8					Ending \0

				jsr PS.AddPtr1ToStrV
				bra .7

.8				clc
.9				rts
*--------------------------------------
PS.AddYAToStrV	>STYA ZPPtr1
PS.AddPtr1ToStrV
				ldy #$ff

.2				iny
				lda (ZPPtr1),y
				sta (ZPPtr2),y
				bne .2

				jsr SHARED.AddYp1ToPtr1
				jmp SHARED.AddYp1ToPtr2
*--------------------------------------
PS.AddYAp12ArgSize
				pha
				tya
				sec						+1 for \0
				adc PS.ArgSize
				sta PS.ArgSize
				pla
				adc PS.ArgSize+1
				sta PS.ArgSize+1
				rts
*/--------------------------------------
* # Kill
* ## C
* `int kill(short int pid, short int sig);`
* ## ASM
* `>PUSHB sig`
* `lda pid`
* `>SYSCALL kill`
* ## RETURN VALUE
* A = Child PSID
*\--------------------------------------
K.Kill.PID		.BS 1
*--------------------------------------
K.Kill			cmp #0
				beq .99					CS

				sta K.Kill.PID
				jsr CORE.GetPSByID
				bcs .99

				>STYA ZPPtr1
				>PULLA
				cmp #2+1
				bcs .9

				asl
				tax
				jmp (.1,x)
.1				.DA K.Kill.0
				.DA K.Kill.1
				.DA K.Kill.2

.9				lda #E.SYN
*				sec
				rts
.99				>RET 1
*--------------------------------------
K.Kill.1		ldy #S.PS.S
				lda #S.PS.S.QUIT
				sta (ZPPtr1),y

K.Kill.0		clc
				rts

K.Kill.2		ldy #S.PS.hSID
				lda (ZPPtr1),y
				tax
				lda S.Table.hSession-1,x
				jsr K.FreeMem

				ldy #S.PS.hENV
				lda (ZPPtr1),y
				>SYSCALL2 FreeStkObj
				
				ldx #4

.11				ldy .10,x
				lda (ZPPtr1),y
				beq .12

				jsr K.FreeMem

.12				dex
				bpl .11

				lda (ZPPtr1)
				bit #S.PS.F.CLOSEONX
				beq .1

				ldy #S.PS.hStdOut
				lda (ZPPtr1),y
				>SYSCALL2 fclose

.1				lda K.Kill.PID

				ldx #0
.2				cmp PS.Table.PID,x
				beq .3

				inx
				cpx CORE.PSCount
				bne .2
				bra *
.3				stz PS.Table.PID,x
				lda PS.TABLE.hPS,x
				stz PS.TABLE.hPS,x
				jmp K.FreeMem

.10				.DA #S.PS.hSS,#S.PS.hDS,#S.PS.hCS
				.DA #S.PS.hARGV,#S.PS.hCWD
*/--------------------------------------
* # LoadTxtFile
* Load TXT a file in memory (with ending 0)
* ## C
* `int loadtxtfile ( const char * filename, short int flags, short int ftype, int auxtype );`
* ## ASM
* **In:**
* `>PUSHW filename`
* `>PUSHB flags`
* `>PUSHB ftype`
* `>PUSHW auxtype`
* `>SYSCALL loadtxtfile`
* ## RETURN VALUE
*  Y,A = File Length (without ending 0)
*  X = hMem of Loaded File
*\--------------------------------------
				.DUMMY
				.OR ZPTMP				5 Bytes
FIO.bTXT		.BS 1
FIO.hFILE		.BS 1
FIO.MemPtr		.BS 2
FIO.hMem		.BS 1
				.ED
*--------------------------------------
K.LoadTxtFile	sec
				.HS 90					BCC
*/--------------------------------------
* # LoadFile
* Load a file in memory
* ## C
* `int loadfile ( const char * filename, short int flags, short int ftype, int auxtype );`
* ## ASM
* **In:**
* `>PUSHW filename`
* `>PUSHB flags`
* `>PUSHB ftype`
* `>PUSHW auxtype`
* `>SYSCALL loadfile`
* ## RETURN VALUE
*  Y,A = File Length
*  X = hMem of Loaded File
*\--------------------------------------
K.LoadFile		clc
				
				ror FIO.bTXT
				>SYSCALL2 FOpen
				bcs .9

.12				sta FIO.hFILE

				>PUSHA
				>PUSHWI K.S.Stat
				>SYSCALL2 FStat
				bcs .11

				lda K.S.Stat+S.STAT.SIZE+3
				ora K.S.Stat+S.STAT.SIZE+2
				bne .10

				>LDYA K.S.Stat+S.STAT.SIZE

				bit FIO.bTXT		Add 1 to buffer size for ending 0
				bpl .1
				iny
				bne .1
				inc
				bne .1
.10				lda #E.FTB
.11				bra .99

.1				jsr K.GetMem
				bcs .99
				>STYA FIO.MemPtr
				stx FIO.hMem
				>PUSHW K.S.Stat+S.STAT.SIZE
				>PUSHW FIO.MemPtr
				lda FIO.hFILE
				>SYSCALL2 FRead

				bcc .2
				pha
				lda FIO.hMem
				jsr K.FreeMem
				pla
.99				pha
				lda FIO.hFILE
				>SYSCALL2 FClose
				pla
				sec
.9				rts

.2				sty .7+1
				sta .8+1
				bit FIO.bTXT
				bpl .5

				pha						set ending 0
				tya

*				clc

				adc FIO.MemPtr
				sta .4+1
				pla
				adc FIO.MemPtr+1
				sta .4+2
.4				stz $ffff				Self Modified

.5				jsr .99					close file

.7				ldy #$ff				SELFMODIFIED
.8				lda #$ff				SELFMODIFIED
				ldx FIO.hMem
				clc
				rts
*/--------------------------------------
* # FileSearch
* Search a file in the provided PATH list
* And return, if found, the full path to it.
* ## C
* `int filesearch( char *filename, char *searchpath, char *fullpath, stat *filestat);`
* ## ASM
* **In:**
* `>PUSHW filename`
* `>PUSHW fullpath`
* `>PUSHW searchpath`
* `>PUSHW filestat`
* `>SYSCALL filesearch`
* ## RETURN VALUE
* CC : success
* DstBuf = FilePath
* DstStat = S.STAT
* CS : not found
*\--------------------------------------
K.FileSearch	>PULLW .4+1				DstStat
				>PULLW .2+1				DstBuf
				>PULLW ENV.Search.2+1	path to search
				>PULLW ENV.Search.4+1	filename to find
				
				stz ENV.Search.98+1
				
				jsr ENV.Search
				bcs K.FileSearch.RTS

				ldx #$ff
.1				inx
				lda K.Buf256,x
.2				sta $ffff,x				Self Modified
				bne .1
				ldx #S.STAT-1
.3				lda K.S.STAT,x
.4				sta $ffff,x				Self Modified
				dex
				bpl .3
*				clc
K.FileSearch.RTS
				rts
*--------------------------------------
ENV.Search.CWD	>STYA ENV.Search.4+1	filename to find
				ldy #S.PS.hCWD
				lda (PS.NewPSPtr),y
				jsr K.GetMemPtr
				>STYA ENV.Search.2+1
				
				stz ENV.Search.98+1
				
				bra ENV.Search
				
ENV.Search.LIB	ldx #0
				.HS 2C					BIT ABS
ENV.Search.DRV	ldx #2
				.HS 2C					BIT ABS
ENV.Search.PATH	ldx #4

				>STYA ENV.Search.4+1	filename to find

				>PUSHW ENV.VARS,x
				>PUSHWI 0				allocate...
				>SYSCALL2 GetEnv		get value for Search Path
				bcs K.FileSearch.RTS

				>STYA ENV.Search.2+1
				stx ENV.Search.98+1

ENV.Search		stz ENV.Search.1+1
			
ENV.Search.1	ldy #0					Self Modified Index in Search list string

				ldx #0

ENV.Search.2	lda $ffff,y				SELF MODIFIED

				beq ENV.Search.3		end of string, try it....

				iny
				cmp #':'
				beq ENV.Search.3

				sta K.Buf256,x
				inx
				bra ENV.Search.2

ENV.Search.3	txa
				beq ENV.Search.98		String is empty....nothing to try

				sty ENV.Search.1+1		save current index

				ldy #0

ENV.Search.4	lda $ffff,y				Self Modified, Append Filename...
				sta K.Buf256,x
				beq ENV.Search.5

				iny
				inx
				bra ENV.Search.4

ENV.Search.5	>PUSHWI K.Buf256
				>PUSHWI K.S.STAT
				>SYSCALL2 stat
				bcs ENV.Search.1		Failed...retry next path...

				lda K.S.STAT+S.STAT.P.TYPE
				cmp #S.FI.T.DIR				Dir ?
				beq ENV.Search.1
				jsr ENV.Search.98			Discard Expanded hSrch list

				clc
				rts

ENV.Search.98	lda #$ff					SELF MODIFIED : Discard  Search list
				beq .1
				
				jsr K.FreeMem

.1				lda #MLI.E.FNOTFND
				sec
				rts
*--------------------------------------
ENV.VARS		.DA .1
				.DA .2
				.DA .3
.1				.AZ "LIB"
.2				.AZ "DRV"
.3				.AZ "PATH"
*/--------------------------------------
* # GetMemStat
* **In:**
*  Y,A = Ptr to 24 bytes buffer
* ## RETURN VALUE
*  Buffer filled with memory stats
*\--------------------------------------
K.GetMemStat	>STYA ZPPtr1

				ldy #23
				ldx #7
.1				lda DevMgr.Stat,x
				sta (ZPPtr1),y
				dey
				dex
				bpl .1
				sta SETREADAUX
				jsr .2
				sta CLRREADAUX
.2				ldx #7
.3				lda Mem.Table,x
				sta (ZPPtr1),y
				dey
				dex
				bpl .3
				clc
				rts
*--------------------------------------
MAN
SAVE USR/SRC/SYS/KERNEL.S.PS
LOAD USR/SRC/SYS/KERNEL.S
ASM
