add definition for ability to produce a backtrace
[unix-history] / usr / src / sys / kern / sys_generic.c
index 76686b8..eb7da95 100644 (file)
@@ -1,10 +1,15 @@
 /*
 /*
- * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)sys_generic.c       8.1 (Berkeley) %G%
+ *     @(#)sys_generic.c       8.9 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
 #include <sys/ktrace.h>
 #endif
 
 #include <sys/ktrace.h>
 #endif
 
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+
 /*
  * Read system call.
  */
 /*
  * Read system call.
  */
-struct read_args {
-       int     fdes;
-       char    *cbuf;
-       unsigned count;
-};
 /* ARGSUSED */
 /* ARGSUSED */
+int
 read(p, uap, retval)
        struct proc *p;
 read(p, uap, retval)
        struct proc *p;
-       register struct read_args *uap;
-       int *retval;
+       register struct read_args /* {
+               syscallarg(int) fd;
+               syscallarg(char *) buf;
+               syscallarg(u_int) nbyte;
+       } */ *uap;
+       register_t *retval;
 {
        register struct file *fp;
        register struct filedesc *fdp = p->p_fd;
 {
        register struct file *fp;
        register struct filedesc *fdp = p->p_fd;
@@ -45,15 +53,15 @@ read(p, uap, retval)
        struct iovec ktriov;
 #endif
 
        struct iovec ktriov;
 #endif
 
-       if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
-           (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
+       if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
+           (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
            (fp->f_flag & FREAD) == 0)
                return (EBADF);
            (fp->f_flag & FREAD) == 0)
                return (EBADF);
-       aiov.iov_base = (caddr_t)uap->cbuf;
-       aiov.iov_len = uap->count;
+       aiov.iov_base = (caddr_t)SCARG(uap, buf);
+       aiov.iov_len = SCARG(uap, nbyte);
        auio.uio_iov = &aiov;
        auio.uio_iovcnt = 1;
        auio.uio_iov = &aiov;
        auio.uio_iovcnt = 1;
-       auio.uio_resid = uap->count;
+       auio.uio_resid = SCARG(uap, nbyte);
        auio.uio_rw = UIO_READ;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_procp = p;
        auio.uio_rw = UIO_READ;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_procp = p;
@@ -64,7 +72,7 @@ read(p, uap, retval)
        if (KTRPOINT(p, KTR_GENIO))
                ktriov = aiov;
 #endif
        if (KTRPOINT(p, KTR_GENIO))
                ktriov = aiov;
 #endif
-       cnt = uap->count;
+       cnt = SCARG(uap, nbyte);
        if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
                if (auio.uio_resid != cnt && (error == ERESTART ||
                    error == EINTR || error == EWOULDBLOCK))
        if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
                if (auio.uio_resid != cnt && (error == ERESTART ||
                    error == EINTR || error == EWOULDBLOCK))
@@ -72,7 +80,8 @@ read(p, uap, retval)
        cnt -= auio.uio_resid;
 #ifdef KTRACE
        if (KTRPOINT(p, KTR_GENIO) && error == 0)
        cnt -= auio.uio_resid;
 #ifdef KTRACE
        if (KTRPOINT(p, KTR_GENIO) && error == 0)
-               ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
+               ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, &ktriov,
+                   cnt, error);
 #endif
        *retval = cnt;
        return (error);
 #endif
        *retval = cnt;
        return (error);
@@ -81,15 +90,15 @@ read(p, uap, retval)
 /*
  * Scatter read system call.
  */
 /*
  * Scatter read system call.
  */
-struct readv_args {
-       int     fdes;
-       struct  iovec *iovp;
-       unsigned iovcnt;
-};
+int
 readv(p, uap, retval)
        struct proc *p;
 readv(p, uap, retval)
        struct proc *p;
-       register struct readv_args *uap;
-       int *retval;
+       register struct readv_args /* {
+               syscallarg(int) fd;
+               syscallarg(struct iovec *) iovp;
+               syscallarg(u_int) iovcnt;
+       } */ *uap;
+       register_t *retval;
 {
        register struct file *fp;
        register struct filedesc *fdp = p->p_fd;
 {
        register struct file *fp;
        register struct filedesc *fdp = p->p_fd;
@@ -98,19 +107,19 @@ readv(p, uap, retval)
        struct iovec *needfree;
        struct iovec aiov[UIO_SMALLIOV];
        long i, cnt, error = 0;
        struct iovec *needfree;
        struct iovec aiov[UIO_SMALLIOV];
        long i, cnt, error = 0;
-       unsigned iovlen;
+       u_int iovlen;
 #ifdef KTRACE
        struct iovec *ktriov = NULL;
 #endif
 
 #ifdef KTRACE
        struct iovec *ktriov = NULL;
 #endif
 
-       if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
-           (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
+       if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
+           (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
            (fp->f_flag & FREAD) == 0)
                return (EBADF);
        /* note: can't use iovlen until iovcnt is validated */
            (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)
+       iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
+       if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
+               if (SCARG(uap, iovcnt) > UIO_MAXIOV)
                        return (EINVAL);
                MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
                needfree = iov;
                        return (EINVAL);
                MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
                needfree = iov;
@@ -119,23 +128,19 @@ readv(p, uap, retval)
                needfree = NULL;
        }
        auio.uio_iov = iov;
                needfree = NULL;
        }
        auio.uio_iov = iov;
-       auio.uio_iovcnt = uap->iovcnt;
+       auio.uio_iovcnt = SCARG(uap, iovcnt);
        auio.uio_rw = UIO_READ;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_procp = p;
        auio.uio_rw = UIO_READ;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_procp = p;
-       if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
+       if (error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen))
                goto done;
        auio.uio_resid = 0;
                goto done;
        auio.uio_resid = 0;
-       for (i = 0; i < uap->iovcnt; i++) {
-               if (iov->iov_len < 0) {
+       for (i = 0; i < SCARG(uap, iovcnt); i++) {
+               if (auio.uio_resid + iov->iov_len < auio.uio_resid) {
                        error = EINVAL;
                        goto done;
                }
                auio.uio_resid += iov->iov_len;
                        error = EINVAL;
                        goto done;
                }
                auio.uio_resid += iov->iov_len;
-               if (auio.uio_resid < 0) {
-                       error = EINVAL;
-                       goto done;
-               }
                iov++;
        }
 #ifdef KTRACE
                iov++;
        }
 #ifdef KTRACE
@@ -156,7 +161,7 @@ readv(p, uap, retval)
 #ifdef KTRACE
        if (ktriov != NULL) {
                if (error == 0)
 #ifdef KTRACE
        if (ktriov != NULL) {
                if (error == 0)
-                       ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
+                       ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, ktriov,
                            cnt, error);
                FREE(ktriov, M_TEMP);
        }
                            cnt, error);
                FREE(ktriov, M_TEMP);
        }
@@ -171,15 +176,15 @@ done:
 /*
  * Write system call
  */
 /*
  * Write system call
  */
-struct write_args {
-       int     fdes;
-       char    *cbuf;
-       unsigned count;
-};
+int
 write(p, uap, retval)
        struct proc *p;
 write(p, uap, retval)
        struct proc *p;
-       register struct write_args *uap;
-       int *retval;
+       register struct write_args /* {
+               syscallarg(int) fd;
+               syscallarg(char *) buf;
+               syscallarg(u_int) nbyte;
+       } */ *uap;
+       register_t *retval;
 {
        register struct file *fp;
        register struct filedesc *fdp = p->p_fd;
 {
        register struct file *fp;
        register struct filedesc *fdp = p->p_fd;
@@ -190,15 +195,15 @@ write(p, uap, retval)
        struct iovec ktriov;
 #endif
 
        struct iovec ktriov;
 #endif
 
-       if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
-           (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
+       if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
+           (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
            (fp->f_flag & FWRITE) == 0)
                return (EBADF);
            (fp->f_flag & FWRITE) == 0)
                return (EBADF);
-       aiov.iov_base = (caddr_t)uap->cbuf;
-       aiov.iov_len = uap->count;
+       aiov.iov_base = (caddr_t)SCARG(uap, buf);
+       aiov.iov_len = SCARG(uap, nbyte);
        auio.uio_iov = &aiov;
        auio.uio_iovcnt = 1;
        auio.uio_iov = &aiov;
        auio.uio_iovcnt = 1;
-       auio.uio_resid = uap->count;
+       auio.uio_resid = SCARG(uap, nbyte);
        auio.uio_rw = UIO_WRITE;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_procp = p;
        auio.uio_rw = UIO_WRITE;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_procp = p;
@@ -209,7 +214,7 @@ write(p, uap, retval)
        if (KTRPOINT(p, KTR_GENIO))
                ktriov = aiov;
 #endif
        if (KTRPOINT(p, KTR_GENIO))
                ktriov = aiov;
 #endif
-       cnt = uap->count;
+       cnt = SCARG(uap, nbyte);
        if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
                if (auio.uio_resid != cnt && (error == ERESTART ||
                    error == EINTR || error == EWOULDBLOCK))
        if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
                if (auio.uio_resid != cnt && (error == ERESTART ||
                    error == EINTR || error == EWOULDBLOCK))
@@ -220,7 +225,7 @@ write(p, uap, retval)
        cnt -= auio.uio_resid;
 #ifdef KTRACE
        if (KTRPOINT(p, KTR_GENIO) && error == 0)
        cnt -= auio.uio_resid;
 #ifdef KTRACE
        if (KTRPOINT(p, KTR_GENIO) && error == 0)
-               ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
+               ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
                    &ktriov, cnt, error);
 #endif
        *retval = cnt;
                    &ktriov, cnt, error);
 #endif
        *retval = cnt;
@@ -230,15 +235,15 @@ write(p, uap, retval)
 /*
  * Gather write system call
  */
 /*
  * Gather write system call
  */
-struct writev_args {
-       int     fdes;
-       struct  iovec *iovp;
-       unsigned iovcnt;
-};
+int
 writev(p, uap, retval)
        struct proc *p;
 writev(p, uap, retval)
        struct proc *p;
-       register struct writev_args *uap;
-       int *retval;
+       register struct writev_args /* {
+               syscallarg(int) fd;
+               syscallarg(struct iovec *) iovp;
+               syscallarg(u_int) iovcnt;
+       } */ *uap;
+       register_t *retval;
 {
        register struct file *fp;
        register struct filedesc *fdp = p->p_fd;
 {
        register struct file *fp;
        register struct filedesc *fdp = p->p_fd;
@@ -247,19 +252,19 @@ writev(p, uap, retval)
        struct iovec *needfree;
        struct iovec aiov[UIO_SMALLIOV];
        long i, cnt, error = 0;
        struct iovec *needfree;
        struct iovec aiov[UIO_SMALLIOV];
        long i, cnt, error = 0;
-       unsigned iovlen;
+       u_int iovlen;
 #ifdef KTRACE
        struct iovec *ktriov = NULL;
 #endif
 
 #ifdef KTRACE
        struct iovec *ktriov = NULL;
 #endif
 
-       if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
-           (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
+       if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
+           (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
            (fp->f_flag & FWRITE) == 0)
                return (EBADF);
        /* note: can't use iovlen until iovcnt is validated */
            (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)
+       iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
+       if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
+               if (SCARG(uap, iovcnt) > UIO_MAXIOV)
                        return (EINVAL);
                MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
                needfree = iov;
                        return (EINVAL);
                MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
                needfree = iov;
@@ -268,23 +273,19 @@ writev(p, uap, retval)
                needfree = NULL;
        }
        auio.uio_iov = iov;
                needfree = NULL;
        }
        auio.uio_iov = iov;
-       auio.uio_iovcnt = uap->iovcnt;
+       auio.uio_iovcnt = SCARG(uap, iovcnt);
        auio.uio_rw = UIO_WRITE;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_procp = p;
        auio.uio_rw = UIO_WRITE;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_procp = p;
-       if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
+       if (error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen))
                goto done;
        auio.uio_resid = 0;
                goto done;
        auio.uio_resid = 0;
-       for (i = 0; i < uap->iovcnt; i++) {
-               if (iov->iov_len < 0) {
+       for (i = 0; i < SCARG(uap, iovcnt); i++) {
+               if (auio.uio_resid + iov->iov_len < auio.uio_resid) {
                        error = EINVAL;
                        goto done;
                }
                auio.uio_resid += iov->iov_len;
                        error = EINVAL;
                        goto done;
                }
                auio.uio_resid += iov->iov_len;
-               if (auio.uio_resid < 0) {
-                       error = EINVAL;
-                       goto done;
-               }
                iov++;
        }
 #ifdef KTRACE
                iov++;
        }
 #ifdef KTRACE
@@ -308,7 +309,7 @@ writev(p, uap, retval)
 #ifdef KTRACE
        if (ktriov != NULL) {
                if (error == 0)
 #ifdef KTRACE
        if (ktriov != NULL) {
                if (error == 0)
-                       ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
+                       ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
                                ktriov, cnt, error);
                FREE(ktriov, M_TEMP);
        }
                                ktriov, cnt, error);
                FREE(ktriov, M_TEMP);
        }
@@ -323,65 +324,67 @@ done:
 /*
  * Ioctl system call
  */
 /*
  * Ioctl system call
  */
-struct ioctl_args {
-       int     fdes;
-       int     cmd;
-       caddr_t cmarg;
-};
 /* ARGSUSED */
 /* ARGSUSED */
+int
 ioctl(p, uap, retval)
        struct proc *p;
 ioctl(p, uap, retval)
        struct proc *p;
-       register struct ioctl_args *uap;
-       int *retval;
+       register struct ioctl_args /* {
+               syscallarg(int) fd;
+               syscallarg(u_long) com;
+               syscallarg(caddr_t) data;
+       } */ *uap;
+       register_t *retval;
 {
        register struct file *fp;
 {
        register struct file *fp;
-       register struct filedesc *fdp = p->p_fd;
-       register int com, error;
+       register struct filedesc *fdp;
+       register u_long com;
+       register int error;
        register u_int size;
        register u_int size;
-       caddr_t memp = 0;
+       caddr_t data, memp;
+       int tmp;
 #define STK_PARAMS     128
        char stkbuf[STK_PARAMS];
 #define STK_PARAMS     128
        char stkbuf[STK_PARAMS];
-       caddr_t data = stkbuf;
-       int tmp;
 
 
-       if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
-           (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
+       fdp = p->p_fd;
+       if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
+           (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
                return (EBADF);
                return (EBADF);
-       if ((fp->f_flag & (FREAD|FWRITE)) == 0)
+
+       if ((fp->f_flag & (FREAD | FWRITE)) == 0)
                return (EBADF);
                return (EBADF);
-       com = uap->cmd;
 
 
-       if (com == FIOCLEX) {
-               fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
+       switch (com = SCARG(uap, com)) {
+       case FIONCLEX:
+               fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE;
                return (0);
                return (0);
-       }
-       if (com == FIONCLEX) {
-               fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
+       case FIOCLEX:
+               fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE;
                return (0);
        }
 
        /*
                return (0);
        }
 
        /*
-        * Interpret high order word to find
-        * amount of data to be copied to/from the
-        * user's address space.
+        * Interpret high order word to find amount of data to be
+        * copied to/from the user's address space.
         */
        size = IOCPARM_LEN(com);
        if (size > IOCPARM_MAX)
                return (ENOTTY);
         */
        size = IOCPARM_LEN(com);
        if (size > IOCPARM_MAX)
                return (ENOTTY);
+       memp = NULL;
        if (size > sizeof (stkbuf)) {
                memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
                data = memp;
        if (size > sizeof (stkbuf)) {
                memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
                data = memp;
-       }
+       } else
+               data = stkbuf;
        if (com&IOC_IN) {
                if (size) {
        if (com&IOC_IN) {
                if (size) {
-                       error = copyin(uap->cmarg, data, (u_int)size);
+                       error = copyin(SCARG(uap, data), data, (u_int)size);
                        if (error) {
                                if (memp)
                                        free(memp, M_IOCTLOPS);
                                return (error);
                        }
                } else
                        if (error) {
                                if (memp)
                                        free(memp, M_IOCTLOPS);
                                return (error);
                        }
                } else
-                       *(caddr_t *)data = uap->cmarg;
+                       *(caddr_t *)data = SCARG(uap, data);
        } else if ((com&IOC_OUT) && size)
                /*
                 * Zero the buffer so the user always
        } else if ((com&IOC_OUT) && size)
                /*
                 * Zero the buffer so the user always
@@ -389,7 +392,7 @@ ioctl(p, uap, retval)
                 */
                bzero(data, size);
        else if (com&IOC_VOID)
                 */
                bzero(data, size);
        else if (com&IOC_VOID)
-               *(caddr_t *)data = uap->cmarg;
+               *(caddr_t *)data = SCARG(uap, data);
 
        switch (com) {
 
 
        switch (com) {
 
@@ -427,7 +430,7 @@ ioctl(p, uap, retval)
                        tmp = p1->p_pgrp->pg_id;
                }
                error = (*fp->f_ops->fo_ioctl)
                        tmp = p1->p_pgrp->pg_id;
                }
                error = (*fp->f_ops->fo_ioctl)
-                       (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
+                       (fp, TIOCSPGRP, (caddr_t)&tmp, p);
                break;
 
        case FIOGETOWN:
                break;
 
        case FIOGETOWN:
@@ -436,7 +439,7 @@ ioctl(p, uap, retval)
                        *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
                        break;
                }
                        *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
                        break;
                }
-               error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
+               error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
                *(int *)data = -*(int *)data;
                break;
 
                *(int *)data = -*(int *)data;
                break;
 
@@ -447,7 +450,7 @@ ioctl(p, uap, retval)
                 * already set and checked above.
                 */
                if (error == 0 && (com&IOC_OUT) && size)
                 * already set and checked above.
                 */
                if (error == 0 && (com&IOC_OUT) && size)
-                       error = copyout(data, uap->cmarg, (u_int)size);
+                       error = copyout(data, SCARG(uap, data), (u_int)size);
                break;
        }
        if (memp)
                break;
        }
        if (memp)
@@ -460,40 +463,44 @@ int       selwait, nselcoll;
 /*
  * Select system call.
  */
 /*
  * Select system call.
  */
-struct select_args {
-       int     nd;
-       fd_set  *in, *ou, *ex;
-       struct  timeval *tv;
-};
+int
 select(p, uap, retval)
        register struct proc *p;
 select(p, uap, retval)
        register struct proc *p;
-       register struct select_args *uap;
-       int *retval;
+       register struct select_args /* {
+               syscallarg(u_int) nd;
+               syscallarg(fd_set *) in;
+               syscallarg(fd_set *) ou;
+               syscallarg(fd_set *) ex;
+               syscallarg(struct timeval *) tv;
+       } */ *uap;
+       register_t *retval;
 {
        fd_set ibits[3], obits[3];
        struct timeval atv;
 {
        fd_set ibits[3], obits[3];
        struct timeval atv;
-       int s, ncoll, ni, error = 0, timo;
+       int s, ncoll, error, timo = 0;
+       u_int ni;
 
        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 > p->p_fd->fd_nfiles)
-               uap->nd = p->p_fd->fd_nfiles;   /* forgiving; slightly wrong */
-       ni = howmany(uap->nd, NFDBITS);
+       if (SCARG(uap, nd) > FD_SETSIZE)
+               return (EINVAL);
+       if (SCARG(uap, nd) > p->p_fd->fd_nfiles) {
+               /* forgiving; slightly wrong */
+               SCARG(uap, nd) = p->p_fd->fd_nfiles;
+       }
+       ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask);
 
 #define        getbits(name, x) \
 
 #define        getbits(name, x) \
-       if (uap->name) { \
-               error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
-                   (unsigned)(ni * sizeof(fd_mask))); \
-               if (error) \
-                       goto done; \
-       }
+       if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, name), \
+           (caddr_t)&ibits[x], ni))) \
+               goto done;
        getbits(in, 0);
        getbits(ou, 1);
        getbits(ex, 2);
 #undef getbits
 
        getbits(in, 0);
        getbits(ou, 1);
        getbits(ex, 2);
 #undef getbits
 
-       if (uap->tv) {
-               error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
+       if (SCARG(uap, tv)) {
+               error = copyin((caddr_t)SCARG(uap, tv), (caddr_t)&atv,
                        sizeof (atv));
                if (error)
                        goto done;
                        sizeof (atv));
                if (error)
                        goto done;
@@ -503,52 +510,54 @@ select(p, uap, retval)
                }
                s = splclock();
                timevaladd(&atv, (struct timeval *)&time);
                }
                s = splclock();
                timevaladd(&atv, (struct timeval *)&time);
-               timo = hzto(&atv);
-               /*
-                * Avoid inadvertently sleeping forever.
-                */
-               if (timo == 0)
-                       timo = 1;
                splx(s);
                splx(s);
-       } else
-               timo = 0;
+       }
 retry:
        ncoll = nselcoll;
 retry:
        ncoll = nselcoll;
-       p->p_flag |= SSEL;
-       error = selscan(p, ibits, obits, uap->nd, retval);
+       p->p_flag |= P_SELECT;
+       error = selscan(p, ibits, obits, SCARG(uap, nd), retval);
        if (error || *retval)
                goto done;
        s = splhigh();
        if (error || *retval)
                goto done;
        s = splhigh();
-       /* this should be timercmp(&time, &atv, >=) */
-       if (uap->tv && (time.tv_sec > atv.tv_sec ||
-           time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
-               splx(s);
-               goto done;
+       if (SCARG(uap, tv)) {
+               if (timercmp(&time, &atv, >=)) {
+                       splx(s);
+                       goto done;
+               }
+               /*
+                * If poll wait was tiny, this could be zero; we will
+                * have to round it up to avoid sleeping forever.  If
+                * we retry below, the timercmp above will get us out.
+                * Note that if wait was 0, the timercmp will prevent
+                * us from getting here the first time.
+                */
+               timo = hzto(&atv);
+               if (timo == 0)
+                       timo = 1;
        }
        }
-       if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
+       if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
                splx(s);
                goto retry;
        }
                splx(s);
                goto retry;
        }
-       p->p_flag &= ~SSEL;
+       p->p_flag &= ~P_SELECT;
        error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
        splx(s);
        if (error == 0)
                goto retry;
 done:
        error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
        splx(s);
        if (error == 0)
                goto retry;
 done:
-       p->p_flag &= ~SSEL;
+       p->p_flag &= ~P_SELECT;
        /* select is not restarted after signals... */
        if (error == ERESTART)
                error = EINTR;
        if (error == EWOULDBLOCK)
                error = 0;
 #define        putbits(name, x) \
        /* select is not restarted after signals... */
        if (error == ERESTART)
                error = EINTR;
        if (error == EWOULDBLOCK)
                error = 0;
 #define        putbits(name, x) \
-       if (uap->name) { \
-               int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
-                   (unsigned)(ni * sizeof(fd_mask))); \
-               if (error2) \
-                       error = error2; \
-       }
+       if (SCARG(uap, name) && (error2 = copyout((caddr_t)&obits[x], \
+           (caddr_t)SCARG(uap, name), ni))) \
+               error = error2;
        if (error == 0) {
        if (error == 0) {
+               int error2;
+
                putbits(in, 0);
                putbits(ou, 1);
                putbits(ex, 2);
                putbits(in, 0);
                putbits(ou, 1);
                putbits(ex, 2);
@@ -557,10 +566,12 @@ done:
        return (error);
 }
 
        return (error);
 }
 
+int
 selscan(p, ibits, obits, nfd, retval)
        struct proc *p;
        fd_set *ibits, *obits;
 selscan(p, ibits, obits, nfd, retval)
        struct proc *p;
        fd_set *ibits, *obits;
-       int nfd, *retval;
+       int nfd;
+       register_t *retval;
 {
        register struct filedesc *fdp = p->p_fd;
        register int msk, i, j, fd;
 {
        register struct filedesc *fdp = p->p_fd;
        register int msk, i, j, fd;
@@ -589,6 +600,7 @@ selscan(p, ibits, obits, nfd, retval)
 }
 
 /*ARGSUSED*/
 }
 
 /*ARGSUSED*/
+int
 seltrue(dev, flag, p)
        dev_t dev;
        int flag;
 seltrue(dev, flag, p)
        dev_t dev;
        int flag;
@@ -642,11 +654,11 @@ selwakeup(sip)
                s = splhigh();
                if (p->p_wchan == (caddr_t)&selwait) {
                        if (p->p_stat == SSLEEP)
                s = splhigh();
                if (p->p_wchan == (caddr_t)&selwait) {
                        if (p->p_stat == SSLEEP)
-                               setrun(p);
+                               setrunnable(p);
                        else
                                unsleep(p);
                        else
                                unsleep(p);
-               } else if (p->p_flag & SSEL)
-                       p->p_flag &= ~SSEL;
+               } else if (p->p_flag & P_SELECT)
+                       p->p_flag &= ~P_SELECT;
                splx(s);
        }
 }
                splx(s);
        }
 }