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