/*
* 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);
}