-/* kern_sig.c 5.4 82/08/22 */
-
-#include "../h/param.h"
-#include "../h/systm.h"
-#include "../h/dir.h"
-#include "../h/user.h"
-#include "../h/reg.h"
-#include "../h/inode.h"
-#include "../h/proc.h"
-#include "../h/clock.h"
-#include "../h/mtpr.h"
-#include "../h/timeb.h"
-#include "../h/times.h"
-#include "../h/conf.h"
-#include "../h/buf.h"
-#include "../h/mount.h"
-#include "../h/text.h"
-#include "../h/seg.h"
-#include "../h/pte.h"
-#include "../h/psl.h"
-#include "../h/vm.h"
-#include "../h/vlimit.h"
-#include "../h/acct.h"
-#include "../h/uio.h"
+/*
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)kern_sig.c 7.8 (Berkeley) %G%
+ */
-/* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */
+#include "param.h"
+#include "systm.h"
+#include "user.h"
+#include "vnode.h"
+#include "proc.h"
+#include "timeb.h"
+#include "times.h"
+#include "buf.h"
+#include "mount.h"
+#include "text.h"
+#include "seg.h"
+#include "vm.h"
+#include "acct.h"
+#include "uio.h"
+#include "file.h"
+#include "kernel.h"
+
+#include "machine/reg.h"
+#include "machine/pte.h"
+#include "machine/psl.h"
+#include "machine/mtpr.h"
+
+#define cantmask (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP))
+#define stopsigmask (sigmask(SIGSTOP)|sigmask(SIGTSTP)| \
+ sigmask(SIGTTIN)|sigmask(SIGTTOU))
+/*
+ * Generalized interface signal handler.
+ */
sigvec()
{
+ register struct a {
+ int signo;
+ struct sigvec *nsv;
+ struct sigvec *osv;
+ } *uap = (struct a *)u.u_ap;
+ struct sigvec vec;
+ register struct sigvec *sv;
+ register int sig;
+ int bit;
+
+ sig = uap->signo;
+ if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) {
+ u.u_error = EINVAL;
+ return;
+ }
+ sv = &vec;
+ if (uap->osv) {
+ sv->sv_handler = u.u_signal[sig];
+ sv->sv_mask = u.u_sigmask[sig];
+ bit = sigmask(sig);
+ sv->sv_flags = 0;
+ if ((u.u_sigonstack & bit) != 0)
+ sv->sv_flags |= SV_ONSTACK;
+ if ((u.u_sigintr & bit) != 0)
+ sv->sv_flags |= SV_INTERRUPT;
+ u.u_error =
+ copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec));
+ if (u.u_error)
+ return;
+ }
+ if (uap->nsv) {
+ u.u_error =
+ copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec));
+ if (u.u_error)
+ return;
+ if (sig == SIGCONT && sv->sv_handler == SIG_IGN) {
+ u.u_error = EINVAL;
+ return;
+ }
+ setsigvec(sig, sv);
+ }
+}
+
+setsigvec(sig, sv)
+ int sig;
+ register struct sigvec *sv;
+{
+ register struct proc *p;
+ register int bit;
+ bit = sigmask(sig);
+ p = u.u_procp;
+ /*
+ * Change setting atomically.
+ */
+ (void) splhigh();
+ u.u_signal[sig] = sv->sv_handler;
+ u.u_sigmask[sig] = sv->sv_mask &~ cantmask;
+ if (sv->sv_flags & SV_INTERRUPT)
+ u.u_sigintr |= bit;
+ else
+ u.u_sigintr &= ~bit;
+ if (sv->sv_flags & SV_ONSTACK)
+ u.u_sigonstack |= bit;
+ else
+ u.u_sigonstack &= ~bit;
+ if (sv->sv_handler == SIG_IGN) {
+ p->p_sig &= ~bit; /* never to be seen again */
+ p->p_sigignore |= bit;
+ p->p_sigcatch &= ~bit;
+ } else {
+ p->p_sigignore &= ~bit;
+ if (sv->sv_handler == SIG_DFL)
+ p->p_sigcatch &= ~bit;
+ else
+ p->p_sigcatch |= bit;
+ }
+ (void) spl0();
}
sigblock()
{
+ struct a {
+ int mask;
+ } *uap = (struct a *)u.u_ap;
+ register struct proc *p = u.u_procp;
+ (void) splhigh();
+ u.u_r.r_val1 = p->p_sigmask;
+ p->p_sigmask |= uap->mask &~ cantmask;
+ (void) spl0();
}
sigsetmask()
{
+ struct a {
+ int mask;
+ } *uap = (struct a *)u.u_ap;
+ register struct proc *p = u.u_procp;
+ (void) splhigh();
+ u.u_r.r_val1 = p->p_sigmask;
+ p->p_sigmask = uap->mask &~ cantmask;
+ (void) spl0();
}
sigpause()
{
+ struct a {
+ int mask;
+ } *uap = (struct a *)u.u_ap;
+ register struct proc *p = u.u_procp;
+ /*
+ * 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 proc structure
+ * to indicate this (should be in u.).
+ */
+ u.u_oldmask = p->p_sigmask;
+ p->p_flag |= SOMASK;
+ p->p_sigmask = uap->mask &~ cantmask;
+ for (;;)
+ sleep((caddr_t)&u, PSLEP);
+ /*NOTREACHED*/
}
+#undef cantmask
sigstack()
{
-
+ register struct a {
+ struct sigstack *nss;
+ struct sigstack *oss;
+ } *uap = (struct a *)u.u_ap;
+ struct sigstack ss;
+
+ if (uap->oss) {
+ u.u_error = copyout((caddr_t)&u.u_sigstack, (caddr_t)uap->oss,
+ sizeof (struct sigstack));
+ if (u.u_error)
+ return;
+ }
+ if (uap->nss) {
+ u.u_error =
+ copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss));
+ if (u.u_error == 0)
+ u.u_sigstack = ss;
+ }
}
-/* BEGIN DEFUNCT */
-okill()
+kill()
{
- register struct proc *p;
- register a, sig;
register struct a {
int pid;
int signo;
- } *uap;
- int f, priv;
+ } *uap = (struct a *)u.u_ap;
+ register struct proc *p;
- uap = (struct a *)u.u_ap;
- f = 0;
- a = uap->pid;
- priv = 0;
- sig = uap->signo;
- if (sig < 0)
- /*
- * A negative signal means send to process group.
- */
- uap->signo = -uap->signo;
- if (uap->signo == 0 || uap->signo > NSIG) {
+ if (uap->signo < 0 || uap->signo > NSIG) {
u.u_error = EINVAL;
return;
}
- if (a > 0 && sig > 0) {
- p = pfind(a);
- if (p == 0 || u.u_uid && u.u_uid != p->p_uid) {
+ if (uap->pid > 0) {
+ /* kill single process */
+ p = pfind(uap->pid);
+ if (p == 0) {
u.u_error = ESRCH;
return;
}
- psignal(p, uap->signo);
+ if (u.u_uid && u.u_uid != p->p_uid)
+ u.u_error = EPERM;
+ else if (uap->signo)
+ psignal(p, uap->signo);
return;
}
- if (a==-1 && u.u_uid==0) {
- priv++;
- a = 0;
- sig = -1; /* like sending to pgrp */
- } else if (a==0) {
- /*
- * Zero process id means send to my process group.
- */
- sig = -1;
- a = u.u_procp->p_pgrp;
- if (a == 0) {
- u.u_error = EINVAL;
- return;
- }
+ switch (uap->pid) {
+ case -1: /* broadcast signal */
+ u.u_error = killpg1(uap->signo, 0, 1);
+ break;
+ case 0: /* signal own process group */
+ u.u_error = killpg1(uap->signo, 0, 0);
+ break;
+ default: /* negative explicit process group */
+ u.u_error = killpg1(uap->signo, -uap->pid, 0);
+ break;
}
- for(p = proc; p < procNPROC; p++) {
- if (p->p_stat == NULL)
- continue;
- if (sig > 0) {
- if (p->p_pid != a)
- continue;
- } else if (p->p_pgrp!=a && priv==0 || p->p_ppid==0 ||
- (p->p_flag&SSYS) || (priv && p==u.u_procp))
- continue;
- if (u.u_uid != 0 && u.u_uid != p->p_uid &&
- (uap->signo != SIGCONT || !inferior(p)))
- continue;
- f++;
- psignal(p, uap->signo);
- }
- if (f == 0)
- u.u_error = ESRCH;
+ return;
}
-ossig()
+killpg()
{
- register int (*f)();
- struct a {
+ register struct a {
+ int pgid;
int signo;
- int (*fun)();
- } *uap;
- register struct proc *p = u.u_procp;
- register a;
- long sigmask;
-
- uap = (struct a *)u.u_ap;
- a = uap->signo & SIGNUMMASK;
- f = uap->fun;
- if (a<=0 || a>=NSIG || a==SIGKILL || a==SIGSTOP ||
- a==SIGCONT && (f == SIG_IGN || f == SIG_HOLD)) {
+ } *uap = (struct a *)u.u_ap;
+
+ if (uap->signo < 0 || uap->signo > NSIG) {
u.u_error = EINVAL;
return;
}
- if ((uap->signo &~ SIGNUMMASK) || (f != SIG_DFL && f != SIG_IGN &&
- SIGISDEFER(f)))
- u.u_procp->p_flag |= SNUSIG;
- /*
- * Don't clobber registers if we are to simulate
- * a ret+rti.
- */
- if ((uap->signo&SIGDORTI) == 0)
- u.u_r.r_val1 = (int)u.u_signal[a];
- /*
- * Change setting atomically.
- */
- (void) spl6();
- sigmask = 1L << (a-1);
- if (u.u_signal[a] == SIG_IGN)
- p->p_sig &= ~sigmask; /* never to be seen again */
- u.u_signal[a] = f;
- if (f != SIG_DFL && f != SIG_IGN && f != SIG_HOLD)
- f = SIG_CATCH;
- if ((int)f & 1)
- p->p_siga0 |= sigmask;
- else
- p->p_siga0 &= ~sigmask;
- if ((int)f & 2)
- p->p_siga1 |= sigmask;
- else
- p->p_siga1 &= ~sigmask;
- (void) spl0();
- /*
- * Now handle options.
- */
- if (uap->signo & SIGDOPAUSE) {
- /*
- * Simulate a PDP11 style wait instrution which
- * atomically lowers priority, enables interrupts
- * and hangs.
+ u.u_error = killpg1(uap->signo, uap->pgid, 0);
+}
+
+/* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */
+
+killpg1(signo, pgid, all)
+ int signo, pgid, all;
+{
+ register struct proc *p;
+ struct pgrp *pgrp;
+ int f = 0, error = 0;
+
+
+ if (all)
+ /*
+ * broadcast
*/
- opause();
- /*NOTREACHED*/
+ for (p = allproc; p != NULL; p = p->p_nxt) {
+ if (p->p_ppid == 0 || p->p_flag&SSYS ||
+ p == u.u_procp ||
+ (u.u_uid && u.u_uid != p->p_uid &&
+ !(signo == SIGCONT && inferior(p))))
+ continue;
+ f++;
+ if (signo)
+ psignal(p, signo);
+ }
+ else {
+ if (pgid == 0)
+ /*
+ * zero pgid means send to my process group.
+ */
+ pgrp = u.u_procp->p_pgrp;
+ else {
+ pgrp = pgfind(pgid);
+ if (pgrp == NULL)
+ return(ESRCH);
+ }
+ if (!(pgrp->pg_jobc) &&
+ (signo==SIGTTIN || signo==SIGTTOU || signo==SIGTSTP))
+ return(EPERM);
+ for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) {
+ if (p->p_ppid == 0 || p->p_flag&SSYS)
+ continue;
+ if (u.u_uid && u.u_uid != p->p_uid &&
+ !(signo == SIGCONT && inferior(p))) {
+ error = EPERM;
+ continue;
+ }
+ f++;
+ if (signo)
+ psignal(p, signo);
+ }
}
- if (uap->signo & SIGDORTI)
- u.u_eosys = SIMULATERTI;
+ return (error ? error : (f == 0 ? ESRCH : 0));
}
/*
* Send the specified signal to
- * all processes with 'pgrp' as
+ * all processes with 'pgid' as
* process group.
- * Called by tty.c for quits and
- * interrupts.
*/
-gsignal(pgrp, sig)
- register int pgrp;
+gsignal(pgid, sig)
+{
+ register struct pgrp *pgrp;
+
+ if (!pgid)
+ return;
+ if ((pgrp = pgfind(pgid)) == NULL)
+ return;
+ pgsignal(pgrp, sig);
+}
+
+pgsignal(pgrp, sig)
+ register struct pgrp *pgrp;
{
register struct proc *p;
- if (pgrp == 0)
+ if (!(pgrp->pg_jobc) &&
+ (sig==SIGTTIN || sig==SIGTTOU || sig==SIGTSTP))
return;
- for(p = proc; p < procNPROC; p++)
- if (p->p_pgrp == pgrp)
- psignal(p, sig);
+ for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt)
+ psignal(p, sig);
}
/*
{
register int s;
register int (*action)();
- long sigmask;
+ int mask;
if ((unsigned)sig >= NSIG)
return;
- sigmask = (1L << (sig-1));
+ mask = sigmask(sig);
/*
* If proc is traced, always give parent a chance.
- * Otherwise get the signal action from the bits in the proc table.
*/
if (p->p_flag & STRC)
action = SIG_DFL;
else {
- s = (p->p_siga1&sigmask) != 0;
- s <<= 1;
- s |= (p->p_siga0&sigmask) != 0;
- action = (int(*)())s;
/*
- * If the signal is ignored, we forget about it immediately.
+ * If the signal is being ignored,
+ * then we forget about it immediately.
*/
- if (action == SIG_IGN)
+ 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;
}
-#define mask(sig) (1<<(sig-1))
-#define stops (mask(SIGSTOP)|mask(SIGTSTP)|mask(SIGTTIN)|mask(SIGTTOU))
if (sig) {
- p->p_sig |= sigmask;
switch (sig) {
case SIGTERM:
- if ((p->p_flag&STRC) != 0 || action != SIG_DFL)
+ if ((p->p_flag&STRC) || action != SIG_DFL)
break;
/* fall into ... */
break;
case SIGCONT:
- p->p_sig &= ~stops;
+ p->p_sig &= ~stopsigmask;
break;
- case SIGSTOP:
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
- p->p_sig &= ~mask(SIGCONT);
+ /*FALLTHROUGH*/
+ case SIGSTOP:
+ p->p_sig &= ~sigmask(SIGCONT);
break;
}
+ p->p_sig |= mask;
}
-#undef mask
-#undef stops
/*
* Defer further processing for signals which are held.
*/
if (action == SIG_HOLD)
return;
- s = spl6();
+ s = splhigh();
switch (p->p_stat) {
case SSLEEP:
*/
if (action != SIG_DFL)
goto run;
- /*
- * Don't clog system with children of init
- * stopped from the keyboard.
- */
- if (sig != SIGSTOP && p->p_pptr == &proc[1]) {
- psignal(p, SIGKILL);
- p->p_sig &= ~sigmask;
- splx(s);
- return;
- }
/*
* If a child in vfork(), stopping could
* cause deadlock.
*/
if (p->p_flag&SVFORK)
goto out;
- p->p_sig &= ~sigmask;
+ p->p_sig &= ~mask;
p->p_cursig = sig;
+ psignal(p->p_pptr, SIGCHLD);
stop(p);
goto out;
case SIGIO:
case SIGURG:
case SIGCHLD:
+ case SIGWINCH:
/*
* These signals are special in that they
* don't get propogated... if the process
*/
if (action != SIG_DFL)
goto run;
- p->p_sig &= ~sigmask; /* take it away */
+ p->p_sig &= ~mask; /* take it away */
goto out;
default:
* Already stopped, don't need to stop again.
* (If we did the shell could get confused.)
*/
- p->p_sig &= ~sigmask; /* take it away */
+ p->p_sig &= ~mask; /* take it away */
goto out;
default:
* Raise priority to at least PUSER.
*/
if (p->p_pri > PUSER)
- if ((p != u.u_procp || noproc) && p->p_stat == SRUN &&
- (p->p_flag & SLOAD)) {
- remrq(p);
- p->p_pri = PUSER;
- setrq(p);
- } else
- p->p_pri = PUSER;
+ p->p_pri = PUSER;
setrun(p);
out:
splx(s);
{
register struct proc *p;
register int sig;
- long sigbits;
- long sigmask;
+ int sigbits, mask;
p = u.u_procp;
for (;;) {
- sigbits = p->p_sig;
+ sigbits = p->p_sig &~ p->p_sigmask;
if ((p->p_flag&STRC) == 0)
- sigbits &= ~p->p_ignsig;
+ sigbits &= ~p->p_sigignore;
if (p->p_flag&SVFORK)
-#define bit(a) (1<<(a-1))
- sigbits &= ~(bit(SIGSTOP)|bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU));
+ sigbits &= ~stopsigmask;
if (sigbits == 0)
break;
- sig = ffs((int)sigbits);
- sigmask = 1L << (sig-1);
- p->p_sig &= ~sigmask; /* take the signal! */
+ sig = ffs((long)sigbits);
+ mask = sigmask(sig);
+ p->p_sig &= ~mask; /* take the signal! */
p->p_cursig = sig;
- if (p->p_flag&STRC && (p->p_flag&SVFORK)==0) {
+ if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) {
/*
* If traced, always stop, and stay
* stopped until released by the parent.
*/
+ psignal(p->p_pptr, SIGCHLD);
do {
stop(p);
swtch();
* If the traced bit got turned off,
* then put the signal taken above back into p_sig
* and go back up to the top to rescan signals.
- * This ensures that siga0 and u_signal are consistent.
+ * This ensures that p_sig* and u_signal are consistent.
*/
if ((p->p_flag&STRC) == 0) {
- p->p_sig |= sigmask;
+ p->p_sig |= mask;
continue;
}
sig = p->p_cursig;
if (sig == 0)
continue;
+
+ /*
+ * If signal is being masked put it back
+ * into p_sig and look for other signals.
+ */
+ mask = sigmask(sig);
+ if (p->p_sigmask & mask) {
+ p->p_sig |= mask;
+ continue;
+ }
}
- switch (u.u_signal[sig]) {
+ switch ((int)u.u_signal[sig]) {
case SIG_DFL:
/*
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
- /*
- * Children of init aren't allowed to stop
- * on signals from the keyboard.
- */
- if (p->p_pptr == &proc[1]) {
- psignal(p, SIGKILL);
- continue;
- }
- /* fall into ... */
-
case SIGSTOP:
if (p->p_flag&STRC)
continue;
+ psignal(p->p_pptr, SIGCHLD);
stop(p);
swtch();
continue;
case SIGCONT:
case SIGCHLD:
+ case SIGURG:
+ case SIGIO:
+ case SIGWINCH:
/*
* These signals are normally not
* sent if the action is the default.
/*
* Put the argument process into the stopped
- * state and notify the parent via wakeup and/or signal.
+ * state and notify the parent via wakeup.
+ * Signals are handled elsewhere.
*/
stop(p)
register struct proc *p;
p->p_stat = SSTOP;
p->p_flag &= ~SWTED;
wakeup((caddr_t)p->p_pptr);
- /*
- * Avoid sending signal to parent if process is traced
- */
- if (p->p_flag&STRC)
- return;
- psignal(p->p_pptr, SIGCHLD);
}
/*
*/
psig()
{
- register struct proc *rp = u.u_procp;
- register int n = rp->p_cursig;
- long sigmask = 1L << (n-1);
+ register struct proc *p = u.u_procp;
+ register int sig = p->p_cursig;
+ int mask = sigmask(sig), returnmask;
register int (*action)();
- if (rp->p_cursig == 0)
+ if (sig == 0)
panic("psig");
- action = u.u_signal[n];
+ action = u.u_signal[sig];
if (action != SIG_DFL) {
- if (action == SIG_IGN || action == SIG_HOLD)
+ if (action == SIG_IGN || (p->p_sigmask & mask))
panic("psig action");
u.u_error = 0;
- if (n != SIGILL && n != SIGTRAP)
- u.u_signal[n] = 0;
/*
- * If this catch value indicates automatic holding of
- * subsequent signals, set the hold value.
+ * Set the new mask value and also defer further
+ * occurences of this signal (unless we're simulating
+ * the old signal facilities).
+ *
+ * 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.
*/
- if (SIGISDEFER(action)) {
- (void) spl6();
- if ((int)SIG_HOLD & 1)
- rp->p_siga0 |= sigmask;
- else
- rp->p_siga0 &= ~sigmask;
- if ((int)SIG_HOLD & 2)
- rp->p_siga1 |= sigmask;
- else
- rp->p_siga1 &= ~sigmask;
- u.u_signal[n] = SIG_HOLD;
- (void) spl0();
- action = SIGUNDEFER(action);
+ (void) splhigh();
+ if (p->p_flag & SOUSIG) {
+ if (sig != SIGILL && sig != SIGTRAP) {
+ u.u_signal[sig] = SIG_DFL;
+ p->p_sigcatch &= ~mask;
+ }
+ mask = 0;
}
- sendsig(action, n);
- rp->p_cursig = 0;
+ if (p->p_flag & SOMASK) {
+ returnmask = u.u_oldmask;
+ p->p_flag &= ~SOMASK;
+ } else
+ returnmask = p->p_sigmask;
+ p->p_sigmask |= u.u_sigmask[sig] | mask;
+ (void) spl0();
+ u.u_ru.ru_nsignals++;
+ sendsig(action, sig, returnmask);
+ p->p_cursig = 0;
return;
}
u.u_acflag |= AXSIG;
- switch (n) {
+ switch (sig) {
case SIGILL:
case SIGIOT:
case SIGFPE:
case SIGSEGV:
case SIGSYS:
- u.u_arg[0] = n;
- if (core())
- n += 0200;
+ u.u_arg[0] = sig;
+ if (core() == 0)
+ sig += 0200;
}
- exit(n);
+ exit(sig);
}
-#ifdef unneeded
-int corestop = 0;
-#endif
/*
* Create a core image on the file "core"
* If you are looking for protection glitches,
*/
core()
{
- register struct inode *ip;
- extern schar();
-
-#ifdef unneeded
- if (corestop) {
- int i;
- for (i = 0; i < 10; i++)
- if (u.u_comm[i])
- putchar(u.u_comm[i], 0);
- printf(", uid %d\n", u.u_uid);
- if (corestop&2)
- asm("halt");
+ register struct vnode *vp;
+ register struct nameidata *ndp = &u.u_nd;
+ struct vattr vattr;
+ int error;
+
+ if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid)
+ return (EFAULT);
+ if (ctob(UPAGES + u.u_dsize + u.u_ssize) >=
+ u.u_rlimit[RLIMIT_CORE].rlim_cur)
+ return (EFAULT);
+ if (u.u_procp->p_textp) {
+ VOP_LOCK(u.u_procp->p_textp->x_vptr);
+ error = vn_access(u.u_procp->p_textp->x_vptr, VREAD, u.u_cred);
+ VOP_UNLOCK(u.u_procp->p_textp->x_vptr);
+ if (error)
+ return (EFAULT);
}
-#endif
- if (u.u_uid != u.u_ruid)
- return (0);
- if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= u.u_limit[LIM_CORE])
- return (0);
- u.u_error = 0;
- u.u_dirp = "core";
- ip = namei(schar, 1, 1);
- if (ip == NULL) {
- if (u.u_error)
- return (0);
- ip = maknode(0666);
- if (ip==NULL)
- return (0);
- }
- if (access(ip, IWRITE) ||
- (ip->i_mode&IFMT) != IFREG ||
- ip->i_nlink != 1) {
- u.u_error = EFAULT;
+ ndp->ni_segflg = UIO_SYSSPACE;
+ ndp->ni_dirp = "core";
+ if (error = vn_open(ndp, FCREAT|FWRITE, 0644))
+ return (error);
+ vp = ndp->ni_vp;
+ if (vp->v_type != VREG ||
+ VOP_GETATTR(vp, &vattr, u.u_cred) ||
+ vattr.va_nlink != 1) {
+ error = EFAULT;
goto out;
}
- itrunc(ip, 0);
+#ifdef MMAP
+ { register int fd;
+ /* unmasp funky devices in the user's address space */
+ for (fd = 0; fd < u.u_lastfile; fd++)
+ if (u.u_ofile[fd] && (u.u_pofile[fd] & UF_MAPPED))
+ munmapfd(fd);
+ }
+#endif
+ vattr_null(&vattr);
+ vattr.va_size = 0;
+ VOP_SETATTR(vp, &vattr, u.u_cred);
u.u_acflag |= ACORE;
- u.u_error =rdwri(UIO_WRITE, ip,
- (caddr_t)&u, ctob(UPAGES),
- 0, 1, (int *)0);
- if (u.u_error)
- rdwri(UIO_WRITE, ip,
- (caddr_t)ctob(u.u_tsize), ctob(u.u_dsize),
- ctob(UPAGES), 0, (int *)0);
- if (u.u_error)
- rdwri(UIO_WRITE, ip,
- (caddr_t)(USRSTACK-ctob(u.u_ssize)), ctob(u.u_ssize),
- ctob(UPAGES)+ctob(u.u_dsize), 0, (int *)0);
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&u, ctob(UPAGES), (off_t)0,
+ UIO_SYSSPACE, IO_UNIT, ndp->ni_cred, (int *)0);
+ if (error == 0)
+ error = vn_rdwr(UIO_WRITE, vp,
+ (caddr_t)ctob(dptov(u.u_procp, 0)),
+ (int)ctob(u.u_dsize), (off_t)ctob(UPAGES),
+ UIO_USERSPACE, IO_UNIT, ndp->ni_cred, (int *)0);
+ if (error == 0)
+ error = vn_rdwr(UIO_WRITE, vp,
+ (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)),
+ (int)ctob(u.u_ssize),
+ (off_t)ctob(UPAGES) + ctob(u.u_dsize),
+ UIO_USERSPACE, IO_UNIT, ndp->ni_cred, (int *)0);
out:
- iput(ip);
- return (u.u_error == 0);
-}
-
-/*
- * alarm clock signal
- */
-oalarm()
-{
- register struct proc *p;
- register c;
- register struct a {
- int deltat;
- } *uap;
-
- uap = (struct a *)u.u_ap;
- p = u.u_procp;
- c = p->p_clktim;
- p->p_clktim = uap->deltat;
- u.u_r.r_val1 = c;
+ if (vp)
+ vrele(vp);
+ return (error);
}
-
-/*
- * indefinite wait.
- * no one should wakeup(&u)
- */
-opause()
-{
-
- for (;;)
- sleep((caddr_t)&u, PSLEP);
-}
-