/* * set process group (setpgid/old setpgrp) * * caller does setpgid(targpid, targpgid) * * pid must be caller or child of caller (ESRCH) * if a child * pid must be in same session (EPERM) * pid can't have done an exec (EACCES) * if pgid != pid * there must exist some pid in same session having pgid (EPERM) * pid must not be session leader (EPERM) */ int sys_setpgid(struct setpgid_args *uap) { struct proc *curp = curproc; struct proc *targp; /* target process */ struct pgrp *pgrp = NULL; /* target pgrp */ int error; if (uap->pgid < 0) return (EINVAL); if (uap->pid != 0 && uap->pid != curp->p_pid) { if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) { if (targp) PRELE(targp); error = ESRCH; targp = NULL; goto done; } lwkt_gettoken(&targp->p_token); /* targp now referenced and its token is held */ if (targp->p_pgrp == NULL || targp->p_session != curp->p_session) { error = EPERM; goto done; } if (targp->p_flags & P_EXEC) { error = EACCES; goto done; } } else { targp = curp; PHOLD(targp); lwkt_gettoken(&targp->p_token); } if (SESS_LEADER(targp)) { error = EPERM; goto done; } if (uap->pgid == 0) { uap->pgid = targp->p_pid; } else if (uap->pgid != targp->p_pid) { if ((pgrp = pgfind(uap->pgid)) == NULL || pgrp->pg_session != curp->p_session) { error = EPERM; goto done; } } error = enterpgrp(targp, uap->pgid, 0); done: if (pgrp) pgrel(pgrp); if (targp) { lwkt_reltoken(&targp->p_token); PRELE(targp); } return (error); }
/* ARGSUSED */ int sys_setpgid(struct proc *curp, void *v, register_t *retval) { struct sys_setpgid_args /* { syscallarg(pid_t) pid; syscallarg(int) pgid; } */ *uap = v; struct process *curpr = curp->p_p; struct process *targpr; /* target process */ struct pgrp *pgrp, *newpgrp; /* target pgrp */ pid_t pid; int pgid, error; pid = SCARG(uap, pid); pgid = SCARG(uap, pgid); if (pgid < 0) return (EINVAL); newpgrp = pool_get(&pgrp_pool, PR_WAITOK); if (pid != 0 && pid != curpr->ps_pid) { if ((targpr = prfind(pid)) == 0 || !inferior(targpr, curpr)) { error = ESRCH; goto out; } if (targpr->ps_session != curpr->ps_session) { error = EPERM; goto out; } if (targpr->ps_flags & PS_EXEC) { error = EACCES; goto out; } } else targpr = curpr; if (SESS_LEADER(targpr)) { error = EPERM; goto out; } if (pgid == 0) pgid = targpr->ps_pid; else if (pgid != targpr->ps_pid) if ((pgrp = pgfind(pgid)) == 0 || pgrp->pg_session != curpr->ps_session) { error = EPERM; goto out; } return (enterpgrp(targpr, pgid, newpgrp, NULL)); out: pool_put(&pgrp_pool, newpgrp); return (error); }
int sys_setsid(struct setsid_args *uap) { struct proc *p = curproc; struct pgrp *pg = NULL; int error; lwkt_gettoken(&p->p_token); if (p->p_pgid == p->p_pid || (pg = pgfind(p->p_pid)) != NULL) { error = EPERM; if (pg) pgrel(pg); } else { enterpgrp(p, p->p_pid, 1); uap->sysmsg_result = p->p_pid; error = 0; } lwkt_reltoken(&p->p_token); return (error); }
/* * setpgid - set process group ID for job control. * * If the specified pid is equal to 0, the process ID of * the calling process is used. Also, if pgid is 0, the process * ID of the indicated process is used. */ int sys_setpgid(pid_t pid, pid_t pgid) { struct proc *p; DPRINTF(("proc: setpgid pid=%d pgid=%d\n", pid, pgid)); if (pid == 0) p = curproc; else { if ((p = p_find(pid)) == NULL) return ESRCH; } if (pgid < 0) return EINVAL; if (pgid == 0) pgid = p->p_pid; if (p->p_pgrp->pg_pgid == pgid) /* already leader */ return 0; return (enterpgrp(p, pgid)); }
/* ARGSUSED */ int sys_setsid(struct proc *p, void *v, register_t *retval) { struct session *newsess; struct pgrp *newpgrp; struct process *pr = p->p_p; pid_t pid = pr->ps_pid; newsess = pool_get(&session_pool, PR_WAITOK); newpgrp = pool_get(&pgrp_pool, PR_WAITOK); if (pr->ps_pgid == pid || pgfind(pid)) { pool_put(&pgrp_pool, newpgrp); pool_put(&session_pool, newsess); return (EPERM); } else { (void) enterpgrp(pr, pid, newpgrp, newsess); *retval = pid; return (0); } }
/* * setsid - create session and set process group ID. */ int sys_setsid(pid_t *retval) { struct proc *p; struct pgrp *pgrp; struct session *sess; int error; DPRINTF(("proc: setsid sid=%d\n", curproc->p_pid)); p = curproc; if (p->p_pid == p->p_pgrp->pg_pgid) /* already leader */ return EPERM; if ((sess = malloc(sizeof(struct session))) == NULL) return ENOMEM; memset(sess, 0, sizeof(*sess)); /* * Create a new process group. */ if ((error = enterpgrp(p, p->p_pid)) != 0) { free(sess); return error; } pgrp = p->p_pgrp; /* * Create a new session. */ sess->s_refcnt = 1; sess->s_leader = p; sess->s_ttyhold = 0; pgrp->pg_session = sess; *retval = p->p_pid; return 0; }