/*
 *		Cross Development System for Atari ST 
 *     Copyright (c) 1988, Memorial University of Newfoundland
 *
 *   Signal routine - the signals are actually done by calling the _do_signal
 * routine - similiar to kill() I guess.
 *
 * 1.3 ERS added SIGABRT handling, generally fixed up stuff
 * 1.2 ERS added kill, changed _do_signal to an internal function
 *
 */
#include	<signal.h>
#include	<errno.h>
#include	<string.h>
#include	<unistd.h>

extern int __check_signals;		/* used in console i/o routines */
#define SIG_EXIT	10		/* exit code */

struct sigarray_str {
      __Sigfunc s_func;
};
/* SIG_DFL == 0, so everything is implicitly set to this */

static struct sigarray_str	sig_array[NSIG] ;

void
_init_signal()			/* needed for dumping */
{
    bzero(sig_array, sizeof(sig_array)); /* for now */
}

__Sigfunc signal(sig, func)
	int	sig;
      __Sigfunc func;
{
      __Sigfunc oldfunc;

	switch (sig) {
	case SIGINT:
	case SIGQUIT:
		if (func != SIG_IGN)
			__check_signals |= (sig==SIGINT ? 1 : 2);
		else
			__check_signals &= (sig==SIGINT ? ~1 : ~2);
		/* falltrough */
	case SIGALRM:
	case SIGABRT:
		oldfunc = sig_array[sig].s_func;
		sig_array[sig].s_func = func;
		break;
	default:
		errno = EINVAL;
		oldfunc = SIG_ERR;
	}
	return oldfunc;
}

static void
_do_signal(sig)
	int	sig;
{
      __Sigfunc func;

	if (sig >= 0 && sig < NSIG) {
		func = sig_array[sig].s_func;
		if (func == SIG_DFL)
			switch (sig) {
			case SIGQUIT:
			case SIGINT:
			case SIGALRM:
			case SIGABRT:
				psignal(sig, "fatal signal received");
				_exit(SIG_EXIT + sig);
			}
		else if (func != SIG_IGN)
			(*func)(sig);
		/* else ignore it */
	}
}

int kill(pid, sig)
	int pid, sig;
{
	if (pid != getpid()) {
		errno = EACCESS;	/* I don't know if this is right */
		return -1;
	}
	_do_signal(sig);
	return 0;
}
