Skip to content

Commit a60c700

Browse files
committed
tools: Do not load names from the environment by default
Our tools are debugging tools and as such we need to have complete control to be able to reproduce setups. This is not currently the case, as we do not use `XKB_CONTEXT_NO_ENVIRONMENT_NAMES` by default nor can we set it. So it is very easy to forget about the various `XKB_DEFAULT_*` environement variables for the default RMLVO values, then to get puzzled by unexpected results. Added to that, these environment variables do not work correctly in `xkbcli-compile-xeymap`: calling the tool without RMLVO values will use these variables only if the RMLVO values are set explicitly empty or if the various *constants* `DEFAULT_XKB_*` are empty. This is unexpected, as the environment variables should *always* be used unless: - `XKB_CONTEXT_NO_ENVIRONMENT_NAMES` is used (not the case here); - the variable is empty; in this case the constants `DEFAULT_XKB_*` are used. Fixed by the following *breaking change*: make the tools use `XKB_CONTEXT_NO_ENVIRONMENT_NAMES` *by default*, unless the new `--enable-environment-names` option is used. We also make `rmlvo` incompatible with `--enable-environment-names` for now in the public tool, as else it requires a private API.
1 parent 2c10e50 commit a60c700

8 files changed

+167
-52
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The tools do not load the *default* RMLVO (rules, model, layout, variant, options)
2+
values from the environment anymore. The previous behavior may be restored by using
3+
the new `--enable-environment-names` option.

test/tool-option-parsing.py

-13
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,6 @@
3333
file=sys.stderr,
3434
)
3535

36-
37-
# Unset some environment variables, so that tools that rely on them for missing
38-
# arguments default have the expected behavior.
39-
for key in (
40-
"XKB_DEFAULT_RULES",
41-
"XKB_DEFAULT_MODEL",
42-
"XKB_DEFAULT_LAYOUT",
43-
"XKB_DEFAULT_VARIANT",
44-
"XKB_DEFAULT_OPTIONS",
45-
):
46-
if key in os.environ:
47-
del os.environ[key]
48-
4936
# Ensure locale is C, so we can check error messages in English
5037
os.environ["LC_ALL"] = "C.UTF-8"
5138

tools/compile-keymap.c

+73-28
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <string.h>
1515

1616
#include "xkbcommon/xkbcommon.h"
17-
#if ENABLE_PRIVATE_APIS
17+
#ifdef ENABLE_PRIVATE_APIS
1818
#include "xkbcomp/xkbcomp-priv.h"
1919
#include "xkbcomp/rules.h"
2020
#endif
@@ -49,7 +49,7 @@ usage(FILE *file, const char *progname)
4949
" Enable verbose debugging output\n"
5050
" --test\n"
5151
" Test compilation but do not print the keymap.\n"
52-
#if ENABLE_PRIVATE_APIS
52+
#ifdef ENABLE_PRIVATE_APIS
5353
" --kccgst\n"
5454
" Print a keymap which only includes the KcCGST component names instead of the full keymap\n"
5555
#endif
@@ -59,7 +59,7 @@ usage(FILE *file, const char *progname)
5959
" --from-xkb <file>\n"
6060
" Load the corresponding XKB file, ignore RMLVO options. If <file>\n"
6161
" is \"-\" or missing, then load from stdin."
62-
#if ENABLE_PRIVATE_APIS
62+
#ifdef ENABLE_PRIVATE_APIS
6363
" This option must not be used with --kccgst.\n"
6464
#endif
6565
" --include\n"
@@ -84,6 +84,14 @@ usage(FILE *file, const char *progname)
8484
" The XKB layout variant (default: '%s')\n"
8585
" --options <options>\n"
8686
" The XKB options (default: '%s')\n"
87+
" --enable-environment-names\n"
88+
" Allow to set the default RMLVO values via the following environment variables:\n"
89+
" - XKB_DEFAULT_RULES\n"
90+
" - XKB_DEFAULT_MODEL\n"
91+
" - XKB_DEFAULT_LAYOUT\n"
92+
" - XKB_DEFAULT_VARIANT\n"
93+
" - XKB_DEFAULT_OPTIONS\n"
94+
" Note that this option may affect the default values of the previous options.\n"
8795
"\n",
8896
progname, DEFAULT_XKB_RULES,
8997
DEFAULT_XKB_MODEL, DEFAULT_XKB_LAYOUT,
@@ -92,7 +100,8 @@ usage(FILE *file, const char *progname)
92100
}
93101

94102
static bool
95-
parse_options(int argc, char **argv, char **path, struct xkb_rule_names *names)
103+
parse_options(int argc, char **argv, bool *use_env_names,
104+
char **path, struct xkb_rule_names *names)
96105
{
97106
enum options {
98107
OPT_VERBOSE,
@@ -102,6 +111,7 @@ parse_options(int argc, char **argv, char **path, struct xkb_rule_names *names)
102111
OPT_FROM_XKB,
103112
OPT_INCLUDE,
104113
OPT_INCLUDE_DEFAULTS,
114+
OPT_ENABLE_ENV_NAMES,
105115
OPT_RULES,
106116
OPT_MODEL,
107117
OPT_LAYOUT,
@@ -112,7 +122,7 @@ parse_options(int argc, char **argv, char **path, struct xkb_rule_names *names)
112122
{"help", no_argument, 0, 'h'},
113123
{"verbose", no_argument, 0, OPT_VERBOSE},
114124
{"test", no_argument, 0, OPT_TEST},
115-
#if ENABLE_PRIVATE_APIS
125+
#ifdef ENABLE_PRIVATE_APIS
116126
{"kccgst", no_argument, 0, OPT_KCCGST},
117127
#endif
118128
{"rmlvo", no_argument, 0, OPT_RMLVO},
@@ -121,6 +131,7 @@ parse_options(int argc, char **argv, char **path, struct xkb_rule_names *names)
121131
{"from-xkb", optional_argument, 0, OPT_FROM_XKB},
122132
{"include", required_argument, 0, OPT_INCLUDE},
123133
{"include-defaults", no_argument, 0, OPT_INCLUDE_DEFAULTS},
134+
{"enable-environment-names", no_argument, 0, OPT_ENABLE_ENV_NAMES},
124135
{"rules", required_argument, 0, OPT_RULES},
125136
{"model", required_argument, 0, OPT_MODEL},
126137
{"layout", required_argument, 0, OPT_LAYOUT},
@@ -130,6 +141,7 @@ parse_options(int argc, char **argv, char **path, struct xkb_rule_names *names)
130141
};
131142

132143
bool has_rmlvo_options = false;
144+
*use_env_names = false;
133145
while (1) {
134146
int option_index = 0;
135147
int c = getopt_long(argc, argv, "h", opts, &option_index);
@@ -154,6 +166,10 @@ parse_options(int argc, char **argv, char **path, struct xkb_rule_names *names)
154166
case OPT_RMLVO:
155167
if (output_format != FORMAT_KEYMAP_FROM_RMLVO)
156168
goto output_format_error;
169+
#ifndef ENABLE_PRIVATE_APIS
170+
if (*use_env_names)
171+
goto rmlvo_env_error;
172+
#endif
157173
output_format = FORMAT_RMLVO;
158174
break;
159175
case OPT_FROM_XKB:
@@ -182,6 +198,13 @@ parse_options(int argc, char **argv, char **path, struct xkb_rule_names *names)
182198
goto too_many_includes;
183199
includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER;
184200
break;
201+
case OPT_ENABLE_ENV_NAMES:
202+
#ifndef ENABLE_PRIVATE_APIS
203+
if (output_format == FORMAT_RMLVO)
204+
goto rmlvo_env_error;
205+
#endif
206+
*use_env_names = true;
207+
break;
185208
case OPT_RULES:
186209
if (output_format == FORMAT_KEYMAP_FROM_XKB)
187210
goto input_format_error;
@@ -243,6 +266,14 @@ parse_options(int argc, char **argv, char **path, struct xkb_rule_names *names)
243266

244267
return true;
245268

269+
#ifndef ENABLE_PRIVATE_APIS
270+
rmlvo_env_error:
271+
/* See comment in print_rmlvo */
272+
fprintf(stderr, "ERROR: --rmlvo is not compatible with "
273+
"--enable-environment-names yet\n");
274+
exit(EXIT_INVALID_USAGE);
275+
#endif
276+
246277
output_format_error:
247278
fprintf(stderr, "ERROR: Cannot mix output formats\n");
248279
usage(stderr, argv[0]);
@@ -260,9 +291,36 @@ parse_options(int argc, char **argv, char **path, struct xkb_rule_names *names)
260291
}
261292

262293
static int
263-
print_rmlvo(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo)
294+
print_rmlvo(struct xkb_context *ctx, struct xkb_rule_names *rmlvo)
264295
{
265-
printf("rules: \"%s\"\nmodel: \"%s\"\nlayout: \"%s\"\nvariant: \"%s\"\noptions: \"%s\"\n",
296+
/* Fill defaults */
297+
#ifndef ENABLE_PRIVATE_APIS
298+
/* FIXME: We should use `xkb_context_sanitize_rule_names`, but this is
299+
* not a public API yet. Instead we just do not support names from
300+
* environment variables. */
301+
if (isempty(rmlvo->rules))
302+
rmlvo->rules = DEFAULT_XKB_RULES;
303+
if (isempty(rmlvo->model))
304+
rmlvo->model = DEFAULT_XKB_MODEL;
305+
/* Layout and variant are tied together, so we either get user-supplied for
306+
* both or default for both */
307+
if (isempty(rmlvo->layout)) {
308+
if (!isempty(rmlvo->variant)) {
309+
fprintf(stderr, "ERROR: a variant requires a layout\n");
310+
return EXIT_INVALID_USAGE;
311+
}
312+
rmlvo->layout = DEFAULT_XKB_LAYOUT;
313+
rmlvo->variant = DEFAULT_XKB_VARIANT;
314+
}
315+
if (isempty(rmlvo->options))
316+
rmlvo->options = DEFAULT_XKB_OPTIONS;
317+
#else
318+
/* Resolve default RMLVO values */
319+
xkb_context_sanitize_rule_names(ctx, rmlvo);
320+
#endif
321+
322+
printf("rules: \"%s\"\nmodel: \"%s\"\nlayout: \"%s\"\nvariant: \"%s\"\n"
323+
"options: \"%s\"\n",
266324
rmlvo->rules, rmlvo->model, rmlvo->layout,
267325
rmlvo->variant ? rmlvo->variant : "",
268326
rmlvo->options ? rmlvo->options : "");
@@ -272,7 +330,7 @@ print_rmlvo(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo)
272330
static int
273331
print_kccgst(struct xkb_context *ctx, struct xkb_rule_names *rmlvo)
274332
{
275-
#if ENABLE_PRIVATE_APIS
333+
#ifdef ENABLE_PRIVATE_APIS
276334
struct xkb_component_names kccgst;
277335

278336
/* Resolve default RMLVO values */
@@ -377,36 +435,23 @@ main(int argc, char **argv)
377435
{
378436
struct xkb_context *ctx;
379437
char *keymap_path = NULL;
380-
struct xkb_rule_names names = {
381-
.rules = DEFAULT_XKB_RULES,
382-
.model = DEFAULT_XKB_MODEL,
383-
/* layout and variant are tied together, so we either get user-supplied for
384-
* both or default for both, see below */
385-
.layout = NULL,
386-
.variant = NULL,
387-
.options = DEFAULT_XKB_OPTIONS,
388-
};
438+
struct xkb_rule_names names = { 0 };
439+
bool use_env_names = false;
389440
int rc = 1;
390441

391442
if (argc < 1) {
392443
usage(stderr, argv[0]);
393444
return EXIT_INVALID_USAGE;
394445
}
395446

396-
if (!parse_options(argc, argv, &keymap_path, &names))
447+
if (!parse_options(argc, argv, &use_env_names, &keymap_path, &names))
397448
return EXIT_INVALID_USAGE;
398449

399-
/* Now fill in the layout */
400-
if (!names.layout || !*names.layout) {
401-
if (names.variant && *names.variant) {
402-
fprintf(stderr, "ERROR: a variant requires a layout\n");
403-
return EXIT_INVALID_USAGE;
404-
}
405-
names.layout = DEFAULT_XKB_LAYOUT;
406-
names.variant = DEFAULT_XKB_VARIANT;
407-
}
450+
enum xkb_context_flags ctx_flags = XKB_CONTEXT_NO_DEFAULT_INCLUDES;
451+
if (!use_env_names)
452+
ctx_flags |= XKB_CONTEXT_NO_ENVIRONMENT_NAMES;
408453

409-
ctx = xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES);
454+
ctx = xkb_context_new(ctx_flags);
410455
assert(ctx);
411456

412457
if (verbose) {

tools/how-to-type.c

+24-4
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,10 @@ parse_char_or_codepoint(const char *raw) {
6363
static void
6464
usage(const char *argv0, FILE *fp)
6565
{
66-
fprintf(fp, "Usage: %s [--help] [--keysym] [--rules <rules>] [--model <model>] "
67-
"[--layout <layout>] [--variant <variant>] [--options <options>]"
68-
" <character/codepoint/keysym>\n", argv0);
66+
fprintf(fp, "Usage: %s [--help] [--keysym] [--rules <rules>] "
67+
"[--model <model>] [--layout <layout>] [--variant <variant>] "
68+
"[--options <options>] [--enable-environment-names] "
69+
"<character/codepoint/keysym>\n", argv0);
6970
fprintf(
7071
fp,
7172
"\n"
@@ -96,6 +97,14 @@ usage(const char *argv0, FILE *fp)
9697
" The XKB layout variant (default: '%s')\n"
9798
" --options <options>\n"
9899
" The XKB options (default: '%s')\n"
100+
" --enable-environment-names\n"
101+
" Allow to set the default RMLVO values via the following environment variables:\n"
102+
" - XKB_DEFAULT_RULES\n"
103+
" - XKB_DEFAULT_MODEL\n"
104+
" - XKB_DEFAULT_LAYOUT\n"
105+
" - XKB_DEFAULT_VARIANT\n"
106+
" - XKB_DEFAULT_OPTIONS\n"
107+
" Note that this option may affect the default values of the previous options.\n"
99108
"\n",
100109
DEFAULT_XKB_RULES, DEFAULT_XKB_MODEL, DEFAULT_XKB_LAYOUT,
101110
DEFAULT_XKB_VARIANT ? DEFAULT_XKB_VARIANT : "<none>",
@@ -110,6 +119,7 @@ main(int argc, char *argv[])
110119
const char *layout_ = NULL;
111120
const char *variant = NULL;
112121
const char *options = NULL;
122+
bool use_env_names = false;
113123
bool keysym_mode = false;
114124
int err = EXIT_FAILURE;
115125
struct xkb_context *ctx = NULL;
@@ -124,6 +134,7 @@ main(int argc, char *argv[])
124134
xkb_mod_index_t num_mods;
125135
enum options {
126136
OPT_KEYSYM,
137+
OPT_ENABLE_ENV_NAMES,
127138
OPT_RULES,
128139
OPT_MODEL,
129140
OPT_LAYOUT,
@@ -133,6 +144,7 @@ main(int argc, char *argv[])
133144
static struct option opts[] = {
134145
{"help", no_argument, 0, 'h'},
135146
{"keysym", no_argument, 0, OPT_KEYSYM},
147+
{"enable-environment-names", no_argument, 0, OPT_ENABLE_ENV_NAMES},
136148
{"rules", required_argument, 0, OPT_RULES},
137149
{"model", required_argument, 0, OPT_MODEL},
138150
{"layout", required_argument, 0, OPT_LAYOUT},
@@ -153,6 +165,9 @@ main(int argc, char *argv[])
153165
case OPT_KEYSYM:
154166
keysym_mode = true;
155167
break;
168+
case OPT_ENABLE_ENV_NAMES:
169+
use_env_names = true;
170+
break;
156171
case OPT_RULES:
157172
rules = optarg;
158173
break;
@@ -211,7 +226,12 @@ main(int argc, char *argv[])
211226
goto err;
212227
}
213228

214-
ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
229+
230+
const enum xkb_context_flags ctx_flags = (use_env_names)
231+
? XKB_CONTEXT_NO_FLAGS
232+
: XKB_CONTEXT_NO_ENVIRONMENT_NAMES;
233+
234+
ctx = xkb_context_new(ctx_flags);
215235
if (!ctx) {
216236
fprintf(stderr, "ERROR: Failed to create XKB context\n");
217237
goto err;

tools/interactive-evdev.c

+18-7
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,8 @@ usage(FILE *fp, char *progname)
362362
{
363363
fprintf(fp, "Usage: %s [--include=<path>] [--include-defaults] "
364364
"[--rules=<rules>] [--model=<model>] [--layout=<layout>] "
365-
"[--variant=<variant>] [--options=<options>]\n",
365+
"[--variant=<variant>] [--options=<options>] "
366+
"[--enable-environment-names]\n",
366367
progname);
367368
fprintf(fp, " or: %s --keymap <path to keymap file>\n",
368369
progname);
@@ -391,6 +392,7 @@ main(int argc, char *argv[])
391392
struct xkb_compose_table *compose_table = NULL;
392393
const char *includes[64];
393394
size_t num_includes = 0;
395+
bool use_env_names = false;
394396
const char *rules = NULL;
395397
const char *model = NULL;
396398
const char *layout = NULL;
@@ -403,6 +405,7 @@ main(int argc, char *argv[])
403405
OPT_VERBOSE,
404406
OPT_INCLUDE,
405407
OPT_INCLUDE_DEFAULTS,
408+
OPT_ENABLE_ENV_NAMES,
406409
OPT_RULES,
407410
OPT_MODEL,
408411
OPT_LAYOUT,
@@ -423,6 +426,7 @@ main(int argc, char *argv[])
423426
{"verbose", no_argument, 0, OPT_VERBOSE},
424427
{"include", required_argument, 0, OPT_INCLUDE},
425428
{"include-defaults", no_argument, 0, OPT_INCLUDE_DEFAULTS},
429+
{"enable-environment-names", no_argument, 0, OPT_ENABLE_ENV_NAMES},
426430
{"rules", required_argument, 0, OPT_RULES},
427431
{"model", required_argument, 0, OPT_MODEL},
428432
{"layout", required_argument, 0, OPT_LAYOUT},
@@ -463,6 +467,9 @@ main(int argc, char *argv[])
463467
goto too_many_includes;
464468
includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER;
465469
break;
470+
case OPT_ENABLE_ENV_NAMES:
471+
use_env_names = true;
472+
break;
466473
case OPT_RULES:
467474
if (keymap_path)
468475
goto input_format_error;
@@ -548,7 +555,11 @@ main(int argc, char *argv[])
548555
}
549556
}
550557

551-
ctx = xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES);
558+
enum xkb_context_flags ctx_flags = XKB_CONTEXT_NO_DEFAULT_INCLUDES;
559+
if (!use_env_names)
560+
ctx_flags |= XKB_CONTEXT_NO_ENVIRONMENT_NAMES;
561+
562+
ctx = xkb_context_new(ctx_flags);
552563
if (!ctx) {
553564
fprintf(stderr, "ERROR: Couldn't create xkb context\n");
554565
goto out;
@@ -584,11 +595,11 @@ main(int argc, char *argv[])
584595
}
585596
else {
586597
struct xkb_rule_names rmlvo = {
587-
.rules = (rules == NULL || rules[0] == '\0') ? NULL : rules,
588-
.model = (model == NULL || model[0] == '\0') ? NULL : model,
589-
.layout = (layout == NULL || layout[0] == '\0') ? NULL : layout,
590-
.variant = (variant == NULL || variant[0] == '\0') ? NULL : variant,
591-
.options = (options == NULL || options[0] == '\0') ? NULL : options
598+
.rules = (isempty(rules)) ? NULL : rules,
599+
.model = (isempty(model)) ? NULL : model,
600+
.layout = (isempty(layout)) ? NULL : layout,
601+
.variant = (isempty(variant)) ? NULL : variant,
602+
.options = (isempty(options)) ? NULL : options
592603
};
593604

594605
if (!rules && !model && !layout && !variant && !options)

0 commit comments

Comments
 (0)