+ p = pfind(SCARG(uap, pid));
+ if (p == 0)
+ return (ESRCH);
+ if (SCARG(uap, req) == PT_ATTACH) {
+ /*
+ * Must be root if the process has used set user or group
+ * privileges or does not belong to the real user. Must
+ * not be already traced. Can't attach to ourselves.
+ */
+ if ((p->p_flag & P_SUGID ||
+ p->p_cred->p_ruid != curp->p_cred->p_ruid) &&
+ (error = suser(p->p_ucred, &p->p_acflag)) != 0)
+ return (error);
+ if (p->p_flag & P_TRACED)
+ return (EALREADY); /* ??? */
+ if (p->p_pid == curp->p_pid)
+ return (EINVAL);
+ /*
+ * It would be nice if the tracing relationship was separate
+ * from the parent relationship but that would require
+ * another set of links in the proc struct or for "wait"
+ * to scan the entire proc table. To make life easier,
+ * we just re-parent the process we're trying to trace.
+ * The old parent is remembered so we can put things back
+ * on a "detach".
+ */
+ p->p_flag |= P_TRACED;
+ p->p_oppid = p->p_pptr->p_pid;
+ proc_reparent(p, curp);
+ psignal(p, SIGSTOP);
+ return (0);