dbservers: 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 =
1157         (struct onode **)malloc(sizeof(struct onode *) *
1158                                 ovw_numHosts_perPage);
1159     if (ovw_fsNames_o == NULL) {
1160         sprintf(errMsg, "[ %s ] Failed to allocate memory for FS onodes\n",
1161                 rn);
1162         afsmon_Exit(295);
1163     }
1164
1165     /* create file server name objects */
1166     ovw_fsNames_o_Ptr = ovw_fsNames_o;
1167     for (i = 0; i < ovw_numHosts_perPage; i++) {
1168         *ovw_fsNames_o_Ptr =
1169             initLightObject("", 0, OVW_FIRST_HOST_ROW + i,
1170                             OVW_HOSTNAME_O_WIDTH, afsmon_win);
1171         if (*ovw_fsNames_o_Ptr == NULL) {
1172             sprintf(errMsg, "[ %s ] Failed to create an FS name onode\n", rn);
1173             afsmon_Exit(300);
1174         }
1175         /*
1176          * if (afsmon_debug) {
1177          * fprintf(debugFD,"[ %s ] fsName_o  %d:  %d\n",
1178          * rn,i,*ovw_fsNames_o_Ptr);
1179          * fflush(debugFD);
1180          * }
1181          */
1182         gtxframe_AddToList(ovwFrame, *ovw_fsNames_o_Ptr);
1183         ovw_fsNames_o_Ptr++;
1184
1185     }
1186
1187
1188     /* allocate memory for a list of onode pointers for cache manager names */
1189     ovw_cmNames_o =
1190         (struct onode **)malloc(sizeof(struct onode *) *
1191                                 ovw_numHosts_perPage);
1192     if (ovw_cmNames_o == NULL) {
1193         sprintf(errMsg, "[ %s ] Failed to allocate memory for CM onodes\n",
1194                 rn);
1195         afsmon_Exit(305);
1196     }
1197
1198     /* create cache manager name objects */
1199     ovw_cmNames_o_Ptr = ovw_cmNames_o;
1200     for (i = 0; i < ovw_numHosts_perPage; i++) {
1201         *ovw_cmNames_o_Ptr =
1202             initLightObject("", maxX / 2, OVW_FIRST_HOST_ROW + i,
1203                             OVW_HOSTNAME_O_WIDTH, afsmon_win);
1204         if (*ovw_cmNames_o_Ptr == NULL) {
1205             sprintf(errMsg, "[ %s ] Failed to create a CM name onode\n", rn);
1206             afsmon_Exit(310);
1207         }
1208         gtxframe_AddToList(ovwFrame, *ovw_cmNames_o_Ptr);
1209         ovw_cmNames_o_Ptr++;
1210     }
1211
1212
1213     /* Calculate the number of pages of overview data to display */
1214     /* host information starts at the 6th line from top and stops at 3rd
1215      * line from bottom of screen */
1216
1217     if (numFS > numCM)
1218         hostLines = numFS;
1219     else
1220         hostLines = numCM;
1221
1222     ovw_numPages = hostLines / (maxY - OVW_NUM_FIXED_LINES);
1223     if (hostLines % (maxY - OVW_NUM_FIXED_LINES))
1224         ovw_numPages++;
1225
1226     if (afsmon_debug)
1227         fprintf(debugFD, "[ %s ] number of ovw pages = %d\n", rn,
1228                 ovw_numPages);
1229
1230     /* When the ovw_refresh() routine is called by the keyboard handlers the
1231      * following variable is used to determine if fs/cm/fs&cm info must be
1232      * updated */
1233     ovw_update_info = 0;
1234     if (numFS)
1235         ovw_update_info |= OVW_UPDATE_FS;
1236     if (numCM)
1237         ovw_update_info |= OVW_UPDATE_CM;
1238
1239     /* bind the overview frame to a keyboard input handler */
1240
1241     /* bind Q and \ 3 to exit */
1242     keymap_BindToString(ovwFrame->keymap, "Q", afsmonExit_gtx, NULL, NULL);
1243     keymap_BindToString(ovwFrame->keymap, "\ 3", afsmonExit_gtx, NULL, NULL);
1244
1245     /* f -> switch of fs frame */
1246     keymap_BindToString(ovwFrame->keymap, "f", Switch_ovw_2_fs, NULL, NULL);
1247     /* c -> switch of cm frame */
1248     keymap_BindToString(ovwFrame->keymap, "c", Switch_ovw_2_cm, NULL, NULL);
1249     /* n -> switch to next overview page */
1250     keymap_BindToString(ovwFrame->keymap, "n", Switch_ovw_next, NULL, NULL);
1251     /* N -> switch to last overview page */
1252     keymap_BindToString(ovwFrame->keymap, "N", Switch_ovw_last, NULL, NULL);
1253     /* p -> switch to previous overview page */
1254     keymap_BindToString(ovwFrame->keymap, "p", Switch_ovw_prev, NULL, NULL);
1255     /* P -> switch to first overview page */
1256     keymap_BindToString(ovwFrame->keymap, "P", Switch_ovw_first, NULL, NULL);
1257
1258
1259     return (0);
1260 }                               /* create_ovwFrame_objects */
1261
1262
1263 /*-----------------------------------------------------------------------
1264  * resolve_CmdLine()
1265  *
1266  * Description:
1267  *      This function is called to determine the permissible keyboard
1268  *      operations on the FS and CM frames. This information is used
1269  *      to create an appropriate command line prompt. It also generates
1270  *      a bit map of the permissible operations on this page which is
1271  *      used by the keyboard-input handler routines.
1272  *
1273  * Returns:
1274  *      Success: page-type (bit map of permissible operations)
1275  *      Failure: -1
1276  *----------------------------------------------------------------------*/
1277
1278 int
1279 resolve_CmdLine(char *a_buffer,     /* buffer to copy command line */
1280                 int a_currFrame,    /* current frame ovw, fs or cm? */
1281                 int a_currPage,     /* current page number */
1282                 int a_numPages,     /* number of pages of data */
1283                 int a_numCols,      /* number of columns of data to display */
1284                 int a_curr_LCol,    /* current number of leftmost column */
1285                 int a_cols_perPage, /* number of columns per page */
1286                 int a_Data_Available)
1287 {                               /* resolve_CmdLine */
1288     static char rn[] = "resolve_CmdLine";
1289     int pageType;
1290
1291     if (afsmon_debug) {
1292         fprintf(debugFD,
1293                 "[ %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",
1294                 rn, a_buffer, a_currFrame, a_currPage, a_numPages, a_numCols,
1295                 a_curr_LCol, a_cols_perPage);
1296         fflush(debugFD);
1297     }
1298
1299     pageType = 0;
1300
1301     /* determine if we have fs/cm frames. If we do, note that we should not
1302      * let the user seen the initial junk we have there until the probe
1303      * results are available  */
1304     if (a_currFrame == 1) {     /* in the fs frame */
1305         if (numCM && cm_Data_Available)
1306             pageType |= CMD_CM;
1307     } else if (a_currFrame == 2) {      /* in the cm frame */
1308         if (numFS && fs_Data_Available)
1309             pageType |= CMD_FS;
1310     } else {
1311         if (afsmon_debug) {
1312             fprintf(debugFD, "[ %s ] Wrong frame type %d\n", rn, a_currFrame);
1313             fflush(debugFD);
1314         }
1315         return (-1);
1316     }
1317
1318     /* do we have next/previous pages */
1319     if (a_currPage < a_numPages)
1320         pageType |= CMD_NEXT;   /* have a next page */
1321     if (a_currPage > 1)
1322         pageType |= CMD_PREV;   /* have a previous page */
1323
1324     if (a_numCols > a_cols_perPage) {
1325         if (a_curr_LCol > 0)
1326             pageType |= CMD_LEFT;       /* have columns on left */
1327         if ((a_curr_LCol + a_cols_perPage) < a_numCols)
1328             pageType |= CMD_RIGHT;      /* have columns on right */
1329     }
1330
1331     /* now build the command line */
1332
1333     strcpy(a_buffer, "Command [oview");
1334     if (pageType & CMD_FS)
1335         strcat(a_buffer, ", fs");
1336     if (pageType & CMD_CM)
1337         strcat(a_buffer, ", cm");
1338     if (pageType & CMD_PREV)
1339         strcat(a_buffer, ", prev");
1340     if (pageType & CMD_NEXT)
1341         strcat(a_buffer, ", next");
1342     if (pageType & CMD_LEFT)
1343         strcat(a_buffer, ", left");
1344     if (pageType & CMD_RIGHT)
1345         strcat(a_buffer, ", right");
1346     strcat(a_buffer, "]? ");
1347
1348     return (pageType);
1349
1350 }                               /* resolve_CmdLine */
1351
1352 /*-----------------------------------------------------------------------
1353  * display_Server_datum()
1354  *
1355  * Description:
1356  *      The data in the file server & cache manager frames are displayed
1357  *      in two objects, one below the other. If the data is too long to
1358  *      fit in the first object it will overflow into the next. This is
1359  *      to conserve real estate on the screen. This function copies the
1360  *      contents of the source buffer adjusted to the two objects if the
1361  *      probe had succeded. Otherwise it enters "--" in the first object
1362  *      blanks out the second. If the object needs to be highlightned
1363  *      (due to a threshold crossing) it is done.
1364  *
1365  * Returns:
1366  *      0 always
1367  *----------------------------------------------------------------------*/
1368 int
1369 display_Server_datum(char *a_srcBuf,              /* source buffer */
1370                      struct onode *a_firstObj_o,  /* first object */
1371                      struct onode *a_secondObj_o, /* second object */
1372                      int a_probeOK,               /* probe OK ? */
1373                      int a_just,                  /* justification */
1374                      int a_highlight)             /* highlight object  ? */
1375 {                               /* display_Server_datum */
1376
1377     static char rn[] = "display_Server_datum";
1378     struct gator_lightobj *tmp_lightobj1;
1379     struct gator_lightobj *tmp_lightobj2;
1380     char part1[FC_COLUMN_WIDTH + 2];
1381     char part2[FC_COLUMN_WIDTH + 2];
1382     int code;
1383
1384     if (afsmon_debug) {
1385         if (a_highlight)
1386             fprintf(debugFD,
1387                     "[ %s ] Called, a_srcBuf= %s, a_firstObj_o= %p, a_secondObj_o= %p, a_probeOK= %d, a_just= %d, a_highlight= %d\n",
1388                     rn, a_srcBuf, a_firstObj_o, a_secondObj_o, a_probeOK,
1389                     a_just, a_highlight);
1390         fflush(debugFD);
1391     }
1392
1393
1394     tmp_lightobj1 = (struct gator_lightobj *)a_firstObj_o->o_data;
1395     tmp_lightobj2 = (struct gator_lightobj *)a_secondObj_o->o_data;
1396
1397     if (a_probeOK) {            /* probe is ok so fill in the data */
1398
1399         /* check if it would fit in one object */
1400         if (strlen(a_srcBuf) < FC_COLUMN_WIDTH) {
1401             strcpy(part1, a_srcBuf);
1402             strcpy(part2, "");
1403         } else {
1404             /* break up the src string into 2 parts */
1405             /* note that column width includes terminator */
1406             strncpy(part1, a_srcBuf, FC_COLUMN_WIDTH - 1);
1407             part1[FC_COLUMN_WIDTH - 1] = '\0';
1408             strncpy(part2, a_srcBuf + FC_COLUMN_WIDTH - 1,
1409                     FC_COLUMN_WIDTH - 1);
1410
1411         }
1412
1413     } else {                    /* probe failed, enter "--"s */
1414         strcpy(part1, "--");
1415         strcpy(part2, "");
1416     }
1417
1418     /* if (afsmon_debug) {
1419      * fprintf(debugFD,"[ %s ] %s split to %s & %s\n",rn,a_srcBuf,part1,part2);
1420      * fflush(debugFD);
1421      * } */
1422
1423     /* initialize both the objects */
1424
1425     code =
1426         justify_light(part1, tmp_lightobj1->label, FC_COLUMN_WIDTH, a_just,
1427                       1);
1428     if (code) {
1429         if (afsmon_debug) {
1430             fprintf(debugFD, "[ %s ] justify_light failed 1 \n", rn);
1431             fflush(debugFD);
1432         }
1433     }
1434
1435     code =
1436         justify_light(part2, tmp_lightobj2->label, FC_COLUMN_WIDTH, a_just,
1437                       1);
1438     if (code) {
1439         if (afsmon_debug) {
1440             fprintf(debugFD, "[ %s ] justify_light failed 1 \n", rn);
1441             fflush(debugFD);
1442         }
1443     }
1444
1445     /* highlight them */
1446     if (a_highlight && (part1[0] != '-'))
1447         gator_light_set(a_firstObj_o, 1);
1448     else
1449         gator_light_set(a_firstObj_o, 0);
1450     if (a_highlight && (part2[0] != '\0'))
1451         gator_light_set(a_secondObj_o, 1);
1452     else
1453         gator_light_set(a_secondObj_o, 0);
1454
1455
1456
1457     return (0);
1458
1459 }                               /* display_Server_datum */
1460
1461
1462 /*-----------------------------------------------------------------------
1463  * display_Server_label()
1464  *
1465  * Description:
1466  *      Display the given server label in three objects. The label is
1467  *      partitioned into three parts by '/'s and each part is copied
1468  *      into each label object.
1469  *
1470  * Returns:
1471  *      0 always.
1472  *----------------------------------------------------------------------*/
1473
1474 int
1475 display_Server_label(char *a_srcBuf,
1476                      struct onode *a_firstObj_o,        /* first object */
1477                      struct onode *a_secondObj_o,       /* second object */
1478                      struct onode *a_thirdObj_o)        /* third object */
1479 {                               /* display_Server_label */
1480     static char rn[] = "display_Server_label";
1481     char part[3][20];           /* buffer for three parts of label */
1482     char *strPtr;
1483     struct gator_lightobj *tmp_lightobj;
1484     struct onode *objPtr_o[3];
1485     int code;
1486     int strLen;
1487     int len;
1488     int i;
1489     int j;
1490
1491 /* the following debug statement floods the debug file */
1492 #ifdef DEBUG_DETAILED
1493     if (afsmon_debug) {
1494         fprintf(debugFD,
1495                 "[ %s ] Called, a_srcBuf= %s, a_firstObj_o= %d, a_secondObj_o= %d, a_thirdObj_o= %d\n",
1496                 rn, a_srcBuf, a_firstObj_o, a_secondObj_o, a_thirdObj_o);
1497         fflush(debugFD);
1498     }
1499 #endif
1500
1501
1502     /* break the label string into three parts */
1503
1504     part[0][0] = '\0';
1505     part[1][0] = '\0';
1506     part[2][0] = '\0';
1507     /* now for a dumb precaution */
1508
1509     strLen = strlen(a_srcBuf);
1510     len = 0;
1511     strPtr = a_srcBuf;
1512     for (i = 0; i < 3; i++) {
1513         j = 0;
1514         while (*strPtr != '\0' && (len++ <= strLen)) {
1515             if (*strPtr == '/') {
1516                 strPtr++;
1517                 break;
1518             } else
1519                 part[i][j] = *strPtr;
1520             strPtr++;
1521             j++;
1522         }
1523         part[i][j] = '\0';
1524     }
1525
1526     /*
1527      * if (afsmon_debug) {
1528      * fprintf(debugFD,"[ %s ] LABELS %s -> %s %s %s\n",
1529      * rn, a_srcBuf, part[0], part[1], part[2]);
1530      * fflush(debugFD);
1531      * }
1532      */
1533
1534     objPtr_o[0] = a_firstObj_o;
1535     objPtr_o[1] = a_secondObj_o;
1536     objPtr_o[2] = a_thirdObj_o;
1537
1538     /* display each label justified CENTER */
1539
1540     for (i = 0; i < 3; i++) {
1541         tmp_lightobj = (struct gator_lightobj *)objPtr_o[i]->o_data;
1542         code =
1543             justify_light(part[i], tmp_lightobj->label, FC_COLUMN_WIDTH,
1544                           CENTER, 1);
1545         if (code) {
1546             if (afsmon_debug) {
1547                 fprintf(debugFD, "[ %s ] justify_light %d failed \n", rn, i);
1548                 fflush(debugFD);
1549             }
1550         }
1551     }
1552     return 0;
1553 }                               /* display_Server_label */
1554
1555
1556
1557
1558
1559 /*-----------------------------------------------------------------------
1560  * fs_refresh()
1561  *
1562  * Description:
1563  *      Refresh the File Servers screen with the given page number starting
1564  *      at the given left-column number. The appropriate contents of
1565  *      prev_fsData are displayed.
1566  *      First the status labels at the four corners of the screen are
1567  *      updated. Next the column labels are updated and then each row
1568  *      of statistics.
1569  *
1570  * Returns:
1571  *      Success: 0
1572  *      Failure: Exits afsmoitor on a severe error.
1573  *----------------------------------------------------------------------*/
1574
1575
1576 int
1577 fs_refresh(int a_pageNum,       /* page to display */
1578            int a_LcolNum)       /* starting (leftmost) column number */
1579 {                               /* fs_refresh */
1580
1581     static char rn[] = "fs_refresh";    /* routine name */
1582     struct gator_lightobj *tmp_lightobj;        /* ptr for object's display data */
1583     struct fs_Display_Data *fsDataP;    /* ptr to FS display data array */
1584     struct ServerInfo_line *tmp_fs_lines_P;     /* tmp ptr to fs_lines */
1585     struct onode **firstSlot_o_Ptr;     /* ptr to first data slot of a datum */
1586     struct onode **secondSlot_o_Ptr;    /* ptr to second data slot of a datum */
1587     struct onode **fsLabels_o_Ptr1;     /* ptr to label row 0 */
1588     struct onode **fsLabels_o_Ptr2;     /* ptr to label row 1 */
1589     struct onode **fsLabels_o_Ptr3;     /* ptr to label row 2 */
1590     char cmdLine[80];           /* buffer for command line */
1591     char printBuf[256];         /* buffer to print to screen */
1592     int i;
1593     int j;
1594     int k;
1595     int code;
1596     int fsIdx;
1597     int labelIdx;
1598     int dataIndex;              /* index to the data[] field of
1599                                  * struct fs_Display_Data */
1600
1601     if (afsmon_debug) {
1602         fprintf(debugFD, "[ %s ] Called with row %d col %d \n", rn, a_pageNum,
1603                 a_LcolNum);
1604         fflush(debugFD);
1605     }
1606
1607
1608     /* if the data is not yet available, ie., not one probe cycle has
1609      * completed, do nothing */
1610
1611     if (!fs_Data_Available)
1612         return (0);
1613
1614
1615     /* validate the page number & column number */
1616     if (a_pageNum < 1 || a_pageNum > fs_numPages) {
1617         if (afsmon_debug) {
1618             fprintf(debugFD, "[ %s ] Called with wrong page # %d \n", rn,
1619                     a_pageNum);
1620             fflush(debugFD);
1621         }
1622         afsmon_Exit(315);
1623     }
1624     if (a_LcolNum < 0 || a_LcolNum > fs_numCols) {
1625         if (afsmon_debug) {
1626             fprintf(debugFD, "[ %s ] Called with wrong column #%d\n", rn,
1627                     a_LcolNum);
1628             fflush(debugFD);
1629         }
1630         afsmon_Exit(320);
1631     }
1632
1633
1634
1635     /* update the fixed labels */
1636
1637     /* we reuse the ovw version lable and hence do not have to do anything
1638      * for it here */
1639
1640     /* page number label */
1641     tmp_lightobj = (struct gator_lightobj *)fs_pageNum_o->o_data;
1642     sprintf(printBuf, "[File Servers, p. %d of %d, c. %d of %d]", a_pageNum,
1643             fs_numPages, a_LcolNum + 1, fs_numCols);
1644     justify_light(printBuf, tmp_lightobj->label, FC_PAGENUM_O_WIDTH,
1645                   RIGHT_JUSTIFY, 1);
1646     gator_light_set(fs_pageNum_o, 1);
1647
1648     /* file servers monitored label */
1649     tmp_lightobj = (struct gator_lightobj *)fs_numFS_o->o_data;
1650     sprintf(printBuf, "%d File Servers monitored, %d alerts on %d machines",
1651             numFS, num_fs_alerts, numHosts_onfs_alerts);
1652     justify_light(printBuf, tmp_lightobj->label, FC_NUMHOSTS_O_WIDTH, CENTER,
1653                   1);
1654
1655
1656     /* command line */
1657
1658     /* figure out what we need to show in the prompt & set the page type */
1659     /* the fs_pageType variable is in turn used by the keyboard handler
1660      * routines to call fs_refresh() with the correct parameters */
1661
1662     fs_pageType = resolve_CmdLine(cmdLine, 1 /* fs frame */ , a_pageNum,
1663                                   fs_numPages, fs_numCols, a_LcolNum,
1664                                   fs_cols_perPage, 0);
1665
1666     /* display the command line */
1667     tmp_lightobj = (struct gator_lightobj *)fs_cmd_o->o_data;
1668     sprintf(printBuf, "%s", cmdLine);
1669     justify_light(printBuf, tmp_lightobj->label, strlen(printBuf) + 1,
1670                   LEFT_JUSTIFY, 1);
1671     gator_light_set(fs_cmd_o, 1);
1672
1673     /* update the probe number label */
1674     tmp_lightobj = (struct gator_lightobj *)fs_probeNum_o->o_data;
1675     sprintf(printBuf, "[FS probes %d, freq=%d sec]", afsmon_fs_prev_probeNum,
1676             afsmon_probefreq);
1677     justify_light(printBuf, tmp_lightobj->label, FC_PROBENUM_O_WIDTH,
1678                   RIGHT_JUSTIFY, 1);
1679     gator_light_set(fs_probeNum_o, 1);
1680
1681     /* update "columns on left" signal */
1682     tmp_lightobj = (struct gator_lightobj *)fs_leftArrows_o->o_data;
1683     if (fs_pageType & CMD_LEFT)
1684         strcpy(printBuf, "<<<");
1685     else
1686         strcpy(printBuf, "");
1687     justify_light(printBuf, tmp_lightobj->label, FC_ARROWS_O_WIDTH,
1688                   LEFT_JUSTIFY, 1);
1689     gator_light_set(fs_leftArrows_o, 0);
1690
1691     /* update "columns on right" signal */
1692     tmp_lightobj = (struct gator_lightobj *)fs_rightArrows_o->o_data;
1693     if (fs_pageType & CMD_RIGHT)
1694         strcpy(printBuf, ">>>");
1695     else
1696         strcpy(printBuf, "");
1697     justify_light(printBuf, tmp_lightobj->label, FC_ARROWS_O_WIDTH,
1698                   RIGHT_JUSTIFY, 1);
1699     gator_light_set(fs_rightArrows_o, 0);
1700
1701
1702
1703     /* UPDATE THE COLUMN LABELS */
1704
1705     /* the column index is also used to index the label arrays */
1706     labelIdx = a_LcolNum;
1707
1708     /* get the pointers to the three arrays of label onodes */
1709     fsLabels_o_Ptr1 = fsLabels_o[0];
1710     fsLabels_o_Ptr2 = fsLabels_o[1];
1711     fsLabels_o_Ptr3 = fsLabels_o[2];
1712
1713     for (k = 0; k < fs_cols_perPage; k++) {
1714
1715         if (labelIdx < fs_numCols) {
1716             dataIndex = fs_Display_map[labelIdx];
1717             code =
1718                 display_Server_label(fs_labels[dataIndex], *fsLabels_o_Ptr1,
1719                                      *fsLabels_o_Ptr2, *fsLabels_o_Ptr3);
1720
1721             labelIdx++;         /* next label */
1722         } else {
1723             code =
1724                 display_Server_label("//", *fsLabels_o_Ptr1, *fsLabels_o_Ptr2,
1725                                      *fsLabels_o_Ptr3);
1726         }
1727
1728         fsLabels_o_Ptr1++;      /* next onode in label row 1 */
1729         fsLabels_o_Ptr2++;      /* next onode in label row 2 */
1730         fsLabels_o_Ptr3++;      /* next onode in label row 3 */
1731
1732     }                           /* labels for each column */
1733
1734
1735     /* UPDATE THE FILE SERVER STATISTICS */
1736
1737     /* move to the right spot in the FS display data array */
1738     fsDataP = prev_fsData;
1739     fsIdx = 0;
1740     for (i = 0; i < ((a_pageNum - 1) * fs_numHosts_perPage); i++) {
1741         fsDataP++;
1742         fsIdx++;
1743     }
1744
1745     if (fsIdx >= numFS) {       /* whoops! screwed up */
1746         sprintf(errMsg, "[ %s ] Programming error 1\n", rn);
1747         afsmon_Exit(325);
1748     }
1749
1750     /* get the pointer to the first line of onodes of the file server frame */
1751     tmp_fs_lines_P = fs_lines;
1752
1753     for (i = 0; i < fs_numHosts_perPage; i++) {
1754
1755
1756         /* if this is the last page we may not have file servers to fill up
1757          * the page, so check the index */
1758         if (fsIdx < numFS) {
1759
1760             if (fsDataP->hostName[0] == '\0') {
1761                 sprintf(errMsg, "[ %s ] empty fs display entry \n", rn);
1762                 afsmon_Exit(330);
1763             }
1764
1765             /* display the hostname , first names only please! */
1766
1767             sprintf(printBuf, "%s", fsDataP->hostName);
1768             for (j = 0; j < strlen(printBuf); j++) {
1769                 if (printBuf[j] == '.') {
1770                     printBuf[j] = '\0';
1771                     break;
1772                 }
1773             }
1774
1775             tmp_lightobj =
1776                 (struct gator_lightobj *)tmp_fs_lines_P->host_o->o_data;
1777             code =
1778                 justify_light(printBuf, tmp_lightobj->label,
1779                               FC_HOSTNAME_O_WIDTH, LEFT_JUSTIFY, 1);
1780             if (code) {
1781                 fprintf(debugFD, "[ %s ] justify_code returned %d\n", rn,
1782                         code);
1783                 fflush(debugFD);
1784             }
1785
1786             /* use the current column value to index into the fs_Display_map
1787              * array to obtain the index of the item to display. check if its
1788              * overflow flag is set and highlight if so. if the probe had failed
1789              * enter "--" is all columns */
1790
1791             /* each host has two rows of slots for datums. get the pointers to
1792              * both the arrays */
1793
1794             firstSlot_o_Ptr = tmp_fs_lines_P->data_o[0];
1795             secondSlot_o_Ptr = tmp_fs_lines_P->data_o[1];
1796             fs_curr_RCol = a_LcolNum;   /* starting column number from which
1797                                          * we are asked to display data */
1798
1799             for (j = 0; j < fs_cols_perPage; j++) {     /* for each column */
1800
1801                 /* if there is another column of data */
1802                 if (fs_curr_RCol < fs_numCols) {
1803
1804                     dataIndex = fs_Display_map[fs_curr_RCol];
1805
1806                     code =
1807                         display_Server_datum(fsDataP->data[dataIndex],
1808                                              *firstSlot_o_Ptr,
1809                                              *secondSlot_o_Ptr,
1810                                              fsDataP->probeOK, RIGHT_JUSTIFY,
1811                                              fsDataP->threshOvf[dataIndex]);
1812
1813                     fs_curr_RCol++;
1814                 } else {        /* no more data, blank out columns */
1815                     code = display_Server_datum("", *firstSlot_o_Ptr, *secondSlot_o_Ptr, 1,     /* probe ok */
1816                                                 RIGHT_JUSTIFY, 0);      /* no overflow */
1817                 }
1818
1819
1820                 firstSlot_o_Ptr++;      /* onode of next column */
1821                 secondSlot_o_Ptr++;     /* onode of next column */
1822
1823             }                   /* for each column */
1824
1825             /* the loop could have taken the right-column-index one over,
1826              * adjust it now */
1827             if (fs_curr_RCol == fs_numCols)
1828                 fs_curr_RCol--;
1829
1830
1831         }
1832
1833
1834
1835         /* if fdIdx < numFS */
1836         /* if fsIdx >= numFS , blank out all succeding rows */
1837         if (fsIdx >= numFS) {
1838
1839             /* blank out host name object */
1840             tmp_lightobj =
1841                 (struct gator_lightobj *)tmp_fs_lines_P->host_o->o_data;
1842             code =
1843                 justify_light("", tmp_lightobj->label, FC_HOSTNAME_O_WIDTH,
1844                               LEFT_JUSTIFY, 1);
1845             if (code) {
1846                 fprintf(debugFD, "[ %s ] justify_code returned %d\n", rn,
1847                         code);
1848                 fflush(debugFD);
1849             }
1850
1851             firstSlot_o_Ptr = tmp_fs_lines_P->data_o[0];
1852             secondSlot_o_Ptr = tmp_fs_lines_P->data_o[1];
1853
1854             for (k = 0; k < fs_cols_perPage; k++) {
1855                 code = display_Server_datum("", *firstSlot_o_Ptr, *secondSlot_o_Ptr, 1, /* probe OK */
1856                                             RIGHT_JUSTIFY, 0);  /* dont highlight */
1857
1858                 firstSlot_o_Ptr++;
1859                 secondSlot_o_Ptr++;
1860             }
1861
1862         }
1863
1864         /* fsIDx >= numFS */
1865         tmp_fs_lines_P++;       /* pointer to next line in the frame */
1866         fsDataP++;              /* next host's data */
1867         fsIdx++;                /* host index */
1868
1869
1870     }                           /* for each row in the File Servers frame */
1871
1872     /* redraw the display if the File Servers screen is currently displayed */
1873     if (afsmon_win->w_frame == fsFrame)
1874         WOP_DISPLAY(afsmon_win);
1875
1876     /* update the global page & column numbers to reflect the changes */
1877     fs_currPage = a_pageNum;
1878     fs_curr_LCol = a_LcolNum;;
1879
1880     return (0);
1881
1882 }                               /* fs_refresh */
1883
1884
1885
1886
1887 /*-----------------------------------------------------------------------
1888  * Switch_fs_2_ovw()
1889  *
1890  * Description:
1891  *      Switch from the File Server screen to the Overview Screen
1892  *----------------------------------------------------------------------*/
1893 int
1894 Switch_fs_2_ovw(void *d1, void *d2)
1895 {
1896     /* bind the overview frame to the window */
1897     gtxframe_SetFrame(afsmon_win, ovwFrame);
1898     return (0);
1899 }
1900
1901 /*-----------------------------------------------------------------------
1902  * Switch_fs_2_cm()
1903  *
1904  * Description:
1905  *      Switch from the File Server screen to the Cache Managers screen.
1906  *----------------------------------------------------------------------*/
1907 int
1908 Switch_fs_2_cm(void *d1, void *d2)
1909 {
1910     if (fs_pageType & CMD_CM) {
1911         /* bind the overview Cache Managers to the window */
1912         gtxframe_SetFrame(afsmon_win, cmFrame);
1913     }
1914     return (0);
1915 }
1916
1917 /*-----------------------------------------------------------------------
1918  * Switch_fs_next()
1919  *
1920  * Description:
1921  *      Switch to next page of file server screen
1922  *----------------------------------------------------------------------*/
1923 int
1924 Switch_fs_next(void *d1, void *d2)
1925 {
1926     if (fs_pageType & CMD_NEXT) {
1927         /* we have a next page, refresh with next page number */
1928         fs_refresh(fs_currPage + 1, fs_curr_LCol);
1929     }
1930
1931     return (0);
1932 }
1933
1934 /*-----------------------------------------------------------------------
1935  * Switch_fs_last()
1936  *
1937  * Description:
1938  *      Switch to last page of file server screen
1939  *----------------------------------------------------------------------*/
1940 int
1941 Switch_fs_last(void *d1, void *d2)
1942 {
1943     if (fs_pageType & CMD_NEXT) {
1944         /* we have a next page, refresh with the last page number */
1945         fs_refresh(fs_numPages, fs_curr_LCol);
1946     }
1947
1948     return (0);
1949 }
1950
1951 /*-----------------------------------------------------------------------
1952  * Switch_fs_prev()
1953  *
1954  * Description:
1955  *      Switch to previous page of file server screen
1956  *----------------------------------------------------------------------*/
1957 int
1958 Switch_fs_prev(void *d1, void *d2)
1959 {
1960     if (fs_pageType & CMD_PREV) {
1961         /* we have a previous page, refresh with the rpevious page number */
1962         fs_refresh(fs_currPage - 1, fs_curr_LCol);
1963     }
1964     return (0);
1965 }
1966
1967 /*-----------------------------------------------------------------------
1968  * Switch_fs_first()
1969  *
1970  * Description:
1971  *      Switch to first page of file server screen
1972  *----------------------------------------------------------------------*/
1973 int
1974 Switch_fs_first(void *d1, void *d2)
1975 {
1976     if (fs_pageType & CMD_PREV) {
1977         /* we have a previous page, got to first page */
1978         fs_refresh(1, fs_curr_LCol);
1979     }
1980     return (0);
1981 }
1982
1983 /*-----------------------------------------------------------------------
1984  * Switch_fs_left()
1985  *
1986  * Description:
1987  *      Scroll left on the file server screen
1988  *----------------------------------------------------------------------*/
1989 int
1990 Switch_fs_left(void *d1, void *d2)
1991 {
1992     if (fs_pageType & CMD_LEFT) {
1993         /* we have columns on left, refresh with new column number */
1994         fs_refresh(fs_currPage, fs_curr_LCol - fs_cols_perPage);
1995     }
1996     return (0);
1997 }
1998
1999
2000 /*-----------------------------------------------------------------------
2001  * Switch_fs_leftmost()
2002  *
2003  * Description:
2004  *      Scroll to first column on  the file server screen
2005  *----------------------------------------------------------------------*/
2006 int
2007 Switch_fs_leftmost(void *d1, void *d2)
2008 {
2009     if (fs_pageType & CMD_LEFT) {
2010         /* we have columns on left, go to the first */
2011         fs_refresh(fs_currPage, 0);
2012     }
2013     return (0);
2014 }
2015
2016 /*-----------------------------------------------------------------------
2017  * Switch_fs_right()
2018  *
2019  * Description:
2020  *      Scroll right on the file server screen
2021  *----------------------------------------------------------------------*/
2022 int
2023 Switch_fs_right(void *d1, void *d2)
2024 {
2025     if (fs_pageType & CMD_RIGHT) {
2026         /* we have columns on right, refresh with new column number */
2027         fs_refresh(fs_currPage, fs_curr_LCol + fs_cols_perPage);
2028     }
2029     return (0);
2030 }
2031
2032 /*-----------------------------------------------------------------------
2033  * Switch_fs_rightmost()
2034  *
2035  * Description:
2036  *      Scroll to last column on the file server screen
2037  *----------------------------------------------------------------------*/
2038 int
2039 Switch_fs_rightmost(void *d1, void *d2)
2040 {
2041     int curr_LCol;
2042
2043     if (fs_pageType & CMD_RIGHT) {
2044         /* we have columns on right, go to the last column */
2045         if (fs_numCols % fs_cols_perPage)
2046             curr_LCol = (fs_numCols / fs_cols_perPage) * fs_cols_perPage;
2047         else
2048             curr_LCol =
2049                 ((fs_numCols / fs_cols_perPage) - 1) * fs_cols_perPage;
2050
2051         fs_refresh(fs_currPage, curr_LCol);
2052     }
2053     return (0);
2054 }
2055
2056
2057 /*-----------------------------------------------------------------------
2058  * create_FSframe_objects()
2059  *
2060  * Description:
2061  *      Create the gtx objects (onodes) for the Fileservers frame and setup
2062  *      the keyboard bindings.
2063  *      Only as many objects as can fit on the display are created. The
2064  *      positions and lengths of all these objects are fixed at creation.
2065  *      These objects are updated with new data at the end of each probe
2066  *      cycle.
2067  *
2068  * Returns:
2069  *      Success: 0
2070  *      Failure: Exits afsmonitor.
2071  *----------------------------------------------------------------------*/
2072
2073 int
2074 create_FSframe_objects(void)
2075 {                               /* create_FSframe_objects */
2076     static char rn[] = "create_FSframe_objects";
2077     struct ServerInfo_line *fs_lines_Ptr;
2078     struct onode **fs_data_o_Ptr;
2079     struct onode **fsLabels_o_Ptr;
2080     int x_pos;
2081     int y_pos;
2082     int i;
2083     int j;
2084     int numBytes;
2085     int arrIdx;
2086
2087
2088     if (afsmon_debug) {
2089         fprintf(debugFD, "[ %s ] Called\n", rn);
2090         fflush(debugFD);
2091     }
2092
2093     /* create the command line object */
2094     fs_cmd_o =
2095         initLightObject("Command [oview, cm, prev, next, left, right] ? ", 0,
2096                         maxY - 1, FC_CMD_O_WIDTH, afsmon_win);
2097     if (fs_cmd_o == NULL) {
2098         sprintf(errMsg, "[ %s ] Failed to create fs command onode\n", rn);
2099         afsmon_Exit(340);
2100     }
2101     gtxframe_AddToList(fsFrame, fs_cmd_o);
2102     gator_light_set(fs_cmd_o, HIGHLIGHT);
2103
2104     /* we already have the dimensions for the frame - same as the ovw frame */
2105     /* use the ovw program name object for the fs screen too */
2106
2107     gtxframe_AddToList(fsFrame, ovw_progName_o);
2108
2109
2110     /* create the page number object */
2111     fs_pageNum_o =
2112         initLightObject("[File Servers, p. X of X, c. Y of Y]",
2113                         maxX - FC_PAGENUM_O_WIDTH, 0, FC_PAGENUM_O_WIDTH,
2114                         afsmon_win);
2115     if (fs_pageNum_o == NULL) {
2116         sprintf(errMsg, "[ %s ] Failed to create pageNumber onode\n", rn);
2117         afsmon_Exit(335);
2118     }
2119     gtxframe_AddToList(fsFrame, fs_pageNum_o);
2120     gator_light_set(fs_pageNum_o, HIGHLIGHT);
2121
2122     /* create the probe number object */
2123     fs_probeNum_o =
2124         initLightObject("[FS probes 1, freq=30 sec]",
2125                         maxX - FC_PROBENUM_O_WIDTH, maxY - 1,
2126                         FC_PROBENUM_O_WIDTH, afsmon_win);
2127     if (fs_probeNum_o == NULL) {
2128         sprintf(errMsg, "[ %s ] Failed to create fs probeNum onode\n", rn);
2129         afsmon_Exit(345);
2130     }
2131     gtxframe_AddToList(fsFrame, fs_probeNum_o);
2132     gator_light_set(fs_probeNum_o, HIGHLIGHT);
2133
2134
2135     /* create the numFS monitored object */
2136     fs_numFS_o =
2137         initLightObject
2138         ("      0 File Servers monitored, 0 alerts on 0 machines", 4, 2,
2139          FC_NUMHOSTS_O_WIDTH, afsmon_win);
2140     if (fs_numFS_o == NULL) {
2141         sprintf(errMsg,
2142                 "[ %s ] Failed to create numFS onode for the fs frame\n", rn);
2143         afsmon_Exit(350);
2144     }
2145     gtxframe_AddToList(fsFrame, fs_numFS_o);
2146
2147     /* create the "more columns to left" indicator */
2148     fs_leftArrows_o =
2149         initLightObject("<<<", 0, 2, FC_ARROWS_O_WIDTH, afsmon_win);
2150     if (fs_leftArrows_o == NULL) {
2151         sprintf(errMsg,
2152                 "[ %s ] Failed to create leftArrows onode for the fs frame\n",
2153                 rn);
2154         afsmon_Exit(355);
2155     }
2156     gtxframe_AddToList(fsFrame, fs_leftArrows_o);
2157
2158     /* create the "more columns to right" indicator */
2159     fs_rightArrows_o =
2160         initLightObject(">>>", maxX - FC_ARROWS_O_WIDTH, 2, FC_ARROWS_O_WIDTH,
2161                         afsmon_win);
2162     if (fs_rightArrows_o == NULL) {
2163         sprintf(errMsg,
2164                 "[ %s ] Failed to create rightArrows onode for the fs frame\n",
2165                 rn);
2166         afsmon_Exit(360);
2167     }
2168     gtxframe_AddToList(fsFrame, fs_rightArrows_o);
2169
2170
2171
2172
2173     /* calculate the maximum number of hosts per page (2 rows per host) */
2174     fs_numHosts_perPage = (maxY - FC_NUM_FIXED_LINES) / 2;
2175
2176     /* determine the number of data columns that can fit in a page */
2177     fs_cols_perPage = (maxX - FC_HOSTNAME_O_WIDTH) / (FC_COLUMN_WIDTH);
2178
2179     if (afsmon_debug) {
2180         fprintf(debugFD, "[ %s ] fs_numHosts_perPage=%d fs_cols_perPage=%d\n",
2181                 rn, fs_numHosts_perPage, fs_cols_perPage);
2182         fflush(debugFD);
2183     }
2184
2185     /* the above two variables give us the information needed to create
2186      * the objects for displaying the file server information */
2187
2188     /* allocate memory for all the onode pointers required to display
2189      * the file server statistics */
2190
2191     numBytes = fs_numHosts_perPage * sizeof(struct ServerInfo_line);
2192     fs_lines = (struct ServerInfo_line *)malloc(numBytes);
2193     if (fs_lines == (struct ServerInfo_line *)0) {
2194         sprintf(errMsg,
2195                 "[ %s ] Failed to allocate %d bytes for FS data lines\n", rn,
2196                 numBytes);
2197         afsmon_Exit(365);
2198     }
2199
2200     /* for each line of server statistics allocate memory to store two arrays
2201      * of data onodes */
2202
2203     fs_lines_Ptr = fs_lines;
2204     for (i = 0; i < fs_numHosts_perPage; i++) {
2205         for (arrIdx = 0; arrIdx < 2; arrIdx++) {
2206             numBytes = fs_cols_perPage * sizeof(struct onode *);
2207             fs_lines_Ptr->data_o[arrIdx] = (struct onode **)malloc(numBytes);
2208             if (fs_lines_Ptr->data_o[arrIdx] == NULL) {
2209                 sprintf(errMsg,
2210                         "[ %s ] Failed to allocate %d bytes for FS data onodes\n",
2211                         rn, numBytes);
2212                 afsmon_Exit(370);
2213             }
2214         }
2215         fs_lines_Ptr++;
2216     }
2217
2218     /* now allocate the onodes itself */
2219
2220     fs_lines_Ptr = fs_lines;
2221     for (i = 0; i < fs_numHosts_perPage; i++) {
2222
2223         /* initialize host name onode */
2224         fs_lines_Ptr->host_o =
2225             initLightObject("FSHostName", 0, FC_FIRST_HOST_ROW + 2 * i,
2226                             FC_HOSTNAME_O_WIDTH, afsmon_win);
2227         if (fs_lines_Ptr->host_o == NULL) {
2228             sprintf(errMsg, "[ %s ] Failed to create an FS name onode\n", rn);
2229             afsmon_Exit(375);
2230         }
2231         gtxframe_AddToList(fsFrame, fs_lines_Ptr->host_o);
2232
2233         /* if (afsmon_debug) {
2234          * fprintf(debugFD,"[ %s ] Addr of host_o = %d for line %d\n",
2235          * rn,fs_lines_Ptr->host_o,i);
2236          * fflush(debugFD);
2237          * } */
2238
2239         /* initialize data onodes for this host */
2240
2241         for (arrIdx = 0; arrIdx < 2; arrIdx++) {        /* for each array index */
2242
2243             fs_data_o_Ptr = fs_lines_Ptr->data_o[arrIdx];
2244             for (j = 0; j < fs_cols_perPage; j++) {     /* for each column */
2245
2246                 char tmpBuf[20];
2247
2248                 /* determine x & y coordinate for this data object */
2249                 /* the 1's are for leaving a blank after each column */
2250                 x_pos = FC_HOSTNAME_O_WIDTH + (j * (FC_COLUMN_WIDTH));
2251                 y_pos = FC_FIRST_HOST_ROW + 2 * i + arrIdx;
2252
2253                 sprintf(tmpBuf, "-FSData %d-", arrIdx);
2254                 *fs_data_o_Ptr =
2255                     initLightObject(tmpBuf, x_pos, y_pos, FC_COLUMN_WIDTH,
2256                                     afsmon_win);
2257                 if (*fs_data_o_Ptr == NULL) {
2258                     sprintf(errMsg,
2259                             "[ %s ] Failed to create an FS data onode\n", rn);
2260                     afsmon_Exit(380);
2261                 }
2262                 gtxframe_AddToList(fsFrame, *fs_data_o_Ptr);
2263
2264                 fs_data_o_Ptr++;
2265             }                   /* for each column */
2266         }                       /* for each onode array index */
2267
2268         fs_lines_Ptr++;
2269     }                           /* for each host slot */
2270
2271
2272     /* INITIALIZE COLUMN LABELS */
2273
2274
2275     /* allocate memory for two arrays of onode pointers for file server column
2276      * labels */
2277     for (arrIdx = 0; arrIdx < 3; arrIdx++) {
2278
2279         fsLabels_o[arrIdx] =
2280             (struct onode **)malloc(sizeof(struct onode *) * fs_cols_perPage);
2281         if (fsLabels_o[arrIdx] == NULL) {
2282             sprintf(errMsg,
2283                     "[ %s ] Failed to allocate memory for FS label onodes\n",
2284                     rn);
2285             afsmon_Exit(385);
2286         }
2287
2288         /* create cache manager name objects */
2289         fsLabels_o_Ptr = fsLabels_o[arrIdx];
2290         for (i = 0; i < fs_cols_perPage; i++) {
2291             *fsLabels_o_Ptr =
2292                 initLightObject("", FC_HOSTNAME_O_WIDTH + i * FC_COLUMN_WIDTH,
2293                                 FC_FIRST_LABEL_ROW + arrIdx, FC_COLUMN_WIDTH,
2294                                 afsmon_win);
2295
2296             if (*fsLabels_o_Ptr == NULL) {
2297                 sprintf(errMsg, "[ %s ] Failed to create a FS label onode\n",
2298                         rn);
2299                 afsmon_Exit(390);
2300             }
2301             gtxframe_AddToList(fsFrame, *fsLabels_o_Ptr);
2302             fsLabels_o_Ptr++;
2303         }
2304
2305     }
2306
2307
2308     /* initialize the column & page counters */
2309
2310     fs_currPage = 1;
2311     fs_numCols = fs_DisplayItems_count;
2312     fs_numPages = numFS / fs_numHosts_perPage;
2313     if (numFS % fs_numHosts_perPage)
2314         fs_numPages++;
2315     fs_curr_LCol = 0;           /* leftmost col */
2316     fs_curr_RCol = 0;           /* rightmost col */
2317
2318     /* create keyboard bindings */
2319     /* bind Q and \ 3 to exit */
2320     keymap_BindToString(fsFrame->keymap, "Q", afsmonExit_gtx, NULL, NULL);
2321     keymap_BindToString(fsFrame->keymap, "\ 3", afsmonExit_gtx, NULL, NULL);
2322
2323     /* o = overview, c = cm, n = next, p = prev, l = left, r = right
2324      * N = last page, P = first page, L = leftmost col, R = rightmost col */
2325
2326     keymap_BindToString(fsFrame->keymap, "o", Switch_fs_2_ovw, NULL, NULL);
2327     keymap_BindToString(fsFrame->keymap, "c", Switch_fs_2_cm, NULL, NULL);
2328     keymap_BindToString(fsFrame->keymap, "n", Switch_fs_next, NULL, NULL);
2329     keymap_BindToString(fsFrame->keymap, "N", Switch_fs_last, NULL, NULL);
2330     keymap_BindToString(fsFrame->keymap, "p", Switch_fs_prev, NULL, NULL);
2331     keymap_BindToString(fsFrame->keymap, "P", Switch_fs_first, NULL, NULL);
2332     keymap_BindToString(fsFrame->keymap, "l", Switch_fs_left, NULL, NULL);
2333     keymap_BindToString(fsFrame->keymap, "L", Switch_fs_leftmost, NULL, NULL);
2334     keymap_BindToString(fsFrame->keymap, "r", Switch_fs_right, NULL, NULL);
2335     keymap_BindToString(fsFrame->keymap, "R", Switch_fs_rightmost, NULL,
2336                         NULL);
2337
2338     return (0);
2339 }                               /* create_FSframe_objects */
2340
2341
2342 /*-----------------------------------------------------------------------
2343  * Function:    cm_refresh()
2344  *
2345  * Description:
2346  *      Refresh the Cache Managers screen with the given page number starting
2347  *      at the given left-column number. The appropriate contents of
2348  *      prev_cmData are displayed.
2349  *      First the status labels at the four corners of the screen are
2350  *      updated. Next the column labels are updated and then each row
2351  *      of statistics.
2352  *
2353  * Returns:
2354  *      Success: 0
2355  *      Failure: Exits afsmoitor on a severe error.
2356  *----------------------------------------------------------------------*/
2357
2358 int
2359 cm_refresh(int a_pageNum,               /* page to display */
2360            int a_LcolNum)               /* starting (leftmost) column number */
2361 {                               /* cm_refresh */
2362
2363     static char rn[] = "cm_refresh";    /* routine name */
2364     struct gator_lightobj *tmp_lightobj;        /* ptr for object's display data */
2365     struct cm_Display_Data *cmDataP;    /* ptr to CM display data array */
2366     struct ServerInfo_line *tmp_cm_lines_P;     /* tmp ptr to cm_lines */
2367     struct onode **firstSlot_o_Ptr;     /* ptr to first data slot of a datum */
2368     struct onode **secondSlot_o_Ptr;    /* ptr to second data slot of a datum */
2369     struct onode **cmLabels_o_Ptr1;     /* ptr to label row 0 */
2370     struct onode **cmLabels_o_Ptr2;     /* ptr to label row 1 */
2371     struct onode **cmLabels_o_Ptr3;     /* ptr to label row 2 */
2372     char cmdLine[80];           /* buffer for command line */
2373     char printBuf[256];         /* buffer to print to screen */
2374     int i;
2375     int j;
2376     int k;
2377     int code;
2378     int cmIdx;
2379     int labelIdx;
2380     int dataIndex;              /* index to the data[] field of
2381                                  * struct cm_Display_Data */
2382
2383     if (afsmon_debug) {
2384         fprintf(debugFD, "[ %s ] Called, a_pageNum= %d, a_LcolNum= %d \n", rn,
2385                 a_pageNum, a_LcolNum);
2386         fflush(debugFD);
2387     }
2388
2389
2390     /* if the data is not yet available, ie., not one probe cycle has
2391      * completed, do nothing */
2392
2393     if (!cm_Data_Available)
2394         return (0);
2395
2396
2397     /* validate the page number & column number */
2398     if (a_pageNum < 1 || a_pageNum > cm_numPages) {
2399         if (afsmon_debug) {
2400             fprintf(debugFD, "[ %s ] Called with wrong page # %d \n", rn,
2401                     a_pageNum);
2402             fflush(debugFD);
2403         }
2404         afsmon_Exit(395);
2405     }
2406     if (a_LcolNum < 0 || a_LcolNum > cm_numCols) {
2407         if (afsmon_debug) {
2408             fprintf(debugFD, "[ %s ] Called with wrong column #%d\n", rn,
2409                     a_LcolNum);
2410             fflush(debugFD);
2411         }
2412         afsmon_Exit(400);
2413     }
2414
2415
2416
2417     /* update the fixed labels */
2418
2419     /* we reuse the ovw version lable and hence do not have to do anything
2420      * for it here */
2421
2422     /* page number label */
2423     tmp_lightobj = (struct gator_lightobj *)cm_pageNum_o->o_data;
2424     sprintf(printBuf, "[Cache Managers, p.%d of %d, c.%d of %d]", a_pageNum,
2425             cm_numPages, a_LcolNum + 1, cm_numCols);
2426     justify_light(printBuf, tmp_lightobj->label, FC_PAGENUM_O_WIDTH,
2427                   RIGHT_JUSTIFY, 1);
2428     gator_light_set(cm_pageNum_o, 1);
2429
2430     /* file servers monitored label */
2431     tmp_lightobj = (struct gator_lightobj *)cm_numCM_o->o_data;
2432     sprintf(printBuf, "%d Cache Managers monitored, %d alerts on %d machines",
2433             numCM, num_cm_alerts, numHosts_oncm_alerts);
2434     justify_light(printBuf, tmp_lightobj->label, FC_NUMHOSTS_O_WIDTH, CENTER,
2435                   1);
2436
2437
2438     /* command line */
2439
2440     /* figure out what we need to show in the prompt & set the page type */
2441     /* the cm_pageType variable is in turn used by the keyboard handler
2442      * routines to call cm_refresh() with the correct parameters */
2443
2444     cm_pageType = resolve_CmdLine(cmdLine, 2 /* cm frame */ , a_pageNum,
2445                                   cm_numPages, cm_numCols, a_LcolNum,
2446                                   cm_cols_perPage, 0);
2447
2448     /* display the command line */
2449     tmp_lightobj = (struct gator_lightobj *)cm_cmd_o->o_data;
2450     sprintf(printBuf, "%s", cmdLine);
2451     justify_light(printBuf, tmp_lightobj->label, strlen(printBuf) + 1,
2452                   LEFT_JUSTIFY, 1);
2453     gator_light_set(cm_cmd_o, 1);
2454
2455     /* update the probe number label */
2456     tmp_lightobj = (struct gator_lightobj *)cm_probeNum_o->o_data;
2457     sprintf(printBuf, "[CM probes %d, freq=%d sec]", afsmon_cm_prev_probeNum,
2458             afsmon_probefreq);
2459     justify_light(printBuf, tmp_lightobj->label, FC_PROBENUM_O_WIDTH,
2460                   RIGHT_JUSTIFY, 1);
2461     gator_light_set(cm_cmd_o, 1);
2462
2463     /* update "columns on left" signal */
2464     tmp_lightobj = (struct gator_lightobj *)cm_leftArrows_o->o_data;
2465     if (cm_pageType & CMD_LEFT)
2466         strcpy(printBuf, "<<<");
2467     else
2468         strcpy(printBuf, "");
2469     justify_light(printBuf, tmp_lightobj->label, FC_ARROWS_O_WIDTH,
2470                   LEFT_JUSTIFY, 1);
2471     gator_light_set(cm_leftArrows_o, 0);
2472
2473     /* update "columns on right" signal */
2474     tmp_lightobj = (struct gator_lightobj *)cm_rightArrows_o->o_data;
2475     if (cm_pageType & CMD_RIGHT)
2476         strcpy(printBuf, ">>>");
2477     else
2478         strcpy(printBuf, "");
2479     justify_light(printBuf, tmp_lightobj->label, FC_ARROWS_O_WIDTH,
2480                   RIGHT_JUSTIFY, 1);
2481     gator_light_set(cm_rightArrows_o, 0);
2482
2483
2484
2485     /* UPDATE THE COLUMN LABELS */
2486
2487     /* the column index is also used to index the label arrays */
2488     labelIdx = a_LcolNum;
2489
2490     /* get the pointers to the three arrays of label onodes */
2491     cmLabels_o_Ptr1 = cmLabels_o[0];
2492     cmLabels_o_Ptr2 = cmLabels_o[1];
2493     cmLabels_o_Ptr3 = cmLabels_o[2];
2494
2495     for (k = 0; k < cm_cols_perPage; k++) {
2496
2497         if (labelIdx < cm_numCols) {
2498             dataIndex = cm_Display_map[labelIdx];
2499             code =
2500                 display_Server_label(cm_labels[dataIndex], *cmLabels_o_Ptr1,
2501                                      *cmLabels_o_Ptr2, *cmLabels_o_Ptr3);
2502
2503             labelIdx++;         /* next label */
2504         } else {
2505             code =
2506                 display_Server_label("//", *cmLabels_o_Ptr1, *cmLabels_o_Ptr2,
2507                                      *cmLabels_o_Ptr3);
2508         }
2509
2510         cmLabels_o_Ptr1++;      /* next onode in label row 1 */
2511         cmLabels_o_Ptr2++;      /* next onode in label row 2 */
2512         cmLabels_o_Ptr3++;      /* next onode in label row 3 */
2513
2514     }                           /* labels for each column */
2515
2516
2517     /* UPDATE THE FILE SERVER STATISTICS */
2518
2519     /* move to the right spot in the CM display data array */
2520     cmDataP = prev_cmData;
2521     cmIdx = 0;
2522     for (i = 0; i < ((a_pageNum - 1) * cm_numHosts_perPage); i++) {
2523         cmDataP++;
2524         cmIdx++;
2525     }
2526
2527     if (cmIdx >= numCM) {       /* whoops! screwed up */
2528         sprintf(errMsg, "[ %s ] Programming error 1\n", rn);
2529         afsmon_Exit(405);
2530     }
2531
2532     /* get the pointer to the first line of onodes of the file server frame */
2533     tmp_cm_lines_P = cm_lines;
2534
2535     for (i = 0; i < cm_numHosts_perPage; i++) {
2536
2537
2538         /* if this is the last page we may not have file servers to fill up
2539          * the page, so check the index */
2540         if (cmIdx < numCM) {
2541
2542             if (cmDataP->hostName[0] == '\0') {
2543                 sprintf(errMsg, "[ %s ] empty cm display entry \n", rn);
2544                 afsmon_Exit(410);
2545             }
2546
2547             /* display the hostname , first names only please! */
2548
2549             sprintf(printBuf, "%s", cmDataP->hostName);
2550             for (j = 0; j < strlen(printBuf); j++) {
2551                 if (printBuf[j] == '.') {
2552                     printBuf[j] = '\0';
2553                     break;
2554                 }
2555             }
2556
2557             tmp_lightobj =
2558                 (struct gator_lightobj *)tmp_cm_lines_P->host_o->o_data;
2559             code =
2560                 justify_light(printBuf, tmp_lightobj->label,
2561                               FC_HOSTNAME_O_WIDTH, LEFT_JUSTIFY, 1);
2562             if (code) {
2563                 fprintf(debugFD, "[ %s ] justify_code returned %d\n", rn,
2564                         code);
2565                 fflush(debugFD);
2566             }
2567
2568             /* use the current column value to index into the cm_Display_map
2569              * array to obtain the index of the item to display. check if its
2570              * overflow flag is set and highlight if so. if the probe had failed
2571              * enter "--" is all columns */
2572
2573             /* each host has two rows of slots for datums. get the pointers to
2574              * both the arrays */
2575
2576             firstSlot_o_Ptr = tmp_cm_lines_P->data_o[0];
2577             secondSlot_o_Ptr = tmp_cm_lines_P->data_o[1];
2578             cm_curr_RCol = a_LcolNum;   /* starting column number from which
2579                                          * we are asked to display data */
2580
2581             for (j = 0; j < cm_cols_perPage; j++) {     /* for each column */
2582
2583                 /* if there is another column of data */
2584                 if (cm_curr_RCol < cm_numCols) {
2585
2586                     dataIndex = cm_Display_map[cm_curr_RCol];
2587
2588                     code =
2589                         display_Server_datum(cmDataP->data[dataIndex],
2590                                              *firstSlot_o_Ptr,
2591                                              *secondSlot_o_Ptr,
2592                                              cmDataP->probeOK, RIGHT_JUSTIFY,
2593                                              cmDataP->threshOvf[dataIndex]);
2594
2595                     cm_curr_RCol++;
2596                 } else {        /* no more data, blank out columns */
2597                     code = display_Server_datum("", *firstSlot_o_Ptr, *secondSlot_o_Ptr, 1,     /* probe ok */
2598                                                 RIGHT_JUSTIFY, 0);      /* no overflow */
2599                 }
2600
2601
2602                 firstSlot_o_Ptr++;      /* onode of next column */
2603                 secondSlot_o_Ptr++;     /* onode of next column */
2604
2605             }                   /* for each column */
2606
2607             /* the loop could have taken the right-column-index one over,
2608              * adjust it now */
2609             if (cm_curr_RCol == cm_numCols)
2610                 cm_curr_RCol--;
2611
2612
2613         }
2614
2615
2616
2617         /* if fdIdx < numCM */
2618         /* if cmIdx >= numCM , blank out all succeding rows */
2619         if (cmIdx >= numCM) {
2620
2621             /* blank out host name object */
2622             tmp_lightobj =
2623                 (struct gator_lightobj *)tmp_cm_lines_P->host_o->o_data;
2624             code =
2625                 justify_light("", tmp_lightobj->label, FC_HOSTNAME_O_WIDTH,
2626                               LEFT_JUSTIFY, 1);
2627             if (code) {
2628                 fprintf(debugFD, "[ %s ] justify_code returned %d\n", rn,
2629                         code);
2630                 fflush(debugFD);
2631             }
2632
2633             firstSlot_o_Ptr = tmp_cm_lines_P->data_o[0];
2634             secondSlot_o_Ptr = tmp_cm_lines_P->data_o[1];
2635
2636             for (k = 0; k < cm_cols_perPage; k++) {
2637                 code = display_Server_datum("", *firstSlot_o_Ptr, *secondSlot_o_Ptr, 1, /* probe OK */
2638                                             RIGHT_JUSTIFY, 0);  /* dont highlight */
2639
2640                 firstSlot_o_Ptr++;
2641                 secondSlot_o_Ptr++;
2642             }
2643
2644         }
2645
2646         /* cmIDx >= numCM */
2647         tmp_cm_lines_P++;       /* pointer to next line in the frame */
2648         cmDataP++;              /* next host's data */
2649         cmIdx++;                /* host index */
2650
2651
2652     }                           /* for each row in the Cache Manager frame */
2653
2654     /* redraw the display if the Cache Managers screen is currently displayed */
2655     if (afsmon_win->w_frame == cmFrame)
2656         WOP_DISPLAY(afsmon_win);
2657
2658     /* update the global page & column numbers to reflect the changes */
2659     cm_currPage = a_pageNum;
2660     cm_curr_LCol = a_LcolNum;;
2661
2662     return (0);
2663
2664 }                               /* cm_refresh */
2665
2666
2667
2668 /*-----------------------------------------------------------------------
2669  * Switch_cm_2_ovw()
2670  *
2671  * Description:
2672  *      Switch from the Cache Manager screen to the Overview Screen
2673  *----------------------------------------------------------------------*/
2674 int
2675 Switch_cm_2_ovw(void *d1, void *d2)
2676 {
2677     /* bind the overview frame to the window */
2678     gtxframe_SetFrame(afsmon_win, ovwFrame);
2679     return (0);
2680 }
2681
2682 /*-----------------------------------------------------------------------
2683  * Switch_cm_2_fs()
2684  *
2685  * Description:
2686  *      Switch from the Cache Manager screen to the File Servers screen
2687  *----------------------------------------------------------------------*/
2688 int
2689 Switch_cm_2_fs(void *d1, void *d2)
2690 {
2691     if (cm_pageType & CMD_FS) {
2692         /* bind the file servers frame to the window */
2693         gtxframe_SetFrame(afsmon_win, fsFrame);
2694     }
2695     return (0);
2696 }
2697
2698 /*-----------------------------------------------------------------------
2699  * Switch_cm_next()
2700  *
2701  * Description:
2702  *      Switch to next page of cache managers screen
2703  *----------------------------------------------------------------------*/
2704 int
2705 Switch_cm_next(void *d1, void *d2)
2706 {
2707     if (cm_pageType & CMD_NEXT) {
2708         /* we have a next page, refresh with next page number */
2709         cm_refresh(cm_currPage + 1, cm_curr_LCol);
2710     }
2711
2712     return (0);
2713 }
2714
2715 /*-----------------------------------------------------------------------
2716  * Switch_cm_last()
2717  *
2718  * Description:
2719  *      Switch to last page of file server screen
2720  *----------------------------------------------------------------------*/
2721 int
2722 Switch_cm_last(void *d1, void *d2)
2723 {
2724     if (cm_pageType & CMD_NEXT) {
2725         /* we have a next page, refresh with last page number */
2726         cm_refresh(cm_numPages, cm_curr_LCol);
2727     }
2728
2729     return (0);
2730 }
2731
2732 /*-----------------------------------------------------------------------
2733  * Switch_cm_prev()
2734  *
2735  * Description:
2736  *      Switch to previous page of cache managers screen
2737  *----------------------------------------------------------------------*/
2738 int
2739 Switch_cm_prev(void *d1, void *d2)
2740 {
2741     if (cm_pageType & CMD_PREV) {
2742         /* we have a previous page, refresh to previous page */
2743         cm_refresh(cm_currPage - 1, cm_curr_LCol);
2744     }
2745     return (0);
2746 }
2747
2748 /*-----------------------------------------------------------------------
2749  * Switch_cm_first()
2750  *
2751  * Description:
2752  *      Switch to first page of cache managers screen
2753  *----------------------------------------------------------------------*/
2754 int
2755 Switch_cm_first(void *d1, void *d2)
2756 {
2757     if (cm_pageType & CMD_PREV) {
2758         /* we have a previous page, refresh to first page */
2759         cm_refresh(1, cm_curr_LCol);
2760     }
2761     return (0);
2762 }
2763
2764 /*-----------------------------------------------------------------------
2765  * Switch_cm_left()
2766  *
2767  * Description:
2768  *      Scroll left on the cache managers screen
2769  *----------------------------------------------------------------------*/
2770 int
2771 Switch_cm_left(void *d1, void *d2)
2772 {
2773     if (cm_pageType & CMD_LEFT) {
2774         /* we have columns on left, refresh with new column number */
2775         cm_refresh(cm_currPage, cm_curr_LCol - cm_cols_perPage);
2776     }
2777     return (0);
2778 }
2779
2780
2781 /*-----------------------------------------------------------------------
2782  * Switch_cm_leftmost()
2783  *
2784  * Description:
2785  *      Scroll to first column on  the cache managers screen
2786  *----------------------------------------------------------------------*/
2787 int
2788 Switch_cm_leftmost(void *d1, void *d2)
2789 {
2790     if (cm_pageType & CMD_LEFT) {
2791         /* we have columns on left, go to the first column */
2792         cm_refresh(cm_currPage, 0);
2793     }
2794     return (0);
2795 }
2796
2797 /*-----------------------------------------------------------------------
2798  * Switch_cm_right()
2799  *
2800  * Description:
2801  *      Scroll right on the cache managers screen
2802  *----------------------------------------------------------------------*/
2803 int
2804 Switch_cm_right(void *d1, void *d2)
2805 {
2806     if (cm_pageType & CMD_RIGHT) {
2807         /* we have columns on right, refresh with new column number */
2808         cm_refresh(cm_currPage, cm_curr_LCol + cm_cols_perPage);
2809     }
2810     return (0);
2811 }
2812
2813 /*-----------------------------------------------------------------------
2814  * Switch_cm_rightmost()
2815  *
2816  * Description:
2817  *      Scroll to last column on the cache managers screen
2818  *----------------------------------------------------------------------*/
2819 int
2820 Switch_cm_rightmost(void *d1, void *d2)
2821 {
2822     int curr_LCol;
2823
2824     if (cm_pageType & CMD_RIGHT) {
2825         /* we have columns on right, go to the last column */
2826         if (cm_numCols % cm_cols_perPage)
2827             curr_LCol = (cm_numCols / cm_cols_perPage) * cm_cols_perPage;
2828         else
2829             curr_LCol =
2830                 ((cm_numCols / cm_cols_perPage) - 1) * cm_cols_perPage;
2831         cm_refresh(cm_currPage, curr_LCol);
2832     }
2833     return (0);
2834 }
2835
2836
2837 /*-----------------------------------------------------------------------
2838  * create_CMframe_objects()
2839  *
2840  * Description:
2841  *      Create the gtx objects (onodes) for the Cache Managers frame and setup
2842  *      the keyboard bindings.
2843  *      Only as many objects as can fit on the display are created. The
2844  *      positions and lengths of all these objects are fixed at creation.
2845  *      These objects are updated with new data at the end of each probe
2846  *      cycle.
2847  *
2848  * Returns:
2849  *      Success: 0
2850  *      Failure: Exits afsmonitor.
2851  *----------------------------------------------------------------------*/
2852
2853 int
2854 create_CMframe_objects(void)
2855 {                               /* create_CMframe_objects */
2856     static char rn[] = "create_CMframe_objects";
2857     struct ServerInfo_line *cm_lines_Ptr;
2858     struct onode **cm_data_o_Ptr;
2859     struct onode **cmLabels_o_Ptr;
2860     int x_pos;
2861     int y_pos;
2862     int i;
2863     int j;
2864     int numBytes;
2865     int arrIdx;
2866
2867     if (afsmon_debug) {
2868         fprintf(debugFD, "[ %s ] Called\n", rn);
2869         fflush(debugFD);
2870     }
2871
2872
2873
2874     /* create the command line object */
2875     cm_cmd_o =
2876         initLightObject("Command [oview, fs, prev, next, left, right] ? ", 0,
2877                         maxY - 1, FC_CMD_O_WIDTH, afsmon_win);
2878     if (cm_cmd_o == NULL) {
2879         sprintf(errMsg, "[ %s ] Failed to create cm command onode\n", rn);
2880         afsmon_Exit(420);
2881     }
2882     gtxframe_AddToList(cmFrame, cm_cmd_o);
2883     gator_light_set(cm_cmd_o, HIGHLIGHT);
2884
2885
2886     /* we already have the dimensions for the frame - same as the ovw frame */
2887     /* use the ovw program name object for the cm screen too */
2888
2889     gtxframe_AddToList(cmFrame, ovw_progName_o);
2890
2891
2892     /* create the page number object */
2893     cm_pageNum_o =
2894         initLightObject("[Cache Managers, p. X of X, c. Y of Y]",
2895                         maxX - FC_PAGENUM_O_WIDTH, 0, FC_PAGENUM_O_WIDTH,
2896                         afsmon_win);
2897     if (cm_pageNum_o == NULL) {
2898         sprintf(errMsg, "[ %s ] Failed to create pageNumber onode\n", rn);
2899         afsmon_Exit(415);
2900     }
2901     gtxframe_AddToList(cmFrame, cm_pageNum_o);
2902     gator_light_set(cm_pageNum_o, HIGHLIGHT);
2903
2904     /* create the probe number object */
2905     cm_probeNum_o =
2906         initLightObject("[CM probes 1, freq=30 sec]",
2907                         maxX - FC_PROBENUM_O_WIDTH, maxY - 1,
2908                         FC_PROBENUM_O_WIDTH, afsmon_win);
2909     if (cm_probeNum_o == NULL) {
2910         sprintf(errMsg, "[ %s ] Failed to create cm probeNum onode\n", rn);
2911         afsmon_Exit(425);
2912     }
2913     gtxframe_AddToList(cmFrame, cm_probeNum_o);
2914     gator_light_set(cm_probeNum_o, HIGHLIGHT);
2915
2916
2917     /* create the numCM monitored object */
2918     cm_numCM_o =
2919         initLightObject
2920         ("      0 Cache Mangers monitored, 0 alerts on 0 machines", 4, 2,
2921          FC_NUMHOSTS_O_WIDTH, afsmon_win);
2922     if (cm_numCM_o == NULL) {
2923         sprintf(errMsg,
2924                 "[ %s ] Failed to create numCM onode for the cm frame\n", rn);
2925         afsmon_Exit(430);
2926     }
2927     gtxframe_AddToList(cmFrame, cm_numCM_o);
2928
2929     /* create the "more columns to left" indicator */
2930     cm_leftArrows_o =
2931         initLightObject("<<<", 0, 2, FC_ARROWS_O_WIDTH, afsmon_win);
2932     if (cm_leftArrows_o == NULL) {
2933         sprintf(errMsg,
2934                 "[ %s ] Failed to create leftArrows onode for the cm frame\n",
2935                 rn);
2936         afsmon_Exit(435);
2937     }
2938     gtxframe_AddToList(cmFrame, cm_leftArrows_o);
2939
2940     /* create the "more columns to right" indicator */
2941     cm_rightArrows_o =
2942         initLightObject(">>>", maxX - FC_ARROWS_O_WIDTH, 2, FC_ARROWS_O_WIDTH,
2943                         afsmon_win);
2944     if (cm_rightArrows_o == NULL) {
2945         sprintf(errMsg,
2946                 "[ %s ] Failed to create rightArrows onode for the cm frame\n",
2947                 rn);
2948         afsmon_Exit(440);
2949     }
2950     gtxframe_AddToList(cmFrame, cm_rightArrows_o);
2951
2952
2953
2954
2955     /* calculate the maximum number of hosts per page (2 rows per host) */
2956     cm_numHosts_perPage = (maxY - FC_NUM_FIXED_LINES) / 2;
2957
2958     /* determine the number of data columns that can fit in a page */
2959     cm_cols_perPage = (maxX - FC_HOSTNAME_O_WIDTH) / (FC_COLUMN_WIDTH);
2960
2961     if (afsmon_debug) {
2962         fprintf(debugFD, "[ %s ] cm_numHosts_perPage=%d cm_cols_perPage=%d\n",
2963                 rn, cm_numHosts_perPage, cm_cols_perPage);
2964         fflush(debugFD);
2965     }
2966
2967     /* the above two variables give us the information needed to create
2968      * the objects for displaying the file server information */
2969
2970     /* allocate memory for all the onode pointers required to display
2971      * the file server statistics */
2972
2973     numBytes = cm_numHosts_perPage * sizeof(struct ServerInfo_line);
2974     cm_lines = (struct ServerInfo_line *)malloc(numBytes);
2975     if (cm_lines == (struct ServerInfo_line *)0) {
2976         sprintf(errMsg,
2977                 "[ %s ] Failed to allocate %d bytes for CM data lines\n", rn,
2978                 numBytes);
2979         afsmon_Exit(445);
2980     }
2981
2982     /* for each line of server statistics allocate memory to store two arrays
2983      * of data onodes */
2984
2985     cm_lines_Ptr = cm_lines;
2986     for (i = 0; i < cm_numHosts_perPage; i++) {
2987         for (arrIdx = 0; arrIdx < 2; arrIdx++) {
2988             numBytes = cm_cols_perPage * sizeof(struct onode *);
2989             cm_lines_Ptr->data_o[arrIdx] = (struct onode **)malloc(numBytes);
2990             if (cm_lines_Ptr->data_o[arrIdx] == NULL) {
2991                 sprintf(errMsg,
2992                         "[ %s ] Failed to allocate %d bytes for CM data onodes\n",
2993                         rn, numBytes);
2994                 afsmon_Exit(450);
2995             }
2996         }
2997         cm_lines_Ptr++;
2998     }
2999
3000     /* now allocate the onodes itself */
3001
3002     cm_lines_Ptr = cm_lines;
3003     for (i = 0; i < cm_numHosts_perPage; i++) {
3004
3005         /* initialize host name onode */
3006         cm_lines_Ptr->host_o =
3007             initLightObject("CMHostName", 0, FC_FIRST_HOST_ROW + 2 * i,
3008                             FC_HOSTNAME_O_WIDTH, afsmon_win);
3009         if (cm_lines_Ptr->host_o == NULL) {
3010             sprintf(errMsg, "[ %s ] Failed to create an CM name onode\n", rn);
3011             afsmon_Exit(455);
3012         }
3013         gtxframe_AddToList(cmFrame, cm_lines_Ptr->host_o);
3014
3015         /* if (afsmon_debug) {
3016          * fprintf(debugFD,"[ %s ] Addr of host_o = %d for line %d\n",
3017          * rn,cm_lines_Ptr->host_o,i);
3018          * fflush(debugFD);
3019          * } */
3020
3021         /* initialize data onodes for this host */
3022
3023         for (arrIdx = 0; arrIdx < 2; arrIdx++) {        /* for each array index */
3024
3025             cm_data_o_Ptr = cm_lines_Ptr->data_o[arrIdx];
3026             for (j = 0; j < cm_cols_perPage; j++) {     /* for each column */
3027
3028                 char tmpBuf[20];
3029
3030                 /* determine x & y coordinate for this data object */
3031                 /* the 1's are for leaving a blank after each column */
3032                 x_pos = FC_HOSTNAME_O_WIDTH + (j * (FC_COLUMN_WIDTH));
3033                 y_pos = FC_FIRST_HOST_ROW + 2 * i + arrIdx;
3034
3035                 sprintf(tmpBuf, "-CMData %d-", arrIdx);
3036                 *cm_data_o_Ptr =
3037                     initLightObject(tmpBuf, x_pos, y_pos, FC_COLUMN_WIDTH,
3038                                     afsmon_win);
3039                 if (*cm_data_o_Ptr == NULL) {
3040                     sprintf(errMsg,
3041                             "[ %s ] Failed to create an CM data onode\n", rn);
3042                     afsmon_Exit(460);
3043                 }
3044                 gtxframe_AddToList(cmFrame, *cm_data_o_Ptr);
3045
3046                 cm_data_o_Ptr++;
3047             }                   /* for each column */
3048         }                       /* for each onode array index */
3049
3050         cm_lines_Ptr++;
3051     }                           /* for each host slot */
3052
3053
3054     /* INITIALIZE COLUMN LABELS */
3055
3056
3057     /* allocate memory for two arrays of onode pointers for file server column
3058      * labels */
3059     for (arrIdx = 0; arrIdx < 3; arrIdx++) {
3060
3061         cmLabels_o[arrIdx] =
3062             (struct onode **)malloc(sizeof(struct onode *) * cm_cols_perPage);
3063         if (cmLabels_o[arrIdx] == NULL) {
3064             sprintf(errMsg,
3065                     "[ %s ] Failed to allocate memory for CM label onodes\n",
3066                     rn);
3067             afsmon_Exit(465);
3068         }
3069
3070         /* create cache manager name objects */
3071         cmLabels_o_Ptr = cmLabels_o[arrIdx];
3072         for (i = 0; i < cm_cols_perPage; i++) {
3073             *cmLabels_o_Ptr =
3074                 initLightObject("", FC_HOSTNAME_O_WIDTH + i * FC_COLUMN_WIDTH,
3075                                 FC_FIRST_LABEL_ROW + arrIdx, FC_COLUMN_WIDTH,
3076                                 afsmon_win);
3077
3078             if (*cmLabels_o_Ptr == NULL) {
3079                 sprintf(errMsg, "[ %s ] Failed to create a CM label onode\n",
3080                         rn);
3081                 afsmon_Exit(470);
3082             }
3083             gtxframe_AddToList(cmFrame, *cmLabels_o_Ptr);
3084             cmLabels_o_Ptr++;
3085         }
3086
3087     }
3088
3089     /* initialize the column & page counters */
3090
3091     cm_currPage = 1;
3092     cm_numCols = cm_DisplayItems_count;
3093     cm_numPages = numCM / cm_numHosts_perPage;
3094     if (numCM % cm_numHosts_perPage)
3095         cm_numPages++;
3096     cm_curr_LCol = 0;           /* leftmost col */
3097     cm_curr_RCol = 0;           /* rightmost col */
3098
3099     /* create keyboard bindings */
3100     /* bind Q and \ 3 to exit */
3101     keymap_BindToString(cmFrame->keymap, "Q", afsmonExit_gtx, NULL, NULL);
3102     keymap_BindToString(cmFrame->keymap, "\ 3", afsmonExit_gtx, NULL, NULL);
3103
3104     /* o = overview, c = cm, n = next, p = prev, l = left, r = right
3105      * N = last page, P = first page, L = leftmost col, R = rightmost col */
3106
3107     keymap_BindToString(cmFrame->keymap, "o", Switch_cm_2_ovw, NULL, NULL);
3108     keymap_BindToString(cmFrame->keymap, "f", Switch_cm_2_fs, NULL, NULL);
3109     keymap_BindToString(cmFrame->keymap, "n", Switch_cm_next, NULL, NULL);
3110     keymap_BindToString(cmFrame->keymap, "N", Switch_cm_last, NULL, NULL);
3111     keymap_BindToString(cmFrame->keymap, "p", Switch_cm_prev, NULL, NULL);
3112     keymap_BindToString(cmFrame->keymap, "P", Switch_cm_first, NULL, NULL);
3113     keymap_BindToString(cmFrame->keymap, "l", Switch_cm_left, NULL, NULL);
3114     keymap_BindToString(cmFrame->keymap, "L", Switch_cm_leftmost, NULL, NULL);
3115     keymap_BindToString(cmFrame->keymap, "r", Switch_cm_right, NULL, NULL);
3116     keymap_BindToString(cmFrame->keymap, "R", Switch_cm_rightmost, NULL,
3117                         NULL);
3118
3119     return (0);
3120 }                               /* create_CMframe_objects */
3121
3122
3123
3124 /*-----------------------------------------------------------------------
3125  * gtx_initialize()
3126  *
3127  * Description:
3128  *      Initialize the gtx package and call routines to create the objects
3129  *      for the overview, File Servers & Cache Managers screens.
3130  *----------------------------------------------------------------------*/
3131 int
3132 gtx_initialize(void)
3133 {                               /* gtx_initialize */
3134     static char rn[] = "gtx_initialize";        /* routine name */
3135     int code;
3136
3137     if (afsmon_debug) {
3138         fprintf(debugFD, "[ %s ] Called\n", rn);
3139         fflush(debugFD);
3140     }
3141
3142     afsmon_win = gtx_Init(0, -1);       /* 0 => dont start input server,
3143                                          * 1 => use curses */
3144     if (afsmon_win == NULL) {
3145         sprintf(errMsg, "[ %s ] gtx initialization failed\n", rn);
3146         afsmon_Exit(475);
3147     }
3148     gtx_initialized = 1;
3149
3150     /* Create the Overview frame */
3151
3152     ovwFrame = gtxframe_Create();
3153     if (ovwFrame == (struct gtx_frame *)0) {
3154         sprintf(errMsg, "[ %s ] Failed to create overview frame\n", rn);
3155         afsmon_Exit(480);
3156     }
3157
3158     /* bind the overview frame to the window */
3159     gtxframe_SetFrame(afsmon_win, ovwFrame);
3160
3161     /* create overview frame objects */
3162     code = create_ovwFrame_objects();
3163     if (code) {
3164         sprintf(errMsg, "[ %s ] Error in creating ovw frame objects\n", rn);
3165         afsmon_Exit(485);
3166     }
3167
3168
3169     /* Create the File Server frame */
3170     fsFrame = gtxframe_Create();
3171     if (fsFrame == (struct gtx_frame *)0) {
3172         sprintf(errMsg, "[ %s ] Failed to create file server frame\n", rn);
3173         afsmon_Exit(490);
3174     }
3175
3176
3177     /* Create File Server frame objects */
3178     code = create_FSframe_objects();
3179     if (code) {
3180         sprintf(errMsg, "[ %s ] Error in creating FS frame objects\n", rn);
3181         afsmon_Exit(495);
3182     }
3183
3184     /* Create the Cache Managers frame */
3185     cmFrame = gtxframe_Create();
3186     if (cmFrame == (struct gtx_frame *)0) {
3187         sprintf(errMsg, "[ %s ] Failed to create Cache Managers frame\n", rn);
3188         afsmon_Exit(500);
3189     }
3190
3191     /* Create Cache Managers frame objects */
3192     code = create_CMframe_objects();
3193     if (code) {
3194         sprintf(errMsg, "[ %s ] Error in creating CM frame objects\n", rn);
3195         afsmon_Exit(505);
3196     }
3197
3198     /* misc initializations */
3199     sprintf(blankline, "%255s", " ");
3200
3201     return (0);
3202 }                               /* gtx_initialize */