163 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * $Id$
 | |
|  *
 | |
|     Copyright (c) 2006-2019 Chung, Hyung-Hwan. All rights reserved.
 | |
| 
 | |
|     Redistribution and use in source and binary forms, with or without
 | |
|     modification, are permitted provided that the following conditions
 | |
|     are met:
 | |
|     1. Redistributions of source code must retain the above copyright
 | |
|        notice, this list of conditions and the following disclaimer.
 | |
|     2. Redistributions in binary form must reproduce the above copyright
 | |
|        notice, this list of conditions and the following disclaimer in the
 | |
|        documentation and/or other materials provided with the distribution.
 | |
| 
 | |
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
 | |
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 | |
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | |
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 | |
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | |
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 | |
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| #include <qse/si/intr.h>
 | |
| 
 | |
| #if defined(_WIN32)
 | |
| #	include <windows.h>
 | |
| 
 | |
| #elif defined(__OS2__)
 | |
| #	define INCL_DOSPROCESS
 | |
| #	define INCL_DOSEXCEPTIONS
 | |
| #	define INCL_ERRORS
 | |
| #	include <os2.h>
 | |
| 
 | |
| #elif defined(__DOS__)
 | |
| #	include <dos.h>
 | |
| #	include <signal.h>
 | |
| #else
 | |
| #	include <unistd.h>
 | |
| #	include <signal.h>
 | |
| #	include <errno.h>
 | |
| #endif
 | |
| 
 | |
| static qse_intr_handler_t intr_handler = QSE_NULL;
 | |
| static void* intr_handler_arg = QSE_NULL;
 | |
| 
 | |
| #if defined(_WIN32)
 | |
| static BOOL WINAPI __intr_handler (DWORD ctrl_type)
 | |
| {
 | |
| 	if (ctrl_type == CTRL_C_EVENT ||
 | |
| 	    ctrl_type == CTRL_CLOSE_EVENT)
 | |
| 	{
 | |
| 		if (intr_handler) intr_handler (intr_handler_arg);
 | |
| 		return TRUE;
 | |
| 	}
 | |
| 
 | |
| 	return FALSE;
 | |
| }
 | |
| 
 | |
| #elif defined(__OS2__)
 | |
| 
 | |
| static EXCEPTIONREGISTRATIONRECORD os2_excrr = { 0 };
 | |
| 
 | |
| static ULONG _System __intr_handler (
 | |
| 	PEXCEPTIONREPORTRECORD p1,
 | |
| 	PEXCEPTIONREGISTRATIONRECORD p2,
 | |
| 	PCONTEXTRECORD p3,
 | |
| 	PVOID pv)
 | |
| {
 | |
| 	if (p1->ExceptionNum == XCPT_SIGNAL)
 | |
| 	{
 | |
| 		if (p1->ExceptionInfo[0] == XCPT_SIGNAL_INTR ||
 | |
| 		    p1->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC ||
 | |
| 		    p1->ExceptionInfo[0] == XCPT_SIGNAL_BREAK)
 | |
| 		 {
 | |
| 			APIRET rc;
 | |
| 
 | |
| 			if (intr_handler) intr_handler (intr_handler_arg);
 | |
| 
 | |
| 			rc = DosAcknowledgeSignalException (p1->ExceptionInfo[0]);
 | |
| 			return (rc != NO_ERROR)? 1: XCPT_CONTINUE_EXECUTION;
 | |
| 		 }
 | |
| 	}
 | |
| 
 | |
| 	return XCPT_CONTINUE_SEARCH; /* exception not resolved */
 | |
| }
 | |
| 
 | |
| #elif defined(__DOS__)
 | |
| 
 | |
| static void __intr_handler (void)
 | |
| {
 | |
| 	if (intr_handler) intr_handler (intr_handler_arg);
 | |
| }
 | |
| 
 | |
| #else
 | |
| 
 | |
| static void __intr_handler (int sig)
 | |
| {
 | |
| 	if (intr_handler) intr_handler (intr_handler_arg);
 | |
| }
 | |
| 
 | |
| static int setsignal (int sig, void(*handler)(int), int restart)
 | |
| {
 | |
| 	struct sigaction sa_int;
 | |
| 
 | |
| 	sa_int.sa_handler = handler;
 | |
| 	sigemptyset (&sa_int.sa_mask);
 | |
| 
 | |
| 	sa_int.sa_flags = 0;
 | |
| 
 | |
| 	if (restart)
 | |
| 	{
 | |
| 	#if defined(SA_RESTART)
 | |
| 		sa_int.sa_flags |= SA_RESTART;
 | |
| 	#endif
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	#if defined(SA_INTERRUPT)
 | |
| 		sa_int.sa_flags |= SA_INTERRUPT;
 | |
| 	#endif
 | |
| 	}
 | |
| 	return sigaction (sig, &sa_int, NULL);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void qse_set_intr_handler (qse_intr_handler_t handler, void* arg)
 | |
| {
 | |
| 	intr_handler = handler;
 | |
| 	intr_handler_arg = arg;
 | |
| 
 | |
| #if defined(_WIN32)
 | |
| 	SetConsoleCtrlHandler (__intr_handler, TRUE);
 | |
| #elif defined(__OS2__)
 | |
| 	os2_excrr.ExceptionHandler = (ERR)__intr_handler;
 | |
| 	DosSetExceptionHandler (&os2_excrr); /* TODO: check if NO_ERROR is returned */
 | |
| #elif defined(__DOS__)
 | |
| 	signal (SIGINT, __intr_handler);
 | |
| #else
 | |
| 	/*setsignal (SIGINT, __intr_handler, 1); TO BE MORE COMPATIBLE WITH WIN32*/
 | |
| 	setsignal (SIGINT, __intr_handler, 0);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void qse_clear_intr_handler (void)
 | |
| {
 | |
| 	intr_handler = QSE_NULL;
 | |
| 	intr_handler_arg = QSE_NULL;
 | |
| 
 | |
| #if defined(_WIN32)
 | |
| 	SetConsoleCtrlHandler (__intr_handler, FALSE);
 | |
| #elif defined(__OS2__)
 | |
| 	DosUnsetExceptionHandler (&os2_excrr);
 | |
| #elif defined(__DOS__)
 | |
| 	signal (SIGINT, SIG_DFL);
 | |
| #else
 | |
| 	setsignal (SIGINT, SIG_DFL, 1);
 | |
| #endif
 | |
| }
 |