Skip to content

Commit 51693b5

Browse files
committed
render: add ASCII output mode and honour NO_COLOR / CLICOLOR
Accessibility for screen readers, non-UTF-8 terminals, and legacy consoles. --ascii (-a) forces plain ASCII, and it is auto-enabled when the locale codeset is not UTF-8 (setlocale + nl_langinfo). The Unicode status glyphs fall back to [ok]/[warn]/[fail]/->, and the block-art and component banners get plain-text forms. The em dash becomes a plain hyphen everywhere — this also changes the default Unicode output. JSON (-j) and oneline (-1) carry no glyphs and are documented as the fully accessible formats. Colour now follows the standard env conventions: NO_COLOR (any value) and CLICOLOR=0 disable it, CLICOLOR_FORCE forces it on even when piped, and an explicit --color / CLICOLOR_FORCE overrides NO_COLOR. Update the man page, usage.md, and --help.
1 parent 43f6a2f commit 51693b5

38 files changed

Lines changed: 223 additions & 106 deletions

docs/usage.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ the vantage. See [limitations.md](limitations.md).
8383
-1, --oneline Single-line summary output (shell-pipeable)
8484
-m, --markdown Markdown table output (for issue trackers)
8585
-c, --color Colorize text output (auto-detected for TTYs)
86+
-a, --ascii ASCII-only output: no Unicode glyphs or banner
87+
(auto-enabled in a non-UTF-8 locale)
8688
-q, --quiet Suppress progress indicator and warnings
8789
-v, --verbose Add banner, system-config block, per-component logs,
8890
per-region Results table, KASLR analysis, and the
@@ -104,6 +106,19 @@ Single-dash short flags may be bundled: `-fq` is `-f -q`, `-vj` is `-v -j`. A
104106
value-taking flag (`-s`/`-t`/`-w`) may appear only as the last flag in a bundle,
105107
taking the next argument — `-fqt 2` is `-f -q -t 2`.
106108

109+
### Accessibility
110+
111+
The text output uses a few Unicode glyphs (`✓ ⚠ ✗ →`) and a box-art banner
112+
under `-v`. These are auto-disabled in a non-UTF-8 locale (`LANG=C`, legacy
113+
consoles), and `--ascii` (`-a`) forces plain ASCII regardless — for screen
114+
readers on a UTF-8 system, or non-UTF-8 pipelines. The JSON (`-j`) and one-line
115+
(`-1`) formats carry no glyphs and are the fully accessible, machine-readable
116+
interfaces.
117+
118+
Colour follows the standard environment conventions: `NO_COLOR` (any value)
119+
disables it, `CLICOLOR=0` disables it, and `CLICOLOR_FORCE` (non-empty, not `0`)
120+
forces it on even when piped. An explicit `--color` overrides `NO_COLOR`.
121+
107122
## Output modes
108123

109124
### Default text mode

man/kasld.1

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,22 @@ Show technique explanations before each component (implies
5555
Suppress the banner, progress, and warnings.
5656
.TP
5757
.BR \-c ", " \-\-color
58-
Colourize text output (auto-detected for TTYs).
58+
Colourize text output. Auto-detected for TTYs and suppressed by the
59+
.B NO_COLOR
60+
and
61+
.B CLICOLOR
62+
environment variables (see
63+
.BR ENVIRONMENT ).
64+
.TP
65+
.BR \-a ", " \-\-ascii
66+
ASCII-only output: replace the Unicode status glyphs and the box-art banner
67+
with ASCII equivalents. Auto-enabled in a non-UTF-8 locale; this flag forces it
68+
regardless (for screen readers on a UTF-8 system). The JSON
69+
.RB ( \-j )
70+
and one-line
71+
.RB ( \-1 )
72+
formats carry no glyphs and are unaffected \(em they are the fully accessible
73+
interfaces.
5974
.TP
6075
.BR \-H ", " \-\-hardening
6176
Append the hardening assessment to text and markdown output.
@@ -124,6 +139,23 @@ skipped.
124139
.B KASLD_EXPERIMENTAL
125140
When set, enable experimental components, equivalent to
126141
.BR \-\-experimental .
142+
.TP
143+
.B NO_COLOR
144+
When present (any value, including empty), disable coloured output regardless of
145+
whether stdout is a TTY. An explicit
146+
.B \-\-color
147+
or
148+
.B CLICOLOR_FORCE
149+
overrides it. See
150+
.IR https://no-color.org .
151+
.TP
152+
.BR CLICOLOR ", " CLICOLOR_FORCE
153+
.B CLICOLOR=0
154+
disables colour;
155+
.B CLICOLOR_FORCE
156+
(non-empty and not
157+
.BR 0 )
158+
forces colour on even when stdout is not a TTY (BSD convention).
127159
.SH FILES
128160
.TP
129161
.I <bindir>/../libexec/kasld/

src/components/acpi_mrrm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ KASLD_EXPLAIN(
5858
"/sys/firmware/acpi/memory_ranges/rangeN/base. The kernel parses the "
5959
"ACPI MRRM table (Intel tiered-memory / CXL systems) and exposes each "
6060
"physical memory range with world-readable (0444) __ATTR_RO attributes "
61-
" no capability check, not gated by kptr_restrict. On architectures "
61+
"- no capability check, not gated by kptr_restrict. On architectures "
6262
"with a fixed physical-to-virtual mapping the base addresses directly "
6363
"yield linear-map kernel virtual addresses. Requires CONFIG_ACPI_MRRM.");
6464

src/components/alsa_seq_ext_ptr.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ KASLD_EXPLAIN(
197197
"sequencer event addressed to itself via direct dispatch, then reads it "
198198
"back. Before commit 705dd6dcbc0e, snd_seq_read() returned the event "
199199
"header with data.ext.ptr still pointing at the kvmalloc'd pool cell that "
200-
"holds the chained payload a kernel direct-map address that bounds "
200+
"holds the chained payload - a kernel direct-map address that bounds "
201201
"the direct-map base. Holds many clients open at once so their pools land "
202202
"at "
203203
"different direct-map addresses, and emits the lowest (tightest "
@@ -437,7 +437,7 @@ int main(int argc, char **argv) {
437437
* empty. Such an address is a real leak but not a page_offset witness, so
438438
* emit nothing rather than mislabel a vmalloc pointer as direct-map. */
439439
kasld_err("leaked pointer 0x%lx is outside the direct-map window "
440-
"(kvmalloc in vmalloc, or coupled arch) nothing to emit",
440+
"(kvmalloc in vmalloc, or coupled arch) - nothing to emit",
441441
addr);
442442
close(fd0);
443443
return 0;

src/components/boot_params_e820.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373

7474
KASLD_EXPLAIN(
7575
"Reads the x86 E820 physical memory map and initrd physical address "
76-
"directly from /sys/kernel/boot_params/data a world-readable "
76+
"directly from /sys/kernel/boot_params/data - a world-readable "
7777
"(0444) 4096-byte binary sysfs file exposing the full struct "
7878
"boot_params passed from the bootloader. No dmesg access is "
7979
"required. The E820 table yields physical DRAM bounds; the "

src/components/bpf_verifier_ksym.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ KASLD_EXPLAIN(
145145
"Before "
146146
"commit 72a85e9464a5 the verifier's pointer-mask left BTF_ID unmasked, so "
147147
"the "
148-
"log printed each resolved kallsyms address kernel .text pointers that "
148+
"log printed each resolved kallsyms address - kernel .text pointers that "
149149
"bracket the image base. Reachable with CAP_BPF (without CAP_PERFMON), a "
150150
"BPF-token userns, or unprivileged_bpf_disabled=0; a silent no-op on "
151151
"patched "
@@ -294,7 +294,7 @@ int main(int argc, char **argv) {
294294
const char *why = "";
295295
int nids = find_func_btf_ids(ids, &why);
296296
if (nids == 0) {
297-
kasld_err("no btf_ids (%s) CONFIG_DEBUG_INFO_BTF off, or BTF unreadable",
297+
kasld_err("no btf_ids (%s) - CONFIG_DEBUG_INFO_BTF off, or BTF unreadable",
298298
why);
299299
return KASLD_EXIT_UNAVAILABLE;
300300
}

src/components/bpf_verifier_log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ KASLD_EXPLAIN(
111111
"Loads a tiny socket-filter BPF program that references a map via an "
112112
"fd_array index (BPF_PSEUDO_MAP_IDX ldimm64) and requests a verifier log. "
113113
"Before commit 72a85e9464a5 the verifier's pointer-mask left MAP_IDX "
114-
"unmasked, so the log printed the resolved kernel pointer the kmalloc'd "
114+
"unmasked, so the log printed the resolved kernel pointer - the kmalloc'd "
115115
"struct bpf_map address, a direct-map VA that bounds the direct-map base. "
116116
"Reachable with CAP_BPF (without CAP_PERFMON), a BPF-token userns, or "
117117
"unprivileged_bpf_disabled=0. Emits only when a real kernel pointer "

src/components/dmesg_backtrace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ KASLD_EXPLAIN(
6868
"Bracketed [<ffffffff...>] tokens are kernel text pointers; register "
6969
"values in the direct-map range bound the direct-map base; the x86 CR3 "
7070
"register exposes the physical page-table base. CR3 is classified by the "
71-
"dump's process context the idle task's CR3 is swapper_pg_dir (kernel "
71+
"dump's process context - the idle task's CR3 is swapper_pg_dir (kernel "
7272
".bss), any other task's is a process page table in generic DRAM. Access "
7373
"is gated by dmesg_restrict.");
7474

src/components/dmesg_efi_memmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ KASLD_EXPLAIN(
5656
"(conventional memory, MMIO, runtime services, loader code, etc.). "
5757
"Extracts physical DRAM, MMIO and EFI_LOADER_CODE ranges. Each "
5858
"EFI_LOADER_CODE entry is emitted as a separate REGION_EFI_LOADER_IMAGE "
59-
"observation with its full [start, end] extent the running kernel is "
59+
"observation with its full [start, end] extent - the running kernel is "
6060
"one of these entries on an EFI stub boot, with bootloader/driver "
6161
"images claiming the others. efi_loader_kernel_pick filters by EFI stub "
6262
"alignment + SF_IMAGE_SIZE_MIN match to identify the running-kernel entry. "

src/components/dmesg_mmu_idmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
KASLD_EXPLAIN(
6060
"Searches dmesg for ARM32 identity_mapping_add() messages printed "
6161
"during early MMU setup. The logged range is the PHYSICAL address of "
62-
"the kernel idmap text (virt_to_phys(__idmap_text)) an interior "
62+
"the kernel idmap text (virt_to_phys(__idmap_text)) - an interior "
6363
"physical kernel-image address. Access is gated by dmesg_restrict.");
6464

6565
KASLD_META("method:parsed\n"

0 commit comments

Comments
 (0)