Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions hdr/sig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* FDPP - freedos port to modern C++
* Copyright (C) 2017-2026 @stsp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

typedef struct {
UWORD sig_off;
UWORD sig_seg;
UBYTE sig_num;
UBYTE sig_action;
} sigact;
ANNOTATE_SIZE(sigact, 6);

enum { _SIG_DFL, _SIG_IGN, _SIG_GET };
enum { _SIGINTR = 1, _SIGHUP, _SIGTERM = 8, _SIGPIPE, _SIGUSER1 = 0xd,
_SIGUSER2 };
23 changes: 23 additions & 0 deletions kernel/break.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,26 @@ void handle_break(struct dhdr FAR *pdev)

spawn_int23(); /* invoke user INT-23 and never come back */
}

void handle_sig(int signum)
{
if (signum != sig_act.sig_num)
return;
switch (sig_act.sig_action) {
case _SIG_DFL:
return_code = 0x400 | signum;
return_user();
/* no break */
case _SIG_IGN:
return;
}
if (!ErrorMode) { /* within int21_handler, InDOS is not incremented */
if (InDOS)
--InDOS; /* fail-safe */
else
panic("Signal not in DOS");
}

/* TODO: if more signals implemented, copy sa to sig_act here */
dispatch_sig();
}
7 changes: 5 additions & 2 deletions kernel/chario.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,10 @@ long cooked_read(struct dhdr FAR *pdev, size_t n, char FAR *bp,
c = raw_get_char(pdev, check_break);
if (c < 0)
return c;
if (c == 256)
if (c == 256) {
handle_sig(_SIGHUP);
break;
}
*bp++ = c;
xfer++;
if ((unsigned char)c == CTL_Z)
Expand Down Expand Up @@ -346,7 +348,7 @@ STATIC unsigned do_read_char_dev(struct dhdr FAR *pdev, BOOL check_break)
else
{
unsigned char c1 = ndread(syscon);
if (c1 == CTL_C)
if (!c1 || c1 == CTL_C)
{
con_flush(syscon);
c = 256; // EOF
Expand Down Expand Up @@ -421,6 +423,7 @@ static unsigned int do_read_line(int sft_in, kbd0a FAR *kp, BOOL check_break,
{
case 0:
case 256:
handle_sig(_SIGHUP);
return c;
case LF:
/* show LF if it's not the first character. Never store it */
Expand Down
2 changes: 2 additions & 0 deletions kernel/entry.asm
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ int21_reentry:
je int21_user
cmp ah,51h
je int21_user
cmp ah,8ch
je int21_user
cmp ah,62h
jne int21_1

Expand Down
1 change: 1 addition & 0 deletions kernel/glob_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ __ASM(dmatch, sda_tmp_dm_ren) SEMIC /* 2nd Temporary directory match buffer */
__ASM(dmatch, dmatch_ff) SEMIC /* directory match buffer for fcb */
__ASM_FAR(void, dta) SEMIC
__ASM(UWORD, cu_psp) SEMIC /* current psp segment */
__ASM(sigact, sig_act) SEMIC
__ASM_FAR(iregs, user_r) SEMIC /* User registers for int 21h call */
__ASM_FAR(fcb, sda_lpFcb) SEMIC /* Pointer to users fcb */
__ASM_FAR(sft, lpCurSft) SEMIC
Expand Down
1 change: 1 addition & 0 deletions kernel/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ static BYTE *Globals_hRcsId =
#include "nls.h"
#include "dyn.h"
#include "memtype.h"
#include "sig.h"
#include "glob_fd.h"
#include "debug.h"

Expand Down
26 changes: 23 additions & 3 deletions kernel/inthndlr.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,26 @@ VOID ASMCFUNC int21_syscall(iregs FAR * irp)
case 0x62:
irp->BX = cu_psp;

/* it must be here and not in int21_service() to not overwrite user_r */
case 0x8c: {
sigact old = sig_act, n;
if (irp->AL != _SIGHUP) {
irp->AX = 1;
irp->FLAGS |= FLG_CARRY;
break;
}
n.sig_num = irp->AL;
n.sig_action = irp->BL;
n.sig_seg = irp->DS;
n.sig_off = irp->DX;
n_fmemcpy(&sig_act, &n, sizeof(n));
irp->AX = old.sig_action;
irp->ES = old.sig_seg;
irp->BX = old.sig_off;
irp->FLAGS &= ~FLG_CARRY;
break;
}

/* Normal DOS function - DO NOT ARRIVE HERE */
/* default: */
}
Expand Down Expand Up @@ -1079,7 +1099,7 @@ VOID ASMCFUNC int21_service(iregs FAR * r)

/* Load and Execute Program */
case 0x4b:
break_flg = FALSE;
break_flg = 0;
rc = DosExec(lr.AL, MK_FP(lr.ES, lr.BX), FP_DS_DX);
goto short_check;

Expand All @@ -1098,8 +1118,8 @@ VOID ASMCFUNC int21_service(iregs FAR * r)
}
else if (break_flg)
{
break_flg = FALSE;
rc = 0x100;
rc = break_flg << 8;
break_flg = 0;
}
return_code = lr.AL | rc;
if (DosMemCheck() != SUCCESS)
Expand Down
9 changes: 8 additions & 1 deletion kernel/kernel.asm
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,14 @@ int21regs_seg dw 0
global critical_sp
critical_sp dw 0 ;268 - critical error internal stack
global current_ddsc
current_ddsc times 2 dw 0
current_ddsc times 2 dw 0 ;26a
global _sig_act
_sig_act:
sig_off dw 0 ;26e
sig_seg dw 0 ;270
global sig_num
sig_num db 0 ;272
sig_act db 0 ;273

; Pad to 027ah
times (27ah - ($ - _internal_data)) db 0
Expand Down
46 changes: 46 additions & 0 deletions kernel/procsupt.asm
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

extern _break_flg ; break detected flag
extern _int21_handler
extern _sig_act
extern sig_num

%include "stacks.inc"

Expand Down Expand Up @@ -131,6 +133,50 @@ _spawn_int23:
??int23_respawn:
jmp DGROUP:_int21_handler

; void ASMFUNC NORETURN dispatch_sig(void);
global _dispatch_sig
_dispatch_sig:
mov ds, [cs:_DGROUP_] ;; Make sure DS is OK
mov bp, [_user_r]
cli
mov ss, [_user_r+2]
RestoreSP
sti
; get all the user registers back
Restore386Registers
POP$ALL
push ds
push bp
mov bp, sp
clc
pushf
mov ds, [cs:_DGROUP_]
call far [ds:_sig_act]
mov sp, bp
pop bp
pop ds
jc ??sig_term
jz ??sig_err
??sig_respawn:
jmp DGROUP:_int21_handler
??sig_term:
;; The user returned via RETF 0, Carry is set
;; --> terminate program
;; This is done by set the _break_flg and modify the
;; AH value, which is passed to the _respawn_ call
;; into 0, which is "Terminate program".
push ds ;; we need DGROUP
mov ds, [cs:_DGROUP_]
mov byte [_break_flg], 4
mov al, byte [sig_num]
pop ds
mov ah, 4ch ;; terminate
jmp ??sig_respawn
??sig_err:
mov ax, 5fh ; interrupted
stc
retf 2

;
; interrupt enable and disable routines
;
Expand Down
2 changes: 2 additions & 0 deletions kernel/proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ unsigned char ctrl_break_pressed(void);
unsigned char check_handle_break(__FAR(struct dhdr) pdev);
void handle_break(__FAR(struct dhdr) pdev);
void clear_break(void);
void handle_sig(int signum);
#ifdef __WATCOMC__
#pragma aux handle_break aborts;
#endif
Expand Down Expand Up @@ -551,5 +552,6 @@ WORD ASMPASCAL INITTEXT init_switchar(WORD chr);
COUNT ASMPASCAL INITTEXT UMB_get_largest(__FAR(void) driverAddress, UDWORD * __seg, UCOUNT * size);
VOID ASMFUNC INITTEXT init_stacks(__FAR(VOID) stack_base, COUNT nStacks, WORD stackSize);
void ASMFUNC NORETURN spawn_int23(void); /* procsupt.asm */
void ASMFUNC NORETURN dispatch_sig(void); /* procsupt.asm */
/* kernel.asm */
VOID ASMFUNC FAR NORETURN call_p_0(__FAR(const struct config)Config); /* P_0, actually */
6 changes: 5 additions & 1 deletion kernel/task.c
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ VOID ASMCFUNC P_0(const struct config FAR *Config)

VOID ASMCFUNC P_0_exit(unsigned short retcode)
{
if ((retcode & 0xff) == 0) {
if ((retcode & 0xff) == 0 || (retcode >> 8)) {
switch (retcode >> 8) {
case 0:
_printf("\nShell %s exited, press any key...\n", GET_PTR(Shell));
Expand All @@ -985,6 +985,10 @@ VOID ASMCFUNC P_0_exit(unsigned short retcode)
case 2:
_printf("\nShell %s aborted due to critical error, press any key...\n", GET_PTR(Shell));
break;
case 4:
_printf("\nShell %s aborted by signal %i, press any key...\n",
GET_PTR(Shell), retcode & 0xff);
break;
}
con_flush_stdin();
read_char_stdin(0);
Expand Down