⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signals.c

📁 汇编源代码大全
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 * 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 + -