iproute2/lib/color.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#include <stdio.h>
   3#include <stdarg.h>
   4#include <stdlib.h>
   5#include <string.h>
   6#include <unistd.h>
   7#include <sys/socket.h>
   8#include <sys/types.h>
   9#include <linux/if.h>
  10
  11#include "color.h"
  12#include "utils.h"
  13
  14static void set_color_palette(void);
  15
  16enum color {
  17        C_RED,
  18        C_GREEN,
  19        C_YELLOW,
  20        C_BLUE,
  21        C_MAGENTA,
  22        C_CYAN,
  23        C_WHITE,
  24        C_BOLD_RED,
  25        C_BOLD_GREEN,
  26        C_BOLD_YELLOW,
  27        C_BOLD_BLUE,
  28        C_BOLD_MAGENTA,
  29        C_BOLD_CYAN,
  30        C_BOLD_WHITE,
  31        C_CLEAR
  32};
  33
  34static const char * const color_codes[] = {
  35        "\e[31m",
  36        "\e[32m",
  37        "\e[33m",
  38        "\e[34m",
  39        "\e[35m",
  40        "\e[36m",
  41        "\e[37m",
  42        "\e[1;31m",
  43        "\e[1;32m",
  44        "\e[1;33m",
  45        "\e[1;34m",
  46        "\e[1;35m",
  47        "\e[1;36m",
  48        "\e[1;37m",
  49        "\e[0m",
  50        NULL,
  51};
  52
  53/* light background */
  54static enum color attr_colors_light[] = {
  55        C_CYAN,
  56        C_YELLOW,
  57        C_MAGENTA,
  58        C_BLUE,
  59        C_GREEN,
  60        C_RED,
  61        C_CLEAR,
  62};
  63
  64/* dark background */
  65static enum color attr_colors_dark[] = {
  66        C_BOLD_CYAN,
  67        C_BOLD_YELLOW,
  68        C_BOLD_MAGENTA,
  69        C_BOLD_BLUE,
  70        C_BOLD_GREEN,
  71        C_BOLD_RED,
  72        C_CLEAR
  73};
  74
  75static int is_dark_bg;
  76static int color_is_enabled;
  77
  78static void enable_color(void)
  79{
  80        color_is_enabled = 1;
  81        set_color_palette();
  82}
  83
  84bool check_enable_color(int color, int json)
  85{
  86        if (json || color == COLOR_OPT_NEVER)
  87                return false;
  88
  89        if (color == COLOR_OPT_ALWAYS || isatty(fileno(stdout))) {
  90                enable_color();
  91                return true;
  92        }
  93        return false;
  94}
  95
  96bool matches_color(const char *arg, int *val)
  97{
  98        char *dup, *p;
  99
 100        if (!val)
 101                return false;
 102
 103        dup = strdupa(arg);
 104        p = strchrnul(dup, '=');
 105        if (*p)
 106                *(p++) = '\0';
 107
 108        if (matches(dup, "-color"))
 109                return false;
 110
 111        if (*p == '\0' || !strcmp(p, "always"))
 112                *val = COLOR_OPT_ALWAYS;
 113        else if (!strcmp(p, "auto"))
 114                *val = COLOR_OPT_AUTO;
 115        else if (!strcmp(p, "never"))
 116                *val = COLOR_OPT_NEVER;
 117        else
 118                return false;
 119        return true;
 120}
 121
 122static void set_color_palette(void)
 123{
 124        char *p = getenv("COLORFGBG");
 125
 126        /*
 127         * COLORFGBG environment variable usually contains either two or three
 128         * values separated by semicolons; we want the last value in either case.
 129         * If this value is 0-6 or 8, background is dark.
 130         */
 131        if (p && (p = strrchr(p, ';')) != NULL
 132                && ((p[1] >= '0' && p[1] <= '6') || p[1] == '8')
 133                && p[2] == '\0')
 134                is_dark_bg = 1;
 135}
 136
 137__attribute__((format(printf, 3, 4)))
 138int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...)
 139{
 140        int ret = 0;
 141        va_list args;
 142
 143        va_start(args, fmt);
 144
 145        if (!color_is_enabled || attr == COLOR_NONE) {
 146                ret = vfprintf(fp, fmt, args);
 147                goto end;
 148        }
 149
 150        ret += fprintf(fp, "%s", color_codes[is_dark_bg ?
 151                attr_colors_dark[attr] : attr_colors_light[attr]]);
 152
 153        ret += vfprintf(fp, fmt, args);
 154        ret += fprintf(fp, "%s", color_codes[C_CLEAR]);
 155
 156end:
 157        va_end(args);
 158        return ret;
 159}
 160
 161enum color_attr ifa_family_color(__u8 ifa_family)
 162{
 163        switch (ifa_family) {
 164        case AF_INET:
 165                return COLOR_INET;
 166        case AF_INET6:
 167                return COLOR_INET6;
 168        default:
 169                return COLOR_NONE;
 170        }
 171}
 172
 173enum color_attr oper_state_color(__u8 state)
 174{
 175        switch (state) {
 176        case IF_OPER_UP:
 177                return COLOR_OPERSTATE_UP;
 178        case IF_OPER_DOWN:
 179                return COLOR_OPERSTATE_DOWN;
 180        default:
 181                return COLOR_NONE;
 182        }
 183}
 184