"Fossies" - the Fresh Open Source Software Archive 
Member "vnstat-2.9/src/dbshow.c" (22 Jan 2022, 32041 Bytes) of package /linux/misc/vnstat-2.9.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "dbshow.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.8_vs_2.9.
1 #include "common.h"
2 #include "dbsql.h"
3 #include "misc.h"
4 #include "dbshow.h"
5
6 void showdb(const char *interface, int qmode, const char *databegin, const char *dataend)
7 {
8 interfaceinfo info;
9
10 if (!db_getinterfacecountbyname(interface)) {
11 return;
12 }
13
14 if (!db_getinterfaceinfo(interface, &info)) {
15 return;
16 }
17
18 if (info.created == info.updated) {
19 printf(" %s: Not enough data available yet.\n", interface);
20 return;
21 }
22
23 switch (qmode) {
24 case 0:
25 showsummary(&info, 0);
26 break;
27 case 1:
28 showlist(&info, "day", databegin, dataend);
29 break;
30 case 2:
31 showlist(&info, "month", databegin, dataend);
32 break;
33 case 3:
34 showlist(&info, "top", databegin, dataend);
35 break;
36 case 5:
37 showsummary(&info, 1);
38 break;
39 case 6:
40 showlist(&info, "year", databegin, dataend);
41 break;
42 case 7:
43 showhours(&info);
44 break;
45 case 9:
46 showoneline(&info);
47 break;
48 case 11:
49 showlist(&info, "hour", databegin, dataend);
50 break;
51 case 12:
52 showlist(&info, "fiveminute", databegin, dataend);
53 break;
54 default:
55 printf("Error: Not such query mode: %d\n", qmode);
56 break;
57 }
58 }
59
60 void showsummary(const interfaceinfo *interface, const int shortmode)
61 {
62 struct tm *d;
63 char datebuff[DATEBUFFLEN];
64 char todaystr[DATEBUFFLEN], yesterdaystr[DATEBUFFLEN];
65 char fieldseparator[8];
66 uint64_t e_rx, e_tx;
67 time_t current, yesterday;
68 dbdatalist *datalist = NULL, *datalist_i = NULL;
69 dbdatalistinfo datainfo;
70
71 timeused_debug(__func__, 1);
72
73 current = time(NULL);
74 yesterday = current - 86400;
75
76 if (interface->updated && !shortmode) {
77 strftime(datebuff, DATEBUFFLEN, DATETIMEFORMAT, localtime(&interface->updated));
78 printf("Database updated: %s\n\n", datebuff);
79 } else if (!shortmode) {
80 printf("\n");
81 }
82
83 if (!shortmode) {
84 snprintf(fieldseparator, 8, " | ");
85 indent(3);
86 } else {
87 snprintf(fieldseparator, 8, " / ");
88 indent(1);
89 }
90 if (strcmp(interface->name, interface->alias) == 0 || strlen(interface->alias) == 0) {
91 printf("%s", interface->name);
92 } else {
93 printf("%s (%s)", interface->alias, interface->name);
94 }
95 if (interface->active == 0) {
96 printf(" [disabled]");
97 }
98 if (shortmode) {
99 printf(":\n");
100 } else {
101 /* get formatted date for creation date */
102 d = localtime(&interface->created);
103 strftime(datebuff, DATEBUFFLEN, cfg.tformat, d);
104 printf(" since %s\n\n", datebuff);
105
106 indent(10);
107 printf("rx: %s", getvalue(interface->rxtotal, 1, RT_Normal));
108 indent(3);
109 printf(" tx: %s", getvalue(interface->txtotal, 1, RT_Normal));
110 indent(3);
111 printf(" total: %s\n\n", getvalue(interface->rxtotal + interface->txtotal, 1, RT_Normal));
112
113 indent(3);
114 printf("monthly\n");
115 indent(5);
116
117 if (cfg.ostyle >= 2) {
118 printf(" rx | tx | total | avg. rate\n");
119 indent(5);
120 printf("------------------------+-------------+-------------+---------------\n");
121 } else {
122 printf(" rx | tx | total\n");
123 indent(5);
124 printf("------------------------+-------------+------------\n");
125 }
126 }
127
128 if (!db_getdata(&datalist, &datainfo, interface->name, "month", 2)) {
129 printf("Error: Failed to fetch month data.\n");
130 return;
131 }
132
133 e_rx = e_tx = 0;
134 datalist_i = datalist;
135
136 while (datalist_i != NULL) {
137 indent(5);
138 d = localtime(&datalist_i->timestamp);
139 if (strftime(datebuff, DATEBUFFLEN, cfg.mformat, d) <= 8) {
140 printf("%*s %s", getpadding(9, datebuff), datebuff, getvalue(datalist_i->rx, 11, RT_Normal));
141 } else {
142 printf("%-*s %s", getpadding(11, datebuff), datebuff, getvalue(datalist_i->rx, 11, RT_Normal));
143 }
144 printf("%s%s", fieldseparator, getvalue(datalist_i->tx, 11, RT_Normal));
145 printf("%s%s", fieldseparator, getvalue(datalist_i->rx + datalist_i->tx, 11, RT_Normal));
146 if (cfg.ostyle >= 2) {
147 if (datalist_i->next == NULL && issametimeslot(LT_Month, datalist_i->timestamp, interface->updated)) {
148 if (datalist_i->rx == 0 || datalist_i->tx == 0 || (interface->updated - datalist_i->timestamp) == 0) {
149 e_rx = e_tx = 0;
150 } else {
151 e_rx = (uint64_t)((double)datalist_i->rx / (double)(mosecs(datalist_i->timestamp, interface->updated))) * (uint64_t)(dmonth(d->tm_mon) * 86400);
152 e_tx = (uint64_t)((double)datalist_i->tx / (double)(mosecs(datalist_i->timestamp, interface->updated))) * (uint64_t)(dmonth(d->tm_mon) * 86400);
153 }
154 if (shortmode && cfg.ostyle != 0) {
155 printf("%s%s", fieldseparator, getvalue(e_rx + e_tx, 11, RT_Estimate));
156 } else if (!shortmode) {
157 printf("%s%s", fieldseparator, gettrafficrate(datalist_i->rx + datalist_i->tx, mosecs(datalist_i->timestamp, interface->updated), 14));
158 }
159 } else if (!shortmode) {
160 printf(" | %s", gettrafficrate(datalist_i->rx + datalist_i->tx, dmonth(d->tm_mon) * 86400, 14));
161 }
162 }
163 printf("\n");
164 datalist_i = datalist_i->next;
165 }
166
167 if (!datalist) {
168 indent(5 + 27);
169 printf("no data available\n");
170 }
171
172 if (!shortmode) {
173 indent(5);
174 if (cfg.ostyle >= 2) {
175 printf("------------------------+-------------+-------------+---------------\n");
176 } else {
177 printf("------------------------+-------------+------------\n");
178 }
179 indent(5);
180 printf("estimated %s", getvalue(e_rx, 11, RT_Estimate));
181 printf(" | %s", getvalue(e_tx, 11, RT_Estimate));
182 printf(" | %s", getvalue(e_rx + e_tx, 11, RT_Estimate));
183 if (cfg.ostyle >= 2) {
184 printf(" |\n\n");
185 } else {
186 printf("\n\n");
187 }
188 }
189
190 dbdatalistfree(&datalist);
191
192 if (!shortmode) {
193 indent(3);
194 printf("daily\n");
195 indent(5);
196
197 if (cfg.ostyle >= 2) {
198 printf(" rx | tx | total | avg. rate\n");
199 indent(5);
200 printf("------------------------+-------------+-------------+---------------\n");
201 } else {
202 printf(" rx | tx | total\n");
203 indent(5);
204 printf("------------------------+-------------+------------\n");
205 }
206 }
207
208 /* get formatted date for today and yesterday */
209 d = localtime(¤t);
210 strftime(todaystr, DATEBUFFLEN, cfg.dformat, d);
211 d = localtime(&yesterday);
212 strftime(yesterdaystr, DATEBUFFLEN, cfg.dformat, d);
213
214 if (!db_getdata(&datalist, &datainfo, interface->name, "day", 2)) {
215 printf("Error: Failed to fetch day data.\n");
216 return;
217 }
218
219 e_rx = e_tx = 0;
220 datalist_i = datalist;
221
222 while (datalist_i != NULL) {
223 indent(5);
224 d = localtime(&datalist_i->timestamp);
225 strftime(datebuff, DATEBUFFLEN, cfg.dformat, d);
226 if (strcmp(datebuff, todaystr) == 0) {
227 snprintf(datebuff, DATEBUFFLEN, " today");
228 } else if (strcmp(datebuff, yesterdaystr) == 0) {
229 snprintf(datebuff, DATEBUFFLEN, "yesterday");
230 }
231 if (strlen(datebuff) <= 8) {
232 printf("%*s %s", getpadding(9, datebuff), datebuff, getvalue(datalist_i->rx, 11, RT_Normal));
233 } else {
234 printf("%-*s %s", getpadding(11, datebuff), datebuff, getvalue(datalist_i->rx, 11, RT_Normal));
235 }
236 printf("%s%s", fieldseparator, getvalue(datalist_i->tx, 11, RT_Normal));
237 printf("%s%s", fieldseparator, getvalue(datalist_i->rx + datalist_i->tx, 11, RT_Normal));
238 if (cfg.ostyle >= 2) {
239 if (datalist_i->next == NULL && issametimeslot(LT_Day, datalist_i->timestamp, interface->updated)) {
240 d = localtime(&interface->updated);
241 if (datalist_i->rx == 0 || datalist_i->tx == 0 || (d->tm_hour * 60 + d->tm_min) == 0) {
242 e_rx = e_tx = 0;
243 } else {
244 e_rx = (uint64_t)((double)datalist_i->rx / (double)(d->tm_hour * 60 + d->tm_min)) * 1440;
245 e_tx = (uint64_t)((double)datalist_i->tx / (double)(d->tm_hour * 60 + d->tm_min)) * 1440;
246 }
247 if (shortmode && cfg.ostyle != 0) {
248 printf("%s%s", fieldseparator, getvalue(e_rx + e_tx, 11, RT_Estimate));
249 } else if (!shortmode) {
250 printf("%s%s", fieldseparator, gettrafficrate(datalist_i->rx + datalist_i->tx, d->tm_sec + (d->tm_min * 60) + (d->tm_hour * 3600), 14));
251 }
252 } else if (!shortmode) {
253 printf(" | %s", gettrafficrate(datalist_i->rx + datalist_i->tx, 86400, 14));
254 }
255 }
256 printf("\n");
257 datalist_i = datalist_i->next;
258 }
259
260 if (!shortmode) {
261 if (!datalist) {
262 indent(5 + 27);
263 printf("no data available\n");
264 }
265 indent(5);
266 if (cfg.ostyle >= 2) {
267 printf("------------------------+-------------+-------------+---------------\n");
268 } else {
269 printf("------------------------+-------------+------------\n");
270 }
271 indent(5);
272 printf("estimated %s", getvalue(e_rx, 11, RT_Estimate));
273 printf(" | %s", getvalue(e_tx, 11, RT_Estimate));
274 printf(" | %s", getvalue(e_rx + e_tx, 11, RT_Estimate));
275 if (cfg.ostyle >= 2) {
276 printf(" |\n");
277 } else {
278 printf("\n");
279 }
280 } else {
281 printf("\n");
282 }
283
284 dbdatalistfree(&datalist);
285 timeused_debug(__func__, 0);
286 }
287
288 void showlist(const interfaceinfo *interface, const char *listname, const char *databegin, const char *dataend)
289 {
290 int32_t limit;
291 ListType listtype = LT_None;
292 int offset = 0, i = 1;
293 int estimatevisible = 0;
294 struct tm *d;
295 time_t current;
296 char datebuff[DATEBUFFLEN], daybuff[DATEBUFFLEN];
297 char titlename[16], colname[8], stampformat[64];
298 uint64_t e_rx = 0, e_tx = 0, e_secs = 0;
299 dbdatalist *datalist = NULL, *datalist_i = NULL;
300 dbdatalistinfo datainfo;
301
302 timeused_debug(__func__, 1);
303
304 if (strcmp(listname, "day") == 0) {
305 listtype = LT_Day;
306 strncpy_nt(colname, listname, 8);
307 snprintf(titlename, 16, "daily");
308 strncpy_nt(stampformat, cfg.dformat, 64);
309 limit = cfg.listdays;
310 } else if (strcmp(listname, "month") == 0) {
311 listtype = LT_Month;
312 strncpy_nt(colname, listname, 8);
313 snprintf(titlename, 16, "monthly");
314 strncpy_nt(stampformat, cfg.mformat, 64);
315 limit = cfg.listmonths;
316 } else if (strcmp(listname, "year") == 0) {
317 listtype = LT_Year;
318 strncpy_nt(colname, listname, 8);
319 snprintf(titlename, 16, "yearly");
320 strncpy_nt(stampformat, "%Y", 64);
321 limit = cfg.listyears;
322 } else if (strcmp(listname, "top") == 0) {
323 listtype = LT_Top;
324 snprintf(colname, 8, "day");
325 snprintf(titlename, 16, "top days");
326 strncpy_nt(stampformat, cfg.tformat, 64);
327 limit = cfg.listtop;
328 offset = 6;
329 } else if (strcmp(listname, "hour") == 0) {
330 listtype = LT_Hour;
331 strncpy_nt(colname, listname, 8);
332 snprintf(titlename, 16, "hourly");
333 strncpy_nt(stampformat, "%H:%M", 64);
334 limit = cfg.listhours;
335 } else if (strcmp(listname, "fiveminute") == 0) {
336 listtype = LT_5min;
337 strncpy_nt(colname, "time", 8);
338 snprintf(titlename, 16, "5 minute");
339 strncpy_nt(stampformat, "%H:%M", 64);
340 limit = cfg.listfivemins;
341 } else {
342 return;
343 }
344
345 if (limit < 0) {
346 limit = 0;
347 }
348
349 daybuff[0] = '\0';
350
351 if (!db_getdata_range(&datalist, &datainfo, interface->name, listname, (uint32_t)limit, databegin, dataend)) {
352 printf("Error: Failed to fetch %s data.\n", titlename);
353 return;
354 }
355
356 if (!datalist) {
357 printf("No %s data available", titlename);
358 if (strlen(databegin) || strlen(dataend)) {
359 printf(" for given date range");
360 }
361 printf(".\n");
362 return;
363 }
364
365 datalist_i = datalist;
366
367 if (strlen(dataend) == 0 && datainfo.count > 0 && (listtype == LT_Day || listtype == LT_Month || listtype == LT_Year)) {
368 estimatevisible = 1;
369 getestimates(&e_rx, &e_tx, listtype, interface->updated, &datalist);
370 if (cfg.estimatebarvisible && e_rx + e_tx > datainfo.max) {
371 datainfo.max = e_rx + e_tx;
372 }
373 }
374
375 if (listtype == LT_Top) {
376 if (limit > 0 && datainfo.count < (uint32_t)limit) {
377 limit = (int32_t)datainfo.count;
378 }
379 if (limit <= 0 || datainfo.count > 999) {
380 snprintf(titlename, 16, "top");
381 } else {
382 snprintf(titlename, 16, "top %d", limit);
383 }
384 current = time(NULL);
385 d = localtime(¤t);
386 strftime(daybuff, DATEBUFFLEN, stampformat, d);
387 }
388
389 printf("\n");
390 if (strcmp(interface->name, interface->alias) == 0 || strlen(interface->alias) == 0) {
391 printf(" %s", interface->name);
392 } else {
393 printf(" %s (%s)", interface->alias, interface->name);
394 }
395 if (interface->active == 0) {
396 printf(" [disabled]");
397 }
398 printf(" / %s", titlename);
399
400 if (listtype == LT_Top && (strlen(databegin))) {
401 printf(" (%s -", databegin);
402 if (strlen(dataend)) {
403 printf(" %s)", dataend);
404 } else {
405 printf(">)");
406 }
407 }
408 printf("\n\n");
409
410 if (cfg.ostyle == 3) {
411 if (listtype == LT_Top) {
412 printf(" # %8s ", colname);
413 } else {
414 indent(5);
415 printf("%8s", colname);
416 }
417 printf(" rx | tx | total | avg. rate\n");
418 if (listtype == LT_Top) {
419 printf(" -----");
420 } else {
421 indent(5);
422 }
423 printf("------------------------+-------------+-------------+---------------\n");
424 } else {
425 if (listtype == LT_Top) {
426 printf(" # %8s ", colname);
427 } else {
428 printf(" %8s", colname);
429 }
430 printf(" rx | tx | total\n");
431 if (listtype == LT_Top) {
432 printf("------");
433 }
434 printf("-------------------------+-------------+------------");
435 if (cfg.ostyle != 0) {
436 printf("---------------------");
437 if (listtype != LT_Top) {
438 printf("------");
439 }
440 }
441 printf("\n");
442 }
443
444 while (datalist_i != NULL) {
445 d = localtime(&datalist_i->timestamp);
446
447 if (listtype == LT_Hour || listtype == LT_5min) {
448 strftime(datebuff, DATEBUFFLEN, cfg.dformat, d);
449 if (strcmp(daybuff, datebuff) != 0) {
450 if (cfg.ostyle == 3) {
451 indent(4);
452 }
453 printf(" %s\n", datebuff);
454 strcpy(daybuff, datebuff);
455 }
456 }
457
458 strftime(datebuff, DATEBUFFLEN, stampformat, d);
459 if (cfg.ostyle == 3) {
460 indent(1);
461 if (listtype != LT_Top) {
462 indent(3);
463 }
464 }
465
466 if (listtype == LT_Top) {
467 if (strcmp(daybuff, datebuff) == 0) {
468 printf("> %2d ", i);
469 } else {
470 printf(" %2d ", i);
471 }
472 }
473
474 if (strlen(datebuff) <= 9 && listtype != LT_Top) {
475 printf(" %*s %s", getpadding(9, datebuff), datebuff, getvalue(datalist_i->rx, 11, RT_Normal));
476 } else {
477 printf(" %-*s %s", getpadding(11, datebuff), datebuff, getvalue(datalist_i->rx, 11, RT_Normal));
478 }
479 printf(" | %s", getvalue(datalist_i->tx, 11, RT_Normal));
480 printf(" | %s", getvalue(datalist_i->rx + datalist_i->tx, 11, RT_Normal));
481 if (cfg.ostyle == 3) {
482 if (datalist_i->next == NULL && issametimeslot(listtype, datalist_i->timestamp, interface->updated)) {
483 e_secs = getperiodseconds(listtype, datalist_i->timestamp, interface->updated, 1);
484 } else {
485 e_secs = getperiodseconds(listtype, datalist_i->timestamp, interface->updated, 0);
486 }
487 printf(" | %s", gettrafficrate(datalist_i->rx + datalist_i->tx, (time_t)e_secs, 14));
488 } else if (cfg.ostyle != 0) {
489 showbar(datalist_i->rx, datalist_i->tx, datainfo.max, 24 - offset);
490 }
491 printf("\n");
492 if (datalist_i->next == NULL) {
493 break;
494 }
495 datalist_i = datalist_i->next;
496 i++;
497 }
498 if (datainfo.count == 0) {
499 if (cfg.ostyle != 3) {
500 printf(" no data available\n");
501 } else {
502 printf(" no data available\n");
503 }
504 }
505 if (cfg.ostyle == 3) {
506 if (listtype == LT_Top) {
507 printf(" -----");
508 } else {
509 indent(5);
510 }
511 printf("------------------------+-------------+-------------+---------------\n");
512 } else {
513 if (listtype == LT_Top) {
514 printf("------");
515 }
516 printf("-------------------------+-------------+------------");
517 if (cfg.ostyle != 0) {
518 printf("---------------------");
519 if (listtype != LT_Top) {
520 printf("------");
521 }
522 }
523 printf("\n");
524 }
525
526 /* estimate or sum visible */
527 if ( (estimatevisible) ||
528 (strlen(dataend) > 0 && datainfo.count > 1 && listtype != LT_Top) ) {
529
530 if (cfg.ostyle == 3) {
531 printf(" ");
532 }
533 if (strlen(dataend) == 0) {
534 printf(" estimated %s", getvalue(e_rx, 11, RT_Estimate));
535 printf(" | %s", getvalue(e_tx, 11, RT_Estimate));
536 printf(" | %s", getvalue(e_rx + e_tx, 11, RT_Estimate));
537 } else {
538 if (datainfo.count < 100) {
539 snprintf(datebuff, DATEBUFFLEN, "sum of %" PRIu32 "", datainfo.count);
540 } else {
541 snprintf(datebuff, DATEBUFFLEN, "sum");
542 }
543 printf(" %9s %s", datebuff, getvalue(datainfo.sumrx, 11, RT_Normal));
544 printf(" | %s", getvalue(datainfo.sumtx, 11, RT_Normal));
545 printf(" | %s", getvalue(datainfo.sumrx + datainfo.sumtx, 11, RT_Normal));
546 }
547 if (cfg.ostyle == 3) {
548 printf(" |");
549 } else if (cfg.ostyle != 0 && estimatevisible && cfg.estimatebarvisible) {
550 showbar(e_rx, e_tx, datainfo.max, 24 - offset);
551 }
552 printf("\n");
553 }
554
555 dbdatalistfree(&datalist);
556 timeused_debug(__func__, 0);
557 }
558
559 void showoneline(const interfaceinfo *interface)
560 {
561 struct tm *d;
562 char daytemp[DATEBUFFLEN];
563 uint64_t div;
564 dbdatalist *datalist = NULL;
565 dbdatalistinfo datainfo;
566
567 timeused_debug(__func__, 1);
568
569 /* version string */
570 printf("%d;", ONELINEVERSION);
571
572 /* interface name */
573 if (strcmp(interface->name, interface->alias) == 0 || strlen(interface->alias) == 0) {
574 printf("%s", interface->name);
575 } else {
576 printf("%s (%s)", interface->alias, interface->name);
577 }
578 if (interface->active == 0) {
579 printf(" [disabled]");
580 }
581 printf(";");
582
583 if (!db_getdata(&datalist, &datainfo, interface->name, "day", 1)) {
584 printf("\nError: Failed to fetch day data.\n");
585 return;
586 }
587
588 if (datainfo.count > 0) {
589 d = localtime(&datalist->timestamp);
590 strftime(daytemp, DATEBUFFLEN, cfg.dformat, d);
591 printf("%s;", daytemp);
592
593 d = localtime(&interface->updated);
594
595 /* daily */
596 if (cfg.ostyle == 4) {
597 printf("%" PRIu64 ";", datalist->rx);
598 printf("%" PRIu64 ";", datalist->tx);
599 printf("%" PRIu64 ";", datalist->rx + datalist->tx);
600 div = (uint64_t)(d->tm_sec + (d->tm_min * 60) + (d->tm_hour * 3600));
601 if (!div) {
602 div = 1;
603 }
604 printf("%" PRIu64 ";", (datalist->rx + datalist->tx) / div);
605 } else {
606 printf("%s;", getvalue(datalist->rx, 1, RT_Normal));
607 printf("%s;", getvalue(datalist->tx, 1, RT_Normal));
608 printf("%s;", getvalue(datalist->rx + datalist->tx, 1, RT_Normal));
609 printf("%s;", gettrafficrate(datalist->rx + datalist->tx, (time_t)(d->tm_sec + (d->tm_min * 60) + (d->tm_hour * 3600)), 1));
610 }
611 } else {
612 printf(";;;;;");
613 }
614 dbdatalistfree(&datalist);
615
616 if (!db_getdata(&datalist, &datainfo, interface->name, "month", 1)) {
617 printf("\nError: Failed to fetch month data.\n");
618 return;
619 }
620
621 if (datainfo.count > 0) {
622 d = localtime(&datalist->timestamp);
623 strftime(daytemp, DATEBUFFLEN, cfg.mformat, d);
624 printf("%s;", daytemp);
625
626 /* monthly */
627 if (cfg.ostyle == 4) {
628 printf("%" PRIu64 ";", datalist->rx);
629 printf("%" PRIu64 ";", datalist->tx);
630 printf("%" PRIu64 ";", datalist->rx + datalist->tx);
631 div = (uint64_t)(mosecs(datalist->timestamp, interface->updated));
632 if (!div) {
633 div = 1;
634 }
635 printf("%" PRIu64 ";", (datalist->rx + datalist->tx) / div);
636 } else {
637 printf("%s;", getvalue(datalist->rx, 1, RT_Normal));
638 printf("%s;", getvalue(datalist->tx, 1, RT_Normal));
639 printf("%s;", getvalue(datalist->rx + datalist->tx, 1, RT_Normal));
640 printf("%s;", gettrafficrate(datalist->rx + datalist->tx, mosecs(datalist->timestamp, interface->updated), 1));
641 }
642 } else {
643 printf(";;;;;");
644 }
645 dbdatalistfree(&datalist);
646
647 /* all time total */
648 if (cfg.ostyle == 4) {
649 printf("%" PRIu64 ";", interface->rxtotal);
650 printf("%" PRIu64 ";", interface->txtotal);
651 printf("%" PRIu64 "\n", interface->rxtotal + interface->txtotal);
652 } else {
653 printf("%s;", getvalue(interface->rxtotal, 1, RT_Normal));
654 printf("%s;", getvalue(interface->txtotal, 1, RT_Normal));
655 printf("%s\n", getvalue(interface->rxtotal + interface->txtotal, 1, RT_Normal));
656 }
657 timeused_debug(__func__, 0);
658 }
659
660 void showhours(const interfaceinfo *interface)
661 {
662 int i, s = 0, hour, minute, declen = cfg.hourlydecimals, div = 1;
663 unsigned int j, k, tmax = 0, dots = 0;
664 uint64_t max = 1;
665 char matrix[HGLINES][81]; /* width is one over 80 so that snprintf can write the end char */
666 char unit[4];
667 struct tm *d;
668 dbdatalist *datalist = NULL, *datalist_i = NULL;
669 dbdatalistinfo datainfo;
670 HOURDATA hourdata[24];
671
672 timeused_debug(__func__, 1);
673
674 for (i = 0; i < 24; i++) {
675 hourdata[i].rx = hourdata[i].tx = 0;
676 hourdata[i].date = 0;
677 }
678
679 if (!db_getdata(&datalist, &datainfo, interface->name, "hour", 24)) {
680 printf("Error: Failed to fetch hour data.\n");
681 return;
682 }
683
684 if (datainfo.count == 0) {
685 return;
686 }
687
688 datalist_i = datalist;
689
690 while (datalist_i != NULL) {
691 d = localtime(&datalist_i->timestamp);
692 if (hourdata[d->tm_hour].date != 0 || interface->updated - datalist_i->timestamp > 86400) {
693 datalist_i = datalist_i->next;
694 continue;
695 }
696 hourdata[d->tm_hour].rx = datalist_i->rx;
697 hourdata[d->tm_hour].tx = datalist_i->tx;
698 hourdata[d->tm_hour].date = datalist_i->timestamp;
699 datalist_i = datalist_i->next;
700 }
701 dbdatalistfree(&datalist);
702
703 /* tmax = time max = current hour */
704 /* max = transfer max */
705
706 d = localtime(&interface->updated);
707 hour = d->tm_hour;
708 minute = d->tm_min;
709
710 for (i = 0; i < 24; i++) {
711 if (hourdata[i].date >= hourdata[tmax].date) {
712 tmax = (unsigned int)i;
713 }
714 if (hourdata[i].rx >= max) {
715 max = hourdata[i].rx;
716 }
717 if (hourdata[i].tx >= max) {
718 max = hourdata[i].tx;
719 }
720 }
721
722 /* mr. proper */
723 for (i = 0; i < HGLINES; i++) {
724 for (j = 0; j < 81; j++) {
725 matrix[i][j] = ' ';
726 }
727 }
728
729 /* unit selection */
730 while ((double)max / (pow(1024, div)) >= 100 && div < UNITPREFIXCOUNT) {
731 div++;
732 }
733 strncpy_nt(unit, getunitprefix(div), 4);
734 div = (int)(pow(1024, div - 1));
735 if (div == 1) {
736 declen = 0;
737 }
738
739 /* structure */
740 snprintf(matrix[11], 81, " -+--------------------------------------------------------------------------->");
741 for (i = 0; i < 3; i++) {
742 snprintf(matrix[14] + (i * 28), 14, " h %*srx (%s)", 1 + cfg.unitmode, " ", unit);
743 snprintf(matrix[14] + (i * 28) + 15 + cfg.unitmode, 10, "tx (%s)", unit);
744 }
745
746 for (i = 10; i > 1; i--)
747 matrix[i][2] = '|';
748
749 matrix[1][2] = '^';
750 matrix[12][2] = '|';
751
752 /* title */
753 if (strcmp(interface->name, interface->alias) == 0 || strlen(interface->alias) == 0) {
754 i = snprintf(matrix[0], 81, " %s", interface->name);
755 } else {
756 i = snprintf(matrix[0], 81, " %s (%s)", interface->alias, interface->name);
757 }
758 if (interface->active == 0) {
759 snprintf(matrix[0] + i + 1, 81, " [disabled]");
760 }
761
762 /* time to the corner */
763 snprintf(matrix[0] + 74, 7, "%02d:%02d", hour, minute);
764
765 /* numbers under x-axis and graphics :) */
766 k = 5;
767 for (i = 23; i >= 0; i--) {
768 s = (int)tmax - i;
769 if (s < 0)
770 s += 24;
771
772 snprintf(matrix[12] + k, 81 - k, "%02d ", s);
773
774 dots = (unsigned int)(10 * ((double)hourdata[s].rx / (double)max));
775 for (j = 0; j < dots; j++)
776 matrix[10 - j][k] = cfg.rxhourchar[0];
777
778 dots = (unsigned int)(10 * ((double)hourdata[s].tx / (double)max));
779 for (j = 0; j < dots; j++)
780 matrix[10 - j][k + 1] = cfg.txhourchar[0];
781
782 k = k + 3;
783 }
784
785 /* section separators */
786 if (cfg.hourlystyle == 1) {
787 matrix[14][26] = '|';
788 matrix[14][54] = '|';
789 } else if (cfg.hourlystyle == 2) {
790 matrix[14][25] = ']';
791 matrix[14][26] = '[';
792 matrix[14][53] = ']';
793 matrix[14][54] = '[';
794 } else if (cfg.hourlystyle == 3) {
795 matrix[14][26] = '[';
796 matrix[14][53] = ']';
797 }
798
799 /* clean \0 */
800 for (i = 0; i < HGLINES; i++) {
801 for (j = 0; j < 80; j++) {
802 if (matrix[i][j] == '\0') {
803 matrix[i][j] = ' ';
804 }
805 }
806 }
807
808 /* show matrix */
809 for (i = 0; i < HGLINES; i++) {
810 for (j = 0; j < 80; j++) {
811 printf("%c", matrix[i][j]);
812 }
813 printf("\n");
814 }
815
816 /* hours and traffic */
817 for (i = 0; i <= 7; i++) {
818 s = (int)tmax + i + 1;
819 for (j = 0; j < 3; j++) {
820 printf("%02d %" DECCONV "10.*f %" DECCONV "10.*f", ((unsigned int)s + (j * 8)) % 24,
821 declen, (double)hourdata[((unsigned int)s + (j * 8)) % 24].rx / (double)div,
822 declen, (double)hourdata[((unsigned int)s + (j * 8)) % 24].tx / (double)div);
823
824 if (j < 2) {
825 if (cfg.hourlystyle == 1) {
826 printf(" | ");
827 } else if (cfg.hourlystyle == 2) {
828 printf(" ][ ");
829 } else if (cfg.hourlystyle == 3) {
830 if (j == 0) {
831 printf(" [ ");
832 } else {
833 printf(" ] ");
834 }
835 } else {
836 printf(" ");
837 }
838 }
839 }
840 printf("\n");
841 }
842
843 timeused_debug(__func__, 0);
844 }
845
846 int showbar(const uint64_t rx, const uint64_t tx, const uint64_t max, const int len)
847 {
848 int i, l, width = len;
849
850 if ((rx + tx) < max) {
851 width = (int)(((double)(rx + tx) / (double)max) * len);
852 } else if ((rx + tx) > max || max == 0) {
853 return 0;
854 }
855
856 if (width <= 0) {
857 return 0;
858 }
859
860 printf(" ");
861
862 if (tx > rx) {
863 l = (int)lrint(((double)rx / (double)(rx + tx) * width));
864
865 for (i = 0; i < l; i++) {
866 printf("%c", cfg.rxchar[0]);
867 }
868 for (i = 0; i < (width - l); i++) {
869 printf("%c", cfg.txchar[0]);
870 }
871 } else {
872 l = (int)lrint(((double)tx / (double)(rx + tx) * width));
873
874 for (i = 0; i < (width - l); i++) {
875 printf("%c", cfg.rxchar[0]);
876 }
877 for (i = 0; i < l; i++) {
878 printf("%c", cfg.txchar[0]);
879 }
880 }
881 return width;
882 }
883
884 void indent(int i)
885 {
886 if ((cfg.ostyle > 0) && (i > 0)) {
887 printf("%*s", i, " ");
888 }
889 }
890
891 int showalert(const char *interface, const AlertOutput output, const AlertExit exit, const AlertType type, const AlertCondition condition, const uint64_t limit)
892 {
893 interfaceinfo ifaceinfo;
894 int i, l, ret = 0, limitexceeded = 0, estimateexceeded = 0;
895 short ongoing = 1;
896 double percentage = 0.0;
897 char tablename[6], typeoutput[8], conditionname[16];
898 char datebuff[DATEBUFFLEN];
899 ListType listtype = LT_None;
900 uint64_t bytes = 0, e_rx = 0, e_tx = 0, e_bytes = 0, periodseconds = 0;
901 dbdatalist *datalist = NULL;
902 dbdatalistinfo datainfo;
903
904 timeused_debug(__func__, 1);
905
906 if (!db_getinterfaceinfo(interface, &ifaceinfo)) {
907 return 1;
908 }
909
910 switch (type) {
911 case AT_None:
912 return 0;
913 case AT_Hour:
914 listtype = LT_Hour;
915 snprintf(tablename, 6, "hour");
916 snprintf(typeoutput, 8, "hourly");
917 break;
918 case AT_Day:
919 listtype = LT_Day;
920 snprintf(tablename, 6, "day");
921 snprintf(typeoutput, 8, "daily");
922 break;
923 case AT_Month:
924 listtype = LT_Month;
925 snprintf(tablename, 6, "month");
926 snprintf(typeoutput, 8, "monthly");
927 break;
928 case AT_Year:
929 listtype = LT_Year;
930 snprintf(tablename, 6, "year");
931 snprintf(typeoutput, 8, "yearly");
932 break;
933 }
934
935 if (!db_getdata(&datalist, &datainfo, interface, tablename, 1)) {
936 printf("Error: Failed to fetch %s data for interface %s.\n", tablename, interface);
937 return 1;
938 }
939
940 if (!datalist) {
941 printf("Error: No %s data available for interface %s.\n", tablename, interface);
942 return 1;
943 }
944
945 switch (condition) {
946 case AC_None:
947 break;
948 case AC_RX:
949 bytes = datalist->rx;
950 snprintf(conditionname, 16, "rx");
951 getestimates(&e_rx, &e_tx, listtype, ifaceinfo.updated, &datalist);
952 e_bytes = e_rx;
953 break;
954 case AC_TX:
955 bytes = datalist->tx;
956 snprintf(conditionname, 16, "tx");
957 getestimates(&e_rx, &e_tx, listtype, ifaceinfo.updated, &datalist);
958 e_bytes = e_tx;
959 break;
960 case AC_Total:
961 bytes = datalist->rx + datalist->tx;
962 snprintf(conditionname, 16, "total");
963 getestimates(&e_rx, &e_tx, listtype, ifaceinfo.updated, &datalist);
964 e_bytes = e_rx + e_tx;
965 break;
966 case AC_RX_Estimate:
967 ongoing = 0;
968 getestimates(&e_rx, &e_tx, listtype, ifaceinfo.updated, &datalist);
969 bytes = e_rx;
970 snprintf(conditionname, 16, "rx estimate");
971 break;
972 case AC_TX_Estimate:
973 ongoing = 0;
974 getestimates(&e_rx, &e_tx, listtype, ifaceinfo.updated, &datalist);
975 bytes = e_tx;
976 snprintf(conditionname, 16, "tx estimate");
977 break;
978 case AC_Total_Estimate:
979 ongoing = 0;
980 getestimates(&e_rx, &e_tx, listtype, ifaceinfo.updated, &datalist);
981 bytes = e_rx + e_tx;
982 snprintf(conditionname, 16, "total estimate");
983 break;
984 }
985
986 if (bytes > limit) {
987 limitexceeded = 1;
988 }
989
990 if (ongoing == 1 && e_bytes > limit) {
991 estimateexceeded = 1;
992 }
993
994 if (limitexceeded && exit == AE_Exit_1_On_Limit) {
995 ret = 1;
996 } else if (estimateexceeded && exit == AE_Exit_1_On_Estimate) {
997 ret = 1;
998 }
999
1000 if (output != AO_No_Output) {
1001 if (output == AO_Always_Output || (output == AO_Output_On_Estimate && estimateexceeded) || ((output == AO_Output_On_Limit || output == AO_Output_On_Estimate) && limitexceeded)) {
1002 if (strlen(ifaceinfo.alias)) {
1003 printf("\n %s (%s)", ifaceinfo.alias, ifaceinfo.name);
1004 } else {
1005 printf("\n %s", interface);
1006 }
1007 if (ifaceinfo.updated) {
1008 strftime(datebuff, DATEBUFFLEN, DATETIMEFORMAT, localtime(&ifaceinfo.updated));
1009 printf(" at %s", datebuff);
1010 }
1011 if (datalist->timestamp) {
1012 printf(" for %s ", tablename);
1013 switch (type) {
1014 case AT_None:
1015 break;
1016 case AT_Hour:
1017 strftime(datebuff, DATEBUFFLEN, "%H", localtime(&datalist->timestamp));
1018 printf("%s of ", datebuff);
1019 strftime(datebuff, DATEBUFFLEN, cfg.dformat, localtime(&datalist->timestamp));
1020 printf("%s", datebuff);
1021 break;
1022 case AT_Day:
1023 strftime(datebuff, DATEBUFFLEN, cfg.dformat, localtime(&datalist->timestamp));
1024 printf("%s", datebuff);
1025 break;
1026 case AT_Month:
1027 strftime(datebuff, DATEBUFFLEN, cfg.mformat, localtime(&datalist->timestamp));
1028 printf("%s", datebuff);
1029 break;
1030 case AT_Year:
1031 strftime(datebuff, DATEBUFFLEN, "%Y", localtime(&datalist->timestamp));
1032 printf("%s", datebuff);
1033 break;
1034 }
1035 }
1036 printf("\n\n");
1037 }
1038
1039 if ((output == AO_Always_Output || output == AO_Output_On_Limit || output == AO_Output_On_Estimate) && limitexceeded) {
1040 printf(" Alert limit exceeded!\n\n");
1041 } else if (output == AO_Always_Output || (output == AO_Output_On_Estimate && estimateexceeded)) {
1042 if (estimateexceeded) {
1043 printf(" Warning: Limit will be exceeded at current rate\n\n");
1044 }
1045 printf(" [");
1046 l = (int)lrint((double)(bytes) / (double)limit * ALERTUSAGELEN);
1047 if (l > ALERTUSAGELEN) {
1048 l = ALERTUSAGELEN;
1049 }
1050 for (i = 0; i < l; i++) {
1051 printf("=");
1052 }
1053 if (ongoing) {
1054 if (!estimateexceeded) {
1055 l = (int)lrint((double)(e_bytes) / (double)limit * ALERTUSAGELEN);
1056 for (; i < l; i++) {
1057 printf("-");
1058 }
1059 } else {
1060 for (; i < ALERTUSAGELEN; i++) {
1061 printf("-");
1062 }
1063 }
1064 }
1065 for (; i < ALERTUSAGELEN; i++) {
1066 printf(".");
1067 }
1068 printf("]\n\n");
1069 }
1070
1071 if (output == AO_Always_Output || (output == AO_Output_On_Estimate && estimateexceeded) || ((output == AO_Output_On_Limit || output == AO_Output_On_Estimate) && limitexceeded)) {
1072 printf(" %8s |", typeoutput);
1073 if (ongoing) {
1074 printf(" %9s |", conditionname);
1075 } else {
1076 printf(" %14s |", conditionname);
1077 }
1078 percentage = (double)(bytes) / (double)limit * 100.0;
1079 printf(" percentage | avg. rate\n");
1080 printf(" ----------+------------------+----------------+--------------\n");
1081 printf(" used | %16s |", getvalue(bytes, 16, RT_Normal));
1082 periodseconds = getperiodseconds(listtype, datalist->timestamp, ifaceinfo.updated, ongoing);
1083 if (ongoing && periodseconds == 0) {
1084 periodseconds = getperiodseconds(listtype, datalist->timestamp, ifaceinfo.updated, 0);
1085 }
1086 if (percentage <= 100000.0) {
1087 printf(" %13.1f%% | %13s\n", percentage, gettrafficrate(bytes, (time_t)periodseconds, 13));
1088 } else {
1089 printf(" %14s | %13s\n", ">100000%", gettrafficrate(bytes, (time_t)periodseconds, 13));
1090 }
1091 printf(" limit | %16s |", getvalue(limit, 16, RT_Normal));
1092 printf(" | %13s\n", gettrafficrate(limit, (time_t)getperiodseconds(listtype, datalist->timestamp, ifaceinfo.updated, 0), 13));
1093
1094 if (limitexceeded) {
1095 printf(" excess | %16s | |\n", getvalue(bytes - limit, 16, RT_Normal));
1096 printf(" ----------+------------------+----------------+--------------\n");
1097 } else {
1098 printf(" remaining | %16s | %13.1f%% |\n", getvalue(limit - bytes, 16, RT_Normal), 100.0 - percentage);
1099 printf(" ----------+------------------+----------------+--------------\n");
1100 }
1101 if (ongoing && e_bytes > 0) {
1102 printf(" estimated | %16s |", getvalue(e_bytes, 16, RT_Normal));
1103 percentage = (double)(e_bytes) / (double)limit * 100.0;
1104 if (percentage <= 100000.0) {
1105 printf(" %13.1f%%", percentage);
1106 } else {
1107 printf(" %14s", ">100000%");
1108 }
1109 if (e_bytes > limit) {
1110 printf(", +%s\n", getvalue(e_bytes - limit, 0, RT_Normal));
1111 } else {
1112 /* rate for estimated is always to same as for used so "bytes" intentionally used here instead of "e_bytes" */
1113 printf(" | %13s\n", gettrafficrate(bytes, (time_t)periodseconds, 13));
1114 }
1115 }
1116 }
1117 }
1118
1119 dbdatalistfree(&datalist);
1120
1121 timeused_debug(__func__, 0);
1122
1123 return ret;
1124 }