afsmonitor: Use NULL, rather than (struct foo *)0
[openafs.git] / src / afsmonitor / afsmonitor.c
index c0ae488..1f019a6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
 
 #include <stdio.h>
 #include <math.h>
 #include <string.h>
 #include <errno.h>
-#include <cmd.h>
+#include <afs/cmd.h>
 #include <signal.h>
 #undef IN
 #include <sys/types.h>
 #include <netinet/in.h>
-#ifndef AFS_DEC_ENV
 #include <sys/socket.h>
 #include <netdb.h>
-#endif
 #include <ctype.h>
-
-#include <gtxwindows.h>                /*Generic window package */
-#include <gtxobjects.h>                /*Object definitions */
-#if 0
-#include <gtxtextobj.h>                /*Text object interface */
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
 #endif
-#include <gtxlightobj.h>       /*Light object interface */
-#include <gtxcurseswin.h>      /*Curses window package */
-#include <gtxdumbwin.h>                /*Dumb terminal window package */
-#include <gtxX11win.h>         /*X11 window package */
-#include <gtxframe.h>          /*Frame package */
-
 
+#include <afs/gtxwindows.h>            /*Generic window package */
+#include <afs/gtxobjects.h>            /*Object definitions */
+#include <afs/gtxlightobj.h>   /*Light object interface */
+#include <afs/gtxcurseswin.h>  /*Curses window package */
+#include <afs/gtxdumbwin.h>            /*Dumb terminal window package */
+#include <afs/gtxX11win.h>             /*X11 window package */
+#include <afs/gtxframe.h>              /*Frame package */
+#include <afs/gtxinput.h>
 
 #include <afs/xstat_fs.h>
 #include <afs/xstat_cm.h>
 
-
 #include "afsmonitor.h"
 
-
 /* command line parameter indices */
 
 #define P_CONFIG       0
@@ -95,7 +88,7 @@ short cm_showFlags[NUM_CM_STAT_ENTRIES];
 #define CM 2                   /* for misc. use */
 
 
-#define        NUM_XSTAT_FS_AFS_PERFSTATS_LONGS 66     /* number of fields (longs) in struct afs_PerfStats that we display */
+#define NUM_XSTAT_FS_AFS_PERFSTATS_LONGS 70    /* number of fields from struct afs_PerfStats that we display */
 #define NUM_AFS_STATS_CMPERF_LONGS 40  /* number of longs in struct afs_stats_CMPerf excluding up/down stats and fields we dont display */
 
 
@@ -124,6 +117,12 @@ static struct afsmon_hostEntry *CMnameList;
 int numFS = 0;
 int numCM = 0;
 
+/* number of xstat collection ids */
+#define MAX_NUM_FS_COLLECTIONS 2
+#define MAX_NUM_CM_COLLECTIONS 1
+int num_fs_collections = 0;
+int num_cm_collections = 0;
+
 /* variables used for processing config file */
 /* ptr to the hostEntry structure of the last "fs" or "cm" entry processed
 in the config file */
@@ -131,7 +130,7 @@ static struct afsmon_hostEntry *last_hostEntry;
 /* names of the last host processed in the config file */
 static char last_fsHost[HOST_NAME_LEN];
 static char last_cmHost[HOST_NAME_LEN];
-static lastHostType = 0;       /* 0 = no host entries processed
+static int lastHostType = 0;   /* 0 = no host entries processed
                                 * 1 = last host was file server
                                 * 2 = last host was cache manager. */
 
@@ -139,8 +138,8 @@ static lastHostType = 0;    /* 0 = no host entries processed
 /* FILE SERVER CIRCULAR BUFFER VARIABLES  */
 
 struct afsmon_fs_Results_list {
-    struct xstat_fs_ProbeResults *fsResults;   /* ptr to results struct */
-    int empty;                 /* fsResults empty ? */
+    struct xstat_fs_ProbeResults *fsResults[MAX_NUM_FS_COLLECTIONS];
+    int empty[MAX_NUM_FS_COLLECTIONS];
     struct afsmon_fs_Results_list *next;
 };
 
@@ -149,12 +148,15 @@ struct afsmon_fs_Results_CBuffer {
     struct afsmon_fs_Results_list *list;       /* ptr to list of results */
 };
 
+int afsmon_fs_results_length[] =
+    { XSTAT_FS_FULLPERF_RESULTS_LEN, XSTAT_FS_CBSTATS_RESULTS_LEN };
+
 /* buffer for FS probe results */
 struct afsmon_fs_Results_CBuffer *afsmon_fs_ResultsCB;
 
 int afsmon_fs_curr_CBindex = 0;        /* current fs CB slot */
 
-/* Probe number variables. The current probe number is incremented 
+/* Probe number variables. The current probe number is incremented
 when the first probe from a new probe cycle is received. The prev probe
 number is incremented when the last probe of the current cycle is
 received. This difference is because of the purpose for which these
@@ -167,8 +169,8 @@ int afsmon_fs_prev_probeNum = 0;    /* previous fs probe number */
 /* CACHE MANAGER CIRCULAR BUFFER VARIABLES  */
 
 struct afsmon_cm_Results_list {
-    struct xstat_cm_ProbeResults *cmResults;   /* ptr to results struct */
-    int empty;                 /* cmResults empty ? */
+    struct xstat_cm_ProbeResults *cmResults[MAX_NUM_CM_COLLECTIONS];
+    int empty[MAX_NUM_CM_COLLECTIONS];
     struct afsmon_cm_Results_list *next;
 };
 
@@ -177,13 +179,15 @@ struct afsmon_cm_Results_CBuffer {
     struct afsmon_cm_Results_list *list;       /* ptr to list of results */
 };
 
+int afsmon_cm_results_length[] = { XSTAT_CM_FULLPERF_RESULTS_LEN };
+
 /* buffer for CM probe results */
 struct afsmon_cm_Results_CBuffer *afsmon_cm_ResultsCB;
 
 int afsmon_cm_curr_CBindex = 0;        /* current cm CB slot */
 
 
-/* Probe number variables. The current probe number is incremented 
+/* Probe number variables. The current probe number is incremented
 when the first probe from a new probe cycle is received. The prev probe
 number is incremented when the last probe of the current cycle is
 received. This difference is because of the purpose for which these
@@ -208,17 +212,8 @@ struct cm_Display_Data *curr_cmData = (struct cm_Display_Data *)0;
        /* for previous probe cycle */
 struct cm_Display_Data *prev_cmData = (struct cm_Display_Data *)0;
 
-
 /* EXTERN DEFINITIONS */
 
-extern struct hostent *hostutil_GetHostByName();
-
-
-
-/* routines from afsmon-output.c */
-extern int afsmon_fsOutput();
-extern int afsmon_cmOutput();
-
 /* file server and cache manager variable names (from afsmon_labels.h) */
 extern char *fs_varNames[];
 extern char *cm_varNames[];
@@ -239,10 +234,10 @@ int numHosts_onfs_alerts;
 int num_cm_alerts;
 int numHosts_oncm_alerts;
 
-/* flag to indicate that atleast one probe cycle has completed and 
+/* flag to indicate that atleast one probe cycle has completed and
 data is available for updating the display */
-extern fs_Data_Available;
-extern cm_Data_Available;
+extern int fs_Data_Available;
+extern int cm_Data_Available;
 
 extern int gtx_initialized;    /* gtx initialized ? */
 
@@ -251,16 +246,16 @@ are to be displayed on the File Servers screen. For example, suppose the
 user wishes to display only the vcache statistics then the following array
 will contain indices 2 to 14 corresponding to the position of the
 vcache data items in the fs_varNames[] array. If the config file contains
-no "show fs .." directives, it will contain the indices of all the 
+no "show fs .." directives, it will contain the indices of all the
 items in the fs_varNames[] array */
 
-short fs_Display_map[XSTAT_FS_FULLPERF_RESULTS_LEN];
+short fs_Display_map[NUM_FS_STAT_ENTRIES];
 int fs_DisplayItems_count = 0; /* number of items to display */
 int fs_showDefault = 1;                /* show all of FS data ? */
 
 
 /* same use as above for Cache Managers  */
-short cm_Display_map[XSTAT_CM_FULLPERF_RESULTS_LEN];
+short cm_Display_map[NUM_CM_STAT_ENTRIES];
 int cm_DisplayItems_count = 0; /* number of items to display */
 int cm_showDefault = 1;                /* show all of CM data ? */
 
@@ -270,20 +265,26 @@ extern int fs_curr_LCol;  /* current leftmost column on display on FS frame */
 extern int cm_currPage;                /* current page number in the Cache Managers frame */
 extern int cm_curr_LCol;       /* current leftmost column on display on CM frame */
 
-/* File server and Cache manager data is classified into sections & 
+/* File server and Cache manager data is classified into sections &
 groups to help the user choose what he wants displayed */
 extern char *fs_categories[];  /* file server data category names */
 extern char *cm_categories[];  /* cache manager data category names */
 
 
+static int fs_FullPerfs_ltoa(struct fs_Display_Data *a_fsData,
+                            struct xstat_fs_ProbeResults *a_fsResults);
+static int fs_CallBackStats_ltoa(struct fs_Display_Data *a_fsData,
+                                struct xstat_fs_ProbeResults *a_fsResults);
 
-#if !defined(AFS_FBSD_ENV) && !defined(AFS_DARWIN70_ENV)
-/*     
-        strcasestr(): Return first occurence of pattern s2 in s1, case 
-       insensitive. 
+#ifdef HAVE_STRCASESTR
+extern char * strcasestr(const char *, const char *);
+#else
+/*
+        strcasestr(): Return first occurence of pattern s2 in s1, case
+       insensitive.
 
        This routine is required since I made pattern matching of the
-       config file to be case insensitive. 
+       config file to be case insensitive.
 */
 
 char *
@@ -298,7 +299,7 @@ strcasestr(s1, s2)
     len2 = strlen(s2);
 
     if (len1 < len2)
-       return ((char *)NULL);
+       return (NULL);
 
     ptr = s1;
 
@@ -308,13 +309,12 @@ strcasestr(s1, s2)
        ptr++;
        len1--;
     }
-    return ((char *)NULL);
+    return (NULL);
 }
 #endif
 
 struct hostent *
-GetHostByName(name)
-     char *name;
+GetHostByName(char *name)
 {
     struct hostent *he;
 #ifdef AFS_SUN5_ENV
@@ -338,22 +338,21 @@ GetHostByName(name)
  *
  * Description
  *     Exit gracefully from the afsmonitor. Frees memory where appropriate,
- *     cleans up after gtx and closes all open file descriptors. If a user 
+ *     cleans up after gtx and closes all open file descriptors. If a user
  *     provided threshold handler is to be exec'ed then gtx cleanup is
- *     not performed and an exec() is made instead of an exit(). 
+ *     not performed and an exec() is made instead of an exit().
  *
  * Returns
  *     Nothing.
  *
- * Comments 
- *     This function is called to execute a user handler only 
+ * Comments
+ *     This function is called to execute a user handler only
  *     by a child process.
- * 
+ *
  *----------------------------------------------------------------------*/
 
 int
-afsmon_Exit(a_exitVal)
-     int a_exitVal;            /* exit code */
+afsmon_Exit(int a_exitVal)     /* exit code */
 {                              /* afsmon_Exit */
     static char rn[] = "afsmon_Exit";
     struct afsmon_fs_Results_list *tmp_fslist;
@@ -363,7 +362,7 @@ afsmon_Exit(a_exitVal)
     struct afsmon_cm_Results_list *next_cmlist;
     struct xstat_cm_ProbeResults *tmp_xstat_cmPR;
     struct afsmon_hostEntry *curr_hostEntry;
-    struct afsmon_hostEntry *prev_hostEntry;
+    struct afsmon_hostEntry *next_hostEntry;
     int i;
     int j;
     int bufslot;
@@ -409,15 +408,17 @@ afsmon_Exit(a_exitVal)
                        break;
                    }
                    next_fslist = tmp_fslist->next;
-                   tmp_xstat_fsPR = tmp_fslist->fsResults;
+                   for (i = 0; i < MAX_NUM_FS_COLLECTIONS; i++) {
+                       tmp_xstat_fsPR = tmp_fslist->fsResults[i];
 
-                   if (afsmon_debug)
-                       fprintf(debugFD, "%d ", numFS - j);
+                       if (afsmon_debug)
+                           fprintf(debugFD, "%d ", numFS - j);
 
-                   /* free xstat_fs_Results data */
-                   free(tmp_xstat_fsPR->data.AFS_CollData_val);
-                   free(tmp_xstat_fsPR->connP);
-                   free(tmp_xstat_fsPR);
+                       /* free xstat_fs_Results data */
+                       free(tmp_xstat_fsPR->data.AFS_CollData_val);
+                       free(tmp_xstat_fsPR->connP);
+                       free(tmp_xstat_fsPR);
+                   }
 
                    /* free the fs list item */
                    free(tmp_fslist);
@@ -453,17 +454,19 @@ afsmon_Exit(a_exitVal)
                        break;
                    }
                    next_cmlist = tmp_cmlist->next;
-                   tmp_xstat_cmPR = tmp_cmlist->cmResults;
+                   for (i = 0; i < MAX_NUM_CM_COLLECTIONS; i++) {
+                       tmp_xstat_cmPR = tmp_cmlist->cmResults[i];
 
-                   if (afsmon_debug)
-                       fprintf(debugFD, "%d ", numCM - j);
-                   /* make sure data is ok */
-                   /* Print_cm_FullPerfInfo(tmp_xstat_cmPR); */
+                       if (afsmon_debug)
+                           fprintf(debugFD, "%d ", numCM - j);
+                       /* make sure data is ok */
+                       /* Print_cm_FullPerfInfo(tmp_xstat_cmPR); */
 
-                   /* free xstat_cm_Results data */
-                   free(tmp_xstat_cmPR->data.AFSCB_CollData_val);
-                   free(tmp_xstat_cmPR->connP);
-                   free(tmp_xstat_cmPR);
+                       /* free xstat_cm_Results data */
+                       free(tmp_xstat_cmPR->data.AFSCB_CollData_val);
+                       free(tmp_xstat_cmPR->connP);
+                   }
+                   free(tmp_cmlist->cmResults);
 
                    /* free the cm list item */
                    free(tmp_cmlist);
@@ -478,22 +481,22 @@ afsmon_Exit(a_exitVal)
 
 
     /* deallocate FS & CM Print buffers */
-    if (curr_fsData != (struct fs_Display_Data *)0) {
+    if (curr_fsData != NULL) {
        if (afsmon_debug)
            fprintf(debugFD, "Deallocating FS Print Buffers .... curr");
        free(curr_fsData);
     }
-    if (prev_fsData != (struct fs_Display_Data *)0) {
+    if (prev_fsData != NULL) {
        if (afsmon_debug)
            fprintf(debugFD, ", prev \n");
        free(prev_fsData);
     }
-    if (prev_cmData != (struct cm_Display_Data *)0) {
+    if (curr_cmData != NULL) {
        if (afsmon_debug)
            fprintf(debugFD, "Deallocating CM Print Buffers .... curr");
        free(curr_cmData);
     }
-    if (prev_cmData != (struct cm_Display_Data *)0) {
+    if (prev_cmData != NULL) {
        if (afsmon_debug)
            fprintf(debugFD, ", prev \n");
        free(prev_cmData);
@@ -504,14 +507,12 @@ afsmon_Exit(a_exitVal)
        if (afsmon_debug)
            fprintf(debugFD, "Deallocating FS hostEntries ..");
        curr_hostEntry = FSnameList;
-       for (i = 0; i < numFS; i++) {
-           prev_hostEntry = curr_hostEntry;
+       while (curr_hostEntry) {
+           next_hostEntry = curr_hostEntry->next;
            if (curr_hostEntry->thresh != NULL)
                free(curr_hostEntry->thresh);
            free(curr_hostEntry);
-           if (afsmon_debug)
-               fprintf(debugFD, " %d", i);
-           curr_hostEntry = prev_hostEntry->next;
+           curr_hostEntry = next_hostEntry;
        }
        if (afsmon_debug)
            fprintf(debugFD, "\n");
@@ -520,14 +521,12 @@ afsmon_Exit(a_exitVal)
        if (afsmon_debug)
            fprintf(debugFD, "Deallocating CM hostEntries ..");
        curr_hostEntry = CMnameList;
-       for (i = 0; i < numCM; i++) {
-           prev_hostEntry = curr_hostEntry;
+       while (curr_hostEntry) {
+           next_hostEntry = curr_hostEntry->next;
            if (curr_hostEntry->thresh != NULL)
                free(curr_hostEntry->thresh);
            free(curr_hostEntry);
-           if (afsmon_debug)
-               fprintf(debugFD, " %d", i);
-           curr_hostEntry = prev_hostEntry->next;
+           curr_hostEntry = next_hostEntry;
        }
        if (afsmon_debug)
            fprintf(debugFD, "\n");
@@ -563,17 +562,14 @@ afsmon_Exit(a_exitVal)
  *----------------------------------------------------------------------*/
 
 int
-insert_FS(a_hostName)
-     char *a_hostName;         /* name of cache manager to be inserted in list */
+insert_FS(char *a_hostName)            /* name of cache manager to be inserted in list */
 {                              /* insert_FS() */
-    static char rn[] = "insert_FS";    /* routine name */
     static struct afsmon_hostEntry *curr_item;
     static struct afsmon_hostEntry *prev_item;
 
     if (*a_hostName == '\0')
        return (-1);
-    curr_item = (struct afsmon_hostEntry *)
-       malloc(sizeof(struct afsmon_hostEntry));
+    curr_item = malloc(sizeof(struct afsmon_hostEntry));
     if (curr_item == (struct afsmon_hostEntry *)0) {
        fprintf(stderr, "Failed to allocate space for FS nameList\n");
        return (-1);
@@ -608,7 +604,7 @@ insert_FS(a_hostName)
  *     Nothing.
  *----------------------------------------------------------------------*/
 void
-print_FS()
+print_FS(void)
 {                              /* print_FS() */
     static char rn[] = "print_FS";
     struct afsmon_hostEntry *tempFS;
@@ -652,17 +648,14 @@ print_FS()
  *----------------------------------------------------------------------*/
 
 int
-insert_CM(a_hostName)
-     char *a_hostName;         /* name of cache manager to be inserted in list */
+insert_CM(char *a_hostName)            /* name of cache manager to be inserted in list */
 {                              /* insert_CM */
-    static char rn[] = "insert_CM";    /* routine name */
     static struct afsmon_hostEntry *curr_item;
     static struct afsmon_hostEntry *prev_item;
 
     if (*a_hostName == '\0')
        return (-1);
-    curr_item = (struct afsmon_hostEntry *)
-       malloc(sizeof(struct afsmon_hostEntry));
+    curr_item = malloc(sizeof(struct afsmon_hostEntry));
     if (curr_item == (struct afsmon_hostEntry *)0) {
        fprintf(stderr, "Failed to allocate space for CM nameList\n");
        return (-1);
@@ -698,7 +691,7 @@ insert_CM(a_hostName)
  *     Nothing.
  *----------------------------------------------------------------------*/
 int
-print_CM()
+print_CM(void)
 {                              /* print_CM() */
     static char rn[] = "print_CM";
     struct afsmon_hostEntry *tempCM;
@@ -750,8 +743,7 @@ print_CM()
  *----------------------------------------------------------------------*/
 
 int
-parse_hostEntry(a_line)
-     char *a_line;
+parse_hostEntry(char *a_line)
 {                              /* parse_hostEntry */
 
     static char rn[] = "parse_hostEntry";      /* routine name */
@@ -816,7 +808,7 @@ parse_hostEntry(a_line)
  *
  * Description
  *     Parse the threshold entry line in the config file. This function is
- *     called in the the first pass of the config file. It checks the syntax 
+ *     called in the the first pass of the config file. It checks the syntax
  *     of the config lines and verifies their positional validity - eg.,
  *     a cm threshold cannot appear after a fs hostname entry, etc.
  *     It also counts the thresholds applicable to each host.
@@ -828,8 +820,7 @@ parse_hostEntry(a_line)
  *----------------------------------------------------------------------*/
 
 int
-parse_threshEntry(a_line)
-     char *a_line;
+parse_threshEntry(char *a_line)
 {                              /* parse_threshEntry */
     static char rn[] = "parse_threshEntry";    /* routine name */
     char opcode[CFG_STR_LEN];  /* specifies type of config entry */
@@ -920,7 +911,7 @@ parse_threshEntry(a_line)
  *     for cache managers. For global thresholds the info is recorded for
  *     all the hosts. This function is called in the second pass of the
  *     config file. In the first pass a count of the number of global
- *     thresholds is determined and this information is used in this 
+ *     thresholds is determined and this information is used in this
  *     routine. If threshold entries are duplicated the first entry is
  *     overwritten.
  *     Each threshold entry also has an index field. This is a positional
@@ -933,12 +924,10 @@ parse_threshEntry(a_line)
  *----------------------------------------------------------------------*/
 
 int
-store_threshold(a_type, a_varName, a_value, a_handler)
-     int a_type;               /* 1 = fs , 2 = cm */
-     char *a_varName;          /* threshold name */
-     char *a_value;            /* threshold value */
-     char *a_handler;          /* threshold overflow handler */
-
+store_threshold(int a_type,            /* 1 = fs , 2 = cm */
+               char *a_varName,        /* threshold name */
+               char *a_value,          /* threshold value */
+               char *a_handler)        /* threshold overflow handler */
 {                              /* store_thresholds */
 
     static char rn[] = "store_thresholds";     /* routine name */
@@ -1101,9 +1090,9 @@ store_threshold(a_type, a_varName, a_value, a_handler)
  *     This data is mapped to the screen thru fs_Display_map[] and
  *     cm_Display_map[]. This routine parses the "show" entry against the
  *     section/group names in the [fs/cm]_categories[] array. If there is
- *     no match it tries to match it against a variable name in 
+ *     no match it tries to match it against a variable name in
  *     [fs/cm]_varNames[] array. In each case the corresponding indices to
- *     the data is the [fs/cm]_displayInfo[] is recorded. 
+ *     the data is the [fs/cm]_displayInfo[] is recorded.
  *
  * Returns:
  *     Success: 0
@@ -1112,8 +1101,7 @@ store_threshold(a_type, a_varName, a_value, a_handler)
  *----------------------------------------------------------------------*/
 
 int
-parse_showEntry(a_line)
-     char *a_line;
+parse_showEntry(char *a_line)
 {                              /* parse_showEntry */
     static char rn[] = "parse_showEntry";
     char opcode[CFG_STR_LEN];  /* specifies type of config entry */
@@ -1170,8 +1158,8 @@ parse_showEntry(a_line)
        /* if it is a section/group name, find it in the fs_categories[] array */
 
        found = 0;
-       if (strcasestr(arg2, "_section") != (char *)NULL
-           || strcasestr(arg2, "_group") != (char *)NULL) {
+       if (strcasestr(arg2, "_section") != NULL
+           || strcasestr(arg2, "_group") != NULL) {
            idx = 0;
            while (idx < FS_NUM_DATA_CATEGORIES) {
                sscanf(fs_categories[idx], "%s %d %d", catName, &fromIdx,
@@ -1194,7 +1182,7 @@ parse_showEntry(a_line)
        /* if it is a group name, read its start/end indices and fill in the
         * fs_Display_map[]. */
 
-       if (strcasestr(arg2, "_group") != (char *)NULL) {
+       if (strcasestr(arg2, "_group") != NULL) {
 
            if (fromIdx < 0 || toIdx < 0 || fromIdx > NUM_FS_STAT_ENTRIES
                || toIdx > NUM_FS_STAT_ENTRIES)
@@ -1214,7 +1202,7 @@ parse_showEntry(a_line)
            /* if it is a section name, get the count of number of groups in it and
             * for each group fill in the start/end indices in the fs_Display_map[] */
 
-       if (strcasestr(arg2, "_section") != (char *)NULL) {
+       if (strcasestr(arg2, "_section") != NULL) {
            /* fromIdx is actually the number of groups in thi section */
            numGroups = fromIdx;
            /* for each group in section */
@@ -1285,8 +1273,8 @@ parse_showEntry(a_line)
        /* if it is a section/group name, find it in the cm_categories[] array */
 
        found = 0;
-       if (strcasestr(arg2, "_section") != (char *)NULL
-           || strcasestr(arg2, "_group") != (char *)NULL) {
+       if (strcasestr(arg2, "_section") != NULL
+           || strcasestr(arg2, "_group") != NULL) {
            idx = 0;
            while (idx < CM_NUM_DATA_CATEGORIES) {
                sscanf(cm_categories[idx], "%s %d %d", catName, &fromIdx,
@@ -1309,7 +1297,7 @@ parse_showEntry(a_line)
        /* if it is a group name, read its start/end indices and fill in the
         * cm_Display_map[]. */
 
-       if (strcasestr(arg2, "_group") != (char *)NULL) {
+       if (strcasestr(arg2, "_group") != NULL) {
 
            if (fromIdx < 0 || toIdx < 0 || fromIdx > NUM_CM_STAT_ENTRIES
                || toIdx > NUM_CM_STAT_ENTRIES)
@@ -1329,7 +1317,7 @@ parse_showEntry(a_line)
            /* if it is a section name, get the count of number of groups in it and
             * for each group fill in the start/end indices in the cm_Display_map[] */
 
-       if (strcasestr(arg2, "_section") != (char *)NULL) {
+       if (strcasestr(arg2, "_section") != NULL) {
            /* fromIdx is actually the number of groups in thi section */
            numGroups = fromIdx;
            /* for each group in section */
@@ -1362,12 +1350,6 @@ parse_showEntry(a_line)
                idx++;
                numGroups--;
            }                   /* for each group in section */
-
-
-
-
-
-
        } else {                /* it is a variable name */
 
            for (i = 0; i < NUM_CM_STAT_ENTRIES; i++) {
@@ -1395,8 +1377,6 @@ parse_showEntry(a_line)
     }
     /* it is an cm entry */
     return (0);
-
-
 }                              /* parse_showEntry */
 
 
@@ -1404,15 +1384,15 @@ parse_showEntry(a_line)
  * process_config_file()
  *
  * Description:
- *     Parse config file entries in two passes. In the first pass: 
+ *     Parse config file entries in two passes. In the first pass:
  *             - the syntax of all the entries is checked
- *             - host names are noted and the FSnamesList and CMnamesList 
- *               constructed. 
- *             - a count of the global thresholds and local thresholds of 
- *               each host are counted. 
+ *             - host names are noted and the FSnamesList and CMnamesList
+ *               constructed.
+ *             - a count of the global thresholds and local thresholds of
+ *               each host are counted.
  *             - "show" entries are processed.
  *     In the second pass:
- *             - thresholds are stored 
+ *             - thresholds are stored
  *
  * Returns:
  *     Success: 0
@@ -1420,8 +1400,7 @@ parse_showEntry(a_line)
  *----------------------------------------------------------------------*/
 
 int
-process_config_file(a_config_filename)
-     char *a_config_filename;
+process_config_file(char *a_config_filename)
 {                              /* process_config_file() */
     static char rn[] = "process_config_file";  /* routine name */
     FILE *configFD;            /* config file descriptor */
@@ -1436,7 +1415,6 @@ process_config_file(a_config_filename)
     char *handlerPtr;          /* ptr to pass theresh handler string */
     int code = 0;              /* error code */
     int linenum = 0;           /* config file line number */
-    int threshCount;           /* count of thresholds for each server */
     int error_in_config;       /* syntax errors in config file  ?? */
     int i;
     int numBytes;
@@ -1472,7 +1450,6 @@ process_config_file(a_config_filename)
 
     numFS = 0;
     numCM = 0;
-    threshCount = 0;
     error_in_config = 0;       /* flag to note if config file has syntax errors */
 
     while ((fgets(line, CFG_STR_LEN, configFD)) != NULL) {
@@ -1518,7 +1495,7 @@ process_config_file(a_config_filename)
     }
 
     /* the threshold count of all hosts in increased by 1 for each global
-     * threshold. If one of the hosts has a local threshold for the same 
+     * threshold. If one of the hosts has a local threshold for the same
      * variable it would end up being counted twice. whats a few bytes of memory
      * wasted anyway ? */
 
@@ -1560,7 +1537,7 @@ process_config_file(a_config_filename)
        }
        if (curr_host->numThresh) {
            numBytes = curr_host->numThresh * sizeof(struct Threshold);
-           curr_host->thresh = (struct Threshold *)malloc(numBytes);
+           curr_host->thresh = malloc(numBytes);
            if (curr_host->thresh == NULL) {
                fprintf(stderr, "[ %s ] Memory Allocation error 1", rn);
                afsmon_Exit(25);
@@ -1578,7 +1555,7 @@ process_config_file(a_config_filename)
        }
        if (curr_host->numThresh) {
            numBytes = curr_host->numThresh * sizeof(struct Threshold);
-           curr_host->thresh = (struct Threshold *)malloc(numBytes);
+           curr_host->thresh = malloc(numBytes);
            if (curr_host->thresh == NULL) {
                fprintf(stderr, "[ %s ] Memory Allocation error 2", rn);
                afsmon_Exit(35);
@@ -1615,7 +1592,7 @@ process_config_file(a_config_filename)
            strncpy(last_cmHost, he->h_name, HOST_NAME_LEN);
        } else if (strcasecmp(opcode, "thresh") == 0) {
            /* if we have a threshold handler it may have arguments
-            * and the sscanf() above would not get them, so do the 
+            * and the sscanf() above would not get them, so do the
             * following */
            if (strlen(arg4)) {
                handlerPtr = line;
@@ -1673,12 +1650,13 @@ process_config_file(a_config_filename)
  *----------------------------------------------------------------------*/
 
 void
-Print_FS_CB()
+Print_FS_CB(void)
 {                              /* Print_FS_CB() */
 
     struct afsmon_fs_Results_list *fslist;
     int i;
     int j;
+    int k;
 
     /* print valid info in the fs CB */
 
@@ -1695,16 +1673,20 @@ Print_FS_CB()
            fslist = afsmon_fs_ResultsCB[i].list;
            j = 0;
            while (j < numFS) {
-               if (!fslist->empty) {
-                   fprintf(debugFD, "\t %d) probeNum = %d host = %s", j,
-                           fslist->fsResults->probeNum,
-                           fslist->fsResults->connP->hostName);
-                   if (fslist->fsResults->probeOK)
-                       fprintf(debugFD, " NOTOK\n");
-                   else
-                       fprintf(debugFD, " OK\n");
-               } else
-                   fprintf(debugFD, "\t %d) -- empty --\n", j);
+               for (k = 0; k < MAX_NUM_FS_COLLECTIONS; k++) {
+                   if (!(fslist->empty[k])) {
+                       fprintf(debugFD, "\t %d) probeNum = %d host = %s cn = %d",
+                               j,
+                               fslist->fsResults[k]->probeNum,
+                               fslist->fsResults[k]->connP->hostName,
+                               fslist->fsResults[k]->collectionNumber);
+                       if (fslist->fsResults[k]->probeOK)
+                           fprintf(debugFD, " NOTOK\n");
+                       else
+                           fprintf(debugFD, " OK\n");
+                   } else
+                       fprintf(debugFD, "\t %d) -- empty --\n", j);
+               }
                fslist = fslist->next;
                j++;
            }
@@ -1731,14 +1713,13 @@ Print_FS_CB()
  *     Failure: Exits afsmonitor.
  *----------------------------------------------------------------------*/
 int
-save_FS_results_inCB(a_newProbeCycle)
-     int a_newProbeCycle;      /* start of a new probe cycle ? */
-
+save_FS_results_inCB(int a_newProbeCycle)      /* start of a new probe cycle ? */
 {                              /* save_FS_results_inCB() */
     static char rn[] = "save_FS_results_inCB"; /* routine name */
     struct afsmon_fs_Results_list *tmp_fslist_item;    /* temp fs list item */
     struct xstat_fs_ProbeResults *tmp_fsPR;    /* temp ptr */
     int i;
+    int index;
 
     if (afsmon_debug) {
        fprintf(debugFD, "[ %s ] Called, a_newProbeCycle= %d\n", rn,
@@ -1746,6 +1727,18 @@ save_FS_results_inCB(a_newProbeCycle)
        fflush(debugFD);
     }
 
+    switch (xstat_fs_Results.collectionNumber) {
+    case AFS_XSTATSCOLL_FULL_PERF_INFO:
+       index = 0;
+       break;
+    case AFS_XSTATSCOLL_CBSTATS:
+       index = 1;
+       break;
+    default:
+       fprintf(stderr, "[ %s ] collection number %d is out of range.\n",
+               rn, xstat_fs_Results.collectionNumber);
+       afsmon_Exit(51);
+    }
 
     /* If a new probe cycle started, mark the list in the current buffer
      * slot empty for resuse. Note that afsmon_fs_curr_CBindex was appropriately
@@ -1754,7 +1747,7 @@ save_FS_results_inCB(a_newProbeCycle)
     if (a_newProbeCycle) {
        tmp_fslist_item = afsmon_fs_ResultsCB[afsmon_fs_curr_CBindex].list;
        for (i = 0; i < numFS; i++) {
-           tmp_fslist_item->empty = 1;
+           tmp_fslist_item->empty[index] = 1;
            tmp_fslist_item = tmp_fslist_item->next;
        }
     }
@@ -1762,13 +1755,13 @@ save_FS_results_inCB(a_newProbeCycle)
     /* locate last unused item in list */
     tmp_fslist_item = afsmon_fs_ResultsCB[afsmon_fs_curr_CBindex].list;
     for (i = 0; i < numFS; i++) {
-       if (tmp_fslist_item->empty)
+       if (tmp_fslist_item->empty[index])
            break;
        tmp_fslist_item = tmp_fslist_item->next;
     }
 
     /* if we could not find one we have an inconsistent list */
-    if (!tmp_fslist_item->empty) {
+    if (!tmp_fslist_item->empty[index]) {
        fprintf(stderr,
                "[ %s ] list inconsistency 1. unable to find an empty slot to store results of probenum %d of %s\n",
                rn, xstat_fs_Results.probeNum,
@@ -1776,7 +1769,7 @@ save_FS_results_inCB(a_newProbeCycle)
        afsmon_Exit(50);
     }
 
-    tmp_fsPR = tmp_fslist_item->fsResults;
+    tmp_fsPR = tmp_fslist_item->fsResults[index];
 
     /* copy hostname and probe number and probe time and probe status.
      * if the probe failed return now */
@@ -1788,7 +1781,7 @@ save_FS_results_inCB(a_newProbeCycle)
     tmp_fsPR->probeOK = xstat_fs_Results.probeOK;
     if (xstat_fs_Results.probeOK) {    /* probeOK = 1 => notOK */
        /* we have a nonempty results structure so mark the list item used */
-       tmp_fslist_item->empty = 0;
+       tmp_fslist_item->empty[index] = 0;
        return (0);
     }
 
@@ -1801,14 +1794,16 @@ save_FS_results_inCB(a_newProbeCycle)
     tmp_fsPR->collectionNumber = xstat_fs_Results.collectionNumber;
 
     /* copy the probe data information */
-    tmp_fsPR->data.AFS_CollData_len = xstat_fs_Results.data.AFS_CollData_len;
+    tmp_fsPR->data.AFS_CollData_len =
+       min(xstat_fs_Results.data.AFS_CollData_len,
+           afsmon_fs_results_length[index]);
     memcpy(tmp_fsPR->data.AFS_CollData_val,
           xstat_fs_Results.data.AFS_CollData_val,
-          xstat_fs_Results.data.AFS_CollData_len * sizeof(afs_int32));
+          tmp_fsPR->data.AFS_CollData_len * sizeof(afs_int32));
 
 
     /* we have a valid results structure so mark the list item used */
-    tmp_fslist_item->empty = 0;
+    tmp_fslist_item->empty[index] = 0;
 
     /* Print the fs circular buffer */
     Print_FS_CB();
@@ -1821,10 +1816,10 @@ save_FS_results_inCB(a_newProbeCycle)
  * fs_Results_ltoa()
  *
  * Description:
- *     The results of xstat probes are stored in a string format in 
+ *     The results of xstat probes are stored in a string format in
  *     the arrays curr_fsData and prev_fsData. The information stored in
- *     prev_fsData is copied to the screen. 
- *     This function converts xstat FS results from longs to strings and 
+ *     prev_fsData is copied to the screen.
+ *     This function converts xstat FS results from longs to strings and
  *     place them in the given buffer (a pointer to an item in curr_fsData).
  *     When a probe cycle completes, curr_fsData is copied to prev_fsData
  *     in afsmon_FS_Hnadler().
@@ -1834,32 +1829,73 @@ save_FS_results_inCB(a_newProbeCycle)
  *----------------------------------------------------------------------*/
 
 int
-fs_Results_ltoa(a_fsData, a_fsResults)
-     struct fs_Display_Data *a_fsData; /* target buffer */
-     struct xstat_fs_ProbeResults *a_fsResults;        /* ptr to xstat fs Results */
+fs_Results_ltoa(struct fs_Display_Data *a_fsData,      /* target buffer */
+               struct xstat_fs_ProbeResults *a_fsResults)      /* ptr to xstat fs Results */
 {                              /* fs_Results_ltoa */
 
     static char rn[] = "fs_Results_ltoa";      /* routine name */
-    afs_int32 *srcbuf;
-    struct fs_stats_FullPerfStats *fullPerfP;
-    int idx;
-    int i, j;
-    afs_int32 *tmpbuf;
 
     if (afsmon_debug) {
-       fprintf(debugFD, "[ %s ] Called, a_fsData= %d, a_fsResults= %d\n", rn,
+       fprintf(debugFD, "[ %s ] Called, a_fsData= %p, a_fsResults= %p\n", rn,
                a_fsData, a_fsResults);
        fflush(debugFD);
     }
 
-    fullPerfP = (struct fs_stats_FullPerfStats *)
-       (a_fsResults->data.AFS_CollData_val);
+    switch (a_fsResults->collectionNumber) {
+    case AFS_XSTATSCOLL_FULL_PERF_INFO:
+       fs_FullPerfs_ltoa(a_fsData, a_fsResults);
+       break;
+    case AFS_XSTATSCOLL_CBSTATS:
+       fs_CallBackStats_ltoa(a_fsData, a_fsResults);
+       break;
+    default:
+       if (afsmon_debug) {
+           fprintf(debugFD, "[ %s ] Unexpected collection id %d\n",
+                   rn, a_fsResults->collectionNumber);
+       }
+    }
+
+    return (0);
+}                              /* fs_Results_ltoa */
 
-    /* there are two parts to the xstat FS statistics 
+/*-----------------------------------------------------------------------
+ * fs_FullPerfs_ltoa()
+ *
+ * Description:
+ *     Convert the full perf xstat collection from int32s to strings.
+ *
+ * Returns:
+ *     Always returns 0.
+ *----------------------------------------------------------------------*/
+static int
+fs_FullPerfs_ltoa(struct fs_Display_Data *a_fsData,
+               struct xstat_fs_ProbeResults *a_fsResults)
+{
+    afs_int32 *srcbuf;
+    struct fs_stats_FullPerfStats *fullPerfP;
+    struct fs_stats_FullPerfStats buffer;
+    int idx;
+    int i, j;
+    afs_int32 *tmpbuf;
+    int code;
+
+    /* there are two parts to the xstat FS statistics
      * - fullPerfP->overall which give the overall performance statistics, and
      * - fullPerfP->det which gives detailed info about file server operation
      * execution times */
 
+    code = xstat_fs_DecodeFullPerfStats(&fullPerfP,
+                                       a_fsResults->data.AFS_CollData_val,
+                                       a_fsResults->data.AFS_CollData_len,
+                                       &buffer);
+    if (code) {
+       /* Not able to decode the full perf stats. Avoid displaying garbage. */
+       for (i = 0; i < NUM_FS_STAT_ENTRIES; i++) {
+           sprintf(a_fsData->data[i], "%s", "--");
+       }
+       return 0;
+    }
+
     /* copy overall performance statistics */
     srcbuf = (afs_int32 *) & (fullPerfP->overall);
     idx = 0;
@@ -1946,18 +1982,44 @@ fs_Results_ltoa(a_fsData, a_fsResults)
     }
 
     return (0);
-}                              /* fs_Results_ltoa */
+}
+
+/*-----------------------------------------------------------------------
+ * fs_CallBackStats_ltoa()
+ *
+ * Description:
+ *     Convert the callback counter xstat collection from
+ *     int32s to strings.
+ *
+ * Returns:
+ *     Always returns 0.
+ *----------------------------------------------------------------------*/
 
+static int
+fs_CallBackStats_ltoa(struct fs_Display_Data *a_fsData,
+                     struct xstat_fs_ProbeResults *a_fsResults)
+{
+    int idx;
+    int i;
+    int len = a_fsResults->data.AFS_CollData_len;
+    afs_int32 *val = a_fsResults->data.AFS_CollData_val;
 
+    /* place callback stats after the full perf stats */
+    idx = NUM_FS_FULLPERF_ENTRIES;
+    for (i=0; i < len && i < NUM_FS_CB_ENTRIES; i++) {
+       sprintf(a_fsData->data[idx++], "%u", val[i]);
+    }
+    return 0;
+}
 
 /*-----------------------------------------------------------------------
  * execute_thresh_handler()
  *
  * Description:
- *     Execute a threshold handler. An agrv[] array of pointers is 
- *     constructed from the given data. A child process is forked 
+ *     Execute a threshold handler. An agrv[] array of pointers is
+ *     constructed from the given data. A child process is forked
  *     which immediately calls afsmon_Exit() with indication that a
- *     threshold handler is to be exec'ed insted of exiting. 
+ *     threshold handler is to be exec'ed insted of exiting.
  *
  * Returns:
  *     Success: 0
@@ -1965,22 +2027,18 @@ fs_Results_ltoa(a_fsData, a_fsResults)
  *----------------------------------------------------------------------*/
 
 int
-execute_thresh_handler(a_handler, a_hostName, a_hostType, a_threshName,
-                      a_threshValue, a_actValue)
-     char *a_handler;          /* ptr to handler function + args */
-     char *a_hostName;         /* host name for which threshold crossed */
-     int a_hostType;           /* fs or cm ? */
-     char *a_threshName;       /* threshold variable name */
-     char *a_threshValue;      /* threshold value */
-     char *a_actValue;         /* actual value */
-
+execute_thresh_handler(char *a_handler,                /* ptr to handler function + args */
+                      char *a_hostName,        /* host name for which threshold crossed */
+                      int a_hostType,          /* fs or cm ? */
+                      char *a_threshName,      /* threshold variable name */
+                      char *a_threshValue,     /* threshold value */
+                      char *a_actValue)        /* actual value */
 {                              /* execute_thresh_handler */
 
     static char rn[] = "execute_thresh_handler";
     char fileName[256];                /* file name to execute */
     int i;
     char *ch;
-    int code;
     int argNum;
     int anotherArg;            /* boolean used to flag if another arg is available */
 
@@ -2045,7 +2103,7 @@ execute_thresh_handler(a_handler, a_hostName, a_hostType, a_threshName,
 
     if (fork() == 0) {
        exec_fsThreshHandler = 1;
-       code = afsmon_Exit(60);
+       afsmon_Exit(60);
     }
 
     return (0);
@@ -2059,11 +2117,11 @@ execute_thresh_handler(a_handler, a_hostName, a_hostType, a_threshName,
  * Description:
  *     Checks the thresholds and sets the overflow flag. Recall that the
  *     thresholds for each host are stored in the hostEntry lists
- *     [fs/cm]nameList arrays. The probe results are passed to this 
+ *     [fs/cm]nameList arrays. The probe results are passed to this
  *     function in the display-ready format - ie., as strings. Though
  *     this looks stupid the overhead incurred in converting the strings
- *     back to floats and comparing them is insignificant and 
- *     programming is easier this way. 
+ *     back to floats and comparing them is insignificant and
+ *     programming is easier this way.
  *     The threshold flags are a part of the display structures
  *     curr_[fs/cm]Data.
  *
@@ -2072,10 +2130,8 @@ execute_thresh_handler(a_handler, a_hostName, a_hostType, a_threshName,
  *----------------------------------------------------------------------*/
 
 int
-check_fs_thresholds(a_hostEntry, a_Data)
-     struct afsmon_hostEntry *a_hostEntry;     /* ptr to hostEntry */
-     struct fs_Display_Data *a_Data;   /* ptr to fs data to be displayed */
-
+check_fs_thresholds(struct afsmon_hostEntry *a_hostEntry, /* ptr to hostEntry */
+                   struct fs_Display_Data *a_Data)       /* ptr to fs data to be displayed */
 {                              /* check_fs_thresholds */
 
     static char rn[] = "check_fs_thresholds";
@@ -2087,7 +2143,7 @@ check_fs_thresholds(a_hostEntry, a_Data)
     int count;                 /* number of thresholds exceeded */
 
     if (afsmon_debug) {
-       fprintf(debugFD, "[ %s ] Called, a_hostEntry= %d, a_Data= %d\n", rn,
+       fprintf(debugFD, "[ %s ] Called, a_hostEntry= %p, a_Data= %p\n", rn,
                a_hostEntry, a_Data);
        fflush(debugFD);
     }
@@ -2155,11 +2211,11 @@ check_fs_thresholds(a_hostEntry, a_Data)
  * Description:
  *     Does the following:
  *     - if the probe number changed (ie, a cycle completed) curr_fsData
- *     is copied to prev_fsData, curr_fsData zeroed and refresh the 
+ *     is copied to prev_fsData, curr_fsData zeroed and refresh the
  *     overview screen and file server screen with the new data.
  *     - store the results of the current probe from xstat_fs_Results into
  *     curr_fsData. ie., convert longs to strings.
- *     - check the thresholds 
+ *     - check the thresholds
  *
  * Returns:
  *     Success: 0
@@ -2167,15 +2223,14 @@ check_fs_thresholds(a_hostEntry, a_Data)
  *----------------------------------------------------------------------*/
 
 int
-save_FS_data_forDisplay(a_fsResults)
-     struct xstat_fs_ProbeResults *a_fsResults;
+save_FS_data_forDisplay(struct xstat_fs_ProbeResults *a_fsResults)
 {                              /* save_FS_data_forDisplay */
 
     static char rn[] = "save_FS_data_forDisplay";      /* routine name */
     struct fs_Display_Data *curr_fsDataP;      /* tmp ptr to curr_fsData */
     struct fs_Display_Data *prev_fsDataP;      /* tmp ptr to prev_fsData */
     struct afsmon_hostEntry *curr_host;
-    static int probes_Received = 0;    /* number of probes reveived in
+    static int results_Received = 0;   /* number of probes reveived in
                                         * the current cycle. If this is equal to numFS we got all
                                         * the data we want in this cycle and can now display it */
     int numBytes;
@@ -2186,12 +2241,10 @@ save_FS_data_forDisplay(a_fsResults)
 
 
     if (afsmon_debug) {
-       fprintf(debugFD, "[ %s ] Called, a_fsResults= %d\n", rn, a_fsResults);
+       fprintf(debugFD, "[ %s ] Called, a_fsResults= %p\n", rn, a_fsResults);
        fflush(debugFD);
     }
 
-
-
     /* store results in the display array */
 
     okay = 0;
@@ -2213,7 +2266,7 @@ save_FS_data_forDisplay(a_fsResults)
     }
 
     /*  Check the status of the probe. If it succeeded, we store its
-     * results in the display data structure. If it failed we only mark 
+     * results in the display data structure. If it failed we only mark
      * the failed status in the display data structure. */
 
     if (a_fsResults->probeOK) {        /* 1 => notOK the xstat results */
@@ -2230,11 +2283,11 @@ save_FS_data_forDisplay(a_fsResults)
     } else {                   /* probe succeeded, update display data structures */
        curr_fsDataP->probeOK = 1;
 
-       /* covert longs to strings and place them in curr_fsDataP */
+       /* convert longs to strings and place them in curr_fsDataP */
        fs_Results_ltoa(curr_fsDataP, a_fsResults);
 
        /* compare with thresholds and set the overflow flags.
-        * note that the threshold information is in the hostEntry structure and 
+        * note that the threshold information is in the hostEntry structure and
         * each threshold item has a positional index associated with it */
 
        /* locate the hostEntry for this host */
@@ -2257,9 +2310,6 @@ save_FS_data_forDisplay(a_fsResults)
            afsmon_Exit(75);
        }
 
-
-
-
        /* print the info we just saved */
 
        if (afsmon_debug) {
@@ -2280,9 +2330,9 @@ save_FS_data_forDisplay(a_fsResults)
     /* if we have received a reply from all the hosts for this probe cycle,
      * it is time to display the data */
 
-    probes_Received++;
-    if (probes_Received == numFS) {
-       probes_Received = 0;
+    results_Received++;
+    if (results_Received == numFS * num_fs_collections) {
+       results_Received = 0;
 
        if (afsmon_fs_curr_probeNum != afsmon_fs_prev_probeNum + 1) {
            sprintf(errMsg, "[ %s ] Probe number %d missed! \n", rn,
@@ -2301,12 +2351,12 @@ save_FS_data_forDisplay(a_fsResults)
        /* initialize curr_fsData but retain the threshold flag information.
         * The previous state of threshold flags is used in check_fs_thresholds() */
 
-       numBytes = NUM_FS_STAT_ENTRIES * CM_STAT_STRING_LEN;
+       numBytes = NUM_FS_STAT_ENTRIES * FS_STAT_STRING_LEN;
        curr_fsDataP = curr_fsData;
        for (i = 0; i < numFS; i++) {
            curr_fsDataP->probeOK = 0;
            curr_fsDataP->ovfCount = 0;
-           memset((char *)curr_fsDataP->data, 0, numBytes);
+           memset(curr_fsDataP->data, 0, numBytes);
            curr_fsDataP++;
        }
 
@@ -2364,7 +2414,7 @@ save_FS_data_forDisplay(a_fsResults)
  *----------------------------------------------------------------------*/
 
 int
-afsmon_FS_Handler()
+afsmon_FS_Handler(void)
 {                              /* afsmon_FS_Handler() */
     static char rn[] = "afsmon_FS_Handler";    /* routine name */
     int newProbeCycle;         /* start of new probe cycle ? */
@@ -2373,9 +2423,10 @@ afsmon_FS_Handler()
 
     if (afsmon_debug) {
        fprintf(debugFD,
-               "[ %s ] Called, hostName= %s, probeNum= %d, status=%s\n", rn,
+               "[ %s ] Called, hostName= %s, probeNum= %d, status=%s, collection=%d\n", rn,
                xstat_fs_Results.connP->hostName, xstat_fs_Results.probeNum,
-               xstat_fs_Results.probeOK ? "FAILED" : "OK");
+               xstat_fs_Results.probeOK ? "FAILED" : "OK",
+               xstat_fs_Results.collectionNumber);
        fflush(debugFD);
     }
 
@@ -2390,7 +2441,7 @@ afsmon_FS_Handler()
        }
     }
 
-    /* Update current probe number and circular buffer index. if current 
+    /* Update current probe number and circular buffer index. if current
      * probenum changed make sure it is only by 1 */
 
     newProbeCycle = 0;
@@ -2408,6 +2459,7 @@ afsmon_FS_Handler()
        }
     }
 
+
     /* store the results of this probe in the FS circular buffer */
     if (num_bufSlots)
        save_FS_results_inCB(newProbeCycle);
@@ -2415,7 +2467,7 @@ afsmon_FS_Handler()
 
     /* store the results of the current probe in the fs data display structure.
      * if the current probe number changed, swap the current and previous display
-     * structures. note that the display screen is updated from these structures 
+     * structures. note that the display screen is updated from these structures
      * and should start showing the data of the just completed probe cycle */
 
     save_FS_data_forDisplay(&xstat_fs_Results);
@@ -2425,21 +2477,22 @@ afsmon_FS_Handler()
 
 
 
-/*----------------------------------------------------------------------- * 
- * Print_CM_CB()     
+/*----------------------------------------------------------------------- *
+ * Print_CM_CB()
  *
  * Description:
  *     Debug routine.
- *     Prints the  Cache Manager circular buffer 
+ *     Prints the  Cache Manager circular buffer
  *----------------------------------------------------------------------*/
 
 void
-Print_CM_CB()
+Print_CM_CB(void)
 {                              /* Print_CM_CB() */
 
     struct afsmon_cm_Results_list *cmlist;
     int i;
     int j;
+    int k;
 
     /* print valid info in the cm CB */
 
@@ -2456,16 +2509,21 @@ Print_CM_CB()
            cmlist = afsmon_cm_ResultsCB[i].list;
            j = 0;
            while (j < numCM) {
-               if (!cmlist->empty) {
-                   fprintf(debugFD, "\t %d) probeNum = %d host = %s", j,
-                           cmlist->cmResults->probeNum,
-                           cmlist->cmResults->connP->hostName);
-                   if (cmlist->cmResults->probeOK)
-                       fprintf(debugFD, " NOTOK\n");
-                   else
-                       fprintf(debugFD, " OK\n");
-               } else
-                   fprintf(debugFD, "\t %d) -- empty --\n", j);
+               for (k = 0; k < MAX_NUM_CM_COLLECTIONS; k++) {
+                   if (!cmlist->empty[k]) {
+                       fprintf(debugFD,
+                               "\t %d) probeNum = %d host = %s cn = %d",
+                               j,
+                               cmlist->cmResults[k]->probeNum,
+                               cmlist->cmResults[k]->connP->hostName,
+                               cmlist->cmResults[k]->collectionNumber);
+                       if (cmlist->cmResults[k]->probeOK)
+                           fprintf(debugFD, " NOTOK\n");
+                       else
+                           fprintf(debugFD, " OK\n");
+                   } else
+                       fprintf(debugFD, "\t %d) -- empty --\n", j);
+               }
                cmlist = cmlist->next;
                j++;
            }
@@ -2494,14 +2552,13 @@ Print_CM_CB()
  *----------------------------------------------------------------------*/
 
 int
-save_CM_results_inCB(a_newProbeCycle)
-     int a_newProbeCycle;      /* start of new probe cycle ? */
-
+save_CM_results_inCB(int a_newProbeCycle)      /* start of new probe cycle ? */
 {                              /* save_CM_results_inCB() */
     static char rn[] = "save_CM_results_inCB"; /* routine name */
     struct afsmon_cm_Results_list *tmp_cmlist_item;    /* temp cm list item */
     struct xstat_cm_ProbeResults *tmp_cmPR;    /* temp ptr */
     int i;
+    int index;
 
 
     if (afsmon_debug) {
@@ -2510,6 +2567,14 @@ save_CM_results_inCB(a_newProbeCycle)
        fflush(debugFD);
     }
 
+    if (xstat_cm_Results.collectionNumber == AFSCB_XSTATSCOLL_FULL_PERF_INFO) {
+       index = 0;
+    } else {
+       fprintf(stderr, "[ %s ] collection number %d is out of range.\n",
+               rn, xstat_cm_Results.collectionNumber);
+       afsmon_Exit(91);
+    }
+
     /* If a new probe cycle started, mark the list in the current buffer
      * slot empty for resuse. Note that afsmon_cm_curr_CBindex was appropriately
      * incremented in afsmon_CM_Handler() */
@@ -2517,7 +2582,7 @@ save_CM_results_inCB(a_newProbeCycle)
     if (a_newProbeCycle) {
        tmp_cmlist_item = afsmon_cm_ResultsCB[afsmon_cm_curr_CBindex].list;
        for (i = 0; i < numCM; i++) {
-           tmp_cmlist_item->empty = 1;
+           tmp_cmlist_item->empty[index] = 1;
            tmp_cmlist_item = tmp_cmlist_item->next;
        }
     }
@@ -2525,13 +2590,13 @@ save_CM_results_inCB(a_newProbeCycle)
     /* locate last unused item in list */
     tmp_cmlist_item = afsmon_cm_ResultsCB[afsmon_cm_curr_CBindex].list;
     for (i = 0; i < numCM; i++) {
-       if (tmp_cmlist_item->empty)
+       if (tmp_cmlist_item->empty[index])
            break;
        tmp_cmlist_item = tmp_cmlist_item->next;
     }
 
     /* if we could not find one we have an inconsistent list */
-    if (!tmp_cmlist_item->empty) {
+    if (!tmp_cmlist_item->empty[index]) {
        fprintf(stderr,
                "[ %s ] list inconsistency 1. unable to find an empty slot to store results of probenum %d of %s\n",
                rn, xstat_cm_Results.probeNum,
@@ -2539,7 +2604,7 @@ save_CM_results_inCB(a_newProbeCycle)
        afsmon_Exit(90);
     }
 
-    tmp_cmPR = tmp_cmlist_item->cmResults;
+    tmp_cmPR = tmp_cmlist_item->cmResults[index];
 
     /* copy hostname and probe number and probe time and probe status.
      * if the probe failed return now */
@@ -2551,7 +2616,7 @@ save_CM_results_inCB(a_newProbeCycle)
     tmp_cmPR->probeOK = xstat_cm_Results.probeOK;
     if (xstat_cm_Results.probeOK) {    /* probeOK = 1 => notOK */
        /* we have a nonempty results structure so mark the list item used */
-       tmp_cmlist_item->empty = 0;
+       tmp_cmlist_item->empty[index] = 0;
        return (0);
     }
 
@@ -2568,14 +2633,15 @@ save_CM_results_inCB(a_newProbeCycle)
 
     /* copy the probe data information */
     tmp_cmPR->data.AFSCB_CollData_len =
-       xstat_cm_Results.data.AFSCB_CollData_len;
+       min(xstat_cm_Results.data.AFSCB_CollData_len,
+           afsmon_cm_results_length[index]);
     memcpy(tmp_cmPR->data.AFSCB_CollData_val,
           xstat_cm_Results.data.AFSCB_CollData_val,
-          xstat_cm_Results.data.AFSCB_CollData_len * sizeof(afs_int32));
+          tmp_cmPR->data.AFSCB_CollData_len * sizeof(afs_int32));
 
 
     /* we have a valid results structure so mark the list item used */
-    tmp_cmlist_item->empty = 0;
+    tmp_cmlist_item->empty[index] = 0;
 
     /* print the stored info - to make sure we copied it right */
     /*   Print_cm_FullPerfInfo(tmp_cmPR);        */
@@ -2590,10 +2656,10 @@ save_CM_results_inCB(a_newProbeCycle)
  * cm_Results_ltoa()
  *
  * Description:
- *     The results of xstat probes are stored in a string format in 
+ *     The results of xstat probes are stored in a string format in
  *     the arrays curr_cmData and prev_cmData. The information stored in
- *     prev_cmData is copied to the screen. 
- *     This function converts xstat FS results from longs to strings and 
+ *     prev_cmData is copied to the screen.
+ *     This function converts xstat FS results from longs to strings and
  *     places them in the given buffer (a pointer to an item in curr_cmData).
  *     When a probe cycle completes, curr_cmData is copied to prev_cmData
  *     in afsmon_CM_Handler().
@@ -2603,9 +2669,8 @@ save_CM_results_inCB(a_newProbeCycle)
  *----------------------------------------------------------------------*/
 
 int
-cm_Results_ltoa(a_cmData, a_cmResults)
-     struct cm_Display_Data *a_cmData; /* target buffer */
-     struct xstat_cm_ProbeResults *a_cmResults;        /* ptr to xstat cm Results */
+cm_Results_ltoa(struct cm_Display_Data *a_cmData,      /* target buffer */
+               struct xstat_cm_ProbeResults *a_cmResults)      /* ptr to xstat cm Results */
 {                              /* cm_Results_ltoa */
 
     static char rn[] = "cm_Results_ltoa";      /* routine name */
@@ -2617,7 +2682,7 @@ cm_Results_ltoa(a_cmData, a_cmResults)
     afs_int32 numLongs;
 
     if (afsmon_debug) {
-       fprintf(debugFD, "[ %s ] Called, a_cmData= %d, a_cmResults= %d\n", rn,
+       fprintf(debugFD, "[ %s ] Called, a_cmData= %p, a_cmResults= %p\n", rn,
                a_cmData, a_cmResults);
        fflush(debugFD);
     }
@@ -2628,7 +2693,7 @@ cm_Results_ltoa(a_cmData, a_cmResults)
 
     /* There are 4 parts to CM statistics
      * - Overall performance statistics (including up/down statistics)
-     * - This CMs FS RPC operations info 
+     * - This CMs FS RPC operations info
      * - This CMs FS RPC errors info
      * - This CMs FS transfers info
      * - Authentication info
@@ -2839,11 +2904,11 @@ cm_Results_ltoa(a_cmData, a_cmResults)
  * Description:
  *     Checks the thresholds and sets the overflow flag. Recall that the
  *     thresholds for each host are stored in the hostEntry lists
- *     [fs/cm]nameList arrays. The probe results are passed to this 
+ *     [fs/cm]nameList arrays. The probe results are passed to this
  *     function in the display-ready format - ie., as strings. Though
  *     this looks stupid the overhead incurred in converting the strings
- *     back to floats and comparing them is insignificant and 
- *     programming is easier this way. 
+ *     back to floats and comparing them is insignificant and
+ *     programming is easier this way.
  *     The threshold flags are a part of the display structures
  *     curr_[fs/cm]Data.
  *
@@ -2852,10 +2917,8 @@ cm_Results_ltoa(a_cmData, a_cmResults)
  *----------------------------------------------------------------------*/
 
 int
-check_cm_thresholds(a_hostEntry, a_Data)
-     struct afsmon_hostEntry *a_hostEntry;     /* ptr to hostEntry */
-     struct cm_Display_Data *a_Data;   /* ptr to cm data to be displayed */
-
+check_cm_thresholds(struct afsmon_hostEntry *a_hostEntry,      /* ptr to hostEntry */
+                   struct cm_Display_Data *a_Data)             /* ptr to cm data to be displayed */
 {                              /* check_cm_thresholds */
 
     static char rn[] = "check_cm_thresholds";
@@ -2867,7 +2930,7 @@ check_cm_thresholds(a_hostEntry, a_Data)
     int count;                 /* number of thresholds exceeded */
 
     if (afsmon_debug) {
-       fprintf(debugFD, "[ %s ] Called, a_hostEntry= %d, a_Data= %d\n", rn,
+       fprintf(debugFD, "[ %s ] Called, a_hostEntry= %p, a_Data= %p\n", rn,
                a_hostEntry, a_Data);
        fflush(debugFD);
     }
@@ -2936,11 +2999,11 @@ check_cm_thresholds(a_hostEntry, a_Data)
  * Description:
  *     Does the following:
  *     - if the probe number changed (ie, a cycle completed) curr_cmData
- *     is copied to prev_cmData, curr_cmData zeroed and refresh the 
+ *     is copied to prev_cmData, curr_cmData zeroed and refresh the
  *     overview screen and file server screen with the new data.
  *     - store the results of the current probe from xstat_cm_Results into
  *     curr_cmData. ie., convert longs to strings.
- *     - check the thresholds 
+ *     - check the thresholds
  *
  * Returns:
  *     Success: 0
@@ -2949,15 +3012,14 @@ check_cm_thresholds(a_hostEntry, a_Data)
  *----------------------------------------------------------------------*/
 
 int
-save_CM_data_forDisplay(a_cmResults)
-     struct xstat_cm_ProbeResults *a_cmResults;
+save_CM_data_forDisplay(struct xstat_cm_ProbeResults *a_cmResults)
 {                              /* save_CM_data_forDisplay */
 
     static char rn[] = "save_CM_data_forDisplay";      /* routine name */
     struct cm_Display_Data *curr_cmDataP;
     struct cm_Display_Data *prev_cmDataP;
     struct afsmon_hostEntry *curr_host;
-    static int probes_Received = 0;    /* number of probes reveived in
+    static int results_Received = 0;   /* number of probes reveived in
                                         * the current cycle. If this is equal to numFS we got all
                                         * the data we want in this cycle and can now display it */
     int numBytes;
@@ -2967,7 +3029,7 @@ save_CM_data_forDisplay(a_cmResults)
     int i;
 
     if (afsmon_debug) {
-       fprintf(debugFD, "[ %s ] Called, a_cmResults= %d\n", rn, a_cmResults);
+       fprintf(debugFD, "[ %s ] Called, a_cmResults= %p\n", rn, a_cmResults);
        fflush(debugFD);
     }
 
@@ -2992,7 +3054,7 @@ save_CM_data_forDisplay(a_cmResults)
     }
 
     /*  Check the status of the probe. If it succeeded, we store its
-     * results in the display data structure. If it failed we only mark 
+     * results in the display data structure. If it failed we only mark
      * the failed status in the display data structure. */
 
 
@@ -3015,7 +3077,7 @@ save_CM_data_forDisplay(a_cmResults)
        cm_Results_ltoa(curr_cmDataP, a_cmResults);
 
        /* compare with thresholds and set the overflow flags.
-        * note that the threshold information is in the hostEntry structure and 
+        * note that the threshold information is in the hostEntry structure and
         * each threshold item has a positional index associated with it */
 
        /* locate the hostEntry for this host */
@@ -3038,7 +3100,6 @@ save_CM_data_forDisplay(a_cmResults)
            afsmon_Exit(105);
        }
 
-
        /* print the info we just saved */
        if (afsmon_debug) {
            fprintf(debugFD, "\n\t\t ----- CM display data ------\n");
@@ -3098,9 +3159,9 @@ save_CM_data_forDisplay(a_cmResults)
     /* if we have received a reply from all the hosts for this probe cycle,
      * it is time to display the data */
 
-    probes_Received++;
-    if (probes_Received == numCM) {
-       probes_Received = 0;
+    results_Received++;
+    if (results_Received == numCM * num_cm_collections) {
+       results_Received = 0;
 
        if (afsmon_cm_curr_probeNum != afsmon_cm_prev_probeNum + 1) {
            sprintf(errMsg, "[ %s ] Probe number %d missed! \n", rn,
@@ -3125,7 +3186,7 @@ save_CM_data_forDisplay(a_cmResults)
        for (i = 0; i < numCM; i++) {
            curr_cmDataP->probeOK = 0;
            curr_cmDataP->ovfCount = 0;
-           memset((char *)curr_cmDataP->data, 0, numBytes);
+           memset(curr_cmDataP->data, 0, numBytes);
            curr_cmDataP++;
        }
 
@@ -3182,7 +3243,7 @@ save_CM_data_forDisplay(a_cmResults)
  *----------------------------------------------------------------------*/
 
 int
-afsmon_CM_Handler()
+afsmon_CM_Handler(void)
 {                              /* afsmon_CM_Handler() */
     static char rn[] = "afsmon_CM_Handler";    /* routine name */
     int code;                  /* return status */
@@ -3207,7 +3268,7 @@ afsmon_CM_Handler()
        }
     }
 
-    /* Update current probe number and circular buffer index. if current 
+    /* Update current probe number and circular buffer index. if current
      * probenum changed make sure it is only by 1 */
 
     newProbeCycle = 0;
@@ -3231,7 +3292,7 @@ afsmon_CM_Handler()
 
     /* store the results of the current probe in the cm data display structure.
      * if the current probe number changed, swap the current and previous display
-     * structures. note that the display screen is updated from these structures 
+     * structures. note that the display screen is updated from these structures
      * and should start showing the data of the just completed probe cycle */
 
     save_CM_data_forDisplay(&xstat_cm_Results);
@@ -3251,7 +3312,7 @@ afsmon_CM_Handler()
  *----------------------------------------------------------------------*/
 
 int
-init_fs_buffers()
+init_fs_buffers(void)
 {                              /* init_fs_buffers() */
     static char rn[] = "init_fs_buffers";      /* routine name */
     struct afsmon_fs_Results_list *new_fslist_item;    /* ptr for new struct */
@@ -3278,7 +3339,7 @@ init_fs_buffers()
        afsmon_fs_ResultsCB[i].probeNum = 0;
     }
 
-    /* create  a list of numFS items to store fs probe results for 
+    /* create  a list of numFS items to store fs probe results for
      * each slot in CB */
 
     if (numFS) {               /* if we have file servers to monitor */
@@ -3287,7 +3348,7 @@ init_fs_buffers()
            while (numfs--) {
 
                /* if any of these mallocs fail we only need to free the memory we
-                * have allocated in this iteration. the rest of it which is in a 
+                * have allocated in this iteration. the rest of it which is in a
                 * proper linked list will be freed in afsmon_Exit */
 
                /* allocate memory for an fs list item */
@@ -3296,36 +3357,37 @@ init_fs_buffers()
                if (new_fslist_item == (struct afsmon_fs_Results_list *)0)
                    return (-1);
 
-               /* allocate memory to store xstat_fs_Results */
-               new_fsPR = (struct xstat_fs_ProbeResults *)
-                   malloc(sizeof(struct xstat_fs_ProbeResults));
-               if (new_fsPR == (struct xstat_fs_ProbeResults *)0) {
-                   free(new_fslist_item);
-                   return (-1);
-               }
-               new_fsPR->connP = (struct xstat_fs_ConnectionInfo *)
-                   malloc(sizeof(struct xstat_fs_ConnectionInfo));
-               if (new_fsPR->connP == (struct xstat_fs_ConnectionInfo *)0) {
-                   free(new_fslist_item);
-                   free(new_fsPR);
-                   return (-1);
-               }
+               for (i = 0; i < MAX_NUM_FS_COLLECTIONS; i++) {
+                   /* allocate memory to store xstat_fs_Results */
+                   new_fsPR = (struct xstat_fs_ProbeResults *)
+                       malloc(sizeof(struct xstat_fs_ProbeResults));
+                   if (!new_fsPR) {
+                       free(new_fslist_item);
+                       return (-1);
+                   }
 
-               /* >>>  need to allocate rx connection info structure here <<< */
+                   new_fsPR->connP = (struct xstat_fs_ConnectionInfo *)
+                       malloc(sizeof(struct xstat_fs_ConnectionInfo));
+                   if (new_fsPR->connP == (struct xstat_fs_ConnectionInfo *)0) {
+                       free(new_fslist_item);
+                       free(new_fsPR);
+                       return (-1);
+                   }
 
-               new_fsPR->data.AFS_CollData_val =
-                   (afs_int32 *) malloc(XSTAT_FS_FULLPERF_RESULTS_LEN *
-                                        sizeof(afs_int32));
-               if (new_fsPR->data.AFS_CollData_val == NULL) {
-                   free(new_fslist_item);
-                   free(new_fsPR->connP);
-                   free(new_fsPR);
-                   return (-1);
+                   /* >>>  need to allocate rx connection info structure here <<< */
+                   new_fsPR->data.AFS_CollData_val = (afs_int32 *)
+                      malloc(afsmon_fs_results_length[i] * sizeof(afs_int32));
+                   if (new_fsPR->data.AFS_CollData_val == NULL) {
+                      free(new_fslist_item);
+                      free(new_fsPR->connP);
+                      free(new_fsPR);
+                      return (-1);
+                   }
+                   new_fslist_item->fsResults[i] = new_fsPR;
+                   new_fslist_item->empty[i] = 1;
                }
 
                /* initialize this list entry */
-               new_fslist_item->fsResults = new_fsPR;
-               new_fslist_item->empty = 1;
                new_fslist_item->next = (struct afsmon_fs_Results_list *)0;
 
                /* store it at the end of the fs list in the current CB slot */
@@ -3369,7 +3431,7 @@ init_fs_buffers()
  *----------------------------------------------------------------------*/
 
 int
-init_cm_buffers()
+init_cm_buffers(void)
 {                              /* init_cm_buffers() */
     static char rn[] = "init_cm_buffers";      /* routine name */
     struct afsmon_cm_Results_list *new_cmlist_item;    /* ptr for new struct */
@@ -3394,7 +3456,7 @@ init_cm_buffers()
        afsmon_cm_ResultsCB[i].probeNum = 0;
     }
 
-    /* create  a list of numCM items to store fs probe results for 
+    /* create  a list of numCM items to store fs probe results for
      * each slot in CB */
 
     if (numCM) {               /* if we have file servers to monitor */
@@ -3403,7 +3465,7 @@ init_cm_buffers()
            while (numcm--) {
 
                /* if any of these mallocs fail we only need to free the memory we
-                * have allocated in this iteration. the rest of it which is in a 
+                * have allocated in this iteration. the rest of it which is in a
                 * proper linked list will be freed in afsmon_Exit */
 
                /* allocate memory for an fs list item */
@@ -3412,36 +3474,39 @@ init_cm_buffers()
                if (new_cmlist_item == (struct afsmon_cm_Results_list *)0)
                    return (-1);
 
-               /* allocate memory to store xstat_cm_Results */
-               new_cmPR = (struct xstat_cm_ProbeResults *)
-                   malloc(sizeof(struct xstat_cm_ProbeResults));
-               if (new_cmPR == (struct xstat_cm_ProbeResults *)0) {
-                   free(new_cmlist_item);
-                   return (-1);
-               }
-               new_cmPR->connP = (struct xstat_cm_ConnectionInfo *)
-                   malloc(sizeof(struct xstat_cm_ConnectionInfo));
-               if (new_cmPR->connP == (struct xstat_cm_ConnectionInfo *)0) {
-                   free(new_cmlist_item);
-                   free(new_cmPR);
-                   return (-1);
-               }
+               for (i = 0; i < MAX_NUM_CM_COLLECTIONS; i++) {
+                   /* allocate memory to store xstat_cm_Results */
+                   new_cmPR = (struct xstat_cm_ProbeResults *)
+                       malloc(sizeof(struct xstat_cm_ProbeResults));
+                   if (!new_cmPR) {
+                       free(new_cmlist_item);
+                       return (-1);
+                   }
+                   new_cmPR->connP = (struct xstat_cm_ConnectionInfo *)
+                       malloc(sizeof(struct xstat_cm_ConnectionInfo));
+                   if (!new_cmPR->connP) {
+                       free(new_cmlist_item);
+                       free(new_cmPR);
+                       return (-1);
+                   }
 
-               /* >>>  need to allocate rx connection info structure here <<< */
+                   /* >>>  need to allocate rx connection info structure here <<< */
 
-               new_cmPR->data.AFSCB_CollData_val =
-                   (afs_int32 *) malloc(XSTAT_CM_FULLPERF_RESULTS_LEN *
-                                        sizeof(afs_int32));
-               if (new_cmPR->data.AFSCB_CollData_val == NULL) {
-                   free(new_cmlist_item);
-                   free(new_cmPR->connP);
-                   free(new_cmPR);
-                   return (-1);
+                   new_cmPR->data.AFSCB_CollData_val =
+                       malloc(XSTAT_CM_FULLPERF_RESULTS_LEN
+                              *sizeof(afs_int32));
+                   if (new_cmPR->data.AFSCB_CollData_val == NULL) {
+                       free(new_cmlist_item);
+                       free(new_cmPR->connP);
+                       free(new_cmPR);
+                       return (-1);
+                   }
+
+                   new_cmlist_item->cmResults[i] = new_cmPR;
+                   new_cmlist_item->empty[i] = 1;
                }
 
                /* initialize this list entry */
-               new_cmlist_item->cmResults = new_cmPR;
-               new_cmlist_item->empty = 1;
                new_cmlist_item->next = (struct afsmon_cm_Results_list *)0;
 
                /* store it at the end of the cm list in the current CB slot */
@@ -3483,8 +3548,8 @@ init_cm_buffers()
  *
  * Description:
  *     Allocate and initialize the buffers used for printing results
- *     to the display screen. These buffers store the current and 
- *     previous probe results in ascii format. 
+ *     to the display screen. These buffers store the current and
+ *     previous probe results in ascii format.
  *
  * Returns:
  *     Success: 0
@@ -3492,7 +3557,7 @@ init_cm_buffers()
  *------------------------------------------------------------------------*/
 
 int
-init_print_buffers()
+init_print_buffers(void)
 {                              /* init_print_buffers */
 
     static char rn[] = "init_print_buffers";   /* routine name */
@@ -3515,12 +3580,12 @@ init_print_buffers()
     /* we need two instances of this structure - one (curr_fsData) for storing
      * the results of the fs probes currently in progress and another (prev_fsData)
      * for the last completed probe. The display is updated from the contents of
-     * prev_fsData. The pointers curr_fsData & prev_fsData are switched whenever 
+     * prev_fsData. The pointers curr_fsData & prev_fsData are switched whenever
      * the probe number changes */
 
     if (numFS) {
        numBytes = numFS * sizeof(struct fs_Display_Data);
-       curr_fsData = (struct fs_Display_Data *)malloc(numBytes);
+       curr_fsData = malloc(numBytes);
        if (curr_fsData == (struct fs_Display_Data *)0) {
            fprintf(stderr, "[ %s ] Memory allocation failure\n", rn);
            return (-1);
@@ -3528,7 +3593,7 @@ init_print_buffers()
        memset(curr_fsData, 0, numBytes);
 
        numBytes = numFS * sizeof(struct fs_Display_Data);
-       prev_fsData = (struct fs_Display_Data *)malloc(numBytes);
+       prev_fsData = malloc(numBytes);
        if (prev_fsData == (struct fs_Display_Data *)0) {
            fprintf(stderr, "[ %s ] Memory allocation failure\n", rn);
            return (-5);
@@ -3551,15 +3616,13 @@ init_print_buffers()
 
     }
 
-
-
     /* if file servers to monitor */
     /* allocate numCM blocks of the CM print structure */
     /* we need two instances of this structure for the same reasons as above */
     if (numCM) {
        numBytes = numCM * sizeof(struct cm_Display_Data);
 
-       curr_cmData = (struct cm_Display_Data *)malloc(numBytes);
+       curr_cmData = malloc(numBytes);
        if (curr_cmData == (struct cm_Display_Data *)0) {
            fprintf(stderr, "[ %s ] Memory allocation failure\n", rn);
            return (-10);
@@ -3567,7 +3630,7 @@ init_print_buffers()
        memset(curr_cmData, 0, numBytes);
 
        numBytes = numCM * sizeof(struct cm_Display_Data);
-       prev_cmData = (struct cm_Display_Data *)malloc(numBytes);
+       prev_cmData = malloc(numBytes);
        if (prev_cmData == (struct cm_Display_Data *)0) {
            fprintf(stderr, "[ %s ] Memory allocation failure\n", rn);
            return (-15);
@@ -3603,11 +3666,8 @@ init_print_buffers()
  *----------------------------------------------------------------------*/
 
 void
-quit_signal(sig)
-     int sig;
+quit_signal(int sig)
 {                              /* quit_signal */
-    static char *rn = "quit_signal";   /* routine name */
-
     fprintf(stderr, "Received signal %d \n", sig);
     afsmon_Exit(120);
 }                              /* quit_signal */
@@ -3620,7 +3680,7 @@ quit_signal(sig)
  * Description:
  *     This is where we start it all. Initialize an array of sockets for
  *     file servers and cache cache managers and call the xstat_[fs/cm]_Init
- *     routines. The last step is to call the gtx input server which 
+ *     routines. The last step is to call the gtx input server which
  *     grabs control of the keyboard.
  *
  * Returns:
@@ -3631,7 +3691,7 @@ quit_signal(sig)
  *----------------------------------------------------------------------*/
 
 int
-afsmon_execute()
+afsmon_execute(void)
 {                              /* afsmon_execute() */
     static char rn[] = "afsmon_execute";       /* routine name */
     static char fullhostname[128];     /* full host name */
@@ -3643,12 +3703,12 @@ afsmon_execute()
     struct afsmon_hostEntry *curr_FS;  /* ptr to FS name list */
     struct afsmon_hostEntry *curr_CM;  /* ptr to CM name list */
     struct hostent *he;                /* host entry */
-    afs_int32 *collIDP;                /* ptr to collection ID */
-    int numCollIDs;            /* number of collection IDs */
     int FSinitFlags = 0;       /* flags for xstat_fs_Init */
     int CMinitFlags = 0;       /* flags for xstat_cm_Init */
     int code;                  /* function return code */
     struct timeval tv;         /* time structure */
+    int i;
+    short index;
 
     if (afsmon_debug) {
        fprintf(debugFD, "[ %s ] Called\n", rn);
@@ -3658,10 +3718,12 @@ afsmon_execute()
 
     /* process file server entries */
     if (numFS) {
+       afs_int32 collIDs[MAX_NUM_FS_COLLECTIONS];
+
        /* Allocate an array of sockets for each fileserver we monitor */
 
        FSsktbytes = numFS * sizeof(struct sockaddr_in);
-       FSSktArray = (struct sockaddr_in *)malloc(FSsktbytes);
+       FSSktArray = malloc(FSsktbytes);
        if (FSSktArray == (struct sockaddr_in *)0) {
            fprintf(stderr,
                    "[ %s ] cannot malloc %d sockaddr_ins for fileservers\n",
@@ -3685,7 +3747,7 @@ afsmon_execute()
            }
            strncpy(curr_FS->hostName, he->h_name, HOST_NAME_LEN);      /* complete name */
            memcpy(&(curr_skt->sin_addr.s_addr), he->h_addr, 4);
-           curr_skt->sin_family = htons(AF_INET);      /*Internet family */
+           curr_skt->sin_family = AF_INET;             /*Internet family */
            curr_skt->sin_port = htons(7000);   /*FileServer port */
 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
            curr_skt->sin_len = sizeof(struct sockaddr_in);
@@ -3696,18 +3758,22 @@ afsmon_execute()
            curr_FS = curr_FS->next;
        }
 
-       /* initialize collection IDs. We need only one entry since we collect
-        * all the information from xstat */
-
-       numCollIDs = 1;
-       collIDP = (afs_int32 *) malloc(sizeof(afs_int32));
-       if (collIDP == NULL) {
-           fprintf(stderr,
-                   "[ %s ] failed to allocate a measely afs_int32 word.Argh!\n",
-                   rn);
-           return (-1);
+       /* Initialize collection IDs, depending on the data requested. */
+       num_fs_collections = 0;
+       for (i = 0; i < fs_DisplayItems_count; i++) {
+           index = fs_Display_map[i];
+           if (FS_FULLPERF_ENTRY_START <= index && index <= FS_FULLPERF_ENTRY_END) {
+               collIDs[num_fs_collections++] = AFS_XSTATSCOLL_FULL_PERF_INFO;
+               break;
+           }
+       }
+       for (i = 0; i < fs_DisplayItems_count; i++) {
+           index = fs_Display_map[i];
+           if (FS_CB_ENTRY_START <= index && index <= FS_CB_ENTRY_END) {
+               collIDs[num_fs_collections++] = AFS_XSTATSCOLL_CBSTATS;
+               break;
+           }
        }
-       *collIDP = 2;           /* USE A macro for this */
 
        FSinitFlags = 0;
        if (afsmon_onceOnly)    /* option not provided at this time */
@@ -3723,8 +3789,8 @@ afsmon_execute()
                             afsmon_probefreq,  /*probe frequency */
                             afsmon_FS_Handler, /*Handler routine */
                             FSinitFlags,       /*Initialization flags */
-                            numCollIDs,        /*Number of collection IDs */
-                            collIDP);  /*Ptr to collection ID */
+                            num_fs_collections,        /*Number of collection IDs */
+                            collIDs);  /*Ptr to collection ID */
 
        if (code) {
            fprintf(stderr, "[ %s ] xstat_fs_init returned error\n", rn);
@@ -3737,10 +3803,12 @@ afsmon_execute()
     /* end of process fileserver entries */
     /* process cache manager entries */
     if (numCM) {
+       afs_int32 collIDs[MAX_NUM_CM_COLLECTIONS];
+
        /* Allocate an array of sockets for each cache manager we monitor */
 
        CMsktbytes = numCM * sizeof(struct sockaddr_in);
-       CMSktArray = (struct sockaddr_in *)malloc(CMsktbytes);
+       CMSktArray = malloc(CMsktbytes);
        if (CMSktArray == (struct sockaddr_in *)0) {
            fprintf(stderr,
                    "[ %s ] cannot malloc %d sockaddr_ins for CM entries\n",
@@ -3764,8 +3832,8 @@ afsmon_execute()
            }
            strncpy(curr_CM->hostName, he->h_name, HOST_NAME_LEN);      /* complete name */
            memcpy(&(curr_skt->sin_addr.s_addr), he->h_addr, 4);
-           curr_skt->sin_family = htons(AF_INET);      /*Internet family */
-           curr_skt->sin_port = htons(7001);   /*Cache Manager port */
+           curr_skt->sin_family = AF_INET;
+           curr_skt->sin_port = htons(7001);   /* Cache Manager port */
 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
            curr_skt->sin_len = sizeof(struct sockaddr_in);
 #endif
@@ -3777,16 +3845,8 @@ afsmon_execute()
 
        /* initialize collection IDs. We need only one entry since we collect
         * all the information from xstat */
-
-       numCollIDs = 1;
-       collIDP = (afs_int32 *) malloc(sizeof(afs_int32));
-       if (collIDP == NULL) {
-           fprintf(stderr,
-                   "[ %s ] failed to allocate a measely long word.Argh!\n",
-                   rn);
-           return (-1);
-       }
-       *collIDP = 2;           /* USE A macro for this */
+       num_cm_collections = 0;
+       collIDs[num_cm_collections++] = AFSCB_XSTATSCOLL_FULL_PERF_INFO;
 
        CMinitFlags = 0;
        if (afsmon_onceOnly)    /* once only ? */
@@ -3802,8 +3862,8 @@ afsmon_execute()
                             afsmon_probefreq,  /*probe frequency */
                             afsmon_CM_Handler, /*Handler routine */
                             CMinitFlags,       /*Initialization flags */
-                            numCollIDs,        /*Number of collection IDs */
-                            collIDP);  /*Ptr to collection ID */
+                            num_cm_collections,        /*Number of collection IDs */
+                            collIDs);  /*Ptr to collection ID */
 
        if (code) {
            fprintf(stderr, "[ %s ] xstat_cm_init returned error\n", rn);
@@ -3814,7 +3874,7 @@ afsmon_execute()
 
 
     /* end of process cache manager entries */
-    /* if only one probe was required setup a waiting process for the 
+    /* if only one probe was required setup a waiting process for the
      * termination signal */
     if (afsmon_onceOnly) {
        code = LWP_WaitProcess(&terminationEvent);
@@ -3829,7 +3889,7 @@ afsmon_execute()
     }
 
     /* start the gtx input server */
-    code = gtx_InputServer(afsmon_win);
+    code = (intptr_t)gtx_InputServer(afsmon_win);
     if (code) {
        fprintf(stderr, "[ %s ] Failed to start input server \n", rn);
        afsmon_Exit(140);
@@ -3877,8 +3937,7 @@ afsmon_execute()
  *----------------------------------------------------------------------*/
 
 int
-afsmonInit(as)
-     struct cmd_syndesc *as;
+afsmonInit(struct cmd_syndesc *as, void *arock)
 {                              /* afsmonInit() */
 
     static char rn[] = "afsmonInit";   /* Routine name */
@@ -3890,7 +3949,7 @@ afsmonInit(as)
     int i;
 
     if (afsmon_debug) {
-       fprintf(debugFD, "[ %s ] Called, as= %d\n", rn, as);
+       fprintf(debugFD, "[ %s ] Called, as= %p\n", rn, as);
        fflush(debugFD);
     }
 
@@ -3996,7 +4055,7 @@ afsmonInit(as)
     FSnameList = (struct afsmon_hostEntry *)0;
     CMnameList = (struct afsmon_hostEntry *)0;
 
-    /* The -config option is mutually exclusive with the -fshosts,-cmhosts 
+    /* The -config option is mutually exclusive with the -fshosts,-cmhosts
      * options */
 
     if (as->parms[P_CONFIG].items) {
@@ -4015,7 +4074,7 @@ afsmonInit(as)
 
 
     /* If a file server host is specified on the command line we reuse
-     * parse_hostEntry() function . Just the pass the info as if it were 
+     * parse_hostEntry() function . Just the pass the info as if it were
      * read off the config file */
 
     if (as->parms[P_FSHOSTS].items) {
@@ -4155,12 +4214,8 @@ afsmonInit(as)
 #include "AFS_component_version_number.c"
 
 int
-main(argc, argv)
-     int argc;
-     char **argv;
+main(int argc, char **argv)
 {                              /* main() */
-
-    static char rn[] = "main"; /* routine name */
     afs_int32 code;            /*Return code */
     struct cmd_syndesc *ts;    /*Ptr to cmd line syntax descriptor */
 
@@ -4182,7 +4237,7 @@ main(argc, argv)
     /*
      * Set up the commands we understand.
      */
-    ts = cmd_CreateSyntax("initcmd", afsmonInit, 0, "initialize the program");
+    ts = cmd_CreateSyntax("initcmd", afsmonInit, NULL, "initialize the program");
     cmd_AddParm(ts, "-config", CMD_SINGLE, CMD_OPTIONAL,
                "configuration file");
     cmd_AddParm(ts, "-frequency", CMD_SINGLE, CMD_OPTIONAL,
@@ -4205,7 +4260,7 @@ main(argc, argv)
                "number of buffer slots");
 
     /*
-     * Parse command-line switches & execute afsmonitor 
+     * Parse command-line switches & execute afsmonitor
      */
 
     code = cmd_Dispatch(argc, argv);