"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(&current);
  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(&current);
  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 }