afsmonitor: fix segv on exit
[openafs.git] / src / afsmonitor / afsmonitor.c
index 63cd5d7..184a0f9 100644 (file)
 #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>
@@ -33,24 +31,24 @@ RCSID
 #include <sys/socket.h>
 #include <netdb.h>
 #include <ctype.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
 
-#include <gtxwindows.h>                /*Generic window package */
-#include <gtxobjects.h>                /*Object definitions */
-#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
@@ -90,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 */
 
 
@@ -119,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 */
@@ -126,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. */
 
@@ -134,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;
 };
 
@@ -144,6 +148,9 @@ 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;
 
@@ -162,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;
 };
 
@@ -172,6 +179,8 @@ 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;
 
@@ -203,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[];
@@ -236,8 +236,8 @@ int numHosts_oncm_alerts;
 
 /* 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 ? */
 
@@ -249,13 +249,13 @@ 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 
 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 ? */
 
@@ -271,8 +271,14 @@ 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);
 
-#ifndef HAVE_STRCASESTR
+#ifdef HAVE_STRCASESTR
+extern char * strcasestr(const char *, const char *);
+#else
 /*     
         strcasestr(): Return first occurence of pattern s2 in s1, case 
        insensitive. 
@@ -308,8 +314,7 @@ strcasestr(s1, s2)
 #endif
 
 struct hostent *
-GetHostByName(name)
-     char *name;
+GetHostByName(char *name)
 {
     struct hostent *he;
 #ifdef AFS_SUN5_ENV
@@ -347,8 +352,7 @@ GetHostByName(name)
  *----------------------------------------------------------------------*/
 
 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;
@@ -358,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;
@@ -404,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);
@@ -448,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);
@@ -499,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");
@@ -515,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");
@@ -558,10 +562,8 @@ 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;
 
@@ -603,7 +605,7 @@ insert_FS(a_hostName)
  *     Nothing.
  *----------------------------------------------------------------------*/
 void
-print_FS()
+print_FS(void)
 {                              /* print_FS() */
     static char rn[] = "print_FS";
     struct afsmon_hostEntry *tempFS;
@@ -647,10 +649,8 @@ 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;
 
@@ -693,7 +693,7 @@ insert_CM(a_hostName)
  *     Nothing.
  *----------------------------------------------------------------------*/
 int
-print_CM()
+print_CM(void)
 {                              /* print_CM() */
     static char rn[] = "print_CM";
     struct afsmon_hostEntry *tempCM;
@@ -745,8 +745,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 */
@@ -823,8 +822,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 */
@@ -928,12 +926,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 */
@@ -1107,8 +1103,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 */
@@ -1357,12 +1352,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++) {
@@ -1390,8 +1379,6 @@ parse_showEntry(a_line)
     }
     /* it is an cm entry */
     return (0);
-
-
 }                              /* parse_showEntry */
 
 
@@ -1415,8 +1402,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 */
@@ -1668,12 +1654,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 */
 
@@ -1690,16 +1677,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++;
            }
@@ -1726,14 +1717,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,
@@ -1741,6 +1731,19 @@ 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;
+    default:
+       if (index < 0) {
+           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
@@ -1749,7 +1752,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;
        }
     }
@@ -1757,13 +1760,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,
@@ -1771,7 +1774,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 */
@@ -1783,7 +1786,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);
     }
 
@@ -1796,14 +1799,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();
@@ -1829,24 +1834,55 @@ 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);
     }
 
+    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 */
+
+/*-----------------------------------------------------------------------
+ * 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;
+    int idx;
+    int i, j;
+    afs_int32 *tmpbuf;
+    afs_int32 numInt32s;
+
     fullPerfP = (struct fs_stats_FullPerfStats *)
        (a_fsResults->data.AFS_CollData_val);
 
@@ -1855,6 +1891,25 @@ fs_Results_ltoa(a_fsData, a_fsResults)
      * - fullPerfP->det which gives detailed info about file server operation
      * execution times */
 
+    /*
+     * Unfortunately, the full perf stats contain timeval structures which
+     * do not have the same size everywhere. Avoid displaying gargbage,
+     * but at least try to show the overall stats.
+     */
+    numInt32s = a_fsResults->data.AFS_CollData_len;
+    if (numInt32s !=
+       (sizeof(struct fs_stats_FullPerfStats) / sizeof(afs_int32))) {
+       srcbuf = a_fsResults->data.AFS_CollData_val;
+       for (i = 0; i < NUM_FS_STAT_ENTRIES; i++) {
+           if (i < numInt32s && i < NUM_XSTAT_FS_AFS_PERFSTATS_LONGS) {
+               sprintf(a_fsData->data[i], "%d", srcbuf[i]);
+           } else {
+               sprintf(a_fsData->data[i], "%s", "--");
+           }
+       }
+       return 0;
+    }
+
     /* copy overall performance statistics */
     srcbuf = (afs_int32 *) & (fullPerfP->overall);
     idx = 0;
@@ -1941,9 +1996,35 @@ 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()
@@ -1960,15 +2041,12 @@ 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";
@@ -2067,10 +2145,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";
@@ -2082,7 +2158,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);
     }
@@ -2162,15 +2238,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;
@@ -2181,12 +2256,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;
@@ -2225,7 +2298,7 @@ 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.
@@ -2252,9 +2325,6 @@ save_FS_data_forDisplay(a_fsResults)
            afsmon_Exit(75);
        }
 
-
-
-
        /* print the info we just saved */
 
        if (afsmon_debug) {
@@ -2275,9 +2345,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,
@@ -2296,12 +2366,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++;
        }
 
@@ -2359,7 +2429,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 ? */
@@ -2368,9 +2438,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);
     }
 
@@ -2403,6 +2474,7 @@ afsmon_FS_Handler()
        }
     }
 
+
     /* store the results of this probe in the FS circular buffer */
     if (num_bufSlots)
        save_FS_results_inCB(newProbeCycle);
@@ -2429,12 +2501,13 @@ afsmon_FS_Handler()
  *----------------------------------------------------------------------*/
 
 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 */
 
@@ -2451,16 +2524,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++;
            }
@@ -2489,14 +2567,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) {
@@ -2505,6 +2582,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() */
@@ -2512,7 +2597,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;
        }
     }
@@ -2520,13 +2605,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,
@@ -2534,7 +2619,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 */
@@ -2546,7 +2631,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);
     }
 
@@ -2563,14 +2648,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);        */
@@ -2598,9 +2684,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 */
@@ -2612,7 +2697,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);
     }
@@ -2847,10 +2932,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";
@@ -2862,7 +2945,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);
     }
@@ -2944,15 +3027,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;
@@ -2962,7 +3044,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);
     }
 
@@ -3033,7 +3115,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");
@@ -3093,9 +3174,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,
@@ -3120,7 +3201,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++;
        }
 
@@ -3177,7 +3258,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 */
@@ -3246,7 +3327,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 */
@@ -3291,36 +3372,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 */
@@ -3364,7 +3446,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 */
@@ -3407,36 +3489,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 =
+                       (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_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 */
@@ -3487,7 +3572,7 @@ init_cm_buffers()
  *------------------------------------------------------------------------*/
 
 int
-init_print_buffers()
+init_print_buffers(void)
 {                              /* init_print_buffers */
 
     static char rn[] = "init_print_buffers";   /* routine name */
@@ -3546,8 +3631,6 @@ 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 */
@@ -3598,11 +3681,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 */
@@ -3626,7 +3706,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 */
@@ -3638,12 +3718,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);
@@ -3653,6 +3733,8 @@ 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);
@@ -3691,18 +3773,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 */
@@ -3718,8 +3804,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);
@@ -3732,6 +3818,8 @@ 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);
@@ -3776,16 +3864,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 ? */
@@ -3801,8 +3881,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);
@@ -3828,7 +3908,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);
@@ -3876,8 +3956,7 @@ afsmon_execute()
  *----------------------------------------------------------------------*/
 
 int
-afsmonInit(as)
-     struct cmd_syndesc *as;
+afsmonInit(struct cmd_syndesc *as, void *arock)
 {                              /* afsmonInit() */
 
     static char rn[] = "afsmonInit";   /* Routine name */
@@ -3889,7 +3968,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);
     }
 
@@ -4154,12 +4233,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 */
 
@@ -4181,7 +4256,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,