]>
git.cameronkatri.com Git - mandoc.git/blob - catman.c
1 /* $Id: catman.c,v 1.22 2020/06/14 23:40:31 schwarze Exp $ */
3 * Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
4 * Copyright (c) 2017 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>
36 #include "compat_fts.h"
44 int process_manpage(int, int, const char *);
45 int process_tree(int, int);
46 void run_mandocd(int, const char *, const char *)
47 __attribute__((__noreturn__
));
48 ssize_t
sock_fd_write(int, int, int, int);
49 void usage(void) __attribute__((__noreturn__
));
53 run_mandocd(int sockfd
, const char *outtype
, const char* defos
)
57 if (snprintf(sockfdstr
, sizeof(sockfdstr
), "%d", sockfd
) == -1)
60 execlp("mandocd", "mandocd", "-T", outtype
,
61 sockfdstr
, (char *)NULL
);
63 execlp("mandocd", "mandocd", "-T", outtype
,
64 "-I", defos
, sockfdstr
, (char *)NULL
);
69 sock_fd_write(int fd
, int fd0
, int fd1
, int fd2
)
71 const struct timespec timeout
= { 0, 10000000 }; /* 0.01 s */
75 struct cmsghdr cmsghdr
;
76 char control
[CMSG_SPACE(3 * sizeof(int))];
81 unsigned char dummy
[1] = {'\0'};
84 iov
.iov_len
= sizeof(dummy
);
91 msg
.msg_control
= cmsgu
.control
;
92 msg
.msg_controllen
= sizeof(cmsgu
.control
);
94 cmsg
= CMSG_FIRSTHDR(&msg
);
95 cmsg
->cmsg_len
= CMSG_LEN(3 * sizeof(int));
96 cmsg
->cmsg_level
= SOL_SOCKET
;
97 cmsg
->cmsg_type
= SCM_RIGHTS
;
99 walk
= (int *)CMSG_DATA(cmsg
);
105 * It appears that on some systems, sendmsg(3)
106 * may return EAGAIN even in blocking mode.
107 * Seen for example on Oracle Solaris 11.2.
108 * The sleeping time was chosen by experimentation,
109 * to neither cause more than a handful of retries
110 * in normal operation nor unnecessary delays.
113 if ((sz
= sendmsg(fd
, &msg
, 0)) != -1 ||
116 nanosleep(&timeout
, NULL
);
122 process_manpage(int srv_fd
, int dstdir_fd
, const char *path
)
127 if ((in_fd
= open(path
, O_RDONLY
)) == -1) {
128 warn("open(%s)", path
);
132 if ((out_fd
= openat(dstdir_fd
, path
,
133 O_WRONLY
| O_NOFOLLOW
| O_CREAT
| O_TRUNC
,
134 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
)) == -1) {
135 warn("openat(%s)", path
);
140 irc
= sock_fd_write(srv_fd
, in_fd
, out_fd
, STDERR_FILENO
);
153 process_tree(int srv_fd
, int dstdir_fd
)
161 argv
[1] = (char *)NULL
;
163 if ((ftsp
= fts_open((char * const *)argv
,
164 FTS_PHYSICAL
| FTS_NOCHDIR
, NULL
)) == NULL
) {
169 while ((entry
= fts_read(ftsp
)) != NULL
) {
170 path
= entry
->fts_path
+ 2;
171 switch (entry
->fts_info
) {
173 if (process_manpage(srv_fd
, dstdir_fd
, path
) == -1) {
180 mkdirat(dstdir_fd
, path
, S_IRWXU
| S_IRGRP
|
181 S_IXGRP
| S_IROTH
| S_IXOTH
) == -1 &&
183 warn("mkdirat(%s)", path
);
184 (void)fts_set(ftsp
, entry
, FTS_SKIP
);
190 warnx("%s: not a regular file", path
);
200 main(int argc
, char **argv
)
202 const char *defos
, *outtype
;
210 while ((opt
= getopt(argc
, argv
, "I:T:")) != -1) {
230 if (socketpair(AF_LOCAL
, SOCK_STREAM
, AF_UNSPEC
, srv_fds
) == -1)
231 err(1, "socketpair");
239 run_mandocd(srv_fds
[1], outtype
, defos
);
245 if ((dstdir_fd
= open(argv
[1], O_RDONLY
| O_DIRECTORY
)) == -1)
246 err(1, "open(%s)", argv
[1]);
248 if (chdir(argv
[0]) == -1)
249 err(1, "chdir(%s)", argv
[0]);
251 return process_tree(srv_fds
[0], dstdir_fd
) == -1 ? 1 : 0;
257 fprintf(stderr
, "usage: %s [-I os=name] [-T output] "
258 "srcdir dstdir\n", BINM_CATMAN
);