Home | History | Annotate | Download | only in syscall
      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