Changes to allow event-based process monitoring and control.
This commit is contained in:
parent
ceb0cf87e8
commit
2a024a2b05
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=31564
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
|
||||
* $Id: trap.c,v 1.117 1997/12/04 14:35:40 jkh Exp $
|
||||
* $Id: trap.c,v 1.118 1997/12/04 21:21:26 jmg Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -50,6 +50,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/pioctl.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/signalvar.h>
|
||||
@ -987,6 +988,8 @@ syscall(frame)
|
||||
p->p_retval[0] = 0;
|
||||
p->p_retval[1] = frame.tf_edx;
|
||||
|
||||
STOPEVENT(p, S_SCE, callp->sy_narg);
|
||||
|
||||
error = (*callp->sy_call)(p, args);
|
||||
|
||||
switch (error) {
|
||||
@ -1037,6 +1040,14 @@ syscall(frame)
|
||||
if (KTRPOINT(p, KTR_SYSRET))
|
||||
ktrsysret(p->p_tracep, code, error, p->p_retval[0]);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This works because errno is findable through the
|
||||
* register set. If we ever support an emulation where this
|
||||
* is not the case, this code will need to be revisited.
|
||||
*/
|
||||
STOPEVENT(p, S_SCX, code);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -36,7 +36,7 @@
|
||||
*
|
||||
* @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
|
||||
*
|
||||
* $Id: procfs_subr.c,v 1.16 1997/06/26 16:12:53 alex Exp $
|
||||
* $Id: procfs_subr.c,v 1.17 1997/08/02 14:32:18 bde Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -351,3 +351,14 @@ vfs_findname(nm, buf, buflen)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
procfs_exit(pid_t pid)
|
||||
{
|
||||
struct pfsnode *pfs;
|
||||
|
||||
for (pfs = pfshead; pfs ; pfs = pfs->pfs_next) {
|
||||
if (pfs->pfs_pid == pid)
|
||||
vgone(PFSTOV(pfs));
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
*
|
||||
* @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
|
||||
*
|
||||
* $Id: procfs_vnops.c,v 1.42 1997/11/07 08:53:15 phk Exp $
|
||||
* $Id: procfs_vnops.c,v 1.43 1997/12/05 19:55:47 bde Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -56,6 +56,7 @@
|
||||
#include <sys/dirent.h>
|
||||
#include <machine/reg.h>
|
||||
#include <miscfs/procfs/procfs.h>
|
||||
#include <sys/pioctl.h>
|
||||
|
||||
static int procfs_abortop __P((struct vop_abortop_args *));
|
||||
static int procfs_access __P((struct vop_access_args *));
|
||||
@ -64,6 +65,7 @@ static int procfs_bmap __P((struct vop_bmap_args *));
|
||||
static int procfs_close __P((struct vop_close_args *));
|
||||
static int procfs_getattr __P((struct vop_getattr_args *));
|
||||
static int procfs_inactive __P((struct vop_inactive_args *));
|
||||
static int procfs_ioctl __P((struct vop_ioctl_args *));
|
||||
static int procfs_lookup __P((struct vop_lookup_args *));
|
||||
static int procfs_open __P((struct vop_open_args *));
|
||||
static int procfs_print __P((struct vop_print_args *));
|
||||
@ -184,6 +186,79 @@ procfs_close(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* do an ioctl operation on a pfsnode (vp).
|
||||
* (vp) is not locked on entry or exit.
|
||||
*/
|
||||
static int
|
||||
procfs_ioctl(ap)
|
||||
struct vop_ioctl_args *ap;
|
||||
{
|
||||
struct pfsnode *pfs = VTOPFS(ap->a_vp);
|
||||
struct proc *procp;
|
||||
int error;
|
||||
int signo;
|
||||
struct procfs_status *psp;
|
||||
|
||||
procp = pfind(pfs->pfs_pid);
|
||||
if (procp == NULL) {
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
switch (ap->a_command) {
|
||||
case PIOCBIS:
|
||||
procp->p_stops |= *(unsigned int*)ap->a_data;
|
||||
break;
|
||||
case PIOCBIC:
|
||||
procp->p_stops &= ~*(unsigned int*)ap->a_data;
|
||||
break;
|
||||
case PIOCSFL:
|
||||
procp->p_pfsflags = (unsigned char)*(unsigned int*)ap->a_data;
|
||||
*(unsigned int*)ap->a_data = procp->p_stops;
|
||||
break;
|
||||
case PIOCSTATUS:
|
||||
psp = (struct procfs_status *)ap->a_data;
|
||||
psp->state = (procp->p_step == 0);
|
||||
psp->flags = procp->p_pfsflags;
|
||||
psp->events = procp->p_stops;
|
||||
if (procp->p_step) {
|
||||
psp->why = procp->p_stype;
|
||||
psp->val = procp->p_xstat;
|
||||
} else {
|
||||
psp->why = psp->val = 0; /* Not defined values */
|
||||
}
|
||||
break;
|
||||
case PIOCWAIT:
|
||||
psp = (struct procfs_status *)ap->a_data;
|
||||
if (procp->p_step == 0) {
|
||||
error = tsleep(&procp->p_stype, PWAIT | PCATCH, "piocwait", 0);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
psp->state = 1; /* It stopped */
|
||||
psp->flags = procp->p_pfsflags;
|
||||
psp->events = procp->p_stops;
|
||||
psp->why = procp->p_stype; /* why it stopped */
|
||||
psp->val = procp->p_xstat; /* any extra info */
|
||||
break;
|
||||
case PIOCCONT: /* Restart a proc */
|
||||
if (procp->p_step == 0)
|
||||
return EINVAL; /* Can only start a stopped process */
|
||||
if (ap->a_data && (signo = *(int*)ap->a_data)) {
|
||||
if (signo >= NSIG || signo <= 0)
|
||||
return EINVAL;
|
||||
if (error = psignal(procp, signo))
|
||||
return error;
|
||||
}
|
||||
procp->p_step = 0;
|
||||
wakeup(&procp->p_step);
|
||||
break;
|
||||
default:
|
||||
return (ENOTTY);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* do block mapping for pfsnode (vp).
|
||||
* since we don't use the buffer cache
|
||||
@ -909,6 +984,7 @@ static struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
|
||||
{ &vop_setattr_desc, (vop_t *) procfs_setattr },
|
||||
{ &vop_symlink_desc, (vop_t *) procfs_badop },
|
||||
{ &vop_write_desc, (vop_t *) procfs_rw },
|
||||
{ &vop_ioctl_desc, (vop_t *) procfs_ioctl },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
static struct vnodeopv_desc procfs_vnodeop_opv_desc =
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
|
||||
* $Id: trap.c,v 1.117 1997/12/04 14:35:40 jkh Exp $
|
||||
* $Id: trap.c,v 1.118 1997/12/04 21:21:26 jmg Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -50,6 +50,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/pioctl.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/signalvar.h>
|
||||
@ -987,6 +988,8 @@ syscall(frame)
|
||||
p->p_retval[0] = 0;
|
||||
p->p_retval[1] = frame.tf_edx;
|
||||
|
||||
STOPEVENT(p, S_SCE, callp->sy_narg);
|
||||
|
||||
error = (*callp->sy_call)(p, args);
|
||||
|
||||
switch (error) {
|
||||
@ -1037,6 +1040,14 @@ syscall(frame)
|
||||
if (KTRPOINT(p, KTR_SYSRET))
|
||||
ktrsysret(p->p_tracep, code, error, p->p_retval[0]);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This works because errno is findable through the
|
||||
* register set. If we ever support an emulation where this
|
||||
* is not the case, this code will need to be revisited.
|
||||
*/
|
||||
STOPEVENT(p, S_SCX, code);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -39,7 +39,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)init_main.c 8.9 (Berkeley) 1/21/94
|
||||
* $Id: init_main.c,v 1.75 1997/11/24 18:35:04 bde Exp $
|
||||
* $Id: init_main.c,v 1.76 1997/11/25 07:07:41 julian Exp $
|
||||
*/
|
||||
|
||||
#include "opt_devfs.h"
|
||||
@ -415,6 +415,12 @@ proc0_init(dummy)
|
||||
* Charge root for one process.
|
||||
*/
|
||||
(void)chgproccnt(0, 1);
|
||||
|
||||
/*
|
||||
* Initialize the procfs flags (to 0, of course)
|
||||
*/
|
||||
p->p_stops = p->p_stype = p->p_step = 0;
|
||||
|
||||
}
|
||||
SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL)
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kern_exec.c,v 1.67 1997/10/15 18:28:34 guido Exp $
|
||||
* $Id: kern_exec.c,v 1.68 1997/11/06 19:29:08 phk Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -40,6 +40,7 @@
|
||||
#include <sys/imgact_elf.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/pioctl.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/sysent.h>
|
||||
@ -338,6 +339,8 @@ execve(p, uap)
|
||||
* If tracing the process, trap to debugger so breakpoints
|
||||
* can be set before the program executes.
|
||||
*/
|
||||
STOPEVENT(p, S_EXEC, 0);
|
||||
|
||||
if (p->p_flag & P_TRACED)
|
||||
psignal(p, SIGTRAP);
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)kern_exit.c 8.7 (Berkeley) 2/12/94
|
||||
* $Id: kern_exit.c,v 1.59 1997/11/06 19:29:08 phk Exp $
|
||||
* $Id: kern_exit.c,v 1.60 1997/11/20 19:09:43 bde Exp $
|
||||
*/
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
@ -46,6 +46,7 @@
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/pioctl.h>
|
||||
#include <sys/tty.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/vnode.h>
|
||||
@ -113,6 +114,7 @@ exit1(p, rv)
|
||||
register struct proc *q, *nq;
|
||||
register struct vmspace *vm;
|
||||
ele_p ep = exit_list;
|
||||
extern void procfs_exit(pid_t);
|
||||
|
||||
if (p->p_pid == 1) {
|
||||
printf("init died (signal %d, exit %d)\n",
|
||||
@ -155,6 +157,14 @@ exit1(p, rv)
|
||||
#ifdef PGINPROF
|
||||
vmsizmon();
|
||||
#endif
|
||||
STOPEVENT(p, S_EXIT, rv);
|
||||
|
||||
/*
|
||||
* Now that we're back from stopevent(), force a close
|
||||
* of all open procfs files for this process.
|
||||
*/
|
||||
procfs_exit(p->p_pid);
|
||||
|
||||
/*
|
||||
* Check if any LKMs need anything done at process exit.
|
||||
* e.g. SYSV IPC stuff
|
||||
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)kern_sig.c 8.7 (Berkeley) 4/18/94
|
||||
* $Id: kern_sig.c,v 1.34 1997/09/13 19:42:12 joerg Exp $
|
||||
* $Id: kern_sig.c,v 1.35 1997/11/06 19:29:14 phk Exp $
|
||||
*/
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
@ -49,6 +49,7 @@
|
||||
#include <sys/namei.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/pioctl.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/acct.h>
|
||||
#include <sys/fcntl.h>
|
||||
@ -743,15 +744,19 @@ psignal(p, signum)
|
||||
register sig_t action;
|
||||
int mask;
|
||||
|
||||
if ((u_int)signum >= NSIG || signum == 0)
|
||||
if ((u_int)signum >= NSIG || signum == 0) {
|
||||
printf("psignal: signum %d\n", signum);
|
||||
panic("psignal signal number");
|
||||
}
|
||||
mask = sigmask(signum);
|
||||
prop = sigprop[signum];
|
||||
|
||||
/*
|
||||
* If proc is traced, always give parent a chance.
|
||||
* If proc is traced, always give parent a chance;
|
||||
* if signal event is tracked by procfs, give *that*
|
||||
* a chance, as well.
|
||||
*/
|
||||
if (p->p_flag & P_TRACED)
|
||||
if ((p->p_flag & P_TRACED) || (p->p_stops & S_SIG))
|
||||
action = SIG_DFL;
|
||||
else {
|
||||
/*
|
||||
@ -948,6 +953,8 @@ issignal(p)
|
||||
register int signum, mask, prop;
|
||||
|
||||
for (;;) {
|
||||
int traced = (p->p_flag & P_TRACED) || (p->p_stops & S_SIG);
|
||||
|
||||
mask = p->p_siglist & ~p->p_sigmask;
|
||||
if (p->p_flag & P_PPWAIT)
|
||||
mask &= ~stopsigmask;
|
||||
@ -956,11 +963,14 @@ issignal(p)
|
||||
signum = ffs((long)mask);
|
||||
mask = sigmask(signum);
|
||||
prop = sigprop[signum];
|
||||
|
||||
STOPEVENT(p, S_SIG, signum);
|
||||
|
||||
/*
|
||||
* We should see pending but ignored signals
|
||||
* only if P_TRACED was on when they were posted.
|
||||
*/
|
||||
if (mask & p->p_sigignore && (p->p_flag & P_TRACED) == 0) {
|
||||
if ((mask & p->p_sigignore) && (traced == 0)) {
|
||||
p->p_siglist &= ~mask;
|
||||
continue;
|
||||
}
|
||||
@ -974,7 +984,8 @@ issignal(p)
|
||||
do {
|
||||
stop(p);
|
||||
mi_switch();
|
||||
} while (!trace_req(p) && p->p_flag & P_TRACED);
|
||||
} while (!trace_req(p)
|
||||
&& p->p_flag & P_TRACED);
|
||||
|
||||
/*
|
||||
* If the traced bit got turned off, go back up
|
||||
@ -1118,6 +1129,8 @@ postsig(signum)
|
||||
signum, action, ps->ps_flags & SAS_OLDMASK ?
|
||||
ps->ps_oldmask : p->p_sigmask, 0);
|
||||
#endif
|
||||
STOPEVENT(p, S_SIG, signum);
|
||||
|
||||
if (action == SIG_DFL) {
|
||||
/*
|
||||
* Default action, where the default is to kill
|
||||
@ -1236,6 +1249,8 @@ coredump(p)
|
||||
int error, error1;
|
||||
char name[MAXCOMLEN+6]; /* progname.core */
|
||||
|
||||
STOPEVENT(p, S_CORE, 0);
|
||||
|
||||
if (p->p_flag & P_SUGID)
|
||||
return (EFAULT);
|
||||
if (ctob(UPAGES + vm->vm_dsize + vm->vm_ssize) >=
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
|
||||
* $Id: trap.c,v 1.117 1997/12/04 14:35:40 jkh Exp $
|
||||
* $Id: trap.c,v 1.118 1997/12/04 21:21:26 jmg Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -50,6 +50,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/pioctl.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/signalvar.h>
|
||||
@ -987,6 +988,8 @@ syscall(frame)
|
||||
p->p_retval[0] = 0;
|
||||
p->p_retval[1] = frame.tf_edx;
|
||||
|
||||
STOPEVENT(p, S_SCE, callp->sy_narg);
|
||||
|
||||
error = (*callp->sy_call)(p, args);
|
||||
|
||||
switch (error) {
|
||||
@ -1037,6 +1040,14 @@ syscall(frame)
|
||||
if (KTRPOINT(p, KTR_SYSRET))
|
||||
ktrsysret(p->p_tracep, code, error, p->p_retval[0]);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This works because errno is findable through the
|
||||
* register set. If we ever support an emulation where this
|
||||
* is not the case, this code will need to be revisited.
|
||||
*/
|
||||
STOPEVENT(p, S_SCX, code);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -28,7 +28,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: sys_process.c,v 1.31 1997/11/06 19:29:22 phk Exp $
|
||||
* $Id: sys_process.c,v 1.32 1997/11/12 12:28:12 tegge Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -503,3 +503,22 @@ trace_req(p)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* stopevent()
|
||||
* Stop a process because of a procfs event;
|
||||
* stay stopped until p->p_step is cleared
|
||||
* (cleared by PIOCCONT in procfs).
|
||||
*/
|
||||
|
||||
void
|
||||
stopevent(struct proc *p, unsigned int event, unsigned int val) {
|
||||
p->p_step = 1;
|
||||
|
||||
do {
|
||||
p->p_xstat = val;
|
||||
p->p_stype = event; /* Which event caused the stop? */
|
||||
wakeup(&p->p_stype); /* Wake up any PIOCWAIT'ing procs */
|
||||
tsleep(&p->p_step, PWAIT, "stopevent", 0);
|
||||
} while (p->p_step);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94
|
||||
* $Id: vfs_vnops.c,v 1.41 1997/11/07 08:53:11 phk Exp $
|
||||
* $Id: vfs_vnops.c,v 1.42 1997/11/29 01:33:10 dyson Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -454,8 +454,9 @@ vn_ioctl(fp, com, data, p)
|
||||
/* fall into ... */
|
||||
|
||||
default:
|
||||
#if 0
|
||||
return (ENOTTY);
|
||||
|
||||
#endif
|
||||
case VFIFO:
|
||||
case VCHR:
|
||||
case VBLK:
|
||||
|
@ -36,7 +36,7 @@
|
||||
*
|
||||
* @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
|
||||
*
|
||||
* $Id: procfs_subr.c,v 1.16 1997/06/26 16:12:53 alex Exp $
|
||||
* $Id: procfs_subr.c,v 1.17 1997/08/02 14:32:18 bde Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -351,3 +351,14 @@ vfs_findname(nm, buf, buflen)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
procfs_exit(pid_t pid)
|
||||
{
|
||||
struct pfsnode *pfs;
|
||||
|
||||
for (pfs = pfshead; pfs ; pfs = pfs->pfs_next) {
|
||||
if (pfs->pfs_pid == pid)
|
||||
vgone(PFSTOV(pfs));
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
*
|
||||
* @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
|
||||
*
|
||||
* $Id: procfs_vnops.c,v 1.42 1997/11/07 08:53:15 phk Exp $
|
||||
* $Id: procfs_vnops.c,v 1.43 1997/12/05 19:55:47 bde Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -56,6 +56,7 @@
|
||||
#include <sys/dirent.h>
|
||||
#include <machine/reg.h>
|
||||
#include <miscfs/procfs/procfs.h>
|
||||
#include <sys/pioctl.h>
|
||||
|
||||
static int procfs_abortop __P((struct vop_abortop_args *));
|
||||
static int procfs_access __P((struct vop_access_args *));
|
||||
@ -64,6 +65,7 @@ static int procfs_bmap __P((struct vop_bmap_args *));
|
||||
static int procfs_close __P((struct vop_close_args *));
|
||||
static int procfs_getattr __P((struct vop_getattr_args *));
|
||||
static int procfs_inactive __P((struct vop_inactive_args *));
|
||||
static int procfs_ioctl __P((struct vop_ioctl_args *));
|
||||
static int procfs_lookup __P((struct vop_lookup_args *));
|
||||
static int procfs_open __P((struct vop_open_args *));
|
||||
static int procfs_print __P((struct vop_print_args *));
|
||||
@ -184,6 +186,79 @@ procfs_close(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* do an ioctl operation on a pfsnode (vp).
|
||||
* (vp) is not locked on entry or exit.
|
||||
*/
|
||||
static int
|
||||
procfs_ioctl(ap)
|
||||
struct vop_ioctl_args *ap;
|
||||
{
|
||||
struct pfsnode *pfs = VTOPFS(ap->a_vp);
|
||||
struct proc *procp;
|
||||
int error;
|
||||
int signo;
|
||||
struct procfs_status *psp;
|
||||
|
||||
procp = pfind(pfs->pfs_pid);
|
||||
if (procp == NULL) {
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
switch (ap->a_command) {
|
||||
case PIOCBIS:
|
||||
procp->p_stops |= *(unsigned int*)ap->a_data;
|
||||
break;
|
||||
case PIOCBIC:
|
||||
procp->p_stops &= ~*(unsigned int*)ap->a_data;
|
||||
break;
|
||||
case PIOCSFL:
|
||||
procp->p_pfsflags = (unsigned char)*(unsigned int*)ap->a_data;
|
||||
*(unsigned int*)ap->a_data = procp->p_stops;
|
||||
break;
|
||||
case PIOCSTATUS:
|
||||
psp = (struct procfs_status *)ap->a_data;
|
||||
psp->state = (procp->p_step == 0);
|
||||
psp->flags = procp->p_pfsflags;
|
||||
psp->events = procp->p_stops;
|
||||
if (procp->p_step) {
|
||||
psp->why = procp->p_stype;
|
||||
psp->val = procp->p_xstat;
|
||||
} else {
|
||||
psp->why = psp->val = 0; /* Not defined values */
|
||||
}
|
||||
break;
|
||||
case PIOCWAIT:
|
||||
psp = (struct procfs_status *)ap->a_data;
|
||||
if (procp->p_step == 0) {
|
||||
error = tsleep(&procp->p_stype, PWAIT | PCATCH, "piocwait", 0);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
psp->state = 1; /* It stopped */
|
||||
psp->flags = procp->p_pfsflags;
|
||||
psp->events = procp->p_stops;
|
||||
psp->why = procp->p_stype; /* why it stopped */
|
||||
psp->val = procp->p_xstat; /* any extra info */
|
||||
break;
|
||||
case PIOCCONT: /* Restart a proc */
|
||||
if (procp->p_step == 0)
|
||||
return EINVAL; /* Can only start a stopped process */
|
||||
if (ap->a_data && (signo = *(int*)ap->a_data)) {
|
||||
if (signo >= NSIG || signo <= 0)
|
||||
return EINVAL;
|
||||
if (error = psignal(procp, signo))
|
||||
return error;
|
||||
}
|
||||
procp->p_step = 0;
|
||||
wakeup(&procp->p_step);
|
||||
break;
|
||||
default:
|
||||
return (ENOTTY);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* do block mapping for pfsnode (vp).
|
||||
* since we don't use the buffer cache
|
||||
@ -909,6 +984,7 @@ static struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
|
||||
{ &vop_setattr_desc, (vop_t *) procfs_setattr },
|
||||
{ &vop_symlink_desc, (vop_t *) procfs_badop },
|
||||
{ &vop_write_desc, (vop_t *) procfs_rw },
|
||||
{ &vop_ioctl_desc, (vop_t *) procfs_ioctl },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
static struct vnodeopv_desc procfs_vnodeop_opv_desc =
|
||||
|
36
sys/sys/pioctl.h
Normal file
36
sys/sys/pioctl.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* procfs ioctl definitions.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _SYS_PIOCTL_H
|
||||
# define _SYS_PIOCTL_H
|
||||
|
||||
# include <sys/ioccom.h>
|
||||
|
||||
struct procfs_status {
|
||||
int state; /* Running, stopped, something else? */
|
||||
int flags; /* Any flags */
|
||||
unsigned long events; /* Events to stop on */
|
||||
int why; /* What event, if any, proc stopped on */
|
||||
unsigned long val; /* Any extra data */
|
||||
};
|
||||
|
||||
# define PIOCBIS _IOW('p', 1, unsigned int) /* Set event flag */
|
||||
# define PIOCBIC _IOW('p', 2, unsigned int) /* Clear event flag */
|
||||
# define PIOCSFL _IOR('p', 3, unsigned int) /* Set flags */
|
||||
/* wait for proc to stop */
|
||||
# define PIOCWAIT _IOR('p', 4, struct procfs_status)
|
||||
# define PIOCCONT _IOW('p', 5, int) /* Continue a process */
|
||||
/* Get proc status */
|
||||
# define PIOCSTATUS _IOW('p', 6, struct procfs_status)
|
||||
|
||||
# define S_EXEC 0x00000001 /* stop-on-exec */
|
||||
# define S_SIG 0x00000002 /* stop-on-signal */
|
||||
# define S_SCE 0x00000004 /* stop on syscall entry */
|
||||
# define S_SCX 0x00000008 /* stop on syscall exit */
|
||||
# define S_CORE 0x00000010 /* stop on coredump */
|
||||
# define S_EXIT 0x00000020 /* stop on exit */
|
||||
|
||||
#endif
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)proc.h 8.15 (Berkeley) 5/19/95
|
||||
* $Id: proc.h,v 1.48 1997/11/24 15:15:20 bde Exp $
|
||||
* $Id: proc.h,v 1.49 1997/11/25 07:07:48 julian Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_PROC_H_
|
||||
@ -151,6 +151,11 @@ struct proc {
|
||||
|
||||
short p_locks; /* DEBUG: lockmgr count of held locks */
|
||||
short p_simple_locks; /* DEBUG: count of held simple locks */
|
||||
unsigned int p_stops; /* procfs event bitmask */
|
||||
unsigned int p_stype; /* procfs stop event type */
|
||||
char p_step; /* procfs stop *once* flag */
|
||||
unsigned char p_pfsflags; /* procfs flags */
|
||||
char p_pad3[2]; /* padding for alignment */
|
||||
register_t p_retval[2]; /* syscall aux returns */
|
||||
|
||||
/* End area that is zeroed on creation. */
|
||||
@ -270,6 +275,10 @@ MALLOC_DECLARE(M_SUBPROC);
|
||||
FREE(s, M_SESSION); \
|
||||
}
|
||||
|
||||
extern void stopevent(struct proc*, unsigned int, unsigned int);
|
||||
#define STOPEVENT(p,e,v) do { \
|
||||
if ((p)->p_stops & (e)) stopevent(p,e,v); } while (0)
|
||||
|
||||
/* hold process U-area in memory, normally for ptrace/procfs work */
|
||||
#define PHOLD(p) { \
|
||||
if ((p)->p_lock++ == 0 && ((p)->p_flag & P_INMEM) == 0) \
|
||||
|
Loading…
Reference in New Issue
Block a user