diff options
Diffstat (limited to 'usr/src/lib/libbc/libc/sys/common/sigaction.c')
-rw-r--r-- | usr/src/lib/libbc/libc/sys/common/sigaction.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/usr/src/lib/libbc/libc/sys/common/sigaction.c b/usr/src/lib/libbc/libc/sys/common/sigaction.c new file mode 100644 index 0000000000..1b1ccccf10 --- /dev/null +++ b/usr/src/lib/libbc/libc/sys/common/sigaction.c @@ -0,0 +1,177 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <errno.h> +#include <signal.h> +#include "signalmap.h" + +static void signal_init(void); +#pragma init(signal_init) + +extern void (*handlers[])(); +extern void maphandler(int, int, struct sigcontext *, char *); +extern void (*_siguhandler[])(); /* libucb */ +extern void _sigvechandler(int, void*, void*); /* libucb */ + +extern int maptonewsig(); +extern int _sigaction(); +extern int maptonewmask(); +extern int maptooldmask(); +extern int _signal(); +extern int _sigprocmask(); +extern char *memset(); +extern int _sigpending(); + +typedef struct { + unsigned long __sigbits[4]; +} S5_sigset_t; + +typedef struct { + int sa_flags; + void (*sa_handler)(); + S5_sigset_t sa_mask; + int sa_resv[2]; +} S5_sigaction; + +#define S5_SA_ONSTACK 0x00000001 +#define S5_SA_RESETHAND 0x00000002 +#define S5_SA_RESTART 0x00000004 +#define S5_SA_NOCLDSTOP 0x00020000 + +int +sigaction(sig, act, oact) +int sig; +struct sigaction *act, *oact; +{ + S5_sigaction S5_act; + S5_sigaction S5_oact; + int ret; + int newsig; + void (*oldhand)(); + void (*oldsiguhand)(); + + newsig = maptonewsig(sig); + oldhand = handlers[newsig]; + oldsiguhand = _siguhandler[newsig]; + if (act == NULL) { + ret = _sigaction(newsig, (S5_sigaction *)NULL, &S5_oact); + } else { + S5_act.sa_flags = 0; + if (act->sa_flags & SA_ONSTACK) + S5_act.sa_flags |= S5_SA_ONSTACK; + if (act->sa_flags & SA_RESETHAND) + S5_act.sa_flags |= S5_SA_RESETHAND; + if (act->sa_flags & SA_NOCLDSTOP) + S5_act.sa_flags |= S5_SA_NOCLDSTOP; + if (!(act->sa_flags & SA_INTERRUPT)) + S5_act.sa_flags |= S5_SA_RESTART; + /* + * _sigvechandler() receives control from the OS. + * It calls through _siguhandler[] to maphandler(), + * which maps the signal number new-to-old, and + * calls the user's handler through handlers[]. + */ + handlers[newsig] = act->sa_handler; + _siguhandler[newsig] = maphandler; + if ((act->sa_handler == SIG_DFL) || + (act->sa_handler == SIG_IGN)) + S5_act.sa_handler = act->sa_handler; + else + S5_act.sa_handler = _sigvechandler; + S5_act.sa_mask.__sigbits[0] = maptonewmask(act->sa_mask); + S5_act.sa_mask.__sigbits[1] = 0; + S5_act.sa_mask.__sigbits[2] = 0; + S5_act.sa_mask.__sigbits[3] = 0; + + ret = _sigaction(newsig, &S5_act, &S5_oact); + } + + if ((oact != NULL) && (ret != -1)) { + oact->sa_flags = 0; + if (S5_oact.sa_flags & S5_SA_ONSTACK) + oact->sa_flags |= SA_ONSTACK; + if (S5_oact.sa_flags & S5_SA_RESETHAND) + oact->sa_flags |= SA_RESETHAND; + if (S5_oact.sa_flags & S5_SA_NOCLDSTOP) + oact->sa_flags |= SA_NOCLDSTOP; + if (!(S5_oact.sa_flags & S5_SA_RESTART)) + oact->sa_flags |= SA_INTERRUPT; + if ((S5_oact.sa_handler == SIG_DFL) || + (S5_oact.sa_handler == SIG_IGN)) + oact->sa_handler = S5_oact.sa_handler; + else + oact->sa_handler = oldhand; + oact->sa_mask = maptooldmask(S5_oact.sa_mask.__sigbits[0]); + } + if (ret == -1) { + handlers[newsig] = oldhand; + _siguhandler[newsig] = oldsiguhand; + } + return (ret); +} + +static void +signal_init() { +#define S5_SIGPOLL 22 + _signal(S5_SIGPOLL, SIG_IGN); +#undef S5_SIGPOLL +} + +int +sigprocmask(how, set, oset) +int how; +sigset_t *set, *oset; +{ + int how_map[] = {0, 1, 2, 0, 3}; + int ret; + S5_sigset_t s5_set, s5_oset; + + if (set == NULL) /* query */ + ret = _sigprocmask(how_map[how], NULL, &s5_oset); + else { + memset(&s5_set, 0, sizeof (S5_sigset_t)); + s5_set.__sigbits[0] = maptonewmask(*set); + ret = _sigprocmask(how_map[how], &s5_set, &s5_oset); + } + if ((oset != NULL) && (ret == 0)) + *oset = maptooldmask(s5_oset.__sigbits[0]); + return (ret); +} + +int +sigpending(set) +sigset_t *set; +{ + S5_sigset_t s5_set; + int ret; + + ret = _sigpending(&s5_set); + *set = maptooldmask(s5_set.__sigbits[0]); + return (ret); +} |