/*========================================================*/
/*-SOURCE OF     (stest.c)  ------------------------------*/
/*--------------------------------------------------------*/
/* (C) Jul/1998  Dr. Adil Temel	(atemel@hotmail.com)	  */
/*--------------------------------------------------------*/
/* stest.c      : BSD Socket test & RAW transfer speed    */
/* Created      : 19980710 03:41:42 Fri		  	  */
/* Last Modified: 19980712 19:06:52 Sun			  */
/*========================================================*/

#define VERSION "0.5"
/*--------------------------------------------------------*/
#define PORTNUM 50000         /* random port number, we need something */
/*--------------------------------------------------------*/
#define MAXDATA (2*1024*1024L)  /* 1024K transfer */
/*--------------------------------------------------------*/
#define MAXBUF (1024L)	      /* Unit of transfer */
/*--------------------------------------------------------*/
#define DUMPLEN (0x40)	      /* dump last received/sent data */
/*--------------------------------------------------------*/
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netdb.h>

/*--------------------------------------------------------*/
#ifdef AMIGA
/*--------------------------------------------------------*/
#include <exec/types.h>
/*--------------------------------------------------------*/
#else
typedef signed long	 LONG;	    /* signed 32-bit quantity */
typedef unsigned long	ULONG;	    /* unsigned 32-bit quantity */
typedef signed short	 WORD;	    /* signed 16-bit quantity */
typedef unsigned short	UWORD;	    /* unsigned 16-bit quantity */
typedef signed char	 BYTE;	    /* signed 8-bit quantity */
typedef unsigned char	UBYTE;	    /* unsigned 8-bit quantity */
#endif



#define COMPILENAME "SocketTest"
/*--------------------------------------------------------*/
#define PROGRAMNAME COMPILENAME " V" VERSION
/*--------------------------------------------------------*/
#define COPYRIGHT  PROGRAMNAME" Test BSD socket communication.\n"  \
		   "Written by Dr. Adil Temel (E-Mail: atemel@hotmail.com) (C) 1998\r\n"
/*--------------------------------------------------------*/

#ifndef MAXHOSTNAME
#define MAXHOSTNAME 256
#endif
#define RETSIGTYPE void

/*--------------------------------------------------------*/
long ntol(char *s);
char sw_server=0,sw_quiet=0,sw_verbose=0,sw_random=0;
char sw_debug=0,sw_checksum=0,sw_readback=0;
char sw_keepalive=0;

char *kw_hostname=NULL;

/*--------------------------------------------------------*/
unsigned short int portnum=PORTNUM;
/*--------------------------------------------------------*/
long maxbuf=MAXBUF,maxdata=MAXDATA;
char *bufptr=NULL;

/*--------------------------------------------------------*/
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
/*--------------------------------------------------------*/
RETSIGTYPE fireman(int x);
int get_connection(int s);
int establish(unsigned short portnum);
int call_socket(char *hostname, unsigned short portnum);
int mygethostname(char *hostname,int maxlen);
struct hostent *mygethostent(char *hostname);
/*--------------------------------------------------------*/
int send_long(int s, long l);
int send_word(int s, short l);
int send_byte(int s, char l);
/*--------------------------------------------------------*/
int  get_long(int s, long *l);
int  get_word(int s, short *l);
int  get_byte(int s, char *l);
/*--------------------------------------------------------*/
int read_data (int s,char *buf,int n);
int write_data(int s,char *buf,int n);
/*--------------------------------------------------------*/
int  receive_data(int s);
int  send_data(void);

/*--------------------------------------------------------*/
void CurrentTime(ULONG *s,ULONG *m);
void DiffTime(ULONG *s1,ULONG *m1,ULONG s2,ULONG m2);
char *SPrintTime(ULONG s,ULONG m);
/*--------------------------------------------------------*/
long  memrnd(void *d,long sd,long len);
void  memcsum(void *d,ULONG *cs,long len);
void  memdump(void *s,long len,long adr);
char  *dumpadr(char *s,long len);

unsigned long RangeSeed(unsigned long s);
unsigned short int RangeRand(int d6);
/*--------------------------------------------------------*/
int main(int argc,char **argv)
{ 
int s, t;
int i,x,ret;
char *karg,skip,argused;
printf(COPYRIGHT);
//printf(COMPILEDATE);
if(argc>=2)
if(argv[1][0]=='?')
  {
    usage:
    printf("Usage: "COMPILENAME" [OPTIONS]\n");
    printf("Available options: (use with prefix - or /)\n");
    printf("----------------------------------------------\n");
    printf(" -s               Run as server\n");
    printf(" -pPORTNUM        Use this portnumber\n");
    printf(" -nHOSTNAME       Call which computer\n");
    printf(" -bMAXBUF_K       Buffer sizeK	[1K]\n");
    printf(" -eMAXDATA_K      Send data sizeK 	[1024K]\n");
    printf(" -r               Use randomized data (hardly compressible)\n");
    printf(" -c               Use simple checksum\n");
    printf(" -f               Read back written data\n");
    printf(" -k               Use socket option: SO_KEEPALIVE\n");
    printf(" -d               DEBUG\n");
    exit(0);
  }
for(i=1;i<argc;i++)
 if(argv[i][0]=='-' || argv[i][0]=='/')
  {
    karg=&argv[i][2];skip=0;argused=0;
    if(!*karg)
     {
         karg=argv[i+1];skip=1;
         if(!karg || *karg=='-' || *karg=='/') {karg="";skip=0;}
     }
    if(!karg) karg="";/* no NULL ptr */
    switch(argv[i][1]|0x20)
     {
       case 'h':
       case '?': goto usage;
       case 'p': portnum=ntol(karg);argused=1;
		 if(!portnum) portnum=PORTNUM;
		 break;
       case 'b': maxbuf=ntol(karg)*1024L;argused=1;
		 if(maxbuf<=0 || maxbuf>(512*1024L)) maxbuf=MAXBUF;
		 break;
       case 'e': maxdata=ntol(karg)*1024L;argused=1;
		 if(maxdata<=0 || maxdata>(16384*1024L)) maxdata=MAXDATA;
		 break;
       case 'n': kw_hostname=karg;argused=1;break;
       case 'k': sw_keepalive=TRUE;break;
       case 'c': sw_checksum=TRUE;break;
       case 'f': sw_readback=TRUE;break;
       case 'r': sw_random=TRUE;break;
       case 's': sw_server=TRUE;break;
       case 'd': sw_debug =TRUE;break;
       case 'v': sw_verbose=TRUE;sw_quiet=FALSE;break;
       case 'q': sw_verbose=FALSE;sw_quiet=TRUE;break;
		 break;
       default:  printf("Unknown option %s ignored\n",argv[i]);
     }
    if(argused) i+=skip;
  }
bufptr=malloc(maxbuf);
if(!bufptr)
  {
    fprintf(stderr,"Can't get %ld buffer.\n",maxbuf);
    exit(1);
  }
printf("Using portnum %d , buf %ldK , data %ldK\n",(long) portnum,maxbuf>>10L,maxdata>>10L);
if(!sw_server)
 {
    send_data();
    exit(0);
 }
printf("Running as server..\n");
if ((s= establish(portnum)) < 0) {  /* plug in the phone */
    perror("establish");
    exit(1);
  }
#if 0
 signal(SIGCHLD, fireman);           /* this eliminates zombies */
#endif
  printf("Waiting for connections.\n");

  for (;;) {                          /* loop for phone calls */
    if ((t= get_connection(s)) < 0) { /* get a connection */
      if (errno == EINTR)             /* EINTR might happen on accept(), */
        continue;                     /* try again */
      perror("accept");               /* bad */
      exit(1);
    }
#if 0 //#ifndef AMIGA
    switch(fork()) {                  /* try to handle connection */
    case -1 :                         /* bad news.  scream and die */
      perror("fork");
      close(s);
      close(t);
      exit(1);
    case 0 :                          /* we're the child, do something */
      close(s);
      receive_data(t);
      exit(0);
    default :                         /* we're the parent so look for */
      close(t);                       /* another connection */
      continue;
    }
#else
      receive_data(t);
      close(t);
#endif

  }
}

/* as children die we should get catch their returns or else we get
 * zombies, A Bad Thing.  fireman() catches falling children.
 */
RETSIGTYPE fireman(int x)
{
  //printf("fireman started.\n");
  while (waitpid(-1,NULL,WNOHANG) > 0)  ;
  //printf("fireman finished.\n");
}


long bytes_msec(ULONG b,ULONG s,ULONG m)
{
m=m/1000L+s*1000L;if(!m) m=1;
b/=m;
return b;
}
/*--------------------------------------------------------*/
void say_result(char *info,ULONG tot,ULONG totb, ULONG s1,ULONG m1,ULONG s2,ULONG m2)
{
ULONG b;
char *rwmode;
DiffTime(&s1,&m1,s2,m2);
tot+=totb;b=bytes_msec(tot,s1,m1);
if(totb) 
  {
    rwmode= sw_server ? "READ/WRITE":"WRITE/READ";
  }
else
  {
    rwmode= sw_server ? "WRITE":"READ";
  }
printf("%s: total %ldK (%ld bytes) %s (%ld bytes/msec %ld bytes/sec %ldK/sec ).\n",
		info,
    		tot/1024L,tot,rwmode,
		b,b*1000L,b*1000L/1024L);
printf("%s: elapsed Time ticks: %s\n",info,SPrintTime(s1,m1));
}

/*--------------------------------------------------------*/
#if 0
/*
After you create a socket to get calls, you must wait for calls to that
socket. The accept() function is used to do this. Calling accept() is
analogous to picking up the telephone if it's ringing. Accept() returns a
new socket which is connected to the caller.

The following function can be used to accept a connection on a socket that
has been created using the establish() function above:
*/

#endif
/*--------------------------------------------------------*/
#define PARMF_RAND 	(1L<<0)
#define PARMF_CSUM 	(1L<<1)
#define PARMF_RBACK	(1L<<2)
#define PARMF_PSIG	(1L<<7) /* parameter id */
/*--------------------------------------------------------*/
#define START_BYTE 	(0xAC)
/*--------------------------------------------------------*/
int send_data(void)
{
   int s,i,c;
   ULONG l;
   ULONG s1,s2,m1,m2;
   ULONG len,tot=0,totb=0,csum=0,rs=0;
   UBYTE x=0;
   char  name[MAXHOSTNAME+1];
   UBYTE parm=PARMF_PSIG;
   if(sw_random  ) parm|=PARMF_RAND;
   if(sw_checksum) parm|=PARMF_CSUM;
   if(sw_readback) parm|=PARMF_RBACK;

   if(kw_hostname) strcpy(name,kw_hostname);
   else mygethostname(name, MAXHOSTNAME);           /* who are we? */
  
   printf("send_data: sending to %s port %d\n",name,(long)portnum);
   if( (s=call_socket(name,portnum)) <0)
   {
      fprintf(stderr,"cannot connect.\n");
      return -1;
    }
   len=maxdata;
   printf("send_data: socket %d , sending %ld\n",s,len);
   if(send_long(s,len)<0)
    {
      error:
      printf("send_data: failed to send parameter!\n");
      goto fin;
    }
   if(send_byte(s,parm)>=0)
    {
       if(parm& PARMF_RAND)  printf("send_data: will send random data.\n");
       if(parm& PARMF_CSUM)  printf("send_data: will use checksum.\n");
       if(parm& PARMF_RBACK) printf("send_data: will read back sent data\n");
    }  else goto error;
    len=maxdata;
    if(len && len<maxbuf) l=len;else l=maxbuf;
    if(!len) len=MAXBUF;/* default send length */
    /* Dummy data */
    if(parm & PARMF_RAND)
     {
         rs=memrnd(bufptr,time(NULL),l);
         if(send_long(s,rs)<0) goto error;
         printf("send_data: using random seed 0x%08lx\n",rs);
     }
    else  memset(bufptr,x++,l);
    if(send_byte(s,START_BYTE)<0) goto error;
    CurrentTime(&s1,&m1);
    while(len && (c=write_data(s,bufptr,l)) >0 )
     {
#if 0
	    if(sw_random) memrnd(bufptr,-1,l);
	    else          memset(bufptr,x++,l);
#endif
	if(parm&PARMF_CSUM) memcsum(bufptr,&csum,l);
        if(parm&PARMF_RBACK)
	  {
		if(read_data(s,bufptr,c)<c)
		 {
		   printf("send_data: cannot read %d\n",c);
		   break;
		 } else totb+=c;
          }
        tot+=c;len-=c;
        if(len<maxbuf) l=len;else l=maxbuf;
     }
    CurrentTime(&s2,&m2);
    memdump(bufptr+c-DUMPLEN,DUMPLEN,tot-DUMPLEN);
    say_result("send_data",tot,totb,s1,m1,s2,m2);
    if(parm&PARMF_CSUM) 
	{
		printf("send_data: checksum 0x%08lx\n",csum);
		send_long(s,csum);
	}
fin:
  close(s);
  printf("send_data: socket closed.\n");
  return 0;
}

/*--------------------------------------------------------*/
/* this is the function that plays with the socket.it will*/
/* be called after getting a connection.		  */
/*--------------------------------------------------------*/
int receive_data(int s)
{
   int i,c;
   ULONG l;
   ULONG s1,s2,m1,m2;
   ULONG len,tot=0,totb=0,csum=0,rs=0;
   UBYTE parm=0;
   UBYTE start;
   printf("receive_data: socket %d\n",s);
   if(get_long(s,&len)<0)
    { 
      error:
      printf("receive_data: failed to read parameter!\n");
      goto fin;
    }
    printf("receive_data: expecting %ld bytes\n",len);
    if(get_byte(s,&parm)>=0)
     {	
       if(!(parm&PARMF_PSIG)) {printf("receive_data: wrong parameter received.\n");goto fin;}
       if(parm&PARMF_RAND)  printf("receive_data: will receive random data.\n");
       if(parm&PARMF_CSUM)  printf("receive_data: will use checksum.\n");
       if(parm&PARMF_RBACK) printf("receive_data: will write back received data\n");
     }
    else goto error;

    if(parm&PARMF_RAND) 
     {
       if(get_long(s,&rs)<0) goto error;
       printf("receive_data: remote random seed 0x%08lx\n",rs);
     }
    if(len && len<maxbuf) l=len;else l=maxbuf;
    if(!len) len=0xFFFFFFFF;
    if(get_byte(s,&start)) goto error;
    if(start!=START_BYTE)
     {
	printf("receive_data: wrong start byte 0x%02lX (expecting 0x%02lX)\n",
			start,START_BYTE);
        goto error;
      }
    CurrentTime(&s1,&m1);
    while(len && (c=read_data(s,bufptr,l)) >0 )
     {
	if(parm&PARMF_CSUM) memcsum(bufptr,&csum,l);
        if(parm&PARMF_RBACK)
	  {
		if(write_data(s,bufptr,c)<c)
		 {
		   printf("receive_data: cannot re-send received data %d\n",c);
		   break;
		 } else totb+=c;
          }

        tot+=c;len-=c;
        if(len<maxbuf) l=len;else l=maxbuf;
     }
     CurrentTime(&s2,&m2);
     memdump(bufptr+c-DUMPLEN,DUMPLEN,tot-DUMPLEN);
     say_result("receive_data",tot,totb,s1,m1,s2,m2);
     if(parm&PARMF_CSUM) 
	{
	  ULONG rsum;
	  get_long(s,&rsum);
	  printf("receive_data: checksum remote 0x%08lx%s0x%08lx %s\n",
		rsum,rsum==csum ? "==":"!=",csum, rsum==csum ? "OK!":"FAILURE!!");
	}
fin:
printf("receive_data: exit\n");
return 0;
}
/*--------------------------------------------------------*/
int ONE = 1;
/*--------------------------------------------------------*/
int sokeepalive(int s)
{
int r;
printf("sokeepalive: keeping %d alive\n",s);
r= setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &ONE, sizeof ONE);
printf("sokeepalive: setsockopt returned %d\n",r);
return r;
}

/*--------------------------------------------------------*/
/* send a long lvalue across network			  */
/*--------------------------------------------------------*/
int send_long(int s, long l)
{
   l=htonl(l);/* host to network long */
   if(write_data(s,(char *)&l,sizeof(long))==sizeof(long)) return 0;
   return -1;/* Failed */
}
/*--------------------------------------------------------*/
/* get  a long lvalue from network			  */
/*--------------------------------------------------------*/
int get_long(int s, long *l)
{
long x;
if(read_data(s,(char *)&x,sizeof(long))==sizeof(long)) 
 {
   *l=ntohl(x);/* network to host long */
   return 0;
 }
return -1;/* failed */
}
/*--------------------------------------------------------*/
/* send a word lvalue across network			  */
/*--------------------------------------------------------*/
int send_word(int s, short l)
{
   l=htons(l);/* host to network long */
   if(write_data(s,(char *)&l,sizeof(long))==sizeof(long)) return 0;
   return -1;/* Failed */
}
/*--------------------------------------------------------*/
/* get  a word lvalue from network			  */
/*--------------------------------------------------------*/
int get_word(int s, short *l)
{
short x;
if(read_data(s,(char *)&x,sizeof(short))==sizeof(short))
 {
   *l=ntohs(x);/* network to host long */
   return 0;
 }
return -1;/* failed */
}

/*--------------------------------------------------------*/
/* send a byte lvalue across network			  */
/*--------------------------------------------------------*/
int send_byte(int s, char l)
{
   if(write_data(s,&l,sizeof(char))==sizeof(char)) return 0;
   return -1;/* Failed */
}
/*--------------------------------------------------------*/
/* get  a word lvalue from network			  */
/*--------------------------------------------------------*/
int get_byte(int s, char *l)
{
if(read_data(s,l,sizeof(char))==sizeof(char))
 {
   return 0;
 }
return -1;/* failed */
}

/*--------------------------------------------------------*/
/* Conversation (or: How to talk between sockets)	  */
/* Now that you have a connection between sockets you want*/
/* to send data between them. The read() and write() 	  */
/* functions are used to do this, just as they are for	  */
/* normal files. There is only one major difference 	  */
/* between socket reading and writing and file reading 	  */
/* and writing: you don't usually get back the same number*/
/* of characters that you asked for, so you must loop     */
/* until you have read the number of characters that you  */
/* want. A simple function to read a given number of      */
/* characters into a buffer is:				  */
/*--------------------------------------------------------*/
int read_data(int s,char *buf,int n)
{ 
  int bcount=0; /* counts bytes read */
  int br=0;     /* bytes read this pass */
  /* loop until full buffer */
  while(bcount<n) 
   { 
     if ((br= read(s,buf,n-bcount)) > 0) 
      {
      bcount += br;                /* increment byte counter */
      buf += br;                   /* move buffer ptr for next read */
       }
     else
      if(br<0) return(-1);         /* signal an error to the caller */
   }
  return(bcount);
}
/*--------------------------------------------------------*/
int write_data(int s,char *buf,int n)
{ 
  int bcount=0; /* counts bytes read */
  int br=0;     /* bytes read this pass */
  /* loop until full buffer */
  while(bcount<n) 
   { 
     if((br= write(s,buf,n-bcount)) > 0) 
      {
       bcount += br;                /* increment byte counter */
       buf += br;                   /* move buffer ptr for next read */
      }
     else
      if(br<0) return(-1);          /* signal an error to the caller */
   }
  return(bcount);
}
/*--------------------------------------------------------*/
/* Determine hostent according to given name or current   */
/* machine config					  */
/*--------------------------------------------------------*/
struct hostent *mygethostent(char *hostname)
{
struct hostent     *hp;
static struct hostent dm;
static unsigned char bf[4];
static char *ls[2],myname[MAXHOSTNAME+1];
char *cx;
if(!hostname || !*hostname)
 {
  mygethostname(myname,MAXHOSTNAME);      /* who are we? */
  if(hostname) strcpy(hostname,myname);
  hostname=myname;
 }
if(*hostname>='0' && *hostname<='9')
 {
     char *c=hostname;
     memset(bf,0,4);
     /* assume dot adress */
     bf[0]=atol(c);while(*c && *c!='.') c++;c++;
     bf[1]=atol(c);while(*c && *c!='.') c++;c++;
     bf[2]=atol(c);while(*c && *c!='.') c++;c++;
     bf[3]=atol(c);
     hp=&dm;
     memset(hp,0,sizeof(dm));
     hp->h_name=hostname;
     hp->h_aliases=NULL;
     hp->h_addrtype=2;
     hp->h_length=4;
     hp->h_addr_list=ls;
     ls[0]=bf;ls[1]=NULL;
   }
else hp=gethostbyname(hostname);/* do we know the host's */
return hp;/* return our static data */
}
/*--------------------------------------------------------*/
/* Unlike with the telephone, you may still accept calls  */ 
/* while processing previous connections. For this reason */
/* you usually fork off jobs to handle  each connection.  */
/* The following code shows how to use establish() and    */
/* get_connection() to allow multiple connections to be   */
/* dealt with:						  */
/*--------------------------------------------------------*/
/* wait for a connection to occur on a socket created with*/
/* establish()						  *
/*--------------------------------------------------------*/
int get_connection(int s)
{ 
int t;                  /* socket of connection */
if ((t = accept(s,NULL,NULL)) < 0)   /* accept connection if there is one */
    return(-1);
if(sw_keepalive) sokeepalive(t);
return(t);
}
/*--------------------------------------------------------*/
/* Dialing (or: How to call a socket)			  */
/* You now know how to create a socket that will accept   */
/*  incoming calls. So how do you call it? As with the 	  */
/* telephone, you must first have the phone before using  */
/* it  to call. You use the socket() function to do this, */
/* exactly as you establish a socket to listen to.	  */
/* After getting a socket to make the call with, and      */
/* giving it an address, you use the connect() function to*/
/*  try to  connect to a listening socket. The            */
/* following function calls a particular port number on a */
/* particular host:					  */
/*--------------------------------------------------------*/
/* This function returns a connected socket through which */
/*  data can flow.					  */
/*--------------------------------------------------------*/
int call_socket(char *hostname, unsigned short portnum)
{
  struct sockaddr_in sa;
  struct hostent     *hp;
  int a, s;
  if((hp= mygethostent(hostname)) == NULL) { /* do we know the host's */
    errno= ECONNREFUSED;                       /* address? */
    return(-1);                                /* no */
  }
  memset(&sa,0,sizeof(sa));
  memcpy((char *)&sa.sin_addr,hp->h_addr,hp->h_length);     /* set address */
  sa.sin_family= hp->h_addrtype;
  sa.sin_port= htons((unsigned short)portnum);
 
  printf("call_socket: calling %s type=%ld %s:%ld\n",
	hostname,hp->h_addrtype,dumpadr(hp->h_addr,hp->h_length),(long)portnum);

  if ((s= socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)     /* get socket */
    return(-1);
  if(sw_keepalive) sokeepalive(s);

  if (connect(s,(struct sockaddr *)&sa,sizeof sa) < 0) { /* connect */
    close(s);
    return(-1);
  }
  return(s);
}
/*--------------------------------------------------------*/
/* Establish a socket; originally from bzs@bu-cs.bu.edu   */
/*--------------------------------------------------------*/
int establish(unsigned short portnum)
{
  int    s;
  struct sockaddr_in sa;
  struct hostent *hp;
  char *cx;
  static char myname[MAXHOSTNAME+1];
  myname[0]=0;
  if((hp= mygethostent(myname)) == NULL) { /* do we know the host's */
    errno= ECONNREFUSED;                       /* address? */
    return(-1);                                /* no */
  }
  printf("establish: %s adr type=%ld %s:%ld\n",
	myname,hp->h_addrtype,dumpadr(hp->h_addr,hp->h_length),(long)portnum);
  memset(&sa, 0, sizeof(struct sockaddr_in)); /* clear our address */
  sa.sin_family= hp->h_addrtype;              /* this is our host address */
  sa.sin_port= htons(portnum);                /* this is our port number */
  if ((s= socket(AF_INET, SOCK_STREAM, 0)) < 0) /* create socket */
    return(-1);
  if(sw_keepalive) sokeepalive(s);

  if (bind(s,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) < 0) {
    close(s);
    return(-1);                               /* bind address to socket */
  }
  listen(s, 3);                               /* max # of queued connects */
  return(s);
}
/*--------------------------------------------------------*/
int mygethostname(char *hostname,int maxlen)
{
char *cx;
gethostname(hostname,maxlen);           /* who are we? */
/* libsocket for djgpp kludge */
if(*hostname)
   {
     cx=hostname+strlen(hostname)-1;
     while(cx>=hostname && *cx==' ') *cx--=0;
   }
return *hostname ? 1:-1;
}
/*--------------------------------------------------------*/
char *dumpadr(char *s,long len)
{
char *c;
static char buf[500];
long i;
//printf("dumpadr: [%08lx] %ld\n",s,len);
if(len>500-1) len=500-1;
for(i=0,c=buf;i<len;i++) 
 {
   sprintf(c,"%03ld.",(unsigned long) ((UBYTE)*s++) );c+=4;
 }
*--c=0;/* remove last . */
return buf;
}
/*--------------------------------------------------------*/
void memdump(void *s,long len,long adr)
{
UBYTE *c=s;
long i;
for(i=0;i<len;i+=0x10,c+=0x10,adr+=0x10) 
 printf("%08lX: %02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX\n",
       adr,
       c[0x0],c[0x1],c[0x2],c[0x3],
       c[0x4],c[0x5],c[0x6],c[0x7],
       c[0x8],c[0x9],c[0xa],c[0xb],
       c[0xc],c[0xd],c[0xe],c[0xf]);
}
/*--------------------------------------------------------*/
/* return hexval+1					  */
/*--------------------------------------------------------*/
UBYTE ishex(UBYTE c)
{
if((c>='0' && c<='9')) c=c-('0'-1);
else
 {
  c|=0x20;/* lowercase */
  if(c>='a' && c<='f'  ) c=c-('a'-10-1);
  else c=0;
 }
return c;
}
/*--------------------------------------------------------*/
long my_htol(char *s,char **ds)
{
register long l=0,sg;
register UBYTE ch;
if(*s=='-') {s++;sg=1;}else sg=0;
/*----------------------------------*/
/* Skip first  chars if they are    */
/* '$' , '0x' or '0X' 		    */
/*----------------------------------*/
if(*s=='$') s++;
if(*s=='0' && (s[1]|0x20)=='x') s+=2;
while((ch=ishex(*s))!=0)
 {
   l=(l<<4)+(ch-1);
   s++;
 }
if(ds) *ds=s;/* Update ptr */
return sg ? -l:l;
}
/*--------------------------------------------------------*/
long ntol(char *s)
{
long num;
if(*s=='0' && (s[1]|0x20)=='x') num=my_htol(s,NULL);
else 				num=atol(s);
return num;
}
/*--------------------------------------------------------*/
char *htoa(long n,char ln)
{
register char *cx,c,h;
static char buf[9];
if(ln==0) ln=8;
buf[ln]=0;cx=buf+ln-1;
for(c=ln;c;c--,n>>=4,cx--)
 {
   h=n&0xF;
   if(h>=10) *cx=h+('A'-10);else *cx=h+'0';
 }
return buf;
}
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
#define TIMEOFFSET ((((1978-1970)*365+2)*24+1)*60*60) // 252464400.00000 , 0xF0C4D10
#define ADJUST (4*60*60)

#if 1 //ifndef AMIGA
void CurrentTime(ULONG *s,ULONG *m)
{
struct timeval tv;
struct timezone tz;
tz.tz_minuteswest=0;
tz.tz_dsttime=0;
gettimeofday(&tv,&tz);
if(s) *s  =(ULONG)tv.tv_sec-TIMEOFFSET+ADJUST;
if(m) *m  =(ULONG)tv.tv_usec;
}
#endif

/* Calc  *(m1)=m2-m1; */
void DiffTime(ULONG *s1,ULONG *m1,ULONG s2,ULONG m2)
{
if(*m1>m2) {m2+=1000000L;s2--;}
(*m1)=m2-*m1;
(*s1)=s2-*s1;
}

char *SPrintTime(ULONG s,ULONG m)
{
static char buf[50];
ULONG day,hour,min;
day  = s/(24*60*60L);s-=day*(24*60*60L);
hour = s/(60*60L)   ;s-=hour*(60*60L);
min  = s/60         ;s-=min*60;
/* DD.HH:MM:SS.TT */
sprintf(buf,"%02ld|%02ld:%02ld:%02ld.%06ld\n",
	day,hour,min,s,m);
return buf;
}

long memrnd(void *d,long sd,long len)
{
UBYTE *p=d;
if(sd!=-1) RangeSeed(sd);
while(len--) *p++=RangeRand(256);
return sd;
}

void memcsum(void *d,ULONG *cs,long len)
{
UBYTE *p=d;
ULONG c=*cs;
while(len--) c+=*p++;
*cs=c;
}
/*--------------------------------------------------------*/
static unsigned long seed=0;
/*--------------------------------------------------------*/
unsigned long RangeSeed(unsigned long s)
{
unsigned long o=seed;
printf("RangeSeed: 0x%08lx\n",s);
seed=s;
return o;
}
/*--------------------------------------------------------*/
unsigned short int RangeRand(int d6)
{
unsigned long d0,d1;
unsigned short int d4,d5;
d5=(unsigned short int)d6;
d4=d5-1;d0=seed;
do
 {
  d1=d0;d0+=d0;
  if(d0<=d1) d0^=0x1d872b41;
  d4>>=1;
 } while(d4);
seed=d0;
if(d5) 
 {
  d0=d5*(d0&0xFFFF);
  return (unsigned short int)(d0>>16L);
 }
return (unsigned short int)(d0&0xFFFF);
}



#if 0
/*

A very similar function should be used to write data; we leave that function
as an exercise to the reader.

Hanging Up (or: What to do when you're done with a socket)

Just as you hang up when you're through speaking to someone over the
telephone, so must you close a connection between sockets. The normal
close() function is used to close each end of a socket connection. If one
end of a socket is closed and the other tries to write to its end, the write
will return an error.

Speaking The Language (or: Byte order is important)

Now that you can talk between machines, you have to be careful what you say.
Many machines use differing dialects, such as ASCII versus (yech) EBCDIC.
More commonly there are byte-order problems. Unless you always pass text,
you'll run up against the byte-order problem. Luckily people have already
figured out what to do about it.

Once upon a time in the dark ages someone decided which byte order was
"right". Now there exist functions that convert one to the other if
necessary. Some of these functions are htons() (host to network short
integer), ntohs() (network to host short integer), htonl() (host to network
long integer), and ntohl() (network to host long integer). Before sending an
integer through a socket, you should first massage it with the htonl()
function:

i= htonl(i);
write_data(s, &i, sizeof(i));

and after reading data you should convert it back with ntohl():

read_data(s, &i, sizeof(i));
i= ntohl(i);

If you keep in the habit of using these functions you'll be less likely to
goof it up in those circumstances where it is necessary.

The Future Is In Your Hands (or: What to do now)

Using just what's been discussed here, you should be able to build your own
programs that communicate with sockets. As with all new things, however, it
would be a good idea to look at what's already been done. While there are
not a lot of books describing BSD sockets, one good reference is Unix
Network Programming by W. Richard Stevens (Prentice-Hall 1990, ISBN
0-13-949876-1). In addition, you should look at some of the many
public-domain applications which make use of sockets, since real
applications are the best teachers. One such application is msend, a utility
used to send messages between users on different hosts.

Beware that the examples given here leave out a lot of error checking which
should be used in a real application. You should check the manual pages for
each of the functions discussed here for further information. If you have
specific questions regarding sockets, please feel free to ask me at
jimf@world.std.com.
*/

#if 0
   printf("reading 256 ..\n");
   l=read_data(s,buf,256);
   printf("read %d bytes.\n",l);
   for(i=0,c=buf;i<l;i+=0x10,c+=0x10) 
     printf("%02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX\n",
       c[0x0],c[0x1],c[0x2],c[0x3],
       c[0x4],c[0x5],c[0x6],c[0x7],
       c[0x8],c[0x9],c[0xa],c[0xb],
       c[0xc],c[0xd],c[0xe],c[0xf]);
   printf("receive_data: closing socket.\n");
   close(s);
   printf("done.. returning.\n");
#endif
#endif

/*========================================================*/
/*-END OF SOURCE (stest.c)      --------------------------*/
/*========================================================*/

