summaryrefslogtreecommitdiffstats
path: root/trace2/tr2_cfg.c
blob: d96d908bb9df6fddb22e4dbecfa07882049bdf78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include "git-compat-util.h"
#include "config.h"
#include "strbuf.h"
#include "trace2.h"
#include "trace2/tr2_cfg.h"
#include "trace2/tr2_sysenv.h"
#include "wildmatch.h"

static struct strbuf **tr2_cfg_patterns;
static int tr2_cfg_count_patterns;
static int tr2_cfg_loaded;

static struct strbuf **tr2_cfg_env_vars;
static int tr2_cfg_env_vars_count;
static int tr2_cfg_env_vars_loaded;

/*
 * Parse a string containing a comma-delimited list of config keys
 * or wildcard patterns into a list of strbufs.
 */
static int tr2_cfg_load_patterns(void)
{
	struct strbuf **s;
	const char *envvar;

	if (tr2_cfg_loaded)
		return tr2_cfg_count_patterns;
	tr2_cfg_loaded = 1;

	envvar = tr2_sysenv_get(TR2_SYSENV_CFG_PARAM);
	if (!envvar || !*envvar)
		return tr2_cfg_count_patterns;

	tr2_cfg_patterns = strbuf_split_buf(envvar, strlen(envvar), ',', -1);
	for (s = tr2_cfg_patterns; *s; s++) {
		struct strbuf *buf = *s;

		if (buf->len && buf->buf[buf->len - 1] == ',')
			strbuf_setlen(buf, buf->len - 1);
		strbuf_trim_trailing_newline(*s);
		strbuf_trim(*s);
	}

	tr2_cfg_count_patterns = s - tr2_cfg_patterns;
	return tr2_cfg_count_patterns;
}

void tr2_cfg_free_patterns(void)
{
	if (tr2_cfg_patterns)
		strbuf_list_free(tr2_cfg_patterns);
	tr2_cfg_count_patterns = 0;
	tr2_cfg_loaded = 0;
}

/*
 * Parse a string containing a comma-delimited list of environment variable
 * names into a list of strbufs.
 */
static int tr2_load_env_vars(void)
{
	struct strbuf **s;
	const char *varlist;

	if (tr2_cfg_env_vars_loaded)
		return tr2_cfg_env_vars_count;
	tr2_cfg_env_vars_loaded = 1;

	varlist = tr2_sysenv_get(TR2_SYSENV_ENV_VARS);
	if (!varlist || !*varlist)
		return tr2_cfg_env_vars_count;

	tr2_cfg_env_vars = strbuf_split_buf(varlist, strlen(varlist), ',', -1);
	for (s = tr2_cfg_env_vars; *s; s++) {
		struct strbuf *buf = *s;

		if (buf->len && buf->buf[buf->len - 1] == ',')
			strbuf_setlen(buf, buf->len - 1);
		strbuf_trim_trailing_newline(*s);
		strbuf_trim(*s);
	}

	tr2_cfg_env_vars_count = s - tr2_cfg_env_vars;
	return tr2_cfg_env_vars_count;
}

void tr2_cfg_free_env_vars(void)
{
	if (tr2_cfg_env_vars)
		strbuf_list_free(tr2_cfg_env_vars);
	tr2_cfg_env_vars_count = 0;
	tr2_cfg_env_vars_loaded = 0;
}

struct tr2_cfg_data {
	const char *file;
	int line;
};

/*
 * See if the given config key matches any of our patterns of interest.
 */
static int tr2_cfg_cb(const char *key, const char *value,
		      const struct config_context *ctx, void *d)
{
	struct strbuf **s;
	struct tr2_cfg_data *data = (struct tr2_cfg_data *)d;

	for (s = tr2_cfg_patterns; *s; s++) {
		struct strbuf *buf = *s;
		int wm = wildmatch(buf->buf, key, WM_CASEFOLD);
		if (wm == WM_MATCH) {
			trace2_def_param_fl(data->file, data->line, key, value,
					    ctx->kvi);
			return 0;
		}
	}

	return 0;
}

void tr2_cfg_list_config_fl(const char *file, int line)
{
	struct tr2_cfg_data data = { file, line };

	if (tr2_cfg_load_patterns() > 0)
		read_early_config(tr2_cfg_cb, &data);
}

void tr2_list_env_vars_fl(const char *file, int line)
{
	struct key_value_info kvi = KVI_INIT;
	struct strbuf **s;

	kvi_from_param(&kvi);
	if (tr2_load_env_vars() <= 0)
		return;

	for (s = tr2_cfg_env_vars; *s; s++) {
		struct strbuf *buf = *s;
		const char *val = getenv(buf->buf);
		if (val && *val)
			trace2_def_param_fl(file, line, buf->buf, val, &kvi);
	}
}

void tr2_cfg_set_fl(const char *file, int line, const char *key,
		    const char *value)
{
	struct key_value_info kvi = KVI_INIT;
	struct config_context ctx = {
		.kvi = &kvi,
	};
	struct tr2_cfg_data data = { file, line };

	if (tr2_cfg_load_patterns() > 0)
		tr2_cfg_cb(key, value, &ctx, &data);
}