1 /*
2 
3  wminet.c
4  Multi-function system monitor
5  by Dave Clark (clarkd@skynet.ca) (http://www.neotokyo.org/illusion)
6  Martijn Pieterse (pieterse@xs4all.nl) (http://windowmaker.mezaway.org)
7  and Antoine Nulle (warp@xs4all.nl) (http://windowmaker.mezaway.org)
8 
9  This software is licensed through the GNU General Public Lisence.
10 
11  ProFTPD support by Mike Kershaw aka Dragorn (dragorn@melchior.nerv-un.ml.org)
12  ProFTPD support was made 64bit clean by Martijn Pieterse (pieterse@xs4all.nl)
13 
14  see http://windowmaker.mezaway.org for more awesome wm dock apps :)
15 
16 */
17 
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <time.h>
22 #include <string.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <ctype.h>
26 
27 #include <sys/wait.h>
28 #include <sys/stat.h>
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 
34 #include <dirent.h>
35 
36 #include <X11/Xlib.h>
37 #include <X11/xpm.h>
38 #include <X11/extensions/shape.h>
39 
40 #include "../wmgeneral/wmgeneral.h"
41 #include "../wmgeneral/misc.h"
42 
43 #include "wmscript-master.xpm"
44 char wminet_mask_bits[64*64];
45 int  wminet_mask_width = 64;
46 int  wminet_mask_height = 64;
47 
48 #define WMSCRIPT_VERSION "1.0"
49 
50 #define CHAR_WIDTH 5
51 #define CHAR_HEIGHT 7
52 
53 // Lame work-around... Sigh... when will they standardize the headers!?!?
54 #define TCP_ESTABLISHED 1
55 
56 extern	char **environ;
57 
58 char	*ProgName;
59 
60 int loopinterval=1;
61 
62 typedef struct
63 {
64     int pos;
65     char script[256];
66     char label[10];
67     char action[256];
68     int interval;
69     int value;
70 } script_t;
71 script_t scripts[6];
72 
73 int timers[6];
74 
75 char uconfig_file[256];
76 
77 void usage(void);
78 void printversion(void);
79 void BlitString(char *name, int x, int y);
80 void BlitNum(int num, int x, int y);
81 void GetStats(int script);
82 void wminet_routine(int, char **);
83 int ReadConfigInt(FILE *fp, char *setting, int *value);
84 int ReadConfigString(FILE *fp, char *setting, char *value);
85 int Read_Config_File( char *filename );
86 int RunScript(const char* script);
87 char *GetAction(const int pos, char *action);
88 void CreateDisplay();
89 void debug(const char* buff);
90 void debugi(const int val);
91 
92 
main(int argc,char * argv[])93 int main(int argc, char *argv[]) {
94 
95 	int		i;
96 
97     uconfig_file[0] = 0;
98 
99 	/* Parse Command Line */
100 
101 	ProgName = argv[0];
102 	if (strlen(ProgName) >= 5)
103 		ProgName += (strlen(ProgName) - 5);
104 
105 	for (i=1; i<argc; i++) {
106 		char *arg = argv[i];
107 
108 		if (*arg=='-') {
109 			switch (arg[1]) {
110 			case 'd' :
111 				if (strcmp(arg+1, "display")) {
112 					usage();
113 					exit(1);
114 				}
115 				break;
116 			case 'g' :
117 				if (strcmp(arg+1, "geometry")) {
118 					usage();
119 					exit(1);
120 				}
121 				break;
122 			case 'v' :
123 				printversion();
124 				exit(0);
125 				break;
126             case 'c' :
127                 if (argc > (i+1))
128                 {
129                     strcpy(uconfig_file, argv[i+1]);
130                     i++;
131                 }
132                 break;
133             default:
134 				usage();
135 				exit(0);
136 				break;
137 			}
138 		}
139 	}
140 
141 	wminet_routine(argc, argv);
142 
143 	return 0;
144 }
145 
146 /*******************************************************************************\
147 |* wminet_routine														   *|
148 \*******************************************************************************/
149 
wminet_routine(int argc,char ** argv)150 void wminet_routine(int argc, char **argv)
151 {
152     int			i;
153 	XEvent		Event;
154 	int			but_stat = -1;
155 
156     time_t		curtime;
157 	time_t		prevtime;
158 
159     char config_file[512];
160 
161     memset(&scripts, 0, sizeof(scripts));
162     memset(&timers, 0, sizeof(timers));
163 
164 	createXBMfromXPM(wminet_mask_bits, wminet_master_xpm, wminet_mask_width, wminet_mask_height);
165 
166 	openXwindow(argc, argv, wminet_master_xpm, wminet_mask_bits, wminet_mask_width, wminet_mask_height);
167 
168 	AddMouseRegion(0, 5, 6, 58, 16);
169 	AddMouseRegion(1, 5, 16, 58, 26);
170 	AddMouseRegion(2, 5, 26, 58, 36);
171 	AddMouseRegion(3, 5, 36, 58, 46);
172 	AddMouseRegion(4, 5, 46, 58, 56);
173 
174     // Read config file
175 
176     if (uconfig_file[0] != 0)
177     {
178         // user-specified config file
179         fprintf(stderr, "Using user-specified config file '%s'.\n", uconfig_file);
180         Read_Config_File(uconfig_file);
181     }
182     else
183     {
184         sprintf(config_file, "%s/.wmscriptrc", getenv("HOME"));
185 
186         if (!Read_Config_File(config_file))
187         {
188             // Fall back to /etc/wmscriptrc
189             sprintf(config_file, "/etc/wmscriptrc");
190 
191             Read_Config_File(config_file);
192         }
193     }
194 
195     // Initial display
196     GetStats(0);
197     CreateDisplay();
198     RedrawWindow();
199 
200     prevtime = time(0) - 1;
201 
202     while (1)
203     {
204 		curtime = time(0);
205 		waitpid(0, NULL, WNOHANG);
206 
207         if ( curtime >= prevtime + loopinterval)
208         {
209             int loop;
210             prevtime = curtime;
211 
212             for (loop = 1;loop<6;loop++)
213             {
214                 timers[loop]++;
215 
216                 if (timers[loop] >= scripts[loop].interval)
217                 {
218                     timers[loop] = 0;
219                     // Get data to display
220                     GetStats(loop);
221                     CreateDisplay();
222                     RedrawWindow();
223                 }
224             }
225         }
226 
227         // X Events
228         while (XPending(display))
229         {
230 			XNextEvent(display, &Event);
231             switch (Event.type)
232             {
233 			case Expose:
234 				RedrawWindow();
235 				break;
236 			case DestroyNotify:
237 				XCloseDisplay(display);
238 				exit(0);
239                 break;
240 			case ButtonPress:
241 				i = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
242 
243 				but_stat = i;
244 				break;
245 			case ButtonRelease:
246 				i = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
247 
248                 if (but_stat == i && but_stat >= 0)
249                 {
250                     char action[256];
251                     execCommand(GetAction(but_stat+1, action));
252 				}
253 				but_stat = -1;
254 //				RedrawWindow();
255 				break;
256 			}
257 		}
258 
259 		usleep(100000L);
260 	}
261 }
262 
263 // runs the script specified by the number passed in, zero for all
GetStats(int script)264 void GetStats(int script)
265 {
266     int loop, loop_start, loop_stop;
267 
268     if (script == 0)
269     {
270         loop_start = 1;
271         loop_stop = 6;
272     }
273     else
274     {
275         loop_start = script;
276         loop_stop = script+1;
277     }
278 
279     for (loop = loop_start; loop<loop_stop;loop++)
280     {
281         if (scripts[loop].pos != 0)
282         {
283             char script[256];
284             int len, ret;
285 
286             len = strlen(scripts[loop].script);
287 
288             strncpy(script, scripts[loop].script, len);
289             script[len] = '\0';
290 
291             ret = RunScript (script);
292 
293             scripts[loop].value = ret;
294 
295         }
296     }
297 }
298 
299 
300 // Blits a string at given co-ordinates
BlitString(char * name,int x,int y)301 void BlitString(char *name, int x, int y)
302 {
303     int		i;
304 	int		c;
305     int		k;
306 
307 	k = x;
308     for (i=0; name[i]; i++)
309     {
310 
311         c = toupper(name[i]);
312         if (c >= 'A' && c <= 'Z')
313         {   // its a letter
314 			c -= 'A';
315 			copyXPMArea(c * 6, 74, 6, 8, k, y);
316 			k += 6;
317         }
318         else
319         {   // its a number or symbol
320 			c -= '0';
321 			copyXPMArea(c * 6, 64, 6, 8, k, y);
322 			k += 6;
323 		}
324 	}
325 
326 }
327 
328 
329 // Blits number to give coordinates.. two 0's, right justified
330 
BlitNum(int num,int x,int y)331 void BlitNum(int num, int x, int y)
332 {
333     char buf[1024];
334     int newx=x;
335 
336     if (num > 99)
337     {
338         newx -= CHAR_WIDTH;
339     }
340 
341     if (num > 999)
342     {
343         num = 999;
344     }
345 
346     sprintf(buf, "%02i", num);
347 
348     BlitString(buf, newx, y);
349 }
350 
351 
352 // ReadConfigSetting
ReadConfigString(FILE * fp,char * setting,char * value)353 int ReadConfigString(FILE *fp, char *setting, char *value)
354 {
355     char str[1024];
356     char buf[1024];
357     int i;
358     int len;
359     int slen;
360     char *p=NULL;
361 
362     if (!fp)
363     {
364         return 0;
365     }
366 
367     sprintf(str, "%s=", setting);
368     slen = strlen(str);
369 
370     fseek(fp, 0, SEEK_SET);
371 
372     while ( !feof(fp) )
373     {
374 
375         if (!fgets(buf, 512, fp))
376             break;
377 
378         len = strlen(buf);
379 
380         // strip linefeed
381         for (i=0; i!=len; i++)
382         {
383             if (buf[i] == '\n')
384             {
385                 buf[i] = 0;
386             }
387         }
388 
389         //printf("Scanning '%s'...\n", buf);
390         if ( strncmp(buf, str, strlen(str)) == 0)
391         {
392             // found our setting
393 
394             for(i=0; i!=slen; i++)
395             {
396                 if ( buf[i] == '=' )
397                 {
398                     p=buf+i+1;
399                     strcpy(value, p);
400                     return 1;
401                 }
402             }
403 
404         }
405     }
406 
407         return 0;
408 }
409 
ReadConfigInt(FILE * fp,char * setting,int * value)410 int ReadConfigInt(FILE *fp, char *setting, int *value)
411 {
412     char buf[1024];
413 
414 
415     if (ReadConfigString(fp, setting, (char *) &buf))
416     {
417         *value = atoi(buf);
418         return 1;
419     }
420 
421     return 0;
422 }
423 
Read_Config_File(char * filename)424 int Read_Config_File( char *filename )
425 {
426     FILE *fp;
427 
428     fp = fopen(filename, "r");
429     if (fp)
430     {
431         int loop;
432 
433         for (loop = 1; loop<6;loop++)
434         {
435             char pos[15], script[15], label[15], action[15], interval[17];
436             sprintf(pos,"script%d.pos",loop);
437             sprintf(script,"script%d.script",loop);
438             sprintf(label,"script%d.label",loop);
439             sprintf(action,"script%d.action",loop);
440             sprintf(interval,"script%d.interval",loop);
441 
442             ReadConfigInt(fp, pos, &scripts[loop].pos);
443             ReadConfigString(fp, script, scripts[loop].script);
444             ReadConfigString(fp, label, scripts[loop].label);
445             ReadConfigString(fp, action, scripts[loop].action);
446             ReadConfigInt(fp, interval, &scripts[loop].interval);
447         }
448 
449         fclose(fp);
450         return 1;
451     }
452     else
453     {
454         perror("Read_Config_File");
455         fprintf(stderr, "Unable to open %s, no settings read.\n", filename);
456         return 0;
457     }
458 
459 }
460 
461 
RunScript(const char * script)462 int RunScript(const char* script)
463 {
464     int ret = -1, loop;
465     FILE *proc;
466     char buff[256];
467     char ch = '\0';
468 
469     memset (buff, 0, 255);
470 
471     proc = popen(script, "r");
472 
473     if (proc != NULL)
474     {
475         for (loop = 0; loop<255 && ch != EOF;loop++)
476         {
477             ch = getc(proc);
478             if (ch != EOF)
479                 buff[loop] = ch;
480         }
481 
482         pclose (proc);
483     }
484     ret = atoi(buff);
485 
486     return ret;
487 }
488 
GetAction(const int pos,char * action)489 char *GetAction(const int pos, char *action)
490 {
491     int loop;
492 
493     for (loop = 1; loop<6;loop++)
494     {
495 
496         if (pos == scripts[loop].pos)
497         {
498             strcpy(action, scripts[loop].action);
499         }
500     }
501 
502     return action;
503 
504 }
505 
506 /*******************************************************************************\
507 |* usage																	   *|
508 \*******************************************************************************/
509 
usage(void)510 void usage(void)
511 {
512     fprintf(stderr, "\nWMScript - Darren Greaves <darren@magma.dircon.co.uk>, illusion <clarkd@skyia.com>, warp <warp@xs4all.nl>\n         & tijno <pieterse@xs4all.nl>\n\n");
513 	fprintf(stderr, "usage:\n");
514 	fprintf(stderr, "    -display <display name>\n");
515 	fprintf(stderr, "    -geometry +XPOS+YPOS      initial window position\n");
516     fprintf(stderr, "    -c <filename>             use specified config file\n");
517     fprintf(stderr, "    -h                        this help screen\n");
518 	fprintf(stderr, "    -v                        print the version number\n");
519 	fprintf(stderr, "\n");
520 }
521 
522 /*******************************************************************************\
523 |* printversion																   *|
524 \*******************************************************************************/
525 
printversion(void)526 void printversion(void)
527 {
528 	fprintf(stderr, "wmscript v%s\n", WMSCRIPT_VERSION);
529 }
530 
debug(const char * buff)531 void debug(const char* buff)
532 {
533     fprintf (stderr, buff);
534     fprintf (stderr, "\n");
535 }
536 
debugi(const int val)537 void debugi(const int val)
538 {
539     char buff[256];
540 
541     sprintf (buff, "%d",val);
542 
543     fprintf (stderr, buff);
544     fprintf (stderr, "\n");
545 }
546 
CreateDisplay()547 void CreateDisplay()
548 {
549     char buf[64];
550     int	i,j,k;
551 
552     for (i=1; i<6; i++)
553     {
554         for (j=1; j<6; j++)
555         {
556             if ( i == scripts[j].pos )
557             {
558                 strncpy(buf, scripts[j].label, 5);
559 
560                 for (k=0; k<5; k++)
561                 {
562                     if (buf[k] == 0)
563                         buf[k] = ' ';
564                 }
565 
566                 buf[5] = ':';
567                 buf[6] = 0;
568 
569                 BlitString(buf, 5, (11*(i-1)) + 5);
570                 copyXPMArea(39, 84, (3*CHAR_WIDTH), 8, 39, (11*(i-1)) + 5);
571                 BlitNum(scripts[j].value, 45, (11*(i-1)) + 5);
572             }
573         }
574     }
575 }
576