/* * The dhcpd-pools has BSD 2-clause license which also known as "Simplified * BSD License" or "FreeBSD License". * * Copyright 2006- Sami Kerola. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of Sami Kerola. */ /*! \file output.c * \brief All about output formats. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "close-stream.h" #include "dhcpd-pools.h" #include "progname.h" #include "strftime.h" /*! \brief Text output format, which is the default. * FIXME: This function should return void. */ int output_txt(void) { unsigned int i; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; int ret; FILE *outfile; int max_ipaddr_length = config.dhcp_version == VERSION_6 ? 39 : 16; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { err(EXIT_FAILURE, "output_txt: %s", config.output_file); } } else { outfile = stdout; } range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; if (config.output_limit[0] & BIT1) { fprintf(outfile, "Ranges:\n"); fprintf (outfile, "%-20s%-*s %-*s %5s %5s %10s %5s %5s %9s", "shared net name", max_ipaddr_length, "first ip", max_ipaddr_length, "last ip", "max", "cur", "percent", "touch", "t+c", "t+c perc"); if (config.backups_found == true) { fprintf(outfile, " bu bu perc"); } fprintf(outfile, "\n"); } if (config.output_limit[1] & BIT1) { for (i = 0; i < num_ranges; i++) { if (range_p->shared_net) { fprintf(outfile, "%-20s", range_p->shared_net->name); } else { fprintf(outfile, "not_defined "); } /* Outputting of first_ip and last_ip need to be * separate since ntop_ipaddr always returns the * same buffer */ fprintf(outfile, "%-*s", max_ipaddr_length, ntop_ipaddr(&range_p->first_ip)); fprintf(outfile, " - %-*s %5g %5g %10.3f %5g %5g %9.3f", max_ipaddr_length, ntop_ipaddr(&range_p->last_ip), range_size, range_p->count, (float)(100 * range_p->count) / range_size, range_p->touched, range_p->touched + range_p->count, (float)(100 * (range_p->touched + range_p->count)) / range_size); if (config.backups_found == true) { fprintf(outfile, "%7g %8.3f", range_p->backups, (float)(100 * range_p->backups) / range_size); } fprintf(outfile, "\n"); range_p++; range_size = get_range_size(range_p); } } if (config.output_limit[1] & BIT1 && config.output_limit[0] & BIT2) { fprintf(outfile, "\n"); } if (config.output_limit[0] & BIT2) { fprintf(outfile, "Shared networks:\n"); fprintf(outfile, "name max cur percent touch t+c t+c perc"); if (config.backups_found == true) { fprintf(outfile, " bu bu perc"); } fprintf(outfile, "\n"); } if (config.output_limit[1] & BIT2) { for (i = 0; i < num_shared_networks; i++) { shared_p++; fprintf(outfile, "%-20s %5g %5g %10.3f %7g %6g %9.3f", shared_p->name, shared_p->available, shared_p->used, (float)(100 * shared_p->used) / shared_p->available, shared_p->touched, shared_p->touched + shared_p->used, (float)(100 * (shared_p->touched + shared_p->used)) / shared_p->available); if (config.backups_found == true) { fprintf(outfile, "%7g %8.3f", shared_p->backups, (float)(100 * shared_p->backups) / shared_p->available); } fprintf(outfile, "\n"); } } if (config.output_limit[1] & BIT2 && config.output_limit[0] & BIT3) { fprintf(outfile, "\n"); } if (config.output_limit[0] & BIT3) { fprintf(outfile, "Sum of all ranges:\n"); fprintf(outfile, "name max cur percent touch t+c t+c perc"); if (config.backups_found == true) { fprintf(outfile, " bu bu perc"); } fprintf(outfile, "\n"); } if (config.output_limit[1] & BIT3) { fprintf(outfile, "%-20s %5g %5g %10.3f %7g %6g %9.3f", shared_networks->name, shared_networks->available, shared_networks->used, (float)(100 * shared_networks->used) / shared_networks->available, shared_networks->touched, shared_networks->touched + shared_networks->used, (float)(100 * (shared_networks->touched + shared_networks->used)) / shared_networks->available); if (config.backups_found == true) { fprintf(outfile, "%7g %8.3f", shared_networks->backups, (float)(100 * shared_networks->backups) / shared_networks->available); } fprintf(outfile, "\n"); } if (outfile == stdout) { ret = fflush(stdout); if (ret) { warn("output_txt: fflush"); } } else { ret = close_stream(outfile); if (ret) { warn("output_txt: fclose"); } } return 0; } /*! \brief The xml output formats. * FIXME: This function should return void. */ int output_xml(void) { unsigned int i; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; int ret; FILE *outfile; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { err(EXIT_FAILURE, "output_xml: %s", config.output_file); } } else { outfile = stdout; } range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; fprintf(outfile, "\n"); if (config.output_format[0] == 'X' || config.output_format[0] == 'J') { struct leases_t *l; for (l = leases; l != NULL; l = l->hh.next) { if (l->type == ACTIVE) { fputs("\n\t", outfile); fputs(ntop_ipaddr(&l->ip), outfile); fputs("\n\t", outfile); if (l->ethernet != NULL) { fputs(l->ethernet, outfile); } fputs("\n\n", outfile); } } } if (config.output_limit[1] & BIT1) { for (i = 0; i < num_ranges; i++) { fprintf(outfile, "\n"); if (range_p->shared_net) { fprintf(outfile, "\t%s\n", range_p->shared_net->name); } else { fprintf(outfile, "\t\n"); } fprintf(outfile, "\t\n"); fprintf(outfile, "\t\n"); fprintf(outfile, "\t%s ", ntop_ipaddr(&range_p->first_ip)); fprintf(outfile, "- %s\n", ntop_ipaddr(&range_p->last_ip)); fprintf(outfile, "\t\n"); fprintf(outfile, "\t%g\n", range_size); fprintf(outfile, "\t%g\n", range_p->count); fprintf(outfile, "\t%g\n", range_size - range_p->count); range_p++; range_size = get_range_size(range_p); fprintf(outfile, "\n"); } } if (config.output_limit[1] & BIT2) { for (i = 0; i < num_shared_networks; i++) { shared_p++; fprintf(outfile, "\n"); fprintf(outfile, "\t%s\n", shared_p->name); fprintf(outfile, "\t%g\n", shared_p->available); fprintf(outfile, "\t%g\n", shared_p->used); fprintf(outfile, "\t%g\n", shared_p->available - shared_p->used); fprintf(outfile, "\n"); } } if (config.output_limit[0] & BIT3) { fprintf(outfile, "\n"); fprintf(outfile, "\t%s\n", shared_networks->name); fprintf(outfile, "\t%g\n", shared_networks->available); fprintf(outfile, "\t%g\n", shared_networks->used); fprintf(outfile, "\t%g\n", shared_networks->available - shared_networks->used); fprintf(outfile, "\n"); } fprintf(outfile, "\n"); if (outfile == stdout) { ret = fflush(stdout); if (ret) { warn("output_xml: fflush"); } } else { ret = close_stream(outfile); if (ret) { warn("output_xml: fclose"); } } return 0; } /*! \brief The json output formats. * FIXME: This function should return void. */ int output_json(void) { unsigned int i = 0; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; int ret; FILE *outfile; unsigned int sep; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { err(EXIT_FAILURE, "output_json: %s", config.output_file); } } else { outfile = stdout; } range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; sep = 0; fprintf(outfile, "{\n"); if (config.output_format[0] == 'X' || config.output_format[0] == 'J') { struct leases_t *l; fprintf(outfile, " \"active_leases\": ["); for (l = leases; l != NULL; l = l->hh.next) { if (l->type == ACTIVE) { if (i == 0) { i = 1; } else { fputc(',', outfile); } fputs("\n { \"ip\":\"", outfile); fputs(ntop_ipaddr(&l->ip), outfile); fputs("\", \"macaddress\":\"", outfile); if (l->ethernet != NULL) { fputs(l->ethernet, outfile); } fputs("\" }", outfile); } } fprintf(outfile, "\n ]"); /* end of active_leases */ sep++; } if (config.output_limit[1] & BIT1) { if (sep) { fprintf(outfile, ",\n"); } fprintf(outfile, " \"subnets\": [\n"); for (i = 0; i < num_ranges; i++) { fprintf(outfile, " "); fprintf(outfile, "{ "); if (range_p->shared_net) { fprintf(outfile, "\"location\":\"%s\", ", range_p->shared_net->name); } else { fprintf(outfile, "\"location\":\"\", "); } fprintf(outfile, "\"range\":\"%s", ntop_ipaddr(&range_p->first_ip)); fprintf(outfile, " - %s\", ", ntop_ipaddr(&range_p->last_ip)); fprintf(outfile, "\"defined\":%g, ", range_size); fprintf(outfile, "\"used\":%g, ", range_p->count); fprintf(outfile, "\"free\":%g ", range_size - range_p->count); range_p++; range_size = get_range_size(range_p); if (i + 1 < num_ranges) fprintf(outfile, "},\n"); else fprintf(outfile, "}\n"); } fprintf(outfile, " ]"); /* end of subnets */ sep++; } if (config.output_limit[1] & BIT2) { if (sep) { fprintf(outfile, ",\n"); } fprintf(outfile, " \"shared-networks\": [\n"); for (i = 0; i < num_shared_networks; i++) { fprintf(outfile, " "); shared_p++; fprintf(outfile, "{ "); fprintf(outfile, "\"location\":\"%s\", ", shared_p->name); fprintf(outfile, "\"defined\":%g, ", shared_p->available); fprintf(outfile, "\"used\":%g, ", shared_p->used); fprintf(outfile, "\"free\":%g ", shared_p->available - shared_p->used); if (i + 1 < num_shared_networks) fprintf(outfile, "},\n"); else fprintf(outfile, "}\n"); } fprintf(outfile, " ]"); /* end of shared-networks */ sep++; } if (config.output_limit[0] & BIT3) { if (sep) { fprintf(outfile, ",\n"); } fprintf(outfile, " \"summary\": {\n"); fprintf(outfile, " \"location\":\"%s\",\n", shared_networks->name); fprintf(outfile, " \"defined\":%g,\n", shared_networks->available); fprintf(outfile, " \"used\":%g,\n", shared_networks->used); fprintf(outfile, " \"free\":%g\n", shared_networks->available - shared_networks->used); fprintf(outfile, " }"); /* end of summary */ sep++; } fprintf(outfile, "\n}\n"); if (outfile == stdout) { ret = fflush(stdout); if (ret) { warn("output_json: fflush"); } } else { ret = close_stream(outfile); if (ret) { warn("output_json: fclose"); } } return 0; } /*! \brief Header for full html output format. * * \param f Output file descriptor. */ static void html_header(FILE *restrict f) { char outstr[200]; struct tm *tmp; struct stat statbuf; stat(config.dhcpdlease_file, &statbuf); tmp = localtime(&statbuf.st_mtime); if (tmp == NULL) { err(EXIT_FAILURE, "html_header: localtime"); } if (strftime(outstr, sizeof(outstr), nl_langinfo(D_T_FMT), tmp) == 0) { errx(EXIT_FAILURE, "html_header: strftime returned 0"); } fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, " ISC dhcpd stats\n"); fprintf(f, " \n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "The lease file mtime: %s", outstr); } /*! \brief Footer for full html output format. * * \param f Output file descriptor. */ static void html_footer(FILE *restrict f) { fprintf(f, "


\n"); fprintf(f, "
\n"); fprintf(f, "

\nData generated by "); fprintf(f, "", PACKAGE_URL); fprintf(f, "%s.\n

\n", PACKAGE_STRING); fprintf(f, "

\n"); fprintf(f, "\n
\n

\n"); fprintf(f, "\n"); fprintf(f, "\n"); } /*! \brief A new row for html output format. * * \param f Output file descriptor. */ static void newrow(FILE *restrict f) { fprintf(f, "\n"); } /*! \brief End a row for html output format. * * \param f Output file descriptor. */ static void endrow(FILE *restrict f) { fprintf(f, "\n\n"); } /*! \brief Line with text in html output format. * * \param f Output file descriptor. * \param type HTML tag name. * \param class How the data is aligned. * \param text Actual payload of the printout. */ static void output_line(FILE *restrict f, char const *restrict type, char const *restrict class, char const *restrict text) { fprintf(f, " <%s class=%s>%s\n", type, class, text, type); } /*! \brief Line with digit in html output format. * * \param f Output file descriptor. * \param type HMTL tag name. * \param d Actual payload of the printout. */ static void output_double(FILE *restrict f, char const *restrict type, double d) { fprintf(f, " <%s class=ralign>%g\n", type, d, type); } /*! \brief Line with float in html output format. * * \param f Output file descriptor. * \param type HTML tag name. * \param fl Actual payload of the printout. */ static void output_float(FILE *f, char const *restrict type, float fl) { fprintf(f, " <%s class=ralign>%.3f\n", type, fl, type); } /*! \brief Begin table in html output format. * * \param f Output file descriptor. */ static void table_start(FILE *restrict f) { fprintf(f, "\n"); } /*! \brief End table in html output format. * * \param f Output file descriptor. */ static void table_end(FILE *restrict f) { fprintf(f, "
\n"); } /*! \brief New section in html output format. * * \param f Output file descriptor. * \param title Table title. */ static void newsection(FILE *restrict f, char const *restrict title) { newrow(f); output_line(f, "td", "calign", " "); endrow(f); newrow(f); output_line(f, "th", "section", title); endrow(f); } /*! \brief Output html format. * FIXME: This function should return void. */ int output_html(void) { unsigned int i; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; int ret; FILE *outfile; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { err(EXIT_FAILURE, "output_html: %s", config.output_file); } } else { outfile = stdout; } range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; if (config.fullhtml) { html_header(outfile); } table_start(outfile); if (config.output_limit[0] & BIT1) { newsection(outfile, "Ranges:"); newrow(outfile); output_line(outfile, "th", "calign", "shared net name"); output_line(outfile, "th", "calign", "first ip"); output_line(outfile, "th", "calign", "last ip"); output_line(outfile, "th", "ralign", "max"); output_line(outfile, "th", "ralign", "cur"); output_line(outfile, "th", "ralign", "percent"); output_line(outfile, "th", "ralign", "touch"); output_line(outfile, "th", "ralign", "t+c"); output_line(outfile, "th", "ralign", "t+c perc"); if (config.backups_found == true) { output_line(outfile, "th", "ralign", "bu"); output_line(outfile, "th", "ralign", "bu perc"); } endrow(outfile); } if (config.output_limit[1] & BIT1) { for (i = 0; i < num_ranges; i++) { newrow(outfile); if (range_p->shared_net) { output_line(outfile, "td", "calign", range_p->shared_net->name); } else { output_line(outfile, "td", "calign", "not_defined"); } output_line(outfile, "td", "calign", ntop_ipaddr(&range_p->first_ip)); output_line(outfile, "td", "calign", ntop_ipaddr(&range_p->last_ip)); output_double(outfile, "td", range_size); output_double(outfile, "td", range_p->count); output_float(outfile, "td", (float)(100 * range_p->count) / range_size); output_double(outfile, "td", range_p->touched); output_double(outfile, "td", range_p->touched + range_p->count); output_float(outfile, "td", (float)(100 * (range_p->touched + range_p->count)) / range_size); if (config.backups_found == true) { output_double(outfile, "td", range_p->backups); output_float(outfile, "td", (float)(100 * range_p->backups) / range_size); } endrow(outfile); range_p++; range_size = get_range_size(range_p); } } table_end(outfile); table_start(outfile); if (config.output_limit[0] & BIT2) { newsection(outfile, "Shared networks:"); newrow(outfile); output_line(outfile, "th", "calign", "name"); output_line(outfile, "th", "ralign", "max"); output_line(outfile, "th", "ralign", "cur"); output_line(outfile, "th", "ralign", "percent"); output_line(outfile, "th", "ralign", "touch"); output_line(outfile, "th", "ralign", "t+c"); output_line(outfile, "th", "ralign", "t+c perc"); if (config.backups_found == true) { output_line(outfile, "th", "ralign", "bu"); output_line(outfile, "th", "ralign", "bu perc"); } endrow(outfile); } if (config.output_limit[1] & BIT2) { for (i = 0; i < num_shared_networks; i++) { shared_p++; newrow(outfile); output_line(outfile, "td", "calign", shared_p->name); output_double(outfile, "td", shared_p->available); output_double(outfile, "td", shared_p->used); output_float(outfile, "td", (float)(100 * shared_p->used) / shared_p->available); output_double(outfile, "td", shared_p->touched); output_double(outfile, "td", shared_p->touched + shared_p->used); output_float(outfile, "td", (float)(100 * (shared_p->touched + shared_p->used)) / shared_p->available); if (config.backups_found == true) { output_double(outfile, "td", shared_p->backups); output_float(outfile, "td", (float)(100 * shared_p->backups) / shared_p->available); } endrow(outfile); } } if (config.output_limit[0] & BIT3) { newsection(outfile, "Sum of all ranges:"); newrow(outfile); output_line(outfile, "th", "calign", "name"); output_line(outfile, "th", "ralign", "max"); output_line(outfile, "th", "ralign", "cur"); output_line(outfile, "th", "ralign", "percent"); output_line(outfile, "th", "ralign", "touch"); output_line(outfile, "th", "ralign", "t+c"); output_line(outfile, "th", "ralign", "t+c perc"); if (config.backups_found == true) { output_line(outfile, "th", "ralign", "bu"); output_line(outfile, "th", "ralign", "bu perc"); } endrow(outfile); } if (config.output_limit[1] & BIT3) { newrow(outfile); output_line(outfile, "td", "calign", shared_networks->name); output_double(outfile, "td", shared_networks->available); output_double(outfile, "td", shared_networks->used); output_float(outfile, "td", (float)(100 * shared_networks->used) / shared_networks->available); output_double(outfile, "td", shared_networks->touched); output_double(outfile, "td", shared_networks->touched + shared_networks->used); output_float(outfile, "td", (float)(100 * (shared_networks->touched + shared_networks->used)) / shared_networks->available); if (config.backups_found == true) { output_double(outfile, "td", shared_networks->backups); output_float(outfile, "td", (float)(100 * shared_networks->backups) / shared_networks->available); } endrow(outfile); } table_end(outfile); if (config.fullhtml) { html_footer(outfile); } if (outfile == stdout) { ret = fflush(stdout); if (ret) { warn("output_html: fflush"); } } else { ret = close_stream(outfile); if (ret) { warn("output_html: fclose"); } } return 0; } /*! \brief Output cvs format. * FIXME: This function should return void. */ int output_csv(void) { unsigned int i; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; FILE *outfile; int ret; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { err(EXIT_FAILURE, "output_csv: %s", config.output_file); } } else { outfile = stdout; } range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; if (config.output_limit[0] & BIT1) { fprintf(outfile, "\"Ranges:\"\n"); fprintf (outfile, "\"shared net name\",\"first ip\",\"last ip\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\""); if (config.backups_found == true) { fprintf(outfile, ",\"bu\",\"bu perc\""); } fprintf(outfile, "\n"); } if (config.output_limit[1] & BIT1) { for (i = 0; i < num_ranges; i++) { if (range_p->shared_net) { fprintf(outfile, "\"%s\",", range_p->shared_net->name); } else { fprintf(outfile, "\"not_defined\","); } fprintf(outfile, "\"%s\",", ntop_ipaddr(&range_p->first_ip)); fprintf(outfile, "\"%s\",\"%g\",\"%g\",\"%.3f\",\"%g\",\"%g\",\"%.3f\"", ntop_ipaddr(&range_p->last_ip), range_size, range_p->count, (float)(100 * range_p->count) / range_size, range_p->touched, range_p->touched + range_p->count, (float)(100 * (range_p->touched + range_p->count)) / range_size); if (config.backups_found == true) { fprintf(outfile, ",\"%g\",\"%.3f\"", range_p->backups, (float)(100 * range_p->backups) / range_size); } fprintf(outfile, "\n"); range_p++; range_size = get_range_size(range_p); } fprintf(outfile, "\n"); } if (config.output_limit[0] & BIT2) { fprintf(outfile, "\"Shared networks:\"\n"); fprintf(outfile, "\"name\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\""); if (config.backups_found == true) { fprintf(outfile, ",\"bu\",\"bu perc\""); } fprintf(outfile, "\n"); } if (config.output_limit[1] & BIT2) { for (i = 0; i < num_shared_networks; i++) { shared_p++; fprintf(outfile, "\"%s\",\"%g\",\"%g\",\"%.3f\",\"%g\",\"%g\",\"%.3f\"", shared_p->name, shared_p->available, shared_p->used, (float)(100 * shared_p->used) / shared_p->available, shared_p->touched, shared_p->touched + shared_p->used, (float)(100 * (shared_p->touched + shared_p->used)) / shared_p->available); if (config.backups_found == true) { fprintf(outfile, ",\"%g\",\"%.3f\"", shared_p->backups, (float)(100 * shared_p->backups) / shared_p->available); } fprintf(outfile, "\n"); } fprintf(outfile, "\n"); } if (config.output_limit[0] & BIT3) { fprintf(outfile, "\"Sum of all ranges:\"\n"); fprintf(outfile, "\"name\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\""); if (config.backups_found == true) { fprintf(outfile, ",\"bu\",\"bu perc\""); } fprintf(outfile, "\n"); } if (config.output_limit[1] & BIT3) { fprintf(outfile, "\"%s\",\"%g\",\"%g\",\"%.3f\",\"%g\",\"%g\",\"%.3f\"", shared_networks->name, shared_networks->available, shared_networks->used, (float)(100 * shared_networks->used) / shared_networks->available, shared_networks->touched, shared_networks->touched + shared_networks->used, (float)(100 * (shared_networks->touched + shared_networks->used)) / shared_networks->available); if (config.backups_found == true) { fprintf(outfile, "%7g %8.3f", shared_networks->backups, (float)(100 * shared_networks->backups) / shared_networks->available); } fprintf(outfile, "\n"); } if (outfile == stdout) { ret = fflush(stdout); if (ret) { warn("output_cvs: fflush"); } } else { ret = close_stream(outfile); if (ret) { warn("output_cvs: fclose"); } } return 0; } /*! \brief Output alarm text, and return program exit value. * FIXME: This function should return void. */ int output_alarming(void) { FILE *outfile; struct range_t *range_p; double range_size; struct shared_network_t *shared_p; unsigned int i; float perc; int rw = 0, rc = 0, ro = 0, sw = 0, sc = 0, so = 0; int ret_val, ret; range_p = ranges; range_size = get_range_size(range_p); shared_p = shared_networks; if (config.output_file[0]) { outfile = fopen(config.output_file, "w+"); if (outfile == NULL) { err(EXIT_FAILURE, "output_alarming: %s", config.output_file); } } else { outfile = stdout; } if (config.output_limit[1] & BIT1) { for (i = 0; i < num_ranges; i++) { perc = (float)(100 * range_p->count) / range_size; if (config.critical < perc) rc++; else if (config.warning < perc) rw++; else ro++; range_p++; range_size = get_range_size(range_p); } } if (config.output_limit[1] & BIT2) { for (i = 0; i < num_shared_networks; i++) { perc = (float)(100 * shared_p->used) / shared_p->available; if (config.critical < perc) sc++; else if (config.warning < perc) sw++; else so++; shared_p++; } } if ((0 < rc && config.output_limit[1] & BIT1) || (0 < sc && config.output_limit[1] & BIT2)) { ret_val = 2; fprintf(outfile, "CRITICAL: %s: ", program_name); } else if ((0 < rw && config.output_limit[1] & BIT1) || (0 < sw && config.output_limit[1] & BIT2)) { ret_val = 1; fprintf(outfile, "WARNING: %s: ", program_name); } else { ret_val = 0; fprintf(outfile, "OK: "); } if (config.output_limit[0] & BIT1) { fprintf(outfile, "Ranges; crit: %d warn: %d ok: %d ", rc, rw, ro); } if (config.output_limit[0] & BIT2) { fprintf(outfile, "Shared nets; crit: %d warn: %d ok: %d", sc, sw, so); } fprintf(outfile, "\n"); if (outfile == stdout) { ret = fflush(stdout); if (ret) { warn("output_alarming: fflush"); } } else { ret = close_stream(outfile); if (ret) { warn("output_alarming: fclose"); } } return ret_val; }