# less (BRINTOS-252) — GNU less 643 (poky recipes-extended), the terminal pager. # DEPENDS on ncurses; `make install` ships three binaries: less, lesskey, lessecho. # # TWO LEGS, because the piped runner cannot see a pager at all. With stdout not a # tty, main.c takes the `if (!is_tty)` branch and cat_file()s each file as a raw # byte copy — edit.c:916 is a bare ch_forw_get/putchr loop, so there is no paging, # no -N line numbering and no -s squeezing on this path (checked against the # source, and confirmed by running it: `less -N` emits the file unnumbered). The # non-tty cases below therefore prove the binary, the alternatives winner and the # byte path; the expect leg is the only thing that exercises the pager itself. # # less/version IS a real assertion, not a banner check: busybox also provides a # `less` applet, and poky's recipe registers GNU less through update-alternatives # at priority 100. "less 643" is what says the alternatives race resolved our way. # # KNOWN UPSTREAM QUIRK, deliberately NOT asserted: given more than one file with # stdout not a tty, less 643 emits only the FIRST file and exits 1, where less 551 # concatenates all of them and exits 0 (edit_ifile fails on the second ifile and # edit.c:889 quit(QUIT_ERROR)s). Reproduced on vanilla 643 built for x86-64 with a # clean environment, so it is upstream GNU less and not this port — no case here # depends on multi-file cat, and none should be added until upstream fixes it. . "$BST_LIB" require less less/present tmp=${TMPDIR:-/tmp}/bst-less.$$ mkdir "$tmp" 2>/dev/null # --- identity: GNU less, not the busybox applet ------------------------------ # The help text is bolded with overstrike (S\bS U\bU ...), which is why the needle # is a plain run from the key list rather than the "SUMMARY" banner. check_out less/version "less 643" less --version check_out less/help "Display this help." less --help # --- the non-tty byte path (main.c: if (!is_tty) -> cat_file()) -------------- i=0 while [ $i -lt 200 ]; do if [ $i -eq 150 ]; then printf 'line%04d MARKER-LESS-BST payload\n' $i else printf 'line%04d the quick brown fox jumps\n' $i; fi i=$((i+1)) done > "$tmp/corpus.txt" less "$tmp/corpus.txt" > "$tmp/out.txt" 2>/dev/null; rc=$? check_eq less/cat-rc 0 "$rc" check less/cat-roundtrip cmp "$tmp/corpus.txt" "$tmp/out.txt" # the same bytes read from a pipe rather than a named file cat "$tmp/corpus.txt" | less > "$tmp/pipe.txt" 2>/dev/null check less/cat-stdin cmp "$tmp/corpus.txt" "$tmp/pipe.txt" # SET_BINARY(1) on the cat path: with -f — which is what suppresses the # binary-file warning — less copies its own executable out byte-exact. Using the # binary itself (rather than printf escapes) keeps NUL and high-bit bytes in the # payload without depending on the shell's printf octal handling. lessbin=$(command -v less) head -c 8192 "$lessbin" > "$tmp/bin.dat" 2>/dev/null less -f "$tmp/bin.dat" > "$tmp/bin.out" 2>/dev/null check less/cat-binary cmp "$tmp/bin.dat" "$tmp/bin.out" # ...and WITHOUT -f the binary guard refuses the same file rather than spraying # control bytes: rc 1 and the warning, which less writes to stdout, not stderr. # The guard fires on the piped path too, so this is reachable from the runner. less "$tmp/bin.dat" > "$tmp/guard.out" 2>&1; grc=$? check_eq less/binary-guard-rc 1 "$grc" if grep -q "may be a binary file" "$tmp/guard.out" 2>/dev/null; then bst_ok less/binary-guard-msg else bst_notok less/binary-guard-msg "no binary-file warning on an unforced binary" fi # --- lessecho: the helper lesspipe drives; pure stdout, no terminal ---------- # Guarded with command -v rather than `require` so an absent helper does not end # the file and cost us the pty leg below. if command -v lessecho >/dev/null 2>&1; then check_out lessecho/args "a b c" lessecho a b c check_out lessecho/quote-all '"foo"' lessecho -a foo check lessecho/version lessecho --version else bst_skip lessecho/present "lessecho not installed" fi # --- lesskey: compiles a key source into less's binary keymap ---------------- # lesskey prints a deprecation NOTE to stderr and still exits 0, so the verdict is # the exit status plus a non-empty keyfile, never the message. if command -v lesskey >/dev/null 2>&1; then printf '#command\nq quit\n' > "$tmp/key.src" check lesskey/compile lesskey -o "$tmp/key.bin" "$tmp/key.src" if [ -s "$tmp/key.bin" ]; then bst_ok lesskey/output else bst_notok lesskey/output "lesskey wrote no keyfile"; fi check lesskey/version lesskey --version else bst_skip lesskey/present "lesskey not installed" fi # --- the real test: a full-screen pager, driven over a real pty -------------- # Everything above runs with less in cat mode, where a build whose ncurses/termcap # link was broken would still pass every case. expect supplies the pty; # 45-expect.test covers whether that machinery works at all, and 61-bitwise.test # is the neighbouring suite that proves it currently does on this image. require expect less/expect-present out=$(expect "$BST_DATA/selftest_less.exp" "$tmp/corpus.txt" 2>&1); rc=$? case "$out" in *ALL-LESS-OK*) all=1 ;; *) all=0 ;; esac if [ "$rc" -eq 0 ] && [ "$all" -eq 1 ]; then bst_ok less/tui-all-ok else bst_notok less/tui-all-ok "rc=$rc $(_bst_1line "$out")"; fi # L1first the first screen painted at all (termcap init + first repaint) # L2page SPACE advanced exactly one window, so a line off screen 1 is now on # L3end G reached end-of-file # L4search /pattern moved to a match 150 lines down # L5quit q left the pager of its own accord, exit 0 for tag in L1first L2page L3end L4search L5quit; do case "$out" in *"LSX-OK $tag"*) bst_ok "less/$tag" ;; *) bst_notok "less/$tag" "not OK in payload output (rc=$rc)" ;; esac done rm -rf "$tmp"