uipc.p1 - part1 of part5

Bradley Smith bes at holin.ATT.COM
Sun Aug 13 02:35:25 AEST 1989


: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
if test -f 'src'
then	rm 'src'
fi
if test -d 'src'
then	:
else	echo 'Making     src/'
	mkdir 'src'
fi
chmod 'u=rwx,g=rx,o=rx' 'src'
echo 'Extracting src/socket1.c'
sed 's/^X//' > src/socket1.c << '+ END-OF-FILE src/socket1.c'
X#ifndef LINT
Xstatic char * sccsdef = "@(#)socket1.c	1.1	(Alex Crain) 6/20/89";
X#endif
X
X/*
X *  socket.c - high level socket routines
X *
X *  Written by Alex Crain.
X *
X *  This file is based in the Berkeley file uipc_socket.c,
X *  but is *not* guarenteed to be in any way compatable. It is
X *  close enough to the Berkeley code that the following applies...
X *
X *  Copyright (c) 1982, 1986, 1988 Regents of the University of California.
X *  All rights reserved.
X * 
X *  Redistribution and use in source and binary forms are permitted
X *  provided that this notice is preserved and that due credit is given
X *  to the University of California at Berkeley. The name of the University
X *  may not be used to endorse or promote products derived from this
X *  software without specific prior written permission. This software
X *  is provided "as is" without express or implied warranty.
X *
X */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/systm.h>
X#include <sys/user.h>
X#include <sys/proc.h>
X#include <sys/file.h>
X#include <sys/var.h>
X#include <sys/errno.h>
X#include <uipc/mbuf.h>
X#include <uipc/socket.h>
X#include <uipc/socketvar.h>
X#include <uipc/domain.h>
X#include <uipc/protosw.h>
X#include <uipc/fproto.h>
X
X
Xint
Xsocreate (domain, sop, type, proto)
X  int domain;
X  struct socket ** sop;
X  int type, proto;
X{
X   register struct protosw * prp;
X   struct socket * so;
X   struct mbuf * m;
X   int error = 0;
X   
X   if (proto)
X       prp = pffindproto (domain, proto, type);
X   else
X       prp = pffindtype (domain, type);
X   
X   if (prp == 0)
X       return EPROTONOSUPPORT;
X
X   if (prp->pr_type != type)
X       return EPROTOTYPE;
X
X   m = m_getclr (M_WAIT, MT_SOCKET);
X   so = mtod (m, struct socket *);
X   
X   so->so_options = 0;
X   so->so_state = (suser () ? SS_PRIV : 0);
X   so->so_type = type;
X   so->so_proto = prp;
X
X   if (error = (* prp->pr_usrreq) (so, PRU_ATTACH, (struct mbuf *) 0,
X			       (struct mbuf *) proto, (struct mbuf *) 0))
X    {
X       so->so_state |= SS_NOFDREF;
X       sofree(so);
X       return error;
X    }
X   * sop = so;
X   return 0;
X}
X
Xint
Xsobind (so, nam)
X  struct socket * so;
X  struct mbuf * nam;
X{
X   int s = splnet ();
X   int error = (* so->so_proto->pr_usrreq) (so, PRU_BIND, 
X		(struct mbuf *) 0, nam, (struct mbuf *) 0);
X
X   splx (s);
X   return error;
X}
X
Xint
Xsolisten (so, backlog)
X  struct socket * so;
X  int backlog;
X{
X   int s = splnet ();
X   int error;
X   if (error = (* so->so_proto->pr_usrreq) (so, PRU_LISTEN,
X		    (struct mbuf *) 0, (struct mbuf *) 0, (struct mbuf *) 0))
X       goto bad;
X   if (so->so_q == 0)
X    {
X       so->so_q = so;
X       so->so_q0 = so;
X       so->so_options |= SO_ACCEPTCONN;
X    }
X
X   if (backlog < 0)
X       backlog = 0;
X   so->so_qlimit = MIN (backlog, SOMAXCONN);
X bad:
X   splx (s);
X   return error;
X}    
X
Xvoid   
Xsofree (so)
X  struct socket * so;
X{
X   if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
X       return;
X   if (so->so_head)
X    {
X       if (! soqremque (so, 0) && ! soqremque (so, 1))
X	   panic ("sofree dq");
X       so->so_head = 0;
X    }
X   sbrelease (&so->so_snd);
X   sorflush (so);
X   (void) m_free (dtom (so));
X}
X
Xint
Xsoclose (so)
X  struct socket * so;
X{
X   int s = splnet ();
X   int error = 0;
X
X   if (so->so_options & SO_ACCEPTCONN)
X    {
X       while (so->so_q0 != so)
X	   (void) soabort (so->so_q0);
X       while (so->so_q != so)
X	   (void) soabort (so->so_q);
X    }
X   if (so->so_pcb == 0)
X       goto discard;
X   if (so->so_state & SS_ISCONNECTED)
X    {
X       if ((so->so_state & SS_ISDISCONNECTING) == 0)
X	   if (error = sodisconnect (so))
X	       goto drop;
X       if (so->so_options & SO_LINGER)
X	{
X	   if ((so->so_state & SS_ISDISCONNECTING) &&
X	       (so->so_state & SS_NBIO))
X	       goto drop;
X	   while (so->so_state & SS_ISCONNECTED)
X	       (void) sleep ((caddr_t) &so->so_timeo, PZERO + 1);
X	}
X    }
X
X drop:
X   if (so->so_pcb)
X    {
X       int error2 = (* so->so_proto->pr_usrreq) (so, PRU_DETACH,
X		      (struct mbuf *) 0, (struct mbuf *) 0, (struct mbuf *) 0);
X       if (error == 0)
X	   error = error2;
X    }
X
X discard:
X   if (so->so_state & SS_NOFDREF)
X       panic ("soclose: NODEREF");
X   so->so_state |= SS_NOFDREF;
X   sofree (so);
X   splx (s);
X   return error;
X}
X
Xint
Xsoabort (so)
X  struct socket * so;
X{
X   return (* so->so_proto->pr_usrreq) (so, PRU_ABORT,
X		(struct mbuf *) 0, (struct mbuf *) 0, (struct mbuf *) 0);
X}
X
Xint
Xsoaccept (so, nam)
X  struct socket * so;
X  struct mbuf * nam;
X{
X   int s = splnet ();
X   int error;
X
X   if ((so->so_state & SS_NOFDREF) == 0)
X       panic ("soaccept: !NOFDREF");
X   so->so_state &= ~SS_NOFDREF;
X   error = (* so->so_proto->pr_usrreq) (so, PRU_ACCEPT,
X		(struct mbuf *) 0, nam, (struct mbuf *) 0);
X   splx (s);
X   return (error);
X}
X
Xint
Xsoconnect (so, nam)
X  struct socket * so;
X  struct mbuf * nam;
X{
X   int s;
X   int error;
X
X   if (so->so_options & SO_ACCEPTCONN)
X       return EOPNOTSUPP;
X   s = splnet ();
X   if (so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING) &&
X       ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
X	(error = sodisconnect (so))))
X       error = EISCONN;
X   else
X       error = (* so->so_proto->pr_usrreq) (so, PRU_CONNECT,
X		(struct mbuf *) 0, nam, (struct mbuf *) 0);
X   splx (s);
X   return error;
X}
X
Xint
Xsoconnect2 (so1, so2)
X  struct socket * so1, * so2;
X{
X   int s = splnet ();
X   int error = (* so1->so_proto->pr_usrreq) (so1, PRU_CONNECT2,
X		(struct mbuf *) 0, (struct mbuf *) so2, (struct mbuf *) 0);
X   splx (s);
X   return error;
X}
X
Xint
Xsodisconnect (so)
X  struct socket * so;
X{
X   int s = splnet ();
X   int error;
X
X   if ((so->so_state & SS_ISCONNECTED) == 0)
X    {
X       error = ENOTCONN;
X       goto bad;
X    }
X   if (so->so_state & SS_ISDISCONNECTING)
X    {
X       error = EALREADY;
X       goto bad;
X    }
X   error = (* so->so_proto->pr_usrreq) (so, PRU_DISCONNECT,
X		(struct mbuf *) 0, (struct mbuf *) 0, (struct mbuf *) 0);
X bad:
X   splx (s);
X   return error;
X}
X
Xint
Xsosend (so, nam, flags, rights)
X  struct socket * so;
X  struct mbuf * nam;
X  int flags;
X  struct mbuf * rights;
X{
X   int space, s, rlen = 0, dontroute;
X   int len, error = 0, first = 1;
X   struct mbuf ** mb, * top = 0, * m;
X
X   /*
X    *  barf if we want to send one big chunk and don't have the space.
X    */
X   if (sendallatonce (so) && u.u_count > so->so_snd.sb_hiwat)
X       return (EMSGSIZE);
X
X   dontroute = (flags & MSG_DONTROUTE) && 
X	       (so->so_options & SO_DONTROUTE) == 0 &&
X	       (so->so_proto->pr_flags & PR_ATOMIC);
X
X   if (rights)
X       rlen = rights->m_len;
X    
X#define snderr(errno)	{ error = errno; splx (s); goto release; }
X
X restart:
X   sblock (&so->so_snd);
X   
X   do {
X       s = splnet ();
X
X       /* check out our basic requirements. */
X
X       if (so->so_state & SS_CANTSENDMORE)
X	   snderr (EPIPE);
X
X       if (so->so_error)
X	{
X	   error = so->so_error;
X	   so->so_error = 0;
X	   splx (s);
X	   goto release;
X	}
X       
X       if ((so->so_state & SS_ISCONNECTED) == 0)
X	{
X	   if (so->so_proto->pr_flags & PR_CONNREQUIRED)
X	       snderr (ENOTCONN);
X	   if (nam == 0)
X	       snderr (EDESTADDRREQ);
X	}
X       if (flags & MSG_OOB)
X	   space = 1024;
X       else
X	{
X	   space = sbspace (&so->so_snd);
X
X	   /*
X	    *  If we need more room, wait for it.
X	    */
X	   if (space <= rlen || 
X	       sendallatonce (so) && space < u.u_count + rlen)
X	    {
X	       if (so->so_state & SS_NBIO)
X		{
X		   if (first)
X		       error = EWOULDBLOCK;
X		   splx (s);
X		   goto release;
X		}
X	       sbunlock (&so->so_snd);
X	       sbwait (&so->so_snd);
X	       splx (s);
X	       goto restart;
X	    }
X	}
X
X       splx (s);
X       
X
X       /*
X	*  We have the room, we've done sanity checks.
X	*  Now make an mbuf chain out of our data, waiting if necessarry.
X	*/
X       mb = ⊤
X       space -= rlen;
X       while (space > 0 && u.u_count)
X	{
X	   MGET (m, M_WAIT, MT_DATA);
X	   len = MIN (MIN (MLEN, u.u_count), space);
X	   space -= len;
X	   iomove (mtod (m, caddr_t), len, IO_WRITE);
X	   m->m_len = len;
X	   * mb = m;
X	   if (error = u.u_error)
X	       goto release;
X	   mb = &m->m_next;
X#ifdef DEBUG
X	   dump_mbuf(m,"sosendit");
X#endif
X	}
X       if (dontroute)
X	   so->so_options |= SO_DONTROUTE;
X
X       /*
X	*  write mbuf to socket.
X	*/
X       s = splnet ();
X       error = (* so->so_proto->pr_usrreq) (so, 
X			  (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
X			  top, (caddr_t) nam, rights);
X       splx (s);
X       if (dontroute)
X	   so->so_options &= ~SO_DONTROUTE;
X       rights = top = (struct mbuf *) 0;
X       rlen = first = 0;
X    } while (error == 0 && u.u_count);
X
X release:
X   sbunlock (&so->so_snd);
X
X   if(select_sleep) {
X      select_sleep = 0;
X      wakeup((caddr_t) &select_sleep_addr);
X   }
X
X   if (top)
X       m_freem (top);
X   if (error == EPIPE)
X       psignal (u.u_procp, SIGPIPE);
X   return error;
X}
X
Xint
Xsoreceive (so, nam, flags, rights)
X  struct socket * so;
X  struct mbuf ** nam;
X  int flags;
X  struct mbuf ** rights;
X{
X   struct mbuf * m, * nextrecord;
X   int len, error = 0, s, moff, offset;
X   struct protosw * pr = so->so_proto;
X
X   if (rights)
X       * rights = (struct mbuf *) 0; /* if we have a rights, zero it */
X   if (nam)
X       * nam = (struct mbuf *) 0; /* zero from buffer address */
X   if (flags & MSG_OOB)
X    {
X       m = m_get (M_WAIT, MT_DATA);
X       if (error = (* pr->pr_usrreq) (so, PRU_RCVOOB, m,
X				      (struct mbuf *) (flags & MSG_PEEK), 
X				      (struct mbuf *) 0))
X	   goto bad;
X       do {
X	   len = MIN (u.u_count, m->m_len);
X	   iomove (mtod (m, caddr_t), len, IO_READ);
X	   m = m_free (m);
X	} while (u.u_count && (error = u.u_error) == 0 && m);
X    bad:
X       if (m)
X	   m_freem (m);
X       return error;
X    }
X	   
X#ifdef DEBUG
X   dump_mbuf (dtom (so),"sorecieve");
X#endif
X restart:
X   sblock (&so->so_rcv);
X   s = splnet ();
X
X   if (so->so_rcv.sb_cc == 0) /* if there is no chars in buffer */
X    {
X       if (so->so_error) /* if there is an error affecting connection */
X	{
X	   error = so->so_error;
X	   so->so_error = 0;
X	   goto release;
X	}
X/*       if ((so->so_state & SS_ISCONNECTED) == 0 &&
X	   (pr->pr_flags & PR_CONNREQUIRED))
X	{
X	   error = ENOTCONN;
X	   goto release;
X	} */
X       if (so->so_state & SS_CANTRCVMORE || u.u_count == 0)
X	   goto release;
X       if (so->so_state & SS_NBIO) /* if nonblocking return EWOULDBLOCK */
X	{
X	   error = EWOULDBLOCK;
X	   goto release;
X	}
X       sbunlock (&so->so_rcv);
X       sbwait (&so->so_rcv);
X       splx (s);
X       goto restart;
X    }
X
X   /* this checks the mbuf chain to see if there is data */
X   if ((m = so->so_rcv.sb_mb) == (struct mbuf *) 0)
X       panic ("receive 1");
X   nextrecord = m->m_act;
X   if (pr->pr_flags & PR_ADDR)
X    {
X       if (m->m_type != MT_SONAME)
X	   panic ("receive 1a");
X       if (flags & MSG_PEEK)
X	{
X	   if (nam)
X	       * nam = m_copy (m, 0, m->m_len);
X           m = m->m_next;
X	}
X       else
X	{
X	   sbfree (&so->so_rcv, m);
X	   if (nam)
X	    {
X	       * nam = m;
X	       m = m->m_next;
X	       (* nam)->m_next = (struct mbuf *) 0;
X	       so->so_rcv.sb_mb = m;
X	    }
X	   else
X	    {
X	       MFREE (m, so->so_rcv.sb_mb);
X	       m = so->so_rcv.sb_mb;
X	    }
X	   if (m)
X	       m->m_act = nextrecord;
X	}
X    }
X   if (m && m->m_type == MT_RIGHTS)
X    {
X       if ((pr->pr_flags & PR_RIGHTS) == 0)
X	   panic ("receive 2");
X       if (flags & MSG_PEEK)
X	{
X	   if (rights)
X	       * rights = m_copy (m, 0, m->m_len);
X	   m = m->m_next;
X	} 
X       else
X	{
X	   sbfree (&so->so_rcv, m);
X	   if (rights)
X	    {
X	       * rights = m;
X	       so->so_rcv.sb_mb = m->m_next;
X	       m->m_next = (struct mbuf *) 0;
X	       m = so->so_rcv.sb_mb;
X	    }
X	   else
X	    {
X	       MFREE (m, so->so_rcv.sb_mb);
X	       m = so->so_rcv.sb_mb;
X	    }
X	   if (m)
X	       m->m_act = nextrecord;
X	}
X    }
X   moff = 0;
X   offset = 0;
X   while (m && u.u_count != 0 && error == 0)
X    {
X       if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
X	   panic ("receive 3");
X       len = u.u_count;
X       so->so_state &= ~SS_RCVATMARK;
X       if (so->so_oobmark && len > so->so_oobmark - offset)
X	   len = so->so_oobmark - offset;
X       if (len > m->m_len - moff)
X	   len = m->m_len - moff;
X       splx (s);
X
X       iomove (mtod (m, caddr_t) + moff, (int) len, IO_READ);
X       error = u.u_error;
X
X       s = splnet ();
X       if (len == m->m_len - moff)
X	{
X	   if (flags & MSG_PEEK)
X	    {
X	       m = m->m_next;
X	       moff = 0;
X	    }
X	   else
X	    {
X	       nextrecord = m->m_act;
X	       sbfree (&so->so_rcv, m);
X	       MFREE (m, so->so_rcv.sb_mb);
X	       if (m = so->so_rcv.sb_mb)
X		   m->m_act = nextrecord;
X	    }
X	}
X       else
X	{
X	   if (flags & MSG_PEEK)
X	       moff += len;
X	   else
X	    {
X	       m->m_off += len;
X	       m->m_len -= len;
X	       so->so_rcv.sb_cc -= len;
X	    }
X	}
X       if (so->so_oobmark)
X	{
X	   if ((flags & MSG_PEEK) == 0)
X	    {
X	       so->so_oobmark -= len;
X	       if (so->so_oobmark == 0)
X		{
X		   so->so_state |= SS_RCVATMARK;
X		   break;
X		}
X	    }
X	   else
X	       offset += len;
X	}
X    }
X   if ((flags & MSG_PEEK) == 0)
X    {
X       if (m == 0)
X	   so->so_rcv.sb_mb = nextrecord;
X       else if (pr->pr_flags & PR_ATOMIC)
X	   (void) sbdroprecord (&so->so_rcv);
X       if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
X	   (* pr->pr_usrreq) (so, PRU_RCVD, (struct mbuf *) 0,
X			      (struct mbuf *) 0, (struct mbuf *) 0);
X       if (error == 0 && rights && * rights &&
X	   pr->pr_domain->dom_externalize)
X	   error = (* pr->pr_domain->dom_externalize) (* rights);
X    }
X
X release:
X   sbunlock (&so->so_rcv);
X   splx (s);
X   return error;
X}
X
Xvoid	       
Xsorflush (so)
X  struct socket * so;
X{
X   struct sockbuf * sb = &so->so_rcv;
X   struct protosw * pr = so->so_proto;
X   int s;
X   struct sockbuf asb;
X
X   sblock (sb);
X   s = splimp ();
X   socantrcvmore (so);
X   sbunlock (sb);
X
X   if(select_sleep) {
X	select_sleep = 0;
X	wakeup((caddr_t) &select_sleep_addr);
X   }
X
X   asb = * sb;
X   bzero ((caddr_t) sb, sizeof (* sb));
X   splx (s);
X   if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
X     (* pr->pr_domain->dom_dispose) (asb.sb_mb);
X   sbrelease (&asb);
X}
X
Xint
Xsosetopt (so, level, optname, m0)
X  struct socket * so;
X  int level, optname;
X  struct mbuf * m0;
X{
X   int error = 0;
X   struct mbuf * m = m0;
X   
X   if (level != SOL_SOCKET)
X    {
X       if (so->so_proto && so->so_proto->pr_ctloutput)
X	   return (* so->so_proto->pr_ctloutput) 
X	             (PRCO_SETOPT, so, level, optname, &m0);
X       error = ENOPROTOOPT;
X    }
X   else
X    {
X       switch (optname)
X	{
X	case SO_LINGER:
X	   if (m == NULL || m->m_len != sizeof (struct linger))
X	    {
X	       error = EINVAL;
X	       goto bad;
X	    }
X	   so->so_linger = mtod (m, struct linger *)->l_linger;
X	   /* fall through ... */
X
X	case SO_DEBUG:
X	case SO_KEEPALIVE:
X	case SO_DONTROUTE:
X	case SO_USELOOPBACK:
X	case SO_BROADCAST:
X	case SO_REUSEADDR:
X	case SO_OOBINLINE:
X	   if (m == (struct mbuf *) 0 || m->m_len < sizeof (int))
X	    {
X	       error = EINVAL;
X	       goto bad;
X	    }
X	   if (* mtod (m, int *))
X	       so->so_options |= optname;
X	   else
X	       so->so_options &= ~optname;
X	   break;
X
X	case SO_SNDBUF:
X	case SO_RCVBUF:
X	case SO_SNDLOWAT:
X	case SO_RCVLOWAT:
X	case SO_SNDTIMEO:
X	case SO_RCVTIMEO:
X
X	   if (m == (struct mbuf *) 0 || m->m_len < sizeof (int))
X	    {
X	       error = EINVAL;
X	       goto bad;
X	    }
X	   switch (optname)
X	    {
X	    case SO_SNDBUF:
X	       if (sbreserve (&so->so_rcv, * mtod (m, int *)) == 0)
X		{
X		   error = ENOBUFS;
X	           goto bad;
X		}
X	       break;
X
X	    case SO_RCVBUF:
X	       if (sbreserve (&so->so_rcv, * mtod (m, int *)) == 0)
X		{
X		   error = ENOBUFS;
X	           goto bad;
X		}
X	       break;
X
X	    case SO_SNDLOWAT:
X	       so->so_snd.sb_lowat = * mtod (m, int *);
X	       break;
X
X	    case SO_RCVLOWAT:
X	       so->so_rcv.sb_lowat = * mtod (m, int *);
X	       break;
X
X	    case SO_SNDTIMEO:
X	       so->so_snd.sb_timeo = * mtod (m, int *);
X	       break;
X
X	    case SO_RCVTIMEO:
X	       so->so_rcv.sb_timeo = * mtod (m, int *);
X	       break;
X	    }
X	   break;
X	   
X	default:
X	   error = ENOPROTOOPT;
X	   break;
X	}
X    }
X bad:
X   if (m)
X       (void) m_free (m);
X   return error;
X}
X
Xint
Xsogetopt (so, level, optname, mp)
X  struct socket * so;
X  int level, optname;
X  struct mbuf ** mp;
X{
X   struct mbuf * m;
X   
X   if (level != SOL_SOCKET)
X    {
X       if (so->so_proto && so->so_proto->pr_ctloutput)
X	   return (* so->so_proto->pr_ctloutput)
X			(PRCO_GETOPT, so, level, optname, mp);
X       else
X	   return ENOPROTOOPT;
X    }
X   else
X    {
X       m = m_get (M_WAIT, MT_SOOPTS);
X       m->m_len = sizeof (int);
X       
X       switch (optname)
X	{
X	case SO_LINGER:
X	   m->m_len = sizeof (struct linger);
X	   mtod (m, struct linger *)->l_onoff = so->so_options & SO_LINGER;
X	   mtod (m, struct linger *)->l_linger = so->so_linger;
X	   break;
X
X	    
X	case SO_DEBUG:
X	case SO_KEEPALIVE:
X	case SO_DONTROUTE:
X	case SO_USELOOPBACK:
X	case SO_BROADCAST:
X	case SO_REUSEADDR:
X	case SO_OOBINLINE:
X	   * mtod (m, int *) = so->so_options & optname;
X	   break;
X
X	case SO_TYPE:
X	   * mtod (m, int *) = so->so_type;
X	   break;
X
X	case SO_ERROR:
X	   * mtod (m, int *) = so->so_error;
X	   break;
X
X	case SO_SNDBUF:
X	   * mtod (m, int *) = so->so_snd.sb_hiwat;
X	   break;
X
X	case SO_RCVBUF:
X	   * mtod (m, int *) = so->so_rcv.sb_hiwat;
X	   break;
X
X	case SO_SNDLOWAT:
X	   * mtod (m, int *) = so->so_snd.sb_lowat;
X	   break;
X
X	case SO_RCVLOWAT:
X	   * mtod (m, int *) = so->so_rcv.sb_lowat;
X	   break;
X
X	case SO_SNDTIMEO:
X	   * mtod (m, int *) = so->so_snd.sb_timeo;
X	   break;
X
X	case SO_RCVTIMEO:
X	   * mtod (m, int *) = so->so_rcv.sb_timeo;
X	   break;
X
X	default:
X	   (void) m_free (m);
X	   return ENOPROTOOPT;
X	}
X       * mp = m;
X       return 0;
X    }
X}
X
Xvoid
Xsohasoutofband (so)
X  struct socket * so;
X{
X   struct proc * p;
X
X   if (so->so_pgrp < 0)
X       signal (-so->so_pgrp, SIGURG);
X   else if (so->so_pgrp)
X       for (p = proc; p < (struct proc *) v.ve_proc; p = p->p_xlink)
X	   if (p->p_pid == so->so_pgrp)
X	    {
X	       psignal (p, SIGURG);
X	       break;
X	    }
X#ifdef SB_COLL
X   if (so->so_rcv.sb_sel)
X    {
X       selwakeup (so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL);
X       so->so_rcv,sb_sel = 0;
X       so->so_rcv.sb_flags &= ~SB_COLL;
X    }
X#endif
X}
+ END-OF-FILE src/socket1.c
chmod 'u=rw,g=rw,o=rw' 'src/socket1.c'
echo '	-rw-rw-rw-   1 bes      HSJ        18033 Aug 12 12:27 src/socket1.c        (as sent)'
echo '	\c'
/bin/ls -l src/socket1.c
echo 'Extracting src/socket2.c'
sed 's/^X//' > src/socket2.c << '+ END-OF-FILE src/socket2.c'
X#ifndef LINT
Xstatic char * sccsdef = "@(#)socket2.c	1.1	(Alex Crain) 6/20/89";
X#endif
X
X/*
X *  socket2.c - low level socket routines
X *
X *  Written by Alex Crain.
X *
X *  This file is based in the Berkeley file uipc_socket2.c,
X *  but is *not* guarenteed to be in any way compatable. It is
X *  close enough to the Berkeley code that the following applies...
X *
X *  Copyright (c) 1982, 1986, 1988 Regents of the University of California.
X *  All rights reserved.
X * 
X *  Redistribution and use in source and binary forms are permitted
X *  provided that this notice is preserved and that due credit is given
X *  to the University of California at Berkeley. The name of the University
X *  may not be used to endorse or promote products derived from this
X *  software without specific prior written permission. This software
X *  is provided "as is" without express or implied warranty.
X *
X */
X
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/systm.h>
X#include <sys/errno.h>
X#include <sys/proc.h>
X#include <sys/var.h>
X#include <uipc/mbuf.h>
X#include <uipc/socket.h>
X#include <uipc/socketvar.h>
X#include <uipc/protosw.h>
X#include <uipc/domain.h>
X#include <uipc/fproto.h>
X
Xvoid
Xsoisconnecting (so)
X  struct socket * so;
X{
X   so->so_state &= ~(SS_ISCONNECTED | SS_ISDISCONNECTING);
X   so->so_state |= SS_ISCONNECTING;
X   wakeup ((caddr_t) &so->so_timeo);
X}
X
Xvoid
Xsoisconnected (so)
X  struct socket * so;
X{
X   struct socket * head = so->so_head;
X   
X   if (head)
X    {
X       if (soqremque (so, 0) == 0)
X	   panic ("soisconnected");
X       soinsque (head, so, 1);
X       sorwakeup (head);
X       wakeup ((caddr_t) &head->so_timeo);
X    }
X
X   so->so_state &= ~(SS_ISCONNECTING | SS_ISDISCONNECTING);
X   so->so_state |= SS_ISCONNECTED;
X   wakeup ((caddr_t) &so->so_timeo);
X   sorwakeup (so);
X   sowwakeup (so);
X}
X
Xvoid
Xsoisdisconnecting (so)
X  struct socket * so;
X{
X   so->so_state &= ~SS_ISCONNECTING;
X   so->so_state |= (SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE);
X   wakeup ((caddr_t) &so->so_timeo);
X   sorwakeup (so);
X   sowwakeup (so);
X}
X
Xvoid
Xsoisdisconnected (so)
X  struct socket * so;
X{
X   so->so_state &= ~(SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING);
X   so->so_state |= (SS_CANTRCVMORE | SS_CANTSENDMORE);
X   wakeup ((caddr_t) &so->so_timeo);
X   sorwakeup (so);
X   sowwakeup (so);
X}
X
Xstruct socket *
Xsonewconn (head)
X  struct socket * head;
X{
X   struct socket * so;
X   struct mbuf * m;
X
X   if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2)
X       goto bad;
X   if ((m = m_getclr(M_DONTWAIT, MT_SOCKET)) == (struct mbuf *) 0)
X       goto bad;
X   so = mtod (m, struct socket *);
X   so->so_type = head->so_type;
X   so->so_options = head->so_options & ~SO_ACCEPTCONN;
X   so->so_linger = head->so_linger;
X   so->so_state = head->so_state | SS_NOFDREF;
X   so->so_proto = head->so_proto;
X   so->so_timeo = head->so_timeo;
X   so->so_pgrp = head->so_pgrp;
X   soinsque (head, so, 0);
X   if ((* so->so_proto->pr_usrreq) (so, PRU_ATTACH,
X		(struct mbuf *) 0, (struct mbuf *) 0, (struct mbuf *) 0))
X    {
X       (void) soqremque (so, 0);
X       (void) m_free (m);
X       goto bad;
X    }
X   return (so);
X bad:
X   return (struct socket *) 0;
X}
X
Xvoid
Xsoinsque (head, so, q)
X  struct socket * head, * so;
X  int q;
X{
X   so->so_head = head;
X   if (q == 0)
X    {
X       head->so_q0len++;
X       so->so_q0 = head->so_q0;
X       head->so_q0 = so;
X    }
X   else
X    {
X       head->so_qlen++;
X       so->so_q = head->so_q;
X       head->so_q = so;
X    }
X}
X
Xint
Xsoqremque (so, q)
X  struct socket * so;
X  int q;
X{
X   struct socket * head, * prev, * next;
X
X   head = so->so_head;
X   prev = head;
X   for (;;) 
X    {
X       next = q ? prev->so_q : prev->so_q0;
X       if (next == so)
X	   break;
X       if (next == head)
X	   return 0;
X       prev = next;
X    }
X   if (q == 0)
X    {
X       prev->so_q0 = next->so_q0;
X       head->so_q0len--;
X    }
X   else
X    {
X       prev->so_q = next->so_q;
X       head->so_qlen--;
X    } 
X   next->so_q0 = next->so_q = 0;
X   next->so_head = 0;
X   return 1;
X}
X
Xvoid
Xsocantsendmore (so)
X  struct socket * so;
X{
X   so->so_state |= SS_CANTSENDMORE;
X   sowwakeup (so);
X}
X
Xvoid
Xsocantrcvmore (so)
X  struct socket * so;
X{
X   so->so_state |= SS_CANTRCVMORE;
X   sorwakeup (so);
X}
X
X#ifdef SB_COLL
Xvoid
Xsbselqueue (sb)
X  struct sockbuf * sb;
X{
X   struct proc * p;
X
X   if ((p = sb->sb_sel) && p->p_wchan == (caddr_t) &selwait)
X       sb->sb_flags |= SB_COLL;
X   else
X       sb->sb_sel = u.u_procp;
X}
X#endif
X
Xvoid
Xsbwait (sb)
X  struct sockbuf * sb;
X{
X   sb->sb_flags |= SB_WAIT;
X   (void) sleep ((caddr_t) &sb->sb_cc, PZERO + 1);
X}
X
Xvoid
Xsbwakeup (sb)
X  struct sockbuf * sb;
X{
X#ifdef SB_COLL
X   if (sb->sb_sel)
X    {
X       selwakeup (sb->sb_sel, sb->sb_flags & SB_COLL);
X       sb->sb_sel = 0;
X       sb->sb_flags &= ~SB_COLL;
X    }
X#endif
X   if (sb->sb_flags & SB_WAIT)
X    {
X       sb->sb_flags &= ~SB_WAIT;
X       wakeup ((caddr_t) &sb->sb_cc);
X    }
X}
X
X/* ARGSUSED */
Xvoid
Xsowakeup (so, sb)
X  struct socket * so;
X  struct sockbuf * sb;
X{
X   struct proc * p;
X
X   sbwakeup (sb);
X
X   if (so->so_state & SS_ASYNC)
X    {
X       if (so->so_pgrp < 0)
X	    signal (-so->so_pgrp, SIGIO);
X       else if (so->so_pgrp)
X	   for (p = proc; p < (struct proc *) v.ve_proc; p = p->p_xlink)
X	       if (p->p_pid == so->so_pgrp)
X		{
X		   psignal (p, SIGURG);
X		   break;
X		}
X    }
X}
X
X/*
X *  Socket buffer utiliy routines.
X */
X
Xint
Xsoreserve (so, sndcc, rcvcc)
X  struct socket * so;
X  int sndcc, rcvcc;
X{
X   if (sbreserve (&so->so_snd, sndcc) == 0)
X       goto bad1;
X   if (sbreserve (&so->so_rcv, rcvcc) == 0)
X       goto bad2;
X   return 0;
X bad2:
X   sbrelease (&so->so_snd);
X bad1:
X   return ENOBUFS;
X}
X
X/*
X *  Reserve mbufs for a socketbuf.
X */
X
Xint
Xsbreserve (sb, cc)
X  struct sockbuf * sb;
X{
X   sb->sb_hiwat = cc;
X   sb->sb_mbmax = cc * 2;
X   return 1;
X}
X
Xvoid
Xsbrelease (sb)
X  struct sockbuf * sb;
X{
X   sbflush (sb);
X   sb->sb_hiwat = sb->sb_mbmax = 0;
X}
X
Xvoid
Xsbappend (sb, m)
X  struct sockbuf * sb;
X  struct mbuf * m;
X{
X   struct mbuf * n;
X
X   if (m == 0)
X       return;
X   if (n = sb->sb_mb)
X    {
X       while (n->m_act)
X	   n = n->m_act;
X       while (n->m_next)
X	   n = n->m_next;
X    }
X   sbcompress (sb, m, n);
X}
X
Xvoid
Xsbappendrecord (sb, m0)
X  struct sockbuf * sb;
X  struct mbuf * m0;
X{
X   struct mbuf * m;
X
X   if (m0 == 0)
X       return;
X
X   if (m = sb->sb_mb)
X       while (m->m_act)
X	   m = m->m_act;
X
X   sballoc (sb, m0);
X   if (m)
X       m->m_act = m0;
X   else
X       sb->sb_mb = m0;
X   m = m0->m_next;
X   m0->m_next = 0;
X   sbcompress (sb, m, m0);
X}
X
Xint
Xsbappendaddr (sb, asa, m0, rights0)
X  struct sockbuf * sb;
X  struct sockaddr * asa;
X  struct mbuf * rights0, * m0;
X{
X   struct mbuf * m, * n;
X   int space = sizeof (* asa);
X
X   for (m = m0; m; m = m->m_next)
X       space += m->m_len;
X   if (rights0)
X       space += rights0->m_len;
X   if (space > sbspace (sb))
X       return 0;
X   MGET (m, M_DONTWAIT, MT_SONAME);
X   if (m == 0)
X       return 0;
X   * mtod (m, struct sockaddr *) = * asa;
X   m->m_len = sizeof (* asa);
X   if (rights0 && rights0->m_len)
X    {
X       if ((m->m_next = m_copy (rights0, 0, rights0->m_len)) == 0)
X	{
X	   m_freem (m);
X	   return 0;
X	}
X       sballoc (sb, m->m_next);
X    }
X   sballoc (sb, m);
X   if (n = sb->sb_mb)
X    {
X       while (n->m_act)
X	   n = n->m_act;
X       n->m_act = m;
X    }
X   else
X       sb->sb_mb = m;
X   if (m->m_next)
X       m = m->m_next;
X   if (m0)
X       sbcompress (sb, m0, m);
X   return 1;
X}
X
Xint
Xsbappendrights (sb, m0, rights)
X  struct sockbuf * sb;
X  struct mbuf * rights, * m0;
X{
X   struct mbuf * m, * n;
X   int space = 0;
X
X   if (rights == 0)
X       panic ("sbappendrights");
X   for (m = m0; m; m = m->m_next)
X       space += m->m_len;
X   space += rights->m_len;
X   if (space > sbspace (sb))
X       return 0;
X   if ((m = m_copy (rights, 0, rights->m_len)) == 0)
X       return 0;
X   sballoc (sb, m);
X   if (n = sb->sb_mb)
X    {
X       while (n->m_act)
X	   n = n->m_act;
X       n->m_act = m;
X    }
X   else
X       sb->sb_mb = m;
X   if (m0)
X       sbcompress (sb, m0, m);
X   return 1;
X}
X
Xvoid
Xsbcompress (sb, m, n)
X  struct sockbuf * sb;
X  struct mbuf * m, * n;
X{
X   while (m)
X    {
X       if (m->m_len == 0)
X	{
X	   m = m_free (m);
X	   continue;
X	}
X       if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF &&
X	   (n->m_off + n->m_len + m->m_len <= MMAXOFF &&
X	    n->m_type == m->m_type))
X	{
X	   bcopy (mtod (m, caddr_t), mtod (n, caddr_t) + n->m_len,
X		  (unsigned) m->m_len);
X	   n->m_len += m->m_len;
X	   sb->sb_cc += m->m_len;
X	   m = m_free (m);
X	   continue;
X	}
X       sballoc (sb, m);
X       if (n)
X	   n->m_next = m;
X       else
X	   sb->sb_mb = m;
X       n = m;
X       m = m->m_next;
X       n->m_next = 0;
X    }
X}
X
Xvoid
Xsbflush (sb)
X  struct sockbuf * sb;
X{
X   if (sb->sb_flags & SB_LOCK)
X       panic ("sbflush");
X   while (sb->sb_mbcnt)
X       sbdrop (sb, (int) sb->sb_cc);
X   if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb)
X       panic ("sbflush 2");
X}
X
X/*
X *  Throw away len bytes from sb, starting at the beginning.
X */
X
Xvoid
Xsbdrop (sb, len)
X  struct sockbuf * sb;
X  int len;
X{
X   register struct mbuf * m, * mn;
X   struct mbuf * next;
X
X   next = (m = sb->sb_mb) ? m->m_act : 0;
X
X   while (len > 0)
X    {
X       if (m == 0)
X	{
X	   if (next == 0)
X	       panic ("sbdrop");
X	   m = next;
X	   next = m->m_act;
X	   continue;
X	}
X
X       if (m->m_len > len)
X	{
X	   m->m_len -= len;
X	   m->m_off += len;
X	   sb->sb_cc -= len;
X	   break;
X	}
X
X       len -= m->m_len;
X       sbfree (sb, m);
X       MFREE (m, mn);
X       m = mn;
X    }
X
X   while (m && m->m_len == 0)	/* when is this case necessary? */
X    {
X       sbfree (sb, m);
X       MFREE (m, mn);
X       m = mn;
X    }
X
X   if (m)
X    {
X       sb->sb_mb = m;
X       m->m_act = next;
X    }
X   else
X       sb->sb_mb = next;
X}
X
Xvoid
Xsbdroprecord (sb)
X  struct sockbuf * sb;
X{
X   struct mbuf * m, * mn;
X
X   m = sb->sb_mb;
X   if (m)
X    {
X       sb->sb_mb = m->m_act;
X       do 
X	{
X	   sbfree (sb, m);
X	   MFREE (m, mn);
X	} 
X       while (m - mn);
X    }
X}
+ END-OF-FILE src/socket2.c
chmod 'u=rw,g=rw,o=rw' 'src/socket2.c'
echo '	-rw-rw-rw-   1 bes      HSJ         9907 Aug 12 12:27 src/socket2.c        (as sent)'
echo '	\c'
/bin/ls -l src/socket2.c
echo 'Extracting src/syscalls.c'
sed 's/^X//' > src/syscalls.c << '+ END-OF-FILE src/syscalls.c'
X#ifndef LINT
Xstatic char * sccsdef = "@(#)syscalls.c	1.1	(Alex Crain) 6/20/89";
X#endif
X
X/*
X *  syscalls.c - system call kernal interface routines.
X *
X *  Written by Alex Crain.
X *
X *  This file is based in the Berkeley file uipc_syscalls.c,
X *  but is *not* guarenteed to be in any way compatable. It is
X *  close enough to the Berkeley code that the following applies...
X *
X *  Copyright (c) 1982, 1986, 1988 Regents of the University of California.
X *  All rights reserved.
X * 
X *  Redistribution and use in source and binary forms are permitted
X *  provided that this notice is preserved and that due credit is given
X *  to the University of California at Berkeley. The name of the University
X *  may not be used to endorse or promote products derived from this
X *  software without specific prior written permission. This software
X *  is provided "as is" without express or implied warranty.
X *
X */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/systm.h>
X#include <sys/user.h>
X#include <sys/file.h>
X#include <sys/buf.h>
X#include <sys/errno.h>
X#include <sys/systm.h>
X#include <sys/tty.h>
X#include <uipc/mbuf.h>
X#include <uipc/socket.h>
X#include <uipc/socketvar.h>
X#include <uipc/domain.h>
X#include <uipc/protosw.h>
X#include <uipc/un.h>
X#include <uipc/fproto.h>
X#include <uipc/pty.h>
X
Xstruct file * getsock ();
X
X/*
X * socket (domain, type, protocol)
X *
X *   Create a socket and add it to the processes open file table. This involves
X * some creativity, because the file structure is really too small for our 
X * uses. The kernal only knows about inodes, so there is no f_type slot. 
X * Instead, the kernal looks for a NULL f_inode, which means that we are a 
X * socket. Unfortunately, this means that there is no room in the file 
X * structure for the socket address, so we keep all of our sockets in a linear
X * table, and store the table offset in f_offset, which has no meaning here 
X * anyway. (see the macros filesock() and sockoffet() in conf.h).
X */
X
Xint	select_sleep; /* value to say if we need to wakeup */
Xint	select_sleep_addr; /* address we select on if wait in select */
X/*
X * this is hard coded righ now....for test only...soon it will be
X * loaded in at boot time so that it is not hard coded
X */
Xint	so_win_major = 0; /* major device of window */
Xunsigned int so_win_tty = 0; /* address of wintty */
X
Xsosetup() /* setup variables */
X{
X   register struct a {
X	int w_major;
X	unsigned int w_tty;
X   } * uap = (struct a *) u.u_ap;
X
X   so_win_major = uap->w_major;
X   so_win_tty = uap->w_tty;
X}
X
Xsoselect ()
X{
X   register struct a {
X      int	nfds;
X      int	*readfds;
X      int	*writefds;
X      int	*execptfds;
X   } * uap = (struct a *) u.u_ap;
X   int i,mask, cnt, *rds;
X   int k,l, j;
X   struct file *fp;
X   struct inode *ip;
X   struct tty *tp;
X   struct socket *so;
X
X   rds = uap->readfds;
X   if(rds) { /* have readbitmask */
X      for(cnt=0,i=0;i < uap->nfds; i++) {
X	u.u_error = 0; /* reset it */
X	mask = 1 << i;
X	if(*rds & mask) { /* is this one? */
X		fp = getsock(i);
X		if(fp != 0) { /* valid socket */
X			so = filesock(fp);
X			if((so->so_rcv.sb_mb != 0) &&
X			    (so->so_rcv.sb_cc != 0)) {
X				/* has buffer & has chars */
X				cnt++;
X			} else {
X				*rds &= ~mask;
X			}
X		} else if((fp = getf(i)) != 0) { /* valid open file */
X			ip = fp->f_inode;
X			if(major(ip->i_rdev) == pty_major) {
X				/* got a pty file descriptor */
X				if(Master(ip->i_rdev) == True) {
X					/* get slot in tty table */
X					k = minor(ip->i_rdev) - PTYCNT;
X					tp = &pts_tty[k]; /* ok */
X				}else { /* normal slot */
X					k = minor(ip->i_rdev) - PTYCNT;
X					tp = &pts_tty[k]; /* ok */
X				}
X				/* check buffer address */
X				if(tp->t_tbuf.c_count) {
X					/* ok to read */
X					cnt++;
X				}else {
X					*rds &= ~mask;
X				}
X			}else if(major(ip->i_rdev) == so_win_major) {
X				/* got a window file descriptor */
X				/* take off 1 for aligment */
X				k = minor(ip->i_rdev) - 1;
X				k *= sizeof(struct tty);
X				tp = (struct tty *) (unsigned) (so_win_tty + k);
X				/* check buffer */
X				k = tp->t_rawq.c_cc;
X				if(k)
X					cnt++;
X				else
X					*rds &= ~mask;
X				
X			} else {
X				*rds &= ~mask;
X			}
X		} else {
X			*rds &= ~mask;
X		}
X	}
X      }
X   }
X   if(cnt) {
X	   u.u_rval1 = cnt;
X	   return;
X   }
X   select_sleep = 1;
X   /* sleep until worked up */
X   sleep( (caddr_t) &select_sleep_addr, PZERO+1 );
X   /* we are here so we let it know that we are ready */
X   u.u_rval1 = 0;
X   return;
X}
X
Xsocket ()
X{
X   register struct a {
X      int	domain;
X      int 	type;
X      int	proto;
X   } * uap = (struct a *) u.u_ap;
X
X   struct socket * so;
X   struct file *fp;
X
X   if ((fp = falloc ((struct inode *) 0, FREAD| FWRITE)) == NULL)
X       return;
X
X   if (u.u_error = socreate (uap->domain, &so, uap->type, uap->proto))
X       goto bad;
X
X   fp->f_offset = sockoffset (so);
X   return;
X
X bad:
X   u.u_ofile[u.u_rval1] = 0;
X   fp->f_count = 0;
X   fp->f_next = ffreelist;
X   ffreelist = fp;
X}
X
Xbind ()
X{
X   struct a {
X      int	s;
X      caddr_t	name;
X      int	namelen;
X   } * uap = (struct a *) u.u_ap;
X
X   struct file * fp;
X   struct mbuf * nam;
X
X   if ((fp = getsock (uap->s)) == 0)
X       return;
X
X   if (u.u_error = sockargs (&nam, uap->name, uap->namelen, MT_SONAME))
X       return;
X
X   u.u_error = sobind (filesock (fp), nam);
X   m_freem (nam);
X}
X
Xlisten ()
X{
X   struct a {
X      int	s;
X      int	backlog;
X   } * uap = (struct a *) u.u_ap;
X   struct file * fp;
X
X   if ((fp = getsock (uap->s)) == 0)
X       return;
X
X   u.u_error = solisten (filesock (fp), uap->backlog);
X}
X
Xaccept ()
X{
X   struct a {
X      int	s;
X      caddr_t	name;
X      int	* anamelen;
X   } * uap = (struct a *) u.u_ap;
X   struct file * fp;
X   struct mbuf * nam;
X   int namelen;
X   int s;
X   struct socket * so;
X
X   if (uap->name == 0)
X       goto noname;
X
X   if (u.u_error = copyin ((caddr_t) uap->anamelen, (caddr_t) &namelen, 
X			   sizeof (namelen)))
X       return;
X
X   if (useracc ((caddr_t) uap->name, (u_int) namelen, UACC_WRITE) == 0)
X    {
X       u.u_error = EFAULT;
X       return;
X    }
X
X noname:
X   if ((fp = getsock (uap->s)) == 0)
X       return;
X   s = splnet ();
X   so = filesock (fp);
X   if ((so->so_options & SO_ACCEPTCONN) == 0)
X    {
X       u.u_error = EINVAL;
X       goto bad;
X    }
X   if ((so->so_state & SS_NBIO) && so->so_qlen == 0)
X    {
X       u.u_error = EWOULDBLOCK;
X       goto bad;
X    }
X   while (so->so_qlen == 0 && so->so_error == 0)
X    {
X       if (so->so_state & SS_CANTRCVMORE)
X	{
X	   so->so_error = ECONNABORTED;
X	   break;
X	}
X       sleep ((caddr_t) &so->so_timeo, PZERO+1);
X    }
X
X   if (so->so_error)
X    {
X       u.u_error = so->so_error;
X       so->so_error = 0;
X       goto bad;
X    }
X
X   if ((fp = falloc ((struct inode *) 0, FREAD| FWRITE)) == 0)
X       goto bad;
X   else
X    {
X       struct socket * so2 = so->so_q;
X       if (soqremque (so2, 1) == 0)
X	   panic ("accept");
X       so = so2;
X    }
X
X   fp->f_offset = sockoffset (so);
X   nam = m_get (M_WAIT, MT_SONAME);
X   (void) soaccept (so, nam);
X
X   if (uap->name)
X    {
X       if (namelen > nam->m_len)
X	   namelen = nam->m_len;
X       (void) copyout (mtod (nam, caddr_t), (caddr_t) uap->name, 
X		       (u_int) namelen);
X       (void) copyout ((caddr_t) &namelen, (caddr_t) uap->anamelen,
X		       sizeof (*uap->anamelen));
X    }
X   m_freem (nam);
X
X bad:
X   splx (s);
X   return;
X}
X
Xconnect ()
X{
X   struct a {
X      int	s;
X      caddr_t	name;
X      int	namelen;
X   } * uap = (struct a *) u.u_ap;
X   struct file * fp;
X   struct socket * so;
X   struct mbuf * nam;
X   int s;
X
X   if ((fp = getsock (uap->s)) == 0)
X       return;
X
X   so = filesock (fp);
X
X   if ((so->so_state & SS_NBIO) &&
X       (so->so_state & SS_ISCONNECTING))
X    {
X       u.u_error = EALREADY;
X       return;
X    }
X
X   if (u.u_error = sockargs (&nam, uap->name, uap->namelen, MT_SONAME))
X       return;
X
X   if (u.u_error = soconnect (so, nam))
X       goto bad;
X
X   if ((so->so_state & SS_NBIO) &&
X       (so->so_state & SS_ISCONNECTING))
X    {
X       u.u_error = EINPROGRESS;
X       m_freem (nam);
X       return;
X    }
X
X   s = splnet ();
X
X   if (setjmp (u.u_qsav))
X    {
X       if (u.u_error == 0)
X	   u.u_error = EINTR;
X       goto bad2;
X    }
X
X   while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
X       sleep ((caddr_t) &so->so_timeo, PZERO + 1);
X
X   u.u_error = so->so_error;
X   so->so_error = 0;
X
X bad2:
X   splx (s);
X
X bad:
X   so->so_state &= ~SS_ISCONNECTING;
X   m_freem (nam);
X}
X
Xsocketpair ()
X{
X   struct a {
X      int	domain;
X      int	type;
X      int	proto;
X      int	* rsv;
X   } * uap = (struct a *) u.u_ap;
X
X   register struct file * fp1, * fp2;
X   struct socket * so1, * so2;
X   int sv[2];
X
X   /*
X    *  verify that uap->rsv is in the users address space & writeable.
X    *  UACC_READ and UACC_WRITE are defined in <uipc/conf.h>.
X    */
X   if (useracc ((caddr_t) uap->rsv, sizeof (int) * 2, UACC_WRITE) == 0)
X    {
X       u.u_error = EFAULT;
X       return;
X    }
X
X   /*
X    *  Create some sockets (2).
X    */
X   if (u.u_error = socreate (uap->domain, &so1, uap->type, uap->proto))
X       return;
X
X   if (u.u_error = socreate (uap->domain, &so2, uap->type, uap->proto))
X       goto free1;
X
X   /*
X    *  assign them to file structures in the open file table.
X    */
X   if ((fp1 = falloc ((struct inode *) 0, FREAD | FWRITE)) == NULL)
X       goto free2;
X   sv[0] = u.u_rval1;
X   fp1->f_offset = sockoffset (so1);
X
X   if ((fp2 = falloc ((struct inode *) 0, FREAD | FWRITE)) == NULL)   
X       goto free3;
X   sv[1] = u.u_rval1;
X   fp2->f_offset = sockoffset (so2);
X
X   /* 
X    *  Connect them together.
X    */
X
X   if (u.u_error = soconnect2 (so1, so2))
X       goto free4;
X
X   /*
X    *  DATAGRAMS need to be connected both ways
X    */
X   if (uap->type == SOCK_DGRAM)
X       if (u.u_error = soconnect2 (so2, so1))
X	   goto free4;
X
X   /*
X    *  done, return 0 and pass the file descriptors back.
X    */
X   u.u_rval1 = 0;
X   copyout ((caddr_t) sv, (caddr_t) uap->rsv, 2 * sizeof (int));
X   return;
X
X free4:
X   fp2->f_count = 0;
X   fp2->f_next = ffreelist;
X   ffreelist = fp2;
X
X free3:
X   fp1->f_count = 0;
X   fp1->f_next = ffreelist;
X   ffreelist = fp1;
X
X free2:
X   (void) soclose (so2);
X   
X free1:
X   (void) soclose (so1);
X}
X
Xsendto ()
X{
X   struct a {
X      int	s;
X      caddr_t	buf;
X      int	len;
X      int	flags;
X      caddr_t	to;
X      int	tolen;
X   } * uap = (struct a *) u.u_ap;
X
X   struct msghdr msg;
X   
X   msg.msg_name = uap->to;
X   msg.msg_namelen = uap->tolen;
X   msg.msg_accrights = (caddr_t) 0;
X   msg.msg_accrightslen = 0;
X
X   u.u_base = uap->buf;
X   u.u_count = uap->len;
X   u.u_segflg = 0;
X
X   sendit (uap->s, &msg, uap->flags);
X}
X
Xsend ()
X{
X   struct a {
X      int	s;
X      caddr_t	buf;
X      int	len;
X      int	flags;
X   } * uap = (struct a *) u.u_ap;
X
X   struct msghdr msg;
X
X   msg.msg_name = (caddr_t) 0;
X   msg.msg_namelen = 0;
X   msg.msg_accrights = (caddr_t) 0;
X   msg.msg_accrightslen = 0;
X
X   u.u_base = uap->buf;
X   u.u_count = uap->len;
X   u.u_segflg = 0;
X      
X   sendit (uap->s, &msg, uap->flags);
X}
X
Xvoid
Xsendit (s, mp, flags)
X  int s;
X  struct msghdr * mp;
X  int flags;
X{
X   struct file * fp;
X   struct mbuf * to, * rights;
X
X   if ((fp = getsock (s)) == 0)
X       return;
X
X   if (u.u_count != 0 && useracc (u.u_base, u.u_count, UACC_READ) == 0)
X    {
X       u.u_error = EFAULT;
X       return;
X    }
X
X   if (mp->msg_name)
X    {
X       if (u.u_error = sockargs (&to, mp->msg_name, mp->msg_namelen,MT_SONAME))
X	   return; 
X    }
X   else
X      to = (struct mbuf *) 0;
X
X   if (mp->msg_accrights)
X    {
X       if (u.u_error = sockargs (&to, mp->msg_accrights, mp->msg_accrightslen,
X				 MT_SONAME))
X	   goto bad;
X    }
X   else
X       rights = (struct mbuf *) 0;
X
X   u.u_error = sosend (filesock (fp), to, flags, rights);
X
X   if (rights)
X       m_freem (rights);
X
X bad:
X   if (to)
X       m_freem (to);
X}
X
Xrecvfrom ()
X{
X   struct a {
X      int	s;
X      caddr_t	buf;
X      int	len;
X      int	flags;
X      caddr_t	from;
X      int	* fromlenaddr;
X   } * uap = (struct a *) u.u_ap;
X
X   struct msghdr msg;
X
X   msg.msg_name = uap->from;
X   if (u.u_error = copyin ((caddr_t) uap->fromlenaddr, 
X			   (caddr_t) &msg.msg_namelen, 
X			   sizeof (msg.msg_namelen)))
X       return;
X
X   msg.msg_accrights = (caddr_t) 0;
X   msg.msg_accrightslen = 0;
X
X   u.u_base = uap->buf;
X   u.u_count = uap->len;
X   u.u_segflg = 0;
X
X   recvit (uap->s, &msg, uap->flags, (caddr_t) uap->fromlenaddr, (caddr_t) 0);
X}
X
Xrecv ()
X{
X   struct a {
X      int	s;
X      caddr_t	buf;
X      int	len;
X      int	flags;
X   } * uap = (struct a *) u.u_ap;
X
X   struct msghdr msg;
X
X   msg.msg_name = (caddr_t) 0;
X   msg.msg_namelen = 0;
X   msg.msg_accrights = (caddr_t) 0;
X   msg.msg_accrightslen = 0;
X
X   u.u_base = uap->buf;
X   u.u_count = uap->len;
X   u.u_segflg = 0;
X
X   recvit (uap->s, &msg, uap->flags, (caddr_t) 0, (caddr_t) 0);
X}
X
Xvoid
Xrecvit (s, mp, flags, namelenp, rightslenp)
X  int s;
X  struct msghdr * mp;
X  int flags;
X  caddr_t namelenp, rightslenp;
X{
X   struct file * fp;
X   struct mbuf * from, * rights;
X   int len;
X
X   if ((fp = getsock (s)) == 0)
X       return;
X
X   if (u.u_count != 0 && useracc (u.u_base, u.u_count, UACC_WRITE) == 0)
X    {
X       u.u_error = EFAULT;
X       return;
X    }
X
X   u.u_error = soreceive (filesock (fp), &from, flags, &rights);
X
X   if (mp->msg_name)
X    {
X       len = mp->msg_namelen;
X       if (len <= 0 || from == (struct mbuf *) 0)
X	   len = 0;
X       else
X	{
X	   if (len > from->m_len)
X	        len = from->m_len;
X	   (void) copyout ((caddr_t) mtod (from, caddr_t), 
X			   (caddr_t) mp->msg_name, (unsigned) len);
X	}
X       (void) copyout ((caddr_t) &len, namelenp, sizeof (int));
X    }
X
X   if (mp->msg_accrights)
X    {
X       len = mp->msg_accrightslen;
X       if (len <= 0 || rights == (struct mbuf *) 0)
X	   len = 0;
X       else
X	{
X	   if (len > rights->m_len)
X	        len = rights->m_len;
X	   (void) copyout ((caddr_t) mtod (rights, caddr_t), 
X			   (caddr_t) mp->msg_accrights, (unsigned) len);
X	}
X       (void) copyout ((caddr_t) &len, rightslenp, sizeof (int));
X    }
X
X   if (rights)
X       m_freem (rights);
X   if (from)
X       m_freem (from);
X}
X
Xsetsockopt ()
X{
X   struct a {
X      int	s;
X      int	level;
X      int	name;
X      caddr_t	val;
X      int	valsize;
X   } * uap = (struct a *) u.u_ap;
X   struct file * fp;
X   struct mbuf * m = (struct mbuf *) 0;
X
X   if ((fp = getsock (uap->s)) == 0)
X       return;
X
X   if (uap->valsize > MLEN)
X    {
X       u.u_error = EINVAL;
X       return;
X    }
X   if (uap->val)
X    {
X       m = m_get (M_WAIT, MT_SOOPTS);
X       if (m == (struct mbuf *) 0)
X	{
X	   u.u_error = ENOBUFS;
X	   return;
X	}
X       if (u.u_error = copyin (uap->val, mtod (m, caddr_t), 
X			       (u_int) uap->valsize))
X	{
X	   (void) m_freem (m);
X	   return;
X	}
X       m->m_len = uap->valsize;
X    }
X   u.u_error = sosetopt (filesock (fp), uap->level, uap->name, m);
X}
X
Xgetsockopt ()
X{
X   struct a {
X      int	s;
X      int	level;
X      int	name;
X      caddr_t	val;
X      int	* avalsize;
X   } * uap = (struct a *) u.u_ap;
X   struct file * fp;
X   struct mbuf * m = (struct mbuf *) 0;
X   int valsize;
X
X   if ((fp = getsock (uap->s)) == 0)
X       return;
X
X   if (uap->val)
X    {
X       if (u.u_error = copyin ((caddr_t) uap->avalsize, (caddr_t) &valsize,
X			   sizeof (valsize)))
X	   return;
X    }
X   else
X       valsize = 0;
X
X   if (u.u_error = sogetopt (filesock (fp), uap->level, uap->name, &m))
X       goto bad;
X
X   if (uap->val && valsize && m != (struct mbuf *) 0)
X    {
X       if (valsize > m->m_len)
X	   valsize = m->m_len;
X       if (u.u_error = copyout (mtod (m, caddr_t), uap->val, (u_int) valsize))
X	   goto bad;
X       u.u_error = copyout ((caddr_t) &valsize, (caddr_t) uap->avalsize,
X			    sizeof (valsize));
X     }
X bad:
X   if (m != (struct mbuf *) 0)
X       (void) m_freem (m);
X}
X
Xsockpipe ()
X{
X   register struct file * fpr, * fpw;
X   struct socket * sor, * sow;
X   int r;
X
X   /*
X    *  Create some sockets (2).
X    */
X   if (u.u_error = socreate (AF_UNIX, &sor, SOCK_STREAM, 0))
X       return;
X
X   if (u.u_error = socreate (AF_UNIX, &sow, SOCK_STREAM, 0))
X       goto free1;
X
X   /*
X    *  assign them to file structures in the open file table.
X    */
X   if ((fpr = falloc ((struct inode *) 0, FREAD | FWRITE)) == NULL)
X       goto free2;
X   fpr->f_offset = sockoffset (sor);
X   r = u.u_rval1;
X
X   if ((fpw = falloc ((struct inode *) 0, FREAD | FWRITE)) == NULL)   
X       goto free3;
X   fpw->f_offset = sockoffset (sow);
X   u.u_rval2 = u.u_rval1;
X   u.u_rval1 = r;
X
X   /* 
X    *  Connect them together.
X    */
X
X   if (u.u_error = unp_connect2 (sow, sor))
X       goto free4;
X
X   /*
X    *  Close one direction.
X    */
X
X   sor->so_state |= SS_CANTSENDMORE;
X   sow->so_state |= SS_CANTRCVMORE;
X   return;
X
X free4:
X   fpw->f_count = 0;
X   fpw->f_next = ffreelist;
X   ffreelist = fpw;
X
X free3:
X   fpr->f_count = 0;
X   fpr->f_next = ffreelist;
X   ffreelist = fpr;
X
X free2:
X   (void) soclose (sow);
X   
X free1:
X   (void) soclose (sor);
X}
X
Xvoid
Xgetsockname ()
X{
X   struct a {
X      int	fdes;
X      caddr_t	asa;
X      int	* alen;
X   } * uap = (struct a *) u.u_ap;
X   struct file * fp;
X   struct socket * so;
X   struct mbuf * m;
X   int len;
X
X   if ((fp = getsock (uap->fdes)) == 0)
X       return;
X   if (u.u_error = copyin ((caddr_t) uap->alen, (caddr_t) &len, sizeof (len)))
X       return;
X   so = filesock (fp);
X   if ((m = m_getclr (M_WAIT, MT_SONAME)) == (struct mbuf *) 0)
X    {
X       u.u_error = ENOBUFS;
X       return;
X    }
X   if (u.u_error = (* so->so_proto->pr_usrreq) (so, PRU_SOCKADDR,
X		       (struct mbuf *) 0, m, (struct mbuf *) 0))
X       goto bad;
X   if (len > m->m_len)
X       len = m->m_len;
X   if (u.u_error = copyout (mtod (m, caddr_t), (caddr_t) uap->asa,
X			    (u_int) len))
X       goto bad;
X   u.u_error = copyout ((caddr_t) &len, (caddr_t) uap->alen, 
X			    sizeof (len));
X bad:
X   m_freem (m);
X}
X
X      
X/*
X *  System call helper functions
X */
X
Xint
Xsockargs (aname, name, namelen, type)
X  struct mbuf ** aname;
X  caddr_t name;
X  int namelen, type;
X{
X   struct mbuf * m;
X   int error;
X
X   if (namelen > MLEN)
X       return EINVAL;
X
X   if ((m = m_get (M_WAIT, type)) == NULL)
X       return ENOBUFS;
X
X   m->m_len = namelen;
X
X   if (error = copyin (name, mtod (m, caddr_t), (u_int) namelen))
X       (void) m_free (m);
X   else
X       * aname = m;
X
X   return error;
X}
X
X/* given a file descriptor see if it is a socket file descriptor */
Xstruct file *
Xgetsock (fd)
X  int fd;
X{
X   struct file * fp;
X
X   /* given an fd, see if it is a valid fd, ie in file table*/
X   if ((fp = getf (fd)) == NULL)
X       return 0;
X   
X   if (fp->f_inode)
X    {
X       u.u_error = ENOTSOCK;
X       return 0;
X    }
X   
X   return fp;
X}
+ END-OF-FILE src/syscalls.c
chmod 'u=rw,g=rw,o=rw' 'src/syscalls.c'
echo '	-rw-rw-rw-   1 bes      HSJ        18437 Aug 12 12:27 src/syscalls.c        (as sent)'
echo '	\c'
/bin/ls -l src/syscalls.c
echo 'Extracting src/sysent.m4'
sed 's/^X//' > src/sysent.m4 << '+ END-OF-FILE src/sysent.m4'
Xdivert(-1)
X#
X#	@(#)sysent.m4	1.1	(Alex Crain) 6/20/89
X#
X# sysent.m4 - generate a sysent.h file from sysconfig.m4
X#
Xdefine(DEFSYSCALL,`define(`SYSENT_OFFSET',incr(SYSENT_OFFSET)){$1,$2},')
Xdefine(DEFINE,`#define $1	$2')
Xdefine(REALTIME,1)
Xdivert
X
X/*
X *  sysent.h - system call entry definitions.
X *
X *  DO NOT EDIT THIS FILE! It is generated by sysent.m4.
X */
X
X/*
X *  The new sysent structure. This looks just like the  original sysent 
X *  structure, see <sys/systm.h>. The order is critical, and the array 
X *  offsets must be equal to SYSL_<call name> - SYSL_FIRST.
X *
X *  The original sysent structure is not used because it defines sy_call
X *  as an int function instead of void.
X */
X
Xstruct void_sysent {
X   char	sy_narg;
X   int	(*sy_call)();
X} sysentries[] = {
Xinclude(../sysconfig.m4)
X};
X
XDEFINE(SYSL_LOCSYS,SYSL_SYSCALL)
XDEFINE(SYSL_FIRST,SYSENT_START)
XDEFINE(SYSL_LAST,SYSENT_OFFSET)
+ END-OF-FILE src/sysent.m4
chmod 'u=rw,g=rw,o=rw' 'src/sysent.m4'
echo '	-rw-rw-rw-   1 bes      HSJ          893 Aug 12 12:27 src/sysent.m4        (as sent)'
echo '	\c'
/bin/ls -l src/sysent.m4
echo 'Extracting src/usrreq.c'
sed 's/^X//' > src/usrreq.c << '+ END-OF-FILE src/usrreq.c'
X#ifndef LINT
Xstatic char * sccsdef = "@(#)usrreq.c	1.1	(Alex Crain) 6/20/89";
X#endif
X
X/*
X *  usrreq.c - Unix domain functions.
X *
X *  Written by Alex Crain.
X *
X *  This file is based in the Berkeley file uipc_socket.c,
X *  but is *not* guarenteed to be in any way compatable. It is
X *  close enough to the Berkeley code that the following applies...
X *
X *  Copyright (c) 1982, 1986, 1988 Regents of the University of California.
X *  All rights reserved.
X * 
X *  Redistribution and use in source and binary forms are permitted
X *  provided that this notice is preserved and that due credit is given
X *  to the University of California at Berkeley. The name of the University
X *  may not be used to endorse or promote products derived from this
X *  software without specific prior written permission. This software
X *  is provided "as is" without express or implied warranty.
X *
X */
X
X#include <sys/types.h>
X#include <uipc/conf.h>
X#include <sys/param.h>
X#include <sys/systm.h>
X#include <sys/user.h>
X#include <sys/inode.h>
X#include <sys/proc.h>
X#include <sys/stat.h>
X#include <sys/var.h>
X#include <sys/tune.h>
X#include <sys/errno.h>
X#include <uipc/mbuf.h>
X#include <uipc/socket.h>
X#include <uipc/socketvar.h>
X#include <uipc/protosw.h>
X#include <uipc/domain.h>
X#include <uipc/unpcb.h>
X#include <uipc/un.h>
X#include <uipc/fproto.h>
X
Xstruct	sockaddr sun_noname = { AF_UNIX };
Xino_t	unp_ino;
X
Xint
Xuipc_usrreq (so, req, m, nam, rights)
X  struct socket * so;
X  int req;
X  struct mbuf * m, * nam, * rights;
X{
X   struct unpcb * unp = sotounpcb (so);
X   struct socket * so2;
X   int error = 0;
X
X   if (req == PRU_CONTROL)
X       return EOPNOTSUPP;
X
X   if (req != PRU_SEND && rights && rights->m_len)
X    {
X       error = EOPNOTSUPP;
X       goto release;
X    }
X
X   if (unp == (struct unpcb *) 0 && req != PRU_ATTACH)
X    {
X       error = EINVAL;
X       goto release;
X    }
X
X   switch (req)
X    {
X    case PRU_ATTACH:
X       if (unp)
X	{
X	   error = EISCONN;
X	   break;
X	}
X       error = unp_attach (so);
X       break;
X
X    case PRU_DETACH:
X       unp_detach (unp);
X       break;
X
X    case PRU_BIND:
X       error = unp_bind (unp, nam);
X       break;
X
X    case PRU_LISTEN:
X       if (unp->unp_inode == 0)
X	   error = EINVAL;
X       break;
X
X    case PRU_CONNECT:
X       error = unp_connect (so, nam);
X       break;
X
X    case PRU_CONNECT2:
X       error = unp_connect2 (so, (struct socket *) nam);
X       break;
X
X    case PRU_DISCONNECT:
X       unp_disconnect (unp);
X       break;
X
X    case PRU_ACCEPT:
X       if (unp->unp_conn && unp->unp_conn->unp_addr)
X	{
X	   nam->m_len = unp->unp_conn->unp_addr->m_len;
X	   bcopy (mtod (unp->unp_conn->unp_addr, caddr_t),
X		  mtod (nam, caddr_t), (unsigned) nam->m_len);
X	}
X       else
X	{
X	   nam->m_len = sizeof (sun_noname);
X	   * (mtod (nam, struct sockaddr *)) = sun_noname;
X	}
X       break;
X
X    case PRU_SHUTDOWN:
X       socantsendmore (so);
X       unp_usrclosed (unp);
X       break;
X
X    case PRU_RCVD:
X       switch (so->so_type)
X	{
X	case SOCK_DGRAM:
X	   panic ("uipc 1");
X	   /* NOTREACHED */;
X
X	case SOCK_STREAM:
X#define rcv (&so->so_rcv)
X#define snd (&so2->so_snd)
X	   if (unp->unp_conn == 0)
X	       break;
X	   /*
X	    *  Adjust backpressure on sender 
X	    *  and wakeup any waiting to write.
X	    */
X	   so2 = unp->unp_conn->unp_socket;
X	   snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt;
X	   unp->unp_mbcnt = rcv->sb_mbcnt;
X	   snd->sb_hiwat += unp->unp_cc - rcv->sb_cc;
X	   unp->unp_cc = rcv->sb_cc;
X	   sowwakeup (so2);
X#undef snd
X#undef rcv
X	   break;
X
X	default:
X	   panic ("uipc 2");
X	}
X       break;
X
X    case PRU_SEND:
X       if (rights && (error = unp_internalize (rights)))
X	   break;
X
X       switch (so->so_type)
X	{
X	case SOCK_DGRAM:
X	   {
X	      struct sockaddr * from;
X
X	      if (nam)
X	       {
X		  if (unp->unp_conn)
X		   {
X		      error = EISCONN;
X		      break;
X		   }
X		  if (error = unp_connect (so, nam))
X		      break;
X	       }
X	      else
X	       {
X		  if (unp->unp_conn == 0)
X		   {
X		      error = ENOTCONN;
X		      break;
X		   }
X	       }
X	      so2 = unp->unp_conn->unp_socket;
X	      if (unp->unp_addr)
X	          from = mtod (unp->unp_addr, struct sockaddr *);
X	      else
X	          from = &sun_noname;
X	      if (sbspace (&so2->so_rcv) > 0 &&
X		  sbappendaddr (&so2->so_rcv, from, m, rights))
X	       {
X		  sorwakeup (so2);
X		  m = 0;
X	       }
X	      else
X	          error = ENOBUFS;
X	      if (nam)
X	          unp_disconnect (unp);
X	      break;
X	   }
X		  
X	case SOCK_STREAM:
X#define rcv (&so2->so_rcv)
X#define snd (&so->so_snd)
X	   if (so->so_state & SS_CANTSENDMORE)
X	    {
X	       error = EPIPE;
X	       break;
X	    }
X	   if (unp->unp_conn == 0)
X	       panic ("uipc 3");
X	   so2 = unp->unp_conn->unp_socket;
X	   /*
X	    * Send to paired receive port, and then reduce
X	    * senders hiwater makrs to maintain backpressure.
X	    * Wake up readers.
X	    */
X	   if (rights)
X	       (void) sbappendrights (rcv, m, rights);
X	   else
X	       sbappend (rcv, m);
X	   snd->sb_mbmax -= rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt;
X	   unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt;
X	   snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc;
X	   unp->unp_conn->unp_cc = rcv->sb_cc;
X	   sorwakeup (so2);
X	   m = 0;
X	   break;
X#undef snd
X#undef rcv
X
X	default:
X	   panic ("uipc 4");
X	}
X       break;
X
X    case PRU_SENSE:
X/*       ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat; */
X       if (so->so_type == SOCK_STREAM && unp->unp_conn != 0)
X	{
X	   so2 = unp->unp_conn->unp_socket;
X/*	   ((struct stat *) m)->st_blksize += so2->so_rcv.sb_cc; */
X	}
X       ((struct stat *) m)->st_dev = NODEV;
X       if (unp->unp_ino == 0)
X	   unp->unp_ino = unp_ino++;
X       ((struct stat *) m)->st_ino = unp->unp_ino;
X       return 0;
X
X    case PRU_ABORT:
X       unp_drop(unp, ECONNABORTED);
X       break;
X
X    case PRU_RCVOOB:
X       return EOPNOTSUPP;
X       
X    case PRU_SENDOOB:
X       error = EOPNOTSUPP;
X       break;
X
X    case PRU_SOCKADDR:
X       break;
X
X    case PRU_PEERADDR:
X       if (unp->unp_conn && unp->unp_conn->unp_addr)
X	{
X	   nam->m_len = unp->unp_conn->unp_addr->m_len;
X	   bcopy (mtod (unp->unp_conn->unp_addr, caddr_t),
X		  mtod (nam, caddr_t), (unsigned) nam->m_len);
X	}
X       break;
X
X    case PRU_SLOWTIMO:
X       break;
X
X    default:
X       panic ("prusrreq");
X    }
X
X release:
X   if (m)
X       m_freem (m);
X   return error;
X}
X
X#define UNPST_SENDSPACE 4096
X#define UNPST_RECVSPACE 4096
X#define UNPDG_SENDSPACE 2048	/* max datagram size */
X#define UNPDG_RECVSPACE 2048
X
Xint unp_rights;
X
Xint
Xunp_attach (so)
X  struct socket * so;
X{
X   struct mbuf * m;
X   struct unpcb * unp;
X   int error = 0;
X
X   switch (so->so_type)
X    {
X    case SOCK_DGRAM:
X       error = soreserve (so, UNPDG_SENDSPACE, UNPDG_RECVSPACE);
X       break;
X
X    case SOCK_STREAM:
X       error = soreserve (so, UNPST_SENDSPACE, UNPST_RECVSPACE);
X       break;
X    }
X   if (error)
X       return error;
X
X   if ((m = m_getclr (M_DONTWAIT, MT_PCB)) == NULL)
X       return ENOBUFS;
X
X   unp = mtod(m, struct unpcb *);
X   so->so_pcb = (caddr_t) unp;
X   unp->unp_socket = so;
X
X   return 0;
X}
X
Xvoid
Xunp_detach (unp)
X  struct unpcb * unp;
X{
X   if (unp->unp_inode)
X    {
X       unp->unp_inode->i_socket = 0;
X       iput (unp->unp_inode);
X       unp->unp_inode = 0;
X    }
X   if (unp->unp_conn)
X       unp_disconnect (unp);
X   while (unp->unp_refs)
X       unp_drop (unp->unp_refs, ECONNRESET);
X   soisdisconnected (unp->unp_socket);
X   unp->unp_socket->so_pcb = 0;
X   m_freem (unp->unp_addr);
X   (void) m_free (dtom (unp));
X   if (unp_rights)
X       unp_gc ();
X}
X
Xint
Xunp_bind (unp, nam)
X  struct unpcb * unp;
X  struct mbuf * nam;
X{
X   struct sockaddr_un * soun = mtod (nam, struct sockaddr_un *);
X   struct inode * ip;
X   int error;
X
X   if (unp->unp_inode != NULL || nam->m_len == MLEN)
X       return EINVAL;
X
X   *(mtod (nam, caddr_t) + nam->m_len) = '\0';
X   u.u_dirp = soun->sun_path;
X
X   if (ip = namei (schar, 1))
X    {
X       iput (ip);
X       return EADDRINUSE;
X    }
X
X   if (error = u.u_error)
X    {
X       u.u_error = 0;
X       return error;
X    }
X
X   if ((ip = maknode (IFREG | 0777)) == NULL)
X    {
X       error = u.u_error;
X       u.u_error = 0;
X       return error;
X    }
X   
X   ip->i_uid = u.u_uid;
X   ip->i_gid = u.u_gid;
X   ip->i_socket = unp->unp_socket;
X   unp->unp_inode = ip;
X   unp->unp_addr = m_copy (nam, 0, (int) M_COPYALL);
X   prele (ip);
X   return 0;
X}
X
Xint
Xunp_connect (so, nam)
X  struct socket * so;
X  struct mbuf * nam;
X{
X   struct sockaddr_un * soun = mtod (nam, struct sockaddr_un *);
X   struct inode * ip;
X   int error;
X   struct socket * so2;
X   caddr_t dirp = u.u_dirp;
X   caddr_t base = u.u_base;
X   unsigned count = u.u_count;
X
X   if ((nam->m_len + (nam->m_off - MMINOFF)) == MLEN)
X    {
X       error = EMSGSIZE;
X       goto bad0;
X    }
X   * (mtod (nam, caddr_t) + nam->m_len) = '\0';
X   u.u_dirp = soun->sun_path;
X   if ((ip = namei (schar, 0)) == 0)
X    {
X       error = u.u_error;
X       u.u_error = 0;
X       goto bad0;
X    }
X   if (access (ip, IWRITE))
X    {
X       error = u.u_error;
X       u.u_error = 0;
X       goto bad;
X    }
X   if ((so2 = ip->i_socket) == 0)
X    {
X       error = ECONNREFUSED;
X       goto bad;
X    }
X   if (so2->so_type != so->so_type)
X    {
X       error = EPROTOTYPE;
X       goto bad;
X    }
X   if (so->so_proto->pr_flags & PR_CONNREQUIRED &&
X       ((so2->so_options & SO_ACCEPTCONN) == 0 ||
X	(so2 = sonewconn (so2)) == 0))
X    {
X       error = ECHILD; /* ECONNREFUSED;*/
X       goto bad;
X    }
X   error = unp_connect2 (so, so2);
X bad:
X   iput (ip);
X bad0:
X   u.u_base = base;
X   u.u_count = count;
X   u.u_dirp = dirp;
X   return error;
X}
X
Xint
Xunp_connect2 (so1, so2)
X  struct socket * so1, * so2;
X{
X   struct unpcb * unp1, * unp2;
X
X   if (so2->so_type != so1->so_type)
X       return EPROTOTYPE;
X   unp1 = sotounpcb (so1);
X   unp2 = sotounpcb (so2);
X   unp1->unp_conn = unp2;
X   switch (so1->so_type)
X    {
X    case SOCK_DGRAM:
X       unp1->unp_nextref = unp2->unp_refs;
X       unp2->unp_refs = unp1;
X       soisconnected (so1);
X       break;
X
X    case SOCK_STREAM:
X       unp2->unp_conn = unp1;
X       soisconnected (so1);
X       soisconnected (so2);
X       break;
X       
X    default:
X       panic ("unp_connect 2");
X    }
X   return 0;
X}
X
Xvoid
Xunp_disconnect (unp)
X  struct unpcb * unp;
X{
X   struct unpcb * unp2 = unp->unp_conn;
X
X   if (unp2 == 0)
X       return;
X   unp->unp_conn = 0;
X   switch (unp->unp_socket->so_type)
X    {
X    case SOCK_DGRAM:
X       if (unp2->unp_refs == unp)
X	   unp2->unp_refs = unp->unp_nextref;
X       else
X	{
X	   unp2 = unp2->unp_refs;
X	   for (;;)
X	    {
X	       if (unp2 == 0)
X		   panic ("unp_disconnect");
X	       if (unp2->unp_nextref == unp)
X		   break;
X	       unp2 = unp2->unp_nextref;
X	    }
X	   unp2->unp_nextref = unp->unp_nextref;
X	}
X       unp->unp_nextref = 0;
X       unp->unp_socket->so_state &= ~SS_ISCONNECTED;
X       break;
X
X    case SOCK_STREAM:
X       soisdisconnected (unp->unp_socket);
X       unp2->unp_conn = 0;
X       soisdisconnected (unp2->unp_socket);
X       break;
X    }
X}
X
X/* ARGSUSED */
Xvoid
Xunp_usrclosed (unp)
X  struct unpcb * unp;
X{
X   /* do not very much */
X   ;
X}
X
Xvoid
Xunp_drop (unp, errno)
X  struct unpcb * unp;
X  int errno;
X{
X   struct socket * so = unp->unp_socket;
X
X   so->so_error = errno;
X   unp_disconnect (unp);
X   if (so->so_head)
X    {
X       so->so_pcb = (caddr_t) 0;
X       m_freem (unp->unp_addr);
X       (void) m_free (dtom (unp));
X       sofree (so);
X    }
X}
X
Xushort f_msgcount[NFILEMAX];
X#define fptoi(FP) (((FP)-file)/sizeof (struct file))
X
X/* ARGSUSED */
Xint
Xunp_externalize (rights)
X  struct mbuf * rights;
X{
X   int newfds = rights->m_len / sizeof (int);   
X   int i, f;
X   struct file ** rp = mtod (rights, struct file **);
X   struct file * fp;
X
X   if (newfds > ufavail ())
X    {
X       for (i = 0; i < newfds; i++)
X	{
X	   fp = *rp;
X	   unp_discard (fp);
X	   * rp++ = 0;
X	}
X       return EMSGSIZE;
X    }
X   for (i = 0, f = 0; i < newfds; i++)
X    {
X       f = ufalloc (f);
X       if (f < 0)
X	   panic ("unp_externalize");
X       fp = * rp;
X       u.u_ofile[f] = fp;
X       f_msgcount[fptoi (fp)]--;
X       unp_rights --;
X       * (int *) rp++ = f;
X    }
X   return 0;
X}
X
X/* ARGSUSED */
Xint
Xunp_internalize (rights)
X  struct mbuf * rights;
X{
X   struct file ** rp, * fp;
X   int oldfds = rights->m_len / sizeof (int);
X   int i;
X
X   rp = mtod (rights, struct file **);
X
X   for (i = 0; i < oldfds; i++)
X       if (getf (* (int *) rp++) == 0)
X	   return EBADF;
X
X   rp = mtod (rights, struct file **);
X
X   for (i = 0; i < oldfds; i++)
X    {
X       fp = getf (* (int *) rp);
X       * rp++ = fp;
X       fp->f_count++;
X       f_msgcount[fptoi (fp)]++;
X       unp_rights++;
X    }
X   return 0;
X}
X
Xint unp_defer, unp_gcing;
Xextern struct domain unixdomain;
X
Xvoid
Xunp_gc ()
X{
X   struct file * fp;
X   struct socket * so;
X   int i;
X
X   if (unp_gcing)
X       return;
X   unp_gcing = 1;
X restart:
X   unp_defer = 0;
X   for (fp = file; fp < (struct file *) v.ve_file; fp++)
X       fp->f_flag &= ~(FMARK | FDEFER);
X   do
X    {
X       for (fp = file; fp < (struct file *) v.ve_file; fp++)
X	{
X	   if (fp->f_count == 0)
X	       continue;
X	   if (fp->f_flag & FDEFER)
X	    {
X	       fp->f_flag &= ~FDEFER;
X	       unp_defer--;
X	    }
X	   else
X	    {
X	       if (fp->f_flag & FMARK)
X		   continue;
X	       if (fp->f_count == f_msgcount[fptoi (fp)])
X		   continue;
X	       fp->f_flag |= FMARK;
X	    }
X	   if (fp->f_inode)
X	       continue;
X	   so = filesock (fp);
X	   if (so->so_proto->pr_domain != &unixdomain ||
X	       so->so_proto->pr_flags & PR_RIGHTS)
X	       continue;
X	   if (so->so_rcv.sb_flags & SB_LOCK)
X	    {
X	       sbwait (&so->so_rcv);
X	       goto restart;
X	    }
X	   unp_scan (so->so_rcv.sb_mb, (int (*)()) unp_mark);
X	}
X    } while (unp_defer);
X   for (fp = file, i = 0; fp < (struct file *) v.ve_file; fp++, i++)
X    {
X       if (fp->f_count == 0)
X	   continue;
X       if (fp->f_count == f_msgcount[i] &&
X	   (fp->f_flag & FMARK) == 0)
X	   while (f_msgcount[i])
X	       unp_discard (fp);
X    }
X   unp_gcing = 0;
X}
X
Xvoid
Xunp_dispose (m)
X  struct mbuf * m;
X{
X   void unp_discard ();
X
X   if (m)
X       unp_scan (m, (int (*)()) unp_discard);
X}
X
X/* ARGSUSED */
Xvoid
Xunp_scan (m0, op)
X  struct mbuf * m0;
X  int (* op)();
X{
X   struct mbuf * m;
X   struct file ** rp;
X   int i;
X   int qfds;
X
X   while (m0)
X    {
X       for (m = m0; m; m = m->m_next)
X	   if (m->m_type == MT_RIGHTS && m->m_len)
X	    {
X	       qfds = m->m_len / sizeof (struct file **);
X	       rp = mtod (m, struct file **);
X	       for (i = 0; i < qfds; i++)
X		   (* op) (* rp++);
X	       break;
X	    }
X       m0 = m0->m_act;
X    }
X}
X
Xvoid
Xunp_mark (fp)
X  struct file * fp;
X{
X   if (fp->f_flag & FMARK)
X       return;
X   unp_defer++;
X   fp->f_flag |= (FMARK | FDEFER);
X}
X
Xvoid
Xunp_discard (fp)
X  struct file * fp;
X{
X   f_msgcount[fptoi (fp)]--;
X   unp_rights--;
X   closef (fp);
X}
X
+ END-OF-FILE src/usrreq.c
chmod 'u=rw,g=rw,o=rw' 'src/usrreq.c'
echo '	-rw-rw-rw-   1 bes      HSJ        14693 Aug 12 12:27 src/usrreq.c        (as sent)'
echo '	\c'
/bin/ls -l src/usrreq.c
exit 0
-- 
Bradley Smith
Computer Systems Offer Integration Laboratory
AT&T Bell Labs, Holmdel, NJ 
201-949-0090 att!holin!bes or bes at holin.ATT.COM



More information about the Comp.sys.att mailing list