1/*
2 *  Name:         Main cas file
3 *
4 *  Purpose:      aMule Statistics
5 *
6 *  Author:       Pedro de Oliveira <falso@rdk.homeip.net>
7 *
8 *  Copyright (c) 2004-2011 Pedro de Oliveira ( falso@rdk.homeip-net )
9 *
10 *  This file is part of aMule.
11 *
12 *  This program is free software; you can redistribute it and/or modify
13 *  it under the terms of the GNU General Public License as published by
14 *  the Free Software Foundation; either version 2 of the License, or
15 *  (at your option) any later version.
16 *
17 *  This program is distributed in the hope that it will be useful,
18 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 *  GNU General Public License for more details.
21 *
22 *  You should have received a copy of the GNU General Public License
23 *  along with this program; if not, write to the
24 *  Free Software Foundation, Inc.,
25 *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
26 */
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <unistd.h>
33#include <time.h>
34#include <getopt.h>
35
36#include "version.h"
37#include "configfile.h"
38#include "functions.h"
39#include "graphics.h"
40#include "html.h"
41#include "lines.h"
42
43#ifdef HAVE_CONFIG_H
44	#include "config.h"	// For HAVE_GETOPT_LONG
45#endif
46
47#ifndef HAVE_GETOPT_LONG
48/* Code from getopt_long.h - getopt_long() for systems that lack it
49  Copyright (c) 2001-2011 Arthur de Jong, GPL 2 and later */
50# define no_argument 0
51# define required_argument 1
52# define optional_argument 2
53
54struct option {
55	const char *name;
56	int has_arg;
57	int *flag;
58	int val;
59};
60
61int getopt_long(int argc,
62		char * const argv[],
63		const char *optstring,
64		const struct option *longopts,
65		int *longindex);
66#endif
67
68/*
69 * History:
70 *
71 * ????.??.?? - falso: creation of cas.
72 * ????.??.?? - Jacobo221: Detect connecting state
73 * ????.??.?? - falso: HTML page generation
74 * 2004.08.27 - GonoszTopi: New line handling routines, to cope with lines
75 *		longer than 80 characters. Fixes buffer overflow.
76 * 2005.12.10 - fulgas: added kad info support
77 * 2005,12,16 - stefanero: fixed Kad related stuff and some other things
78 */
79
80static struct option long_options[] = {
81	{ "help", no_argument, NULL, 'h' },
82	{ "html", optional_argument, NULL, 'p' },
83	{ "picture", optional_argument, NULL, 'o' },
84	{ "config-dir", required_argument, NULL, 'c' },
85	{ NULL, 0, NULL, 0 }
86};
87
88void usage(char *myname)
89{
90	printf	("   ___    _ _   ___    c aMule statistics\n"
91			" /'___) /'_` )/',__)   by Pedro de Oliveira\n"
92			"( (___ ( (_| |\\__, \\   <falso@rdk.homeip.net>\n"
93			"`\\____)`\\__,_)(____/   Version %s\n\n"
94
95			"Usage: %s [OPTION]\n"
96			"If run without any option prints stats to stdout\n\n"
97			"OPTIONS:\n"
98#ifdef __GD__
99			"-o, --picture, -P\tWrites the online signature picture\n"
100#endif
101			"-p, --html, -H\t\tHTML Page with stats and picture\n"
102			"-c, --config-dir\tSpecifies a config-dir different from home\n"
103			"-h, --help\t\tThis help you're reading\n", CAS_VERSION, myname);
104}
105
106#ifndef HAVE_GETOPT_LONG
107
108/* Code from getopt_long.c - getopt_long() for systems that lack it
109  Copyright (c) 2001-2011 Arthur de Jong, GPL 2 and later
110  Slightly edited for the sake of clarity by Gaznevada */
111
112int getopt_long(int argc,
113                char * const argv[],
114                const char *optstring,
115                const struct option *longopts,
116                int *longindex)
117{
118int i;
119int length;
120if ( (optind > 0) && (optind < argc) &&
121     (strncmp(argv[optind],"--",2) == 0) &&
122     (argv[optind][2] != '\0') ) {
123        for (i = 0; longopts[i].name != NULL; i++) {
124                length = strlen(longopts[i].name);
125                if (strncmp(argv[optind]+2,longopts[i].name,length) == 0) {
126                        if ( (longopts[i].has_arg == no_argument) && (argv[optind][2+length] == '\0') ) {
127                                optind++;
128                                return longopts[i].val;
129                        }
130                else if ( (longopts[i].has_arg == required_argument) && (argv[optind][2+length] == '=') ) {
131                        optarg=argv[optind]+3+length;
132                        optind++;
133                        return longopts[i].val;
134                        }
135                else if ( (longopts[i].has_arg == required_argument) && (argv[optind][2+length] == '\0') ) {
136                        optarg=argv[optind+1];
137                        optind+=2;
138                        return longopts[i].val;
139                        }
140                else if ( (longopts[i].has_arg == optional_argument) && (argv[optind][2+length] == '=') ) {
141                        optarg=argv[optind]+3+length;
142                        optind++;
143                        return longopts[i].val;
144                        }
145                else if ( (longopts[i].has_arg==optional_argument) && (argv[optind][2+length] == '\0') ) {
146                        optind++;
147                        return longopts[i].val;
148                        }
149                }
150        }
151}
152return getopt(argc,argv,optstring);
153}
154
155#endif // HAVE_GETOPT_LONG
156
157int main(int argc, char *argv[])
158{
159	/* Declaration of variables */
160	FILE *amulesig;
161	int use_out_pic = 0;
162	int use_page = 0;
163	char *config_path=NULL;
164	char *path;
165	char *stats[20];
166	char *lines[IMG_TEXTLINES];
167	long lSize;
168	char * buffer;
169	int i;
170	int c;
171	int errflag = 0;
172	char *path_for_picture=NULL;
173	char *path_for_html=NULL;
174	CONF config;
175	time_t lt;
176	struct tm *ltp;
177	char arr[20];
178
179	while ((c = getopt_long (argc, argv, "c:P:H:hpo", long_options, NULL)) != -1)
180
181		switch (c)
182		{
183		case 'c':
184			config_path=optarg;
185			break;
186		case 'h':
187			usage(argv[0]);
188			exit(0);
189		case 'H':
190		case 'p':
191			use_page=1;
192			if (optarg != NULL) {
193				path_for_html = optarg;
194			}
195			break;
196		case 'P':
197		case 'o':
198			use_out_pic=1;
199			if (optarg != NULL) {
200				path_for_picture = optarg;
201			}
202			break;
203		case '?':
204			errflag++;
205		}
206		if (errflag) {
207			usage(argv[0]);
208               		exit (2);
209          	}
210
211	/* get amulesig path */
212
213	path = get_amule_path("amulesig.dat", 1, config_path);
214
215	if (path == NULL) {
216		perror("Unable to get aMule settings path\n");
217		exit(1);
218	}
219
220	/* open the file and if not exists exit with an error */
221	if ((amulesig = fopen(path, "r")) == NULL) {
222		fprintf(stderr, "Unable to open file %s\nCheck if you have amule online signature enabled.\n", path);
223		exit(2);
224	}
225	/* i believe this shouldnt be here.
226	The freq of update could be higher than 60 seconds.
227	And it doesn't mean that the amule is not running.
228	*/
229	/*
230	else {
231		struct stat s_file;
232		if ( stat(path, &s_file) == 0 ) {
233			time_t t_now = time(0);
234			if ( (t_now - s_file.st_mtime) > 60 ) {
235				perror("aMule online signature last updated more then 60 sec ago\n");
236				perror("Check that your aMule is running\n");
237			}
238		}
239	}*/
240	free(path);
241
242	/* initialize all the strings with nothing */
243	for (i = 0; i <= 19; i++)
244		stats[i] = 0;
245
246	/* start reading the stuff from amulesign to the stats array */
247	// obtain file size.
248	fseek (amulesig , 0 , SEEK_END);
249	lSize = ftell (amulesig);
250	if (0 == lSize) {
251		perror("aMule signature file is 0 Byte, exiting.\n");
252		exit(2);
253	}
254	rewind (amulesig);
255	buffer = (char*) malloc (lSize);
256	if (buffer == NULL) {
257		perror("Could not create buffer\n");
258		exit (2);
259	}
260	if (fread(buffer,1,lSize,amulesig)){}	// // prevent GCC warning
261	fclose(amulesig);
262
263	stats[0] = strtok (buffer,"\n");
264	for (i=1;i<17;i++) {
265		stats[i] = strtok (NULL,"\n");
266		if (NULL == stats[i]) {
267			perror("Too few fields in aMule signature file, exiting.\n");
268			exit(2);
269		}
270	}
271
272	// local time stored as stats[17]
273	lt = time(NULL);
274	ltp = localtime(&lt);
275	strftime(arr, 20, "%b %d %Y, %H:%M", ltp);
276
277	// if amule isn't running say that and exit else print out the stuff
278
279	// if amule uptime is 0, then its not running...
280	if (strncmp(stats[16],"0",1) == 0 ) {
281		perror("aMule is not running\n");
282		exit(3);
283	}
284
285
286	if (strncmp(stats[0],"2",1) == 0)
287		CreateLine(lines, 0 ,"aMule %s is connecting\n", stats[13]);
288	else
289		CreateLine(lines, 0, "aMule %s has been running for %s\n",
290				stats[13], timeconv(stats[16]));
291
292
293
294	if (strncmp(stats[0],"0",1) == 0 && strncmp(stats[5],"0",1) == 0)
295		CreateLine(lines, 1, "%s is not connected ", stats[10]);
296	else if (strncmp(stats[0],"0",1) == 0 && strncmp(stats[5],"0",1) != 0)
297		CreateLine(lines, 1, "%s is connected to ", stats[10]);
298	else
299		CreateLine(lines, 1, "%s is connected to %s [%s:%s] with ", stats[10],
300			stats[1], stats[2], stats[3]);
301
302
303	if (strncmp(stats[5],"2",1) == 0) {
304		if (strncmp(stats[4],"H",1) == 0)
305			AppendToLine(lines, 1, "HighID | Kad: ok \n");
306		else if (strncmp(stats[4],"L",1) == 0)
307                        AppendToLine(lines, 1, "LowID | Kad: ok \n");
308		else
309			AppendToLine(lines, 1, "Kad: ok \n");
310	} else if (strncmp(stats[5],"1",1) == 0) {
311		if (strncmp(stats[4],"H",1) == 0)
312			AppendToLine(lines, 1, "HighID | Kad: firewalled \n");
313		else if (strncmp(stats[4],"L",1) == 0)
314                        AppendToLine(lines, 1, "LowID | Kad: firewalled \n");
315        	else
316			AppendToLine(lines, 1, "Kad: firewalled \n");
317	} else {
318		if (strncmp(stats[4],"H",1) == 0)
319			AppendToLine(lines, 1, "HighID | Kad: off \n");
320		else if (strncmp(stats[4],"L",1) == 0)
321                        AppendToLine(lines, 1, "LowID | Kad: off \n");
322		else
323			AppendToLine(lines, 1, "but running\n");
324	}
325
326	stats[11] = strdup(convbytes(stats[11]));
327	stats[12] = strdup(convbytes(stats[12]));
328
329	CreateLine(lines, 2, "Total Download: %s, Upload: %s\n",stats[11] , stats[12]);
330
331	stats[15] = strdup(convbytes(stats[15]));
332	stats[14] = strdup(convbytes(stats[14]));
333
334	CreateLine(lines, 3, "Session Download: %s, Upload: %s\n",stats[14], stats[15]);
335
336	CreateLine(lines, 4, "Download: %s kB/s, Upload: %s kB/s\n", stats[6], stats[7]);
337
338	CreateLine(lines, 5, "Sharing: %s file(s), Clients on queue: %s\n", stats[9] , stats[8]);
339
340	CreateLine(lines, 6, "Time: %s\n", arr);
341
342#ifdef __GD__
343	if (use_out_pic == 1) {
344		if (!readconfig(&config)) {
345			perror("Could not read config file\n");
346			exit(4);
347		}
348
349		if (!createimage(&config, lines, path_for_picture)) {
350			perror("Could not create image!\n");
351			exit(5);
352		}
353		exit(0);
354	}
355#endif
356
357	if (use_page == 1) {
358
359		if (!readconfig(&config)) {
360			perror("Could not read config file\n");
361			exit(4);
362		}
363
364		if (!create_html(stats,lines,config.template, path_for_html)) {
365			perror("Could not create the HTML Page.\n");
366		}
367
368#ifdef __GD__
369		if (!createimage(&config, lines, path_for_picture)) {
370			perror("Could not create image!\n");
371			exit(5);
372		}
373#endif
374
375
376		exit(0);
377	}
378	for (i = 0; i <= 6; i++) {
379		printf("%s", lines[i]);
380		free(lines[i]);
381	}
382	free(buffer);
383	exit(0);
384}
385
386