vnstat  2.9
About: vnStat is a console-based network traffic monitor (using the /proc filesystem).
  Fossies Dox: vnstat-2.9.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

vnstati.c
Go to the documentation of this file.
1/*
2vnStat image output - Copyright (C) 2007-2022 Teemu Toivola <tst@iki.fi>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 dated June, 1991.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16*/
17
18#include "common.h"
19#include "iflist.h"
20#include "dbsql.h"
21#include "image.h"
22#include "cfg.h"
23#include "misc.h"
24#include "vnstati.h"
25
26int main(int argc, char *argv[])
27{
28 int currentarg;
29 IPARAMS p;
30 IMAGECONTENT ic;
31
32 initiparams(&p);
34
35 /* early check for debug and config parameter */
36 if (argc > 1) {
37 for (currentarg = 1; currentarg < argc; currentarg++) {
38 if ((strcmp(argv[currentarg], "-D") == 0) || (strcmp(argv[currentarg], "--debug") == 0)) {
39 debug = 1;
40 printf("Debug enabled, vnstati %s, LibGD %d.%d.%d\n", VERSION, GD_MAJOR_VERSION, GD_MINOR_VERSION, GD_RELEASE_VERSION);
41 } else if (strcmp(argv[currentarg], "--config") == 0) {
42 if (currentarg + 1 < argc) {
43 strncpy_nt(p.cfgfile, argv[currentarg + 1], 512);
44 if (debug)
45 printf("Used config file: %s\n", p.cfgfile);
46 currentarg++;
47 } else {
48 printf("Error: File for --config missing.\n");
49 return 1;
50 }
51 }
52 }
53 }
54
55 /* load config if available */
56 if (!loadcfg(p.cfgfile, CT_Image)) {
57 return 1;
58 }
59 cfg.qmode = 0;
60
63 ic.current = time(NULL);
64
65 parseargs(&p, &ic, argc, argv);
66 validateinput(&p);
68 handlecaching(&p, &ic);
69 handledatabase(&p, &ic);
70
71 if (debug)
72 printf("Qmode: %d\n", cfg.qmode);
73
74 drawimage(&ic);
75 db_close();
76
77 if (ic.im == NULL) {
78 return 1;
79 }
80
81#if HAVE_DECL_GD_NEAREST_NEIGHBOUR
82 scaleimage(&ic);
83#endif
84 writeoutput(&p, &ic);
85
86 if (debug)
87 printf("all done\n");
88
89 return 0;
90}
91
93{
94 db = NULL;
95 noexit = 0; /* allow functions to exit in case of error */
96 debug = 0; /* debug disabled by default */
97 disableprints = 0; /* let prints be visible */
98
99 p->interface[0] = '\0';
100 p->filename[0] = '\0';
101 p->cfgfile[0] = '\0';
102 p->cache = 0;
103 p->help = 0;
104 p->limit = -1;
105}
106
108{
109 printf("vnStat image output %s by Teemu Toivola <tst at iki dot fi>\n\n", getversion());
110
111 printf(" -5, --fiveminutes [limit] output 5 minutes\n");
112 printf(" -5g, --fivegraph [limit] [height] output 5 minutes graph\n");
113 printf(" -h, --hours [limit] output hours\n");
114 printf(" -hg, --hoursgraph output hours graph\n");
115 printf(" -d, --days [limit] output days\n");
116 printf(" -m, --months [limit] output months\n");
117 printf(" -y, --years [limit] output years\n");
118 printf(" -t, --top [limit] output top days\n");
119 printf(" -s, --summary output summary\n");
120 printf(" -hs, --hsummary [graph] output horizontal summary with graph\n");
121 printf(" -vs, --vsummary [graph] output vertical summary with graph\n\n");
122
123 printf(" -nh, --noheader remove header from output\n");
124 printf(" -ne, --noedge remove edge from output\n");
125 printf(" -nl, --nolegend remove legend from output\n");
126 printf(" -ru, --rateunit [mode] swap configured rate unit\n");
127 printf(" -S, --small use small fonts");
128 if (!cfg.largefonts) {
129 printf(" (default)");
130 }
131 printf("\n");
132 printf(" -L, --large use large fonts");
133 if (cfg.largefonts) {
134 printf(" (default)");
135 }
136 printf("\n");
137 printf(" -o, --output <file> select output filename\n");
138 printf(" -c, --cache <minutes> update output only when too old\n");
139 printf(" -i, --iface <interface> select interface");
140 if (strlen(p->interface)) {
141 printf(" (default: %s)", p->interface);
142 }
143 printf("\n");
144 printf(" -b, --begin <date> set list begin date\n");
145 printf(" -e, --end <date> set list end date\n");
146 printf(" -?, --help this help\n");
147 printf(" -D, --debug show some additional debug information\n");
148 printf(" -v, --version show version\n");
149 printf(" --limit <limit> set list entry limit\n");
150 printf(" --dbdir <directory> select database directory\n");
151 printf(" --style <mode> select output style (0-3)\n");
152 printf(" --locale <locale> set locale\n");
153 printf(" --config <config file> select config file\n");
154 printf(" --altdate use alternative date location\n");
155 printf(" --headertext <text> specify header text string\n");
156#if HAVE_DECL_GD_NEAREST_NEIGHBOUR
157 printf(" --scale <percent> change image size by scaling it\n");
158#endif
159 printf(" --transparent [enabled] toggle background transparency\n\n");
160
161 printf("See also \"man vnstati\".\n");
162}
163
164void parseargs(IPARAMS *p, IMAGECONTENT *ic, int argc, char **argv)
165{
166 int currentarg;
167
168 /* parse parameters */
169 for (currentarg = 1; currentarg < argc; currentarg++) {
170 if (debug)
171 printf("arg %d: \"%s\"\n", currentarg, argv[currentarg]);
172 if ((strcmp(argv[currentarg], "-?") == 0) || (strcmp(argv[currentarg], "--help")) == 0) {
173 p->help = 1;
174 } else if ((strcmp(argv[currentarg], "-i") == 0) || (strcmp(argv[currentarg], "--iface")) == 0 || (strcmp(argv[currentarg], "--interface") == 0)) {
175 if (currentarg + 1 < argc) {
176 if (strlen(argv[currentarg + 1]) > 31) {
177 printf("Error: Interface name is limited to 31 characters.\n");
178 exit(EXIT_FAILURE);
179 }
180 strncpy_nt(p->interface, argv[currentarg + 1], 32);
181 if (debug)
182 printf("Used interface: \"%s\"\n", p->interface);
183 currentarg++;
184 } else {
185 printf("Error: Interface for %s missing.\n", argv[currentarg]);
186 exit(EXIT_FAILURE);
187 }
188 } else if ((strcmp(argv[currentarg], "-o") == 0) || (strcmp(argv[currentarg], "--output")) == 0) {
189 if (currentarg + 1 < argc) {
190 strncpy_nt(p->filename, argv[currentarg + 1], 512);
191 if (debug)
192 printf("Output file: \"%s\"\n", p->filename);
193 currentarg++;
194 } else {
195 printf("Error: Filename for %s missing.\n", argv[currentarg]);
196 exit(EXIT_FAILURE);
197 }
198 } else if ((strcmp(argv[currentarg], "-c") == 0) || (strcmp(argv[currentarg], "--cache")) == 0) {
199 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
200 p->cache = atoi(argv[currentarg + 1]);
201 if (debug)
202 printf("Cache time: %d minutes\n", p->cache);
203 currentarg++;
204 } else {
205 printf("Error: Parameter for %s missing or invalid.\n", argv[currentarg]);
206 exit(EXIT_FAILURE);
207 }
208 } else if ((strcmp(argv[currentarg], "--style")) == 0) {
209 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
210 cfg.ostyle = atoi(argv[currentarg + 1]);
211 if (cfg.ostyle > 3 || cfg.ostyle < 0) {
212 printf("Error: Invalid style parameter \"%d\" for --style.\n", cfg.ostyle);
213 exit(EXIT_FAILURE);
214 }
215 if (debug)
216 printf("Style changed: %d\n", cfg.ostyle);
217 currentarg++;
218 } else {
219 printf("Error: Style parameter for --style missing.\n");
220 exit(EXIT_FAILURE);
221 }
222 } else if ((strcmp(argv[currentarg], "--scale")) == 0) {
223#if HAVE_DECL_GD_NEAREST_NEIGHBOUR
224 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
225 cfg.imagescale = atoi(argv[currentarg + 1]);
226 if (cfg.imagescale > 500 || cfg.imagescale < 50) {
227 printf("Error: Invalid parameter \"%d\" for --scale. Supported value range: 50 <= N <= 500\n", cfg.imagescale);
228 exit(EXIT_FAILURE);
229 }
230 if (debug)
231 printf("Scale changed: %d\n", cfg.imagescale);
232 currentarg++;
233 } else {
234 printf("Error: Percent parameter for --scale missing.\n");
235 exit(EXIT_FAILURE);
236 }
237#else
238 printf("Error: Function needed by --scale is not available in used LibGD %d.%d.%d.\n", GD_MAJOR_VERSION, GD_MINOR_VERSION, GD_RELEASE_VERSION);
239 exit(EXIT_FAILURE);
240#endif
241 } else if ((strcmp(argv[currentarg], "--transparent")) == 0) {
242 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
243 cfg.transbg = atoi(argv[currentarg + 1]);
244 if (cfg.transbg > 1 || cfg.transbg < 0) {
245 printf("Error: Invalid parameter \"%d\" for --transparent.\n", cfg.transbg);
246 exit(EXIT_FAILURE);
247 }
248 if (debug)
249 printf("Transparency changed: %d\n", cfg.transbg);
250 currentarg++;
251 } else {
253 if (debug)
254 printf("Transparency changed: %d\n", cfg.transbg);
255 }
256 } else if ((strcmp(argv[currentarg], "--dbdir")) == 0) {
257 if (currentarg + 1 < argc) {
258 strncpy_nt(cfg.dbdir, argv[currentarg + 1], 512);
259 if (debug)
260 printf("DatabaseDir: \"%s\"\n", cfg.dbdir);
261 currentarg++;
262 } else {
263 printf("Error: Directory for --dbdir missing.\n");
264 exit(EXIT_FAILURE);
265 }
266 } else if ((strcmp(argv[currentarg], "--locale")) == 0) {
267 if (currentarg + 1 < argc) {
268 setlocale(LC_ALL, argv[currentarg + 1]);
269 if (debug)
270 printf("Locale: \"%s\"\n", argv[currentarg + 1]);
271 currentarg++;
272 } else {
273 printf("Error: Locale for --locale missing.\n");
274 exit(EXIT_FAILURE);
275 }
276 } else if (strcmp(argv[currentarg], "--config") == 0) {
277 /* config has already been parsed earlier so nothing to do here */
278 currentarg++;
279 } else if ((strcmp(argv[currentarg], "--headertext")) == 0) {
280 if (currentarg + 1 < argc) {
281 strncpy_nt(ic->headertext, argv[currentarg + 1], 65);
282 if (debug)
283 printf("Header text: \"%s\"\n", ic->headertext);
284 currentarg++;
285 } else {
286 printf("Error: Text string parameter for --headertext missing.\n");
287 exit(EXIT_FAILURE);
288 }
289 } else if (strcmp(argv[currentarg], "--altdate") == 0) {
290 ic->altdate = 1;
291 } else if ((strcmp(argv[currentarg], "-L") == 0) || (strcmp(argv[currentarg], "--large")) == 0) {
292 cfg.largefonts = 1;
293 } else if ((strcmp(argv[currentarg], "-S") == 0) || (strcmp(argv[currentarg], "--small")) == 0) {
294 cfg.largefonts = 0;
295 } else if ((strcmp(argv[currentarg], "-D") == 0) || (strcmp(argv[currentarg], "--debug")) == 0) {
296 debug = 1;
297 } else if ((strcmp(argv[currentarg], "-d") == 0) || (strcmp(argv[currentarg], "--days")) == 0) {
298 cfg.qmode = 1;
299 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
300 cfg.listdays = atoi(argv[currentarg + 1]);
301 if (cfg.listdays < 0) {
302 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
303 exit(EXIT_FAILURE);
304 }
305 currentarg++;
306 }
307 } else if ((strcmp(argv[currentarg], "-m") == 0) || (strcmp(argv[currentarg], "--months")) == 0) {
308 cfg.qmode = 2;
309 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
310 cfg.listmonths = atoi(argv[currentarg + 1]);
311 if (cfg.listmonths < 0) {
312 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
313 exit(EXIT_FAILURE);
314 }
315 currentarg++;
316 }
317 } else if ((strcmp(argv[currentarg], "-t") == 0) || (strcmp(argv[currentarg], "--top")) == 0) {
318 cfg.qmode = 3;
319 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
320 cfg.listtop = atoi(argv[currentarg + 1]);
321 if (cfg.listtop < 0) {
322 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
323 exit(EXIT_FAILURE);
324 }
325 currentarg++;
326 }
327 } else if ((strcmp(argv[currentarg], "-y") == 0) || (strcmp(argv[currentarg], "--years")) == 0) {
328 cfg.qmode = 4;
329 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
330 cfg.listyears = atoi(argv[currentarg + 1]);
331 if (cfg.listyears < 0) {
332 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
333 exit(EXIT_FAILURE);
334 }
335 currentarg++;
336 }
337 } else if ((strcmp(argv[currentarg], "-h") == 0) || (strcmp(argv[currentarg], "--hours")) == 0) {
338 cfg.qmode = 8;
339 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
340 cfg.listhours = atoi(argv[currentarg + 1]);
341 if (cfg.listhours < 0) {
342 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
343 exit(EXIT_FAILURE);
344 }
345 currentarg++;
346 }
347 } else if ((strcmp(argv[currentarg], "-5") == 0) || (strcmp(argv[currentarg], "--fiveminutes")) == 0) {
348 cfg.qmode = 9;
349 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
350 cfg.listfivemins = atoi(argv[currentarg + 1]);
351 if (cfg.listfivemins < 0) {
352 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
353 exit(EXIT_FAILURE);
354 }
355 currentarg++;
356 }
357 } else if ((strcmp(argv[currentarg], "-s") == 0) || (strcmp(argv[currentarg], "--summary")) == 0) {
358 cfg.qmode = 5;
359 } else if ((strcmp(argv[currentarg], "-hg") == 0) || (strcmp(argv[currentarg], "--hoursgraph") == 0) || (strcmp(argv[currentarg], "--hourlygraph")) == 0) {
360 cfg.qmode = 7;
361 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
362 if (!isdigit(argv[currentarg + 1][0]) || atoi(argv[currentarg + 1]) > 1 || atoi(argv[currentarg + 1]) < 0) {
363 if (!ishelprequest(argv[currentarg + 1]))
364 printf("Error: Invalid mode selection \"%s\".\n", argv[currentarg + 1]);
365 printf(" Valid modes for %s:\n", argv[currentarg]);
366 printf(" 0 - 24 hour sliding windows\n");
367 printf(" 1 - graph start from midnight\n");
368 exit(EXIT_FAILURE);
369 }
370 cfg.hourlygmode = atoi(argv[currentarg + 1]);
371 if (debug)
372 printf("Hourly graph mode changed: %d\n", cfg.hourlygmode);
373 currentarg++;
374 }
375 } else if ((strcmp(argv[currentarg], "-5g") == 0) || (strcmp(argv[currentarg], "--fivegraph")) == 0) {
376 cfg.qmode = 10;
377 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
378 cfg.fivegresultcount = atoi(argv[currentarg + 1]);
380 printf("Error: Invalid limit parameter \"%s\" for %s. A value equal or over %d is expected.\n", argv[currentarg + 1], argv[currentarg], FIVEGMINRESULTCOUNT);
381 exit(EXIT_FAILURE);
382 } else if (cfg.fivegresultcount > cfg.fiveminutehours * 12) {
383 printf("Error: Invalid limit parameter \"%s\" for %s. Value cannot be larger than configured data retention (5MinuteHours %d * 12 = %d).\n", argv[currentarg + 1], argv[currentarg], cfg.fiveminutehours, cfg.fiveminutehours * 12);
384 exit(EXIT_FAILURE);
385 }
386 currentarg++;
387 }
388 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
389 cfg.fivegheight = atoi(argv[currentarg + 1]);
391 printf("Error: Invalid height parameter \"%s\" for %s. A value equal or over %d is expected.\n", argv[currentarg + 1], argv[currentarg], FIVEGMINHEIGHT);
392 exit(EXIT_FAILURE);
393 }
394 currentarg++;
395 }
396 } else if ((strcmp(argv[currentarg], "-hs") == 0) || (strcmp(argv[currentarg], "--hsummary")) == 0) {
397 cfg.qmode = 51;
398 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
399 if (!isdigit(argv[currentarg + 1][0]) || atoi(argv[currentarg + 1]) > 1 || atoi(argv[currentarg + 1]) < 0) {
400 if (!ishelprequest(argv[currentarg + 1]))
401 printf("Error: Invalid graph selection \"%s\".\n", argv[currentarg + 1]);
402 printf(" Valid graphs for %s:\n", argv[currentarg]);
403 printf(" 0 - hours\n");
404 printf(" 1 - 5 minutes\n");
405 exit(EXIT_FAILURE);
406 }
407 cfg.summarygraph = atoi(argv[currentarg + 1]);
408 if (debug)
409 printf("Summary graph changed: %d\n", cfg.summarygraph);
410 currentarg++;
411 }
412 } else if ((strcmp(argv[currentarg], "-vs") == 0) || (strcmp(argv[currentarg], "--vsummary")) == 0) {
413 cfg.qmode = 52;
414 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
415 if (!isdigit(argv[currentarg + 1][0]) || atoi(argv[currentarg + 1]) > 1 || atoi(argv[currentarg + 1]) < 0) {
416 if (!ishelprequest(argv[currentarg + 1]))
417 printf("Error: Invalid graph selection \"%s\".\n", argv[currentarg + 1]);
418 printf(" Valid graphs for %s:\n", argv[currentarg]);
419 printf(" 0 - hours\n");
420 printf(" 1 - 5 minutes\n");
421 exit(EXIT_FAILURE);
422 }
423 cfg.summarygraph = atoi(argv[currentarg + 1]);
424 if (debug)
425 printf("Summary graph changed: %d\n", cfg.summarygraph);
426 currentarg++;
427 }
428 } else if ((strcmp(argv[currentarg], "-nh") == 0) || (strcmp(argv[currentarg], "--noheader")) == 0) {
429 ic->showheader = 0;
430 } else if ((strcmp(argv[currentarg], "-ne") == 0) || (strcmp(argv[currentarg], "--noedge")) == 0) {
431 ic->showedge = 0;
432 } else if ((strcmp(argv[currentarg], "-nl") == 0) || (strcmp(argv[currentarg], "--nolegend")) == 0) {
433 ic->showlegend = 0;
434 } else if ((strcmp(argv[currentarg], "-ru") == 0) || (strcmp(argv[currentarg], "--rateunit")) == 0) {
435 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
436 if (!isdigit(argv[currentarg + 1][0]) || atoi(argv[currentarg + 1]) > 1 || atoi(argv[currentarg + 1]) < 0) {
437 if (!ishelprequest(argv[currentarg + 1]))
438 printf("Error: Invalid parameter \"%s\".\n", argv[currentarg + 1]);
439 printf(" Valid parameters for %s:\n", argv[currentarg]);
440 printf(" 0 - bytes\n");
441 printf(" 1 - bits\n");
442 exit(EXIT_FAILURE);
443 }
444 cfg.rateunit = atoi(argv[currentarg + 1]);
445 if (debug)
446 printf("Rateunit changed: %d\n", cfg.rateunit);
447 currentarg++;
448 } else {
450 if (debug)
451 printf("Rateunit changed: %d\n", cfg.rateunit);
452 }
453 } else if ((strcmp(argv[currentarg], "-b") == 0) || (strcmp(argv[currentarg], "--begin") == 0)) {
454 if (currentarg + 1 < argc) {
455 if (!validatedatetime(argv[currentarg + 1])) {
456 printf("Error: Invalid date format, expected YYYY-MM-DD HH:MM, YYYY-MM-DD or \"today\".\n");
457 exit(EXIT_FAILURE);
458 }
459 strncpy_nt(ic->databegin, argv[currentarg + 1], 18);
460 currentarg++;
461 } else {
462 printf("Error: Date of format YYYY-MM-DD HH:MM, YYYY-MM-DD or \"today\" for %s missing.\n", argv[currentarg]);
463 exit(EXIT_FAILURE);
464 }
465 } else if ((strcmp(argv[currentarg], "-e") == 0) || (strcmp(argv[currentarg], "--end") == 0)) {
466 if (currentarg + 1 < argc) {
467 if (!validatedatetime(argv[currentarg + 1])) {
468 printf("Error: Invalid date format, expected YYYY-MM-DD HH:MM or YYYY-MM-DD.\n");
469 exit(EXIT_FAILURE);
470 }
471 strncpy_nt(ic->dataend, argv[currentarg + 1], 18);
472 currentarg++;
473 } else {
474 printf("Error: Date of format YYYY-MM-DD HH:MM or YYYY-MM-DD for %s missing.\n", argv[currentarg]);
475 exit(EXIT_FAILURE);
476 }
477 } else if (strcmp(argv[currentarg], "--limit") == 0) {
478 if (currentarg + 1 < argc && isdigit(argv[currentarg + 1][0])) {
479 p->limit = atoi(argv[currentarg + 1]);
480 if (p->limit < 0) {
481 printf("Error: Invalid limit parameter \"%s\" for %s. Only a zero and positive numbers are allowed.\n", argv[currentarg + 1], argv[currentarg]);
482 exit(EXIT_FAILURE);
483 }
484 currentarg++;
485 } else {
486 printf("Error: Invalid or missing parameter for %s.\n", argv[currentarg]);
487 exit(EXIT_FAILURE);
488 }
489 } else if ((strcmp(argv[currentarg], "-v") == 0) || (strcmp(argv[currentarg], "--version")) == 0) {
490 printf("vnStat image output %s by Teemu Toivola <tst at iki dot fi> (LibGD %d.%d.%d)\n", getversion(), GD_MAJOR_VERSION, GD_MINOR_VERSION, GD_RELEASE_VERSION);
491 exit(EXIT_SUCCESS);
492 } else {
493 if (argv[currentarg][0] == '-') {
494 printf("Unknown parameter \"%s\". Use --help for help.\n", argv[currentarg]);
495 exit(EXIT_FAILURE);
496 } else {
497 if (strlen(argv[currentarg]) > 31) {
498 printf("Error: Interface name is limited to 31 characters.\n");
499 exit(EXIT_FAILURE);
500 }
501 strncpy_nt(p->interface, argv[currentarg], 32);
502 if (debug)
503 printf("Used interface: \"%s\"\n", p->interface);
504 }
505 }
506 }
507
508 if (p->help || argc == 1) {
509 showihelp(p);
510 exit(EXIT_SUCCESS);
511 }
512
513 if (p->limit != -1) {
515 }
516
517 if (cfg.largefonts) {
518 ic->font = gdFontGetLarge();
519 ic->lineheight = 16;
520 ic->large = 1;
521 } else {
522 ic->font = gdFontGetSmall();
523 ic->lineheight = 12;
524 ic->large = 0;
525 }
526}
527
529{
530 if (!cfg.qmode || !strlen(p->filename)) {
531 printf("At least output mode and file parameter needs to be given. ");
532 printf("Use -? or --help for getting short help.\n");
533 exit(EXIT_FAILURE);
534 }
535}
536
538{
539 struct stat filestat;
540
541 if (p->cache == 0 || p->filename[0] == '-') {
542 return;
543 }
544
545 if (stat(p->filename, &filestat) == 0) {
546 if ((ic->current - filestat.st_mtime) < (p->cache * 60)) {
547 if (debug)
548 printf("Using cached file (%d<%d).\n", (int)(ic->current - filestat.st_mtime), p->cache * 60);
549 exit(EXIT_SUCCESS);
550 }
551 } else {
552 /* abort if error is something else than file not found */
553 if (errno != ENOENT) {
554 printf("Error: Getting status for file \"%s\" failed: %s (%d)\n", p->filename, strerror(errno), errno);
555 exit(EXIT_FAILURE);
556 }
557 }
558}
559
561{
562 int i, found = 0;
563 iflist *dbifl = NULL;
564
565 if (!db_open_ro()) {
566 printf("Error: Failed to open database \"%s/%s\" in read-only mode.\n", cfg.dbdir, DATABASEFILE);
567 exit(EXIT_FAILURE);
568 }
569 if (strlen(p->interface)) {
571 if (strchr(p->interface, '+') == NULL) {
572 for (i = 1; i <= cfg.ifacematchmethod; i++) {
573 found = db_setinterfacebyalias(p->interface, p->interface, i);
574 if (found) {
575 if (debug) {
576 printf("Found \"%s\" with method %d\n", p->interface, i);
577 }
578 break;
579 }
580 }
581 if (!found) {
582 printf("Error: No interface matching \"%s\" found in database.\n", p->interface);
583 exit(EXIT_FAILURE);
584 }
585 } else {
586 printf("Error: Not all requested interfaces found in database or given interfaces aren't unique.\n");
587 exit(EXIT_FAILURE);
588 }
589 }
590 } else {
591 if (db_getiflist_sorted(&dbifl, 1) <= 0) {
592 printf("Error: Unable to discover suitable interface from database.\n");
593 exit(EXIT_FAILURE);
594 }
595 strncpy_nt(p->interface, dbifl->interface, 32);
596 iflistfree(&dbifl);
597 if (debug)
598 printf("Automatically selected interface: \"%s\"\n", p->interface);
599 }
600 if (!db_getinterfaceinfo(p->interface, &ic->interface)) {
601 printf("Error: Failed to fetch interface \"%s\" details from database.\n", p->interface);
602 exit(EXIT_FAILURE);
603 }
604}
605
607{
608#if HAVE_DECL_GDIMAGEFILE
609 /* not output to stdout */
610 if (!(strlen(p->filename) == 1 && p->filename[0] == '-')) {
611 if (!gdSupportsFileType(p->filename, 1)) {
612 printf("Error: Image format file extension for \"%s\" is not supported or recognized\n\n", p->filename);
613 showsupportedfileextensions();
614 exit(EXIT_FAILURE);
615 }
616 }
617#else
618 /* show warning if given filename doesn't end with .png when gdImageFile() isn't available */
619 if (!(strlen(p->filename) >= 4 && strcmp(p->filename + strlen(p->filename) - 4, ".png") == 0)) {
620 printf("Warning: Image format selection based on file extension is not available in used LibGD %d.%d.%d, \"%s\" will be written as png.\n", GD_MAJOR_VERSION, GD_MINOR_VERSION, GD_RELEASE_VERSION, p->filename);
621 }
622#endif
623}
624
626{
627 if (ic->im == NULL) {
628 return;
629 }
630
631 /* output to stdout is always png */
632 if (strlen(p->filename) == 1 && p->filename[0] == '-') {
633 if ((p->pngout = fdopen(1, "w")) == NULL) {
634 printf("Error: Opening stdout for output failed: %s\n", strerror(errno));
635 exit(EXIT_FAILURE);
636 }
637 gdImagePng(ic->im, p->pngout);
638 fclose(p->pngout);
639 } else {
640#if HAVE_DECL_GDIMAGEFILE
641 /* avoid "Palette image not supported by webp" */
642 if (strlen(p->filename) >= 5 && strcmp(p->filename + strlen(p->filename) - 5, ".webp") == 0) {
643 gdImagePaletteToTrueColor(ic->im);
644 }
645 if (!gdImageFile(ic->im, p->filename)) {
646 printf("Error: Writing output to \"%s\" failed: %s\n", p->filename, strerror(errno));
647 exit(EXIT_FAILURE);
648 }
649#else
650 if ((p->pngout = fopen(p->filename, "w")) == NULL) {
651 printf("Error: Opening file \"%s\" for output failed: %s\n", p->filename, strerror(errno));
652 exit(EXIT_FAILURE);
653 }
654 gdImagePng(ic->im, p->pngout);
655 fclose(p->pngout);
656#endif
657 }
658
659 gdImageDestroy(ic->im);
660}
661
662#if HAVE_DECL_GDIMAGEFILE
663void showsupportedfileextensions(void)
664{
665 int i;
666 const char *extensions[] = {".avif", ".bmp", ".gif", ".heif", ".heix", ".jpeg", ".jpg", ".png", ".tga", ".tif", ".tiff", ".wbmp", ".webp", ".xbm", ".xpm"};
667
668 printf("Supported image format file extensions in current environment:\n");
669
670 for (i = 0; i < 15; i++) {
671 if (gdSupportsFileType(extensions[i], 1)) {
672 printf("%s ", extensions[i]);
673 }
674 }
675 printf("\n");
676}
677#endif
void configlocale(void)
Definition: cfg.c:549
int loadcfg(const char *cfgfile, const ConfigType type)
Definition: cfg.c:4
@ CT_Image
Definition: cfg.h:16
int noexit
Definition: common.c:9
int disableprints
Definition: common.c:12
int debug
Definition: common.c:8
char * getversion(void)
Definition: common.c:285
CFG cfg
Definition: common.c:4
char * strncpy_nt(char *dest, const char *src, size_t n)
Definition: common.c:253
#define DATABASEFILE
Definition: common.h:72
#define FIVEGMINRESULTCOUNT
Definition: common.h:277
#define FIVEGMINHEIGHT
Definition: common.h:278
int db_close(void)
Definition: dbsql.c:248
int db_open_ro(void)
Definition: dbsql.c:11
uint64_t db_getinterfacecountbyname(const char *iface)
Definition: dbsql.c:419
int db_getiflist_sorted(iflist **ifl, const int orderbytraffic)
Definition: dbsql.c:771
int db_setinterfacebyalias(char *iface, const char *alias, const int matchmethod)
Definition: dbsql.c:527
sqlite3 * db
Definition: dbsql.c:7
int db_getinterfaceinfo(const char *iface, interfaceinfo *info)
Definition: dbsql.c:651
void iflistfree(iflist **ifl)
Definition: iflist.c:43
void initimagecontent(IMAGECONTENT *ic)
Definition: image.c:8
void drawimage(IMAGECONTENT *ic)
Definition: image.c:25
int ishelprequest(const char *arg)
Definition: misc.c:553
int validatedatetime(const char *str)
Definition: misc.c:357
int32_t summarygraph
Definition: common.h:318
int32_t listfivemins
Definition: common.h:324
int32_t listtop
Definition: common.h:324
int32_t listjsonxml
Definition: common.h:324
int32_t imagescale
Definition: common.h:316
char iface[32]
Definition: common.h:308
char dbdir[512]
Definition: common.h:310
int32_t transbg
Definition: common.h:315
int32_t listmonths
Definition: common.h:324
int32_t fivegheight
Definition: common.h:318
int32_t ifacematchmethod
Definition: common.h:314
int32_t fiveminutehours
Definition: common.h:323
int32_t qmode
Definition: common.h:314
int32_t ostyle
Definition: common.h:315
int32_t largefonts
Definition: common.h:317
int32_t listdays
Definition: common.h:324
int32_t listyears
Definition: common.h:324
int32_t fivegresultcount
Definition: common.h:317
int32_t hourlygmode
Definition: common.h:318
int32_t listhours
Definition: common.h:324
int32_t rateunit
Definition: common.h:314
int showedge
Definition: image.h:26
gdFontPtr font
Definition: image.h:23
int large
Definition: image.h:27
time_t current
Definition: image.h:29
interfaceinfo interface
Definition: image.h:24
gdImagePtr im
Definition: image.h:22
char dataend[18]
Definition: image.h:28
int altdate
Definition: image.h:26
char databegin[18]
Definition: image.h:28
char headertext[65]
Definition: image.h:28
int showlegend
Definition: image.h:26
int showheader
Definition: image.h:26
int lineheight
Definition: image.h:27
Definition: vnstati.h:4
char cfgfile[512]
Definition: vnstati.h:7
char interface[32]
Definition: vnstati.h:7
FILE * pngout
Definition: vnstati.h:8
int help
Definition: vnstati.h:5
int32_t limit
Definition: vnstati.h:6
char filename[512]
Definition: vnstati.h:7
int cache
Definition: vnstati.h:5
Definition: iflist.h:4
char interface[32]
Definition: iflist.h:5
int main(int argc, char *argv[])
Definition: vnstati.c:26
void validateinput(IPARAMS *p)
Definition: vnstati.c:528
void handlecaching(IPARAMS *p, IMAGECONTENT *ic)
Definition: vnstati.c:537
void handledatabase(IPARAMS *p, IMAGECONTENT *ic)
Definition: vnstati.c:560
void writeoutput(IPARAMS *p, IMAGECONTENT *ic)
Definition: vnstati.c:625
void initiparams(IPARAMS *p)
Definition: vnstati.c:92
void showihelp(IPARAMS *p)
Definition: vnstati.c:107
void parseargs(IPARAMS *p, IMAGECONTENT *ic, int argc, char **argv)
Definition: vnstati.c:164
void validateoutput(IPARAMS *p)
Definition: vnstati.c:606