From Lucho: enable interactive re-execution of the SHELL.

git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@795 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Bart Oldeman 2004-03-07 12:19:43 +00:00
parent d61defe941
commit 3e3c05ff22
7 changed files with 122 additions and 48 deletions

View File

@ -152,6 +152,9 @@ VOID ASMCFUNC FAR int2a_handler(void);
VOID ASMCFUNC FAR int2f_handler(void);
VOID ASMCFUNC FAR cpm_entry(void);
/* kernel.asm */
VOID ASMCFUNC FAR init_call_p_0(struct config FAR *Config); /* P_0, actually */
/* main.c */
VOID ASMCFUNC FreeDOSmain(void);
BOOL init_device(struct dhdr FAR * dhp, char * cmdLine,

View File

@ -89,6 +89,36 @@ segment HMA_TEXT
_intr:
INTR
;; COUNT ASMCFUNC res_DosExec(COUNT mode, exec_blk * ep, BYTE * lp)
global _res_DosExec
_res_DosExec:
mov ah, 4bh
mov bx, sp
mov al, [bx+2]
push ds
pop es
mov dx, [bx+6] ; filename
mov bx, [bx+4] ; exec block
int 21h
jc short no_exec_error
xor ax, ax
no_exec_error:
ret
;; UCOUNT ASMCFUNC res_read(int fd, void *buf, UCOUNT count);
global _res_read
_res_read:
mov bx, sp
mov cx, [bx+6]
mov dx, [bx+4]
mov bx, [bx+2]
mov ah, 3fh
int 21h
jnc no_read_error
mov ax, -1
no_read_error:
ret
segment INIT_TEXT
;
; void init_call_intr(nr, rp)

View File

@ -673,6 +673,10 @@ _swap_indos:
; _swap_indos but only if int2a ah=80/81 (critical section start/end)
; are called upon entry and exit of the device drivers
times 96 dw 0x9090 ; Process 0 Stack
global _p_0_tos
_p_0_tos:
segment DYN_DATA
global _Dyn
@ -830,6 +834,11 @@ _reloc_call_clk_driver:
_CharMapSrvc: jmp 0:_reloc_call_CharMapSrvc
call near forceEnableA20
global _init_call_p_0
extern reloc_call_p_0
_init_call_p_0: jmp 0:reloc_call_p_0
call near forceEnableA20
global __HMARelocationTableEnd
__HMARelocationTableEnd:

View File

@ -336,17 +336,14 @@ STATIC VOID signon()
STATIC void kernel()
{
exec_blk exb;
CommandTail Cmd;
int rc;
exb.exec.env_seg = DOS_PSP + 8;
if (master_env[0] == '\0') /* some shells panic on empty master env. */
strcpy(master_env, "PATH=.");
fmemcpy(MK_FP(exb.exec.env_seg, 0), master_env, sizeof(master_env));
fmemcpy(MK_FP(DOS_PSP + 8, 0), master_env, sizeof(master_env));
/* process 0 */
/* Execute command.com /P from the drive we just booted from */
/* Execute command.com from the drive we just booted from */
memset(Cmd.ctBuffer, 0, sizeof(Cmd.ctBuffer));
memcpy(Cmd.ctBuffer, Config.cfgInitTail, sizeof(Config.cfgInitTail));
@ -356,7 +353,8 @@ STATIC void kernel()
/* if stepping CONFIG.SYS (F5/F8), tell COMMAND.COM about it */
if (Cmd.ctCount < sizeof(Cmd.ctBuffer) - 3)
/* 3 for string + 2 for "\r\n" */
if (Cmd.ctCount < sizeof(Cmd.ctBuffer) - 5)
{
char *insertString = NULL;
@ -376,55 +374,16 @@ STATIC void kernel()
{
if (*p == ' ' || *p == '\t' || *p == '\r')
{
for (q = &Cmd.ctBuffer[Cmd.ctCount - 1]; q >= p; q--)
for (q = &Cmd.ctBuffer[Cmd.ctCount + 1]; q >= p; q--)
q[3] = q[0];
memcpy(p, insertString, 3);
Cmd.ctCount += 3;
break;
}
}
strcpy(Config.cfgInitTail, Cmd.ctBuffer); /* save buffer */
}
}
exb.exec.cmd_line = (CommandTail FAR *) & Cmd;
exb.exec.fcb_1 = exb.exec.fcb_2 = (fcb FAR *) 0xfffffffful;
#ifdef DEBUG
printf("Process 0 starting: %s\n\n", Config.cfgInit);
#endif
while ((rc =
init_DosExec(Config.cfgP_0_startmode, &exb,
Config.cfgInit)) != SUCCESS)
{
BYTE *pLine;
printf("\nBad or missing Command Interpreter: %d - %s\n", rc,
Cmd.ctBuffer);
printf
("\nPlease enter the correct location (for example C:\\COMMAND.COM):\n");
rc = read(STDIN, Cmd.ctBuffer, sizeof(Cmd.ctBuffer) - 1);
Cmd.ctBuffer[rc] = '\0';
/* Get the string argument that represents the new init pgm */
pLine = GetStringArg(Cmd.ctBuffer, Config.cfgInit);
/* Now take whatever tail is left and add it on as a single */
/* string. */
strcpy(Cmd.ctBuffer, pLine);
/* and add a DOS new line just to be safe */
strcat(Cmd.ctBuffer, "\r\n");
Cmd.ctCount = rc - (pLine - Cmd.ctBuffer);
#ifdef DEBUG
printf("Process 0 starting: %s\n\n", Config.cfgInit);
#endif
}
printf("\nSystem shutdown complete\nReboot now.\n");
for (;;) ;
init_call_p_0(&Config); /* go execute process 0 (the shell) */
}
/* check for a block device and update device control block */

View File

@ -275,3 +275,22 @@ _spawn_int23:
; cli
; ret
;_disable endp
extern _p_0_tos,_P_0
; prepare to call process 0 (the shell) from P_0() in C
global reloc_call_p_0
reloc_call_p_0:
pop ax ; return address (32-bit, unused)
pop ax
pop ax ; fetch parameter 0 (32-bit) from the old stack
pop dx
mov ds,[cs:_DGROUP_]
cli
mov ss,[cs:_DGROUP_]
mov sp,_p_0_tos ; load the dedicated process 0 stack
sti
push dx ; pass parameter 0 onto the new stack
push ax
call _P_0 ; no return, allow parameter fetch from C

View File

@ -220,6 +220,10 @@ UBYTE FcbClose(xfcb FAR * lpXfcb);
void FcbCloseAll(void);
UBYTE FcbFindFirstNext(xfcb FAR * lpXfcb, BOOL First);
/* intr.asm */
COUNT ASMCFUNC res_DosExec(COUNT mode, exec_blk * ep, BYTE * lp);
UCOUNT ASMCFUNC res_read(int fd, void *buf, UCOUNT count);
/* ioctl.c */
COUNT DosDevIOctl(lregs * r);

View File

@ -48,6 +48,13 @@ static BYTE *RcsId =
#define ExeHeader (*(exe_header *)(SecPathName + 0))
#define TempExeBlock (*(exec_blk *)(SecPathName + sizeof(exe_header)))
#define Shell (SecPathName + sizeof(exe_header) + sizeof(exec_blk))
#ifdef __TURBOC__ /* this is a Borlandism and doesn't work elsewhere */
#if sizeof(SecPathName) < sizeof(exe_header) + sizeof(exec_blk) + NAMEMAX
#error No room in SecPathName to be recycled!
#endif
#endif
#define CHUNK 32256
#define MAXENV 32768u
@ -792,3 +799,46 @@ COUNT DosExec(COUNT mode, exec_blk FAR * ep, BYTE FAR * lp)
return rc;
}
#include "config.h" /* config structure definition */
/* start process 0 (the shell) */
VOID ASMCFUNC P_0(struct config FAR *Config)
{
BYTE *tailp, *endp;
exec_blk exb;
UBYTE mode = Config->cfgP_0_startmode;
/* build exec block and save all parameters here as init part will vanish! */
exb.exec.fcb_1 = exb.exec.fcb_2 = (fcb FAR *)-1L;
exb.exec.env_seg = DOS_PSP + 8;
fstrcpy(Shell, Config->cfgInit);
fstrcpy(Shell + strlen(Shell), Config->cfgInitTail); /* join name and tail */
endp = Shell + strlen(Shell);
for ( ; ; ) /* endless shell load loop - reboot or shut down to exit it! */
{
BYTE *p;
/* if there are no parameters, point to end without "\r\n" */
if((tailp = strchr(Shell,'\t')) == NULL &&
(tailp = strchr(Shell, ' ')) == NULL)
tailp = endp - 2;
/* shift tail to right by 2 to make room for '\0', ctCount */
for (p = endp - 1; p >= tailp; p--)
*(p + 2) = *p;
/* terminate name and tail */
*tailp = *(endp + 2) = '\0';
/* ctCount: just past '\0' do not count the "\r\n" */
exb.exec.cmd_line = (CommandTail *)(tailp + 1);
exb.exec.cmd_line->ctCount = endp - tailp - 2;
#ifdef DEBUG
printf("Process 0 starting: %s%s\n\n", Shell, tailp + 2);
#endif
res_DosExec(mode, &exb, Shell);
put_string("Bad or missing Command Interpreter: "); /* failure _or_ exit */
put_string(Shell);
put_string(tailp + 2);
put_string(" Enter the full shell command line: ");
endp = Shell + res_read(STDIN, Shell, NAMEMAX);
*endp = '\0'; /* terminate string for strchr */
}
}