1.\" $Id: catman.8,v 1.15 2025/07/13 14:15:26 schwarze Exp $ 2.\" 3.\" Copyright (c) 2017, 2025 Ingo Schwarze <schwarze@openbsd.org> 4.\" 5.\" Permission to use, copy, modify, and distribute this software for any 6.\" purpose with or without fee is hereby granted, provided that the above 7.\" copyright notice and this permission notice appear in all copies. 8.\" 9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16.\" 17.Dd $Mdocdate: July 13 2025 $ 18.Dt CATMAN 8 19.Os 20.Sh NAME 21.Nm catman 22.Nd format all manual pages below a directory 23.Sh SYNOPSIS 24.Nm catman 25.Op Fl I Cm os Ns = Ns Ar name 26.Op Fl T Ar output 27.Ar srcdir dstdir 28.Sh DESCRIPTION 29The 30.Nm 31utility assumes that all files below 32.Ar srcdir 33are manual pages in 34.Xr mdoc 7 35and 36.Xr man 7 37format and formats all of them, storing the formatted versions in 38the same relative paths below 39.Ar dstdir . 40Unless they already exist, 41.Ar dstdir 42itself and any required subdirectories are created. 43Existing files are not explicitly deleted, but possibly overwritten. 44.Pp 45The options are as follows: 46.Bl -tag -width Ds 47.It Fl I Cm os Ns = Ns Ar name 48Override the default operating system 49.Ar name 50for the 51.Xr mdoc 7 52.Ic \&Os 53and for the 54.Xr man 7 55.Ic TH 56macro. 57.It Fl T Ar output 58Output format. 59The 60.Ar output 61argument can be 62.Cm ascii , 63.Cm utf8 , 64or 65.Cm html ; 66see 67.Xr mandoc 1 . 68In 69.Cm html 70output mode, the 71.Cm fragment 72output option is implied. 73Other output options are not supported. 74.It Fl v 75Verbose mode, printing additional information to standard error output. 76Specifying this once prints a summary about the number of files 77and directories processed at the end of the iteration. 78Specifying it twice additionally prints debugging information 79about the backchannel from 80.Xr mandocd 8 81to 82.Nm 83that is used to limit the number of files in flight at any given time. 84For details, see 85.Sx DIAGNOSTICS . 86.El 87.Sh IMPLEMENTATION NOTES 88Since this version avoids 89.Xr fork 2 90and 91.Xr exec 3 92overhead and uses the much faster 93.Sy mandoc 94parsers and formatters rather than 95.Sy groff , 96it may be about one order of magnitude faster than other 97.Nm 98implementations. 99.Sh EXIT STATUS 100.Ex -std 101.Pp 102Failures while trying to open individual manual pages for reading, 103to save individual formatted files to the file system, 104or even to read or create subdirectories do not cause 105.Nm 106to return an error exit status. 107In such cases, 108.Nm 109simply continues with the next file or subdirectory. 110.Sh DIAGNOSTICS 111Some fatal errors cause 112.Nm 113to exit before the iteration over input files is even started: 114.Bl -tag -width Ds -offset indent 115.It unknown option \-\- Ar option 116An invalid option was passed on the command line. 117.It missing arguments: srcdir and dstdir 118No argument was provided. 119Both 120.Ar srcdir 121and 122.Ar dstdir 123are mandatory. 124.It missing argument: dstdir 125Only one argument was provided. 126The second argument, 127.Ar dstdir , 128is mandatory, too. 129.It too many arguments: Ar third argument 130Three or more arguments were provided, but only two are supported. 131.It Sy socketpair : Ar reason 132The sockets needed for communication with 133.Xr mandocd 8 134could not be created, for example due to file descriptor or memory exhaustion. 135.It Sy fork : Ar reason 136The new process needed to run 137.Xr mandocd 8 138could not be created, for example due to process table exhaustion 139or system resource limits. 140.It Sy exec Ns Po Sy mandocd Pc : Ar reason 141The 142.Xr mandocd 8 143child program could not be started, for example because it is not in the 144.Ev PATH 145or has no execute permission. 146.It Sy mkdir No destination Ar dstdir : reason 147The 148.Ar dstdir 149does not exist and could not be created, for example because 150the parent directory does not exist or permission is denied. 151.It Sy open No destination Ar dstdir : reason 152The 153.Ar dstdir 154could not be opened for reading, for example because 155it is not a directory or permission is denied. 156.It Sy chdir No to source Ar srcdir : reason 157The current working directory could not be changed to 158.Ar srcdir , 159for example because it does not exist, it is not a directory, 160or permission is denied. 161.It Sy fts_open : Ar reason 162Starting the iteration was attempted but failed, 163for example due to memory exhaustion. 164.El 165.Pp 166Some fatal errors cause the iteration over input files to be aborted 167prematurely: 168.Bl -tag -width Ds -offset indent 169.It FATAL: Sy fts_read : Ar reason 170A call to 171.Xr fts_read 3 172returned 173.Dv NULL , 174meaning that the iteration failed before being complete. 175.It FATAL: mandocd child died: got Ar SIGNAME 176This message appears if 177.Nm 178gets the 179.Dv SIGCHLD 180or 181.Dv SIGPIPE 182signal, most likely due to a fatal bug in 183.Xr mandocd 8 . 184.It FATAL: Sy sendmsg : Ar reason 185The file descriptors needed to process one of the manual pages 186could not be sent to 187.Xr mandocd 8 , 188for example because 189.Xr mandocd 8 190could not be started or died unexpectedly. 191.It FATAL: Sy recv : Ar reason 192Trying to read a reply message from 193.Xr mandocd 8 194failed, most likely because 195.Xr mandocd 8 196unexpectedly died or closed the socket. 197.It FATAL: signal Ar SIGNAME 198This message appears if 199.Nm 200gets a 201.Dv SIGHUP , 202.Dv SIGINT , 203or 204.Dv SIGTERM 205signal, for example because the user deliberately killed it. 206.El 207.Pp 208Some non-fatal errors cause a single subdirectory to be skipped. 209The iteration is not aborted but continues with the next subdirectory, 210and the exit status is unaffected: 211.Bl -tag -width Ds -offset indent 212.It directory Ar subdirectory No unreadable : Ar reason 213A directory below 214.Ar srcdir 215could not be read and is skipped. 216.It directory Ar subdirectory No causes cycle 217A directory below 218.Ar srcdir 219is skipped because it would cause cyclic processing. 220.It Sy mkdirat Ar subdirectory : reason 221A required directory below 222.Ar dstdir 223does not exist and could not be created. 224The corresponding subdirectory below 225.Ar srcdir 226is skipped. 227.El 228.Pp 229Some non-fatal errors cause a single source file to be skipped. 230The iteration is not aborted but continues with the next file, 231and the exit status is unaffected: 232.Bl -tag -width Ds -offset indent 233.It file Ar filename : reason 234The function 235.Xr fts_read 3 236reported a non-fatal error with respect to 237.Ar filename . 238.It file Ar filename : No not a regular file 239For example, it might be a symbolic link or a device file. 240.It Sy open Ar filename No for reading : Ar reason 241A file below 242.Ar srcdir 243could not be read, for example due to permission problems. 244.It Sy openat Ar filename No for writing : Ar reason 245A file below 246.Ar dstdir 247could not be created or truncated, for example due to permission problems. 248.El 249.Pp 250If errors occur, the applicable summary messages appear 251after the end of the iteration: 252.Pp 253.Bl -tag -width Ds -offset indent -compact 254.It skipped Ar number No directories due to errors 255.It skipped Ar number No files due to errors 256.It processing aborted due to fatal error 257.El 258.Pp 259If the 260.Fl v 261flag is specified, the following summary message also appears: 262.Bl -tag -width Ds -offset indent 263.It processed Ar nfiles No files in Ar ndirs No directories 264A file is counted if it could be opened for reading and the 265corresponding output file could be opened for writing; 266this does not necessarily mean that it is a useful manual page. 267A directory is counted if it could be opened for reading and the 268corresponding output directory existed or could be created; 269this does not necessarily mean that any files could be 270processed inside. 271.El 272.Pp 273If the 274.Fl v 275flag is specified twice, the following messages also appear: 276.Bl -tag -width Ds -offset indent 277.It allowing up to Ar number No files in flight 278This is printed at the beginning of the iteration, 279showing the maximum number of files that 280.Nm 281allows to be in flight at any given time. 282.It files in flight: Ar old No \- Ar decrement No = Ar new 283This message is printed when 284.Nm 285learns about 286.Xr mandocd 8 287accepting more than one file at the same time. 288The three numbers printed are the old number of files in flight, 289the amount this number is being reduced, and the resulting 290new number of files in flight. 291.It waiting for Ar number No files in flight 292This message is printed at the end of the iteration, after 293.Nm 294has submitted all files to 295.Xr mandocd 8 296that it intends to. 297THe message informs about the number of files still in flight 298at this point. 299The 300.Nm 301program then waits until 302.Xr mandocd 8 303has accepted them all or until an error occurs. 304.El 305.Sh SEE ALSO 306.Xr mandoc 1 , 307.Xr mandocd 8 308.Sh HISTORY 309A 310.Nm 311utility first appeared in 312.Fx 1.0 . 313Other, incompatible implementations appeared in 314.Nx 1.0 315and in 316.Sy man-db No 2.2 . 317.Pp 318This version appeared in version 1.14.1 of the 319.Sy mandoc 320toolkit. 321.Sh AUTHORS 322.An -nosplit 323The first 324.Nm 325implementation was a short shell script by 326.An Christoph Robitschko 327in July 1993. 328.Pp 329The 330.Nx 331implementations were written by 332.An J. T. Conklin Aq Mt jtc@netbsd.org 333in 1993, 334.An Christian E. Hopps Aq Mt chopps@netbsd.org 335in 1994, 336and 337.An Dante Profeta Aq Mt dante@netbsd.org 338in 1999; the 339.Sy man-db 340implementation by 341.An Graeme W. Wilford 342in 1994; and the 343.Fx 344implementations by 345.An Wolfram Schneider Aq Mt wosch@freebsd.org 346in 1995 and 347.An John Rochester Aq Mt john@jrochester.org 348in 2002. 349.Pp 350The concept of the present version was designed and implemented by 351.An Michael Stapelberg Aq Mt stapelberg@debian.org 352in 2017. 353Option and argument handling and directory iteration was added by 354.An Ingo Schwarze Aq Mt schwarze@openbsd.org . 355.Sh CAVEATS 356All versions of 357.Nm 358are incompatible with each other because each caters to the needs 359of a specific operating system, for example regarding directory 360structures and file naming conventions. 361.Pp 362This version is more flexible than the others in so far as it does 363not assume any particular directory structure or naming convention. 364That flexibility comes at the price of not being able to change the 365names and relative paths of the source files when reusing them to 366store the formatted files, of not supporting any configuration file 367formats or environment variables, and of being unable to scan for 368and remove junk files in 369.Ar dstdir . 370.Pp 371Currently, 372.Nm 373always reformats each page, even if the formatted version is newer 374than the source version. 375