#define KERNEL
#define _INTERNAL_FILE
#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
#include <user.h>
#include <sys/syslog.h>
#include <errno.h>
extern int errno;
#include <proto/socket.h>
/*#include <sys/syslog.h>*/
/*#include <stdio.h>*/

#include <proto/exec.h>
#define u (*((struct user *)((struct Task *)(FindTask(0))->tc_TrapData)))
extern struct file *_getsock(int);

#if 1
static int findsock(int s);
#else
static int findsock(int *fdlist, int s);
#endif

int WaitSelect(int sk, fd_set *fst, fd_set *snd, fd_set *trd, struct timeval *tme, ULONG *maskp) {
    struct file *fp= _getsock(sk-1), *fp2;
    int sock = 64;
    fd_set first,second,third;
    int i,err,fd2;

    /* remap the fd_sets from ixemul.library's into AmiTCP's socket numbers */
    for (i=0; i < howmany(FD_SETSIZE,NFDBITS);i++) {
      if (FD_ISSET(i,fst)) {
	fp2=_getsock(i);
	if (fp2->f_type == DTYPE_SOCKET) {
	    /*syslog(LOG_DEBUG,"fd %d has COMM socket %d\n",i,(int)fp2->f_so);*/
	    FD_SET((int)fp2->f_so,&first);
	}
	else {
	    /*syslog(LOG_DEBUG,"IX->TCP found regular fd %d\n",i);*/
	    FD_SET(i,&first);
	}
      }
      if (FD_ISSET(i,trd)) {
	fp2=_getsock(i);
	if (fp2->f_type == DTYPE_SOCKET) {
	    FD_SET((int)fp2->f_so,&third);
	    /*syslog(LOG_DEBUG,"fd %d has COMM socket %d\n",i,(int)fp2->f_so);*/
	}
	else {
	    /*syslog(LOG_DEBUG,"IX->TCP found regular fd %d\n",i);*/
	    FD_SET(i,&third);
	}
      }
      if (FD_ISSET(i,snd)) {
	fp2=_getsock(i);
	if (fp2->f_type == DTYPE_SOCKET) {
	    FD_SET((int)fp2->f_so,&second);
	    /*syslog(LOG_DEBUG,"fd %d has COMM socket %d\n",i,(int)fp2->f_so);*/
	}
	else {
	    /*syslog(LOG_DEBUG,"IX->TCP found regular fd %d\n",i);*/
	    FD_SET(i,&second);
	}
       }
    }/*for */

    /* hack extraordinaire!! */
    if (fp && fp->f_type == DTYPE_SOCKET)
	sock=(int)fp->f_so+1;
    else
	sock=NOFILE; /* hopefully this is big enough */

    err=TCP_WaitSelect(sock,&first,&second,&third,tme,maskp);

    #if 0 /*doesn't work (locks up) */
    FD_ZERO(fst);
    FD_ZERO(snd);
    FD_ZERO(trd);
    #endif

    /* map back the fd_sets from AmiTCP to ixemul.library's */
    for (i=0; i < howmany(FD_SETSIZE,NFDBITS);i++) {
      if (FD_ISSET(i,&first)) {
	fd2=findsock(i);
	if (fd2 != -1) {
	    /*syslog(LOG_DEBUG,"COMM socket %d has fd %d\n",i,fd2);*/
	    FD_SET(fd2,fst);
	}
	else {
	    /*syslog(LOG_DEBUG,"TCP->IX found regular fd %d\n",i);*/
	    FD_SET(i,fst);
	}
      }
      /*else FD_CLR(i,fst); */

      if (FD_ISSET(i,&third)) {
	fd2=findsock(i);
	if (fd2 != -1) {
	    /*syslog(LOG_DEBUG,"COMM socket %d has fd %d\n",i,fd2);*/
	    FD_SET(fd2,trd);
	}
	else {
	    /*syslog(LOG_DEBUG,"TCP->IX found regular fd %d\n",i);*/
	    FD_SET(i,trd);
	}
      }
      /*else FD_CLR(i,trd);*/

      if (FD_ISSET(i,&second)) {
	fd2=findsock(i);
	if (fd2 != -1) {
	    /*syslog(LOG_DEBUG,"COMM socket %d has fd %d",i,fd2);*/
	    FD_SET(fd2,snd);
	}
	else {
	    /*syslog(LOG_DEBUG,"TCP->IX found regular fd %d\n",i);*/
	    FD_SET(i,snd);
	}
      }
      /* else FD_CLR(i,snd); */

    }/*for */
    return err;
}


#if 1

static int findsock(int s) {

  struct file *fp;
  int i;

  for (i=0; i < NOFILE; i++) {
    fp = u.u_ofile[i];
    if (fp && fp->f_type == DTYPE_SOCKET && fp->f_so == (struct socket *)s) {
	return i;
    }
  }
  errno = EBADF;
  return -1;
}
#else
static int findsock(int *fdlist, int s) {

  struct file *fp;
  int i;

  for (i=0; i < howmany(FD_SETSIZE,NFDBITS); i++) {
    if (fdlist[i] == s) {
      return i;
    }
  }
  errno = EBADF;
  /*printf("cannot find socket with fd %d\n",s);*/
  return -1;
}
#endif

