wmfsm: Add -a command line option to select appearance at runtime.
[dockapps.git] / wmfsm / wmfsm / wmfsm.c
blob9f57aae55c63b119299b7efe6079757960f76b96
1 /*
3 * wmfsm-0.33 (C) 1999 Stefan Eilemann (Stefan.Eilemann@dlr.de)
5 * - Shows file system usage ala mfsm
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program (see the file COPYING); if not, write to the
22 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23 * Boston, MA 02110-1301, USA
27 * Changes: #include "../ChangeLog"
36 * Includes
38 #include <stdio.h>
39 #include <unistd.h>
40 #include <stdlib.h>
41 #include <ctype.h>
42 #include <string.h>
43 #include <X11/X.h>
44 #include <X11/xpm.h>
45 #include "../wmgeneral/wmgeneral.h"
46 #include "wmfsm_master.xpm"
47 #include "wmfsm_mask.xbm"
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
53 #ifdef SVR4
54 #include <netdb.h>
55 #include <sys/systeminfo.h>
56 #endif /* SVR4 */
58 #ifdef HAVE_SYS_VFS_H
59 #include <sys/vfs.h>
60 #endif
61 #ifdef HAVE_SYS_STATFS_H
62 #include <sys/statfs.h>
63 #endif
64 #ifdef HAVE_SYS_MOUNT_H
65 #include <sys/mount.h>
66 #endif
67 #ifdef HAVE_SYS_PARAM_H
68 #include <sys/param.h>
69 #endif
70 #ifdef HAVE_SYS_TYPES_H
71 #include <sys/types.h>
72 #endif
74 #ifdef STATFS_2_ARGUMENTS
75 # define STATFS(a,b) statfs(a,b)
76 #elif defined STATFS_4_ARGUMENTS
77 # define STATFS(a,b) statfs(a,b,sizeof(struct statfs),0)
78 #else
79 # define STATFS(a,b) statfs(a,b) /* Maybe configure got messed up */
80 #endif
83 #if defined IRIX64
84 # include <sys/types.h>
85 # define STATFS(a,b) statfs(a,b,sizeof(struct statfs),0)
86 #elif defined linux
87 # define STATFS(a,b) statfs(a,b)
88 #elif defined(SunOS)
89 # define STATFS(a,b) statfs(a,b,sizeof(struct statfs),0)
90 #elif defined(__OpenBSD__) || defined(__FreeBSD__)
91 # define STATFS(a,b) statfs(a,b)
92 # include <sys/param.h>
93 #endif
96 #define _GNU_SOURCE
97 #include <getopt.h>
99 * Delay between refreshes (in microseconds), uses the 10*DELAY_10
100 * coz irix has max of 100000L :(.
102 #define DELAY_10 99999L
103 #define WMFSM_VERSION "0.33"
104 #define LENMP 5 /*max 10, number char for mountpoint */
106 /*modes for drawing*/
107 #define NORMAL 0
108 #define FIRE 1
111 void ParseCMDLine(int argc, char *argv[]);
112 void pressEvent(XButtonEvent * xev);
113 void readFileSystems(void);
114 void excludeFileSystems(void);
115 void print_usage(void);
117 int UpToDate = 0;
118 int ForceUpdate = 1;
119 char *mp[100];
120 int per[9];
121 int numberfs;
122 int mode = FIRE;
123 int blink = 1;
124 int blinkper = 95;
125 char dummy[4096];
126 char *myName;
127 int delay = DELAY_10;
128 char appearance[256] = "";
130 int xpos[] = { 66, 71, 76, 81, 86, 91, /* A B C D E F */
131 66, 71, 76, 81, 86, 91, /* G H I J K L */
132 66, 71, 76, 81, 86, 91, /* M N O P Q R */
133 66, 71, 76, 81, 86, 91, /* S T U V W X */
134 66, 71, 76, 81, 86, 91, /* Y Z / _ - . */
135 96, 101, /* 0 1 */
136 96, 101, /* 2 3 */
137 96, 101, /* 4 5 */
138 96, 101, /* 6 7 */
139 96, 101
140 }; /* 8 9 */
142 int ypos[] = { 4, 4, 4, 4, 4, 4,
143 9, 9, 9, 9, 9, 9,
144 14, 14, 14, 14, 14, 14,
145 19, 19, 19, 19, 19, 19,
146 24, 24, 24, 24, 24, 24,
147 4, 4,
148 9, 9,
149 14, 14,
150 19, 19,
151 24, 24
156 * main
159 main(int argc, char *argv[])
162 XEvent event;
163 int dx, dy;
164 char hostname[100];
165 int i, j, k;
166 int xpm_free = 0;
167 int c, on[9] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
168 struct statfs buffer;
169 char **pixmap;
172 * Parse any command line arguments.
174 myName = strdup(argv[0]);
175 ParseCMDLine(argc, argv);
177 if (appearance[0] == 0) {
178 pixmap = wmfsm_master_xpm;
179 } else {
180 if (XpmReadFileToData(appearance, &pixmap) != XpmSuccess) {
181 fprintf(stderr, "warning: could not read appearance file; using default.\n");
182 pixmap = wmfsm_master_xpm;
183 } else {
184 xpm_free = 1;
188 openXwindow(argc, argv, pixmap, wmfsm_mask_bits, wmfsm_mask_width, wmfsm_mask_height);
190 if (xpm_free)
191 XpmFree(pixmap);
193 #ifndef SVR4
194 if (gethostname(hostname, 100) != 0) {
195 perror("gethostname");
196 exit(10);
198 #else
199 if (sysinfo(SI_HOSTNAME, hostname, 100) < 0) {
200 perror("sysinfo(SI_HOSTNAME)");
201 exit(20);
203 #endif
204 while (1) {
206 readFileSystems ();
207 usleep (100);
210 * Process any pending X events.
212 while (XPending(display)) {
213 XNextEvent(display, &event);
214 switch (event.type) {
215 case Expose:
216 RedrawWindow();
217 break;
218 case ButtonPress:
219 pressEvent(&event.xbutton);
220 mode = (mode + 1) % 2;
221 break;
222 case ButtonRelease:
223 break;
226 /*! Here read data
228 for (i = 0; i < numberfs; i++) {
229 if (STATFS(mp[i], &buffer) != -1) {
230 per[i] = 100 - (int) ((float) buffer.f_bfree / (float) buffer.f_blocks * 100.0);
234 * Draw window.
237 * Clear window.
239 copyXPMArea(5, 69, 54, 54, 5, 5);
240 /*! here draw values
241 * void copyXPMArea(int x, int y, int sx, int sy, int dx, int dy)
244 if (numberfs > 4) {
245 for (i = 0, dy = 0; i < numberfs; i++) {
246 for (j = 0, dx = 0; j < LENMP && (unsigned int)j < strlen(mp[i]); j++) {
247 k = j + (strlen(mp[i]) > LENMP ? strlen(mp[i]) - LENMP : 0);
248 c = (int) mp[i][k];
249 switch (c) {
250 case '/':
251 c = 123;
252 break;
253 case '_':
254 c = 124;
255 break;
256 case '0':
257 case '1':
258 case '2':
259 case '3':
260 case '4':
261 case '5':
262 case '6':
263 case '7':
264 case '8':
265 case '9':
266 c += 79;
267 break;
268 default:
269 c = tolower(c);
270 break;
272 copyXPMArea(xpos[c - 97], ypos[c - 97], 5, 5, 6 + dx, 5 + dy);
273 dx += 5;
275 c = (int) ((float) per[i] * 0.52 + 66.0);
276 k = (10 - LENMP) * 5 + 2;
277 k = (float) per[i] / 100.0 * k;
278 k = LENMP * 5 + k;
279 k = k < LENMP * 5 + 1 ? LENMP * 5 + 1 : k;
280 c = c > 66 ? c : 66;
281 c = c > 117 ? 117 : c;
282 if (blink) {
283 if ((int) per[i] >= blinkper)
284 on[i] = !on[i];
285 else
286 on[i] = 1;
288 else
289 on[i] = 1;
291 for (j = LENMP * 5; j < k; j++) {
292 if (mode == FIRE && on[i])
293 copyXPMArea(66 + (float) (j - LENMP * 5) * 52.0 / (float) ((10 - LENMP) * 5), 29, 1, 5, 6 + j, 5 + dy);
294 else if (mode == NORMAL && on[i])
295 copyXPMArea(c, 29, 1, 5, 6 + j, 5 + dy);
297 dy += 6;
300 else { /*one fs in two lines */
301 for (i = 0, dy = 0; i < numberfs; i++) {
302 for (j = 0, dx = 0; j < 10 && (unsigned int)j < strlen(mp[i]); j++) {
303 c = (int) mp[i][j + (strlen(mp[i]) > 10 ? strlen(mp[i]) - 10 : 0)];
304 switch (c) {
305 case '/':
306 c = 123;
307 break;
308 case '_':
309 c = 124;
310 break;
311 case '0':
312 case '1':
313 case '2':
314 case '3':
315 case '4':
316 case '5':
317 case '6':
318 case '7':
319 case '8':
320 case '9':
321 c += 79;
322 break;
323 default:
324 c = tolower(c);
325 break;
327 copyXPMArea(xpos[c - 97], ypos[c - 97], 5, 5, 6 + dx, 5 + dy);
328 dx += 5;
330 dy += 6;
331 c = (int) ((float) per[i] * 0.52 + 66.0);
332 k = (float) per[i] / 100.0 * 52;
333 k = k < 1 ? 1 : k;
334 c = c > 66 ? c : 66;
335 c = c > 117 ? 117 : c;
336 if (blink) {
337 if ((int) per[i] >= blinkper)
338 on[i] = !on[i];
339 else
340 on[i] = 1;
342 else
343 on[i] = 1;
345 for (j = 0; j < k; j++) {
346 if (mode == FIRE && on[i])
347 copyXPMArea(66 + (float) (j) * 52.0 / 50.0, 29, 1, 5, 6 + j, 5 + dy);
348 else if (mode == NORMAL && on[i])
349 copyXPMArea(c, 29, 1, 5, 6 + j, 5 + dy);
351 dy += 6;
354 if (numberfs < 9) {
355 for (j = 0, dx = 0, dy = 47; j < 10 && (unsigned int)j < strlen(hostname); j++) {
356 c = (int) hostname[j];
357 switch (c) {
358 case '/':
359 c = 123;
360 break;
361 case '_':
362 c = 124;
363 break;
364 case '-':
365 c = 125;
366 break;
367 case '.':
368 c = 126;
369 break;
370 case '0':
371 case '1':
372 case '2':
373 case '3':
374 case '4':
375 case '5':
376 case '6':
377 case '7':
378 case '8':
379 case '9':
380 c += 79;
381 break;
382 default:
383 c = tolower(c);
384 break;
386 copyXPMArea(xpos[c - 97], ypos[c - 97], 5, 5, 6 + dx, 6 + dy);
387 dx += 5;
391 RedrawWindow();
393 * Wait for next update
395 i = 0;
396 while (i < 10) {
397 usleep(delay);
398 i++;
406 * ParseCMDLine()
408 void
409 ParseCMDLine(int argc, char *argv[])
412 int c, option_index;
413 static struct option long_options[] = {
414 {"fire", no_argument, 0, 'f'},
415 {"normal", no_argument, 0, 'n'},
416 {"blink", no_argument, &blink, 1},
417 {"noblink", no_argument, &blink, 0},
418 {"delay", required_argument, 0, 'd'},
419 {"appearance", required_argument, 0, 'a'},
420 {"help", no_argument, 0, 'h'},
421 {0, 0, 0, 0}
423 while (1) {
424 c = getopt_long(argc, argv, "a:bd:fhn", long_options, &option_index);
425 if (c == -1)
426 break;
427 switch (c) {
428 case 0: /* If blink or noblink was toggled */
429 break;
430 case 'a':
431 strcpy(appearance, optarg);
432 break;
433 case 'b':
434 blink = 1;
435 break;
436 case 'd':
437 delay = atoi(optarg);
438 break;
439 case 'f':
440 mode = FIRE;
441 break;
442 case 'h':
443 print_usage();
444 exit(0);
445 case 'n':
446 mode = NORMAL;
447 break;
448 case '?':
449 break;
450 default:
451 print_usage();
452 exit(1);
458 void
459 print_usage()
462 printf("\nwmfsm version: %s\n", WMFSM_VERSION);
463 printf("\nusage: wmfsm \n");
464 printf("\t--normal, -n\t\tDraw bars in normal mode.\n");
465 printf("\t--fire, -f\t\t\tDraw bars in fire mode.\n");
466 printf("\t--[no]blink\t\tBlinks if a filesystem is 95 percent full.\n");
467 printf("\t-display <Display>\tUse alternate X display.\n");
468 printf("\t--delay <number>, -d\tUse a delay that is not the default.\n");
469 printf("\t--appearance <file>, -a\tSelect an appearance file.\n");
470 printf("\t-h\t\t\tDisplay help screen.\n");
473 void
474 pressEvent(XButtonEvent * xev)
476 (void)xev;
477 ForceUpdate = 1;
478 return;
481 void
482 readFileSystems()
484 /* Wipe mp[] */
485 int i;
486 for (i = 0; i < 100; i++)
487 if (mp[i]) {
488 free(mp[i]);
489 mp[i]=0;
492 /* Look for the goods between #if defined(__OpenBSD__) -- tschroed */
493 #if defined(__OpenBSD__) || defined(__FreeBSD__)
494 #define MAXMOUNT 32
495 struct statfs sfs[MAXMOUNT];
496 int fscount;
498 /* OpenBSD has no /etc/mtab, we use getfsstat instead -- tschroed */
499 if ((fscount = getfsstat(sfs, sizeof(sfs), 0)) == -1) {
500 perror("getfsstat");
501 exit(1);
503 for (numberfs = 0; numberfs < fscount; numberfs++)
504 /* We won't watch RO mounts. */
505 if (sfs[numberfs].f_flags & MNT_RDONLY) {
506 numberfs--;
507 fscount--;
509 else
510 mp[numberfs] = strdup(sfs[numberfs].f_mntonname);
511 #else /* __OpenBSD__ || __FreeBSD__ */
513 FILE *fp;
514 char mountPoint[255], dummy[255], fstype[255], options[255];
516 #if defined(SunOS)
517 /* Solaris uses /etc/mnttab */
518 fp = fopen("/etc/mnttab", "r");
519 if (!fp) {
520 fprintf(stderr, "%s:Can't open /etc/mnttab for reading\n", myName);
521 exit(1);
523 #else
524 fp = fopen("/etc/mtab", "r");
525 if (!fp) {
526 fprintf(stderr, "%s:Can't open /etc/mtab for reading\n", myName);
527 exit(1);
529 #endif
531 numberfs = 0;
532 while (!feof(fp) && numberfs < 100) {
533 #if defined(SunOS)
534 /* only five entries per row in /etc/mnttab */
535 if (fscanf(fp, "%s %s %s %s %s\n", dummy, mountPoint, fstype, options, dummy) < 5)
536 fprintf(stderr, "%s:/etc/mnttab not in expected format\n", myName);
537 #else
538 if (fscanf(fp, "%s %s %s %s %s %s\n", dummy, mountPoint, fstype, options, dummy, dummy) < 6)
539 fprintf(stderr, "%s:/etc/mtab not in expected format\n", myName);
540 #endif
542 if (
543 #if defined IRIX64 || defined(SunOS)
544 strcmp(fstype, "hwgfs") && strcmp(fstype, "autofs") && strcmp(fstype, "proc") && strcmp(fstype, "fd") && !strstr(options, "ignore")
545 #elif defined linux
546 strcmp(fstype, "proc") && strcmp(fstype, "tmpfs") && strcmp(fstype, "devfs") && strcmp(fstype, "ramfs") && strcmp(fstype, "sysfs") && strcmp(fstype, "devpts") && strcmp(fstype, "usbfs")
547 #else
549 #endif
551 if (mp[numberfs]) free(mp[numberfs]);
552 mp[numberfs++] = strdup(mountPoint);
555 #endif /* __OpenBSD__ || __FreeBSD__ */
557 fclose (fp);
558 excludeFileSystems();
561 void
562 excludeFileSystems()
564 char confFileName[255];
565 char workString[255];
566 int i, j, exnumberfs = 0;
567 int excluded, finalnumberfs = 0;
568 char *mount_points[100];
569 FILE *confFile;
570 int include = -1;
571 int included = 0;
573 strncpy(confFileName, (char *) getenv("HOME"), 245);
574 strcat(confFileName, "/.wmfsmrc");
575 confFile = fopen(confFileName, "r");
576 if (confFile) {
577 while (!feof(confFile)) {
578 if (fgets(workString, 255, confFile)) {
579 if(strstr(workString, "\n")){
580 /* This is probably dangerous, but easy */
581 *(strstr(workString, "\n")) = '\0';
583 if (!strcmp(workString, "[include]")) {
584 include = 1;
586 else if (!strcmp(workString, "[exclude]")) {
587 include = 0;
589 else {
590 mount_points[exnumberfs] = strdup(workString);
591 exnumberfs++;
596 if (include < 0) {
597 printf("wmfsm: Please specify either to include or exclude filesystems.\n");
598 exit(1);
600 fclose(confFile);
602 else {
603 numberfs = numberfs > 9 ? 9 : numberfs;
604 goto CLEANUP;
606 if (!exnumberfs) {
607 numberfs = numberfs > 9 ? 9 : numberfs;
608 goto CLEANUP;
610 excluded = 0;
611 for (i = 0; i < numberfs; i++) {
612 for (j = 0, excluded = 0; j < exnumberfs; j++) {
613 if (!strcmp(mp[i], mount_points[j]) && !include) {
614 excluded = 1;
615 } else if (!strcmp(mp[i], mount_points[j]) && include) {
616 included = 1;
619 if ((!excluded && !include) || (included && include)) {
620 if (finalnumberfs == i) {
621 finalnumberfs++;
622 } else {
623 if (mp[finalnumberfs]) free(mp[finalnumberfs]);
624 mp[finalnumberfs++] = strdup(mp[i]);
627 included = excluded = 0;
629 numberfs = finalnumberfs > 9 ? 9 : finalnumberfs;
631 CLEANUP:
632 for (j = 0; j < exnumberfs; j++)
633 if (mount_points[j]) {
634 free(mount_points[j]);
635 mount_points[j]=0;