BSD 4_4_Lite2 release
[unix-history] / usr / src / sys / kern / uipc_socket.c
index 391eb50..a9c5453 100644 (file)
@@ -2,9 +2,35 @@
  * Copyright (c) 1982, 1986, 1988, 1990, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
  * Copyright (c) 1982, 1986, 1988, 1990, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)uipc_socket.c       8.5 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)uipc_socket.c       8.6 (Berkeley) 5/2/95
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -152,7 +178,7 @@ soclose(so)
                                goto drop;
                        while (so->so_state & SS_ISCONNECTED)
                                if (error = tsleep((caddr_t)&so->so_timeo,
                                goto drop;
                        while (so->so_state & SS_ISCONNECTED)
                                if (error = tsleep((caddr_t)&so->so_timeo,
-                                   PSOCK | PCATCH, netcls, so->so_linger))
+                                   PSOCK | PCATCH, netcls, so->so_linger * hz))
                                        break;
                }
        }
                                        break;
                }
        }
@@ -528,10 +554,8 @@ restart:
        if (m == 0 || ((flags & MSG_DONTWAIT) == 0 &&
            so->so_rcv.sb_cc < uio->uio_resid) &&
            (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
        if (m == 0 || ((flags & MSG_DONTWAIT) == 0 &&
            so->so_rcv.sb_cc < uio->uio_resid) &&
            (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
-           ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)))
-               if (m && (m->m_nextpkt || (m->m_flags & M_EOR) ||
-                         m->m_type == MT_OOBDATA || m->m_type == MT_CONTROL))
-                       break;
+           ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
+           m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0) {
 #ifdef DIAGNOSTIC
                if (m == 0 && so->so_rcv.sb_cc)
                        panic("receive 1");
 #ifdef DIAGNOSTIC
                if (m == 0 && so->so_rcv.sb_cc)
                        panic("receive 1");
@@ -550,6 +574,11 @@ restart:
                        else
                                goto release;
                }
                        else
                                goto release;
                }
+               for (; m; m = m->m_next)
+                       if (m->m_type == MT_OOBDATA  || (m->m_flags & M_EOR)) {
+                               m = so->so_rcv.sb_mb;
+                               goto dontblock;
+                       }
                if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
                    (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
                        error = ENOTCONN;
                if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
                    (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
                        error = ENOTCONN;
@@ -568,10 +597,10 @@ restart:
                        return (error);
                goto restart;
        }
                        return (error);
                goto restart;
        }
+dontblock:
        if (uio->uio_procp)
                uio->uio_procp->p_stats->p_ru.ru_msgrcv++;
        nextrecord = m->m_nextpkt;
        if (uio->uio_procp)
                uio->uio_procp->p_stats->p_ru.ru_msgrcv++;
        nextrecord = m->m_nextpkt;
-       record_eor = m->m_flags & M_EOR;
        if (pr->pr_flags & PR_ADDR) {
 #ifdef DIAGNOSTIC
                if (m->m_type != MT_SONAME)
        if (pr->pr_flags & PR_ADDR) {
 #ifdef DIAGNOSTIC
                if (m->m_type != MT_SONAME)
@@ -661,6 +690,8 @@ restart:
                } else
                        uio->uio_resid -= len;
                if (len == m->m_len - moff) {
                } else
                        uio->uio_resid -= len;
                if (len == m->m_len - moff) {
+                       if (m->m_flags & M_EOR)
+                               flags |= MSG_EOR;
                        if (flags & MSG_PEEK) {
                                m = m->m_next;
                                moff = 0;
                        if (flags & MSG_PEEK) {
                                m = m->m_next;
                                moff = 0;
@@ -703,10 +734,8 @@ restart:
                                        break;
                        }
                }
                                        break;
                        }
                }
-               if (m == 0 && record_eor) {
-                       flags |= record_eor;
+               if (flags & MSG_EOR)
                        break;
                        break;
-               }
                /*
                 * If the MSG_WAITALL flag is set (for non-atomic socket),
                 * we must not quit until "uio->uio_resid == 0" or an error
                /*
                 * If the MSG_WAITALL flag is set (for non-atomic socket),
                 * we must not quit until "uio->uio_resid == 0" or an error
@@ -715,7 +744,7 @@ restart:
                 * Keep sockbuf locked against other readers.
                 */
                while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
                 * Keep sockbuf locked against other readers.
                 */
                while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
-                  !(flags & MSG_OOB) && !sosendallatonce(so)) {
+                   !sosendallatonce(so) && !nextrecord) {
                        if (so->so_error || so->so_state & SS_CANTRCVMORE)
                                break;
                        error = sbwait(&so->so_rcv);
                        if (so->so_error || so->so_state & SS_CANTRCVMORE)
                                break;
                        error = sbwait(&so->so_rcv);
@@ -724,10 +753,8 @@ restart:
                                splx(s);
                                return (0);
                        }
                                splx(s);
                                return (0);
                        }
-                       if (m = so->so_rcv.sb_mb) {
+                       if (m = so->so_rcv.sb_mb)
                                nextrecord = m->m_nextpkt;
                                nextrecord = m->m_nextpkt;
-                               record_eor |= m->m_flags & M_EOR;
-                       }
                }
        }
 
                }
        }