+ register char *pop;
+ struct vnode *vp;
+ int i, tmp, error, flg = F_POSIX;
+ struct flock fl;
+
+ if ((unsigned)uap->fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[uap->fd]) == NULL)
+ return (EBADF);
+ pop = &fdp->fd_ofileflags[uap->fd];
+ switch(uap->cmd) {
+ case F_DUPFD:
+ if ((unsigned)uap->arg >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
+ return (EINVAL);
+ if (error = fdalloc(p, uap->arg, &i))
+ return (error);
+ fdp->fd_ofiles[i] = fp;
+ fdp->fd_ofileflags[i] = *pop &~ UF_EXCLOSE;
+ fp->f_count++;
+ if (i > fdp->fd_lastfile)
+ fdp->fd_lastfile = i;
+ *retval = i;
+ return (0);
+
+ case F_GETFD:
+ *retval = *pop & 1;
+ return (0);
+
+ case F_SETFD:
+ *pop = (*pop &~ 1) | (uap->arg & 1);
+ return (0);
+
+ case F_GETFL:
+ *retval = OFLAGS(fp->f_flag);
+ return (0);
+
+ case F_SETFL:
+ fp->f_flag &= ~FCNTLFLAGS;
+ fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS;
+ if (tmp = (fp->f_flag & FNDELAY))
+ fp->f_flag |= FNDELAY;
+ else
+ fp->f_flag &= ~FNDELAY;
+ error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
+ if (error)
+ return (error);
+ if (tmp = (fp->f_flag & FASYNC))
+ fp->f_flag |= FASYNC;
+ else
+ fp->f_flag &= ~FASYNC;
+ error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
+ if (!error)
+ return (0);
+ fp->f_flag &= ~FNDELAY;
+ tmp = 0;
+ (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
+ return (error);
+
+ case F_GETOWN:
+ if (fp->f_type == DTYPE_SOCKET) {
+ *retval = ((struct socket *)fp->f_data)->so_pgid;
+ return (0);
+ }
+ error = (*fp->f_ops->fo_ioctl)
+ (fp, (int)TIOCGPGRP, (caddr_t)retval, p);
+ *retval = -*retval;
+ return (error);
+
+ case F_SETOWN:
+ if (fp->f_type == DTYPE_SOCKET) {
+ ((struct socket *)fp->f_data)->so_pgid = uap->arg;
+ return (0);
+ }
+ if (uap->arg <= 0) {
+ uap->arg = -uap->arg;
+ } else {
+ struct proc *p1 = pfind(uap->arg);
+ if (p1 == 0)
+ return (ESRCH);
+ uap->arg = p1->p_pgrp->pg_id;
+ }
+ return ((*fp->f_ops->fo_ioctl)
+ (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));
+
+ case F_SETLKW:
+ flg |= F_WAIT;
+ /* Fall into F_SETLK */
+
+ case F_SETLK:
+ if (fp->f_type != DTYPE_VNODE)
+ return (EBADF);
+ vp = (struct vnode *)fp->f_data;
+ /* Copy in the lock structure */
+ error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
+ if (error)
+ return (error);
+ if (fl.l_whence == SEEK_CUR)
+ fl.l_start += fp->f_offset;
+ switch (fl.l_type) {
+
+ case F_RDLCK:
+ if ((fp->f_flag & FREAD) == 0)
+ return (EBADF);
+ return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
+
+ case F_WRLCK:
+ if ((fp->f_flag & FWRITE) == 0)
+ return (EBADF);
+ return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
+
+ case F_UNLCK:
+ return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
+ F_POSIX));
+
+ default:
+ return (EINVAL);
+ }