#define	    IDENT	"1C06"
/*---------------------------------------------------------------------------*/
#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:cpgplot.olb/lib
**!	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 := tas_src:[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/data/lnslib -I.			    \
**			~/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.
**
**====================================================================
*/

#include    <errno.h>
#include    <netdb.h>
#include    <stdio.h>
#include    <stdlib.h>
#include    <stdarg.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>
#include    <X11/Intrinsic.h>

#ifdef	__VMS
#include    <pgplot_dir:cpgplot.h>
#else
#include    <cpgplot.h>
#endif
/*
**====================	Global Definitions =====================================
*/
#include    <sinq_prototypes.h>

#include    "SinqHM_def.h"

#define	    uchar	unsigned char
#define	    usint	unsigned short int
#define	    uint	unsigned int
#define	    NIL		'\0'
#define	    NL		'\n'
#define	    MAXERR	10
#define	    MAX_HIS	16
#define	    BSIZE	((128*1024)/512)	/* Specify 128 kbyte buffer */

#ifndef True
#define True	1
#endif

#ifndef False
#define False	0
#endif

  /*
  **			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		Verbose;
  int		Rmt_port;
  int		Pkt_size;
  char		Rmt_host[32];
  int		Rw_bytes_got, Rw_bytes_put;
  static int	Cnct_skt = 0;	    /* Connect socket */
  static int	Rw_skt = 0;	    /* Read/write socket */
  int		Dbg_mode;	    /* Setting of <strt_mode> in the SQHM_CNCT
				    **	message to SINQHM server */
/*
**		The buffer for holding Hist Mem data is pointed to
**		by Hm_buff_addr. The number of bytes allocated is Hm_buff_size.
*/
  void		*Hm_buff_addr = NULL;
  uint		 Hm_buff_size;
  uint		 Hm_buff_used;
  uint		 Hm_mode;	/* Histogramming Mode of Histogram Memory */
  uint		 N_hists;	/* The number of histograms */
  uint		 Hm_nbins;	/* The number of bins per histogram */
  uint		 Compress;	/* The span of each bin */
  uint		 Bytes_per_bin;	/* The number of bytes per bin */
  uint		 Curr_hist;	/* The current histogram */
  uint		 Max_block;
  uint		 Lo_cntr;
  uint		 Lo_bin;
  uint		 Total_bytes;

  int		 PGPLOT_started = 0;

  float		 P1 = 2000000,
		 P2 =   10000, 
		 P3 =       0, 
		 P4 =  200000, 
		 P5 =     500, 
		 P6 =       0;

  static XrmOptionDescRec OpTable_0[] = {
      {"-name",	    ".name",		XrmoptionSepArg, (XPointer) NULL},
      {"-dbg",	    ".sqhmDebug",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-debug",    ".sqhmDebug",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-h",	    ".sqhmHelp",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-he",	    ".sqhmHelp",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-hel",	    ".sqhmHelp",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-help",	    ".sqhmHelp",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-ho",	    ".sqhmHost",	XrmoptionSepArg, (XPointer) NULL},
      {"-hos",	    ".sqhmHost",	XrmoptionSepArg, (XPointer) NULL},
      {"-host",	    ".sqhmHost",	XrmoptionSepArg, (XPointer) NULL},
      {"-port",	    ".sqhmPort",	XrmoptionSepArg, (XPointer) NULL},
      {"-pktsize",  ".sqhmPktSize",	XrmoptionSepArg, (XPointer) NULL},
      {"-size",	    ".sqhmPktSize",	XrmoptionSepArg, (XPointer) NULL},
      {"-v",	    ".sqhmVerbose",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-?",	    ".sqhmHelpItem",	XrmoptionSepArg, (XPointer) NULL},
    };
/*
**=============================================================================
**  Local routines.
**
**  do_dump		: Dump out the contents of the histogram buffer.
**  do_load		: Load the histogram buffer from a file.
**  do_plot		: Plot the data.
**  do_project		: Handle the "PROJECT" command.
**  do_status		: Get and display status of SinqHM_srv.
**  do_1d		: Handle the "READ" command.
**  do_2d		: Handle the "2D"   command.
**  do_2d_plot		: Plot the data 2-dimensionally.
**  exit_handler	: Exit handler in case a forced exit is made.
**  gen_data		: Generate sum of 2 Lorenzians.
**  gen_data_2d		: Generate sum of 2 Lorenzians in pseudo 2-dim mode.
**  get_recd		: Read a record from file.
**  new_config_quit	: Quit because SinqHM config'n has changed.
**  openConnection	: Open connection to SinqHM.
**  openConnectionGbl	: Call openConnection then set up some globals.
**  print_HM_mode	: Interpret the HM configuration.
**  print_uptime	: Print out the up-time.
**  read_hm		: Read block of bins from SINQHM_SRV
**  read_project	: Read projected block of bins from SINQHM_SRV
**  show_help		: Display the help text.
**  split_args		: Parse a command line.
**  write_hm		: Write block of bins to SINQHM_SRV
**----------------------------------------------------------------------------
**							    Prototypes
*/
  void	    do_dump (char *args);
  void	    do_load (char *args, int dbg_mode);
  void	    do_plot (uint first, uint n_bins, uint bytes_per_bin, uint total);
  void	    do_project (char *args, int dbg_mode);
  void	    do_status (int dbg_mode);
  void	    do_1d (char *args, int dbg_mode);
  void	    do_2d (char *args, int dbg_mode);
  void	    do_2d_plot (uint f_hist, uint n_hists, uint f_bin, uint n_bins,
			    uint bytes_per_bin, uint total);
  void	    exit_handler ();
  void	    gen_data (char *args);
  void	    gen_data_2d (char *args);
  int	    get_check_resources (XrmDatabase *db,
				 char	     *appName,
				 int	     *argc,
				 char	     *argv[],
				 int	      verbose);
  int	    get_recd (FILE *lun, char *recd, int recd_len);
  void	    new_config_quit (char *txt);
  int	    openConnection (char    *node,
			    int	    *port,
			    int	    *pkt_size,
			    int	     mode,
			    struct rply_buff_struct *reply,
			    int	     verbose);
  int	    openConnectionGbl (char     *node,
			       int	*port,
			       int	*pkt_size,
			       int	 mode,
			       struct rply_buff_struct *reply,
			       int	 verbose);
  void	    print_HM_mode (uint mode, int n_pad);
  void	    print_uptime (FILE *lun, char *prefix, int secs, char *suffix);
  int	    read_hm (char  *buff,
		     uint  hbuf_size,
		     uint  f_bin,
		     uint  n_bins,
		     uint  hist_num,
		     uint *cntr_lo,
		     uint *cntr_hi);
  int	    read_project (char	  *buff,
		     uint  hbuf_size,
		     uint  f_hist,
		     uint  n_hists,
		     uint  f_bin,
		     uint  n_bins,
		     uint  axis,
		     uint  xdim,
		     uint  h_select,
		     uint *cntr_lo,
		     uint *cntr_hi);
  int	    setup_xrm_database (XrmDatabase	*db,
				char		*name[],
				int		*argc,
				char		*argv[],
				int		verbose);
  void	    show_help (char *token);
  void	    split_args (char *args, ...);
  int	    write_hm (void  *buff,
		     uint  hist_no,
		     uint  f_bin,
		     uint  n_bins,
		     uint  bpb);
/*
**----------------------------------------------------------------------------*/
  void 	do_dump (char *args) {
/*	=======
**		Dump out the contents of the histogram buffer
**		Args are:
**		    Number of first bin	to dump (dflt = 0)
**		    Number of bins to dump      (dflt = rest of buffer)
**		    File to receive the data    (dflt = standard output)
*/
    int		i, j, k;
    time_t	time_now;
    uint	n_items, f_bin, n_bins;
    uint	total = 0;
    char	*p_p1, *p_p2, *p_p3;
    char	recd[256];
    FILE	*lun;

    uchar	*p_byte;
    usint	*p_word;
    uint	*p_long;

    if (Hm_buff_used == 0) {
      printf ("There is nothing available to dump!\n");
      return;
    }

    n_items = Hm_buff_used/Bytes_per_bin;

    split_args (args, &p_p1, &p_p2, &p_p3, NULL);
    if (p_p1 == NULL) p_p1 = "0";
    if ((sscanf (p_p1, "%u", &f_bin) != 1) ||
	(f_bin >= n_items)) {
      printf ("<1st-bin> is invalid: \"%s\"\n", p_p1);
      return;
    }

    if (p_p2 == NULL) {
      n_bins = n_items - f_bin;
    }else {
      if ((sscanf (p_p2, "%u", &n_bins) != 1) ||
          (n_bins > n_items) ||
	  ((n_bins + f_bin) > n_items)) {
	printf ("<#-bins> is invalid: \"%s\"\n", p_p2);
	n_bins = n_items - f_bin;
	printf ("It has been set to %d\n", n_bins);
      }
    }

    if (p_p3 == NULL) {
      printf (" Dumping histogram memory buffer ...\n");
      lun = stdout;
    }else {
      printf (" Opening file %s to receive the memory dump ...\n", p_p3);
      lun = fopen (p_p3, "w");
      if (lun == NULL) {
	printf ("  ... failed to open file. No dump made!\n");
	return;
      }
      time_now = time (NULL);
      fprintf (lun, "! Histogram Memory Dump of %s at %s",
				Rmt_host, asctime (localtime (&time_now)));
      fprintf (lun, "! =====================\n");
    }

    fprintf (lun, "First-bin:      %5u\n", f_bin);
    fprintf (lun, "Number-of-bins: %5u\n", n_bins);

    p_byte = (uchar	*) Hm_buff_addr;
    p_word = (usint	*) Hm_buff_addr;
    p_long = (uint	*) Hm_buff_addr;

    for (i = 0; i < n_bins; i += 10) {
      k = 0;
      for (j = 0; j < 10; j++) {
	if ((i + j) >= n_bins) break;
	switch (Bytes_per_bin) {
	 case 1: k += sprintf (&recd[k], "%5d", p_byte[f_bin+i+j]);
		 total += p_byte[f_bin+i+j];
		 break;
	 case 2: k += sprintf (&recd[k], "%6d", p_word[f_bin+i+j]);
		 total += p_word[f_bin+i+j];
		 break;
	 case 4: k += sprintf (&recd[k], "%7d", p_long[f_bin+i+j]);
		 total += p_long[f_bin+i+j];
	}
      }
      if (j > 0) fprintf (lun, "%6d: %s\n", f_bin+i, recd);
    }
    if (lun == stdout) printf ("\n");
    fprintf (lun, "Total: %u\n", total);
    if (lun != stdout) {
      fclose (lun);
      chmod (p_p3, 0644);
      printf (" ... dump completed.\n");
    }
  }
/*
**----------------------------------------------------------------------------*/
  void 	do_load (char *args, int dbg_mode) {
/*	=======
**		Load the contents of the histogram buffer from a file
**		Args are:
**		    File to read to get the data (dflt = standard input)
*/
    int		i, j, binnum, status;
    uint	bytes_needed, f_bin, n_bins, value;
    uint	total = 0;
    char	*p_p1, *pBinnum, *tok;
    char	recd[256];
    FILE	*lun;

    uchar	*p_byte;
    usint	*p_word;
    uint	*p_long;

    if (Rw_skt == 0) {
      Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, dbg_mode,
					    &Rply_buff, Verbose);
      if (Rw_skt == 0) FailInet ("\ndo_load/openConnectionGbl error.");
    }

    split_args (args, &p_p1, NULL);
    if (p_p1 == NULL) {
      printf (" Loading histogram memory from standard input ...\n");
      lun = stdin;
    }else {
      printf (" Reading histogram memory data from file %s ...\n", p_p1);
      lun = fopen (p_p1, "r");
      if (lun == NULL) {
	printf ("  ... failed to open file. No load done!\n");
	return;
      }
    }

    get_recd (lun, recd, sizeof (recd));    /* Get first non-comment record */
    i = sscanf (recd, "First-bin: %i%n", &f_bin, &j);
    if ((i != 1) || (j != strlen (recd))) {
      printf ("  ... First-bin record not found. No load done!\n");
      if (lun != stdin) fclose (lun);
      return;
    }

    get_recd (lun, recd, sizeof (recd));    /* Get second non-comment record */
    i = sscanf (recd, "Number-of-bins: %i%n", &n_bins, &j);
    if ((i != 1) || (j != strlen (recd))) {
      printf ("  ... Number-of-bins record not found. No load done!\n");
      if (lun != stdin) fclose (lun);
      return;
    }
    printf ("First-bin:      %5u\n", f_bin);
    printf ("Number-of-bins: %5u\n", n_bins);

    bytes_needed = n_bins * Bytes_per_bin;
    if (bytes_needed > Hm_buff_size) {		/* Expand buffer space? */
      Hm_buff_addr = realloc (Hm_buff_addr, bytes_needed);  /* Yes */
      if (Hm_buff_addr != NULL) {
	Hm_buff_size = bytes_needed;
      }else {
	printf ("Error getting memory buffer for file data. No load done!\n");
	if (lun != stdin) fclose (lun);
	return;
      }
    }
    Hm_buff_used = bytes_needed;

    p_byte = (uchar *) Hm_buff_addr;
    p_word = (usint *) Hm_buff_addr;
    p_long = (uint  *) Hm_buff_addr;

    for (i = 0; i < n_bins; i += 10) {
      status = get_recd (lun, recd, sizeof (recd));    /* Get another record */
      if (!status) {
	printf ("Error getting data from file at record %d! No load done!\n",
			    (i+10)/10);
	if (lun != stdin) fclose (lun);
	return;
      }
      pBinnum = strtok (recd, ":");
      if ((pBinnum == NULL) ||
	  (sscanf (pBinnum, "%i", &binnum) != 1) ||
	  (binnum != (i + f_bin))) {
	printf ("Bin number wrong at record %d! No load done!\n", (i+10)/10);
	if (lun != stdin) fclose (lun);
	return;
      }
      for (j = 0; j < 10; j++) {
	if ((i + j) >= n_bins) break;
	tok = strtok (NULL, " ");
	if ((tok == NULL) || (sscanf (tok , "%u", &value) != 1)) {
	  printf ("Bad data value on record %d! No load done!\n", (i+10)/10);
	  if (lun != stdin) fclose (lun);
	  return;
	}
	switch (Bytes_per_bin) {
	 case 1: p_byte[i+j] = value; total += p_byte[i+j]; break;
	 case 2: p_word[i+j] = value; total += p_word[i+j]; break;
	 case 4: p_long[i+j] = value; total += p_long[i+j];
	}
      }
    }

    get_recd (lun, recd, sizeof (recd));    /* Get last non-comment record */
    i = sscanf (recd, "Total: %i%n", &value, &j);
    if ((i != 1) || (j != strlen (recd))) {
      printf ("  ... \"Total\" record not found. No load done!\n");
      if (lun != stdin) fclose (lun);
      return;
    }
    if (value != total) {
      printf ("  ... the \"Total\" record is inconsistent. No load done!\n");
      printf ("           Total of bins           = %6u\n"
	      "           Total on \"Total\" record = %6u\n", total, value);
      if (lun != stdin) fclose (lun);
      return;
    }
    printf (" Sending the data ...");
    status = write_hm (Hm_buff_addr, -1, f_bin, n_bins, Bytes_per_bin);
    if (lun != stdin) fclose (lun);
    if (status) printf (" load completed.\n");
  }
/*
**----------------------------------------------------------------------------*/
  void do_plot (uint first, uint n_bins, uint bytes_per_bin, uint total) {
/*     =======
**				Make a plot of the data.
*/
    int		i;
    char	total_txt[21];
#ifdef LINUX
    char	dev[] = "/XSERV";
#else
    char	dev[] = "/XW";
#endif
    char	xlab[] = "Bins";
    char	ylab[] = "Counts";
    float	xlo, xhi, yhi;
    float	*x;
    float	*y;

    uchar	*p_byte;
    usint	*p_word;
    uint	*p_long;

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

    x = (float *) malloc ((n_bins + 1) * 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");
      return;
    }

    sprintf (total_txt, "Bin Total = %8d", total);

    p_byte = (uchar *) Hm_buff_addr;
    p_word = (usint *) Hm_buff_addr;
    p_long = (uint  *) Hm_buff_addr;

    if (PGPLOT_started == 0) {
      cpgbeg (0, dev, 1, 1);
	    /* - - - - - - - - - - - - - - - - - - - - - -
	    ** Set black on white (hopefully)
	    */
      cpgscr (0, 0.79, 0.67, 0.57);
      cpgscr (1, 0.0, 0.0, 0.0);

      cpgask (0);
      PGPLOT_started = 1;
    }
    xlo = (float) first;
    xhi = (float) first + n_bins + 1;
    yhi = 10.0;
    switch (bytes_per_bin) {
     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;
    }
    x[n_bins] = first + n_bins;
    yhi = cpgrnd (yhi, &i);
    cpgenv (xlo, xhi, 0.0, yhi, 0, 0);
    cpglab (xlab, ylab, total_txt);
    cpgbin (n_bins, x, y, False);
    cpgmove (x[n_bins], y[n_bins-1]); cpgdraw (x[n_bins], 0.0);

    free (x);
    free (y);
  }
/*
**----------------------------------------------------------------------------*/
  void 	do_project (char *args, int dbg_mode) {
/*	==========
**	Generate a projected plot of a 2-dim hist (e.g. of TOF array of cntrs)
**		Args are:
**		    Number of first histogram
**		    Number of histograms
**		    Number of first bin
**		    Number of bins
**		    Axis ('X' = x-axis, 'Y' = y-axis)
**		    x-dim
**		Default is to project everything onto x-axis
*/
    char	    *p_p1, *p_p2, *p_p3, *p_p4, *p_p5, *p_p6, *p_p7;
    int		    i, status, axis;
    uint	    f_hist, n_hists, f_bin, n_bins;
    uint	    x_dim, h_slct, eff_nbins, eff_nhists;
    uint	    nbins_to_read, bytes_needed, total, cntr_lo, cntr_hi;

    uchar	*p_byte;
    usint	*p_word;
    uint	*p_long;

    if (Rw_skt == 0) {
      Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, dbg_mode,
					    &Rply_buff, Verbose);
      if (Rw_skt == 0) FailInet ("\ndo_project/openConnectionGbl error.");
    }

    split_args (args, &p_p1, &p_p2, &p_p3, &p_p4,	/* Get pntrs to */
			    &p_p5, &p_p6, &p_p7, NULL);	/* the 7 args */

    if (p_p6 == NULL) {
      x_dim = 0;
    }else {
      if ((sscanf (p_p6, "%u", &x_dim) != 1) ||
	  (x_dim > Hm_nbins) ||
	  ((x_dim != 0) && ((Hm_nbins % x_dim) != 0))) {
	printf ("<x-dim> is invalid: \"%s\"\n", p_p6);
	printf ("<x-dim> must be an exact divisor of the number of bins "
			    "per histogram, %d\n", Hm_nbins);
	return;
      }
    }
    eff_nbins  = (x_dim == 0) ? Hm_nbins : x_dim;
    eff_nhists = (x_dim == 0) ? N_hists  : (Hm_nbins/x_dim);

    if (p_p1 == NULL) p_p1 = "0";
    if ((sscanf (p_p1, "%u", &f_hist) != 1) ||
	(f_hist >= eff_nhists)) {
      printf ("<1st-hist> is invalid: \"%s\"\n", p_p1);
      printf ("It must be an integer in the range 0 to %d\n", (eff_nhists - 1));
      return;
    }

    if (p_p2 == NULL) {
      n_hists = eff_nhists - f_hist;
    }else {
      if ((sscanf (p_p2, "%u", &n_hists) != 1) ||
	  (n_hists == 0) ||
	  (n_hists > eff_nhists) ||
	  ((n_hists + f_hist) > eff_nhists)) {
	printf ("<#-hists> is invalid: \"%s\"\n", p_p2);
	printf ("It must be an integer in the range 1 to %d\n",
			    (eff_nhists - f_hist));
	return;
      }
    }

    if (p_p3 == NULL) p_p3 = "0";
    if ((sscanf (p_p3, "%u", &f_bin) != 1) ||
	(f_bin >= eff_nbins)) {
      printf ("<1st-bin> is invalid: \"%s\"\n", p_p3);
      printf ("It must be an integer in the range 0 to %d\n",
			    (eff_nbins - 1));
      return;
    }

    if (p_p4 == NULL) {
      n_bins = eff_nbins - f_bin;
    }else {
      if ((sscanf (p_p4, "%u", &n_bins) != 1) ||
	  (n_bins > eff_nbins) ||
	  ((n_bins + f_bin) > eff_nbins)) {
	printf ("<#-bins> is invalid: \"%s\"\n", p_p4);
	printf ("It must be an integer in the range 1 to %d\n",
			    (eff_nbins - f_bin));
	return;
      }
    }

    if (p_p5 == NULL) {
      axis = 0;
    }else {
      if (strcmp ("x", p_p5) == 0) {
	axis = 0;
      }else if (strcmp ("y", p_p5) == 0) {
	axis = 1;
      }else if (sscanf (p_p4, "%u", &axis) == 1) {
	if (axis != 0) axis = 1;
      }else {
	printf ("<axis> is invalid: \"%s\"\n", p_p5);
	printf ("It should be \"x\" or \"y\"\n");
	return;
      }
    }

    if (p_p7 == NULL) {
      h_slct = 0;
    }else {
      if ((sscanf (p_p7, "%u", &h_slct) != 1) ||
	  (h_slct > N_hists)) {
	printf ("<hist-#> is invalid: \"%s\"\n", p_p7);
	printf ("It must be an integer in the range 1 to %d\n", (N_hists - 1));
	return;
      }
    }

    printf ("\n Read Projected Region of 2-dimensional histogram ...\n"
	          "       First histogram      = %5u\n"
		  "       Number of histograms = %5u\n"
	          "       First bin            = %5u\n"
		  "       Number of bins       = %5u\n",
			    f_hist, n_hists, f_bin, n_bins, axis);
    if (axis == 0) printf ("       Axis                 =     X\n");
    if (axis != 0) printf ("       Axis                 =     Y\n");
    if (x_dim != 0) printf ("       x-dimension          = %5u\n", x_dim);
		/*
		** Allocate buffer space for holding the data. The space needed
		** depends on whether it is an x- or y-projection.
		*/
    nbins_to_read = (axis == 0) ? n_bins : n_hists;
    bytes_needed = nbins_to_read * sizeof (uint);
    if (bytes_needed > Hm_buff_size) {		/* Expand buffer space? */
      Hm_buff_addr = realloc (Hm_buff_addr, bytes_needed);  /* Yes */
      if (Hm_buff_addr != NULL) {
	Hm_buff_size = bytes_needed;
      }else {
	printf ("SinqHM_Client -- "
			"error getting memory buffer for histogram data.\n");
	exit (EXIT_FAILURE);
      }
    }
    Hm_buff_used = bytes_needed;

    status = read_project (Hm_buff_addr, Hm_buff_size,
			    f_bin, n_bins, f_hist, n_hists, axis, x_dim, h_slct,
			    &cntr_lo, &cntr_hi);
    if (status == EXIT_SUCCESS) {
      total = 0;
      switch (Bytes_per_bin) {
       case 1:
	p_byte = (uchar *) Hm_buff_addr;
	for (i = 0; i < nbins_to_read; i++) total += p_byte[i];
	break;
       case 2:
	p_word = (usint *) Hm_buff_addr;
	for (i = 0; i < nbins_to_read; i++) total += p_word[i];
	break;
       case 4:
	p_long = (uint *) Hm_buff_addr;
	for (i = 0; i < nbins_to_read; i++) total += p_long[i];
      }
      printf (" Done! Total contents of bins = %d\n", total);
      if (cntr_lo != 0) printf (" Number of underflow events = %u\n", cntr_lo);
      if (cntr_hi != 0) printf (" Number of overflow  events = %u\n", cntr_hi);
      if (axis == 0) {
	do_plot (f_bin, n_bins, Bytes_per_bin, total);
      }else {
	do_plot (f_hist, n_hists, Bytes_per_bin, total);
      }
    }
  }
/*
**----------------------------------------------------------------------------*/
  void 	do_status (int dbg_mode) {
/*	=========
**		Get and display status of SinqHM_srv
*/
    int		i, status, secs, mins, hrs, days;
    int		off_a, off_b, off_c, off_d, off_e, off_f;
    int		off_g, off_h, off_i, off_j, off_k, off_l;
    uint	state, nh, nb, bpb, span, ch, bytes_to_come;
    char	recd[256], *p_buff, *p_nxt;
    uint	tsi_status, tsi_flags, dt_or_dts, num_bad_ev;

    if (Rw_skt == 0) {
      Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, dbg_mode,
					&Rply_buff, Verbose);
      if (Rw_skt == 0) FailInet ("\ndo_status/openConnectionGbl error.");
    }
    printf ("\n Getting histogram memory identification ...\n");
		/*
		** Send the ident request message first
		*/
    Req_buff.bigend = htonl (0x12345678);
    Req_buff.cmnd   = htonl (SQHM_IDENT);
    status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    if (status == -1) FailInet ("do_status -- 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 ident message.
		*/
    status = recv (Rw_skt, (char *) &Rply_buff, sizeof (Rply_buff), 0);
    if (status == -1) {
      FailInet ("do_status -- R/W-Socket recv error\n");
      exit (EXIT_FAILURE);
    }else if (status != sizeof (Rply_buff)) {
      printf ("do_status --  Cnct-Socket recv error - ");
      printf ("unexpected byte count: %d.\n", status);
      exit (EXIT_FAILURE);
    }
    if (ntohl (Rply_buff.bigend) != 0x12345678) {
      printf (
	    "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__BAD_VALUE) {
      printf ("   ... identification request not supported\n");
    }else if (ntohl (Rply_buff.status) != KER__SUCCESS) {
      printf ("SinqHM_Client -- Bad status from Ident Request: %d.\n",
		    ntohl (Rply_buff.status));
      printf ("     \"%s\"\n", Rply_buff.u.message);
      exit (EXIT_FAILURE);
    }else {
		/*
		**	    Get the rest of the response
		*/
      bytes_to_come = ntohl (Rply_buff.u.ident.n_extra_bytes);
      p_buff = calloc (bytes_to_come, 1);
      if (p_buff == NULL) {
	printf ("Could not get buffer space for ident information\n");
	exit (EXIT_FAILURE);
      }
      p_nxt = p_buff;
      while (bytes_to_come > 0) {
	i = (bytes_to_come > Pkt_size) ? Pkt_size : bytes_to_come;
	status = recv (Rw_skt, p_nxt, i, 0);
	Rw_bytes_got += status;
	if (status == -1) FailInet ("do_status -- R/W-Socket data recv error\n");
	bytes_to_come -= status;
	p_nxt	      += status;
      }
		/*
		**	    Extract and print the information
		*/
      off_a = ntohs (Rply_buff.u.ident.offset_vxWorks_ident);
      off_b = ntohs (Rply_buff.u.ident.offset_vxWorks_date);
      off_c = ntohs (Rply_buff.u.ident.offset_instr);
      off_d = ntohs (Rply_buff.u.ident.offset_def_ident);
      off_e = ntohs (Rply_buff.u.ident.offset_sinqhm_main_ident);
      off_f = ntohs (Rply_buff.u.ident.offset_sinqhm_main_date);
      off_g = ntohs (Rply_buff.u.ident.offset_sinqhm_server_ident);
      off_h = ntohs (Rply_buff.u.ident.offset_sinqhm_server_date);
      off_i = ntohs (Rply_buff.u.ident.offset_sinqhm_filler_ident);
      off_j = ntohs (Rply_buff.u.ident.offset_sinqhm_filler_date);
      off_k = ntohs (Rply_buff.u.ident.offset_sinqhm_routines_ident);
      off_l = ntohs (Rply_buff.u.ident.offset_sinqhm_routines_date);
      i = strlen (&p_buff[off_b]) + 1;
      StrEdit (&p_buff[off_b], &p_buff[off_b], "compress trim", &i);
      i = strlen (&p_buff[off_f]) + 1;
      StrEdit (&p_buff[off_f], &p_buff[off_f], "compress trim", &i);
      i = strlen (&p_buff[off_h]) + 1;
      StrEdit (&p_buff[off_h], &p_buff[off_h], "compress trim", &i);
      i = strlen (&p_buff[off_j]) + 1;
      StrEdit (&p_buff[off_j], &p_buff[off_j], "compress trim", &i);
      i = strlen (&p_buff[off_l]) + 1;
      StrEdit (&p_buff[off_l], &p_buff[off_l], "compress trim", &i);

      printf (" Instrument = %s, SinqHM Protocol Identifier = %s\n",
		    &p_buff[off_c], &p_buff[off_d]);
      printf (" SinqHM_srv_main     Identifier %s compiled on %s\n",
			    &p_buff[off_e], &p_buff[off_f]);
      printf (" SinqHM_srv_server   Identifier %s compiled on %s\n",
			    &p_buff[off_g], &p_buff[off_h]);
      printf (" SinqHM_srv_filler   Identifier %s compiled on %s\n",
			    &p_buff[off_i], &p_buff[off_j]);
      printf (" SinqHM_srv_routines Identifier %s compiled on %s\n",
			    &p_buff[off_k], &p_buff[off_l]);
      printf (" vxWorks Version %s created on %s\n", &p_buff[off_a],
			    &p_buff[off_b]);
      print_uptime (stdout, " Up-time = ", ntohl (Rply_buff.u.ident.up_time),
				    "\n");
      free (p_buff);
    }
/*----------------------------------------------------------------------------*/
    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 ("do_status -- 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 ("do_status -- R/W-Socket recv error\n");
      exit (EXIT_FAILURE);
    }else if (status != sizeof (Rply_buff)) {
      printf ("do_status --  Cnct-Socket recv error - ");
      printf ("unexpected byte count: %d.\n", status);
      exit (EXIT_FAILURE);
    }
    if (ntohl (Rply_buff.bigend) != 0x12345678) {
      printf (
	    "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.
		*/
      printf (" Maximum number of connections        = %6d\n",
		Rply_buff.u.status.max_srvrs);
      printf (" Maximum number of histograms         = %6d\n",
		ntohl (Rply_buff.u.status.max_n_hists));
      printf (" Maximum number of bins per histogram = %6d\n",
		ntohl (Rply_buff.u.status.max_num_bins));
      if (Rply_buff.u.status.cfg_state == 0) {
	printf (" Space available for histograms       = %6d\n\n",
		ntohl (Rply_buff.u.status.max_block));
      }else {
	printf (" Free buffer space available          = %6d\n\n",
		ntohl (Rply_buff.u.status.max_block));
      }

      if (Rply_buff.u.status.cfg_state == 0) {
	printf (" SINQHM has not yet been configured.\n");
      }else {
	state = ntohl (Rply_buff.u.status.cfg_state);
	nh    = ntohs (Rply_buff.u.status.n_hists);
	ch    = ntohs (Rply_buff.u.status.curr_hist);
	nb    = ntohl (Rply_buff.u.status.num_bins);
	bpb   = Rply_buff.u.status.bytes_per_bin;
	span  = Rply_buff.u.status.compress;
	if ((Hm_mode & (~SQHM__SUB_MODE_MSK)) !=
	    (state   & (~SQHM__SUB_MODE_MSK)))
	  new_config_quit ("hm_mode/cfg_state");
	if (N_hists != nh) new_config_quit ("n_hists");
	if (Hm_nbins != nb) new_config_quit ("num_bins");
	if (Bytes_per_bin != bpb) new_config_quit ("bytes_per_bin");

	print_HM_mode (state, 10);
	if (nh != 1) printf (" Number of histograms         = %6d\n", nh);
	if (ch != 0) printf (" Current histogram            = %6d\n", ch);
	printf (" Number of bins per histogram = %6d\n", nb);
	if (nh > 1) printf (" Total number of bins         = %6d\n", nh * nb);
	if (span > 1) printf (" Bin span                     = %6d\n", span);
	printf (" Number of bytes per bin      = %6d\n", bpb);
	printf (" Number of active connections = %6d\n",
			Rply_buff.u.status.act_srvrs);
	if (Rply_buff.u.status.daq_now == 0) {
	  printf (" Data acquisition is active\n");
	}else {
	  printf (" Data acquisition is not active\n");
	}
	tsi_status = ntohs (Rply_buff.u.status.tsi_status);
	tsi_flags  = ntohs (Rply_buff.u.status.flags);
	dt_or_dts  = ntohl (Rply_buff.u.status.dt_or_dts.both);
	num_bad_ev = ntohl (Rply_buff.u.status.num_bad_events);
	if (dt_or_dts != 0) {
	  if ((Hm_mode & (~SQHM__SUB_MODE_MSK)) == SQHM__TOF) {
	    printf (" Delay-Time-to-Start          = %6u\n", dt_or_dts);
	  }else {
	    printf (" Dead-Time                    = %6u\n", dt_or_dts);
	  }
	}
	if (num_bad_ev != 0) {
	  printf (" Number-of-Bad-Events         = %u\n", num_bad_ev);
	}
	if ((tsi_status != 0) || (tsi_flags != 0)) {
	  printf (" TSI Status Info              =   0x%04x\n", tsi_status);
	  printf (" TSI Flags                    =   0x%04x", tsi_flags);
	  if ((tsi_flags & STATUS_FLAGS__PF)    != 0) printf (" PF");
	  if ((tsi_flags & STATUS_FLAGS__SWC)   != 0) printf (" SWC");
	  if ((tsi_flags & STATUS_FLAGS__NRL)   != 0) printf (" NRL");
	  if ((tsi_flags & STATUS_FLAGS__DAQ)   != 0) printf (" DAQ");
	  if ((tsi_flags & STATUS_FLAGS__SYNC3) != 0) printf (" SYNC3");
	  if ((tsi_flags & STATUS_FLAGS__SYNC2) != 0) printf (" SYNC2");
	  if ((tsi_flags & STATUS_FLAGS__SYNC1) != 0) printf (" SYNC1");
	  if ((tsi_flags & STATUS_FLAGS__SYNC0) != 0) printf (" SYNC0");
	  if ((tsi_flags & STATUS_FLAGS__UD)    != 0) printf (" UD");
	  if ((tsi_flags & STATUS_FLAGS__GU)    != 0) printf (" GU");
	  printf ("\n");
	}
      }
    }
  }
/*
**----------------------------------------------------------------------------*/
  void 	do_1d (char *args, int dbg_mode) {
/*	=====
**		Generate a 1-dim plot
**		Args are:
**		    Number of first bin	(dflt = 0)
**		    Number of bins      (dflt = rest of histogram)
**		    Number of histogram (dflt = -1)
**		Default is to plot everything.
*/
    int		i, status;
    uint	f_bin, n_bins, hist_num;
    uint	cntr_lo, cntr_hi;
    uint	total;
    char	*p_p1, *p_p2, *p_p3;

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

    if (Rw_skt == 0) {
      Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, dbg_mode,
					    &Rply_buff, Verbose);
      if (Rw_skt == 0) FailInet ("\ndo_1d/openConnectionGbl error.");
    }
    split_args (args, &p_p1, &p_p2, &p_p3, NULL);
    if (p_p1 == NULL) p_p1 = "0";
    if (sscanf (p_p1, "%u", &f_bin) != 1) {
      printf ("<1st-bin> is invalid: \"%s\"\n", p_p1);
      return;
    }

    if (p_p3 == NULL) p_p3 = "-1";
    if ((sscanf (p_p3, "%u", &hist_num) != 1) ||
        ((hist_num != -1) && (hist_num >= N_hists))) {
      printf ("<hist-#> is invalid: \"%s\"\n", p_p3);
      printf ("There are %d histograms defined.\n", N_hists);
      return;
    }
    if (((hist_num != -1) && (f_bin >= Hm_nbins)) ||
        (f_bin >= (N_hists * Hm_nbins))) {
      printf ("<1st-bin> is invalid: \"%s\"\n", p_p1);
      printf ("The number of bins is %d\n",
			(hist_num == -1) ? (N_hists * Hm_nbins) : Hm_nbins);
      return;
    }

    if (p_p2 != NULL) {
      if ((sscanf (p_p2, "%d", &n_bins) != 1) ||
          ((hist_num != -1) && ((f_bin + n_bins) > Hm_nbins)) ||
          ((f_bin + n_bins) >= (N_hists * Hm_nbins))) {
	printf ("<#-bins> is invalid: \"%s\"\n", p_p2);
	n_bins = (hist_num == -1) ? (N_hists * Hm_nbins) : Hm_nbins;
	n_bins = n_bins - f_bin;
	printf ("The value has been set to %d.\n", n_bins);
      }
    }else {
      n_bins = (hist_num == -1) ? (N_hists * Hm_nbins) : Hm_nbins;
      n_bins = n_bins - f_bin;
    }

    printf (" Read histogram memory ...\n"
	    "       First bin        = %5d\n"
	    "       Number of bins   = %5d\n"
	    "       Histogram number = %5d\n", f_bin, n_bins, hist_num);
		/*
		** Allocate buffer space for holding the data.
		*/
    if ((n_bins * Bytes_per_bin) > Hm_buff_size) { /* Expand buffer space? */
      Hm_buff_addr = realloc (Hm_buff_addr, (n_bins * Bytes_per_bin)); /* Yes */
      if (Hm_buff_addr != NULL) {
	Hm_buff_size = n_bins * Bytes_per_bin;
      }else {
	printf ("SinqHM_Client -- "
			"error getting memory buffer for histogram data.\n");
	exit (EXIT_FAILURE);
      }
    }
    Hm_buff_used = n_bins * Bytes_per_bin;

    status = read_hm (Hm_buff_addr, Hm_buff_size,
			    f_bin, n_bins, hist_num, &cntr_lo, &cntr_hi);
    if (status == EXIT_SUCCESS) {
      total = 0;
      switch (Bytes_per_bin) {
       case 1:
	p_byte = (uchar *) Hm_buff_addr;
	for (i=0; i < n_bins; i++) total += p_byte[i];
	break;
       case 2:
	p_word = (usint *) Hm_buff_addr;
	for (i=0; i < n_bins; i++) total += p_word[i];
	break;
       case 4:
	p_long = (uint *) Hm_buff_addr;
	for (i=0; i < n_bins; i++) total += p_long[i];
	break;
      }
      printf (" Done! Total contents of bins = %d\n", total);
      if (cntr_lo != 0) printf (" Number of underflow events = %u\n", cntr_lo);
      if (cntr_hi != 0) printf (" Number of overflow  events = %u\n", cntr_hi);
      do_plot (f_bin, n_bins, Bytes_per_bin, total);
    }
  }
/*
**----------------------------------------------------------------------------*/
  void 	do_2d (char *args, int dbg_mode) {
/*	=====
**		Generate a 2-dim plot (e.g. of TOF array of counters
**		Args are:
**		    Number of first histogram
**		    Number of histograms
**		    Number of first bin
**		    Number of bins
**		Default is to plot everything.
*/
    char	    *p_p1, *p_p2, *p_p3, *p_p4;
    int		    i, status;
    uint	    f_hist, n_hists, f_bin, n_bins;
    uint	    bytes_needed, total, cntr_lo, cntr_hi;

    uchar	*p_byte;
    usint	*p_word;
    uint	*p_long;

    if (Rw_skt == 0) {
      Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, dbg_mode,
					    &Rply_buff, Verbose);
      if (Rw_skt == 0) FailInet ("\ndo_2d/openConnectionGbl error.");
    }

    split_args (args, &p_p1, &p_p2, &p_p3, &p_p4, NULL);    /* Get pointers to
							    ** the 4 args */
    if (p_p1 == NULL) p_p1 = "0";
    if ((sscanf (p_p1, "%u", &f_hist) != 1) ||
	(f_hist >= N_hists)) {
      printf ("<1st-hist> is invalid: \"%s\"\n", p_p1);
      printf ("There are %d histograms defined.\n", N_hists);
      return;
    }

    if (p_p2 == NULL) {
      n_hists = N_hists - f_hist;
    }else {
      if ((sscanf (p_p2, "%u", &n_hists) != 1) ||
	  (n_hists > N_hists) ||
	  ((n_hists + f_hist) > N_hists)) {
	printf ("<#-hists> is invalid: \"%s\"\n", p_p2);
	printf ("There are %d histograms defined.\n", N_hists);
	return;
      }
    }

    if (p_p3 == NULL) p_p3 = "0";
    if ((sscanf (p_p3, "%u", &f_bin) != 1) ||
	(f_bin >= Hm_nbins)) {
      printf ("<1st-bin> is invalid: \"%s\"\n", p_p3);
      printf ("The number of bins is %d\n", Hm_nbins);
      return;
    }

    if (p_p4 == NULL) {
      n_bins = Hm_nbins - f_bin;
    }else {
      if ((sscanf (p_p4, "%u", &n_bins) != 1) ||
	  (n_bins > Hm_nbins) ||
	  ((n_bins + f_bin) > Hm_nbins)) {
	printf ("<#-bins> is invalid: \"%s\"\n", p_p4);
	printf ("The number of bins is %d\n", Hm_nbins);
	return;
      }
    }

    printf ("\n Read 2-dimensional histogram memory ...\n"
	          "       First histogram      = %5u\n"
		  "       Number of histograms = %5u\n"
	          "       First bin            = %5u\n"
		  "       Number of bins       = %5u\n",
			    f_hist, n_hists, f_bin, n_bins);
		/*
		** Allocate buffer space for holding the data. Note that the
		** data in the Hist Mem is stored as a 1-dim array with
		** the bins of each histogram contiguous. It is usually
		** more efficient (at least, it is easier to program) to
		** transfer over complete histograms if we need to pick out
		** a sub-range of bins.
		*/
    bytes_needed = n_hists * Hm_nbins * Bytes_per_bin;
    if (bytes_needed > Hm_buff_size) {		/* Expand buffer space? */
      Hm_buff_addr = realloc (Hm_buff_addr, bytes_needed);  /* Yes */
      if (Hm_buff_addr != NULL) {
	Hm_buff_size = bytes_needed;
      }else {
	printf ("SinqHM_Client -- "
			"error getting memory buffer for histogram data.\n");
	exit (EXIT_FAILURE);
      }
    }
    Hm_buff_used = bytes_needed;

    status = read_hm (Hm_buff_addr, Hm_buff_size,
			    (f_hist * Hm_nbins), (n_hists * Hm_nbins), -1,
			    &cntr_lo, &cntr_hi);
    if (status == EXIT_SUCCESS) {
      total = 0;
      switch (Bytes_per_bin) {
       case 1:
	p_byte = (uchar *) Hm_buff_addr;
	for (i=0; i<(n_hists * Hm_nbins); i++) total += p_byte[i];
	break;
       case 2:
	p_word = (usint *) Hm_buff_addr;
	for (i=0; i<(n_hists * Hm_nbins); i++) total += p_word[i];
	break;
       case 4:
	p_long = (uint *) Hm_buff_addr;
	for (i=0; i<(n_hists * Hm_nbins); i++) total += p_long[i];
      }
      printf (" Done! Total contents of bins = %d\n", total);
      if (cntr_lo != 0) printf (" Number of underflow events = %u\n", cntr_lo);
      if (cntr_hi != 0) printf (" Number of overflow  events = %u\n", cntr_hi);
      do_2d_plot (f_hist, n_hists, f_bin, n_bins, Bytes_per_bin, total);
    }
  }
/*
**----------------------------------------------------------------------------*/
  void do_2d_plot (
/*     ==========
**			    Make a 2-dimensional plot of the data.
*/
		    uint f_hist, uint n_hists, uint f_bin, uint n_bins,
		    uint bytes_per_bin, uint total) {

    int		i, t_bins, ix1, ix2, iy1, iy2, ioff;
    int		nx = 1;
    int		ny = 1;
    char	total_txt[21];
#ifdef LINUX
    char	dev[] = "/XSERV";
#else
    char	dev[] = "/XW";
#endif
    char	xlab[] = "Bins";
    char	ylab[] = "Counts";
    float	xlo, xhi, yhi, bias;
    float	*data;
    float	*x, *ylims;

    uchar	*p_byte;
    usint	*p_word;
    uint	*p_long;

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

    p_byte = (uchar *) Hm_buff_addr;
    p_word = (usint *) Hm_buff_addr;
    p_long = (uint  *) Hm_buff_addr;

    t_bins = n_hists * Hm_nbins;

    data = (float *) malloc (t_bins * sizeof (float));
    if (data == NULL) {
      printf ("Cannot get plot memory for 2-dim array\n");
      return;
    }

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

    ylims = (float *) malloc ((n_bins + 1) * sizeof (float));
    if (x == NULL) {
      printf ("Cannot get workspace memory for 2-dim plot\n");
      return;
    }

    switch (bytes_per_bin) {
     case 1:
      for (i = 0; i < t_bins; i++) data[i] = p_byte[i]; break;
     case 2:
      for (i = 0; i < t_bins; i++) data[i] = p_word[i]; break;
     case 4:
      for (i = 0; i < t_bins; i++) data[i] = p_long[i]; break;
    }

    yhi = 10.0;
    for (i = 0; i < t_bins; i++) if (data[i] > yhi) yhi = data[i];
    yhi = yhi * 1.3;
    yhi = cpgrnd (yhi, &i);

    ioff = 1;
    for (i = 0; i <= n_bins; i++) x[i] = (float) (f_bin + i);
    xlo = (float) f_bin;
    xhi = (float) f_bin + n_bins + 1 + (n_hists * ioff);
    
    ix1 = 1;
    ix2 = n_hists;
    iy1 = f_bin + 1;
    iy2 = f_bin + n_bins;

    bias = yhi * 0.0001;

    sprintf (total_txt, "Bin Total = %8d", total);

    if (PGPLOT_started == 0) {
      cpgbeg (0, dev, 1, 1);
	    /* - - - - - - - - - - - - - - - - - - - - - -
	    ** Set black on white (hopefully)
	    */
      cpgscr (0, 0.79, 0.67, 0.57);
      cpgscr (1, 0.0, 0.0, 0.0);

      cpgask (0);
      PGPLOT_started = 1;
    }
    cpgenv (xlo, xhi, 0.0, yhi, 0, 0);
    cpglab (xlab, ylab, total_txt);

    cpghi2d (data, n_hists, Hm_nbins, ix1, ix2, iy1, iy2, x, ioff,
		    bias, False, ylims);

    free (data);
    free (x);
    free (ylims);
  }
/*
**--------------------------------------------------------------------------*/
  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_host);
      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 (char *args) {
/*     ========
**				Generate sum of 2 Lorenzians.
*/

    int		 i, j, nbins;
    char	*p_p1, *p_p2, *p_p3, *p_p4, *p_p5, *p_p6;
    float	 p1, p2, p3, p4, p5, p6;
    float	 ff, fact_1, fact_2;
    char	*p_byte;
    short int	*p_word;
    int		*p_long;
		/*
		** Allocate buffer space for holding the data.
		*/
    nbins = Hm_nbins * N_hists;
    if ((nbins * Bytes_per_bin) > Hm_buff_size) {  /* Expand buffer space? */
      Hm_buff_addr = realloc (Hm_buff_addr, (nbins * Bytes_per_bin)); /* Yes */
      if (Hm_buff_addr != NULL) {
        Hm_buff_size = nbins * Bytes_per_bin;
      }else {
        printf ("SinqHM_Client -- "
			"error getting memory buffer for histogram data.\n");
        exit (EXIT_FAILURE);
      }
    }
    Hm_buff_used = nbins * Bytes_per_bin;
		/*
		** Parse the arguments
		*/
    split_args (args, &p_p1, &p_p2, &p_p3, &p_p4, &p_p5, &p_p6, NULL);

    if ((p_p1 != NULL) && (sscanf (p_p1, "%f", &p1) == 1)) P1 = p1;
    if ((p_p2 != NULL) && (sscanf (p_p2, "%f", &p2) == 1)) P2 = p2;
    if ((p_p3 != NULL) && (sscanf (p_p3, "%f", &p3) == 1)) P3 = p3;
    if ((p_p4 != NULL) && (sscanf (p_p4, "%f", &p4) == 1)) P4 = p4;
    if ((p_p5 != NULL) && (sscanf (p_p5, "%f", &p5) == 1)) P5 = p5;
    if ((p_p6 != NULL) && (sscanf (p_p6, "%f", &p6) == 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 (j = 0; j < N_hists; j++) {    /* Calculate sum of 2 Lorenzians */
      fact_1 = 0.5 + (float) (j)/(float) (N_hists);
      fact_2 = 2.0 - fact_1;

      for (i = 0; i < Hm_nbins; i++) {

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

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

	ff = p2 + p4;
	switch (Bytes_per_bin) {
	 case 1:
	  *p_byte++ = (char) ff;
	  break;
	 case 2:
	  *p_word++ = (short int) ff;
	  break;
	 case 4:
	  *p_long++ = (int) ff;
	  break;
	}
      }
    }
  }
/*
**--------------------------------------------------------------------------*/
  void gen_data_2d (char *args) {
/*     ===========
**				Same as gen_data, i.e. generate sum of 2
**				Lorenzians, but suitable for pseudo 2-dim mode.
**				The first arg is the number of sub-histograms.
*/
    char	*p_nhis, *p_p1, *p_p2, *p_p3, *p_p4, *p_p5, *p_p6;
    int		 i, j, totbins, nhis, nbins;
    float	 p1, p2, p3, p4, p5, p6;
    float	 ff, fact_1, fact_2;
    char	*p_byte;
    short int	*p_word;
    int		*p_long;

		/*
		** Allocate buffer space for holding the data.
		*/
    totbins = Hm_nbins * N_hists;
    if ((totbins * Bytes_per_bin) > Hm_buff_size) {  /* Expand buffer space? */
      Hm_buff_addr = realloc (Hm_buff_addr, (totbins * Bytes_per_bin)); /* Yes */
      if (Hm_buff_addr != NULL) {
        Hm_buff_size = totbins * Bytes_per_bin;
      }else {
        printf ("SinqHM_Client -- "
			"error getting memory buffer for histogram data.\n");
        exit (EXIT_FAILURE);
      }
    }
    Hm_buff_used = totbins * Bytes_per_bin;
		/*
		** Parse the arguments
		*/
    split_args (args, &p_nhis,
		      &p_p1, &p_p2, &p_p3, &p_p4, &p_p5, &p_p6, NULL);
    if (p_nhis != NULL) {
      i = sscanf (p_nhis, "%i", &nhis);
      if ((i != 1) || ((totbins % nhis) != 0)) {
	if (i != 1) printf ("<#-hists> is invalid. It must be an integer!\n");
	if (i == 1) printf ("<#-hists> is invalid. It must be a factor"
				" of the total number of bins!\n");
	printf ("<#-hists> is \"%s\", total number of bins = %d\n",
				p_nhis, totbins);
	printf ("<#-hists> set to 1\n");
	nhis = 1;
      }
    }else {
      nhis = 1;
    }
    nbins = totbins/nhis;

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

    if (P2 <= 0) P2 = 1000;
    if (P5 <= 0) P5 = 1000;

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

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

    for (j = 0; j < nhis; j++) {    /* Calculate sum of 2 Lorenzians */
      fact_1 = 0.5 + (float) (j)/(float) (nhis);
      fact_2 = 2.0 - fact_1;

      for (i = 0; i < nbins; i++) {

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

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

	ff = p2 + p4;
	switch (Bytes_per_bin) {
	 case 1:
	  *p_byte++ = (char) ff;
	  break;
	 case 2:
	  *p_word++ = (short int) ff;
	  break;
	 case 4:
	  *p_long++ = (int) ff;
	  break;
	}
      }
    }
  }
/*
**---------------------------------------------------------------------------
**			get_check_resources - get and check our resources
*/
  int	get_check_resources (
/*	===================
*/			    XrmDatabase	*db,
			    char	*appName,
			    int		*argc,
			    char	*argv[],
			    int		verbose) {

    int			i, status, len, do_help;
    char		buff[80];
    char		*type;
    XrmValue		value;
    time_t		time_now;
    float		tmp_secs;
/*----------------------------------------------------------	-help	*/
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmHelp"),
			     "ProgramName.Values",
			     &type, &value);
    do_help = (status) ? True : False;
    if (do_help) {
      show_help (NULL);
      exit (EXIT_SUCCESS);
    }
/*----------------------------------------------------------	-?	*/
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmHelpItem"),
			     "ProgramName.Values",
			     &type, &value);
    do_help = (status) ? True : False;
    if (do_help) {
      len = sizeof (buff);
      StrEdit (buff, value.addr, "trim lowercase", &len);
      show_help (buff);
      exit (EXIT_SUCCESS);
    }
/*----------------------------------------------------------	-verbose */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmVerbose"),
			     "ProgramName.Values",
			     &type, &value);
    Verbose = verbose = (status) ? True : False;
/*----------------------------------------------------------	-host	*/
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmHost"),
			     "ProgramName.Values",
			     &type, &value);
    if (status) {
      StrJoin (Rmt_host, sizeof (Rmt_host), value.addr, "");
    }else {
      if (*argc >= 2) {
	StrJoin (Rmt_host, sizeof (Rmt_host), argv[1], "");
	(*argc)--;
	for (i = 1; i < *argc; i++) argv[i] = argv[i+1];
      }else {
	printf ("\n"
		"  Target host not specified, there is no default!\n");
	show_help (NULL);
	exit (EXIT_FAILURE);
      }
    }
    if (verbose) printf ("Target host is \"%s\".\n", Rmt_host);
/*----------------------------------------------------------	-port	*/
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmPort"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status || (sscanf (value.addr, "%d", &Rmt_port) != 1)) {
      Rmt_port = 2400;
      if (verbose) printf ("Using the default TCP/IP port number of ");
    }else {
      if (verbose) printf ("TCP/IP  port  number = ");
    }
    if (verbose) printf ("%d\n", Rmt_port);
/*----------------------------------------------------------	-pktsize */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmPktSize"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status || (sscanf (value.addr, "%d", &Pkt_size) != 1)) {
      Pkt_size = 8192;
      if (verbose) printf ("Using the default packet size of ");
    }else {
      if (verbose) printf ("Packet size = ");
    }
    if (verbose) printf ("%d\n", Pkt_size);
/*----------------------------------------------------------	-debug	*/
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmDebug"),
			     "ProgramName.Values",
			     &type, &value);
    Dbg_mode = (status) ? 1 : 0;
/*----------------------------------------------------------*/
    return True;
  }
/*
**----------------------------------------------------------------------------*/
  int	get_recd (FILE *lun, char *recd, int recd_len) {
/*	========
**				Get a non-comment record from a file
*/
    int nbytes = -1;

    while (nbytes <= 0) {
      if (fgets (recd, (recd_len - 1), lun) == NULL) return False;

      nbytes = recd_len;
      StrEdit (recd, recd, "trim compress uncomment", &nbytes);
    }
    return True;
  }
/*
**--------------------------------------------------------------------------*/
  void new_config_quit (
/*     ===============
**			    Quit because SinqHM config'n has changed.
**
*/		char	 *txt) {

    printf ("\n"
	" It looks as though the configuration of SinqHM has been changed\n"
	" whilst we were not looking. This should not be possible!\n"
	" Please report the incident.\n"
	" The item which has changed is \"%s\".\n\n", txt);
    exit (EXIT_FAILURE);
  }
/*
**--------------------------------------------------------------------------*/
  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		 verbose) {

    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 ("\nopenConnection/Gethostbyname 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 ("openConnection -- Cnct_skt 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 ("openConnection -- Cnct_skt 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 ("openConnection -- 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 (" 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 ("openConnection -- 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 ("openConnection -- 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 (
	    "SinqHM_Client -- big-endian/little-endian problem!\n"
	    "    Buffer received in non-network byte order!\n");
      exit (EXIT_FAILURE);
    }
    status = ntohl (reply->status);
    if (status != KER__SUCCESS) {
      if (status == KER__BAD_STATE) {
	printf (" SinqHM_Client -- Histogram memory has not yet been "
					    "configured!\n");
	print_uptime (stdout, " Up-time = ", ntohl (reply->u.cnct.up_time),
						"\n");
      }else if (status == KER__BAD_CREATE) {
	status = ntohl (reply->sub_status);
	printf (
	 "SinqHM_Client -- creation of histogram memory server process "
							    "failed!\n"
	 "                 Sub-status = ");
	switch (status) {
	 case -1: printf ("%d. Spawn failed.\n", status); break;
	 case -2: printf ("%d. No more ports available.\n", status); break;
	 case -3: printf ("%d. Time-out.\n", status); break;
	 case -4: printf ("%d. Child process detected a problem "
				    "during startup.\n", status); break;
	 default: printf ("%d. Undefined. Refer to the source code!\n", status);
	}
      }else {
	printf ("SinqHM_Client -- Bad and unrecognised status from Connect "
					    "Request: %d.\n", status);
      }
      exit (EXIT_FAILURE);
    }
    status = close (Cnct_skt);
    Cnct_skt = 0;
    if (status != 0) FailInet ("openConnection -- Cnct-Socket close error\n");

    *port = ntohl (reply->u.cnct.port);
    if (verbose) printf (" Server port to use           = %6d\n", *port);
    *pkt_size = ntohl (reply->u.cnct.pkt_size);
    if (verbose) 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 ("openConnection -- Srvr-Skt 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 ("openConnection -- Srvr-Skt 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 ("openConnection -- Srvr-Skt 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		 verbose) {

    int	    my_skt = 0;

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

    Hm_mode = ntohl (Rply_buff.u.cnct.hm_mode);
    if (verbose) print_HM_mode (Hm_mode, 10);

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

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

    Compress = ntohl (Rply_buff.u.cnct.compress);
    if ((verbose) && (Compress > 1))
      printf (" Bin span                     = %6d\n", Compress);

    if (verbose && (N_hists > 1))
      printf (" Total number of bins         = %6d\n", N_hists * Hm_nbins);

    Bytes_per_bin = ntohl (Rply_buff.u.cnct.bytes_per_bin);
    if (verbose)
      printf (" Number of bytes per bin      = %6d\n", Bytes_per_bin);

    Lo_cntr = ntohl (Rply_buff.u.cnct.lo_cntr);
    if (verbose && (Lo_cntr != 0))
      printf (" Low counter number           = %6d\n", Lo_cntr);

    Lo_bin = ntohl (Rply_buff.u.cnct.lo_bin);
    if (verbose && (Lo_bin != 0))
      printf (" Low counter number           = %6d\n", Lo_bin);

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

    Total_bytes = ntohl (Rply_buff.u.cnct.total_bytes);
    if (verbose)
      printf (" Histogram buffer size        = %6d bytes\n", Total_bytes);

    Max_block = ntohl (Rply_buff.u.cnct.max_block);
    if (verbose)
      printf (" Free memory space available  = %6d bytes\n", Max_block);

    return my_skt;
  }
/*
**--------------------------------------------------------------------------
*/
  void print_HM_mode (
/*     =============
**			    Interpret the HM configuration.
**
*/		    uint   mode,    /* The configuration to be interpreted */
		    int	   n_pad) { /* A padding count to move the "=" */

    uint    my_mode;

    printf (" Histogramming Mode%*s = 0x%x", n_pad, "", mode);

    my_mode = mode & (~SQHM__SUB_MODE_MSK);
    if (my_mode == SQHM__TRANS)  printf (" TRANS");
    if (my_mode == SQHM__HM_DIG) printf (" HM_DIG");
    if (my_mode == SQHM__TOF)    printf (" TOF");
    if (my_mode == SQHM__HM_PSD) printf (" HM_PSD");
    if (my_mode == SQHM__HRPT)   printf (" HRPT");
    if ((mode & SQHM__DEBUG)   != 0) printf (" DEBUG");
    if ((mode & SQHM__UD)      != 0) printf (" UD");
    if ((mode & SQHM__STROBO)  != 0) printf (" STROBO");
    if ((mode & SQHM__REFLECT) != 0) printf (" REFLECT");
    if ((mode & SQHM__NO_STAT) != 0) printf (" NO_FILLER_STATUS");
    printf ("\n");

    printf (" Bin Overflow Mode %*s = ", n_pad, "");
    my_mode = mode & SQHM__BO_MSK;
    if (my_mode == SQHM__BO_IGN) {
      printf ("\"Ignore\"\n");
    }else if (my_mode == SQHM__BO_SMAX) {
      printf ("\"Stop-at-Max\"\n");
    }else if (my_mode == SQHM__BO_CNT) {
      printf ("\"Count\"");
    }else {
      printf ("\"Unrecognised\" = 0x%x\n", my_mode);
    }
  }
/*
**--------------------------------------------------------------------------*/
  void	print_uptime (
/*	============
**			Print out the up-time
*/
	    FILE    *lun,   	/* The output stream */
	    char    *prefix,	/* A message prefix */
	    int	     secs,	/* The up-time in seconds */
	    char    *suffix) {	/* A message suffix */

    int		mins, hrs, days;

    mins = secs/60; secs -= mins * 60;
    hrs  = mins/60; mins -= hrs  * 60;
    days = hrs/24;  hrs  -= days * 24;
    fprintf (lun, "%s", prefix);
    if (days > 0) {
      printf (" %d days, %d%02d%02d%s", days, hrs, mins, secs, suffix);
    }else if (hrs > 0) {
      printf (" %d hrs, %d mins, %d secs%s", hrs, mins, secs, suffix);
    }else if (mins > 0) {
      printf (" %d mins, %d secs%s", mins, secs, suffix);
    }else {
      printf (" %d secs%s", secs, suffix);
    }
  }
/*
**--------------------------------------------------------------------------*/
  int read_hm (
/*    =======
**			Read block of bins from SINQHM_SRV
*/
	    char *hbuf,		/* Buffer to hold data */
	    uint  hbuf_size,	/* Size of hbuf */
	    uint  f_bin,	/* First bin to read */
	    uint  n_bins,	/* Number of bins to read	*/
	    uint  hist_no,	/* Histogram number to read	*/
	    uint *cntr_lo,	/* # events below histo range */
	    uint *cntr_hi) {	/* # events above histo range */
/*
**		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;
    uint	    my_n_bins, my_bytes_per_bin;

    uchar	*nxt_byte;
    usint	*nxt_word;
    uint	*nxt_long;

    bytes_to_come = n_bins * Bytes_per_bin;
    if (bytes_to_come > hbuf_size) {
        printf ("read_hm: buffer is too small!\n"
		    "         It is %d rather than %d bytes long.\n",
		    hbuf_size, bytes_to_come);
	return EXIT_FAILURE;
    }

    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 (hist_no);
    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 (
	    "read_hm: 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));
      printf ("                                  Sub-status: %d.\n",
	 	    ntohl (Rply_buff.sub_status));
      if (Rply_buff.u.message[0] != NIL)
	printf ("           Message is: %s\n", Rply_buff.u.message);
      return EXIT_FAILURE;
    }
	/*
	**	Data was read OK so read the data which has been sent.
	*/
    my_n_bins	     = ntohl (Rply_buff.u.read.n_bins);
    my_bytes_per_bin = ntohl (Rply_buff.u.read.bytes_per_bin);
    *cntr_lo	     = ntohl (Rply_buff.u.read.cnts_lo);
    *cntr_hi	     = ntohl (Rply_buff.u.read.cnts_hi);
    if (my_n_bins != n_bins) {
      printf ("read_hm: "
	"Warning -- server is sending us %d bins of data rather than %d!\n",
	my_n_bins, n_bins);
    }
    bytes_to_come = my_n_bins * my_bytes_per_bin;
    if (bytes_to_come > hbuf_size) {
      printf ("read_hm: Warning -- buffer size = %d bytes\n"
		  "                    Server is sending us %d bytes of data.\n"
		  "                    Some data will have to be flushed!\n",
		    hbuf_size, bytes_to_come);
    }
    nxt_byte = (uchar *) Hm_buff_addr;
    while (bytes_to_come > 0) {
      i = (bytes_to_come > Pkt_size) ? Pkt_size : bytes_to_come;
      if (bytes_to_come > hbuf_size) {
	i = hbuf_size;
	nxt_byte = (uchar *) Hm_buff_addr;
      }
      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 ((Bytes_per_bin > 0) && (Rply_buff.bigend != 0x12345678)) {
      switch (Bytes_per_bin) {	    /* Byte swapping is necessary */
       case 2:
			/* Not sure how to do this - this might be wrong! */
        nxt_word = (usint *) Hm_buff_addr;
	for (i = 0; i < n_bins; i++) nxt_word[i] = ntohs (nxt_word[i]);
        break;
       case 4:
        nxt_long = (uint *) Hm_buff_addr;
	for (i = 0; i < n_bins; i++) nxt_long[i] = ntohl (nxt_long[i]);
        break;
      }
    }
    return EXIT_SUCCESS;
  }
/*
**--------------------------------------------------------------------------*/
  int read_project (
/*    ============
**			Read projected block of bins from SINQHM_SRV.
**			Send SQHM_PROJECT request to server.
**			On return, the data is in the buffer pointed to by hbuf.
*/
	    char *hbuf,		/* Buffer to hold data */
	    uint  hbuf_size,	/* Size of hbuf */
	    uint  f_bin,	/* First bin to read */
	    uint  n_bins,	/* Number of bins to read */
	    uint  f_hist,	/* First histogram to read */
	    uint  n_hists,	/* Number of histograms to read */
	    uint  axis,		/* Projection axis */
	    uint  xdim,		/* Pseudo-x-dimension */
	    uint  h_select,	/* Histogram to select (pseudo 2-d mode) */
	    uint *cntr_lo,	/* # events below histo range */
	    uint *cntr_hi) {	/* # events above histo range */

    int		    status, is, i;
    int		    bytes_to_come;
    uint	    nbins_to_read, my_n_bins, my_bytes_per_bin;

    uchar	*nxt_byte;
    usint	*nxt_word;
    uint	*nxt_long;

    nbins_to_read = (axis == 0) ? n_bins : n_hists;
    bytes_to_come = nbins_to_read * sizeof (uint);
    if (bytes_to_come > hbuf_size) {
        printf ("read_project: buffer is too small!\n"
		    "              It is %d rather than %d bytes long.\n",
		    hbuf_size, bytes_to_come);
	return EXIT_FAILURE;
    }

    status = EXIT_SUCCESS;		/* Assume success. */
    Req_buff.bigend = htonl (0x12345678);
    Req_buff.cmnd = htonl (SQHM_PROJECT);

    i = (axis == 0) ? 0 : PROJECT__ON_Y;
    if (xdim != 0) i |= PROJECT__1_DIM;
    Req_buff.u.project.sub_code = htonl (i);

    Req_buff.u.project.x_lo     = htonl (f_bin);
    Req_buff.u.project.nx	= htonl (n_bins);
    Req_buff.u.project.y_lo     = htonl (f_hist);
    Req_buff.u.project.ny	= htonl (n_hists);
    Req_buff.u.project.xdim     = htonl (xdim);
    Req_buff.u.project.nhist    = htonl (h_select);
    status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    Rw_bytes_put += status;
    if (status == -1) FailInet ("read_project -- R/W-Socket send error\n");
    if (status != sizeof (Req_buff)) {
        printf ("read_project: 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_project -- R/W-Socket recv error\n");
    }else if (status != sizeof (Rply_buff)) {
      printf ("read_project: R/W-Socket recv error - ");
      printf ("unexpected byte count: %d.\n", status);
      return EXIT_FAILURE;
    }
    if (ntohl (Rply_buff.bigend) != 0x12345678) {
      printf (
	    "read_project: 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_project: Bad status from SQHM_READ Request: %d.\n",
	 	    ntohl (Rply_buff.status));
      printf ("                                  Sub-status: %d.\n",
	 	    ntohl (Rply_buff.sub_status));
      if (Rply_buff.u.message[0] != NIL)
	printf ("           Message is: %s\n", Rply_buff.u.message);
      return EXIT_FAILURE;
    }
	/*
	**	Data was read OK so read the data which has been sent.
	*/
    my_n_bins	     = ntohl (Rply_buff.u.project.n_bins);
    my_bytes_per_bin = ntohl (Rply_buff.u.project.bytes_per_bin);
    *cntr_lo	     = ntohl (Rply_buff.u.project.cnts_lo);
    *cntr_hi	     = ntohl (Rply_buff.u.project.cnts_hi);
    if (my_n_bins != nbins_to_read) {
      printf ("read_project: Warning -- "
	"server is sending us %d bins of data rather than %d!\n",
	my_n_bins, n_bins);
    }
    bytes_to_come = my_n_bins * my_bytes_per_bin;  /* Compute length of data */
    if (bytes_to_come > hbuf_size) {
      printf ("read_project: Warning -- buffer size = %d bytes\n"
		  "                Server is sending us %d bytes of data.\n"
		  "                Some data will have to be flushed!\n",
		    hbuf_size, bytes_to_come);
    }
    nxt_byte = (uchar *) hbuf;
    while (bytes_to_come > 0) {
      i = (bytes_to_come > Pkt_size) ? Pkt_size : bytes_to_come;
      if (bytes_to_come > hbuf_size) {
	i = hbuf_size;
	nxt_byte = (uchar *) hbuf;
      }
      status = recv (Rw_skt, nxt_byte, i, 0);
      Rw_bytes_got += status;
      if (status == -1) FailInet ("read_project -- 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 ((my_bytes_per_bin > 0) && (Rply_buff.bigend != 0x12345678)) {
      switch (my_bytes_per_bin) {	    /* Byte swapping is necessary */
       case 2:
			/* Not sure how to do this - this might be wrong! */
        nxt_word = (usint *) hbuf;
	for (i = 0; i < nbins_to_read; i++) nxt_word[i] = ntohs (nxt_word[i]);
        break;
       case 4:
        nxt_long = (uint *) hbuf;
	for (i = 0; i < nbins_to_read; i++) nxt_long[i] = ntohl (nxt_long[i]);
        break;
      }
    }
    return EXIT_SUCCESS;
  }
/*
**---------------------------------------------------------------------------
**			setup_xrm_database    - setup Resource Manager Database
*/
  int	setup_xrm_database (
/*	==================
*/			XrmDatabase	*db,
			char		*name[],
			int		*argc,
			char		*argv[],
			int		verbose) {

    static char	our_name[80]  = "Unknown";  /* This holds the program name */
    static char lkup_name[80] = "Unknown";  /* Name for looking in database */

    int		status, i, first = True;
    char	text[80];
    char	full_nm0[80];
    char	full_nm1[80];
    char	*p_fil[] = {0,0,0,0,0,0,0,0,0,0};
    char	*my_name;
    char	*my_name_last;

    char	*name_type;
    XrmValue	name_value;

    XrmDatabase cmnd_line_db = NULL;
    XrmDatabase	lcl_db	     = NULL;
  /*-----------------------------------------------------
  ** This routine merges some resource databases with options specified on
  ** the command line. Resources can then be looked up using XrmGetResource.
  ** This is a bit like the X-toolkit routine XtAppInitialize does for the
  ** extraction of resources by XtGetApplicationResources.
  ** 
  ** I can't help but think that there's a simpler way of doing this but I
  ** can't find it in the X manuals. Basically, the problem arises with wanting
  ** to avoid the calling program being associated with an X-display, i.e. it
  ** is intended for use by "command-line oriented" programs. All the nice,
  ** easy-to-use resource/command-line setup routines in Xlib or Xtlib seem to
  ** assume one is going to use a display -- not surprising, I suppose,
  ** since the concept of Xlib is for writing window based applications!
  **
  ** Anyway, the point is that the following way turns out to be lacking
  ** when it gets tested in anger.
  */
    status = True;		/* Assume success	*/

    our_name[0] = NIL;
	/*
	** Make a list of the databases to be merged, highest priority first.
	*/
#ifdef  __VMS
    p_fil[0] = "decw$user_defaults:SinQ_rc.dat";
    p_fil[1] = "decw$group_defaults:SinQ_rc.dat";
    p_fil[2] = "decw$system_defaults:SinQ_rc.dat";
    p_fil[3] = "decw$user_defaults:decw$xdefaults.dat";
    p_fil[4] = "decw$group_defaults:decw$xdefaults.dat";
    p_fil[5] = "decw$system_defaults:decw$xdefaults.dat";
    p_fil[6] = NULL;
    if (*argc > 0) {	     /* Find out what we are called - parse file nm */
      my_name = strstr (argv[0], "]");	/* Find end of directory, i.e. "]" */
      my_name++;			/* Skip over "]" */
      if (my_name[0] == '[') {		/* Handle possible concealed device */
        my_name = strstr (my_name, "]");
	my_name++;
      }
      i = sizeof (our_name);
      StrEdit (our_name, my_name, "lowercase", &i);	    /* Copy the rest */
      strtok (our_name, ".");		/* Close it off at "." */
    }
#else
    p_fil[0] = StrJoin (full_nm0, sizeof (full_nm0),
			    getenv ("HOME"), "/SinQ_rc");
    p_fil[1] = "/usr/lib/X11/app-defaults/SinQ_rc";
    p_fil[2] = StrJoin (full_nm1, sizeof (full_nm1),
			    getenv ("HOME"), "/.Xdefaults");
    p_fil[3] = "/usr/lib/X11/app-defaults/Xdefaults";
    p_fil[4] = NULL;
    if (*argc > 0) {	      /* Find out what we are called - parse file nm  */
			      /* Find end of directories */
      my_name = argv[0] - 1;
      while (my_name != NULL) {
        my_name_last = my_name;
	my_name_last++;
	my_name = strstr (my_name_last, "/");
      }
      StrJoin (our_name, sizeof (our_name), my_name_last, "");
    }
#endif
    if (verbose) printf ("My name is \"%s\"\n", our_name);
	/*
	**  Initialise and combine all databases
	*/
    XrmInitialize ();
    for (i = 0; i < XtNumber (p_fil); i++) {
      if (p_fil[i] == NULL) break;
      status = XrmCombineFileDatabase (p_fil[i], &lcl_db, False);
      if ((status != 0) && verbose) {
	if (first)
	  printf ("Resource database created from file %s.\n", p_fil[i]);
	if (!first)
	  printf ("File %s merged into resource database.\n", p_fil[i]);
	first = False;
      }
    }
	/*----------------------------------------------------------------
	**  See if there's anything specified on cmnd line, incl "name".
	*/
    XrmParseCommand (&cmnd_line_db,
			OpTable_0, XtNumber(OpTable_0), our_name, argc, argv);
    if (cmnd_line_db != NULL) {
	    /*
	    ** There was at least 1 item on cmnd line. Process the line.
	    ** If -name was specified, adopt it.
	    */
      status = XrmGetResource (cmnd_line_db,  /* See if a name was specified  */
			    StrJoin (text, sizeof (text), our_name, ".name"),
			    "ProgramName.Values",
			    &name_type, &name_value);
      if (status) {
	i = sizeof (lkup_name);
	StrEdit (lkup_name, name_value.addr, "lowercase", &i);
	printf ("Option list name is \"%s\"\n", lkup_name);
      }else {
        strcpy (lkup_name, our_name);
      }
	    /*
	    ** Loop over all items in OpTable_0 and merge them into database,
	    ** taking care of any possible name changes.
	    */
      for (i = 0; i < XtNumber (OpTable_0); i++) {
	if (strcmp (OpTable_0[i].option, "-name") == 0) continue;
        status = XrmGetResource (cmnd_line_db,
				StrJoin (text, sizeof (text),
				    our_name, OpTable_0[i].specifier),
				"ProgramName.Values",
				&name_type, &name_value);
	if (status) {
	  StrJoin (text, sizeof (text), lkup_name, OpTable_0[i].specifier);
	  XrmPutResource (&lcl_db, text, "String", &name_value);
	}
      }
    }
/*----------------------------------------------------------------
*/
    *name = lkup_name;
    *db = lcl_db;
    if ((lcl_db == NULL) && verbose)
      printf ("Warning -- no resource database found.\n");

    XrmDestroyDatabase (cmnd_line_db);
/*
**    XrmPutFileDatabase (lcl_db, "sinqhm_client.db");
*/
    return status;
  }
/*
**--------------------------------------------------------------------------*/
  void show_help (char *token) {
/*     =========
**		    Display help text
*/
    int	    len;

    if (token == NULL) token = "";
    if (token[0] == NIL) {
      printf ("\n"
	    " The following commands are recognised by SinqHM_Client:\n"
	    "\n"
	    "    Help or ?   - generate this help information\n"
	    "    Open or     - open the connection to the histogram memory\n"
	    "      Connect\n"
	    "    Status or   - show the status of the histogram memory\n"
	    "      Show\n"
	    "    Read        - read a region of histogram memory\n"
	    "    2D          - read a region of a 2-dimensional histogram\n"
	    "    Project     - read a projected region of a 2-dim histogram\n"
	    "    Dump        - dump the contents of the histogram buffer\n"
	    "    LOAD        - write the histogram buffer from a file\n"
	    "    WRIte       - write data to a histogram region\n"
	    "    W2D         - write data to a histogram region in pseudo 2-dim mode\n"
	    "    GO          - start data acquisition\n"
	    "    STOP        - stop data acquisition\n"
	    "    ZERO        - zero a region of histogram memory\n"
	    "    Quit or     - end the program\n"
	    "      Exit or End\n"
	    "\n"
	    " To get more detailed help on a specific command, issue "
				"the command:\n"
	    "\n"
	    "    ? <cmnd>\n"
	    "\n"
	    " For information on environment setup for SinqHM_Client, issue"
				"the command:\n"
	    "\n"
	    "    ? SETUP\n"
	    "\n");
    } else {
      len = strlen (token);
      if (StrMatch (token, "read", 1)) {
	printf ("\n"
	    " Read <1st-bin> <#-bins> <hist-#>\n"
	    "          ^        ^        ^\n"
	    "          |        |        |\n"
	    "          |        |        +--- Dflt = -1\n"
	    "          |        +------------ Dflt = see below\n"
	    "          +--------------------- Dflt = 0\n"
	    "\n"
	    "   Read <#-bins> bins starting at <1st-bin> of histogram <hist-#>.\n"
	    "\n"
	    "   If <hist-#> is -1, the histogram data is regarded as a single "
								"histogram.\n"
	    "   The default for <#-bins> depends on the value of <hist-#>. "
								"If <hist-#>\n"
	    "   is -1, it defaults to the total histogram size (i.e. "
							"<#-bins-per-hist> *\n"
	    "   <#-histograms>). Otherwise, it defaults to <#-bins-per-hist>.\n"
	    "\n"
	    "   The command verb should be terminated by a space or tab.\n"
	    "   Arguments may be separated by spaces, tabs or commas.\n"
	    "\n"
	    "   Hence, to read the whole of histogram number 5, for example, "
							    "specify:\n"
	    "\n"
	    "          READ ,,5\n"
	    "\n");
      }else if (StrMatch (token, "2d", 2)) {
	printf ("\n"
	    " 2D <1st-hist> <#-hists> <1st-bin> <#-bins>\n"
	    "        ^          ^         ^        ^\n"
	    "        |          |         |        |\n"
	    "        |          |         |        +--- Dflt = histogram size\n"
	    "        |          |         +------------ Dflt = 0\n"
	    "        |          +---------------------- Dflt = number of histograms\n"
	    "        +--------------------------------- Dflt = 0\n"
	    "\n"
	    "   Read a rectangular array of the 2-dim histogram memory (e.g. a TOF\n"
	    "   spectrum). From each histogram, <#-bins> bins starting at <1st-bin>\n"
	    "   are read. The same region is read from histograms <1st-hist> to\n"
	    "   <1st-hist>+<#-hists>-1.\n"
	    "\n");
      }else if (StrMatch (token, "project", 1)) {
	printf ("\n"
	    " Project <1st-hist>,  <-- dflt = 0.\n"
	    "         <#-hists>,   <-- dflt = number of histograms.\n"
	    "         <1st-bin>,   <-- dflt = 0.\n"
	    "         <#-bins>,    <-- dflt = histogram size.\n"
	    "         <axis>,      <-- \"X\" or \"Y\" for proj'n onto x- or "
						    "y-axis. Dflt = \"X\".\n"
	    "         <x-dim>,     <-- gives x-extent of histog in pseudo-2-"
							"dim mode.\n"
	    "         <hist-#>     <-- selects a histogram in pseudo-2-dim "
							"mode. Dflt = 0.\n"
	    "\n"
	    "   Read a rectangular array of the 2-dim histogram memory (e.g. "
							    "a TOF\n"
	    "   spectrum) projected onto the x or y axis. From each histogram, "
							    "<#-bins> bins\n"
	    "   starting at <1st-bin> are read. The same region is read"
							    "from histograms\n"
	    "   <1st-hist> to <1st-hist>+<#-hists>-1.\n"
	    "\n"
	    "   If <x-dim> is non-zero, pseudo-2-dim mode will be assumed "
							"(i.e. the\n"
	    "   PROJECT__1_DIM sub_code bit will be set.\n"
	    "\n");
      }else if (StrMatch (token, "dump", 1)) {
	printf ("\n"
	    " DUMP <1st-bin> <#-bins> <file>\n"
	    "          ^        ^       ^\n"
	    "          |        |       |\n"
	    "          |        |       +---- Dflt = standard output\n"
	    "          |        +------------ Dflt = rest of buffer\n"
	    "          +--------------------- Dflt = 0\n"
	    "\n"
	    "   Dump <#-bins> bins starting at <1st-bin> of buffer.\n"
	    "\n"
	    "   The command verb should be terminated by a space or tab.\n"
	    "   Arguments may be separated by spaces, tabs or commas.\n"
	    "\n"
	    "   Hence, to dump 25 bins starting at bin 100, specify:\n"
	    "\n"
	    "          DUMP 100,25\n"
	    "\n");
      }else if (StrMatch (token, "load", 1)) {
	printf ("\n"
	    " LOAD <file>\n"
	    "        ^\n"
	    "        |\n"
	    "        +---- Dflt = standard input\n"
	    "\n"
	    "   Read the contents of the file and write to hist mem.\n"
	    "   The file format should be the same as that generated by DUMP\n"
	    "\n");
      }else if (StrMatch (token, "write", 2)) {
	printf ("\n"
	    " WRITE <p1> <p2> <p3> <p4> <p5> <p6>\n"
	    "        ^    ^    ^    ^    ^    ^\n"
	    "        |    |    |    |    |    |\n"
	    "        |    |    |    |    |    +--- Dflt = 0.60 * Number of bins\n"
	    "        |    |    |    |    +-------- Dflt = 1000\n"
	    "        |    |    |    +------------- Dflt =  200000\n"
	    "        |    |    +------------------ Dflt = 0.23 * Number of bins\n"
	    "        |    +----------------------- Dflt = 1000\n"
	    "        +---------------------------- Dflt = 2000000\n"
	    "\n"
	    "   Preset the histogram memory to the sum of 2 Lorenzians given by\n"
	    "   <p1> ... <p6>.\n"
	    "\n");
      }else if (StrMatch (token, "w2d", 2)) {
	printf ("\n"
	    " WRITE <#-hists> <p1> <p2> <p3> <p4> <p5> <p6>\n"
	    "          ^       ^    ^    ^    ^    ^    ^\n"
	    "          |       |    |    |    |    |    |\n"
	    "          |       |    |    |    |    |    +--- Dflt = 0.60 * Number of bins\n"
	    "          |       |    |    |    |    +-------- Dflt = 1000\n"
	    "          |       |    |    |    +------------- Dflt =  200000\n"
	    "          |       |    |    +------------------ Dflt = 0.23 * Number of bins\n"
	    "          |       |    +----------------------- Dflt = 1000\n"
	    "          |       +---------------------------- Dflt = 2000000\n"
	    "          +--------- Dflt = 1. The total allocated hist mem is\n"
	    "                     split into <#-hists> histograms.\n"
	    "\n"
	    "   Preset the histogram memory to the sum of 2 Lorenzians given by\n"
	    "   <p1> ... <p6>.\n"
	    "\n");
      }else if (StrMatch (token, "go", 1)) {
	printf ("\n"
	    " GO\n"
	    "\n"
	    "   Start data acquisition.\n"
	    "\n");
      }else if (StrMatch (token, "show", 2)) {
	printf ("\n"
	    " SHOW\n"
	    "\n"
	    "   Show Hist Mem status.\n"
	    "\n");
      }else if (StrMatch (token, "stop", 2)) {
	printf ("\n"
	    " STOP\n"
	    "\n"
	    "   Stop data acquisition.\n"
	    "\n");
      }else if (StrMatch (token, "zero", 1)) {
	printf ("\n"
	    " ZERO <1st-bin> <#-bins>\n"
	    "          ^        ^\n"
	    "          |        |\n"
	    "          |        +---- Dflt = histogram size\n"
	    "          +------------- Dflt = 0\n"
	    "\n"
	    "   Zero <#-bins> bins starting at <1st-bin>.\n"
	    "\n");
      }else if ((StrMatch (token, "open", 1)) ||
		(StrMatch (token, "connect", 1))) {
	if (StrMatch (token, "open", 1)) {
	  printf ("\n OPEN\n\n");
	}else {
	  printf ("\n CONNECT\n\n");
	}
	printf (
	    "   Open the connection to the Hist Mem.\n"
	    "   The connection is usually not opened until the first "
							"action command\n"
	    "   is given.\n"
	    "\n");
      }else if (StrMatch (token, "setup", 2)) {
	printf ("\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 itself to allow debugging.\n"
	    "\n");
      }else {
	printf ("Sorry, no help available for \"%s\"!\n", token);
      }
    }
  }
/*
**--------------------------------------------------------------------------*/
  void split_args (
/*     ==========
**		    Split up a text string into arguments. The arguments
**		    may be separated by white space or commas. Adjacent
**		    commas indicate a default argument.
**
**		    Each argument in the variable length argument list will
**		    get set to the address of the start of the appropriate
**		    argument. A defaulted argument is returned as NULL.
*/
	char *str,  /* The string to be parsed. This string will get modified
		    ** as it is split up into tokens */
	...) {	    /* A NULL terminated list of char** arguments. */

    va_list	ap;	    /* Pointer to variable args */
    int		i, s_len, l_nxt;
    char	*nxt_str;
    char	**arg_ptr;

    va_start (ap, str);	    /* Set up var arg machinery */

    s_len = strlen (str);
    if (s_len <= 0) {	    /* If input string is null, return lots of NULLs */
      arg_ptr = va_arg (ap, char **);
      while (arg_ptr != NULL) {
	*arg_ptr = NULL;
	arg_ptr = va_arg (ap, char **);
      }
      return;
    }
			/* Turn all white space chars into spaces */
    l_nxt = strcspn (str, "\t\f\v\n");
    while (l_nxt != s_len) {
      str[l_nxt] = ' ';
      l_nxt = strcspn (str, "\t\f\v\n");
    }
			/* Now compress out multiple spaces */
    nxt_str = strstr (str, "  ");
    while (nxt_str != NULL) {
      nxt_str[1] = NIL;
      StrJoin (str, (s_len + 1), str, &nxt_str[2]);
      nxt_str = strstr (str, "  ");
    }
    if (str[0] == ' ') str++;	/* Remove a leading space, if present */

			/* Remove a space if followed by a comma */
    nxt_str = strstr (str, " ,");
    while (nxt_str != NULL) {
      nxt_str[0] = NIL;
      StrJoin (str, (s_len + 1), str, &nxt_str[1]);
      nxt_str = strstr (str, " ,");
    }
			/* Remove a space if preceded by a comma */
    nxt_str = strstr (str, ", ");
    while (nxt_str != NULL) {
      nxt_str[1] = NIL;
      StrJoin (str, (s_len + 1), str, &nxt_str[2]);
      nxt_str = strstr (str, ", ");
    }
			/* Turn all remaining spaces into commas */
    s_len = strlen (str);
    l_nxt = strcspn (str, " ");
    while (l_nxt != s_len) {
      str[l_nxt] = ',';
      l_nxt = strcspn (str, " ");
    }
			/* Now split up the comma-separated tokens */
    arg_ptr = va_arg (ap, char **);	/* Get pntr to first argument */
    while (arg_ptr != NULL) {		/* Loop till all have been done */
      if (strlen (str) == 0) {
	*arg_ptr = NULL;	    /* If str is exhausted, keep giving NULL */
      }else {
	l_nxt = strcspn (str, ",");	/* Find end of next token */
	if (l_nxt > 0) {		/* Is it a null token? */
	  *arg_ptr = str;		    /* No, so set up next arg pntr */
	  str[l_nxt] = NIL;		    /* Terminate the token */
	  str = &str[l_nxt+1];		    /* Move over the separator */
	}else {				/* It is a null token */
	  *arg_ptr = NULL;
	  str++;			/* Move over the separator */
	}
      }
      arg_ptr = va_arg (ap, char **);	/* Get pntr to next parameter ident */
    }
  }
/*
**--------------------------------------------------------------------------*/
  int write_hm (
/*    ========
**			Write block of bins to SINQHM_SRV
*/
	    void *hbuf,		/* Buffer holding data */
	    uint  hist_no,	/* Histogram number to write */
	    uint  f_bin,	/* First bin to write */
	    uint  n_bins,	/* Number of bins to write */
	    uint  bpb) {	/* # bytes per bin */

    int		i, status, bytes_to_go;

    uchar	*p_byte;
    usint	*p_word;
    uint	*p_long;

    p_byte = (uchar *) hbuf;
    p_word = (usint *) hbuf;
    p_long = (uint  *) hbuf;

    if (0x12345678 != ntohl (0x12345678)) {	/* Swap bytes, if necessary */
      switch (bpb) {
       case 1: break;
       case 2: for (i=0; i<n_bins; i++) p_word[i] = htons (p_word[i]); break;
       case 4: for (i=0; i<n_bins; i++) p_long[i] = htonl (p_long[i]);
      }
    }
		/*
		** Send the request message first
		*/
    Req_buff.bigend		   = htonl (0x12345678);
    Req_buff.cmnd		   = htonl (SQHM_WRITE);
    Req_buff.u.write.hist_no       = htonl (hist_no);
    Req_buff.u.write.n_bins	   = htonl (n_bins);
    Req_buff.u.write.first_bin     = htonl (f_bin);
    Req_buff.u.write.bytes_per_bin = htonl (bpb);
    status = send (Rw_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    if (status == -1) FailInet ("write_hm -- 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 = n_bins * bpb;
    p_byte = (uchar *) hbuf;
    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 ("write_hm -- 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 ("write_hm -- 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 (
	    "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);
    }
			    /* Finally, swap bytes back again, if necessary,
			    ** so that a DUMP command will make sense.
			    */
    if (0x12345678 != ntohl (0x12345678)) {
      switch (bpb) {
       case 1: break;
       case 2: for (i=0; i<n_bins; i++) p_word[i] = ntohs (p_word[i]); break;
       case 4: for (i=0; i<n_bins; i++) p_long[i] = ntohl (p_long[i]);
      }
    }
    return True;
  }
/*
**==========================================================================
**				Main line program
**				-----------------
**==========================================================================*/
  main (int argc, char *argv[]) {
/*==========================================================================*/
    int			i, j, k, status, is, nerr, vlen, nbins;
    char		*cmnd;
    int			bytes_to_come, bytes_to_go;
    uint		f_bin, n_bins, hist_num;
    uint		daq_was, daq_now, filler_mask, server_mask;

    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;
    XrmDatabase		my_db;
    char		*appName;
/*============================================================================
*/
    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);
    }
	/*-------------------------------------------------------------
	**	Setup the resource database and look up the resources.
	*/
    Verbose = False;
    for (i = 1; i < argc; i++) if (strcmp ("-v", argv[i]) == 0) Verbose = True;

    setup_xrm_database (&my_db, &appName, &argc, argv, Verbose);
    status = get_check_resources (&my_db, appName, &argc, argv, Verbose);
    if (!status) return False;

    if (argc > 1) {
      printf ("\nThe following arguments were not used:\n\n     ");
      for (i = 1; i < argc; i++) {
	  printf ("\"%s\" ", argv[i]);
      }
      printf ("\n");
      show_help (NULL);
      return False;
    }
/*====================================================== Wait for work =========
*/
    printf ("\n"
	" The following commands are available:\n"
	"    Help Open Status Read 2D Project Dump LOAD WRITE W2D GO STOP ZERO "
					"Quit\n");
    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\nInput 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;
      }
      StrJoin (recd1, sizeof (recd1), recd1, " ,,,,,,,,,,");
	    /*
	    ** Parse the command
	    */
      verb = strtok (recd1, " \t\f\v\n");
      vlen = strlen (verb);

      if (StrMatch (verb, "read", 1)) {
	do_1d (&verb[vlen+1], Dbg_mode);   /* Generate a 1-dim plot */
      }else if (StrMatch (verb, "2d", 2)) {
	do_2d (&verb[vlen+1], Dbg_mode);   /* Generate a 2-dim plot */
      }else if (StrMatch (verb, "project", 1)) {
	do_project (&verb[vlen+1], Dbg_mode);   /* Do a projected read */
      }else if (StrMatch (verb, "dump", 1)) {
	do_dump (&verb[vlen+1]);	    /* Generate a dump of the data */
      }else if (StrMatch (verb, "load", 4)) {
	do_load (&verb[vlen+1], Dbg_mode);    /* Load histog mem from file */
      }else if (StrMatch (verb, "write", 5)) {
	if (Rw_skt == 0) {
	  Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
					&Rply_buff, Verbose);
	  if (Rw_skt == 0) FailInet ("\nmain/openConnectionGbl error.");
	}

	printf ("\n Writing data to histogram memory ...");
	gen_data (&verb[vlen+1]);	/* Generate some pseudo data */
	hist_num = -1;
	f_bin = 0;
	nbins = Hm_nbins * N_hists;
	status = write_hm (Hm_buff_addr, hist_num, f_bin, nbins, Bytes_per_bin);
	if (status) printf (" OK\n");
      }else if (StrMatch (verb, "w2d", 3)) {
	if (Rw_skt == 0) {
	  Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
					&Rply_buff, Verbose);
	  if (Rw_skt == 0) FailInet ("\nmain/openConnectionGbl error.");
	}

	printf ("\n Writing pseudo 2-dim data to histogram memory ...");
	gen_data_2d (&verb[vlen+1]);	/* Generate some pseudo data */
	hist_num = -1;
	f_bin = 0;
	nbins = Hm_nbins * N_hists;
	status = write_hm (Hm_buff_addr, hist_num, f_bin, nbins, Bytes_per_bin);
	if (status) printf (" OK\n");
      }else if (StrMatch (verb, "go", 2)) {
	if (Rw_skt == 0) {
	  Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
					&Rply_buff, Verbose);
	  if (Rw_skt == 0) FailInet ("\nmain/openConnectionGbl 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 ("\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 ("\n"
		  "SinqHM_Client --  Cnct-Socket recv error - "
		  "unexpected byte count: %d.\n", status);
	  exit (EXIT_FAILURE);
	}
	if (ntohl (Rply_buff.bigend) != 0x12345678) {
	  printf ("\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 ("\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 (" Actually, data acquisition was already active.\n");
	  }else {
	    printf ("\n"
		    " Data acquisition not yet started. The various masks"
								" are:\n"
		    "     Daq-state-now = 0x%04x\n"
		    "     Filler-mask   = 0x%04x\n"
		    "     Server-mask   = 0x%04x\n",
			daq_now, filler_mask, server_mask);
	  }
	}
      }else if ((StrMatch (verb, "show", 1)) ||
		(StrMatch (verb, "status", 1))) {
	do_status (Dbg_mode);		    /* Get status of SinqHM_srv */
      }else if (StrMatch (verb, "stop", 4)) {
	if (Rw_skt == 0) {
	  Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
					&Rply_buff, Verbose);
	  if (Rw_skt == 0) FailInet ("\nmain/openConnectionGbl 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 ("\nmain/send -- R/W-Socket send error\n");
	if (status != sizeof (Req_buff)) {
	  printf ("\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 ("\nmain/recv -- R/W-Socket recv error\n");
	  exit (EXIT_FAILURE);
	}else if (status != sizeof (Rply_buff)) {
	  printf ("\n"
		  "SinqHM_Client --  Cnct-Socket recv error - "
		  "unexpected byte count: %d.\n", status);
	  exit (EXIT_FAILURE);
	}
	if (ntohl (Rply_buff.bigend) != 0x12345678) {
	  printf ("\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 ("\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"
		    "     Daq-state-now = 0x%04x\n"
		    "     Filler-mask   = 0x%04x\n"
		    "     Server-mask   = 0x%04x\n",
			daq_now, filler_mask, server_mask);
	  }else {
	    printf ("\n"
		    " Data acquisition is still active!\n");
	  }
	}
      }else if (StrMatch (verb, "zero", 4)) {
	if (Rw_skt == 0) {
	  Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
					&Rply_buff, Verbose);
	  if (Rw_skt == 0) FailInet ("\nmain/openConnectionGbl error.");
	}
	p_p1 = strtok (NULL, " \t,");	/* Get pointers to the 2 args */
	p_p2 = strtok (NULL, " \t,");
	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 * N_hists;
	}
	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 ("\nmain/send -- 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 ("\nmain/recv -- 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 (
	    "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 ((StrMatch (verb, "open", 1)) ||
		(StrMatch (verb, "connect", 1))) {
	if (Rw_skt == 0) {
	  printf ("\n Opening the connection ...\n");
	  Rw_skt = openConnectionGbl (Rmt_host, &Rmt_port, &Pkt_size, Dbg_mode,
					&Rply_buff, Verbose);
	  if (Rw_skt == 0) FailInet ("\nmain/openConnection error.");
	}else {
	  printf ("\n The connection is already open!\n");
	}
      }else if ((StrMatch (verb, "exit", 1)) ||
		(StrMatch (verb, "quit", 1)) ||
		(StrMatch (verb, "end", 1))) {
	break;
      }else if ((StrMatch (verb, "?", 1)) ||
		(StrMatch (verb, "help", 1))) {
	show_help (strtok (NULL, " \t,"));
      }else {
        printf (" Illegal command - type \"?\" for help.\n");
      }
      strcpy (last_recd, recd);
	    /*
	    ** Get another command.
	    */
      printf ("> ");
    }
/*
**			Time to quit. Note that the exit handler will tidy
**			up any open connection to the Hist Mem Server,
*/
    exit (EXIT_SUCCESS);
  }
/*============================================= End of SinqHM_Client.C ======*/
