#define	    ident	"1B02"
/*---------------------------------------------------------------------------*/
#ifdef __DECC
#pragma	    module	    SinqHM_Client	    ident
#endif
/*
** Link_options - Here is the Linker Option File
**!	sinqhm_client
**!	sinq_olb/lib/inc=deltat_messages
**!	pgplot_dir:grpckg.olb/lib
**!	sys$share:decw$xlibshr/share
**!!
**!!	    To build SINQHM_CTRL on LNSA09
**!!
**!!	$ import tasmad
**!!	$ define/job deltat_c_tlb sinq_c_tlb
**!!	$ sss := ud0:[maden.pss123.wind.sinqhm]
**!!	$ bui 'sss'sinqhm_client debug
** Link_options_end
**
**	Building on Alpha OSF/1:
**
**	    cc -Dmain=MAIN__ -std1 -g -c -o sinqhm_client.o	    \
**			-I/public/lib/include			    \
**			~/SinqHM/sinqhm_client.c
**	    f77 -g -o ~/bin/sinqhm_client sinqhm_client.o		\
**			-L/public/lib -lsinq -lcpgplot -lpgplot -lX11
**	    rm sinqhm_client.o
**
** +--------------------------------------------------------------+
** |                  Paul Scherrer Institute                     |
** |                     Computing Section                        |
** |                                                              |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name  . . . . . . . . : [...sinqhm]sinqhm_client.c
**
** Author   . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Jan 1997
**
**  SinqHM_Client is the main program of an Internet Client which transmits
**  requests to a SinqHM server running on a front-end processor.
**
** Updates:
**   9-Jan-1997 DM.	Initial version.
**
** Usage on VMS Systems
** --------------------
**   The following group logical name definitions are used ...
**
**	SINQHM_FRONTEND <nodename>,	The node where SINQHM_SRV is running.
**		     <port>,	 TCP/IP port number of SINQHM_SRV (dflt = 2400).
**		     <pkt_size>  Max packet size for send/rcve (dflt = 8192).
**
**	SINQHM_DBG_MODE	<dbg>	The setting of <strt_mode> in the SQHM_CNCT
**				message to SINQHM. Dflt=0. If non-zero, the
**				client will suspend itself immediately after
**				it has started to allow interactive debugging.
**
**   If the logical names cannot be found, DCL symbols will be used instead.
**
** Usage on UNIX Systems
** ---------------------
**   The SINQHM_FRONTEND and SINQHM_DBG_MODE environment variables are used
**   to obtain the required setup information.
**====================================================================
*/

#include    <errno.h>
#include    <netdb.h>
#include    <stdio.h>
#include    <stdlib.h>
#include    <time.h>

#include    <netinet/in.h>
#include    <arpa/inet.h>

#include    <ctype.h>
#include    <math.h>
#include    <sys/socket.h>
#include    <string.h>
#include    <sys/types.h>

#ifdef	__VMS

#include    <descrip>
#define	_DESCRIPTOR $DESCRIPTOR

#define	    PGBEGIN(arg1,arg2,arg3,arg4) pgbegin (&arg1, &arg2, &arg3, &arg4)
#define	    PGASK(arg1)			 pgask (&arg1)
#define	    PGENV(arg1,arg2,arg3,arg4,arg5,arg6) \
			pgenv (&arg1, &arg2, &arg3, &arg4, &arg5, &arg6)
#define	    PGLINE(arg1,arg2,arg3)	 pgline (&arg1, &arg2, &arg3)
#define	    PGLABEL(arg1,arg2,arg3)	 pglabel (&arg1, &arg2, &arg3)
#define	    PGRND(arg1,arg2)		 pgrnd (&arg1, &arg2)

    void    pgbegin ();
    void    pgask ();
    void    pgenv ();
    void    pgline ();
    void    pglabel ();
    float   pgrnd ();
#else
#include    <pgplot/cpgplot.h>
#define _DESCRIPTOR(name,string) char name[] = string
#define	    PGBEGIN(arg1,arg2,arg3,arg4) cpgbeg (arg1, arg2, arg3, arg4)
#define	    PGASK(arg1)			 cpgask (arg1)
#define	    PGENV(arg1,arg2,arg3,arg4,arg5,arg6) \
			cpgenv (arg1, arg2, arg3, arg4, arg5, arg6)
#define	    PGLINE(arg1,arg2,arg3)	 cpgline (arg1, &arg2, &arg3)
#define	    PGLABEL(arg1,arg2,arg3)	 cpglab (arg1, arg2, arg3)
#define	    PGRND(arg1,arg2)		 cpgrnd (arg1, &arg2)

#define	    pgbegin cpgbeg
#define	    pgask   cpgask
#define	    pgenv   cpgenv
#define	    pgline  cpgline
#define	    pglabel cpglab
#define	    pgrnd   cpgrnd
#endif
/*
**====================	Global Definitions =====================================
*/
#include    <sinq_prototypes.h>
#include    "sinqhm_def.h"

#define	    NIL		'\0'
#define	    NL		'\n'
#define	    MAXERR	10
#define	    MAX_HIS	16
#define	    BSIZE	((128*1024)/512)	/* Specify 128 kbyte buffer */

  /*
  **			Define the Data Structures we need
  */

/*
**====================	Global Variables ======================================
*/
  int			    My_errno, My_vaxc_errno;
  struct req_buff_struct    Req_buff;
  struct rply_buff_struct   Rply_buff;

  int		Rmt_port;
  int		Pkt_size;
  char		Rmt_node[32];
  int		Rw_bytes_got, Rw_bytes_put;
  static int	Cnct_skt = 0;	    /* Connect socket */
  static int	Rw_skt = 0;	    /* Read/write socket */

/*
**		The buffer for holding Hist Mem data is pointed to
**		by Hm_buff_addr. The number of bytes allocated is Hm_buff_size.
*/
  char		*Hm_buff_addr = NULL;
  int		 Hm_buff_size;
  int		 N_hists;	/* The number of histograms */
  int		 Hm_nbins;	/* The number of bins per histogram */
  int		 Bin_wid;	/* The number of bytes per bin */
  int		 Curr_hist;	/* The current histogram */
  int		 Max_block;

  int		 PGPLOT_started = 0;

  float		 P1 = 2000000,
		 P2 =   10000, 
		 P3 =       0, 
		 P4 =  200000, 
		 P5 =     500, 
		 P6 =       0;
/*
**=============================================================================
**  Local routines.
**
**  do_plot		: Plot the data.
**  exit_handler	: Exit handler in case a forced exit is made.
**  gen_data		: Generate sum of 2 Lorenzians.
**  get_SINQHM_DBG_MODE	: Extract info from SINQHM_DBG_MODE environment variable
**  get_SINQHM_FRONTEND	: Extract info from SINQHM_FRONTEND environment variable
**  read_hm		: Read  block of bins from SINQHM_SRV.
**  show_help		: Display the help text.
**----------------------------------------------------------------------------
**							    Prototypes
*/
  void	    do_plot (int first, int n_bins, int binwid, int total);
  void	    exit_handler ();
  void	    gen_data (char *p_p1, char *p_p2,
		      char *p_p3, char *p_p4,
		      char *p_p5, char *p_p6);
  void	    get_SINQHM_DBG_MODE (int *mode, int mode_dflt);
  void	    get_SINQHM_FRONTEND (char	  *node, int node_l, char *node_dflt,
				 int *port,		     int  port_dflt,
				 int *pktlen,		     int  pktlen_dflt);
  int	    openConnection (char    *node,
			    int	    *port,
			    int	    *pkt_size,
			    int	     mode,
			    struct rply_buff_struct *reply);
  int	    openConnectionGbl (char     *node,
			       int	*port,
			       int	*pkt_size,
			       int	 mode,
			       struct rply_buff_struct *reply);
  int	    read_hm (int f_bin, int n_bins);
  void	    show_help ();
/*
**----------------------------------------------------------------------------
*/
  void do_plot (int first, int n_bins, int binwid, int total) {
/*     ========
**				Make a plot of the data.
*/
    int		i;
    int		null = 0;
    int		nx = 1;
    int		ny = 1;
    char	total_txt[21];
    _DESCRIPTOR(dev, "/XW");
    _DESCRIPTOR(xlab, "Bins");
    _DESCRIPTOR(ylab, "Counts");
    _DESCRIPTOR(totl, total_txt);
    float	xlo, xhi, yhi;
    float	zero = 0.0;
    float	*x;
    float	*y;

    unsigned char	*p_byte;
    unsigned short int	*p_word;
    unsigned int	*p_long;

    if ((n_bins <= 0) || (total == 0)) {
      printf ("Nothing to plot!\n");
      return;
    }

    x = (float *) malloc (n_bins * sizeof (float));
    if (x == NULL) {
      printf ("Cannot get plot memory for x-array\n");
      return;
    }
    y = (float *) malloc (n_bins * sizeof (float));
    if (y == NULL) {
      printf ("Cannot get plot memory for y-array\n");
      free (x);
      return;
    }

    sprintf (total_txt, "Bin Total = %8d", total); total_txt[20] = ' ';

    p_byte = (unsigned char	 *) Hm_buff_addr;
    p_word = (unsigned short int *) Hm_buff_addr;
    p_long = (unsigned int	 *) Hm_buff_addr;

    if (PGPLOT_started == 0) {
      PGBEGIN (null, dev, nx, ny);
      PGASK (null);
      PGPLOT_started = 1;
    }
    xlo = (float) first;
    xhi = (float) first + n_bins + 1;
    yhi = 10.0;
    switch (binwid) {
     case 1:
      for (i = 0; i < n_bins; i++) {
	x[i] = first + i;
	y[i] = p_byte[i];
        if (y[i] > yhi) yhi = y[i];
      }
      break;
     case 2:
      for (i = 0; i < n_bins; i++) {
	x[i] = first + i;
	y[i] = p_word[i];
        if (y[i] > yhi) yhi = y[i];
      }
      break;
     case 4:
      for (i = 0; i < n_bins; i++) {
	x[i] = first + i;
	y[i] = p_long[i];
        if (y[i] > yhi) yhi = y[i];
      }
      break;
    }
    yhi = PGRND (yhi, i);
    PGENV (xlo, xhi, zero, yhi, null, null);
    PGLABEL (xlab, ylab, totl);
    PGLINE (n_bins, x[0], y[0]);
    free (x);
    free (y);
  }
/*
**--------------------------------------------------------------------------*/
  void exit_handler () {
/*     ============
**			We must exit. Tidy up first.
**			Close TCP/IP link to front-end.
*/
    int	    status;
/*
**			Tell server we're quitting.
*/
    if (Rw_skt != 0) {
      printf ("Closing connection to %s ...\n", Rmt_node);
      Req_buff.bigend = htonl (0x12345678);
      Req_buff.cmnd = htonl (SQHM_CLOSE);
      status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
      Rw_bytes_put += status;
      if (status == -1) FailInet ("EXIT_HANDLER -- R/W-Socket send error\n");
      if (status != sizeof (Req_buff)) {
        printf ("EXIT_HANDLER -- wrong number of bytes sent: %d", status);
        exit (EXIT_FAILURE);
      }
      status = close (Rw_skt);
      Rw_skt = 0;
      if (status != 0) FailInet ("EXIT_HANDLER -- R/W-Socket close error\n");
    }
  }
/*
**--------------------------------------------------------------------------*/
  void gen_data (
/*     ========
**				Generate sum of 2 Lorenzians.
*/		  char	*p_p1,
		  char	*p_p2,
		  char	*p_p3,
		  char	*p_p4,
		  char	*p_p5,
		  char	*p_p6) {

    int		 i;
    float	 p1, p2, p3, p4, p5, p6;
    float	 ff;
    char	*p_byte;
    short int	*p_word;
    int		*p_long;
		/*
		** Allocate buffer space for holding the data.
		*/
    if ((Hm_nbins * Bin_wid) > Hm_buff_size) {	      /* Expand buffer space? */
      Hm_buff_addr = realloc (Hm_buff_addr, (Hm_nbins * Bin_wid));  /* Yes */
      if (Hm_buff_addr != NULL) {
        Hm_buff_size = Hm_nbins * Bin_wid;
      }else {
        printf ("SinqHM_Client -- "
			"error getting memory buffer for histogram data.\n");
        exit (EXIT_FAILURE);
      }
    }

    if (p_p1 != NULL) {
      i = sscanf (p_p1, "%f", &p1);
      if  (i == 1) P1 = p1;
      if ((i == 1) && (p_p2 != NULL)) {
	i = sscanf (p_p2, "%f", &p2);
	if  (i == 1) P2 = p2;
	if ((i == 1) && (p_p3 != NULL)) {
	  i = sscanf (p_p3, "%f", &p3);
	  if  (i == 1) P3 = p3;
	  if ((i == 1) && (p_p4 != NULL)) {
	    i = sscanf (p_p4, "%f", &p4);
	    if  (i == 1) P4 = p4;
	    if ((i == 1) && (p_p5 != NULL)) {
	      i = sscanf (p_p5, "%f", &p5);
	      if  (i == 1) P5 = p5;
	      if ((i == 1) && (p_p6 != NULL)) {
		i = sscanf (p_p6, "%f", &p6);
		if  (i == 1) P6 = p6;
	      }
	    }
	  }
	}
      }
    }
    if (P2 <= 0) P2 = 1000;
    if (P5 <= 0) P5 = 1000;

    if (P3 <= 0) P3 = ((float) Hm_nbins) * 0.25;
    if (P6 <= 0) P6 = ((float) Hm_nbins) * 0.60;

    p_byte = (char	*) Hm_buff_addr;
    p_word = (short int *) Hm_buff_addr;
    p_long = (int	*) Hm_buff_addr;

    for (i = 0; i < Hm_nbins; i++) {    /* Calculate sum of 2 Lorenzians */

      p1 = ((float) i) - P3;	/* First Lorenzian */
      p1 = p1 * p1;
      p2 = P1/(P2 + p1);

      p3 = ((float) i) - P6;	/* Second Lorenzian */
      p3 = p3 * p3;
      p4 = P4/(P5 + p3);

      ff = p2 + p4;
      switch (Bin_wid) {
       case 1:
        *p_byte++ = (char) ff;
        break;
       case 2:
        *p_word++ = (short int) ff;
        break;
       case 4:
        *p_long++ = (int) ff;
        break;
      }
    }
  }
/*
**--------------------------------------------------------------------------*/
  void get_SINQHM_DBG_MODE (
/*     ===================
**			    Extract info from the SINQHM_DBG_MODE
**			    environment variable.
**
*/		int *mode,  int mode_dflt) {

    int	  env_len;
    char *p_env, *token;
    char  my_env[100];

    p_env = getenv ("SINQHM_DBG_MODE");    /* Get pointer to env var */
    if (p_env == NULL) {
      *mode = mode_dflt;    /* Env. var. not found, return default */
    }else {	    /* Make a local copy of it in case the original is in ..
		    ** .. read-protected memory (strtok needs to be able to ..
		    ** .. modify it */
      env_len = sizeof (my_env);
      StrEdit (my_env, p_env, "uncomment compress trim", &env_len);
      token = (env_len == 0) ? NULL : strtok (my_env, " ,"); /* Get mode token */
      if ((token == NULL) || (token[0] == ' ')) {
        *mode = mode_dflt;  /* Mode token not found, return default */
      }else {
	if (sscanf (token, "%d", mode) != 1) {
	  *mode   = mode_dflt;    /* Mode token illegal, return default */
	}
      }
    }
  }
/*
**--------------------------------------------------------------------------*/
  void get_SINQHM_FRONTEND (
/*     ===================
**			    Extract info from the SINQHM_FRONTEND
**			    environment variable.
**
*/		char	 *node, int node_l, char *node_dflt,
		int	 *port,		    int	  port_dflt,
		int	 *pktlen,	    int	  pktlen_dflt) {

    int	  env_len;
    char *p_env, *token;
    char  my_env[100];

    p_env = getenv ("SINQHM_FRONTEND");    /* Get pointer to env var */
    if (p_env == NULL) {
			    /* Env. var. not found, return defaults */
      StrJoin (node, node_l, node_dflt, "");
      *port	= port_dflt;
      *pktlen	= pktlen_dflt;
    }else {	    /* Make a local copy of it in case the original is in ..
		    ** .. read-protected memory (strtok needs to be able to ..
		    ** .. modify it */
      env_len = sizeof (my_env);
      StrEdit (my_env, p_env, "uncomment compress trim", &env_len);
      token = (env_len == 0) ? NULL : strtok (my_env, " ,"); /* Get node token */
      if ((token == NULL) || (token[0] == ' ')) {
			    /* Node token not found, return defaults */
	StrJoin (node, node_l, node_dflt, "");
        *port	= port_dflt;
        *pktlen	= pktlen_dflt;
      }else {
        StrJoin (node, node_l, token, "");
	token = strtok (NULL, " ,");	/* Get port token */
	if (token == NULL) {
	  *port   = port_dflt;	/* Port token not found, return defaults */
	  *pktlen = pktlen_dflt;
	}else {
	  if (sscanf (token, "%d", port) != 1) {
	    *port   = port_dflt;    /* Port token illegal, return defaults */
	    *pktlen = pktlen_dflt;
	  }else {
	    token = strtok (NULL, " ,");    /* Get packet-size token */
	    if (token == NULL) {
	      *pktlen = pktlen_dflt; /* Packet-size token not found, use dflt */
	    }else {
	      if (sscanf (token, "%d", pktlen) != 1) {
	        *pktlen = pktlen_dflt;	/* Packet-size token illegal, use dflt */
	      }
	    }
	  }
	}
      }
    }
  }
/*
**--------------------------------------------------------------------------*/
  int openConnection (
/*    ==============
**			Open connection to histogram memory front-end.
**			Return value is socket id for communication with server.
**			On successful connection, the SQHM_CNCT status reply
**			is returned in <request>.
*/
	    char	*node,
	    int		*port,		       /* <== this arg gets modified! */
	    int		*pkt_size,	       /* <== this arg gets modified! */
	    int		 mode,
	    struct rply_buff_struct *reply) {  /* <== this arg gets modified! */

    int	    i, status;
    int	    my_skt = 0;
    struct sockaddr_in	lcl_sockname;
    struct sockaddr_in	rmt_sockname;
    int			rmt_inet_addr;
    struct in_addr	*rmt_inet_addr_pntr;
    struct hostent	*rmt_hostent;
    int			rmt_sockname_len;
		/*
		** Get Internet address of the front-end.
		*/
    for (i=0; i < strlen (node); i++) node[i] = tolower (node[i]);
    rmt_hostent = gethostbyname (node);
    if (rmt_hostent == NULL) {
		/*
		** The following code is to handle nodes which are not yet
		** in the BIND data base.
		*/
      if (strcmp (node, "sqfe01") == 0) {
        rmt_inet_addr_pntr = (struct in_addr *) &rmt_inet_addr;
	rmt_inet_addr = inet_addr ("129.129.56.181");
      }else {
	printf ("Server Node is %s.\n", node);
        FailInet ("\nGethostbyname error.");
      }
    }else {
      rmt_inet_addr_pntr = (struct in_addr *) rmt_hostent->h_addr_list[0];
    }
    printf (" SinqHM Server is %s ", rmt_hostent->h_name);
    printf ("(%s),", inet_ntoa (*rmt_inet_addr_pntr));
    printf (" Base port %d\n", *port);
/*
**	    Create a TCP/IP socket for prelim. connect to server and bind it.
*/
    Cnct_skt = socket (AF_INET, SOCK_STREAM, 0);
    if (Cnct_skt == -1) FailInet ("Socket error.\n");

    lcl_sockname.sin_family = AF_INET;
    lcl_sockname.sin_port   = htons (0);
    lcl_sockname.sin_addr.s_addr = 0;
    status = bind (Cnct_skt, (struct sockaddr *) &lcl_sockname,
				    sizeof (lcl_sockname));
    if (status == -1) FailInet ("Bind error.\n");
/*
**=========================================  Now connect to the server.
*/
    rmt_sockname_len = sizeof (rmt_sockname);
    rmt_sockname.sin_family	 = AF_INET;
    rmt_sockname.sin_port	 = htons (*port);
    rmt_sockname.sin_addr.s_addr = rmt_inet_addr_pntr->s_addr;
    status = connect (Cnct_skt, (struct sockaddr *) &rmt_sockname,
				    sizeof (rmt_sockname));
    if (status == -1) {
      GetErrno (&My_errno, &My_vaxc_errno);
      FailInet ("Connect error\n");
    }
/*
**============================== Set up and send a connection request message.
*/
    Req_buff.bigend = htonl (0x12345678);
    Req_buff.cmnd   = htonl (SQHM_CNCT);
    Req_buff.u.cnct.max_pkt = htonl (*pkt_size);
    Req_buff.u.cnct.strt_mode = htonl (mode);
    if (mode != 0) {
      printf ("\007 Warning -- mode = %d\n", mode);
      printf (" Use the debugger in the Hist Mem to get our server to run.\n");
    }
    status = send (Cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    if (status == -1) FailInet ("SinqHM_Client -- Cnct-Socket send error\n");
    if (status != sizeof (Req_buff)) {
      printf ("SinqHM_Client -- wrong number of bytes sent: %d\n", status);
      exit (EXIT_FAILURE);
    }
/*
**	Wait for the response telling us the port to use.
*/
    status = recv (Cnct_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
    if (status == -1) {
      FailInet ("SinqHM_Client -- Cnct-Socket recv error\n");
    }else if (status != sizeof (Rply_buff)) {
      printf ("SinqHM_Client --  Cnct-Socket recv error - ");
      printf ("unexpected byte count: %d.\n", status);
      exit (EXIT_FAILURE);
    }
    if (ntohl (reply->bigend) != 0x12345678) {
      printf ("\007"
	    "SinqHM_Client -- big-endian/little-endian problem!\n"
	    "    Buffer received in non-network byte order!\n");
      exit (EXIT_FAILURE);
    }
    if (ntohl (reply->status) != KER__SUCCESS) {
      printf ("SinqHM_Client -- Bad status from Connect Request: %d.\n",
		    ntohl (reply->status));
      exit (EXIT_FAILURE);
    }
    status = close (Cnct_skt);
    Cnct_skt = 0;
    if (status != 0) FailInet ("SinqHM_Client -- Cnct-Socket close error\n");

    *port = ntohl (reply->u.cnct.port);
    printf (" Server port to use           = %6d\n", *port);
    *pkt_size = ntohl (reply->u.cnct.pkt_size);
    printf (" Agreed packet size           = %6d\n", *pkt_size);
/*
**     Now create, bind and connect a TCP/IP socket to our remote server port.
*/
    my_skt = socket (AF_INET, SOCK_STREAM, 0);
    if (my_skt == -1) {
      FailInet ("Socket error.\n");
      return 0;
    }

    lcl_sockname.sin_family = AF_INET;
    lcl_sockname.sin_port   = htons (0);
    lcl_sockname.sin_addr.s_addr = 0;
    status = bind (my_skt, (struct sockaddr *) &lcl_sockname,
						    sizeof (lcl_sockname));
    if (status == -1) {
      FailInet ("Bind error.\n");
      return 0;
    }

    rmt_sockname_len = sizeof (rmt_sockname);
    rmt_sockname.sin_family	 = AF_INET;
    rmt_sockname.sin_port	 = htons (*port);
    rmt_sockname.sin_addr.s_addr = rmt_inet_addr_pntr->s_addr;
    status = connect (my_skt, (struct sockaddr *) &rmt_sockname,
						    sizeof (rmt_sockname));
    if (status == -1) {
      GetErrno (&My_errno, &My_vaxc_errno);
      FailInet ("Connect error\n");
      return 0;
    }
    Rw_bytes_got = 0; Rw_bytes_put = 0;

    return my_skt;
  }
/*
**--------------------------------------------------------------------------*/
  int openConnectionGbl (
/*    =================
**			Call openConnection then set up some global variables.
*			Return value is socket id for communication with server.
*/
	    char	*node,
	    int		*port,		       /* <== this arg gets modified! */
	    int		*pkt_size,	       /* <== this arg gets modified! */
	    int		 mode,
	    struct rply_buff_struct *reply) {  /* <== this arg gets modified! */

    int	    my_skt = 0;

    my_skt = openConnection (node, port, pkt_size, mode, reply);
    if (my_skt == 0) return my_skt;

    N_hists = ntohl (Rply_buff.u.cnct.n_hists);
    printf (" Number of histograms         = %6d\n", N_hists);

    Hm_nbins = ntohl (Rply_buff.u.cnct.num_bins);
    printf (" Number of bins per histogram = %6d\n", Hm_nbins);

    Bin_wid = ntohl (Rply_buff.u.cnct.binwid);
    printf (" Number of bytes per bin      = %6d\n", Hm_nbins);

    Curr_hist = ntohl (Rply_buff.u.cnct.curr_hist);
    if (Curr_hist != 0)
	printf (" Current histogram            = %6d\n", Curr_hist);

    Max_block = ntohl (Rply_buff.u.cnct.max_block);
    printf (" Biggest block of free memory = %6d bytes\n", Max_block);

    return my_skt;
  }
/*
**--------------------------------------------------------------------------*/
  int read_hm (int f_bin, int n_bins) {
/*    =======
**		Send SQHM_READ request to server to read n_bins hist mem bins
**		starting at bin f_bin. On return, the data is in the buffer
**		pointed to by Hm_buff_addr.
*/
    int		 status, is, i;
    int		 bytes_to_come;
    char	*nxt_byte;
    short int	*nxt_word;
    int		*nxt_long;
    char	 msg0[] = "Histogram memory bin 99999 has overflowed.";

    status = EXIT_SUCCESS;		/* Assume success. */
    Req_buff.bigend = htonl (0x12345678);
    Req_buff.cmnd = htonl (SQHM_READ);
    Req_buff.u.read.n_bins     = htonl (n_bins);
    Req_buff.u.read.first_bin    = htonl (f_bin);
    Req_buff.u.read.hist_no	 = htonl (-1);
    status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    Rw_bytes_put += status;
    if (status == -1) FailInet ("READ_HM -- R/W-Socket send error\n");
    if (status != sizeof (Req_buff)) {
        printf ("READ_HM -- wrong number of bytes sent: %d", status);
	return EXIT_FAILURE;
    }
	/*
	**	Wait for the status response.
	*/
    status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
    Rw_bytes_got += status;
    if (status == -1) {
      FailInet ("READ_HM -- R/W-Socket recv error\n");
    }else if (status != sizeof (Rply_buff)) {
      printf ("READ_HM --  R/W-Socket recv error - ");
      printf ("unexpected byte count: %d.\n", status);
      return EXIT_FAILURE;
    }
    if (ntohl (Rply_buff.bigend) != 0x12345678) {
      printf ("\007"
	    "SinqHM_Client -- big-endian/little-endian problem!\n"
	    "    Buffer received in non-network byte order!\n");
      return EXIT_FAILURE;
    }
    if (ntohl (Rply_buff.status) != KER__SUCCESS) {
      printf ("READ_HM -- Bad status from SQHM_READ Request: %d.\n",
	 	    ntohl (Rply_buff.status));
      return ntohl (Rply_buff.status);
    }
	/*
	**	Data was read OK so read the data which has been sent.
	*/
    bytes_to_come = n_bins * Bin_wid;	/* Compute length of Histogram data */
    nxt_byte = Hm_buff_addr;
    while (bytes_to_come > 0) {
      if (bytes_to_come > Pkt_size) i = Pkt_size; else i = bytes_to_come;
      status = recv (Rw_skt, nxt_byte, i, 0);
      Rw_bytes_got += status;
      if (status == -1) FailInet ("READ_HM -- R/W-Socket data recv error\n");
      bytes_to_come = bytes_to_come - status;
      nxt_byte      = nxt_byte      + status;
    }
		/*
		** If byte swapping is necessary, do it!
		*/
    if ((Bin_wid > 0) && (Rply_buff.bigend != 0x12345678)) {
      switch (Bin_wid) {	    /* Byte swapping is necessary */
       case 2:
			/* Not sure how to do this - this might be wrong! */
        nxt_word = (short int *) Hm_buff_addr;
	for (i = 0; i < n_bins; i++) nxt_word[i] = ntohs (nxt_word[i]);
        break;
       case 4:
        nxt_long = (int *) Hm_buff_addr;
	for (i = 0; i < n_bins; i++) nxt_long[i] = ntohl (nxt_long[i]);
        break;
      }
    }
    return EXIT_SUCCESS;
  }
/*
**--------------------------------------------------------------------------*/
  void show_help () {
/*     =========
*/
	printf ("\n"
	" The following commands are recognised by SinqHM_Client:\n"
	"\n"
	"    READ <start-bin> <#-bins>	- read <#-bins> bins starting at\n"
	"                                 <start-bin>. Dflt <start-bin> = 0\n"
	"                                 Dflt <#-bins> = histogram size.\n"
	"\n"
	"    WRITE <p1> <p2> <p3> <p4> <p5> <p6> - presets the histogram\n"
	"                   memory. The 6 parameters are used to generate\n"
	"                   a function.\n"
	"\n"
	"    GO           - start data acquisition.\n"
	"\n"
	"    STOP         - stop data acquisition.\n"
	"\n"
	"    SHOW         - show Hist Mem status.\n"
	"\n"
	"    ZERO <start-bin> <#-bins>	- zero <#-bins> bins starting at\n"
	"                                 <start-bin>. Dflt <start-bin> = 0\n"
	"                                 Dflt <#-bins> = histogram size.\n"
	"\n"
	"    OPEN         - open the connection to the Hist Mem.\n"
	"\n"
	"    HELP or ?    - generate this help text.\n"
	"\n"
	" The following environment variables should be set on Unix systems:\n"
	"\n"
	"           setenv SINQHM_FRONTEND \"<host> <port> <pkt-size>\"\n"
	"           setenv SINQHM_DBG_MODE <mode>\n"
	"\n"
	" The following logical names should be set on VMS systems:\n"
	"\n"
	"           define/group sinqhm_frontend \"<host> <port> <pkt-size>\"\n"
	"           define/group sinqhm_dbg_mode <mode>\n"
	"\n"
	" Defaults:\n"
	"      <host>     None          <mode>  0\n"
	"      <port>     2400\n"
	"      <pkt-size> 8192\n"
	"\n"
	" If <mode> is non-zero, the server will suspend to allow debugging.\n"
	"\n");
  }
/*
**==========================================================================
**				Main line program
**				-----------------
**==========================================================================*/
  main (int argc, char *argv[]) {
/*==========================================================================*/
    int			i, j, k, status, is, nerr;
    char		*cmnd;
    int			bytes_to_come, bytes_to_go;
    int			f_bin, n_bins, binwid, hist_num;
    unsigned int	daq_was, daq_now, filler_mask, server_mask;
    int			mode;

    char    recd[256], recd1[256];
    char    last_recd[256] = {NIL};
    char    *verb, *p_p1, *p_p2, *p_p3, *p_p4, *p_p5, *p_p6;
    int	    l_recd;

    unsigned char	*p_byte;
    unsigned short int	*p_word;
    unsigned int	*p_long;
    unsigned int	 total;
/*============================================================================
*/
    printf ("SinqHM_Client Ident \"%s\" started.\n", ident);
/*============================================================================
**	    Declare an exit handler to tidy up if we get forced to exit.
*/
    is = atexit (exit_handler);
    if (is != 0) {
      printf ("SinqHM_Client -- error setting up exit handler.");
      exit (is);
    }
/*============================================================================
**	    Find out the location of the SINQHM root and make
**	    a connection to it. Any errors during this phase cause the program
**	    to exit with an error status.
*/
    get_SINQHM_FRONTEND (Rmt_node, sizeof (Rmt_node), "",
			 &Rmt_port, PORT_BASE,
			 &Pkt_size, 8192);
    if (Rmt_node[0] == NIL) {
      show_help ();
      printf ("\007\n"
	" The histogram memory is not defined correctly.\n"
	"\n"
	" If this is a UNIX system, check that the environment variable\n"
	" \"SINQHM_FRONTEND\" is defined correctly.\n"
	"\n"
	" If this is a VMS system, check that the logical name "
						"\"SINQHM_FRONTEND\" is\n"
	" defined correctly.\n"
	"\n");
      return EXIT_FAILURE;
    }

    get_SINQHM_DBG_MODE (&mode, 0);
/*====================================================== Wait for work =========
*/
    recd[0] = NIL;
    printf ("> ");
    while (fgets (recd, sizeof (recd), stdin) != NULL) {
      nerr = 0;	    /* Reset error counter for each unit of work. */
      if (strlen (recd) == (sizeof (recd) - 1)) {
	printf ("\n\n\007Input buffer overflow -- command ignored!\n\n");
	do {					/* Flush the remains */
	  fgets (recd, sizeof (recd), stdin);
	} while (strlen (recd) == (sizeof (recd) - 1));
	printf ("> ");
	continue;
      }
      i = strlen (recd) - 1;
      if (recd[i] == NL) recd[i] = NIL;	    /* Suppress the trailing \n */
      if (recd[0] == NIL) {		    /* If just <Return>, repeat */
        strcpy (recd, last_recd);
      }
      l_recd = sizeof (recd1);
      StrEdit (recd1, recd, "trim compress uncomment lowercase", &l_recd);
      if (l_recd <= 0) {	/* Skip empty lines */
        printf ("\n> ");
	continue;
      }
	    /*
	    ** Parse the command
	    */
      verb = strtok (recd1, " ,");
      if ((strcmp (verb, "r") == 0) ||
	  (strcmp (verb, "re") == 0) ||
	  (strcmp (verb, "rea") == 0) ||
	  (strcmp (verb, "read") == 0)) {
	if (Rw_skt == 0) {
	  Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode,
					    &Rply_buff);
	  if (Rw_skt == 0) FailInet ("\nopenConnection error.");
	}
	p_p1 = strtok (NULL, " ,");	/* Get pointers to the 3 args */
	p_p2 = strtok (NULL, " ,");
	p_p3 = strtok (NULL, " ,");
	if ((p_p1 != NULL) && (sscanf (p_p1, "%d", &f_bin) == 1)) {
	  if ((p_p2 != NULL) && (sscanf (p_p2, "%d", &n_bins) == 1)) {
	    if ((p_p3 != NULL) && (sscanf (p_p3, "%d", &hist_num) == 1)) {
	    }else {
	      hist_num = 0;
	    }
	  }else {
	    hist_num = 0;
	    n_bins = Hm_nbins;
	  }
	}else {
	  hist_num = 0;
	  n_bins = Hm_nbins;
	  f_bin = 0;
	}
	printf ("\n Read histogram memory ...\n"
	          "       First bin        = %5d\n"
		  "       Number of bins   = %5d\n"
		  "       Histogram number = %5d\n", f_bin, n_bins, hist_num);
		/*
		** Send the request message
		*/
	Req_buff.bigend = htonl (0x12345678);
	Req_buff.cmnd   = htonl (SQHM_READ);
	Req_buff.u.read.hist_no	  = htonl (hist_num);
	Req_buff.u.read.first_bin = htonl (f_bin);
	Req_buff.u.read.n_bins  = htonl (n_bins);
	status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
	if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n");
	if (status != sizeof (Req_buff)) {
	  printf ("SinqHM_Client -- wrong number of bytes sent: %d", status);
	  exit (EXIT_FAILURE);
	}
		/*
		** Now get the server's status message.
		*/
	status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
	if (status == -1) {
	  FailInet ("SinqHM_Client -- R/W-Socket recv error\n");
	  exit (EXIT_FAILURE);
	}else if (status != sizeof (Rply_buff)) {
	  printf ("SinqHM_Client --  Cnct-Socket recv error - ");
	  printf ("unexpected byte count: %d.\n", status);
	  exit (EXIT_FAILURE);
	}
	if (ntohl (Rply_buff.bigend) != 0x12345678) {
	  printf ("\007"
	    "SinqHM_Client -- big-endian/little-endian problem!\n"
	    "    Buffer received in non-network byte order!\n");
	  exit (EXIT_FAILURE);
	}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
	  printf ("SinqHM_Client -- Bad status from Read Request: %d.\n",
		    ntohl (Rply_buff.status));
	  printf ("     \"%s\"\n", Rply_buff.u.message);
	  exit (EXIT_FAILURE);
	}
		/*
		** Allocate buffer space for holding the data.
		*/
	f_bin  = ntohl (Rply_buff.u.read.first_bin);
	n_bins = ntohl (Rply_buff.u.read.n_bins);
	binwid = ntohl (Rply_buff.u.read.binwid);
	bytes_to_come = n_bins * binwid;

	if (bytes_to_come > Hm_buff_size) {	    /* Expand buffer space? */
	  Hm_buff_addr = realloc (Hm_buff_addr, bytes_to_come);   /* Yes */
	  if (Hm_buff_addr != NULL) {
	    Hm_buff_size = bytes_to_come;
	  }else {
	    printf ("SinqHM_Client -- "
			"error getting memory buffer for histogram data.\n");
	    exit (EXIT_FAILURE);
	  }
	}
		/*
		** Now read the data.
		*/
	p_byte = (unsigned char *) Hm_buff_addr;
	while (bytes_to_come > 0) {
	  i = (bytes_to_come > Pkt_size) ? Pkt_size : bytes_to_come;
	  status = recv (Rw_skt, (char *) p_byte, i, 0);
	  if (status <= 0) {
	    FailInet ("SinqHM_Client -- R/W-Socket recv error\n");
	    exit (EXIT_FAILURE);
	  }
	  bytes_to_come -= status;
	  p_byte += status;
	}
	if (0x12345678 != ntohl (0x12345678)) {	/* Swap bytes, if necessary */
	  total = 0;
	  switch (Bin_wid) {
	   case 1:
	    p_byte = (unsigned char *) Hm_buff_addr;
	    for (i=0; i<n_bins; i++) total += p_byte[i];
	    break;
	   case 2:
	    p_word = (unsigned short int *) Hm_buff_addr;
	    for (i=0; i<n_bins; i++) {
	      p_word[i] = ntohs (p_word[i]);
	      total += p_word[i];
	    }
	    break;
	   case 4:
	    p_long = (unsigned int *) Hm_buff_addr;
	    for (i=0; i<n_bins; i++) {
	      p_long[i] = ntohl (p_long[i]);
	      total += p_long[i];
	    }
	    break;
	  }
	}
	printf (" Done! Total contents of bins = %d\n", total);
	do_plot (f_bin, n_bins, binwid, total);
      }else if ((strcmp (verb, "w") == 0) ||
		(strcmp (verb, "wr") == 0) ||
		(strcmp (verb, "wri") == 0) ||
		(strcmp (verb, "writ") == 0) ||
		(strcmp (verb, "write") == 0)) {

	if (Rw_skt == 0) {
	  Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode,
					&Rply_buff);
	  if (Rw_skt == 0) FailInet ("\nopenConnection error.");
	}

	printf ("\n Writing data to histogram memory ...");
	p_p1 = strtok (NULL, " ,");	/* Get pointers to the 6 args */
	p_p2 = strtok (NULL, " ,");
	p_p3 = strtok (NULL, " ,");
	p_p4 = strtok (NULL, " ,");
	p_p5 = strtok (NULL, " ,");
	p_p6 = strtok (NULL, " ,");

	gen_data (p_p1, p_p2, p_p3, p_p4, p_p5, p_p6);
	if (0x12345678 != ntohl (0x12345678)) {	/* Swap bytes, if necessary */
	  switch (Bin_wid) {
	   case 1:
	    break;
	   case 2:
	    p_word = (unsigned short int *) Hm_buff_addr;
	    for (i=0; i<Hm_nbins; i++) p_word[i] = ntohs (p_word[i]);
	    break;
	   case 4:
	    p_long = (unsigned int *) Hm_buff_addr;
	    for (i=0; i<Hm_nbins; i++) p_long[i] = ntohl (p_long[i]);
	    break;
	  }
	}
		/*
		** Send the request message first
		*/
	Req_buff.bigend = htonl (0x12345678);
	Req_buff.cmnd   = htonl (SQHM_WRITE);
	Req_buff.u.write.n_bins  = htonl (Hm_nbins);
	Req_buff.u.write.first_bin = htonl (0);
	Req_buff.u.write.binwid  = htonl (Bin_wid);
	Req_buff.u.write.hist_no = htonl (0);
	status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
	if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n");
	if (status != sizeof (Req_buff)) {
	  printf ("SinqHM_Client -- wrong number of bytes sent: %d", status);
	  exit (EXIT_FAILURE);
	}
		/*
		** Now send the data.
		*/
	bytes_to_go = Hm_nbins * Bin_wid;
	p_byte = (unsigned char *) Hm_buff_addr;
	while (bytes_to_go > 0) {
	  i = (bytes_to_go > Pkt_size) ? Pkt_size : bytes_to_go;
	  status = send (Rw_skt, (char *) p_byte, i, 0);
	  if (status <= 0) {
	    FailInet ("SinqHM_Client -- R/W-Socket send error\n");
	    exit (EXIT_FAILURE);
	  }
	  bytes_to_go -= status;
	  p_byte += status;
	}
		/*
		** Now get the server's status message.
		*/
	status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
	if (status == -1) {
	  FailInet ("SinqHM_Client -- R/W-Socket recv error\n");
	  exit (EXIT_FAILURE);
	}else if (status != sizeof (Rply_buff)) {
	  printf ("SinqHM_Client --  Cnct-Socket recv error - ");
	  printf ("unexpected byte count: %d.\n", status);
	  exit (EXIT_FAILURE);
	}
	if (ntohl (Rply_buff.bigend) != 0x12345678) {
	  printf ("\007"
	    "SinqHM_Client -- big-endian/little-endian problem!\n"
	    "    Buffer received in non-network byte order!\n");
	  exit (EXIT_FAILURE);
	}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
	  printf ("SinqHM_Client -- Bad status from Write Request: %d.\n",
		    ntohl (Rply_buff.status));
	  printf ("     \"%s\"\n", Rply_buff.u.message);
	  exit (EXIT_FAILURE);
	}else {
	  printf (" done.\n");
	}
      }else if ((strcmp (verb, "g") == 0) ||
		(strcmp (verb, "go") == 0)) {
	if (Rw_skt == 0) {
	  Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode,
					&Rply_buff);
	  if (Rw_skt == 0) FailInet ("\nopenConnection error.");
	}
	printf ("\n Starting data acquisition ...");
		/*
		** Send the request message
		*/
	Req_buff.bigend = htonl (0x12345678);
	Req_buff.cmnd   = htonl (SQHM_DAQ);
	Req_buff.u.daq.sub_cmnd = htonl (DAQ__GO);
	status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
	if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n");
	if (status != sizeof (Req_buff)) {
	  printf ("\007\n"
		  "SinqHM_Client -- wrong number of bytes sent: %d", status);
	  exit (EXIT_FAILURE);
	}
		/*
		** Now get the server's status message.
		*/
	status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
	if (status == -1) {
	  FailInet ("\nSinqHM_Client -- R/W-Socket recv error\n");
	  exit (EXIT_FAILURE);
	}else if (status != sizeof (Rply_buff)) {
	  printf ("\007\n"
		  "SinqHM_Client --  Cnct-Socket recv error - "
		  "unexpected byte count: %d.\n", status);
	  exit (EXIT_FAILURE);
	}
	if (ntohl (Rply_buff.bigend) != 0x12345678) {
	  printf ("\007\n"
	    "SinqHM_Client -- big-endian/little-endian problem!\n"
	    "    Buffer received in non-network byte order!\n");
	  exit (EXIT_FAILURE);
	}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
	  printf ("\007\n"
		  "SinqHM_Client -- Bad status from Go Request: %d.\n",
		    ntohl (Rply_buff.status));
	  printf ("     \"%s\"\n", Rply_buff.u.message);
	  exit (EXIT_FAILURE);
	}else {
	  daq_was = ntohs (Rply_buff.u.daq.daq_was);
	  daq_now = ntohs (Rply_buff.u.daq.daq_now);
	  filler_mask = ntohs (Rply_buff.u.daq.filler_mask);
	  server_mask = ntohs (Rply_buff.u.daq.server_mask);
	  if (daq_now == 0) {
	    printf (" OK.\n");
	    if (daq_was == 0)
	      printf ("\007 Actually, data acquisition was already active.\n");
	  }else {
	    printf ("\007\n"
		    " Data acquisition not yet started. The various masks"
								" are:\n"
		    "     Dsbl_Mask   = 0x%08x\n"
		    "     Filler_Mask = 0x%08x\n"
		    "     Server_Mask = 0x%08x\n",
			daq_now, filler_mask, server_mask);
	  }
	}
      }else if ((strcmp (verb, "st") == 0) ||
		(strcmp (verb, "sto") == 0) ||
		(strcmp (verb, "stop") == 0)) {
	if (Rw_skt == 0) {
	  Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode,
					&Rply_buff);
	  if (Rw_skt == 0) FailInet ("\nopenConnection error.");
	}
	printf ("\n Stopping data acquisition ...");
		/*
		** Send the request message
		*/
	Req_buff.bigend = htonl (0x12345678);
	Req_buff.cmnd   = htonl (SQHM_DAQ);
	Req_buff.u.daq.sub_cmnd = htonl (DAQ__STOP);
	status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
	if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n");
	if (status != sizeof (Req_buff)) {
	  printf ("\007\n"
		  "SinqHM_Client -- wrong number of bytes sent: %d", status);
	  exit (EXIT_FAILURE);
	}
		/*
		** Now get the server's status message.
		*/
	status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
	if (status == -1) {
	  FailInet ("\nSinqHM_Client -- R/W-Socket recv error\n");
	  exit (EXIT_FAILURE);
	}else if (status != sizeof (Rply_buff)) {
	  printf ("\007\n"
		  "SinqHM_Client --  Cnct-Socket recv error - "
		  "unexpected byte count: %d.\n", status);
	  exit (EXIT_FAILURE);
	}
	if (ntohl (Rply_buff.bigend) != 0x12345678) {
	  printf ("\007\n"
	    "SinqHM_Client -- big-endian/little-endian problem!\n"
	    "    Buffer received in non-network byte order!\n");
	  exit (EXIT_FAILURE);
	}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
	  printf ("\007\n"
		  "SinqHM_Client -- Bad status from Stop Request: %d.\n",
		    ntohl (Rply_buff.status));
	  printf ("     \"%s\"\n", Rply_buff.u.message);
	  exit (EXIT_FAILURE);
	}else {
	  daq_was = ntohs (Rply_buff.u.daq.daq_was);
	  daq_now = ntohs (Rply_buff.u.daq.daq_now);
	  filler_mask = ntohs (Rply_buff.u.daq.filler_mask);
	  server_mask = ntohs (Rply_buff.u.daq.server_mask);
	  if (daq_now != 0) {
	    printf (" OK. The various masks are:\n"
		    "     Dsbl_Mask   = 0x%08x\n"
		    "     Filler_Mask = 0x%08x\n"
		    "     Server_Mask = 0x%08x\n",
			daq_now, filler_mask, server_mask);
	  }else {
	    printf ("\007\n"
		    " Data acquisition is still active!\n");
	  }
	}
      }else if ((strcmp (verb, "z") == 0) ||
		(strcmp (verb, "ze") == 0) ||
		(strcmp (verb, "zer") == 0) ||
		(strcmp (verb, "zero") == 0)) {
	if (Rw_skt == 0) {
	  Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode,
					&Rply_buff);
	  if (Rw_skt == 0) FailInet ("\nopenConnection error.");
	}
	p_p1 = strtok (NULL, " ,");	/* Get pointers to the 2 args */
	p_p2 = strtok (NULL, " ,");
	if ((p_p1 != NULL) && (sscanf (p_p1, "%d", &f_bin) == 1)) {
	  if (p_p2 != NULL) {
	    if (sscanf (p_p2, "%d", &n_bins) != 1) n_bins = Hm_nbins;
	  }
	}else {
	  f_bin = 0;
	  n_bins = Hm_nbins;
	}
	printf ("\n Zeroing histogram memory ...\n"
	          "       First bin = %d\n"
		  "       # bins    = %d\n", f_bin, n_bins);
		/*
		** Send the request message first
		*/
	Req_buff.bigend = htonl (0x12345678);
	Req_buff.cmnd   = htonl (SQHM_ZERO);
	Req_buff.u.zero.hist_no = htonl (-1);
	Req_buff.u.zero.first_bin = htonl (f_bin);
	Req_buff.u.zero.n_bins  = htonl (n_bins);
	status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
	if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n");
	if (status != sizeof (Req_buff)) {
	  printf ("SinqHM_Client -- wrong number of bytes sent: %d", status);
	  exit (EXIT_FAILURE);
	}
		/*
		** Now get the server's status message.
		*/
	status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
	if (status == -1) {
	  FailInet ("SinqHM_Client -- R/W-Socket recv error\n");
	  exit (EXIT_FAILURE);
	}else if (status != sizeof (Rply_buff)) {
	  printf ("SinqHM_Client --  Cnct-Socket recv error - ");
	  printf ("unexpected byte count: %d.\n", status);
	  exit (EXIT_FAILURE);
	}
	if (ntohl (Rply_buff.bigend) != 0x12345678) {
	  printf ("\007"
	    "SinqHM_Client -- big-endian/little-endian problem!\n"
	    "    Buffer received in non-network byte order!\n");
	  exit (EXIT_FAILURE);
	}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
	  printf ("SinqHM_Client -- Bad status from Zero Request: %d.\n",
		    ntohl (Rply_buff.status));
	  printf ("     \"%s\"\n", Rply_buff.u.message);
	  exit (EXIT_FAILURE);
	}else {
	  printf (" done.\n");
	}
      }else if ((strcmp (verb, "s") == 0) ||
		(strcmp (verb, "sh") == 0) ||
		(strcmp (verb, "sho") == 0) ||
		(strcmp (verb, "show") == 0)) {
	if (Rw_skt == 0) {
	  Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode,
					&Rply_buff);
	  if (Rw_skt == 0) FailInet ("\nopenConnection error.");
	}
	printf ("\n Getting histogram memory status ...\n");
		/*
		** Send the request message first
		*/
	Req_buff.bigend = htonl (0x12345678);
	Req_buff.cmnd   = htonl (SQHM_STATUS);
	status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
	if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n");
	if (status != sizeof (Req_buff)) {
	  printf ("SinqHM_Client -- wrong number of bytes sent: %d", status);
	  exit (EXIT_FAILURE);
	}
		/*
		** Now get the server's status message.
		*/
	status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
	if (status == -1) {
	  FailInet ("SinqHM_Client -- R/W-Socket recv error\n");
	  exit (EXIT_FAILURE);
	}else if (status != sizeof (Rply_buff)) {
	  printf ("SinqHM_Client --  Cnct-Socket recv error - ");
	  printf ("unexpected byte count: %d.\n", status);
	  exit (EXIT_FAILURE);
	}
	if (ntohl (Rply_buff.bigend) != 0x12345678) {
	  printf ("\007"
	    "SinqHM_Client -- big-endian/little-endian problem!\n"
	    "    Buffer received in non-network byte order!\n");
	  exit (EXIT_FAILURE);
	}else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
	  printf ("SinqHM_Client -- Bad status from Status Request: %d.\n",
		    ntohl (Rply_buff.status));
	  printf ("     \"%s\"\n", Rply_buff.u.message);
	  exit (EXIT_FAILURE);
	}else {
		/*
		**	    Display the status obtained.
		*/
	  if (Rply_buff.u.status.cfg_state == 0) {
	    printf (" SINQHM has not yet been configured.\n");
	    printf ("\n Maximum number of parallel connections supported = %d.",
		Rply_buff.u.status.max_srvrs);
	    printf ("\n Maximum number of histograms = %d.",
		ntohl (Rply_buff.u.status.max_n_hists));
	    printf ("\n Maximum number of bins per histogram = %d.",
		ntohl (Rply_buff.u.status.max_num_bins));
	    printf ("\n Maximum space available for histograms = %d.\n",
		ntohl (Rply_buff.u.status.max_block));
	  }else {
	    memcpy (recd, (char *) &Rply_buff.sub_status, 4); /* Get SinqHM Id */
	    recd[4] = '\0';
	    printf ("\n SinqHM Identifier is \"%s\"", recd);
	    printf ("\n Histogramming Mode = 0x%x",
		ntohl (Rply_buff.u.status.cfg_state));
	    printf ("\n Number of histograms/Current histogram = %d/%d",
		ntohs (Rply_buff.u.status.n_hists), (Rply_buff.u.status.curr_hist));
	    printf ("\n Number of bins per histogram = %d",
		ntohl (Rply_buff.u.status.num_bins));
	    printf ("\n Number of bytes per bin = %d", Rply_buff.u.status.binwid);
	    printf ("\n Maximum number of parallel connections supported = %d.",
		Rply_buff.u.status.max_srvrs);
	    printf ("\n Current number of connections = %d.",
		Rply_buff.u.status.act_srvrs);
	    printf ("\n Maximum free memory block = %d bytes.",
		ntohl (Rply_buff.u.status.max_block));
	    if (Rply_buff.u.status.daq_now == 0) {
	      printf ("\n Data acquisition is active\n");
	    }else {
	      printf ("\n Data acquisition is not active\n");
	    }
	  }
	}
      }else if ((strcmp (verb, "o") == 0) ||
		(strcmp (verb, "op") == 0) ||
		(strcmp (verb, "ope") == 0) ||
		(strcmp (verb, "open") == 0)) {
	if (Rw_skt == 0) {
	  printf ("\n Opening the connection ...\n");
	  Rw_skt = openConnectionGbl (Rmt_node, &Rmt_port, &Pkt_size, mode,
					&Rply_buff);
	  if (Rw_skt == 0) FailInet ("\nopenConnection error.");
	}else {
	  printf ("\n The connection is already open!");
	}
      }else if ((strcmp (verb, "?") == 0) ||
		(strcmp (verb, "h") == 0) ||
		(strcmp (verb, "he") == 0) ||
		(strcmp (verb, "hel") == 0) ||
		(strcmp (verb, "help") == 0)) {
	show_help ();
      }else {
        printf ("\n Illegal command - type \"?\" for help.\n");
      }
      strcpy (last_recd, recd);
	    /*
	    ** Get another command.
	    */
      printf ("> ");
    }
/*
**			Tell server we're quitting.
*/
    printf (" Closing connection to %s ...\n", Rmt_node);
    Req_buff.bigend = htonl (0x12345678);
    Req_buff.cmnd = htonl (SQHM_CLOSE);
    status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    Rw_bytes_put += status;
    if (status == -1) FailInet ("SinqHM_Client -- R/W-Socket send error\n");
    if (status != sizeof (Req_buff)) {
        printf ("SinqHM_Client -- wrong number of bytes sent: %d", status);
        exit (EXIT_FAILURE);
    }
    status = close (Rw_skt);
    Rw_skt = 0;
    if (status != 0) FailInet ("SinqHM_Client -- R/W-Socket close error\n");

    exit (EXIT_SUCCESS);
  }
/*============================================= End of SinqHM_Client.C ======*/
