]>
git.cameronkatri.com Git - mandoc.git/blob - mandocd.c
1 /* $Id: mandocd.c,v 1.13 2022/04/14 16:43:44 schwarze Exp $ */
3 * Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
4 * Copyright (c) 2017, 2019, 2021 Ingo Schwarze <schwarze@openbsd.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 #include <sys/types.h>
25 #include <sys/socket.h>
40 #include "mandoc_dbg.h"
45 #include "mandoc_parse.h"
55 static void process(struct mparse
*, enum outt
, void *);
56 static int read_fds(int, int *);
57 static void usage(void) __attribute__((__noreturn__
));
62 read_fds(int clientfd
, int *fds
)
66 unsigned char dummy
[1];
71 /* Union used for alignment. */
73 uint8_t controlbuf
[CMSG_SPACE(NUM_FDS
* sizeof(int))];
77 memset(&msg
, '\0', sizeof(msg
));
78 msg
.msg_control
= u
.controlbuf
;
79 msg
.msg_controllen
= sizeof(u
.controlbuf
);
82 * Read a dummy byte - sendmsg cannot send an empty message,
83 * even if we are only interested in the OOB data.
86 iov
[0].iov_base
= dummy
;
87 iov
[0].iov_len
= sizeof(dummy
);
91 switch (recvmsg(clientfd
, &msg
, 0)) {
101 if ((cmsg
= CMSG_FIRSTHDR(&msg
)) == NULL
) {
102 warnx("CMSG_FIRSTHDR: missing control message");
106 if (cmsg
->cmsg_level
!= SOL_SOCKET
||
107 cmsg
->cmsg_type
!= SCM_RIGHTS
||
108 cmsg
->cmsg_len
!= CMSG_LEN(NUM_FDS
* sizeof(int))) {
109 warnx("CMSG_FIRSTHDR: invalid control message");
113 walk
= (int *)CMSG_DATA(cmsg
);
114 for (cnt
= 0; cnt
< NUM_FDS
; cnt
++)
121 main(int argc
, char *argv
[])
123 struct manoutput options
;
124 struct mparse
*parser
;
137 mandoc_dbg_init(argc
, argv
);
141 outtype
= OUTT_ASCII
;
142 while ((opt
= getopt(argc
, argv
, "I:T:")) != -1) {
145 if (strncmp(optarg
, "os=", 3) == 0)
148 warnx("-I %s: Bad argument", optarg
);
153 if (strcmp(optarg
, "ascii") == 0)
154 outtype
= OUTT_ASCII
;
155 else if (strcmp(optarg
, "utf8") == 0)
157 else if (strcmp(optarg
, "html") == 0)
160 warnx("-T %s: Bad argument", optarg
);
177 clientfd
= strtonum(argv
[0], 3, INT_MAX
, &errstr
);
179 errx(1, "file descriptor %s %s", argv
[1], errstr
);
182 parser
= mparse_alloc(MPARSE_SO
| MPARSE_UTF8
| MPARSE_LATIN1
|
183 MPARSE_VALIDATE
, MANDOC_OS_OTHER
, defos
);
185 memset(&options
, 0, sizeof(options
));
188 formatter
= ascii_alloc(&options
);
191 formatter
= utf8_alloc(&options
);
194 options
.fragment
= 1;
195 formatter
= html_alloc(&options
);
199 state
= 1; /* work to do */
202 if ((old_stdin
= dup(STDIN_FILENO
)) == -1 ||
203 (old_stdout
= dup(STDOUT_FILENO
)) == -1 ||
204 (old_stderr
= dup(STDERR_FILENO
)) == -1) {
206 state
= -1; /* error */
209 while (state
== 1 && (state
= read_fds(clientfd
, fds
)) == 1) {
210 if (dup2(fds
[0], STDIN_FILENO
) == -1 ||
211 dup2(fds
[1], STDOUT_FILENO
) == -1 ||
212 dup2(fds
[2], STDERR_FILENO
) == -1) {
222 process(parser
, outtype
, formatter
);
223 mparse_reset(parser
);
224 if (outtype
== OUTT_HTML
)
225 html_reset(formatter
);
229 /* Close file descriptors by restoring the old ones. */
230 if (dup2(old_stderr
, STDERR_FILENO
) == -1 ||
231 dup2(old_stdout
, STDOUT_FILENO
) == -1 ||
232 dup2(old_stdin
, STDIN_FILENO
) == -1) {
243 ascii_free(formatter
);
246 html_free(formatter
);
254 return state
== -1 ? 1 : 0;
258 process(struct mparse
*parser
, enum outt outtype
, void *formatter
)
260 struct roff_meta
*meta
;
262 mparse_readfd(parser
, STDIN_FILENO
, "<unixfd>");
263 meta
= mparse_result(parser
);
264 if (meta
->macroset
== MACROSET_MDOC
) {
268 terminal_mdoc(formatter
, meta
);
271 html_mdoc(formatter
, meta
);
275 if (meta
->macroset
== MACROSET_MAN
) {
279 terminal_man(formatter
, meta
);
282 html_man(formatter
, meta
);
291 fprintf(stderr
, "usage: mandocd [-I os=name] [-T output] socket_fd\n");