1 /*==============================================================================
2
3 M A I N . C
4
5 This is the main module for the 'wmnet' project.This code was
6 originally based on the 'wmifs' project done by Martijn Pieterse
7 (pieterse @ xs4all.nl).I was going to originally port his code, but
8 since most of the guts was Linux - specific, I really only ended up
9 using the X windows code.
10
11 main.c,v 1.15 1999/01/30 05:32:23 rneswold Exp
12 ==============================================================================*/
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <ctype.h>
16 #include <string.h>
17 #include <unistd.h>
18
19 #include <X11/Xlib.h>
20 #include <X11/xpm.h>
21
22 #include "wmnet.h"
23 #include "wmgeneral.h"
24 #include "wmnet-master.xpm"
25 #include "wmnet-mask.xbm"
26
27 #define LED_NET_1 (1)
28 #define LED_NET_2 (2)
29 #define LED_NET_3 (3)
30
31 #define LED_SZE_X (4)
32 #define LED_SZE_Y (4)
33
34 #define LED_ON_NET_X (87)
35 #define LED_ON_NET_Y (92)
36 #define LED_OFF_NET_X (93)
37 #define LED_OFF_NET_Y (92)
38 #define LED_ERR_NET_X (81)
39 #define LED_ERR_NET_Y (92)
40
41 #define LED_PWR_X (53)
42 #define LED_PWR_Y (7)
43 #define LED_SND_X (47)
44 #define LED_SND_Y (7)
45 #define LED_RCV_X (41)
46 #define LED_RCV_Y (7)
47
48 /* Function prototypes... */
49
50 static void DrawActiveIFS(char const *);
51 static void DrawStats(unsigned, int, int, int);
52 static unsigned findInterface(char const*);
53 static void printversion(void);
54 static char const *rateToStr(unsigned long);
55 static double getRate(unsigned long, char *);
56 static void SetErrLED(int);
57 static void SetOffLED(int);
58 static void SetOnLED(int);
59 static void usage(void);
60 static void wmnet_routine(int, char **);
61
62 /* Local variables... */
63
64 static char* active_interface = NULL;
65 static int delay = 1;
66
67 /*------------------------------------------------------------------------------
68 DrawActiveIFS
69 ------------------------------------------------------------------------------*/
DrawActiveIFS(char const * name)70 static void DrawActiveIFS(char const* name)
71 {
72 copyXPMArea(5, 110, 30, 10, 5, 5);
73
74 if (name) {
75 int ii, kk = 5;
76
77 for (ii = 0; name[ii]; ++ii) {
78 int const ch = toupper(name[ii]);
79
80 if (ch >= 'A' && ch <= 'Z')
81 copyXPMArea((ch - 'A') * 6, 100, 6, 9, kk, 5);
82 else
83 copyXPMArea((ch - '0') * 6, 90, 6, 9, kk, 5);
84 kk += 6;
85 }
86 }
87 }
88
89 /*------------------------------------------------------------------------------
90 DrawStats
91 ------------------------------------------------------------------------------*/
DrawStats(unsigned ifCurr,int height,int x_left,int y_bottom)92 static void DrawStats(unsigned ifCurr, int height, int x_left, int y_bottom)
93 {
94 unsigned baseLine = y_bottom - height / 2;
95 unsigned maxVal = 0, ii, currVal = 0;
96 char const* ptr = 0;
97
98 /* Find the maximum value. We'll scale the graph to this value. */
99 unsigned long rcv, xmt;
100
101 for (ii = 0; ii < G_WIDTH; ++ii) {
102
103 ifGetData(ifCurr, ii, &xmt, &rcv);
104
105 xmt /= delay;
106 rcv /= delay;
107 currVal = xmt > rcv ? xmt : rcv ;
108 if (currVal > maxVal)
109 maxVal = currVal;
110 }
111
112 /* Now draw the data points. */
113
114 for (ii = 0; ii < G_WIDTH; ++ii) {
115 unsigned long rcv, xmt;
116 unsigned long start = baseLine, stop = baseLine;
117 int jj;
118
119 if (maxVal > 0) {
120 ifGetData(ifCurr, ii, &xmt, &rcv);
121 xmt /= delay;
122 rcv /= delay;
123 start = baseLine + (xmt * height) / (2 * maxVal);
124 stop = baseLine - (rcv * height) / (2 * maxVal);
125 }
126 for (jj = 0; jj < height; ++jj)
127 if (y_bottom - jj <= start && y_bottom - jj >= stop)
128 copyXPMArea(99 + 1, 106, 1, 1, ii + x_left, y_bottom - jj);
129 else
130 copyXPMArea(99, 106, 1, 1, ii + x_left, y_bottom - jj);
131
132 /* Draw the base line. */
133
134 copyXPMArea(100, 106, 1, 1, ii + x_left, baseLine);
135 }
136
137 /* Now draw the download data rate... */
138
139 /* Clear area */
140 copyXPMArea( 6, 111, 54 , 9 , 6, 63);
141
142 ptr = rateToStr(rcv);
143 copyXPMArea(('D' - 'A') * 6, 100, 6, 9, 6,
144 62);
145 copyXPMArea(64, 90, 4, 9, 12,
146 62);
147 for (ii = 20; *ptr; ++ptr)
148 if (isdigit(*ptr)) {
149 copyXPMArea((*ptr - '0') * 6, 90, 6, 9, 1 + ii, 62 );
150 ii += 6;
151 } else if ('.' == *ptr) {
152 copyXPMArea(60, 90, 4, 9, 1 + ii, 62);
153 ii += 4;
154 } else {
155 copyXPMArea((toupper(*ptr) - 'A') * 6, 100, 6, 9, 1 + ii,
156 62);
157 ii += 6;
158 }
159
160 /* Now draw the upload data rate... */
161
162 /* Clear area */
163 copyXPMArea( 6, 111, 54 , 9 , 6, 76);
164
165 ptr = rateToStr(xmt);
166 copyXPMArea(('U' - 'A') * 6, 100, 6, 9, 6,
167 75);
168 copyXPMArea(64, 90, 4, 9, 12,
169 75);
170 for (ii = 20; *ptr; ++ptr)
171 if (isdigit(*ptr)) {
172 copyXPMArea((*ptr - '0') * 6, 90, 6, 9, 1 + ii, 75 );
173 ii += 6;
174 } else if ('.' == *ptr) {
175 copyXPMArea(60, 90, 4, 9, 1 + ii, 75);
176 ii += 4;
177 } else {
178 copyXPMArea((toupper(*ptr) - 'A') * 6, 100, 6, 9, 1 + ii,
179 75);
180 ii += 6;
181 }
182
183 /* Finally, update the LEDs. */
184
185 if (ifIsUp(ifCurr))
186 SetOnLED(LED_NET_1);
187 else
188 SetOffLED(LED_NET_1);
189
190 if (ifIsRunning(ifCurr))
191 SetOnLED(LED_NET_2);
192 else
193 SetOffLED(LED_NET_2);
194
195 if (ifIsPromisc(ifCurr))
196 SetErrLED(LED_NET_3);
197 else
198 SetOffLED(LED_NET_3);
199 }
200
201 /*------------------------------------------------------------------------------
202 findInterface
203
204 This function attempt to find the indicated interface. It returns the
205 index of the interface, or zero if the interface isn't found.
206 ------------------------------------------------------------------------------*/
findInterface(char const * name)207 static unsigned findInterface(char const* name)
208 {
209 unsigned ii;
210
211 /* Since strcasecmp doesn't like NULL pointers, make sure we don't
212 pass one to it. */
213
214 if (name)
215 for (ii = 0; ii < ifTotal(); ++ii)
216 if (!strcasecmp(name, ifName(ii)))
217 return ii;
218 return 0;
219 }
220
221 /*------------------------------------------------------------------------------
222 printversion
223 ------------------------------------------------------------------------------*/
printversion(void)224 static void printversion(void)
225 {
226 fprintf(stderr, "wmnet, v1p2\n");
227 }
228
229 /*------------------------------------------------------------------------------
230 rateToStr
231
232 Converts a data rate into its string representation.The string is
233 saved in a static buffer which is overwritten for each call.
234 ------------------------------------------------------------------------------*/
rateToStr(unsigned long rate)235 static char const* rateToStr(unsigned long rate)
236 {
237 static char buffer[14];
238 char scaleFactor='\0', *ptr = buffer;
239
240 double drate = getRate(rate,&scaleFactor);
241
242 /* Transform the rate value into a left - justified string. */
243 ptr+=sprintf(ptr,"%.1f",drate);
244 *ptr++ = scaleFactor;
245 *ptr = '\0';
246 return buffer;
247 }
248
249 /*------------------------------------------------------------------------------
250 getRate
251 ------------------------------------------------------------------------------*/
getRate(unsigned long rate,char * scaleFactor)252 static double getRate(unsigned long rate, char *scaleFactor)
253 {
254 double drate = rate;
255
256 /* Based upon its magnitude, determine how much 'rate' needs to be
257 scaled and also indicate its unit of scale. */
258
259 if (rate > 1048576) {
260 drate /= 1048576;
261 *scaleFactor = 'M';
262 } else if (rate > 1024) {
263 drate /= 1024;
264 *scaleFactor = 'K';
265 }
266 return drate;
267 }
268
269 /*------------------------------------------------------------------------------
270 SetErrLED
271 ------------------------------------------------------------------------------*/
SetErrLED(int led)272 static void SetErrLED(int led)
273 {
274 if (LED_NET_3 == led)
275 copyXPMArea(LED_ERR_NET_X, LED_ERR_NET_Y, LED_SZE_X, LED_SZE_Y,
276 LED_PWR_X, LED_PWR_Y);
277 }
278
279 /*------------------------------------------------------------------------------
280 SetOffLED
281 ------------------------------------------------------------------------------*/
SetOffLED(int led)282 static void SetOffLED(int led)
283 {
284 int x, y;
285
286 switch (led) {
287 case LED_NET_1:
288 x = LED_RCV_X;
289 y = LED_RCV_Y;
290 break;
291
292 case LED_NET_2:
293 x = LED_SND_X;
294 y = LED_SND_Y;
295 break;
296
297 case LED_NET_3:
298 x = LED_PWR_X;
299 y = LED_PWR_Y;
300 break;
301
302 default:
303 return;
304 }
305 copyXPMArea(LED_OFF_NET_X, LED_OFF_NET_Y, LED_SZE_X, LED_SZE_Y, x, y);
306 }
307
308 /*------------------------------------------------------------------------------
309 SetOnLED
310 ------------------------------------------------------------------------------*/
SetOnLED(int led)311 static void SetOnLED(int led)
312 {
313 int x, y;
314
315 switch (led) {
316 case LED_NET_1:
317 x = LED_RCV_X;
318 y = LED_RCV_Y;
319 break;
320
321 case LED_NET_2:
322 x = LED_SND_X;
323 y = LED_SND_Y;
324 break;
325
326 case LED_NET_3:
327 x = LED_PWR_X;
328 y = LED_PWR_Y;
329 break;
330
331 default:
332 return;
333 }
334 copyXPMArea(LED_ON_NET_X, LED_ON_NET_Y, LED_SZE_X, LED_SZE_Y, x, y);
335 }
336
337 /*------------------------------------------------------------------------------
338 usage
339 ------------------------------------------------------------------------------*/
usage(void)340 static void usage(void)
341 {
342 static char const txt[] =
343 "\nwmnet, v1p2 - A network interface monitor for WindowMaker.\n\n"
344 "\t-h this help screen\n"
345 "\t-i name start with interface 'name'\n"
346 "\t-u delay seconds between samples (defaults to 1)\n"
347 "\t-geom <geometry> geometry to use\n"
348 "\t-v print the version number\n";
349
350 fputs(txt, stderr);
351 }
352
353 /*------------------------------------------------------------------------------
354 wmnet_routine
355 ------------------------------------------------------------------------------*/
wmnet_routine(int argc,char ** argv)356 static void wmnet_routine(int argc, char **argv)
357 {
358 unsigned ifCurr = findInterface(active_interface);
359 int i;
360 XEvent Event;
361 int but_stat = -1;
362
363 /* Build up our X connection. */
364
365 openXwindow(argc, argv, wmnet_master_xpm, wmnet_mask_bits,
366 wmnet_mask_width, wmnet_mask_height);
367
368 /* > Button */
369
370 AddMouseRegion(0, 5, 5, 35, 15);
371 AddMouseRegion(1, 5, 20, 58, 58);
372
373 DrawActiveIFS(ifName(ifCurr));
374 DrawStats(ifCurr, 40, 5, 58);
375 RedrawWindow();
376
377 while (1) {
378 static int count = 0;
379
380 /* After 1 second (10 * 100 milliseconds), take new samples and
381 redraw the graph. */
382
383 if (++count == 10 * delay) {
384 ifSample();
385 DrawStats(ifCurr, 40, 5, 58);
386 RedrawWindow();
387 count = 0;
388 }
389 while (XPending(display)) {
390 XNextEvent(display, &Event);
391 switch (Event.type) {
392 case Expose:
393 RedrawWindow();
394 break;
395
396 case DestroyNotify:
397 XCloseDisplay(display);
398 exit(0);
399 break;
400
401 case ButtonPress:
402 but_stat = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
403 break;
404
405 case ButtonRelease:
406 i = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
407 if (but_stat == i && !but_stat) {
408 ifCurr = (ifCurr + 1) % ifTotal();
409 DrawActiveIFS(ifName(ifCurr));
410 DrawStats(ifCurr, 40, 5, 58);
411 }
412 but_stat = -1;
413 RedrawWindow();
414 break;
415 }
416 }
417 usleep(100000L);
418 }
419 }
420
421 /*------------------------------------------------------------------------------
422 main
423 ------------------------------------------------------------------------------*/
main(int argc,char * argv[])424 int main(int argc, char *argv[])
425 {
426 int ii;
427
428 for (ii = 1; ii < argc; ++ii) {
429 char const* const arg = argv[ii];
430
431 if (*arg == '-') {
432 switch (arg[1]) {
433 case 'i':
434 if (ii + 1 < argc)
435 active_interface = argv[++ii];
436 else {
437 printf("wmnet: must specify the interface\n");
438 return 0;
439 }
440 break;
441
442 case 'u':
443 if (ii + 1 < argc) {
444 delay = atoi(argv[++ii]);
445 if (delay < 1)
446 delay = 1;
447 } else {
448 printf("wmnet: must specify a delay\n");
449 return 0;
450 }
451 break;
452
453 case 'v':
454 printversion();
455 return 0;
456
457 case 'g':
458 if (ii + 1 == argc) {
459 printf("wmnet: must specify geometry\n");
460 return 0;
461 }
462 break;
463
464 default:
465 usage();
466 return 0;
467 }
468 }
469 }
470 (void) ifInit();
471 wmnet_routine(argc, argv);
472 return 0;
473 }
474