#define NOT_REDEFINE

#include "squid.h"

int snprintf(char *buf, size_t len, const char *format,...);
#define howmany(x, y)   (((x)+((y)-1))/(y))


#ifdef DEBUG_SPY

 #define INCL_DOS
 #include <os2.h>

static int  writeBlocOfData(int idData[7],char *buff, int len);
static int  readBlocOfData(int idData[7],char *buff, int &len);
static int CheckParam(int idFunc,int paramid,int InOut, char *buff, int &len);
static int Ncalls =0;
static int Nbytes = 0;
#define iDSELECT       0
#define iDGETSOCKNAME  1
#define iDGETTIMEOFDAY 2
#define iDGETHOSTNAME  3
#define iDGETHOSTBYNAME  4
#define iDGETHOSTBYADDR  5
#define iDSOCKERRNO      6
#define iDINET_NTOA      7
#define iDINET_ADDR      8
#define iDGETSERVBYNAME  9
#define iDRECV           10
#define iDRECVFROM       11
#define iDBIND           12
#define iDSEND           13
#define iDIOCTL3         14
#define iDIOCTL4         15
#define iDACCEPT         16
#define iDSOCKET         17
#define iDSOCLOSE        18
#define iDSENDTO         19
#define iDSETSOCKOPT     20
#define iDGETSOCKOPT     21
#define iDLISTEN         22
#define iDCONNECT        23

int  DebugConnect(int s, const struct sockaddr *name, int namelen)
{ int rc,l0,l,t,t0;
   t0 = clock();
   l = sizeof(int);
   CheckParam(iDCONNECT ,0,0, (char *)&s, l);
   l = sizeof(int);
   CheckParam(iDCONNECT ,2,0, (char *)&namelen, l);
   if(name) l = namelen;
   else     l = 0;
   CheckParam(iDCONNECT ,1,0, (char *)name, l);
#if DEBUG_SPY
;
#else
   rc = connect(s, (sockaddr*)name,namelen);
#endif
   if(name) l = namelen;
   else     l = 0;
   CheckParam(iDCONNECT ,1,1, (char *)name, l);

   l = sizeof(int);
   CheckParam(iDCONNECT,2,1, (char *)&rc, l);
   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDCONNECT,100,1, (char *)&t, l);

#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;

}

int  DebugListen(int s, int backlog)
{ int rc,l0,l,t,t0;
   t0 = clock();
   l = sizeof(int);
   CheckParam(iDLISTEN ,0,0, (char *)&s, l);
   l = sizeof(int);
   CheckParam(iDLISTEN,1,0, (char *)&backlog, l);

#if DEBUG_SPY
;
#else
   rc = listen(s, backlog);
#endif
   l = sizeof(int);
   CheckParam(iDLISTEN,2,1, (char *)&rc, l);
   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDLISTEN,100,1, (char *)&t, l);

#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;

}

int DebugGetsockopt(int s, int level, int optname,
                           char * optval, int *optlen)
{ int rc,l0,l,t,t0;
   t0 = clock();
 debug(99, 0) ("**Getsockopt: Socket%i level %x optname %x  optlen=%i\n",s,level,optname,*optlen);
   l = sizeof(int);
   CheckParam(iDGETSOCKOPT ,0,0, (char *)&s, l);
   l = sizeof(int);
   CheckParam(iDGETSOCKOPT ,1,0, (char *)&level, l);
   l = sizeof(int);
   CheckParam(iDGETSOCKOPT ,2,0, (char *)&optname, l);
   if(optlen) l = sizeof(int);
   else       l = 0;
   CheckParam(iDGETSOCKOPT ,4,0, (char *)optlen, l);
#if DEBUG_SPY
;
#else
   rc = getsockopt(s, level, optname, (char *)optval, optlen);
 debug(99, 0) ("**Getsockopt: rc %x optlen%i opt %x\n",rc,*optlen,*((int *)optval));
#endif
   if(optlen) l = sizeof(int);
   else       l = 0;
   CheckParam(iDGETSOCKOPT ,4,1, (char *)optlen, l);
   l = 0;
   if(optlen)
   {  if(*optlen && optval) l = *optlen;
      CheckParam(iDGETSOCKOPT ,4,1, (char *)optval, l);
   }
   l = sizeof(int);
   CheckParam(iDGETSOCKOPT,5,1, (char *)&rc, l);
   if(optval) l = *optlen;
   else       l = 0;
   CheckParam(iDGETSOCKOPT ,3,1, (char *)optval, l);

   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDGETSOCKOPT,100,1, (char *)&t, l);
#if DEBUG_SPY
 debug(99, 0) ("**Getsockopt: rc %x optlen%i opt %x\n",rc,*optlen,*((int *)optval));
#endif

#if DEBUG_SPY
   if(t>1000) t = 1000;
   DosSleep(t);
#endif

  return rc;
}

int DebugSetsockopt (int  s, int level, int optname,
                           const char * optval, int optlen)
{ int rc,l0,l,t,t0;
   t0 = clock();
 debug(99, 0) ("**Setsockopt: Socket%i level %x optname %x optlen%i opt %x\n",s,level,optname,optlen,*((int *)optval));
   l = sizeof(int);
   CheckParam(iDSETSOCKOPT ,0,0, (char *)&s, l);
   l = sizeof(int);
   CheckParam(iDSETSOCKOPT ,1,0, (char *)&level, l);
   l = sizeof(int);
   CheckParam(iDSETSOCKOPT ,2,0, (char *)&optname, l);
   l = sizeof(int);
   CheckParam(iDSETSOCKOPT ,4,0, (char *)&optlen, l);
   if(optval) l = optlen;
   else       l = 0;
   CheckParam(iDSETSOCKOPT ,3,0, (char *)optval, l);
#if DEBUG_SPY
;
#else
   rc = setsockopt(s, level, optname, (char *)optval, optlen);
#endif
   l = sizeof(int);
   CheckParam(iDSETSOCKOPT,5,1, (char *)&rc, l);
   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDSETSOCKOPT,100,1, (char *)&t, l);

#if DEBUG_SPY
    if(t > 10000) t = 10000;
    DosSleep(t);
#endif
 debug(99, 0) ("**Setsockopt: rc %i \n",rc);

  return rc;

}

int DebugSoclose( int socket)
{ int rc,l0,l,t,t0;
   t0 = clock();
   l = sizeof(int);
   CheckParam(iDSOCKET ,0,0, (char *)&socket, l);
#if DEBUG_SPY
;
#else
   rc = soclose(socket);
#endif
   l = sizeof(int);
   CheckParam(iDSOCKET,1,1, (char *)&rc, l);
   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDSOCKET,100,1, (char *)&t, l);

#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;

}

int  DebugSocket(int af, int type, int protocol)
{ int rc,l0,l,t,t0;
   t0 = clock();
   l = sizeof(int);
   CheckParam(iDSOCKET ,0,0, (char *)&af, l);
   l = sizeof(int);
   CheckParam(iDSOCKET ,1,0, (char *)&type, l);
   l = sizeof(int);
   CheckParam(iDSOCKET ,2,0, (char *)&protocol, l);

#if DEBUG_SPY
;
#else
   rc = socket(af,type, protocol);
#endif

   l = sizeof(int);
   CheckParam(iDSOCKET,3,1, (char *)&rc, l);

   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDSOCKET,100,1, (char *)&t, l);

#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;
}

int  DebugAccept(int s, struct sockaddr *addr, int *addrlen)
{ int rc,l0,l,t,t0;
   t0 = clock();
   l = sizeof(int);
   CheckParam(iDACCEPT ,0,0, (char *)&s, l);
   if(addrlen) l = sizeof(int);
   else        l = 0;
   CheckParam(iDACCEPT ,2,0, (char *)addrlen, l);
//   if(addr && addrlen)  l = *addrlen;
//   else        l = 0;
//   CheckParam(iDACCEPT ,1,0, (char *)addr, l);
#if DEBUG_SPY
;
#else
   rc = accept(s,addr, addrlen);
#endif
   if(addrlen)
   {   l=1;
       CheckParam(iDACCEPT,2,1, (char *)addrlen, l);
       if(*addrlen > 0 && addr)
       {  l=*addrlen;
          CheckParam(iDACCEPT,1,1, (char *)addr, l);
       }
   }

   l = sizeof(int);
   CheckParam(iDACCEPT,3,1, (char *)&rc, l);

   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDSEND,100,1, (char *)&t, l);

#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;
}

int  DebugIoctl(int s, int cmd, char* data, int len)
{ int rc,l0,l,t,t0;
   t0 = clock();
   l = sizeof(int);
   CheckParam(iDIOCTL4,0,0, (char *)&s, l);
   l = sizeof(int);
   CheckParam(iDIOCTL4,1,0, (char *)&cmd, l);
   l = sizeof(int);
   CheckParam(iDIOCTL4,3,0, (char *)&len, l);
   if(data) l = len;
   else     l = 0;
   CheckParam(iDIOCTL4,3,0, (char *)data, l);
#if DEBUG_SPY
   ;
#else
   rc = ioctl(s,cmd, data,len);
#endif
   l = sizeof(int);
   CheckParam(iDIOCTL4,4,1, (char *)&rc, l);

   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDIOCTL4,100,1, (char *)&t, l);
#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;
}

int  DebugIoctl(int s, int cmd, char* data)
{ int rc,l0,l,t,t0;

   t0 = clock();
   l = sizeof(int);
   CheckParam(iDIOCTL3,0,0, (char *)&s, l);
   l = sizeof(int);
   CheckParam(iDIOCTL3,1,0, (char *)&cmd, l);

   fatalf("DebugIoctl: жопа - 3 параметра\n");
   return -1;
}


int  DebugSend(int s, const char * buf, int len, int flags)
{ int rc,l0,l,t,t0;

   t0 = clock();
   l = sizeof(int);
   CheckParam(iDSEND,0,0, (char *)&s, l);
   l = sizeof(int);
   CheckParam(iDSEND,2,0, (char *)&len, l);
   if(buf) l = len;
   else    l = 0;
   CheckParam(iDSEND,1,0, (char *)buf, l);
   l = sizeof(int);
   CheckParam(iDSEND,3,0, (char *)&flags, l);
#if DEBUG_SPY
   ;
#else
   rc = send(s,(char *)buf,len,flags);
#endif
   l = sizeof(int);
   CheckParam(iDSEND,3,1, (char *)&rc, l);
   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDSEND,100,1, (char *)&t, l);
#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;

}

int DebugSendto (int  s, const char * buf, int len, int flags,
                       const struct sockaddr *to, int tolen)
{ int rc,l0,l,t,t0;

   t0 = clock();
   l = sizeof(int);
   CheckParam(iDSENDTO,0,0, (char *)&s, l);
   l = sizeof(int);
   CheckParam(iDSENDTO,2,0, (char *)&len, l);
   if(buf) l = len;
   else    l = 0;
   CheckParam(iDSENDTO,1,0, (char *)buf, l);
   l = sizeof(int);
   CheckParam(iDSENDTO,3,0, (char *)&flags, l);

   l = sizeof(int);
   CheckParam(iDSENDTO,5,0, (char *)&tolen, l);
   if(to) l = tolen;
   else   l = 0;
   CheckParam(iDSENDTO,4,0, (char *)to, l);

#if DEBUG_SPY
   ;
#else
   rc = sendto(s,(char *)buf,len,flags,(sockaddr*)to,tolen);
#endif
   l = sizeof(int);
   CheckParam(iDSENDTO,6,1, (char *)&rc, l);
   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDSENDTO,100,1, (char *)&t, l);
#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;

}

int DebugBind(int s, const struct sockaddr *addr, int namelen)
{ int rc,l0,l,t,t0;

   t0 = clock();
   l = sizeof(int);
   CheckParam(iDBIND,0,0, (char *)&s, l);
   l = sizeof(int);
   CheckParam(iDBIND,2,0, (char *)&namelen, l);
   if(addr)  l = namelen;
   else      l = 0;
   CheckParam(iDBIND,1,0, (char *)addr, l);
#if DEBUG_SPY
   ;
#else
   rc = bind(s,(sockaddr*)addr,namelen);
#endif
   l = sizeof(int);
   CheckParam(iDBIND,3,1, (char *)&rc, l);
   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDBIND,100,1, (char *)&t, l);
#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;

}

int  DebugRecvfrom(int s, char * buf, int len, int flags,
                struct sockaddr *from, int * fromlen)
{ int rc,l0,l,t,t0;

   t0 = clock();
   l = sizeof(int);
   CheckParam(iDRECVFROM,0,0, (char *)&s, l);
   l = sizeof(int);
   CheckParam(iDRECVFROM,2,0, (char *)&len, l);
   l = sizeof(int);
   CheckParam(iDRECVFROM,3,0, (char *)&flags, l);

   if(fromlen) l = sizeof(int);
   else        l = 0;
   CheckParam(iDRECVFROM,5,0, (char *)fromlen, l);
   if(from && fromlen)    l = *fromlen;
   else                   l = 0;
   CheckParam(iDRECVFROM,4,0, (char *)from, l);
#if DEBUG_SPY
   l=1;
#else
   rc = recvfrom(s,buf,len,flags,from,fromlen);

   if(buf) l = len;
   else l = 0;
#endif
   l = sizeof(int);
   CheckParam(iDRECVFROM,6,1, (char *)&rc, l);
   if(rc > 0)
   {   l = rc;
       CheckParam(iDRECVFROM,1,1, (char *)buf, l);
   }
   if(fromlen) l = sizeof(int);
   else        l = 0;
   CheckParam(iDRECVFROM,5,1, (char *)fromlen, l);
   if(from && fromlen)    l = *fromlen;
   else                   l = 0;
   CheckParam(iDRECVFROM,4,1, (char *)from, l);

   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDRECVFROM,100,1, (char *)&t, l);
#if DEBUG_SPY
    if(t>1000) t = 1000;
     DosSleep(t);
#endif

  return rc;

}

int  DebugRecv(int s, char * buf, int len, int flags)
{ int rc,l0,l,t,t0;

   t0 = clock();
   l = sizeof(int);
   CheckParam(iDRECV,0,0, (char *)&s, l);
   l = sizeof(int);
   CheckParam(iDRECV,2,0, (char *)&len, l);
   l = sizeof(int);
   CheckParam(iDRECV,3,0, (char *)&flags, l);
#if DEBUG_SPY
   l=1;
#else
   rc = recv(s,buf,len,flags);

   if(buf) l = len;
   else l = 0;
#endif

   CheckParam(iDRECV,2,1, (char *)buf, l);
   l = sizeof(int);
   CheckParam(iDRECV,4,1, (char *)&rc, l);

   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDRECV,100,1, (char *)&t, l);
#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;
}

struct servent * DebugGetservbyname(const char * name, const char * proto)
{  int rc,l;
struct servent * prc;
static struct  servent  serv;
   prc = &serv;
   if(name)l = strlen(name)+1;
   else  l = 0;
   CheckParam(iDGETSERVBYNAME,0,0, (char *)name, l);
   if(proto)l = strlen(proto)+1;
   else  l = 0;
   CheckParam(iDGETSERVBYNAME,1,0, (char *)proto, l);
#if DEBUG_SPY
   l=1;
#else
   prc =getservbyname((char*)name, (char *)proto);
   if(prc) l = sizeof(struct  servent);
   else l = 0;
#endif

   CheckParam(iDINET_NTOA,1,1, (char *)prc, l);
   if(l == 0) prc = NULL;
   return prc;
}


unsigned long  DebugInet_addr(const char * cp)
{  int rc,l;

   if(cp)l = strlen(cp)+1;
   else  l = 0;
   CheckParam(iDINET_ADDR,0,0, (char *)cp, l);

#if DEBUG_SPY
   ;
#else
   rc = inet_addr((char *) cp);
#endif
   l = sizeof(int);
   CheckParam(iDINET_ADDR,0,1, (char *)&rc, l);
   return rc;
}

char *  DebugInet_ntoa(struct in_addr in)
{ int l0,l,t,t0;
static  char rcStr[20];
  char *prc;
  prc = &rcStr[0];
   t0 = clock();
   l = sizeof(struct in_addr);
   CheckParam(iDINET_NTOA,0,0, (char *)&in, l);

#if DEBUG_SPY
   l = 1;
#else
   prc = inet_ntoa(in);
   if(prc) l = strlen(prc)+1;
   else    l = 0;

#endif

   CheckParam(iDINET_NTOA,1,1, (char *)prc, l);
   if(l == 0) prc = NULL;

   return prc;
}

int  DebugSock_errno( void )
{  int rc,l;
#if DEBUG_SPY
;
#else
   rc = sock_errno();
#endif
   l = sizeof(int);
   CheckParam(iDSOCKERRNO,0,1, (char *)&rc, l);
   return rc;
}

struct hostent * DebugGethostbyaddr(const char * addr, int len, int type)
{ int l0,l,t,t0;
static  struct hostent sthost;
struct hostent *phost;
   phost = &sthost;
   t0 = clock();
   l = sizeof(int);
   CheckParam(iDGETHOSTBYADDR,1,0, (char *)&len, l);
   CheckParam(iDGETHOSTBYADDR,0,0, (char *)addr, len);
   l = sizeof(int);
   CheckParam(iDGETHOSTBYADDR,1,0, (char *)&type, l);
#if DEBUG_SPY
   l = 1;
   CheckParam(iDGETHOSTBYADDR,3,1, (char *)phost, l);
   if(l == 0) phost = NULL;

#else
   phost = gethostbyaddr((char *)addr,len,type);
   l = sizeof(struct hostent);
   if(phost == NULL) l = 0;
   CheckParam(iDGETHOSTBYADDR,3,1, (char *)phost, l);
#endif

   t = clock()-t0;
   l = sizeof(int);
   CheckParam(iDGETHOSTBYADDR,100,1, (char *)&t, l);
#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return phost;
}

struct hostent * DebugGethostbyname(const char * name)
{ int l0,l,t,t0;
static  struct hostent sthost;
struct hostent *phost;
   phost = &sthost;

   t0 = clock();
   l = sizeof(int);
   l = strlen(name)+1;
   CheckParam(iDGETHOSTBYNAME,0,0, (char *)name, l);
#if DEBUG_SPY
   l = 1;
   CheckParam(iDGETHOSTBYNAME,1,1, (char *)phost, l);
#else
   phost = gethostbyname((char *)name);
   l = sizeof(struct hostent);
   if(phost == NULL) l = 0;
   CheckParam(iDGETHOSTBYNAME,1,1, (char *)phost, l);
   if(l == 0) phost = NULL;

#endif

   t = clock()-t0;
   l = sizeof(t);
   CheckParam(iDGETHOSTBYNAME,100,1, (char *)&t, l);
#if DEBUG_SPY
   if(t>1000) t = 1000;
   DosSleep(t);
#endif

  return phost;
}

int DebugGethostname (char * name, int namelen)
{ int rc,l0,l,t,t0;
   t0 = clock();
   l = sizeof(int);
   CheckParam(iDGETHOSTNAME,1,0, (char *)&namelen, l);
#if DEBUG_SPY
;
#else
   rc = gethostname(name,namelen);
#endif
   l = sizeof(int);
   CheckParam(iDGETHOSTNAME,3,1, (char *)&rc, l);
   l = sizeof(struct timeval);
#if DEBUG_SPY
    l = 1;
#else
    l = strlen(name)+1;
#endif
   if(name == NULL) l = 0;
   CheckParam(iDGETHOSTNAME,0,1, (char *)name, l);

   t = clock()-t0;
   l = sizeof(t);
   CheckParam(iDGETHOSTNAME,100,1, (char *)&t, l);
#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;
}
int DebugGettimeofday (struct timeval * timev, struct timezone *timez)
{ int rc,l0,l,t,t0;
   t0 = clock();

   l = sizeof(struct timezone);
   if(timez == NULL) l = 0;
   CheckParam(iDGETTIMEOFDAY,1,0, (char *)timez, l);
#if DEBUG_SPY
;
#else
   rc = gettimeofday( timev, timez);
#endif
   l = sizeof(int);
   CheckParam(iDGETTIMEOFDAY,3,1, (char *)&rc, l);
   l = sizeof(struct timeval);
   if(timev == NULL) l = 0;
   CheckParam(iDGETTIMEOFDAY,3,1, (char *)timev, l);
   t = clock()-t0;
   l = sizeof(t);
   CheckParam(iDGETTIMEOFDAY,100,1, (char *)&t, l);
#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif

  return rc;
}

int DebugGetsockname( int s, struct sockaddr *name, int *namelen)
{ int rc,l0,l,t,t0;
   t0 = clock();
   l = sizeof(int);
   CheckParam(iDGETSOCKNAME,0,0, (char *)&s, l );
   l = sizeof(int);
//   CheckParam(iDGETSOCKNAME,2,0, (char *)&namelen, l );
   CheckParam(iDGETSOCKNAME,2,0, (char *)namelen, l );
#if DEBUG_SPY
;
#else
   rc = getsockname( s, name, namelen);
#endif
   l = sizeof(int);
   CheckParam(iDGETSOCKNAME,3,1, (char *)&rc, l);
   l = sizeof(struct sockaddr);
   if(name == NULL) l = 0;
   CheckParam(iDGETSOCKNAME,1,1, (char *)name, l);
   l = sizeof(int);
   if(namelen == NULL) l = 0;
   CheckParam(iDGETSOCKNAME,2,1, (char *)namelen, l);

   t = clock()-t0;
   l = sizeof(t);
   CheckParam(iDGETSOCKNAME,100,1, (char *)&t, l);
#if DEBUG_SPY
    if(t>1000) t = 1000;
    DosSleep(t);
#endif
  return rc;
}

//os2_select
int DebugSelect(int *s, int noreads, int nowrites, int noexepts, long timeout)
{ int num,l0,l,t,t0;
   t0 = clock();
   l = sizeof(int);
   CheckParam(iDSELECT,0,0, (char *)&noreads, l );
   l = sizeof(int);
   CheckParam(iDSELECT,1,0, (char *)&nowrites, l );
   l = sizeof(int);
   CheckParam(iDSELECT,2,0, (char *)&noexepts, l );
   l = sizeof(int);
   CheckParam(iDSELECT,3,0, (char *)&timeout, l );
#if DEBUG_SPY
;
#else
   num = select(s, noreads, nowrites, noexepts, timeout);
#endif
   l = sizeof(int);
   CheckParam(iDSELECT,5,1, (char *)&num, l);

   l = (noreads+nowrites+noexepts) * sizeof(int);
   CheckParam(iDSELECT,6,1, (char *)s, l);

   t = clock()-t0;
   l = sizeof(t);
   CheckParam(iDSELECT,100,1, (char *)&t, l);
#if DEBUG_SPY
   if(t>1000) t = 1000;
    DosSleep(t);
#endif
  return num;
}

#ifdef BSD_SELECT
int DebugSelectBSD(int nfds,  fd_set *readfds,  fd_set *writefds,  fd_set *exceptfds,  struct timeval *timeout)
{ int num,l0,l,t,t0;
   t0 = clock();
//   l0 = howmany(nfds, 32);
   l0 = sizeof(fd_set);
   l = sizeof(int);
   CheckParam(iDSELECT,0,0, (char *)&nfds, l );
   l = l0;
   if(readfds == NULL) l = 0;
   CheckParam(iDSELECT,1,0, (char *)readfds, l);
   l = l0;
   if(writefds == NULL) l = 0;
   CheckParam(iDSELECT,2,0, (char *)writefds, l);
   l = l0;
   if(exceptfds == NULL) l = 0;
   CheckParam(iDSELECT,3,0, (char *)exceptfds, l);
   l = sizeof(struct timeval);
   if(timeout == NULL) l = 0;
   CheckParam(iDSELECT,4,0, (char *)timeout, l);
#if DEBUG_SPY
;
#else
   num = select(nfds, readfds, writefds, exceptfds, timeout);
#endif
   l = sizeof(int);
   CheckParam(iDSELECT,5,1, (char *)&num, l);
   l = l0;
   if(readfds == NULL) l = 0;
   CheckParam(iDSELECT,1,1, (char *)readfds, l);
   l = l0;
   if(writefds == NULL) l = 0;
   CheckParam(iDSELECT,2,1, (char *)writefds, l);
   l = l0;
   if(exceptfds == NULL) l = 0;
   CheckParam(iDSELECT,3,1, (char *)exceptfds, l);
   l = sizeof(struct timeval);
   if(timeout == NULL) l = 0;
   CheckParam(iDSELECT,4,1, (char *)timeout, l);
   t = clock()-t0;
   l = sizeof(t);
   CheckParam(iDSELECT,100,1, (char *)&t, l);
#if DEBUG_SPY
   if(t>1000) t = 1000;
    DosSleep(t);
#endif
  return num;
}

#endif //BSD_SELECT
static char debugFileName[]="debug.spy";
static DebugMode=0;
static FILE *fp;
static int NumOfCalls[128];
int StartT;

int InitDebugSpy(int mode)
{  int i;
   for(i=0;i<128;i++)
      NumOfCalls[i] = 0;
   StartT = clock();
   DebugMode = mode;
  if(DebugMode)
   fp = fopen(debugFileName,"rb");
  else
   fp = fopen(debugFileName,"wb");
  return 0;
}
void _Optlink CloseDebugSpy(void)
{   fclose(fp);
}

/* InOut=0 - входной параметр => buff и len проверять */
/* InOut=1 - вЫодной параметр => buff и len НЕ проверять */
int CheckParam(int idFunc,int paramid,int InOut, char *buff, int &len)
{   int idData[7];
    int rc,lenbuf,i, deltaT;
static  char CheckBuff[61440];

if(FatalInProgress) return 2;

    Ncalls++;
    NumOfCalls[idFunc]++;
    deltaT = clock() - StartT;
    switch(DebugMode)
    { case 0:
       idData[0] = idFunc;
       idData[1] = paramid;
       idData[2] = InOut;
       idData[3] = len;
       idData[4] = NumOfCalls[idFunc];
       idData[5] = deltaT;
       idData[6] = Ncalls;
       rc =  writeBlocOfData(idData,buff,len);
       if(len >= sizeof(CheckBuff) )
             debug(99, 0) ("CheckParam: Please increase buffer %d to %d+1\n", sizeof(CheckBuff),len);

       break;
      case 1:
        rc = readBlocOfData(idData,CheckBuff,lenbuf);
        if(rc != 0)
         {  debug(99, 0) ("readBlocOfData: Error  %d, %s\n", rc,xstdio_strerror());
            fatalf("CheckParam: No more data (%i,%i) ?, Calls%i, bytes%i\n",idFunc, paramid,Ncalls,Nbytes);
         }
        if(idFunc != idData[0])
           fatalf("CheckParam: idFunc %d != %d (%i,%i), Calls%i, bytes%i\n",idFunc ,idData[0],idFunc, paramid,Ncalls,Nbytes);
        if(paramid != idData[1])
           fatalf("CheckParam: paramid %d != %d (%i,%i), Calls%i, bytes%i\n",paramid ,idData[1],idFunc, paramid,Ncalls,Nbytes);
        if(InOut != idData[2])
           fatalf("CheckParam: InOut %d != %d (%i,%i), Calls%i, bytes%i\n",
                       InOut ,idData[2],idFunc, paramid,Ncalls,Nbytes);
        if(NumOfCalls[idFunc] != idData[4])
           fatalf("CheckParam: NumOfCalls[idFunc]%d != %d (%i,%i), Calls%i, bytes%i\n",
                               NumOfCalls[idFunc] ,idData[4],idFunc, paramid,Ncalls,Nbytes);
        if(Ncalls != idData[6])
           fatalf("CheckParam: Ncalls%d != %d (%i,%i), Calls%i, bytes%i\n",
                               Ncalls ,idData[6],idFunc, paramid,Ncalls,Nbytes);

        if(InOut == 0)
        {  int l,isdiff=0;
           l = lenbuf;
           if(lenbuf > len) l = len;
           for(i=0;i<l;i++)
           {  if(CheckBuff[i] != buff[i])
              {  isdiff++;
              }
           }
           if(isdiff)
              debug(99, 0) ("CheckParam: CheckBuff[%i] != buff[%i] in %i bytes; (%i,%i), Calls%i, bytes%i\n",
                                   lenbuf, len, isdiff,idFunc, paramid,Ncalls,Nbytes);
           else
              if(lenbuf != len)
                    fatalf("CheckParam: Different Buffers length, though CheckBuff[%i] = buff[%i] in first %i bytes (%i,%i),\n Calls%i, bytes%i\n",
                                                   lenbuf, len, l,idFunc, paramid,Ncalls,Nbytes);
           if(isdiff)
           {  isdiff=0;
              for(i=0;i<l && isdiff < 8;i++)
              {  if(CheckBuff[i] != buff[i])
                  {  isdiff++;
                     debug(99, 0) ("CheckParam: CheckBuff[%i]%x != buff[%i]%x\n",i,(int)CheckBuff[i],i,(int) buff[i]);
                  }
              }
              fatalf("CheckParam: Different Buffers (%i,%i), Calls%i, bytes%i\n",idFunc, paramid,Ncalls,Nbytes);
           }

        } else {
            len = lenbuf;
            if(buff == NULL && len>0)
                 fatalf("CheckParam: buff == NULL, but len=%i (%i,%i), Calls%i, bytes%i\n",
                           len,idFunc, paramid,Ncalls,Nbytes);

            if(len && buff)
                memcpy(buff, CheckBuff,len);
        }
        if(deltaT+10 < idData[5])
        {   int dt = idData[5]-deltaT-10;
            if(dt > 5000) dt = 5000;
            DosSleep(idData[5]-deltaT-10);
        }
       break;
    }
   return 0;
}

int  writeBlocOfData(int idData[7],char *buff, int len)
{  int rc;
    rc = fwrite(idData,sizeof(int),7,fp);
    if(rc != 7)
    {  fatalf("writeBlocOfData: Error writing fp=%p, %s\n",fp,xstdio_strerror());
    }
   Nbytes += 7*sizeof(int);
   if(len)
   {  rc = fwrite(buff,len,1,fp);
      if(rc != 1)
      {  fatalf("writeBlocOfData: Error writing fp=%p, %s\n",fp,xstdio_strerror());
      }
     Nbytes += len;
   }
   return 0;
}
int  readBlocOfData(int idData[7],char *buff, int &len)
{  int rc;
   rc = fread(idData,sizeof(int),7,fp);
   if(rc < 1)
           return -1;
   Nbytes += 7*sizeof(int);
   len = idData[3];
   if(len)
   {  rc = fread(buff,len,1,fp);
      if(rc < 1)
           return -2;
      Nbytes += len;
   }
   return 0;
}

#endif //#ifdef DEBUG_SPY


int CheckSockets(fd_set *readfds,  fd_set *writefds, int inf, int maxsock)
{  int i,n, nread,nwrite,nmax ;
    char str[256],buf[1024];
    int options, optlen;
   buf[0] = 0;
   n = sizeof(fd_set)*(8*4);
   if(n >  maxsock) n =  maxsock;
   nmax = 0;
   for(nread=0,i=0;i<n;i++)
   { if(FD_ISSET(i, readfds)) { nread++; nmax=i; }
   }
  if(nread>0)
  { snprintf(str,256,"%d ReadS ",nread);
    strcat(buf,str);
    for(i=0;i<nmax+1;i++)
    { if(FD_ISSET(i, readfds))
       {  snprintf(str,256," %d",i);
          strcat(buf,str);
          optlen = sizeof(int);
#ifdef DEBUG_SPY
          DebugGetsockopt(i, SOL_SOCKET,SO_OPTIONS,(char *)&options, &optlen);
#else
         getsockopt(i, SOL_SOCKET,SO_OPTIONS,(char *)&options, &optlen);
#endif
          snprintf(str,256,"[%x]",options);
          strcat(buf,str);
       }
    }
  }
   for(nread=0,i=0;i<n;i++)
   { if(FD_ISSET(i, writefds)) { nread++; nmax=i; }
   }

  if(nread>0)
  { snprintf(str,256,"|%d WriteS ",nread);
    strcat(buf,str);
    for(i=0;i<nmax+1;i++)
    { if(FD_ISSET(i, writefds))
       {  snprintf(str,256," %d",i);
          strcat(buf,str);
          optlen = sizeof(int);
#ifdef DEBUG_SPY
          DebugGetsockopt(i, SOL_SOCKET,SO_OPTIONS,(char *)&options, &optlen);
#else
          getsockopt(i, SOL_SOCKET,SO_OPTIONS,(char *)&options, &optlen);
#endif
          snprintf(str,256,"[%x]",options);
          strcat(buf,str);
       }
    }
  }
  debug(5, 2) ("CheckSockets:%d %s\n", inf,buf);

  return 0;
}

int CheckSockets2(fd_set *readfds,  fd_set *writefds, int minsock, int maxsock,
                  int sockList[], int &NumsockListRead, int &NumsockListWrite)
{  int i,n, nread ;
//   n = sizeof(fd_set);
//printf("\nsizeof(fd_set)=%i\n",n);
//exit(1);
//to redo: сделать цикл по squid_fd_table.fd_table[i]
   n = maxsock;
   for(nread=0,i=minsock;i<n;i++)
   { if(FD_ISSET(i, readfds))
     { sockList[nread++] = i;
     }
   }
   NumsockListRead = nread;
   for(i=minsock;i<n;i++)
   { if(FD_ISSET(i, writefds))
     { sockList[nread++] = i;
     }
   }
   NumsockListWrite = nread - NumsockListRead;

  return 0;
}

int CheckSockets2R(fd_set *readfds,  fd_set *writefds, int sockList[],  int NumsockListRead, int NumsockListWrite)
{  int i;

   FD_ZERO(readfds);
   FD_ZERO(writefds);

   for(i=0;i<NumsockListRead;i++)
   { if(sockList[i] >= 0 )
     {    FD_SET(sockList[i], readfds);
          debug(5, 9) ("CheckSockets2R: Read Select socket %d\n",sockList[i]);
     }
   }
   for(i=NumsockListRead;i<NumsockListRead+NumsockListWrite;i++)
   { if(sockList[i] >= 0 )
     {   FD_SET(sockList[i], writefds);
         debug(5, 9) ("CheckSockets2R: Write Select socket %d\n",sockList[i]);
     }
   }
  return 0;
}

