localtime can return NULL if unable to read system clock
[openafs.git] / src / afsmonitor / afsmon-win.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Afsmon-win: Curses interface for the Afsmonitor using the gtx library.
12  *
13  *-------------------------------------------------------------------------*/
14
15 #include <afsconfig.h>
16 #include <afs/param.h>
17
18
19 #include <stdio.h>
20 #include <signal.h>
21 #include <math.h>
22 #include <afs/cmd.h>
23 #include <string.h>
24 #undef IN
25 #include <time.h>
26
27 #include <afs/gtxwindows.h>             /*Generic window package */
28 #include <afs/gtxobjects.h>             /*Object definitions */
29 #include <afs/gtxkeymap.h>
30 #include <afs/gtxlightobj.h>    /*Light object interface */
31 #include <afs/gtxcurseswin.h>   /*Curses window package */
32 #include <afs/gtxdumbwin.h>             /*Dumb terminal window package */
33 #include <afs/gtxX11win.h>              /*X11 window package */
34 #include <afs/gtxframe.h>               /*Frame package */
35
36 #include <afs/xstat_fs.h>
37 #include <afs/xstat_cm.h>
38
39
40 #include "afsmonitor.h"
41 #include "afsmon-labels.h"
42
43
44 /* afsmonitor version number */
45 static char afsmon_version[] = "1.0";
46
47 /* EXTERNAL VARIABLES (from afsmonitor.c) */
48
49 extern int afsmon_debug;        /* debug info to file ? */
50 extern FILE *debugFD;           /* debugging file descriptor */
51 extern char errMsg[256];        /* buffers used to print error messages after */
52 extern char errMsg1[256];       /* gtx is initialized (stderr/stdout gone !) */
53
54 /* number of fileservers and cache managers to monitor */
55 extern int numFS;
56 extern int numCM;
57
58 /* number of FS alerts and number of hosts on FS alerts */
59 extern int num_fs_alerts;
60 extern int numHosts_onfs_alerts;
61
62 /* number of CM alerts and number of hosts on FS alerts */
63 extern int num_cm_alerts;
64 extern int numHosts_oncm_alerts;
65
66 /* ptr to array holding the results of FS probes in ascii format */
67 extern struct fs_Display_Data *prev_fsData;
68
69 /* ptr to array holding the results of CM probes in ascii format */
70 extern struct cm_Display_Data *prev_cmData;
71
72 extern int afsmon_fs_curr_probeNum;     /* current fs probe number */
73 extern int afsmon_fs_prev_probeNum;     /* previous fs probe number */
74 extern int afsmon_cm_curr_probeNum;     /* current cm probe number */
75 extern int afsmon_cm_prev_probeNum;     /* previous cm probe number */
76
77 extern int afsmon_probefreq;    /* probe frequency */
78
79 /* map of fs results items we must display. This array contains indices to
80 the fs_varNames[] array corresponding to the stats we want to display. It is
81 initialized while processing the config file */
82
83 extern short fs_Display_map[XSTAT_FS_FULLPERF_RESULTS_LEN];
84 extern int fs_DisplayItems_count;       /* number of items to display */
85
86 extern short cm_Display_map[XSTAT_FS_FULLPERF_RESULTS_LEN];
87 extern int cm_DisplayItems_count;       /* number of items to display */
88
89
90 /* GTX VARIABLES */
91
92 /* minimum window size */
93 #define MINX 80
94 #define MINY 12
95
96 /* justifications */
97 #define RIGHT_JUSTIFY 0
98 #define LEFT_JUSTIFY 1
99 #define CENTER 2
100
101 /* width of overview frame objects */
102 /* field widths include the terminating null character */
103
104 #define PROGNAME_O_WIDTH (maxX/2)       /* program name object */
105 #define OVW_PAGENUM_O_WIDTH     29      /* page number object */
106 #define OVW_PROBENUM_O_WIDTH  39        /* probe number object */
107 #define OVW_CMD_O_WIDTH  (maxX/2)       /* cmd line object */
108 #define OVW_NUMFS_O_WIDTH       40      /* num FSs monitored */
109 #define OVW_NUMCM_O_WIDTH       40      /* num CMs monitored */
110 #define OVW_FSALERTS_O_WIDTH 40 /* num FS alerts */
111 #define OVW_CMALERTS_O_WIDTH 40 /* num CM alerts */
112 #define OVW_HOSTNAME_O_WIDTH (maxX / 2) /* FS & CM host names */
113 #define OVW_HOSTNAME_O_WIDTH_HGL 30     /* cosmetic, atleast this many chars
114                                          * will be highlightned */
115
116 /* widths of FS and CM frame objects */
117 #define FC_NUMHOSTS_O_WIDTH  (maxX - 8) /* number of fs monitored. leave 4
118                                          * chars on either side for '<<','>>' */
119 #define FC_PAGENUM_O_WIDTH 43
120 #define FC_HOSTNAME_O_WIDTH 11  /* width of FS hostnames column */
121 #define FC_CMD_O_WIDTH    55    /* width of cmd line */
122 #define FC_PROBENUM_O_WIDTH 30  /* width of probe number object */
123 #define FC_ARROWS_O_WIDTH    4  /* width of arrow indicators */
124 #define FC_COLUMN_WIDTH    11   /* width of data columns */
125
126 /* bit definitions for use in resolving command line */
127 /* these bits are set in the xx_pageType variables to indicate what commands
128 are acceptable */
129
130 #define CMD_NEXT  1             /* next page ? */
131 #define CMD_PREV  2             /* previous page ? */
132 #define CMD_LEFT  4             /* left scroll ? */
133 #define CMD_RIGHT 8             /* right scroll ? */
134 #define CMD_FS    16            /* file servers frame exists ? */
135 #define CMD_CM    32            /* cache managers frame exists ? */
136
137
138 #define FC_NUM_FIXED_LINES 10   /* number of fixed lines */
139 #define FC_FIRST_HOST_ROW 8     /* first host entry row number */
140 #define FC_FIRST_LABEL_ROW 4    /* first label row number */
141
142 /* number of fixed lines (that dont change) on the overview screen */
143 #define OVW_NUM_FIXED_LINES 7
144 #define OVW_FIRST_HOST_ROW 5    /* row index of first host entry in ovw frame */
145
146 #define HIGHLIGHT 1             /* highlight object? */
147
148 static char blankline[256];     /* blank line */
149
150 /* maximum X & Y coordinates of the frames */
151 int maxX;
152 int maxY;
153
154 struct gwin *afsmon_win;        /* afsmonitor window */
155 int gtx_initialized = 0;
156
157 /* Overview screen related definitions */
158
159 struct gtx_frame *ovwFrame;     /* overview screen frame */
160 struct gwin_sizeparams frameDims;       /* frame dimensions. all frames have
161                                          * same dimensions */
162
163 /* overview frame object names */
164 struct onode *ovw_progName_o;   /* program name object */
165 struct onode *ovw_pageNum_o;    /* page number onject */
166 struct onode *ovw_cmd_o;        /* command line object */
167 struct onode *ovw_probeNum_o;   /* probe number object */
168 struct onode *ovw_numFS_o;      /* num FS monitored */
169 struct onode *ovw_numCM_o;      /* num CM monitored */
170 struct onode *ovw_FSalerts_o;   /* nunber of FS alerts */
171 struct onode *ovw_CMalerts_o;   /* nunber of CM alerts */
172 struct onode *initMsg_o;        /* initialization message */
173
174 /* number of pages of data for the overview frame */
175 int ovw_numPages = 0;
176 int ovw_currPage = 1;           /* current page number */
177
178 static int ovw_pageType = 0;    /* one of the above types */
179
180 /* number of rows of server names that can be displayed on one overview page*/
181 int ovw_numHosts_perPage;
182
183 /* ptr to a block of ovw_numHosts_perPage number of objects for file servers */
184 struct onode **ovw_fsNames_o;
185 /*ptr to a block of ovw_numHosts_perPage number of objects for cache managers */
186 struct onode **ovw_cmNames_o;
187
188 /* When the ovw_refresh routine is called by the keyboard handlers the
189 following variable is used to determine if fs/cm/fs&cm info must be updated */
190 int ovw_update_info = 0;
191
192 /* Variables needed to display an intialization message on startup */
193 static char *initMsg = "AFSMonitor Collecting Statistics ...";
194 static int initMsg_on = 0;      /* message on ? */
195
196 /* FILE SERVER Screen related definitions */
197
198 struct gtx_frame *fsFrame;      /* File Server screen frame */
199
200 struct onode *fs_pageNum_o;     /* fs page number object */
201 struct onode *fs_cmd_o;         /* fs command line object */
202 struct onode *fs_probeNum_o;    /* fs probe number object */
203 struct onode *fs_numFS_o;       /* fs number of FSs object */
204 struct onode *fs_leftArrows_o;  /* fs cols on left signal object */
205 struct onode *fs_rightArrows_o; /* fs cols on right signal object */
206 struct onode **fs_hostNames_o;  /* ptr to host names objects */
207
208 /* bit-map to characterize page type and contents of command prompt */
209 static int fs_pageType = 0;
210
211 /* coordinates for the File Servers screen */
212
213 /* we use page numbers to navigate vertically (ie, across hosts) and column
214 numbers to navigate horizontally */
215
216 int fs_numHosts_perPage;        /* number of file servers per page */
217 int fs_cols_perPage;            /* number of data columns per file server page */
218 int fs_currPage;                /* current FS page number */
219 int fs_numPages;                /* number of FS pages */
220
221 /* column numbers are index to the mapping structure fs_Display_map. this
222 map contains the indices of datums that should be displayed */
223
224 int fs_numCols;                 /* number of columns of FS data (excluding hostname) */
225                         /* this is the same as fs_DisplayItems_count */
226 /* following column indices run from 1 to (fs_numCols -1) */
227 int fs_curr_LCol = 0;           /* column number of leftmost column on display */
228 int fs_curr_RCol = 0;           /* column number of rightmost column on display */
229 int fs_Data_Available = 0;      /* atleast one fs probe cycle completed ? */
230
231
232 /* structure that defines a line of data in the fs/cm frames */
233
234 /* we store each datum value in two objects, one below the other. The reason
235 for doing this is to conserve screen area. most of the datums are just longs
236 and will fit into one object. some of them are timing values and require 13
237 characters to be displayed - such fields may overflow to the second object
238 placed below the first one. */
239
240 struct ServerInfo_line {
241     struct onode *host_o;       /* hostname object */
242     struct onode **data_o[2];   /* ptrs to two arrays of data objects. */
243
244 };
245
246 struct ServerInfo_line *fs_lines;       /* ptr to the file server data objects */
247
248 /* file server label onodes - three rows of them */
249 struct onode **fsLabels_o[3];
250
251 /* CACHE MANAGER Screen related definitions */
252
253 struct gtx_frame *cmFrame;      /* Cache Manager screen frame */
254
255 struct onode *cm_pageNum_o;     /* cm page number object */
256 struct onode *cm_cmd_o;         /* cm command line object */
257 struct onode *cm_probeNum_o;    /* cm probe number object */
258 struct onode *cm_numCM_o;       /* cm number of FSs object */
259 struct onode *cm_leftArrows_o;  /* fs cols on left signal object */
260 struct onode *cm_rightArrows_o; /* fs cols on right signal object */
261
262 struct onode **cm_hostNames_o;  /* ptr to host names objects */
263
264 /* bit-map to characterize page type and contents of command prompt */
265 static int cm_pageType = 0;
266
267 /* coordinates for the Cache Managers screen */
268
269 /* we use page numbers to navigate vertically (ie, across hosts) and column
270 numbers to navigate horizontally */
271
272 int cm_numHosts_perPage;        /* number of cache managers per page */
273 int cm_cols_perPage;            /* number of data columns per file server page */
274 int cm_currPage;                /* current CM page number */
275 int cm_numPages;                /* number of CM pages */
276
277 /* column numbers are index to the mapping structure cm_Display_map. this
278 map contains the indices of datums that should be displayed */
279
280 int cm_numCols;                 /* number of columns of FS data (excluding hostname) */
281                         /* this is the same as cm_DisplayItems_count */
282 /* following column indices run from 1 to (cm_numCols -1) */
283 int cm_curr_LCol = 0;           /* column number of leftmost column on display */
284 int cm_curr_RCol = 0;           /* column number of rightmost column on display */
285 int cm_Data_Available = 0;      /* atleast one cm probe cycle completed ? */
286
287
288 /* structure that defines a line of data in the fs/cm frames */
289 struct ServerInfo_line *cm_lines;       /* ptr to the file server data objects */
290
291 /* file server label onodes - three rows of them */
292 struct onode **cmLabels_o[3];
293
294
295
296 /*------------------------------------------------------------------------
297  * initLightObject
298  *
299  * Description:
300  *      Create and initialize a light onode according to the given
301  *      parameters.
302  *      ( Borrowed from scout.c )
303  *
304  * Arguments:
305  *      char *a_name       : Ptr to the light's string name.
306  *      int a_x            : X offset.
307  *      int a_y            : Y offset.
308  *      int a_width        : Width in chars.
309  *      struct gwin *a_win : Ptr to window structure.
310  *
311  * Returns:
312  *      Ptr to new light onode on success,
313  *      A null pointer otherwise.
314  *
315  * Environment:
316  *      See above.
317  *
318  * Side Effects:
319  *      As advertised.
320  *------------------------------------------------------------------------*/
321
322 static struct onode *
323 initLightObject(char *a_name, int a_x, int a_y, int a_width,
324                 struct gwin *a_win)
325 {                               /*initLightObject */
326     struct onode *newlightp;    /*Ptr to new light onode */
327     struct gator_light_crparams light_crparams; /*Light creation params */
328     char *truncname;            /*Truncated name, if needed */
329     int name_len;               /*True length of name */
330
331 /* the following debug statement floods the debug file */
332 #ifdef DEBUG_DETAILED
333     if (afsmon_debug) {
334         fprintf(debugFD,
335                 "[ %s ] Called, a_name= %s, a_x= %d, a_y= %d, a_width= %d, a_win= %d\n",
336                 rn, a_name, a_x, a_y, a_width, a_win);
337         fflush(debugFD);
338     }
339 #endif
340
341     newlightp = NULL;
342
343     /*
344      * Set up the creation parameters according to the information we've
345      * received.
346      */
347     light_crparams.onode_params.cr_type = GATOR_OBJ_LIGHT;
348     name_len = strlen(a_name);
349
350     if (name_len <= a_width)
351         sprintf(light_crparams.onode_params.cr_name, "%s", a_name);
352     else {
353         /*
354          * We need to truncate the given name, leaving a `*' at the end to
355          * show us it's been truncated.
356          */
357         truncname = light_crparams.onode_params.cr_name;
358         strncpy(truncname, a_name, a_width - 1);
359         truncname[a_width - 1] = '*';
360         truncname[a_width] = 0;
361     }
362     light_crparams.onode_params.cr_x = a_x;
363     light_crparams.onode_params.cr_y = a_y;
364     light_crparams.onode_params.cr_width = a_width;
365     light_crparams.onode_params.cr_height = 1;
366     light_crparams.onode_params.cr_window = a_win;
367     light_crparams.onode_params.cr_home_obj = NULL;
368     light_crparams.onode_params.cr_prev_obj = NULL;
369     light_crparams.onode_params.cr_parent_obj = NULL;
370     light_crparams.onode_params.cr_helpstring = NULL;
371
372     light_crparams.appearance = 0;
373     light_crparams.flashfreq = 0;
374     sprintf(light_crparams.label, "%s", a_name);
375     light_crparams.label_x = 0;
376     light_crparams.label_y = 0;
377
378     newlightp =
379         gator_objects_create((struct onode_createparams *)(&light_crparams));
380
381     /*
382      * Return the news, happy or not.
383      */
384     return (newlightp);
385
386 }                               /*initLightObject */
387
388
389
390 /*------------------------------------------------------------------------
391  * justify_light
392  *
393  * Description:
394  *      Place the chars in the source buffer into the target buffer
395  *      with the desired justification, either centered, left-justified
396  *      or right-justified.  Also, support inidication of truncation
397  *      with a star (*), either on the left or right of the string,
398  *      and whether we're justifying a labeled disk quantity.
399  *
400  *      (derived from mini_justify() in scout.c)
401  *
402  * Arguments:
403  *      char *a_srcbuff     : Ptr to source char buffer.
404  *      char *a_dstbuff     : Ptr to dest char buffer.
405  *      int a_dstwidth      : Width of dest buffer in chars.
406  *      int a_justification : Kind of justification.
407  *      int a_rightTrunc    : If non-zero, place the truncation char
408  *                            on the right of the string.  Otherwise,
409  *                            place it on the left.
410  *
411  * Returns:
412  *      0 on success,
413  *      -1 otherwise.
414  *
415  *------------------------------------------------------------------------*/
416
417 int
418 justify_light(char *a_srcbuff, char *a_dstbuff, int a_dstwidth,
419               int a_justification, int a_rightTrunc)
420 {                               /*justify_light */
421
422     static char rn[] = "justify_light"; /*Routine name */
423     int leftpad_chars;          /*# of chars for left-padding */
424     int num_src_chars;          /*# of chars in source */
425     int true_num_src_chars;     /*# src chars before truncation */
426     int trunc_needed;           /*Is truncation needed? */
427
428
429 /* the following debug statement floods the debug file */
430 #ifdef DEBUG_DETAILED
431     if (afsmon_debug) {
432         fprintf(debugFD,
433                 "[ %s ] Called, a_srcbuff= %s, a_dstbuff= %d, a_dstwidth= %d, a_justification= %d, a_rightTrunc= %d\n",
434                 rn, a_srcbuff, a_dstbuff, a_dstwidth, a_justification,
435                 a_rightTrunc);
436         fflush(debugFD);
437     }
438 #endif
439
440
441     /*
442      * If the destination width will overrun the gtx string storage,
443      * we automatically shorten up.
444      */
445     if (a_dstwidth > GATOR_LABEL_CHARS) {
446         /*
447          * if (afsmon_debug) {
448          * fprintf(debugFD,
449          * "[%s] Dest width (%d) > gtx buflen (%d), shrinking dest width\n",
450          * rn, a_dstwidth, GATOR_LABEL_CHARS);
451          * fflush(debugFD);
452          * }
453          */
454         a_dstwidth = GATOR_LABEL_CHARS;
455     }
456
457     /*
458      * If our source string is too long, prepare for truncation.
459      */
460     true_num_src_chars = strlen(a_srcbuff);
461     if (true_num_src_chars >= a_dstwidth) {
462         trunc_needed = 1;
463         num_src_chars = a_dstwidth - 1;
464         leftpad_chars = 0;
465         if (!a_rightTrunc)
466             a_srcbuff += (true_num_src_chars - num_src_chars);
467     } else {
468         trunc_needed = 0;
469         num_src_chars = true_num_src_chars;
470
471         /*
472          * Compute the necessary left-padding.
473          */
474         switch (a_justification) {
475
476         case RIGHT_JUSTIFY:
477             leftpad_chars = (a_dstwidth - 1) - num_src_chars;
478             break;
479
480         case LEFT_JUSTIFY:
481             /*
482              * This is the really easy one.
483              */
484             leftpad_chars = 0;
485             break;
486
487         case CENTER:
488             leftpad_chars = ((a_dstwidth - 1) - num_src_chars) / 2;
489             break;
490
491         default:
492             if (afsmon_debug) {
493                 fprintf(debugFD, "[%s] Illegal justification command: %d", rn,
494                         a_justification);
495                 fprintf(debugFD, "[%s] Called with '%s', dest width=%d\n", rn,
496                         a_srcbuff, a_dstwidth);
497                 fflush(debugFD);
498             }
499             return (-1);
500         }                       /*Switch on justification type */
501     }
502
503     /*
504      * Clear out the dest buffer, then place the source string at the
505      * appropriate padding location.  Remember to place a string
506      * terminator at the end of the dest buffer, plus whatever truncation
507      * may be needed.  If we're left-truncating, we've already shifted
508      * the src buffer appropriately.
509      */
510     strncpy(a_dstbuff, blankline, a_dstwidth);
511     strncpy(a_dstbuff + leftpad_chars, a_srcbuff, num_src_chars);
512     *(a_dstbuff + a_dstwidth - 1) = '\0';
513     if (trunc_needed) {
514         if (a_rightTrunc)
515             *(a_dstbuff + a_dstwidth - 2) = '*';        /*Truncate on the right */
516         else {
517             *a_dstbuff = '*';   /*Truncate on the left, non-disk */
518         }
519     }
520
521     /*Handle truncations */
522     /*
523      * Return the good news.
524      */
525     return (0);
526
527 }                               /*justify_light */
528
529
530
531 /*-----------------------------------------------------------------------
532  * afsmonExit_gtx()
533  *
534  * Description:
535  *      Call the exit routine. This function is mapped
536  *      to the keys Q and \ 3 in all the frames and is called by the
537  *      gtx input server.
538  *----------------------------------------------------------------------*/
539
540 int
541 afsmonExit_gtx(void *d1, void *d2)
542 {
543     static char rn[] = "afsmonExit_gtx";
544
545     if (afsmon_debug) {
546         fprintf(debugFD, "[ %s ] Called\n", rn);
547         fflush(debugFD);
548     }
549
550     afsmon_Exit(0);
551     return 0; /* not reached */
552 }
553
554
555 /*-----------------------------------------------------------------------
556  * ovw_refresh()
557  *
558  * Description:
559  *      Refresh the overview screen with the contents of the specified page.
560  *      There are two parts to the overview screen - the file server column
561  *      and the cache manager column and each of them is independent of the
562  *      other. Hence it takes as an argumnet the "type" of update to be
563  *      performed.
564  *
565  * Returns:
566  *      Success: 0
567  *      Failure: Exits afsmonitor.
568  *----------------------------------------------------------------------*/
569
570 int
571 ovw_refresh(int a_pageNum,      /* page to refresh overview display */
572             int a_updateType)   /* OVW_UPDATE_FS = update fs column only,
573                                  * OVW_UPDATE_CM = update cm column only,
574                                  * OVW_UPDATE_BOTH = update fs & cm columns. Note that
575                                  * we do not want to update a column until the
576                                  * corresponding probe cycle has completed */
577 {                               /* ovw_refresh */
578
579     static char rn[] = "ovw_refresh";   /* routine name */
580     struct onode **tmp_fsNames_o;       /* ptr to fsNames onodes */
581     struct gator_lightobj *tmp_lightobj;        /* ptr for object's display data */
582     struct fs_Display_Data *fsDataP;    /* ptr to FS display data array */
583     struct onode **tmp_cmNames_o;       /* ptr to fsNames onodes */
584     struct cm_Display_Data *cmDataP;    /* ptr to CM display data array */
585     int fsIdx;                  /* for counting # of CM hosts */
586     int cmIdx;                  /* for counting # of CM hosts */
587     char cmdLine[80];           /* buffer for command line */
588     char printBuf[256];         /* buffer to print to screen */
589     int i;
590     int code;
591     int len;
592
593     if (afsmon_debug) {
594         fprintf(debugFD, "[ %s ] Called, a_pageNum= %d, a_updateType= %d\n",
595                 rn, a_pageNum, a_updateType);
596         fflush(debugFD);
597     }
598
599     /* if the data is not yet available  ie., not one probe cycle has
600      * completed, do nothing */
601
602     if ((a_updateType & OVW_UPDATE_FS) && !fs_Data_Available)
603         return (0);
604     if ((a_updateType & OVW_UPDATE_CM) && !cm_Data_Available)
605         return (0);
606
607
608     /* validate page number */
609     if (a_pageNum < 1 || a_pageNum > ovw_numPages) {
610         sprintf(errMsg, "[ %s ] called with incorrect page number %d\n", rn,
611                 a_pageNum);
612         afsmon_Exit(235);
613     }
614
615     /* set the current page number */
616     ovw_currPage = a_pageNum;
617
618     /* turn off init message */
619     if (initMsg_on) {
620         initMsg_on = 0;
621         gtxframe_RemoveFromList(ovwFrame, initMsg_o);
622     }
623
624     /* update the labels */
625
626     /* version label */
627     tmp_lightobj = (struct gator_lightobj *)ovw_progName_o->o_data;
628     sprintf(printBuf, "AFSMonitor [Version %s]", afsmon_version);
629     justify_light(printBuf, tmp_lightobj->label, strlen(printBuf) + 1,
630                   LEFT_JUSTIFY, 1);
631     gator_light_set(ovw_progName_o, 1);
632
633     /* page number label */
634     tmp_lightobj = (struct gator_lightobj *)ovw_pageNum_o->o_data;
635     sprintf(printBuf, "[System Overview, p. %d of %d]", ovw_currPage,
636             ovw_numPages);
637     justify_light(printBuf, tmp_lightobj->label, OVW_PAGENUM_O_WIDTH,
638                   RIGHT_JUSTIFY, 1);
639     gator_light_set(ovw_pageNum_o, 1);
640
641     /* file servers monitored label */
642     tmp_lightobj = (struct gator_lightobj *)ovw_numFS_o->o_data;
643     sprintf(printBuf, "    %d File Servers monitored", numFS);
644     justify_light(printBuf, tmp_lightobj->label, strlen(printBuf) + 1,
645                   LEFT_JUSTIFY, 1);
646
647     /* cache managers monitored label */
648     tmp_lightobj = (struct gator_lightobj *)ovw_numCM_o->o_data;
649     sprintf(printBuf, "    %d Cache Managers monitored", numCM);
650     justify_light(printBuf, tmp_lightobj->label, strlen(printBuf) + 1,
651                   LEFT_JUSTIFY, 1);
652
653
654     /* no. of fs alerts label */
655     tmp_lightobj = (struct gator_lightobj *)ovw_FSalerts_o->o_data;
656     sprintf(printBuf, "    %d alerts on %d machines", num_fs_alerts,
657             numHosts_onfs_alerts);
658     justify_light(printBuf, tmp_lightobj->label, strlen(printBuf) + 1,
659                   LEFT_JUSTIFY, 1);
660
661     /* no. of cm alerts label */
662     tmp_lightobj = (struct gator_lightobj *)ovw_CMalerts_o->o_data;
663     sprintf(printBuf, "    %d alerts on %d machines", num_cm_alerts,
664             numHosts_oncm_alerts);
665     justify_light(printBuf, tmp_lightobj->label, strlen(printBuf) + 1,
666                   LEFT_JUSTIFY, 1);
667
668     /* command line */
669     /* determine if we have fs/cm, more/previous pages of data to display */
670
671     ovw_pageType = 0;
672     if (numFS && fs_Data_Available)
673         ovw_pageType |= CMD_FS; /* we have an fs frame & data avail. */
674     if (numCM && cm_Data_Available)
675         ovw_pageType |= CMD_CM; /* we have a cm frame & data avail. */
676     if (ovw_currPage > 1)
677         ovw_pageType |= CMD_PREV;       /* got a previous page */
678     if (ovw_currPage < ovw_numPages)
679         ovw_pageType |= CMD_NEXT;       /* got a next page */
680
681     strcpy(cmdLine, "Command [");
682     if ((ovw_pageType & CMD_FS) && (ovw_pageType & CMD_CM))
683         strcat(cmdLine, "fs, cm");
684     else if (ovw_pageType & CMD_FS)
685         strcat(cmdLine, "fs");
686     else if (ovw_pageType & CMD_CM)
687         strcat(cmdLine, "cm");
688
689     if (ovw_pageType & CMD_PREV)
690         strcat(cmdLine, ", prev");
691     if (ovw_pageType & CMD_NEXT)
692         strcat(cmdLine, ", next");
693
694     strcat(cmdLine, "]? ");
695
696     /* display the command line */
697     tmp_lightobj = (struct gator_lightobj *)ovw_cmd_o->o_data;
698     sprintf(printBuf, "%s", cmdLine);
699     justify_light(printBuf, tmp_lightobj->label, strlen(printBuf) + 1,
700                   LEFT_JUSTIFY, 1);
701     gator_light_set(ovw_cmd_o, 1);
702
703     /* display probe numbers line */
704     tmp_lightobj = (struct gator_lightobj *)ovw_probeNum_o->o_data;
705     sprintf(printBuf, "[probes %d(fs) %d(cm), freq=%d sec]",
706             afsmon_fs_prev_probeNum, afsmon_cm_prev_probeNum,
707             afsmon_probefreq);
708     justify_light(printBuf, tmp_lightobj->label, OVW_PROBENUM_O_WIDTH,
709                   RIGHT_JUSTIFY, 1);
710     gator_light_set(ovw_probeNum_o, 1);
711
712     /* update the file server names column if we are asked to */
713
714     if (numFS && (a_updateType & OVW_UPDATE_FS)) {
715
716         /* move to the right spot in the FS display data array */
717         fsDataP = prev_fsData;
718         fsIdx = 0;
719         for (i = 0; i < ((a_pageNum - 1) * ovw_numHosts_perPage); i++) {
720             fsDataP++;
721             fsIdx++;
722         }
723
724         /* get the address to the first FS name */
725         tmp_fsNames_o = ovw_fsNames_o;
726
727         for (i = 0; i < ovw_numHosts_perPage; i++) {
728             if (fsIdx < numFS) {        /* this could be the last & partial page */
729
730                 if (fsDataP->hostName[0] == '\0') {
731                     sprintf(errMsg, "[ %s ] empty fs display entry \n", rn);
732                     afsmon_Exit(240);
733                 }
734
735                 /* check if the probe succeeded. if it did check for thresholds
736                  * overflow. A failed probe is indicated by "PF" */
737
738                 if (!fsDataP->probeOK) {
739                     sprintf(printBuf, "[ PF] %s", fsDataP->hostName);
740                 } else if (fsDataP->ovfCount)   /* thresholds overflow */
741                     sprintf(printBuf, "[%3d] %s", fsDataP->ovfCount,
742                             fsDataP->hostName);
743                 else {
744                     sprintf(printBuf, "      %s", fsDataP->hostName);
745
746                 }
747                 if (afsmon_debug)
748                     fprintf(debugFD, "[ %s ] to display %s\n", rn, printBuf);
749
750                 tmp_lightobj =
751                     (struct gator_lightobj *)(*tmp_fsNames_o)->o_data;
752
753                 if (strlen(printBuf) + 1 < OVW_HOSTNAME_O_WIDTH_HGL)
754                     len = OVW_HOSTNAME_O_WIDTH_HGL;
755                 else
756                     len = strlen(printBuf) + 1;
757
758                 code =
759                     justify_light(printBuf, tmp_lightobj->label, len,
760                                   LEFT_JUSTIFY, 1);
761                 if (code) {
762                     if (afsmon_debug) {
763                         fprintf(debugFD, "[ %s ] justify_code returned %d\n",
764                                 rn, code);
765                     }
766                 }
767
768                 /* highlighten if overflowed or probe failed */
769
770                 if (fsDataP->ovfCount || !fsDataP->probeOK)
771                     gator_light_set(*tmp_fsNames_o, 1);
772                 else
773                     gator_light_set(*tmp_fsNames_o, 0);
774
775
776             } else {            /* no more hosts, blank the rest of the entries */
777                 tmp_lightobj =
778                     (struct gator_lightobj *)(*tmp_fsNames_o)->o_data;
779                 sprintf(tmp_lightobj->label, "%s", "");
780             }
781
782             tmp_fsNames_o++;    /* next onode */
783             fsDataP++;          /* next host's data */
784             fsIdx++;            /* host index */
785         }
786     }
787
788     /* if numFS */
789     /* if we have any cache managers, update them if we are asked to */
790     if (numCM && (a_updateType & OVW_UPDATE_CM)) {
791
792         /* move to the right spot in the CM display data array */
793         cmDataP = prev_cmData;
794         cmIdx = 0;
795         for (i = 0; i < ((a_pageNum - 1) * ovw_numHosts_perPage); i++) {
796             cmDataP++;
797             cmIdx++;
798         }
799
800         /* get the address to the first CM name */
801         tmp_cmNames_o = ovw_cmNames_o;
802
803         for (i = 0; i < ovw_numHosts_perPage; i++) {
804             if (cmIdx < numCM) {        /* this could be the last & partial page */
805
806                 if (cmDataP->hostName[0] == '\0') {
807                     sprintf(errMsg, "[ %s ] empty cm display entry \n", rn);
808                     afsmon_Exit(245);
809                 }
810
811                 /* check if the probe succeeded. if it did check for thresholds
812                  * overflow. A failed probe is indicated by "PF" */
813
814                 if (!cmDataP->probeOK) {
815                     sprintf(printBuf, "[ PF] %s", cmDataP->hostName);
816                 } else if (cmDataP->ovfCount) { /* thresholds overflow */
817                     sprintf(printBuf, "[%3d] %s", cmDataP->ovfCount,
818                             cmDataP->hostName);
819                 } else
820                     sprintf(printBuf, "      %s", cmDataP->hostName);
821
822                 if (afsmon_debug)
823                     fprintf(debugFD, "[ %s ] to display %s\n", rn, printBuf);
824
825                 tmp_lightobj =
826                     (struct gator_lightobj *)(*tmp_cmNames_o)->o_data;
827
828                 if (strlen(printBuf) + 1 < OVW_HOSTNAME_O_WIDTH_HGL)
829                     len = OVW_HOSTNAME_O_WIDTH_HGL;
830                 else
831                     len = strlen(printBuf) + 1;
832
833                 code =
834                     justify_light(printBuf, tmp_lightobj->label, len,
835                                   LEFT_JUSTIFY, 1);
836                 if (code) {
837                     if (afsmon_debug) {
838                         fprintf(debugFD, "[ %s ] justify_code returned %d\n",
839                                 rn, code);
840                     }
841                 }
842
843                 /* highlighten if overflow or if probe failed */
844                 if (cmDataP->ovfCount || !cmDataP->probeOK)
845                     gator_light_set(*tmp_cmNames_o, 1);
846                 else
847                     gator_light_set(*tmp_cmNames_o, 0);
848
849
850             } else {            /* no more hosts, blank the rest of the entries */
851                 tmp_lightobj =
852                     (struct gator_lightobj *)(*tmp_cmNames_o)->o_data;
853                 sprintf(tmp_lightobj->label, "%s", "");
854             }
855
856             tmp_cmNames_o++;    /* next onode */
857             cmDataP++;          /* next host's data */
858             cmIdx++;            /* host index */
859         }
860     }
861
862     /* if numCM */
863     /* redraw the display if the overview screen is currently displayed */
864     if (afsmon_win->w_frame == ovwFrame)
865         WOP_DISPLAY(afsmon_win);
866
867     return (0);
868
869 }                               /* ovw_refresh */
870
871
872
873 /*-----------------------------------------------------------------------
874  * Switch_ovw_2_fs()
875  *
876  * Description:
877  *              Switch from the overview screen to the FS screen
878  *----------------------------------------------------------------------*/
879 int
880 Switch_ovw_2_fs(void *d1, void *d2)
881 {
882     static char rn[] = "Switch_ovw_2_fs";
883
884     if (afsmon_debug) {
885         fprintf(debugFD, "[ %s ] Called\n", rn);
886         fflush(debugFD);
887     }
888
889     /* bind the File Server frame to the window */
890     if (ovw_pageType & CMD_FS)
891         gtxframe_SetFrame(afsmon_win, fsFrame);
892     return (0);
893 }
894
895 /*-----------------------------------------------------------------------
896  * Switch_ovw_2_cm()
897  *
898  * Description:
899  *              Switch from the overview screen to the CM screen
900  *----------------------------------------------------------------------*/
901 int
902 Switch_ovw_2_cm(void *d1, void *d2)
903 {
904     static char rn[] = "Switch_ovw_2_cm";
905
906     if (afsmon_debug) {
907         fprintf(debugFD, "[ %s ] Called\n", rn);
908         fflush(debugFD);
909     }
910
911     /* bind the Cache Managers frame to the window */
912     if (ovw_pageType & CMD_CM)
913         gtxframe_SetFrame(afsmon_win, cmFrame);
914     return (0);
915 }
916
917 /*-----------------------------------------------------------------------
918  * Switch_ovw_next()
919  *
920  * Description:
921  *              Switch to the next page in overview screen
922  *----------------------------------------------------------------------*/
923 int
924 Switch_ovw_next(void *d1, void *d2)
925 {
926     static char rn[] = "Switch_ovw_next";
927
928     if (afsmon_debug) {
929         fprintf(debugFD, "[ %s ] Called\n", rn);
930         fflush(debugFD);
931     }
932
933     if (ovw_pageType & CMD_NEXT) {
934         /* call refresh with the next page number */
935         ovw_refresh(ovw_currPage + 1, ovw_update_info);
936     }
937
938     return (0);
939 }
940
941 /*-----------------------------------------------------------------------
942  * Switch_ovw_last()
943  *
944  * Description:
945  *              Switch to the last page in the overview screen
946  *----------------------------------------------------------------------*/
947 int
948 Switch_ovw_last(void *d1, void *d2)
949 {
950     static char rn[] = "Switch_ovw_last";
951
952     if (afsmon_debug) {
953         fprintf(debugFD, "[ %s ] Called\n", rn);
954         fflush(debugFD);
955     }
956
957     if (ovw_pageType & CMD_NEXT) {
958         /* call refresh with the last page number */
959         ovw_refresh(ovw_numPages, ovw_update_info);
960     }
961
962     return (0);
963 }
964
965 /*-----------------------------------------------------------------------
966  * Switch_ovw_prev()
967  *
968  * Description:
969  *              Switch to the previous page in the overview screen
970  *----------------------------------------------------------------------*/
971 int
972 Switch_ovw_prev(void *d1, void *d2)
973 {
974     static char rn[] = "Switch_ovw_prev";
975
976     if (afsmon_debug) {
977         fprintf(debugFD, "[ %s ] Called\n", rn);
978         fflush(debugFD);
979     }
980
981     if (ovw_pageType & CMD_PREV) {
982         /* call refresh with the previous page number */
983         ovw_refresh(ovw_currPage - 1, ovw_update_info);
984     }
985     return (0);
986 }
987
988 /*-----------------------------------------------------------------------
989  * Switch_ovw_first()
990  *
991  * Description:
992  *              Switch to the first page in the overview screen
993  *----------------------------------------------------------------------*/
994 int
995 Switch_ovw_first(void *d1, void *d2)
996 {
997     static char rn[] = "Switch_ovw_first";
998
999     if (afsmon_debug) {
1000         fprintf(debugFD, "[ %s ] Called\n", rn);
1001         fflush(debugFD);
1002     }
1003
1004     if (ovw_pageType & CMD_PREV) {
1005         /* refresh with the first page number */
1006         ovw_refresh(1, ovw_update_info);
1007     }
1008     return (0);
1009 }
1010
1011 /*-----------------------------------------------------------------------
1012  * create_ovwFrame_objects()
1013  *
1014  * Description:
1015  *      Create the gtx objects (onodes) for the overview frame and setup
1016  *      the keyboard bindings.
1017  *      Only as many objects as can fit on the display are created. The
1018  *      positions and lengths of all these objects are fixed at creation.
1019  *      These objects are updated with new data at the end of each probe
1020  *      cycle.
1021  *
1022  * Returns:
1023  *      Success: 0
1024  *      Failure: Exits afsmonitor.
1025  *----------------------------------------------------------------------*/
1026
1027 int
1028 create_ovwFrame_objects(void)
1029 {                               /* create_ovwFrame_objects */
1030
1031     static char rn[] = "create_ovwFrame_objects";
1032     int hostLines;              /* number of lines of host names to display */
1033     struct onode **ovw_fsNames_o_Ptr;   /* index to list of fs names onodes */
1034     struct onode **ovw_cmNames_o_Ptr;   /* index to list of cm names onodes */
1035     int i;
1036
1037     if (afsmon_debug) {
1038         fprintf(debugFD, "[ %s ] Called\n", rn);
1039         fflush(debugFD);
1040     }
1041
1042     /* get frame dimensions, it must be atleast MINXxMINY for any sensible output */
1043     WOP_GETDIMENSIONS(ovwFrame->window, &frameDims);
1044     maxX = frameDims.maxx;
1045     maxY = frameDims.maxy;
1046     if (maxX + 1 < MINX || maxY + 1 < MINY) {
1047         sprintf(errMsg1, "[ %s ] Window size %dx%d; must be at least %dx%d\n",
1048                 rn, maxX + 1, maxY + 1, MINX, MINY);
1049         return (-1);
1050     }
1051     if (afsmon_debug)
1052         fprintf(debugFD, "maxX = %d maxY = %d\n", maxX, maxY);
1053
1054
1055     /* Print an Intial message to the screen. The init message is 36 chars
1056      * long */
1057     initMsg_o =
1058         initLightObject(initMsg, maxX / 2 - 18, maxY / 3, sizeof(initMsg),
1059                         afsmon_win);
1060     if (initMsg_o == NULL) {
1061         sprintf(errMsg, "[ %s ] Failed to create initMsg_o onode\n", rn);
1062         afsmon_Exit(250);
1063     }
1064     gtxframe_AddToList(ovwFrame, initMsg_o);
1065     gator_light_set(initMsg_o, HIGHLIGHT);
1066     initMsg_on = 1;
1067
1068
1069
1070     /* create the command line object */
1071
1072     ovw_cmd_o = initLightObject("", 0, maxY - 1, OVW_CMD_O_WIDTH, afsmon_win);
1073     if (ovw_cmd_o == NULL) {
1074         sprintf(errMsg, "[ %s ] Failed to create command onode\n", rn);
1075         afsmon_Exit(265);
1076     }
1077     gtxframe_AddToList(ovwFrame, ovw_cmd_o);
1078     gator_light_set(ovw_cmd_o, HIGHLIGHT);
1079
1080     /* create the program name object */
1081
1082     ovw_progName_o = initLightObject("", 0, 0, PROGNAME_O_WIDTH, afsmon_win);
1083     if (ovw_progName_o == NULL) {
1084         sprintf(errMsg, "[ %s ] Failed to create programName onode\n", rn);
1085         afsmon_Exit(255);
1086     }
1087     gtxframe_AddToList(ovwFrame, ovw_progName_o);
1088     gator_light_set(ovw_progName_o, HIGHLIGHT);
1089
1090     /* create the page number object */
1091
1092     ovw_pageNum_o =
1093         initLightObject("", maxX - OVW_PAGENUM_O_WIDTH, 0,
1094                         OVW_PAGENUM_O_WIDTH, afsmon_win);
1095     if (ovw_pageNum_o == NULL) {
1096         sprintf(errMsg, "[ %s ] Failed to create pageNumber onode\n", rn);
1097         afsmon_Exit(260);
1098     }
1099     gtxframe_AddToList(ovwFrame, ovw_pageNum_o);
1100     gator_light_set(ovw_pageNum_o, HIGHLIGHT);
1101
1102     /* create the probe number object */
1103     ovw_probeNum_o =
1104         initLightObject("", maxX - OVW_PROBENUM_O_WIDTH, maxY - 1,
1105                         OVW_PROBENUM_O_WIDTH, afsmon_win);
1106     if (ovw_probeNum_o == NULL) {
1107         sprintf(errMsg, "[ %s ] Failed to create probe number onode\n", rn);
1108         afsmon_Exit(270);
1109     }
1110     gtxframe_AddToList(ovwFrame, ovw_probeNum_o);
1111     gator_light_set(ovw_probeNum_o, HIGHLIGHT);
1112
1113     /* create the numFS monitored object */
1114     ovw_numFS_o = initLightObject("", 0, 2, FC_NUMHOSTS_O_WIDTH, afsmon_win);
1115     if (ovw_numFS_o == NULL) {
1116         sprintf(errMsg, "[ %s ] Failed to create numFS onode\n", rn);
1117         afsmon_Exit(275);
1118     }
1119     gtxframe_AddToList(ovwFrame, ovw_numFS_o);
1120
1121     /* create the numCM monitored object */
1122     ovw_numCM_o =
1123         initLightObject("", maxX / 2, 2, OVW_NUMCM_O_WIDTH, afsmon_win);
1124     if (ovw_numCM_o == NULL) {
1125         sprintf(errMsg, "[ %s ] Failed to create numCM_o onode\n", rn);
1126         afsmon_Exit(280);
1127     }
1128     gtxframe_AddToList(ovwFrame, ovw_numCM_o);
1129
1130     /* create the number-of-FS-alerts object */
1131     ovw_FSalerts_o =
1132         initLightObject("", 0, 3, OVW_FSALERTS_O_WIDTH, afsmon_win);
1133     if (ovw_FSalerts_o == NULL) {
1134         sprintf(errMsg, "[ %s ] Failed to create FSalerts_o onode\n", rn);
1135         afsmon_Exit(285);
1136     }
1137     gtxframe_AddToList(ovwFrame, ovw_FSalerts_o);
1138
1139     /* create the number-of-CM-alerts object */
1140     ovw_CMalerts_o =
1141         initLightObject("", maxX / 2, 3, OVW_CMALERTS_O_WIDTH, afsmon_win);
1142     if (ovw_CMalerts_o == NULL) {
1143         sprintf(errMsg, "[ %s ] Failed to create CMalerts_o onode\n", rn);
1144         afsmon_Exit(290);
1145     }
1146     gtxframe_AddToList(ovwFrame, ovw_CMalerts_o);
1147
1148     /* create file-server-name and cache-manager-names objects */
1149     ovw_numHosts_perPage = maxY - OVW_NUM_FIXED_LINES;
1150
1151     /* allocate memory for a list of onode pointers for file server names */
1152     ovw_fsNames_o = malloc(sizeof(struct onode *) * ovw_numHosts_perPage);
1153     if (ovw_fsNames_o == NULL) {
1154         sprintf(errMsg, "[ %s ] Failed to allocate memory for FS onodes\n",
1155                 rn);
1156         afsmon_Exit(295);
1157     }
1158
1159     /* create file server name objects */
1160     ovw_fsNames_o_Ptr = ovw_fsNames_o;
1161     for (i = 0; i < ovw_numHosts_perPage; i++) {
1162         *ovw_fsNames_o_Ptr =
1163             initLightObject("", 0, OVW_FIRST_HOST_ROW + i,
1164                             OVW_HOSTNAME_O_WIDTH, afsmon_win);
1165         if (*ovw_fsNames_o_Ptr == NULL) {
1166             sprintf(errMsg, "[ %s ] Failed to create an FS name onode\n", rn);
1167             afsmon_Exit(300);
1168         }
1169         /*
1170          * if (afsmon_debug) {
1171          * fprintf(debugFD,"[ %s ] fsName_o  %d:  %d\n",
1172          * rn,i,*ovw_fsNames_o_Ptr);
1173          * fflush(debugFD);
1174          * }
1175          */
1176         gtxframe_AddToList(ovwFrame, *ovw_fsNames_o_Ptr);
1177         ovw_fsNames_o_Ptr++;
1178
1179     }
1180
1181
1182     /* allocate memory for a list of onode pointers for cache manager names */
1183     ovw_cmNames_o = malloc(sizeof(struct onode *) * ovw_numHosts_perPage);
1184     if (ovw_cmNames_o == NULL) {
1185         sprintf(errMsg, "[ %s ] Failed to allocate memory for CM onodes\n",
1186                 rn);
1187         afsmon_Exit(305);
1188     }
1189
1190     /* create cache manager name objects */
1191     ovw_cmNames_o_Ptr = ovw_cmNames_o;
1192     for (i = 0; i < ovw_numHosts_perPage; i++) {
1193         *ovw_cmNames_o_Ptr =
1194             initLightObject("", maxX / 2, OVW_FIRST_HOST_ROW + i,
1195                             OVW_HOSTNAME_O_WIDTH, afsmon_win);
1196         if (*ovw_cmNames_o_Ptr == NULL) {
1197             sprintf(errMsg, "[ %s ] Failed to create a CM name onode\n", rn);
1198             afsmon_Exit(310);
1199         }
1200         gtxframe_AddToList(ovwFrame, *ovw_cmNames_o_Ptr);
1201         ovw_cmNames_o_Ptr++;
1202     }
1203
1204
1205     /* Calculate the number of pages of overview data to display */
1206     /* host information starts at the 6th line from top and stops at 3rd
1207      * line from bottom of screen */
1208
1209     if (numFS > numCM)
1210         hostLines = numFS;
1211     else
1212         hostLines = numCM;
1213
1214     ovw_numPages = hostLines / (maxY - OVW_NUM_FIXED_LINES);
1215     if (hostLines % (maxY - OVW_NUM_FIXED_LINES))
1216         ovw_numPages++;
1217
1218     if (afsmon_debug)
1219         fprintf(debugFD, "[ %s ] number of ovw pages = %d\n", rn,
1220                 ovw_numPages);
1221
1222     /* When the ovw_refresh() routine is called by the keyboard handlers the
1223      * following variable is used to determine if fs/cm/fs&cm info must be
1224      * updated */
1225     ovw_update_info = 0;
1226     if (numFS)
1227         ovw_update_info |= OVW_UPDATE_FS;
1228     if (numCM)
1229         ovw_update_info |= OVW_UPDATE_CM;
1230
1231     /* bind the overview frame to a keyboard input handler */
1232
1233     /* bind Q and \ 3 to exit */
1234     keymap_BindToString(ovwFrame->keymap, "Q", afsmonExit_gtx, NULL, NULL);
1235     keymap_BindToString(ovwFrame->keymap, "\ 3", afsmonExit_gtx, NULL, NULL);
1236
1237     /* f -> switch of fs frame */
1238     keymap_BindToString(ovwFrame->keymap, "f", Switch_ovw_2_fs, NULL, NULL);
1239     /* c -> switch of cm frame */
1240     keymap_BindToString(ovwFrame->keymap, "c", Switch_ovw_2_cm, NULL, NULL);
1241     /* n -> switch to next overview page */
1242     keymap_BindToString(ovwFrame->keymap, "n", Switch_ovw_next, NULL, NULL);
1243     /* N -> switch to last overview page */
1244     keymap_BindToString(ovwFrame->keymap, "N", Switch_ovw_last, NULL, NULL);
1245     /* p -> switch to previous overview page */
1246     keymap_BindToString(ovwFrame->keymap, "p", Switch_ovw_prev, NULL, NULL);
1247     /* P -> switch to first overview page */
1248     keymap_BindToString(ovwFrame->keymap, "P", Switch_ovw_first, NULL, NULL);
1249
1250
1251     return (0);
1252 }                               /* create_ovwFrame_objects */
1253
1254
1255 /*-----------------------------------------------------------------------
1256  * resolve_CmdLine()
1257  *
1258  * Description:
1259  *      This function is called to determine the permissible keyboard
1260  *      operations on the FS and CM frames. This information is used
1261  *      to create an appropriate command line prompt. It also generates
1262  *      a bit map of the permissible operations on this page which is
1263  *      used by the keyboard-input handler routines.
1264  *
1265  * Returns:
1266  *      Success: page-type (bit map of permissible operations)
1267  *      Failure: -1
1268  *----------------------------------------------------------------------*/
1269
1270 int
1271 resolve_CmdLine(char *a_buffer,     /* buffer to copy command line */
1272                 int a_currFrame,    /* current frame ovw, fs or cm? */
1273                 int a_currPage,     /* current page number */
1274                 int a_numPages,     /* number of pages of data */
1275                 int a_numCols,      /* number of columns of data to display */
1276                 int a_curr_LCol,    /* current number of leftmost column */
1277                 int a_cols_perPage, /* number of columns per page */
1278                 int a_Data_Available)
1279 {                               /* resolve_CmdLine */
1280     static char rn[] = "resolve_CmdLine";
1281     int pageType;
1282
1283     if (afsmon_debug) {
1284         fprintf(debugFD,
1285                 "[ %s ] Called, a_buffer= %p, a_currFrame= %d, a_currPage= %d, a_numPages= %d, a_numCols= %d, a_curr_LCol= %d, a_cols_perPage= %d\n",
1286                 rn, a_buffer, a_currFrame, a_currPage, a_numPages, a_numCols,
1287                 a_curr_LCol, a_cols_perPage);
1288         fflush(debugFD);
1289     }
1290
1291     pageType = 0;
1292
1293     /* determine if we have fs/cm frames. If we do, note that we should not
1294      * let the user seen the initial junk we have there until the probe
1295      * results are available  */
1296     if (a_currFrame == 1) {     /* in the fs frame */
1297         if (numCM && cm_Data_Available)
1298             pageType |= CMD_CM;
1299     } else if (a_currFrame == 2) {      /* in the cm frame */
1300         if (numFS && fs_Data_Available)
1301             pageType |= CMD_FS;
1302     } else {
1303         if (afsmon_debug) {
1304             fprintf(debugFD, "[ %s ] Wrong frame type %d\n", rn, a_currFrame);
1305             fflush(debugFD);
1306         }
1307         return (-1);
1308     }
1309
1310     /* do we have next/previous pages */
1311     if (a_currPage < a_numPages)
1312         pageType |= CMD_NEXT;   /* have a next page */
1313     if (a_currPage > 1)
1314         pageType |= CMD_PREV;   /* have a previous page */
1315
1316     if (a_numCols > a_cols_perPage) {
1317         if (a_curr_LCol > 0)
1318             pageType |= CMD_LEFT;       /* have columns on left */
1319         if ((a_curr_LCol + a_cols_perPage) < a_numCols)
1320             pageType |= CMD_RIGHT;      /* have columns on right */
1321     }
1322
1323     /* now build the command line */
1324
1325     strcpy(a_buffer, "Command [oview");
1326     if (pageType & CMD_FS)
1327         strcat(a_buffer, ", fs");
1328     if (pageType & CMD_CM)
1329         strcat(a_buffer, ", cm");
1330     if (pageType & CMD_PREV)
1331         strcat(a_buffer, ", prev");
1332     if (pageType & CMD_NEXT)
1333         strcat(a_buffer, ", next");
1334     if (pageType & CMD_LEFT)
1335         strcat(a_buffer, ", left");
1336     if (pageType & CMD_RIGHT)
1337         strcat(a_buffer, ", right");
1338     strcat(a_buffer, "]? ");
1339
1340     return (pageType);
1341
1342 }                               /* resolve_CmdLine */
1343
1344 /*-----------------------------------------------------------------------
1345  * display_Server_datum()
1346  *
1347  * Description:
1348  *      The data in the file server & cache manager frames are displayed
1349  *      in two objects, one below the other. If the data is too long to
1350  *      fit in the first object it will overflow into the next. This is
1351  *      to conserve real estate on the screen. This function copies the
1352  *      contents of the source buffer adjusted to the two objects if the
1353  *      probe had succeded. Otherwise it enters "--" in the first object
1354  *      blanks out the second. If the object needs to be highlightned
1355  *      (due to a threshold crossing) it is done.
1356  *
1357  * Returns:
1358  *      0 always
1359  *----------------------------------------------------------------------*/
1360 int
1361 display_Server_datum(char *a_srcBuf,              /* source buffer */
1362                      struct onode *a_firstObj_o,  /* first object */
1363                      struct onode *a_secondObj_o, /* second object */
1364                      int a_probeOK,               /* probe OK ? */
1365                      int a_just,                  /* justification */
1366                      int a_highlight)             /* highlight object  ? */
1367 {                               /* display_Server_datum */
1368
1369     static char rn[] = "display_Server_datum";
1370     struct gator_lightobj *tmp_lightobj1;
1371     struct gator_lightobj *tmp_lightobj2;
1372     char part1[FC_COLUMN_WIDTH + 2];
1373     char part2[FC_COLUMN_WIDTH + 2];
1374     int code;
1375
1376     if (afsmon_debug) {
1377         if (a_highlight)
1378             fprintf(debugFD,
1379                     "[ %s ] Called, a_srcBuf= %s, a_firstObj_o= %p, a_secondObj_o= %p, a_probeOK= %d, a_just= %d, a_highlight= %d\n",
1380                     rn, a_srcBuf, a_firstObj_o, a_secondObj_o, a_probeOK,
1381                     a_just, a_highlight);
1382         fflush(debugFD);
1383     }
1384
1385
1386     tmp_lightobj1 = (struct gator_lightobj *)a_firstObj_o->o_data;
1387     tmp_lightobj2 = (struct gator_lightobj *)a_secondObj_o->o_data;
1388
1389     if (a_probeOK) {            /* probe is ok so fill in the data */
1390
1391         /* check if it would fit in one object */
1392         if (strlen(a_srcBuf) < FC_COLUMN_WIDTH) {
1393             strcpy(part1, a_srcBuf);
1394             strcpy(part2, "");
1395         } else {
1396             /* break up the src string into 2 parts */
1397             /* note that column width includes terminator */
1398             strncpy(part1, a_srcBuf, FC_COLUMN_WIDTH - 1);
1399             part1[FC_COLUMN_WIDTH - 1] = '\0';
1400             strncpy(part2, a_srcBuf + FC_COLUMN_WIDTH - 1,
1401                     FC_COLUMN_WIDTH - 1);
1402
1403         }
1404
1405     } else {                    /* probe failed, enter "--"s */
1406         strcpy(part1, "--");
1407         strcpy(part2, "");
1408     }
1409
1410     /* if (afsmon_debug) {
1411      * fprintf(debugFD,"[ %s ] %s split to %s & %s\n",rn,a_srcBuf,part1,part2);
1412      * fflush(debugFD);
1413      * } */
1414
1415     /* initialize both the objects */
1416
1417     code =
1418         justify_light(part1, tmp_lightobj1->label, FC_COLUMN_WIDTH, a_just,
1419                       1);
1420     if (code) {
1421         if (afsmon_debug) {
1422             fprintf(debugFD, "[ %s ] justify_light failed 1 \n", rn);
1423             fflush(debugFD);
1424         }
1425     }
1426
1427     code =
1428         justify_light(part2, tmp_lightobj2->label, FC_COLUMN_WIDTH, a_just,
1429                       1);
1430     if (code) {
1431         if (afsmon_debug) {
1432             fprintf(debugFD, "[ %s ] justify_light failed 1 \n", rn);
1433             fflush(debugFD);
1434         }
1435     }
1436
1437     /* highlight them */
1438     if (a_highlight && (part1[0] != '-'))
1439         gator_light_set(a_firstObj_o, 1);
1440     else
1441         gator_light_set(a_firstObj_o, 0);
1442     if (a_highlight && (part2[0] != '\0'))
1443         gator_light_set(a_secondObj_o, 1);
1444     else
1445         gator_light_set(a_secondObj_o, 0);
1446
1447
1448
1449     return (0);
1450
1451 }                               /* display_Server_datum */
1452
1453
1454 /*-----------------------------------------------------------------------
1455  * display_Server_label()
1456  *
1457  * Description:
1458  *      Display the given server label in three objects. The label is
1459  *      partitioned into three parts by '/'s and each part is copied
1460  *      into each label object.
1461  *
1462  * Returns:
1463  *      0 always.
1464  *----------------------------------------------------------------------*/
1465
1466 int
1467 display_Server_label(char *a_srcBuf,
1468                      struct onode *a_firstObj_o,        /* first object */
1469                      struct onode *a_secondObj_o,       /* second object */
1470                      struct onode *a_thirdObj_o)        /* third object */
1471 {                               /* display_Server_label */
1472     static char rn[] = "display_Server_label";
1473     char part[3][20];           /* buffer for three parts of label */
1474     char *strPtr;
1475     struct gator_lightobj *tmp_lightobj;
1476     struct onode *objPtr_o[3];
1477     int code;
1478     int strLen;
1479     int len;
1480     int i;
1481     int j;
1482
1483 /* the following debug statement floods the debug file */
1484 #ifdef DEBUG_DETAILED
1485     if (afsmon_debug) {
1486         fprintf(debugFD,
1487                 "[ %s ] Called, a_srcBuf= %s, a_firstObj_o= %d, a_secondObj_o= %d, a_thirdObj_o= %d\n",
1488                 rn, a_srcBuf, a_firstObj_o, a_secondObj_o, a_thirdObj_o);
1489         fflush(debugFD);
1490     }
1491 #endif
1492
1493
1494     /* break the label string into three parts */
1495
1496     part[0][0] = '\0';
1497     part[1][0] = '\0';
1498     part[2][0] = '\0';
1499     /* now for a dumb precaution */
1500
1501     strLen = strlen(a_srcBuf);
1502     len = 0;
1503     strPtr = a_srcBuf;
1504     for (i = 0; i < 3; i++) {
1505         j = 0;
1506         while (*strPtr != '\0' && (len++ <= strLen)) {
1507             if (*strPtr == '/') {
1508                 strPtr++;
1509                 break;
1510             } else
1511                 part[i][j] = *strPtr;
1512             strPtr++;
1513             j++;
1514         }
1515         part[i][j] = '\0';
1516     }
1517
1518     /*
1519      * if (afsmon_debug) {
1520      * fprintf(debugFD,"[ %s ] LABELS %s -> %s %s %s\n",
1521      * rn, a_srcBuf, part[0], part[1], part[2]);
1522      * fflush(debugFD);
1523      * }
1524      */
1525
1526     objPtr_o[0] = a_firstObj_o;
1527     objPtr_o[1] = a_secondObj_o;
1528     objPtr_o[2] = a_thirdObj_o;
1529
1530     /* display each label justified CENTER */
1531
1532     for (i = 0; i < 3; i++) {
1533         tmp_lightobj = (struct gator_lightobj *)objPtr_o[i]->o_data;
1534         code =
1535             justify_light(part[i], tmp_lightobj->label, FC_COLUMN_WIDTH,
1536                           CENTER, 1);
1537         if (code) {
1538             if (afsmon_debug) {
1539                 fprintf(debugFD, "[ %s ] justify_light %d failed \n", rn, i);
1540                 fflush(debugFD);
1541             }
1542         }
1543     }
1544     return 0;
1545 }                               /* display_Server_label */
1546
1547
1548
1549
1550
1551 /*-----------------------------------------------------------------------
1552  * fs_refresh()
1553  *
1554  * Description:
1555  *      Refresh the File Servers screen with the given page number starting
1556  *      at the given left-column number. The appropriate contents of
1557  *      prev_fsData are displayed.
1558  *      First the status labels at the four corners of the screen are
1559  *      updated. Next the column labels are updated and then each row
1560  *      of statistics.
1561  *
1562  * Returns:
1563  *      Success: 0
1564  *      Failure: Exits afsmoitor on a severe error.
1565  *----------------------------------------------------------------------*/
1566
1567
1568 int
1569 fs_refresh(int a_pageNum,       /* page to display */
1570            int a_LcolNum)       /* starting (leftmost) column number */
1571 {                               /* fs_refresh */
1572
1573     static char rn[] = "fs_refresh";    /* routine name */
1574     struct gator_lightobj *tmp_lightobj;        /* ptr for object's display data */
1575     struct fs_Display_Data *fsDataP;    /* ptr to FS display data array */
1576     struct ServerInfo_line *tmp_fs_lines_P;     /* tmp ptr to fs_lines */
1577     struct onode **firstSlot_o_Ptr;     /* ptr to first data slot of a datum */
1578     struct onode **secondSlot_o_Ptr;    /* ptr to second data slot of a datum */
1579     struct onode **fsLabels_o_Ptr1;     /* ptr to label row 0 */
1580     struct onode **fsLabels_o_Ptr2;     /* ptr to label row 1 */
1581     struct onode **fsLabels_o_Ptr3;     /* ptr to label row 2 */
1582     char cmdLine[80];           /* buffer for command line */
1583     char printBuf[256];         /* buffer to print to screen */
1584     int i;
1585     int j;
1586     int k;
1587     int code;
1588     int fsIdx;
1589     int labelIdx;
1590     int dataIndex;              /* index to the data[] field of
1591                                  * struct fs_Display_Data */
1592
1593     if (afsmon_debug) {
1594         fprintf(debugFD, "[ %s ] Called with row %d col %d \n", rn, a_pageNum,
1595                 a_LcolNum);
1596         fflush(debugFD);
1597     }
1598
1599
1600     /* if the data is not yet available, ie., not one probe cycle has
1601      * completed, do nothing */
1602
1603     if (!fs_Data_Available)
1604         return (0);
1605
1606
1607     /* validate the page number & column number */
1608     if (a_pageNum < 1 || a_pageNum > fs_numPages) {
1609         if (afsmon_debug) {
1610             fprintf(debugFD, "[ %s ] Called with wrong page # %d \n", rn,
1611                     a_pageNum);
1612             fflush(debugFD);
1613         }
1614         afsmon_Exit(315);
1615     }
1616     if (a_LcolNum < 0 || a_LcolNum > fs_numCols) {
1617         if (afsmon_debug) {
1618             fprintf(debugFD, "[ %s ] Called with wrong column #%d\n", rn,
1619                     a_LcolNum);
1620             fflush(debugFD);
1621         }
1622         afsmon_Exit(320);
1623     }
1624
1625
1626
1627     /* update the fixed labels */
1628
1629     /* we reuse the ovw version lable and hence do not have to do anything
1630      * for it here */
1631
1632     /* page number label */
1633     tmp_lightobj = (struct gator_lightobj *)fs_pageNum_o->o_data;
1634     sprintf(printBuf, "[File Servers, p. %d of %d, c. %d of %d]", a_pageNum,
1635             fs_numPages, a_LcolNum + 1, fs_numCols);
1636     justify_light(printBuf, tmp_lightobj->label, FC_PAGENUM_O_WIDTH,
1637                   RIGHT_JUSTIFY, 1);
1638     gator_light_set(fs_pageNum_o, 1);
1639
1640     /* file servers monitored label */
1641     tmp_lightobj = (struct gator_lightobj *)fs_numFS_o->o_data;
1642     sprintf(printBuf, "%d File Servers monitored, %d alerts on %d machines",
1643             numFS, num_fs_alerts, numHosts_onfs_alerts);
1644     justify_light(printBuf, tmp_lightobj->label, FC_NUMHOSTS_O_WIDTH, CENTER,
1645                   1);
1646
1647
1648     /* command line */
1649
1650     /* figure out what we need to show in the prompt & set the page type */
1651     /* the fs_pageType variable is in turn used by the keyboard handler
1652      * routines to call fs_refresh() with the correct parameters */
1653
1654     fs_pageType = resolve_CmdLine(cmdLine, 1 /* fs frame */ , a_pageNum,
1655                                   fs_numPages, fs_numCols, a_LcolNum,
1656                                   fs_cols_perPage, 0);
1657
1658     /* display the command line */
1659     tmp_lightobj = (struct gator_lightobj *)fs_cmd_o->o_data;
1660     sprintf(printBuf, "%s", cmdLine);
1661     justify_light(printBuf, tmp_lightobj->label, strlen(printBuf) + 1,
1662                   LEFT_JUSTIFY, 1);
1663     gator_light_set(fs_cmd_o, 1);
1664
1665     /* update the probe number label */
1666     tmp_lightobj = (struct gator_lightobj *)fs_probeNum_o->o_data;
1667     sprintf(printBuf, "[FS probes %d, freq=%d sec]", afsmon_fs_prev_probeNum,
1668             afsmon_probefreq);
1669     justify_light(printBuf, tmp_lightobj->label, FC_PROBENUM_O_WIDTH,
1670                   RIGHT_JUSTIFY, 1);
1671     gator_light_set(fs_probeNum_o, 1);
1672
1673     /* update "columns on left" signal */
1674     tmp_lightobj = (struct gator_lightobj *)fs_leftArrows_o->o_data;
1675     if (fs_pageType & CMD_LEFT)
1676         strcpy(printBuf, "<<<");
1677     else
1678         strcpy(printBuf, "");
1679     justify_light(printBuf, tmp_lightobj->label, FC_ARROWS_O_WIDTH,
1680                   LEFT_JUSTIFY, 1);
1681     gator_light_set(fs_leftArrows_o, 0);
1682
1683     /* update "columns on right" signal */
1684     tmp_lightobj = (struct gator_lightobj *)fs_rightArrows_o->o_data;
1685     if (fs_pageType & CMD_RIGHT)
1686         strcpy(printBuf, ">>>");
1687     else
1688         strcpy(printBuf, "");
1689     justify_light(printBuf, tmp_lightobj->label, FC_ARROWS_O_WIDTH,
1690                   RIGHT_JUSTIFY, 1);
1691     gator_light_set(fs_rightArrows_o, 0);
1692
1693
1694
1695     /* UPDATE THE COLUMN LABELS */
1696
1697     /* the column index is also used to index the label arrays */
1698     labelIdx = a_LcolNum;
1699
1700     /* get the pointers to the three arrays of label onodes */
1701     fsLabels_o_Ptr1 = fsLabels_o[0];
1702     fsLabels_o_Ptr2 = fsLabels_o[1];
1703     fsLabels_o_Ptr3 = fsLabels_o[2];
1704
1705     for (k = 0; k < fs_cols_perPage; k++) {
1706
1707         if (labelIdx < fs_numCols) {
1708             dataIndex = fs_Display_map[labelIdx];
1709             display_Server_label(fs_labels[dataIndex], *fsLabels_o_Ptr1,
1710                                  *fsLabels_o_Ptr2, *fsLabels_o_Ptr3);
1711
1712             labelIdx++;         /* next label */
1713         } else {
1714             display_Server_label("//", *fsLabels_o_Ptr1, *fsLabels_o_Ptr2,
1715                                  *fsLabels_o_Ptr3);
1716         }
1717
1718         fsLabels_o_Ptr1++;      /* next onode in label row 1 */
1719         fsLabels_o_Ptr2++;      /* next onode in label row 2 */
1720         fsLabels_o_Ptr3++;      /* next onode in label row 3 */
1721
1722     }                           /* labels for each column */
1723
1724
1725     /* UPDATE THE FILE SERVER STATISTICS */
1726
1727     /* move to the right spot in the FS display data array */
1728     fsDataP = prev_fsData;
1729     fsIdx = 0;
1730     for (i = 0; i < ((a_pageNum - 1) * fs_numHosts_perPage); i++) {
1731         fsDataP++;
1732         fsIdx++;
1733     }
1734
1735     if (fsIdx >= numFS) {       /* whoops! screwed up */
1736         sprintf(errMsg, "[ %s ] Programming error 1\n", rn);
1737         afsmon_Exit(325);
1738     }
1739
1740     /* get the pointer to the first line of onodes of the file server frame */
1741     tmp_fs_lines_P = fs_lines;
1742
1743     for (i = 0; i < fs_numHosts_perPage; i++) {
1744
1745
1746         /* if this is the last page we may not have file servers to fill up
1747          * the page, so check the index */
1748         if (fsIdx < numFS) {
1749
1750             if (fsDataP->hostName[0] == '\0') {
1751                 sprintf(errMsg, "[ %s ] empty fs display entry \n", rn);
1752                 afsmon_Exit(330);
1753             }
1754
1755             /* display the hostname , first names only please! */
1756
1757             sprintf(printBuf, "%s", fsDataP->hostName);
1758             for (j = 0; j < strlen(printBuf); j++) {
1759                 if (printBuf[j] == '.') {
1760                     printBuf[j] = '\0';
1761                     break;
1762                 }
1763             }
1764
1765             tmp_lightobj =
1766                 (struct gator_lightobj *)tmp_fs_lines_P->host_o->o_data;
1767             code =
1768                 justify_light(printBuf, tmp_lightobj->label,
1769                               FC_HOSTNAME_O_WIDTH, LEFT_JUSTIFY, 1);
1770             if (code) {
1771                 fprintf(debugFD, "[ %s ] justify_code returned %d\n", rn,
1772                         code);
1773                 fflush(debugFD);
1774             }
1775
1776             /* use the current column value to index into the fs_Display_map
1777              * array to obtain the index of the item to display. check if its
1778              * overflow flag is set and highlight if so. if the probe had failed
1779              * enter "--" is all columns */
1780
1781             /* each host has two rows of slots for datums. get the pointers to
1782              * both the arrays */
1783
1784             firstSlot_o_Ptr = tmp_fs_lines_P->data_o[0];
1785             secondSlot_o_Ptr = tmp_fs_lines_P->data_o[1];
1786             fs_curr_RCol = a_LcolNum;   /* starting column number from which
1787                                          * we are asked to display data */
1788
1789             for (j = 0; j < fs_cols_perPage; j++) {     /* for each column */
1790
1791                 /* if there is another column of data */
1792                 if (fs_curr_RCol < fs_numCols) {
1793
1794                     dataIndex = fs_Display_map[fs_curr_RCol];
1795
1796                     display_Server_datum(fsDataP->data[dataIndex],
1797                                          *firstSlot_o_Ptr,
1798                                          *secondSlot_o_Ptr,
1799                                          fsDataP->probeOK, RIGHT_JUSTIFY,
1800                                          fsDataP->threshOvf[dataIndex]);
1801
1802                     fs_curr_RCol++;
1803                 } else {        /* no more data, blank out columns */
1804                     display_Server_datum("", *firstSlot_o_Ptr, *secondSlot_o_Ptr, 1,    /* probe ok */
1805                                          RIGHT_JUSTIFY, 0);     /* no overflow */
1806                 }
1807
1808
1809                 firstSlot_o_Ptr++;      /* onode of next column */
1810                 secondSlot_o_Ptr++;     /* onode of next column */
1811
1812             }                   /* for each column */
1813
1814             /* the loop could have taken the right-column-index one over,
1815              * adjust it now */
1816             if (fs_curr_RCol == fs_numCols)
1817                 fs_curr_RCol--;
1818
1819
1820         }
1821
1822
1823
1824         /* if fdIdx < numFS */
1825         /* if fsIdx >= numFS , blank out all succeding rows */
1826         if (fsIdx >= numFS) {
1827
1828             /* blank out host name object */
1829             tmp_lightobj =
1830                 (struct gator_lightobj *)tmp_fs_lines_P->host_o->o_data;
1831             code =
1832                 justify_light("", tmp_lightobj->label, FC_HOSTNAME_O_WIDTH,
1833                               LEFT_JUSTIFY, 1);
1834             if (code) {
1835                 fprintf(debugFD, "[ %s ] justify_code returned %d\n", rn,
1836                         code);
1837                 fflush(debugFD);
1838             }
1839
1840             firstSlot_o_Ptr = tmp_fs_lines_P->data_o[0];
1841             secondSlot_o_Ptr = tmp_fs_lines_P->data_o[1];
1842
1843             for (k = 0; k < fs_cols_perPage; k++) {
1844                 display_Server_datum("", *firstSlot_o_Ptr, *secondSlot_o_Ptr, 1,        /* probe OK */
1845                                      RIGHT_JUSTIFY, 0); /* dont highlight */
1846
1847                 firstSlot_o_Ptr++;
1848                 secondSlot_o_Ptr++;
1849             }
1850
1851         }
1852
1853         /* fsIDx >= numFS */
1854         tmp_fs_lines_P++;       /* pointer to next line in the frame */
1855         fsDataP++;              /* next host's data */
1856         fsIdx++;                /* host index */
1857
1858
1859     }                           /* for each row in the File Servers frame */
1860
1861     /* redraw the display if the File Servers screen is currently displayed */
1862     if (afsmon_win->w_frame == fsFrame)
1863         WOP_DISPLAY(afsmon_win);
1864
1865     /* update the global page & column numbers to reflect the changes */
1866     fs_currPage = a_pageNum;
1867     fs_curr_LCol = a_LcolNum;;
1868
1869     return (0);
1870
1871 }                               /* fs_refresh */
1872
1873
1874
1875
1876 /*-----------------------------------------------------------------------
1877  * Switch_fs_2_ovw()
1878  *
1879  * Description:
1880  *      Switch from the File Server screen to the Overview Screen
1881  *----------------------------------------------------------------------*/
1882 int
1883 Switch_fs_2_ovw(void *d1, void *d2)
1884 {
1885     /* bind the overview frame to the window */
1886     gtxframe_SetFrame(afsmon_win, ovwFrame);
1887     return (0);
1888 }
1889
1890 /*-----------------------------------------------------------------------
1891  * Switch_fs_2_cm()
1892  *
1893  * Description:
1894  *      Switch from the File Server screen to the Cache Managers screen.
1895  *----------------------------------------------------------------------*/
1896 int
1897 Switch_fs_2_cm(void *d1, void *d2)
1898 {
1899     if (fs_pageType & CMD_CM) {
1900         /* bind the overview Cache Managers to the window */
1901         gtxframe_SetFrame(afsmon_win, cmFrame);
1902     }
1903     return (0);
1904 }
1905
1906 /*-----------------------------------------------------------------------
1907  * Switch_fs_next()
1908  *
1909  * Description:
1910  *      Switch to next page of file server screen
1911  *----------------------------------------------------------------------*/
1912 int
1913 Switch_fs_next(void *d1, void *d2)
1914 {
1915     if (fs_pageType & CMD_NEXT) {
1916         /* we have a next page, refresh with next page number */
1917         fs_refresh(fs_currPage + 1, fs_curr_LCol);
1918     }
1919
1920     return (0);
1921 }
1922
1923 /*-----------------------------------------------------------------------
1924  * Switch_fs_last()
1925  *
1926  * Description:
1927  *      Switch to last page of file server screen
1928  *----------------------------------------------------------------------*/
1929 int
1930 Switch_fs_last(void *d1, void *d2)
1931 {
1932     if (fs_pageType & CMD_NEXT) {
1933         /* we have a next page, refresh with the last page number */
1934         fs_refresh(fs_numPages, fs_curr_LCol);
1935     }
1936
1937     return (0);
1938 }
1939
1940 /*-----------------------------------------------------------------------
1941  * Switch_fs_prev()
1942  *
1943  * Description:
1944  *      Switch to previous page of file server screen
1945  *----------------------------------------------------------------------*/
1946 int
1947 Switch_fs_prev(void *d1, void *d2)
1948 {
1949     if (fs_pageType & CMD_PREV) {
1950         /* we have a previous page, refresh with the rpevious page number */
1951         fs_refresh(fs_currPage - 1, fs_curr_LCol);
1952     }
1953     return (0);
1954 }
1955
1956 /*-----------------------------------------------------------------------
1957  * Switch_fs_first()
1958  *
1959  * Description:
1960  *      Switch to first page of file server screen
1961  *----------------------------------------------------------------------*/
1962 int
1963 Switch_fs_first(void *d1, void *d2)
1964 {
1965     if (fs_pageType & CMD_PREV) {
1966         /* we have a previous page, got to first page */
1967         fs_refresh(1, fs_curr_LCol);
1968     }
1969     return (0);
1970 }
1971
1972 /*-----------------------------------------------------------------------
1973  * Switch_fs_left()
1974  *
1975  * Description:
1976  *      Scroll left on the file server screen
1977  *----------------------------------------------------------------------*/
1978 int
1979 Switch_fs_left(void *d1, void *d2)
1980 {
1981     if (fs_pageType & CMD_LEFT) {
1982         /* we have columns on left, refresh with new column number */
1983         fs_refresh(fs_currPage, fs_curr_LCol - fs_cols_perPage);
1984     }
1985     return (0);
1986 }
1987
1988
1989 /*-----------------------------------------------------------------------
1990  * Switch_fs_leftmost()
1991  *
1992  * Description:
1993  *      Scroll to first column on  the file server screen
1994  *----------------------------------------------------------------------*/
1995 int
1996 Switch_fs_leftmost(void *d1, void *d2)
1997 {
1998     if (fs_pageType & CMD_LEFT) {
1999         /* we have columns on left, go to the first */
2000         fs_refresh(fs_currPage, 0);
2001     }
2002     return (0);
2003 }
2004
2005 /*-----------------------------------------------------------------------
2006  * Switch_fs_right()
2007  *
2008  * Description:
2009  *      Scroll right on the file server screen
2010  *----------------------------------------------------------------------*/
2011 int
2012 Switch_fs_right(void *d1, void *d2)
2013 {
2014     if (fs_pageType & CMD_RIGHT) {
2015         /* we have columns on right, refresh with new column number */
2016         fs_refresh(fs_currPage, fs_curr_LCol + fs_cols_perPage);
2017     }
2018     return (0);
2019 }
2020
2021 /*-----------------------------------------------------------------------
2022  * Switch_fs_rightmost()
2023  *
2024  * Description:
2025  *      Scroll to last column on the file server screen
2026  *----------------------------------------------------------------------*/
2027 int
2028 Switch_fs_rightmost(void *d1, void *d2)
2029 {
2030     int curr_LCol;
2031
2032     if (fs_pageType & CMD_RIGHT) {
2033         /* we have columns on right, go to the last column */
2034         if (fs_numCols % fs_cols_perPage)
2035             curr_LCol = (fs_numCols / fs_cols_perPage) * fs_cols_perPage;
2036         else
2037             curr_LCol =
2038                 ((fs_numCols / fs_cols_perPage) - 1) * fs_cols_perPage;
2039
2040         fs_refresh(fs_currPage, curr_LCol);
2041     }
2042     return (0);
2043 }
2044
2045
2046 /*-----------------------------------------------------------------------
2047  * create_FSframe_objects()
2048  *
2049  * Description:
2050  *      Create the gtx objects (onodes) for the Fileservers frame and setup
2051  *      the keyboard bindings.
2052  *      Only as many objects as can fit on the display are created. The
2053  *      positions and lengths of all these objects are fixed at creation.
2054  *      These objects are updated with new data at the end of each probe
2055  *      cycle.
2056  *
2057  * Returns:
2058  *      Success: 0
2059  *      Failure: Exits afsmonitor.
2060  *----------------------------------------------------------------------*/
2061
2062 int
2063 create_FSframe_objects(void)
2064 {                               /* create_FSframe_objects */
2065     static char rn[] = "create_FSframe_objects";
2066     struct ServerInfo_line *fs_lines_Ptr;
2067     struct onode **fs_data_o_Ptr;
2068     struct onode **fsLabels_o_Ptr;
2069     int x_pos;
2070     int y_pos;
2071     int i;
2072     int j;
2073     int numBytes;
2074     int arrIdx;
2075
2076
2077     if (afsmon_debug) {
2078         fprintf(debugFD, "[ %s ] Called\n", rn);
2079         fflush(debugFD);
2080     }
2081
2082     /* create the command line object */
2083     fs_cmd_o =
2084         initLightObject("Command [oview, cm, prev, next, left, right] ? ", 0,
2085                         maxY - 1, FC_CMD_O_WIDTH, afsmon_win);
2086     if (fs_cmd_o == NULL) {
2087         sprintf(errMsg, "[ %s ] Failed to create fs command onode\n", rn);
2088         afsmon_Exit(340);
2089     }
2090     gtxframe_AddToList(fsFrame, fs_cmd_o);
2091     gator_light_set(fs_cmd_o, HIGHLIGHT);
2092
2093     /* we already have the dimensions for the frame - same as the ovw frame */
2094     /* use the ovw program name object for the fs screen too */
2095
2096     gtxframe_AddToList(fsFrame, ovw_progName_o);
2097
2098
2099     /* create the page number object */
2100     fs_pageNum_o =
2101         initLightObject("[File Servers, p. X of X, c. Y of Y]",
2102                         maxX - FC_PAGENUM_O_WIDTH, 0, FC_PAGENUM_O_WIDTH,
2103                         afsmon_win);
2104     if (fs_pageNum_o == NULL) {
2105         sprintf(errMsg, "[ %s ] Failed to create pageNumber onode\n", rn);
2106         afsmon_Exit(335);
2107     }
2108     gtxframe_AddToList(fsFrame, fs_pageNum_o);
2109     gator_light_set(fs_pageNum_o, HIGHLIGHT);
2110
2111     /* create the probe number object */
2112     fs_probeNum_o =
2113         initLightObject("[FS probes 1, freq=30 sec]",
2114                         maxX - FC_PROBENUM_O_WIDTH, maxY - 1,
2115                         FC_PROBENUM_O_WIDTH, afsmon_win);
2116     if (fs_probeNum_o == NULL) {
2117         sprintf(errMsg, "[ %s ] Failed to create fs probeNum onode\n", rn);
2118         afsmon_Exit(345);
2119     }
2120     gtxframe_AddToList(fsFrame, fs_probeNum_o);
2121     gator_light_set(fs_probeNum_o, HIGHLIGHT);
2122
2123
2124     /* create the numFS monitored object */
2125     fs_numFS_o =
2126         initLightObject
2127         ("      0 File Servers monitored, 0 alerts on 0 machines", 4, 2,
2128          FC_NUMHOSTS_O_WIDTH, afsmon_win);
2129     if (fs_numFS_o == NULL) {
2130         sprintf(errMsg,
2131                 "[ %s ] Failed to create numFS onode for the fs frame\n", rn);
2132         afsmon_Exit(350);
2133     }
2134     gtxframe_AddToList(fsFrame, fs_numFS_o);
2135
2136     /* create the "more columns to left" indicator */
2137     fs_leftArrows_o =
2138         initLightObject("<<<", 0, 2, FC_ARROWS_O_WIDTH, afsmon_win);
2139     if (fs_leftArrows_o == NULL) {
2140         sprintf(errMsg,
2141                 "[ %s ] Failed to create leftArrows onode for the fs frame\n",
2142                 rn);
2143         afsmon_Exit(355);
2144     }
2145     gtxframe_AddToList(fsFrame, fs_leftArrows_o);
2146
2147     /* create the "more columns to right" indicator */
2148     fs_rightArrows_o =
2149         initLightObject(">>>", maxX - FC_ARROWS_O_WIDTH, 2, FC_ARROWS_O_WIDTH,
2150                         afsmon_win);
2151     if (fs_rightArrows_o == NULL) {
2152         sprintf(errMsg,
2153                 "[ %s ] Failed to create rightArrows onode for the fs frame\n",
2154                 rn);
2155         afsmon_Exit(360);
2156     }
2157     gtxframe_AddToList(fsFrame, fs_rightArrows_o);
2158
2159
2160
2161
2162     /* calculate the maximum number of hosts per page (2 rows per host) */
2163     fs_numHosts_perPage = (maxY - FC_NUM_FIXED_LINES) / 2;
2164
2165     /* determine the number of data columns that can fit in a page */
2166     fs_cols_perPage = (maxX - FC_HOSTNAME_O_WIDTH) / (FC_COLUMN_WIDTH);
2167
2168     if (afsmon_debug) {
2169         fprintf(debugFD, "[ %s ] fs_numHosts_perPage=%d fs_cols_perPage=%d\n",
2170                 rn, fs_numHosts_perPage, fs_cols_perPage);
2171         fflush(debugFD);
2172     }
2173
2174     /* the above two variables give us the information needed to create
2175      * the objects for displaying the file server information */
2176
2177     /* allocate memory for all the onode pointers required to display
2178      * the file server statistics */
2179
2180     numBytes = fs_numHosts_perPage * sizeof(struct ServerInfo_line);
2181     fs_lines = malloc(numBytes);
2182     if (fs_lines == (struct ServerInfo_line *)0) {
2183         sprintf(errMsg,
2184                 "[ %s ] Failed to allocate %d bytes for FS data lines\n", rn,
2185                 numBytes);
2186         afsmon_Exit(365);
2187     }
2188
2189     /* for each line of server statistics allocate memory to store two arrays
2190      * of data onodes */
2191
2192     fs_lines_Ptr = fs_lines;
2193     for (i = 0; i < fs_numHosts_perPage; i++) {
2194         for (arrIdx = 0; arrIdx < 2; arrIdx++) {
2195             numBytes = fs_cols_perPage * sizeof(struct onode *);
2196             fs_lines_Ptr->data_o[arrIdx] = malloc(numBytes);
2197             if (fs_lines_Ptr->data_o[arrIdx] == NULL) {
2198                 sprintf(errMsg,
2199                         "[ %s ] Failed to allocate %d bytes for FS data onodes\n",
2200                         rn, numBytes);
2201                 afsmon_Exit(370);
2202             }
2203         }
2204         fs_lines_Ptr++;
2205     }
2206
2207     /* now allocate the onodes itself */
2208
2209     fs_lines_Ptr = fs_lines;
2210     for (i = 0; i < fs_numHosts_perPage; i++) {
2211
2212         /* initialize host name onode */
2213         fs_lines_Ptr->host_o =
2214             initLightObject("FSHostName", 0, FC_FIRST_HOST_ROW + 2 * i,
2215                             FC_HOSTNAME_O_WIDTH, afsmon_win);
2216         if (fs_lines_Ptr->host_o == NULL) {
2217             sprintf(errMsg, "[ %s ] Failed to create an FS name onode\n", rn);
2218             afsmon_Exit(375);
2219         }
2220         gtxframe_AddToList(fsFrame, fs_lines_Ptr->host_o);
2221
2222         /* if (afsmon_debug) {
2223          * fprintf(debugFD,"[ %s ] Addr of host_o = %d for line %d\n",
2224          * rn,fs_lines_Ptr->host_o,i);
2225          * fflush(debugFD);
2226          * } */
2227
2228         /* initialize data onodes for this host */
2229
2230         for (arrIdx = 0; arrIdx < 2; arrIdx++) {        /* for each array index */
2231
2232             fs_data_o_Ptr = fs_lines_Ptr->data_o[arrIdx];
2233             for (j = 0; j < fs_cols_perPage; j++) {     /* for each column */
2234
2235                 char tmpBuf[20];
2236
2237                 /* determine x & y coordinate for this data object */
2238                 /* the 1's are for leaving a blank after each column */
2239                 x_pos = FC_HOSTNAME_O_WIDTH + (j * (FC_COLUMN_WIDTH));
2240                 y_pos = FC_FIRST_HOST_ROW + 2 * i + arrIdx;
2241
2242                 sprintf(tmpBuf, "-FSData %d-", arrIdx);
2243                 *fs_data_o_Ptr =
2244                     initLightObject(tmpBuf, x_pos, y_pos, FC_COLUMN_WIDTH,
2245                                     afsmon_win);
2246                 if (*fs_data_o_Ptr == NULL) {
2247                     sprintf(errMsg,
2248                             "[ %s ] Failed to create an FS data onode\n", rn);
2249                     afsmon_Exit(380);
2250                 }
2251                 gtxframe_AddToList(fsFrame, *fs_data_o_Ptr);
2252
2253                 fs_data_o_Ptr++;
2254             }                   /* for each column */
2255         }                       /* for each onode array index */
2256
2257         fs_lines_Ptr++;
2258     }                           /* for each host slot */
2259
2260
2261     /* INITIALIZE COLUMN LABELS */
2262
2263
2264     /* allocate memory for two arrays of onode pointers for file server column
2265      * labels */
2266     for (arrIdx = 0; arrIdx < 3; arrIdx++) {
2267
2268         fsLabels_o[arrIdx] = malloc(sizeof(struct onode *) * fs_cols_perPage);
2269         if (fsLabels_o[arrIdx] == NULL) {
2270             sprintf(errMsg,
2271                     "[ %s ] Failed to allocate memory for FS label onodes\n",
2272                     rn);
2273             afsmon_Exit(385);
2274         }
2275
2276         /* create cache manager name objects */
2277         fsLabels_o_Ptr = fsLabels_o[arrIdx];
2278         for (i = 0; i < fs_cols_perPage; i++) {
2279             *fsLabels_o_Ptr =
2280                 initLightObject("", FC_HOSTNAME_O_WIDTH + i * FC_COLUMN_WIDTH,
2281                                 FC_FIRST_LABEL_ROW + arrIdx, FC_COLUMN_WIDTH,
2282                                 afsmon_win);
2283
2284             if (*fsLabels_o_Ptr == NULL) {
2285                 sprintf(errMsg, "[ %s ] Failed to create a FS label onode\n",
2286                         rn);
2287                 afsmon_Exit(390);
2288             }
2289             gtxframe_AddToList(fsFrame, *fsLabels_o_Ptr);
2290             fsLabels_o_Ptr++;
2291         }
2292
2293     }
2294
2295
2296     /* initialize the column & page counters */
2297
2298     fs_currPage = 1;
2299     fs_numCols = fs_DisplayItems_count;
2300     fs_numPages = numFS / fs_numHosts_perPage;
2301     if (numFS % fs_numHosts_perPage)
2302         fs_numPages++;
2303     fs_curr_LCol = 0;           /* leftmost col */
2304     fs_curr_RCol = 0;           /* rightmost col */
2305
2306     /* create keyboard bindings */
2307     /* bind Q and \ 3 to exit */
2308     keymap_BindToString(fsFrame->keymap, "Q", afsmonExit_gtx, NULL, NULL);
2309     keymap_BindToString(fsFrame->keymap, "\ 3", afsmonExit_gtx, NULL, NULL);
2310
2311     /* o = overview, c = cm, n = next, p = prev, l = left, r = right
2312      * N = last page, P = first page, L = leftmost col, R = rightmost col */
2313
2314     keymap_BindToString(fsFrame->keymap, "o", Switch_fs_2_ovw, NULL, NULL);
2315     keymap_BindToString(fsFrame->keymap, "c", Switch_fs_2_cm, NULL, NULL);
2316     keymap_BindToString(fsFrame->keymap, "n", Switch_fs_next, NULL, NULL);
2317     keymap_BindToString(fsFrame->keymap, "N", Switch_fs_last, NULL, NULL);
2318     keymap_BindToString(fsFrame->keymap, "p", Switch_fs_prev, NULL, NULL);
2319     keymap_BindToString(fsFrame->keymap, "P", Switch_fs_first, NULL, NULL);
2320     keymap_BindToString(fsFrame->keymap, "l", Switch_fs_left, NULL, NULL);
2321     keymap_BindToString(fsFrame->keymap, "L", Switch_fs_leftmost, NULL, NULL);
2322     keymap_BindToString(fsFrame->keymap, "r", Switch_fs_right, NULL, NULL);
2323     keymap_BindToString(fsFrame->keymap, "R", Switch_fs_rightmost, NULL,
2324                         NULL);
2325
2326     return (0);
2327 }                               /* create_FSframe_objects */
2328
2329
2330 /*-----------------------------------------------------------------------
2331  * Function:    cm_refresh()
2332  *
2333  * Description:
2334  *      Refresh the Cache Managers screen with the given page number starting
2335  *      at the given left-column number. The appropriate contents of
2336  *      prev_cmData are displayed.
2337  *      First the status labels at the four corners of the screen are
2338  *      updated. Next the column labels are updated and then each row
2339  *      of statistics.
2340  *
2341  * Returns:
2342  *      Success: 0
2343  *      Failure: Exits afsmoitor on a severe error.
2344  *----------------------------------------------------------------------*/
2345
2346 int
2347 cm_refresh(int a_pageNum,               /* page to display */
2348            int a_LcolNum)               /* starting (leftmost) column number */
2349 {                               /* cm_refresh */
2350
2351     static char rn[] = "cm_refresh";    /* routine name */
2352     struct gator_lightobj *tmp_lightobj;        /* ptr for object's display data */
2353     struct cm_Display_Data *cmDataP;    /* ptr to CM display data array */
2354     struct ServerInfo_line *tmp_cm_lines_P;     /* tmp ptr to cm_lines */
2355     struct onode **firstSlot_o_Ptr;     /* ptr to first data slot of a datum */
2356     struct onode **secondSlot_o_Ptr;    /* ptr to second data slot of a datum */
2357     struct onode **cmLabels_o_Ptr1;     /* ptr to label row 0 */
2358     struct onode **cmLabels_o_Ptr2;     /* ptr to label row 1 */
2359     struct onode **cmLabels_o_Ptr3;     /* ptr to label row 2 */
2360     char cmdLine[80];           /* buffer for command line */
2361     char printBuf[256];         /* buffer to print to screen */
2362     int i;
2363     int j;
2364     int k;
2365     int code;
2366     int cmIdx;
2367     int labelIdx;
2368     int dataIndex;              /* index to the data[] field of
2369                                  * struct cm_Display_Data */
2370
2371     if (afsmon_debug) {
2372         fprintf(debugFD, "[ %s ] Called, a_pageNum= %d, a_LcolNum= %d \n", rn,
2373                 a_pageNum, a_LcolNum);
2374         fflush(debugFD);
2375     }
2376
2377
2378     /* if the data is not yet available, ie., not one probe cycle has
2379      * completed, do nothing */
2380
2381     if (!cm_Data_Available)
2382         return (0);
2383
2384
2385     /* validate the page number & column number */
2386     if (a_pageNum < 1 || a_pageNum > cm_numPages) {
2387         if (afsmon_debug) {
2388             fprintf(debugFD, "[ %s ] Called with wrong page # %d \n", rn,
2389                     a_pageNum);
2390             fflush(debugFD);
2391         }
2392         afsmon_Exit(395);
2393     }
2394     if (a_LcolNum < 0 || a_LcolNum > cm_numCols) {
2395         if (afsmon_debug) {
2396             fprintf(debugFD, "[ %s ] Called with wrong column #%d\n", rn,
2397                     a_LcolNum);
2398             fflush(debugFD);
2399         }
2400         afsmon_Exit(400);
2401     }
2402
2403
2404
2405     /* update the fixed labels */
2406
2407     /* we reuse the ovw version lable and hence do not have to do anything
2408      * for it here */
2409
2410     /* page number label */
2411     tmp_lightobj = (struct gator_lightobj *)cm_pageNum_o->o_data;
2412     sprintf(printBuf, "[Cache Managers, p.%d of %d, c.%d of %d]", a_pageNum,
2413             cm_numPages, a_LcolNum + 1, cm_numCols);
2414     justify_light(printBuf, tmp_lightobj->label, FC_PAGENUM_O_WIDTH,
2415                   RIGHT_JUSTIFY, 1);
2416     gator_light_set(cm_pageNum_o, 1);
2417
2418     /* file servers monitored label */
2419     tmp_lightobj = (struct gator_lightobj *)cm_numCM_o->o_data;
2420     sprintf(printBuf, "%d Cache Managers monitored, %d alerts on %d machines",
2421             numCM, num_cm_alerts, numHosts_oncm_alerts);
2422     justify_light(printBuf, tmp_lightobj->label, FC_NUMHOSTS_O_WIDTH, CENTER,
2423                   1);
2424
2425
2426     /* command line */
2427
2428     /* figure out what we need to show in the prompt & set the page type */
2429     /* the cm_pageType variable is in turn used by the keyboard handler
2430      * routines to call cm_refresh() with the correct parameters */
2431
2432     cm_pageType = resolve_CmdLine(cmdLine, 2 /* cm frame */ , a_pageNum,
2433                                   cm_numPages, cm_numCols, a_LcolNum,
2434                                   cm_cols_perPage, 0);
2435
2436     /* display the command line */
2437     tmp_lightobj = (struct gator_lightobj *)cm_cmd_o->o_data;
2438     sprintf(printBuf, "%s", cmdLine);
2439     justify_light(printBuf, tmp_lightobj->label, strlen(printBuf) + 1,
2440                   LEFT_JUSTIFY, 1);
2441     gator_light_set(cm_cmd_o, 1);
2442
2443     /* update the probe number label */
2444     tmp_lightobj = (struct gator_lightobj *)cm_probeNum_o->o_data;
2445     sprintf(printBuf, "[CM probes %d, freq=%d sec]", afsmon_cm_prev_probeNum,
2446             afsmon_probefreq);
2447     justify_light(printBuf, tmp_lightobj->label, FC_PROBENUM_O_WIDTH,
2448                   RIGHT_JUSTIFY, 1);
2449     gator_light_set(cm_cmd_o, 1);
2450
2451     /* update "columns on left" signal */
2452     tmp_lightobj = (struct gator_lightobj *)cm_leftArrows_o->o_data;
2453     if (cm_pageType & CMD_LEFT)
2454         strcpy(printBuf, "<<<");
2455     else
2456         strcpy(printBuf, "");
2457     justify_light(printBuf, tmp_lightobj->label, FC_ARROWS_O_WIDTH,
2458                   LEFT_JUSTIFY, 1);
2459     gator_light_set(cm_leftArrows_o, 0);
2460
2461     /* update "columns on right" signal */
2462     tmp_lightobj = (struct gator_lightobj *)cm_rightArrows_o->o_data;
2463     if (cm_pageType & CMD_RIGHT)
2464         strcpy(printBuf, ">>>");
2465     else
2466         strcpy(printBuf, "");
2467     justify_light(printBuf, tmp_lightobj->label, FC_ARROWS_O_WIDTH,
2468                   RIGHT_JUSTIFY, 1);
2469     gator_light_set(cm_rightArrows_o, 0);
2470
2471
2472
2473     /* UPDATE THE COLUMN LABELS */
2474
2475     /* the column index is also used to index the label arrays */
2476     labelIdx = a_LcolNum;
2477
2478     /* get the pointers to the three arrays of label onodes */
2479     cmLabels_o_Ptr1 = cmLabels_o[0];
2480     cmLabels_o_Ptr2 = cmLabels_o[1];
2481     cmLabels_o_Ptr3 = cmLabels_o[2];
2482
2483     for (k = 0; k < cm_cols_perPage; k++) {
2484
2485         if (labelIdx < cm_numCols) {
2486             dataIndex = cm_Display_map[labelIdx];
2487             display_Server_label(cm_labels[dataIndex], *cmLabels_o_Ptr1,
2488                                  *cmLabels_o_Ptr2, *cmLabels_o_Ptr3);
2489
2490             labelIdx++;         /* next label */
2491         } else {
2492             display_Server_label("//", *cmLabels_o_Ptr1, *cmLabels_o_Ptr2,
2493                                  *cmLabels_o_Ptr3);
2494         }
2495
2496         cmLabels_o_Ptr1++;      /* next onode in label row 1 */
2497         cmLabels_o_Ptr2++;      /* next onode in label row 2 */
2498         cmLabels_o_Ptr3++;      /* next onode in label row 3 */
2499
2500     }                           /* labels for each column */
2501
2502
2503     /* UPDATE THE FILE SERVER STATISTICS */
2504
2505     /* move to the right spot in the CM display data array */
2506     cmDataP = prev_cmData;
2507     cmIdx = 0;
2508     for (i = 0; i < ((a_pageNum - 1) * cm_numHosts_perPage); i++) {
2509         cmDataP++;
2510         cmIdx++;
2511     }
2512
2513     if (cmIdx >= numCM) {       /* whoops! screwed up */
2514         sprintf(errMsg, "[ %s ] Programming error 1\n", rn);
2515         afsmon_Exit(405);
2516     }
2517
2518     /* get the pointer to the first line of onodes of the file server frame */
2519     tmp_cm_lines_P = cm_lines;
2520
2521     for (i = 0; i < cm_numHosts_perPage; i++) {
2522
2523
2524         /* if this is the last page we may not have file servers to fill up
2525          * the page, so check the index */
2526         if (cmIdx < numCM) {
2527
2528             if (cmDataP->hostName[0] == '\0') {
2529                 sprintf(errMsg, "[ %s ] empty cm display entry \n", rn);
2530                 afsmon_Exit(410);
2531             }
2532
2533             /* display the hostname , first names only please! */
2534
2535             sprintf(printBuf, "%s", cmDataP->hostName);
2536             for (j = 0; j < strlen(printBuf); j++) {
2537                 if (printBuf[j] == '.') {
2538                     printBuf[j] = '\0';
2539                     break;
2540                 }
2541             }
2542
2543             tmp_lightobj =
2544                 (struct gator_lightobj *)tmp_cm_lines_P->host_o->o_data;
2545             code =
2546                 justify_light(printBuf, tmp_lightobj->label,
2547                               FC_HOSTNAME_O_WIDTH, LEFT_JUSTIFY, 1);
2548             if (code) {
2549                 fprintf(debugFD, "[ %s ] justify_code returned %d\n", rn,
2550                         code);
2551                 fflush(debugFD);
2552             }
2553
2554             /* use the current column value to index into the cm_Display_map
2555              * array to obtain the index of the item to display. check if its
2556              * overflow flag is set and highlight if so. if the probe had failed
2557              * enter "--" is all columns */
2558
2559             /* each host has two rows of slots for datums. get the pointers to
2560              * both the arrays */
2561
2562             firstSlot_o_Ptr = tmp_cm_lines_P->data_o[0];
2563             secondSlot_o_Ptr = tmp_cm_lines_P->data_o[1];
2564             cm_curr_RCol = a_LcolNum;   /* starting column number from which
2565                                          * we are asked to display data */
2566
2567             for (j = 0; j < cm_cols_perPage; j++) {     /* for each column */
2568
2569                 /* if there is another column of data */
2570                 if (cm_curr_RCol < cm_numCols) {
2571
2572                     dataIndex = cm_Display_map[cm_curr_RCol];
2573
2574                     display_Server_datum(cmDataP->data[dataIndex],
2575                                          *firstSlot_o_Ptr,
2576                                          *secondSlot_o_Ptr,
2577                                          cmDataP->probeOK, RIGHT_JUSTIFY,
2578                                          cmDataP->threshOvf[dataIndex]);
2579
2580                     cm_curr_RCol++;
2581                 } else {        /* no more data, blank out columns */
2582                     display_Server_datum("", *firstSlot_o_Ptr, *secondSlot_o_Ptr, 1,    /* probe ok */
2583                                          RIGHT_JUSTIFY, 0);     /* no overflow */
2584                 }
2585
2586
2587                 firstSlot_o_Ptr++;      /* onode of next column */
2588                 secondSlot_o_Ptr++;     /* onode of next column */
2589
2590             }                   /* for each column */
2591
2592             /* the loop could have taken the right-column-index one over,
2593              * adjust it now */
2594             if (cm_curr_RCol == cm_numCols)
2595                 cm_curr_RCol--;
2596
2597
2598         }
2599
2600
2601
2602         /* if fdIdx < numCM */
2603         /* if cmIdx >= numCM , blank out all succeding rows */
2604         if (cmIdx >= numCM) {
2605
2606             /* blank out host name object */
2607             tmp_lightobj =
2608                 (struct gator_lightobj *)tmp_cm_lines_P->host_o->o_data;
2609             code =
2610                 justify_light("", tmp_lightobj->label, FC_HOSTNAME_O_WIDTH,
2611                               LEFT_JUSTIFY, 1);
2612             if (code) {
2613                 fprintf(debugFD, "[ %s ] justify_code returned %d\n", rn,
2614                         code);
2615                 fflush(debugFD);
2616             }
2617
2618             firstSlot_o_Ptr = tmp_cm_lines_P->data_o[0];
2619             secondSlot_o_Ptr = tmp_cm_lines_P->data_o[1];
2620
2621             for (k = 0; k < cm_cols_perPage; k++) {
2622                 display_Server_datum("", *firstSlot_o_Ptr, *secondSlot_o_Ptr, 1,        /* probe OK */
2623                                             RIGHT_JUSTIFY, 0);  /* dont highlight */
2624
2625                 firstSlot_o_Ptr++;
2626                 secondSlot_o_Ptr++;
2627             }
2628
2629         }
2630
2631         /* cmIDx >= numCM */
2632         tmp_cm_lines_P++;       /* pointer to next line in the frame */
2633         cmDataP++;              /* next host's data */
2634         cmIdx++;                /* host index */
2635
2636
2637     }                           /* for each row in the Cache Manager frame */
2638
2639     /* redraw the display if the Cache Managers screen is currently displayed */
2640     if (afsmon_win->w_frame == cmFrame)
2641         WOP_DISPLAY(afsmon_win);
2642
2643     /* update the global page & column numbers to reflect the changes */
2644     cm_currPage = a_pageNum;
2645     cm_curr_LCol = a_LcolNum;;
2646
2647     return (0);
2648
2649 }                               /* cm_refresh */
2650
2651
2652
2653 /*-----------------------------------------------------------------------
2654  * Switch_cm_2_ovw()
2655  *
2656  * Description:
2657  *      Switch from the Cache Manager screen to the Overview Screen
2658  *----------------------------------------------------------------------*/
2659 int
2660 Switch_cm_2_ovw(void *d1, void *d2)
2661 {
2662     /* bind the overview frame to the window */
2663     gtxframe_SetFrame(afsmon_win, ovwFrame);
2664     return (0);
2665 }
2666
2667 /*-----------------------------------------------------------------------
2668  * Switch_cm_2_fs()
2669  *
2670  * Description:
2671  *      Switch from the Cache Manager screen to the File Servers screen
2672  *----------------------------------------------------------------------*/
2673 int
2674 Switch_cm_2_fs(void *d1, void *d2)
2675 {
2676     if (cm_pageType & CMD_FS) {
2677         /* bind the file servers frame to the window */
2678         gtxframe_SetFrame(afsmon_win, fsFrame);
2679     }
2680     return (0);
2681 }
2682
2683 /*-----------------------------------------------------------------------
2684  * Switch_cm_next()
2685  *
2686  * Description:
2687  *      Switch to next page of cache managers screen
2688  *----------------------------------------------------------------------*/
2689 int
2690 Switch_cm_next(void *d1, void *d2)
2691 {
2692     if (cm_pageType & CMD_NEXT) {
2693         /* we have a next page, refresh with next page number */
2694         cm_refresh(cm_currPage + 1, cm_curr_LCol);
2695     }
2696
2697     return (0);
2698 }
2699
2700 /*-----------------------------------------------------------------------
2701  * Switch_cm_last()
2702  *
2703  * Description:
2704  *      Switch to last page of file server screen
2705  *----------------------------------------------------------------------*/
2706 int
2707 Switch_cm_last(void *d1, void *d2)
2708 {
2709     if (cm_pageType & CMD_NEXT) {
2710         /* we have a next page, refresh with last page number */
2711         cm_refresh(cm_numPages, cm_curr_LCol);
2712     }
2713
2714     return (0);
2715 }
2716
2717 /*-----------------------------------------------------------------------
2718  * Switch_cm_prev()
2719  *
2720  * Description:
2721  *      Switch to previous page of cache managers screen
2722  *----------------------------------------------------------------------*/
2723 int
2724 Switch_cm_prev(void *d1, void *d2)
2725 {
2726     if (cm_pageType & CMD_PREV) {
2727         /* we have a previous page, refresh to previous page */
2728         cm_refresh(cm_currPage - 1, cm_curr_LCol);
2729     }
2730     return (0);
2731 }
2732
2733 /*-----------------------------------------------------------------------
2734  * Switch_cm_first()
2735  *
2736  * Description:
2737  *      Switch to first page of cache managers screen
2738  *----------------------------------------------------------------------*/
2739 int
2740 Switch_cm_first(void *d1, void *d2)
2741 {
2742     if (cm_pageType & CMD_PREV) {
2743         /* we have a previous page, refresh to first page */
2744         cm_refresh(1, cm_curr_LCol);
2745     }
2746     return (0);
2747 }
2748
2749 /*-----------------------------------------------------------------------
2750  * Switch_cm_left()
2751  *
2752  * Description:
2753  *      Scroll left on the cache managers screen
2754  *----------------------------------------------------------------------*/
2755 int
2756 Switch_cm_left(void *d1, void *d2)
2757 {
2758     if (cm_pageType & CMD_LEFT) {
2759         /* we have columns on left, refresh with new column number */
2760         cm_refresh(cm_currPage, cm_curr_LCol - cm_cols_perPage);
2761     }
2762     return (0);
2763 }
2764
2765
2766 /*-----------------------------------------------------------------------
2767  * Switch_cm_leftmost()
2768  *
2769  * Description:
2770  *      Scroll to first column on  the cache managers screen
2771  *----------------------------------------------------------------------*/
2772 int
2773 Switch_cm_leftmost(void *d1, void *d2)
2774 {
2775     if (cm_pageType & CMD_LEFT) {
2776         /* we have columns on left, go to the first column */
2777         cm_refresh(cm_currPage, 0);
2778     }
2779     return (0);
2780 }
2781
2782 /*-----------------------------------------------------------------------
2783  * Switch_cm_right()
2784  *
2785  * Description:
2786  *      Scroll right on the cache managers screen
2787  *----------------------------------------------------------------------*/
2788 int
2789 Switch_cm_right(void *d1, void *d2)
2790 {
2791     if (cm_pageType & CMD_RIGHT) {
2792         /* we have columns on right, refresh with new column number */
2793         cm_refresh(cm_currPage, cm_curr_LCol + cm_cols_perPage);
2794     }
2795     return (0);
2796 }
2797
2798 /*-----------------------------------------------------------------------
2799  * Switch_cm_rightmost()
2800  *
2801  * Description:
2802  *      Scroll to last column on the cache managers screen
2803  *----------------------------------------------------------------------*/
2804 int
2805 Switch_cm_rightmost(void *d1, void *d2)
2806 {
2807     int curr_LCol;
2808
2809     if (cm_pageType & CMD_RIGHT) {
2810         /* we have columns on right, go to the last column */
2811         if (cm_numCols % cm_cols_perPage)
2812             curr_LCol = (cm_numCols / cm_cols_perPage) * cm_cols_perPage;
2813         else
2814             curr_LCol =
2815                 ((cm_numCols / cm_cols_perPage) - 1) * cm_cols_perPage;
2816         cm_refresh(cm_currPage, curr_LCol);
2817     }
2818     return (0);
2819 }
2820
2821
2822 /*-----------------------------------------------------------------------
2823  * create_CMframe_objects()
2824  *
2825  * Description:
2826  *      Create the gtx objects (onodes) for the Cache Managers frame and setup
2827  *      the keyboard bindings.
2828  *      Only as many objects as can fit on the display are created. The
2829  *      positions and lengths of all these objects are fixed at creation.
2830  *      These objects are updated with new data at the end of each probe
2831  *      cycle.
2832  *
2833  * Returns:
2834  *      Success: 0
2835  *      Failure: Exits afsmonitor.
2836  *----------------------------------------------------------------------*/
2837
2838 int
2839 create_CMframe_objects(void)
2840 {                               /* create_CMframe_objects */
2841     static char rn[] = "create_CMframe_objects";
2842     struct ServerInfo_line *cm_lines_Ptr;
2843     struct onode **cm_data_o_Ptr;
2844     struct onode **cmLabels_o_Ptr;
2845     int x_pos;
2846     int y_pos;
2847     int i;
2848     int j;
2849     int numBytes;
2850     int arrIdx;
2851
2852     if (afsmon_debug) {
2853         fprintf(debugFD, "[ %s ] Called\n", rn);
2854         fflush(debugFD);
2855     }
2856
2857
2858
2859     /* create the command line object */
2860     cm_cmd_o =
2861         initLightObject("Command [oview, fs, prev, next, left, right] ? ", 0,
2862                         maxY - 1, FC_CMD_O_WIDTH, afsmon_win);
2863     if (cm_cmd_o == NULL) {
2864         sprintf(errMsg, "[ %s ] Failed to create cm command onode\n", rn);
2865         afsmon_Exit(420);
2866     }
2867     gtxframe_AddToList(cmFrame, cm_cmd_o);
2868     gator_light_set(cm_cmd_o, HIGHLIGHT);
2869
2870
2871     /* we already have the dimensions for the frame - same as the ovw frame */
2872     /* use the ovw program name object for the cm screen too */
2873
2874     gtxframe_AddToList(cmFrame, ovw_progName_o);
2875
2876
2877     /* create the page number object */
2878     cm_pageNum_o =
2879         initLightObject("[Cache Managers, p. X of X, c. Y of Y]",
2880                         maxX - FC_PAGENUM_O_WIDTH, 0, FC_PAGENUM_O_WIDTH,
2881                         afsmon_win);
2882     if (cm_pageNum_o == NULL) {
2883         sprintf(errMsg, "[ %s ] Failed to create pageNumber onode\n", rn);
2884         afsmon_Exit(415);
2885     }
2886     gtxframe_AddToList(cmFrame, cm_pageNum_o);
2887     gator_light_set(cm_pageNum_o, HIGHLIGHT);
2888
2889     /* create the probe number object */
2890     cm_probeNum_o =
2891         initLightObject("[CM probes 1, freq=30 sec]",
2892                         maxX - FC_PROBENUM_O_WIDTH, maxY - 1,
2893                         FC_PROBENUM_O_WIDTH, afsmon_win);
2894     if (cm_probeNum_o == NULL) {
2895         sprintf(errMsg, "[ %s ] Failed to create cm probeNum onode\n", rn);
2896         afsmon_Exit(425);
2897     }
2898     gtxframe_AddToList(cmFrame, cm_probeNum_o);
2899     gator_light_set(cm_probeNum_o, HIGHLIGHT);
2900
2901
2902     /* create the numCM monitored object */
2903     cm_numCM_o =
2904         initLightObject
2905         ("      0 Cache Mangers monitored, 0 alerts on 0 machines", 4, 2,
2906          FC_NUMHOSTS_O_WIDTH, afsmon_win);
2907     if (cm_numCM_o == NULL) {
2908         sprintf(errMsg,
2909                 "[ %s ] Failed to create numCM onode for the cm frame\n", rn);
2910         afsmon_Exit(430);
2911     }
2912     gtxframe_AddToList(cmFrame, cm_numCM_o);
2913
2914     /* create the "more columns to left" indicator */
2915     cm_leftArrows_o =
2916         initLightObject("<<<", 0, 2, FC_ARROWS_O_WIDTH, afsmon_win);
2917     if (cm_leftArrows_o == NULL) {
2918         sprintf(errMsg,
2919                 "[ %s ] Failed to create leftArrows onode for the cm frame\n",
2920                 rn);
2921         afsmon_Exit(435);
2922     }
2923     gtxframe_AddToList(cmFrame, cm_leftArrows_o);
2924
2925     /* create the "more columns to right" indicator */
2926     cm_rightArrows_o =
2927         initLightObject(">>>", maxX - FC_ARROWS_O_WIDTH, 2, FC_ARROWS_O_WIDTH,
2928                         afsmon_win);
2929     if (cm_rightArrows_o == NULL) {
2930         sprintf(errMsg,
2931                 "[ %s ] Failed to create rightArrows onode for the cm frame\n",
2932                 rn);
2933         afsmon_Exit(440);
2934     }
2935     gtxframe_AddToList(cmFrame, cm_rightArrows_o);
2936
2937
2938
2939
2940     /* calculate the maximum number of hosts per page (2 rows per host) */
2941     cm_numHosts_perPage = (maxY - FC_NUM_FIXED_LINES) / 2;
2942
2943     /* determine the number of data columns that can fit in a page */
2944     cm_cols_perPage = (maxX - FC_HOSTNAME_O_WIDTH) / (FC_COLUMN_WIDTH);
2945
2946     if (afsmon_debug) {
2947         fprintf(debugFD, "[ %s ] cm_numHosts_perPage=%d cm_cols_perPage=%d\n",
2948                 rn, cm_numHosts_perPage, cm_cols_perPage);
2949         fflush(debugFD);
2950     }
2951
2952     /* the above two variables give us the information needed to create
2953      * the objects for displaying the file server information */
2954
2955     /* allocate memory for all the onode pointers required to display
2956      * the file server statistics */
2957
2958     numBytes = cm_numHosts_perPage * sizeof(struct ServerInfo_line);
2959     cm_lines = malloc(numBytes);
2960     if (cm_lines == (struct ServerInfo_line *)0) {
2961         sprintf(errMsg,
2962                 "[ %s ] Failed to allocate %d bytes for CM data lines\n", rn,
2963                 numBytes);
2964         afsmon_Exit(445);
2965     }
2966
2967     /* for each line of server statistics allocate memory to store two arrays
2968      * of data onodes */
2969
2970     cm_lines_Ptr = cm_lines;
2971     for (i = 0; i < cm_numHosts_perPage; i++) {
2972         for (arrIdx = 0; arrIdx < 2; arrIdx++) {
2973             numBytes = cm_cols_perPage * sizeof(struct onode *);
2974             cm_lines_Ptr->data_o[arrIdx] = malloc(numBytes);
2975             if (cm_lines_Ptr->data_o[arrIdx] == NULL) {
2976                 sprintf(errMsg,
2977                         "[ %s ] Failed to allocate %d bytes for CM data onodes\n",
2978                         rn, numBytes);
2979                 afsmon_Exit(450);
2980             }
2981         }
2982         cm_lines_Ptr++;
2983     }
2984
2985     /* now allocate the onodes itself */
2986
2987     cm_lines_Ptr = cm_lines;
2988     for (i = 0; i < cm_numHosts_perPage; i++) {
2989
2990         /* initialize host name onode */
2991         cm_lines_Ptr->host_o =
2992             initLightObject("CMHostName", 0, FC_FIRST_HOST_ROW + 2 * i,
2993                             FC_HOSTNAME_O_WIDTH, afsmon_win);
2994         if (cm_lines_Ptr->host_o == NULL) {
2995             sprintf(errMsg, "[ %s ] Failed to create an CM name onode\n", rn);
2996             afsmon_Exit(455);
2997         }
2998         gtxframe_AddToList(cmFrame, cm_lines_Ptr->host_o);
2999
3000         /* if (afsmon_debug) {
3001          * fprintf(debugFD,"[ %s ] Addr of host_o = %d for line %d\n",
3002          * rn,cm_lines_Ptr->host_o,i);
3003          * fflush(debugFD);
3004          * } */
3005
3006         /* initialize data onodes for this host */
3007
3008         for (arrIdx = 0; arrIdx < 2; arrIdx++) {        /* for each array index */
3009
3010             cm_data_o_Ptr = cm_lines_Ptr->data_o[arrIdx];
3011             for (j = 0; j < cm_cols_perPage; j++) {     /* for each column */
3012
3013                 char tmpBuf[20];
3014
3015                 /* determine x & y coordinate for this data object */
3016                 /* the 1's are for leaving a blank after each column */
3017                 x_pos = FC_HOSTNAME_O_WIDTH + (j * (FC_COLUMN_WIDTH));
3018                 y_pos = FC_FIRST_HOST_ROW + 2 * i + arrIdx;
3019
3020                 sprintf(tmpBuf, "-CMData %d-", arrIdx);
3021                 *cm_data_o_Ptr =
3022                     initLightObject(tmpBuf, x_pos, y_pos, FC_COLUMN_WIDTH,
3023                                     afsmon_win);
3024                 if (*cm_data_o_Ptr == NULL) {
3025                     sprintf(errMsg,
3026                             "[ %s ] Failed to create an CM data onode\n", rn);
3027                     afsmon_Exit(460);
3028                 }
3029                 gtxframe_AddToList(cmFrame, *cm_data_o_Ptr);
3030
3031                 cm_data_o_Ptr++;
3032             }                   /* for each column */
3033         }                       /* for each onode array index */
3034
3035         cm_lines_Ptr++;
3036     }                           /* for each host slot */
3037
3038
3039     /* INITIALIZE COLUMN LABELS */
3040
3041
3042     /* allocate memory for two arrays of onode pointers for file server column
3043      * labels */
3044     for (arrIdx = 0; arrIdx < 3; arrIdx++) {
3045
3046         cmLabels_o[arrIdx] = malloc(sizeof(struct onode *) * cm_cols_perPage);
3047         if (cmLabels_o[arrIdx] == NULL) {
3048             sprintf(errMsg,
3049                     "[ %s ] Failed to allocate memory for CM label onodes\n",
3050                     rn);
3051             afsmon_Exit(465);
3052         }
3053
3054         /* create cache manager name objects */
3055         cmLabels_o_Ptr = cmLabels_o[arrIdx];
3056         for (i = 0; i < cm_cols_perPage; i++) {
3057             *cmLabels_o_Ptr =
3058                 initLightObject("", FC_HOSTNAME_O_WIDTH + i * FC_COLUMN_WIDTH,
3059                                 FC_FIRST_LABEL_ROW + arrIdx, FC_COLUMN_WIDTH,
3060                                 afsmon_win);
3061
3062             if (*cmLabels_o_Ptr == NULL) {
3063                 sprintf(errMsg, "[ %s ] Failed to create a CM label onode\n",
3064                         rn);
3065                 afsmon_Exit(470);
3066             }
3067             gtxframe_AddToList(cmFrame, *cmLabels_o_Ptr);
3068             cmLabels_o_Ptr++;
3069         }
3070
3071     }
3072
3073     /* initialize the column & page counters */
3074
3075     cm_currPage = 1;
3076     cm_numCols = cm_DisplayItems_count;
3077     cm_numPages = numCM / cm_numHosts_perPage;
3078     if (numCM % cm_numHosts_perPage)
3079         cm_numPages++;
3080     cm_curr_LCol = 0;           /* leftmost col */
3081     cm_curr_RCol = 0;           /* rightmost col */
3082
3083     /* create keyboard bindings */
3084     /* bind Q and \ 3 to exit */
3085     keymap_BindToString(cmFrame->keymap, "Q", afsmonExit_gtx, NULL, NULL);
3086     keymap_BindToString(cmFrame->keymap, "\ 3", afsmonExit_gtx, NULL, NULL);
3087
3088     /* o = overview, c = cm, n = next, p = prev, l = left, r = right
3089      * N = last page, P = first page, L = leftmost col, R = rightmost col */
3090
3091     keymap_BindToString(cmFrame->keymap, "o", Switch_cm_2_ovw, NULL, NULL);
3092     keymap_BindToString(cmFrame->keymap, "f", Switch_cm_2_fs, NULL, NULL);
3093     keymap_BindToString(cmFrame->keymap, "n", Switch_cm_next, NULL, NULL);
3094     keymap_BindToString(cmFrame->keymap, "N", Switch_cm_last, NULL, NULL);
3095     keymap_BindToString(cmFrame->keymap, "p", Switch_cm_prev, NULL, NULL);
3096     keymap_BindToString(cmFrame->keymap, "P", Switch_cm_first, NULL, NULL);
3097     keymap_BindToString(cmFrame->keymap, "l", Switch_cm_left, NULL, NULL);
3098     keymap_BindToString(cmFrame->keymap, "L", Switch_cm_leftmost, NULL, NULL);
3099     keymap_BindToString(cmFrame->keymap, "r", Switch_cm_right, NULL, NULL);
3100     keymap_BindToString(cmFrame->keymap, "R", Switch_cm_rightmost, NULL,
3101                         NULL);
3102
3103     return (0);
3104 }                               /* create_CMframe_objects */
3105
3106
3107
3108 /*-----------------------------------------------------------------------
3109  * gtx_initialize()
3110  *
3111  * Description:
3112  *      Initialize the gtx package and call routines to create the objects
3113  *      for the overview, File Servers & Cache Managers screens.
3114  *----------------------------------------------------------------------*/
3115 int
3116 gtx_initialize(void)
3117 {                               /* gtx_initialize */
3118     static char rn[] = "gtx_initialize";        /* routine name */
3119     int code;
3120
3121     if (afsmon_debug) {
3122         fprintf(debugFD, "[ %s ] Called\n", rn);
3123         fflush(debugFD);
3124     }
3125
3126     afsmon_win = gtx_Init(0, -1);       /* 0 => dont start input server,
3127                                          * 1 => use curses */
3128     if (afsmon_win == NULL) {
3129         sprintf(errMsg, "[ %s ] gtx initialization failed\n", rn);
3130         afsmon_Exit(475);
3131     }
3132     gtx_initialized = 1;
3133
3134     /* Create the Overview frame */
3135
3136     ovwFrame = gtxframe_Create();
3137     if (ovwFrame == (struct gtx_frame *)0) {
3138         sprintf(errMsg, "[ %s ] Failed to create overview frame\n", rn);
3139         afsmon_Exit(480);
3140     }
3141
3142     /* bind the overview frame to the window */
3143     gtxframe_SetFrame(afsmon_win, ovwFrame);
3144
3145     /* create overview frame objects */
3146     code = create_ovwFrame_objects();
3147     if (code) {
3148         sprintf(errMsg, "[ %s ] Error in creating ovw frame objects\n", rn);
3149         afsmon_Exit(485);
3150     }
3151
3152
3153     /* Create the File Server frame */
3154     fsFrame = gtxframe_Create();
3155     if (fsFrame == (struct gtx_frame *)0) {
3156         sprintf(errMsg, "[ %s ] Failed to create file server frame\n", rn);
3157         afsmon_Exit(490);
3158     }
3159
3160
3161     /* Create File Server frame objects */
3162     code = create_FSframe_objects();
3163     if (code) {
3164         sprintf(errMsg, "[ %s ] Error in creating FS frame objects\n", rn);
3165         afsmon_Exit(495);
3166     }
3167
3168     /* Create the Cache Managers frame */
3169     cmFrame = gtxframe_Create();
3170     if (cmFrame == (struct gtx_frame *)0) {
3171         sprintf(errMsg, "[ %s ] Failed to create Cache Managers frame\n", rn);
3172         afsmon_Exit(500);
3173     }
3174
3175     /* Create Cache Managers frame objects */
3176     code = create_CMframe_objects();
3177     if (code) {
3178         sprintf(errMsg, "[ %s ] Error in creating CM frame objects\n", rn);
3179         afsmon_Exit(505);
3180     }
3181
3182     /* misc initializations */
3183     sprintf(blankline, "%255s", " ");
3184
3185     return (0);
3186 }                               /* gtx_initialize */