1BusyBox less doesn't support tag files (-T option), hence we previously
2disabled tag file support in mandoc at compile-time (HAVE_LESS_T).
3However, on Alpine it is entirely possible to replace BusyBox less with
4an implementation that supports tag files (e.g. main/less). In order to
5support tag files when such an implementation is installed, we need to
6detect at runtime whether -T is supported.
7
8This patch achieves this by invoking the pager once with -T beforehand
9and checking if it terminates with a non-zero exit status.
10
11diff -upr mandoc-1.14.6.orig/configure mandoc-1.14.6/configure
12--- mandoc-1.14.6.orig/configure 2023-07-02 19:38:31.011639507 +0200
13+++ mandoc-1.14.6/configure 2023-07-02 19:38:41.794998501 +0200
14@@ -67,7 +67,6 @@ HAVE_FTS_COMPARE_CONST=
15 HAVE_GETLINE=
16 HAVE_GETSUBOPT=
17 HAVE_ISBLANK=
18-HAVE_LESS_T=
19 HAVE_MKDTEMP=
20 HAVE_MKSTEMPS=
21 HAVE_NANOSLEEP=
22@@ -363,21 +362,6 @@ fi
23 echo "selected BINM_PAGER=${BINM_PAGER}${manual}" 1>&2
24 echo "selected BINM_PAGER=${BINM_PAGER}${manual}" 1>&3
25
26-# --- tagging support in the pager ---
27-if ismanual "${BINM_PAGER} -T" LESS_T ${HAVE_LESS_T}; then
28- :
29-elif ${BINM_PAGER} -T /dev/null test-noop.c 1>/dev/null 2>&3; then
30- HAVE_LESS_T=1
31- echo "tested ${BINM_PAGER} -T: yes" 1>&2
32- echo "tested ${BINM_PAGER} -T: yes" 1>&3
33- echo 1>&3
34-else
35- HAVE_LESS_T=0
36- echo "tested ${BINM_PAGER} -T: no" 1>&2
37- echo "tested ${BINM_PAGER} -T: no" 1>&3
38- echo 1>&3
39-fi
40-
41 # --- wide character and locale support ---
42 if get_locale; then
43 runtest wchar WCHAR "-DUTF8_LOCALE=\"${UTF8_LOCALE}\"" \
44@@ -484,7 +468,6 @@ cat << __HEREDOC__
45 #define HAVE_GETLINE ${HAVE_GETLINE}
46 #define HAVE_GETSUBOPT ${HAVE_GETSUBOPT}
47 #define HAVE_ISBLANK ${HAVE_ISBLANK}
48-#define HAVE_LESS_T ${HAVE_LESS_T}
49 #define HAVE_MKDTEMP ${HAVE_MKDTEMP}
50 #define HAVE_MKSTEMPS ${HAVE_MKSTEMPS}
51 #define HAVE_NTOHL ${HAVE_NTOHL}
52diff -upr mandoc-1.14.6.orig/main.c mandoc-1.14.6/main.c
53--- mandoc-1.14.6.orig/main.c 2023-07-02 19:38:31.011639507 +0200
54+++ mandoc-1.14.6/main.c 2023-07-02 19:38:50.635019538 +0200
55@@ -1271,6 +1271,44 @@ run_pager(struct outstate *outst, char *
56 }
57 }
58
59+static int
60+supports_tags(const char *pager, char *tagfile)
61+{
62+ int fd;
63+ pid_t pid;
64+ int wstatus;
65+
66+ if (strcmp(pager, "less") != 0)
67+ return 0;
68+
69+ pid = fork();
70+ switch (pid) {
71+ case -1:
72+ err(1, "fork");
73+ case 0:
74+ close(STDIN_FILENO);
75+ fd = open("/dev/null", O_RDWR);
76+ if (fd == -1)
77+ err(1, "open");
78+ assert(fd == STDIN_FILENO);
79+
80+ close(STDOUT_FILENO);
81+ dup2(fd, STDOUT_FILENO);
82+ close(STDERR_FILENO);
83+ dup2(fd, STDERR_FILENO);
84+
85+ /* If the pager doesn't support -T we expect a non-zero exit code */
86+ execlp(pager, pager, "-T", tagfile, "-", (char *)NULL);
87+ exit(EXIT_FAILURE);
88+ default:
89+ if (waitpid(pid, &wstatus, 0) == -1)
90+ err(1, "waitpid");
91+ break;
92+ }
93+
94+ return wstatus == EXIT_SUCCESS;
95+}
96+
97 static pid_t
98 spawn_pager(struct outstate *outst, char *tag_target)
99 {
100@@ -1279,9 +1317,7 @@ spawn_pager(struct outstate *outst, char
101 char *argv[MAX_PAGER_ARGS];
102 const char *pager;
103 char *cp;
104-#if HAVE_LESS_T
105 size_t cmdlen;
106-#endif
107 int argc, use_ofn;
108 pid_t pager_pid;
109
110@@ -1316,11 +1352,10 @@ spawn_pager(struct outstate *outst, char
111 /* For less(1), use the tag file. */
112
113 use_ofn = 1;
114-#if HAVE_LESS_T
115 if (*outst->tag_files->tfn != '\0' &&
116 (cmdlen = strlen(argv[0])) >= 4) {
117 cp = argv[0] + cmdlen - 4;
118- if (strcmp(cp, "less") == 0) {
119+ if (supports_tags(pager, outst->tag_files->tfn)) {
120 argv[argc++] = mandoc_strdup("-T");
121 argv[argc++] = outst->tag_files->tfn;
122 if (tag_target != NULL) {
123@@ -1330,7 +1365,7 @@ spawn_pager(struct outstate *outst, char
124 }
125 }
126 }
127-#endif
128+
129 if (use_ofn) {
130 if (outst->outtype == OUTT_HTML && tag_target != NULL)
131 mandoc_asprintf(&argv[argc], "file://%s#%s",