"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.

    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 }