141486Smckusick /* 241486Smckusick * Copyright (c) 1988 University of Utah. 341486Smckusick * Copyright (c) 1990 The Regents of the University of California. 441486Smckusick * All rights reserved. 541486Smckusick * 641486Smckusick * This code is derived from software contributed to Berkeley by 741486Smckusick * the Systems Programming Group of the University of Utah Computer 841486Smckusick * Science Department. 941486Smckusick * 1041486Smckusick * %sccs.include.redist.c% 1141486Smckusick * 1245753Smckusick * from: Utah $Hdr: hpux_sig.c 1.1 90/07/09$ 1341486Smckusick * 14*45816Smckusick * @(#)hpux_sig.c 7.7 (Berkeley) 12/16/90 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1841486Smckusick * Signal related HPUX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2241486Smckusick 2345788Sbostic #include "sys/param.h" 2445788Sbostic #include "sys/systm.h" 2545788Sbostic #include "sys/user.h" 2645788Sbostic #include "sys/kernel.h" 2745788Sbostic #include "sys/proc.h" 28*45816Smckusick #include "hpux.h" 2941486Smckusick 3041486Smckusick /* indexed by HPUX signal number - 1 */ 3141486Smckusick char hpuxtobsdsigmap[NSIG] = { 3241486Smckusick /*01*/ SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGIOT, SIGEMT, SIGFPE, 3341486Smckusick /*09*/ SIGKILL, SIGBUS, SIGSEGV, SIGSYS, SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, 3441486Smckusick /*17*/ SIGUSR2, SIGCHLD, 0, SIGVTALRM,SIGPROF, SIGIO, SIGWINCH, SIGSTOP, 3541486Smckusick /*25*/ SIGTSTP, SIGCONT,SIGTTIN, SIGTTOU, SIGURG, 0, 0, 0 3641486Smckusick }; 3741486Smckusick 3841486Smckusick /* indexed by BSD signal number - 1 */ 3941486Smckusick char bsdtohpuxsigmap[NSIG] = { 4041486Smckusick /*01*/ 1, 2, 3, 4, 5, 6, 7, 8, 4141486Smckusick /*09*/ 9, 10, 11, 12, 13, 14, 15, 29, 4241486Smckusick /*17*/ 24, 25, 26, 18, 27, 28, 22, 0, 4341486Smckusick /*25*/ 0, 20, 21, 23, 0, 16, 17, 0 4441486Smckusick }; 4541486Smckusick 4641486Smckusick /* 4741486Smckusick * XXX: In addition to mapping the signal number we also have 4841486Smckusick * to see if the "old" style signal mechinism is needed. 4941486Smckusick * If so, we set the OUSIG flag. This is not really correct 5041486Smckusick * as under HP-UX "old" style handling can be set on a per 5141486Smckusick * signal basis and we are setting it for all signals in one 5241486Smckusick * swell foop. I suspect we can get away with this since I 5341486Smckusick * doubt any program of interest mixes the two semantics. 5441486Smckusick */ 5543453Shibler hpuxsigvec(p, uap, retval) 5643453Shibler struct proc *p; 5743453Shibler register struct args { 5841486Smckusick int signo; 5941486Smckusick struct sigvec *nsv; 6041486Smckusick struct sigvec *osv; 6143453Shibler } *uap; 6243453Shibler int *retval; 6343453Shibler { 6441486Smckusick struct sigvec vec; 6541486Smckusick register struct sigvec *sv; 6641486Smckusick register int sig; 6743453Shibler int bit, error; 6841486Smckusick 6941486Smckusick sig = hpuxtobsdsig(uap->signo); 7043453Shibler if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) 7144421Skarels return (EINVAL); 7241486Smckusick sv = &vec; 7341486Smckusick if (uap->osv) { 7441486Smckusick sv->sv_handler = u.u_signal[sig]; 7541486Smckusick sv->sv_mask = u.u_sigmask[sig]; 7641486Smckusick bit = sigmask(sig); 7741486Smckusick sv->sv_flags = 0; 7841486Smckusick if ((u.u_sigonstack & bit) != 0) 7941486Smckusick sv->sv_flags |= SV_ONSTACK; 8041486Smckusick if ((u.u_sigintr & bit) != 0) 8141486Smckusick sv->sv_flags |= SV_INTERRUPT; 8241486Smckusick #if 0 8341486Smckusick /* XXX -- SOUSIG no longer exists, do something here */ 8443453Shibler if (p->p_flag & SOUSIG) 8541486Smckusick sv->sv_flags |= HPUXSV_RESET; /* XXX */ 8641486Smckusick #endif 8743453Shibler error = copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)); 8843453Shibler if (error) 8944421Skarels return (error); 9041486Smckusick } 9141486Smckusick if (uap->nsv) { 9243453Shibler error = copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec)); 9343453Shibler if (error) 9444421Skarels return (error); 9543453Shibler if (sig == SIGCONT && sv->sv_handler == SIG_IGN) 9644421Skarels return (EINVAL); 9743453Shibler setsigvec(p, sig, (struct sigaction *)sv); 9841486Smckusick #if 0 9941486Smckusick /* XXX -- SOUSIG no longer exists, do something here */ 10041486Smckusick if (sv->sv_flags & HPUXSV_RESET) 10143453Shibler p->p_flag |= SOUSIG; /* XXX */ 10241486Smckusick #endif 10341486Smckusick } 10444421Skarels return (0); 10541486Smckusick } 10641486Smckusick 10743453Shibler hpuxsigblock(p, uap, retval) 10843453Shibler register struct proc *p; 10943453Shibler struct args { 11043453Shibler int mask; 11143453Shibler } *uap; 11243453Shibler int *retval; 11341486Smckusick { 11441486Smckusick 11541486Smckusick (void) splhigh(); 11643453Shibler *retval = bsdtohpuxmask(p->p_sigmask); 11743453Shibler p->p_sigmask |= hpuxtobsdmask(uap->mask) &~ sigcantmask; 11841486Smckusick (void) spl0(); 11944421Skarels return (0); 12041486Smckusick } 12141486Smckusick 12243453Shibler hpuxsigsetmask(p, uap, retval) 12343453Shibler struct proc *p; 12443453Shibler struct args { 12543453Shibler int mask; 12643453Shibler } *uap; 12743453Shibler int *retval; 12841486Smckusick { 12941486Smckusick 13041486Smckusick (void) splhigh(); 13143453Shibler *retval = bsdtohpuxmask(p->p_sigmask); 13243453Shibler p->p_sigmask = hpuxtobsdmask(uap->mask) &~ sigcantmask; 13341486Smckusick (void) spl0(); 13444421Skarels return (0); 13541486Smckusick } 13641486Smckusick 13743453Shibler hpuxsigpause(p, uap, retval) 13843453Shibler struct proc *p; 13943453Shibler struct args { 14043453Shibler int mask; 14143453Shibler } *uap; 14243453Shibler int *retval; 14341486Smckusick { 14441486Smckusick 14541486Smckusick uap->mask = hpuxtobsdmask(uap->mask); 14644421Skarels return (sigsuspend(p, uap, retval)); 14741486Smckusick } 14841486Smckusick 14941486Smckusick /* not totally correct, but close enuf' */ 15043453Shibler hpuxkill(p, uap, retval) 15143453Shibler struct proc *p; 15243453Shibler struct args { 15341486Smckusick int pid; 15441486Smckusick int signo; 15543453Shibler } *uap; 15643453Shibler int *retval; 15743453Shibler { 15841486Smckusick 15941486Smckusick if (uap->signo) { 16041486Smckusick uap->signo = hpuxtobsdsig(uap->signo); 16141486Smckusick if (uap->signo == 0) 16241486Smckusick uap->signo = NSIG; 16341486Smckusick } 16444421Skarels return (kill(p, uap, retval)); 16541486Smckusick } 16641486Smckusick 16745753Smckusick /* 16845753Smckusick * The following (sigprocmask, sigpending, sigsuspend, sigaction are 16945753Smckusick * POSIX calls. Under BSD, the library routine dereferences the sigset_t 17045753Smckusick * pointers before traping. Not so under HP-UX. 17145753Smckusick */ 17245753Smckusick 17345753Smckusick /* 17445753Smckusick * Manipulate signal mask. 17545753Smckusick * Note that we receive new mask, not pointer, 17645753Smckusick * and return old mask as return value; 17745753Smckusick * the library stub does the rest. 17845753Smckusick */ 17945753Smckusick hpuxsigprocmask(p, uap, retval) 18045753Smckusick register struct proc *p; 18145753Smckusick struct args { 18245753Smckusick int how; 18345753Smckusick hpuxsigset_t *set; 18445753Smckusick hpuxsigset_t *oset; 18545753Smckusick } *uap; 18645753Smckusick int *retval; 18745753Smckusick { 18845753Smckusick int mask, error = 0; 18945753Smckusick hpuxsigset_t sigset; 19045753Smckusick 19145753Smckusick /* 19245753Smckusick * Copy out old mask first to ensure no errors. 19345753Smckusick * (proc sigmask should not be changed if call fails for any reason) 19445753Smckusick */ 19545753Smckusick if (uap->oset) { 19645753Smckusick bzero((caddr_t)&sigset, sizeof(sigset)); 19745753Smckusick sigset.sigset[0] = bsdtohpuxmask(p->p_sigmask); 19845753Smckusick if (copyout((caddr_t)&sigset, (caddr_t)uap->oset, sizeof(sigset))) 19945753Smckusick return (EFAULT); 20045753Smckusick } 20145753Smckusick if (uap->set) { 20245753Smckusick if (copyin((caddr_t)uap->set, (caddr_t)&sigset, sizeof(sigset))) 20345753Smckusick return (EFAULT); 20445753Smckusick mask = hpuxtobsdmask(sigset.sigset[0]); 20545753Smckusick (void) splhigh(); 20645753Smckusick switch (uap->how) { 20745753Smckusick case HPUXSIG_BLOCK: 20845753Smckusick p->p_sigmask |= mask &~ sigcantmask; 20945753Smckusick break; 21045753Smckusick case HPUXSIG_UNBLOCK: 21145753Smckusick p->p_sigmask &= ~mask; 21245753Smckusick break; 21345753Smckusick case HPUXSIG_SETMASK: 21445753Smckusick p->p_sigmask = mask &~ sigcantmask; 21545753Smckusick break; 21645753Smckusick default: 21745753Smckusick error = EINVAL; 21845753Smckusick break; 21945753Smckusick } 22045753Smckusick (void) spl0(); 22145753Smckusick } 22245753Smckusick return (error); 22345753Smckusick } 22445753Smckusick 22545753Smckusick hpuxsigpending(p, uap, retval) 22645753Smckusick register struct proc *p; 22745753Smckusick struct args { 22845753Smckusick hpuxsigset_t *set; 22945753Smckusick } *uap; 23045753Smckusick int *retval; 23145753Smckusick { 23245753Smckusick hpuxsigset_t sigset; 23345753Smckusick 23445753Smckusick sigset.sigset[0] = bsdtohpuxmask(p->p_sig); 23545753Smckusick return (copyout((caddr_t)&sigset, (caddr_t)uap->set, sizeof(sigset))); 23645753Smckusick } 23745753Smckusick 23845753Smckusick hpuxsigsuspend(p, uap, retval) 23945753Smckusick register struct proc *p; 24045753Smckusick struct args { 24145753Smckusick hpuxsigset_t *set; 24245753Smckusick } *uap; 24345753Smckusick int *retval; 24445753Smckusick { 24545753Smckusick hpuxsigset_t sigset; 24645753Smckusick int mask; 24745753Smckusick 24845753Smckusick if (copyin((caddr_t)uap->set, (caddr_t)&sigset, sizeof(sigset))) 24945753Smckusick return (EFAULT); 25045753Smckusick mask = hpuxtobsdmask(sigset.sigset[0]); 25145753Smckusick u.u_oldmask = p->p_sigmask; 25245753Smckusick p->p_flag |= SOMASK; 25345753Smckusick p->p_sigmask = mask &~ sigcantmask; 25445753Smckusick (void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0); 25545753Smckusick /* always return EINTR rather than ERESTART... */ 25645753Smckusick return (EINTR); 25745753Smckusick } 25845753Smckusick 25945753Smckusick hpuxsigaction(p, uap, retval) 26045753Smckusick struct proc *p; 26145753Smckusick register struct args { 26245753Smckusick int signo; 26345753Smckusick struct hpuxsigaction *nsa; 26445753Smckusick struct hpuxsigaction *osa; 26545753Smckusick } *uap; 26645753Smckusick int *retval; 26745753Smckusick { 26845753Smckusick struct hpuxsigaction action; 26945753Smckusick register struct hpuxsigaction *sa; 27045753Smckusick register int sig; 27145753Smckusick int bit; 27245753Smckusick 27345753Smckusick sig = hpuxtobsdsig(uap->signo); 27445753Smckusick if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) 27545753Smckusick return (EINVAL); 27645753Smckusick 27745753Smckusick sa = &action; 27845753Smckusick if (uap->osa) { 27945753Smckusick sa->sa_handler = u.u_signal[sig]; 28045753Smckusick bzero((caddr_t)&sa->sa_mask, sizeof(sa->sa_mask)); 28145753Smckusick sa->sa_mask.sigset[0] = bsdtohpuxmask(u.u_sigmask[sig]); 28245753Smckusick bit = sigmask(sig); 28345753Smckusick sa->sa_flags = 0; 28445753Smckusick if ((u.u_sigonstack & bit) != 0) 28545753Smckusick sa->sa_flags |= HPUXSA_ONSTACK; 28645753Smckusick #if 0 28745753Smckusick /* XXX -- SOUSIG no longer exists, do something here */ 28845753Smckusick if (p->p_flag & SOUSIG) 28945753Smckusick sa->sa_flags |= HPUXSA_RESETHAND; /* XXX */ 29045753Smckusick #endif 29145753Smckusick if (p->p_flag & SNOCLDSTOP) 29245753Smckusick sa->sa_flags |= HPUXSA_NOCLDSTOP; 29345753Smckusick if (copyout((caddr_t)sa, (caddr_t)uap->osa, sizeof (action))) 29445753Smckusick return (EFAULT); 29545753Smckusick } 29645753Smckusick if (uap->nsa) { 29745753Smckusick struct sigaction act; 29845753Smckusick 29945753Smckusick if (copyin((caddr_t)uap->nsa, (caddr_t)sa, sizeof (action))) 30045753Smckusick return (EFAULT); 30145753Smckusick if (sig == SIGCONT && sa->sa_handler == SIG_IGN) 30245753Smckusick return (EINVAL); 30345753Smckusick /* 30445753Smckusick * Create a sigaction struct for setsigvec 30545753Smckusick */ 30645753Smckusick act.sa_handler = sa->sa_handler; 30745753Smckusick act.sa_mask = hpuxtobsdmask(sa->sa_mask.sigset[0]); 30845753Smckusick act.sa_flags = 0; 30945753Smckusick if (sa->sa_flags & HPUXSA_ONSTACK) 31045753Smckusick act.sa_flags |= SA_ONSTACK; 31145753Smckusick if (sa->sa_flags & HPUXSA_NOCLDSTOP) 31245753Smckusick act.sa_flags |= SA_NOCLDSTOP; 31345753Smckusick setsigvec(p, sig, &act); 31445753Smckusick #if 0 31545753Smckusick /* XXX -- SOUSIG no longer exists, do something here */ 31645753Smckusick if (sa->sa_flags & HPUXSA_RESETHAND) 31745753Smckusick p->p_flag |= SOUSIG; /* XXX */ 31845753Smckusick #endif 31945753Smckusick } 32045753Smckusick return (0); 32145753Smckusick } 32245753Smckusick 32343453Shibler ohpuxssig(p, uap, retval) 32443453Shibler struct proc *p; 32543453Shibler struct args { 32641486Smckusick int signo; 32741486Smckusick sig_t fun; 32843453Shibler } *uap; 32943453Shibler int *retval; 33043453Shibler { 33141486Smckusick register int a; 33241486Smckusick struct sigvec vec; 33341486Smckusick register struct sigvec *sv = &vec; 33441486Smckusick 33541486Smckusick a = hpuxtobsdsig(uap->signo); 33641486Smckusick sv->sv_handler = uap->fun; 33741486Smckusick /* 33841486Smckusick * Kill processes trying to use job control facilities 33941486Smckusick * (this'll help us find any vestiges of the old stuff). 34041486Smckusick */ 34141486Smckusick if ((a &~ 0377) || 34241486Smckusick (sv->sv_handler != SIG_DFL && sv->sv_handler != SIG_IGN && 34341486Smckusick ((int)sv->sv_handler) & 1)) { 34441486Smckusick psignal(p, SIGSYS); 34544421Skarels return (0); 34641486Smckusick } 34741486Smckusick if (a <= 0 || a >= NSIG || a == SIGKILL || a == SIGSTOP || 34843453Shibler a == SIGCONT && sv->sv_handler == SIG_IGN) 34944421Skarels return (EINVAL); 35041486Smckusick sv->sv_mask = 0; 35141486Smckusick sv->sv_flags = SV_INTERRUPT; 35243453Shibler *retval = (int)u.u_signal[a]; 35343453Shibler setsigvec(p, a, (struct sigaction *)sv); 35441486Smckusick #if 0 35541486Smckusick p->p_flag |= SOUSIG; /* mark as simulating old stuff */ 35641486Smckusick #endif 35744421Skarels return (0); 35841486Smckusick } 35941486Smckusick 36041486Smckusick /* signal numbers: convert from HPUX to BSD */ 36141486Smckusick hpuxtobsdsig(sig) 36241486Smckusick register int sig; 36341486Smckusick { 36441486Smckusick if (--sig < 0 || sig >= NSIG) 36541486Smckusick return(0); 36641486Smckusick return((int)hpuxtobsdsigmap[sig]); 36741486Smckusick } 36841486Smckusick 36941486Smckusick /* signal numbers: convert from BSD to HPUX */ 37041486Smckusick bsdtohpuxsig(sig) 37141486Smckusick register int sig; 37241486Smckusick { 37341486Smckusick if (--sig < 0 || sig >= NSIG) 37441486Smckusick return(0); 37541486Smckusick return((int)bsdtohpuxsigmap[sig]); 37641486Smckusick } 37741486Smckusick 37841486Smckusick /* signal masks: convert from HPUX to BSD (not pretty or fast) */ 37941486Smckusick hpuxtobsdmask(mask) 38041486Smckusick register int mask; 38141486Smckusick { 38241486Smckusick register int nmask, sig, nsig; 38341486Smckusick 38441486Smckusick if (mask == 0 || mask == -1) 38541486Smckusick return(mask); 38641486Smckusick nmask = 0; 38741486Smckusick for (sig = 1; sig < NSIG; sig++) 38841486Smckusick if ((mask & sigmask(sig)) && (nsig = hpuxtobsdsig(sig))) 38941486Smckusick nmask |= sigmask(nsig); 39041486Smckusick return(nmask); 39141486Smckusick } 39241486Smckusick 39341486Smckusick bsdtohpuxmask(mask) 39441486Smckusick register int mask; 39541486Smckusick { 39641486Smckusick register int nmask, sig, nsig; 39741486Smckusick 39841486Smckusick if (mask == 0 || mask == -1) 39941486Smckusick return(mask); 40041486Smckusick nmask = 0; 40141486Smckusick for (sig = 1; sig < NSIG; sig++) 40241486Smckusick if ((mask & sigmask(sig)) && (nsig = bsdtohpuxsig(sig))) 40341486Smckusick nmask |= sigmask(nsig); 40441486Smckusick return(nmask); 40541486Smckusick } 40641486Smckusick #endif 407