2 * Copyright 2000, International Business Machines Corporation and others.
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
11 * Scout: A quick and (semi-)dirty attempt at the old CMU vopcon.
12 *------------------------------------------------------------------------*/
14 #include <afsconfig.h>
15 #include <afs/param.h>
20 #include <afs/gtxwindows.h> /*Generic window package */
21 #include <afs/gtxobjects.h> /*Object definitions */
22 #include <afs/gtxtextobj.h> /*Text object interface */
23 #include <afs/gtxlightobj.h> /*Light object interface */
24 #include <afs/gtxcurseswin.h> /*Curses window package */
25 #include <afs/gtxdumbwin.h> /*Dumb terminal window package */
26 #include <afs/gtxX11win.h> /*X11 window package */
27 #include <afs/gtxframe.h> /*Frame package */
28 #include <afs/gtxinput.h>
29 #include <afs/cmd.h> /*Command interpretation library */
30 #include <afs/fsprobe.h> /*Interface for fsprobe module */
31 #include <afs/afsutil.h>
34 * Command line parameter indicies.
48 * Define the default width in chars for each light object on the mini-line.
50 #define LIGHTOBJ_CONN_WIDTH 5
51 #define LIGHTOBJ_FETCH_WIDTH 10
52 #define LIGHTOBJ_STORE_WIDTH 10
53 #define LIGHTOBJ_WK_WIDTH 5
54 #define LIGHTOBJ_SRVNAME_WIDTH 13
55 #define LIGHTOBJ_DISK_WIDTH 12
58 * Define column width indices.
68 * Define the types of justification we can perform.
70 #define SCOUT_RIGHT_JUSTIFY 0
71 #define SCOUT_LEFT_JUSTIFY 1
72 #define SCOUT_CENTER 2
75 * Define the types of truncation we can perform.
77 #define SCOUT_LEFT_TRUNC 0
78 #define SCOUT_RIGHT_TRUNC 1
81 * Define whether the value passed is a labeled disk quantity.
83 #define SCOUT_ISNT_LDISK 0
84 #define SCOUT_IS_LDISK 1
87 * We sometimes use index-base pointers, so we need a distinguished
90 #define SCOUT_NIL (-1)
93 * Structure describing everything you want to know about a FileServer
97 int prev
; /*Index of previous list entry */
98 int next
; /*Index of next list entry */
99 int active
; /*Is this disk known to exist? */
100 char *name
; /*Single-letter disk name */
101 struct onode
*disk_lp
; /*Ptr to disk light object */
105 * Structure defining all the objects in the Scout line (or lines)
106 * for each server being watched. Note that scout_disk linked list
107 * for used disks is ordered alphabetically.
111 * Information on server location & configuration.
113 struct sockaddr_in skt
; /*Server's socket info */
114 int numDisks
; /*Number of disks used */
116 * Screen location info.
118 int base_line
; /*Line number on the screen */
119 int num_lines
; /*Number of lines of info */
121 * Associated light objects.
123 struct onode
*currConns_lp
; /*Number of current connections */
124 struct onode
*fetches_lp
; /*Number of data fetches */
125 struct onode
*stores_lp
; /*Number of data stores */
126 struct onode
*workstations_lp
; /*Workstation info */
127 struct onode
*srvName_lp
; /*Server name */
128 struct scout_disk disks
[VOLMAXPARTS
]; /*Info on all the disks */
129 int used_head
; /*Index of first used disk struct */
130 int used_tail
; /*Index of last used disk struct */
131 int free_head
; /*Index of first free disk struct */
132 int free_tail
; /*Index of last free disk struct */
136 * Structure defining the contents of the Scout screen.
139 int numServers
; /*Number of servers being watched */
140 int base_line_num
; /*Base mini-line number */
141 struct mini_line
*line
; /*Array of screen lines */
144 static char pn
[] = "scout"; /*Program name */
145 static int scout_debug
= 0; /*Is debugging turned on? */
146 static FILE *scout_debugfd
; /*Debugging file descriptor */
147 static int scout_gtx_initialized
= 0; /*Has gtx been initialized? */
148 static struct mini_screen scout_screen
; /*Mini-screen itself */
149 static int scout_probefreq
; /*Probe frequency in seconds */
150 static char scout_basename
[64]; /*Base server name */
151 static char scout_hostname
[128]; /*Name of machine we're running on */
152 static int scout_showhostname
= 0; /*Show name of machine we're on? */
153 static char scout_blankline
[256]; /*Blank line */
154 static struct gwin
*scout_gwin
; /*Window to use */
155 static struct gtx_frame
*scout_frame
; /*Frame to use */
156 static struct onode
*scout_banner0_lp
; /*Banner light, line 0 */
157 static struct onode
*scout_banner1_lp
; /*Banner light, line 1 */
158 static struct onode
*scout_banner2_lp
; /*Banner light, line 2 */
159 static int scout_DiskLightLeftCol
= 0; /*Column for leftmost disk light */
160 static struct gwin_sizeparams scout_frameDims
; /*Frame dimensions */
162 static int scout_col_width
[] = { LIGHTOBJ_CONN_WIDTH
,
163 LIGHTOBJ_FETCH_WIDTH
,
164 LIGHTOBJ_STORE_WIDTH
,
166 LIGHTOBJ_SRVNAME_WIDTH
,
171 * Attention thresholds & modes.
173 #define SCOUT_ATTN_NOTUSED (-1)
174 #define SCOUT_DISKM_PCUSED 0
175 #define SCOUT_DISKM_MINFREE 1
177 static int scout_attn_conn
= SCOUT_ATTN_NOTUSED
;
178 static int scout_attn_fetch
= SCOUT_ATTN_NOTUSED
;
179 static int scout_attn_store
= SCOUT_ATTN_NOTUSED
;
180 static int scout_attn_workstations
= SCOUT_ATTN_NOTUSED
;
181 static int scout_attn_disk_mode
= SCOUT_DISKM_PCUSED
;
182 static int scout_attn_disk_minfree
= 1000;
183 static float scout_attn_disk_pcused
= 0.95;
184 static char scout_attn_disk_pcusedstr
[8] = "95";
187 * Some strings we'll be using over and over again.
189 static char scout_Banner
[256];
190 static const char *scout_label
[] =
191 { "Conn", "Fetch", "Store", "Ws", "", "Disk attn" };
192 static const char *scout_underline
[] =
193 { "----", "--------", "--------", "-----", "", "----------" };
196 /*------------------------------------------------------------------------
200 * Exits cleanly from the Scout. If gtx has not yet been initialized,
201 * then we simply call exit() with the value provided. Otherwise,
202 * we call the appropriate gtx routine to exit cleanly from gtx, which
203 * must reset the terminal or window. We also close the debugging
204 * file descriptor, if one has been opened.
207 * int a_exitval : Value with which to exit the program.
213 * Actions depend on scout_gtx_initialized.
216 * This routine will always exit Scout.
217 *------------------------------------------------------------------------*/
220 scout_CleanExit(int a_exitval
)
221 { /*scout_CleanExit */
223 static char rn
[] = "scout_CleanExit"; /*Routine name */
225 if (scout_debugfd
!= (FILE *) 0) {
226 fprintf(scout_debugfd
, "[%s] Closing debugging file\n", rn
);
227 fclose(scout_debugfd
);
230 if (scout_gtx_initialized
) {
231 gtxframe_exitValue
= a_exitval
;
232 gtxframe_ExitCmd((void *)(>xframe_exitValue
), NULL
);
236 } /*scout_CleanExit */
238 /*------------------------------------------------------------------------
239 * mini_initLightObject
242 * Create and initialize a light onode according to the given
246 * char *a_name : Ptr to the light's string name.
247 * int a_x : X offset.
248 * int a_y : Y offset.
249 * int a_width : Width in chars.
250 * struct gwin *a_win : Ptr to window structure.
253 * Ptr to new light onode on success,
254 * A null pointer otherwise.
261 *------------------------------------------------------------------------*/
263 static struct onode
*
264 mini_initLightObject(char *a_name
, int a_x
, int a_y
, int a_width
, struct gwin
*a_win
)
265 { /*mini_initLightObject */
267 static char rn
[] = "mini_initLightObject"; /*Routine name */
268 struct onode
*newlightp
; /*Ptr to new light onode */
269 /*We only support curses right now */
270 struct gator_light_crparams light_crparams
; /*Light creation params */
271 char *truncname
; /*Truncated name, if needed */
272 int name_len
; /*True length of name */
275 fprintf(scout_debugfd
,
276 "[%s] Called for name '%s', [%d, %d], %d-char field\n", rn
,
277 a_name
, a_x
, a_y
, a_width
);
278 fflush(scout_debugfd
);
283 * Set up the creation parameters according to the information we've
286 light_crparams
.onode_params
.cr_type
= GATOR_OBJ_LIGHT
;
287 name_len
= strlen(a_name
);
289 fprintf(scout_debugfd
, "[%s] Name '%s' has %d chars\n", rn
, a_name
,
291 if (name_len
<= a_width
)
292 sprintf(light_crparams
.onode_params
.cr_name
, "%s", a_name
);
295 * We need to truncate the given name, leaving a `*' at the end to
296 * show us it's been truncated.
298 truncname
= light_crparams
.onode_params
.cr_name
;
299 strncpy(truncname
, a_name
, a_width
- 1);
300 truncname
[a_width
- 1] = '*';
301 truncname
[a_width
] = 0;
303 light_crparams
.onode_params
.cr_x
= a_x
;
304 light_crparams
.onode_params
.cr_y
= a_y
;
305 light_crparams
.onode_params
.cr_width
= a_width
;
306 light_crparams
.onode_params
.cr_height
= 1;
307 light_crparams
.onode_params
.cr_window
= a_win
;
308 light_crparams
.onode_params
.cr_home_obj
= NULL
;
309 light_crparams
.onode_params
.cr_prev_obj
= NULL
;
310 light_crparams
.onode_params
.cr_parent_obj
= NULL
;
311 light_crparams
.onode_params
.cr_helpstring
= NULL
;
313 light_crparams
.appearance
= 0;
314 light_crparams
.flashfreq
= 0;
315 sprintf(light_crparams
.label
, "%s", a_name
);
316 light_crparams
.label_x
= 0;
317 light_crparams
.label_y
= 0;
320 gator_objects_create((struct onode_createparams
*)(&light_crparams
));
323 * Return the news, happy or not.
327 } /*mini_initLightObject */
329 /*------------------------------------------------------------------------
330 * scout_initDiskLightObjects
333 * Create and initialize all Scout light objects for a server's
337 * struct scout_disk *a_line : Ptr to the server object line.
338 * struct gwin *a_win : Ptr to window structure.
349 *------------------------------------------------------------------------*/
352 scout_initDiskLightObjects(struct mini_line
*a_line
, struct gwin
*a_win
)
353 { /*scout_initDiskLightObjects */
355 static char rn
[] = "scout_initDiskLightObjects"; /*Routine name */
356 struct scout_disk
*curr_disk
; /*Ptr to current disk being set up */
357 int i
; /*Loop variable */
360 fprintf(scout_debugfd
, "[%s] Called\n", rn
);
361 fflush(scout_debugfd
);
365 * Set up the base linked list fields.
367 a_line
->used_head
= SCOUT_NIL
;
368 a_line
->used_tail
= SCOUT_NIL
;
369 a_line
->free_head
= 0;
370 a_line
->free_tail
= VOLMAXPARTS
- 1;
373 * Sweep through the disk structures, creating the light objects and
374 * marking them all as free.
376 curr_disk
= a_line
->disks
;
377 for (i
= 0; i
< VOLMAXPARTS
; i
++) {
379 * Create the disk light object.
381 if ((curr_disk
->disk_lp
= mini_initLightObject("Disk", /*Object name */
384 scout_col_width
[COL_DISK
], /*Width */
387 fprintf(stderr
, "[%s:%s] Can't create disk %d light object\n", pn
,
393 * Set the other fields in the disk records; Note that in the
394 * fencepost cases, the prev and next pointers will have to be
397 curr_disk
->prev
= i
- 1;
398 curr_disk
->next
= i
+ 1;
399 curr_disk
->active
= 0;
400 curr_disk
->name
= "";
403 * Bump up to the next disk structure.
407 } /*for each disk structure */
410 * We made it all the way through. Fix the fencepost pointers, set
411 * the overall pointers, then return success.
413 a_line
->disks
[0].prev
= SCOUT_NIL
;
414 a_line
->disks
[VOLMAXPARTS
- 1].next
= SCOUT_NIL
;
418 } /*scout_initDiskLightObjects */
421 /*------------------------------------------------------------------------
425 * Place the chars in the source buffer into the target buffer
426 * with the desired justification, either centered, left-justified
427 * or right-justified. Also, support inidication of truncation
428 * with a star (*), either on the left or right of the string,
429 * and whether we're justifying a labeled disk quantity.
432 * char *a_srcbuff : Ptr to source char buffer.
433 * char *a_dstbuff : Ptr to dest char buffer.
434 * int a_dstwidth : Width of dest buffer in chars.
435 * int a_justification : Kind of justification.
436 * int a_rightTrunc : If non-zero, place the truncation char
437 * on the right of the string. Otherwise,
438 * place it on the left.
439 * int a_isLabeledDisk : Is this a labeled disk quantity?
446 * All it needs to know is exported by the fsprobe module, namely
447 * the data structure where the probe results are stored.
451 *------------------------------------------------------------------------*/
454 mini_justify(char *a_srcbuff
, char *a_dstbuff
, int a_dstwidth
,
455 int a_justification
, int a_rightTrunc
,
459 static char rn
[] = "mini_justify"; /*Routine name */
460 int leftpad_chars
; /*# of chars for left-padding */
461 int num_src_chars
; /*# of chars in source */
462 int true_num_src_chars
; /*# src chars before truncation */
463 int trunc_needed
; /*Is truncation needed? */
464 char diskChar
= 0; /*Disk name prefix */
467 fprintf(scout_debugfd
, "[%s] Called with '%s', dest width=%d\n", rn
,
468 a_srcbuff
, a_dstwidth
);
469 fflush(scout_debugfd
);
473 * Remember the disk label, if we've been passed such a thing.
476 diskChar
= *a_srcbuff
;
479 * If the destination width will overrun the gtx string storage,
480 * we automatically shorten up.
482 if (a_dstwidth
> GATOR_LABEL_CHARS
) {
484 fprintf(scout_debugfd
,
485 "[%s] Dest width (%d) > gtx buflen (%d), shrinking dest width\n",
486 rn
, a_dstwidth
, GATOR_LABEL_CHARS
);
487 fflush(scout_debugfd
);
489 a_dstwidth
= GATOR_LABEL_CHARS
;
493 * If our source string is too long, prepare for truncation.
495 true_num_src_chars
= strlen(a_srcbuff
);
496 if (true_num_src_chars
>= a_dstwidth
) {
498 num_src_chars
= a_dstwidth
- 1;
501 a_srcbuff
+= (true_num_src_chars
- num_src_chars
);
504 num_src_chars
= true_num_src_chars
;
507 * Compute the necessary left-padding.
509 switch (a_justification
) {
511 case SCOUT_RIGHT_JUSTIFY
:
512 leftpad_chars
= (a_dstwidth
- 1) - num_src_chars
;
515 case SCOUT_LEFT_JUSTIFY
:
517 * This is the really easy one.
523 leftpad_chars
= ((a_dstwidth
- 1) - num_src_chars
) / 2;
527 fprintf(stderr
, "[%s] Illegal justification command: %d", rn
,
530 } /*Switch on justification type */
534 * Clear out the dest buffer, then place the source string at the
535 * appropriate padding location. Remember to place a string
536 * terminator at the end of the dest buffer, plus whatever truncation
537 * may be needed. If we're left-truncating, we've already shifted
538 * the src buffer appropriately.
540 strncpy(a_dstbuff
, scout_blankline
, a_dstwidth
);
541 strncpy(a_dstbuff
+ leftpad_chars
, a_srcbuff
, num_src_chars
);
542 *(a_dstbuff
+ a_dstwidth
- 1) = '\0';
545 *(a_dstbuff
+ a_dstwidth
- 2) = '*'; /*Truncate on the right */
547 if (a_isLabeledDisk
) {
548 *a_dstbuff
= diskChar
;
549 *(a_dstbuff
+ 1) = ':';
550 *(a_dstbuff
+ 2) = '*'; /*Truncate on the left, disk */
552 *a_dstbuff
= '*'; /*Truncate on the left, non-disk */
556 /*Handle truncations */
558 * Return the good news.
564 /*------------------------------------------------------------------------
565 * scout_SetNonDiskLightLine
568 * Given a mini-line and a line number, place all non-disk lights
572 * struct mini_line *a_srvline : Ptr to server descriptor.
573 * int a_linenum : Line number to move to.
579 * The light's location is stored not only in the onode, but in
580 * the light's rock, so we have to change both sets of value.
584 *------------------------------------------------------------------------*/
587 scout_SetNonDiskLightLine(struct mini_line
*a_srvline
, int a_linenum
)
588 { /*scout_SetNonDiskLightLine */
590 struct gator_lightobj
*nondisk_lightdata
; /*Non-disk light data field */
591 struct gwin_strparams
*nondisk_strparams
; /*Associated string params */
594 * Do the exact same operation for each non-disk light in the record.
596 a_srvline
->currConns_lp
->o_y
= a_linenum
;
598 (struct gator_lightobj
*)(a_srvline
->currConns_lp
->o_data
);
599 nondisk_strparams
= (struct gwin_strparams
*)(nondisk_lightdata
->llrock
);
600 nondisk_strparams
->y
= a_linenum
;
602 a_srvline
->fetches_lp
->o_y
= a_linenum
;
604 (struct gator_lightobj
*)(a_srvline
->fetches_lp
->o_data
);
605 nondisk_strparams
= (struct gwin_strparams
*)(nondisk_lightdata
->llrock
);
606 nondisk_strparams
->y
= a_linenum
;
608 a_srvline
->stores_lp
->o_y
= a_linenum
;
610 (struct gator_lightobj
*)(a_srvline
->stores_lp
->o_data
);
611 nondisk_strparams
= (struct gwin_strparams
*)(nondisk_lightdata
->llrock
);
612 nondisk_strparams
->y
= a_linenum
;
614 a_srvline
->workstations_lp
->o_y
= a_linenum
;
616 (struct gator_lightobj
*)(a_srvline
->workstations_lp
->o_data
);
617 nondisk_strparams
= (struct gwin_strparams
*)(nondisk_lightdata
->llrock
);
618 nondisk_strparams
->y
= a_linenum
;
620 a_srvline
->srvName_lp
->o_y
= a_linenum
;
622 (struct gator_lightobj
*)(a_srvline
->srvName_lp
->o_data
);
623 nondisk_strparams
= (struct gwin_strparams
*)(nondisk_lightdata
->llrock
);
624 nondisk_strparams
->y
= a_linenum
;
626 } /*scout_SetNonDiskLightLine */
628 /*------------------------------------------------------------------------
629 * scout_RecomputeLightLocs
632 * Given a pointer to a server record, recompute its disk light
633 * locations (and keep proper track of the number of screen lines
634 * required for the server record).
637 * struct mini_line *a_srvline : Ptr to server descriptor.
640 * 0 if anything went wrong,
641 * else the number of lines used by this server record.
644 * One or more records have joined or left the used light list
645 * for this server. We're not sure which ones, so we recompute
646 * them all. We may also have had a width change in the gtx
647 * frame. The base_line field in the server record is guaranteed
648 * to be correct at this point.
652 *------------------------------------------------------------------------*/
655 scout_RecomputeLightLocs(struct mini_line
*a_srvline
)
656 { /*scout_RecomputeLightLocs */
658 static char rn
[] = "scout_RecomputeLightLocs"; /*Routine name */
659 int lights_per_line
; /*# lights/line */
660 int lights_this_line
; /*# lights on cur line */
661 int curr_idx
; /*Current disk light idx */
662 struct scout_disk
*sc_disk
; /*Ptr to disk record array */
663 int lines_for_server
; /*Num lines in server record */
664 int curr_line
; /*Current line being filled */
665 int curr_x
; /*Current x value for light */
666 struct gator_lightobj
*disk_lightdata
; /*Disk light data field */
667 struct gwin_strparams
*disk_strparams
; /*String params for disk light */
670 fprintf(scout_debugfd
, "[%s] Called\n", rn
);
671 fflush(scout_debugfd
);
675 * If we haven't yet computed the column for the leftmost disk light,
678 if (scout_DiskLightLeftCol
== 0) {
680 int num_cols
= sizeof(scout_col_width
) / sizeof(*scout_col_width
);
681 scout_DiskLightLeftCol
= 0;
682 for (i
= 0; i
< (num_cols
- 1); i
++) {
683 scout_DiskLightLeftCol
+= scout_col_width
[i
] + 1;
688 * Calculate how many disk light objects can fit in one line.
691 (scout_frameDims
.maxx
-
692 scout_DiskLightLeftCol
) / (scout_col_width
[COL_DISK
] + 1);
694 fprintf(scout_debugfd
, "[%s] %d lights per line\n", rn
,
696 fflush(scout_debugfd
);
700 * Sweep through the used disk light list, computing the location
703 lights_this_line
= 0;
704 curr_idx
= a_srvline
->used_head
;
705 lines_for_server
= 1;
706 curr_line
= a_srvline
->base_line
;
707 curr_x
= scout_DiskLightLeftCol
;
709 while (curr_idx
!= SCOUT_NIL
) {
711 * Bump the number of lines for the server if we've already
712 * filled up the current line.
714 if (lights_this_line
>= lights_per_line
) {
715 lights_this_line
= 0;
718 curr_x
= scout_DiskLightLeftCol
;
721 /*Current line filled up */
723 * Set the current disk light's location.
725 sc_disk
= a_srvline
->disks
;
726 sc_disk
[curr_idx
].disk_lp
->o_x
= curr_x
;
727 sc_disk
[curr_idx
].disk_lp
->o_y
= curr_line
;
729 (struct gator_lightobj
*)(sc_disk
[curr_idx
].disk_lp
->o_data
);
730 disk_strparams
= (struct gwin_strparams
*)(disk_lightdata
->llrock
);
731 disk_strparams
->x
= curr_x
;
732 disk_strparams
->y
= curr_line
;
734 fprintf(scout_debugfd
,
735 "[%s] Disk light at index %d located at [%d, %d]\n", rn
,
736 curr_idx
, curr_x
, curr_line
);
737 fflush(scout_debugfd
);
741 * Record the inclusion of the light and move on to the next
745 curr_x
+= scout_col_width
[COL_DISK
] + 1;
746 curr_idx
= sc_disk
[curr_idx
].next
;
748 } /*Update each used disk light */
751 * Remember to record the (possibly new) number of lines in the
752 * server record before returning the value of that field.
754 if (a_srvline
->num_lines
!= lines_for_server
) {
756 fprintf(scout_debugfd
,
757 "[%s] Server previously had %d screen lines; now changed\n",
758 rn
, a_srvline
->num_lines
);
759 fflush(scout_debugfd
);
761 a_srvline
->num_lines
= lines_for_server
;
765 fprintf(scout_debugfd
, "[%s] Server has %d screen lines\n", rn
,
766 a_srvline
->num_lines
);
767 fflush(scout_debugfd
);
769 return (a_srvline
->num_lines
);
771 } /*scout_RecomputeLightLocs */
773 /*------------------------------------------------------------------------
777 * Given a single-letter disk name and a pointer to the current server
778 * record, look for a used disk record with that name within the server.
779 * If we can't find one, we create and incorporate one, and return that
780 * fact to our caller.
783 * char a_diskname : Single-char disk name.
784 * struct mini_line *a_srvline : Ptr to server descriptor.
785 * int *a_record_added : Was a new record added?
788 * Index of matching used disk record,
789 * SCOUT_NIL otherwise.
791 * Return via parameter:
792 * a_record_added set to 1 iff record was added to the used disk list.
795 * Used disk records are kept in alphabetical order by the single-char
796 * disk name. Should a matching used disk record not be found, one is
797 * pulled from the free pool.
800 * An entry may be pulled off the free list and inserted into the
801 * used list. This entry is placed in the update list for the
802 * current gtx frame (at least not by this routine).
803 *------------------------------------------------------------------------*/
806 scout_FindUsedDisk(char *a_diskname
, struct mini_line
*a_srvline
, int *a_record_added
)
807 { /*scout_FindUsedDisk */
809 static char rn
[] = "scout_FindUsedDisk"; /*Routine name */
810 int curr_idx
; /*Disk record index */
811 int append_idx
; /*Index to append after */
812 int new_idx
; /*Index of new used record */
813 struct scout_disk
*sc_disk
; /*Ptr to disk record */
814 int code
; /*Function return value */
817 fprintf(scout_debugfd
, "[%s] Called\n", rn
);
818 fflush(scout_debugfd
);
822 * Sweep through the used disk records, looking for a match.
824 curr_idx
= a_srvline
->used_head
;
825 append_idx
= SCOUT_NIL
;
826 sc_disk
= a_srvline
->disks
;
828 fprintf(scout_debugfd
,
829 "[%s] Scanning existing used disk entries for disk '%s'\n",
831 fflush(scout_debugfd
);
833 while (curr_idx
!= SCOUT_NIL
) {
835 fprintf(scout_debugfd
, "[%s] Disk %d is named '%s'\n", rn
,
836 curr_idx
, sc_disk
[curr_idx
].name
);
837 fflush(scout_debugfd
);
839 if (strcmp(sc_disk
[curr_idx
].name
, a_diskname
) == 0) {
841 * We found it! Bug out.
844 fprintf(scout_debugfd
, "[%s] Match found\n", rn
);
845 fflush(scout_debugfd
);
851 * If we are alphabetically past the given disk name, we
852 * know that we won't find it in the used disk list; we
853 * also have the append index set correctly.
855 if (strcmp(a_diskname
, sc_disk
[curr_idx
].name
) < 0) {
857 fprintf(scout_debugfd
, "[%s] Disk '%s' can't be here\n", rn
,
859 fflush(scout_debugfd
);
865 * There's still hope we'll find it. Move on to the next used
866 * disk record, keeping this index as the best candidate so far
867 * for appending a missing entry.
869 append_idx
= curr_idx
;
870 curr_idx
= sc_disk
[curr_idx
].next
;
871 } /*Look for match */
874 * We didn't find the record we wanted, which means we'll pull a
875 * record out of the free pool for it. If we didn't find a place
876 * to append it, we then insert it at the beginning of the queue.
878 if (a_srvline
->free_head
== SCOUT_NIL
)
881 new_idx
= a_srvline
->free_head
;
883 fprintf(scout_debugfd
, "[%s] Choosing free index %d for new entry\n",
885 fflush(scout_debugfd
);
887 a_srvline
->free_head
= sc_disk
[new_idx
].next
;
888 if (a_srvline
->free_head
== SCOUT_NIL
)
889 a_srvline
->free_tail
= SCOUT_NIL
;
892 * Fill in the new record.
894 sc_disk
[new_idx
].active
= 0;
895 sc_disk
[new_idx
].name
= a_diskname
;
898 * Insert the new record where it belongs on the used disk list.
900 if (append_idx
== SCOUT_NIL
) {
902 * It belongs at the beginning of the list.
905 fprintf(scout_debugfd
, "[%s] Inserted at used disk head\n", rn
);
906 fflush(scout_debugfd
);
908 sc_disk
[new_idx
].next
= a_srvline
->used_head
;
909 sc_disk
[new_idx
].prev
= SCOUT_NIL
;
910 a_srvline
->used_head
= new_idx
;
911 if (a_srvline
->used_tail
== SCOUT_NIL
)
912 a_srvline
->used_tail
= new_idx
;
915 fprintf(scout_debugfd
, "[%s] Entry appended after index %d\n", rn
,
917 fflush(scout_debugfd
);
919 sc_disk
[new_idx
].prev
= append_idx
;
920 sc_disk
[new_idx
].next
= sc_disk
[append_idx
].next
;
921 sc_disk
[append_idx
].next
= new_idx
;
922 if (sc_disk
[new_idx
].next
== SCOUT_NIL
)
923 a_srvline
->used_tail
= new_idx
;
925 sc_disk
[sc_disk
[new_idx
].next
].prev
= new_idx
;
929 * Add the new used disk light object to the display list for
933 fprintf(scout_debugfd
,
934 "[%s] Adding disk light at index %d to display list\n", rn
,
936 fflush(scout_debugfd
);
938 code
= gtxframe_AddToList(scout_frame
, sc_disk
[new_idx
].disk_lp
);
941 fprintf(scout_debugfd
,
942 "[%s] Can't add to display list, code is %d\n", rn
, code
);
943 fflush(scout_debugfd
);
948 } /*scout_FindUsedDisk */
950 /*------------------------------------------------------------------------
951 * scout_RemoveInactiveDisk
954 * Given a server record and a used disk index, remove the disk
955 * record from the used list, put it on the free list, and remove
956 * it from the gtx frame update list.
959 * struct mini_line *a_srvline : Ptr to server descriptor.
960 * int a_used_idx : Index of used disk record.
966 * Formerly-used disk records are returned to the free pool.
969 * Free and used disk record lists are modified for this server.
970 * The disk record in question is pulled off the gtx update list
972 *------------------------------------------------------------------------*/
975 scout_RemoveInactiveDisk(struct mini_line
*a_srvline
, int a_used_idx
)
976 { /*scout_RemoveInactiveDisk */
978 static char rn
[] = "scout_RemoveInactiveDisk"; /*Routine name */
981 fprintf(scout_debugfd
, "[%s] Called\n", rn
);
982 fflush(scout_debugfd
);
985 /*code = gtxframe_RemoveFromList(scout_frame->window, lightobj); */
987 } /*scout_RemoveInactiveDisk */
989 /*------------------------------------------------------------------------
990 * mini_PrintDiskStats
993 * Given server indexing and light object information, a pointer
994 * to a set of statistics, and whether the probe that produced these
995 * stats succeeded or not, print out the stats in a nice way.
998 * struct mini_line *a_srvline : Ptr to server descriptor.
999 * struct ProbeViceStatistics *a_stats : Ptr to current stats.
1000 * int a_probeOK : Was the probe OK?
1001 * int a_width_changed : Has the frame width changed?
1002 * int a_fix_line_num : Is the line number wrong?
1003 * int a_delta_line_num : Change in line number.
1006 * 0 if something went wrong,
1007 * else the number of lines taken up by this server record.
1010 * Nothing interesting.
1014 *------------------------------------------------------------------------*/
1017 mini_PrintDiskStats(struct mini_line
*a_srvline
,
1018 struct ProbeViceStatistics
*a_stats
,
1019 int a_probeOK
, int a_width_changed
,
1020 int a_fix_line_num
, int a_delta_line_num
)
1021 { /*mini_PrintDiskStats */
1023 static char rn
[] = "mini_PrintDiskStats"; /*Routine name */
1024 char s
[128]; /*String buffer */
1025 struct onode
*curr_disklight
; /*Ptr to current disk light */
1026 struct onode
*srvname_light
; /*Ptr to server name light */
1027 ViceDisk
*curr_diskstat
; /*Ptr to current disk stat */
1028 int curr_disk
; /*Current disk stat number */
1029 int used_disk_idx
; /*Used disk index */
1030 int next_used_idx
; /*Ditto */
1031 int pastthreshold
; /*Was disk past threshold? */
1032 struct gator_lightobj
*diskdata
; /*Private light data */
1033 struct gwin_strparams
*disk_strparams
; /*String params for disk light */
1034 char *diskname
= 0; /*Name of disk */
1035 int found_idx
; /*Idx of matching disk */
1036 char *srv_name
; /*Server name */
1037 struct scout_disk
*sc_disk
; /*Ptr to scout disk desc */
1038 int fix_light_locs
; /*Recompute disk light locs? */
1041 fprintf(scout_debugfd
, "[%s] Called\n", rn
);
1042 fflush(scout_debugfd
);
1046 * Remember the current server's print name, don't recompute light
1049 srvname_light
= a_srvline
->srvName_lp
;
1050 srv_name
= ((struct gator_lightobj
*)(srvname_light
->o_data
))->label
;
1053 fprintf(scout_debugfd
, "[%s] Value of a_delta_line_num is %d\n", rn
,
1055 fflush(scout_debugfd
);
1059 * If the probe failed, we simply blank out all the used disk
1060 * objects. Note: a NON-ZERO value of a_probeOK implies failure.
1063 used_disk_idx
= a_srvline
->used_head
;
1064 while (used_disk_idx
!= SCOUT_NIL
) {
1066 * Point to the current used disk's light, blank out its
1067 * contents, and make sure highlighting is turned off. We
1068 * also take this opportunity to fix the line numbers if
1071 curr_disklight
= a_srvline
->disks
[used_disk_idx
].disk_lp
;
1072 diskdata
= (struct gator_lightobj
*)(curr_disklight
->o_data
);
1074 fprintf(scout_debugfd
,
1075 "[%s] Prev value of disk light %d: '%s'\n", rn
,
1076 used_disk_idx
, diskdata
->label
);
1077 fflush(scout_debugfd
);
1079 mini_justify(" ", /*Src buffer */
1080 diskdata
->label
, /*Dest buffer */
1081 scout_col_width
[COL_DISK
], /*Dest's width */
1082 SCOUT_RIGHT_JUSTIFY
, /*Right-justify */
1083 SCOUT_LEFT_TRUNC
, /*Left-truncate */
1084 SCOUT_ISNT_LDISK
); /*Not a labeled disk */
1085 gator_light_set(curr_disklight
, 0);
1086 if (a_fix_line_num
) {
1087 curr_disklight
->o_y
+= a_delta_line_num
;
1088 disk_strparams
= (struct gwin_strparams
*)(diskdata
->llrock
);
1089 disk_strparams
->y
+= a_delta_line_num
;
1093 * Advance to next used disk, if any.
1095 used_disk_idx
= a_srvline
->disks
[used_disk_idx
].next
;
1097 } /*Blank out disk name field */
1100 * If the frame width has changed, we have to recompute all disk
1101 * light locations. After that, the number of lines in the server
1102 * record will be accurate, and we return them.
1104 if (a_width_changed
)
1105 scout_RecomputeLightLocs(a_srvline
);
1107 return (a_srvline
->num_lines
);
1111 /*Probe failed for the server */
1113 * Probe was successful. Sweep through the statistics records,
1114 * and put up all values having to do with AFS partitions. First,
1115 * mark all used disk objects for this server as inactive and fix
1116 * their line numbers if needed.
1118 used_disk_idx
= a_srvline
->used_head
;
1119 while (used_disk_idx
!= SCOUT_NIL
) {
1121 fprintf(scout_debugfd
, "[%s] Marking used disk %d inactive\n", rn
,
1123 fflush(scout_debugfd
);
1125 sc_disk
= (a_srvline
->disks
) + used_disk_idx
;
1126 sc_disk
->active
= 0;
1127 used_disk_idx
= sc_disk
->next
;
1128 if (a_fix_line_num
) {
1129 sc_disk
->disk_lp
->o_y
+= a_delta_line_num
;
1130 diskdata
= (struct gator_lightobj
*)(sc_disk
->disk_lp
->o_data
);
1131 disk_strparams
= (struct gwin_strparams
*)(diskdata
->llrock
);
1132 disk_strparams
->y
+= a_delta_line_num
;
1134 } /*Mark used disks inactive */
1136 curr_diskstat
= (ViceDisk
*) a_stats
->Disk
;
1137 for (curr_disk
= 0; curr_disk
< VOLMAXPARTS
; curr_disk
++) {
1139 * An AFS partition name must be prefixed by `/vicep`.
1142 fprintf(scout_debugfd
, "[%s] Disk stats at %p for disk '%s'\n",
1143 rn
, curr_diskstat
, curr_diskstat
->Name
);
1144 fflush(scout_debugfd
);
1146 if (strncmp("/vice", curr_diskstat
->Name
, 5) == 0) {
1148 * Pull out the single-letter name (actually, abbreviation)
1149 * of the disk and look for such an entry in the used disks.
1151 diskname
= &curr_diskstat
->Name
[6];
1152 found_idx
= scout_FindUsedDisk(diskname
, /*1-char name */
1153 a_srvline
, /*Server record */
1154 &fix_light_locs
); /*Recompute? */
1155 if (found_idx
== SCOUT_NIL
) {
1157 "[%s] Can't display /vicep%s on server '%s'\n", rn
,
1158 diskname
, srv_name
);
1161 * Found (or created) record for this disk. Fill in the single-
1162 * letter name of the disk followed by the number of free blocks.
1163 * Turn the disk light on if the number of free blocks exceeds
1164 * the threshold the user set, either % used or min free blocks.
1166 sprintf(s
, "%s:%d", diskname
, curr_diskstat
->BlocksAvailable
);
1167 if (scout_attn_disk_mode
== SCOUT_DISKM_PCUSED
) {
1169 (curr_diskstat
->TotalBlocks
-
1170 curr_diskstat
->BlocksAvailable
) /
1171 (float)(curr_diskstat
->TotalBlocks
) >
1172 scout_attn_disk_pcused
)
1178 (curr_diskstat
->BlocksAvailable
<
1179 scout_attn_disk_minfree
) ? 1 : 0;
1180 sc_disk
= (a_srvline
->disks
) + found_idx
;
1181 sc_disk
->active
= 1;
1183 (struct gator_lightobj
*)(sc_disk
->disk_lp
->o_data
);
1185 fprintf(scout_debugfd
,
1186 "[%s] Justifying %s for disk idx %d (prev value: '%s')\n",
1187 rn
, s
, found_idx
, diskdata
->label
);
1188 fflush(scout_debugfd
);
1190 mini_justify(s
, /*Src buffer */
1191 diskdata
->label
, /*Dest buffer */
1192 scout_col_width
[COL_DISK
], /*Dest's width */
1193 SCOUT_LEFT_JUSTIFY
, /*Left-justify */
1194 SCOUT_LEFT_TRUNC
, /*Left-truncate */
1195 SCOUT_IS_LDISK
); /*Labeled disk */
1197 gator_light_set(sc_disk
->disk_lp
, pastthreshold
);
1199 } /*Found disk record */
1202 /*Found AFS disk name */
1204 * Advance to the next disk statistics record.
1207 } /*For each statistics record */
1210 * We've now pulled out all the disk statistics from the probe.
1211 * See if any used disks that were there from the last time are
1212 * now gone. If so, we remove them.
1215 fprintf(scout_debugfd
,
1216 "[%s] Scanning used disk records for inactive entries\n", rn
);
1217 fflush(scout_debugfd
);
1219 used_disk_idx
= a_srvline
->used_head
;
1220 while (used_disk_idx
!= SCOUT_NIL
) {
1222 fprintf(scout_debugfd
, "[%s] Examining entry at index %d\n", rn
,
1224 fflush(scout_debugfd
);
1226 sc_disk
= (a_srvline
->disks
) + used_disk_idx
;
1227 next_used_idx
= sc_disk
->next
;
1228 if (!(sc_disk
->active
)) {
1229 scout_RemoveInactiveDisk(a_srvline
, /*Server record */
1230 used_disk_idx
); /*Disk index to nuke */
1233 used_disk_idx
= next_used_idx
;
1235 } /*Remove inactive used disks */
1238 * If we've had to add or remove disks to/from the used list,
1239 * or if the frame width has changed, we recompute the light
1240 * locations before returning.
1242 if (fix_light_locs
|| a_width_changed
)
1243 scout_RecomputeLightLocs(a_srvline
);
1246 * Return the (possibly new) size of the current server record.
1248 return (a_srvline
->num_lines
);
1250 } /*mini_PrintDiskStats */
1252 /*------------------------------------------------------------------------
1256 * Handler routine passed to the fsprobe module. This handler is
1257 * called immediately after a poll of all the FileServers has taken
1258 * place. Its job is to write out selected data to the scout
1269 * All it needs to know is exported by the fsprobe module, namely
1270 * the data structure where the probe results are stored.
1273 * Recomputes disk light locations in response to reshaping the
1274 * scout window or from adding/deleting disk lights to/from
1275 * individual servers.
1276 *------------------------------------------------------------------------*/
1282 static char rn
[] = "FS_Handler"; /*Routine name */
1283 int code
; /*Return code */
1284 struct ProbeViceStatistics
*curr_stats
; /*Ptr to current stats */
1285 int *curr_probeOK
; /*Ptr to current probeOK field */
1286 int curr_srvidx
; /*Current server index */
1287 char s
[128]; /*String buffer */
1288 static char sblank
[] = " "; /*Blank string buffer */
1289 char *sp
; /*Ptr to string buffer */
1290 struct mini_line
*curr_line
; /*Current mini-line */
1291 int curr_line_num
; /*Current line number */
1292 struct gator_lightobj
*lightdata
; /*Private light data */
1293 int setting
; /*Light setting (on or off) */
1294 int old_width
; /*Keep the old width value */
1295 int width_changed
; /*Has the frame width changed? */
1296 int fix_line_num
; /*Line number needs fixing */
1297 int delta_line_num
; /*Change in line number */
1300 * See if the size of the scout frame has changed since the last
1303 old_width
= scout_frameDims
.maxx
;
1305 fprintf(scout_debugfd
, "[%s] Calling wop_getdimensions\n", rn
);
1306 fflush(scout_debugfd
);
1308 WOP_GETDIMENSIONS(scout_frame
->window
, &scout_frameDims
);
1309 width_changed
= (old_width
== scout_frameDims
.maxx
) ? 0 : 1;
1311 fprintf(scout_debugfd
,
1312 "[%s] Frame dimensions are %d rows, %d columns\n", rn
,
1313 scout_frameDims
.maxy
, scout_frameDims
.maxx
);
1315 fprintf(scout_debugfd
, "[%s] Width has changed from %d columns\n",
1317 fflush(scout_debugfd
);
1321 * Print out the selected fields for each server. We actually change
1322 * the light's label to the new data.
1324 curr_line
= scout_screen
.line
;
1325 curr_stats
= fsprobe_Results
.stats
;
1326 curr_probeOK
= fsprobe_Results
.probeOK
;
1327 curr_line_num
= curr_line
->base_line
;
1329 for (curr_srvidx
= 0; curr_srvidx
< scout_screen
.numServers
;
1332 * If the current server record is set up on the wrong line, fix
1333 * the non-disk light objects directly, and remember to fix the
1334 * disk light objects later on.
1336 if (curr_line
->base_line
!= curr_line_num
) {
1338 delta_line_num
= curr_line_num
- curr_line
->base_line
;
1339 curr_line
->base_line
= curr_line_num
;
1340 scout_SetNonDiskLightLine(curr_line
, curr_line_num
);
1347 (struct gator_lightobj
*)(curr_line
->currConns_lp
->o_data
);
1348 if (*curr_probeOK
== 0) {
1350 sprintf(sp
, "%d", curr_stats
->CurrentConnections
);
1353 mini_justify(sp
, /*Src buffer */
1354 lightdata
->label
, /*Dest buffer */
1355 scout_col_width
[COL_CONN
], /*Dest's width */
1356 SCOUT_RIGHT_JUSTIFY
, /*Right-justify */
1357 SCOUT_LEFT_TRUNC
, /*Left-truncate */
1358 SCOUT_ISNT_LDISK
); /*Not a labeled disk */
1359 if (scout_attn_conn
!= SCOUT_ATTN_NOTUSED
1360 && curr_stats
->CurrentConnections
>= scout_attn_conn
)
1364 gator_light_set(curr_line
->currConns_lp
, setting
);
1366 lightdata
= (struct gator_lightobj
*)(curr_line
->fetches_lp
->o_data
);
1367 if (*curr_probeOK
== 0) {
1369 sprintf(sp
, "%u", curr_stats
->TotalFetchs
);
1372 mini_justify(sp
, /*Src buffer */
1373 lightdata
->label
, /*Dest buffer */
1374 scout_col_width
[COL_FETCH
], /*Dest's width */
1375 SCOUT_RIGHT_JUSTIFY
, /*Right-justify */
1376 SCOUT_LEFT_TRUNC
, /*Left-truncate */
1377 SCOUT_ISNT_LDISK
); /*Not a labeled disk */
1378 if (scout_attn_fetch
!= SCOUT_ATTN_NOTUSED
1379 && curr_stats
->TotalFetchs
>= scout_attn_fetch
)
1383 gator_light_set(curr_line
->fetches_lp
, setting
);
1385 lightdata
= (struct gator_lightobj
*)(curr_line
->stores_lp
->o_data
);
1386 if (*curr_probeOK
== 0) {
1388 sprintf(sp
, "%u", curr_stats
->TotalStores
);
1391 mini_justify(sp
, /*Src buffer */
1392 lightdata
->label
, /*Dest buffer */
1393 scout_col_width
[COL_STORE
], /*Dest's width */
1394 SCOUT_RIGHT_JUSTIFY
, /*Right-justify */
1395 SCOUT_LEFT_TRUNC
, /*Left-truncate */
1396 SCOUT_ISNT_LDISK
); /*Not a labeled disk */
1397 if (scout_attn_store
!= SCOUT_ATTN_NOTUSED
1398 && curr_stats
->TotalStores
>= scout_attn_store
)
1402 gator_light_set(curr_line
->stores_lp
, setting
);
1405 (struct gator_lightobj
*)(curr_line
->workstations_lp
->o_data
);
1406 if (*curr_probeOK
== 0) {
1408 sprintf(sp
, "%d", curr_stats
->WorkStations
);
1411 mini_justify(sp
, /*Src buffer */
1412 lightdata
->label
, /*Dest buffer */
1413 scout_col_width
[COL_WK
], /*Dest's width */
1414 SCOUT_RIGHT_JUSTIFY
, /*Right-justify */
1415 SCOUT_LEFT_TRUNC
, /*Left-truncate */
1416 SCOUT_ISNT_LDISK
); /*Not a labeled disk */
1417 if (scout_attn_workstations
!= SCOUT_ATTN_NOTUSED
1418 && curr_stats
->WorkStations
>= scout_attn_workstations
)
1422 gator_light_set(curr_line
->workstations_lp
, setting
);
1425 * We turn the server light on if there was an error in the
1426 * current probe (e.g., if the curr_probeOK field is non-zero.
1427 * (Don't forget to fix the light's line if it needs it).
1429 setting
= (*curr_probeOK
) ? 1 : 0;
1430 gator_light_set(curr_line
->srvName_lp
, setting
);
1433 * Print out the disk statistics. The value returned is the
1434 * number of lines taken up by the server record (or 0 if
1435 * something went wrong).
1437 code
= mini_PrintDiskStats(curr_line
, /*Ptr to server line */
1438 curr_stats
, /*Fresh disk stats */
1439 *curr_probeOK
, /*Was probe OK? */
1440 width_changed
, /*Has the width changed? */
1441 fix_line_num
, /*Fix the line number? */
1442 delta_line_num
); /*Change in line number */
1444 fprintf(stderr
, "[%s] Error in printing out disk statistics\n",
1448 curr_line_num
+= code
;
1451 * Advance the current mini_line, stats source, and probe success
1458 } /*for each server probed */
1461 * Display the scout frame.
1463 sprintf(s
, "Probe %d results", fsprobe_Results
.probeNum
);
1464 gtxframe_DisplayString(scout_frame
, s
);
1465 WOP_DISPLAY(scout_gwin
);
1468 * Return the happy news.
1474 /*------------------------------------------------------------------------
1478 * Initialize each line in the mini_screen.
1481 * struct sockaddr_in *a_skt : Ptr to server socket info.
1482 * int a_lineNum; : Line number being created.
1483 * struct mini_line *a_line : Ptr to mini_line to set up.
1484 * char *a_srvname : Printable server name.
1488 * Error value otherwise.
1491 * Nothing interesting.
1495 *------------------------------------------------------------------------*/
1498 init_mini_line(struct sockaddr_in
*a_skt
, int a_lineNum
,
1499 struct mini_line
*a_line
, char *a_srvname
)
1500 { /*init_mini_line */
1502 static char rn
[] = "init_mini_line"; /*Routine name */
1503 int curr_x
; /*Current X position */
1504 int curr_y
; /*Current Y position */
1505 char s
[128]; /*Scratch buffer */
1506 int code
; /*Return code */
1507 struct gator_lightobj
*lightdata
; /*Private light data */
1510 fprintf(scout_debugfd
, "[%s] Called for base line %d\n", rn
,
1512 fflush(scout_debugfd
);
1516 * Fill in the top fields (except the disk fields, which will be
1517 * done elsewhere), then create the light onodes.
1519 memcpy((char *)&(a_line
->skt
), (char *)a_skt
, sizeof(struct sockaddr_in
));
1520 a_line
->numDisks
= 0;
1521 a_line
->base_line
= a_lineNum
+ scout_screen
.base_line_num
;
1522 a_line
->num_lines
= 1;
1525 curr_y
= a_line
->base_line
;
1526 if ((a_line
->currConns_lp
=
1527 mini_initLightObject("Conns", curr_x
, curr_y
, scout_col_width
[COL_CONN
],
1530 fprintf(stderr
, "[%s:%s] Can't create currConns light object\n", pn
,
1534 curr_x
+= scout_col_width
[COL_CONN
] + 1;
1536 if ((a_line
->fetches_lp
=
1537 mini_initLightObject("Fetches", curr_x
, curr_y
, scout_col_width
[COL_FETCH
],
1538 scout_frame
->window
))
1540 fprintf(stderr
, "[%s:%s] Can't create fetches light object\n", pn
,
1544 curr_x
+= scout_col_width
[COL_FETCH
] + 1;
1546 if ((a_line
->stores_lp
=
1547 mini_initLightObject("Stores", curr_x
, curr_y
, scout_col_width
[COL_STORE
],
1548 scout_frame
->window
))
1550 fprintf(stderr
, "[%s:%s] Can't create stores light object\n", pn
, rn
);
1553 curr_x
+= scout_col_width
[COL_STORE
] + 1;
1555 if ((a_line
->workstations_lp
=
1556 mini_initLightObject("WrkStn", curr_x
, curr_y
, scout_col_width
[COL_WK
],
1557 scout_frame
->window
))
1559 fprintf(stderr
, "[%s:%s] Can't create workstations light object\n",
1563 curr_x
+= scout_col_width
[COL_WK
] + 1;
1565 if ((a_line
->srvName_lp
=
1566 mini_initLightObject(a_srvname
, curr_x
, curr_y
,
1567 scout_col_width
[COL_SRVNAME
], scout_frame
->window
))
1569 fprintf(stderr
, "[%s:%s] Can't create server name light object\n", pn
,
1573 sprintf(s
, "%s", a_srvname
);
1574 lightdata
= (struct gator_lightobj
*)(a_line
->srvName_lp
->o_data
);
1575 code
= mini_justify(s
, /*Src buffer */
1576 lightdata
->label
, /*Dest buffer */
1577 scout_col_width
[COL_SRVNAME
], /*Dest's width */
1578 SCOUT_CENTER
, /*Centered */
1579 SCOUT_RIGHT_TRUNC
, /*Right-truncate */
1580 SCOUT_ISNT_LDISK
); /*Not a labeled disk */
1583 "[%s] Can't center server name inside of light object\n", rn
);
1587 if (scout_initDiskLightObjects(a_line
, scout_frame
->window
)) {
1588 fprintf(stderr
, "[%s:%s] Can't create disk light objects\n", pn
, rn
);
1593 * Finally, return the happy news.
1597 } /*init_mini_line */
1599 /*------------------------------------------------------------------------
1603 * Workhorse routine that starts up the FileServer probe.
1606 * int a_numservers : Length of above list.
1607 * struct cmd_item *a_srvname : List of FileServer machines to
1609 * int a_pkg : Window package to use.
1613 * Error value otherwise.
1616 * Nothing interesting.
1620 *------------------------------------------------------------------------*/
1623 execute_scout(int a_numservers
, struct cmd_item
*a_srvname
, int a_pkg
)
1624 { /*execute_scout */
1626 static char rn
[] = "execute_scout"; /*Routine name */
1627 static char fullsrvname
[128]; /*Full server name */
1628 int code
; /*Return code */
1629 struct sockaddr_in
*FSSktArray
; /*Server socket array */
1630 int sktbytes
; /*Num bytes in above */
1631 struct sockaddr_in
*curr_skt
; /*Ptr to current socket */
1632 struct cmd_item
*curr_item
; /*Ptr to current cmd item */
1633 struct hostent
*he
; /*Host entry */
1634 struct mini_line
*mini_lines
; /*Ptr to all mini-lines */
1635 struct mini_line
*curr_line
; /*Ptr to current line */
1636 int i
; /*Generic loop variable */
1637 int mini_line_bytes
; /*Num bytes in mini_lines */
1638 struct timeval tv
; /*Time structure */
1639 int linenum
; /*Current mini-line number */
1641 PROCESS pid
; /*Main LWP process ID */
1642 PROCESS gxlistener_ID
; /*Input Server LWP process ID */
1644 struct gator_lightobj
*lightdata
; /*Private light data */
1647 fprintf(scout_debugfd
, "[%s] Called\n", rn
);
1648 fflush(scout_debugfd
);
1652 * We have to initialize LWP support before we start up any of
1656 code
= LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY
, &pid
);
1658 fprintf(stderr
, "[%s:%s] Can't initialize LWP\n", pn
, rn
);
1659 scout_CleanExit(code
);
1664 * Initialize the gtx package.
1667 fprintf(stderr
, "[%s:%s] Starting up gtx package\n", pn
, rn
);
1669 scout_gwin
= gtx_Init(0, /*Don't start up InputServer yet */
1670 -1); /*Type of window package */
1671 if (scout_gwin
== NULL
) {
1672 fprintf(stderr
, "[%s:%s] Call to gtx_Init() failed!\n", pn
, rn
);
1677 * Remember we've set up gtx so we can exit cleanly from now on.
1679 scout_gtx_initialized
= 1;
1682 * Create the frame everything will go into, set it up as our only
1683 * frame for this window.
1685 scout_frame
= gtxframe_Create();
1686 if (scout_frame
== (struct gtx_frame
*)0) {
1687 fprintf(stderr
, "[%s:%s] Call to gtxframe_Create() failed!\n", pn
,
1691 gtxframe_SetFrame(scout_gwin
, scout_frame
);
1692 WOP_GETDIMENSIONS(scout_frame
->window
, &scout_frameDims
);
1695 * Allocate an array of sockets to describe each FileServer we'll be
1698 sktbytes
= a_numservers
* sizeof(struct sockaddr_in
);
1699 FSSktArray
= calloc(1, sktbytes
);
1700 if (FSSktArray
== (struct sockaddr_in
*)0) {
1702 "[%s] Can't malloc() %d sockaddrs (%d bytes) for the given servers\n",
1703 rn
, a_numservers
, sktbytes
);
1704 scout_CleanExit(-1);
1708 * Sweep through the server names provided, filling in the socket
1709 * info for each. Take into account the fact that we may have a
1710 * base name associated for each.
1712 curr_item
= a_srvname
;
1713 curr_skt
= FSSktArray
;
1715 if (*scout_basename
== '\0')
1716 sprintf(fullsrvname
, "%s", curr_item
->data
);
1718 sprintf(fullsrvname
, "%s.%s", curr_item
->data
, scout_basename
);
1719 he
= hostutil_GetHostByName(fullsrvname
);
1721 fprintf(stderr
, "[%s] Can't get host info for '%s'\n", rn
,
1725 memcpy(&(curr_skt
->sin_addr
.s_addr
), he
->h_addr
, 4);
1726 curr_skt
->sin_family
= AF_INET
;
1727 curr_skt
->sin_port
= htons(7000); /* FileServer port */
1730 * Bump our pointers.
1732 curr_item
= curr_item
->next
;
1735 } /*Build socket entry for each server */
1738 * Create the set of mini-lines, one per server.
1740 mini_line_bytes
= a_numservers
* sizeof(struct mini_line
);
1741 mini_lines
= calloc(1, mini_line_bytes
);
1742 if (mini_lines
== (struct mini_line
*)0) {
1743 fprintf(stderr
, "[%s] Can't malloc() %d bytes for %d screen lines\n",
1744 rn
, mini_line_bytes
, a_numservers
);
1749 * Set up each line in the mini_lines, creating and initializing
1750 * its light objects.
1752 scout_screen
.base_line_num
= 4;
1753 curr_line
= mini_lines
;
1754 curr_skt
= FSSktArray
;
1756 curr_item
= a_srvname
;
1757 gtxframe_ClearList(scout_frame
);
1760 * Create the light objects that server as banner lines. Remember
1761 * to take into account the server basename, if any, and the name
1762 * of the host that scout if running on, if that's wanted.
1764 if (scout_showhostname
) {
1765 if (*scout_basename
== '\0')
1766 sprintf(scout_Banner
, "[%s] %s", scout_hostname
, "Scout");
1768 sprintf(scout_Banner
, "[%s] Scout for %s", scout_hostname
,
1771 if (*scout_basename
== '\0')
1772 sprintf(scout_Banner
, "%s", " Scout");
1774 sprintf(scout_Banner
, " Scout for %s", scout_basename
);
1776 scout_banner0_lp
= mini_initLightObject("Banner 0", /*Light name */
1777 0, /*X*/ 0, /*Y*/ scout_frameDims
.maxx
, /*Width */
1778 scout_gwin
); /*Window */
1779 if (scout_banner0_lp
!= NULL
) {
1780 lightdata
= (struct gator_lightobj
*)(scout_banner0_lp
->o_data
);
1781 mini_justify(scout_Banner
, lightdata
->label
, scout_frameDims
.maxx
,
1782 SCOUT_CENTER
, SCOUT_RIGHT_TRUNC
, SCOUT_ISNT_LDISK
);
1783 gator_light_set(scout_banner0_lp
, 1);
1784 gtxframe_AddToList(scout_frame
, scout_banner0_lp
);
1788 fprintf(scout_debugfd
, "[%s] Scout label is '%s', %" AFS_SIZET_FMT
" chars\n", rn
,
1789 lightdata
->label
, strlen(lightdata
->label
));
1792 scout_banner1_lp
= mini_initLightObject("Banner 1", /*Light name */
1793 0, /*X*/ 2, /*Y*/ scout_frameDims
.maxx
, /*Width */
1794 scout_gwin
); /*Window */
1795 if (scout_banner1_lp
!= NULL
) {
1796 char attn_label
[256];
1797 if (scout_attn_disk_mode
== SCOUT_DISKM_PCUSED
) {
1798 snprintf(attn_label
, sizeof(attn_label
), "%s: > %s%% used",
1799 scout_label
[5], scout_attn_disk_pcusedstr
);
1801 snprintf(attn_label
, sizeof(attn_label
), "%s: < %d blocks free",
1802 scout_label
[5], scout_attn_disk_minfree
);
1804 snprintf(scout_Banner
, sizeof(scout_Banner
),
1805 "%*s %*s %*s %*s %*s %s",
1806 scout_col_width
[0], scout_label
[0],
1807 scout_col_width
[1], scout_label
[1],
1808 scout_col_width
[2], scout_label
[2],
1809 scout_col_width
[3], scout_label
[3],
1810 scout_col_width
[4], scout_label
[4],
1813 lightdata
= (struct gator_lightobj
*)(scout_banner1_lp
->o_data
);
1814 mini_justify(scout_Banner
, lightdata
->label
, scout_frameDims
.maxx
,
1815 SCOUT_LEFT_JUSTIFY
, SCOUT_RIGHT_TRUNC
,
1818 gtxframe_AddToList(scout_frame
, scout_banner1_lp
);
1821 scout_banner2_lp
= mini_initLightObject("Banner 2", /*Light name */
1822 0, /*X*/ 3, /*Y*/ scout_frameDims
.maxx
, /*Width */
1823 scout_gwin
); /*Window */
1824 if (scout_banner2_lp
!= NULL
) {
1825 snprintf(scout_Banner
, sizeof(scout_Banner
),
1826 "%*s %*s %*s %*s %*s %s",
1827 scout_col_width
[0], scout_underline
[0],
1828 scout_col_width
[1], scout_underline
[1],
1829 scout_col_width
[2], scout_underline
[2],
1830 scout_col_width
[3], scout_underline
[3],
1831 scout_col_width
[4], scout_underline
[4],
1832 scout_underline
[5]);
1834 lightdata
= (struct gator_lightobj
*)(scout_banner2_lp
->o_data
);
1835 mini_justify(scout_Banner
, lightdata
->label
,
1836 scout_frameDims
.maxx
, SCOUT_LEFT_JUSTIFY
,
1837 SCOUT_RIGHT_TRUNC
, SCOUT_ISNT_LDISK
);
1838 gtxframe_AddToList(scout_frame
, scout_banner2_lp
);
1841 for (i
= 0; i
< a_numservers
; i
++) {
1842 code
= init_mini_line(curr_skt
, linenum
, curr_line
, curr_item
->data
);
1844 fprintf(stderr
, "[%s] Can't initialize line for server %d\n", rn
,
1851 curr_item
= curr_item
->next
;
1855 * Now that all lines have been set up, we feed in the light items
1856 * created. Note: the disk lights are entered at a later time,
1857 * as they enter the used disk list for each server.
1859 curr_line
= mini_lines
;
1860 for (i
= 0; i
< a_numservers
; i
++) {
1861 code
= gtxframe_AddToList(scout_frame
, curr_line
->currConns_lp
);
1864 "[%s] Can't add client connections light to display list\n",
1869 code
= gtxframe_AddToList(scout_frame
, curr_line
->fetches_lp
);
1872 "[%s] Can't add fetches light to frame display list\n",
1877 code
= gtxframe_AddToList(scout_frame
, curr_line
->stores_lp
);
1880 "[%s] Can't add stores light to frame display list\n",
1885 code
= gtxframe_AddToList(scout_frame
, curr_line
->workstations_lp
);
1888 "[%s] Can't add workstation light to display list\n", rn
);
1892 code
= gtxframe_AddToList(scout_frame
, curr_line
->srvName_lp
);
1895 "[%s] Can't add server name light to display list\n", rn
);
1900 * Move down to the next server record.
1904 } /*Add lights in server records to display list */
1908 * Set up the minimal keymap.
1910 code
= keymap_BindToString(scout_frame
->keymap
, /*Ptr to keymap */
1911 "e", /*Key to bind */
1912 ExitCmd
, /*Cmd to execute */
1914 NULL
); /*Ptr to rock */
1916 fprintf(stderr
, "[%s] Can't bind key `e', code is %d\n", rn
, code
);
1922 * Finish setting up the overall mini_screen structure.
1924 scout_screen
.numServers
= a_numservers
;
1925 scout_screen
.line
= mini_lines
;
1926 WOP_GETDIMENSIONS(scout_frame
->window
, &scout_frameDims
);
1929 * Start up the fsprobe package, which will gather FileServer
1930 * statistics for us on a regular basis.
1932 gtxframe_DisplayString(scout_frame
,
1933 "Establishing File Server connection(s)...");
1934 code
= fsprobe_Init(a_numservers
, /*Num FileServers to probe */
1935 FSSktArray
, /*FileServer socket array */
1936 scout_probefreq
, /*Probe frequency */
1937 FS_Handler
, /*Handler routine */
1938 0); /*Turn debugging output off */
1940 scout_debug
); /*Turn debugging output off */
1943 fprintf(stderr
, "[%s] Error returned by fsprobe_Init: %d\n", rn
,
1950 * Start up the input server LWP for our window.
1953 code
= LWP_CreateProcess(gtx_InputServer
, /*Fcn to start up */
1954 8192, /*Stack size in bytes */
1955 LWP_NORMAL_PRIORITY
, /*Priority */
1956 (void *)scout_gwin
, /*Params: Ptr to window */
1957 "gx-listener", /*Name to use */
1958 &gxlistener_ID
); /*Returned LWP process ID */
1961 code
= (int)(intptr_t)gtx_InputServer(scout_gwin
);
1964 "[%s] Error exit from gtx_InputServer(), error is %d\n", rn
,
1966 scout_CleanExit(code
);
1970 * We fall into a loop, sleeping forever.
1973 tv
.tv_sec
= 60 * 60; /*Sleep for an hour at a time */
1975 select(0, /*Num fds */
1976 0, /*Descriptors ready for reading */
1977 0, /*Descriptors ready for writing */
1978 0, /*Descriptors with exceptional conditions */
1979 &tv
); /*Timeout structure */
1980 } /*Sleep forever */
1984 * How did we get here? Oh, well, clean up our windows and
1985 * return sweetness and light anyway.
1987 WOP_CLEANUP(&scout_gwin
);
1991 } /*execute_scout */
1993 /*------------------------------------------------------------------------
1997 * Given a pointer to the list of servers we'll be polling,
1998 * compute the length of the list.
2001 * struct cmd_item *a_firstItem : Ptr to first item in list.
2004 * Length of the above list.
2007 * Nothing interesting.
2011 *------------------------------------------------------------------------*/
2013 static int countServers(struct cmd_item
*a_firstItem
)
2016 int list_len
; /*List length */
2017 struct cmd_item
*curr_item
; /*Ptr to current item */
2020 curr_item
= a_firstItem
;
2027 curr_item
= curr_item
->next
;
2037 /*------------------------------------------------------------------------
2038 * scout_AdoptThresholds
2041 * Parse and adopt one or more threshold values, as read off the
2045 * struct cmd_item *a_thresh_item : Ptr to item on command-line
2049 * Nothing (but may exit the entire program on error!)
2052 * Valid keywords are:
2053 * conn, disk, fetch, store, ws
2054 * The disk value, if it has a % sign, signifies that attention
2055 * will be triggered when the disk is more than that percentage
2056 * full; otherwise, it will specify the minimum number of free
2061 *------------------------------------------------------------------------*/
2063 static void scout_AdoptThresholds(struct cmd_item
*a_thresh_item
)
2064 { /*scout_AdoptThresholds */
2066 static char rn
[] = "scout_AdoptThresholds"; /*Routine name */
2067 struct cmd_item
*curr_item
; /*Current item */
2068 char *curr_name
; /*Current name half of pair */
2069 char *curr_value
; /*Current value half of pair */
2070 int diskval_len
; /*Length of disk attn value */
2072 curr_item
= a_thresh_item
;
2075 * If there isn't a corresponding value for the current
2076 * attention field, bitch & die.
2078 if (curr_item
->next
== (struct cmd_item
*)0) {
2079 printf("[%s] No threshold value given for '%s'\n", rn
,
2081 scout_CleanExit(-1);
2084 curr_name
= curr_item
->data
;
2085 curr_value
= curr_item
->next
->data
;
2087 if (strcmp(curr_name
, "conn") == 0) {
2089 fprintf(scout_debugfd
,
2090 "[%s] Setting conn attn value to %d (default %d)\n",
2091 rn
, atoi(curr_value
), scout_attn_conn
);
2092 fflush(scout_debugfd
);
2094 scout_attn_conn
= atoi(curr_value
);
2095 } else if (strcmp(curr_name
, "disk") == 0) {
2097 * If there's a '%' as the last character in the value,
2098 * we use percentage mode.
2100 diskval_len
= strlen(curr_value
);
2101 if (curr_value
[diskval_len
- 1] == '%') {
2102 curr_value
[diskval_len
- 1] = '\0';
2104 fprintf(scout_debugfd
,
2105 "[%s] New disk attn value: 0.%s used (default %f)\n",
2106 rn
, curr_value
, scout_attn_disk_pcused
);
2107 fflush(scout_debugfd
);
2109 sprintf(scout_attn_disk_pcusedstr
, "%s", curr_value
);
2110 scout_attn_disk_pcused
=
2111 ((float)(atoi(curr_value
))) / ((float)(100));
2112 } /*Percentage mode */
2115 fprintf(scout_debugfd
,
2116 "[%s] New disk attn value: %s min free (default %f)\n",
2117 rn
, curr_value
, scout_attn_disk_pcused
);
2118 fflush(scout_debugfd
);
2120 scout_attn_disk_mode
= SCOUT_DISKM_MINFREE
;
2121 scout_attn_disk_minfree
= atoi(curr_value
);
2122 } /*Min free blocks mode */
2123 } else if (strcmp(curr_name
, "fetch") == 0) {
2125 fprintf(scout_debugfd
,
2126 "[%s] Setting fetch attn value to %d (default %d)\n",
2127 rn
, atoi(curr_value
), scout_attn_fetch
);
2128 fflush(scout_debugfd
);
2130 scout_attn_fetch
= atoi(curr_value
);
2131 } else if (strcmp(curr_name
, "store") == 0) {
2133 fprintf(scout_debugfd
,
2134 "[%s] Setting store attn value to %d (default %d)\n",
2135 rn
, atoi(curr_value
), scout_attn_store
);
2136 fflush(scout_debugfd
);
2138 scout_attn_store
= atoi(curr_value
);
2139 } else if (strcmp(curr_name
, "ws") == 0) {
2141 fprintf(scout_debugfd
,
2142 "[%s] Setting workstation attn value to %d (default %d)\n",
2143 rn
, atoi(curr_value
), scout_attn_workstations
);
2144 fflush(scout_debugfd
);
2146 scout_attn_workstations
= atoi(curr_value
);
2148 printf("[%s] Unknown attention item: '%s'\n", rn
,
2150 scout_CleanExit(-1);
2154 * Advance past the just-processed pair.
2156 curr_item
= curr_item
->next
->next
;
2158 } /*Interpret each name-value pair */
2160 } /*scout_AdoptThresholds */
2163 * Setup the user specified column widths.
2165 * The column widths specifies the number of digits which
2166 * will be displayed without truncation. The column widths
2167 * are given in the same order in which they are displayed,
2168 * from left to right. Not all columns need to be specified
2169 * on the command line. The default column widths for those
2170 * columns not specified. Column widths can not be set smaller
2171 * than the heading underline.
2173 * @param[in] a_width_item command line width item list
2176 scout_SetColumnWidths(struct cmd_item
*a_width_item
)
2180 int num_cols
= sizeof(scout_col_width
) / sizeof(*scout_col_width
);
2182 for (i
= 0; a_width_item
&& i
< num_cols
; i
++) {
2183 width
= atoi(a_width_item
->data
);
2185 int min_width
= strlen(scout_underline
[i
]);
2187 width
= max(width
, min_width
);
2189 scout_col_width
[i
] = width
+ 1;
2191 a_width_item
= a_width_item
->next
;
2194 fprintf(stderr
, "Too many values given for -columnwidths\n");
2199 /*------------------------------------------------------------------------
2203 * Routine called when Scout is invoked, responsible for basic
2204 * initialization, command line parsing, and calling the
2205 * routine that does all the work.
2208 * as : Command syntax descriptor.
2209 * arock : Associated rock (not used here).
2212 * Zero (but may exit the entire program on error!)
2215 * Nothing interesting.
2218 * Initializes this program.
2219 *------------------------------------------------------------------------*/
2221 static int scoutInit(struct cmd_syndesc
*as
, void *arock
)
2224 static char rn
[] = "scoutInit"; /*Routine name */
2225 int code
; /*Return code */
2226 int wpkg_to_use
; /*Window package to use */
2227 int server_count
; /*Number of servers to watch */
2228 char *debug_filename
; /*Name of debugging output file */
2231 fprintf(scout_debugfd
, "[%s] Called\n", rn
);
2232 fflush(scout_debugfd
);
2235 if (as
->parms
[P_DEBUG
].items
!= 0) {
2237 debug_filename
= as
->parms
[P_DEBUG
].items
->data
;
2238 scout_debugfd
= fopen(debug_filename
, "w");
2239 if (scout_debugfd
== (FILE *) 0) {
2240 printf("[%s] Can't open debugging file '%s'!\n", rn
,
2242 scout_CleanExit(-1);
2244 fprintf(scout_debugfd
, "[%s] Writing to Scout debugging file '%s'\n",
2245 rn
, debug_filename
);
2248 wpkg_to_use
= atoi(as
->parms
[P_PACKAGE
].items
->data
);
2250 wpkg_to_use
= 2; /*Always use curses for now */
2252 fprintf(stderr
, "[%s:%s] Using graphics package %d: ", pn
, rn
,
2254 switch (wpkg_to_use
) {
2255 case GATOR_WIN_CURSES
:
2256 fprintf(stderr
, "curses\n");
2258 case GATOR_WIN_DUMB
:
2259 fprintf(stderr
, "dumb terminal\n");
2262 fprintf(stderr
, "X11\n");
2265 fprintf(stderr
, "Illegal graphics package: %d\n", wpkg_to_use
);
2266 scout_CleanExit(-1);
2267 } /*end switch (wpkg_to_use) */
2270 if (as
->parms
[P_FREQ
].items
!= 0)
2271 scout_probefreq
= atoi(as
->parms
[P_FREQ
].items
->data
);
2273 scout_probefreq
= 60;
2276 * See if we've been fed a base server name.
2278 if (as
->parms
[P_BASE
].items
!= 0)
2279 sprintf(scout_basename
, "%s", as
->parms
[P_BASE
].items
->data
);
2281 *scout_basename
= '\0';
2284 * Count the number of servers we've been asked to monitor.
2286 server_count
= countServers(as
->parms
[P_SERVER
].items
);
2289 * Create a line of blanks, a generally-useful thing.
2291 sprintf(scout_blankline
, "%255s", " ");
2294 * Pull in the name of the host we're executing on if we've been
2295 * asked to. If we can't get the name, we provide a default.
2297 if (as
->parms
[P_HOST
].items
!= 0) {
2298 scout_showhostname
= 1;
2299 *scout_hostname
= '\0';
2300 code
= gethostname(scout_hostname
, 128);
2302 sprintf(scout_hostname
, "%s", "*No Hostname*");
2306 * Pull in any and all attention/highlighting thresholds.
2308 if (as
->parms
[P_ATTENTION
].items
!= 0)
2309 scout_AdoptThresholds(as
->parms
[P_ATTENTION
].items
);
2311 if (as
->parms
[P_WIDTHS
].items
!= 0) {
2312 scout_SetColumnWidths(as
->parms
[P_WIDTHS
].items
);
2316 * Now, drive the sucker.
2318 code
= execute_scout(server_count
, /*Num servers */
2319 as
->parms
[P_SERVER
].items
, /*Ptr to srv names */
2320 wpkg_to_use
); /*Graphics pkg */
2322 fprintf(stderr
, "[%s] Error executing scout: %d\n", rn
, code
);
2323 scout_CleanExit(-1);
2327 * We initialized (and ran) correctly, so return the good news.
2333 #include "AFS_component_version_number.c"
2336 main(int argc
, char **argv
)
2339 afs_int32 code
; /*Return code */
2340 struct cmd_syndesc
*ts
; /*Ptr to cmd line syntax descriptor */
2342 #ifdef AFS_AIX32_ENV
2344 * The following signal action for AIX is necessary so that in case of a
2345 * crash (i.e. core is generated) we can include the user's data section
2346 * in the core dump. Unfortunately, by default, only a partial core is
2347 * generated which, in many cases, isn't too useful.
2349 struct sigaction nsa
;
2351 sigemptyset(&nsa
.sa_mask
);
2352 nsa
.sa_handler
= SIG_DFL
;
2353 nsa
.sa_flags
= SA_FULLDUMP
;
2354 sigaction(SIGSEGV
, &nsa
, NULL
);
2357 * Set up the commands we understand.
2359 ts
= cmd_CreateSyntax("initcmd", scoutInit
, NULL
, 0, "initialize the program");
2360 cmd_AddParm(ts
, "-server", CMD_LIST
, CMD_REQUIRED
,
2361 "FileServer name(s) to monitor");
2362 cmd_AddParm(ts
, "-basename", CMD_SINGLE
, CMD_OPTIONAL
,
2363 "base server name");
2365 cmd_AddParm(ts
, "-package", CMD_SINGLE
, CMD_REQUIRED
,
2366 "Graphics package to use");
2368 cmd_AddParm(ts
, "-frequency", CMD_SINGLE
, CMD_OPTIONAL
,
2369 "poll frequency, in seconds");
2370 cmd_AddParm(ts
, "-host", CMD_FLAG
, CMD_OPTIONAL
,
2371 "show name of host you're running on");
2372 cmd_AddParm(ts
, "-attention", CMD_LIST
, CMD_OPTIONAL
,
2373 "specify attention (highlighting) level");
2374 cmd_AddParm(ts
, "-debug", CMD_SINGLE
, CMD_OPTIONAL
,
2375 "turn debugging output on to the named file");
2376 cmd_AddParm(ts
, "-columnwidths", CMD_LIST
, CMD_OPTIONAL
,
2377 "specify column widths");
2380 * Parse command-line switches & execute the test, then get the heck
2383 code
= cmd_Dispatch(argc
, argv
);
2386 fprintf(stderr
, "[%s:%s] Call to cmd_Dispatch() failed; code is %d\n",
2393 return 0; /* not reachable */