Blame lib/color.c

Packit d3f73b
/* SPDX-License-Identifier: GPL-2.0 */
Packit d3f73b
#include <stdio.h>
Packit d3f73b
#include <stdarg.h>
Packit d3f73b
#include <stdlib.h>
Packit d3f73b
#include <string.h>
Packit d3f73b
#include <unistd.h>
Packit d3f73b
#include <sys/socket.h>
Packit d3f73b
#include <sys/types.h>
Packit d3f73b
#include <linux/if.h>
Packit d3f73b
Packit d3f73b
#include "color.h"
Packit d3f73b
#include "utils.h"
Packit d3f73b
Packit d3f73b
static void set_color_palette(void);
Packit d3f73b
Packit d3f73b
enum color {
Packit d3f73b
	C_RED,
Packit d3f73b
	C_GREEN,
Packit d3f73b
	C_YELLOW,
Packit d3f73b
	C_BLUE,
Packit d3f73b
	C_MAGENTA,
Packit d3f73b
	C_CYAN,
Packit d3f73b
	C_WHITE,
Packit d3f73b
	C_BOLD_RED,
Packit d3f73b
	C_BOLD_GREEN,
Packit d3f73b
	C_BOLD_YELLOW,
Packit d3f73b
	C_BOLD_BLUE,
Packit d3f73b
	C_BOLD_MAGENTA,
Packit d3f73b
	C_BOLD_CYAN,
Packit d3f73b
	C_BOLD_WHITE,
Packit d3f73b
	C_CLEAR
Packit d3f73b
};
Packit d3f73b
Packit d3f73b
static const char * const color_codes[] = {
Packit d3f73b
	"\e[31m",
Packit d3f73b
	"\e[32m",
Packit d3f73b
	"\e[33m",
Packit d3f73b
	"\e[34m",
Packit d3f73b
	"\e[35m",
Packit d3f73b
	"\e[36m",
Packit d3f73b
	"\e[37m",
Packit d3f73b
	"\e[1;31m",
Packit d3f73b
	"\e[1;32m",
Packit d3f73b
	"\e[1;33m",
Packit d3f73b
	"\e[1;34m",
Packit d3f73b
	"\e[1;35m",
Packit d3f73b
	"\e[1;36m",
Packit d3f73b
	"\e[1;37m",
Packit d3f73b
	"\e[0m",
Packit d3f73b
	NULL,
Packit d3f73b
};
Packit d3f73b
Packit d3f73b
/* light background */
Packit d3f73b
static enum color attr_colors_light[] = {
Packit d3f73b
	C_CYAN,
Packit d3f73b
	C_YELLOW,
Packit d3f73b
	C_MAGENTA,
Packit d3f73b
	C_BLUE,
Packit d3f73b
	C_GREEN,
Packit d3f73b
	C_RED,
Packit d3f73b
	C_CLEAR,
Packit d3f73b
};
Packit d3f73b
Packit d3f73b
/* dark background */
Packit d3f73b
static enum color attr_colors_dark[] = {
Packit d3f73b
	C_BOLD_CYAN,
Packit d3f73b
	C_BOLD_YELLOW,
Packit d3f73b
	C_BOLD_MAGENTA,
Packit d3f73b
	C_BOLD_BLUE,
Packit d3f73b
	C_BOLD_GREEN,
Packit d3f73b
	C_BOLD_RED,
Packit d3f73b
	C_CLEAR
Packit d3f73b
};
Packit d3f73b
Packit d3f73b
static int is_dark_bg;
Packit d3f73b
static int color_is_enabled;
Packit d3f73b
Packit d3f73b
static void enable_color(void)
Packit d3f73b
{
Packit d3f73b
	color_is_enabled = 1;
Packit d3f73b
	set_color_palette();
Packit d3f73b
}
Packit d3f73b
Packit d3f73b
bool check_enable_color(int color, int json)
Packit d3f73b
{
Packit d3f73b
	if (json || color == COLOR_OPT_NEVER)
Packit d3f73b
		return false;
Packit d3f73b
Packit d3f73b
	if (color == COLOR_OPT_ALWAYS || isatty(fileno(stdout))) {
Packit d3f73b
		enable_color();
Packit d3f73b
		return true;
Packit d3f73b
	}
Packit d3f73b
	return false;
Packit d3f73b
}
Packit d3f73b
Packit d3f73b
bool matches_color(const char *arg, int *val)
Packit d3f73b
{
Packit d3f73b
	char *dup, *p;
Packit d3f73b
Packit d3f73b
	if (!val)
Packit d3f73b
		return false;
Packit d3f73b
Packit d3f73b
	dup = strdupa(arg);
Packit d3f73b
	p = strchrnul(dup, '=');
Packit d3f73b
	if (*p)
Packit d3f73b
		*(p++) = '\0';
Packit d3f73b
Packit d3f73b
	if (matches(dup, "-color"))
Packit d3f73b
		return false;
Packit d3f73b
Packit d3f73b
	if (*p == '\0' || !strcmp(p, "always"))
Packit d3f73b
		*val = COLOR_OPT_ALWAYS;
Packit d3f73b
	else if (!strcmp(p, "auto"))
Packit d3f73b
		*val = COLOR_OPT_AUTO;
Packit d3f73b
	else if (!strcmp(p, "never"))
Packit d3f73b
		*val = COLOR_OPT_NEVER;
Packit d3f73b
	else
Packit d3f73b
		return false;
Packit d3f73b
	return true;
Packit d3f73b
}
Packit d3f73b
Packit d3f73b
static void set_color_palette(void)
Packit d3f73b
{
Packit d3f73b
	char *p = getenv("COLORFGBG");
Packit d3f73b
Packit d3f73b
	/*
Packit d3f73b
	 * COLORFGBG environment variable usually contains either two or three
Packit d3f73b
	 * values separated by semicolons; we want the last value in either case.
Packit d3f73b
	 * If this value is 0-6 or 8, background is dark.
Packit d3f73b
	 */
Packit d3f73b
	if (p && (p = strrchr(p, ';')) != NULL
Packit d3f73b
		&& ((p[1] >= '0' && p[1] <= '6') || p[1] == '8')
Packit d3f73b
		&& p[2] == '\0')
Packit d3f73b
		is_dark_bg = 1;
Packit d3f73b
}
Packit d3f73b
Packit d3f73b
__attribute__((format(printf, 3, 4)))
Packit d3f73b
int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...)
Packit d3f73b
{
Packit d3f73b
	int ret = 0;
Packit d3f73b
	va_list args;
Packit d3f73b
Packit d3f73b
	va_start(args, fmt);
Packit d3f73b
Packit d3f73b
	if (!color_is_enabled || attr == COLOR_NONE) {
Packit d3f73b
		ret = vfprintf(fp, fmt, args);
Packit d3f73b
		goto end;
Packit d3f73b
	}
Packit d3f73b
Packit d3f73b
	ret += fprintf(fp, "%s", color_codes[is_dark_bg ?
Packit d3f73b
		attr_colors_dark[attr] : attr_colors_light[attr]]);
Packit d3f73b
Packit d3f73b
	ret += vfprintf(fp, fmt, args);
Packit d3f73b
	ret += fprintf(fp, "%s", color_codes[C_CLEAR]);
Packit d3f73b
Packit d3f73b
end:
Packit d3f73b
	va_end(args);
Packit d3f73b
	return ret;
Packit d3f73b
}
Packit d3f73b
Packit d3f73b
enum color_attr ifa_family_color(__u8 ifa_family)
Packit d3f73b
{
Packit d3f73b
	switch (ifa_family) {
Packit d3f73b
	case AF_INET:
Packit d3f73b
		return COLOR_INET;
Packit d3f73b
	case AF_INET6:
Packit d3f73b
		return COLOR_INET6;
Packit d3f73b
	default:
Packit d3f73b
		return COLOR_NONE;
Packit d3f73b
	}
Packit d3f73b
}
Packit d3f73b
Packit d3f73b
enum color_attr oper_state_color(__u8 state)
Packit d3f73b
{
Packit d3f73b
	switch (state) {
Packit d3f73b
	case IF_OPER_UP:
Packit d3f73b
		return COLOR_OPERSTATE_UP;
Packit d3f73b
	case IF_OPER_DOWN:
Packit d3f73b
		return COLOR_OPERSTATE_DOWN;
Packit d3f73b
	default:
Packit d3f73b
		return COLOR_NONE;
Packit d3f73b
	}
Packit d3f73b
}