From 3e3c05ff229571d6ea4513781aa755e7f4964ef0 Mon Sep 17 00:00:00 2001 From: Bart Oldeman Date: Sun, 7 Mar 2004 12:19:43 +0000 Subject: [PATCH] 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 --- kernel/init-mod.h | 3 +++ kernel/intr.asm | 30 +++++++++++++++++++++++++ kernel/kernel.asm | 9 ++++++++ kernel/main.c | 55 ++++++--------------------------------------- kernel/procsupt.asm | 19 ++++++++++++++++ kernel/proto.h | 4 ++++ kernel/task.c | 50 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 122 insertions(+), 48 deletions(-) diff --git a/kernel/init-mod.h b/kernel/init-mod.h index 9fc3ec2..3a63973 100644 --- a/kernel/init-mod.h +++ b/kernel/init-mod.h @@ -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, diff --git a/kernel/intr.asm b/kernel/intr.asm index 41ac128..ad08028 100644 --- a/kernel/intr.asm +++ b/kernel/intr.asm @@ -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) diff --git a/kernel/kernel.asm b/kernel/kernel.asm index 0404a94..265b118 100644 --- a/kernel/kernel.asm +++ b/kernel/kernel.asm @@ -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: diff --git a/kernel/main.c b/kernel/main.c index a909c3f..176500e 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -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 */ diff --git a/kernel/procsupt.asm b/kernel/procsupt.asm index 1039238..432972c 100644 --- a/kernel/procsupt.asm +++ b/kernel/procsupt.asm @@ -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 diff --git a/kernel/proto.h b/kernel/proto.h index 4f2acb8..a7d59e0 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -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); diff --git a/kernel/task.c b/kernel/task.c index cbaa5f1..11d19a6 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -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 */ + } +}