trace2 / tr2_sysenv.con commit Merge branch 'mh/import-transport-fd-fix' (2a983b2)
   1#include "cache.h"
   2#include "config.h"
   3#include "dir.h"
   4#include "tr2_sysenv.h"
   5
   6/*
   7 * Each entry represents a trace2 setting.
   8 * See Documentation/technical/api-trace2.txt
   9 */
  10struct tr2_sysenv_entry {
  11        const char *env_var_name;
  12        const char *git_config_name;
  13
  14        char *value;
  15        unsigned int getenv_called : 1;
  16};
  17
  18/*
  19 * This table must match "enum tr2_sysenv_variable" in tr2_sysenv.h.
  20 *
  21 * The strings in this table are constant and must match the published
  22 * config and environment variable names as described in the documentation.
  23 *
  24 * We do not define entries for the GIT_TRACE2_PARENT_* environment
  25 * variables because they are transient and used to pass information
  26 * from parent to child git processes, rather than settings.
  27 */
  28/* clang-format off */
  29static struct tr2_sysenv_entry tr2_sysenv_settings[] = {
  30        [TR2_SYSENV_CFG_PARAM]     = { "GIT_TRACE2_CONFIG_PARAMS",
  31                                       "trace2.configparams" },
  32
  33        [TR2_SYSENV_DST_DEBUG]     = { "GIT_TRACE2_DST_DEBUG",
  34                                       "trace2.destinationdebug" },
  35
  36        [TR2_SYSENV_NORMAL]        = { "GIT_TRACE2",
  37                                       "trace2.normaltarget" },
  38        [TR2_SYSENV_NORMAL_BRIEF]  = { "GIT_TRACE2_BRIEF",
  39                                       "trace2.normalbrief" },
  40
  41        [TR2_SYSENV_EVENT]         = { "GIT_TRACE2_EVENT",
  42                                       "trace2.eventtarget" },
  43        [TR2_SYSENV_EVENT_BRIEF]   = { "GIT_TRACE2_EVENT_BRIEF",
  44                                       "trace2.eventbrief" },
  45        [TR2_SYSENV_EVENT_NESTING] = { "GIT_TRACE2_EVENT_NESTING",
  46                                       "trace2.eventnesting" },
  47
  48        [TR2_SYSENV_PERF]          = { "GIT_TRACE2_PERF",
  49                                       "trace2.perftarget" },
  50        [TR2_SYSENV_PERF_BRIEF]    = { "GIT_TRACE2_PERF_BRIEF",
  51                                       "trace2.perfbrief" },
  52};
  53/* clang-format on */
  54
  55static int tr2_sysenv_cb(const char *key, const char *value, void *d)
  56{
  57        int k;
  58
  59        if (!starts_with(key, "trace2."))
  60                return 0;
  61
  62        for (k = 0; k < ARRAY_SIZE(tr2_sysenv_settings); k++) {
  63                if (!strcmp(key, tr2_sysenv_settings[k].git_config_name)) {
  64                        free(tr2_sysenv_settings[k].value);
  65                        tr2_sysenv_settings[k].value = xstrdup(value);
  66                        return 0;
  67                }
  68        }
  69
  70        return 0;
  71}
  72
  73/*
  74 * Load Trace2 settings from the system config (usually "/etc/gitconfig"
  75 * unless we were built with a runtime-prefix).  These are intended to
  76 * define the default values for Trace2 as requested by the administrator.
  77 *
  78 * Then override with the Trace2 settings from the global config.
  79 */
  80void tr2_sysenv_load(void)
  81{
  82        if (ARRAY_SIZE(tr2_sysenv_settings) != TR2_SYSENV_MUST_BE_LAST)
  83                BUG("tr2_sysenv_settings size is wrong");
  84
  85        read_very_early_config(tr2_sysenv_cb, NULL);
  86}
  87
  88/*
  89 * Return the value for the requested Trace2 setting from these sources:
  90 * the system config, the global config, and the environment.
  91 */
  92const char *tr2_sysenv_get(enum tr2_sysenv_variable var)
  93{
  94        if (var >= TR2_SYSENV_MUST_BE_LAST)
  95                BUG("tr2_sysenv_get invalid var '%d'", var);
  96
  97        if (!tr2_sysenv_settings[var].getenv_called) {
  98                const char *v = getenv(tr2_sysenv_settings[var].env_var_name);
  99                if (v && *v) {
 100                        free(tr2_sysenv_settings[var].value);
 101                        tr2_sysenv_settings[var].value = xstrdup(v);
 102                }
 103                tr2_sysenv_settings[var].getenv_called = 1;
 104        }
 105
 106        return tr2_sysenv_settings[var].value;
 107}
 108
 109/*
 110 * Return a friendly name for this setting that is suitable for printing
 111 * in an error messages.
 112 */
 113const char *tr2_sysenv_display_name(enum tr2_sysenv_variable var)
 114{
 115        if (var >= TR2_SYSENV_MUST_BE_LAST)
 116                BUG("tr2_sysenv_get invalid var '%d'", var);
 117
 118        return tr2_sysenv_settings[var].env_var_name;
 119}
 120
 121void tr2_sysenv_release(void)
 122{
 123        int k;
 124
 125        for (k = 0; k < ARRAY_SIZE(tr2_sysenv_settings); k++)
 126                free(tr2_sysenv_settings[k].value);
 127}