// SIGNAL.C -- Install a CTRL-C handler with signal()

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <conio.h>
#include <ctype.h>
#include <dos.h>
#include <pharlap.h>
#include <pldos32.h>

#ifdef __WATCOMC__
#define _intdos intdos
#define _toupper toupper
#define _REGS REGS
// Names of regs in _REGS union are nonstandard
#define dx              edx 
#endif

void CCHandler(int sig);
void ReadKey(UCHAR *pch);
void WriteStr(char *pStr);

int main()
{
	UCHAR	ch;

//
// Test 1: Install our CTRL-C handler, and prompt user to type CTRL-C
//
	if (signal(SIGINT, CCHandler) == SIG_ERR)
	{
		printf("Couldn't install CTRL-C handler\n");
		return 1;
	}
	do 
	{
		printf("\nType CTRL-C to invoke handler, 'N' for next test: ");
		fflush(stdout);
		ReadKey(&ch);
	}
	while (_toupper(ch) != 'N');

//
// Test 2:  Ignore CTRL-C, and prompt user
//
	if (signal(SIGINT, SIG_IGN) == SIG_ERR)
	{
		printf("Couldn't ignore CTRL-C\n");
		return 1;
	}
	do
	{
		printf("\nCTRL-C should be ignored, type 'N' for next test: ");
		fflush(stdout);
		ReadKey(&ch);
	}
	while (_toupper(ch) != 'N');

//
// Test 3:  System-default response is to kill program.
//
	if (signal(SIGINT, SIG_DFL) == SIG_ERR)
	{
		printf("Couldn't set default response for CTRL-C\n");
		return 1;
	}
	do
	{
		printf("\nType CTRL-C to kill program, 'N' for normal exit: ");
		fflush(stdout);
		ReadKey(&ch);
	}
	while (_toupper(ch) != 'N');
	printf("\nTerminating normally\n");

	return 0;
}

//
// CCHandler -- prompts user to kill program or continue
//
// C run-time library I/O routines are not safe to use inside a signal
// handler, so call DOS directly for I/O.
//
void CCHandler(int sig)
{
	UCHAR	ch;

//
// Disallow a second CTRL-C while we're handling this one
//
	signal(SIGINT, SIG_IGN);

//
// Prompt user to continue or die
//
	WriteStr("\r\nCTRL-C typed!!!!  Enter 'K' to kill program: $");
	ReadKey(&ch);
	if (toupper(ch) == 'K')
		abort();

//
// Re-install our handler, re-prompt user, and continue program
//
	signal(SIGINT, CCHandler);
	WriteStr("\r\nType CTRL-C to invoke handler, 'N' for next test: $");
	return;
}

//
// Wait for a key to be typed with INT 21h function 01h
//
void ReadKey(UCHAR *pch)
{
	union _REGS r; 

        memset(&r, 0, sizeof(r));
        r.h.ah = 0x01;
        _intdos(&r, &r); 
	*pch = (UCHAR) r.h.al;
	return;
}

//
// Write a character string to the console with INT 21h function 09h
//
void WriteStr(char *pStr)
{
	union _REGS r; 

        memset(&r, 0, sizeof(r));
        r.h.ah = 0x09;
	r.x.dx = (UINT) pStr;
        _intdos(&r, &r); 
	return;
}
