diff options
author | Christopher Faylor <me@cgf.cx> | 2000-02-17 19:39:52 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2000-02-17 19:39:52 +0000 |
commit | 8a0efa53e44919bcf5ccb1d3353618a82afdf8bc (patch) | |
tree | 68c3dbf3f2c6fd5d49777def9914d77b5cd4589d /newlib/libc/signal/signal.c | |
parent | 1fd5e000ace55b323124c7e556a7a864b972a5c4 (diff) | |
download | cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.tar.gz cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.tar.bz2 cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.zip |
import newlib-2000-02-17 snapshot
Diffstat (limited to 'newlib/libc/signal/signal.c')
-rw-r--r-- | newlib/libc/signal/signal.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/newlib/libc/signal/signal.c b/newlib/libc/signal/signal.c new file mode 100644 index 000000000..fc52bbab5 --- /dev/null +++ b/newlib/libc/signal/signal.c @@ -0,0 +1,269 @@ +/* +FUNCTION +<<signal>>---specify handler subroutine for a signal + +INDEX + signal +INDEX + _signal_r +INDEX + raise +INDEX + _raise_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); + + int raise (int <[sig]>); + + int _raise_r (void *<[reent]>, int <[sig]>); + +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]> )(); + + int raise (<[sig]>)() + int <[sig]>; + + int _raise_r (<[reent]>, <[sig]>)() + char *<[reent]>; + int <[sig]>; + +DESCRIPTION +<<signal, raise>> provide a simple signal/raise 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 @code{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. + +<<raise>> sends the signal sig to the executing program. It returns zero if +successful, non-zero if unsuccessful. + +The alternate functions <<_signal_r, _raise_r>> are the reentrant versions. +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 <<raise>>, <<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, *temp; + + 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 +_raise_r (ptr, sig) + struct _reent *ptr; + int sig; +{ + _sig_func_ptr func; + int result = 0; + + if (sig < 0 || sig >= NSIG) + { + ptr->_errno = EINVAL; + return -1; + } + + if (ptr->_sig_func == NULL && _init_signal_r (ptr) != 0) + return -1; + + switch ((_POINTER_INT) ptr->_sig_func[sig]) + { + case SIG_DFL: + return _kill_r (ptr, _getpid_r (ptr), sig); + + case SIG_IGN: + break; + + case SIG_ERR: + ptr->_errno = EINVAL; + result = 1; + break; + + default: + func = ptr->_sig_func[sig]; + ptr->_sig_func[sig] = SIG_DFL; + func (sig); + break; + } + + return result; +} + +int +__sigtramp_r (ptr, sig) + struct _reent *ptr; + 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; + + switch ((_POINTER_INT) ptr->_sig_func[sig]) + { + case SIG_DFL: + return 1; + + case SIG_ERR: + return 2; + + case SIG_IGN: + return 3; + + default: + func = ptr->_sig_func[sig]; + ptr->_sig_func[sig] = SIG_DFL; + func (sig); + return 0; + } +} + +#ifndef _REENT_ONLY + +int +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 +_init_signal () +{ + return _init_signal_r (_REENT); +} + +int +__sigtramp (int sig) +{ + return __sigtramp_r (_REENT, sig); +} + +#endif + +#endif /* !SIGNAL_PROVIDED */ |