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