+ ps->ps_oldmask = p->p_sigmask;
+ ps->ps_flags |= SAS_OLDMASK;
+ p->p_sigmask = uap->mask &~ sigcantmask;
+ (void) tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0);
+ /* always return EINTR rather than ERESTART... */
+ return (EINTR);
+}
+
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
+struct osigstack_args {
+ struct sigstack *nss;
+ struct sigstack *oss;
+};
+/* ARGSUSED */
+osigstack(p, uap, retval)
+ struct proc *p;
+ register struct osigstack_args *uap;
+ int *retval;
+{
+ struct sigstack ss;
+ struct sigacts *psp;
+ int error = 0;
+
+ psp = p->p_sigacts;
+ ss.ss_sp = psp->ps_sigstk.ss_base;
+ ss.ss_onstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
+ if (uap->oss && (error = copyout((caddr_t)&ss, (caddr_t)uap->oss,
+ sizeof (struct sigstack))))
+ return (error);
+ if (uap->nss && (error = copyin((caddr_t)uap->nss, (caddr_t)&ss,
+ sizeof (ss))) == 0) {
+ psp->ps_sigstk.ss_base = ss.ss_sp;
+ psp->ps_sigstk.ss_size = 0;
+ psp->ps_sigstk.ss_flags |= ss.ss_onstack & SA_ONSTACK;
+ psp->ps_flags |= SAS_ALTSTACK;
+ }
+ return (error);
+}
+#endif /* COMPAT_43 || COMPAT_SUNOS */
+
+struct sigaltstack_args {
+ struct sigaltstack *nss;
+ struct sigaltstack *oss;
+};
+/* ARGSUSED */
+sigaltstack(p, uap, retval)
+ struct proc *p;
+ register struct sigaltstack_args *uap;
+ int *retval;
+{
+ struct sigacts *psp;
+ struct sigaltstack ss;
+ int error;
+
+ psp = p->p_sigacts;
+ if ((psp->ps_flags & SAS_ALTSTACK) == 0)
+ psp->ps_sigstk.ss_flags |= SA_DISABLE;
+ if (uap->oss && (error = copyout((caddr_t)&psp->ps_sigstk,
+ (caddr_t)uap->oss, sizeof (struct sigaltstack))))
+ return (error);
+ if (uap->nss == 0)
+ return (0);
+ if (error = copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)))
+ return (error);
+ if (ss.ss_flags & SA_DISABLE) {
+ if (psp->ps_sigstk.ss_flags & SA_ONSTACK)
+ return (EINVAL);
+ psp->ps_flags &= ~SAS_ALTSTACK;
+ psp->ps_sigstk.ss_flags = ss.ss_flags;
+ return (0);
+ }
+ if (ss.ss_size < MINSIGSTKSZ)
+ return (ENOMEM);
+ psp->ps_flags |= SAS_ALTSTACK;
+ psp->ps_sigstk= ss;
+ return (0);
+}
+
+struct kill_args {
+ int pid;
+ int signo;
+};
+/* ARGSUSED */
+kill(cp, uap, retval)
+ register struct proc *cp;
+ register struct kill_args *uap;
+ int *retval;
+{
+ register struct proc *p;
+ register struct pcred *pc = cp->p_cred;
+
+ if ((unsigned) uap->signo >= NSIG)
+ return (EINVAL);
+ if (uap->pid > 0) {
+ /* kill single process */
+ p = pfind(uap->pid);
+ if (p == 0)
+ return (ESRCH);
+ if (!CANSIGNAL(cp, pc, p, uap->signo))
+ return (EPERM);
+ if (uap->signo)
+ psignal(p, uap->signo);
+ return (0);
+ }
+ switch (uap->pid) {
+ case -1: /* broadcast signal */
+ return (killpg1(cp, uap->signo, 0, 1));
+ case 0: /* signal own process group */
+ return (killpg1(cp, uap->signo, 0, 0));
+ default: /* negative explicit process group */
+ return (killpg1(cp, uap->signo, -uap->pid, 0));
+ }
+ /* NOTREACHED */
+}
+
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
+struct okillpg_args {
+ int pgid;
+ int signo;
+};
+/* ARGSUSED */
+okillpg(p, uap, retval)
+ struct proc *p;
+ register struct okillpg_args *uap;
+ int *retval;
+{
+
+ if ((unsigned) uap->signo >= NSIG)
+ return (EINVAL);
+ return (killpg1(p, uap->signo, uap->pgid, 0));
+}
+#endif /* COMPAT_43 || COMPAT_SUNOS */
+
+/*
+ * Common code for kill process group/broadcast kill.
+ * cp is calling process.
+ */
+killpg1(cp, signo, pgid, all)
+ register struct proc *cp;
+ int signo, pgid, all;
+{
+ register struct proc *p;
+ register struct pcred *pc = cp->p_cred;
+ struct pgrp *pgrp;
+ int nfound = 0;
+
+ if (all)
+ /*
+ * broadcast