📄 krun5.asm
字号:
;*
;* COW : Character Oriented Windows
;*
;* krun5.asm : Run/Exec
TITLE KRUN - Kernel RUN
include kernel.inc
include uevent.inc
;----------------------------------------------------------------------------
cbArgMax equ 79+1+3+128+2 ; Max size pszArg to DosExecPgm.
; 79 = max comspec filename size
; 1 = sepearating zero.
; 3 = "/C "
; 128 = max real argument size
; 2 = 00 00 terminating bytes.
;----------------------------------------------------------------------------
sBegin KERNEL
assumes DS,KERNEL
;* * data that MUST be in code space
;* * code strings
staticB szComspec, <"COMSPEC", 0> ; COMSPEC name (note: no '=' for OS/2)
staticB szCmdProg, <"\CMD.EXE", 0> ; if COMSPEC not found
sEnd KERNEL
;----------------------------------------------------------------------------
externFP <PeekMessage>
externFPublic <LeaveCow,BackToCow> ;* in INIT
externFP <DosExecPgm>
externFP <DosScanEnv>
externFP <VioWrtTty>
externFP <EnableKeyboard>
sBegin KERNEL
assumes CS,KERNEL
assumes DS,NOTHING
assumes SS,DATA
;********** RerrExec **********
;* entry : szCmd = program name (or NULL => shell)
;* pchParm = parameter string:
;* Byte-length prefixed, 0Dh terminated.
;* Null is invalid, use 01,"0Dh" for subshell.
;* Use <length> "/C xxxxx" when szCmd == NULL.
;* rgchPrompt = "Press a key to resume MangoSoft$"; -1 if none.
;* fClearScreen = whether to clear it or not.
;* fRestoreScreenMode = whether to reset mode on way back in.
;* exit : AX = 0 if ok, AX != 0 if error (interpreted as "rerr" code,
;* (see kmem.h).
;* DX = return code of child process (undefined if AX != 0)
assumes CS,KERNEL
assumes DS,DGROUP
assumes ES,NOTHING
assumes SS,DATA
cPublic RerrExec, <>, <SI,DI,DS> ;* NOT ATOMIC !
parmDP szCmd
parmDP pchParm
parmDP rgchPrompt ; Dollar-sign terminated!
parmW fClearScreen
parmW fRestoreScreenMode
localV msgScreen,cbMsgMin
localV pszArgs,cbArgMax ; Where we'll build arg string.
localD lszProgram ; far pointer to Comspec
localD ReturnCodes ; 1st word = Termination code from OS/2.
; 2nd word = Result code from child process.
cBegin RerrExec
AssertData DS ; Make sure that ss=ds.
;------ Push the first three arguments to DosExecPgm.
xor bx,bx
push ss ; pchFailName. We don't use the name
push bx ; in any case, so give null buffer.
push bx ; cbFailName = 0.
push bx ; AsyncTraceFlags = synchronous.
mov SEG_lszProgram,ss ; If szCmd is not Null,
mov ax,szCmd ; then that's the program
mov OFF_lszProgram,ax ; that we'll exec.
or ax,ax
jnz @F ; Otherwise, we go for a Comspec.
push cs
push kernelOffset szComspec ; Hey OS/2, go look for "COMSPEC".
push ss
lea ax,lszProgram ; Where OS/2 will put ptr to Comspec.
push ax
call DosScanEnv
or ax,ax ; Jump if OS/2 found it.
jz @F
mov SEG_lszProgram,cs ; Guess: use \CMD.EXE
mov OFF_lszProgram,kernelOffset szCmdProg ; for Comspec.
@@:
; At this point, all we've done is get lszProgram containing the segment and
; offset of the program we'll be Exec'ing, whether it be our program itself,
; the Comspec, or our best guess at a Comspec.
;
; Now build the pszArgs string. Non-direct / Comspec types look like this:
;
; "c:\os2\pbin\cmd.exe" 00 "/c ourprog /arg1 /arg2" 00 00
;
; Direct / non-Comspec types look like this:
;
; "ourprog" 00 "/arg1 /arg2" 00 00
push ds
mov ax,ss
mov es,ax
assumes es,DATA
lea di,pszArgs ; es:si -> buffer.
lds si,lszProgram ; ds:si -> program we'll exec
assumes DS,NOTHING
@@: lodsb ; Transfer over the entire program
stosb ; name, and the 0 byte at the end.
or al,al
jnz @B
pop ds
assumes DS,DGROUP
AssertNE pchParm,0 ; Null is bogus.
mov si,pchParm ; ss:si = ds:si -> the parameters
xor ax,ax
lodsb ; al = count, ah = 00.
AssertNe al,0 ; Have to at least have the 0D byte.
dec ax ; Don't transfer the 0D at the end.
mov cx,ax ; cx = count
rep movsb ; Move over the argument string.
mov es:[di],cx ; Finish it off with a double 0 byte.
; --------------------------------------
push ss ; Our mondo big and complicated
lea ax,pszArgs ; local buffer
push ax
push cx ; EnvPointer = 0000:0000 -
push cx ; inherit the parent's env.
push ss ; Address of DWord buffer where OS/2
lea ax,ReturnCodes ; will put Termination Code and
push ax ; Result Code of the child.
push SEG_lszProgram ; Address of ASCIIZ string specifying
push OFF_lszProgram ; drive and dir of prog to execute
mov ax,2
; ----------------------- ; Do at the last minute:
cCall LeaveCow, <fClearScreen> ; Leave & maybe clear
; ----------------------- ; the screen.
call DosExecPgm ; Do it.
push ax
cCall EnableKeyboard, <sp>
pop cx ; DosExecPgm return code.
jcxz @F
mov ax,2 ; Guess it'll be one of these errors:
cmp cx,3 ; If "Path not found", then no error
je NoFile ; messages.
cmp cx,ax ; If "File not found", then no error
je NoFile ; messages.
cmp cx,00BFh ; If ERROR_INVALID_EXE_SIGNATURE
je NoFile ; then treat like "file not found".
AssertEq cx,0
@@:
; -----------------------
mov di,rgchPrompt ; ds:di -> "Press a key$"
cmp di,-1
je NoPrompt
mov ax,ds
mov es,ax
assumes es,DGROUP
push ax ; ax:di -> "Press a key$"
push di
mov ax,0124h ; al = "$"
mov cx,ax ; Assumption: the "Press a key to
repne scasb ; "resume" string is < 292 bytes.
AssertZR
sub ax,cx
dec ax ; Don't count the "$".
push ax ; Length of the string.
push 0 ; VioHandle
call VioWrtTty
AssertEq ax,0 ; Shouldn't err.
@@: AssertData DS ; Make sure that ss=ds.
lea ax,msgScreen ; Wait until we get a message
push ax
call PeekMessage ; that's a character.
or ax,ax
jz @B
cmp [msgScreen.messageMsg],WM_CHAR
jne @B
NoPrompt:
mov ax,OFF_ReturnCodes ; return 1st word = termination code
NoFile:
; -----------------------
push ax ; This calls an INIT proc
cCall BackToCow,<fRestoreScreenMode> ; in the INIT segment.
pop ax
; -----------------------
mov dx,SEG_ReturnCodes ; return 2nd word = child result code
cEnd RerrExec
sEnd KERNEL
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -