/*
 *	signal - catch or ignore signals
 */
#include <rsts.h>
#include <signal.h>

extern	$$rsts;
extern	$$opsy;

extern	$$sig0();

int	(*$$sigs[NSIG])() = {
    SIG_DFL,	/*		Undefined */
    SIG_DFL,	/* SIGHUP	hangup */
    SIG_DFL,	/* SIGINT	interrupt */
    SIG_DFL,	/* SIGQUIT	quit */
    SIG_DFL,	/* SIGILL	illegal instruction (not reset when caught) */
    SIG_DFL,	/* SIGTRAP	trace trap (not reset when caught) */
    SIG_DFL,	/* SIGIOT	IOT instruction */
    SIG_DFL,	/* SIGEMT	EMT instruction */
    SIG_DFL,	/* SIGFPE	floating point exception */
    SIG_DFL,	/* SIGKILL	kill (cannot be caught or ignored) */
    SIG_DFL,	/* SIGBUS	bus error */
    SIG_DFL,	/* SIGSEGV	segmentation violation */
    SIG_DFL,	/* SIGSYS	bad argument to system call */
    SIG_DFL,	/* SIGPIPE	write to a pipe with no one to read it */
    SIG_DFL,	/* SIGALRM	alarm clock */
    SIG_DFL,	/* SIGTERM	software termination signal from kill */
    SIG_DFL	/* 16		Unassigned */
};

#define EMT	0104000
#define	_SETCC	EMT+0362		/* RT11/RSTS .setcc call	*/
#define	_RCTRLO	EMT+0355		/* RT11 clear CTRL/O call	*/
#define	r_cast	(*((int *) 024))	/* RSX/RSTS CTRL/C AST vector	*/

signal(sig, func)
int	sig;
int	func;
{
    int	catcher;
    int	old;

    if (sig <= 0 || sig >= NSIG)
        return(-1);

    if (func == SIG_DFL)
        catcher = 0;
    else
        catcher = ((int) $$sig0) - (sig * 4);

    if (func & 1)
        func = SIG_IGN;

    switch(sig) {
	case SIGINT:	/* interrupt */
	case SIGQUIT:	/* quit */
            if ($$rsts) {
                if ($$opsy == 7) {
                    rtemt(_SETCC, catcher);
                }
                else {
                    r_cast = catcher;
                }
            }
            break;
	case SIGHUP:	/* hangup */
	case SIGILL:	/* illegal instruction (not reset when caught) */
	case SIGTRAP:	/* trace trap (not reset when caught) */
	case SIGIOT:	/* IOT instruction */
	case SIGEMT:	/* EMT instruction */
	case SIGFPE:	/* floating point exception */
	case SIGKILL:	/* kill (cannot be caught or ignored) */
	case SIGBUS:	/* bus error */
	case SIGSEGV:	/* segmentation violation */
	case SIGSYS:	/* bad argument to system call */
	case SIGPIPE:	/* write to a pipe with no one to read it */
	case SIGALRM:	/* alarm clock */
	case SIGTERM:	/* software termination signal from kill */
            break;
        default:
            return(-1);
        break;
    }
    old = $$sigs[sig];
    $$sigs[sig] = func;
    return(old);    
}

ssignal(sig, func)
int	sig;
int	func;
{
    int	err;

    err = signal(sig, func);
    if (err == -1)
        return(0);
    else
        return(err);
}
