=================================================================== RCS file: /cvs/mandoc/catman.c,v retrieving revision 1.24 retrieving revision 1.27 diff -u -p -r1.24 -r1.27 --- mandoc/catman.c 2025/06/29 20:47:01 1.24 +++ mandoc/catman.c 2025/06/30 01:44:28 1.27 @@ -1,7 +1,7 @@ -/* $Id: catman.c,v 1.24 2025/06/29 20:47:01 schwarze Exp $ */ +/* $Id: catman.c,v 1.27 2025/06/30 01:44:28 schwarze Exp $ */ /* + * Copyright (c) 2017, 2025 Ingo Schwarze * Copyright (c) 2017 Michael Stapelberg - * Copyright (c) 2017 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -35,21 +35,33 @@ #else #include "compat_fts.h" #endif +#include +#include #include #include #include #include #include +int verbose_flag = 0; +sig_atomic_t got_signal = 0; + int process_manpage(int, int, const char *); int process_tree(int, int); void run_mandocd(int, const char *, const char *) __attribute__((__noreturn__)); +void signal_handler(int); ssize_t sock_fd_write(int, int, int, int); void usage(void) __attribute__((__noreturn__)); void +signal_handler(int signum) +{ + got_signal = signum; +} + +void run_mandocd(int sockfd, const char *outtype, const char* defos) { char sockfdstr[10]; @@ -175,7 +187,8 @@ process_tree(int srv_fd, int dstdir_fd) fatal = 0; gooddirs = baddirs = goodfiles = badfiles = 0; - while (fatal == 0 && (entry = fts_read(ftsp)) != NULL) { + while (fatal == 0 && got_signal == 0 && + (entry = fts_read(ftsp)) != NULL) { path = entry->fts_path + 2; switch (entry->fts_info) { case FTS_F: @@ -224,16 +237,32 @@ process_tree(int srv_fd, int dstdir_fd) badfiles++; break; default: - warnx("%s: not a regular file", path); + warnx("file %s: not a regular file", path); fflush(stderr); badfiles++; 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; + } + fatal = 1; + } else if (fatal == 0 && (fatal = errno) != 0) warn("FATAL: fts_read"); fts_close(ftsp); + if (verbose_flag) + warnx("processed %d files in %d directories", + goodfiles, gooddirs); if (baddirs > 0) warnx("skipped %d %s due to errors", baddirs, baddirs == 1 ? "directory" : "directories"); @@ -250,6 +279,7 @@ process_tree(int srv_fd, int dstdir_fd) int main(int argc, char **argv) { + struct sigaction sa; const char *defos, *outtype; int srv_fds[2]; int dstdir_fd; @@ -258,7 +288,7 @@ main(int argc, char **argv) defos = NULL; outtype = "ascii"; - while ((opt = getopt(argc, argv, "I:T:")) != -1) { + while ((opt = getopt(argc, argv, "I:T:v")) != -1) { switch (opt) { case 'I': defos = optarg; @@ -266,6 +296,9 @@ main(int argc, char **argv) case 'T': outtype = optarg; break; + case 'v': + verbose_flag = 1; + break; default: usage(); } @@ -275,8 +308,36 @@ main(int argc, char **argv) argc -= 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(); + } + + 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) err(1, "socketpair");