-------- Original Message -------- From: Ingo Schwarze Sent: 5 September 2025 17:50:10 CEST To: g.branden.robinson@gmail.com Cc: groff@gnu.org, man-db-devel@nongnu.org Subject: Re: [man-db] remove magic to act like -l without -l ? Hello Branden, G. Branden Robinson wrote on Sun, Aug 31, 2025 at 11:06:43PM -0500: [...] > The problem with mandoc(1) and man(1) keeping the status quo is that the > name space in which you're searching for a page is ambiguous. The `-l` > option disambiguates it, and selects the file system as the name space. > The traditional name space for man page resolution, I would term the > "topic" name space. Correct. Actually, there are three mutually exclusive options that govern argument interpretation, resulting in the four main operation modes: option arguments are traditional program name -f page names whatis(1) -k search expressions apropos(1) -l file names nroff(1) or, more recently, mandoc(1) neither page names man(1) > Ingo has pointed out that a slash is actually encountered in real-world > man page topic names. (I long knew it was "legal", but didn't know any > actual pages exercised this freedom, and had supposed that one could > decide a name space based on the presence of a slash. Ingo's exhibits > have overturned my supposition.) > > Thus, given a command: > > $ man foo/bar > > when a page listing "foo/bar" as a topic, _and_ a file ./foo/bar > relative to your current working directory are both extant, which one > wins? Where is the rule written down? In that case, * man-1.5e, likely released in July 1998, according to its manual page: "If name contains a / then it is first tried as a filename." This sounds as if it would fall back to page name lookup, but inspecting the source code reveals that it doesn't, prints an error message, and proceeds to the next argument. Shortened code exhibit: int main (int argc, char **argv) { while (optind < argc) { nextarg = argv[optind++]; status = man (nextarg, section); } } static int man (char *name, char *section) { if (index(name, '/')) { FILE *fp = fopen(name, "r"); if (!fp) { perror(name); return 0; * man-1.6g, likely released in December 2010, according to its manual page: "If name contains a slash (/) then man interprets it as a file specification, so that you can do man ./foo.5 or even man /cd/foo/bar.1.gz." Code inspection reveals that the above is still in place, so it appears the maintainers realized the manual was misleading and removed the wording "is first tried". * man-db says in its manual page: "If this option is not used, then man will also fall back to interpreting manual page arguments as local file names if the argument contains a "/" character." Code inspection shows that the code structure in main() with the "nextarg" variable is still in place (though there is lots of new complication), but instead of man(), a new function man_maybe_local() was introducted: if (strchr (name, '/')) { int status = local_man_loop (name); if (status == OK) *found = 1; return status; } return man (name, found); Now this looks as if: - Around the "*found = 1; return status;" the block braces were forgotten, which is a classic programming mistake. - The consequence of the bug seems to be that man-db does *not* actually support manual pages names containing slashes and contrary to what the manual claims, even without -l man-db does not only use local filenames as a fallback, but names containing slashes are *only* treated as local filenames and *never* as manual page names - just like in man-1.5/man-1.6. - Even if the bug with the missing braces were fixed, the order of fallback would be the opposite of what the manual page claims: the code would first try each name containing a slash as a local filename and only then fall back to normal page name lookup. I'm not completely sure about all this because the code of man-db is quite hard to read and contains a lot of complication, but at least testing on Debian bookworm with man-db-2.11.2-2 seems to confirm that man-db does not support names with slashes and does not support fallback, unless i'm doing something wrong. * The mandoc implementation of man(1) was designed to be compatible with the man-db manual page in 2018, i.e. from 2018 to 2025, it first used names containing slashes as page names, and if not found, fell back to using them as local file names, without documenting this behaviour. Now, the fallback was removed, and without -l, mandoc man(1) no longer interprets any names as local file names. * The FreeBSD man(1) manual says: "The man utility also supports displaying a specific manual page if passed a path to the file as long as it contains a '/' character." So the manual is not very clear whether or not that is a fallback, but looking at the code reveals that for names containing a slash, FreeBSD prefers the local file if it exists and falls back to using it as a page name (which actually works according to my testing, even if the name contains a slash). * The NetBSD man(1) manual says: "If name is given with a full path (beginning with `/') or a relative path that begins with `./' or `../', then man interprets it as a file specification, so that you can do man ./foo.5 or even man /cd/foo/bar.1.gz. If name contains `/' but does not match one of the above cases, then the search path is used; this allows you to request machine-specific man pages, such as man vax/boot." Code inspection reveals that the description is accurate, there is no fallback, and fewer names are treated as local filenames than in the other systems. Regarding -l, the current status is: * NetBSD has just committed a patch implementing -l that i sent to them. They are planning to remove support for "man ./filename.1" at some point in the future, but did not consider yet how long the deprecation phase should be. https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=59625 * FreeBSD is planning to commit a patch implementing -l that i sent to them, and they are also planning to add a deprecation notice for "man ./filename.1" to that patch. The timing is not decided yet. https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=289245 * Once the patch is committed to FreeBSD, i'm planning to contact Illumos - even though it's harder for them because they are currently using -l for a *different* purpose for Oracle Solaris compatibility. So they would have to implement -w, which is not identitcal to their -l, but similar in purpose, then deprecate, theit current -l, then later implement the -l we are used to from man-db and mandoc. > Is the ordering intuitive? Why or why not? To answer that, let's summarize what happens for names containing slashes: System file name page name fallback man-1.5e manual prefer fallback -->> man-1.5e reality always never none man-1.6g manual yes unclear ???? man-1.6g reality always never none man-db manual fallback prefer <<-- man-db reality always never none mandoc manual unclear always ???? mandoc reality fallback prefer <<-- FreeBSD manual yes unclear ???? FreeBSD reality prefer fallback -->> NetBSD / ./ ../ foo/bar none So, that's obviously completely intuitive. Why is it so intuitive? Duh, because it is very simple and highly consistent, of course! > The fact that such a wrapper would have to decide which name space it > searches first motivates removal of this "DWIM" feature, because if you > were to survey man(1) users, I predict that you would find consensus > lacking on what they "M". > > But, I'll wager, most of them don't know that. They know which > resolution order they expect and have come to rely upon, and would > express astonishment that anyone would expect the opposite one. I'll wager that most users won't even know which resolution order their favourite implementation, the one that they use daily, actually implements. It looks like even most people who WTFM ("wrote the fantastic manuals") barely knew. It appears NetBSD was the only implementation providing complete and accurate documentation, but its semantics matched *none* of the others. > Implicit, unexamined assumptions are how a great many unproductive > disagreements originate and are sustained. Amen. > [1] I admit that "topic" is my own invention. groff_man(7) presents > the distinction between a "title" and a "topic". I hate that terminology. The mandoc manual pages just call arguments you can pass to man(1) for lookup "names", plain and simple. That makes sense because the same thing or person can have multiple names, and the same name can refer to multiple things or persons. Calling it "name" is also very natural terminology because there are three places where names can come from, and the majority of them are already called "name" for other reasons: 1. file names (sic!) For example, a file name man1/cat.1 below the MANPATH establishes a manual page name "cat" and a section "1". 2. .Dt and .TH first arguments The man(7) manual from the mandoc package gives the .TH synopsis as: .TH name section date [source [volume]] Probably, the mdoc(7) manual should als give the .Dt synopsis as: .Dt name section [arch] (Right now, it says ".Dt TITLE section [arch]", which is probably a bad idea.) 3. the NAME section (sic!), and specifically the first few words in that section, which, in mdoc(7) input, are marked up with .Nm (sic!) Looks like overwhelming support for calling this "name" to me. Yours, Ingo