1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/* raise( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <signal.h>
#ifndef REGTEST
#include <stdio.h>
#include <stdlib.h>
extern void ( *_PDCLIB_sigabrt )( int );
extern void ( *_PDCLIB_sigfpe )( int );
extern void ( *_PDCLIB_sigill )( int );
extern void ( *_PDCLIB_sigint )( int );
extern void ( *_PDCLIB_sigsegv )( int );
extern void ( *_PDCLIB_sigterm )( int );
int raise( int sig )
{
void ( *sighandler )( int );
const char * message;
switch ( sig )
{
case SIGABRT:
sighandler = _PDCLIB_sigabrt;
message = "Abnormal termination (SIGABRT)";
break;
case SIGFPE:
sighandler = _PDCLIB_sigfpe;
message = "Arithmetic exception (SIGFPE)";
break;
case SIGILL:
sighandler = _PDCLIB_sigill;
message = "Illegal instruction (SIGILL)";
break;
case SIGINT:
sighandler = _PDCLIB_sigint;
message = "Interactive attention signal (SIGINT)";
break;
case SIGSEGV:
sighandler = _PDCLIB_sigsegv;
message = "Invalid memory access (SIGSEGV)";
break;
case SIGTERM:
sighandler = _PDCLIB_sigterm;
message = "Termination request (SIGTERM)";
break;
default:
fprintf( stderr, "Unknown signal #%d\n", sig );
_Exit( EXIT_FAILURE );
}
if ( sighandler == SIG_DFL )
{
fputs( message, stderr );
_Exit( EXIT_FAILURE );
}
else if ( sighandler != SIG_IGN )
{
/* FIXME: "The implementation shall behave as if no library function
calls the signal function."
*/
sighandler = signal( sig, SIG_DFL );
sighandler( sig );
}
return 0;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
#include <stdlib.h>
static volatile sig_atomic_t flag = 0;
static int expected_signal = 0;
static void test_handler( int sig )
{
TESTCASE( sig == expected_signal );
flag = 1;
}
int main( void )
{
void ( *sighandler )( int );
/* Could be other than SIG_DFL if you changed the implementation. */
sighandler = signal( SIGABRT, SIG_IGN );
#ifndef REGTEST
TESTCASE( sighandler == SIG_DFL );
#endif
/* Should be ignored. */
TESTCASE( raise( SIGABRT ) == 0 );
/* Installing test handler, old handler should be returned */
TESTCASE( signal( SIGABRT, test_handler ) == SIG_IGN );
/* Raising and checking SIGABRT */
expected_signal = SIGABRT;
TESTCASE( raise( SIGABRT ) == 0 );
TESTCASE( flag == 1 );
/* Re-installing test handler, should have been reset to default */
/* Could be other than SIG_DFL if you changed the implementation. */
sighandler = signal( SIGABRT, test_handler );
#ifndef REGTEST
TESTCASE( sighandler == SIG_DFL );
#endif
/* Raising and checking SIGABRT */
flag = 0;
TESTCASE( raise( SIGABRT ) == 0 );
TESTCASE( flag == 1 );
/* Installing test handler for different signal... */
TESTCASE( signal( SIGTERM, test_handler ) == SIG_DFL );
/* Raising and checking SIGTERM */
expected_signal = SIGTERM;
TESTCASE( raise( SIGTERM ) == 0 );
TESTCASE( flag == 1 );
/* void expression to avoid "unused" warning in regtest */
(void)sighandler;
return TEST_RESULTS;
}
#endif
|