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