
/* Copyright Massachusetts Institute of Technology 1990,1991 */

#ifndef lint
static char rcsid[] = "$Header: _signal.c,v 1.4 91/07/09 15:23:22 root Exp $";
#endif lint
/* $Log:	_signal.c,v $
 * Revision 1.4  91/07/09  15:23:22  root
 * removed unused variables _signalOPbuf, _signalOPibuf
 * 
 * Revision 1.3  91/06/06  13:51:10  dcurtis
 * added copyright notice
 * 
 * Revision 1.2  91/06/03  16:59:43  root
 * sparcstation compatibility: int->CLUREF
 * 
 * Revision 1.1  91/02/04  23:21:01  mtv
 * Initial revision
 * 
 */

/*						*/
/*						*/
/*		IMPLEMENTATION OF		*/
/*			_signal			*/
/*						*/

#include <signal.h>
#undef signal

#include "pclu_err.h"
#include "pclu_sys.h"

#include <sys/types.h>
#include <sys/dir.h>

extern CLUREF clu_empty_string;
extern char **environ;
extern int wrpipe;
extern int errno;
extern int gcflag;

typedef void (VPROC)();

extern void _signalOPhand();
static int _signalOPflags;
static int _signalOPholds;
static int _signalOPcnts[32];
static VPROC *_signalOPohands[32];
static int _signalOPomasks[32];
static int _signalOPostks[32];
static int _signalOPmsgs = 0;   /* CLUREF/CLUSEQUENCE in disguise */

errcode _signalOPset(sig, hold)
CLUREF sig, hold;
{
int omask;
struct sigvec vec, ovec;

	if (sig.num < 0 || sig.num > 32) signal(ERR_bad_code);
	if (~hold.tf) {
		vec.sv_handler = _signalOPhand;
		vec.sv_mask = 0xf8e70020;
#ifdef sparc
		vec.sv_flags = 0;
#else
		vec.sv_flags = SV_ONSTACK;
#endif
		sigvec(sig.num, &vec, &ovec);
		if (~(_signalOPflags & (1 << (sig.num - 1)))) {
			_signalOPflags |= 1 << (sig.num - 1); 
			_signalOPohands[sig.num - 1] = ovec.sv_handler;
			_signalOPomasks[sig.num - 1] = ovec.sv_mask;
			_signalOPostks[sig.num - 1] = ovec.sv_flags;
			}
		if (_signalOPholds & (1 << (sig.num - 1))) {
			_signalOPholds &= ~(1 << (sig.num - 1));
			omask = sigblock(0);
			omask &= ~(1 << (sig.num - 1));
			sigsetmask(omask);
			}
		}
	else {
		_signalOPholds |= (1 << (sig.num - 1));
		sigblock( 1 << (sig.num - 1) );
		}
	signal(ERR_ok);
			
}

void _signalOPhand(sig)
int sig;
{
CLUREF msgs, str;

	/* printf("signal caught: %d\n", sig); */
	_signalOPcnts[sig-1] += 1;
	if (gcflag) return;
	if (_signalOPmsgs == 0) return;
	msgs.num = _signalOPmsgs;
	if (msgs.vec->data[sig - 1] != 0)
		str.num = msgs.vec->data[sig - 1];
		write(1, str.vec->data, 
			 str.vec->size);
	return;
	}

errcode _signalOPunset(sig)
CLUREF sig;
{
int omask;
errcode err;
struct sigvec vec;

	if (sig.num < 0 || sig.num > 32) signal(ERR_bad_code);
	if (_signalOPflags && (1 << (sig.num - 1))) {
		_signalOPflags &= ~(1 << (sig.num - 1)); 
		vec.sv_handler = _signalOPohands[sig.num - 1];
		vec.sv_mask = _signalOPomasks[sig.num - 1];
		vec.sv_flags = _signalOPostks[sig.num - 1];
		sigvec(sig.num, &vec, 0);
		}
	if (_signalOPholds && (1 << (sig.num - 1))) {
		_signalOPholds &= ~(1 << (sig.num - 1));
		omask = sigblock(0);
		omask &= ~(1 << (sig.num - 1));
		sigsetmask(omask);
		}
	signal(ERR_ok);
}


errcode _signalOPget(sig, ans)
CLUREF sig, *ans;
{
	if (sig.num < 0 || sig.num > 32) signal(ERR_bad_code);
	ans->num = _signalOPcnts[sig.num - 1];
	_signalOPcnts[sig.num - 1] = 0;
	signal(ERR_ok);
}

errcode _signalOPset_message(sig, msg)
CLUREF sig, msg;
{
errcode err;
CLUREF msgs, str;

	if (sig.num < 0 || sig.num > 32) signal(ERR_bad_code);
	if (_signalOPmsgs == 0) { 
		err = sequenceOPfill(CLU_32, CLU_0, &_signalOPmsgs);
		if (err != ERR_ok) resignal(err);
		}
	msgs.num = _signalOPmsgs;
	msgs.vec->data[sig.num - 1] = msg.num;
	signal(ERR_ok);
	}

errcode _signalOPget_message(sig, ans)
CLUREF sig, *ans;
{
CLUREF msgs, str;

	if (sig.num < 0 || sig.num > 32) signal(ERR_bad_code);
	msgs.num = _signalOPmsgs;
	if (_signalOPmsgs == 0 || msgs.vec->data[sig.num - 1] == 0) {
		ans->vec = clu_empty_string.vec;
		signal(ERR_ok);
		}
	ans->num = msgs.vec->data[sig.num - 1];
	signal(ERR_ok);
	}

