1 /* ************************************************************************* *
2    xfsm - (C) Copyright 1993-1999 Robert Gasch (Robert_Gasch@peoplesoft.com)
3 	  http://www.peoplesoft.com/peoplepages/g/robert_gasch/src/
4 
5    Permission to use, copy, modify and distribute this software for any
6    purpose and without fee is hereby granted, provided that this copyright
7    notice appear in all copies as well as supporting documentation. All
8    work developed as a consequence of the use of this program should duly
9    acknowledge such use.
10 
11    No representations are made about the suitability of this software for
12    any purpose. This software is provided "as is" without express or implied
13    warranty.
14 
15    See the GNU General Public Licence for more information.
16  * ************************************************************************* */
17 
18 
19 
20 /* *************************************************************************
21    This program displays a list of bar graphs for the file systems of the
22    machine you are on. The following switches are supported:
23 
24 	+rv			reverse video (use to override xrdb entry)
25 	+synchronous		syncronous mode (use to override xrdb entry)
26 	-?			help
27 	-A			show available space in MB
28 	-a			absolute display mode
29 	-background <arg>	backgound color
30 	-b			black bars (disable gray fill)
31 	-bg <arg>		same as -background
32 	-bordercolor <arg>	border color
33 	-borderwidth <arg>	border width
34 	-d <arg1 ... argn>      ignore these file systems
35         -D <arg1 ... argn>      ignore file systems matching these patterns
36 	-detailgeometry <arg> 	Geometry of detail window. Only X and Y are
37 					honoured
38 	-display		display
39 	-e			extend warning to ring bell when at least
40 					one file system is above warning level
41 	-fg <arg>		same as -forground
42 	-font <arg>		font
43 	-foreground <arg>	forground color (also file system bar color)
44 	-geometry <arg>		geometry (will override extreme window sizes to
45 					apply reasonable settings)
46 	-help			help
47 	-i <arg>		interval at which stats are updated(default=60s)
48 	-iconic			iconic
49 	-it <arg1 ... argn>     ignore file systems of this type (*)
50 	-m			minimize window size
51 	-mb			draw menu borders
52 	-mnl			minimize window size so that the longest file
53 					system name fits
54 	-name <arg>		run xfsm under this name
55 	-ot <arg>               show only file systems of this type (*)
56 	-oi			override ignore
57 	-p			don't display percentages
58 	-pu			popup alarm flag
59 	-r			display space with respect to root
60 	-rootdf			show df % values when running in root mode
61 	-rs <arg>		specify the amount of space reserved for root
62 	-rv 			reverse video
63 	-s <arg1 ... argn>	show only these file systems
64 	-S <arg1 ... argn>	select only file systems matching these patterns
65 	-sb			show biggest file system size in lower right
66 	-sort			sort file systems according to name
67 	-synchronous		synchronous mode
68 	-title			title for main window
69 	-v			verbose
70 	-w <arg>		display warning when usage reaches <arg> %
71 	-wl0c			color for all entries below first warning level
72 	-wl1 <arg>		threshold for first warning level
73 	-wl1c <arg>		color for first warning level
74 	-wl2 <arg>		threshold for second warning level
75 	-wl2c <arg>		color for second warning level
76 	-wl3 <arg>		threshold for third warning level
77 	-wl3c <arg>		color for third warning level
78 	-xrm			set an entry in the resource database for this
79 					execution only
80 	help			help
81 
82 
83 
84    Version History:
85 	24-03-93: 1.00
86 	29-03-93: 1.01
87 			Added support for gray filling of graphs
88 	10-04-93: 1.10
89 			Added resize support, detail window title,
90 			fixed interval handling in msleep delay loop,
91 			added -m, -p and -s option
92 	12-04-93: 1.11
93 			Fixed resize bug which resulted in graph
94 			heights being too small
95 	14-04-93: 1.20
96 			Fixed percent display placement, added -t flag
97 			and toggle handling
98 	16-04-93: 1.21
99 			Added MB line for detail window
100 	18-04-93: 1.22
101 			Fixed overflow problem for MB line (detail window)
102 			for very large file systems, adapted sleep
103 			handling to allow larger scaling of sleep time
104 	19-04-93: 1.23
105 			Added LINUX ifdefs
106 	22-04-93: 1.24
107 			Added close on direct mouse button in detail window
108 	23-04-93: 1.30
109 			Fixed Expose event handling problem which resulted
110 			in too may redraws upon resizing, corrected the
111 			handling of get_fs_stat, fixed problem where in a
112 			small window percentages get overwritten by long
113 			file system names and added some cosmetic
114 			changes to the code.
115 	25-04-93: 1.31
116 			Fixed file system truncation for corrent handling
117 			of percent option.
118 	26-04-93: 1.32
119 			Fixed AIX handling, added HPUX #defines and fixed some
120 			problems which resulted in warnings and errors on
121 			stringent compilers.
122 	29-04-93: 1.40
123 			Added OSF1, DYNIX, SOLARIS and ULTRIX #ifdefs, fixed
124 			expose event handling problems, added warning pixmap
125 			and bell options, fixed potential problem for command
126 			line options handling for flags which require arguments,
127 			added automount handling and -l flag, added window
128 			resize code for changing number of FS, changed
129 			workings of -d option in conjuction with -l option
130 	05-05-93: 1.41
131 			Added -v optionm, added -mb option, fixed bugs in
132 			autmount resize code.
133 	06-05-93: 1.42
134 			Moved warning pixmap to right of percent display,
135 			made 'q' global quit key, made 'c' close key for
136 			detail window , added -D flag
137 	19-05-93: 1.43
138 			changed structure handling to #defines in main.h to
139 			avoid all the porting exceptions messing up the code.
140 	22-05-93: 1.50
141 			changed popen() to actual system calls (*much* more
142 			efficient), removed -l flag made the continoual
143 			rechecking default (and only) mode, added device
144 			name to detail window, added stat() check for
145 			updating mounted FS list.
146 	25-05-93: 1.51
147 			Added "+" warning to device name string on length
148 			overflow
149 	01-06-93: 1.52
150 			Standardized and fixed -d and -D options, fixed
151 			update for OSF1, fixed some *nasty* bugs for AIX
152 	02-06-93: 1.53
153 			Added check for file system of type ignore,
154 			fixed pointer to integer comarisons for strcmp()
155 	03-06-93: 1.54
156 			Added -mnl flag, fixed some redraw inefficiencies
157 	07-06-93: 1.55
158 			Fixed bug for -mnl option resizing, added ULTRIX &&
159 			DYNIX patches, added strstr for DYNIX
160 	10-06-93: 1.56
161 			Added dynamic resizing for detail window.
162 	10-06-93: 1.60
163 			Added XResource handling, colors, fixed core
164 			dump for AIX, added missing AIX ifdef, ifndefed
165 			caluclations unsuitable for TOS
166 	23-07-93: 1.61
167 			Changed AIX getfsent to mntctl, fixed some resize
168 			problems, extended -geometry option to include size.
169 	04-08-93: 1.62
170 			Removed f_bavail for HPUX, fix core causing bug in
171 			call to fix_fs_win_width(), started wondering about
172 			portability of catlist(), removed display of f_favail
173 			for AIX, DYNIX and HPUX.
174 	13-08-93: 1.63
175 			Fixed problem for bar/percentage association when 				file systems are umounted (this is a rather quick
176 			and dirty fix but it should not be a problem even
177 			though it requires 2 extra redraws), improved
178 			protability for catlist().
179 	17-08-93: 1.64
180 			Applied some OSF1 patches, fixed resize bug,
181 			finally got warning levels correctly working,
182 			added automatic disabling of gray fill upon use
183 			of -fg, added -rs flag.
184 	20-08-93: 1.65
185 			fixed initialization of main window size in
186 			conjunction with file system of size 0, cleaned
187 			up old, outdated code ...
188 	06-09-93: 1.66
189 			fixed inconsistency with HPUX && SYSV #define,
190 			made getBoolResource case insensitive, made
191 			detail window resize font independent ...
192 	10-09-93: 1.70
193 			removed TOS support, added mount type and
194 			option info, changed MOUNT_FILE for SOLARIS
195 	14-09-93: 1.71
196 			added SCO support, cleaned up some more code,
197 			accounted for ULTRIX fixed block size (1K)
198 	21-09-93: 1.72
199 			added -sort option, changed warning levels
200 			default to -1, added -fsb option
201 	19-10-93: 1.73
202 			added indexing scheme to make sort more efficient
203 			and flexible, changed some data structures
204 	11-02-94: 1.74
205 			finished SCO support, added support for multiple
206 			block sizes
207 	14-02-94: 1.75
208 			changed SCO stuff to use popen (), fixed some misspelled
209 			OSF1 lables, fixed comparison in write_percent()
210 
211 	15-02-94: 1.76
212 			changed comparison with warn<x>val to fix bug in
213 			assigning warning colors, changes SYSV ifdefs back to
214 			SVR4 to solve inconsistencies
215 
216 	17-02-94: 1.77
217 			Fixed ULTRIX core dump, added FreeBSD #ifdefs,
218 			changed AIX buffer to 128K, added NFS bounds
219 			checking for AIX,
220 	18-02-94: 1.78
221 			changed AIX buffer size to #define BUFFERSIZE, added
222 			-it and -ot options, ifndefed some more stuff for SCO
223 
224 	22-02-94: 1.79
225 			added AUX support
226 
227 	04-03-94: 1.80
228 			fixed -mnl option core dump under SunOS and -mnl
229 			problems under other machines
230 
231 	10-03-94: 1.81
232 			changed file structure to allow code sharing with
233 			xofm
234 	04-08-94: 1.82
235 			changed Imakefile, APP_DEFAULTS_DIR handling and
236 			the format of the call the DefaultDepth which
237 			broke some preprocessors.
238 	09-09-94: 1.83
239 			added check for resrouce file. Xfsm will now look
240 			first in XAPPLRESDIR. If that turns up empty, we
241 			look in  APP_DEFAULTS_DIR (which is the global
242 			preferences stuff). Also fixed the problem with
243 			system which don't allow the stat() shortcut where
244 			file systems of size 0 are reported on each update
245 			in verbose mode.
246 	21-10-94: 1.84
247 			fixed -fb flag message
248 	11-11-94: 1.85
249 			added SGI ifdefs
250 	31-03-95: 1.86
251 			Fixed handling of any file system type containing the
252                         string "msdos": no reserved space is assumed now,
253 			fixed potential core dump when checking non-existant
254                         XAPPLRESDIR, reduced SCO detail window size, added
255 			-sb flag, fixed unitialized msg in process_databases().
256 
257 	04-05-95: 1.87
258 			Added -A, -s, -S flag, allowed SOLARIS to ignore
259 			file systems via MNTOPT_IGNORE/MNTTYPE_IGNORE,
260 			fixed slight resource problems, fixed man page.
261 	28-03-96: 1.88
262 			Changed address to Robert_Gasch@peoplesoft.com,
263 			fixed some warnings gcc -Wall showed
264 	07-07-96: 1.89
265 			Fixed MS-DOS free system calculation, fixed
266 			-e flag problems
267 	14-10-96: 1.90
268 			Changed LINUX default for reserverd space to
269 			5% since this is the default for ext2.
270 	20-01-97: 1.91
271 			Added -wl0c argument to set a color for all file
272 			systems below the wl1 warning level, added
273 			-title argument which can override hostname in
274 			Main window title (useful when monitoring other
275 			system's NFS-mounted file systems -- you can put
276 			the other host's name in the title bar). Also
277 			added a port for DG/UX. (patch supplied by Eric
278 			H. Raskin (ehr@internetmci.com))
279 	01-02-97: 1.92
280 			Added some minor fixes, most noticably whenever
281 			you specify a other than -bg the gray fill pattern
282 			will be turned off, fixed -w bug.
283 	04-02-97: 1.93
284 			Added -oi (override ignore) to keep file systems
285 			which are marked ignore.
286 
287 	15-07-97: 1.94
288 			Patch to fix minor SGI problem
289 	10-08-97: 1.95
290 			Not sure anymore, something minor
291 	02-12-97: 1.96
292 			added BSDI ifdefs
293 	12-05-98: 1.97
294 			added -rootdf flag, fixed round error for percentace
295 			calculation.
296 	07-02-98: 1.98
297 			fixes for SGI and added -ab (alwaysbeep) flag
298 	15-02-98: 1.99
299 			added -n32 to SGI flags in Makefile.std
300 
301   ************************************************************************* */
302 
303 
304 #include "xfsm.h"
305 
306 Display			*mydisplay;
307 char*			myname;		/* Name we hunt resources with */
308 char*			title=NULL;	/* Title to put on main window */
309 XrmDatabase		resourceDB;		/* X resources. */
310 WinType			main_win,		/* main window */
311 			menu[MENU_ITEMS],	/* menu items */
312 			fs_win[MAXFS],		/* FS graphs */
313 			detail_win,		/* detail window */
314 			global_win;		/* compatability in util.c */
315 XGCValues		gray_gc_val;		/* GC values for gray fill */
316 XEvent			myevent;		/* event */
317 unsigned long		fg, bg;			/* forgrund, background */
318 unsigned long		warncols[4];		/* warning level colors */
319 XSizeHints		mainwin_hint,		/* main Window size hints */
320 			szhint;			/* detail Window size hints */
321 Pixmap			warn_pix,		/* Warning Pixmap */
322 			popup_pix;		/* Popup Pixmap */
323 int 			show_use=TRUE,		/* do we show user or root */
324 			upd_interval=60,	/* when do we update stats */
325 			NFS=0,			/* number of file systems */
326 			detail_open=NOGOOD,	/* which detail_wind is open */
327 			detail_share_color = FALSE, /* */
328 			minimize=FALSE,		/* minimize dimensions */
329 			menu_border=FALSE,	/* menu border */
330 			fs_border=1,		/* file system border */
331 			percent=TRUE,		/* show percent */
332 			absolute=FALSE,		/* make bar size relative */
333 			available=FALSE,	/* show available MB */
334 			bell=FALSE,		/* ring bell for warning */
335 			alwaysbeep=FALSE,	/* aways ring bell (or just first time) */
336 			popup=FALSE,		/* activate popup */
337 			fs_level[MAXFS],        /* warn level for FS */
338 			fs_warn[MAXFS],         /* warn this time? (per FS) */
339 			fs_bell[MAXFS],         /* sound bell this time? (per FS) */
340 			verbose=FALSE,		/* verbose mode */
341 			sort=FALSE,		/* do we sort by name? */
342 			gray,			/* use gray fill */
343 			override_ignore,	/* do we keep FSs marked ignore? */
344 			rootdf=FALSE,		/* show df % output when running in root mode */
345 			idx[MAXFS],		/* index to use when sorting */
346 			show_blocks,		/* compatability in util.c */
347 			show_biggest=FALSE,	/* show biggest size */
348 #ifdef SCO
349 			root=TRUE;		/* root or non-root */
350 #else
351 			root=FALSE;		/* root or non-root */
352 #endif /* SCO */
353 double			b_blocks=0,		/* biggest # of blocks */
354 			b_bsize=0,		/* biggest block size */
355 			b_bytes,		/*for compatability in util.c */
356 			o_b_blocks,		/* old biggest blocks */
357 			o_b_bsize,		/* old biggest block size */
358 			o_b_bytes,		/*for compatability in util.c */
359 			b_disk,			/* biggest disk */
360 			o_b_disk;		/* old biggest disk */
361 unsigned long		turns=0;		/* how many turns */
362 float			fs_perc[MAXFS],		/* percentage for FS */
363 			res_space,		/* % space reserved for root */
364 			warnvals[4],		/* warn val level 3 */
365 			warn_val=0;		/* waring threshold used
366 						   for "!" after FS name */
367 StringInfo		strinfo[MAXFS];		/* all system static strings */
368 MyString		hname;			/* hostname */
369 struct statfs 		stats[MAXFS];		/* FS stats structure */
370 
371 
372 /* *** get the gray bitmap and define our warning bitmap *** */
373 #include <X11/bitmaps/gray1>
374 static char warn_bits[] = {
375    0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x06, 0x06};
376 
377 static char popup_bits[] = {
378    0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 0x18, 0x18, 0x18};
379 
380 static XrmOptionDescRec opTable[] = {
381 		/* KEEP THIS SORTED BY THE FIRST ARGUMENT! */
382 /* the char * should be XPointer but many systems don't support it */
383 {"+rv",		"*reverseVideo", XrmoptionNoArg,	(char *) "off"},
384 {"+synchronous","*synchronous",	XrmoptionNoArg,		(char *) "off"},
385 {"-?",		".help",	XrmoptionNoArg,		(char *) "on"},
386 {"-A",		".available",	XrmoptionNoArg,		(char *) "on"},
387 {"-a",		".absolute",	XrmoptionNoArg,		(char *) "on"},
388 {"-ab",		".alwaysbeep",	XrmoptionNoArg,		(char *) "off"},
389 {"-background",	"*background",	XrmoptionSepArg,	(char *) NULL},
390 {"-b",		".gray",	XrmoptionNoArg,		(char *) "off"},
391 {"-bg",		"*background",	XrmoptionSepArg,	(char *) NULL},
392 {"-bordercolor","*borderColor",	XrmoptionSepArg,	(char *) NULL},
393 {"-borderwidth",".borderWidth",	XrmoptionSepArg,	(char *) NULL},
394 {"-detailgeometry", "*detailWin.geometry", XrmoptionSepArg,	(char *) NULL},
395 {"-display",	".display",     XrmoptionSepArg,	(char *) NULL},
396 {"-e",		".bell",	XrmoptionNoArg,		(char *) "on"},
397 {"-f",		".used",	XrmoptionNoArg,		(char *) "off"},
398 {"-fg",		"*foreground",	XrmoptionSepArg,	(char *) NULL},
399 {"-font",	"*font",	XrmoptionSepArg,	(char *) NULL},
400 {"-foreground",	"*foreground",	XrmoptionSepArg,	(char *) NULL},
401 {"-fsb",	".fs_border",	XrmoptionNoArg,		(char *) "off"},
402 {"-geometry",	"*mainWin.geometry",	XrmoptionSepArg,(char *) NULL},
403 {"-help",	".help",	XrmoptionNoArg,		(char *) "on"},
404 {"-i",		".updInterval",	XrmoptionSepArg,	(char *) NULL},
405 {"-iconic",	".iconic",	XrmoptionNoArg,		(char *) "on"},
406 {"-m",		".minimize",	XrmoptionNoArg,		(char *) "1"},
407 {"-mb",		".menuborder",	XrmoptionNoArg,		(char *) "on"},
408 {"-mnl",	".minimize",	XrmoptionNoArg,		(char *) "2"},
409 {"-name",	".name",	XrmoptionSepArg,	(char *) NULL},
410 {"-oi",		".override_ignore",XrmoptionNoArg, 	(char *) "on"},
411 {"-p",		".percent",	XrmoptionNoArg,		(char *) "off"},
412 {"-pu",		".popup",	XrmoptionNoArg,		(char *) "on"},
413 #ifndef SCO
414 {"-r",		".root",	XrmoptionNoArg,		(char *) "on"},
415 {"-rootdf",	".rootdf",	XrmoptionNoArg,		(char *) "on"},
416 #endif
417 {"-rs",		".reserved_space",XrmoptionSepArg,	(char *) "NULL"},
418 {"-rv",		"*reverseVideo", XrmoptionNoArg,	(char *) "on"},
419 {"-sb",		".showbiggest" , XrmoptionNoArg,	(char *) "on"},
420 {"-sort",	".sort",	XrmoptionNoArg,		(char *) "on"},
421 {"-synchronous","*synchronous",	XrmoptionNoArg,		(char *) "on"},
422 {"-title",	".title",	XrmoptionSepArg,	(char *) NULL},
423 {"-v",		".verbose",	XrmoptionNoArg,		(char *) "on"},
424 {"-w",		".warnval",     XrmoptionSepArg,	(char *) NULL},
425 {"-wl0c",	".warn0col",	XrmoptionSepArg,	(char *) NULL},
426 {"-wl1",	".warn1val",    XrmoptionSepArg,	(char *) NULL},
427 {"-wl1c",	".warn1col",    XrmoptionSepArg,	(char *) NULL},
428 {"-wl2",	".warn2val",    XrmoptionSepArg,	(char *) NULL},
429 {"-wl2c",	".warn2col",    XrmoptionSepArg,	(char *) NULL},
430 {"-wl3",	".warn3val",    XrmoptionSepArg,	(char *) NULL},
431 {"-wl3c",	".warn3col",    XrmoptionSepArg,	(char *) NULL},
432 {"-xrm",	NULL,		XrmoptionResArg,	(char *) NULL},
433 {"help",	".help",	XrmoptionNoArg,		(char *) "on"},
434 };
435 
436 
main(argc,argv)437 int main (argc, argv)
438 int argc;
439 char **argv;
440 {
441 	int 		i=0;
442 	XrmDatabase 	commandlineDB=NULL;
443 	char* 		myDisplayName = NULL;
444 	XrmString 	str_type;
445 	XrmValue 	value;
446 
447 	/* *** Try and work out the name the application will run under *** */
448 	/* *** This needed for finding the correct resources. *** */
449 	{
450 	char** ptr = &argv[1];
451 
452 	for (; *ptr != NULL; ptr++)
453 	if (strcmp(*ptr, "-name") == 0 && *(ptr + 1) != NULL)
454 		{
455 		myname = *(ptr + 1);
456 		break;
457 		}
458 
459 	if (*ptr == NULL)
460 		{
461 		char* ptr1 = rindex(argv[0], '/');
462 		if (ptr1)
463 			myname = ++ptr1;
464 		else
465 			myname = argv[0];
466 		}
467 	}
468 
469 	XrmInitialize();
470 	XrmParseCommand(&commandlineDB, opTable,
471 		sizeof(opTable) / sizeof(opTable[0]), myname, &argc, argv);
472 	if (XrmGetResource(commandlineDB,
473 		catlist(myname, ".name", (char*) NULL), "Xfsm.Name",
474 		&str_type, &value))
475 			myname = value.addr;
476 
477 	if (XrmGetResource(commandlineDB,
478 		catlist(myname, ".title", (char*) NULL), "Xfsm.Title",
479 		&str_type, &value))
480                         title = value.addr;
481 
482 	if (XrmGetResource(commandlineDB,
483 		catlist(myname, ".display", (char*) NULL), "Xfsm.Display",
484 		&str_type, &value))
485 			myDisplayName = value.addr;
486 
487 	/* *** connect to X Server and assign screen *** */
488 	if ((mydisplay = XOpenDisplay(myDisplayName)) == NULL)
489 		{
490 		fprintf (stderr, "Error Opening Display ... Exiting\n");
491 		exit (1);
492 		}
493 
494 	/* *** process arguments and the resource database *** */
495 	process_databases (argc, argv, commandlineDB);
496 
497 	/* *** Turn on X server synchronization if the user wants it. *** */
498 	XSynchronize(mydisplay, getBoolResource(resourceDB,
499 		catlist(myname, ".synchronous", (char*) NULL),
500 		"Xfsm.Synchronous", False));
501 
502 	/* *** get hostname *** */
503 	if (!(gethostname (hname, STRLENGTH)))
504 		{
505 		if (verbose)
506 			printf ("Hostname = %s\n", hname);
507 		}
508 	else
509 		fprintf (stderr, "Can't read hostname ...\n");
510 
511 	/* *** initialize index *** */
512 	for (i=0; i<MAXFS; i++)
513 		{
514 		idx[i]=i;
515 		fs_level[i]=0;
516 		fs_bell[i]=0;
517 		fs_warn[i]=FALSE;
518 		}
519 
520 	/* *** get the file system statistics *** */
521 	/* *** this also handles getting the  *** */
522 	/* *** info from mount                *** */
523 	if (minimize == MNL)
524 		main_win.font_info = getFontResource (resourceDB,
525 			catlist(myname, ".mainWin.font", (char*) NULL),
526 			"Xfsm.MainWin.Font",
527 			XLoadQueryFont(mydisplay, DEFAULT_FONT));
528 	get_fs_stat();
529 	if (verbose)
530 		{
531 		for (i = 0; i < NFS; i++)
532 			printf ("%s\n", FsName);
533 		printf ("%d valid file systems found ...\n", NFS);
534 		}
535 
536 	init_all_windows();
537 
538 	/* *** Check to see of the user wants the colors reversed. *** */
539 	if (getBoolResource(resourceDB,
540 		catlist(myname, ".reverseVideo", (char*) NULL),
541 		"Xfsm.ReverseVideo", False))
542 		{
543 		long temp;
544 		temp = fg;
545 		fg = bg ;
546 		bg = temp;
547 		}
548 
549 	/* *** create Main Program Window and set up the properties. *** */
550 	{
551 	XClassHint clshint;
552 	XWMHints wmhints;
553 
554 	mainwin_hint.min_width = MIN_WIN_X;
555 	mainwin_hint.min_height = ((MIN_INTERVAL(main_win) * NFS) +
556 		BEGIN_NFS(main_win));
557 	mainwin_hint.width = main_win.width;
558 	mainwin_hint.height = main_win.height;
559 	mainwin_hint.x = main_win.x;
560 	mainwin_hint.y = main_win.y;
561 	mainwin_hint.flags = main_win.flags | PMinSize | PSize;
562 
563 	clshint.res_name  = myname;
564 	clshint.res_class = CLASS_NAME;
565 
566 	wmhints.input = True;
567 	wmhints.initial_state = (getBoolResource(resourceDB,
568 		catlist(myname, ".iconic", (char*) NULL),
569 		"Xfsm.Iconic", False))
570       		? IconicState : NormalState;
571 	wmhints.window_group = main_win.win;
572 	wmhints.flags = InputHint | StateHint | WindowGroupHint;
573 
574 	create_window (DefaultRootWindow(mydisplay), &main_win, fg, bg);
575 	XSetStandardProperties (mydisplay, main_win.win, main_win.text,
576 		main_win.text, None, argv, argc, &mainwin_hint);
577 	XSetClassHint(mydisplay, main_win.win, &clshint);
578 	XSetWMHints(mydisplay, main_win.win, &wmhints);
579 	}
580 
581 	/* ** Create the pixmap of the gray background. ** */
582 	gray_gc_val.stipple = XCreatePixmapFromBitmapData(mydisplay,
583 		DefaultRootWindow(mydisplay), gray1_bits, gray1_width,
584 		gray1_height, fg, bg, 1);
585 
586 	if (!gray_gc_val.stipple)
587 		{
588 		fprintf (stderr,
589 		   "Couldn't create gray tile ... escaping to black fill.\n");
590 		gray = FALSE;
591 		}
592 	else
593 		gray_gc_val.fill_style = FillOpaqueStippled;
594 
595 	/* *** create all the buttons using child windows *** */
596 	for (i = 0; i < MENU_ITEMS ; ++i)
597 		create_window (main_win.win, &menu[i], fg, bg);
598 	for (i = 0; i < NFS; i++)
599 		{
600 		fix_fs_win_width(i);
601 		create_window (main_win.win, &fs_win[i],
602 			getColorResource(resourceDB,
603 			catlist(myname, ".", FsName,
604 			".foreground", (char*)NULL),
605 			"Xfsm.FileSystem.Foreground", fg),
606 			getColorResource(resourceDB,
607 			catlist(myname, ".", FsName,
608 			".background", (char*)NULL),
609 			"Xfsm.FileSystem.Background", bg));
610 
611 	if (gray)
612 		XChangeGC (mydisplay, fs_win[i].gc, GCFillStyle | GCStipple,
613 		&gray_gc_val);
614 		}
615 
616 	/* *** create warning pixmap *** */
617 	if (!(warn_pix = XCreatePixmapFromBitmapData (mydisplay, main_win.win,
618 		warn_bits, warn_width, warn_height, fg, bg,
619 		DefaultDepth (mydisplay, DefaultScreen (mydisplay)))))
620 		{
621 		fprintf (stderr,
622 			"Couldn't create Warning pixmap ... \
623 ignoring specified threshold.\n");
624 		warn_val = FALSE;
625 		}
626 
627 	/* *** create popup pixmap *** */
628 	if (!(popup_pix = XCreatePixmapFromBitmapData (mydisplay, main_win.win,
629 		popup_bits, popup_width, popup_height, fg, bg,
630 		DefaultDepth (mydisplay, DefaultScreen (mydisplay)))))
631 		{
632 		fprintf (stderr,
633                         "Couldn't create Popup pixmap ... \
634 ignoring Popup request.\n");
635 		popup = FALSE;
636 		}
637 
638 	/* *** Map window definitions onto screen *** */
639 	XMapSubwindows (mydisplay, main_win.win);
640 	XMapRaised (mydisplay, main_win.win);
641 
642 	if (popup)
643 		redraw_main_win();
644 
645 #ifdef DEBUG
646 	fprintf (stdout, "Setup is Done!\n");
647 #endif
648 
649 /* ************************************************************ */
650 /* ************** setup is done - main event loop ************* */
651 /* ************************************************************ */
652 
653 	do_event_loop (argc, argv);
654 
655 	/* *** we are done - destroy all the windows *** */
656 	if (detail_open != NOGOOD)
657 		{
658 		XFreeGC (mydisplay, detail_win.gc);
659 		XDestroyWindow (mydisplay, detail_win.win);
660 		}
661 
662 	destroy_menu (menu, MENU_ITEMS);
663 	destroy_menu (fs_win, NFS);
664 	XFreeGC (mydisplay, main_win.gc);
665 	XDestroyWindow (mydisplay, main_win.win);
666 	XCloseDisplay (mydisplay);
667 	exit (0);
668 }
669 
670 
671 
672 /* *** This is the main event loop. Here we handle events and deal *** */
673 /* ***                 with all the user inputs we get             *** */
do_event_loop(argc,argv)674 void do_event_loop (argc, argv)
675 int argc;
676 char **argv;
677 {
678 	XEvent	tevent;
679 	int	count, cont, this_item, i, ppnfs, OFS, done=FALSE;
680 	long	target = time(NULL) + upd_interval;
681 	char	text[10];
682 
683     while (!done)
684 	{
685 	/* *** here we wait while there are no events *** */
686 	/* *** and count out down our interval.       *** */
687 	while (XPending (mydisplay) == 0)
688 		{
689 		struct timeval  sleept;
690 		fd_set reads;
691 
692 		FD_ZERO(&reads);
693 		FD_SET(ConnectionNumber(mydisplay), &reads);
694 		sleept.tv_sec = target - time(NULL);
695 		sleept.tv_usec = 0;
696 #ifdef HPUX
697 		select(ConnectionNumber(mydisplay) + 1, (int *) &reads, NULL,
698 			NULL, &sleept);
699 #else
700 		select(ConnectionNumber(mydisplay) + 1, &reads, NULL, NULL,
701 			&sleept);
702 #endif
703 
704 		if ((time(NULL)) >= target)
705 			{
706 			OFS = NFS;
707 			o_b_blocks = b_blocks;
708 			o_b_bsize = b_bsize;
709 			o_b_disk = b_disk;
710 			ppnfs = ((main_win.height - BEGIN_NFS(main_win)) / NFS);
711 			get_fs_stat ();
712 			/* XClearWindow (mydisplay, main_win.win); */
713 			main_win.height = (BEGIN_NFS(main_win) + (ppnfs * NFS));
714 			handle_NFS_change (ppnfs, OFS);
715 			if (detail_open != NOGOOD)
716 				write_detail (detail_open);
717 			target = target + upd_interval;
718 			}
719 		}
720 
721 	/* *** read the next event *** */
722 	XNextEvent (mydisplay, &myevent);
723 
724 	switch (myevent.type)
725 	{
726 	/* *** expose event -> redraw the window *** */
727 	 case Expose:
728 	/* ********************************************* *
729 	 *  since a window can generate multiple expose  *
730 	 *  events we can collapse these into one redraw *
731 	 * ********************************************* */
732 		count=0;
733 		do
734 			{
735 			if (XPending (mydisplay) == 0)
736 				break;
737 			XPeekEvent (mydisplay, &tevent);
738 			if (tevent.xexpose.window ==  myevent.xexpose.window)
739 				{
740 				XNextEvent (mydisplay, &myevent);
741 				count++;
742 				}
743 			}
744 		while(tevent.xexpose.window==myevent.xexpose.window);
745 
746 #ifdef DEBUG
747 		if (!count)
748 			fprintf(stdout, "got expose event in window: %d\n",
749 			myevent.xexpose.window);
750 		else
751 			fprintf(stdout,
752 			"Compressed %d expose events into 1 in window: %d\n",
753 			count, myevent.xexpose.window);
754 #endif
755 
756 		/* ******************************************* *
757 		 * ** now deal with the actual expose event ** *
758 		 * ******************************************* */
759 		if (myevent.xexpose.window == main_win.win &&
760 		    myevent.xexpose.count == 0)
761 			{
762 			redraw_main_win ();
763 			break;
764 			}
765 		else
766 		if (myevent.xexpose.window == detail_win.win)
767 			write_detail (detail_open);
768 
769 		cont = TRUE;
770 		cont = expose_win (menu, MENU_ITEMS);
771 		if (!cont) break;
772 			for (i = 0; i < NFS; i++)
773 		if (myevent.xexpose.window == fs_win[i].win)
774 			{
775 			redraw_fs_win (i);
776 			i = NFS;
777 			}
778 		break;
779 
780 	/* *** change work window if main window changes *** */
781 	case ConfigureNotify:
782 #ifdef DEBUG
783 		fprintf(stdout, "got configure notify event in window: %d\n",
784 			myevent.xconfigure.window);
785 #endif
786 		/* *** we don't allow changes in the detail window *** */
787 		if (myevent.xconfigure.window != main_win.win)
788 			break;
789 
790 		/* *** size stays the same -> nothing to do *** */
791 		if (myevent.xconfigure.width == main_win.width &&
792 		    myevent.xconfigure.height == main_win.height)
793 			break;
794 
795 		/* *** figure out how many points per nfs we have *** */
796 		ppnfs = ((myevent.xconfigure.height -
797 			BEGIN_NFS(main_win)) / NFS);
798 #ifdef DEBUG
799 	fprintf (stdout,
800 	       "got resize event - new interval = %d\nwidth = %d height = %d\n",
801 	       ppnfs, myevent.xconfigure.width, myevent.xconfigure.height);
802 #endif
803 
804 		XClearWindow (mydisplay, main_win.win);
805 		main_win.width = myevent.xconfigure.width;
806 		main_win.height = myevent.xconfigure.height;
807 		XResizeWindow (mydisplay, main_win.win, main_win.width,
808 			main_win.height);
809 		redraw_main_win ();
810 		fix_menu_pos (myevent.xconfigure.width);
811 
812 		for (i = 0; i < NFS; i++)
813 			{
814 			set_fs_win_size (i, ppnfs);
815 			XClearWindow (mydisplay, fs_win[i].win);
816 			XMoveResizeWindow (mydisplay, fs_win[i].win, OFF_X,
817 				fs_win[i].y, fs_win[i].width, fs_win[i].height);
818 			/* XClearWindow (mydisplay, main_win.win); */
819 			if (fs_perc[i] != NOGOOD)
820 				redraw_fs_win (i);
821 			}
822 
823 		XClearWindow (mydisplay, main_win.win);
824 		break;
825 
826 	/* *** process keyboard mapping changes *** */
827 	case MappingNotify:
828 #ifdef DEBUG
829 	fprintf(stdout, "got mapping notify event in window: %d\n",
830 		myevent.xexpose.window);
831 #endif
832 
833 		XRefreshKeyboardMapping ((XMappingEvent *) &myevent );
834 		break;
835 
836       /* *** drag in work window *** */
837 	case MotionNotify:
838 #ifdef DEBUG
839 	fprintf(stdout, "got motion notify event in window: %d\n",
840 		myevent.xbutton.window);
841 #endif
842 	break;
843 
844 	/* *** mouse enters a window *** */
845 	case EnterNotify:
846 		this_item = highlight_menu (menu, MENU_ITEMS, TRUE);
847 		break;
848 
849 	/* *** Mouse Leaves a window *** */
850 	case LeaveNotify:
851 		this_item = highlight_menu (menu, MENU_ITEMS, FALSE);
852 		break;
853 
854 	/* *** process mouse-button presses *** */
855 	case ButtonPress:
856 #ifdef DEBUG
857 	fprintf(stdout, "button press (%d) in window: %d\n",
858 		myevent.xbutton.button, myevent.xbutton.window);
859 #endif
860 
861 	if (myevent.xbutton.button == 1 || myevent.xbutton.button == 2)
862 		{
863 		this_item = which_button_pressed (menu, MENU_ITEMS);
864 
865 		if (this_item == UPDATE)
866 			{
867 			clear_fs_warn_flags();
868 			OFS = NFS;
869 			o_b_blocks = b_blocks;
870 			o_b_bsize = b_bsize;
871 			o_b_disk = b_disk;
872 			ppnfs = ((main_win.height - BEGIN_NFS(main_win)) / NFS);
873 			get_fs_stat ();
874 			main_win.height = (BEGIN_NFS(main_win) + (ppnfs * NFS));
875 			handle_NFS_change (ppnfs, OFS);
876 			if (detail_open != NOGOOD)
877 				write_detail (detail_open);
878 			redraw_main_win ();
879 			target = time(NULL) + upd_interval;
880 			break;
881 			}
882 		else if (this_item == QUIT)
883 			{
884 			done = TRUE;
885 			break;
886 			}
887 
888 	/* *** see if btnpress was in detail window *** */
889 	if (myevent.xbutton.window == detail_win.win)
890 		{
891 		XFreeGC (mydisplay, detail_win.gc);
892 		XDestroyWindow (mydisplay, detail_win.win);
893 		detail_open = NOGOOD;
894 		break;
895 		}
896 
897 	/* *** see if btnpress was in a graph window *** */
898 		this_item = which_button_pressed (fs_win, NFS);
899 		if (this_item == NOGOOD)
900 			break;
901 
902 	/* *** open a detail window *** */
903 	if (detail_open == NOGOOD)
904 		{
905 		open_detail_win (argc, argv);
906 		detail_open = this_item;
907 		if (detail_share_color)
908 			{
909 			XSetBackground (mydisplay, detail_win.gc,
910 				fs_win[this_item].bg);
911 			XSetForeground (mydisplay, detail_win.gc,
912 				fs_win[this_item].fg);
913 			XSetWindowBackground(mydisplay, detail_win.win,
914 				fs_win[this_item].bg);
915 			}
916 		}
917 
918 	/* *** det_win for this graph open - close it *** */
919 	else
920 	if (detail_open == this_item)
921 		{
922 		XFreeGC (mydisplay, detail_win.gc);
923 		XDestroyWindow (mydisplay, detail_win.win);
924 		detail_open = NOGOOD;
925 		}
926 	else
927 		{
928 		if (detail_share_color)
929 			{
930 			XSetBackground (mydisplay, detail_win.gc,
931 				fs_win[this_item].bg);
932 			XSetForeground (mydisplay, detail_win.gc,
933 				fs_win[this_item].fg);
934 			XSetWindowBackground(mydisplay, detail_win.win,
935 				fs_win[this_item].bg);
936 			}
937 		detail_open = this_item;
938 		write_detail (this_item);
939 		}
940 	}
941 	/* *** Button 3 pressed *** */
942 	else
943 		toggle_mode();
944 	break;
945 
946 	/* *** process mouse-button release *** */
947 	case ButtonRelease:
948 #ifdef DEBUG
949 		fprintf(stdout, "button release in window: %d\n",
950 			myevent.xbutton.window);
951 #endif
952 	break;
953 
954 	/* *** process Resize *** */
955 	case ResizeRequest:
956 #ifdef DEBUG
957 		fprintf (stdout, "got resize event \n");
958 #endif
959 	break;
960 
961 	/* *** process keyboard input *** */
962 	case KeyPress:
963 #ifdef DEBUG
964 		fprintf (stdout, "got keypress event in window: %d\n",
965 			myevent.xkey.window);
966 #endif
967 		i = XLookupString ((XKeyEvent *)&myevent, text, 10, NULL, 0 );
968 
969 		if (text[0] == UPDATE_KEY)
970 			{
971 			clear_fs_warn_flags();
972 			OFS = NFS;
973 			o_b_blocks = b_blocks;
974 			o_b_bsize = o_b_bsize;
975 			o_b_disk = b_disk;
976 			ppnfs = ((main_win.height - BEGIN_NFS(main_win)) / NFS);
977 			get_fs_stat ();
978 			main_win.height = (BEGIN_NFS(main_win) + (ppnfs * NFS));
979 			handle_NFS_change (ppnfs, OFS);
980 			if (detail_open != NOGOOD)
981 				write_detail (detail_open);
982 			redraw_main_win ();
983 			target = time(NULL) + upd_interval;
984 			break;
985 			}
986 		else
987 		if (text[0] == QUIT_KEY)
988 			{
989 			done = TRUE;
990 			break;
991 			}
992 		else
993 		if (text[0] == CLOSE_KEY)
994 			{
995 			if (detail_open != NOGOOD)
996 				{
997 				XFreeGC (mydisplay, detail_win.gc);
998 				XDestroyWindow (mydisplay, detail_win.win);
999 				detail_open = NOGOOD;
1000 				break;
1001 				}
1002 			}
1003 		else
1004 		if (text[0] == TOGGLE_KEY)
1005 			{
1006 			toggle_mode ();
1007 			break;
1008 			}
1009 		break;
1010 	} /* switch (myevent.type) */
1011     } /* while (done == 0) */
1012 }
1013