sleep doesn't need spl0 (idle does it)
[unix-history] / usr / src / sys / kern / sys_generic.c
index 94ee513..405c62a 100644 (file)
@@ -4,14 +4,15 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)sys_generic.c       7.22 (Berkeley) %G%
+ *     @(#)sys_generic.c       7.30 (Berkeley) %G%
  */
 
 #include "param.h"
 #include "systm.h"
  */
 
 #include "param.h"
 #include "systm.h"
-#include "user.h"
+#include "filedesc.h"
 #include "ioctl.h"
 #include "file.h"
 #include "ioctl.h"
 #include "file.h"
+#include "socketvar.h"
 #include "proc.h"
 #include "uio.h"
 #include "kernel.h"
 #include "proc.h"
 #include "uio.h"
 #include "kernel.h"
@@ -24,6 +25,7 @@
 /*
  * Read system call.
  */
 /*
  * Read system call.
  */
+/* ARGSUSED */
 read(p, uap, retval)
        struct proc *p;
        register struct args {
 read(p, uap, retval)
        struct proc *p;
        register struct args {
@@ -34,6 +36,7 @@ read(p, uap, retval)
        int *retval;
 {
        register struct file *fp;
        int *retval;
 {
        register struct file *fp;
+       register struct filedesc *fdp = p->p_fd;
        struct uio auio;
        struct iovec aiov;
        long cnt, error = 0;
        struct uio auio;
        struct iovec aiov;
        long cnt, error = 0;
@@ -41,8 +44,8 @@ read(p, uap, retval)
        struct iovec ktriov;
 #endif
 
        struct iovec ktriov;
 #endif
 
-       if (((unsigned)uap->fdes) >= NOFILE ||
-           (fp = u.u_ofile[uap->fdes]) == NULL ||
+       if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
+           (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
            (fp->f_flag & FREAD) == 0)
                return (EBADF);
        aiov.iov_base = (caddr_t)uap->cbuf;
            (fp->f_flag & FREAD) == 0)
                return (EBADF);
        aiov.iov_base = (caddr_t)uap->cbuf;
@@ -52,6 +55,7 @@ read(p, uap, retval)
        auio.uio_resid = uap->count;
        auio.uio_rw = UIO_READ;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_resid = uap->count;
        auio.uio_rw = UIO_READ;
        auio.uio_segflg = UIO_USERSPACE;
+       auio.uio_procp = p;
 #ifdef KTRACE
        /*
         * if tracing, save a copy of iovec
 #ifdef KTRACE
        /*
         * if tracing, save a copy of iovec
@@ -76,6 +80,7 @@ read(p, uap, retval)
 /*
  * Scatter read system call.
  */
 /*
  * Scatter read system call.
  */
+/* ARGSUSED */
 readv(p, uap, retval)
        struct proc *p;
        register struct args {
 readv(p, uap, retval)
        struct proc *p;
        register struct args {
@@ -86,31 +91,36 @@ readv(p, uap, retval)
        int *retval;
 {
        register struct file *fp;
        int *retval;
 {
        register struct file *fp;
+       register struct filedesc *fdp = p->p_fd;
        struct uio auio;
        register struct iovec *iov;
        struct uio auio;
        register struct iovec *iov;
+       struct iovec *saveiov;
        struct iovec aiov[UIO_SMALLIOV];
        long i, cnt, error = 0;
        struct iovec aiov[UIO_SMALLIOV];
        long i, cnt, error = 0;
+       unsigned iovlen;
 #ifdef KTRACE
        struct iovec *ktriov = NULL;
 #endif
 
 #ifdef KTRACE
        struct iovec *ktriov = NULL;
 #endif
 
-       if (((unsigned)uap->fdes) >= NOFILE ||
-           (fp = u.u_ofile[uap->fdes]) == NULL ||
+       if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
+           (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
            (fp->f_flag & FREAD) == 0)
                return (EBADF);
            (fp->f_flag & FREAD) == 0)
                return (EBADF);
+       /* note: can't use iovlen until iovcnt is validated */
+       iovlen = uap->iovcnt * sizeof (struct iovec);
        if (uap->iovcnt > UIO_SMALLIOV) {
                if (uap->iovcnt > UIO_MAXIOV)
                        return (EINVAL);
        if (uap->iovcnt > UIO_SMALLIOV) {
                if (uap->iovcnt > UIO_MAXIOV)
                        return (EINVAL);
-               MALLOC(iov, struct iovec *, 
-                     sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
+               MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
+               saveiov = iov;
        } else
                iov = aiov;
        auio.uio_iov = iov;
        auio.uio_iovcnt = uap->iovcnt;
        auio.uio_rw = UIO_READ;
        auio.uio_segflg = UIO_USERSPACE;
        } else
                iov = aiov;
        auio.uio_iov = iov;
        auio.uio_iovcnt = uap->iovcnt;
        auio.uio_rw = UIO_READ;
        auio.uio_segflg = UIO_USERSPACE;
-       if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
-           uap->iovcnt * sizeof (struct iovec)))
+       auio.uio_procp = p;
+       if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
                goto done;
        auio.uio_resid = 0;
        for (i = 0; i < uap->iovcnt; i++) {
                goto done;
        auio.uio_resid = 0;
        for (i = 0; i < uap->iovcnt; i++) {
@@ -130,8 +140,6 @@ readv(p, uap, retval)
         * if tracing, save a copy of iovec
         */
        if (KTRPOINT(p, KTR_GENIO))  {
         * if tracing, save a copy of iovec
         */
        if (KTRPOINT(p, KTR_GENIO))  {
-               unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec);
-
                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
        }
                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
        }
@@ -153,7 +161,7 @@ readv(p, uap, retval)
        *retval = cnt;
 done:
        if (uap->iovcnt > UIO_SMALLIOV)
        *retval = cnt;
 done:
        if (uap->iovcnt > UIO_SMALLIOV)
-               FREE(iov, M_IOV);
+               FREE(saveiov, M_IOV);
        return (error);
 }
 
        return (error);
 }
 
@@ -170,6 +178,7 @@ write(p, uap, retval)
        int *retval;
 {
        register struct file *fp;
        int *retval;
 {
        register struct file *fp;
+       register struct filedesc *fdp = p->p_fd;
        struct uio auio;
        struct iovec aiov;
        long cnt, error = 0;
        struct uio auio;
        struct iovec aiov;
        long cnt, error = 0;
@@ -177,8 +186,8 @@ write(p, uap, retval)
        struct iovec ktriov;
 #endif
 
        struct iovec ktriov;
 #endif
 
-       if (((unsigned)uap->fdes) >= NOFILE ||
-           (fp = u.u_ofile[uap->fdes]) == NULL ||
+       if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
+           (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
            (fp->f_flag & FWRITE) == 0)
                return (EBADF);
        aiov.iov_base = (caddr_t)uap->cbuf;
            (fp->f_flag & FWRITE) == 0)
                return (EBADF);
        aiov.iov_base = (caddr_t)uap->cbuf;
@@ -188,6 +197,7 @@ write(p, uap, retval)
        auio.uio_resid = uap->count;
        auio.uio_rw = UIO_WRITE;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_resid = uap->count;
        auio.uio_rw = UIO_WRITE;
        auio.uio_segflg = UIO_USERSPACE;
+       auio.uio_procp = p;
 #ifdef KTRACE
        /*
         * if tracing, save a copy of iovec
 #ifdef KTRACE
        /*
         * if tracing, save a copy of iovec
@@ -226,31 +236,36 @@ writev(p, uap, retval)
        int *retval;
 {
        register struct file *fp;
        int *retval;
 {
        register struct file *fp;
+       register struct filedesc *fdp = p->p_fd;
        struct uio auio;
        register struct iovec *iov;
        struct uio auio;
        register struct iovec *iov;
+       struct iovec *saveiov;
        struct iovec aiov[UIO_SMALLIOV];
        long i, cnt, error = 0;
        struct iovec aiov[UIO_SMALLIOV];
        long i, cnt, error = 0;
+       unsigned iovlen;
 #ifdef KTRACE
        struct iovec *ktriov = NULL;
 #endif
 
 #ifdef KTRACE
        struct iovec *ktriov = NULL;
 #endif
 
-       if (((unsigned)uap->fdes) >= NOFILE ||
-           (fp = u.u_ofile[uap->fdes]) == NULL ||
+       if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
+           (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
            (fp->f_flag & FWRITE) == 0)
                return (EBADF);
            (fp->f_flag & FWRITE) == 0)
                return (EBADF);
+       /* note: can't use iovlen until iovcnt is validated */
+       iovlen = uap->iovcnt * sizeof (struct iovec);
        if (uap->iovcnt > UIO_SMALLIOV) {
                if (uap->iovcnt > UIO_MAXIOV)
                        return (EINVAL);
        if (uap->iovcnt > UIO_SMALLIOV) {
                if (uap->iovcnt > UIO_MAXIOV)
                        return (EINVAL);
-               MALLOC(iov, struct iovec *, 
-                     sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
+               MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
+               saveiov = iov;
        } else
                iov = aiov;
        auio.uio_iov = iov;
        auio.uio_iovcnt = uap->iovcnt;
        auio.uio_rw = UIO_WRITE;
        auio.uio_segflg = UIO_USERSPACE;
        } else
                iov = aiov;
        auio.uio_iov = iov;
        auio.uio_iovcnt = uap->iovcnt;
        auio.uio_rw = UIO_WRITE;
        auio.uio_segflg = UIO_USERSPACE;
-       if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
-           uap->iovcnt * sizeof (struct iovec)))
+       auio.uio_procp = p;
+       if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
                goto done;
        auio.uio_resid = 0;
        for (i = 0; i < uap->iovcnt; i++) {
                goto done;
        auio.uio_resid = 0;
        for (i = 0; i < uap->iovcnt; i++) {
@@ -270,8 +285,6 @@ writev(p, uap, retval)
         * if tracing, save a copy of iovec
         */
        if (KTRPOINT(p, KTR_GENIO))  {
         * if tracing, save a copy of iovec
         */
        if (KTRPOINT(p, KTR_GENIO))  {
-               unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec);
-
                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
        }
                MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
                bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
        }
@@ -296,7 +309,7 @@ writev(p, uap, retval)
        *retval = cnt;
 done:
        if (uap->iovcnt > UIO_SMALLIOV)
        *retval = cnt;
 done:
        if (uap->iovcnt > UIO_SMALLIOV)
-               FREE(iov, M_IOV);
+               FREE(saveiov, M_IOV);
        return (error);
 }
 
        return (error);
 }
 
@@ -314,26 +327,28 @@ ioctl(p, uap, retval)
        int *retval;
 {
        register struct file *fp;
        int *retval;
 {
        register struct file *fp;
+       register struct filedesc *fdp = p->p_fd;
        register int com, error;
        register u_int size;
        caddr_t memp = 0;
 #define STK_PARAMS     128
        char stkbuf[STK_PARAMS];
        caddr_t data = stkbuf;
        register int com, error;
        register u_int size;
        caddr_t memp = 0;
 #define STK_PARAMS     128
        char stkbuf[STK_PARAMS];
        caddr_t data = stkbuf;
+       int tmp;
 
 
-       if ((unsigned)uap->fdes >= NOFILE ||
-           (fp = u.u_ofile[uap->fdes]) == NULL)
+       if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
+           (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
                return (EBADF);
        if ((fp->f_flag & (FREAD|FWRITE)) == 0)
                return (EBADF);
        com = uap->cmd;
 
        if (com == FIOCLEX) {
                return (EBADF);
        if ((fp->f_flag & (FREAD|FWRITE)) == 0)
                return (EBADF);
        com = uap->cmd;
 
        if (com == FIOCLEX) {
-               u.u_pofile[uap->fdes] |= UF_EXCLOSE;
+               fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
                return (0);
        }
        if (com == FIONCLEX) {
                return (0);
        }
        if (com == FIONCLEX) {
-               u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
+               fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
                return (0);
        }
 
                return (0);
        }
 
@@ -371,22 +386,54 @@ ioctl(p, uap, retval)
        switch (com) {
 
        case FIONBIO:
        switch (com) {
 
        case FIONBIO:
-               error = fset(fp, FNDELAY, *(int *)data);
+               if (tmp = *(int *)data)
+                       fp->f_flag |= FNONBLOCK;
+               else
+                       fp->f_flag &= ~FNONBLOCK;
+               error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
                break;
 
        case FIOASYNC:
                break;
 
        case FIOASYNC:
-               error = fset(fp, FASYNC, *(int *)data);
+               if (tmp = *(int *)data)
+                       fp->f_flag |= FASYNC;
+               else
+                       fp->f_flag &= ~FASYNC;
+               error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
                break;
 
        case FIOSETOWN:
                break;
 
        case FIOSETOWN:
-               error = fsetown(fp, *(int *)data);
+               tmp = *(int *)data;
+               if (fp->f_type == DTYPE_SOCKET) {
+                       ((struct socket *)fp->f_data)->so_pgid = tmp;
+                       error = 0;
+                       break;
+               }
+               if (tmp <= 0) {
+                       tmp = -tmp;
+               } else {
+                       struct proc *p1 = pfind(tmp);
+                       if (p1 == 0) {
+                               error = ESRCH;
+                               break;
+                       }
+                       tmp = p1->p_pgrp->pg_id;
+               }
+               error = (*fp->f_ops->fo_ioctl)
+                       (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
                break;
 
        case FIOGETOWN:
                break;
 
        case FIOGETOWN:
-               error = fgetown(fp, (int *)data);
+               if (fp->f_type == DTYPE_SOCKET) {
+                       error = 0;
+                       *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
+                       break;
+               }
+               error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
+               *(int *)data = -*(int *)data;
                break;
                break;
+
        default:
        default:
-               error = (*fp->f_ops->fo_ioctl)(fp, com, data);
+               error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
                /*
                 * Copy any data to user, size was
                 * already set and checked above.
                /*
                 * Copy any data to user, size was
                 * already set and checked above.
@@ -400,7 +447,7 @@ ioctl(p, uap, retval)
        return (error);
 }
 
        return (error);
 }
 
-int    nselcoll;
+int    selwait, nselcoll;
 
 /*
  * Select system call.
 
 /*
  * Select system call.
@@ -420,8 +467,8 @@ select(p, uap, retval)
 
        bzero((caddr_t)ibits, sizeof(ibits));
        bzero((caddr_t)obits, sizeof(obits));
 
        bzero((caddr_t)ibits, sizeof(ibits));
        bzero((caddr_t)obits, sizeof(obits));
-       if (uap->nd > NOFILE)
-               uap->nd = NOFILE;       /* forgiving, if slightly wrong */
+       if (uap->nd > p->p_fd->fd_nfiles)
+               uap->nd = p->p_fd->fd_nfiles;   /* forgiving; slightly wrong */
        ni = howmany(uap->nd, NFDBITS);
 
 #define        getbits(name, x) \
        ni = howmany(uap->nd, NFDBITS);
 
 #define        getbits(name, x) \
@@ -452,7 +499,7 @@ select(p, uap, retval)
 retry:
        ncoll = nselcoll;
        p->p_flag |= SSEL;
 retry:
        ncoll = nselcoll;
        p->p_flag |= SSEL;
-       error = selscan(ibits, obits, uap->nd, retval);
+       error = selscan(p, ibits, obits, uap->nd, retval);
        if (error || *retval)
                goto done;
        s = splhigh();
        if (error || *retval)
                goto done;
        s = splhigh();
@@ -494,10 +541,12 @@ done:
        return (error);
 }
 
        return (error);
 }
 
-selscan(ibits, obits, nfd, retval)
+selscan(p, ibits, obits, nfd, retval)
+       struct proc *p;
        fd_set *ibits, *obits;
        int nfd, *retval;
 {
        fd_set *ibits, *obits;
        int nfd, *retval;
 {
+       register struct filedesc *fdp = p->p_fd;
        register int which, i, j;
        register fd_mask bits;
        int flag;
        register int which, i, j;
        register fd_mask bits;
        int flag;
@@ -520,12 +569,12 @@ selscan(ibits, obits, nfd, retval)
                        bits = ibits[which].fds_bits[i/NFDBITS];
                        while ((j = ffs(bits)) && i + --j < nfd) {
                                bits &= ~(1 << j);
                        bits = ibits[which].fds_bits[i/NFDBITS];
                        while ((j = ffs(bits)) && i + --j < nfd) {
                                bits &= ~(1 << j);
-                               fp = u.u_ofile[i + j];
+                               fp = fdp->fd_ofiles[i + j];
                                if (fp == NULL) {
                                        error = EBADF;
                                        break;
                                }
                                if (fp == NULL) {
                                        error = EBADF;
                                        break;
                                }
-                               if ((*fp->f_ops->fo_select)(fp, flag)) {
+                               if ((*fp->f_ops->fo_select)(fp, flag, p)) {
                                        FD_SET(i + j, &obits[which]);
                                        n++;
                                }
                                        FD_SET(i + j, &obits[which]);
                                        n++;
                                }
@@ -537,9 +586,14 @@ selscan(ibits, obits, nfd, retval)
 }
 
 /*ARGSUSED*/
 }
 
 /*ARGSUSED*/
-seltrue(dev, flag)
+#ifdef __STDC__
+seltrue(dev_t dev, int which, struct proc *p)
+#else
+seltrue(dev, flag, p)
        dev_t dev;
        int flag;
        dev_t dev;
        int flag;
+       struct proc *p;
+#endif
 {
 
        return (1);
 {
 
        return (1);