/* * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. * All rights reserved. * * %sccs.include.redist.c% * * @(#)kern_sig.c 7.35 (Berkeley) 06/28/91 */ #define SIGPROP /* include signal properties table */ #include "param.h" #include "signalvar.h" #include "resourcevar.h" #include "namei.h" #include "vnode.h" #include "proc.h" #include "systm.h" #include "timeb.h" #include "times.h" #include "buf.h" #include "seg.h" #include "acct.h" #include "file.h" #include "kernel.h" #include "wait.h" #include "ktrace.h" #include "machine/cpu.h" #include "vm/vm.h" #include "kinfo_proc.h" #include "user.h" /* for coredump */ /* * Can process p, with pcred pc, send the signal signo to process q? */ #define CANSIGNAL(p, pc, q, signo) \ ((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 || \ ((signo) == SIGCONT && (q)->p_session == (p)->p_session)) /* ARGSUSED */ sigaction(p, uap, retval) struct proc *p; register struct args { int signo; struct sigaction *nsa; struct sigaction *osa; } *uap; int *retval; { struct sigaction vec; register struct sigaction *sa; register struct sigacts *ps = p->p_sigacts; register int sig; int bit, error; sig = uap->signo; if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) return (EINVAL); sa = &vec; if (uap->osa) { sa->sa_handler = ps->ps_sigact[sig]; sa->sa_mask = ps->ps_catchmask[sig]; bit = sigmask(sig); 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; if (p->p_flag & SNOCLDSTOP) sa->sa_flags |= SA_NOCLDSTOP; if (error = copyout((caddr_t)sa, (caddr_t)uap->osa, sizeof (vec))) return (error); } if (uap->nsa) { if (error = copyin((caddr_t)uap->nsa, (caddr_t)sa, sizeof (vec))) return (error); setsigvec(p, sig, sa); } return (0); } setsigvec(p, sig, sa) register struct proc *p; int sig; register struct sigaction *sa; { register struct sigacts *ps = p->p_sigacts; register int bit; bit = sigmask(sig); /* * Change setting atomically. */ (void) splhigh(); ps->ps_sigact[sig] = sa->sa_handler; ps->ps_catchmask[sig] = 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; if (sig == SIGCHLD) { if (sa->sa_flags & SA_NOCLDSTOP) p->p_flag |= SNOCLDSTOP; else p->p_flag &= ~SNOCLDSTOP; } /* * 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[sig] & SA_IGNORE && sa->sa_handler == SIG_DFL)) { p->p_sig &= ~bit; /* never to be seen again */ if (sig != 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_sig &= ~mask; } ps->ps_sigact[nc] = SIG_DFL; } /* * Reset stack state to the user stack. * Clear set of signals caught on the signal stack. */ ps->ps_onstack = 0; ps->ps_sigsp = 0; ps->ps_sigonstack = 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. */ sigprocmask(p, uap, retval) register struct proc *p; struct args { int how; sigset_t mask; } *uap; int *retval; { int error = 0; *retval = p->p_sigmask; (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; default: error = EINVAL; break; } (void) spl0(); return (error); } /* ARGSUSED */ sigpending(p, uap, retval) struct proc *p; void *uap; int *retval; { *retval = p->p_sig; return (0); } #ifdef COMPAT_43 /* * Generalized interface signal handler, 4.3-compatible. */ /* ARGSUSED */ osigvec(p, uap, retval) struct proc *p; register struct args { int signo; struct sigvec *nsv; struct sigvec *osv; } *uap; int *retval; { struct sigvec vec; register struct sigacts *ps = p->p_sigacts; register struct sigvec *sv; register int sig; int bit, error; sig = uap->signo; if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) return (EINVAL); sv = &vec; if (uap->osv) { *(sig_t *)&sv->sv_handler = ps->ps_sigact[sig]; sv->sv_mask = ps->ps_catchmask[sig]; bit = sigmask(sig); 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; if (p->p_flag & SNOCLDSTOP) sv->sv_flags |= SA_NOCLDSTOP; if (error = copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec))) return (error); } if (uap->nsv) { if (error = copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec))) return (error); sv->sv_flags ^= SA_RESTART; /* opposite of SV_INTERRUPT */ setsigvec(p, sig, (struct sigaction *)sv); } return (0); } osigblock(p, uap, retval) register struct proc *p; struct args { int mask; } *uap; int *retval; { (void) splhigh(); *retval = p->p_sigmask; p->p_sigmask |= uap->mask &~ sigcantmask; (void) spl0(); return (0); } osigsetmask(p, uap, retval) struct proc *p; struct args { int mask; } *uap; int *retval; { (void) splhigh(); *retval = p->p_sigmask; p->p_sigmask = uap->mask &~ sigcantmask; (void) spl0(); return (0); } #endif /* * 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. */ /* ARGSUSED */ sigsuspend(p, uap, retval) register struct proc *p; struct args { sigset_t mask; } *uap; int *retval; { 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 proc structure * to indicate this (should be in sigacts). */ ps->ps_oldmask = p->p_sigmask; ps->ps_flags |= SA_OLDMASK; p->p_sigmask = uap->mask &~ sigcantmask; (void) tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0); /* always return EINTR rather than ERESTART... */ return (EINTR); } /* ARGSUSED */ sigstack(p, uap, retval) struct proc *p; register struct args { struct sigstack *nss; struct sigstack *oss; } *uap; int *retval; { struct sigstack ss; int error = 0; if (uap->oss && (error = copyout((caddr_t)&p->p_sigacts->ps_sigstack, (caddr_t)uap->oss, sizeof (struct sigstack)))) return (error); if (uap->nss && (error = copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss))) == 0) p->p_sigacts->ps_sigstack = ss; return (error); } /* ARGSUSED */ kill(cp, uap, retval) register struct proc *cp; register struct args { int pid; int signo; } *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 */ } #ifdef COMPAT_43 /* ARGSUSED */ okillpg(p, uap, retval) struct proc *p; register struct args { int pgid; int signo; } *uap; int *retval; { if ((unsigned) uap->signo >= NSIG) return (EINVAL); return (killpg1(p, uap->signo, uap->pgid, 0)); } #endif /* * 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 */ for (p = allproc; p != NULL; p = p->p_nxt) { if (p->p_pid <= 1 || p->p_flag&SSYS || p == cp || !CANSIGNAL(cp, pc, p, signo)) continue; nfound++; if (signo) psignal(p, signo); } else { if (pgid == 0) /* * zero pgid means send to my process group. */ pgrp = cp->p_pgrp; else { pgrp = pgfind(pgid); if (pgrp == NULL) return (ESRCH); } for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) { if (p->p_pid <= 1 || p->p_flag&SSYS || p->p_stat == SZOMB || !CANSIGNAL(cp, pc, p, signo)) continue; nfound++; if (signo) psignal(p, signo); } } return (nfound ? 0 : ESRCH); } /* * Send the specified signal to * all processes with 'pgid' as * process group. */ void gsignal(pgid, sig) int pgid, sig; { struct pgrp *pgrp; if (pgid && (pgrp = pgfind(pgid))) pgsignal(pgrp, sig, 0); } /* * Send sig to every member of a process group. * If checktty is 1, limit to members which have a controlling * terminal. */ void pgsignal(pgrp, sig, checkctty) struct pgrp *pgrp; int sig, checkctty; { register struct proc *p; if (pgrp) for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) if (checkctty == 0 || p->p_flag&SCTTY) psignal(p, sig); } /* * 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, sig, code) struct proc *p; register int sig; unsigned code; { register struct sigacts *ps = p->p_sigacts; int mask; mask = sigmask(sig); if ((p->p_flag & STRC) == 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)) ktrpsig(p->p_tracep, sig, ps->ps_sigact[sig], p->p_sigmask, code); #endif sendsig(ps->ps_sigact[sig], sig, p->p_sigmask, code); p->p_sigmask |= ps->ps_catchmask[sig] | mask; } else { ps->ps_code = code; /* XXX for core dump/debugger */ psignal(p, sig); } } /* * Send the specified signal to the specified process. * If the signal has an action, the action is usually performed * by the target process rather than the caller; we simply 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, sig) register struct proc *p; register int sig; { register int s, prop; register sig_t action; int mask; if ((unsigned)sig >= NSIG || sig == 0) panic("psignal sig"); mask = sigmask(sig); prop = sigprop[sig]; /* * If proc is traced, always give parent a chance. */ if (p->p_flag & STRC) 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 && (sig == SIGKILL || sig == SIGTERM && (p->p_flag&STRC || action != SIG_DFL))) p->p_nice = NZERO; if (prop & SA_CONT) p->p_sig &= ~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_sig &= ~contsigmask; } p->p_sig |= 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 & SSINTR) == 0) goto out; /* * Process is sleeping and traced... make it runnable * so it can discover the signal in issig() and stop * for the parent. */ if (p->p_flag&STRC) goto run; /* * 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&SPPWAIT) goto out; p->p_sig &= ~mask; p->p_xstat = sig; if ((p->p_pptr->p_flag & SNOCLDSTOP) == 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&STRC) goto out; /* * Kill signal always sets processes running. */ if (sig == 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_sig, * as it has no further action. If SIGCONT is held, * continue the process and leave the signal in p_sig. * 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_sig &= ~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_sig &= ~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 setrun the process, leave it stopped. */ if (p->p_wchan && p->p_flag & SSINTR) 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); goto out; } /*NOTREACHED*/ runfast: /* * Raise priority to at least PUSER. */ if (p->p_pri > PUSER) p->p_pri = PUSER; run: setrun(p); out: splx(s); } /* * If the current process has a signal to process (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 actually calling * issig by checking the pending signal masks in the CURSIG macro.) * The normal call sequence is * * while (sig = CURSIG(curproc)) * psig(sig); */ issig(p) register struct proc *p; { register int sig, mask, prop; for (;;) { mask = p->p_sig &~ p->p_sigmask; if (p->p_flag&SPPWAIT) mask &= ~stopsigmask; if (mask == 0) /* no signal to send */ return (0); sig = ffs((long)mask); mask = sigmask(sig); prop = sigprop[sig]; /* * We should see pending but ignored signals * only if STRC was on when they were posted. */ if (mask & p->p_sigignore && (p->p_flag&STRC) == 0) { p->p_sig &= ~mask; continue; } if (p->p_flag&STRC && (p->p_flag&SPPWAIT) == 0) { /* * If traced, always stop, and stay * stopped until released by the parent. */ p->p_xstat = sig; psignal(p->p_pptr, SIGCHLD); do { stop(p); swtch(); } while (!procxmt(p) && p->p_flag&STRC); /* * 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&STRC) == 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_sig &= ~mask; /* clear the old signal */ sig = p->p_xstat; if (sig == 0) continue; /* * Put the new signal into p_sig. * If signal is being masked, * look for other signals. */ mask = sigmask(sig); p->p_sig |= 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. */ switch ((int)p->p_sigacts->ps_sigact[sig]) { case SIG_DFL: /* * Don't take default actions on system processes. */ if (p->p_pid <= 1) 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&STRC || (p->p_pgrp->pg_jobc == 0 && prop & SA_TTYSTOP)) break; /* == ignore */ p->p_xstat = sig; stop(p); if ((p->p_pptr->p_flag & SNOCLDSTOP) == 0) psignal(p->p_pptr, SIGCHLD); swtch(); break; } else if (prop & SA_IGNORE) { /* * Except for SIGCONT, shouldn't get here. * Default action is to ignore; drop it. */ break; /* == ignore */ } else return (sig); /*NOTREACHED*/ case SIG_IGN: /* * 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&STRC) == 0) printf("issig\n"); break; /* == ignore */ default: /* * This signal has an action, let * psig process it. */ return (sig); } p->p_sig &= ~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. */ stop(p) register struct proc *p; { p->p_stat = SSTOP; p->p_flag &= ~SWTED; wakeup((caddr_t)p->p_pptr); } /* * Take the action for the specified signal * from the current set of pending signals. */ void psig(sig) register int sig; { register struct proc *p = curproc; register struct sigacts *ps = p->p_sigacts; register sig_t action; int mask, returnmask; #ifdef DIAGNOSTIC if (sig == 0) panic("psig"); #endif mask = sigmask(sig); p->p_sig &= ~mask; action = ps->ps_sigact[sig]; #ifdef KTRACE if (KTRPOINT(p, KTR_PSIG)) ktrpsig(p->p_tracep, sig, action, ps->ps_flags & SA_OLDMASK ? ps->ps_oldmask : p->p_sigmask, 0); #endif if (action == SIG_DFL) { /* * Default action, where the default is to kill * the process. (Other cases were ignored above.) */ sigexit(p, sig); /* NOTREACHED */ } else { /* * If we get here, the signal must be caught. */ #ifdef DIAGNOSTIC if (action == SIG_IGN || (p->p_sigmask & mask)) panic("psig 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 & SA_OLDMASK) { returnmask = ps->ps_oldmask; ps->ps_flags &= ~SA_OLDMASK; } else returnmask = p->p_sigmask; p->p_sigmask |= ps->ps_catchmask[sig] | mask; (void) spl0(); p->p_stats->p_ru.ru_nsignals++; sendsig(action, sig, returnmask, 0); } } /* * 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. */ sigexit(p, sig) register struct proc *p; int sig; { p->p_acflag |= AXSIG; if (sigprop[sig] & SA_CORE) { p->p_sigacts->ps_sig = sig; if (coredump(p) == 0) sig |= WCOREFLAG; } exit(p, W_EXITCODE(0, sig)); /* NOTREACHED */ } /* * Create a core dump. * The file name is "core.progname". * Core dumps are not created if the process is setuid. */ coredump(p) register struct proc *p; { register struct vnode *vp; register struct pcred *pcred = p->p_cred; register struct ucred *cred = pcred->pc_ucred; register struct vmspace *vm = p->p_vmspace; struct vattr vattr; int error, error1; struct nameidata nd; char name[MAXCOMLEN+6]; /* core.progname */ if (pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid) return (EFAULT); if (ctob(UPAGES + vm->vm_dsize + vm->vm_ssize) >= p->p_rlimit[RLIMIT_CORE].rlim_cur) return (EFAULT); sprintf(name, "core.%s", p->p_comm); nd.ni_dirp = name; nd.ni_segflg = UIO_SYSSPACE; if (error = vn_open(&nd, p, O_CREAT|FWRITE, 0644)) return (error); vp = nd.ni_vp; if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) { error = EFAULT; goto out; } VATTR_NULL(&vattr); vattr.va_size = 0; VOP_SETATTR(vp, &vattr, cred, p); p->p_acflag |= ACORE; bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc)); fill_eproc(p, &p->p_addr->u_kproc.kp_eproc); #ifdef HPUXCOMPAT /* * BLETCH! If we loaded from an HPUX format binary file * we have to dump an HPUX style user struct so that the * HPUX debuggers can grok it. */ if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXBIN) error = hpuxdumpu(vp, cred); else #endif error = vn_rdwr(UIO_WRITE, vp, (caddr_t) p->p_addr, ctob(UPAGES), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); if (error == 0) error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr, (int)ctob(vm->vm_dsize), (off_t)ctob(UPAGES), UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); if (error == 0) error = vn_rdwr(UIO_WRITE, vp, (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)), round_page(ctob(vm->vm_ssize)), (off_t)ctob(UPAGES) + ctob(vm->vm_dsize), UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); out: VOP_UNLOCK(vp); error1 = vn_close(vp, FWRITE, cred, p); if (error == 0) error = error1; return (error); } /* * Nonexistent system call-- signal process (may want to handle it). * Flag error in case process won't see signal immediately (blocked or ignored). */ /* ARGSUSED */ nosys(p, args, retval) struct proc *p; void *args; int *retval; { psignal(p, SIGSYS); return (EINVAL); }