/* * Send a signal to all process in the process group. */ int kill_pg(pid_t pgid, int sig) { struct proc *p; struct pgrp *pgrp; list_t head, n; int err = 0; DPRINTF(("proc: killpg pgid=%d sig=%d\n", pgid, sig)); if ((pgrp = pgrp_find(pgid)) == NULL) return ESRCH; head = &pgrp->pg_members; for (n = list_first(head); n != head; n = list_next(n)) { p = list_entry(n, struct proc, p_link); if ((err = send_sig(p, sig)) != 0) break; } return err; }
/* * Most actions in the fcntl() call are straightforward; simply * pass control to the NetBSD system call. A few commands need * conversions after the actual system call has done its work, * because the flag values and lock structure are different. */ int linux_sys_fcntl(struct lwp *l, const struct linux_sys_fcntl_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(int) cmd; syscallarg(void *) arg; } */ struct proc *p = l->l_proc; int fd, cmd, error; u_long val; void *arg; struct sys_fcntl_args fca; file_t *fp; struct vnode *vp; struct vattr va; long pgid; struct pgrp *pgrp; struct tty *tp; fd = SCARG(uap, fd); cmd = SCARG(uap, cmd); arg = SCARG(uap, arg); switch (cmd) { case LINUX_F_DUPFD: cmd = F_DUPFD; break; case LINUX_F_GETFD: cmd = F_GETFD; break; case LINUX_F_SETFD: cmd = F_SETFD; break; case LINUX_F_GETFL: SCARG(&fca, fd) = fd; SCARG(&fca, cmd) = F_GETFL; SCARG(&fca, arg) = arg; if ((error = sys_fcntl(l, &fca, retval))) return error; retval[0] = bsd_to_linux_ioflags(retval[0]); return 0; case LINUX_F_SETFL: { file_t *fp1 = NULL; val = linux_to_bsd_ioflags((unsigned long)SCARG(uap, arg)); /* * Linux seems to have same semantics for sending SIGIO to the * read side of socket, but slightly different semantics * for SIGIO to the write side. Rather than sending the SIGIO * every time it's possible to write (directly) more data, it * only sends SIGIO if last write(2) failed due to insufficient * memory to hold the data. This is compatible enough * with NetBSD semantics to not do anything about the * difference. * * Linux does NOT send SIGIO for pipes. Deal with socketpair * ones and DTYPE_PIPE ones. For these, we don't set * the underlying flags (we don't pass O_ASYNC flag down * to sys_fcntl()), but set the FASYNC flag for file descriptor, * so that F_GETFL would report the ASYNC i/o is on. */ if (val & O_ASYNC) { if (((fp1 = fd_getfile(fd)) == NULL)) return (EBADF); if (((fp1->f_type == DTYPE_SOCKET) && fp1->f_data && ((struct socket *)fp1->f_data)->so_state & SS_ISAPIPE) || (fp1->f_type == DTYPE_PIPE)) val &= ~O_ASYNC; else { /* not a pipe, do not modify anything */ fd_putfile(fd); fp1 = NULL; } } SCARG(&fca, fd) = fd; SCARG(&fca, cmd) = F_SETFL; SCARG(&fca, arg) = (void *) val; error = sys_fcntl(l, &fca, retval); /* Now set the FASYNC flag for pipes */ if (fp1) { if (!error) { mutex_enter(&fp1->f_lock); fp1->f_flag |= FASYNC; mutex_exit(&fp1->f_lock); } fd_putfile(fd); } return (error); } case LINUX_F_GETLK: do_linux_getlk(fd, cmd, arg, linux, flock); case LINUX_F_SETLK: case LINUX_F_SETLKW: do_linux_setlk(fd, cmd, arg, linux, flock, LINUX_F_SETLK); case LINUX_F_SETOWN: case LINUX_F_GETOWN: /* * We need to route fcntl() for tty descriptors around normal * fcntl(), since NetBSD tty TIOC{G,S}PGRP semantics is too * restrictive for Linux F_{G,S}ETOWN. For non-tty descriptors, * this is not a problem. */ if ((fp = fd_getfile(fd)) == NULL) return EBADF; /* Check it's a character device vnode */ if (fp->f_type != DTYPE_VNODE || (vp = (struct vnode *)fp->f_data) == NULL || vp->v_type != VCHR) { fd_putfile(fd); not_tty: /* Not a tty, proceed with common fcntl() */ cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN; break; } vn_lock(vp, LK_SHARED | LK_RETRY); error = VOP_GETATTR(vp, &va, l->l_cred); VOP_UNLOCK(vp); fd_putfile(fd); if (error) return error; if ((tp = cdev_tty(va.va_rdev)) == NULL) goto not_tty; /* set tty pg_id appropriately */ mutex_enter(proc_lock); if (cmd == LINUX_F_GETOWN) { retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID; mutex_exit(proc_lock); return 0; } if ((long)arg <= 0) { pgid = -(long)arg; } else { struct proc *p1 = proc_find((long)arg); if (p1 == NULL) { mutex_exit(proc_lock); return (ESRCH); } pgid = (long)p1->p_pgrp->pg_id; } pgrp = pgrp_find(pgid); if (pgrp == NULL || pgrp->pg_session != p->p_session) { mutex_exit(proc_lock); return EPERM; } tp->t_pgrp = pgrp; mutex_exit(proc_lock); return 0; default: return EOPNOTSUPP; } SCARG(&fca, fd) = fd; SCARG(&fca, cmd) = cmd; SCARG(&fca, arg) = arg; return sys_fcntl(l, &fca, retval); }