📄 signals.c
字号:
/*****************************************************************************
* FILE: signals.c *
* *
* DESC: *
* - signal handling *
* - exception handler *
* - DPMI 1.0 page fault handler *
* *
* Copyright (C) 1993,1994 *
* Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld *
* email: rainer@mathematik.uni-bielefeld.de *
* *
*****************************************************************************/
#include <string.h>
#include "PRINTF.H"
#include "DPMI.H"
#include "DPMI10.H"
#include "RMLIB.H"
#include "PROCESS.H"
#include "SIGNALS.H"
#include "START32.H"
#include "CDOSX32.H"
#include "EXCEP32.H"
#include "ADOSX32.H"
#include "COPY32.H"
#include "RSX.H"
#include "LOADPRG.H"
#include "KDEB.H"
#include "DOSERRNO.H"
#define SIGSA(no) ((no)-1)
#define SIGMASK(no) (1L<<((no)-1))
#define SIGBLOCK (~(SIGSA(SIGKILL)))
#define SA_NOTBSD (SA_SYSV | SA_ACK)
/* local functions */
static int exception2signal(WORD);
static int do_signal(int);
static void print_exception_exit(void);
static void print_regs_exception(void);
extern char *sigtext[];
/*
** give back a signal no from a hardware exception fault no
*/
static int exception2signal(WORD faultno)
{
int signal;
switch (faultno) {
case 0:
case 2:
case 4:
case 5:
case 6:
case 8:
case 10:
case 15:
signal = SIGILL;
break;
case 1:
case 3:
signal = SIGTRAP;
break;
case 7:
case 16:
signal = SIGFPE;
break;
case 9:
case 11:
case 12:
case 13:
case 14:
case 17:
signal = SIGSEGV;
break;
default:
signal = SIGSEGV;
break;
}
return signal;
}
/*
** set signal for one process
*/
int send_signal(NEWPROCESS * p, int signal)
{
if (!p || signal < 0 || signal >= MAX_SIGNALS)
return EMX_EINVAL;
p->sig_raised |= SIGMASK(signal);
return 0;
}
static void check_pending(int signum)
{
struct sigaction *p;
p = signum - 1 + npz->sigaction;
if (p->sa_handler == SIG_IGN) {
if (signum == SIGCHLD)
return;
npz->sig_raised &= ~ SIGMASK(signum);
return;
}
if (p->sa_handler == SIG_DFL) {
if (signum != SIGCHLD)
return;
npz->sig_raised &= ~ SIGMASK(signum);
return;
}
}
int sys_sigaction(int signum, DWORD action, DWORD oldaction)
{
struct sigaction new_sa, *p;
if (signum<1 || signum>=MAX_SIGNALS || signum==SIGKILL)
return -EMX_EINVAL;
p = signum - 1 + npz->sigaction;
if (action) {
if (verify_illegal(npz, action, sizeof(action)))
return -EMX_EINVAL;
cpy32_16(npz->data32sel, action, &new_sa, sizeof(struct sigaction));
new_sa.sa_mask |= SIGMASK(signum);
new_sa.sa_mask &= SIGBLOCK;
}
if (oldaction) {
if (verify_illegal_write(npz, oldaction, sizeof(oldaction)))
return -EMX_EINVAL;
cpy16_32(npz->data32sel, oldaction, p, sizeof(struct sigaction));
}
if (action) {
*p = new_sa;
check_pending(signum);
}
return 0;
}
int sys_sigpending(DWORD set_addr)
{
DWORD set = npz->sig_blocked & npz->sig_raised;
if (verify_illegal_write(npz, set, 4))
return -EMX_EINVAL;
store32(npz->data32sel, set_addr, set);
return 0;
}
int sys_sigprocmask(int how, DWORD set, DWORD oset)
{
sigset_t new_set, old_set = npz->sig_blocked;
if (set) {
if (verify_illegal(npz, set, sizeof(sigset_t)))
return -EMX_EINVAL;
new_set = read32(npz->data32sel, set) & SIGBLOCK;
switch (how) {
case SIG_BLOCK:
npz->sig_blocked |= new_set;
break;
case SIG_UNBLOCK:
npz->sig_blocked &= ~new_set;
break;
case SIG_SETMASK:
npz->sig_blocked = new_set;
break;
default:
return -EMX_EINVAL;
}
}
if (oset) {
if (verify_illegal_write(npz, oset, sizeof(sigset_t)))
return -EMX_EINVAL;
store32(npz->data32sel, oset, old_set);
}
return 0;
}
/*
** signal handler returned via syscall 0x10
*/
int signal_handler_returned(void)
{
DWORD signal, sig_blocked;
DWORD r;
signal = read32(npz->data32sel, ESPORG);
if (opt_printall)
printf("return signal handler: %lX\n", signal);
sig_blocked = read32(npz->data32sel, ESPORG + 4);
/* unblock old signal mask, if not emx ack */
if (!(npz->sigaction[SIGSA(signal)].sa_flags & SA_ACK))
npz->sig_blocked = sig_blocked & ~SIGMASK(signal);
r = read32(npz->data32sel, ESPORG + 8); /* nop ; mov $7f10, %eax */
if (r != 0x7F07b890) {
puts("sigreturn: illegal frame");
return 1;
}
r = read32(npz->data32sel, ESPORG + 12); /* int 0x21 */
if (r != 0x21cd0000) {
puts("sigreturn: illegal frame");
return 1;
}
cpy32_16(npz->data32sel, ESPORG + 16, &(npz->regs), sizeof(REG386));
if (AX == 0x7f0E) { /* back from raise() */
EAX = ECX = 0; /* put return values */
back_from_syscall();
return 1;
}
/*
** if we had a hardware exception, we zero the user handler, to
** prevent a exception loop to handler (may be changed in future)
*/
if (signal == SIGSEGV || signal == SIGILL ||
signal == SIGFPE || signal == SIGTRAP) {
(npz->sigaction[SIGSA(signal)]).sa_handler = 0;
npz->sig_blocked &= ~SIGMASK(signal);
}
return 1;
}
/*
** called before return to user process
*/
int check_signals(void)
{
int i;
DWORD sigs;
sigs = ~npz->sig_blocked & npz->sig_raised;
if (!sigs)
return 0;
while (sigs) {
for (i = 1; i <= MAX_SIGNALS; i++) {
if (sigs & 1) {
if (do_signal(i))
break; /* restart loop, if handler called */
}
sigs >>= 1;
}
sigs = ~npz->sig_blocked & npz->sig_raised;
}
return 0;
}
#define SIGDFL_IGNORE 0
#define SIGDFL_TERMINATE 1
#define SIGDFL_CORE 2
static struct {
char *text;
char action;
} sigdfl[MAX_SIGNALS] = {
{ "SIGHUP", SIGDFL_TERMINATE },
{ "SIGINT", SIGDFL_TERMINATE },
{ "SIGQUIT", SIGDFL_CORE },
{ "SIGILL", SIGDFL_CORE },
{ "SIGTRAP", SIGDFL_CORE },
{ "SIGABRT", SIGDFL_CORE },
{ "SIGEMT", SIGDFL_CORE },
{ "SIGFPE", SIGDFL_CORE },
{ "SIGKILL", SIGDFL_TERMINATE },
{ "SIGBUS", SIGDFL_CORE },
{ "SIGSEGV", SIGDFL_CORE },
{ "SIGSYS", SIGDFL_CORE },
{ "SIGPIPE", SIGDFL_TERMINATE },
{ "SIGALRM", SIGDFL_TERMINATE },
{ "SIGTERM", SIGDFL_TERMINATE },
{ "SIGUSR1", SIGDFL_IGNORE },
{ "SIGUSR2", SIGDFL_IGNORE },
{ "SIGCHLD", SIGDFL_IGNORE },
{ "SIG19", SIGDFL_IGNORE },
{ "SIG20", SIGDFL_IGNORE },
{ "SIGBREAK", SIGDFL_TERMINATE }
};
void setup_frame(DWORD address, DWORD oldmask, int signal)
{
DWORD code;
if (ESP == ESPORG) /* build stack-frame,if not */
ESP -= 12;
/* save regs for handler return, put reg values on user stack */
cpy16_32(npz->data32sel, ESP - sizeof(REG386),
&(npz->regs), sizeof(REG386));
ESP -= sizeof(REG386); /* sub register-frame */
EIP = address; /* sighandler address */
ESP -= sizeof(long); /* put code: int 0x21 */
store32(npz->data32sel, ESP, 0x21cd0000);
ESP -= sizeof(long); /* put code: popl %eax ; movl $7f07, %eax */
store32(npz->data32sel, ESP, 0x7F07b890);
code = ESP;
ESP -= sizeof(long); /* put signal mask on user stack */
store32(npz->data32sel, ESP, oldmask);
ESP -= sizeof(long); /* put signalno on user stack */
store32(npz->data32sel, ESP, signal);
ESP -= sizeof(long); /* put return address: stack code */
store32(npz->data32sel, ESP, code);
ESPORG = ESP;
ESP -= 12; /* sub iret frame */
}
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -