home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / comm / amitcp-3.0ß2.lha / AmiTCP / src / amitcp / api / amiga_generic.c < prev    next >
C/C++ Source or Header  |  1994-03-22  |  24KB  |  1,013 lines

  1. RCS_ID_C="$Id: amiga_generic.c,v 3.6 1994/03/22 08:41:36 jraja Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  * 
  7.  * Created: Fri Feb 12 13:26:55 1993 too
  8.  * Last modified: Wed Feb  2 21:35:39 1994 ppessi
  9.  * 
  10.  * HISTORY
  11.  * $Log: amiga_generic.c,v $
  12.  * Revision 3.6  1994/03/22  08:41:36  jraja
  13.  * Added calls to the libPtr->fdCallback to the appropriate places.
  14.  *
  15.  * Revision 3.5  1994/02/03  04:10:55  ppessi
  16.  * Changed the interface IOCTL codes
  17.  *
  18.  * Revision 3.4  1994/01/20  02:10:36  jraja
  19.  * Added support for 0 domain for ObtainSocket() if id is unique.
  20.  *
  21.  * Revision 3.3  1994/01/12  07:35:25  jraja
  22.  * Moved dtable functions (getLastSockFd(), _SetDTableSize() and
  23.  * _getdtablesize()) to amiga_generic2.c.
  24.  *
  25.  * Revision 3.2  1994/01/07  15:40:29  too
  26.  * Bug fixes after revision 3.1. Now tested.
  27.  *
  28.  * Revision 3.1  1994/01/04  14:38:35  too
  29.  * Added static function getLastSock(). Revised Dup2Socket, CloseSocket,
  30.  * SetDTableSize, ObtainSocket and ReleaseSocket to utilize socket usage
  31.  * bitmask. Changed behaviour of Dup2Socket when fd1 == -1.
  32.  * Moved some functions to amiga_generic2.c
  33.  *
  34.  * Revision 1.61  1993/12/22  08:16:22  jraja
  35.  * Cleaned some types, added 'static' to local functions.
  36.  *
  37.  * Revision 1.60  1993/10/16  17:20:49  too
  38.  * Fixed copying bug in SetDTableSize
  39.  *
  40.  * Revision 1.59  1993/09/14  22:15:16  jraja
  41.  * Added zeroing of obits in WaitSelect() if new memory is allocated for it.
  42.  *
  43.  * Revision 1.58  1993/08/01  22:15:07  ppessi
  44.  * Changed CloseSocket() to use api/apicall.h protos.
  45.  *
  46.  * Revision 1.57  1993/07/13  21:58:59  ppessi
  47.  * Added internal prototypes; changed interface ioctl codes to 'I'
  48.  *
  49.  * Revision 1.56  1993/06/13  16:38:43  too
  50.  * Added range check for fd2 in Dup2Socket()
  51.  *
  52.  * Revision 1.55  1993/06/11  20:18:09  too
  53.  * Added Dup2Socket(). Chahanged ioctl to IoctlSocket()
  54.  * Made function countSockets() which is needed to determine if last reference
  55.  * to that socket is given away.
  56.  *
  57.  * Revision 1.54  1993/06/07  12:37:20  too
  58.  * Changed inet_ntoa, netdatabase functions and WaitSelect() use
  59.  * separate buffers for their dynamic buffers
  60.  *
  61.  */
  62.  
  63. #include <conf.h>
  64.  
  65. #include <sys/param.h>
  66. #include <sys/systm.h>
  67. #include <sys/socketvar.h>
  68. #include <sys/kernel.h>
  69. #include <sys/ioctl.h>
  70. #include <sys/protosw.h>
  71. #include <sys/malloc.h>
  72. #include <sys/synch.h>
  73.  
  74. #include <sys/time.h>
  75. #include <sys/errno.h>
  76.  
  77. #include <sys/socket.h>
  78. #include <net/route.h>
  79.  
  80. #include <kern/amiga_includes.h>
  81.  
  82. #include <api/amiga_api.h>
  83. #include <api/amiga_libcallentry.h>
  84. #include <api/allocdatabuffer.h>
  85.  
  86. #include <api/apicalls.h>
  87.  
  88. #include <net/if_protos.h>
  89.  
  90. #include <amitcp/socketbasetags.h>
  91.  
  92. #include <kern/uipc_domain_protos.h>
  93. #include <kern/uipc_socket_protos.h>
  94. #include <kern/uipc_socket2_protos.h>
  95.  
  96. /* Local protos */
  97. static int selscan(struct SocketBase *p, 
  98.            fd_set *in, fd_set *ou, fd_set *ex, fd_mask *obits,
  99.            int nfd, int *retval, int *selitemcount_p);
  100. void selenter(struct SocketBase * p, struct newselitem ** hdr);
  101. static void unselect(register struct newselbuf * sb);
  102. void selwakeup(struct newselitem **hdr);
  103. static int soo_select(struct socket *so, int which, struct SocketBase *p);
  104. static int countSockets(struct SocketBase * libPtr, struct socket * so);
  105.  
  106. /*
  107.  * itimerfix copied from bsdss/server/kern/kern_time.c. since fields
  108.  * in struct timeval in amiga are ULONGs, values less than zero need
  109.  * not be checked. the second check, timeval less than resolution of
  110.  * the clock is not needed in amiga...hmm, is removed also.
  111.  */
  112. static inline int itimerfix(struct timeval *tv)
  113. {
  114.     if (tv->tv_sec > 100000000 || tv->tv_usec >= 1000000)
  115.         return (EINVAL);
  116. /*    if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
  117.         tv->tv_usec = tick;
  118. */    return (0);
  119. }
  120.  
  121. /*
  122.  * ffs() copied directly from bsdss/server/kern/subr_xxx.c
  123.  */
  124. static inline int ffs(register long mask)
  125. {
  126.   register int bit;
  127.  
  128.   if (!mask)
  129.     return(0);
  130.   for (bit = 1;; ++bit) {
  131.     if (mask&0x01)
  132.       return(bit);
  133.     mask >>= 1;
  134.   }
  135.   /* NOT REACHED */
  136. }
  137.  
  138.  
  139. /*
  140.  * Ioctl system call
  141.  */
  142.  
  143. LONG SAVEDS RAF4(_IoctlSocket,
  144.          struct SocketBase *,    libPtr,    a6,
  145.          LONG,            fdes,    d0,
  146.          ULONG,        cmd,    d1,
  147.          caddr_t,        data,    a0)
  148. #if 0
  149. {
  150. #endif
  151.  
  152.   register int error;
  153.   register u_int size;
  154.   struct socket *so;
  155.  
  156.   /*
  157.    * Note: Syscall semaphore is essential here if two processes can access
  158.    * the same socket. (can it be changed to spl_? ?)
  159.    */
  160.   CHECK_TASK();
  161.   ObtainSyscallSemaphore(libPtr);
  162.   
  163.   if (error = getSock(libPtr, fdes, &so))
  164.     goto Return;
  165.  
  166.   /*
  167.    * Interpret high order word to get size of the user data area
  168.    */
  169.   size = IOCPARM_LEN(cmd);
  170.   if (size == 0 || size > IOCPARM_MAX) {
  171.     error = ENOTTY;
  172.     goto Return;
  173.   }
  174.   if (!(cmd & IOC_IN) && cmd & IOC_OUT)
  175.     /*
  176.      * Zero the buffer so the user always
  177.      * gets back something deterministic.
  178.      */
  179.     bzero(data, size);
  180.   
  181.   switch (cmd) {
  182.   case FIOCLEX:
  183.   case FIONCLEX:        /* should this return error ???? */
  184.     goto Return;
  185.  
  186.   case FIOSETOWN:
  187.   case SIOCSPGRP:
  188.     /*
  189.      * data is a struct Task **, find corresponding SocketBase * and set owner
  190.      */
  191.     so->so_pgid = FindSocketBase(*(struct Task **)data);
  192.     goto Return;
  193.     
  194.   case FIOGETOWN:
  195.   case SIOCGPGRP:
  196.     if (so->so_pgid)
  197.       *(struct Task **)data = so->so_pgid->thisTask;
  198.     else
  199.       *(struct Task **)data = NULL;
  200.     goto Return;
  201.  
  202.   case FIONBIO:
  203.     if (*(int *)data)
  204.       so->so_state |= SS_NBIO;
  205.     else
  206.       so->so_state &= ~SS_NBIO;
  207.     goto Return;
  208.     
  209.   case FIOASYNC:
  210.     if (*(int *)data) {
  211.       so->so_state |= SS_ASYNC;
  212.       so->so_rcv.sb_flags |= SB_ASYNC;
  213.       so->so_snd.sb_flags |= SB_ASYNC;
  214.     } else {
  215.       so->so_state &= ~SS_ASYNC;
  216.       so->so_rcv.sb_flags &= ~SB_ASYNC;
  217.       so->so_snd.sb_flags &= ~SB_ASYNC;
  218.     }
  219.     goto Return;
  220.     
  221.   case FIONREAD:
  222.     *(int *)data = so->so_rcv.sb_cc;
  223.     goto Return;
  224.     
  225.   case SIOCATMARK:
  226.     *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
  227.     goto Return;
  228.   }
  229.  
  230.   /*
  231.    * Interface/routing/protocol specific ioctls:
  232.    * interface and routing ioctls should have a
  233.    * different entry since a socket's unnecessary -- not really,
  234.    * ifioctl needs the socket (?)
  235.    */
  236.   if ((IOCGROUP(cmd) & 0XDF) == 'I') {
  237.     error = (ifioctl(so, cmd, data));
  238.     goto Return;
  239.   }
  240.   if (IOCGROUP(cmd) == 'r') {
  241.     error = (rtioctl(cmd, data));
  242.     goto Return;
  243.   }
  244.   error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 
  245.       (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0));
  246.  
  247.  Return:
  248.   ReleaseSyscallSemaphore(libPtr);
  249.   API_STD_RETURN(error, 0);
  250. }
  251.  
  252.  
  253. /*
  254.  *  Semaphore to prevent select buffers from simultaneous modifications
  255.  */
  256. struct SignalSemaphore select_semaphore = { 0 };
  257.  
  258. struct newselbuf {
  259.   int s_state;
  260. #define    SB_CLEAR    0        /* wait condition cleared */
  261. #define    SB_WILLWAIT    1        /* will wait if not cleared */
  262. #define    SB_WAITING    2        /* waiting - wake up */
  263.   int s_count;
  264.   struct newselitem {
  265.     struct    newselitem  *    si_next;    /* next selbuf in item chain */
  266.     struct    newselitem **    si_prev;    /* back pointer */
  267.     struct    newselbuf   *    si_selbuf;    /* 'thread' waiting */
  268.   } s_item[0]; /* selitems are allocated at select when right
  269.           number of descriptors are known */
  270. };
  271.  
  272. void select_init(void)
  273. {
  274.   InitSemaphore(&select_semaphore);
  275. }
  276.  
  277. /*
  278.  *  symbolic names FREAD and FWRITE aren'n needed anywhere else if only
  279.  *  socket descriptors are in use.
  280.  */
  281. #define FREAD    0x1
  282. #define FWRITE    0x2
  283.  
  284. /*
  285.  * Select(), selscan(), selenter(), selwakeup() and unselect() are taken from
  286.  * ../server/kern/sys_generic.h in bsdss distribution. soo_select() is
  287.  * taken from ../server/kern/sys_socket.h, same distribution.
  288.  */
  289.  
  290. /* 
  291.  * Althrough the fd_set is used as the type of the masks, the size
  292.  * of the fd_set is not fixed, and is indeed calculated from nfds.
  293.  */
  294. LONG SAVEDS RAF7(_WaitSelect,
  295.          struct SocketBase *,    libPtr,        a6,
  296.          ULONG,            nfds,        d0,
  297.          fd_set *,        readfds,    a0,
  298.          fd_set *,        writefds,    a1,
  299.          fd_set *,        exeptfds,    a2,
  300.          struct timeval *,    timeout,    a3,
  301.          ULONG *,        sigmp,        d1)
  302. #if 0
  303. {
  304. #endif
  305.   
  306.   fd_mask * obits;
  307.   u_int obitsize;  /* in bytes */
  308.   int error, retv