[BACK]Return to catman.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/catman.c between version 1.24 and 1.29

version 1.24, 2025/06/29 20:47:01 version 1.29, 2025/06/30 12:23:42
Line 1 
Line 1 
 /*      $Id$ */  /* $Id$ */
 /*  /*
    * Copyright (c) 2017, 2025 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>   * Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
  * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>  
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above   * purpose with or without fee is hereby granted, provided that the above
Line 25 
Line 25 
 #include <sys/socket.h>  #include <sys/socket.h>
 #include <sys/stat.h>  #include <sys/stat.h>
   
   #include <assert.h>
 #if HAVE_ERR  #if HAVE_ERR
 #include <err.h>  #include <err.h>
 #endif  #endif
Line 35 
Line 36 
 #else  #else
 #include "compat_fts.h"  #include "compat_fts.h"
 #endif  #endif
   #include <signal.h>
   #include <stdint.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <time.h>  #include <time.h>
 #include <unistd.h>  #include <unistd.h>
   
   int             verbose_flag = 0;
   sig_atomic_t    got_signal = 0;
   
 int      process_manpage(int, int, const char *);  int      process_manpage(int, int, const char *);
 int      process_tree(int, int);  int      process_tree(int, int);
 void     run_mandocd(int, const char *, const char *)  void     run_mandocd(int, const char *, const char *)
                 __attribute__((__noreturn__));                  __attribute__((__noreturn__));
   void     signal_handler(int);
 ssize_t  sock_fd_write(int, int, int, int);  ssize_t  sock_fd_write(int, int, int, int);
 void     usage(void) __attribute__((__noreturn__));  void     usage(void) __attribute__((__noreturn__));
   
   
 void  void
   signal_handler(int signum)
   {
           got_signal = signum;
   }
   
   void
 run_mandocd(int sockfd, const char *outtype, const char* defos)  run_mandocd(int sockfd, const char *outtype, const char* defos)
 {  {
         char     sockfdstr[10];          char     sockfdstr[10];
Line 157  process_manpage(int srv_fd, int dstdir_fd, const char 
Line 170  process_manpage(int srv_fd, int dstdir_fd, const char 
 int  int
 process_tree(int srv_fd, int dstdir_fd)  process_tree(int srv_fd, int dstdir_fd)
 {  {
           const struct timespec timeout = { 0, 10000000 };  /* 0.01 s */
           const int        max_inflight = 16;
   
         FTS             *ftsp;          FTS             *ftsp;
         FTSENT          *entry;          FTSENT          *entry;
         const char      *argv[2];          const char      *argv[2];
         const char      *path;          const char      *path;
         int              fatal;          int              inflight, irc, decr, fatal;
         int              gooddirs, baddirs, goodfiles, badfiles;          int              gooddirs, baddirs, goodfiles, badfiles;
           char             dummy[1];
   
         argv[0] = ".";          argv[0] = ".";
         argv[1] = (char *)NULL;          argv[1] = (char *)NULL;
Line 173  process_tree(int srv_fd, int dstdir_fd)
Line 190  process_tree(int srv_fd, int dstdir_fd)
                 return -1;                  return -1;
         }          }
   
         fatal = 0;          if (verbose_flag >= 2) {
         gooddirs = baddirs = goodfiles = badfiles = 0;                  warnx("allowing up to %d files in flight", max_inflight);
         while (fatal == 0 && (entry = fts_read(ftsp)) != NULL) {                  fflush(stderr);
           }
           inflight = fatal = gooddirs = baddirs = goodfiles = badfiles = 0;
           while (fatal == 0 && got_signal == 0 &&
               (entry = fts_read(ftsp)) != NULL) {
                   if (inflight >= max_inflight) {
                           while (recv(srv_fd, dummy, sizeof(dummy), 0) == -1) {
                                   if (errno != EAGAIN) {
                                           warn("FATAL: recv");
                                           fatal = errno;
                                           break;
                                   }
                                   nanosleep(&timeout, NULL);
                           }
                           if (fatal != 0)
                                   break;
                           decr = 1;
                           while ((irc = recv(srv_fd, dummy, sizeof(dummy),
                               MSG_DONTWAIT)) > 0)
                                   decr++;
                           assert(inflight >= decr);
                           if (verbose_flag >= 2 && decr > 1) {
                                   warnx("files in flight: %d - %d = %d",
                                       inflight, decr, inflight - decr);
                                   fflush(stderr);
                           }
                           inflight -= decr;
                           if (irc == 0) {
                                   errno = ECONNRESET;
                                   inflight = -1;
                           }
                           if (errno != EAGAIN) {
                                   warn("FATAL: recv");
                                   fatal = errno;
                                   break;
                           }
                   }
                 path = entry->fts_path + 2;                  path = entry->fts_path + 2;
                 switch (entry->fts_info) {                  switch (entry->fts_info) {
                 case FTS_F:                  case FTS_F:
Line 188  process_tree(int srv_fd, int dstdir_fd)
Line 241  process_tree(int srv_fd, int dstdir_fd)
                                 break;                                  break;
                         default:                          default:
                                 goodfiles++;                                  goodfiles++;
                                   inflight++;
                                 break;                                  break;
                         }                          }
                         break;                          break;
Line 224  process_tree(int srv_fd, int dstdir_fd)
Line 278  process_tree(int srv_fd, int dstdir_fd)
                         badfiles++;                          badfiles++;
                         break;                          break;
                 default:                  default:
                         warnx("%s: not a regular file", path);                          warnx("file %s: not a regular file", path);
                         fflush(stderr);                          fflush(stderr);
                         badfiles++;                          badfiles++;
                         break;                          break;
                 }                  }
         }          }
         if (fatal == 0 && (fatal = errno) != 0)          if (got_signal != 0) {
                   switch (got_signal) {
                   case SIGCHLD:
                           warnx("FATAL: mandocd child died: got SIGCHLD");
                           break;
                   case SIGPIPE:
                           warnx("FATAL: mandocd child died: got SIGPIPE");
                           break;
                   default:
                           warnx("FATAL: signal SIG%s", sys_signame[got_signal]);
                           break;
                   }
                   inflight = -1;
                   fatal = 1;
           } else if (fatal == 0 && (fatal = errno) != 0)
                 warn("FATAL: fts_read");                  warn("FATAL: fts_read");
   
         fts_close(ftsp);          fts_close(ftsp);
           if (verbose_flag >= 2 && inflight > 0) {
                   warnx("waiting for %d files in flight", inflight);
                   fflush(stderr);
           }
           while (inflight > 0) {
                   irc = recv(srv_fd, dummy, sizeof(dummy), 0);
                   if (irc > 0)
                           inflight--;
                   else if (irc == -1 && errno == EAGAIN)
                           nanosleep(&timeout, NULL);
                   else {
                           if (irc == 0)
                                   errno = ECONNRESET;
                           warn("recv");
                           inflight = -1;
                   }
           }
           if (verbose_flag)
                   warnx("processed %d files in %d directories",
                       goodfiles, gooddirs);
         if (baddirs > 0)          if (baddirs > 0)
                 warnx("skipped %d %s due to errors", baddirs,                  warnx("skipped %d %s due to errors", baddirs,
                     baddirs == 1 ? "directory" : "directories");                      baddirs == 1 ? "directory" : "directories");
Line 243  process_tree(int srv_fd, int dstdir_fd)
Line 331  process_tree(int srv_fd, int dstdir_fd)
         if (fatal != 0) {          if (fatal != 0) {
                 warnx("processing aborted due to fatal error, "                  warnx("processing aborted due to fatal error, "
                     "results are probably incomplete");                      "results are probably incomplete");
                   inflight = -1;
         }          }
         return 0;          return inflight;
 }  }
   
 int  int
 main(int argc, char **argv)  main(int argc, char **argv)
 {  {
           struct sigaction sa;
         const char      *defos, *outtype;          const char      *defos, *outtype;
         int              srv_fds[2];          int              srv_fds[2];
         int              dstdir_fd;          int              dstdir_fd;
Line 258  main(int argc, char **argv)
Line 348  main(int argc, char **argv)
   
         defos = NULL;          defos = NULL;
         outtype = "ascii";          outtype = "ascii";
         while ((opt = getopt(argc, argv, "I:T:")) != -1) {          while ((opt = getopt(argc, argv, "I:T:v")) != -1) {
                 switch (opt) {                  switch (opt) {
                 case 'I':                  case 'I':
                         defos = optarg;                          defos = optarg;
Line 266  main(int argc, char **argv)
Line 356  main(int argc, char **argv)
                 case 'T':                  case 'T':
                         outtype = optarg;                          outtype = optarg;
                         break;                          break;
                   case 'v':
                           verbose_flag += 1;
                           break;
                 default:                  default:
                         usage();                          usage();
                 }                  }
Line 275  main(int argc, char **argv)
Line 368  main(int argc, char **argv)
                 argc -= optind;                  argc -= optind;
                 argv += optind;                  argv += optind;
         }          }
         if (argc != 2)          if (argc != 2) {
                   switch (argc) {
                   case 0:
                           warnx("missing arguments: srcdir and dstdir");
                           break;
                   case 1:
                           warnx("missing argument: dstdir");
                           break;
                   default:
                           warnx("too many arguments: %s", argv[2]);
                           break;
                   }
                 usage();                  usage();
           }
   
           memset(&sa, 0, sizeof(sa));
           sa.sa_handler = &signal_handler;
           sa.sa_flags = SA_NOCLDWAIT;
           if (sigfillset(&sa.sa_mask) == -1)
                   err(1, "sigfillset");
           if (sigaction(SIGHUP, &sa, NULL) == -1)
                   err(1, "sigaction(SIGHUP)");
           if (sigaction(SIGINT, &sa, NULL) == -1)
                   err(1, "sigaction(SIGINT)");
           if (sigaction(SIGPIPE, &sa, NULL) == -1)
                   err(1, "sigaction(SIGPIPE)");
           if (sigaction(SIGTERM, &sa, NULL) == -1)
                   err(1, "sigaction(SIGTERM)");
           if (sigaction(SIGCHLD, &sa, NULL) == -1)
                   err(1, "sigaction(SIGCHLD)");
   
         if (socketpair(AF_LOCAL, SOCK_STREAM, AF_UNSPEC, srv_fds) == -1)          if (socketpair(AF_LOCAL, SOCK_STREAM, AF_UNSPEC, srv_fds) == -1)
                 err(1, "socketpair");                  err(1, "socketpair");

Legend:
Removed from v.1.24  
changed lines
  Added in v.1.29

CVSweb