It's quite common to have options in the commands specified in the PAGER environment variable, to customize the behavior of the configured output filter. For example, someone might want to include the "-X" option when less(1) is configured as the output filter, or might want to specifically not include it, depending on the personal preferences. For example, man(1), git(1) and bat(1) already allow and properly handle the presence of any options in the configured output filter commands, which assures that it's fine to do the same in util-linux. Here's also a quotation from the description of the man(1) utility that describes the PAGER environment variable, as found in The Single UNIX Specification, version 4: PAGER Determine an output filtering command for writing the output to a terminal. Any string acceptable as a command_string operand to the sh -c command shall be valid. When standard output is a terminal device, the reference page output shall be piped through the command. If the PAGER variable is null or not set, the command shall be either more or another paginator utility documented in the system documentation. This quotation just confirms, rather formally, that allowing options in the output filter commands is a perfectly valid thing to do. While there, perform a couple of minor cleanups as well, to make the formatting of the code a tiny bit more consistent, and to slightly improve one of the logged debug messages. Signed-off-by: Dragan Simic <dsimic@xxxxxxxxxxx> --- lib/pager.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/pager.c b/lib/pager.c index 9429032b3..db7a989df 100644 --- a/lib/pager.c +++ b/lib/pager.c @@ -178,35 +178,45 @@ static void wait_for_pager_signal(int signo) static int has_command(const char *cmd) { const char *path; - char *p, *s; + char *b, *c, *p, *s; int rc = 0; if (!cmd) goto done; - if (*cmd == '/') { - rc = access(cmd, X_OK) == 0; + + c = xstrdup(cmd); + if (!c) goto done; + b = strtok(c, " "); /* cmd may contain options */ + if (!b) + goto cleanup; + + if (*b == '/') { + rc = access(b, X_OK) == 0; + goto cleanup; } path = getenv("PATH"); if (!path) - goto done; + goto cleanup; p = xstrdup(path); if (!p) - goto done; + goto cleanup; - for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) { + for (s = strtok(p, ":"); s; s = strtok(NULL, ":")) { int fd = open(s, O_RDONLY|O_CLOEXEC); if (fd < 0) continue; - rc = faccessat(fd, cmd, X_OK, 0) == 0; + rc = faccessat(fd, b, X_OK, 0) == 0; close(fd); if (rc) break; } free(p); +cleanup: + free(c); done: - /*fprintf(stderr, "has PAGER %s rc=%d\n", cmd, rc);*/ + /*fprintf(stderr, "has PAGER '%s': rc=%d\n", cmd, rc);*/ return rc; } -- 2.33.1