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