1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 1982, 1986, 1989, 1991, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
* (c) UNIX System Laboratories, Inc.
|
|
|
|
* All or some portions of this file are derived from material licensed
|
|
|
|
* to the University of California by American Telephone and Telegraph
|
|
|
|
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
|
|
|
* the permission of UNIX System Laboratories, Inc.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
* California, Berkeley and its contributors.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* @(#)kern_sig.c 8.7 (Berkeley) 4/18/94
|
1998-10-21 16:31:38 +00:00
|
|
|
* $Id: kern_sig.c,v 1.47 1998/09/14 23:25:18 jdp Exp $
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
|
|
|
|
1997-12-16 17:40:42 +00:00
|
|
|
#include "opt_compat.h"
|
1996-01-03 21:42:35 +00:00
|
|
|
#include "opt_ktrace.h"
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
#define SIGPROP /* include signal properties table */
|
|
|
|
#include <sys/param.h>
|
1998-06-28 08:37:45 +00:00
|
|
|
#include <sys/kernel.h>
|
1995-11-12 06:43:28 +00:00
|
|
|
#include <sys/sysproto.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/signalvar.h>
|
|
|
|
#include <sys/resourcevar.h>
|
|
|
|
#include <sys/namei.h>
|
|
|
|
#include <sys/vnode.h>
|
|
|
|
#include <sys/proc.h>
|
1997-12-06 04:11:14 +00:00
|
|
|
#include <sys/pioctl.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/acct.h>
|
1997-03-23 03:37:54 +00:00
|
|
|
#include <sys/fcntl.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <sys/ktrace.h>
|
|
|
|
#include <sys/syslog.h>
|
|
|
|
#include <sys/stat.h>
|
Mega-commit for Linux emulator update.. This has been stress tested under
netscape-2.0 for Linux running all the Java stuff. The scrollbars are now
working, at least on my machine. (whew! :-)
I'm uncomfortable with the size of this commit, but it's too
inter-dependant to easily seperate out.
The main changes:
COMPAT_LINUX is *GONE*. Most of the code has been moved out of the i386
machine dependent section into the linux emulator itself. The int 0x80
syscall code was almost identical to the lcall 7,0 code and a minor tweak
allows them to both be used with the same C code. All kernels can now
just modload the lkm and it'll DTRT without having to rebuild the kernel
first. Like IBCS2, you can statically compile it in with "options LINUX".
A pile of new syscalls implemented, including getdents(), llseek(),
readv(), writev(), msync(), personality(). The Linux-ELF libraries want
to use some of these.
linux_select() now obeys Linux semantics, ie: returns the time remaining
of the timeout value rather than leaving it the original value.
Quite a few bugs removed, including incorrect arguments being used in
syscalls.. eg: mixups between passing the sigset as an int, vs passing
it as a pointer and doing a copyin(), missing return values, unhandled
cases, SIOC* ioctls, etc.
The build for the code has changed. i386/conf/files now knows how
to build linux_genassym and generate linux_assym.h on the fly.
Supporting changes elsewhere in the kernel:
The user-mode signal trampoline has moved from the U area to immediately
below the top of the stack (below PS_STRINGS). This allows the different
binary emulations to have their own signal trampoline code (which gets rid
of the hardwired syscall 103 (sigreturn on BSD, syslog on Linux)) and so
that the emulator can provide the exact "struct sigcontext *" argument to
the program's signal handlers.
The sigstack's "ss_flags" now uses SS_DISABLE and SS_ONSTACK flags, which
have the same values as the re-used SA_DISABLE and SA_ONSTACK which are
intended for sigaction only. This enables the support of a SA_RESETHAND
flag to sigaction to implement the gross SYSV and Linux SA_ONESHOT signal
semantics where the signal handler is reset when it's triggered.
makesyscalls.sh no longer appends the struct sysentvec on the end of the
generated init_sysent.c code. It's a lot saner to have it in a seperate
file rather than trying to update the structure inside the awk script. :-)
At exec time, the dozen bytes or so of signal trampoline code are copied
to the top of the user's stack, rather than obtaining the trampoline code
the old way by getting a clone of the parent's user area. This allows
Linux and native binaries to freely exec each other without getting
trampolines mixed up.
1996-03-02 19:38:20 +00:00
|
|
|
#include <sys/sysent.h>
|
1998-06-28 08:37:45 +00:00
|
|
|
#include <sys/sysctl.h>
|
1998-07-08 06:38:39 +00:00
|
|
|
#include <sys/malloc.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
|
|
|
|
#include <machine/cpu.h>
|
1998-03-03 20:55:26 +00:00
|
|
|
#ifdef SMP
|
|
|
|
#include <machine/smp.h>
|
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1995-12-14 08:32:45 +00:00
|
|
|
static int killpg1 __P((struct proc *cp, int signum, int pgid, int all));
|
1997-08-26 00:31:04 +00:00
|
|
|
static void setsigvec __P((struct proc *p, int signum, struct sigaction *sa));
|
1995-12-14 08:32:45 +00:00
|
|
|
static void stop __P((struct proc *));
|
1994-05-25 09:21:21 +00:00
|
|
|
|
1998-07-28 22:34:12 +00:00
|
|
|
static int kern_logsigexit = 1;
|
|
|
|
SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW, &kern_logsigexit, 0, "");
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Can process p, with pcred pc, send the signal signum to process q?
|
|
|
|
*/
|
|
|
|
#define CANSIGNAL(p, pc, q, signum) \
|
|
|
|
((pc)->pc_ucred->cr_uid == 0 || \
|
|
|
|
(pc)->p_ruid == (q)->p_cred->p_ruid || \
|
|
|
|
(pc)->pc_ucred->cr_uid == (q)->p_cred->p_ruid || \
|
|
|
|
(pc)->p_ruid == (q)->p_ucred->cr_uid || \
|
|
|
|
(pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \
|
|
|
|
((signum) == SIGCONT && (q)->p_session == (p)->p_session))
|
|
|
|
|
1998-09-14 05:36:51 +00:00
|
|
|
int sugid_coredump;
|
1998-06-28 08:37:45 +00:00
|
|
|
SYSCTL_INT(_kern, OID_AUTO, sugid_coredump, CTLFLAG_RW, &sugid_coredump, 0, "");
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sigaction_args {
|
|
|
|
int signum;
|
|
|
|
struct sigaction *nsa;
|
|
|
|
struct sigaction *osa;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
sigaction(p, uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
struct proc *p;
|
|
|
|
register struct sigaction_args *uap;
|
|
|
|
{
|
|
|
|
struct sigaction vec;
|
|
|
|
register struct sigaction *sa;
|
|
|
|
register struct sigacts *ps = p->p_sigacts;
|
|
|
|
register int signum;
|
|
|
|
int bit, error;
|
|
|
|
|
|
|
|
signum = uap->signum;
|
1996-11-29 18:01:55 +00:00
|
|
|
if (signum <= 0 || signum >= NSIG)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EINVAL);
|
|
|
|
sa = &vec;
|
|
|
|
if (uap->osa) {
|
|
|
|
sa->sa_handler = ps->ps_sigact[signum];
|
|
|
|
sa->sa_mask = ps->ps_catchmask[signum];
|
|
|
|
bit = sigmask(signum);
|
|
|
|
sa->sa_flags = 0;
|
|
|
|
if ((ps->ps_sigonstack & bit) != 0)
|
|
|
|
sa->sa_flags |= SA_ONSTACK;
|
|
|
|
if ((ps->ps_sigintr & bit) == 0)
|
|
|
|
sa->sa_flags |= SA_RESTART;
|
1996-03-15 08:01:33 +00:00
|
|
|
if ((ps->ps_sigreset & bit) != 0)
|
|
|
|
sa->sa_flags |= SA_RESETHAND;
|
1996-03-30 15:15:30 +00:00
|
|
|
if ((ps->ps_signodefer & bit) != 0)
|
1995-10-19 19:16:01 +00:00
|
|
|
sa->sa_flags |= SA_NODEFER;
|
1996-03-30 15:15:30 +00:00
|
|
|
if (signum == SIGCHLD && p->p_flag & P_NOCLDSTOP)
|
|
|
|
sa->sa_flags |= SA_NOCLDSTOP;
|
1997-09-13 19:42:29 +00:00
|
|
|
if (signum == SIGCHLD && p->p_flag & P_NOCLDWAIT)
|
|
|
|
sa->sa_flags |= SA_NOCLDWAIT;
|
1994-09-25 19:34:02 +00:00
|
|
|
if ((error = copyout((caddr_t)sa, (caddr_t)uap->osa,
|
|
|
|
sizeof (vec))))
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
if (uap->nsa) {
|
1994-09-25 19:34:02 +00:00
|
|
|
if ((error = copyin((caddr_t)uap->nsa, (caddr_t)sa,
|
|
|
|
sizeof (vec))))
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
1996-11-29 18:01:55 +00:00
|
|
|
if ((signum == SIGKILL || signum == SIGSTOP) &&
|
|
|
|
sa->sa_handler != SIG_DFL)
|
|
|
|
return (EINVAL);
|
1994-05-24 10:09:53 +00:00
|
|
|
setsigvec(p, signum, sa);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1997-08-26 00:31:04 +00:00
|
|
|
static void
|
1994-05-24 10:09:53 +00:00
|
|
|
setsigvec(p, signum, sa)
|
|
|
|
register struct proc *p;
|
|
|
|
int signum;
|
|
|
|
register struct sigaction *sa;
|
|
|
|
{
|
|
|
|
register struct sigacts *ps = p->p_sigacts;
|
|
|
|
register int bit;
|
|
|
|
|
|
|
|
bit = sigmask(signum);
|
|
|
|
/*
|
|
|
|
* Change setting atomically.
|
|
|
|
*/
|
|
|
|
(void) splhigh();
|
|
|
|
ps->ps_sigact[signum] = sa->sa_handler;
|
|
|
|
ps->ps_catchmask[signum] = sa->sa_mask &~ sigcantmask;
|
|
|
|
if ((sa->sa_flags & SA_RESTART) == 0)
|
|
|
|
ps->ps_sigintr |= bit;
|
|
|
|
else
|
|
|
|
ps->ps_sigintr &= ~bit;
|
|
|
|
if (sa->sa_flags & SA_ONSTACK)
|
|
|
|
ps->ps_sigonstack |= bit;
|
|
|
|
else
|
|
|
|
ps->ps_sigonstack &= ~bit;
|
1996-03-15 08:01:33 +00:00
|
|
|
if (sa->sa_flags & SA_RESETHAND)
|
|
|
|
ps->ps_sigreset |= bit;
|
1995-10-19 19:16:01 +00:00
|
|
|
else
|
1996-03-15 08:01:33 +00:00
|
|
|
ps->ps_sigreset &= ~bit;
|
1996-03-30 15:15:30 +00:00
|
|
|
if (sa->sa_flags & SA_NODEFER)
|
|
|
|
ps->ps_signodefer |= bit;
|
|
|
|
else
|
|
|
|
ps->ps_signodefer &= ~bit;
|
1994-05-24 10:09:53 +00:00
|
|
|
#ifdef COMPAT_SUNOS
|
|
|
|
if (sa->sa_flags & SA_USERTRAMP)
|
|
|
|
ps->ps_usertramp |= bit;
|
|
|
|
else
|
|
|
|
ps->ps_usertramp &= ~bit;
|
|
|
|
#endif
|
|
|
|
if (signum == SIGCHLD) {
|
|
|
|
if (sa->sa_flags & SA_NOCLDSTOP)
|
|
|
|
p->p_flag |= P_NOCLDSTOP;
|
|
|
|
else
|
|
|
|
p->p_flag &= ~P_NOCLDSTOP;
|
1997-09-13 19:42:29 +00:00
|
|
|
if (sa->sa_flags & SA_NOCLDWAIT) {
|
|
|
|
/*
|
|
|
|
* Paranoia: since SA_NOCLDWAIT is implemented by
|
|
|
|
* reparenting the dying child to PID 1 (and
|
|
|
|
* trust it to reap the zombie), PID 1 itself is
|
|
|
|
* forbidden to set SA_NOCLDWAIT.
|
|
|
|
*/
|
|
|
|
if (p->p_pid == 1)
|
|
|
|
p->p_flag &= ~P_NOCLDWAIT;
|
|
|
|
else
|
|
|
|
p->p_flag |= P_NOCLDWAIT;
|
|
|
|
} else
|
|
|
|
p->p_flag &= ~P_NOCLDWAIT;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Set bit in p_sigignore for signals that are set to SIG_IGN,
|
|
|
|
* and for signals set to SIG_DFL where the default is to ignore.
|
|
|
|
* However, don't put SIGCONT in p_sigignore,
|
|
|
|
* as we have to restart the process.
|
|
|
|
*/
|
|
|
|
if (sa->sa_handler == SIG_IGN ||
|
|
|
|
(sigprop[signum] & SA_IGNORE && sa->sa_handler == SIG_DFL)) {
|
|
|
|
p->p_siglist &= ~bit; /* never to be seen again */
|
|
|
|
if (signum != SIGCONT)
|
|
|
|
p->p_sigignore |= bit; /* easier in psignal */
|
|
|
|
p->p_sigcatch &= ~bit;
|
|
|
|
} else {
|
|
|
|
p->p_sigignore &= ~bit;
|
|
|
|
if (sa->sa_handler == SIG_DFL)
|
|
|
|
p->p_sigcatch &= ~bit;
|
|
|
|
else
|
|
|
|
p->p_sigcatch |= bit;
|
|
|
|
}
|
|
|
|
(void) spl0();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize signal state for process 0;
|
|
|
|
* set to ignore signals that are ignored by default.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
siginit(p)
|
|
|
|
struct proc *p;
|
|
|
|
{
|
|
|
|
register int i;
|
|
|
|
|
|
|
|
for (i = 0; i < NSIG; i++)
|
|
|
|
if (sigprop[i] & SA_IGNORE && i != SIGCONT)
|
|
|
|
p->p_sigignore |= sigmask(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset signals for an exec of the specified process.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
execsigs(p)
|
|
|
|
register struct proc *p;
|
|
|
|
{
|
|
|
|
register struct sigacts *ps = p->p_sigacts;
|
|
|
|
register int nc, mask;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset caught signals. Held signals remain held
|
|
|
|
* through p_sigmask (unless they were caught,
|
|
|
|
* and are now ignored by default).
|
|
|
|
*/
|
|
|
|
while (p->p_sigcatch) {
|
|
|
|
nc = ffs((long)p->p_sigcatch);
|
|
|
|
mask = sigmask(nc);
|
|
|
|
p->p_sigcatch &= ~mask;
|
|
|
|
if (sigprop[nc] & SA_IGNORE) {
|
|
|
|
if (nc != SIGCONT)
|
|
|
|
p->p_sigignore |= mask;
|
|
|
|
p->p_siglist &= ~mask;
|
|
|
|
}
|
|
|
|
ps->ps_sigact[nc] = SIG_DFL;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Reset stack state to the user stack.
|
|
|
|
* Clear set of signals caught on the signal stack.
|
|
|
|
*/
|
Mega-commit for Linux emulator update.. This has been stress tested under
netscape-2.0 for Linux running all the Java stuff. The scrollbars are now
working, at least on my machine. (whew! :-)
I'm uncomfortable with the size of this commit, but it's too
inter-dependant to easily seperate out.
The main changes:
COMPAT_LINUX is *GONE*. Most of the code has been moved out of the i386
machine dependent section into the linux emulator itself. The int 0x80
syscall code was almost identical to the lcall 7,0 code and a minor tweak
allows them to both be used with the same C code. All kernels can now
just modload the lkm and it'll DTRT without having to rebuild the kernel
first. Like IBCS2, you can statically compile it in with "options LINUX".
A pile of new syscalls implemented, including getdents(), llseek(),
readv(), writev(), msync(), personality(). The Linux-ELF libraries want
to use some of these.
linux_select() now obeys Linux semantics, ie: returns the time remaining
of the timeout value rather than leaving it the original value.
Quite a few bugs removed, including incorrect arguments being used in
syscalls.. eg: mixups between passing the sigset as an int, vs passing
it as a pointer and doing a copyin(), missing return values, unhandled
cases, SIOC* ioctls, etc.
The build for the code has changed. i386/conf/files now knows how
to build linux_genassym and generate linux_assym.h on the fly.
Supporting changes elsewhere in the kernel:
The user-mode signal trampoline has moved from the U area to immediately
below the top of the stack (below PS_STRINGS). This allows the different
binary emulations to have their own signal trampoline code (which gets rid
of the hardwired syscall 103 (sigreturn on BSD, syslog on Linux)) and so
that the emulator can provide the exact "struct sigcontext *" argument to
the program's signal handlers.
The sigstack's "ss_flags" now uses SS_DISABLE and SS_ONSTACK flags, which
have the same values as the re-used SA_DISABLE and SA_ONSTACK which are
intended for sigaction only. This enables the support of a SA_RESETHAND
flag to sigaction to implement the gross SYSV and Linux SA_ONESHOT signal
semantics where the signal handler is reset when it's triggered.
makesyscalls.sh no longer appends the struct sysentvec on the end of the
generated init_sysent.c code. It's a lot saner to have it in a seperate
file rather than trying to update the structure inside the awk script. :-)
At exec time, the dozen bytes or so of signal trampoline code are copied
to the top of the user's stack, rather than obtaining the trampoline code
the old way by getting a clone of the parent's user area. This allows
Linux and native binaries to freely exec each other without getting
trampolines mixed up.
1996-03-02 19:38:20 +00:00
|
|
|
ps->ps_sigstk.ss_flags = SS_DISABLE;
|
1994-05-24 10:09:53 +00:00
|
|
|
ps->ps_sigstk.ss_size = 0;
|
1995-01-29 01:19:25 +00:00
|
|
|
ps->ps_sigstk.ss_sp = 0;
|
1994-05-24 10:09:53 +00:00
|
|
|
ps->ps_flags = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Manipulate signal mask.
|
|
|
|
* Note that we receive new mask, not pointer,
|
|
|
|
* and return old mask as return value;
|
|
|
|
* the library stub does the rest.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sigprocmask_args {
|
|
|
|
int how;
|
|
|
|
sigset_t mask;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
sigprocmask(p, uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
register struct proc *p;
|
|
|
|
struct sigprocmask_args *uap;
|
|
|
|
{
|
|
|
|
int error = 0;
|
|
|
|
|
1997-11-06 19:29:57 +00:00
|
|
|
p->p_retval[0] = p->p_sigmask;
|
1994-05-24 10:09:53 +00:00
|
|
|
(void) splhigh();
|
|
|
|
|
|
|
|
switch (uap->how) {
|
|
|
|
case SIG_BLOCK:
|
|
|
|
p->p_sigmask |= uap->mask &~ sigcantmask;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIG_UNBLOCK:
|
|
|
|
p->p_sigmask &= ~uap->mask;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIG_SETMASK:
|
|
|
|
p->p_sigmask = uap->mask &~ sigcantmask;
|
|
|
|
break;
|
1995-05-30 08:16:23 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
(void) spl0();
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sigpending_args {
|
|
|
|
int dummy;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
sigpending(p, uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
struct proc *p;
|
|
|
|
struct sigpending_args *uap;
|
|
|
|
{
|
|
|
|
|
1997-11-06 19:29:57 +00:00
|
|
|
p->p_retval[0] = p->p_siglist;
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
|
|
|
/*
|
|
|
|
* Generalized interface signal handler, 4.3-compatible.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct osigvec_args {
|
|
|
|
int signum;
|
|
|
|
struct sigvec *nsv;
|
|
|
|
struct sigvec *osv;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
osigvec(p, uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
struct proc *p;
|
|
|
|
register struct osigvec_args *uap;
|
|
|
|
{
|
|
|
|
struct sigvec vec;
|
|
|
|
register struct sigacts *ps = p->p_sigacts;
|
|
|
|
register struct sigvec *sv;
|
|
|
|
register int signum;
|
|
|
|
int bit, error;
|
|
|
|
|
|
|
|
signum = uap->signum;
|
1996-11-29 18:01:55 +00:00
|
|
|
if (signum <= 0 || signum >= NSIG)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EINVAL);
|
|
|
|
sv = &vec;
|
|
|
|
if (uap->osv) {
|
|
|
|
*(sig_t *)&sv->sv_handler = ps->ps_sigact[signum];
|
|
|
|
sv->sv_mask = ps->ps_catchmask[signum];
|
|
|
|
bit = sigmask(signum);
|
|
|
|
sv->sv_flags = 0;
|
|
|
|
if ((ps->ps_sigonstack & bit) != 0)
|
|
|
|
sv->sv_flags |= SV_ONSTACK;
|
|
|
|
if ((ps->ps_sigintr & bit) != 0)
|
|
|
|
sv->sv_flags |= SV_INTERRUPT;
|
1996-03-30 15:15:30 +00:00
|
|
|
if ((ps->ps_sigreset & bit) != 0)
|
|
|
|
sv->sv_flags |= SV_RESETHAND;
|
|
|
|
if ((ps->ps_signodefer & bit) != 0)
|
|
|
|
sv->sv_flags |= SV_NODEFER;
|
1994-05-24 10:09:53 +00:00
|
|
|
#ifndef COMPAT_SUNOS
|
1996-03-30 15:15:30 +00:00
|
|
|
if (signum == SIGCHLD && p->p_flag & P_NOCLDSTOP)
|
|
|
|
sv->sv_flags |= SV_NOCLDSTOP;
|
1994-05-24 10:09:53 +00:00
|
|
|
#endif
|
1994-09-25 19:34:02 +00:00
|
|
|
if ((error = copyout((caddr_t)sv, (caddr_t)uap->osv,
|
|
|
|
sizeof (vec))))
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
if (uap->nsv) {
|
1994-09-25 19:34:02 +00:00
|
|
|
if ((error = copyin((caddr_t)uap->nsv, (caddr_t)sv,
|
|
|
|
sizeof (vec))))
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
1996-11-29 18:01:55 +00:00
|
|
|
if ((signum == SIGKILL || signum == SIGSTOP) &&
|
|
|
|
sv->sv_handler != SIG_DFL)
|
|
|
|
return (EINVAL);
|
1994-05-24 10:09:53 +00:00
|
|
|
#ifdef COMPAT_SUNOS
|
|
|
|
sv->sv_flags |= SA_USERTRAMP;
|
|
|
|
#endif
|
|
|
|
sv->sv_flags ^= SA_RESTART; /* opposite of SV_INTERRUPT */
|
|
|
|
setsigvec(p, signum, (struct sigaction *)sv);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct osigblock_args {
|
|
|
|
int mask;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
osigblock(p, uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
register struct proc *p;
|
|
|
|
struct osigblock_args *uap;
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) splhigh();
|
1997-11-06 19:29:57 +00:00
|
|
|
p->p_retval[0] = p->p_sigmask;
|
1994-05-24 10:09:53 +00:00
|
|
|
p->p_sigmask |= uap->mask &~ sigcantmask;
|
|
|
|
(void) spl0();
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct osigsetmask_args {
|
|
|
|
int mask;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
osigsetmask(p, uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
struct proc *p;
|
|
|
|
struct osigsetmask_args *uap;
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) splhigh();
|
1997-11-06 19:29:57 +00:00
|
|
|
p->p_retval[0] = p->p_sigmask;
|
1994-05-24 10:09:53 +00:00
|
|
|
p->p_sigmask = uap->mask &~ sigcantmask;
|
|
|
|
(void) spl0();
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
#endif /* COMPAT_43 || COMPAT_SUNOS */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Suspend process until signal, providing mask to be set
|
|
|
|
* in the meantime. Note nonstandard calling convention:
|
|
|
|
* libc stub passes mask, not pointer, to save a copyin.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sigsuspend_args {
|
|
|
|
sigset_t mask;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
sigsuspend(p, uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
register struct proc *p;
|
|
|
|
struct sigsuspend_args *uap;
|
|
|
|
{
|
|
|
|
register struct sigacts *ps = p->p_sigacts;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When returning from sigpause, we want
|
|
|
|
* the old mask to be restored after the
|
|
|
|
* signal handler has finished. Thus, we
|
|
|
|
* save it here and mark the sigacts structure
|
|
|
|
* to indicate this.
|
|
|
|
*/
|
|
|
|
ps->ps_oldmask = p->p_sigmask;
|
|
|
|
ps->ps_flags |= SAS_OLDMASK;
|
|
|
|
p->p_sigmask = uap->mask &~ sigcantmask;
|
|
|
|
while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0) == 0)
|
|
|
|
/* void */;
|
|
|
|
/* always return EINTR rather than ERESTART... */
|
|
|
|
return (EINTR);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct osigstack_args {
|
|
|
|
struct sigstack *nss;
|
|
|
|
struct sigstack *oss;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
osigstack(p, uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
struct proc *p;
|
|
|
|
register struct osigstack_args *uap;
|
|
|
|
{
|
|
|
|
struct sigstack ss;
|
|
|
|
struct sigacts *psp;
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
psp = p->p_sigacts;
|
1995-01-29 01:19:25 +00:00
|
|
|
ss.ss_sp = psp->ps_sigstk.ss_sp;
|
Mega-commit for Linux emulator update.. This has been stress tested under
netscape-2.0 for Linux running all the Java stuff. The scrollbars are now
working, at least on my machine. (whew! :-)
I'm uncomfortable with the size of this commit, but it's too
inter-dependant to easily seperate out.
The main changes:
COMPAT_LINUX is *GONE*. Most of the code has been moved out of the i386
machine dependent section into the linux emulator itself. The int 0x80
syscall code was almost identical to the lcall 7,0 code and a minor tweak
allows them to both be used with the same C code. All kernels can now
just modload the lkm and it'll DTRT without having to rebuild the kernel
first. Like IBCS2, you can statically compile it in with "options LINUX".
A pile of new syscalls implemented, including getdents(), llseek(),
readv(), writev(), msync(), personality(). The Linux-ELF libraries want
to use some of these.
linux_select() now obeys Linux semantics, ie: returns the time remaining
of the timeout value rather than leaving it the original value.
Quite a few bugs removed, including incorrect arguments being used in
syscalls.. eg: mixups between passing the sigset as an int, vs passing
it as a pointer and doing a copyin(), missing return values, unhandled
cases, SIOC* ioctls, etc.
The build for the code has changed. i386/conf/files now knows how
to build linux_genassym and generate linux_assym.h on the fly.
Supporting changes elsewhere in the kernel:
The user-mode signal trampoline has moved from the U area to immediately
below the top of the stack (below PS_STRINGS). This allows the different
binary emulations to have their own signal trampoline code (which gets rid
of the hardwired syscall 103 (sigreturn on BSD, syslog on Linux)) and so
that the emulator can provide the exact "struct sigcontext *" argument to
the program's signal handlers.
The sigstack's "ss_flags" now uses SS_DISABLE and SS_ONSTACK flags, which
have the same values as the re-used SA_DISABLE and SA_ONSTACK which are
intended for sigaction only. This enables the support of a SA_RESETHAND
flag to sigaction to implement the gross SYSV and Linux SA_ONESHOT signal
semantics where the signal handler is reset when it's triggered.
makesyscalls.sh no longer appends the struct sysentvec on the end of the
generated init_sysent.c code. It's a lot saner to have it in a seperate
file rather than trying to update the structure inside the awk script. :-)
At exec time, the dozen bytes or so of signal trampoline code are copied
to the top of the user's stack, rather than obtaining the trampoline code
the old way by getting a clone of the parent's user area. This allows
Linux and native binaries to freely exec each other without getting
trampolines mixed up.
1996-03-02 19:38:20 +00:00
|
|
|
ss.ss_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
|
1994-05-24 10:09:53 +00:00
|
|
|
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) {
|
1995-01-29 01:19:25 +00:00
|
|
|
psp->ps_sigstk.ss_sp = ss.ss_sp;
|
1994-05-24 10:09:53 +00:00
|
|
|
psp->ps_sigstk.ss_size = 0;
|
Mega-commit for Linux emulator update.. This has been stress tested under
netscape-2.0 for Linux running all the Java stuff. The scrollbars are now
working, at least on my machine. (whew! :-)
I'm uncomfortable with the size of this commit, but it's too
inter-dependant to easily seperate out.
The main changes:
COMPAT_LINUX is *GONE*. Most of the code has been moved out of the i386
machine dependent section into the linux emulator itself. The int 0x80
syscall code was almost identical to the lcall 7,0 code and a minor tweak
allows them to both be used with the same C code. All kernels can now
just modload the lkm and it'll DTRT without having to rebuild the kernel
first. Like IBCS2, you can statically compile it in with "options LINUX".
A pile of new syscalls implemented, including getdents(), llseek(),
readv(), writev(), msync(), personality(). The Linux-ELF libraries want
to use some of these.
linux_select() now obeys Linux semantics, ie: returns the time remaining
of the timeout value rather than leaving it the original value.
Quite a few bugs removed, including incorrect arguments being used in
syscalls.. eg: mixups between passing the sigset as an int, vs passing
it as a pointer and doing a copyin(), missing return values, unhandled
cases, SIOC* ioctls, etc.
The build for the code has changed. i386/conf/files now knows how
to build linux_genassym and generate linux_assym.h on the fly.
Supporting changes elsewhere in the kernel:
The user-mode signal trampoline has moved from the U area to immediately
below the top of the stack (below PS_STRINGS). This allows the different
binary emulations to have their own signal trampoline code (which gets rid
of the hardwired syscall 103 (sigreturn on BSD, syslog on Linux)) and so
that the emulator can provide the exact "struct sigcontext *" argument to
the program's signal handlers.
The sigstack's "ss_flags" now uses SS_DISABLE and SS_ONSTACK flags, which
have the same values as the re-used SA_DISABLE and SA_ONSTACK which are
intended for sigaction only. This enables the support of a SA_RESETHAND
flag to sigaction to implement the gross SYSV and Linux SA_ONESHOT signal
semantics where the signal handler is reset when it's triggered.
makesyscalls.sh no longer appends the struct sysentvec on the end of the
generated init_sysent.c code. It's a lot saner to have it in a seperate
file rather than trying to update the structure inside the awk script. :-)
At exec time, the dozen bytes or so of signal trampoline code are copied
to the top of the user's stack, rather than obtaining the trampoline code
the old way by getting a clone of the parent's user area. This allows
Linux and native binaries to freely exec each other without getting
trampolines mixed up.
1996-03-02 19:38:20 +00:00
|
|
|
psp->ps_sigstk.ss_flags |= ss.ss_onstack & SS_ONSTACK;
|
1994-05-24 10:09:53 +00:00
|
|
|
psp->ps_flags |= SAS_ALTSTACK;
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
#endif /* COMPAT_43 || COMPAT_SUNOS */
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sigaltstack_args {
|
|
|
|
struct sigaltstack *nss;
|
|
|
|
struct sigaltstack *oss;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
sigaltstack(p, uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
struct proc *p;
|
|
|
|
register struct sigaltstack_args *uap;
|
|
|
|
{
|
|
|
|
struct sigacts *psp;
|
|
|
|
struct sigaltstack ss;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
psp = p->p_sigacts;
|
|
|
|
if ((psp->ps_flags & SAS_ALTSTACK) == 0)
|
Mega-commit for Linux emulator update.. This has been stress tested under
netscape-2.0 for Linux running all the Java stuff. The scrollbars are now
working, at least on my machine. (whew! :-)
I'm uncomfortable with the size of this commit, but it's too
inter-dependant to easily seperate out.
The main changes:
COMPAT_LINUX is *GONE*. Most of the code has been moved out of the i386
machine dependent section into the linux emulator itself. The int 0x80
syscall code was almost identical to the lcall 7,0 code and a minor tweak
allows them to both be used with the same C code. All kernels can now
just modload the lkm and it'll DTRT without having to rebuild the kernel
first. Like IBCS2, you can statically compile it in with "options LINUX".
A pile of new syscalls implemented, including getdents(), llseek(),
readv(), writev(), msync(), personality(). The Linux-ELF libraries want
to use some of these.
linux_select() now obeys Linux semantics, ie: returns the time remaining
of the timeout value rather than leaving it the original value.
Quite a few bugs removed, including incorrect arguments being used in
syscalls.. eg: mixups between passing the sigset as an int, vs passing
it as a pointer and doing a copyin(), missing return values, unhandled
cases, SIOC* ioctls, etc.
The build for the code has changed. i386/conf/files now knows how
to build linux_genassym and generate linux_assym.h on the fly.
Supporting changes elsewhere in the kernel:
The user-mode signal trampoline has moved from the U area to immediately
below the top of the stack (below PS_STRINGS). This allows the different
binary emulations to have their own signal trampoline code (which gets rid
of the hardwired syscall 103 (sigreturn on BSD, syslog on Linux)) and so
that the emulator can provide the exact "struct sigcontext *" argument to
the program's signal handlers.
The sigstack's "ss_flags" now uses SS_DISABLE and SS_ONSTACK flags, which
have the same values as the re-used SA_DISABLE and SA_ONSTACK which are
intended for sigaction only. This enables the support of a SA_RESETHAND
flag to sigaction to implement the gross SYSV and Linux SA_ONESHOT signal
semantics where the signal handler is reset when it's triggered.
makesyscalls.sh no longer appends the struct sysentvec on the end of the
generated init_sysent.c code. It's a lot saner to have it in a seperate
file rather than trying to update the structure inside the awk script. :-)
At exec time, the dozen bytes or so of signal trampoline code are copied
to the top of the user's stack, rather than obtaining the trampoline code
the old way by getting a clone of the parent's user area. This allows
Linux and native binaries to freely exec each other without getting
trampolines mixed up.
1996-03-02 19:38:20 +00:00
|
|
|
psp->ps_sigstk.ss_flags |= SS_DISABLE;
|
1994-05-24 10:09:53 +00:00
|
|
|
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);
|
1994-09-25 19:34:02 +00:00
|
|
|
if ((error = copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss))))
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
Mega-commit for Linux emulator update.. This has been stress tested under
netscape-2.0 for Linux running all the Java stuff. The scrollbars are now
working, at least on my machine. (whew! :-)
I'm uncomfortable with the size of this commit, but it's too
inter-dependant to easily seperate out.
The main changes:
COMPAT_LINUX is *GONE*. Most of the code has been moved out of the i386
machine dependent section into the linux emulator itself. The int 0x80
syscall code was almost identical to the lcall 7,0 code and a minor tweak
allows them to both be used with the same C code. All kernels can now
just modload the lkm and it'll DTRT without having to rebuild the kernel
first. Like IBCS2, you can statically compile it in with "options LINUX".
A pile of new syscalls implemented, including getdents(), llseek(),
readv(), writev(), msync(), personality(). The Linux-ELF libraries want
to use some of these.
linux_select() now obeys Linux semantics, ie: returns the time remaining
of the timeout value rather than leaving it the original value.
Quite a few bugs removed, including incorrect arguments being used in
syscalls.. eg: mixups between passing the sigset as an int, vs passing
it as a pointer and doing a copyin(), missing return values, unhandled
cases, SIOC* ioctls, etc.
The build for the code has changed. i386/conf/files now knows how
to build linux_genassym and generate linux_assym.h on the fly.
Supporting changes elsewhere in the kernel:
The user-mode signal trampoline has moved from the U area to immediately
below the top of the stack (below PS_STRINGS). This allows the different
binary emulations to have their own signal trampoline code (which gets rid
of the hardwired syscall 103 (sigreturn on BSD, syslog on Linux)) and so
that the emulator can provide the exact "struct sigcontext *" argument to
the program's signal handlers.
The sigstack's "ss_flags" now uses SS_DISABLE and SS_ONSTACK flags, which
have the same values as the re-used SA_DISABLE and SA_ONSTACK which are
intended for sigaction only. This enables the support of a SA_RESETHAND
flag to sigaction to implement the gross SYSV and Linux SA_ONESHOT signal
semantics where the signal handler is reset when it's triggered.
makesyscalls.sh no longer appends the struct sysentvec on the end of the
generated init_sysent.c code. It's a lot saner to have it in a seperate
file rather than trying to update the structure inside the awk script. :-)
At exec time, the dozen bytes or so of signal trampoline code are copied
to the top of the user's stack, rather than obtaining the trampoline code
the old way by getting a clone of the parent's user area. This allows
Linux and native binaries to freely exec each other without getting
trampolines mixed up.
1996-03-02 19:38:20 +00:00
|
|
|
if (ss.ss_flags & SS_DISABLE) {
|
|
|
|
if (psp->ps_sigstk.ss_flags & SS_ONSTACK)
|
1994-05-24 10:09:53 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
1994-10-10 01:00:49 +00:00
|
|
|
/*
|
|
|
|
* Common code for kill process group/broadcast kill.
|
|
|
|
* cp is calling process.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
killpg1(cp, signum, pgid, all)
|
|
|
|
register struct proc *cp;
|
|
|
|
int signum, pgid, all;
|
|
|
|
{
|
|
|
|
register struct proc *p;
|
|
|
|
register struct pcred *pc = cp->p_cred;
|
|
|
|
struct pgrp *pgrp;
|
|
|
|
int nfound = 0;
|
1995-05-30 08:16:23 +00:00
|
|
|
|
|
|
|
if (all)
|
|
|
|
/*
|
|
|
|
* broadcast
|
1994-10-10 01:00:49 +00:00
|
|
|
*/
|
1996-03-11 06:05:03 +00:00
|
|
|
for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
|
1995-05-30 08:16:23 +00:00
|
|
|
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
|
1994-10-10 01:00:49 +00:00
|
|
|
p == cp || !CANSIGNAL(cp, pc, p, signum))
|
|
|
|
continue;
|
|
|
|
nfound++;
|
|
|
|
if (signum)
|
|
|
|
psignal(p, signum);
|
|
|
|
}
|
|
|
|
else {
|
1995-05-30 08:16:23 +00:00
|
|
|
if (pgid == 0)
|
|
|
|
/*
|
1994-10-10 01:00:49 +00:00
|
|
|
* zero pgid means send to my process group.
|
|
|
|
*/
|
|
|
|
pgrp = cp->p_pgrp;
|
|
|
|
else {
|
|
|
|
pgrp = pgfind(pgid);
|
|
|
|
if (pgrp == NULL)
|
|
|
|
return (ESRCH);
|
|
|
|
}
|
1996-03-11 06:05:03 +00:00
|
|
|
for (p = pgrp->pg_members.lh_first; p != 0;
|
|
|
|
p = p->p_pglist.le_next) {
|
1994-10-10 01:00:49 +00:00
|
|
|
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
|
|
|
|
p->p_stat == SZOMB ||
|
|
|
|
!CANSIGNAL(cp, pc, p, signum))
|
|
|
|
continue;
|
|
|
|
nfound++;
|
|
|
|
if (signum)
|
|
|
|
psignal(p, signum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (nfound ? 0 : ESRCH);
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct kill_args {
|
|
|
|
int pid;
|
|
|
|
int signum;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
kill(cp, uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
register struct proc *cp;
|
|
|
|
register struct kill_args *uap;
|
|
|
|
{
|
|
|
|
register struct proc *p;
|
|
|
|
register struct pcred *pc = cp->p_cred;
|
|
|
|
|
|
|
|
if ((u_int)uap->signum >= NSIG)
|
|
|
|
return (EINVAL);
|
|
|
|
if (uap->pid > 0) {
|
|
|
|
/* kill single process */
|
|
|
|
if ((p = pfind(uap->pid)) == NULL)
|
|
|
|
return (ESRCH);
|
|
|
|
if (!CANSIGNAL(cp, pc, p, uap->signum))
|
|
|
|
return (EPERM);
|
|
|
|
if (uap->signum)
|
|
|
|
psignal(p, uap->signum);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
switch (uap->pid) {
|
|
|
|
case -1: /* broadcast signal */
|
|
|
|
return (killpg1(cp, uap->signum, 0, 1));
|
|
|
|
case 0: /* signal own process group */
|
|
|
|
return (killpg1(cp, uap->signum, 0, 0));
|
|
|
|
default: /* negative explicit process group */
|
|
|
|
return (killpg1(cp, uap->signum, -uap->pid, 0));
|
|
|
|
}
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct okillpg_args {
|
|
|
|
int pgid;
|
|
|
|
int signum;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
okillpg(p, uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
struct proc *p;
|
|
|
|
register struct okillpg_args *uap;
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((u_int)uap->signum >= NSIG)
|
|
|
|
return (EINVAL);
|
|
|
|
return (killpg1(p, uap->signum, uap->pgid, 0));
|
|
|
|
}
|
|
|
|
#endif /* COMPAT_43 || COMPAT_SUNOS */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send a signal to a process group.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
gsignal(pgid, signum)
|
|
|
|
int pgid, signum;
|
|
|
|
{
|
|
|
|
struct pgrp *pgrp;
|
|
|
|
|
|
|
|
if (pgid && (pgrp = pgfind(pgid)))
|
|
|
|
pgsignal(pgrp, signum, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-02-10 02:22:35 +00:00
|
|
|
* Send a signal to a process group. If checktty is 1,
|
1994-05-24 10:09:53 +00:00
|
|
|
* limit to members which have a controlling terminal.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
pgsignal(pgrp, signum, checkctty)
|
|
|
|
struct pgrp *pgrp;
|
|
|
|
int signum, checkctty;
|
|
|
|
{
|
|
|
|
register struct proc *p;
|
|
|
|
|
|
|
|
if (pgrp)
|
1996-03-11 06:05:03 +00:00
|
|
|
for (p = pgrp->pg_members.lh_first; p != 0;
|
|
|
|
p = p->p_pglist.le_next)
|
1994-05-24 10:09:53 +00:00
|
|
|
if (checkctty == 0 || p->p_flag & P_CONTROLT)
|
|
|
|
psignal(p, signum);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send a signal caused by a trap to the current process.
|
|
|
|
* If it will be caught immediately, deliver it with correct code.
|
|
|
|
* Otherwise, post it normally.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
trapsignal(p, signum, code)
|
|
|
|
struct proc *p;
|
|
|
|
register int signum;
|
1996-03-11 02:22:02 +00:00
|
|
|
u_long code;
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
register struct sigacts *ps = p->p_sigacts;
|
|
|
|
int mask;
|
|
|
|
|
|
|
|
mask = sigmask(signum);
|
|
|
|
if ((p->p_flag & P_TRACED) == 0 && (p->p_sigcatch & mask) != 0 &&
|
|
|
|
(p->p_sigmask & mask) == 0) {
|
|
|
|
p->p_stats->p_ru.ru_nsignals++;
|
|
|
|
#ifdef KTRACE
|
|
|
|
if (KTRPOINT(p, KTR_PSIG))
|
1995-05-30 08:16:23 +00:00
|
|
|
ktrpsig(p->p_tracep, signum, ps->ps_sigact[signum],
|
1994-05-24 10:09:53 +00:00
|
|
|
p->p_sigmask, code);
|
|
|
|
#endif
|
Mega-commit for Linux emulator update.. This has been stress tested under
netscape-2.0 for Linux running all the Java stuff. The scrollbars are now
working, at least on my machine. (whew! :-)
I'm uncomfortable with the size of this commit, but it's too
inter-dependant to easily seperate out.
The main changes:
COMPAT_LINUX is *GONE*. Most of the code has been moved out of the i386
machine dependent section into the linux emulator itself. The int 0x80
syscall code was almost identical to the lcall 7,0 code and a minor tweak
allows them to both be used with the same C code. All kernels can now
just modload the lkm and it'll DTRT without having to rebuild the kernel
first. Like IBCS2, you can statically compile it in with "options LINUX".
A pile of new syscalls implemented, including getdents(), llseek(),
readv(), writev(), msync(), personality(). The Linux-ELF libraries want
to use some of these.
linux_select() now obeys Linux semantics, ie: returns the time remaining
of the timeout value rather than leaving it the original value.
Quite a few bugs removed, including incorrect arguments being used in
syscalls.. eg: mixups between passing the sigset as an int, vs passing
it as a pointer and doing a copyin(), missing return values, unhandled
cases, SIOC* ioctls, etc.
The build for the code has changed. i386/conf/files now knows how
to build linux_genassym and generate linux_assym.h on the fly.
Supporting changes elsewhere in the kernel:
The user-mode signal trampoline has moved from the U area to immediately
below the top of the stack (below PS_STRINGS). This allows the different
binary emulations to have their own signal trampoline code (which gets rid
of the hardwired syscall 103 (sigreturn on BSD, syslog on Linux)) and so
that the emulator can provide the exact "struct sigcontext *" argument to
the program's signal handlers.
The sigstack's "ss_flags" now uses SS_DISABLE and SS_ONSTACK flags, which
have the same values as the re-used SA_DISABLE and SA_ONSTACK which are
intended for sigaction only. This enables the support of a SA_RESETHAND
flag to sigaction to implement the gross SYSV and Linux SA_ONESHOT signal
semantics where the signal handler is reset when it's triggered.
makesyscalls.sh no longer appends the struct sysentvec on the end of the
generated init_sysent.c code. It's a lot saner to have it in a seperate
file rather than trying to update the structure inside the awk script. :-)
At exec time, the dozen bytes or so of signal trampoline code are copied
to the top of the user's stack, rather than obtaining the trampoline code
the old way by getting a clone of the parent's user area. This allows
Linux and native binaries to freely exec each other without getting
trampolines mixed up.
1996-03-02 19:38:20 +00:00
|
|
|
(*p->p_sysent->sv_sendsig)(ps->ps_sigact[signum], signum,
|
|
|
|
p->p_sigmask, code);
|
1996-03-30 15:15:30 +00:00
|
|
|
p->p_sigmask |= ps->ps_catchmask[signum] |
|
|
|
|
(mask & ~ps->ps_signodefer);
|
1996-03-15 08:01:33 +00:00
|
|
|
if ((ps->ps_sigreset & mask) != 0) {
|
1996-03-30 15:15:30 +00:00
|
|
|
/*
|
|
|
|
* See setsigvec() for origin of this code.
|
|
|
|
*/
|
1996-03-15 08:01:33 +00:00
|
|
|
p->p_sigcatch &= ~mask;
|
|
|
|
if (signum != SIGCONT && sigprop[signum] & SA_IGNORE)
|
|
|
|
p->p_sigignore |= mask;
|
|
|
|
ps->ps_sigact[signum] = SIG_DFL;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
} else {
|
|
|
|
ps->ps_code = code; /* XXX for core dump/debugger */
|
1996-03-11 02:22:02 +00:00
|
|
|
ps->ps_sig = signum; /* XXX to verify code */
|
1994-05-24 10:09:53 +00:00
|
|
|
psignal(p, signum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send the signal to the process. If the signal has an action, the action
|
|
|
|
* is usually performed by the target process rather than the caller; we add
|
|
|
|
* the signal to the set of pending signals for the process.
|
|
|
|
*
|
|
|
|
* Exceptions:
|
|
|
|
* o When a stop signal is sent to a sleeping process that takes the
|
|
|
|
* default action, the process is stopped without awakening it.
|
|
|
|
* o SIGCONT restarts stopped processes (or puts them back to sleep)
|
|
|
|
* regardless of the signal action (eg, blocked or ignored).
|
|
|
|
*
|
|
|
|
* Other ignored signals are discarded immediately.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
psignal(p, signum)
|
|
|
|
register struct proc *p;
|
|
|
|
register int signum;
|
|
|
|
{
|
|
|
|
register int s, prop;
|
|
|
|
register sig_t action;
|
|
|
|
int mask;
|
|
|
|
|
1997-12-06 04:11:14 +00:00
|
|
|
if ((u_int)signum >= NSIG || signum == 0) {
|
|
|
|
printf("psignal: signum %d\n", signum);
|
1994-05-24 10:09:53 +00:00
|
|
|
panic("psignal signal number");
|
1997-12-06 04:11:14 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
mask = sigmask(signum);
|
|
|
|
prop = sigprop[signum];
|
|
|
|
|
|
|
|
/*
|
1997-12-06 04:11:14 +00:00
|
|
|
* If proc is traced, always give parent a chance;
|
|
|
|
* if signal event is tracked by procfs, give *that*
|
|
|
|
* a chance, as well.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1997-12-06 04:11:14 +00:00
|
|
|
if ((p->p_flag & P_TRACED) || (p->p_stops & S_SIG))
|
1994-05-24 10:09:53 +00:00
|
|
|
action = SIG_DFL;
|
|
|
|
else {
|
|
|
|
/*
|
|
|
|
* If the signal is being ignored,
|
|
|
|
* then we forget about it immediately.
|
|
|
|
* (Note: we don't set SIGCONT in p_sigignore,
|
|
|
|
* and if it is set to SIG_IGN,
|
|
|
|
* action will be SIG_DFL here.)
|
|
|
|
*/
|
|
|
|
if (p->p_sigignore & mask)
|
|
|
|
return;
|
|
|
|
if (p->p_sigmask & mask)
|
|
|
|
action = SIG_HOLD;
|
|
|
|
else if (p->p_sigcatch & mask)
|
|
|
|
action = SIG_CATCH;
|
|
|
|
else
|
|
|
|
action = SIG_DFL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->p_nice > NZERO && action == SIG_DFL && (prop & SA_KILL) &&
|
|
|
|
(p->p_flag & P_TRACED) == 0)
|
|
|
|
p->p_nice = NZERO;
|
|
|
|
|
|
|
|
if (prop & SA_CONT)
|
|
|
|
p->p_siglist &= ~stopsigmask;
|
|
|
|
|
|
|
|
if (prop & SA_STOP) {
|
|
|
|
/*
|
|
|
|
* If sending a tty stop signal to a member of an orphaned
|
|
|
|
* process group, discard the signal here if the action
|
|
|
|
* is default; don't stop the process below if sleeping,
|
|
|
|
* and don't clear any pending SIGCONT.
|
|
|
|
*/
|
|
|
|
if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0 &&
|
|
|
|
action == SIG_DFL)
|
|
|
|
return;
|
|
|
|
p->p_siglist &= ~contsigmask;
|
|
|
|
}
|
|
|
|
p->p_siglist |= mask;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Defer further processing for signals which are held,
|
|
|
|
* except that stopped processes must be continued by SIGCONT.
|
|
|
|
*/
|
|
|
|
if (action == SIG_HOLD && ((prop & SA_CONT) == 0 || p->p_stat != SSTOP))
|
|
|
|
return;
|
|
|
|
s = splhigh();
|
|
|
|
switch (p->p_stat) {
|
|
|
|
|
|
|
|
case SSLEEP:
|
|
|
|
/*
|
|
|
|
* If process is sleeping uninterruptibly
|
|
|
|
* we can't interrupt the sleep... the signal will
|
|
|
|
* be noticed when the process returns through
|
|
|
|
* trap() or syscall().
|
|
|
|
*/
|
|
|
|
if ((p->p_flag & P_SINTR) == 0)
|
|
|
|
goto out;
|
|
|
|
/*
|
|
|
|
* Process is sleeping and traced... make it runnable
|
|
|
|
* so it can discover the signal in issignal() and stop
|
|
|
|
* for the parent.
|
|
|
|
*/
|
|
|
|
if (p->p_flag & P_TRACED)
|
|
|
|
goto run;
|
|
|
|
/*
|
|
|
|
* If SIGCONT is default (or ignored) and process is
|
|
|
|
* asleep, we are finished; the process should not
|
|
|
|
* be awakened.
|
|
|
|
*/
|
|
|
|
if ((prop & SA_CONT) && action == SIG_DFL) {
|
|
|
|
p->p_siglist &= ~mask;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* When a sleeping process receives a stop
|
|
|
|
* signal, process immediately if possible.
|
|
|
|
* All other (caught or default) signals
|
|
|
|
* cause the process to run.
|
|
|
|
*/
|
|
|
|
if (prop & SA_STOP) {
|
|
|
|
if (action != SIG_DFL)
|
|
|
|
goto runfast;
|
|
|
|
/*
|
|
|
|
* If a child holding parent blocked,
|
|
|
|
* stopping could cause deadlock.
|
|
|
|
*/
|
|
|
|
if (p->p_flag & P_PPWAIT)
|
|
|
|
goto out;
|
|
|
|
p->p_siglist &= ~mask;
|
|
|
|
p->p_xstat = signum;
|
|
|
|
if ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0)
|
|
|
|
psignal(p->p_pptr, SIGCHLD);
|
|
|
|
stop(p);
|
|
|
|
goto out;
|
|
|
|
} else
|
|
|
|
goto runfast;
|
|
|
|
/*NOTREACHED*/
|
|
|
|
|
|
|
|
case SSTOP:
|
|
|
|
/*
|
|
|
|
* If traced process is already stopped,
|
|
|
|
* then no further action is necessary.
|
|
|
|
*/
|
|
|
|
if (p->p_flag & P_TRACED)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Kill signal always sets processes running.
|
|
|
|
*/
|
|
|
|
if (signum == SIGKILL)
|
|
|
|
goto runfast;
|
|
|
|
|
|
|
|
if (prop & SA_CONT) {
|
|
|
|
/*
|
|
|
|
* If SIGCONT is default (or ignored), we continue the
|
|
|
|
* process but don't leave the signal in p_siglist, as
|
|
|
|
* it has no further action. If SIGCONT is held, we
|
|
|
|
* continue the process and leave the signal in
|
|
|
|
* p_siglist. If the process catches SIGCONT, let it
|
|
|
|
* handle the signal itself. If it isn't waiting on
|
|
|
|
* an event, then it goes back to run state.
|
|
|
|
* Otherwise, process goes back to sleep state.
|
|
|
|
*/
|
|
|
|
if (action == SIG_DFL)
|
|
|
|
p->p_siglist &= ~mask;
|
|
|
|
if (action == SIG_CATCH)
|
|
|
|
goto runfast;
|
|
|
|
if (p->p_wchan == 0)
|
|
|
|
goto run;
|
|
|
|
p->p_stat = SSLEEP;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prop & SA_STOP) {
|
|
|
|
/*
|
|
|
|
* Already stopped, don't need to stop again.
|
|
|
|
* (If we did the shell could get confused.)
|
|
|
|
*/
|
|
|
|
p->p_siglist &= ~mask; /* take it away */
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If process is sleeping interruptibly, then simulate a
|
|
|
|
* wakeup so that when it is continued, it will be made
|
|
|
|
* runnable and can look at the signal. But don't make
|
|
|
|
* the process runnable, leave it stopped.
|
|
|
|
*/
|
|
|
|
if (p->p_wchan && p->p_flag & P_SINTR)
|
|
|
|
unsleep(p);
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* SRUN, SIDL, SZOMB do nothing with the signal,
|
|
|
|
* other than kicking ourselves if we are running.
|
|
|
|
* It will either never be noticed, or noticed very soon.
|
|
|
|
*/
|
|
|
|
if (p == curproc)
|
|
|
|
signotify(p);
|
1998-03-03 20:55:26 +00:00
|
|
|
#ifdef SMP
|
|
|
|
else if (p->p_stat == SRUN)
|
|
|
|
forward_signal(p);
|
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/*NOTREACHED*/
|
|
|
|
|
|
|
|
runfast:
|
|
|
|
/*
|
|
|
|
* Raise priority to at least PUSER.
|
|
|
|
*/
|
|
|
|
if (p->p_priority > PUSER)
|
|
|
|
p->p_priority = PUSER;
|
|
|
|
run:
|
|
|
|
setrunnable(p);
|
|
|
|
out:
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the current process has received a signal (should be caught or cause
|
|
|
|
* termination, should interrupt current syscall), return the signal number.
|
|
|
|
* Stop signals with default action are processed immediately, then cleared;
|
|
|
|
* they aren't returned. This is checked after each entry to the system for
|
|
|
|
* a syscall or trap (though this can usually be done without calling issignal
|
|
|
|
* by checking the pending signal masks in the CURSIG macro.) The normal call
|
|
|
|
* sequence is
|
|
|
|
*
|
|
|
|
* while (signum = CURSIG(curproc))
|
|
|
|
* postsig(signum);
|
|
|
|
*/
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1994-05-24 10:09:53 +00:00
|
|
|
issignal(p)
|
|
|
|
register struct proc *p;
|
|
|
|
{
|
|
|
|
register int signum, mask, prop;
|
|
|
|
|
|
|
|
for (;;) {
|
1997-12-06 04:11:14 +00:00
|
|
|
int traced = (p->p_flag & P_TRACED) || (p->p_stops & S_SIG);
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
mask = p->p_siglist & ~p->p_sigmask;
|
|
|
|
if (p->p_flag & P_PPWAIT)
|
|
|
|
mask &= ~stopsigmask;
|
|
|
|
if (mask == 0) /* no signal to send */
|
|
|
|
return (0);
|
|
|
|
signum = ffs((long)mask);
|
|
|
|
mask = sigmask(signum);
|
|
|
|
prop = sigprop[signum];
|
1997-12-06 04:11:14 +00:00
|
|
|
|
|
|
|
STOPEVENT(p, S_SIG, signum);
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* We should see pending but ignored signals
|
|
|
|
* only if P_TRACED was on when they were posted.
|
|
|
|
*/
|
1997-12-06 04:11:14 +00:00
|
|
|
if ((mask & p->p_sigignore) && (traced == 0)) {
|
1994-05-24 10:09:53 +00:00
|
|
|
p->p_siglist &= ~mask;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) {
|
|
|
|
/*
|
|
|
|
* If traced, always stop, and stay
|
|
|
|
* stopped until released by the parent.
|
|
|
|
*/
|
|
|
|
p->p_xstat = signum;
|
|
|
|
psignal(p->p_pptr, SIGCHLD);
|
|
|
|
do {
|
|
|
|
stop(p);
|
|
|
|
mi_switch();
|
1997-12-06 04:11:14 +00:00
|
|
|
} while (!trace_req(p)
|
|
|
|
&& p->p_flag & P_TRACED);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the traced bit got turned off, go back up
|
|
|
|
* to the top to rescan signals. This ensures
|
|
|
|
* that p_sig* and ps_sigact are consistent.
|
|
|
|
*/
|
|
|
|
if ((p->p_flag & P_TRACED) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If parent wants us to take the signal,
|
|
|
|
* then it will leave it in p->p_xstat;
|
|
|
|
* otherwise we just look for signals again.
|
|
|
|
*/
|
|
|
|
p->p_siglist &= ~mask; /* clear the old signal */
|
|
|
|
signum = p->p_xstat;
|
|
|
|
if (signum == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Put the new signal into p_siglist. If the
|
|
|
|
* signal is being masked, look for other signals.
|
|
|
|
*/
|
|
|
|
mask = sigmask(signum);
|
|
|
|
p->p_siglist |= mask;
|
|
|
|
if (p->p_sigmask & mask)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Decide whether the signal should be returned.
|
|
|
|
* Return the signal's number, or fall through
|
|
|
|
* to clear it from the pending mask.
|
|
|
|
*/
|
1998-07-15 02:32:35 +00:00
|
|
|
switch ((int)(intptr_t)p->p_sigacts->ps_sigact[signum]) {
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1994-09-20 05:42:46 +00:00
|
|
|
case (int)SIG_DFL:
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Don't take default actions on system processes.
|
|
|
|
*/
|
|
|
|
if (p->p_pid <= 1) {
|
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
/*
|
|
|
|
* Are you sure you want to ignore SIGSEGV
|
|
|
|
* in init? XXX
|
|
|
|
*/
|
1994-10-10 01:00:49 +00:00
|
|
|
printf("Process (pid %lu) got signal %d\n",
|
|
|
|
(u_long)p->p_pid, signum);
|
1994-05-24 10:09:53 +00:00
|
|
|
#endif
|
|
|
|
break; /* == ignore */
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* If there is a pending stop signal to process
|
|
|
|
* with default action, stop here,
|
|
|
|
* then clear the signal. However,
|
|
|
|
* if process is member of an orphaned
|
|
|
|
* process group, ignore tty stop signals.
|
|
|
|
*/
|
|
|
|
if (prop & SA_STOP) {
|
|
|
|
if (p->p_flag & P_TRACED ||
|
|
|
|
(p->p_pgrp->pg_jobc == 0 &&
|
|
|
|
prop & SA_TTYSTOP))
|
|
|
|
break; /* == ignore */
|
|
|
|
p->p_xstat = signum;
|
|
|
|
stop(p);
|
|
|
|
if ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0)
|
|
|
|
psignal(p->p_pptr, SIGCHLD);
|
|
|
|
mi_switch();
|
|
|
|
break;
|
|
|
|
} else if (prop & SA_IGNORE) {
|
|
|
|
/*
|
|
|
|
* Except for SIGCONT, shouldn't get here.
|
|
|
|
* Default action is to ignore; drop it.
|
|
|
|
*/
|
|
|
|
break; /* == ignore */
|
|
|
|
} else
|
|
|
|
return (signum);
|
|
|
|
/*NOTREACHED*/
|
|
|
|
|
1994-09-20 05:42:46 +00:00
|
|
|
case (int)SIG_IGN:
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Masking above should prevent us ever trying
|
|
|
|
* to take action on an ignored signal other
|
|
|
|
* than SIGCONT, unless process is traced.
|
|
|
|
*/
|
|
|
|
if ((prop & SA_CONT) == 0 &&
|
|
|
|
(p->p_flag & P_TRACED) == 0)
|
|
|
|
printf("issignal\n");
|
|
|
|
break; /* == ignore */
|
|
|
|
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* This signal has an action, let
|
|
|
|
* postsig() process it.
|
|
|
|
*/
|
|
|
|
return (signum);
|
|
|
|
}
|
|
|
|
p->p_siglist &= ~mask; /* take the signal! */
|
|
|
|
}
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Put the argument process into the stopped state and notify the parent
|
|
|
|
* via wakeup. Signals are handled elsewhere. The process must not be
|
|
|
|
* on the run queue.
|
|
|
|
*/
|
1994-05-25 09:21:21 +00:00
|
|
|
void
|
1994-05-24 10:09:53 +00:00
|
|
|
stop(p)
|
|
|
|
register struct proc *p;
|
|
|
|
{
|
|
|
|
|
|
|
|
p->p_stat = SSTOP;
|
|
|
|
p->p_flag &= ~P_WAITED;
|
|
|
|
wakeup((caddr_t)p->p_pptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Take the action for the specified signal
|
|
|
|
* from the current set of pending signals.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
postsig(signum)
|
|
|
|
register int signum;
|
|
|
|
{
|
|
|
|
register struct proc *p = curproc;
|
|
|
|
register struct sigacts *ps = p->p_sigacts;
|
|
|
|
register sig_t action;
|
|
|
|
int code, mask, returnmask;
|
|
|
|
|
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (signum == 0)
|
|
|
|
panic("postsig");
|
|
|
|
#endif
|
|
|
|
mask = sigmask(signum);
|
|
|
|
p->p_siglist &= ~mask;
|
|
|
|
action = ps->ps_sigact[signum];
|
|
|
|
#ifdef KTRACE
|
|
|
|
if (KTRPOINT(p, KTR_PSIG))
|
|
|
|
ktrpsig(p->p_tracep,
|
|
|
|
signum, action, ps->ps_flags & SAS_OLDMASK ?
|
|
|
|
ps->ps_oldmask : p->p_sigmask, 0);
|
|
|
|
#endif
|
1997-12-06 04:11:14 +00:00
|
|
|
STOPEVENT(p, S_SIG, signum);
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
if (action == SIG_DFL) {
|
|
|
|
/*
|
|
|
|
* Default action, where the default is to kill
|
|
|
|
* the process. (Other cases were ignored above.)
|
|
|
|
*/
|
|
|
|
sigexit(p, signum);
|
|
|
|
/* NOTREACHED */
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* If we get here, the signal must be caught.
|
|
|
|
*/
|
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (action == SIG_IGN || (p->p_sigmask & mask))
|
|
|
|
panic("postsig action");
|
|
|
|
#endif
|
|
|
|
/*
|
|
|
|
* Set the new mask value and also defer further
|
|
|
|
* occurences of this signal.
|
|
|
|
*
|
|
|
|
* Special case: user has done a sigpause. Here the
|
|
|
|
* current mask is not of interest, but rather the
|
|
|
|
* mask from before the sigpause is what we want
|
|
|
|
* restored after the signal processing is completed.
|
|
|
|
*/
|
|
|
|
(void) splhigh();
|
|
|
|
if (ps->ps_flags & SAS_OLDMASK) {
|
|
|
|
returnmask = ps->ps_oldmask;
|
|
|
|
ps->ps_flags &= ~SAS_OLDMASK;
|
|
|
|
} else
|
|
|
|
returnmask = p->p_sigmask;
|
1996-03-30 15:15:30 +00:00
|
|
|
p->p_sigmask |= ps->ps_catchmask[signum] |
|
|
|
|
(mask & ~ps->ps_signodefer);
|
1996-03-15 08:01:33 +00:00
|
|
|
if ((ps->ps_sigreset & mask) != 0) {
|
1996-03-30 15:15:30 +00:00
|
|
|
/*
|
|
|
|
* See setsigvec() for origin of this code.
|
|
|
|
*/
|
1996-03-15 08:01:33 +00:00
|
|
|
p->p_sigcatch &= ~mask;
|
|
|
|
if (signum != SIGCONT && sigprop[signum] & SA_IGNORE)
|
|
|
|
p->p_sigignore |= mask;
|
|
|
|
ps->ps_sigact[signum] = SIG_DFL;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
(void) spl0();
|
|
|
|
p->p_stats->p_ru.ru_nsignals++;
|
|
|
|
if (ps->ps_sig != signum) {
|
|
|
|
code = 0;
|
|
|
|
} else {
|
|
|
|
code = ps->ps_code;
|
|
|
|
ps->ps_code = 0;
|
1996-03-11 02:22:02 +00:00
|
|
|
ps->ps_sig = 0;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
Mega-commit for Linux emulator update.. This has been stress tested under
netscape-2.0 for Linux running all the Java stuff. The scrollbars are now
working, at least on my machine. (whew! :-)
I'm uncomfortable with the size of this commit, but it's too
inter-dependant to easily seperate out.
The main changes:
COMPAT_LINUX is *GONE*. Most of the code has been moved out of the i386
machine dependent section into the linux emulator itself. The int 0x80
syscall code was almost identical to the lcall 7,0 code and a minor tweak
allows them to both be used with the same C code. All kernels can now
just modload the lkm and it'll DTRT without having to rebuild the kernel
first. Like IBCS2, you can statically compile it in with "options LINUX".
A pile of new syscalls implemented, including getdents(), llseek(),
readv(), writev(), msync(), personality(). The Linux-ELF libraries want
to use some of these.
linux_select() now obeys Linux semantics, ie: returns the time remaining
of the timeout value rather than leaving it the original value.
Quite a few bugs removed, including incorrect arguments being used in
syscalls.. eg: mixups between passing the sigset as an int, vs passing
it as a pointer and doing a copyin(), missing return values, unhandled
cases, SIOC* ioctls, etc.
The build for the code has changed. i386/conf/files now knows how
to build linux_genassym and generate linux_assym.h on the fly.
Supporting changes elsewhere in the kernel:
The user-mode signal trampoline has moved from the U area to immediately
below the top of the stack (below PS_STRINGS). This allows the different
binary emulations to have their own signal trampoline code (which gets rid
of the hardwired syscall 103 (sigreturn on BSD, syslog on Linux)) and so
that the emulator can provide the exact "struct sigcontext *" argument to
the program's signal handlers.
The sigstack's "ss_flags" now uses SS_DISABLE and SS_ONSTACK flags, which
have the same values as the re-used SA_DISABLE and SA_ONSTACK which are
intended for sigaction only. This enables the support of a SA_RESETHAND
flag to sigaction to implement the gross SYSV and Linux SA_ONESHOT signal
semantics where the signal handler is reset when it's triggered.
makesyscalls.sh no longer appends the struct sysentvec on the end of the
generated init_sysent.c code. It's a lot saner to have it in a seperate
file rather than trying to update the structure inside the awk script. :-)
At exec time, the dozen bytes or so of signal trampoline code are copied
to the top of the user's stack, rather than obtaining the trampoline code
the old way by getting a clone of the parent's user area. This allows
Linux and native binaries to freely exec each other without getting
trampolines mixed up.
1996-03-02 19:38:20 +00:00
|
|
|
(*p->p_sysent->sv_sendsig)(action, signum, returnmask, code);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Kill the current process for stated reason.
|
|
|
|
*/
|
1994-05-25 09:21:21 +00:00
|
|
|
void
|
1994-05-24 10:09:53 +00:00
|
|
|
killproc(p, why)
|
|
|
|
struct proc *p;
|
|
|
|
char *why;
|
|
|
|
{
|
1996-01-31 12:44:33 +00:00
|
|
|
log(LOG_ERR, "pid %d (%s), uid %d, was killed: %s\n", p->p_pid, p->p_comm,
|
|
|
|
p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : -1, why);
|
1994-05-24 10:09:53 +00:00
|
|
|
psignal(p, SIGKILL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Force the current process to exit with the specified signal, dumping core
|
|
|
|
* if appropriate. We bypass the normal tests for masked and caught signals,
|
|
|
|
* allowing unrecoverable failures to terminate the process without changing
|
|
|
|
* signal state. Mark the accounting record with the signal termination.
|
|
|
|
* If dumping core, save the signal number for the debugger. Calls exit and
|
|
|
|
* does not return.
|
|
|
|
*/
|
1994-05-25 09:21:21 +00:00
|
|
|
void
|
1994-05-24 10:09:53 +00:00
|
|
|
sigexit(p, signum)
|
|
|
|
register struct proc *p;
|
|
|
|
int signum;
|
|
|
|
{
|
|
|
|
|
|
|
|
p->p_acflag |= AXSIG;
|
|
|
|
if (sigprop[signum] & SA_CORE) {
|
|
|
|
p->p_sigacts->ps_sig = signum;
|
1994-09-30 00:38:34 +00:00
|
|
|
/*
|
|
|
|
* Log signals which would cause core dumps
|
1995-05-30 08:16:23 +00:00
|
|
|
* (Log as LOG_INFO to appease those who don't want
|
1994-09-30 00:38:34 +00:00
|
|
|
* these messages.)
|
|
|
|
* XXX : Todo, as well as euid, write out ruid too
|
|
|
|
*/
|
1998-09-14 05:36:51 +00:00
|
|
|
if (p->p_sysent->sv_coredump != NULL &&
|
|
|
|
(*p->p_sysent->sv_coredump)(p) == 0)
|
1994-05-24 10:09:53 +00:00
|
|
|
signum |= WCOREFLAG;
|
1998-07-28 22:34:12 +00:00
|
|
|
if (kern_logsigexit)
|
|
|
|
log(LOG_INFO,
|
|
|
|
"pid %d (%s), uid %d: exited on signal %d%s\n",
|
|
|
|
p->p_pid, p->p_comm,
|
|
|
|
p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : -1,
|
|
|
|
signum &~ WCOREFLAG,
|
|
|
|
signum & WCOREFLAG ? " (core dumped)" : "");
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
exit1(p, W_EXITCODE(0, signum));
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
1998-07-08 06:38:39 +00:00
|
|
|
static char corefilename[MAXPATHLEN+1] = {"%N.core"};
|
|
|
|
SYSCTL_STRING(_kern, OID_AUTO, corefile, CTLFLAG_RW, corefilename,
|
|
|
|
sizeof(corefilename), "process corefile name format string");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* expand_name(name, uid, pid)
|
|
|
|
* Expand the name described in corefilename, using name, uid, and pid.
|
|
|
|
* corefilename is a printf-like string, with three format specifiers:
|
|
|
|
* %N name of process ("name")
|
|
|
|
* %P process id (pid)
|
|
|
|
* %U user id (uid)
|
|
|
|
* For example, "%N.core" is the default; they can be disabled completely
|
|
|
|
* by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P".
|
|
|
|
* This is controlled by the sysctl variable kern.corefile (see above).
|
|
|
|
*/
|
|
|
|
|
1998-09-14 05:36:51 +00:00
|
|
|
char *
|
1998-07-08 06:38:39 +00:00
|
|
|
expand_name(name, uid, pid)
|
|
|
|
const char *name; int uid; int pid; {
|
|
|
|
char *temp;
|
|
|
|
char buf[11]; /* Buffer for pid/uid -- max 4B */
|
|
|
|
int i, n;
|
|
|
|
char *format = corefilename;
|
|
|
|
|
|
|
|
temp = malloc(MAXPATHLEN + 3, M_TEMP, M_NOWAIT);
|
|
|
|
bzero(temp, MAXPATHLEN+3);
|
|
|
|
for (i = 0, n = 0; i < MAXPATHLEN && format[i]; i++) {
|
|
|
|
int l;
|
|
|
|
switch (format[i]) {
|
|
|
|
case '%': /* Format character */
|
|
|
|
i++;
|
|
|
|
switch (format[i]) {
|
|
|
|
case '%':
|
|
|
|
temp[n++] = '%';
|
|
|
|
break;
|
|
|
|
case 'N': /* process name */
|
|
|
|
l = strlen(name);
|
|
|
|
if ((n + l) > MAXPATHLEN) {
|
|
|
|
log(LOG_ERR, "pid %d (%s), uid (%d): Path `%s%s' is too long\n",
|
|
|
|
pid, name, uid, temp, name);
|
|
|
|
free(temp, M_TEMP);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memcpy(temp+n, name, l);
|
|
|
|
n += l;
|
|
|
|
break;
|
|
|
|
case 'P': /* process id */
|
|
|
|
sprintf(buf, "%u", pid);
|
|
|
|
l = strlen(buf);
|
|
|
|
if ((n + l) > MAXPATHLEN) {
|
|
|
|
log(LOG_ERR, "pid %d (%s), uid (%d): Path `%s%s' is too long\n",
|
|
|
|
pid, name, uid, temp, name);
|
|
|
|
free(temp, M_TEMP);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memcpy(temp+n, buf, l);
|
|
|
|
n += l;
|
|
|
|
break;
|
|
|
|
case 'U': /* user id */
|
|
|
|
sprintf(buf, "%u", uid);
|
|
|
|
l = strlen(buf);
|
|
|
|
if ((n + l) > MAXPATHLEN) {
|
|
|
|
log(LOG_ERR, "pid %d (%s), uid (%d): Path `%s%s' is too long\n",
|
|
|
|
pid, name, uid, temp, name);
|
|
|
|
free(temp, M_TEMP);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memcpy(temp+n, buf, l);
|
|
|
|
n += l;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
log(LOG_ERR, "Unknown format character %c in `%s'\n", format[i], format);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
temp[n++] = format[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Nonexistent system call-- signal process (may want to handle it).
|
|
|
|
* Flag error in case process won't see signal immediately (blocked or ignored).
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nosys_args {
|
|
|
|
int dummy;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
1997-11-06 19:29:57 +00:00
|
|
|
nosys(p, args)
|
1994-05-24 10:09:53 +00:00
|
|
|
struct proc *p;
|
|
|
|
struct nosys_args *args;
|
|
|
|
{
|
|
|
|
|
|
|
|
psignal(p, SIGSYS);
|
|
|
|
return (EINVAL);
|
|
|
|
}
|