/*
 *        T T C P . C
 *
 * Test TCP connection.  Makes a connection on port 5001
 * and transfers fabricated buffers or data copied from stdin.
 *
 * Usable on 4.2, 4.3, and 4.1a systems by defining one of
 * BSD42 BSD43 (BSD41a)
 * Machines using System V with BSD sockets should define SYSV.
 *
 * Modified for operation under 4.2BSD, 18 Dec 84
 *       T.C. Slattery, USNA
 * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85.
 * Modified in 1989 at Silicon Graphics, Inc.
 *        catch SIGPIPE to be able to print stats when receiver has died 
 *        for tcp, don't look for sentinel during reads to allow small transfers
 *        increased default buffer size to 8K, nbuf to 2K to transfer 16MB
 *        moved default port to 5001, beyond IPPORT_USERRESERVED
 *        make sinkmode default because it is more popular, 
 *                -s now means don't sink/source 
 *        count number of read/write system calls to see effects of 
 *                blocking from full socket buffers
 *        for tcp, -D option turns off buffered writes (sets TCP_NODELAY sockopt)
 *        buffer alignment options, -A and -O
 *        print stats in a format that's a bit easier to use with grep & awk
 *        for SYSV, mimic BSD routines to use most of the existing timing code
 * Modified by Steve Miller of the University of Maryland, College Park
 *        -b sets the socket buffer size (SO_SNDBUF/SO_RCVBUF)
 * Modified Sept. 1989 at Silicon Graphics, Inc.
 *        restored -s sense at request of tcs@brl
 * Modified Oct. 1991 at Silicon Graphics, Inc.
 *        use getopt(3) for option processing, add -f and -T options.
 *        SGI IRIX 3.3 and 4.0 releases don't need #define SYSV.
 *
 * Modified --> Nov 1996 at CERN (Daniel DAVIDS)
 *        printout of the Socket-Buffer-Sizes 
 *        configured for HP-UX 9000 OS        
 *        configured for Windows NT OS 
 * Modified Dec 1996 at CERN (Jacques ROCHEZ)
 *        severe cleanup
 *        addaptation to the gcc compiler (ANSI)
 *        configured for Lynx OS 
 *        automatic format for the rate display (G/M/K/)bytes/sec
 *        added log (L) and more help (h) options.
 * Modified May 1997 at CERN (Jacques ROCHEZ) 
 *        removed the mes() function following err() function.
 *        changed the default port to 5010
 * Modified jul 1997 at CERN (Jacques ROCHEZ)
 *        adapted the timing calculation in microseconds 
 *        addapted the code for Vsisual C++ under NT4.0 
 * Modified aug 1997 at CERN (Jacques ROCHEZ)
 *        initialise to 0 the variables nbytes, numcalls  
 *        moved the buffer pre-load outside the measured timed area 
 * Distribution Status -
 *        Public Domain.  Distribution Unlimited.
 * Modified jun 1998 at Epigram
 *        - print hash marks to indicate prograss on transmitting side
 *        - sleep between bursts of buffers
 *        - set number of buffers/burst
 * Modified jul 1998 at Epigram
 *        - send random size buffers
 * Modified jan 1999 at Epigram (WES)
 *        - added start and end patterns to UDP start and end packets
 *        - added handling of missed start, end, or data packets for UDP tests
 */
#ifndef lint
static char RCSid[] = "ttcp.c $- CERN Revision: 3.8 (dev level) -$";
#endif

static char VersDate[] = "Epigram 15-jul-98";

/*                system dependent setting
 *                ------------------------
 * uname -a,gcc -v a.c are the tools used                              
 *
 * Platform/OS          #define         MACRO predefined 
 * -----------          -------   ---------------------------------------------------
 * SunOS OS             BSD43     __unix__   __sun__   __sparc__
 * SUN Solaris           SYSV     __unix__   __sun__   __sparc__   __svr4__ 
 * SGI-IRIX  < 3.3 SYSV     set as #define sgi
 * HP-UX 9000           SYSV      __unix__   __hpux__  __hp9k8__
 * OSF/1 V3.2           SYSV      __unix__   __osf__   __alpha__
 * OSF/1 V4.0           SYSV      __unix__   __osf__   __alpha__   _CFE
 * LynxOS               SYSV      __unix__   __lynx__  __powerpc__
 * Windows NT           SYSV                 __WINNT__ __i386__    __M_COFF__
 * AIX                  SYSV      _AIX       _AIX32    _POWER      _IBMR2   _ARCH_PWR
 

 * Micosoft Visual C++ compiler under WindowNT 4.0
 * Windows NT                    _WINDOWS    WIN32 

 * Unix BSD 41a         BSD41a
 *          42          BSD42
 *          43          BSD43
 
 * Machines using System V with BSD sockets should define SYSV.
 *
 *            Compiler commands 
 *            -----------------
 * LynxOS : gcc -c ttcp.c -o ttcp.o | gcc -o ttcp -O ttcp.o -lnetinet -lc_p -lc
 */

/* -------------attempt to set an automatic UNIX  OS family detection -------*/

#if defined(__hp9k8__) || defined(__osf__) || defined(__srv4__)  
#define SYSV
#endif
#if defined(__lynx__)  
#define SYSV
#endif
/* for solaris (__srv4__) the parameters SYSV is already set */

/* version A.09.01  'key words' differs from A.09.05 A */ 
#if defined(__hpux)
#define __hpux__
#endif

#if defined(__sun__)&&!defined(__srv4__)
#define BSD43                  /* changed by BSD42 if necessary */
#endif

#if defined(_WIN32)                /* Window NT 4.0 compiled with VisualC++ 4 */
#define __NTVIS__
#define SYSV
#endif 

#if defined(__FreeBSD__)
#define BSD43
#endif

#if defined(__linux__)
#define BSD43
#endif
/*--------------------------------------------------------------------------*/

#if !defined(UNDER_CE)
#include <signal.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#endif

#if defined(SYSV)

#if defined(__osf__) 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>           /* struct timeval */
#include <sys/resource.h>       /* definition of struct rusage */    

#else  /* else of __osf__ */ 
#if defined(__NTVIS__)
#include <winsock2.h>
#include <windows.h>            /* required for all Windows applications */
#include <ws2tcpip.h>
#include <memory.h>
#include <time.h>
#if !defined(UNDER_CE)
#include <sys\timeb.h> 
#include <fcntl.h>
#endif
#include <stdlib.h>
#include <io.h>
struct rusage { struct timeval ru_utime, ru_stime; };
#define RUSAGE_SELF 0
#else  /* else of __NTVIS__ */  
#if defined(__lynx__)
#include <socket.h>             /* located in  /usr/include/..... */
#include <netinet/in.h>    
#include <netinet/tcp.h> 
#include <arpa/inet.h>     
#include <netdb.h>         
#include <time.h> 
#include <resource.h>           /* definition of struct rusage */    
#include <sys/times.h>
#define RUSAGE_SELF 0
#include <conf.h>               /* definition of TICKSPERSEC (HZ) */
#include <sys/param.h>     

#else  /* else of __Lynx__  */
#if defined(__svr4__)
#include <sys/socket.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>           /* struct timeval */
#include <sys/resource.h>       /* definition of struct rusage */    
#include <sys/times.h>
#define RUSAGE_SELF 0
#include <sys/param.h>     

#else  /* else of __svr4__    all SYSV cases except those mentionned before */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>           /* struct timeval */
#include <sys/resource.h>       /* definition of struct rusage */    
#include <sys/times.h>
#define RUSAGE_SELF 0
#include <sys/param.h>     

#endif /* __svr4__  */
#endif /* __lynx__  */
#endif /* __NTVIS__ */
#endif /* __osf__   */

#else  /* else of SYSV      it is a BSD OS  */
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#if defined(__linux__)
#include <time.h>           /* struct timeval */
#else
#include <sys/time.h>           /* struct timeval */
#endif
#include <sys/resource.h>       /* definition of struct rusage */
#include <unistd.h>		/* for usleep() - henry */
#define SOCKET_ERROR	-1

#endif /* SYSV */

#if defined(__NTVIS__)

#if defined(_DEBUG)     /* usual debug symbol for VC++ */
#define DEBUG 1
#endif

void usleep(unsigned int microseconds);

#define bcopy(a,b,n) memcpy((b), (a), (n))
#define bzero(a,n) memset((a), 0, (n))

#ifndef _GETOPT_
#define _GETOPT_
int getopt(int argc, char **argv, char *optstring);

extern char *optarg;                // returned arg to go with this option
extern int optind;                  // index to next argv element to process
extern int opterr;                  // should error messages be printed?
extern int optopt;                  //

#define BADCH ('?')
#endif // _GETOPT

/* get option letter from argument vector  */
int
        opterr = 1,                  // should error messages be printed?
        optind = 1,                  // index into parent argv vector
        optopt;                      // character checked for validity
char   *optarg;                      // argument associated with option

#define EMSG        ""
char *progname;                      // may also be defined elsewhere
#endif /*__NTVIS__*/

/* sockaddr_in ==  file server address structure 
 * 
 * Socket address, internet style.   declared in : /netinet/in.h
 * struct sockaddr_in {short   sin_family;
 *                     u_short sin_port;
 *                     struct  in_addr sin_addr;
 *                     char    sin_zero[8];
 *                    };
 *
 * Structure used by kernel to store most addresses. declared in ./sys/socket.h
 * struct sockaddr{u_short sa_family;       address family
 *                 char    sa_data[14];     up to 14 bytes of direct address 
 *                };
 * PS : sin stand for "socket internet number" 
 */

#ifndef __NTVIS__
#define FAR
#endif

#if     defined(__CONST_SOCKADDR_ARG)
#define SOCKADDR_CAST   (__CONST_SOCKADDR_ARG)
#elif  defined(__lynx__) || defined(__sun__) || defined(_AIX) || defined(__FreeBSD__) || defined(__NTVIS__)
#define SOCKADDR_CAST   (struct sockaddr FAR *)
#else
#define SOCKADDR_CAST
#endif

#if defined(__sun__)
struct sockaddr_in sockaddr;   /* done in ./X11/Xdmcp.h */
#endif 

struct sockaddr_in sinme;     /* is the socket struct. in the local host */
struct sockaddr_in sinhim;    /* is the socket struc. in the remote host */

#if defined(__lynx__) || defined(__svr4__) || defined(_AIX) 
struct sockaddr frominet;
#else
struct sockaddr_in frominet;
#endif /* __lynx__ */

int domain, fromlen;

#if !defined(__NTVIS__)
#define SOCKET int
#endif /* __NTVIS__ */
SOCKET fd;                             /* fd of network socket */

#if !defined(__lynx__)
extern int errno;
#endif 

#include <stdio.h>

FILE  *fplog = NULL;                   /* file pointer for the log file */
char  logfile[100];                    /* file name for the log */
static char logfile_head[] ="ttcp_log";   /* header  name for the log */
int   buflen = 8 * 1024;               /* length of buffer */
char  *buf;                            /* ptr to dynamic buffer */
int   nbuf = 2 * 1024;                 /* number of buffers to send in sinkmode */

#define START_PKT_LEN 4
#define START_PATTERN_LEN 4
#define END_PKT_LEN 8
#define END_PATTERN_LEN 4
#define MIN_UDP_LEN 5

char start_pattern[START_PATTERN_LEN] = {1, 2, 3, 4};
char end_pattern[END_PATTERN_LEN] = {2, 2, 2, 2};

int   bufoffset = 0;                   /* align buffer to this */
int   bufalign = 16*1024;              /* modulo this */

int   udp = 0;                         /* 0 = tcp, !0 = udp */
int   options = 0;                     /* socket options */
int   one = 1;                         /* for 4.3 BSD style setsockopt() */
short port = 5010;                     /* TCP port number */
char *host;                            /* ptr to name of host */
int  rndm = 0;                         /* 0="normal", !0=random data */
int  trans;                            /* 0=receive, !0=transmit mode */
int  timeout;                          /* read timeout in millisec */
int  debug = 0;                        /* 0=No-Debug, 1=Debug-Set-On */
int  sinkmode = 0;                     /* 0=normal I/O, !0=sink/source mode */
int  verbose = 0;                      /* 0=print basic info, 1=print cpu rate,
                                        * proc resource usage. */
int  nodelay = 0;                      /* set TCP_NODELAY socket option */
int  pri = 0;                          /* link layer priority */
int  b_flag = 0;                       /* use mread() */
int  log_cnt = 0;                      /* append result to a log */
int  sockbufsize = 0;                  /* socket buffer size to use */
char fmt = 'A';                        /* output format:
                                        *  b = bits,     B = bytes,
                                        *  k = kilobits, K = kilobytes,
                                        *  m = megabits, M = megabytes, 
                                        *  g = gigabits, G = gigabytes,
                                        *  A = automatic Xbytes (default) */
int  touchdata = 0;                    /* access data after reading */
int  seq_info = 0;                     /* report out of order seq nums */

int hash = 0;                          /* print hash marks for each buffer */
int udpsleep = 0;                      /* sleep in between udp buffers */
int burstn = 1;                        /* number of buffers per burst */
int bufmin = -1;                       /* minimum buffer size to use when
                                          sending random-size buffers */
unsigned int seed = 1;                 /* seed for random number generator
                                          used for random buffer lengths */
int no_start = 0;                      /* skip the start frames for UDP */
int no_data = 0;                       /* skip all data frames for UDP */
int no_end = 0;                        /* skip the end frames for UDP */

double   nbytes;                       /* bytes on net */
unsigned long numCalls;                /* # of I/O system calls */

struct hostent *addr;
extern int optind;
extern char *optarg;

#if defined(UNDER_CE)
static int errno;
static char *weekday[] ={"Sun", "Mon","Tues", "Wed", "Thurs", "Fri", "Sat"};
static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "July", "Aug", "Sep", "Oct", "Nov", "Dec"};
#define perror printf
#endif

/*--------------------------------------------------------------------------*/
static struct timeval time0;    /* Time at which timing started */
static struct timeval time1;
static struct rusage ru0;       /* Resource utilization at the start */
static struct rusage ru1;
static struct tm *tms;        /* system time structure */


/*-----------Prototype functions definitions -------------------------------*/
/*--------------------------------------------------------------------------*/

                                   /* ANSI input/output functions (stdio.h) */

#if defined(__lynx__)
int  getopt(int, char**, char*);
int  gettimeofday(struct timeval *tp, struct timezone *tzp);

#else
#if defined(__svr4__)

#else 
#if defined(_AIX)

#else
#if defined(__hpux__)
#else
#if defined(__NTVIS__)
#else 
#if defined(BSD42) || defined(BSD43)
#else

int  printf( char*, ...);
int  fprintf(FILE*,char*, ...);
void perror(char*);
int  getopt(int, char**, char*);
int  gettimeofday(struct timeval *tp, struct timezone *tzp);
#endif  /* BSD42 || BSD43 */
#endif  /* __NTVIS__ */
#endif  /* __hpux__ */
#endif  /*  _AIX    */
#endif  /* __svr4__ */
#endif  /* __lynx__ */ 

int main(int argc, char* argv[]); 
#if ( (!(defined(BSD42))) && (!(defined(BSD43))) && (!(defined(__NTVIS__))) )
int  read(int, char*, int);
int  write(int, char*, int);
int  close(int);
#endif /* !(BSD42) && !(BSD43) */
int  fclose(FILE *stream);

#if !defined(BSD43) && !defined(__NTVIS__)
void bzero(char*,int);
void bcopy(char*, char*, int);
char strncpy(char *s1,char *s2,size_t n);
int  atoi(char*);
int  malloc(int);
#endif


                           /* ANSI socket functions prototype /sys/socket.h */
#if defined(__lynx__)
int  select(int, fd_set*, fd_set*, fd_set*, struct timeval*); 

#else 
#if defined(__svr4__) && !defined(sparc)

/*  informations in : /usr/include/sys/socket.h */
int  socket(int, int, int); 
int  connect(int, struct sockaddr *, int);
int  bind(int, struct sockaddr *, int);
int  listen(int, int);
int  accept(int, struct sockaddr *, int *);
int  sendto(int, const char *, int, int, const struct sockaddr *, int);
int  recvfrom(int, char *, int, int, struct sockaddr *, int *);
int  getpeername(int, struct sockaddr *, int *);
int  getsockopt(int, int, int, char *, int *);
int  select(int, fd_set*, fd_set*, fd_set*, struct timeval*); 

#else
#if defined(_AIX)
int  select(unsigned long, void *, void *, void *, struct timeval *);

#else
#if defined(__hpux__)
int getrusage(int who,struct rusage *rusage);

#else 
#if defined(__NTVIS__)

#else
#if defined(BSD42) || defined(BSD43)

#else

int  socket(int, int, int);
int  connect(int s,struct sockaddr_in *name, int namelen);
int  bind(int s,struct sockaddr *name,int namelen);
int  listen(int, int);
int  accept(int, struct sockaddr_in *, int *);
int  sendto(int, char *, int, int, struct sockaddr_in *, int);
int  recvfrom(int, char *, int, int, struct sockaddr_in *, int *);
int  getpeername(int, struct sockaddr *, int *);
int  setsockopt(int, int, int, char *, int);

int  getsockopt(int, int, int, char*, int*);
int  select(int, fd_set*, fd_set*, fd_set*, struct timeval*); 

#endif /* BSD42 || BSD43 */
#endif /* __hpux__ */
#endif /*  _AIX    */
#endif /* __svr4__ */
#endif /* __lynx__ */ 
#endif /* __NTVIS__ */

/* ttcp prototype functions */
void udp_rcv_test(void);
double calc_cpu_time(struct rusage *r0, struct rusage *r1);
double calc_real_time(struct timeval *t0, struct timeval *t1);
int  getrusage(int who,struct rusage *rusage);
void sockets_err(char*);
void err(char *);
void mes(char *);
void pattern(char *, int);
int  Nread(SOCKET, void *, int);
int  Nwrite(int, void *, int);
void delay(int);
int  mread(int, char *,unsigned);
char *outfmt(char format, double b);
void prep_timer(void);
void read_timer(void);
void result_summary(void);
void prusage(struct rusage*,  struct rusage*,
             struct timeval*, struct timeval*); 
void tvadd(struct timeval *tsum, struct timeval *t0,struct timeval *t1);
void tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0);
void psecs(int);
void open_log(void);
void close_log(void);
void do_Usage(void);
void do_help(void);

/*--------------------------------------------------------------------------*/
#if !defined(__NTVIS__)
void 
sigpipe()
{;
}
#endif
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
  unsigned long addr_tmp;
  int c,k;
  int sockbufsndsize,sockbufrcvsize;
  int sockbuflen;
  struct sockaddr_in peer;
  int peerlen = sizeof(peer);

#if defined(__NTVIS__)
  extern char *optarg;
  WSADATA WSAData;
  WSAStartup(MAKEWORD(1,1), &WSAData);
#endif /* __NTVIS__ */

  if (argc < 2) { do_Usage(); exit(1); }

  while (1) {
    while ((c=getopt(argc, argv, "hidrstuvxHVBDTLb:f:l:n:p:A:O:S:N:P:R:I:w:")) != -1) {
      switch (c) {
        case 'w':
           timeout = atoi(optarg);
           break;
        case 'I':
           seed = atoi(optarg);
           break;
        case 'N':
           burstn = atoi(optarg);
           break;
	case 'P':
#if defined(__linux__)
	   pri = atoi(optarg);
	   break;
#else
	   fprintf(stderr, "ttcp: -P option not supported on this OS\n");
	   exit(1);
#endif
	case 'R':
	   bufmin = atoi(optarg);
	   break;
        case 'S':
           udpsleep = atoi(optarg);
           if (udpsleep < 0) udpsleep = 0;
           /* convert msec arg to usec for usleep, minimum 10ms */
           udpsleep = udpsleep * 1000;
           break;
        case 'H':
           hash = 1;
           break;
        case 'V':
           fprintf(stdout,"%s %s\n" , RCSid , VersDate );
           exit(0);
        case 'B':
          b_flag = 1;
          break;
        case 'L':
          log_cnt = 1;
          break;
        case 'h':
          do_help();
          exit(1);
          break;
        case 't':
          trans = 1;
          break;
        case 'r':
          trans = 0;
          break;
        case 'x':
          rndm = 1;
          break;
        case 'd':
          options |= SO_DEBUG;
          break;
        case 'D':
#ifdef TCP_NODELAY
        nodelay = 1;
#else
        fprintf(stderr, 
       "ttcp: -D option ignored: TCP_NODELAY socket option not supported\n");
#endif
          break;
        case 'n':
          nbuf = atoi(optarg);
          break;
        case 'l':
          buflen = atoi(optarg);
          break;
        case 's':
          sinkmode = !sinkmode;
          break;
        case 'p':
          port = atoi(optarg);
          break;
        case 'u':
          udp = 1;
          break;
        case 'v':
          verbose = 1;
          break;
        case 'A':
          bufalign = atoi(optarg);
          break;
        case 'O':
          bufoffset = atoi(optarg);
          break;
        case 'b':
#if defined(SO_SNDBUF) || defined(SO_RCVBUF)
          sockbufsize = atoi(optarg);
#else
          fprintf(stderr, 
"ttcp: -b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported\n");
#endif
          break;
        case 'f':
          fmt = *optarg;
          break;
        case 'T':
          touchdata = 1;
          break;
        case 'i':
          seq_info = 1;
          break;
          
      default:
          {do_Usage(); exit(1);}
       }/*switch */
    }/* while getopt() */

    argc -= optind;
    argv += optind;
    optind = 0;
    
    /* check for '--' args */
    if (argc == 0) {
      /* no more args */
      break; /* while (1) */
#if defined(DEBUG)
    } else if (!strcmp(argv[0], "--nostart")) {
      no_start = 1;
      argc--; argv++;
    } else if (!strcmp(argv[0], "--nodata")) {
      no_data = 1;
      argc--; argv++;
    } else if (!strcmp(argv[0], "--noend")) {
      no_end = 1;
      argc--; argv++;
    } else if (!strcmp(argv[0], "--debug")) {
      debug = 1;
      argc--; argv++;
#endif /* DEBUG */
    } else if (!strncmp(argv[0], "--", 2)) {
      fprintf(stderr, "ttcp: illegal option: %s\n", argv[0]);
      do_Usage(); exit(1);
    } else {
      /* the arg was not a '--' arg */
      break; /* while (1) */
    }
  } /* while (1) */
  
    
 /* ----------------------- main part ----------------------- */

#if defined(__NTVIS__) && !defined(UNDER_CE)
  /* Set "stdin" to have binary mode: */
  if (_setmode(_fileno(stdin), _O_BINARY) == -1)
    perror("%s: Error setting stdin to binary mode");
  /* Set "stdout" to have binary mode: */
  if (_setmode(_fileno(stdout), _O_BINARY) == -1)
    perror("%s: Error setting stdout to binary mode");
#endif /* __NTVIS__ */

if (log_cnt) open_log(); 

/* input error checking */
if (burstn > nbuf) {
    fprintf(stderr, "ttcp: buffers per burst must be less than or equal to "
        "total number of buffers\n");
    exit(1);
}
if (bufmin < -1) {
    fprintf(stderr, "ttcp: minimum buffer size specified with -R option must "
        "be non-negative\n");
    exit(1);
}
if (buflen > 65535) {
    fprintf(stderr, "ttcp: maximum buffer size specified with -l option must "
        "be <= 65536\n");
    exit(1);
}
if (bufmin > buflen) {
    fprintf(stderr, "ttcp: minimum buffer size specified with -R option must "
        "be less than or equal to (maximum) buffer size specified with -l\n");
    exit(1);
}

/* buffer allocation */

 if (udp && buflen < MIN_UDP_LEN) 
   buflen = MIN_UDP_LEN;        /* send more than the sentinel size */
 
 if ( (buf = (char *)malloc(buflen+bufalign)) == (char *)NULL) 
      err("malloc");
 if (bufalign != 0)
      buf +=(bufalign - ((int)buf % bufalign) + bufoffset) % bufalign;
 
 fprintf(stderr,"ttcp%s: buflen=%d, nbuf=%d, align=%d/%d, port=%d\n",
            trans?"-t":"-r",buflen, nbuf, bufalign, bufoffset, port);
 if (log_cnt)fprintf(fplog," %6d %6d %6d %6d %4d",
                      buflen, nbuf, bufalign, bufoffset, port);

 /* preload the buffer for the transmit condition */
 pattern( buf, buflen );

 /* seed the random number generator */
 if ((bufmin != -1) || (rndm != 0)) {
#if defined(__NTVIS__)
   srand(seed);
#else /* ! __NTVIS__ */
   srandom(seed);
#endif /* __NTVIS__ */
 }

 if(trans)  
   {/* xmitr */
     if (argc == 0) {
       fprintf(stderr, "ttcp: missing destination host arg\n");
       do_Usage(); exit(1);
     }
     
     bzero((char *)&sinhim, sizeof(sinhim));
     host = argv[0];
     if (atoi(host) > 0 )  
       {/* Numeric */
         sinhim.sin_family = AF_INET;
         sinhim.sin_addr.s_addr = inet_addr(host);
       } 
     else 
       {if ((addr=gethostbyname(host)) == NULL) sockets_err("bad hostname");
        sinhim.sin_family = addr->h_addrtype;
        bcopy(addr->h_addr,(char*)&addr_tmp, addr->h_length);
        sinhim.sin_addr.s_addr = addr_tmp;
       }
     sinhim.sin_port = htons(port);
     sinme.sin_port = 0;                /* free choice */
   } 
 else 
   {/* rcvr */
     sinme.sin_port =  htons(port);
   }
#if defined(__NTVIS__)
 sinme.sin_family = AF_INET;
#endif
 
 fd = socket(AF_INET, udp?SOCK_DGRAM:SOCK_STREAM, 0);

#if defined(__NTVIS__)
 if (fd == INVALID_SOCKET) sockets_err("socket");
#else
 if (fd < 0) sockets_err("socket");
#endif
 
 if (verbose) {
	char *label = trans?"ttcp-t":"ttcp-r";
#if defined(UNDER_CE)
	SYSTEMTIME SystemTime;
	char time_str[30];

	GetLocalTime(&SystemTime);
	sprintf(time_str, "%s %s %d %02d:%02d:%02d %d\n", weekday[SystemTime.wDayOfWeek], month[SystemTime.wMonth - 1],
		SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, SystemTime.wYear);
#else
   time_t now;
   char *time_str; 
       
   time(&now);
   time_str = ctime(&now);
#endif
   fprintf(stdout,"%s: start time %s", label, time_str);
   fprintf(stdout,"%s: File-Descriptor 0x%x Opened\n", label, fd );
 }

#if defined(__NTVIS__)
 if (bind(fd, (struct sockaddr FAR *)&sinme, sizeof(sinme)) == SOCKET_ERROR) 
   sockets_err("bind");
#else
 if (bind(fd, SOCKADDR_CAST &sinme, sizeof(sinme)) < 0) 
   sockets_err("bind");
#endif /* __NTVIS__ */


#if defined(SO_SNDBUF) || defined(SO_RCVBUF)
 if (sockbufsize) 
   {
#if defined(__lynx__) || defined(__sun__)  || defined(__NTVIS__)
     if (trans) 
       {if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize,
                       sizeof sockbufsize) < 0)  
        sockets_err("setsockopt: sndbuf");
       } 
     else 
       {if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize,
                       sizeof sockbufsize) < 0)  
        sockets_err("setsockopt: rcvbuf");
       }

#else
     if (trans) 

         {if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockbufsize,
                       sizeof sockbufsize) < 0) 
        sockets_err("setsockopt: sndbuf");
       } 
     else 
       {if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufsize,
                       sizeof sockbufsize) < 0) 
        sockets_err("setsockopt: rcvbuf");
       }
#endif /* __lynx__ __sun__ __NTVIS__ */ 
   }
 else
   {/*
    ** Added by Daniel Davids to Know Socket-Buffer-Sizes
    */
     sockbuflen = sizeof sockbufsndsize;
#if defined(__lynx__) || defined(__sun__) || defined(__NTVIS__)
     getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsndsize, 
                &sockbuflen);
     sockbuflen = sizeof sockbufrcvsize;
     getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufrcvsize, 
                     &sockbuflen);
#else
     getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockbufsndsize, &sockbuflen);
     sockbuflen = sizeof sockbufrcvsize;
     getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufrcvsize, &sockbuflen);
#endif /* __lynx__ __sun__ __NTVIS__ */
     sockbufsize = ( sockbufsndsize + sockbufrcvsize ) / 2;

     if ( sockbufsndsize != sockbufrcvsize )
       {fprintf(stderr, "sockbufsndsize=%d, ", sockbufsndsize );
       fprintf(stderr, "sockbufrcvsize=%d, ", sockbufrcvsize );
       }
   }
#endif /* defined(SO_SNDBUF) || defined(SO_RCVBUF) */
 
 if (sockbufsize) fprintf(stderr, "sockbufsize=%d, \n", sockbufsize);

 if (log_cnt)
   {if (sockbufsize)fprintf(fplog," %6d",sockbufsize);
    else fprintf(fplog," 0");
   }

#if defined(__linux__)
 if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (char *)&pri, sizeof pri) < 0)  
   sockets_err("setsockopt: priority");
#endif


 if (trans)  fprintf(stderr, "# %s sender -> %s #\n", udp?"udp":"tcp", host);
 else        fprintf(stderr, "# %s receiver #\n", udp?"udp":"tcp");
 
 if (!udp)  
   {
#if !defined(__NTVIS__)
     signal(SIGPIPE, sigpipe);
#endif /* !__NTVIS__ */

     if (trans) 
       {/* We are the client if transmitting */
         if (options)  
           {
#if defined(BSD42)
            if( setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0)
#else /* BSD43 */
       if( setsockopt(fd, SOL_SOCKET, options, (char *)&one, sizeof(one)) < 0)
#endif /* BDS42 */
           sockets_err("setsockopt");
           }
#ifdef TCP_NODELAY
         if (nodelay) 
           {struct protoent *p;
            p = getprotobyname("tcp");
#if defined(__lynx__)  || defined(__sun__)        || defined(__NTVIS__)
                if( p && setsockopt(fd, p->p_proto, TCP_NODELAY, 
                                      (char *) &one, sizeof(one)) < 0)
#else 
            if( p && setsockopt(fd, p->p_proto, TCP_NODELAY, 
                                      &one, sizeof(one)) < 0)
#endif /* __lynx__  __sun__ __NTVIS__ */
            sockets_err("setsockopt: nodelay");
           }
#endif /* TCP_NODELAY */
         if (connect(fd, SOCKADDR_CAST &sinhim, sizeof(sinhim) ) < 0) 
         sockets_err("connect");
       }/* if (trans) */ 
     else 
       {/* otherwise, we are the server and should listen for connections */

errno = 0;

#if defined(sgi) || ( defined(__osf__) && !defined(_CFE) )
        if( listen(fd,1) <0 )   
#else
        if( listen(fd,0) <0 )   /* allow a queue of 0 */
#endif
        sockets_err("listen");

        if(options) {
          int err;
#if defined(BSD42)
          err = setsockopt(fd, SOL_SOCKET, options, 0, 0);
#elif defined(__lynx__) || defined(__sun__) || defined(__NTVIS__)
          err = setsockopt(fd, SOL_SOCKET, options, (char *) &one, sizeof(one));
#else
          err = setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one));
#endif /* BSD42 */
          if (err < 0)
            sockets_err("setsockopt");
        }
        fromlen = sizeof(frominet);
        domain = AF_INET;
 if (timeout > 0) {
   fd_set readfds, exceptfds;
   struct timeval tv_timeout;
   int n;
   
   tv_timeout.tv_sec = timeout/1000;
   tv_timeout.tv_usec = (timeout%1000)*1000;
   
   FD_ZERO(&readfds);
   FD_ZERO(&exceptfds);
   FD_SET(fd, &readfds);
   FD_SET(fd, &exceptfds);
   
   n =  select( fd+1, &readfds, NULL, &exceptfds, &tv_timeout );
   if (n == 0 || n == SOCKET_ERROR) {
     sockets_err("select listen");
     return 0;
   } 
 }
        if((fd=accept(fd, SOCKADDR_CAST &frominet, &fromlen) ) < 0) 
                sockets_err("accept");

        if (getpeername(fd, SOCKADDR_CAST &peer, &peerlen) < 0)
          sockets_err("getpeername");
         
        fprintf(stderr,"ttcp-r: accept from %s\n",inet_ntoa(peer.sin_addr));

       } /* otherwise we are ... */
   }

 prep_timer();
 errno = 0;
 nbytes = 0.0;
 numCalls = 0;

 {
   register int cnt,multi;
   char *pb;
   int nb = 0;
   unsigned long rbuflen = 0;
   multi = nbuf;

   if (trans) {
#if !defined(BSD43)
     if(udp) {
       int err;
       int nochecksum_opt = 0;
       err = setsockopt(fd, IPPROTO_UDP, UDP_NOCHECKSUM,
                        (char *)&nochecksum_opt, sizeof(nochecksum_opt));
       if (err < 0)
         sockets_err("setsockopt");
     }
#endif
     
     if(udp && !no_start) {
       int start_count = 2;
       char start_pkt[START_PKT_LEN];
       memset(start_pkt, 0, START_PKT_LEN);
       memcpy(start_pkt, start_pattern, START_PATTERN_LEN);

       while (start_count-- > 0) {
         (void)Nwrite( fd, start_pkt, START_PKT_LEN ); /* rcvr start */
         if (udpsleep) {
           usleep(udpsleep);
           /* clear errno (see man page for errno(3), definition of
              EINTR.  usleep() uses SIGCONT? ) */
           if (errno == EINTR) errno = 0;
         } /* udpsleep */
       }
     }

     /* initial seqence num for UDP */
     if (udp) buf[0] = 0;
     k = burstn;

     if (sinkmode) {
       while (multi-- > 0 && !no_data) {

         if (bufmin == -1) {
           rbuflen = buflen;
         } else {
           /* set rbuflen to a random value evenly distributed in 
              [bufmin, buflen].  As long as buflen is < 2^16, we can 
              fit the calculation in 32 bits */
#if defined(__NTVIS__)
           rbuflen = (( (unsigned long)rand() *
                        ((unsigned long)(buflen-bufmin+1)) ) >> 15) + bufmin;
#else /* ! __NTVIS__ */
           rbuflen = (( ((unsigned long)random() >> 15) *
                        ((unsigned long)(buflen-bufmin+1)) ) >> 16) + bufmin;
#endif /* __NTVIS__ */
         }

         if (rndm) {
           unsigned int i, j, l;
           unsigned long data;
           
           if (udp)
             l = 1;
           else
             l = 0;

           for (i = l; i < rbuflen; /* null */) {
#if defined(__NTVIS__)
             data = (unsigned long)rand();
#else /* ! __NTVIS__ */
             data = (unsigned long)random();
#endif /* __NTVIS__ */
             /*fprintf(stderr, "%08x\n",data);*/ /* DEBUG */
             /* The NT rand() function returns only 16 useful bits! */
             for (j = 0; (j < 2/*4*/) && (i < rbuflen) ; j++) {
               buf[i++] = (unsigned char)(data & 0xff);
               data >>= 8;
             }
           }
         }
         
         if ((cnt=Nwrite(fd,buf,rbuflen)) != (int)rbuflen)
         sockets_err("error from the socket write");
         /* increment sequence num if UDP */
         if (udp) buf[0] = (char)(((unsigned char)(buf[0])+1) & 0xFF);
         
         if (debug)
           fprintf(stdout,"ttcp-t: %5d | %d Bytes Written in %d write commands \n",
                   ++nb, cnt, nbuf );

         nbytes += rbuflen;

         /* hashes */
         if (hash) {
           fprintf(stderr,"#");
         }

         /* Check for the end of a burst */
         if (--k <= 0) {
           k = burstn;
           
           /* sleep to avoid overrunning slower receivers - henry */
           if (udpsleep) {
             usleep(udpsleep);
             /* clear errno (see man page for errno(3), definition of
              EINTR.  usleep() uses SIGCONT? ) */
             if (errno == EINTR) errno = 0;
           } /* udpsleep */
         }
       } /* while */

     } /* if (sinkmode) */
     else 
     {

       nbuf = 0;

       if (bufmin == -1) {
         rbuflen = buflen;
       } else {
         /* set rbuflen to a random value evenly distributed in 
            [bufmin, buflen].  As long as buflen is < 2^16, we can 
            fit the calculation in 32 bits */
#if defined(__NTVIS__)
         rbuflen = (( (unsigned long)rand() *
                      ((unsigned long)(buflen-bufmin+1)) ) >> 15) + bufmin;
#else /* ! __NTVIS__ */
         rbuflen = (( ((unsigned long)random() >> 15) *
                      ((unsigned long)(buflen-bufmin+1)) ) >> 16) + bufmin;
#endif /* __NTVIS__ */
       }

       if (udp)
         pb = &(buf[1]);
       else
         pb = &(buf[0]);

#if !defined(__NTVIS__)     /* else case specific to WINNT */
       while((cnt=read(0,pb,rbuflen)) > 0)
#else /* __NTVIS__ */
       while((cnt=(int)fread(pb,1,rbuflen,stdin)) > 0)
#endif /* __NTVIS__ */
        {

         if (udp)
           multi = cnt+1; /* don't include seq. num. in count of data */
         else
           multi = cnt;
         if ((cnt=Nwrite(fd,buf,multi)) != (int)multi)
           sockets_err("error from the socket write");
         /* increment seqence num if UDP */
         if (udp) buf[0] = (char)(((unsigned char)(buf[0])+1) & 0xFF);
         nbuf++;

         if (debug)
           fprintf(stdout,"ttcp-t: %5d | %d Bytes Written in %d write commands \n",
                   ++nb, cnt, nbuf );

         nbytes += multi;

         /* hashes */
         if (hash) {
           fprintf(stderr,"#");
         }

         /* Check for the end of a burst */
         if (--k <= 0) {
           k = burstn;
           
           /* sleep to avoid overrunning slower receivers - henry */
           if (udpsleep) {
             usleep(udpsleep);
             /* clear errno (see man page for errno(3), definition of
              EINTR.  usleep() uses SIGCONT? ) */
             if (errno == EINTR) errno = 0;
           } /* udpsleep */
         }

         if (bufmin == -1) {
           rbuflen = buflen;
         } else {
           /* set rbuflen to a random value evenly distributed in 
              [bufmin, buflen].  As long as buflen is < 2^16, we can 
              fit the calculation in 32 bits */
#if defined(__NTVIS__)
           rbuflen = (( (unsigned long)rand() *
                        ((unsigned long)(buflen-bufmin+1)) ) >> 15) + bufmin;
#else /* ! __NTVIS__ */
           rbuflen = (( ((unsigned long)random() >> 15) *
                        ((unsigned long)(buflen-bufmin+1)) ) >> 16) + bufmin;
#endif /* __NTVIS__ */
         }

       } /* while */

     } /* if (sinkmode) */
     
     if (hash) {
       fprintf(stderr,"\n");
       fflush(stderr);
     }
     
#if defined(UNDER_CE)
	 errno = WSAGetLastError();
#endif
     if (!errno) {
       read_timer();
       if(udp && !no_end) {
         int end_count = 4;
         int data_count = nbuf;
         char end_pkt[END_PKT_LEN];
         unsigned char* net_byte = &end_pkt[END_PATTERN_LEN];
         memset(end_pkt, 0, END_PKT_LEN);
         memcpy(end_pkt, end_pattern, END_PATTERN_LEN);
         net_byte[3] = data_count & 0xFF; data_count >>= 8;
         net_byte[2] = data_count & 0xFF; data_count >>= 8;
         net_byte[1] = data_count & 0xFF; data_count >>= 8;
         net_byte[0] = data_count & 0xFF;
         
         while (end_count-- > 0) {
           Nwrite( fd, end_pkt, END_PKT_LEN ); /* rcvr end */
           if (udpsleep && end_count>0) usleep(udpsleep);
         }
       }
       result_summary();
     }
   } /* trans */ 
   else 
   {
       if (udp) {
         udp_rcv_test();
       }
       else 
       {/* not udp received transfer */
         while ((cnt=Nread(fd,buf,buflen)) > 0)
           {if(debug)fprintf(stdout,
                            "ttcp%s: %5d | %d Bytes Read\n",
                            trans?"-t":"-r", ++nb, cnt );
           nbytes += cnt;
           if (!sinkmode) {
#if !defined(__NTVIS__)     /* else case specific to WINNT */
             if (write(1,buf,cnt) != cnt) err("write");
#else /* __NTVIS__ */
             if ((int)fwrite(buf,1,cnt,stdout) != cnt) err("fwrite");
#endif /* __NTVIS__ */
           }
         }
#if defined(UNDER_CE)
		 errno = WSAGetLastError();
#endif
         if (!errno) {
           read_timer();
           result_summary();
         }
       }
     }
   }

 if(errno) err("IO");

#if defined(__NTVIS__) 
  closesocket ( fd );
#else 
  close ( fd );
#endif /* __NTVIS__ */

  if (verbose) fprintf(stdout,"ttcp%s: File-Descriptor  fd 0x%x Closed\n" ,
                       trans?"-t":"-r", fd );

  if (log_cnt) close_log();

  fprintf(stderr,"ttcp done.\n");
  fflush(stdout);

  exit(0);
}
/*--------------------------------------------------------------------------*/
void
udp_rcv_test(void)
{
  enum {START_WAIT, DATA_WAIT, DATA_RCV, END_TEST} rcv_state;
  enum {START_PKT_TYPE, END_PKT_TYPE, DATA_PKT_TYPE} pkt_type;
  int cnt;
  int nbuffers = 0;
  unsigned int start_pkt_cnt = 0;
  unsigned int end_pkt_cnt = 0;
  unsigned int data_pkt_cnt = 0;
  unsigned int expected_pkt_cnt = 0;
  unsigned char seq = 0;
  unsigned char buf_seq;
  
  rcv_state = START_WAIT;
  while (rcv_state != END_TEST && (cnt=Nread(fd,buf,buflen)) > 0) {
    /* Determine the type of packet received */
    if (!memcmp(buf, start_pattern, START_PATTERN_LEN)) {
      pkt_type = START_PKT_TYPE;
      start_pkt_cnt++;
    } else if (!memcmp(buf, end_pattern, END_PATTERN_LEN)) {
      /* read the expected data packet count from the end packet */
      unsigned char* net_byte = buf;
      net_byte += END_PATTERN_LEN;
      expected_pkt_cnt = ((net_byte[0] << 24) + (net_byte[1] << 16) +
                          (net_byte[2] << 8) + net_byte[3]);
      pkt_type = END_PKT_TYPE;
      end_pkt_cnt++;
    } else {
      data_pkt_cnt++;
      pkt_type = DATA_PKT_TYPE;
    }
           
    if (rcv_state == START_WAIT) {
      /* Wait until we see a vaild start packet */
      if (pkt_type == START_PKT_TYPE) {
        prep_timer();
        rcv_state = DATA_WAIT;
      } else if (pkt_type == DATA_PKT_TYPE) {
        fprintf(stderr, "ERROR: Missed UDP start packet.\n");
        prep_timer();
        rcv_state = DATA_RCV;
      } else if (pkt_type == END_PKT_TYPE) {
        fprintf(stderr, "ERROR: Found UDP end packet before start packet or data.\n");
        rcv_state = END_TEST;
      }
    } else if (rcv_state == DATA_WAIT) {
      /* Skip any extra start packets until we see data */
      if (pkt_type == START_PKT_TYPE) {
        prep_timer();
      } else if (pkt_type == DATA_PKT_TYPE) {
        rcv_state = DATA_RCV;
      } else if (pkt_type == END_PKT_TYPE) {
        fprintf(stderr, "ERROR: Found UDP end packet without receiving "
                "any data packets.\n");
        rcv_state = END_TEST;
      }
    } else { /* DATA_RCV */
      /* Collect data packets until we see a vaild end packet */
      if (pkt_type == START_PKT_TYPE) {
        /* We missed the end packets and now a new test is
         * starting. Report the results of this test then start
         * another. */
        read_timer();
        result_summary();
        fprintf(stderr, "ERROR: Found UDP start packet while receiving data.\n"
                "ERROR: Expected more data packets or an end packet.\n");
        nbytes = 0.0;
        nbuffers = 0;
        numCalls = 0;
        prep_timer();
        rcv_state = DATA_WAIT;
      } else if (pkt_type == DATA_PKT_TYPE) {
        /* loop in this state */
      } else if (pkt_type == END_PKT_TYPE) {
        /* we used to print results here but now we do when the loop ends */
        rcv_state = END_TEST;
      }
    }
    
    /* tally data packets the same way from whatever state we are in */
    if (pkt_type == DATA_PKT_TYPE) {
      if (debug)
        fprintf(stderr, "ttcp-r: %5d | %d Bytes Read\n", ++nbuffers, cnt);
      nbytes += cnt;
      if (seq_info) {
        /* check seqence num */
        buf_seq = (unsigned char)(buf[0]);
        if (buf_seq != seq) {
          fprintf(stderr, "ERROR: Out of sequence. "
                  "Buffer %u, seq %u, expected %u\n",
                  data_pkt_cnt, buf_seq, seq);
          seq = buf_seq;
        }
        seq++;
      }
      if (!sinkmode) {
#if !defined(__NTVIS__)     /* else case specific to WINNT */
        if (write(1,&(buf[1]),cnt-1) != cnt-1) err("write");
#else /* __NTVIS__ */
        if ((int)fwrite(&(buf[1]),1,cnt-1,stdout) != cnt-1) err("fwrite");
#endif /* __NTVIS__ */
      }
    }
  } /* end-while */

  /* normal end of test */
  read_timer();
  result_summary();
  fprintf(stderr, "ttcp-r: packets %u data, %u start, %u end\n",
          data_pkt_cnt, start_pkt_cnt, end_pkt_cnt);
  if (expected_pkt_cnt != 0) {
    int lost_cnt = expected_pkt_cnt - data_pkt_cnt;

    fprintf(stderr, "ttcp-r: %g%% (%u/%u) packet loss\n",
            100.0 * (double)lost_cnt/(double)expected_pkt_cnt,
            lost_cnt, expected_pkt_cnt);
  }
}

/*--------------------------------------------------------------------------*/
/* calc_cpu_time(): Time difference, in usecs, of the combined user and
 * sys times of the given start and end usage info */
double
calc_cpu_time(
  struct rusage *r0,
  struct rusage *r1
)
{
  double time;
  time_t ms;
  struct timeval tdiff, tend, tstart;
    
  /* total user delta time + total system delta time */
  tvadd( &tend, &r1->ru_utime, &r1->ru_stime );   /* user + sys time  @ end */
  tvadd( &tstart, &r0->ru_utime, &r0->ru_stime ); /* user + sys time  @ start*/
  tvsub( &tdiff, &tend, &tstart );

  /* useconds */
  time = ((double)tdiff.tv_sec)*1e6 + (double)tdiff.tv_usec;

  /* debug mseconds */
  ms = tdiff.tv_sec*(time_t)1000 + tdiff.tv_usec/(time_t)1000;
  if (ms != (time_t)(time/1000.0)) {
    fprintf(stderr, "ERROR: time calc mismatch of msec (%d) to usec (%f)\n",
            (int)ms, time/1000.0);
  }

  return time;
}

/*--------------------------------------------------------------------------*/
/* calc_real_time(): Time difference in usecs of the given times */
double
calc_real_time(
  struct timeval *t0,
  struct timeval *t1
)
{
  double time;
  time_t ms;
  struct timeval tdiff;
    
  tvsub(&tdiff, t1 ,t0);

  /* useconds */
  time = ((double)tdiff.tv_sec)*1e6 + (double)tdiff.tv_usec;
  
  /* debug mseconds */
  ms = tdiff.tv_sec*(time_t)1000 + tdiff.tv_usec/(time_t)1000;
  if (ms != (time_t)(time/1000.0)) {
    fprintf(stderr, "ERROR: time calc mismatch of msec (%d) to usec (%f)\n",
            (int)ms, time/1000.0);
  }

  return time;
}
/*--------------------------------------------------------------------------*/
void
result_summary(void)
{
  char* label = trans ? "ttcp-t" : "ttcp-r";
  double cput = calc_cpu_time(&ru0, &ru1);
  double realt = calc_real_time(&time0, &time1);
  double t_min;
  double bytes_per_sec;

  /* lower end boundary conditions */
  t_min = 10.0;                 /* 10 usec */
#if  defined(__NTVIS__)
  t_min = 1000.0;               /* 1 msec */
#endif
  if (cput <= t_min) {          /* value in usec */
    cput = t_min;
    fprintf(stderr,"%s: cpu time too short set at %.0f usec, NOT accurate result.\n",
            label,t_min);
  }
  if (realt <= t_min) {         /* value in usec */
    realt = t_min;
    fprintf(stderr,"%s: real time too short, set at %.0f usec, NOT accurate result.\n",
            label,t_min);
  }

  bytes_per_sec = (nbytes/realt)*1e6;

  fprintf(stderr,"%s: %.0f bytes in %.06f real seconds = %s/sec +++\n",
          label, nbytes, realt/1e6, outfmt(fmt, bytes_per_sec));

  if (verbose)
    fprintf(stderr,"%s: %.0f bytes in %.06f cpu  seconds = %s/cpu sec\n",
            label, nbytes,cput/1e6, outfmt(fmt, (nbytes/cput)*1e6));

  fprintf(stderr,"%s: %ld I/O calls, %.3f msec(real)/call, %.3f msec(cpu)/call\n",
          label, numCalls,
          (numCalls>0)?(realt/(double)numCalls)/1000.0:0.0,
          (numCalls>0)?(cput /(double)numCalls)/1000.0:0.0);

  fprintf(stderr,"%s: ", label);
  prusage(&ru0, &ru1, &time0, &time1);
  fprintf(stderr,"\n");

  if (verbose)
    printf("%s: buffer address %#x\n", label, (unsigned int)buf);

  if (fplog) {
    struct timeval tdiff;
    /* User time */
    tvsub(&tdiff, &ru1.ru_utime, &ru0.ru_utime);
    fprintf(fplog," %ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec);
    /* System time */
    tvsub(&tdiff, &ru1.ru_stime, &ru0.ru_stime);
    fprintf(fplog," %ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec);
    /* Percent of cput usage */
    fprintf(fplog," %.1f", 100.0 * (cput/realt));
    /* validity of real time mesurment */
    fprintf(fplog, (realt == t_min)?" 0":" 1");
    /* bytes, seconds, MBytes/sec, IO calls */
    fprintf(fplog," %10.0f %4.06f %4.3f %6ld",
            nbytes, realt/1e6, bytes_per_sec/(1024.0*1024.0), numCalls);
  }
}
/*--------------------------------------------------------------------------*/
void
sockets_err(char* s)
{
#if defined(__NTVIS__)
  int err = WSAGetLastError();
  char* prefix = trans?"ttcp-t":"ttcp-r";
  fprintf(stderr,"%s: %s\n", prefix, s);
  fprintf(stderr,"%s: errno=%d\n", prefix, err);
  exit(1);
#else
  err(s);
#endif /* __NTVIS__ */
}

/*--------------------------------------------------------------------------*/
void
err(char *s)
{
  char* prefix = trans?"ttcp-t":"ttcp-r";
  fprintf(stderr,"%s: ", prefix);
  perror(s);
  fprintf(stderr,"%s: errno=%d\n", prefix, errno);
  exit(1);
}
/*--------------------------------------------------------------------------*/
void
mes(char *s)
{
        fprintf(stderr,"ttcp%s: %s\n", trans?"-t":"-r", s);
}
/*--------------------------------------------------------------------------*/
void
pattern( char *cp, int cnt )
{
        register char c;
        register int cnt1;
        cnt1 = cnt;
        c = 0;
        while( cnt1-- > 0 )  {
                while( !isprint((c&0x7F)) )  c++;
                *cp++ = (c++&0x7F);
        }
}
/*--------------------------------------------------------------------------*/
char *
outfmt(char format, double b)
{
  static char obuf[50];
  double giga = 1024.0 * 1024.0 * 1024.0;
  double mega = 1024.0 * 1024.0;
  double kilo = 1024.0;
  
  if (format == 'A') {
    if (b >= giga)
      format = 'G';
    else if (b >= mega)
      format = 'M';
    else if (b >= kilo)
      format = 'K';
    else
      format = 'B';
  }

  switch (format) {
  case 'G':
    sprintf(obuf, "%.3f GB", b / giga);
    break;
  case 'M':
    sprintf(obuf, "%.3f MB", b / mega);
    break;
  case 'K':
    sprintf(obuf, "%.3f KB", b / kilo);
    break;
  case 'B':
    sprintf(obuf, "%4f B", b);
    break;
  case 'g':
    sprintf(obuf, "%.3f Gbit", b * 8.0 / giga);
    break;
  case 'm':
    sprintf(obuf, "%.3f Mbit", b * 8.0 / mega);
    break;
  case 'k':
    sprintf(obuf, "%.3f Kbit", b * 8.0 / kilo);
    break;
  case 'b':
    sprintf(obuf, "%4f b", b * 8.0);
    break;
  default:
    sprintf(obuf, "default.........."); 
  }
  return obuf;
}
/*--------------------------------------------------------------------------*/
#if defined(SYSV)

/*ARGSUSED*/

#if defined(__osf__)
/* getrusage defined in the system lib */
#else 
#if defined(__lynx__)
/* getrusage defined in the system lib */
#else 
#if defined(__sun__) 
/* getrusage defined in the system lib */
#else 

int
getrusage(ignored, ru)
     int ignored;
     register struct rusage *ru;
{


#if defined(__NTVIS__)
  HANDLE phd;
  FILETIME CreateTime, ExitTime, KernelTime, UserTime;
  SYSTEMTIME SysTime;
#if defined(UNDER_CE)
  phd = GetCurrentThread();
  if( GetThreadTimes(phd, &CreateTime, &ExitTime, &KernelTime, &UserTime) 
      != TRUE) 
#else
  phd = GetCurrentProcess();
  if( GetProcessTimes(phd, &CreateTime, &ExitTime, &KernelTime, &UserTime) 
      != TRUE) 
#endif
    {ru->ru_stime.tv_sec  = 0;
    ru->ru_stime.tv_usec = 0;
    ru->ru_utime.tv_sec  = 0;
    ru->ru_utime.tv_usec = 0;
    } 
  else 
   {
     (void) FileTimeToSystemTime(&KernelTime, &SysTime);
     /*
      * fprintf(stdout,
      * "System sec=%d, msec=%d\n", SysTime.wSecond, SysTime.wMilliseconds);
      */
     ru->ru_stime.tv_sec  = SysTime.wSecond; 
     ru->ru_stime.tv_usec = SysTime.wMilliseconds * 1000;
     (void) FileTimeToSystemTime(&UserTime, &SysTime);
     /*
      *  fprintf(stdout,
      *  "   User sec=%d, msec=%d\n", SysTime.wSecond, SysTime.wMilliseconds);
      */
     ru->ru_utime.tv_sec  = SysTime.wSecond;
     ru->ru_utime.tv_usec = SysTime.wMilliseconds * 1000;
    }

#else   /* __NTVIS__ */

  struct tms buftime;
  times(&buftime);
  /* Assumption: HZ <= 2147 (LONG_MAX/1000000) */
  /* info : in lynxOS HZ is called TICKSPERSEC (<conf.h>) */

    ru->ru_stime.tv_sec  = buftime.tms_stime / HZ;
    ru->ru_stime.tv_usec = ((buftime.tms_stime % HZ) * 1000000) / HZ;
    ru->ru_utime.tv_sec  = buftime.tms_utime / HZ;
    ru->ru_utime.tv_usec = ((buftime.tms_utime % HZ) * 1000000) / HZ;
#endif /* __NTVIS__ */
return(0);

} /* static getrusage */

#endif /* __sun__ */
#endif /* __lynx__ */
#endif /* __osf__ */
#endif /* SYSV */
/*--------------------------------------------------------------------------*/
#if defined(SYSV) 
#if defined(__hpux__) || defined(_AIX) || defined(__sun__)
/* gettimeofday defined in the system lib */
#else
# if defined (__osf__) ||defined (__lynx__)
/* gettimeofday defined in the system lib */
#else
/*ARGSUSED*/
static 
gettimeofday(tp, zp)
struct timeval *tp;
struct timezone *zp;
{
#if defined(__NTVIS__)
#if defined(UNDER_CE)
	SYSTEMTIME SystemTime;

	GetLocalTime(&SystemTime); 
	tp->tv_sec = SystemTime.wSecond;
	tp->tv_usec = SystemTime.wMilliseconds * 1000;
#else
  struct _timeb timeptr;

  _ftime(&timeptr);
  tp->tv_sec = timeptr.time;
  tp->tv_usec = timeptr.millitm * 1000;
#endif
#else /* all cases */
  tp->tv_sec = time(0);
  tp->tv_usec = 0;
#endif /* __NTVIS__ */
return(1);
} /* static gettimeofday */

#endif /*__osf__ || __lynx__ */
#endif /* __hpux__ || _AIX || __sun__ || __osf__*/
#endif /* SYSV */
/*--------------------------------------------------------------------------*/
/*
 *                        P R E P _ T I M E R
 */
void
prep_timer(void)
{
  gettimeofday(&time0, (struct timezone *)0);
  getrusage(RUSAGE_SELF, &ru0);
}
/*--------------------------------------------------------------------------*/
/*
 *                        R E A D _ T I M E R
 * 
 */
void
read_timer(void)
{
  getrusage(RUSAGE_SELF, &ru1);
  gettimeofday(&time1, (struct timezone *)0);
}
/*--------------------------------------------------------------------------*/
/*         Print the process usage calculated from timers values extracted 
 *         before and after the transfer execution.
 */
void
prusage(
  struct rusage *r0, struct rusage *r1,
  struct timeval *t0, struct timeval *t1
)
{
  struct timeval tdiff;
  int t, ms;
  register char *cp;
  double cput = calc_cpu_time(r0, r1);
  double realt = calc_real_time(t0, t1);

  /* t == total user delta time + total system delta time */
  if (debug)   
  { 
    printf("timers     : end          startup\n");
    printf("user (sec) : %9ld  %9ld\n",r1->ru_utime.tv_sec, 
           r0->ru_utime.tv_sec);
    printf("user (usec): %9ld  %9ld\n",r1->ru_utime.tv_usec, 
           r0->ru_utime.tv_usec);
    printf("sys  (sec) : %9ld  %9ld\n",r1->ru_stime.tv_sec, 
           r0->ru_stime.tv_sec);
    printf("sys  (usec): %9ld  %9ld\n",r1->ru_stime.tv_usec, 
           r0->ru_stime.tv_usec);
    printf("time (sec) : %9ld  %9ld\n",t1->tv_sec,t0->tv_sec);
    printf("time (usec): %9ld  %9ld\n",t1->tv_usec,t0->tv_usec);
  }
  /* for the AIX debug, most counters are outside a good range  
    printf("                               r0                   r1\n");
    printf("ru_ixrss    %20ld %20ld \n", r0->ru_ixrss  ,r1->ru_ixrss  );    
    printf("ru_idrss    %20ld %20ld \n", r0->ru_idrss  ,r1->ru_idrss  );    
    printf("ru_isrss    %20ld %20ld \n", r0->ru_isrss ,r1->ru_isrss );  
    printf("ru_minflt   %20ld %20ld \n", r0->ru_minflt  ,r1->ru_minflt  );   
    printf("ru_majflt   %20ld %20ld \n", r0->ru_majflt  ,r1->ru_majflt  );   
    printf("ru_nswap    %20ld %20ld \n", r0->ru_nswap  ,r1->ru_nswap  );    
    printf("ru_inblock  %20ld %20ld \n", r0->ru_inblock  ,r1->ru_inblock );  
    printf("ru_oublock  %20ld %20ld \n", r0->ru_oublock  ,r1->ru_oublock  );  
    printf("ru_msgsnd   %20ld %20ld \n", r0->ru_msgsnd  ,r1->ru_msgsnd  );   
    printf("ru_msgrcv   %20ld %20ld \n", r0->ru_msgrcv  ,r1->ru_msgrcv   );   
    printf("ru_nsignals %20ld %20ld \n", r0->ru_nsignals  ,r1->ru_nsignals); 
    printf("ru_nvcsw    %20ld %20ld \n", r0->ru_nvcsw   ,r1->ru_nvcsw   );    
    printf("ru_nivcsw   %20ld %20ld \n", r0->ru_nivcsw  ,r1->ru_nivcsw  );   
  */

  /* cpu time in mseconds */
  t = (int)(cput / 1000.0);

  /* ms == value of the internal clock at the end of the xfer   */      
  /*                             also called real time.         */
  /* real time in mseconds */
  ms = (int)(realt / 1000.0);

  /* The display is based on variables provided by the function getrusage 
     Info located in : /usr/include/sys/resource.h  
  */                       
#if defined(SYSV)

#if defined(_AIX)
  /* with AIX cernsp most counters are wrong  
   * cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw\0";
   */
  cp = "%Uuser %Ssys %Ereal %P\0";

#else 
#if defined(__osf__)
  cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw\0";
#else
#if defined(sgi)                        /* IRIX 3.3 will show 0 for %M,%F,%R,%C */
  cp = "%Uuser %Ssys %Ereal %P %Mmaxrss %F+%Rpf %Ccsw\0";
#else 
#if defined(__Lynx__)
  cp = "%Uuser %Ssys %Ereal %P\0";
#else 
  cp = "%Uuser %Ssys %Ereal %P\0";    /* all SYSV except those mentionned */
#endif /*__lynx__ */
#endif /* sgi     */
#endif /*__osf__  */
#endif /* _AIX    */

#else  /* BSD system */
  cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw\0"; 

#endif /* SYSV    */

  for (; *cp; cp++) {
    if (*cp != '%') {
      putc(*cp, stderr);
      /*  *outp++ = *cp; */
    } else if (cp[1]) 
      switch(*++cp) {
      case 'U':
        tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
        fprintf(stderr,"%ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec);
        break;

      case 'S':
        tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
        fprintf(stderr,"%ld.%06ld", (long)tdiff.tv_sec, (long)tdiff.tv_usec);
        break;

      case 'E':
        psecs( ms / 1000);
        break;

      case 'P':
        fprintf(stderr,"%.1f%%", (cput*100.0 / (realt ? realt : 1.0)) );
        break;

#if !defined(SYSV) || defined(__osf__) || defined(_AIX)
      case 'W':
        {
          int i = r1->ru_nswap - r0->ru_nswap;
          fprintf(stderr,"%d", i);
          break;
        }
            
      case 'X':
        fprintf(stderr,"%ld", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
        break;

      case 'D':
        fprintf(stderr,"%ld", t == 0 ? 0 :
                (r1->ru_idrss+r1->ru_isrss - (r0->ru_idrss+r0->ru_isrss))/t);
        break;

      case 'K':
        fprintf(stderr,"%ld", t == 0 ? 0 :
                ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) -
                 (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t);
        break;

      case 'M':
        fprintf(stderr,"%ld", r1->ru_maxrss/2);
        break;
  
      case 'F':
        fprintf(stderr,"%ld", r1->ru_majflt-r0->ru_majflt);
        break;

      case 'R':
        fprintf(stderr,"%ld", r1->ru_minflt-r0->ru_minflt);
        break;

      case 'I':
        fprintf(stderr,"%ld", r1->ru_inblock-r0->ru_inblock);
        break;

      case 'O':
        fprintf(stderr,"%ld", r1->ru_oublock-r0->ru_oublock);
        break;

      case 'C':
        fprintf(stderr,"%ld+%ld",
                r1->ru_nvcsw-r0->ru_nvcsw, r1->ru_nivcsw-r0->ru_nivcsw);
        break;
#endif /* !SYSV || __osf__ */
      default:
        putc(*cp, stderr);
        break;
      } /* switch */
  } /* for */
}
/*--------------------------------------------------------------------------*/
/* add 2 times structure and move usec bigger than 1000000 to sec */
void              
tvadd(tsum, t0, t1)
     struct timeval *tsum, *t0, *t1;
{
  tsum->tv_sec = t0->tv_sec + t1->tv_sec;
  tsum->tv_usec = t0->tv_usec + t1->tv_usec;
  if (tsum->tv_usec > 1000000) tsum->tv_sec++, tsum->tv_usec -= 1000000;
}
/*--------------------------------------------------------------------------*/
/* substract 2 time structure (t1 > t0) */
void             
tvsub(tdiff, t1, t0)
     struct timeval *tdiff, *t1, *t0;
{ 
  tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  if (tdiff->tv_usec < 0)  tdiff->tv_sec--, tdiff->tv_usec += 1000000;
}

/*--------------------------------------------------------------------------*/
void          
psecs(int l)
{
  int i = (int)l/3600;

  if (i) {
    /* hours:min:sec */
    fprintf(stderr,"%d:", i);
    i = (int)l % 3600;
    fprintf(stderr,"%.2d:%.2d", i/60, i%60);
  } else {
    /* min:sec */
    i = (int)l;
    fprintf(stderr,"%d:%.2d", i/60, i%60);
  }
}
/*--------------------------------------------------------------------------*/
/*                        N R E A D                                           */

int                          
Nread(SOCKET s, void* bufp, int count )
{
#if defined(__lynx__) || defined(__svr4__) || defined(_AIX) || defined(__NTVIS__) || defined(__FreeBSD__)
  struct sockaddr from;
#else
  struct sockaddr_in from;
#endif
  int len = sizeof(from);
  register int cnt;

  if (timeout > 0) {
    fd_set readfds, exceptfds;
    struct timeval tv_timeout;
    int n;

    tv_timeout.tv_sec = timeout/1000;
    tv_timeout.tv_usec = (timeout%1000)*1000;

    FD_ZERO(&readfds);
    FD_ZERO(&exceptfds);
    FD_SET(s, &readfds);
    FD_SET(s, &exceptfds);

    n =  select( s+1, &readfds, NULL, &exceptfds, &tv_timeout );
    if (n == SOCKET_ERROR) {
      sockets_err("select read");
    } else if (n == 0) {
      return (0);
    }

  }

  if( udp )  
    {cnt = recvfrom( s, bufp, count, 0, SOCKADDR_CAST &from, &len );
    numCalls++;
    } 
  else 
    {if( b_flag )  cnt = mread( s, bufp, count );        /* fill bufp */
    else 
      {
#if defined(__NTVIS__)
        cnt = recv( s, bufp, count, 0 );
#else
        cnt = read( s, bufp, count );
#endif /* __NTVIS__ */
        numCalls++;
      }
    if (touchdata && cnt > 0) 
      {register int c = cnt, sum = 0;
       register char *b = bufp;
       while (c--) sum += *b++;
      }
    }
  /* rchrch   printf (" numcall %d read buffer %d bytes \n",numCalls,cnt); */
  return(cnt);
}
/*--------------------------------------------------------------------------*/
/*                        N W R I T E                                         */

int                                    
Nwrite( int s, void* bufp, int count )
{
  register int cnt;
  if( udp )  
    {
    again:
      cnt = sendto( s, bufp, count, 0, SOCKADDR_CAST &sinhim,
                                                sizeof(sinhim) );

      numCalls++;

#if defined(__NTVIS__)
      if( cnt<0 && WSAENOBUFS == WSAGetLastError()) 
#else
      if( cnt<0 && errno == ENOBUFS )  
#endif /* __NTVIS__ */

        { delay(18000); errno = 0; goto again; }
    }  else /* if (udp) */
    {

#if defined(__NTVIS__)
      cnt = send( s, bufp, count, 0 );
      numCalls++;
#else
      cnt = write( s, bufp, count );
      numCalls++;
#endif /* __NTVIS__ */
    }        
  return(cnt);
}
/*--------------------------------------------------------------------------*/
void
delay(us)
int us;        
{
  struct timeval tv;

  tv.tv_sec = 0;
  tv.tv_usec = (time_t)us;

#if defined(__hpux__)
  select(1, 0, 0, 0, &tv); 
#else
  select(1, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv); 
#endif
}
/*--------------------------------------------------------------------------*/
/*                        M R E A D        
 *
 * This function performs the function of a read(II) but will
 * call read(II) multiple times in order to get the requested
 * number of characters.  This can be necessary because
 * network connections don't deliver data with the same
 * grouping as it is written with.  Written by Robert S. Miles, BRL.
 */
int
mread(int s, char* bufp, unsigned n)
{
  register unsigned        count = 0;
  register int                nread;
  
  do
    {
#if defined(__NTVIS__)
     nread = recv(s, bufp, n-count, 0);
#else
     nread = read(s, bufp, n-count);
#endif /* __NTVIS__ */
     numCalls++;
     if(nread < 0)  {perror("ttcp_mread"); return(-1); }
     if(nread == 0)  return((int)count);
     count += (unsigned)nread;
     bufp += nread;
    }while(count < n);
  return((int)count);
}

/*--------------------------------------------------------------------------*/
void
open_log()
{static long sysTicks;
#if defined(UNDER_CE)
	SYSTEMTIME SystemTime;
#endif
 sprintf(logfile,"%s_%s",logfile_head,trans?"t":"r");

 fprintf(stderr,"open the log file >%s<\n",logfile);
 if ((fplog = fopen(logfile,"r")) == NULL)    
       
   {if ((fplog = fopen(logfile,"a+")) == NULL)
     {fprintf(stderr,"Failure : creation of the file >%s< \n",logfile );
      exit(1);
     }
    else 
     {fprintf(fplog," creation date : ");
      /* get date */
#if defined(UNDER_CE)
	GetLocalTime(&SystemTime);
	sprintf(fplog,"%02d-%02d-%02d %02d:%02d\n", SystemTime.wDay, month[SystemTime.wMonth - 1],
		SystemTime.wYear, SystemTime.wHour, SystemTime.wMinute);
#else
      time(&sysTicks);
      tms = localtime(&sysTicks);
      fprintf(fplog,"%02d-%02d-%02d %02d:%02d\n",
              tms->tm_mday, tms->tm_mon, tms->tm_year,tms->tm_hour, tms->tm_min);
#endif

      /* An other version will produce : Mon Aug  4 16:32:16 1997
       * long  lDxcomsTicks;  char *pDateTime; 
       * time(&lDxcomsTicks);
       * pDateTime = ctime(&lDxcomsTicks);  *(pDateTime+24) = '\0';
       * fprintf(fplog," ttcp called : %s", pDateTime);
       */
      fprintf(fplog,"format\n");
      fprintf(fplog,",buflen, nbuf(byte), bufalign(byte), bufoffset(byte)");
      fprintf(fplog,",  port, sockbufsize(byte), UserTime(sec), SysTime(sec)\n");
      fprintf(fplog,",  CPUusage(%%), Validity, nbytes(byte), realt(sec)");
      fprintf(fplog,",  rate(MB/sec), I/O call, hours*3600+min*60+sec\n\n");
      /* day-month-year, hour:minute\n\n");  */
    }
  } /* file already exist */
   else 
   {fclose (fplog);
     if ((fplog = fopen(logfile,"a+")) == NULL)     
       {fprintf(stderr,"Failure : access of the file >%s< \n",logfile );
        exit(1);
           }
   }
} 
/*--------------------------------------------------------------------------*/
void
close_log()
{
#if defined(UNDER_CE)
	SYSTEMTIME SystemTime;

	GetLocalTime(&SystemTime);
	fprintf(fplog," %d\n", SystemTime.wHour * 3600 + SystemTime.wMinute * 60 + SystemTime.wSecond);
#else
 static long sysTicks;
 time(&sysTicks);
 tms = localtime(&sysTicks);
 fprintf(fplog," %d\n",((tms->tm_hour)*3600 + (tms->tm_min)*60 + tms->tm_sec));
#endif
 fclose(fplog);
 fflush(fplog);
}
/*--------------------------------------------------------------------------*/
/* routine emulating UNIX function under NT */
#if defined(__NTVIS__)

/*---------------------------------------------------------------------------*/
static void
error(char *pch)
{
        if (!opterr) {
                return;                // without printing
        }
        fprintf(stderr, "%s: %s: %c\n",
                (NULL != progname) ? progname : "getopt", pch, optopt);
}
/*---------------------------------------------------------------------------*/
int
getopt(int argc, char **argv, char *ostr)
{
  static char *place = EMSG;    /* option letter processing */
  register char *oli;           /* option letter list index */

  if (!*place) {
    // update scanning pointer
    if (optind >= argc || *(place = argv[optind]) != '-' || !*++place) {
      place = EMSG;
      return -1; 
    }
    // place now points to the first char past the initial '-'
    if (place[0] == '-') {
      // found "--"
      // Was the word just a '--'?
      if (place[1] == '\0')
        ++optind; // yes, so consume the word
      // otherwise, the '--' was the start of a longer word,
      // so do not consume it.
      place = EMSG;
      return -1;
    }
  }

  /* option letter okay? */
  if ((optopt = (int)*place++) == (int)':'
      || !(oli = strchr(ostr, optopt))) {
    if (!*place) {
      ++optind;
    }
    error("illegal option");
    return BADCH;
  }
  if (*++oli != ':') {        
    /* don't need argument */
    optarg = NULL;
    if (!*place)
      ++optind;
  } else {
    /* need an argument */
    if (*place) {
      optarg = place;                /* no white space */
    } else  if (argc <= ++optind) {
      /* no arg */
      place = EMSG;
      error("option requires an argument");
      return BADCH;
    } else {
      optarg = argv[optind];                /* white space */
    }
    place = EMSG;
    ++optind;
  }
  return optopt;                        // return option letter
}

void
usleep(unsigned int microseconds)
{
  Sleep(microseconds/1000);
}
#endif /* __NTVIS__ */
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
void
do_help()
{
char More_help[] =
" Details about the reply: \n"
"   Example: \n"
"   ttcp-t: buflen=8192, nbuf=100, align=16384/0, port=5010\n"
"   ttcp-t: File-Descriptor 0x4 Opened\n"
"   # tcp sender -> <host> #\n"
"   ttcp-t: 819200 bytes in 1.152557 real seconds = 694.109 KB/sec +++\n"
"   ttcp-t: 100 I/O calls, 11.526 msec(real)/call, 0.213 msec(cpu)/call\n"
"   ttcp-t: 0.001914user 0.019388sys 0:01real 1% 9i+58d 190maxrss 1+2pf 177+180csw\n"
"   ttcp-t: buffer address 0x28000\n"
"   ttcp-t: File-Descriptor  fd 0x4 Closed\n"
"   ttcp done.\n\n"
"cpu seconds  ==  (sec) elapse ru_utime + elapse ru_stime.\n"
"                 ru_utime == The total amount of time running in user mode.\n"
"                 ru_stime == The total amount of time spent in the system.\n"
"                             executing on behalf of the process.\n"
"real seconds ==  elapse time calculated by the system timer (date).\n"
"I/O calls    ==  I/O call to the driver.\n"
"msec/call    ==  average elapse time (Real seconds) between each I/O.\n"
"calls/sec    ==  invert of msec/call.\n"
"user         ==  (sec.msec) elaspe ru_utime.\n"
"sys          ==  (sec.msec) elapse ru_stime.\n"
"real         ==  (min:sec)  CPU seconds.\n"
"%%           ==  Real seconds / CPU seconds.\n"
"(ru_ixrss)i+(ru_idrss)d\n"
"             ru_ixrss  == An integral value indicating the amount of memory \n"
"                          used by the text segment that was also shared among\n"
"                          other processes. This value is expressed in units of\n"
"                          kilobytes * seconds-of-execution and is calculated \n"
"                          by adding the number of shared memory pages in use \n"
"                          each time the internal system clock ticks, and then\n"
"                          averaging over one-second intervals.\n"
"             ru_idrss  == An integral value of the amount of unshared memory \n"
"                          in the data segment of a process (expressed in \n"
"                          units of kilobytes * seconds-of-execution).\n";
 
char More_help1[] =
"  (ru_maxrss/2)maxrss.\n"
"             ru_maxrss == The maximum size, in kilobytes, of the used\n"
"                          resident set size. \n"
"  (ru_majflt)+(ru_minflt)pf : Page fault\n"
"             ru_majflt == The number of page faults serviced that required\n"
"                          I/O activity.\n"
"             ru_minflt == The number of page faults serviced without any\n"
"                          I/O activity. In this case, I/O activity is \n"
"                          avoided by reclaiming a page frame from the list \n"
"                          of pages awaiting reallocation. \n"
"(ru_nvcsw)+(ru_nivcsw)csw : context switch\n"
"             ru_nvcsw  == The number of times a context switch resulted \n"
"                          because a process voluntarily gave up the \n"
"                          processor before its time slice was completed. \n"
"                          This usually occurs while the process waits \n"
"                          for availability of a resource.\n"
"             ru_nivcsw == The number of times a context switch resulted \n"
"                          because a higher priority process ran or because\n"
"                          the current process exceeded its time slice.\n\n";

char More_help2[] =
"log file format :\n"
"         buflen, nbuf(byte), bufalign(byte), bufoffset(byte)\n"
"         port, sockbufsize(byte), UserTime(sec), SysTime(sec), CPUusage(%)\n"
"         nbytes(byte), realt(sec), rate(MB/sec), I/O call,\n"
"                 hours*3600+min*60+sec\n\n";

  fprintf(stderr,More_help);
  fprintf(stderr,More_help1);
  fprintf(stderr,More_help2);
}
/*---------------------------------------------------------------------------*/
void
do_Usage()
{
char Usage[] =
"  Usage: ttcp -t [-options] host [ < in ]    ttcp -r [-options > out]\n"
"Example: ttcp -t -s -v -n100 host            ttcp -r -s -v -n100\n"
"Common options:\n"
"    -V      prints version number and date of last modification\n"
"    -L      create and append all results to a file named ttcp_log\n"
"    -h      more help\n"
"    -l ##   length of bufs read from or written to network (default 8192,\n"
"            max 65535)\n"
"    -u      use UDP instead of TCP\n"
"    -p ##   port number to send to or listen at (default 5001)\n"
#if defined(__linux__)
"    -P ##   link-layer priority (default 0)\n"
#endif
"    -s      (ttcp -t) : source a pattern to network\n"
"            (ttcp -r) : sink (discard) all data from network\n"
"    -A ##   align the start of buffers to this modulus (default 16384)\n"
"    -O ##   start buffers at this offset from the modulus (default 0)\n"
"    -v      verbose: print more statistics\n"
"    -d      set SO_DEBUG socket option\n"
"    -b ##   set socket buffer size (if supported)\n"
"    -f X    format for rate: b,B = bits, bytes k,K = kilo{bits,bytes};\n"
"                             m,M = mega{bits,bytes}; g,G = giga{bits,bytes}\n"
"    -w ##   set timeout value (in milliseconds) to exit if no receive data or tcp connect\n"
"Options specific to (ttcp -t) :\n"
"    -n ##   number of source bufs written to network (default 2048)\n"
"    -x      use random data in tcp/udp frames (-I provides seed)\n"
"    -D      don't buffer TCP writes (sets TCP_NODELAY socket option)\n"
"    -H      print hash marks to indicate progress, one per buffer\n"
"    -I      init/seed value for RNG when sending random size bufs (default 1)\n"
"    -N ##   number of source bufs per burst, i.e between sleeps (default 1)\n"
"    -R ##   send random size buffers with minimum size specified, max size\n"
"            is value of -l option\n"
"    -S ##   millisecs between bursts (only used for udp, 10ms resolution)\n"
"Options specific to (ttcp -r) :\n"
"    -B      for -s, only output full blocks as specified by -l (for TAR)\n"
"    -T      \"touch\": access each byte as it's read\n"
"    -i      report information on out of order sequence numbers\n"
#if defined(DEBUG)
"Options for debug:\n"
"    --nostart do not send UDP start packets\n"
"    --noend   do not send UDP end packets\n"
"    --nodata  do not send UDP data packets\n"
"    --debug   print extra debug outputs\n"
#endif /* DEBUG */
;
 
  fprintf(stderr,Usage);
}

/* Define automatic Emacs variables for consistent code formatting */
/* Local Variables:     */
/* c-basic-offset:2     */
/* indent-tabs-mode:nil */
/* End:                 */
