0,0 → 1,260 |
/* |
FUNCTION |
<<signal>>---specify handler subroutine for a signal |
|
INDEX |
signal |
INDEX |
_signal_r |
|
ANSI_SYNOPSIS |
#include <signal.h> |
void (*signal(int <[sig]>, void(*<[func]>)(int))) (int); |
|
void (*_signal_r(void *<[reent]>, int <[sig]>, void(*<[func]>)(int))) (int); |
|
TRAD_SYNOPSIS |
#include <signal.h> |
char ( * signal(<[sig]>, <[func]>) )() |
int <[sig]>; |
char ( * <[func]> )(); |
|
char ( * _signal_r(<[reent]>, <[sig]>, <[func]>) )() |
char *<[reent]>; |
int <[sig]>; |
char ( * <[func]> )(); |
|
DESCRIPTION |
<<signal>> provides a simple signal-handling implementation for embedded |
targets. |
|
<<signal>> allows you to request changed treatment for a particular |
signal <[sig]>. You can use one of the predefined macros <<SIG_DFL>> |
(select system default handling) or <<SIG_IGN>> (ignore this signal) |
as the value of <[func]>; otherwise, <[func]> is a function pointer |
that identifies a subroutine in your program as the handler for this signal. |
|
Some of the execution environment for signal handlers is |
unpredictable; notably, the only library function required to work |
correctly from within a signal handler is <<signal>> itself, and |
only when used to redefine the handler for the current signal value. |
|
Static storage is likewise unreliable for signal handlers, with one |
exception: if you declare a static storage location as `<<volatile |
sig_atomic_t>>', then you may use that location in a signal handler to |
store signal values. |
|
If your signal handler terminates using <<return>> (or implicit |
return), your program's execution continues at the point |
where it was when the signal was raised (whether by your program |
itself, or by an external event). Signal handlers can also |
use functions such as <<exit>> and <<abort>> to avoid returning. |
|
The alternate function <<_signal_r>> is the reentrant version. |
The extra argument <[reent]> is a pointer to a reentrancy structure. |
|
@c FIXME: do we have setjmp.h and assoc fns? |
|
RETURNS |
If your request for a signal handler cannot be honored, the result is |
<<SIG_ERR>>; a specific error number is also recorded in <<errno>>. |
|
Otherwise, the result is the previous handler (a function pointer or |
one of the predefined macros). |
|
PORTABILITY |
ANSI C requires <<signal>>. |
|
No supporting OS subroutines are required to link with <<signal>>, but |
it will not have any useful effects, except for software generated signals, |
without an operating system that can actually raise exceptions. |
*/ |
|
/* |
* signal.c |
* Original Author: G. Haley |
* |
* signal associates the function pointed to by func with the signal sig. When |
* a signal occurs, the value of func determines the action taken as follows: |
* if func is SIG_DFL, the default handling for that signal will occur; if func |
* is SIG_IGN, the signal will be ignored; otherwise, the default handling for |
* the signal is restored (SIG_DFL), and the function func is called with sig |
* as its argument. Returns the value of func for the previous call to signal |
* for the signal sig, or SIG_ERR if the request fails. |
*/ |
|
/* _init_signal initialises the signal handlers for each signal. This function |
is called by crt0 at program startup. */ |
|
#ifdef SIGNAL_PROVIDED |
|
int _dummy_simulated_signal; |
|
#else |
|
#include <errno.h> |
#include <signal.h> |
#include <stddef.h> |
#include <stdlib.h> |
#include <reent.h> |
#include <_syslist.h> |
|
int |
_DEFUN (_init_signal_r, (ptr), |
struct _reent *ptr) |
{ |
int i; |
|
if (ptr->_sig_func == NULL) |
{ |
ptr->_sig_func = (_sig_func_ptr *)_malloc_r (ptr, sizeof (_sig_func_ptr) * NSIG); |
if (ptr->_sig_func == NULL) |
return -1; |
|
for (i = 0; i < NSIG; i++) |
ptr->_sig_func[i] = SIG_DFL; |
} |
|
return 0; |
} |
|
_sig_func_ptr |
_DEFUN (_signal_r, (ptr, sig, func), |
struct _reent *ptr _AND |
int sig _AND |
_sig_func_ptr func) |
{ |
_sig_func_ptr old_func; |
|
if (sig < 0 || sig >= NSIG) |
{ |
ptr->_errno = EINVAL; |
return SIG_ERR; |
} |
|
if (ptr->_sig_func == NULL && _init_signal_r (ptr) != 0) |
return SIG_ERR; |
|
old_func = ptr->_sig_func[sig]; |
ptr->_sig_func[sig] = func; |
|
return old_func; |
} |
|
int |
_DEFUN (_raise_r, (ptr, sig), |
struct _reent *ptr _AND |
int sig) |
{ |
_sig_func_ptr func; |
|
if (sig < 0 || sig >= NSIG) |
{ |
ptr->_errno = EINVAL; |
return -1; |
} |
|
if (ptr->_sig_func == NULL) |
func = SIG_DFL; |
else |
func = ptr->_sig_func[sig]; |
|
if (func == SIG_DFL) |
return _kill_r (ptr, _getpid_r (ptr), sig); |
else if (func == SIG_IGN) |
return 0; |
else if (func == SIG_ERR) |
{ |
ptr->_errno = EINVAL; |
return 1; |
} |
else |
{ |
ptr->_sig_func[sig] = SIG_DFL; |
func (sig); |
return 0; |
} |
} |
|
int |
_DEFUN (__sigtramp_r, (ptr, sig), |
struct _reent *ptr _AND |
int sig) |
{ |
_sig_func_ptr func; |
|
if (sig < 0 || sig >= NSIG) |
{ |
return -1; |
} |
|
if (ptr->_sig_func == NULL && _init_signal_r (ptr) != 0) |
return -1; |
|
func = ptr->_sig_func[sig]; |
if (func == SIG_DFL) |
return 1; |
else if (func == SIG_ERR) |
return 2; |
else if (func == SIG_IGN) |
return 3; |
else |
{ |
ptr->_sig_func[sig] = SIG_DFL; |
func (sig); |
return 0; |
} |
} |
|
|
int _DEFUN (_kill_r, (ptr, pid, sig), |
struct _reent *ptr _AND |
int pid _AND |
int sig) |
{ |
// int ret; |
|
// errno = 0; |
// if ((ret = _kill (pid, sig)) == -1 && errno != 0) |
// ptr->_errno = errno; |
// return ret; |
|
/* sorry, guys */ |
|
ptr->_errno = EPERM; |
return -1; |
} |
|
|
#ifndef _REENT_ONLY |
|
int |
_DEFUN (raise, (sig), |
int sig) |
{ |
return _raise_r (_REENT, sig); |
} |
|
_sig_func_ptr |
_DEFUN (signal, (sig, func), |
int sig _AND |
_sig_func_ptr func) |
{ |
return _signal_r (_REENT, sig, func); |
} |
|
int |
_DEFUN_VOID (_init_signal) |
{ |
return _init_signal_r (_REENT); |
} |
|
int |
_DEFUN (__sigtramp, (sig), int sig) |
{ |
return __sigtramp_r (_REENT, sig); |
} |
|
#endif |
|
#endif /* !SIGNAL_PROVIDED */ |