man-db-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Man-db-devel] [PATCH v5] Add fallback pager if the compile time default


From: nsajko
Subject: [Man-db-devel] [PATCH v5] Add fallback pager if the compile time default is not executable
Date: Sun, 07 Jan 2018 13:03:36 -0800 (PST)

A problem with man-db's man is that in the case of the user giving no
configuration via conf files, argv, or environment variables; man
defaults to less as pager (PAGER); but less may not be present on the
system. Sure, other pagers may be selected in aforementioned ways, but
then the defaults are overrided, making that unsuitable for
install-time configuration.

This patch makes man check (if that becomes relevant) if PAGER is
executable, further defaulting to cat (which is basically ubiquitous,
being in original Unix, POSIX, and GNU Coreutils) if it is not. Thus
the poor beginner Unix users without less installed will  be able to
get man pages.

Regards,
Neven


diff --git a/man/man1/man.man1 b/man/man1/man.man1
index 4df2823f..740ae983 100644
--- a/man/man1/man.man1
+++ b/man/man1/man.man1
@@ -874,7 +874,12 @@ Specify which output pager to use.
 By default,
 .B %man%
 uses
-.BR "%pager%" .
+.BR "%pager%" ,
+falling back to
+.B %cat%
+if
+.B %pager%
+is not found or is not executable.
 This option overrides the
 .RB $ MANPAGER
 environment variable, which in turn overrides the
@@ -1240,7 +1245,11 @@ is used in preference), its value is used as the name of 
the program used to
 display the manual page.
 By default,
 .B %pager%
-is used.
+is used, falling back to
+.B %cat%
+if
+.B %pager%
+is not found or is not executable.

 The value may be a simple command name or a command with arguments, and may
 use shell quoting (backslashes, single quotes, or double quotes).
diff --git a/man/replace.sin.in b/man/replace.sin.in
index 72a7e098..16674b1c 100644
--- a/man/replace.sin.in
+++ b/man/replace.sin.in
@@ -1,3 +1,4 @@
+s,%cat%,@cat@,g
 s,%pager%,@pager@,g
 s,%troff%,@troff@,g
 s,%date%,@date@,g
diff --git a/src/man.c b/src/man.c
index 6bc9642c..c044b583 100644
--- a/src/man.c
+++ b/src/man.c
@@ -4020,6 +4020,89 @@ static const char **get_section_list (void)
        }
 }

+/*
+ * Returns the first token of a libpipeline/sh-style command. See SUSv4TC2:
+ * 2.2 Shell Command Language: Quoting.
+ *
+ * Free the returned value.
+ *
+ * Examples:
+ * sh_lang_first_word ("echo 3") returns "echo"
+ * sh_lang_first_word ("'e ho' 3") returns "e ho"
+ * sh_lang_first_word ("e\\cho 3") returns "echo"
+ * sh_lang_first_word ("e\\\ncho 3") returns "echo"
+ * sh_lang_first_word ("\"echo t\" 3") returns "echo t"
+ * sh_lang_first_word ("\"ech\\o t\" 3") returns "ech\\o t"
+ * sh_lang_first_word ("\"ech\\\\o t\" 3") returns "ech\\o t"
+ * sh_lang_first_word ("\"ech\\\no t\" 3") returns "echo t"
+ * sh_lang_first_word ("\"ech\\$ t\" 3") returns "ech$ t"
+ * sh_lang_first_word ("\"ech\\` t\" 3") returns "ech` t"
+ * sh_lang_first_word ("e\"ch\"o 3") returns "echo"
+ * sh_lang_first_word ("e'ch'o 3") returns "echo"
+ */
+static char *sh_lang_first_word (const char *cmd)
+{
+       int i, o = 0;
+       char *ret = xmalloc (strlen (cmd) + 1);
+
+       for (i = 0; cmd[i] != '\0'; i++) {
+               if (cmd[i] == '\\') {
+                       /* Escape Character (Backslash) */
+                       i++;
+                       if (cmd[i] == '\0') {
+                               break;
+                       }
+                       if (cmd[i] != '\n') {
+                               ret[o] = cmd[i];
+                               o++;
+                       }
+               } else if (cmd[i] == '\'') {
+                       /* Single-Quotes */
+                       i++;
+                       while (cmd[i] != '\0' && cmd[i] != '\'') {
+                               ret[o] = cmd[i];
+                               o++;
+                               i++;
+                       }
+               } else if (cmd[i] == '"') {
+                       /* Double-Quotes */
+                       i++;
+                       while (cmd[i] != '\0' && cmd[i] != '"') {
+                               if (cmd[i] == '\\') {
+                                       if (cmd[i+1] == '$' ||
+                                           cmd[i+1] == '`' ||
+                                           cmd[i+1] == '"' ||
+                                           cmd[i+1] == '\\') {
+                                               i++;
+                                               ret[o] = cmd[i];
+                                               o++;
+                                       } else if (cmd[i+1] == '\n') {
+                                               i++;
+                                       } else {
+                                               ret[o] = cmd[i];
+                                               o++;
+                                       }
+                               } else {
+                                       ret[o] = cmd[i];
+                                       o++;
+                               }
+
+                               i++;
+                       }
+               } else if (cmd[i] == '\t' || cmd[i] == ' ' || cmd[i] == '\n' ||
+                          cmd[i] == '#') {
+                       break;
+               } else {
+                       ret[o] = cmd[i];
+                       o++;
+               }
+       }
+
+       ret[o] = '\0';
+
+       return ret;
+}
+
 int main (int argc, char *argv[])
 {
        int argc_env, exit_status = OK;
@@ -4115,13 +4198,24 @@ int main (int argc, char *argv[])
        if (htmlout)
                pager = html_pager;
 #endif /* TROFF_IS_GROFF */
+
        if (pager == NULL) {
                pager = getenv ("MANPAGER");
-               if (pager == NULL) {
-                       pager = getenv ("PAGER");
-                       if (pager == NULL)
-                               pager = get_def_user ("pager", PAGER);
+       }
+       if (pager == NULL) {
+               pager = getenv ("PAGER");
+       }
+       if (pager == NULL) {
+               pager = get_def_user ("pager", NULL);
+       }
+       if (pager == NULL) {
+               char *pager_program = sh_lang_first_word (PAGER);
+               if (pathsearch_executable (pager_program)) {
+                       pager = PAGER;
+               } else {
+                       pager = "";
                }
+               free (pager_program);
        }
        if (*pager == '\0')
                pager = get_def_user ("cat", CAT);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]