Hi again,

I have added the modifications I think you told me.

Also I changed the extension of the tmp file then it can be interpreted as HTML by any browser used as pager. The extension is set when using html format.

Now this works: MANPAGER="lynx" ./man -T html -O tag=k pfctl (no need to force_html also)

Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/main.c,v
retrieving revision 1.252
diff -u -p -r1.252 main.c
--- main.c      11 Jun 2020 16:12:14 -0000      1.252
+++ main.c      15 Jun 2020 10:30:38 -0000
@@ -107,8 +107,8 @@ static      void              parse(struct mparse *, in
 static void              passthrough(int, int);
 static void              process_onefile(struct mparse *, struct manpage *,
                                int, struct outstate *, struct manconf *);
-static void              run_pager(struct tag_files *, char *);
-static pid_t             spawn_pager(struct tag_files *, char *);
+static void              run_pager(struct outstate, char *);
+static pid_t             spawn_pager(struct outstate, char *);
 static void              usage(enum argmode) __attribute__((__noreturn__));
 static int               woptions(char *, enum mandoc_os *, int *);

@@ -621,7 +621,7 @@ out:

        if (outst.tag_files != NULL) {
                if (term_tag_close() != -1)
-                       run_pager(outst.tag_files, conf.output.tag);
+                       run_pager(outst, conf.output.tag);
                term_tag_unlink();
        } else if (outst.had_output && outst.outtype != OUTT_LINT)
                mandoc_msg_summary();
@@ -815,7 +815,10 @@ process_onefile(struct mparse *mp, struc

        if (outst->use_pager) {
                outst->use_pager = 0;
-               outst->tag_files = term_tag_init();
+               if (outst->outtype == OUTT_HTML)
+                       outst->tag_files = term_tag_init("html");
+               else
+                       outst->tag_files = term_tag_init(NULL);
        }
        if (outst->had_output && outst->outtype <= OUTT_UTF8) {
                if (outst->outdata == NULL)
@@ -1122,14 +1125,14 @@ woptions(char *arg, enum mandoc_os *os_e
  * then fork the pager and wait for the user to close it.
  */
 static void
-run_pager(struct tag_files *tag_files, char *tag_target)
+run_pager(struct outstate outst, char *tag_target)
 {
        int      signum, status;
        pid_t    man_pgid, tc_pgid;
        pid_t    pager_pid, wait_pid;

        man_pgid = getpgid(0);
-       tag_files->tcpgid = man_pgid == getpid() ? getpgid(getppid()) :
+       outst.tag_files->tcpgid = man_pgid == getpid() ? getpgid(getppid()) :
            man_pgid;
        pager_pid = 0;
        signum = SIGSTOP;
@@ -1144,7 +1147,7 @@ run_pager(struct tag_files *tag_files, c
                                if (signum == SIGTTIN)
                                        continue;
                        } else
-                               tag_files->tcpgid = tc_pgid;
+                               outst.tag_files->tcpgid = tc_pgid;
                        kill(0, signum);
                        continue;
                }
@@ -1155,7 +1158,7 @@ run_pager(struct tag_files *tag_files, c
                        (void)tcsetpgrp(STDOUT_FILENO, pager_pid);
                        kill(pager_pid, SIGCONT);
                } else
-                       pager_pid = spawn_pager(tag_files, tag_target);
+                       pager_pid = spawn_pager(outst, tag_target);

                /* Wait for the pager to stop or exit. */

@@ -1176,19 +1179,20 @@ run_pager(struct tag_files *tag_files, c
 }

 static pid_t
-spawn_pager(struct tag_files *tag_files, char *tag_target)
+spawn_pager(struct outstate outst, char *tag_target)
 {
        const struct timespec timeout = { 0, 100000000 };  /* 0.1s */
 #define MAX_PAGER_ARGS 16
        char            *argv[MAX_PAGER_ARGS];
+       char            *ofurl;
        const char      *pager;
        char            *cp;
        size_t           cmdlen;
        int              argc, use_ofn;
        pid_t            pager_pid;

-       assert(tag_files->ofd == -1);
-       assert(tag_files->tfs == NULL);
+       assert(outst.tag_files->ofd == -1);
+       assert(outst.tag_files->tfs == NULL);

        pager = getenv("MANPAGER");
        if (pager == NULL || *pager == '\0')
@@ -1218,11 +1222,11 @@ spawn_pager(struct tag_files *tag_files,
        /* For more(1) and less(1), use the tag file. */

        use_ofn = 1;
-       if (*tag_files->tfn != '\0' && (cmdlen = strlen(argv[0])) >= 4) {
+       if (*outst.tag_files->tfn != '\0' && (cmdlen = strlen(argv[0])) >= 4) {
                cp = argv[0] + cmdlen - 4;
                if (strcmp(cp, "less") == 0 || strcmp(cp, "more") == 0) {
                        argv[argc++] = mandoc_strdup("-T");
-                       argv[argc++] = tag_files->tfn;
+                       argv[argc++] = outst.tag_files->tfn;
                        if (tag_target != NULL) {
                                argv[argc++] = mandoc_strdup("-t");
                                argv[argc++] = tag_target;
@@ -1230,8 +1234,19 @@ spawn_pager(struct tag_files *tag_files,
                        }
                }
        }
-       if (use_ofn)
-               argv[argc++] = tag_files->ofn;
+
+       if (use_ofn) {
+               /* Use file:///tmp/man.XXXXXXXX.html URL scheme */
+               if (outst.outtype == OUTT_HTML) {
+                       if (tag_target == NULL)
+                               mandoc_asprintf(&ofurl, "file://%s", 
outst.tag_files->ofn);
+                       else
+ mandoc_asprintf(&ofurl, "file://%s#%s", outst.tag_files->ofn, tag_target);
+                       argv[argc++] = ofurl;
+               } else
+                       argv[argc++] = outst.tag_files->ofn;
+       }
+
        argv[argc] = NULL;

        switch (pager_pid = fork()) {
@@ -1248,7 +1263,7 @@ spawn_pager(struct tag_files *tag_files,
                            "%s", strerror(errno));
                        exit(mandoc_msg_getrc());
                }
-               tag_files->pager_pid = pager_pid;
+               outst.tag_files->pager_pid = pager_pid;
                return pager_pid;
        }

Index: term_tag.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/term_tag.c,v
retrieving revision 1.4
diff -u -p -r1.4 term_tag.c
--- term_tag.c  18 Apr 2020 20:28:46 -0000      1.4
+++ term_tag.c  15 Jun 2020 10:30:38 -0000
@@ -28,6 +28,7 @@
 #include <unistd.h>

 #include "mandoc.h"
+#include "mandoc_aux.h"
 #include "roff.h"
 #include "roff_int.h"
 #include "tag.h"
@@ -44,7 +45,7 @@ static struct tag_files tag_files;
  * but for simplicity, create it anyway.
  */
 struct tag_files *
-term_tag_init(void)
+term_tag_init(const char *out_fext)
 {
        struct sigaction         sa;
        int                      ofd;   /* In /tmp/, dup(2)ed to stdout. */
@@ -81,20 +82,25 @@ term_tag_init(void)

        /* Create both temporary output files. */

-       (void)strlcpy(tag_files.ofn, "/tmp/man.XXXXXXXXXX",
-           sizeof(tag_files.ofn));
-       (void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX",
-           sizeof(tag_files.tfn));
-       if ((ofd = mkstemp(tag_files.ofn)) == -1) {
+       mandoc_asprintf(&tag_files.ofn, out_fext == NULL ?
+           "/tmp/man.XXXXXXXXXX" : "/tmp/man.XXXXXXXXXX.%s", out_fext);
+       mandoc_asprintf(&tag_files.tfn, out_fext == NULL ?
+           "/tmp/man.XXXXXXXXXX" : "/tmp/man.XXXXXXXXXX.%s", out_fext);
+
+       if ((ofd = mkstemps(tag_files.ofn, out_fext == NULL ? 0 :
+           strlen(out_fext) + 1)) == -1) {
                mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
                    "%s: %s", tag_files.ofn, strerror(errno));
                goto fail;
        }
-       if ((tfd = mkstemp(tag_files.tfn)) == -1) {
-               mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
-                   "%s: %s", tag_files.tfn, strerror(errno));
+
+       if ((tfd = mkstemps(tag_files.tfn, out_fext == NULL ? 0 :
+           strlen(out_fext) + 1)) == -1) {
+                mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
+                    "%s: %s", tag_files.tfn, strerror(errno));
                goto fail;
        }
+
        if ((tag_files.tfs = fdopen(tfd, "w")) == NULL) {
                mandoc_msg(MANDOCERR_FDOPEN, 0, 0, "%s", strerror(errno));
                goto fail;
Index: term_tag.h
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/term_tag.h,v
retrieving revision 1.2
diff -u -p -r1.2 term_tag.h
--- term_tag.h  2 Apr 2020 22:10:27 -0000       1.2
+++ term_tag.h  15 Jun 2020 10:30:38 -0000
@@ -19,8 +19,8 @@
  */

 struct tag_files {
-       char     ofn[20];       /* Output file name. */
-       char     tfn[20];       /* Tag file name. */
+       char     *ofn;          /* Output file name. */
+       char     *tfn;          /* Tag file name. */
        FILE    *tfs;           /* Tag file object. */
        int      ofd;           /* Original output file descriptor. */
        pid_t    tcpgid;        /* Process group controlling the terminal. */
@@ -28,7 +28,7 @@ struct        tag_files {
 };


-struct tag_files       *term_tag_init(void);
+struct tag_files       *term_tag_init(const char *);
 void                    term_tag_write(struct roff_node *, size_t);
 int                     term_tag_close(void);
 void                    term_tag_unlink(void);

On 2020-06-15 10:58, Romero Pérez, Abel wrote:

Thanks for the handy answer, Ingo.

I am going to develop it better.

On 2020-06-15 04:13, Ingo Schwarze wrote:
Hi Abel,

Romero Perez, Abel wrote on Mon, Jun 15, 2020 at 03:06:26AM +0200:
Romero Perez, Abel wrote:

I tried to view the manuals in HTML format with lynx, but I couldn't

I assume what you mean is that you could, but the "-O tag" option had
no effect.

because lynx and links can't accept the /tmp/man.XXXXXX... file as
an URL...

In "-T html" output mode, the tag file isn't even written in the first
place.  Only the terminal formatter writes a tag file.

then I decided to add a new parameter (-U)

Absolutely not.  Adding new options to man(1) is completely out of
the question.  Option space is almost full and very messy already:

   https://mandoc.bsd.lv/man/man.options.1.html

It hardly matters that -U is already taken:

   https://mandoc.bsd.lv/man/man.options.1.html#U

You certainly can't take an option that is still free for this
purpose, either.

to pass the pager a formal file URL scheme as follows:
file:///tmp/man.XXXXXXX#tag
Then man spawns the pager (lynx for my case):
lynx -force_html file:///tmp/man.XXXXXXX#tag

That's an interesting idea.

It needs to be done by default when -T html -O tag is given, just
like tagging is enabled by default when the pager is less(1).

The testing command is:
PAGER="" MANPAGER="lynx -force_html" ./man -U -T html -O tag=k pfctl

The PAGER="" variable has no effect when MANPAGER is set,
see the man(1) manual.

So the goal is to make this work:

   MANPAGER="lynx -force_html" ./man -T html -O tag=k pfctl

Sorry, I didn't reviewed the code well. The first diff has some bugs.
As follows the stable diff (please, review):

I didn't review the diff closely, yet.

Obviously, using strncpy(3) or strncat(3) is not permitted,
but those should be easy to replace, perhaps with mandoc_asprintf(),
not sure yet.

It looks like you will have to pass outst into run_pager() and
spawn_pager() rather than outst.tag_files, such that you can check
for outst.outtype == OUTT_HTML inside spawn_pager().

In any case, thanks for the nice idea!

Yours,
   Ingo


Reply via email to