/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* 61haes_r714 src/43haes/usr/sbin/cluster/clstat/xclstat.c 1.20          */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* Restricted Materials of IBM                                            */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 1990,2009              */
/* All Rights Reserved                                                    */
/*                                                                        */
/* US Government Users Restricted Rights - Use, duplication or            */
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
static char xclstat_c_sccsid[] = "@(#)46  1.20  src/43haes/usr/sbin/cluster/clstat/xclstat.c, hacmp.clstat, 61haes_r714 2/11/09 07:40:30";
/*
 *   COMPONENT_NAME: CLSTAT
 *
 *   FUNCTIONS: SetOffset
 *		Usage
 *		Xmain
 *		clstat_init
 *		create_bottom
 *		create_helptext
 *		create_nodemap
 *		create_textbuf
 *		create_top
 *		delWidgetByLabel
 *		freeWidgetList
 *		getWidgetByLabel
 *		getWidgetByTag
 *              getWidgetTag
 *		setWidgetTag
 *		help
 *		highlight
 *		mkdatestr
 *		nextCluster
 *		prevCluster
 *		putWidget
 *		quit
 *		quitPopup
 *		refreshMap
 *		title
 *		unHighlight
 *		viewNode
 *
 *   ORIGINS: 27
 *
 *
 *   (C) COPYRIGHT International Business Machines Corp. 1990,1994
 *   All Rights Reserved
 *   Licensed Materials - Property of IBM
 *   US Government Users Restricted Rights - Use, duplication or
 *   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 */

#include <stdio.h>
#include <sys/types.h>
#include <errno.h>

#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <netinet/in.h>

#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>

/* Needed to get XtClassname */
#include <Xm/XmP.h>

#include <Xm/Form.h>
#include <Xm/Command.h>
#include <Xm/Label.h>
#include <Xm/ScrolledW.h>
#include <Xm/Text.h>
#include <locale.h>
#include <nl_types.h>

#ifdef SUPPORT_EDITRES
#include <X11/Xmu/Editres.h>
#endif

#include "cluster.h"
#include "clinfo.h"
#include "xclstat.h"

#ifdef SUPPORT_DMALLOC
#include "dmalloc.h"
#endif

/* ILS */
#include <mbstr.h>
#include <langinfo.h>
#include "utilities_msg.h"
#define MSGSTR(Num, Str) catgets((nl_catd)get_catd("utilities.cat"), CLSTAT_MSG_SET, Num, Str)

#ifndef lint
#endif

char *progname;

/* Forward decl */
int compareNetifs();
int compareNodemap();
void copyNodemap();
void resetNodemap();
static nl_catd get_catd(char *);
static char *create_textbuf (int, int);


/* globals */
int CL_cid = 0;
int CL_nid = 0;
static struct cl_cluster *clusterMap; /* new cluster information */
static struct cl_node *pNodeMap; /* new node info */

static int ALLSERVICES = 0;

Arg xargv[64];
Cardinal xargc;

XtActionsRec viewNodeAction[]= { {"viewNode", viewNode} };
XtActionsRec prevClusterAction[]= { {"prevCluster", prevCluster} };
XtActionsRec nextClusterAction[]= { {"nextCluster", nextCluster} };
XtActionsRec quitAction[]= { {"quit", quit} };
XtActionsRec helpAction[]= { {"help", help} };
XtActionsRec quitPopupAction[]= { {"quitPopup", quitPopup} };
XtActionsRec titleAction[]= { {"title", title} };

String viewNodeTable = "<Btn1Down>:viewNode(%s)";
String prevClusterTable = "<Btn1Down>:prevCluster()";
String nextClusterTable = "<Btn1Down>:nextCluster()";
String quitTable = "<Btn1Down>:quit()";
String helpTable = "<Btn1Down>:help()";
String quitPopupTable = "<Btn1Down>:quitPopup(%s)";
String titleTable = "<Btn1Down>:title()";

/*
** Application resources
*/
static struct clstatRes appRes;
#define SetOffset(n,f)	(appResourceList[n].resource_offset = \
			            ((Cardinal)&appRes.f - (Cardinal)&appRes))

XtResource appResourceList[] = {
{XtNbackground, XtCBackground, XtRPixel, sizeof (Pixel), 0, XtRString, XtExtdefaultbackground},
{XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel), 0, XtRString, XtExtdefaultforeground},
{XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof (Dimension), 0, XtRString, "1"},
{XtNreverseVideo, XtCReverseVideo, XtRBool, sizeof (Bool), 0, XtRString, XtEfalse},
{"upColor", "UpColor", XtRPixel, sizeof (Pixel), 0, XtRString, "#00FF00"},
{"downColor", "DownColor", XtRPixel, sizeof (Pixel), 0, XtRString, "#FF0000"},
{"fluxColor", "FluxColor", XtRPixel, sizeof (Pixel), 0, XtRString, "#00FFFF"},
{"refreshInterval", "RefreshInterval", XtRInt, sizeof(int), 0, XtRString, "100"},
{"helpFile", "HelpFile", XtRString, sizeof(String), 0, XtRString, "/usr/lpp/cluster/man/clstat.1"} };

Boolean XtIsWidgetValid(Widget w) {

   /* NULL widget passed */
   if (! w) return(False);

   /* Non widget passed or widget struct corrupt */
   if (w != w->core.self) return(False);

   /* widget is marked for destruction */
   if (w->core.being_destroyed) return(False);

   return(True);

}

String XtClassName (Widget w) {

   if (XtIsWidgetValid(w))
      return(XtClass(w)->core_class.class_name);
   else
      return(NULL);

} 

int main (int argc, char **argv)
{
    int opt;
    extern int optind;
    extern char *optarg;

    int clusterid = 0;
    char *clustername = (char *)NULL;
    int debug_level = 1;
    int info_level = 0;
    int rflagn = 1;

    Widget topLevel;
    Widget frame;

    Pixel save_pix;
    XColor color;
    XVisualInfo *visp, vistemp;
    int visnum;

    (void) setlocale(LC_ALL, "");

    progname = strrchr (argv[0], '/');
    if ((char *)NULL == progname)
        progname = argv[0];
    else
        progname++;

    (void) dbprint_init (DBPRINT_FILE, 0, 0, 0, progname);
    (void) dbprint_set_file (getenv ("XCLSTAT_LOGFILE"), stderr);

    while (EOF != (opt = getopt (argc, argv, "sc:n:D:I:r:")))
    {
        switch (opt)
        {
            case 'c':
                ATOI (optarg, clusterid);
                break;
            case 'n':
                clustername = optarg;
                break;
            case 'D':
                ATOI (optarg, debug_level);
                break;
            case 'I':
                ATOI (optarg, info_level);
                break;
            case 'r':
                ATOI (optarg, appRes.cr_refreshInterval);
                rflagn = 0;
                break;
	    case 's':
	        ALLSERVICES = 1;
		break;
            default:
                Usage ();
                break;
        }
    }

    (void) dbprint_set_levels (debug_level, 0, info_level);

    /* Create the topLevel widget, parent to everyone.  */
    topLevel = XtInitialize (progname, "Xclstat", 0, 0, 0, 0);
    putWidget ("topLevel", topLevel);

#ifdef SUPPORT_EDITRES
    XtAddEventHandler(topLevel, (EventMask) 0, True,
              (XtEventHandler) _XEditResCheckMessages, NULL);
#endif

    /* set offsets */
    SetOffset (0, cr_background);
    SetOffset (1, cr_foreground);
    SetOffset (2, cr_borderWidth);
    SetOffset (3, cr_reverseVideo);
    SetOffset (4, cr_upColor);
    SetOffset (5, cr_downColor);
    SetOffset (6, cr_fluxColor);
    if(rflagn)
    {
        SetOffset (7, cr_refreshInterval);
    }
    SetOffset (8, cr_helpFile);

    xargc = 0;
    XtGetApplicationResources (topLevel, &appRes, appResourceList,
                               XtNumber(appResourceList), xargv, xargc);

    if (appRes.cr_reverseVideo)
    {
        save_pix = appRes.cr_foreground;
        appRes.cr_foreground = appRes.cr_background;
        appRes.cr_background = save_pix;

    }

    vistemp.visual = DefaultVisualOfScreen(DefaultScreenOfDisplay(XtDisplay(topLevel)));
    vistemp.visualid = XVisualIDFromVisual(vistemp.visual);
    visp = XGetVisualInfo(XtDisplay(topLevel), VisualIDMask, &vistemp, &visnum);

    if((visp->class == StaticGray) || (visp->class == GrayScale))
      {
	XParseColor(XtDisplay(topLevel),
		    DefaultColormapOfScreen(DefaultScreenOfDisplay(XtDisplay(topLevel))),
		    "gray80", &color);
	XAllocColor(XtDisplay(topLevel),
		    DefaultColormapOfScreen(DefaultScreenOfDisplay(XtDisplay(topLevel))),
		    &color);
	appRes.cr_downColor = color.pixel;
	XParseColor(XtDisplay(topLevel),
		    DefaultColormapOfScreen(DefaultScreenOfDisplay(XtDisplay(topLevel))),
		    "gray30", &color);
	XAllocColor(XtDisplay(topLevel),
		    DefaultColormapOfScreen(DefaultScreenOfDisplay(XtDisplay(topLevel))),
		    &color);
	appRes.cr_upColor = color.pixel;
	XParseColor(XtDisplay(topLevel),
		    DefaultColormapOfScreen(DefaultScreenOfDisplay(XtDisplay(topLevel))),
		    "gray50", &color);
	XAllocColor(XtDisplay(topLevel),
		    DefaultColormapOfScreen(DefaultScreenOfDisplay(XtDisplay(topLevel))),
		    &color);
	appRes.cr_fluxColor = color.pixel;
      }

    if (appRes.cr_refreshInterval <= 0)
    {
        appRes.cr_refreshInterval = 100;
    }

    /* initialize clinfo library and determine cluster ID
       of cluster to monitor. */
    if(0 != clstat_init (clusterid, clustername))
        exit (-1);

    /* set icon name */
    xargc = 0;
    XtSetValues (topLevel, xargv, xargc);

    /* top level form widget */
    xargc = 0;
    frame = XtCreateWidget ("frame", xmFormWidgetClass, topLevel,
                            xargv, xargc);
    putWidget ("frame", frame);

    create_top (frame);
    create_nodemap (frame);
    create_bottom (frame);

    XtManageChild (frame);
    XtRealizeWidget (topLevel);

    refreshMap (NULL, NULL, FALSE);
    XtMainLoop();
}

/*
** |--------------------------------------|
** |                                      |
** |  |--------------------------------|  |
** |  | PREV | CLUSTER NAME: ID | NEXT |  |
** |  |--------------------------------|  |
** |                                      |
** |--------------------------------------|
**/
void
create_top (Widget parent)
{
    char title[128];

    Widget topControl;
    Widget prevButton;
    Widget titleLabel;
    Widget nextButton;

    /* control panel */
    xargc = 0;
    topControl = XtCreateManagedWidget ("topControl", xmFormWidgetClass, parent,
                                        xargv, xargc);
    putWidget ("topControl", topControl);

    /* prev button */
    xargc = 0;
    XtSetArg (xargv[xargc], XmNuserData, strdup("prevButton")); xargc++;
    prevButton = XtCreateManagedWidget ("prevButton", xmLabelWidgetClass,
                                        topControl, xargv, xargc);
    putWidget ("prevButton", prevButton);
    XtAddActions (prevClusterAction, XtNumber(prevClusterAction));
    XtAugmentTranslations (prevButton, XtParseTranslationTable(prevClusterTable));
    XtAddEventHandler (prevButton, EnterWindowMask, FALSE, highlight, NULL);
    XtAddEventHandler (prevButton, LeaveWindowMask, FALSE, unHighlight, NULL);

    /* cluster name and id */
    xargc = 0;
    titleLabel = XtCreateManagedWidget ("titleLabel", xmLabelWidgetClass,
                                       topControl, xargv, xargc);
    putWidget ("titleLabel", titleLabel);
    XtAddActions (titleAction, XtNumber(titleAction));
    XtAugmentTranslations (titleLabel, XtParseTranslationTable(titleTable));

    /* next button */
    xargc = 0;
    XtSetArg (xargv[xargc], XmNuserData, strdup("nextButton")); xargc++;
    nextButton = XtCreateManagedWidget ("nextButton", xmLabelWidgetClass,
                                        topControl, xargv, xargc);
    putWidget ("nextButton", nextButton);
    XtAddActions (nextClusterAction, XtNumber(nextClusterAction));
    XtAugmentTranslations (nextButton, XtParseTranslationTable(nextClusterTable));
    XtAddEventHandler (nextButton, EnterWindowMask, FALSE, highlight, NULL);
    XtAddEventHandler (nextButton, LeaveWindowMask, FALSE, unHighlight, NULL);

    return;
}

/*
** |------------------------------|
** |                              |
** |  |------------------------|  |
** |  |  1 |  2 |  3 |  4 |  5 |  |
** |  |------------------------|  |
** |  |  6 |  7 |  8 |  9 | 10 |  |
** |  |------------------------|  |
** |  | 11 | 12 | 13 | 14 | 15 |  |
** |  |------------------------|  |
** |                              |
** |------------------------------|
*/
void
create_nodemap (Widget parent)
{
    int top;
    int bottom;
    int left;
    int right;
    int rows;
    int section;

    int n;
    char label[128];

    char TableBuf [128];

    Widget nodeMap;
    Widget entry;

    xargc = 0;
    nodeMap = XtCreateManagedWidget ("nodeMap", xmFormWidgetClass, parent,
                                     xargv, xargc);
    putWidget ("nodeMap", nodeMap);

    rows = 1;
    while (CL_MAXNODES > (rows * rows))
        rows++;

    section = 100/rows;
    for (n = 0; n < CL_MAXNODES; n++)
    {
        ITOA (n, label);

        top = (section * (n/rows)) + 1;
        bottom = (section * (n/rows)) + section - 1;

        left = (section * (n%rows)) + 1;
        right = (section * (n%rows)) + section - 1;

        xargc = 0;
        XtSetArg (xargv[xargc], XmNtopPosition, top); xargc++;
        XtSetArg (xargv[xargc], XmNbottomPosition, bottom); xargc++;
        XtSetArg (xargv[xargc], XmNleftPosition,  left); xargc++;
        XtSetArg (xargv[xargc], XmNrightPosition, right); xargc++;
        XtSetArg (xargv[xargc], XmNuserData, strdup(label)); xargc++;
        entry = XtCreateManagedWidget (label, xmLabelWidgetClass, nodeMap,
                                       xargv, xargc);
        putWidget (label, entry);
        XtAddActions (viewNodeAction, XtNumber(viewNodeAction));
        (void) sprintf (TableBuf, viewNodeTable, label);
        XtAugmentTranslations (entry, XtParseTranslationTable(TableBuf));
        XtAddEventHandler (entry, EnterWindowMask, FALSE, highlight, NULL);
        XtAddEventHandler (entry, LeaveWindowMask, FALSE, unHighlight, NULL);
    }

    return;
}

/*
** |--------------------------------------------|
** |                                            |
** |  |--------------------------------------|  |
** |  | quitButton | dateWindow | helpButton |  |
** |  |--------------------------------------|  |
** |                                            |
** |--------------------------------------------|
*/
void
create_bottom (Widget parent)
{
    Widget bottomControl;
    Widget quitButton;
    Widget dateLabel;
    Widget helpButton;

    xargc = 0;
    bottomControl = XtCreateManagedWidget("bottomControl", xmFormWidgetClass,
                                          parent, xargv, xargc);
    putWidget ("bottomControl", bottomControl);

    xargc = 0;
    XtSetArg (xargv[xargc], XmNuserData, strdup("quitButton")); xargc++;
    quitButton = XtCreateManagedWidget("quitButton", xmLabelWidgetClass,
                                       bottomControl, xargv, xargc);
    putWidget ("quitButton", quitButton);
    XtAddActions (quitAction, XtNumber(quitAction));
    XtAugmentTranslations (quitButton, XtParseTranslationTable(quitTable));
    XtAddEventHandler (quitButton, EnterWindowMask, FALSE, highlight, NULL);
    XtAddEventHandler (quitButton, LeaveWindowMask, FALSE, unHighlight, NULL);

    xargc = 0;
    dateLabel = XtCreateManagedWidget("dateLabel", xmLabelWidgetClass,
                                      bottomControl, xargv, xargc);
    putWidget ("dateLabel", dateLabel);

    xargc = 0;
    XtSetArg (xargv[xargc], XmNuserData, strdup("helpButton")); xargc++;
    helpButton = XtCreateManagedWidget("helpButton", xmLabelWidgetClass,
                                       bottomControl, xargv, xargc);
    putWidget ("helpButton", helpButton);
    XtAddActions (helpAction, XtNumber(helpAction));
    XtAugmentTranslations (helpButton, XtParseTranslationTable(helpTable));
    XtAddEventHandler (helpButton, EnterWindowMask, FALSE, highlight, NULL);
    XtAddEventHandler (helpButton, LeaveWindowMask, FALSE, unHighlight, NULL);

    return;
}

/*
 * NAME:        create_textbuf
 *
 * Format a text buffer with the node, interface and resource group information
 * for a specific cluster and node.
 * 
 * NOTE: it is the caller's responsibility to free the storage alloced here
 *
 * Arguments
 *      clusterid - desired cluster
 *      index - index of node withing map 
 *
 * Returns
 *      A formatted char buffer
 */
static
char *create_textbuf (int clusterid, int index)
{
  int i;
  int clstatus;
  struct cl_node *nodebuf;
  int nbr_groups;
  int nbr_nodes;
  int tnode, tif;
  
  char textBuf[4096];
  char *bufp;
  char primaryNodeName[CL_MAXNAMELEN];

  static struct cl_group *groupmap;
  static int group_map_alloced = 0;
  if (group_map_alloced ==0)
  {
	cl_alloc_groupmap(&groupmap);
	group_map_alloced = 1;
  }

  memset(textBuf, '\0', 4096);

  nodebuf = &pNodeMap[index];

  bufp = textBuf;
  (void) sprintf(bufp, "%s %s\n", MSGSTR(CLSTAT_NODE,"\nCluster Node"),
	nodebuf->cln_nodename);
  bufp += strlen(bufp);

  if (CLS_UP == nodebuf->cln_state)
      {
          (void) sprintf(bufp, MSGSTR(CLSTAT_STATE_STRING, "State = %s\n"), 
		MSGSTR(CLSTAT_STATE_UP, "UP")); 
      }
  else if (CLS_DOWN == nodebuf->cln_state)
      {
          (void) sprintf(bufp, MSGSTR(CLSTAT_STATE_STRING, "State = %s\n"), 
		MSGSTR(CLSTAT_STATE_DOWN, "DOWN")); 
      }
  else if (CLS_JOINING == nodebuf->cln_state)
      {
          (void) sprintf(bufp, MSGSTR(CLSTAT_STATE_STRING, "State = %s\n"), 
		MSGSTR(CLSTAT_STATE_JOINING, "JOINING")); 
      }
  else if (CLS_LEAVING == nodebuf->cln_state)
      {
          (void) sprintf(bufp, MSGSTR(CLSTAT_STATE_STRING, "State = %s\n"), 
		MSGSTR(CLSTAT_STATE_LEAVING, "LEAVING")); 
      }

  bufp += strlen(bufp);
  for (i = 0; nodebuf->cln_nif > i; i++)
    {
          /* only display boot and standby here (service will
                           be displayed below)  */
          if ((nodebuf->cln_if[i].cli_role != CL_INT_ROLE_BOOT &&
               nodebuf->cln_if[i].cli_role != CL_INT_ROLE_STANDBY))
                  continue;

	  (void) sprintf (bufp, MSGSTR(CLSTAT_NAME_ADDRESS, "\nname: %s (%s)\naddress: %s\n"),
			  nodebuf->cln_if[i].cli_name,
			  get_state(nodebuf->cln_if[i].cli_state),
			  inet_ntoa (nodebuf->cln_if[i].cli_addr.sin_addr.s_addr));
	  bufp += strlen(bufp);
    }
  /*
   * We have displayed the all the boot interfaces, now look
   * for any service labels which may be up on this node.
   * Note that we look at all services on all nodes since
   * there could be a takeover label currently on this node.
   */
  nbr_nodes = cl_getnodemap(clusterid, pNodeMap);
  for(tnode=0; tnode < nbr_nodes; tnode++)
    {
        for(tif=0; tif<pNodeMap[tnode].cln_nif; tif++)
        {
            /* only do service - all others were printed above */
            if ((pNodeMap[tnode].cln_if[tif].cli_role == CL_INT_ROLE_BOOT ||
                 pNodeMap[tnode].cln_if[tif].cli_role == CL_INT_ROLE_STANDBY))
                continue;
            /* if the service is shared it will show up in the
               interface list for all nodes whereas if its
               just plain service it will only be in the ifs
               list for one node  - the trick is to just
               display it once if its shared */
            if ((ALLSERVICES && pNodeMap[tnode].cln_if[tif].cli_nodeid == nodebuf->cln_nodeid) 
		|| (pNodeMap[tnode].cln_if[tif].cli_active_nodeid == nodebuf->cln_nodeid))
            {

                /* its active on this node, but only display
                   once if its shared. We cant rely on the
                   role of service/shared unfortunately because
                   ipat via aliasing treats both equally -
                   instead we will look for it on the local
                   node and skip displaying it here */
                if (ifs_is_shared(pNodeMap, nbr_nodes,
                                        &pNodeMap[tnode].cln_if[tif]) &&
                                  tnode != index)
                    continue;

	        (void) sprintf (bufp, MSGSTR(CLSTAT_NAME_ADDRESS, "\nname: %s (%s)\naddress: %s\n"),
			  pNodeMap[tnode].cln_if[tif].cli_name,
			  get_state(pNodeMap[tnode].cln_if[tif].cli_state),
			  inet_ntoa (pNodeMap[tnode].cln_if[tif].cli_addr.sin_addr.s_addr));
	  	bufp += strlen(bufp);
	    }
	} /* for tif */

    } /* for tnode */

  nbr_groups = cl_getgroupmap(clusterid, groupmap);
  dbprintf (20, "create_textbuf: cl_getgroupmap returned %d groups\n", nbr_groups);
  if(nbr_groups > 0 && nbr_groups < CL_MAXGROUPS)
  {
      for(i=0; i<nbr_groups; i++)
      {
          if (notOfflineGroupState(&groupmap[i], nodebuf->cln_nodeid))
          {
              sprintf(bufp, MSGSTR(CLSTAT_RESOURCE_GROUP, "\nResource Group: %s\tState: %s\n"),
                  groupmap[i].clg_name,
                  resourceStateStr(&groupmap[i], nodebuf->cln_nodeid));
  	      dbprintf (20, "adding [%s] to textBuf\n",bufp);

      	      bufp += strlen(bufp);
	  }
      } 
  }
  
  dbprintf (20, "create_textbuf: %s", textBuf);
  return (strdup (textBuf));
}

void refreshMap (Widget widget, caddr_t closure, int timerfired)
{
  int c, i, j;
  int n;
  int clstatus;
  int numClusters;
  int num_nodes;
  static int first_time = 1;
  char date[CL_MAXNAMELEN];
  char label[CL_MAXNAMELEN];
  char title[CL_MAXNAMELEN];
  char *bufp;
  char **oldNodes;
  struct cl_cluster clusterBuf; /* new cluster information buffer */
  struct cl_node nodebuf; /* new node information buffer */

  static char oldDate [32];        /* date currently displayed in window */
  static int refreshTimer = -1; /* timer set flag -1 = no */
  Widget nodeMapParent;
  WidgetList wl;
  int nw;
  Pixel defBgColor;
  XmString str;
  Widget w;

  /*
   * initialize the array of old nodes
   */
  if (0 == (oldNodes = (char **)malloc(CL_MAXNODES * sizeof(char *))))
  {
    exit (-1);
  }
  for (n = 0; n < CL_MAXNODES; n++)
  {
    oldNodes[n] = (char *)NULL;
  }

  /*
   * always allocate memory for the "new" map, newMap
   */
    if (first_time)
    {
	cl_alloc_clustermap(&clusterMap);
	cl_alloc_nodemap(&pNodeMap);
	if (clusterMap == (struct cl_cluster *)NULL || 
	    pNodeMap == (struct cl_node *)NULL)
	{
	    dbprintf (0, "refreshMap: cl_alloc problem.\n");
	    exit (-1);
	}
	first_time = 0;
    }

    /*
     * if this call was not caused by the timer going off clear it so there are
     * no interruptions
     */
    if (-1 != refreshTimer && ! timerfired)
        XtRemoveTimeOut (refreshTimer);  

    refreshTimer = -1;


    /*
     * update the date in the xclstat window if necessary
     */
    (void) mkdatestr (date);
    if (0 != mbscmp (oldDate, date))
    {
        w = NULL;
        w = getWidgetByLabel ("dateLabel");
        if (w != NULL) {
           xargc = 0;
           str = XmStringCreate (date, XmSTRING_DEFAULT_CHARSET);
           XtSetArg (xargv[xargc], XmNlabelString, str); xargc++;
           XtSetValues (w, xargv, xargc);
           XmStringFree(str);
           mbscpy (oldDate, date);
        }
    }

    /*
     * read in the cluster specific information, name, id, state..
     */
    clstatus = cl_getcluster (CL_cid, & clusterBuf);
    if (CLE_OK != clstatus)
    {
        strcpy (clusterBuf.clc_name, "NoName");
	dbprintf (10, "refreshMap: cl_getcluster (%d): %s.\n", CL_cid,
                  cl_errmsg(clstatus));
    }

    /*
     * always update the cluster information
     */
    xargc = 0;
    memset(title, '\0', CL_MAXNAMELEN);
    (void) sprintf (title, "%s: %d", clusterBuf.clc_name, CL_cid);
    str = XmStringCreate (title, XmSTRING_DEFAULT_CHARSET);
    XtSetArg (xargv[xargc], XmNlabelString, str); xargc++;

    if (CLSS_STABLE == clusterBuf.clc_substate)
    {
      XtSetArg(xargv[xargc], XmNbackground, appRes.cr_upColor);
      xargc++;
    }
    else if (CLSS_UNSTABLE == clusterBuf.clc_substate)
    {
      XtSetArg(xargv[xargc], XmNbackground, appRes.cr_fluxColor);
      xargc++;
    }
    else if (CLSS_RECONFIG == clusterBuf.clc_substate)
    {
      XtSetArg(xargv[xargc], XmNbackground, appRes.cr_fluxColor);
      xargc++;
    }
    else
    {
      XtSetArg(xargv[xargc], XmNbackground, appRes.cr_downColor);
      xargc++;
    }

    w = getWidgetByLabel ("titleLabel");
    if (w != NULL) {
       XtSetValues (getWidgetByLabel ("titleLabel"), xargv, xargc);
       setWidgetTag("titleLabel", title);
       XmStringFree(str);
    }

    /*
     * read in the list of nodes from the new map and compare them with the old
     * map, the only thing compared here is the state of the node, and if there
     * are any differences copy the new information to the current.
     */
    num_nodes = cl_getnodemap(CL_cid, pNodeMap);

    /* If we make it here, node info changed.  Update all nodes. */
    for (n = 0; n < num_nodes; n++)
    {
        ITOA (n, label);
        strcpy(title, pNodeMap[n].cln_nodename);
	
        xargc = 0;

        if (CLS_UP == pNodeMap[n].cln_state)
	{
            XtSetArg (xargv[xargc], XmNbackground, appRes.cr_upColor);
	    xargc++;
	}
        else if (CLS_DOWN == pNodeMap[n].cln_state)
	{
	    XtSetArg (xargv[xargc], XmNbackground, appRes.cr_downColor);
	    xargc++;
	}
	else if ((CLS_LEAVING == pNodeMap[n].cln_state) ||
		 (CLS_JOINING == pNodeMap[n].cln_state))
	{
	    XtSetArg(xargv[xargc], XmNbackground, appRes.cr_fluxColor); 
	    xargc++;
	}
        else
	{
	    XtSetArg (xargv[xargc], XmNbackground, appRes.cr_background);
	    xargc++;
	}

        str = XmStringCreate (title, XmSTRING_DEFAULT_CHARSET);
        XtSetArg (xargv[xargc], XmNlabelString, str); xargc++;

	if (getWidgetByLabel(label) == (Widget)NULL)
	{
	  printf("clstat internal error. Can't get widget with label %s.\n", label);
	  exit(-1);
	}

	XtSetValues(getWidgetByLabel(label), xargv, xargc);
	getWidgetTag(label, &oldNodes[n]);
	setWidgetTag(label, title);

        XmStringFree(str);

    } /* end for each node */

    /*
     * Blank out any remaining nodes that may be set from a previous
     * cluster map
     */
    nodeMapParent = getWidgetByLabel("nodeMap");
    if (nodeMapParent == (Widget)NULL)
    {
        printf("clstat internal error.  Can't get nodeMapParent widget.\n");
	exit (0);
    }
    XtVaGetValues (nodeMapParent,
		   XmNnumChildren, &nw,
		   XmNchildren, &wl,
		   XmNbackground, &defBgColor,
		   NULL);

    str = XmStringCreateSimple ("");
    for (j = n; j < nw; j++)
    {
        XtVaSetValues (wl[j], XmNbackground, defBgColor, 
		              XmNlabelString, str, 
		              NULL);
	ITOA (j, label);
	getWidgetTag(label, &oldNodes[j]);
	setWidgetTag(label, (char *)NULL);
    }
    XmStringFree(str);

    /*
     * remove the interface windows for the nodes that have been deleted
     */
    for (n = 0; ((n < nw) && ((char *)NULL != oldNodes[n])); n++)
    {
      if ((char *)NULL == getWidgetByTag(oldNodes[n]))
      {
	(void) sprintf (label, "%dNode%s", CL_cid, oldNodes[n]);
	while ((char *)NULL != getWidgetByTag(label))
	{
	  delWidgetByTag(label);
	}
      }
      free (oldNodes[n]);
    }
    free ((char*)oldNodes);

    /*
     * update all the interface windows
     */
    numClusters = cl_getclusters(clusterMap);
    for (c = 0; c < numClusters; c++)
    {
        for (n = 0; n < num_nodes; n++)
        {
            (void) sprintf (label, "%dtext%s", clusterMap[c].clc_clusterid,
                            pNodeMap[n].cln_nodename);

            if ((Widget)NULL != getWidgetByLabel (label))
            {
                bufp = create_textbuf (clusterMap[c].clc_clusterid, n);
                                       /* pNodeMap[n].cln_nodename); */
                if ((char *)NULL == bufp)
                {
                    dbperror (0, "refreshMap: malloc");
                }
                else
                {

                    XmTextSetString (getWidgetByLabel (label), bufp);
                    free (bufp);
                }
            }
        }
    }

    refreshTimer = XtAddTimeOut (appRes.cr_refreshInterval*100,
                                 refreshMap, TRUE);
    return;
} /* end refreshMap */

struct widgetList *widgetHead = (struct widgetList *)NULL;

void putWidget (char *label, Widget widget)
{
   struct widgetList *newp;

   newp = (struct widgetList*) malloc (sizeof (struct widgetList));
   if ((struct widgetList *)NULL == newp)
   {
        dbperror (0, "malloc");
        return;
   }

   dbprintf(10, "putWidget: adding widget XtName=%s XtClass=%s label=%s widget=%08X list=%08X\n",
                XtName(widget), XtClassName(widget), label, widget, newp);

   /* insert at top of list */
   newp->wl_label = strdup (label);
   newp->wl_widget = widget;
   newp->wl_tag = (char *)NULL;

   newp->wl_next = widgetHead;
   widgetHead = newp;

   return;

}

Widget
getWidgetByLabel (char *label)
{
    struct widgetList *currp;

    for (currp = widgetHead; currp != (struct widgetList *)NULL;
	 currp = currp->wl_next)
    {
        if (0 == strcmp (label, currp->wl_label))
            return (currp->wl_widget);
    }

    dbprintf (10, "getWidgetByLabel: widget %s not found.\n", label);
    return (NULL);
}

Widget
getWidgetByTag (char *tag)
{
    struct widgetList *currp;

    for (currp = widgetHead; currp != (struct widgetList *)NULL;
	 currp = currp->wl_next)
    {
        if (0 == strcmp (tag, currp->wl_tag))
            return (currp->wl_widget);
    }

    dbprintf (10, "getWidgetByTag: widget %s not found.\n", tag);
    return (NULL);
}

void setWidgetTag (char *label, char *tag)
{
    struct widgetList *currp;

    dbprintf(20, "setWidgetTag: set widget %s tag to %s\n", label, tag);

    for (currp = widgetHead; currp != (struct widgetList *)NULL;
	 currp = currp->wl_next)
    {
        if (0 == strcmp (label, currp->wl_label))
	{
	  if ((char *)NULL != currp->wl_tag)
	  {
	    free ((char*)currp->wl_tag);
	  }

	  if ((char *)NULL == (currp->wl_tag = strdup (tag)))
	  {
	    dbprintf(30, "setWidgetTag: strdup failed\n");
	  }
	  return;
	}
    }

    dbprintf (10, "setWidgetTag: widget %s not found.\n", label);
    return;
}

void
getWidgetTag (char *label, char **tag)
{
    struct widgetList *currp;

    dbprintf(20, "getWidgetTag: get title for widget %s\n", label);

    for (currp = widgetHead; currp != (struct widgetList *)NULL;
	 currp = currp->wl_next)
    {
        if (0 == strcmp (label, currp->wl_label))
	{
            if ((char *)NULL == (*tag = strdup(currp->wl_tag)))
	    {
	        dbprintf(30, "getWidgetTag: strdup failed\n");
	    }
	    return;
	}
    }

    dbprintf (10, "getWidgetTag: widget %s not found.\n", label);
    *tag = NULL;
    return;
}

#ifdef SUPPORT_DELETE_BY_LABEL
void
delWidgetByLabel (char *label)
{
    struct widgetList *prevp;
    struct widgetList *currp;

    dbprintf(10, "delWidgetByLabel: deleting widgets with label %s\n", label);

    prevp = (struct widgetList *)NULL;
    currp = widgetHead;
    while ((struct widgetList *)NULL != currp)
    {
        if (0 == strcmp (label, currp->wl_label))
        {
            if (prevp == (struct widgetList *)NULL)
            {
                widgetHead = currp->wl_next;
            }
            else
            {
                prevp->wl_next = currp->wl_next;
            }

	    dbprintf(20, "delWidgetByLabel: deleting widget %s with tag %s\n",
		     currp->wl_label, currp->wl_tag);
            free (currp->wl_label);
            free (currp->wl_tag);
            XtDestroyWidget (currp->wl_widget);
            free ((char*)currp);
            return;
        }

        prevp = currp;
        currp = currp->wl_next;
    }

    dbprintf (10, "delWidgetByLabel: widget %s not found.\n", label);
    return;
} /* end delWidgetByLabel */
#endif

/*
 * A crash occurs when CRASH is defined. I'm unsure whether this is the
 * correct behavior or not for the compiler. Also, if the code is compiled
 * with -g crashes do not occur.
 *
 * It appears that when *str is not set to NULL a previous value is being
 * taken from the stack as an assignment. The end result is that the toplevel
 * widget for the entire application gets destroyed, which in turn destroys
 * every widget in the tree. After that, all is lost...
 *
 * #define CRASH
 *
 */

void
delWidgetByTag (char *tag)
{

    struct widgetList *prevp;
    struct widgetList *currp;

    #ifdef CRASH
       char *str;
    #else
       char *str = NULL;
    #endif

    dbprintf(10, "delWidgetByTag: searching for widget with tag=%s str=<%s>\n", tag, str);

    #ifdef CRASH
       if (strlen(str) != 0) {
          printf("\n\n<<<<<=====>>>>>strlen(str) is %d <%s>\n\n\n",strlen(str),str);
       }
    #endif

    prevp = (struct widgetList *)NULL;
    currp = widgetHead;

    while ((struct widgetList *)NULL != currp) {

        if (0 == strcmp (tag, currp->wl_tag)) {

            if (prevp == (struct widgetList *)NULL)
            {
                widgetHead = currp->wl_next;
            }
            else
            {
                prevp->wl_next = currp->wl_next;
            }

	    dbprintf(15, "delWidgetByTag: deleting widget label=%s tag=%s XtName=%s XtClass=%s widget=%08X list=%08X\n",
		     currp->wl_label, currp->wl_tag,
                     XtName(currp->wl_widget), XtClassName(currp->wl_widget),
                     currp->wl_widget, currp);

            #ifdef CRASH
                if (strlen(str) != 0) {
                   printf("strlen(str) is %d <%s>\n",strlen(str),str);
                }
            #endif

            xargc = 0;
            XtSetArg(xargv[xargc], XmNuserData, &str); xargc++;

            #ifdef CRASH
                if (strlen(str) != 0) {
                   printf("strlen(str) is %d <%s>\n",strlen(str),str);
                }
            #endif

            XtGetValues(currp->wl_widget,xargv,xargc);

            #ifdef CRASH
                if (strlen(str) != 0) {
                   printf("strlen(str) is %d <%s>\n",strlen(str),str);
                }
            #endif

   	    dbprintf(20, "delWidgetByTag: delete XmNuserData - %s <%s>\n",
               XtName(currp->wl_widget), str);

            #ifdef CRASH
                if (strlen(str) != 0) {
                   printf("strlen(str) is %d <%s>\n",strlen(str),str);
                }
            #endif

            if (str != NULL && *str != NULL) { free(str); }
            free(currp->wl_label);
            free(currp->wl_tag);
            XtDestroyWidget (currp->wl_widget);
            free((char*)currp);

            return;

        }

        prevp = currp;
        currp = currp->wl_next;

    }

    dbprintf (10, "delWidgetByTag: widget %s not found.\n", tag);

    return;

} /* end delWidgetByTag */

void
freeWidgetList ()
{
    struct widgetList *savep;

    while ((struct widgetList *)NULL != widgetHead)
    {
        savep = widgetHead->wl_next;
        if (widgetHead->wl_label) free (widgetHead->wl_label);
        if (widgetHead->wl_tag)   free (widgetHead->wl_tag);
        XtDestroyWidget (widgetHead->wl_widget);
        free ((char*)widgetHead);

        widgetHead = savep;
    }

    return;
}

void
prevCluster (Widget widget, XEvent *event, char **params, int *num_params)
{
    int i;
    int start, end;
    int numClusters;
    struct cl_cluster *clusterMap;

    if (cl_alloc_clustermap(&clusterMap) == -1)
    {
        dbprintf (0, "prevCluster: cl_alloc problem.\n");
	exit (-1);
    }

    numClusters = cl_getclusters (clusterMap);
    if (0 < numClusters)
    {
        for (i = numClusters - 1; i >= 0; i--)
        {
            if (CL_cid == clusterMap[i].clc_clusterid)
            {
                end = i;
                start = end == 0 ? (numClusters - 1) : (end - 1);
                break;
            }
        }
        if (0 > i)
        {
            end = 0;
            start = numClusters - 1;
            CL_cid = clusterMap[start].clc_clusterid;
        }

        for (i = start; end != i; i = i == 0 ? (numClusters - 1) : (i - 1))
        {
            if (CLS_UP == clusterMap[i].clc_state)
            {
                CL_cid = clusterMap[i].clc_clusterid;
                refreshMap (NULL, NULL, FALSE);
		cl_free_clustermap(clusterMap);
                return;
            }
        }
    }

    dbprintf (10, "prevCluster: no previous cluster defined.\n");
    cl_free_clustermap(clusterMap);
    return;
}

void
nextCluster (Widget widget, XEvent *event, char **params, int *num_params)
{
    int i;
    int start, end;
    int numClusters;
    struct cl_cluster *clusterMap;

    if (cl_alloc_clustermap(&clusterMap) == -1)
    {
        dbprintf (0, "nextCluster: cl_alloc problem.\n");
	exit (-1);
    }

    numClusters = cl_getclusters (clusterMap);
    if (0 < numClusters)
    {
        for (i = 0; i < numClusters; i++)
        {
            if (CL_cid == clusterMap[i].clc_clusterid)
            {
                end = i;
                start = end == (numClusters - 1) ? 0 : (end + 1);
                break;
            }
        }
        if (i == numClusters)
        {
            end = numClusters - 1;
            start = 0;
            CL_cid = clusterMap[start].clc_clusterid;
        }

        for (i = start; end != i; i = i == (numClusters - 1) ? 0 : (i + 1))
        {
            if (CLS_UP == clusterMap[i].clc_state)
            {
                CL_cid = clusterMap[i].clc_clusterid;
                refreshMap (NULL, NULL, FALSE);
		cl_free_clustermap(clusterMap);
                return;
            }
        }
    }

    dbprintf (10, "nextCluster: no next cluster defined.\n");
    cl_free_clustermap(clusterMap);
    return;
}

void
viewNode (Widget widget, XEvent *event, char **params, int *num_params)
{
    int clstatus;

    char shellLabel[64];
    char frameLabel[64];
    char scrollLabel[64];
    char textLabel[64];
    char quitLabel[64];
    char name[64];
    char tmp[64];
    char label[64];
    int  nodeid;

    char tableBuf[64];
    char *nodename;
    char *bufp;
    int i, nbr_nodes;

    Widget nodeShell;
    Widget nodeFrame;
    Widget nodeScroll;
    Widget nodeText;
    Widget nodeQuit;
    Widget w;

    dbprintf(10, ">>>viewNode: entering viewNode()\n");

    strcpy(label, params[0]);

    getWidgetTag(label, &nodename);

    /* find the node index from the name */
    nbr_nodes = cl_getnodemap(CL_cid, pNodeMap);
    for (i = 0; i < nbr_nodes; i++)
	if (!strcmp(nodename, pNodeMap[i].cln_nodename))
	    break;

    /* if already created just popit up */
    (void) sprintf (shellLabel, "%dNode%s", CL_cid, nodename);
    nodeShell = getWidgetByLabel (shellLabel);
    if((Widget)NULL != nodeShell)
    {
        XtPopup (nodeShell, XtGrabNone);
        XtMapWidget (nodeShell);
	free (nodename);
        return;
    }

    /* format variable strings */
    (void) sprintf (name, "%s: %d, %s", progname, CL_cid, nodename);
    (void) sprintf (frameLabel, "%dframe%s", CL_cid, nodename);
    (void) sprintf (scrollLabel, "%dscroll%s", CL_cid, nodename);
    (void) sprintf (textLabel, "%dtext%s", CL_cid, nodename);
    (void) sprintf (quitLabel, "%dquit%s", CL_cid, nodename);


    /* create the data for this node */
    bufp = create_textbuf (CL_cid, i);
    if ((char *)NULL == bufp)
    {
        dbprintf(20, "viewNode: error from create_textbuf()\n");
        free (nodename);
        return;
    }

    xargc = 0;
    XtSetArg (xargv[xargc], XmNtitle, name); xargc++;
    XtSetArg (xargv[xargc], XmNiconName, name); xargc++;
    nodeShell = XtCreatePopupShell ("nodeShell", wmShellWidgetClass,
                                    getWidgetByLabel("frame"), xargv, xargc);
    putWidget (shellLabel, nodeShell);
    setWidgetTag (shellLabel, shellLabel);

    nodeFrame = XtCreateWidget ("nodeFrame", xmFormWidgetClass, nodeShell, NULL, 0);
    putWidget (frameLabel, nodeFrame);
    setWidgetTag (frameLabel, shellLabel);

    nodeScroll = XtCreateManagedWidget ("nodeScroll", xmScrolledWindowWidgetClass, nodeFrame, NULL, 0);
    putWidget (scrollLabel, nodeScroll);
    setWidgetTag (scrollLabel, shellLabel);

    nodeText = XtCreateManagedWidget ("nodeText", xmTextWidgetClass, nodeScroll, NULL, 0);
    putWidget (textLabel, nodeText);
    setWidgetTag (textLabel, shellLabel);
    XmTextSetString (nodeText, bufp);

    xargc=0;
    XtSetArg (xargv[xargc], XmNuserData, strdup(quitLabel)); xargc++;
    nodeQuit = XtCreateManagedWidget ("nodeQuit", xmLabelWidgetClass, nodeFrame, xargv, xargc);
    putWidget (quitLabel, nodeQuit);
    setWidgetTag (quitLabel, shellLabel);
    XtAddActions (quitPopupAction, XtNumber(quitPopupAction));
    (void) sprintf (tableBuf, quitPopupTable, shellLabel);
    XtAugmentTranslations (nodeQuit, XtParseTranslationTable(tableBuf));
    
    dbprintf(10, "viewNode: nodeQuit=%08X %s %s\n",nodeQuit, XtName(nodeQuit), quitLabel);

    XtAddEventHandler (nodeQuit, EnterWindowMask, FALSE, highlight, NULL);
    XtAddEventHandler (nodeQuit, LeaveWindowMask, FALSE, unHighlight, NULL);

    XtManageChild (nodeFrame);
    XtRealizeWidget (nodeShell);
    XtPopup (nodeShell, XtGrabNone);

    free (bufp);
    free (nodename);
    return;

}

void
quit (Widget widget, XEvent *event, char **params, int *num_params)
{
    freeWidgetList ();
    exit (0);
}

void
title (Widget widget, XEvent *event, char **params, int *num_params)
{
    refreshMap (NULL, NULL, FALSE);
    return;
}

void
quitPopup (Widget widget, XEvent *event, char **params, int *num_params)
{
    dbprintf(10, "quitPopup: quiting pop up widget <%s>\n", params[0]);

    XtPopdown (getWidgetByLabel (params[0]));
    while ((char *)NULL != getWidgetByTag(params[0]))
    {
      delWidgetByTag(params[0]);
    }
    return;
}

void help (Widget widget, XEvent *event, char **params, int *num_params)
{
    char name [64];
    char tableBuf[64];

    char *bufp;

    Widget helpShell;
    Widget helpFrame;
    Widget helpText;
    Widget helpScroll;
    Widget helpQuit;

    /* if already created just popit up */
    helpShell = getWidgetByLabel ("helpShell");
    if((Widget)NULL != helpShell)
    {
        XtPopup (helpShell, XtGrabNone);
        return;
    }

    bufp = create_helptext (appRes.cr_helpFile);
    if (bufp == (char *)NULL)
    {
        return;
    }

    xargc = 0;
    helpShell = XtCreatePopupShell ("helpShell", wmShellWidgetClass,
                                    getWidgetByLabel("frame"), xargv, xargc);
    putWidget ("helpShell", helpShell);

    (void) sprintf (name, "%s: help window", progname);

    xargc = 0;
    XtSetArg (xargv[xargc], XmNtitle, name); xargc++;
    XtSetArg (xargv[xargc], XmNiconName, name); xargc++;
    XtSetValues (helpShell, xargv, xargc);

    xargc = 0;
    helpFrame = XtCreateWidget ("helpFrame", xmFormWidgetClass, helpShell,
                                xargv, xargc);
    putWidget ("helpFrame", helpFrame);

    xargc = 0;
    helpScroll = XtCreateManagedWidget ("helpScroll",
                                        xmScrolledWindowWidgetClass,
                                        helpFrame, xargv, xargc);
    putWidget ("helpScroll", helpScroll);

    xargc = 0;
    helpText = XtCreateManagedWidget ("helpText", xmTextWidgetClass,
                                      helpScroll, xargv, xargc);
    putWidget ("helpText", helpText);
    XmTextSetString (helpText, bufp);

    xargc = 0;
    XtSetArg (xargv[xargc], XmNuserData, strdup("helpQuit")); xargc++;
    helpQuit = XtCreateManagedWidget ("helpQuit", xmLabelWidgetClass,
                                      helpFrame, xargv, xargc);
    putWidget ("helpQuit", helpQuit);
    XtAddActions (quitPopupAction, XtNumber(quitPopupAction));
    (void) sprintf (tableBuf, quitPopupTable, "helpShell");
    XtAugmentTranslations (helpQuit, XtParseTranslationTable(tableBuf));
    XtAddEventHandler (helpQuit, EnterWindowMask, FALSE, highlight, NULL);
    XtAddEventHandler (helpQuit, LeaveWindowMask, FALSE, unHighlight, NULL);

    XtManageChild (helpFrame);
    XtRealizeWidget (helpShell);
    XtPopup (helpShell, XtGrabNone);

    free (bufp);
    return;
}

int
clstat_init (int clusterid, char *clustername)
{
    int c;
    int counter = 0;
    int clstatus;
    FILE* fp;
    char *returnval=NULL;
    char check_main_mib[512]="grep \"^VACM_VIEW *defaultView *internet.*- *included *-\" /etc/snmpdv3.conf 2>/dev/null";
    char check_sub_mib[512]="grep \"^VACM_VIEW *defaultView *1.3.6.1.4.1.2.3.1.2.1.5 *- *included *-\" /etc/snmpdv3.conf 2>/dev/null";
    char output_array[512];
    char search_string[15]="VACM_VIEW";

    struct cl_cluster *clmap;

    clstatus = cl_initialize ();
    if (CLE_OK != clstatus)
    {
        dbprintf (0, "%s: cl_initialize (): %s\n", progname,
                  cl_errmsg(clstatus));
        return (-1);
    }

    if ((char *)NULL != clustername)
    {
        clstatus = cl_getclusterid (clustername);
        if (0 > clstatus)
        {
            dbprintf (0, "%s: cl_getclusterid(%s): %s\n", progname,
                      clustername, cl_errmsg(clstatus));
            return (-1);
        }
        CL_cid = clstatus;
    }
    else if (0 != clusterid)
    {
        if (! ISUPCLUSTER (clusterid))
        {
            dbprintf (0, "%d: Is not up or is an invalid cluster id.\n",
                      clusterid);
            return (-1);
        }
        CL_cid = clusterid;
    }
    else
    {
    	if(cl_alloc_clustermap(&clmap) == -1)
	{
            dbprintf (0, "clstat_init: cl_alloc problem.\n");
            return(-1);
	}

        clstatus = cl_getclusters (clmap);
        if (0 > clstatus)
        {
             printf(MSGSTR(CLSTAT_CHECK_CLINFO_1, "Failed retrieving cluster information.\n\n\
There are a number of possible causes:\n\
clinfoES or snmpd subsystems are not active.\n\
snmp is unresponsive.\n\
snmp is not configured correctly.\n\
Cluster services are not active on any nodes.\n\n\
Refer to the HACMP Administration Guide for more information.\n"));

            cl_free_clustermap(clmap);
#ifdef SNMP_CONF_CHECK

            output_array[0]=0;
            fp = popen(check_main_mib,"r");
            if(fp == NULL) {
                return (-1);
            }
            else {
                returnval = fgets(output_array,512,fp);
                if (returnval != NULL) {
                    /* Entry found so return */
                    pclose(fp);
                    return (-1);
                }
                    pclose(fp);
                    fp = popen(check_sub_mib,"r");
                    if(fp == NULL) {
                        return (-1);
                    }
                    else {
                        returnval = NULL;
                        output_array[0]=0;
                        returnval = fgets(output_array,512,fp);
                        if (returnval != NULL) {
                            pclose(fp);
                            return (-1);
                        }
                            dbprintf (0, "\nInternet MIB tree not enabled. Please refer the PowerHA \nreadme file for more information on how to enable it.\n");
                            pclose(fp);
                     }
             }
#endif

            return (-1);
        }

        /* set to first up, if none up set to first defined. */
        for (c = 0; CL_MAXCLUSTERS > c; c++)
        {
            if (CLS_UP == clmap[c].clc_state)
            {
                CL_cid = clmap[c].clc_clusterid;
                break;
            }

            if (0 == CL_cid && ISDEFCLUSTER(clmap[c]))
                CL_cid = clmap[c].clc_clusterid;
        }
	cl_free_clustermap(clmap);
    }

    return (0);
}

void
Usage ()
{
    fprintf(stderr, MSGSTR(CLSTAT_XUSAGE, "Usage: %s [-D debug_level] [-c Id | -n name] [-r #] [-s]\nWhere,\n"), progname);
    fprintf(stderr, MSGSTR(CLSTAT_xD_OPT, "\t-D debug_level  Debug Level.\n"));
    fprintf(stderr, MSGSTR(CLSTAT_xc_OPT, "\t-c Id       Cluster Id.\n"));
    fprintf(stderr, MSGSTR(CLSTAT_xn_OPT, "\t-n name     Cluster name.\n"));
    fprintf(stderr, MSGSTR(CLSTAT_xr_OPT, "\t-r #        Refresh interval in 10th of seconds.\n"));
    fprintf(stderr, MSGSTR(CLSTAT_xs_OPT, "\t-s          Display both up and down service labels.\n"));

    exit (0);
}

size_t mkdatestr (char *date)
{
time_t curtime;
size_t rc;

curtime = time(0);
rc = strftime(date, CL_MAXNAMELEN, nl_langinfo(D_T_FMT), 
              (struct tm *)localtime(&curtime));
return rc;
}

#define THICK 3
void
highlight (Widget widget, char *client, XEvent *event)
{
    Position x, y;
    Dimension width, height;

    char *name;

    if (EnterNotify == event->type)
    {

        xargc = 0;
        XtSetArg (xargv[xargc], XmNuserData, &name); xargc++;
        XtGetValues(widget,xargv,xargc);

        xargc = 0;
        XtSetArg (xargv[xargc], XmNwidth, &width); xargc++;
        XtSetArg (xargv[xargc], XmNheight, &height); xargc++;
        XtSetArg (xargv[xargc], XmNx, &x); xargc++;
        XtSetArg (xargv[xargc], XmNy, &y); xargc++;
        XtGetValues (getWidgetByLabel(name), xargv, xargc);

        XtConfigureWidget (getWidgetByLabel(name), x, y, width - THICK,
                           height - THICK, appRes.cr_borderWidth + THICK);

        dbprintf (20, "highlight: %s border increased by %d\n", name, THICK);

    }

    return;

}

void
unHighlight (Widget widget, char *client, XEvent *event)
{
    Position x, y;
    Dimension width, height;

    char *name;

    if (LeaveNotify == event->type)
    {

        xargc = 0;
        XtSetArg (xargv[xargc], XmNuserData, &name); xargc++;
        XtGetValues(widget,xargv,xargc);

        xargc = 0;
        XtSetArg (xargv[xargc], XmNwidth, &width); xargc++;
        XtSetArg (xargv[xargc], XmNheight, &height); xargc++;
        XtSetArg (xargv[xargc], XmNx, &x); xargc++;
        XtSetArg (xargv[xargc], XmNy, &y); xargc++;
        XtGetValues (getWidgetByLabel(name), xargv, xargc);

        XtConfigureWidget (getWidgetByLabel(name), x, y, width + THICK,
                           height + THICK, appRes.cr_borderWidth);

        dbprintf (20, "unHighlight: %s border reset to %d\n",
		  client, appRes.cr_borderWidth);
    }
    return;
}

char *
create_helptext (char *helpfile)
{
    int rcode;
    char *bufp;

    int fd;
    struct stat stbuf;

    if (-1 == stat (helpfile, &stbuf))
    {
        dbprintf (0, "create_helptext: stat: ");
        dbperror (0, helpfile);
        return (NULL);
    }

    fd = open (helpfile, O_RDONLY);
    if (-1 == fd)
    {
        dbprintf (0, "create_helptext: open: ");
        dbperror (0, helpfile);
        return (NULL);
    }

    bufp = (char*)malloc (stbuf.st_size);
    if ((char *)NULL == bufp)
    {
        dbperror (0, "create_helptext: malloc");
        return (NULL);
    }

    rcode = read (fd, bufp, stbuf.st_size);
    close (fd);
    if (stbuf.st_size != rcode)
    {
        dbprintf (0, "create_helptext: read: ");
        dbperror (0, helpfile);
        free (bufp);
        return (NULL);
    }

    return (bufp);
}

/*
 * Name:        get_catd
 *
 * Description: return catalog file desciptor for the named catalog
 *
 *
 * Arguments:   catalog name
 *
 * Return:      file descriptor handle or CATD_ERR
 *
 * Global data affectec:        none
 *
 */
static
nl_catd get_catd(char *name)
{

        nl_catd cat_id;

        if (! name || strlen (name) == 0)
                return(CATD_ERR);

        (void) setlocale(LC_ALL, "");
        cat_id = catopen(name, 0);
        return(cat_id);

}


