uipc socket patch#1

Bradley Smith bes at holin.ATT.COM
Mon Aug 14 03:32:45 AEST 1989


Michael Gersten, sent me a nice piece of mail stating that he done
some select work and that his code didn't have the select return
when a close was called on the other side.  Well mine didn't either,
so here are some new update files (linesw.c, syscalls.c and interface.c)
which now allow close to get signaled on sockets and named pipes.

I haven't tried to close on ptys to see what happens, and I know that
you must call accept before select will work.  I am going to look at
this so one could use select to figure out when one might need to call
accept.  Also I need to work on the write bitmask.

=======cut here====
: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
echo 'Extracting interface.c'
sed 's/^X//' > interface.c << '+ END-OF-FILE interface.c'
X#ifndef LINT
Xstatic char * sccsdef = "@(#)interface.c	1.1	(Alex Crain) 6/20/89";
X#endif
X
X/*
X *  interface.c - loadable driver interface.
X *
X *  Written By Alex Crain.
X *
X *  This file contains the driver interface routines for the uipc driver, as
X *    discribed in drivers(7). These interface routines are:
X *	uipcinit ();
X *
X */
X
X#include <sys/types.h>
X#include <sys/systm.h>
X#include <sys/errno.h>
X#include <sys/user.h>
X#include <sys/conf.h>
X#include <uipc/socketvar.h>
X#include <uipc/mbuf.h>
X#include <uipc/protosw.h>
X#include <uipc/domain.h>
X#include <uipc/fproto.h>
X#include <uipc/pty.h>
X
X#include "sysent.h"
X
Xextern void (* sock_read)();
Xextern void (* sock_write)();
Xextern void (* sock_close)();
X
X/* stuff to wake up on */
Xextern int select_sleep, select_sleep_addr;
X
Xvoid
Xptyinit ()
X{
X   int i;
X
X   /*
X    * add our own system call processor.
X    */
X
X   sysent[SYSL_LOCSYS].sy_call = (int (*)()) dosyscall;
X   sysent[SYSL_LOCSYS].sy_narg = 3;
X
X   /*
X    *  link to the existing hooks in the kernal.
X    */
X
X   sock_read = uipc_read;
X   sock_write = uipc_write;
X   sock_close = uipc_close;
X
X   /*
X    *  Initialize the system.
X    */
X
X   mbinit ();
X   domaininit ();
X
X   /*
X    * find out where the pty major device is
X    */
X   for(i=0;i<cdevcnt;i++) {
X	if(cdevsw[i].d_open == ptyopen)
X		pty_major = i; /* got it */
X   }
X   so_linesw_setup();
X}
X
Xvoid
Xdosyscall()
X{
X   int index = u.u_ap[0] - SYSL_FIRST;
X   /*
X    * Intercept our calls
X    */
X
X   if (index >= 0 && index <= (SYSL_LAST - SYSL_FIRST))
X    {
X       /*
X	*  syscall arguments are available via the users %sp, at u.u_ar0[15].
X	*  These arguments must be copied to the argument vector u.u_arg[]
X	*  for access by the kernal. Noting that the stack looks like:
X	*	%sp -> [ frame link, &67, arg1, arg2 ... ]
X	*/
X       int arg = 0;
X       int * ap = (int *) (u.u_ar0[15]) + 2;
X       while (arg < sysentries[index].sy_narg)
X	   u.u_arg[arg++] = fuword(ap++);
X
X       /*
X	*  Perform the call.
X	*/
X       (* sysentries[index].sy_call) ();
X    }
X   else
X       locsys ();
X}
X
Xint
Xuipcrelease ()
X{
X   int mbmem_ref;
X   int s = spl5();
X   struct mbuf * m;
X   
X   for (m = mbmem; m < &mbmem[NMBUF+1]; m++)
X       if (m->m_type == MT_SOCKET)
X	   if (soclose (mtod (m, struct socket *)))
X	        return EBUSY;
X   for (mbmem_ref =0, m = mbmem; m < &mbmem[NMBUF+1]; m++, mbmem_ref++)
X       if (m->m_type != MT_FREE)
X	{
X	   int * i;
X	   (void) printf ("\n\n\nUIPC: Illegal mbuf type %d.\n", m->m_type);
X	   (void) printf ("m = ([*|%x] [m_next|%x] [m_len|%x] [m_type|%x])\n",
X			  m, m->m_next, m->m_len, m->m_type);
X	   (void) printf ("mbmem_ref=%d, NMBUF=%d\n", mbmem_ref, NMBUF);
X	   for (i = mtod (m, int *); 
X		i < ((int *) ((caddr_t) m + MSIZE - MTAIL));
X		i+=4)
X	       (void) printf ("%x %x %x %x\n", *i, *(i+1), *(i+2), *(i+3));
X	   panic ("uipc_release");
X	}
X
X   splx (s);
X   so_linesw_release();
X   return 0;
X}
X
X/*
X *  rdwr() uses this for reading sockets. 
X *
X *  There are no arguments, pertinant info is available as:
X *	u.u_ap[0] -	The file descriptor number
X *	u.u_base - 	IO buffer address
X *	u.u_count -	size of buffer.
X *	u.u_segflg -	IO buffer location
X *
X *  Errors do not return, rather an error condition is handled with a longjmp
X *  to u.u_qsav, with some non-zero argument. the call will return -1 to the 
X *  user, passing the error in errno (u.u_error). Since the jump returns
X *  directly to trap(), we need to do any houskeeping here.
X */
X
Xvoid
Xuipc_write ()
X{
X   struct file * fp = getf (u.u_ap[0]);
X
X   u.u_error = sosend (filesock (fp), (struct mbuf *) 0, 0, (struct mbuf *) 0);
X   
X   /*
X    *  process errors
X    */
X
X   if (u.u_error)
X       longjmp (u.u_qsav, 1);
X}
X
Xvoid
Xuipc_read ()
X{
X   struct file * fp = getf (u.u_ap[0]);
X
X   u.u_error = 
X       soreceive (filesock (fp), (struct mbuf **) 0, 0, (struct mbuf **) 0);
X			  
X			  
X   
X   /*
X    *  process errors
X    */
X
X   if (u.u_error)
X       longjmp (u.u_qsav, 1);
X}
X
Xvoid
Xuipc_close (sp)
X  off_t sp;
X{
X   u.u_error = soclose (mtod (ptom (sp), struct socket *));
X
X   /* next check us for wakeup maybe? */
X   if(select_sleep) {
X	select_sleep = 0;
X	wakeup((caddr_t) &select_sleep_addr);
X   }
X   /*
X    *  process errors
X    */
X
X   if (u.u_error)
X       longjmp (u.u_qsav, 1);
X}
X
X
X/*
X *  General utilities for the BSD<->sysV mix.
X */
X
X#ifdef unixpc
X
Xasm("	global bzero	");
Xasm("bzero:		");
Xasm("	mov.l	4(%sp),%a0");
Xasm("	mov.w	10(%sp),%d0");
Xasm("	sub.w	&1,%d0	");
Xasm("	bmi	end	");
Xasm("loop:		");
Xasm("	mov.b	&0,(%a0)+");
Xasm("	dbf	%d0,loop");
Xasm("end:		");
Xasm("	rts		");
X
X#else
X
Xvoid
Xbzero (s, n)
X  char * s; 
X  int n;
X{
X   while (n--)
X       *s++ = '\0';
X}
X
X#endif
X
Xint
Xufavail ()
X{
X   int avail = 0, fd = 0;
X
X   for (fd = 0; fd < 80; fd++)
X       if (u.u_ofile[fd] == 0)
X	   avail++;
X
X   return avail;
X}
+ END-OF-FILE interface.c
chmod 'u=rw,g=r,o=r' 'interface.c'
echo '	-rw-r--r--   1 bes      HSJ         4757 Aug 13 13:08 interface.c        (as sent)'
echo '	\c'
/bin/ls -l interface.c
echo 'Extracting linesw.c'
sed 's/^X//' > linesw.c << '+ END-OF-FILE linesw.c'
X#include	<sys/types.h>
X#include	<sys/sysmacros.h>
X#include	<sys/conf.h>
X#include	<sys/tty.h>
X
Xint (*real_linesw_read)(), (*real_linesw_write)();
Xint (*real_linesw_l_input)();
Xint (*real_linesw_close)();
Xint so_linesw_read(), so_linesw_write();
Xint so_linesw_l_input();
Xint so_linesw_close();
X
X/* stuff to wake up on */
Xextern int select_sleep, select_sleep_addr;
X
X/* unsigned addr_win_tty = 384636; /* */
X
Xso_linesw_read(tp)
Xstruct tty *tp;
X{
X	extern int (*real_linesw_read) ();
X
X	/* next check us for wakeup maybe? */
X	if(select_sleep) {
X		select_sleep = 0;
X		wakeup((caddr_t) &select_sleep_addr);
X	}
X	(*real_linesw_read)(tp);
X}
Xso_linesw_close(tp)
Xstruct tty *tp;
X{
X	extern int (*real_linesw_close) ();
X
X	/* next check us for wakeup maybe? */
X	if(select_sleep) {
X		select_sleep = 0;
X		wakeup((caddr_t) &select_sleep_addr);
X	}
X	(*real_linesw_close)(tp);
X}
Xso_linesw_write(tp)
Xstruct tty *tp;
X{
X	extern int (*real_linesw_write) ();
X
X	/* next check us for wakeup maybe? */
X	if(select_sleep) {
X		select_sleep = 0;
X		wakeup((caddr_t) &select_sleep_addr);
X	}
X	(*real_linesw_write)(tp);
X}
Xso_linesw_l_input(tp)
Xstruct tty *tp;
X{
X
X	/* next check us for wakeup maybe? */
X	if(select_sleep) {
X		select_sleep = 0;
X		wakeup((caddr_t) &select_sleep_addr);
X	}
X	/* first call real input routine */
X	(*real_linesw_l_input)(tp);
X}
Xso_linesw_setup()
X{
X	extern int (*real_linesw_write) ();
X	extern int (*real_linesw_read) ();
X	extern int (*real_linesw_close) ();
X	extern int (*real_linesw_l_input) ();
X
X	/* setup to route tty ouput to here */
X	real_linesw_read = linesw[0].l_read;
X	linesw[0].l_read = so_linesw_read;
X
X	real_linesw_write = linesw[0].l_write;
X	linesw[0].l_write = so_linesw_write;
X
X	real_linesw_l_input = linesw[0].l_input;
X	linesw[0].l_input = so_linesw_l_input;
X
X	real_linesw_close = linesw[0].l_close;
X	linesw[0].l_close = so_linesw_close;
X
X
X}
Xso_linesw_release()
X{
X
X	/* setup to route tty ouput to here */
X	linesw[0].l_read = real_linesw_read;
X
X	linesw[0].l_write = real_linesw_write;
X
X	linesw[0].l_input = real_linesw_l_input;
X
X	linesw[0].l_close = real_linesw_close;
+ END-OF-FILE linesw.c
chmod 'u=rw,g=r,o=r' 'linesw.c'
echo '	-rw-r--r--   1 bes      HSJ         2071 Aug 13 13:23 linesw.c        (as sent)'
echo '	\c'
/bin/ls -l linesw.c
echo 'Extracting syscalls.c'
sed 's/^X//' > syscalls.c << '+ END-OF-FILE 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, *wds;
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   wds = uap->writefds;
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			j = (SS_CANTRCVMORE | SS_CANTSENDMORE);
X		 	k = SS_ISCONNECTED;
X			/* first check for closed sockets
X			 * closed sockets appear only to have j set
X			 */
X			if((so->so_state & ~j) == 0) {
X				/* socket is close. mark as having
X				 * data on it, so a read will fail 
X				 */
X				cnt++;
X			}
X			/* next we check for a socket in accept state
X			 */
X			/* this really doesn't work */
X			else if( so->so_state  == 0 ) {
X				/* here we want to sleep */
X				*rds &= ~mask;
X			}
X			/* next we check for a state of incomming ie
X			 * accept needs to be called
X			 */
X
X			/* this doesn't work right now */
X
X			/* and this is for regular sockets already
X			 * connected
X			 */
X			else 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				
X			/* here we have named pipes */
X			else if(ip->i_mode & IFIFO) {
X				/* if i_count == 1 no opens left
X				 * we notify select of this
X				 */
X				if (ip->i_count == 1) 
X					cnt++;
X				else if (ip->i_fwptr) 
X					cnt++;
X				else
X					*rds &= ~mask;
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 the user level 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 syscalls.c
chmod 'u=rw,g=r,o=r' 'syscalls.c'
echo '	-rw-r--r--   1 bes      HSJ        19412 Aug 13 13:18 syscalls.c        (as sent)'
echo '	\c'
/bin/ls -l syscalls.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 Unix-pc.sources mailing list