Skip to content

Commit

Permalink
Give the DOSBox DOS shell a proper INT 23h CTRL+C handler, revise
Browse files Browse the repository at this point in the history
  • Loading branch information
joncampbell123 committed Sep 29, 2023
1 parent 63c2122 commit 1168cfb
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 14 deletions.
15 changes: 13 additions & 2 deletions src/dos/dos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,11 +640,11 @@ bool DOS_BreakTest(bool print=true) {
if (print) DOS_PrintCBreak();

DOS_BreakFlag = false;
DOS_BreakConioFlag = false;
DOS_BreakConioFlag = false;

offv = mem_readw((0x23*4)+0);
segv = mem_readw((0x23*4)+2);
if (offv != 0 && segv != 0) { /* HACK: DOSBox's shell currently does not assign INT 23h */
if (segv != 0) {
/* NTS: DOS calls are allowed within INT 23h! */
Bitu save_sp = reg_sp;

Expand All @@ -659,6 +659,11 @@ bool DOS_BreakTest(bool print=true) {
*
* This fixes: PC Mix compiler PCL.EXE
*
* 2023/09/28: Some basic debugging with MS-DOS 6.22 shows the INT 23h handler
* installed by COMMAND.COM does the same thing (INT 21h AH=0x4C)
* which is normally still there unless the DOS application itself
* replaces the vector.
*
* FIXME: This is an ugly hack! */
try {
DOS_BreakINT23InProgress = true;
Expand Down Expand Up @@ -691,6 +696,12 @@ bool DOS_BreakTest(bool print=true) {
if (reg_sp != save_sp) reg_sp += 2;
}
}
else {
/* Old comment: "HACK: DOSBox's shell currently does not assign INT 23h"
* 2023/09/28: The DOSBox command shell now installs a handler, therefore
* a null vector is now something to warn about. */
LOG_MSG("WARNING: INT 23h CTRL+C vector is NULL\n");
}

if (terminate) {
LOG_MSG("Note: DOS break terminating program\n");
Expand Down
38 changes: 26 additions & 12 deletions src/shell/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ bool shellrun = false, prepared = false, testerr = false;

uint16_t shell_psp = 0;
Bitu call_int2e = 0;
Bitu call_int23 = 0;

std::string GetDOSBoxXPath(bool withexe=false);
const char* DOS_GetLoadedLayout(void);
Expand Down Expand Up @@ -272,13 +273,13 @@ DOS_Shell::DOS_Shell():Program(){
input_handle=STDIN;
echo=true;
exit=false;
perm = false;
perm = false;
bf=0;
call=false;
exec=false;
lfnfor = uselfn;
input_eof=false;
completion_index = 0;
input_eof=false;
completion_index = 0;
}

Bitu DOS_Shell::GetRedirection(char *s, char **ifn, char **ofn, char **toc,bool * append) {
Expand Down Expand Up @@ -1321,6 +1322,12 @@ void AUTOEXEC_Init() {
AddVMEventFunction(VM_EVENT_DOS_SURPRISE_REBOOT,AddVMEventFunctionFuncPair(AUTOEXEC_ShutDown));
}

static Bitu INT23_Handler(void) {
LOG(LOG_MISC,LOG_DEBUG)("DOS shell received CTRL+C signal");
SETFLAGBIT(CF,true);
return CBRET_NONE;
}

static Bitu INT2E_Handler(void) {
/* Save return address and current process */
RealPt save_ret=real_readd(SegValue(ss),reg_sp);
Expand Down Expand Up @@ -1816,20 +1823,27 @@ void SHELL_Init() {
real_writed(psp_seg+16+1,1,real_readd(0,0x24*4));
real_writed(0,0x24*4,((uint32_t)psp_seg<<16) | ((16+1)<<4));

/* Set up int 23 to "int 20" in the psp. Fixes what.exe */
real_writed(0,0x23*4,((uint32_t)psp_seg<<16));
/* Old comment: Set up int 23 to "int 20" in the psp. Fixes what.exe */
/* 2023/09/28: Point INT 23h at a vector that calls our callback and then calls INT 21h AH=4Ch. Real COMMAND.COM does this too. */
if (call_int23 == 0)
call_int23 = CALLBACK_Allocate();

RealPt addr_int23=RealMake(psp_seg,8+((16+2)*16));

CALLBACK_Setup(call_int23,&INT23_Handler,CB_RETF,Real2Phys(addr_int23),"Shell Int 23 CTRL+C");
RealSetVec(0x23,addr_int23);

/* Set up int 2e handler */
if (call_int2e == 0)
call_int2e = CALLBACK_Allocate();
if (call_int2e == 0)
call_int2e = CALLBACK_Allocate();

// RealPt addr_int2e=RealMake(psp_seg+16+1,8);
// NTS: It's apparently common practice to enumerate MCBs by reading the segment value of INT 2Eh and then
// scanning forward from there. The assumption seems to be that COMMAND.COM writes INT 2Eh there using
// it's PSP segment and an offset like that of a COM executable even though COMMAND.COM is often an EXE file.
// RealPt addr_int2e=RealMake(psp_seg+16+1,8);
// NTS: It's apparently common practice to enumerate MCBs by reading the segment value of INT 2Eh and then
// scanning forward from there. The assumption seems to be that COMMAND.COM writes INT 2Eh there using
// it's PSP segment and an offset like that of a COM executable even though COMMAND.COM is often an EXE file.
RealPt addr_int2e=RealMake(psp_seg,8+((16+1)*16));

CALLBACK_Setup(call_int2e,&INT2E_Handler,CB_IRET_STI,Real2Phys(addr_int2e),"Shell Int 2e");
CALLBACK_Setup(call_int2e,&INT2E_Handler,CB_IRET_STI,Real2Phys(addr_int2e),"Shell Int 2e");
RealSetVec(0x2e,addr_int2e);

/* Setup environment */
Expand Down

0 comments on commit 1168cfb

Please sign in to comment.