#define	    IDENT	"1A14"
/*---------------------------------------------------------------------------*/
#ifdef __DECC
#pragma	    module	    sinqhm_ctrl	    IDENT
#endif
/*
** Link_options - Here is the Linker Option File
**!	sinqhm_ctrl
**!	tas_src:[lib]sinq/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_ctrl debug
** Link_options_end
**
**	Building on Alpha OSF/1:
**
	    cc -std1 -g -o ~/bin/sinqhm_ctrl -I/public/lib/include	\
			-transitive_link -L/public/lib -lsinq -lrt	\
			~/SinqHM/sinqhm_ctrl.c
**
** +--------------------------------------------------------------+
** |                  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  . . . . . . . . : TAS_SRC:[SINQHM]sinqhm_ctrl.c
**
** Author   . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Dec 1996
**
** Purpose
** =======
**    sinqhm_ctrl.c is an Internet Client which can be used to send control
**    messages to a front-end processor running the SINQHM histogram
**    memory server process. Control messages may be sent to configure,
**    de-configure, rundown, set the level of debug printing, start data
**    acquisition, stop data acquisition, show the status of SINQHM_SRV, or
**    zero the histogram memory.
**
**  1) Configure:
**     =========
**    The configuration information is obtained from options on the command
**    line. Use the "-help config" option for details.
**
**    Once the configuration information has been checked, a connection is
**    made to the SINQHM_SRV root process on the front-end and a configure
**    message is sent. SINQHM_SRV will check the information, start up a child
**    process, FILLER, which will do the work of filling histograms, and then
**    send a reply.
**
**    Note: If SINQHM_SRV has already been successfully configured, i.e. it
**	    already has an active FILLER child process, it must be
**	    de-configured first.
**
**  2) Debug:
**     ======
**    The level of debug printing in the SINQHM_SRV root process can be set. The
**    higher the level, the more print-out on the front-end processor's console
**    occurs. The debug level is inherited by any server children (or FILLER)
**    which subsequently get started.
**
**  3) De-configure:
**     ============
**    "De-configuration" involves terminating any child processes of the
**    SINQHM_SRV root process. Normally, it is expected that the server children
**    will have been terminated via the protocol between the servers and their
**    clients so that a de-configure involves simply the termination of FILLER.
**    This is a so-called "gentle" de-configure. However, in order to facilitate
**    the recovery from error situations, it is possible to specify a "harsh"
**    de-configure in which any active server children will also be terminated.
**    A gentle de-configure will fail if there are active children.
**
**  4) Rundown:
**     =======
**    "Rundown" implies the termination not only of the SINQHM_SRV children but
**    also of the root process itself. Once a rundown has been performed,
**    intervention will be required on the front-end (e.g. reboot or creation
**    of a new SINQHM_SRV root job from the front-end console) before SINQHM_SRV
**    can be used again.
**
**  5) Show-Status:
**     ===========
**    The status of SINQHM_SRV is illicited and printed out.
**
**  6) Start-Data-Acquisition
**     ======================
**    The SinqHM-Filler process in the HM is instructed to start data-acq.
**
**  7) Stop-Data-Acquisition
**     =====================
**    The SinqHM-Filler process in the HM is instructed to stop data-acq.
**
**  8) Zero:
**     ====
**    The complete histogram area is set to zero.
**
** Use:
** ===
**	Define the foreign command:
**
**	    $ sinqhm_ctrl :== $mad_exe:sinqhm_ctrl
**
**	Then issue the command:
**
**	    $ sinqhm_ctrl <cmnd> <modifier>
**
**	where <cmnd> may be "CONFIG", "DEBUG", "DECONFIG", "GO", "HELP",
**	"RUNDOWN", "STATUS", "STOP" or "ZERO". If <cmnd> is omitted or none of
**	the above or if any error occurs obtaining the configuration
**	information for the "CONFIG" command, a "HELP" command will be assumed.
**
**	For the "CONFIG" command, <modifier> may be specified as "SUSPEND".
**	If so, the filler task in the front-end will suspend as soon as it
**	starts so that it can be debugged. Note that the same action can be
**	achieved by specifying "DEBUG" as a token in SINQHM_MODE.
**
**	For the "DEBUG" command, <modifier> is an integer specifying the debug
**	level. <modifier> may also be specified as "ON" or "OFF", corresponding
**	to levels 1 and 0 respectively. If <modifier> is anything else (or
**	absent), "ON" is assumed.
**
**	For the "DECONFIG" command, <modifier> is used to specify the
**	"harshness" of the de-configure. If <modifier> is specified as
**	"HARSH", the de-configure will be "harsh". If <modifier> is anything
**	else (or absent) the de-configure will be gentle.
**
**  Communication between sinqhm_ctrl and the server is via TCP/IP protocol.
**
** Updates:
**  1A01 18-Dec-1996 DM.	Initial version.
**====================================================================
*/
#include    <errno.h>
#include    <netdb.h>
#include    <stdio.h>
#include    <stdlib.h>
#include    <time.h>

#ifdef	__VMS
 #include    <ucx$inetdef.h>
#else
 #include    <netinet/tcp.h>
 #include    <unistd.h>
#endif

#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>

/*
**====================	Global Definitions =====================================
*/
#include    <sinq_prototypes.h>
#include    "SinqHM_def.h"

#define SUCCESS	       1
#define ERROR	       0
#define NIL	       '\0'

#define HM_SIZE	   65536	/* Number of Bins in Hist Mem */
/*
**====================	Some functions and structures =====================
**
**					Fixed-Length Descriptor:
*/
    struct  dsc__descriptor_s {
	unsigned short  dsc__w_length;   /* length of data item in bytes */
	unsigned char   dsc__b_dtype;    /* data type code */
	unsigned char   dsc__b_class;    /* descriptor class code */
	char		*dsc__a_pointer; /* address of data storage */
    };
/*
**====================	Global Variables ======================================
*/
  int		    My_errno, My_vaxc_errno;

  struct req_buff_struct	    Req_buff;
  struct rply_buff_struct	    Rply_buff;

  int		Verbose;
  char		Rmt_host[32];
  int		Rmt_port;
  int		Pkt_size;

  int		Do_config;
  int		Do_debug;
  int		Do_deconfig;
  int		Do_go;
  int		Do_rundown;
  int		Do_status;
  int		Do_stop;
  int		Do_zero;

  int		Dbg_level;
  int		Be_harsh;	/* Set to True if -harsh option specified */
  char		Mode[64];	/* The "-mode" option */
  int		Hm_mode;	/* The histogramming mode */
  int		Nhist;		/* The number of histograms to fill */
  int		Nbins;		/* The number of bins to fill */
  int		Lo_bin;		/* The first bin */
  int		Compress;	/* The bin compression factor */
  int		Bytes_per_bin;	/* The number of bytes per bin */
  int		Ncntrs;		/* The number of counters (TOF mode) */
  int		Lo_cntr;	/* The first counter */
  int		Span;		/* The time span per bin */
  int		Delay_time_to_start;	/* The DTS for the MDI in TOF mode */
  int		Nbuff;		/* The # buffers in TRANS mode */
  int		Buff_size;	/* The buffer size in TRANS mode */
  int           xOff;           /* X Offset in PSD mode */ 
  int           yOff;           /* Y Offset in PSD mode */
  int           xFac;           /* X factor in PSD mode */
  int           yFac;           /* Y factor in PSD mode */
  int           xSize;          /* xSize in PSD mode */
  int           ySize;          /* ySize in PSD mode */

  struct dsc__descriptor_s Name_desc;

  static XrmOptionDescRec OpTable_0[] = {
      {"-name",	    ".name",		XrmoptionSepArg, (XPointer) NULL},
      {"-h",	    ".sqhmHelp",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-he",	    ".sqhmHelp",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-hel",	    ".sqhmHelp",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-help",	    ".sqhmHelp",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-?",	    ".sqhmHelp",	XrmoptionNoArg,  (XPointer) "1"},
      {"-ho",	    ".sqhmHost",	XrmoptionSepArg, (XPointer) NULL},
      {"-hos",	    ".sqhmHost",	XrmoptionSepArg, (XPointer) NULL},
      {"-host",	    ".sqhmHost",	XrmoptionSepArg, (XPointer) NULL},
      {"-port",	    ".sqhmPort",	XrmoptionSepArg, (XPointer) NULL},
      {"-size",	    ".sqhmPktSize",	XrmoptionSepArg, (XPointer) NULL},
      {"-v",	    ".sqhmVerbose",	XrmoptionNoArg,	 (XPointer) "1"},
      {"-config",   ".sqhmConfig",	XrmoptionNoArg,  (XPointer) "1"},
      {"-debug",    ".sqhmDebug",	XrmoptionSepArg, (XPointer) NULL},
      {"-deconfig", ".sqhmDeconfig",	XrmoptionNoArg,  (XPointer) "1"},
      {"-go",	    ".sqhmGo",		XrmoptionNoArg,  (XPointer) "1"},
      {"-rundown",  ".sqhmRundown",	XrmoptionNoArg,  (XPointer) "1"},
      {"-show",	    ".sqhmStatus",	XrmoptionNoArg,  (XPointer) "1"},
      {"-status",   ".sqhmStatus",	XrmoptionNoArg,  (XPointer) "1"},
      {"-stop",	    ".sqhmStop",	XrmoptionNoArg,  (XPointer) "1"},
      {"-zero",	    ".sqhmZero",	XrmoptionNoArg,  (XPointer) "1"},
      {"-mode",	    ".sqhmMode",	XrmoptionSepArg, (XPointer) NULL},
      {"-nhist",    ".sqhmNhist",	XrmoptionSepArg, (XPointer) NULL},
      {"-nbins",    ".sqhmNbins",	XrmoptionSepArg, (XPointer) NULL},
      {"-lo_bin",   ".sqhmLoBin",	XrmoptionSepArg, (XPointer) NULL},
      {"-compress", ".sqhmCompress",	XrmoptionSepArg, (XPointer) NULL},
      {"-bpb",	    ".sqhmBpb",		XrmoptionSepArg, (XPointer) NULL},
      {"-ncntr",    ".sqhmNcntr",	XrmoptionSepArg, (XPointer) NULL},
      {"-lo_cntr",  ".sqhmLoCntr",	XrmoptionSepArg, (XPointer) NULL},
      {"-span",	    ".sqhmSpan",	XrmoptionSepArg, (XPointer) NULL},
      {"-delay",    ".sqhmDelay",	XrmoptionSepArg, (XPointer) NULL},
      {"-nbuff",    ".sqhmNbuff",	XrmoptionSepArg, (XPointer) NULL},
      {"-buff_size",".sqhmBuffSize",	XrmoptionSepArg, (XPointer) NULL},
      {"-harsh",    ".sqhmHarsh",	XrmoptionNoArg,  (XPointer) "1"},
      {"-xoff",     ".sqhmxoff",	XrmoptionNoArg,  (XPointer) "1"},
      {"-yoff",     ".sqhmyoff",	XrmoptionNoArg,  (XPointer) "1"},
      {"-xfac",     ".sqhmxfac",	XrmoptionNoArg,  (XPointer) "1"},
      {"-yfac",     ".sqhmyfac",	XrmoptionNoArg,  (XPointer) "1"},
      {"-xsize",    ".sqhmxsize",	XrmoptionNoArg,  (XPointer) "1"},
      {"-ysize",    ".sqhmyszie",	XrmoptionNoArg,  (XPointer) "1"},
    };

  extern int	 C_gbl_status;	    /*  Return status from C_... routines */
/*
**=============================================================================
**  Local routines.
**
**  show_help		: Display the help text.
**----------------------------------------------------------------------------
**							    Prototypes
*/
  int	    getCheckStatusResponse (
			int			 skt,
			struct rply_buff_struct *reply,
			int			 rlen);
  int	    get_check_resources (
			XrmDatabase *db,
			char	    *appName,
			int	    *argc,
			char	    *argv[],
			int	     verbose);
  int	    get_no_arg_resource (
			XrmDatabase	*db,
			char		*appName,
			int		*argc,
			char		*argv[],
			char		*resource,
			char		*cmnd,
			int		 min_len);
  int	    open_socket (
			char		*host,
			int		 port);
  void	    print_HM_mode (uint mode);
  void	    print_uptime (FILE *lun, char *prefix, int secs, char *suffix);
  int	    setup_xrm_database (XrmDatabase	*db,
				char		*name[],
				int		*argc,
				char		*argv[],
				int		verbose);
  void	    show_help (char *mod0, char *mod1);
/*
**--------------------------------------------------------------------------*/
  int	getCheckStatusResponse (
/*	======================
**			    Wait for the status response from SinqHM and
**			    check it for errors.
**
*/		int			 skt,	    /* The socket for recv */
		struct rply_buff_struct	*reply,	    /* The buffer to use */
		int			 rlen) {    /* Size of buffer */

    int	    status;

    status = recv (skt, (char *) reply, rlen, 0);
    if (status == -1) {
      FailInet ("\n\007sinqhm_ctrl -- recv error");
      return ERROR;
    } else if (status != rlen) {
      printf ("\007"
	    "sinqhm_ctrl --  recv error - unexpected byte count: %d/%d\n",
		    rlen, status);
      return ERROR;
    }
    if (ntohl (reply->bigend) != 0x12345678) {
      printf ("\007"
	    "sinqhm_ctrl -- big-endian/little-endian problem!\n"
	    "    Buffer received in non-network byte order!\n");
      return ERROR;
    }
    status = ntohl (reply->status);
    if (status == KER__SUCCESS) {
      return SUCCESS;
    }else if (status == KER__BAD_CREATE) {
      printf ("\007 Status response is KER__BAD_CREATE\n");
      printf (" Sub-status = %d\n", ntohl (reply->sub_status));
    }else if (status == KER__BAD_STATE) {
      printf ("\007 Status response is KER__BAD_STATE\n");
    }else if (status == KER__BAD_VALUE) {
      printf ("\007 Status response is KER__BAD_VALUE\n");
    }else if (status == KER__BAD_RECV) {
      printf ("\007 Status response is KER__BAD_RECV\n");
    }else if (status == KER__BAD_ALLOC) {
      printf ("\007 Status response is KER__BAD_ALLOC\n");
    }else {
      printf ("\007 Bad and unrecognised status response: 0x%x\n",
		    status);
    }
    if (reply->u.message[0] != NIL) {
      printf (" Message = \"%s\"\n", &reply->u.message[0]);
    }
    return ERROR;
  }
/*
**---------------------------------------------------------------------------
**			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;
    char		buff[80];
    char		*type;
    XrmValue		value;
    time_t		time_now;
    float		tmp_secs;
/*----------------------------------------------------------	-help	*/
    status = get_no_arg_resource (db, appName, argc, argv,
					    ".sqhmHelp", "help", 1);
    if (status) {
      if (*argc <= 1) {
	show_help (NULL, NULL);
      }else if (*argc <= 2) {
	show_help (argv[1], NULL);
      }else {
	show_help (argv[1], argv[2]);
      }
      exit (EXIT_SUCCESS);
    }
/*----------------------------------------------------------	-v */
    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, 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);
/*----------------------------------------------------------	-size */
    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);
/*----------------------------------------------------------*/
    Do_config   = get_no_arg_resource (db, appName, argc, argv,
					    ".sqhmConfig", "config", 1);
    Do_deconfig = get_no_arg_resource (db, appName, argc, argv,
					    ".sqhmDeconfig", "deconfig", 8);
    Do_go       = get_no_arg_resource (db, appName, argc, argv,
					    ".sqhmGo", "go", 2);
    Do_rundown  = get_no_arg_resource (db, appName, argc, argv,
					    ".sqhmRundown", "rundown", 7);
    Do_status   = get_no_arg_resource (db, appName, argc, argv,
					    ".sqhmStatus", "status", 1);
    if (!Do_status) Do_status = get_no_arg_resource (db, appName, argc, argv,
					    ".sqhmStatus", "show", 1);
    Do_stop     = get_no_arg_resource (db, appName, argc, argv,
					    ".sqhmStop", "stop", 4);
    Do_zero     = get_no_arg_resource (db, appName, argc, argv,
					    ".sqhmZero", "zero", 4);
    Be_harsh    = get_no_arg_resource (db, appName, argc, argv,
					    ".sqhmHarsh", "harsh", 5);
/*----------------------------------------------------------	-debug */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmDebug"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Do_debug = False;
    }else {
      if (StrMatch (value.addr, "ON", 2)) {
	Dbg_level = 0x0001;
      }else if (StrMatch (value.addr, "OFF", 2)) {
	Dbg_level = 0x0000;
      }else if ((sscanf (value.addr, "%i", &Dbg_level) != 1) ||
		(Dbg_level < 0) ||
		(Dbg_level > 0x0ff)) {
	printf ("\n"
		"  \"-debug %s\" is invalid!\n"
		"\n", value.addr);
	show_help ("debug", NULL);
	exit (EXIT_FAILURE);
      }
      Do_debug = True;
    }
/*----------------------------------------------------------	-mode	*/
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmMode"),
			     "ProgramName.Values",
			     &type, &value);
    if (status) {
      StrJoin (Mode, sizeof (Rmt_host), value.addr, "");
      if (verbose) printf ("-mode is \"%s\"\n", Mode);
    }else {
      StrJoin (Mode, sizeof (Rmt_host), "", "");
    }
/*----------------------------------------------------------	-nhist	*/
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmNhist"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Nhist = 1;
    }else if (sscanf (value.addr, "%d", &Nhist) != 1) {
      printf (" \"-nhist %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (Nhist <= 0) {
      printf (" \"-nhist %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-nbins	*/
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmNbins"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Nbins = 0;
    }else if (sscanf (value.addr, "%d", &Nbins) != 1) {
      printf (" \"-nbins %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (Nbins <= 0) {
      printf (" \"-nbins %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-lo_bin	*/
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmLoBin"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Lo_bin = 0;
    }else if (sscanf (value.addr, "%d", &Lo_bin) != 1) {
      printf ("\"-lo_bin %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (Lo_bin < 0) {
      printf ("\"-lo_bin %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-compress */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmCompress"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Compress = 1;
    }else if (sscanf (value.addr, "%d", &Compress) != 1) {
      printf (" \"-compress %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (Compress <= 0) {
      printf (" \"-compress %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-bpb */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmBpb"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Bytes_per_bin = 4;
    }else if (sscanf (value.addr, "%d", &Bytes_per_bin) != 1) {
      printf (" \"-bpb %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if ((Bytes_per_bin != 1) ||
	      (Bytes_per_bin != 2) ||
	      (Bytes_per_bin != 4)) {
      printf (" \"-bpb %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-ncntr */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmNcntr"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Ncntrs = 0;
    }else if (sscanf (value.addr, "%d", &Ncntrs) != 1) {
      printf (" \"-ncntr %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (Ncntrs <= 0) {
      printf (" \"-ncntr %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-lo_cntr */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmLoCntr"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Lo_cntr = 0;
    }else if (sscanf (value.addr, "%d", &Lo_cntr) != 1) {
      printf (" \"-lo_cntr %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (Lo_cntr < 0) {
      printf (" \"-lo_cntr %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-span */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmSpan"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Span = -1;
    }else if (sscanf (value.addr, "%d", &Span) != 1) {
      printf (" \"-span %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (Span <= 0) {
      printf (" \"-span %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-delay */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmDelay"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Delay_time_to_start = 0;
    }else if (sscanf (value.addr, "%d", &Delay_time_to_start) != 1) {
      printf (" \"-delay %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (Delay_time_to_start <= 0) {
      printf (" \"-delay %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-nbuff */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmNbuff"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Nbuff = 5;
    }else if (sscanf (value.addr, "%d", &Nbuff) != 1) {
      printf (" \"-nbuff %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (Nbuff <= 0) {
      printf (" \"-nbuff %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-buff_size */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmBuffSize"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      Buff_size = 8192;
    }else if (sscanf (value.addr, "%d", &Buff_size) != 1) {
      printf (" \"-buff_size %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (Buff_size <= 0) {
      printf (" \"-buff_size %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-xoff */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmxoff"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      xOff = 100;
    }else if (sscanf (value.addr, "%d", &xOff) != 1) {
      printf (" \"-xoff %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (xOff <= 0) {
      printf (" \"-xoff %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-yoff */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmyoff"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      yOff = 100;
    }else if (sscanf (value.addr, "%d", &yOff) != 1) {
      printf (" \"-yoff %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (yOff <= 0) {
      printf (" \"-yoff %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-yfac */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmyfac"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      yFac = 10;
    }else if (sscanf (value.addr, "%d", &yFac) != 1) {
      printf (" \"-yfac %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (yFac <= 0) {
      printf (" \"-yfac %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-xfac */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmxfac"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      xFac = 10;
    }else if (sscanf (value.addr, "%d", &xFac) != 1) {
      printf (" \"-xfac %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (xFac <= 0) {
      printf (" \"-xfac %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-xsize */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmxsize"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      xSize = 256;
    }else if (sscanf (value.addr, "%d", &xSize) != 1) {
      printf (" \"-xsize %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (xSize <= 0) {
      printf (" \"-xsize %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------	-ysize */
    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff),
				      appName, ".sqhmxsize"),
			     "ProgramName.Values",
			     &type, &value);
    if (!status) {
      ySize = 256;
    }else if (sscanf (value.addr, "%d", &ySize) != 1) {
      printf (" \"-ysize %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }else if (ySize <= 0) {
      printf (" \"-ysize %s\" is invalid!\n", value.addr);
      exit (EXIT_FAILURE);
    }
/*----------------------------------------------------------------------*/
    return True;
  }
/*
**---------------------------------------------------------------------------
**			get_no_arg_resource - get a resource with no args
*/
  int	get_no_arg_resource (
/*	===================
*/			XrmDatabase	*db,
			char		*appName,
			int		*argc,
			char		*argv[],
			char		*resource,
			char		*cmnd,
			int		 min_len) {

    int			i, status;
    char		buff[80];
    char		*type;
    XrmValue		value;

    status = XrmGetResource (*db,
			     StrJoin (buff, sizeof (buff), appName, resource),
			     "ProgramName.Values",
			     &type, &value);
    if (status) {
      return True;
    }else {
      if ((*argc >= 2) && StrMatch (argv[1], cmnd, min_len)) {
	(*argc)--;
	for (i = 1; i < *argc; i++) argv[i] = argv[i+1];
	return True;
      }
    }
    return False;
  }
/*
**---------------------------------------------------------------------------
** Function:		open_socket ()
**
** Description:
**   Create a "stream" socket and connect to a given Host/Port combination.
**
**   Return value is socket.
**   If an error is detected, a message will be printed and return value = 0.
*/
  int	open_socket (
/*	===========
*/
	    char	*host,	    /* The host's name */
	    int		 port) {    /* The port on the host to connect to */

    int			 status, my_skt, my_port;
    char		 old_time_out[4];
    union {
      char  chars[4];
      int   val;
    } time_out;
    unsigned int	 oto_status;
    struct sockaddr_in	 lcl_sockname;
    struct sockaddr_in	 rmt_sockname;
    struct in_addr	 rmt_inet_addr;
    struct in_addr	*rmt_inet_addr_pntr;
    struct hostent	*rmt_hostent;
    int			 rmt_sockname_len;
#ifdef	__VMS
    unsigned int    oto_len;
    int		    tcp_option = UCX$C_TCP_PROBE_IDLE;
#else
    int		    oto_len;
  #ifdef LINUX
    int		    tcp_option = 0;
  #else
    int		    tcp_option = TCP_KEEPINIT;
  #endif
#endif
/*------------------------------------------------------------------*/
		/*
		** Get the Internet address of the Host
		*/
    rmt_inet_addr.s_addr = inet_addr (host);
    if (rmt_inet_addr.s_addr != -1) {
      rmt_inet_addr_pntr = &rmt_inet_addr;
    }else {
      rmt_hostent = gethostbyname (host);
      if (rmt_hostent == NULL) {
	printf ("failed!\n\n"
	      "   Host name, \"%s\", is not a known "
			"Internet address.\n", host);
	return 0;
      }
      rmt_inet_addr_pntr = (struct in_addr *) rmt_hostent->h_addr_list[0];
    }
	    /*---------------------------
	    ** Create a TCP/IP socket for connecting to server and bind it.
	    */
    my_skt = socket (AF_INET, SOCK_STREAM, 0);
    if (my_skt <= 0) {
      printf ("failed!\n\n"
	      "   Could not create a socket.\n\n");
      perror ("OpenSocket");
      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) {
      close (my_skt);
      printf ("failed!\n\n"
	      "   Could not bind the socket.\n\n");
      perror ("OpenSocket");
      return 0;
    }
		/*---------------------------
		** Set short time-out
		*/
    oto_len = sizeof (old_time_out);	/* Save current time-out first */
    oto_status = getsockopt (my_skt, IPPROTO_TCP, tcp_option,
				old_time_out, &oto_len);
    if (oto_status == 0) {
      time_out.val = 5;			/* Set new time-out */
      status = setsockopt (my_skt, IPPROTO_TCP, tcp_option,
			    time_out.chars, sizeof (time_out));
    }
		/*---------------------------
		** Connect to host
		*/
    my_port = port;
    rmt_sockname_len = sizeof (rmt_sockname);
    rmt_sockname.sin_family	 = AF_INET;
    rmt_sockname.sin_port	 = htons (my_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 != 0) {
      close (my_skt);
      printf ("failed!\n\n"
	      "   Could not connect to Host %s, Port %d.\n\n",
		    host, my_port);
      perror ("OpenSocket");
      return 0;
    }
		/*---------------------------
		** Restore time-out
		*/
    if (oto_status == 0) {
      setsockopt (my_skt, IPPROTO_TCP, tcp_option,
			    old_time_out, oto_len);
    }
    return my_skt;
  }
/*
**--------------------------------------------------------------------------
*/
  void print_HM_mode (
/*     =============
**			    Interpret the HM configuration.
**
*/		    uint  mode) {   /* The configuration to be interpreted */

    uint    my_mode;

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

    my_mode = mode & (~SQHM__SUB_MODE_MSK);
    if (my_mode == SQHM__TRANS)  printf (" SQHM__TRANS");
    if (my_mode == SQHM__HM_DIG) printf (" SQHM__HM_DIG");
    if (my_mode == SQHM__TOF)    printf (" SQHM__TOF");
    if (my_mode == SQHM__HM_PSD) printf (" SQHM__HM_PSD");
    if (my_mode == SQHM__HRPT)   printf (" SQHM__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   Bin overflow mode = ");
    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);
    }
  }
/*
**---------------------------------------------------------------------------
**			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 ("\007Warning -- no resource database found.\n");

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

    len = (mod0 == NULL) ? 0 : strlen (mod0);
    if (len == 0) goto sh_basic;

    if (StrMatch (mod0, "host", 1))      goto sh_host;
    if (StrMatch (mod0, "resources", 2)) goto sh_resources;
    if (StrMatch (mod0, "config", 1))    goto sh_config;
    if (StrMatch (mod0, "debug", 3))     goto sh_debug;
    if (StrMatch (mod0, "deconfig", 3))  goto sh_deconfig;
    if (StrMatch (mod0, "go", 1))        goto sh_go;
    if (StrMatch (mod0, "rundown", 2))   goto sh_rundown;
    if (StrMatch (mod0, "show", 1))	 goto sh_show;
    if (StrMatch (mod0, "status", 2))    goto sh_status;
    if (StrMatch (mod0, "stop", 3))	 goto sh_stop;
    if (StrMatch (mod0, "zero", 1))	 goto sh_zero;

    printf ("\n"
	    " \"%s\" in an unrecognised help option. Here are some\n"
	    " hints on using sinqhm_ctrl:\n", mod0);
sh_basic:
    printf ("\n"
	"  The following major command options are recognised by sinqhm_ctrl:\n"
	"\n"
	"    -host ...           - specifies the target histogram memory.\n"
	"\n"
	"    -config ...         - configure the hist memory.\n"
	"    -debug <level>      - sets the debug level.\n"
	"    -deconfig           - de-configure the hist memory.\n"
	"    -go                 - start data acquisition.\n"
	"    -rundown            - run down SinqHM server.\n"
	"    -status (or -show)  - get status of hist memory.\n"
	"    -stop               - stop data acquisition.\n"
	"    -zero               - zero the HM buffer.\n"
	"\n"
	"  In order to use sinqhm_ctrl on a VMS system, the DCL$PATH logical\n"
	"  name must be defined, e.g:\n"
	"                   $ define/job dcl$path mad_exe:\n"
	"\n"
	"  To get more help, issue the command:    sinqhm_ctrl -help <subject>\n"
	"\n"
	"  where <subject> may be any of\n"
	"\n"
	"    host\n"
	"    config    debug    deconfig  go\n"
	"    rundown   status   stop      zero\n"
	"    resources\n"
	"\n");
    return;

  sh_host:
    printf ("\n -host\n"
	"\n"
	"  The histogram memory with which sinqhm_ctrl is to communicate is\n"
	"  specified on the command line, thus:\n"
	"\n"
	"           -host <host> -port <port> -size <pkt-size>\n"
	"\n"
	"  <host> is the Internet name of the histogram memory specified as\n"
	"  a name or in the normal Internet dot notation. There is no default.\n"
	"\n"
	"  <port> defaults to 2400 and is the Internet port number at which "
									"the\n"
	"  SinqHM server in <host> is accepting connections.\n"
	"\n"
	"  <pkt-size> defaults to 8192 and is the maximum size to be used "
								"in send/recv\n"
	"  calls for transmitting messegas and data between the client and "
								    "<host>.\n"
	"  It is not recommended to make this value too large since it causes "
									"the\n"
	"  network software to reserve too much dynamic memory.\n"
	"\n");
    return;

  sh_resources:
    printf ("\n"
	    " Sorry, \"-help resources\" is not yet available.\n\n");

  sh_config:
    len = (mod1 == NULL) ? 0 : strlen (mod1);
    if (len == 0) goto shc_basic;

    if (StrMatch (mod1, "hm_dig", 4))     goto shmc_hm_dig;
    if (StrMatch (mod1, "tof",    2))     goto shmc_tof;
    if (StrMatch (mod1, "hrpt",   2))     goto shmc_hrpt;
    if (StrMatch (mod1, "hm_psd", 4))     goto shmc_psd;
    if (StrMatch (mod1, "trans",  2))     goto shmc_trans;
    printf ("\n"
	    " \"%s\" in an unrecognised \"-help config\" option. Here is\n"
	    " the basic \"-help config\" information:\n", mod1);
  shc_basic:
    printf ("\n -config           Configure the histogram memory.\n"
	"\n"
	"  When the -config option is used to configure the histogram memory,\n"
	"  the -mode option must also be given to specify the histogramming mode.\n"
	"  The -mode option takes the form:\n"
	"\n"
	"         -mode <main-mode>[/<sub-mode>][/<sub-mode>]...\n"
	"  \n"
	"  <main-mode> specifies the histogramming mode. Recognised values are:\n"
	"      HM_DIG = Digitised histogramming mode (e.g. DMC or SANS)\n"
	"      TOF    = Time-of-Flight mode\n"
	"      HRPT   = HRPT mode\n"
	"      HM_PSD = Position-Sensitive-Detector mode\n"
	"      TRANS  = Transparent mode\n"
	"\n"
	"  <sub-mode> specifies extra options for the mode. Recognised values are:\n"
	"      DEBUG    - debug mode. The filler task will suspend itself as\n"
	"                   soon as it is started so that it can be debugged.\n"
	"      UD       - Up/Down mode.\n"
	"      BO_IGN   - Ignore bin overflows when histogramming.\n"
	"      BO_SMAX  - If a bin overflows, stop at maximum value.\n"
	"      BO_CNT   - Keep a count of bin overflows (not yet available).\n"
	"      STROBO   - Stroboscopic (gummi) mode.\n"
	"      REFLECT  - histograms are reflected (used on HRPT)\n"
	"      NO_STAT  - Suppress status information from the filler task.\n"
	"\n"
	"  Further options must also be specified depending on the value of <main-mode>.\n"
	"  To get more help, issue the command:\n"
	"\n"
	"         sinqhm_ctrl -help config <main-mode>\n"
	"\n"
	"  where <main-mode> may be any of HM_DIG, TOF, HRPT, HM_PSD or TRANS.\n"
	"\n"
	"  The configuring of the histogram memory results in the starting up\n"
	"  of the filler process.\n"
	"\n");
    return;

  shmc_hm_dig:
    printf ("\n -config -mode HM_DIG           Digitised histogramming mode.\n"
	"\n"
	"  The following options are required to define the HM_DIG mode:\n");
    goto shmc_hm_dig_hrpt_comn;

  shmc_hrpt:
    printf ("\n -config -mode HRPT             HRPT histogramming mode.\n"
	"\n"
	"  The following options are required to define the HRPT mode:\n");

  shmc_hm_dig_hrpt_comn:
    printf ("\n"
	"    -nhist    <#-hists>     (Dflt =    1) = Number of histograms.\n"
	"    -nbins    <#-bins>      (Dflt = none) = Number of bins.\n"
	"    -bpb      <bpb>         (Dflt =    4) = Bytes per bin.\n"
	"    -lo_bin   <lo_bin>      (Dflt =    0) = Number of lowest bin.\n"
	"    -compress <cmprs>       (Dflt =    1) = Bin compression factor.\n"
	"\n");
    return;

  shmc_tof:
    printf ("\n -config -mode TOF          Time-of-Flight histogramming mode.\n"
	"\n"
	"  The following options are required to define the TOF mode:\n"
	"    -ncntr    <#-cntrs>     (Dflt = none) = Number of counters.\n"
	"    -nbins    <#-bins>      (Dflt = none) = Number of bins.\n"
	"    -lo_bin   <lo_bin>      (Dflt =    0) = Tick value of first bin.\n"
	"    -lo_cntr  <lo_cntr>     (Dflt =    0) = Number of first counter.\n"
	"    -bpb      <bpb>         (Dflt =    4) = Bytes per bin.\n"
	"    -span     <span>        (Dflt = none) = Number of ticks spanned by a bin.\n"
	"    -delay    <delay>       (Dflt =    0) = Delay time to start\n"
	"\n");
    return;

  shmc_psd:
    printf ("\n -config -mode HM_PSD          PSD histogramming mode.\n"
	"\n"
	"          Not yet available!\n"
	"\n");
    return;

  shmc_trans:
    printf ("\n -config -mode TRANS            Transparent mode.\n"
	"\n"
	"  The following options are required to define the Transparent mode:\n"
	"    -nbuff     <#-buff>     (Dflt =    5) = Number of buffers.\n"
	"    -buff_size <size>       (Dflt = 8192) = Size in bytes of each buffer.\n"
	"\n");
    return;

  sh_debug:
    printf ("\n -debug <level>   Set the level of debug messages.\n"
	"\n"
	"  The value of <level> sets the verbosity of the SinqHM system\n"
	"  in generating messages to the COM1 port of the histogram\n"
	"  memory.\n"
	"\n"
	"  <level> may be set to \"OFF\", \"ON\", 0, 1, 2 or 3.\n"
	"\n"
	" \"OFF\" is equivalent to 0\n"
	" \"ON\"  is equivalent to 1\n"
	" The default is \"ON\".\n"
	"\n");
    return;

  sh_deconfig:
    printf ("\n -deconfig <harshness>    De-configure the hist memory.\n"
	"\n"
	" If <harshness> is not specified, there must be no active clients\n"
	" for the command to be accepted.\n"
	"\n"
	" If <harshness> is specified as \"HARSH\", any active clients will\n"
	" be killed.\n"
	"\n"
	" The filler task is also terminated.\n"
	"\n");
    return;

  sh_go:
    printf ("\n -go     Start data acquisition by SinqHM-filler\n"
	"\n"
	"  An SQHM_DAQ/DAQ__GO command will be sent to SinqHM-master to cause\n"
	"  SinqHM-filler to start data acquisition.\n"
	"\n");
    return;

  sh_rundown:
    printf ("\n -rundown     Runs down SinqHM\n"
	"\n"
	"          +------------------+\n"
	"          | USE WITH CAUTION |\n"
	"          +------------------+\n"
	"\n"
	" SinqHM-master, SinqHM-filler and all SinqHM-servers will\n"
	" be terminated.\n"
	"\n"
	" After issuing this command, manual intervention on the\n"
	" histogram memory will be necessary in order to restart\n"
	" SinqHM.\n"
	"\n");
    return;

  sh_show:
    printf ("\n -show      Same as -status\n"
	"\n"
	"      Get and display the status of the hist memory.\n"
	"\n");
    return;

  sh_status:
    printf ("\n -status      Get and display the status of the hist memory.\n"
	"\n");
    return;

  sh_stop:
    printf ("\n -stop     Stop data acquisition by SinqHM-filler\n"
	"\n"
	"  An SQHM_DAQ/DAQ__STOP command will be sent to SinqHM-master to cause\n"
	"  SinqHM-filler to stop data acquisition.\n"
	"\n");
    return;

  sh_zero:
    printf ("\n -zero         Zero the histogram memory buffer\n"
	"\n"
	" An SQHM_ZERO command will be sent to SinqHM-master. The values of\n"
	" hist_no, first_bin and n_bins will be set to -1 so that the entire\n"
	" histogram memory buffer will be set to zero.\n"
	"\n");
    return;
  }
/*
**==========================================================================
**
**  Main line program
**  ------------------
**==========================================================================*/
  main (int argc, char *argv[]) {
/*==========================================================================*/
    int			i, j, k, status, cmnd_len, mod_len;
    int			is1, is2, mode;
    int			nh, ch, bph, bpb, span;
    int			tsi_status, tsi_flags, dt_or_dts, num_bad_ev;
    char		*p_addr, *opt, tmp_ch;
    char		buff[64], my_cmnd[32], my_mod[32];
    char		*token;
    unsigned int	daq_state_now;
    unsigned int	daq_state_was;
    unsigned int	filler_mask;
    unsigned int	server_mask;
    XrmDatabase		my_db;
    char		*appName;

    int			cnct_skt;	/* Connect socket */
    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;
    int			oto_status;
    char		old_time_out[4];
    union {
      char  chars[4];
      int   val;
    } time_out;
/*============================================================================*/
    printf ("sinqhm_ctrl ident %s.\n", IDENT);

	/*-------------------------------------------------------------
	**	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 (Verbose) printf (" Server is %s ", Rmt_host);
    if (Verbose) printf ("(%s),", inet_ntoa (*rmt_inet_addr_pntr));
    if (Verbose) printf (" Port %d.\n", Rmt_port);
/*============================================================================
**		Execute the user's wish.
*/
    i = 0;
    if (Do_config)   i++;
    if (Do_debug)    i++;
    if (Do_deconfig) i++;
    if (Do_go)	     i++;
    if (Do_rundown)  i++;
    if (Do_status)   i++;
    if (Do_stop)     i++;
    if (Do_zero)     i++;
    if (i == 0) {
      printf ("No action has been specified. Assume \"-status\" ...\n");
      Do_status = True;
    }else if (i != 1) {
      printf ("Only one action may be specified on the command line.\n");
      show_help (NULL, NULL); exit (EXIT_FAILURE);
    }
/*============================================================================
**		Switch according to value of <cmnd>
*/
    if (Do_config)	goto config;
    if (Do_debug)	goto debug;
    if (Do_deconfig)	goto deconfig;
    if (Do_go)		goto go;
    if (Do_rundown)	goto rundown;
    if (Do_status)	goto status;
    if (Do_stop)	goto stop;
    if (Do_zero)	goto zero;
    goto status;
/*============================================================================*/
  config:
/*======		Configure - Extract values from the logical names.
*/
    Hm_mode = 0;
    StrJoin (buff, sizeof (buff), Mode, "");
    token = strtok (buff, "/");   /* Split up the tokens */
    while (token != NULL) {
      if (StrMatch (token, "HM_DIG", 4)) {
	Hm_mode = (Hm_mode & ~SQHM__SUB_MODE_MSK) | SQHM__HM_DIG;
      }else if (StrMatch (token, "TOF", 3)) {
	Hm_mode = (Hm_mode & ~SQHM__SUB_MODE_MSK) | SQHM__TOF;
      }else if (StrMatch (token, "HRPT", 3)) {
	Hm_mode = (Hm_mode & ~SQHM__SUB_MODE_MSK) | SQHM__HRPT;
      }else if (StrMatch (token, "TRANS", 3)) {
	Hm_mode = (Hm_mode & ~SQHM__SUB_MODE_MSK) | SQHM__TRANS;
      }else if (StrMatch (token, "HM_PSD", 4)) {
	Hm_mode = (Hm_mode & ~SQHM__SUB_MODE_MSK) | SQHM__HM_PSD;
      }else if (StrMatch (token, "DEBUG", 3)) {
	Hm_mode |= SQHM__DEBUG;
      }else if (StrMatch (token, "UD", 2)) {
	Hm_mode |= SQHM__UD;
      }else if (StrMatch (token, "BO_IGN", 4)) {
	Hm_mode = (Hm_mode & ~SQHM__BO_MSK ) | SQHM__BO_IGN;
      }else if (StrMatch (token, "BO_SMAX", 4)) {
	Hm_mode = (Hm_mode & ~SQHM__BO_MSK ) | SQHM__BO_SMAX;
      }else if (StrMatch (token, "BO_CNT", 4)) {
	Hm_mode = (Hm_mode & ~SQHM__BO_MSK ) | SQHM__BO_CNT;
      }else if (StrMatch (token, "STROBO", 3)) {
	Hm_mode |= SQHM__STROBO;
      }else if (StrMatch (token, "REFLECT", 4)) {
	Hm_mode |= SQHM__REFLECT;
      }else if (StrMatch (token, "NO_STAT", 4)) {
	Hm_mode |= SQHM__NO_STAT;
      }else {
	printf ("\007 The -mode option is not valid.\n");
	printf (" Here is some help ...\n");
	show_help ("config", NULL);
	return EXIT_FAILURE;
      }
      token = strtok (NULL, "/");
    }

    is1 = EXIT_SUCCESS;
    if (((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__HM_DIG) ||
	((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__HRPT)) {
      if (Nbins <= 0) {is1 = !EXIT_SUCCESS; opt = "-nbins";}
    }else if ((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__TOF) {
      if (Ncntrs <= 0) {
	is1 = !EXIT_SUCCESS;
	opt = "-ncntr";
      }else if (Nbins <= 0) {
	is1 = !EXIT_SUCCESS;
	opt = "-nbins";
      }else if (Span < 0) {
	is1 = !EXIT_SUCCESS;
	opt = "-span";
      }
    }else if((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__HM_PSD){
      if(xSize <= 0) {
        is1 = !EXIT_SUCCESS;
        opt = "-xsize";
      }else if(ySize <= 0) {
        is1 = !EXIT_SUCCESS;
        opt = "-ysize";
      }
    }else if ((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__TRANS) {
    }else {
      is1 = !EXIT_SUCCESS;
      opt = "-mode";
    }
    if (is1 != EXIT_SUCCESS) {
      printf ("\007 The configuration is not defined or not complete.\n");
      printf (" Here is some help ...\n");
      show_help ("config", NULL);
      printf (" The problem is with %s\n", opt);
      printf ("\n");
      return EXIT_FAILURE;
    }
/*
**		    The configuration seems to be OK. Connect to the target.
*/
    cnct_skt = open_socket (Rmt_host, Rmt_port);
    if (cnct_skt <= 0) exit (EXIT_FAILURE);
/*
**		    Set up and send the configure message.
*/
    Req_buff.bigend = htonl (0x12345678);
    Req_buff.cmnd   = htonl (SQHM_CONFIG);

    Req_buff.u.cnfg.mode     = htonl (Hm_mode);
    if ((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__HM_DIG) {
      Req_buff.u.cnfg.u.hm_dig.n_hists	     = htonl (Nhist);
      Req_buff.u.cnfg.u.hm_dig.lo_bin	     = htonl (Lo_bin);
      Req_buff.u.cnfg.u.hm_dig.num_bins	     = htonl (Nbins);
      Req_buff.u.cnfg.u.hm_dig.bytes_per_bin = htonl (Bytes_per_bin);
      Req_buff.u.cnfg.u.hm_dig.compress	     = htonl (Compress);
    }else if ((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__TOF) {
      Req_buff.u.cnfg.u.tof.n_extra_bytes = htonl (0);
      Req_buff.u.cnfg.u.tof.n_edges	  = htons (1);
      Req_buff.u.cnfg.u.tof.n_banks	  = htons (1);

      Req_buff.u.cnfg.u.tof.edge_0.n_bins   = htonl (Nbins);
      Req_buff.u.cnfg.u.tof.edge_0.flag     = htonl (0);    /* Fixed bin span */
      Req_buff.u.cnfg.u.tof.edge_0.edges[0] = htonl (Lo_bin);
      Req_buff.u.cnfg.u.tof.edge_0.edges[1] = htonl (Lo_bin+Span);
      Req_buff.u.cnfg.u.tof.preset_delay    = htonl (Delay_time_to_start);

      Req_buff.u.cnfg.u.tof.bank_0.first         = htons (Lo_cntr);
      Req_buff.u.cnfg.u.tof.bank_0.n_cntrs       = htons (Ncntrs);
      Req_buff.u.cnfg.u.tof.bank_0.edge_indx	 = htons (0);
      Req_buff.u.cnfg.u.tof.bank_0.bytes_per_bin = htons (Bytes_per_bin);
    }else if ((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__HM_PSD) {
      Req_buff.u.cnfg.u.psd.n_extra_bytes = htonl (0);
      Req_buff.u.cnfg.u.psd.n_edges	  = htons (1);
      Req_buff.u.cnfg.u.psd.n_banks	  = htons (1);
      Req_buff.u.cnfg.u.psd.xOffset	  = htons (xOff);
      Req_buff.u.cnfg.u.psd.yOffset	  = htons (yOff);
      Req_buff.u.cnfg.u.psd.xFactor	  = htons (xFac);
      Req_buff.u.cnfg.u.psd.yFactor	  = htons (yFac);
      Req_buff.u.cnfg.u.psd.xSize	  = htons (xSize);
      Req_buff.u.cnfg.u.psd.ySize	  = htons (ySize);


      Req_buff.u.cnfg.u.psd.edge_0.n_bins   = htonl (Nbins);
      Req_buff.u.cnfg.u.psd.edge_0.flag     = htonl (0);    /* Fixed bin span */

      Req_buff.u.cnfg.u.psd.edge_0.edges[0] = htonl (0);
      Req_buff.u.cnfg.u.psd.edge_0.edges[1] = htonl (Span);
      Req_buff.u.cnfg.u.psd.preset_delay    = htonl (Delay_time_to_start);

      Req_buff.u.cnfg.u.psd.bank_0.first         = htons (Lo_cntr);
      Req_buff.u.cnfg.u.psd.bank_0.n_cntrs       = htons (xSize*ySize);
      Req_buff.u.cnfg.u.psd.bank_0.edge_indx	 = htons (0);
      Req_buff.u.cnfg.u.psd.bank_0.bytes_per_bin = htons (Bytes_per_bin);
    }else if ((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__TRANS) {
      Req_buff.u.cnfg.u.trans.n_buffs = htonl (Nbuff);
      Req_buff.u.cnfg.u.trans.n_bytes = htons (Buff_size);
    }

    printf (" Configuration:\n"
	    "   Histogramming mode is 0x%08x", Hm_mode);
    if ((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__HM_DIG) {
      printf (" = HM_DIG");
    }else if ((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__HM_PSD) {
      printf (" = HM_PSD");
    }else if ((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__HRPT) {
      printf (" = HRPT");
    }else if ((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__TRANS) {
      printf (" = TRANS");
    }else if ((Hm_mode & ~SQHM__SUB_MODE_MSK) == SQHM__TOF) {
      printf (" = TOF");
    }
    if ((Hm_mode & SQHM__DEBUG) != 0) printf (" + DEBUG");
    printf ("\n");
    if ((Hm_mode & ~SQHM__SUB_MODE_MSK) != SQHM__TOF) {
      printf ("   Number of histograms         = %5d\n"
	    "   Index of first bin           = %5d\n"
	    "   Number of bins per histogram = %5d\n"
	    "   Number of bytes per bin      = %5d\n"
	    "   Bin compression factor       = %5d\n",
			Nhist, Lo_bin, Nbins, Bytes_per_bin, Compress);
    } else if (((Hm_mode & ~SQHM__SUB_MODE_MSK) != SQHM__HM_DIG) ||
	       ((Hm_mode & ~SQHM__SUB_MODE_MSK) != SQHM__HRPT)) {
      printf ("   Number of counters           = %5d\n"
	    "   First counter                = %5d\n"
	    "   Number of bins per histogram = %5d\n"
	    "   Lower edge of first bin      = %5d\n"
	    "   Bin width                    = %5d\n"
	    "   Number of bytes per bin      = %5d\n"
	    "   Delay-Time-to-Start          = %5d\n",
			Ncntrs, Lo_cntr, Nbins, Lo_bin, Span, Bytes_per_bin,
			Delay_time_to_start);
    }
    if ((Hm_mode & SQHM__DEBUG) != 0)
      printf ("\007\n   Warning -- DEBUG suspend flag is set!\n\n");
    printf (" Configuring ..."); fflush (NULL);

    status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    if (status == -1) FailInet ("\nsinqhm_ctrl -- send error");
    if (status != sizeof (Req_buff)) {
      printf ("\nsinqhm_ctrl -- wrong number of bytes sent: %d", status);
      return EXIT_FAILURE;
    }
/*
**		    Wait for the status response.
*/
    status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
    if (status == SUCCESS) {
      printf (" done.\n");
    }
/*
**		Close the connection.
*/
    status = close (cnct_skt);
    if ((status != 0) && (errno != ECONNRESET))
	    FailInet ("\nsinqhm_ctrl -- close error");
    return EXIT_SUCCESS;
/*============================================================================*/
  debug:
/*=====		Debug. Set up the debug level of the front-end..
*/
    printf (" Setting SinqHM debug mask = 0x%04x ...", Dbg_level); fflush (NULL);
    Req_buff.bigend = htonl (0x12345678);
    Req_buff.cmnd   = htonl (SQHM_DBG);
    Req_buff.u.dbg.mask = htonl (Dbg_level);

    cnct_skt = open_socket (Rmt_host, Rmt_port);
    if (cnct_skt <= 0) exit (EXIT_FAILURE);

    status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    if (status == -1) FailInet ("\nsinqhm_ctrl -- send error");
    if (status != sizeof (Req_buff)) {
      printf ("sinqhm_ctrl -- wrong number of bytes sent: %d", status);
      status = close (cnct_skt);
      return EXIT_FAILURE;
    }
/*
**		Wait for the status response.
*/
    status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
    if (status == SUCCESS) {
      printf (" done.\n");
    }
/*
**		Close the connection.
*/
    status = close (cnct_skt);
    if ((status != 0) && (errno != ECONNRESET))
	    FailInet ("\nsinqhm_ctrl -- close error");
    return EXIT_SUCCESS;
/*============================================================================*/
  deconfig:
/*========		De-configure. Set up and send the deconfig message.
*/
    Req_buff.bigend = htonl (0x12345678);
    Req_buff.cmnd   = htonl (SQHM_DECONFIG);
    Req_buff.u.decnfg.sub_code = 0;		/* Be gentle, by default */
    if (Be_harsh) {
      Req_buff.u.decnfg.sub_code = htonl (1);	/* But be harsh, if ordered */
      printf (" Deconfiguring (mit Gewalt!) ...");
    }else {
      printf (" Deconfiguring ...");
    }
    fflush (NULL);
    
    cnct_skt = open_socket (Rmt_host, Rmt_port);
    if (cnct_skt <= 0) exit (EXIT_FAILURE);

    status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    if (status == -1) FailInet ("\nsinqhm_ctrl -- send error");
    if (status != sizeof (Req_buff)) {
      printf ("sinqhm_ctrl -- wrong number of bytes sent: %d", status);
      status = close (cnct_skt);
      return EXIT_FAILURE;
    }
/*
**		Wait for the status response.
*/
    status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
    if (status == SUCCESS) {
      printf (" done.\n");
    }
/*
**		Close the connection.
*/
    status = close (cnct_skt);
    if ((status != 0) && (errno != ECONNRESET))
	    FailInet ("\nsinqhm_ctrl -- close error");
    return EXIT_SUCCESS;
/*============================================================================*/
  go:
/*==		Go. Get SinqHM-filler to start taking data.
*/
    printf (" Starting data acquisition ..."); fflush (NULL);

    Req_buff.bigend	    = htonl (0x12345678);
    Req_buff.cmnd	    = htonl (SQHM_DAQ);
    Req_buff.u.daq.sub_cmnd = htonl (DAQ__GO);

    cnct_skt = open_socket (Rmt_host, Rmt_port);
    if (cnct_skt <= 0) exit (EXIT_FAILURE);

    status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    if (status == -1) FailInet ("\nsinqhm_ctrl -- send error");
    if (status != sizeof (Req_buff)) {
      printf ("sinqhm_ctrl -- wrong number of bytes sent: %d", status);
      status = close (cnct_skt);
      return EXIT_FAILURE;
    }
/*
**		Wait for the status response.
*/
    status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
    if (status == SUCCESS) {
      daq_state_now = ntohs (Rply_buff.u.daq.daq_now);
      daq_state_was = ntohs (Rply_buff.u.daq.daq_was);
      filler_mask   = ntohs (Rply_buff.u.daq.filler_mask);
      server_mask   = ntohs (Rply_buff.u.daq.server_mask);
      if (daq_state_now == 0) {
	if (daq_state_was == 0) {
	  printf (" done. It was already active!\n");
	}else {
	  printf (" done.\n");
	}
      }else {
	printf ("\n\007 Data acquisition is still disabled.\n"
	      "   Daq-state-now is 0x%04x\n"
	      "   Filler-mask   is 0x%04x\n", daq_state_now, filler_mask);
      }
    }
/*
**		Close the connection.
*/
    status = close (cnct_skt);
    if ((status != 0) && (errno != ECONNRESET))
	    FailInet ("\nsinqhm_ctrl -- close error");
    return EXIT_SUCCESS;
/*============================================================================*/
  rundown:
/*=======		Rundown. Set up and send the rundown message.
*/
    printf (" Sending SQHM_EXIT command to SinqHM ..."); fflush (NULL);
    Req_buff.bigend = htonl (0x12345678);
    Req_buff.cmnd   = htonl (SQHM_EXIT);
    
    cnct_skt = open_socket (Rmt_host, Rmt_port);
    if (cnct_skt <= 0) exit (EXIT_FAILURE);

    status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    if (status == -1) FailInet ("\nsinqhm_ctrl -- send error");
    if (status != sizeof (Req_buff)) {
      printf ("sinqhm_ctrl -- wrong number of bytes sent: %d", status);
      status = close (cnct_skt);
      return EXIT_FAILURE;
    }
/*
**		Wait for the status response.
*/
    status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
    if (status == SUCCESS) {
      printf (" done.\n");
    }
/*
**		Close the connection.
*/
    status = close (cnct_skt);
    if ((status != 0) && (errno != ECONNRESET))
	    FailInet ("\nsinqhm_ctrl -- close error");
    return EXIT_SUCCESS;
/*============================================================================*/
  status:
/*======	    Show-status. Set up and send the status message.
*/
    printf (" Getting status of SinqHM ..."); fflush (NULL);

    Req_buff.bigend = htonl (0x12345678);
    Req_buff.cmnd   = htonl (SQHM_STATUS);
    
    cnct_skt = open_socket (Rmt_host, Rmt_port);
    if (cnct_skt <= 0) exit (EXIT_FAILURE);

    status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    if (status == -1) FailInet ("\nsinqhm_ctrl -- send error");
    if (status != sizeof (Req_buff)) {
      printf ("sinqhm_ctrl -- wrong number of bytes sent: %d", status);
      status = close (cnct_skt);
      return EXIT_FAILURE;
    }
/*
**		Wait for the status response.
*/
    status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
    if (status == SUCCESS) {
			/*
			**    Display the status obtained.
			*/
      memcpy (buff, (char *) &Rply_buff.sub_status, 4); /* Get SinqHM Ident */
      buff[4] = '\0';
      printf ("\n"
	" SinqHM Identifier is \"%s\"\n", buff);
      printf (" Maximum number of histograms = %d\n",
	    ntohl (Rply_buff.u.status.max_n_hists));
      printf (" Maximum number of bins per histogram = %d\n",
	    ntohl (Rply_buff.u.status.max_num_bins));
      printf (" Maximum number of active connections supported = %d\n",
	    Rply_buff.u.status.max_srvrs);
      printf (" Maximum space available for histograms = %d bytes\n",
	    ntohl (Rply_buff.u.status.max_block));
      print_uptime (stdout, " Up-time = ",
		    ntohl (Rply_buff.u.status.up_time), "\n\n");
      if (Rply_buff.u.status.cfg_state == 0) {
	printf (" SINQHM has not yet been configured.\n");
      }else {
	mode = ntohl (Rply_buff.u.status.cfg_state);
	print_HM_mode (mode);
	printf ("\n");

	nh	   = ntohs (Rply_buff.u.status.n_hists);
	ch	   = ntohs (Rply_buff.u.status.curr_hist);
	bph	   = ntohl (Rply_buff.u.status.num_bins);
	bpb	   = Rply_buff.u.status.bytes_per_bin;
	span	   = Rply_buff.u.status.compress;
	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 (((mode & ~SQHM__SUB_MODE_MSK) == SQHM__HM_DIG) ||
	    ((mode & ~SQHM__SUB_MODE_MSK) == SQHM__HRPT)) {
	  if (nh != 0) {
	    printf (" Number of histograms         = %d\n", nh);
	    printf (" Current   histogram          = %d\n", ch);
	  }
	  printf (" Number of bins per histogram = %d\n", bph);
	  printf (" Number of bytes per bin      = %d\n", bpb);
	  if (span > 1) printf (" Bin compression factor       = %d\n", span);
	  if (dt_or_dts != 0) 
	    printf (" Dead-Time                    = %u\n", dt_or_dts);
	}else if ((mode & ~SQHM__SUB_MODE_MSK) == SQHM__TOF) {
	  nh = ntohs (Rply_buff.u.status.n_hists);
	  printf (" Number of counters           = %d\n", nh);
	  printf (" Number of bins per histogram = %d\n", bph);
	  printf (" Number of bytes per bin      = %d\n", bpb);
	  if (span > 1) printf (" Time span per bin            = %d\n", span);
	  if (dt_or_dts != 0) 
	    printf (" Delay-Time-to-Start          = %u\n", dt_or_dts);
	}else if ((mode & ~SQHM__SUB_MODE_MSK) == SQHM__HM_PSD) {
	}else if ((mode & ~SQHM__SUB_MODE_MSK) == SQHM__TRANS) {
	  printf (" Number of buffers            = %d\n", nh);
	  printf (" Current   buffer             = %d\n", ch);
	  printf (" Number of bytes per buffer   = %d\n", bph);
	}
	printf (" Number of active connections = %d\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");
	}
	if ((tsi_status != 0) || (tsi_flags != 0)) {
	  if (tsi_flags != 0) {
	    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");
	}
	if (num_bad_ev != 0)
	  printf (" Number-of-Bad-Events = %u\n", num_bad_ev);
      }
    }
/*
**		Close the connection.
*/
    status = close (cnct_skt);
    if ((status != 0) && (errno != ECONNRESET))
	    FailInet ("\nsinqhm_ctrl -- close error");
    return EXIT_SUCCESS;
/*============================================================================*/
  stop:
/*====		Stop. Get SinqHM-filler to stop taking data.
*/
    printf (" Stopping data acquisition ..."); fflush (NULL);

    Req_buff.bigend	    = htonl (0x12345678);
    Req_buff.cmnd	    = htonl (SQHM_DAQ);
    Req_buff.u.daq.sub_cmnd = htonl (DAQ__STOP);

    cnct_skt = open_socket (Rmt_host, Rmt_port);
    if (cnct_skt <= 0) exit (EXIT_FAILURE);

    status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    if (status == -1) FailInet ("\nsinqhm_ctrl -- send error");
    if (status != sizeof (Req_buff)) {
      printf ("sinqhm_ctrl -- wrong number of bytes sent: %d", status);
      status = close (cnct_skt);
      return EXIT_FAILURE;
    }
/*
**		Wait for the status response.
*/
    status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
    if (status == SUCCESS) {
      daq_state_now = ntohs (Rply_buff.u.daq.daq_now);
      daq_state_was = ntohs (Rply_buff.u.daq.daq_was);
      filler_mask   = ntohs (Rply_buff.u.daq.filler_mask);
      server_mask   = ntohs (Rply_buff.u.daq.server_mask);
      if (daq_state_now != 0) {
	if (daq_state_was == 0) {
	  printf (" done.\n");
	}else {
	  printf (" done. It was already stopped!\n");
	}
      }else {
	printf ("\n\007 Data acquisition is still enabled!\n"
	      "   Daq-state-now is 0x%04x\n"
	      "   Filler-mask   is 0x%04x\n", daq_state_now, filler_mask);
      }
    }
/*
**		Close the connection.
*/
    status = close (cnct_skt);
    if ((status != 0) && (errno != ECONNRESET))
	    FailInet ("\nsinqhm_ctrl -- close error");
    return EXIT_SUCCESS;
/*============================================================================*/
  zero:
/*====		Zero. Zero the complete histogram buffer
*/
    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 (-1);
    Req_buff.u.zero.n_bins    = htonl (-1);
    printf (" Zeroing the histogram memory buffer ..."); fflush (NULL);

    cnct_skt = open_socket (Rmt_host, Rmt_port);
    if (cnct_skt <= 0) exit (EXIT_FAILURE);

    status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
    if (status == -1) FailInet ("\nsinqhm_ctrl -- send error");
    if (status != sizeof (Req_buff)) {
      printf ("\nsinqhm_ctrl -- wrong number of bytes sent: %d", status);
      status = close (cnct_skt);
      return EXIT_FAILURE;
    }
/*
**		Wait for the status response.
*/
    status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
    if (status == SUCCESS) {
      printf (" done.\n");
    }
/*
**		Close the connection.
*/
    status = close (cnct_skt);
    if ((status != 0) && (errno != ECONNRESET))
	    FailInet ("\nsinqhm_ctrl -- close error");
    return EXIT_SUCCESS;
  }
/*================================================ End of SINQHM_CTRL.C =====*/
