[comp.sys.ibm.pc] Datalight C signal Handler

kent@ncoast.UUCP (05/04/87)

[ LINE EATER LINE EATER - (I don't really know why people do this) ]

The following is a simple implementation of signal, which seemed to
be missing from the Datalight C library.  It implements only the
SIGINT signal, which is the only one that makes any sense under
MSDOS, unless you have support from the floating point library.
----------------------------SIGNAL.MAN----------------------------------------
signal

Summary

int (*signal(sig,func))()
int sig; int (*func)();

Description

The signal function allows a program to handle an interrupt event
generated by the operating system.  The only signal implemented here
is SIGINT, which for MSDOS means that the user has typed a
<control-C> or <control-break> character.

The 'func' parameter specifies how the program wishes to respond to
the event specified by 'sig.' The three options for handling the
SIGINT event are :

1) SIG_DFL - The program is terminated and control is returned to the
command interpreter.

2) SIG_IGN - The interrupt event is ignored.  In the case of MS-DOS,
a '^C' is echoed to the console, but program execution continues
normally.

3) A user defined function may be specified.  Control is passed to
the specified function when the event occurs.  The function can then
do whatever is necessary to respond to the event -  It can simply
return, call 'exit', or call 'longjmp' to transfer control back to a
location previously specified by 'setjmp.'


Example

#include <stdio.h>
#include <signal.h>
int onintr()
{
	signal(SIGINT,SIG_IGN);
	printf("Break caught\n");
	exit(0);
}

main()
{
	signal(SIGINT,onintr);
	while(EOF != getchar());
}
----------------------------SIGNAL.H------------------------------------------
/* signal.h - Header for signal function for Datalight C */
#define SIGINT	0

#define SIG_DFL	(int (*) ()) 0
#define SIG_IGN	(int (*) ()) 1
#define SIG_ILL	(int (*) ()) -1
extern int (*signal(int,int (*)()))();
/* end of signal.h */
----------------------------SIGNAL.C------------------------------------------
/* signal.c - signal package for Datalight C */
#ifdef TEST
#include <stdio.h>
#endif

#include <signal.h>
#include <dos.h>

static	int (*brk_sig)() = SIG_DFL;

extern void _sig_hand();

int (*signal(sig,func))()
int sig; int (*func)();
{
	int (*oldsig)() = brk_sig;
	static unsigned offset = 0xFFFF,segment = 0xFFFF;
	if (sig != SIGINT)
		return SIG_ILL;
	/* if we're supposed to let dos do what it wants */
	if (func == SIG_DFL)
	{
		/* if we've never installed our handler */
		if (offset == 0xFFFF && segment == 0xFFFF)
			return SIG_DFL;
		/* otherwise, restore the handler stored in offset and segment */
		int_setvector(0x23,offset,segment);
		return oldsig;
	}
	if (func == SIG_IGN)
	{
		brk_sig = SIG_IGN;
		if (offset == 0xFFFF && segment == 0xFFFF)
		{
			/* need to install our handler */
			struct SREGS segregs;
			segread(&segregs);	/* pick up segment values */
			int_getvector(0x23,&offset,&segment);	/* get old handler */
			int_setvector(0x23,_sig_hand,segregs.cs);
			return oldsig;
		}
		else
			return oldsig;
	}
	/* otherwise install the specified function */
	if (offset == 0xFFFF && segment == 0xFFFF)
	{
		/* need to install our handler */
		struct SREGS segregs;
		segread(&segregs);	/* pick up segment values */
		int_getvector(0x23,&offset,&segment);	/* get old handler */
		int_setvector(0x23,_sig_hand,segregs.cs);
	}
	brk_sig = func;
	return oldsig;
}

void _c_sig_hand()
{
	int (*oldsig)() = brk_sig;
	if (brk_sig == SIG_IGN)
		return;
	if (brk_sig == SIG_DFL)
		_exit(1);
	signal(SIGINT,SIG_DFL);	/* reset the handler */
	(*oldsig)();			/* call the handler */
}

#ifdef TEST
int onintr()
{
	signal(SIGINT,SIG_IGN);
	printf("Break caught\n");
	exit(0);
}

main()
{
	signal(SIGINT,onintr);
	while(EOF != getchar());
}
#endif
/* end of signal.c */
----------------------------SIGHAND.ASM---------------------------------------
;;
;; sighand.asm - assembly level 'glue' for signal package
;;
	include	macros.asm
	SIG_IGN	equ 1
begcode
begdata
enddata
if	LCODE
	extrn	_c_sig_hand:far
else
	extrn _c_sig_hand:near
endif
	public _sig_hand
if LCODE
_sig_hand	proc	far
else
_sig_hand	proc	near
endif
	push	ax
	push	bx
	push	cx
	push	dx
	push	si
	push	si
	push	di
	push	es
	push	ds
	mov		ax,dgroup
	mov		ds,ax
	call	_c_sig_hand
	pop		ds
	pop		es
	pop		di
	pop		si
	pop		dx
	pop		cx
	pop		bx
	pop		ax
	iret
_sig_hand	endp

endcode
	end
;;
;; end of sighand.asm
;;
----------------------------END OF DATALIGHT SIGNAL PACKAGE-------------------