1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 22 /* All Rights Reserved */ 23 24 25 /* 26 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 #pragma ident "@(#)ssig.c 1.146 07/01/10 SMI" 31 32 #include <sys/param.h> 33 #include <sys/types.h> 34 #include <sys/sysmacros.h> 35 #include <sys/systm.h> 36 #include <sys/user.h> 37 #include <sys/errno.h> 38 #include <sys/proc.h> 39 #include <sys/fault.h> 40 #include <sys/procset.h> 41 #include <sys/signal.h> 42 #include <sys/schedctl.h> 43 #include <sys/debug.h> 44 45 46 /* 47 * ssig() is the old common entry for signal, sigset, sighold, 48 * sigrelse, sigignore and sigpause. 49 * 50 * All of these interfaces have been reimplemented in libc using 51 * calls to sigaction, sigsuspend and sigprocmask. 52 * 53 * This kernel interface is no longer called by any application 54 * that is dynamically linked with libc. It exists solely for 55 * the benefit of really old statically-linked applications. 56 * It should be removed from the system. 57 */ 58 59 int 60 ssig(int signo, void (*func)()) 61 { 62 int sig; 63 struct proc *p; 64 int flags; 65 int retval = 0; 66 int sigcld_look = 0; 67 68 sig = signo & SIGNO_MASK; 69 70 if (sig <= 0 || sig >= NSIG || sigismember(&cantmask, sig)) 71 return (set_errno(EINVAL)); 72 73 p = ttoproc(curthread); 74 mutex_enter(&p->p_lock); 75 schedctl_finish_sigblock(curthread); 76 switch (signo & ~SIGNO_MASK) { 77 78 case SIGHOLD: /* sighold */ 79 sigaddset(&curthread->t_hold, sig); 80 mutex_exit(&p->p_lock); 81 return (0); 82 83 case SIGRELSE: /* sigrelse */ 84 sigdelset(&curthread->t_hold, sig); 85 curthread->t_sig_check = 1; /* so ISSIG will see release */ 86 mutex_exit(&p->p_lock); 87 return (0); 88 89 case SIGPAUSE: /* sigpause */ 90 sigdelset(&curthread->t_hold, sig); 91 curthread->t_sig_check = 1; /* so ISSIG will see release */ 92 /* pause() */ 93 while (cv_wait_sig_swap(&curthread->t_delay_cv, &p->p_lock)) 94 ; 95 mutex_exit(&p->p_lock); 96 return (set_errno(EINTR)); 97 98 case SIGIGNORE: /* signore */ 99 sigdelset(&curthread->t_hold, sig); 100 curthread->t_sig_check = 1; /* so ISSIG will see release */ 101 func = SIG_IGN; 102 flags = 0; 103 break; 104 105 case SIGDEFER: /* sigset */ 106 if (sigismember(&curthread->t_hold, sig)) 107 retval = (int)SIG_HOLD; 108 else 109 retval = (int)(uintptr_t)PTOU(curproc)->u_signal[sig-1]; 110 if (func == SIG_HOLD) { 111 sigaddset(&curthread->t_hold, sig); 112 mutex_exit(&p->p_lock); 113 return (retval); 114 } 115 116 #if defined(__sparc) 117 /* 118 * Check alignment of handler 119 */ 120 if (func != SIG_IGN && func != SIG_DFL && 121 ((uintptr_t)func & 0x3) != 0) { 122 mutex_exit(&p->p_lock); 123 return (set_errno(EINVAL)); 124 } 125 #endif 126 sigdelset(&curthread->t_hold, sig); 127 curthread->t_sig_check = 1; /* so post_syscall sees it */ 128 flags = 0; 129 break; 130 131 case 0: /* signal */ 132 #if defined(__sparc) 133 /* 134 * Check alignment of handler 135 */ 136 if (func != SIG_IGN && func != SIG_DFL && 137 ((uintptr_t)func & 0x3) != 0) { 138 mutex_exit(&p->p_lock); 139 return (set_errno(EINVAL)); 140 } 141 #endif 142 retval = (int)(uintptr_t)PTOU(curproc)->u_signal[sig-1]; 143 flags = SA_RESETHAND|SA_NODEFER; 144 break; 145 146 default: /* error */ 147 mutex_exit(&p->p_lock); 148 return (set_errno(EINVAL)); 149 } 150 151 if (sigismember(&stopdefault, sig)) 152 flags |= SA_RESTART; 153 else if (sig == SIGCLD) { 154 flags |= SA_NOCLDSTOP; 155 if (func == SIG_IGN) 156 flags |= SA_NOCLDWAIT; 157 else if (func != SIG_DFL) 158 sigcld_look = 1; 159 } 160 161 setsigact(sig, func, nullsmask, flags); 162 mutex_exit(&p->p_lock); 163 164 if (sigcld_look) 165 sigcld_repost(); 166 167 return (retval); 168 } 169