output: add color support to text output

When --warning or --critical thresholds are defined with text output lines
that exceed threshold will be either yellow (warning) or red (critical).

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
Sami Kerola 2017-11-05 17:07:16 +00:00
parent 48962004b8
commit 344ed2900d
No known key found for this signature in database
GPG key ID: A9553245FDE9B739
8 changed files with 128 additions and 28 deletions

View file

@ -39,6 +39,7 @@
#include <config.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
@ -109,6 +110,7 @@ int main(int argc, char **argv)
OPT_MINSIZE,
OPT_WARN_COUNT,
OPT_CRIT_COUNT,
OPT_COLOR,
OPT_SET_IPV
};
int ret_val;
@ -116,6 +118,7 @@ int main(int argc, char **argv)
static struct option const long_options[] = {
{"config", required_argument, NULL, 'c'},
{"leases", required_argument, NULL, 'l'},
{"color", required_argument, NULL, OPT_COLOR},
{"format", required_argument, NULL, 'f'},
{"sort", required_argument, NULL, 's'},
{"reverse", no_argument, NULL, 'r'},
@ -152,6 +155,7 @@ int main(int argc, char **argv)
config.warn_count = 0x100000000; /* == 2^32 that is the entire IPv4 space */
config.crit_count = 0x100000000; /* basically turns off the count criteria */
config.perfdata = 0;
config.color_mode = color_auto;
/* File location defaults */
strncpy(config.dhcpdconf_file, DHCPDCONF_FILE, MAXLEN - 1);
strncpy(config.dhcpdlease_file, DHCPDLEASE_FILE, MAXLEN - 1);
@ -219,6 +223,11 @@ int main(int argc, char **argv)
config.header_limit = return_limit(optarg[0]);
config.number_limit = return_limit(optarg[1]);
break;
case OPT_COLOR:
config.color_mode = parse_color_mode(optarg);
if (config.color_mode == color_unknown)
error(EXIT_FAILURE, errno, "unknown color mode: %s", quote(optarg));
break;
case OPT_SNET_ALARMS:
config.snet_alarms = 1;
break;

View file

@ -187,6 +187,21 @@ enum limbits {
# define STATE_WARNING 1
# define STATE_CRITICAL 2
/*! \def COLOR_BOLD_RED
* \brief Shell warning color.
*/
# define COLOR_BOLD_RED "\033[1;31m"
# define COLOR_BOLD_YELLOW "\033[1;33m"
# define COLOR_BOLD_GREEN "\033[1;32m"
# define COLOR_BOLD_BLUE "\033[1;34m"
# define COLOR_RESET "\033[0m"
enum color_mode {
color_unknown,
color_off,
color_on,
color_auto /* default */
};
/*! \var comparer_t
* \brief Function pointer holding sort algorithm.
*/
@ -222,8 +237,10 @@ struct configuration_t {
perfdata:1,
all_as_shared:1,
header_limit:3,
number_limit:3;
number_limit:3,
color_mode:2;
};
/* Global variables */
/* \var prefix_length Length of each prefix. */
extern int prefix_length[2][NUM_OF_PREFIX];
@ -284,6 +301,7 @@ _DP_ATTRIBUTE_HOT;
extern int xstrstr_v6(const char *restrict str)
_DP_ATTRIBUTE_HOT;
extern int parse_color_mode(const char *restrict optarg);
extern double strtod_or_err(const char *restrict str, const char *restrict errmesg);
extern void __attribute__ ((noreturn)) print_version(void);
extern void __attribute__ ((noreturn)) usage(int status);

View file

@ -454,6 +454,22 @@ int
return NUM_OF_PREFIX;
}
/*! \brief Parse option argument color mode.
*
* \param Color mode string.
* \return color mode enum.
*/
int parse_color_mode(const char *restrict optarg)
{
if (!strcmp(optarg, "always"))
return color_on;
if (!strcmp(optarg, "auto"))
return color_auto;
if (!strcmp(optarg, "never"))
return color_off;
return color_unknown;
}
/*! \brief Return a double floating point value.
*
* \param str String to be converted to a double.
@ -562,6 +578,7 @@ void __attribute__ ((__noreturn__)) usage(int status)
fputs( " -r, --reverse reverse order sort\n", out);
fputs( " -o, --output=FILE output into a file\n", out);
fputs( " -L, --limit=NR output limit mask 77 - 00\n", out);
fputs( " --color=WHEN use colors 'always', 'never', or 'auto'\n", out);
fputs( " --warning=PERC set warning alarming limit\n", out);
fputs( " --critical=PERC set critical alarming limit\n", out);
fputs( " --warn-count=NR a number of free leases before warning raised\n", out);

View file

@ -50,6 +50,7 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "close-stream.h"
#include "error.h"
@ -70,25 +71,19 @@ static void range_output_helper(struct output_helper_t *oh, struct range_t *rang
oh->bup = (double)(100 * range_p->backups) / oh->range_size;
}
/* set status */
if (config.snet_alarms && range_p->shared_net != shared_networks) {
oh->status = STATUS_SUPPRESSED;
return;
}
if (oh->range_size <= config.minsize) {
oh->status = STATUS_IGNORED;
return;
}
if (config.critical < oh->percent
&& (oh->range_size - range_p->count) < config.crit_count) {
oh->status = STATUS_CRIT;
return;
}
if (config.warning < oh->percent
&& (oh->range_size - range_p->count) < config.warn_count) {
oh->status = STATUS_WARN;
return;
}
oh->status = STATUS_OK;
if (config.critical < oh->percent
&& (oh->range_size - range_p->count) < config.crit_count)
oh->status = STATUS_CRIT;
else if (config.warning < oh->percent
&& (oh->range_size - range_p->count) < config.warn_count)
oh->status = STATUS_WARN;
if (oh->status != STATUS_OK) {
if (oh->range_size <= config.minsize)
oh->status = STATUS_IGNORED;
else if (config.snet_alarms && range_p->shared_net != shared_networks)
oh->status = STATUS_SUPPRESSED;
}
}
/*! \brief Calculate shared network percentages and such. */
@ -109,7 +104,11 @@ static void shnet_output_helper(struct output_helper_t *oh, struct shared_networ
}
}
/* set status */
if (oh->percent == NAN || shared_p->available <= config.minsize) {
if (oh->percent == NAN) {
oh->status = STATUS_SUPPRESSED;
return;
}
if (shared_p->available <= config.minsize) {
oh->status = STATUS_IGNORED;
return;
}
@ -124,6 +123,26 @@ static void shnet_output_helper(struct output_helper_t *oh, struct shared_networ
oh->status = STATUS_OK;
}
static int start_color(struct output_helper_t *oh, FILE *outfile)
{
if (oh->status == STATUS_CRIT) {
fputs(COLOR_BOLD_RED, outfile);
return 1;
}
if (oh->status == STATUS_WARN) {
fputs(COLOR_BOLD_YELLOW, outfile);
return 1;
}
if (oh->status == STATUS_IGNORED) {
fputs(COLOR_BOLD_GREEN, outfile);
return 1;
}
if (oh->status == STATUS_SUPPRESSED) {
fputs(COLOR_BOLD_BLUE, outfile);
return 1;
}
return 0;
}
/*! \brief Text output format, which is the default. */
static int output_txt(void)
{
@ -135,6 +154,10 @@ static int output_txt(void)
FILE *outfile;
int max_ipaddr_length = config.ip_version == IPv6 ? 39 : 16;
if (config.color_mode == color_auto && isatty(STDIN_FILENO)) {
config.color_mode = color_on;
}
if (config.output_file[0]) {
outfile = fopen(config.output_file, "w+");
if (outfile == NULL) {
@ -164,7 +187,10 @@ static int output_txt(void)
}
if (config.number_limit & R_BIT) {
for (i = 0; i < num_ranges; i++) {
int color_set = 0;
range_output_helper(&oh, range_p);
if (config.color_mode == color_on)
color_set = start_color(&oh, outfile);
if (range_p->shared_net) {
fprintf(outfile, "%-20s", range_p->shared_net->name);
} else {
@ -189,6 +215,8 @@ static int output_txt(void)
fprintf(outfile, "%7g %8.3f",
range_p->backups, oh.bup);
}
if (color_set)
fputs(COLOR_RESET, outfile);
fprintf(outfile, "\n");
range_p++;
}
@ -207,8 +235,11 @@ static int output_txt(void)
}
if (config.number_limit & S_BIT) {
for (i = 0; i < num_shared_networks; i++) {
int color_set = 0;
shared_p++;
shnet_output_helper(&oh, shared_p);
if (config.color_mode == color_on)
color_set = start_color(&oh, outfile);
fprintf(outfile,
"%-20s %5g %5g %10.3f %7g %6g %9.3f",
shared_p->name,
@ -223,7 +254,8 @@ static int output_txt(void)
shared_p->backups,
oh.bup);
}
if (color_set)
fputs(COLOR_RESET, outfile);
fprintf(outfile, "\n");
}
}
@ -241,7 +273,10 @@ static int output_txt(void)
fprintf(outfile, "\n");
}
if (config.number_limit & A_BIT) {
int color_set = 0;
shnet_output_helper(&oh, shared_networks);
if (config.color_mode == color_on)
color_set = start_color(&oh, outfile);
fprintf(outfile, "%-20s %5g %5g %10.3f %7g %6g %9.3f",
shared_networks->name,
shared_networks->available,
@ -256,6 +291,8 @@ static int output_txt(void)
shared_networks->backups,
oh.bup);
}
if (color_set)
fputs(COLOR_RESET, outfile);
fprintf(outfile, "\n");
}
if (outfile == stdout) {