10

On my FreeBSD 13.2 system, the zless utility cannot view text files compressed with gzip or compress, warning that they may be binary files and then showing garbage if I say I want to see the contents anyway. Strangely, using zmore or gunzip -c seems to work.

$ zless znapzend.log.1.gz
"znapzend.log.1.gz" may be a binary file.  See it anyway?

(Answering affirmatively sends binary data to the terminal.)

$ zless --version
less 608 (POSIX regular expressions)
Copyright (C) 1984-2022  Mark Nudelman

less comes with NO WARRANTY, to the extent permitted by law.
For information about the terms of redistribution,
see the file named README in the less distribution.
Home page: https://greenwoodsoftware.com/less
$ zmore --version
less 608 (POSIX regular expressions)
Copyright (C) 1984-2022  Mark Nudelman

less comes with NO WARRANTY, to the extent permitted by law.
For information about the terms of redistribution,
see the file named README in the less distribution.
Home page: https://greenwoodsoftware.com/less

What is the cause of this?

Kusalananda
  • 320,670
  • 36
  • 633
  • 936

1 Answers1

11

Short story shorter: It is due to the internal pipe command being disabled when less runs in "secure" mode, i.e, LESSOPEN can't start with | if LESSSECURE is 1.

After poking at this for a while, I looked at the zless and zmore executables themselves.

On FreeBSD, both are shell scripts, but while zmore is a more traditional wrapper around gzip (for decompression) and less (for viewing the decompressed document(s)), zless is a much shorter shell script calling less with the environment variable LESSOPEN set to invoke the script /usr/bin/lesspipe.sh:

#!/bin/sh
#
# $FreeBSD$
#

export LESSOPEN="||/usr/bin/lesspipe.sh %s"
exec /usr/bin/less "$@"

The lesspipe.sh script then consists of a case statement that calls the correct decompression utility depending on the input file's filename suffix, but that's unimportant here. The main point is that the internal pipe command is used in the LESSOPEN environment variable.

When the environment variable LESSSECURE is set to 1, less runs in "secure" mode. When this is the case, the utility ignores the | (pipe) command.

The final part of the puzzle was remembering that I actually set LESSSECURE=1 in my shell's initialisation files.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
  • 1
    looking at the `zless` that comes with my Linux distro (and probably most other distros) is from other authors (Paul Eggert) and copyrighted with the FSF, it also does `LESSOPEN="|$check_exit_status${use_input_pipe_on_stdin}gzip -cdfq -- %s"` ; `export LESSOPEN`, and hence **does** fall prey to the same problems! (the less installed on most Linuxes is also `less` by Mark Nudelman) – Marcus Müller Apr 16 '23 at 12:47
  • looks like something that could be reported as a bug, probably separately in those various OSes and distributions – ilkkachu Apr 16 '23 at 12:52
  • @ilkkachu on it. On a patch, in fact. But as everywhere with GNU software¹, there's yaks to be shaved²… – Marcus Müller Apr 16 '23 at 12:58
  • I've been having this problem for weeks (and somehow hadn't noticed that I had set `LESSSECURE`). 1. I find it surprising that `LESSSECURE` breaks input pipes from `LESSOPEN`; this isn't mentioned in `less`'s manual regarding `LESSSECURE`, where I was under the (mistaken) belief that it affected only what I could do interactively. (My primarily intention for using `LESSSECURE` in the first place was to limit what I could do from accidental keypresses within `less`.) – jamesdlin Apr 16 '23 at 22:54
  • is that supposed to be `||` in the script? Do you really have `LESSOPEN="||/usr/bin/lesspipe.sh %s"` and not `LESSOPEN="|/usr/bin/lesspipe.sh %s"`? – terdon Apr 17 '23 at 11:10
  • @terdon It is intentional. The double pipe influences how empty input is handled. This is mentioned towards the end of the "INPUT PREPROCESSOR" section of the manual. – Kusalananda Apr 17 '23 at 11:24