]> git.cameronkatri.com Git - mandoc.git/blobdiff - catman.c
In fragment identifiers, use ~%d for ordinal suffixes,
[mandoc.git] / catman.c
index 5ecef67ed3371b9f4bd1eec382d6c2bd0ccd0b5d..7d62c0e74addd37dc2c2846e81700c87729bbdd8 100644 (file)
--- a/catman.c
+++ b/catman.c
@@ -1,4 +1,4 @@
-/*     $Id: catman.c,v 1.14 2017/02/06 19:02:37 schwarze Exp $ */
+/*     $Id: catman.c,v 1.21 2017/02/18 12:24:24 schwarze Exp $ */
 /*
  * Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
  * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
  */
 #include "config.h"
 
+#if HAVE_CMSG_XPG42
+#define _XPG4_2
+#endif
+
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 
 int     process_manpage(int, int, const char *);
 int     process_tree(int, int);
 void    run_mandocd(int, const char *, const char *)
-               __attribute__((noreturn));
+               __attribute__((__noreturn__));
 ssize_t         sock_fd_write(int, int, int, int);
-void    usage(void) __attribute__((noreturn));
+void    usage(void) __attribute__((__noreturn__));
 
 
 void
@@ -52,16 +57,18 @@ run_mandocd(int sockfd, const char *outtype, const char* defos)
        if (snprintf(sockfdstr, sizeof(sockfdstr), "%d", sockfd) == -1)
                err(1, "snprintf");
        if (defos == NULL)
-               execlp("mandocd", "mandocd", "-T", outtype, sockfdstr, NULL);
+               execlp("mandocd", "mandocd", "-T", outtype,
+                   sockfdstr, (char *)NULL);
        else
                execlp("mandocd", "mandocd", "-T", outtype,
-                   "-I", defos, sockfdstr, NULL);
+                   "-I", defos, sockfdstr, (char *)NULL);
        err(1, "exec");
 }
 
 ssize_t
 sock_fd_write(int fd, int fd0, int fd1, int fd2)
 {
+       const struct timespec timeout = { 0, 10000000 };  /* 0.01 s */
        struct msghdr    msg;
        struct iovec     iov;
        union {
@@ -70,6 +77,7 @@ sock_fd_write(int fd, int fd0, int fd1, int fd2)
        } cmsgu;
        struct cmsghdr  *cmsg;
        int             *walk;
+       ssize_t          sz;
        unsigned char    dummy[1] = {'\0'};
 
        iov.iov_base = dummy;
@@ -93,7 +101,21 @@ sock_fd_write(int fd, int fd0, int fd1, int fd2)
        *(walk++) = fd1;
        *(walk++) = fd2;
 
-       return sendmsg(fd, &msg, 0);
+       /*
+        * It appears that on some systems, sendmsg(3)
+        * may return EAGAIN even in blocking mode.
+        * Seen for example on Oracle Solaris 11.2.
+        * The sleeping time was chosen by experimentation,
+        * to neither cause more than a handful of retries
+        * in normal operation nor unnecessary delays.
+        */
+       for (;;) {
+               if ((sz = sendmsg(fd, &msg, 0)) != -1 ||
+                   errno != EAGAIN)
+                       break;
+               nanosleep(&timeout, NULL);
+       }
+       return sz;
 }
 
 int
@@ -232,7 +254,7 @@ main(int argc, char **argv)
 void
 usage(void)
 {
-       fprintf(stderr, "usage: catman [-I os=name] [-T output] "
-           "srcdir dstdir\n");
+       fprintf(stderr, "usage: %s [-I os=name] [-T output] "
+           "srcdir dstdir\n", BINM_CATMAN);
        exit(1);
 }