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 >
Wrap
C/C++ Source or Header
|
1994-03-22
|
24KB
|
1,013 lines
RCS_ID_C="$Id: amiga_generic.c,v 3.6 1994/03/22 08:41:36 jraja Exp $";
/*
* Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
* Helsinki University of Technology, Finland.
* All rights reserved.
*
* Created: Fri Feb 12 13:26:55 1993 too
* Last modified: Wed Feb 2 21:35:39 1994 ppessi
*
* HISTORY
* $Log: amiga_generic.c,v $
* Revision 3.6 1994/03/22 08:41:36 jraja
* Added calls to the libPtr->fdCallback to the appropriate places.
*
* Revision 3.5 1994/02/03 04:10:55 ppessi
* Changed the interface IOCTL codes
*
* Revision 3.4 1994/01/20 02:10:36 jraja
* Added support for 0 domain for ObtainSocket() if id is unique.
*
* Revision 3.3 1994/01/12 07:35:25 jraja
* Moved dtable functions (getLastSockFd(), _SetDTableSize() and
* _getdtablesize()) to amiga_generic2.c.
*
* Revision 3.2 1994/01/07 15:40:29 too
* Bug fixes after revision 3.1. Now tested.
*
* Revision 3.1 1994/01/04 14:38:35 too
* Added static function getLastSock(). Revised Dup2Socket, CloseSocket,
* SetDTableSize, ObtainSocket and ReleaseSocket to utilize socket usage
* bitmask. Changed behaviour of Dup2Socket when fd1 == -1.
* Moved some functions to amiga_generic2.c
*
* Revision 1.61 1993/12/22 08:16:22 jraja
* Cleaned some types, added 'static' to local functions.
*
* Revision 1.60 1993/10/16 17:20:49 too
* Fixed copying bug in SetDTableSize
*
* Revision 1.59 1993/09/14 22:15:16 jraja
* Added zeroing of obits in WaitSelect() if new memory is allocated for it.
*
* Revision 1.58 1993/08/01 22:15:07 ppessi
* Changed CloseSocket() to use api/apicall.h protos.
*
* Revision 1.57 1993/07/13 21:58:59 ppessi
* Added internal prototypes; changed interface ioctl codes to 'I'
*
* Revision 1.56 1993/06/13 16:38:43 too
* Added range check for fd2 in Dup2Socket()
*
* Revision 1.55 1993/06/11 20:18:09 too
* Added Dup2Socket(). Chahanged ioctl to IoctlSocket()
* Made function countSockets() which is needed to determine if last reference
* to that socket is given away.
*
* Revision 1.54 1993/06/07 12:37:20 too
* Changed inet_ntoa, netdatabase functions and WaitSelect() use
* separate buffers for their dynamic buffers
*
*/
#include <conf.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socketvar.h>
#include <sys/kernel.h>
#include <sys/ioctl.h>
#include <sys/protosw.h>
#include <sys/malloc.h>
#include <sys/synch.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <net/route.h>
#include <kern/amiga_includes.h>
#include <api/amiga_api.h>
#include <api/amiga_libcallentry.h>
#include <api/allocdatabuffer.h>
#include <api/apicalls.h>
#include <net/if_protos.h>
#include <amitcp/socketbasetags.h>
#include <kern/uipc_domain_protos.h>
#include <kern/uipc_socket_protos.h>
#include <kern/uipc_socket2_protos.h>
/* Local protos */
static int selscan(struct SocketBase *p,
fd_set *in, fd_set *ou, fd_set *ex, fd_mask *obits,
int nfd, int *retval, int *selitemcount_p);
void selenter(struct SocketBase * p, struct newselitem ** hdr);
static void unselect(register struct newselbuf * sb);
void selwakeup(struct newselitem **hdr);
static int soo_select(struct socket *so, int which, struct SocketBase *p);
static int countSockets(struct SocketBase * libPtr, struct socket * so);
/*
* itimerfix copied from bsdss/server/kern/kern_time.c. since fields
* in struct timeval in amiga are ULONGs, values less than zero need
* not be checked. the second check, timeval less than resolution of
* the clock is not needed in amiga...hmm, is removed also.
*/
static inline int itimerfix(struct timeval *tv)
{
if (tv->tv_sec > 100000000 || tv->tv_usec >= 1000000)
return (EINVAL);
/* if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
tv->tv_usec = tick;
*/ return (0);
}
/*
* ffs() copied directly from bsdss/server/kern/subr_xxx.c
*/
static inline int ffs(register long mask)
{
register int bit;
if (!mask)
return(0);
for (bit = 1;; ++bit) {
if (mask&0x01)
return(bit);
mask >>= 1;
}
/* NOT REACHED */
}
/*
* Ioctl system call
*/
LONG SAVEDS RAF4(_IoctlSocket,
struct SocketBase *, libPtr, a6,
LONG, fdes, d0,
ULONG, cmd, d1,
caddr_t, data, a0)
#if 0
{
#endif
register int error;
register u_int size;
struct socket *so;
/*
* Note: Syscall semaphore is essential here if two processes can access
* the same socket. (can it be changed to spl_? ?)
*/
CHECK_TASK();
ObtainSyscallSemaphore(libPtr);
if (error = getSock(libPtr, fdes, &so))
goto Return;
/*
* Interpret high order word to get size of the user data area
*/
size = IOCPARM_LEN(cmd);
if (size == 0 || size > IOCPARM_MAX) {
error = ENOTTY;
goto Return;
}
if (!(cmd & IOC_IN) && cmd & IOC_OUT)
/*
* Zero the buffer so the user always
* gets back something deterministic.
*/
bzero(data, size);
switch (cmd) {
case FIOCLEX:
case FIONCLEX: /* should this return error ???? */
goto Return;
case FIOSETOWN:
case SIOCSPGRP:
/*
* data is a struct Task **, find corresponding SocketBase * and set owner
*/
so->so_pgid = FindSocketBase(*(struct Task **)data);
goto Return;
case FIOGETOWN:
case SIOCGPGRP:
if (so->so_pgid)
*(struct Task **)data = so->so_pgid->thisTask;
else
*(struct Task **)data = NULL;
goto Return;
case FIONBIO:
if (*(int *)data)
so->so_state |= SS_NBIO;
else
so->so_state &= ~SS_NBIO;
goto Return;
case FIOASYNC:
if (*(int *)data) {
so->so_state |= SS_ASYNC;
so->so_rcv.sb_flags |= SB_ASYNC;
so->so_snd.sb_flags |= SB_ASYNC;
} else {
so->so_state &= ~SS_ASYNC;
so->so_rcv.sb_flags &= ~SB_ASYNC;
so->so_snd.sb_flags &= ~SB_ASYNC;
}
goto Return;
case FIONREAD:
*(int *)data = so->so_rcv.sb_cc;
goto Return;
case SIOCATMARK:
*(int *)data = (so->so_state&SS_RCVATMARK) != 0;
goto Return;
}
/*
* Interface/routing/protocol specific ioctls:
* interface and routing ioctls should have a
* different entry since a socket's unnecessary -- not really,
* ifioctl needs the socket (?)
*/
if ((IOCGROUP(cmd) & 0XDF) == 'I') {
error = (ifioctl(so, cmd, data));
goto Return;
}
if (IOCGROUP(cmd) == 'r') {
error = (rtioctl(cmd, data));
goto Return;
}
error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
(struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0));
Return:
ReleaseSyscallSemaphore(libPtr);
API_STD_RETURN(error, 0);
}
/*
* Semaphore to prevent select buffers from simultaneous modifications
*/
struct SignalSemaphore select_semaphore = { 0 };
struct newselbuf {
int s_state;
#define SB_CLEAR 0 /* wait condition cleared */
#define SB_WILLWAIT 1 /* will wait if not cleared */
#define SB_WAITING 2 /* waiting - wake up */
int s_count;
struct newselitem {
struct newselitem * si_next; /* next selbuf in item chain */
struct newselitem ** si_prev; /* back pointer */
struct newselbuf * si_selbuf; /* 'thread' waiting */
} s_item[0]; /* selitems are allocated at select when right
number of descriptors are known */
};
void select_init(void)
{
InitSemaphore(&select_semaphore);
}
/*
* symbolic names FREAD and FWRITE aren'n needed anywhere else if only
* socket descriptors are in use.
*/
#define FREAD 0x1
#define FWRITE 0x2
/*
* Select(), selscan(), selenter(), selwakeup() and unselect() are taken from
* ../server/kern/sys_generic.h in bsdss distribution. soo_select() is
* taken from ../server/kern/sys_socket.h, same distribution.
*/
/*
* Althrough the fd_set is used as the type of the masks, the size
* of the fd_set is not fixed, and is indeed calculated from nfds.
*/
LONG SAVEDS RAF7(_WaitSelect,
struct SocketBase *, libPtr, a6,
ULONG, nfds, d0,
fd_set *, readfds, a0,
fd_set *, writefds, a1,
fd_set *, exeptfds, a2,
struct timeval *, timeout, a3,
ULONG *, sigmp, d1)
#if 0
{
#endif
fd_mask * obits;
u_int obitsize; /* in bytes */
int error, retv