xref: /freebsd/contrib/mandoc/mandocd.8 (revision cb2887746f8b9dd4ad6b1e757cdc053a08b25a2e)
1.\" $Id: mandocd.8,v 1.5 2025/06/30 15:07:38 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: June 30 2025 $
18.Dt MANDOCD 8
19.Os
20.Sh NAME
21.Nm mandocd
22.Nd server process to format manual pages in batch mode
23.Sh SYNOPSIS
24.Nm mandocd
25.Op Fl I Cm os Ns = Ns Ar name
26.Op Fl T Ar output
27.Ar socket_fd
28.Sh DESCRIPTION
29The
30.Nm
31utility formats many manual pages without requiring
32.Xr fork 2
33and
34.Xr exec 3
35overhead in between.
36It does not require listing all the manuals to be formatted on the
37command line, and it supports writing each formatted manual to its
38own file descriptor.
39.Pp
40This server requires that a connected UNIX domain
41.Xr socket 2
42is already present at
43.Xr exec 3
44time.
45Consequently, it cannot be started from the
46.Xr sh 1
47command line because the shell cannot supply such a socket.
48Typically, the socket is created by the parent process using
49.Xr socketpair 2
50before calling
51.Xr fork 2
52and
53.Xr exec 3
54on
55.Nm .
56The parent process will pass the file descriptor number as an argument to
57.Xr exec 3 ,
58formatted as a decimal ASCII-encoded integer.
59See
60.Xr catman 8
61for a typical implementation of a parent process.
62.Pp
63.Nm
64loops reading one-byte messages with
65.Xr recvmsg 2
66from the file descriptor number
67.Ar socket_fd .
68It ignores the byte read and only uses the out-of-band auxiliary
69.Vt struct cmsghdr
70control data, typically supplied by the calling process using
71.Xr CMSG_FIRSTHDR 3 .
72The parent process is expected to pass three file descriptors
73with each dummy byte.
74The first one is used for
75.Xr mdoc 7
76or
77.Xr man 7
78input, the second one for formatted output, and the third one
79for error output.
80.Pp
81After accepting each message,
82.Nm
83replies with a one-byte message of its own,
84such that the parent process can keep track of how many messages
85.Nm
86has already accepted and how many file descriptors
87consequently are still in flight, such that the parent process
88can limit the number of file descriptors in flight at any given time
89in order to prevent
90.Er EMFILE
91failure of
92.Xr sendmsg 2 .
93.Pp
94The options are as follows:
95.Bl -tag -width Ds
96.It Fl I Cm os Ns = Ns Ar name
97Override the default operating system
98.Ar name
99for the
100.Xr mdoc 7
101.Ic \&Os
102and for the
103.Xr man 7
104.Ic TH
105macro.
106.It Fl T Ar output
107Output format.
108The
109.Ar output
110argument can be
111.Cm ascii ,
112.Cm utf8 ,
113or
114.Cm html ;
115see
116.Xr mandoc 1 .
117In
118.Cm html
119output mode, the
120.Cm fragment
121output option is implied.
122Other output options are not supported.
123.El
124.Pp
125After exhausting one input file descriptor, all three file descriptors
126are closed before reading the next dummy byte and control message.
127.Pp
128When a zero-byte message or a misformatted message is read, when the
129.Ar socket_fd
130is closed by the parent process,
131or when an error occurs,
132.Nm
133exits.
134.Sh EXIT STATUS
135.Ex -std
136.Pp
137A zero-byte message or a closed
138.Ar socket_fd
139is considered success.
140Possible errors include:
141.Bl -bullet
142.It
143missing, invalid, or excessive
144.Xr exec 3
145arguments
146.It
147communication failure with the parent, for example failure in
148.Xr recvmsg 2
149or
150.Xr send 2
151.It
152missing or unexpected control data, in particular a
153.Fa cmsg_level
154in the
155.Vt struct cmsghdr
156that differs from
157.Dv SOL_SOCKET ,
158a
159.Fa cmsg_type
160that differs from
161.Dv SCM_RIGHTS ,
162or a
163.Fa cmsg_len
164that is not three times the size of an
165.Vt int
166.It
167invalid file descriptors passed in the
168.Xr CMSG_DATA 3
169.It
170resource exhaustion, in particular
171.Xr dup 2
172or
173.Xr malloc 3
174failure
175.El
176.Pp
177Except for memory exhaustion and similar system-level failures,
178parsing and formatting errors do not cause
179.Nm
180to return an error exit status.
181Even after severe parsing errors,
182.Nm
183will simply accept and process the next input file descriptor.
184.Sh SEE ALSO
185.Xr mandoc 1 ,
186.Xr mandoc 3 ,
187.Xr catman 8
188.Sh HISTORY
189The
190.Nm
191utility appeared in version 1.14.1 of the
192.Sy mandoc
193toolkit.
194.Sh AUTHORS
195.An -nosplit
196The concept was designed and implemented by
197.An Michael Stapelberg Aq Mt stapelberg@debian.org .
198The
199.Xr mandoc 3
200glue needed to make it a stand-alone process was added by
201.An Ingo Schwarze Aq Mt schwarze@openbsd.org .
202.Sh CAVEATS
203If the parsed manual pages contain
204.Xr roff 7
205.Pf . Ic so
206requests,
207.Nm
208needs to be started with the current working directory set to the
209root of the manual page tree.
210Avoid starting it in directories that contain secret files in any
211subdirectories, in particular if the user starting it has read
212access to these secret files.
213