diff --git a/README b/README index 40c8171..747e8f1 100644 --- a/README +++ b/README @@ -43,6 +43,12 @@ Dependencies to other projects. See quick start. + https://getbootstrap.com/ + https://datatables.net/ + + Java Bootstrap and DataTables java scripts are used in html + output. + Test data wanted. Maintainer is interested to get copy of your dhcpd.conf diff --git a/man/dhcpd-pools.1.in b/man/dhcpd-pools.1.in index e55f5b6..4f5ca76 100644 --- a/man/dhcpd-pools.1.in +++ b/man/dhcpd-pools.1.in @@ -68,12 +68,10 @@ Sort results in reverse order. Output format. Text .RI ( t ). -Standard html -.RI ( h ) -outputs only the HTML tables, and is useful for embedding more complex web -pages. Full-html +Full-html .RI ( H ) -provides complete HTML headers, etc., including in-line CSS. The +page output. +The .RI ( c ) stands for comma-separated values. Output format xml .RI ( x ) diff --git a/src/dhcpd-pools.c b/src/dhcpd-pools.c index 7b765d7..8c92b3a 100644 --- a/src/dhcpd-pools.c +++ b/src/dhcpd-pools.c @@ -145,7 +145,6 @@ int main(int argc, char **argv) config.output_limit[0] = (*tmp - '0'); tmp++; config.output_limit[1] = (*tmp - '0'); - config.fullhtml = false; /* Make sure some output format is selected by default */ strncpy(config.output_format, OUTPUT_FORMAT, (size_t)1); /* Default sort order is by IPs small to big */ @@ -245,11 +244,10 @@ int main(int argc, char **argv) output_analysis = output_alarming; break; case 'h': - output_analysis = output_html; + error(EXIT_FAILURE, 0, "html table only output format is deprecated"); break; case 'H': output_analysis = output_html; - config.fullhtml = true; break; case 'x': output_analysis = output_xml; diff --git a/src/dhcpd-pools.h b/src/dhcpd-pools.h index 79335fb..afee609 100644 --- a/src/dhcpd-pools.h +++ b/src/dhcpd-pools.h @@ -124,7 +124,6 @@ struct configuration_t { char *dhcpdconf_file; char *dhcpdlease_file; char output_format[2]; - bool fullhtml; char sort[6]; bool reverse_order; char *output_file; diff --git a/src/other.c b/src/other.c index 040c55a..bfdb6bb 100644 --- a/src/other.c +++ b/src/other.c @@ -448,7 +448,6 @@ This is ISC dhcpd pools usage analyzer.\n\ fprintf(out, "\ -f, --format=[thHcxXjJ] output format\n\ t for text\n\ - h for html table\n\ H for full html page\n\ x for xml\n\ X for xml with active lease details\n\ diff --git a/src/output.c b/src/output.c index 0828646..add823f 100644 --- a/src/output.c +++ b/src/output.c @@ -478,63 +478,23 @@ static void html_header(FILE *restrict f) if (strftime(outstr, sizeof(outstr), nl_langinfo(D_T_FMT), &result) == 0) { error(EXIT_FAILURE, 0, "html_header: strftime returned 0"); } - - fprintf(f, "\n"); + fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); - fprintf(f, "\n"); - fprintf(f, "ISC dhcpd stats\n"); + fprintf(f, "ISC dhcpd dhcpd-pools output\n"); + fprintf(f, "\n"); + fprintf(f, "\n"); + fprintf(f, "\n"); + fprintf(f, "\n"); + fprintf(f, ""); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); - fprintf(f, "The lease file mtime: %s", outstr); + fprintf(f, "
\n"); + fprintf(f, "

ISC DHCPD status

\n"); + fprintf(f, "File %s was last modified at %s
\n", config.dhcpdlease_file, outstr); } /*! \brief Footer for full html output format. @@ -543,36 +503,36 @@ static void html_header(FILE *restrict f) */ 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"); + fprintf(f, "
\n"); + fprintf(f, "Generated using %s
\n", PACKAGE_STRING); + fprintf(f, "More info at %s\n", PACKAGE_URL, PACKAGE_URL); + fprintf(f, "
\n"); + fprintf(f, "\n"); + fprintf(f, "\n"); + fprintf(f, "\n"); + fprintf(f, "\n"); + fprintf(f, "\n"); + fprintf(f, "\n"); } -/*! \brief A new row for html output format. +/*! \brief Start a html tag. * * \param f Output file descriptor. + * \param tag The html tag. */ -static void newrow(FILE *restrict f) +static void start_tag(FILE *restrict f, char const *restrict tag) { - fprintf(f, "\n"); + fprintf(f, "<%s>\n", tag); } -/*! \brief End a row for html output format. +/*! \brief End a html tag. * * \param f Output file descriptor. + * \param tag The html tag. */ -static void endrow(FILE *restrict f) +static void end_tag(FILE *restrict f, char const *restrict tag) { - fprintf(f, "\n"); + fprintf(f, "\n", tag); } /*! \brief Line with text in html output format. @@ -583,9 +543,9 @@ static void endrow(FILE *restrict f) * \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) + char const *restrict text) { - fprintf(f, "<%s class=\"%s\">%s\n", type, class, text, type); + fprintf(f, "<%s>%s\n", type, text, type); } /*! \brief Line with digit in html output format. @@ -596,7 +556,7 @@ static void output_line(FILE *restrict f, char const *restrict type, */ static void output_double(FILE *restrict f, char const *restrict type, double d) { - fprintf(f, "<%s class=\"ralign\">%g\n", type, d, type); + fprintf(f, "<%s>%g\n", type, d, type); } /*! \brief Line with float in html output format. @@ -605,20 +565,18 @@ static void output_double(FILE *restrict f, char const *restrict type, double d) * \param type HTML tag name. * \param fl Actual payload of the printout. */ -static void output_float(FILE *f, char const *restrict type, float fl) +static void output_float(FILE *restrict f, char const *restrict type, float fl) { - fprintf(f, "<%s class=\"ralign\">%.3f\n", type, fl, type); + fprintf(f, "<%s>%.3f\n", type, fl, type); } /*! \brief Begin table in html output format. * * \param f Output file descriptor. */ -static void table_start(FILE *restrict f) +static void table_start(FILE *restrict f, char const *restrict id, char const *restrict summary) { - fprintf(f, "\n"); + fprintf(f, "
\n", id, summary); } /*! \brief End table in html output format. @@ -637,12 +595,7 @@ static void table_end(FILE *restrict f) */ static void newsection(FILE *restrict f, char const *restrict title) { - newrow(f); - output_line(f, "td", "lalign", " "); - endrow(f); - newrow(f); - output_line(f, "th", "section", title); - endrow(f); + output_line(f, "h3", title); } /*! \brief Output html format. @@ -669,123 +622,30 @@ int output_html(void) 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", "lalign", "shared net name"); - output_line(outfile, "th", "lalign", "first ip"); - output_line(outfile, "th", "lalign", "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", "lalign", range_p->shared_net->name); - } else { - output_line(outfile, "td", "lalign", "not_defined"); - } - output_line(outfile, "td", "lalign", ntop_ipaddr(&range_p->first_ip)); - output_line(outfile, "td", "lalign", 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", "lalign", "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", "lalign", shared_p->name); - output_double(outfile, "td", shared_p->available); - output_double(outfile, "td", shared_p->used); - output_float(outfile, "td", - shared_p->available == - 0 ? -NAN : (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", - shared_p->available == 0 ? -NAN : (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", - shared_p->available == 0 ? -NAN : (float)(100 * - shared_p->backups) - / shared_p->available); - } - - endrow(outfile); - } - } + html_header(outfile); + newsection(outfile, "Sum of all"); + table_start(outfile, "a", "all"); if (config.output_limit[0] & BIT3) { - newsection(outfile, "Sum of all ranges:"); - newrow(outfile); - output_line(outfile, "th", "lalign", "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"); + start_tag(outfile, "thead"); + start_tag(outfile, "tr"); + output_line(outfile, "th", "name"); + output_line(outfile, "th", "max"); + output_line(outfile, "th", "cur"); + output_line(outfile, "th", "percent"); + output_line(outfile, "th", "touch"); + output_line(outfile, "th", "t+c"); + output_line(outfile, "th", "t+c perc"); if (config.backups_found == true) { - output_line(outfile, "th", "ralign", "bu"); - output_line(outfile, "th", "ralign", "bu perc"); + output_line(outfile, "th", "bu"); + output_line(outfile, "th", "bu perc"); } - - endrow(outfile); + end_tag(outfile, "tr"); + end_tag(outfile, "thead"); } if (config.output_limit[1] & BIT3) { - newrow(outfile); - output_line(outfile, "td", "lalign", shared_networks->name); + start_tag(outfile, "tbody"); + start_tag(outfile, "tr"); + output_line(outfile, "td", shared_networks->name); output_double(outfile, "td", shared_networks->available); output_double(outfile, "td", shared_networks->used); output_float(outfile, "td", @@ -807,12 +667,113 @@ int output_html(void) shared_networks->backups) / shared_networks->available); } - endrow(outfile); + end_tag(outfile, "tr"); + end_tag(outfile, "tbody"); } table_end(outfile); - if (config.fullhtml) { - html_footer(outfile); + newsection(outfile, "Shared networks"); + table_start(outfile, "s", "snet"); + if (config.output_limit[0] & BIT2) { + start_tag(outfile, "thead"); + start_tag(outfile, "tr"); + output_line(outfile, "th", "name"); + output_line(outfile, "th", "max"); + output_line(outfile, "th", "cur"); + output_line(outfile, "th", "percent"); + output_line(outfile, "th", "touch"); + output_line(outfile, "th", "t+c"); + output_line(outfile, "th", "t+c perc"); + if (config.backups_found == true) { + output_line(outfile, "th", "bu"); + output_line(outfile, "th", "bu perc"); + } + end_tag(outfile, "tr"); + end_tag(outfile, "thead"); } + if (config.output_limit[1] & BIT2) { + start_tag(outfile, "tbody"); + for (i = 0; i < num_shared_networks; i++) { + shared_p++; + start_tag(outfile, "tr"); + output_line(outfile, "td", shared_p->name); + output_double(outfile, "td", shared_p->available); + output_double(outfile, "td", shared_p->used); + output_float(outfile, "td", + shared_p->available == + 0 ? -NAN : (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", + shared_p->available == 0 ? -NAN : (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", + shared_p->available == 0 ? -NAN : (float)(100 * + shared_p->backups) + / shared_p->available); + } + end_tag(outfile, "tr"); + } + end_tag(outfile, "tbody"); + } + table_end(outfile); + newsection(outfile, "Ranges"); + table_start(outfile, "r", "ranges"); + if (config.output_limit[0] & BIT1) { + start_tag(outfile, "thead"); + start_tag(outfile, "tr"); + output_line(outfile, "th", "shared net name"); + output_line(outfile, "th", "first ip"); + output_line(outfile, "th", "last ip"); + output_line(outfile, "th", "max"); + output_line(outfile, "th", "cur"); + output_line(outfile, "th", "percent"); + output_line(outfile, "th", "touch"); + output_line(outfile, "th", "t+c"); + output_line(outfile, "th", "t+c perc"); + if (config.backups_found == true) { + output_line(outfile, "th", "bu"); + output_line(outfile, "th", "bu perc"); + } + end_tag(outfile, "tr"); + end_tag(outfile, "thead"); + } + if (config.output_limit[1] & BIT1) { + start_tag(outfile, "tbody"); + for (i = 0; i < num_ranges; i++) { + start_tag(outfile, "tr"); + if (range_p->shared_net) { + output_line(outfile, "td", range_p->shared_net->name); + } else { + output_line(outfile, "td", "not_defined"); + } + output_line(outfile, "td", ntop_ipaddr(&range_p->first_ip)); + output_line(outfile, "td", 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); + } + end_tag(outfile, "tr"); + range_p++; + range_size = get_range_size(range_p); + } + end_tag(outfile, "tbody"); + } + table_end(outfile); + html_footer(outfile); if (outfile == stdout) { ret = fflush(stdout); if (ret) {