Hello,

i'm suggesting a user-visible change in the behaviour of man(1).
Currently, "man -w" without any argument prints the usage() message
and exits with error code 5.  I propose to instead print the manpath
and exit successfully.

This is motivated by the following facts:

 1. It is what the man(1) implementation in the man-db package
    does, which is probably the most widespread man(1) implementation
    nowadays because most Linux distributions use it by default.
    So the change improves compatibility.

 2. Colin Watson introduced the behaviour in man-db in 2012 with
    this ChangeLog entry: "Running 'man -w' (etc.) without a name
    now prints the manpath, for compatibility with other man
    implementations."  He didn't specify which ones he had in mind,
    but i suspect it was probably man-1.6, which most Linux
    distributions used before man-db.

 3. Some software in the wild appears to actually rely on this,
    for example, as Matej Cepl made me aware, the manual page viewing
    mode in vim(1).  Given how different the layouts of manual page
    directories are on different operating systems, i'm not convinced
    using this feature and then trying to manually inspect these
    directories is a wise choice for a random application program
    other than man(1) itself.  Then again, i see no pressing need
    to force such a hard failure as we currently do.

 4. In man-db, setting up the manpath is very complicated, so
    having this as a debugging tool (in addition to the separate
    manpath(1) command they have) seems somewhat useful.  With
    mandoc, manpath configuration is vastly simpler, so debugging
    it is less of a concern.  Still, it might occasionally help
    people to figure out how -m, -M, $MANPATH, man.conf(5), and
    the default manpath interact and why man(1) does not appear
    to search the directories they were hoping for.

I'm probably going to commit this unless somebody raises a concern.
For example, does anybody *rely* on the fact that "man -w" without
arguments currently fails, and would be inconvenienced if it
suddenly succeeded, doing something mildly useful?

Note one difference of this implementation compared to what man-db
does.  This one takes all input into account: command line options,
environment, the configuration file, and the default path.
By contrast, man-db appears to ignore the -m and -M command line
options when reporting the manpath.  I have no doubt that respecting
them, too, is more useful when people want to use this as a debugging
tool, and i do not expect the difference to cause compatibility
issues.

Comparison with other implementations (from code inspection):

 * NetBSD: "man -w" prints usage(); "man -p" prints the manpath.
   Re-using -p feels dubious to me because Eaton man, FreeBSD man,
   man-db, and man-1.6 all use -p for a completely different purpose,
   and groff, catman, makewhatis, mandb, and apropos use it for
   yet other purposes.

 * FreeBSD: "man -w" prints "What manual page do you want?" and
   errors out; there is a separate manpath(1) command.

 * man-1.6: like man-db, but longer, at least since man-1.5e (1998)

 * Oracle Solaris 11: Testing shows it doesn't provide -w at all.

 * Illumos: According to the manual page, "man -w" is essentially
   what we call makewhatis(8).

OK?
  Ingo


Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/main.c,v
retrieving revision 1.245
diff -u -p -r1.245 main.c
--- main.c      6 Feb 2020 19:41:34 -0000       1.245
+++ main.c      6 Feb 2020 19:53:42 -0000
@@ -427,8 +427,20 @@ main(int argc, char *argv[])
        /* man(1): Resolve each name individually. */
 
        if (search.argmode == ARG_NAME) {
-               if (argc < 1)
-                       usage(ARG_NAME);
+               if (argc < 1) {
+                       if (outmode != OUTMODE_FLN)
+                               usage(ARG_NAME);
+                       if (conf.manpath.sz == 0) {
+                               warnx("The manpath is empty.");
+                               mandoc_msg_setrc(MANDOCLEVEL_BADARG);
+                       } else {
+                               for (i = 0; i + 1 < conf.manpath.sz; i++)
+                                       printf("%s:", conf.manpath.paths[i]);
+                               printf("%s\n", conf.manpath.paths[i]);
+                       }
+                       manconf_free(&conf);
+                       return (int)mandoc_msg_getrc();
+               }
                for (res = NULL, ressz = 0; argc > 0; argc--, argv++) {
                        (void)mansearch(&search, &conf.manpath,
                            1, argv, &resn, &resnsz);
Index: man.1
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/man.1,v
retrieving revision 1.34
diff -u -p -r1.34 man.1
--- man.1       7 Jan 2020 11:15:12 -0000       1.34
+++ man.1       6 Feb 2020 19:53:42 -0000
@@ -3,7 +3,7 @@
 .\" Copyright (c) 1989, 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\" Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <[email protected]>
-.\" Copyright (c) 2010, 2011, 2014-2018 Ingo Schwarze <[email protected]>
+.\" Copyright (c) 2010, 2011, 2014-2020 Ingo Schwarze <[email protected]>
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
@@ -199,6 +199,9 @@ Kernel internals.
 .It Fl w
 List the pathnames of all matching manual pages instead of displaying
 any of them.
+If no
+.Ar name
+is given, list the directories that would be searched.
 .El
 .Pp
 The options

Reply via email to