Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 06 Feb 2026 00:31:51 +0000
From:      Alexander Ziaee <ziaee@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: a1f4ccd6c794 - stable/14 - mandoc: Vendor import of upstream at 2025-07-27
Message-ID:  <69853677.3136f.67cd70e@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch stable/14 has been updated by ziaee:

URL: https://cgit.FreeBSD.org/src/commit/?id=a1f4ccd6c79470eb0180f4d9a012b24c267d2574

commit a1f4ccd6c79470eb0180f4d9a012b24c267d2574
Author:     Alexander Ziaee <ziaee@FreeBSD.org>
AuthorDate: 2025-08-15 19:03:22 +0000
Commit:     Alexander Ziaee <ziaee@FreeBSD.org>
CommitDate: 2026-02-06 00:30:48 +0000

    mandoc: Vendor import of upstream at 2025-07-27
    
    Groff Compat Edition -- Interesting changes:
    + italics in section/subsection headers are now also bold, like groff
    + display "LOCAL" in response to invalid section numbers, like groff
    + tbl(7) rendering has been tweaked to be more like groff
    + scaling has been improved to better render poorly generated manuals
    + display "UNTITLED" in response to invalid man(7) titles, like groff
    + improve mandocd error handling of broken pipes
    + manual footers now always show NAME(SECTION) on the right, like groff
    
    MFC after:      3 days
    
    (cherry picked from commit 06410c1b51637e5e1f392d553b5008948af58014)
---
 contrib/mandoc/Makefile        |   2 +-
 contrib/mandoc/TODO            |  11 +-
 contrib/mandoc/catman.8        | 238 ++++++++++++++++++++++++++++++----
 contrib/mandoc/catman.c        | 231 +++++++++++++++++++++++++++++----
 contrib/mandoc/gmdiff          |   4 +-
 contrib/mandoc/man.7           | 151 +++++++++++++---------
 contrib/mandoc/man.options.1   |   9 +-
 contrib/mandoc/man_html.c      |  19 ++-
 contrib/mandoc/man_term.c      | 133 +++++++++----------
 contrib/mandoc/man_validate.c  |  18 ++-
 contrib/mandoc/mandoc.1        |  31 ++---
 contrib/mandoc/mandoc.css      |   4 +-
 contrib/mandoc/mandocd.8       |  26 +++-
 contrib/mandoc/mandocd.c       |  34 ++++-
 contrib/mandoc/manpath.c       |  11 +-
 contrib/mandoc/mdoc_html.c     |  15 ++-
 contrib/mandoc/mdoc_man.c      |   5 +-
 contrib/mandoc/mdoc_markdown.c |  10 +-
 contrib/mandoc/mdoc_term.c     | 122 ++++++++++--------
 contrib/mandoc/mdoc_validate.c |  10 +-
 contrib/mandoc/out.c           |  63 ++++++---
 contrib/mandoc/out.h           |  24 ++--
 contrib/mandoc/roff.7          | 195 +++++++++++++++++++++-------
 contrib/mandoc/roff_term.c     |  31 +++--
 contrib/mandoc/tbl.h           |  16 +--
 contrib/mandoc/tbl_html.c      |  34 +----
 contrib/mandoc/tbl_layout.c    |  10 +-
 contrib/mandoc/tbl_term.c      | 287 +++++++++++++++++++++++------------------
 contrib/mandoc/term.c          | 201 ++++++++++++++++-------------
 contrib/mandoc/term.h          |  38 +++---
 contrib/mandoc/term_ascii.c    |  91 +++++++------
 contrib/mandoc/term_ps.c       |  18 +--
 contrib/mandoc/term_tab.c      |  27 +---
 33 files changed, 1365 insertions(+), 754 deletions(-)

diff --git a/contrib/mandoc/Makefile b/contrib/mandoc/Makefile
index 7ec34a560504..0830c9f289a3 100644
--- a/contrib/mandoc/Makefile
+++ b/contrib/mandoc/Makefile
@@ -15,7 +15,7 @@
 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-VERSION = 1.14.6s20250613
+VERSION = 1.14.6s20250727
 
 # === LIST OF FILES ====================================================
 
diff --git a/contrib/mandoc/TODO b/contrib/mandoc/TODO
index 3f5a449af68f..5d582b85b154 100644
--- a/contrib/mandoc/TODO
+++ b/contrib/mandoc/TODO
@@ -1,6 +1,6 @@
 ************************************************************************
 * Official mandoc TODO.
-* $Id: TODO,v 1.337 2025/04/08 21:53:14 schwarze Exp $
+* $Id: TODO,v 1.338 2025/07/22 13:36:54 schwarze Exp $
 ************************************************************************
 
 Many issues are annotated for difficulty as follows:
@@ -505,6 +505,15 @@ are mere guesses, and some may be wrong.
   re-reported by tb@ Mon, 16 Mar 2015 16:47:21 +0100
   loc **  exist **  algo **  size *  imp **
 
+- Check for bad line breaks caused by PostScript and PDF using variable-
+  width fonts, for example in .Bl -width "string".  The difficulty line
+  below describes a naive solution by simply scaling up widths internally
+  or adding default spacing (like in terminal output).  If fixes are
+  needed in width measurements, it might be a bit harder, but likely
+  not unreasonably so.
+  reported by Jan Stary 20 May 2024 10:19:01 +0200
+  loc *  exist *  algo **  size *  imp **
+
 --- HTML issues --------------------------------------------------------
 
 - support the idiom .TP .IP .TP for multi-paragraph list item bodies
diff --git a/contrib/mandoc/catman.8 b/contrib/mandoc/catman.8
index 903fa1fa82c9..c0f14872afc6 100644
--- a/contrib/mandoc/catman.8
+++ b/contrib/mandoc/catman.8
@@ -1,6 +1,6 @@
-.\"	$Id: catman.8,v 1.8 2017/03/18 19:56:01 schwarze Exp $
+.\" $Id: catman.8,v 1.15 2025/07/13 14:15:26 schwarze Exp $
 .\"
-.\" Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2017, 2025 Ingo Schwarze <schwarze@openbsd.org>
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
 .\" purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: March 18 2017 $
+.Dd $Mdocdate: July 13 2025 $
 .Dt CATMAN 8
 .Os
 .Sh NAME
@@ -37,9 +37,9 @@ and
 format and formats all of them, storing the formatted versions in
 the same relative paths below
 .Ar dstdir .
-Subdirectories of
+Unless they already exist,
 .Ar dstdir
-are created as needed.
+itself and any required subdirectories are created.
 Existing files are not explicitly deleted, but possibly overwritten.
 .Pp
 The options are as follows:
@@ -71,6 +71,18 @@ output mode, the
 .Cm fragment
 output option is implied.
 Other output options are not supported.
+.It Fl v
+Verbose mode, printing additional information to standard error output.
+Specifying this once prints a summary about the number of files
+and directories processed at the end of the iteration.
+Specifying it twice additionally prints debugging information
+about the backchannel from
+.Xr mandocd 8
+to
+.Nm
+that is used to limit the number of files in flight at any given time.
+For details, see
+.Sx DIAGNOSTICS .
 .El
 .Sh IMPLEMENTATION NOTES
 Since this version avoids
@@ -87,33 +99,209 @@ implementations.
 .Sh EXIT STATUS
 .Ex -std
 .Pp
-Possible errors include:
-.Bl -bullet
-.It
-missing, invalid, or excessive command line arguments
-.It
-failure to change the current working directory to
+Failures while trying to open individual manual pages for reading,
+to save individual formatted files to the file system,
+or even to read or create subdirectories do not cause
+.Nm
+to return an error exit status.
+In such cases,
+.Nm
+simply continues with the next file or subdirectory.
+.Sh DIAGNOSTICS
+Some fatal errors cause
+.Nm
+to exit before the iteration over input files is even started:
+.Bl -tag -width Ds -offset indent
+.It unknown option \-\- Ar option
+An invalid option was passed on the command line.
+.It missing arguments: srcdir and dstdir
+No argument was provided.
+Both
 .Ar srcdir
-.It
-failure to open
+and
 .Ar dstdir
-.It
-communication failure with
+are mandatory.
+.It missing argument: dstdir
+Only one argument was provided.
+The second argument,
+.Ar dstdir ,
+is mandatory, too.
+.It too many arguments: Ar third argument
+Three or more arguments were provided, but only two are supported.
+.It Sy socketpair : Ar reason
+The sockets needed for communication with
+.Xr mandocd 8
+could not be created, for example due to file descriptor or memory exhaustion.
+.It Sy fork : Ar reason
+The new process needed to run
 .Xr mandocd 8
-.It
-resource exhaustion, for example file descriptor, process table,
-or memory exhaustion
+could not be created, for example due to process table exhaustion
+or system resource limits.
+.It Sy exec Ns Po Sy mandocd Pc : Ar reason
+The
+.Xr mandocd 8
+child program could not be started, for example because it is not in the
+.Ev PATH
+or has no execute permission.
+.It Sy mkdir No destination Ar dstdir : reason
+The
+.Ar dstdir
+does not exist and could not be created, for example because
+the parent directory does not exist or permission is denied.
+.It Sy open No destination Ar dstdir : reason
+The
+.Ar dstdir
+could not be opened for reading, for example because
+it is not a directory or permission is denied.
+.It Sy chdir No to source Ar srcdir : reason
+The current working directory could not be changed to
+.Ar srcdir ,
+for example because it does not exist, it is not a directory,
+or permission is denied.
+.It Sy fts_open : Ar reason
+Starting the iteration was attempted but failed,
+for example due to memory exhaustion.
 .El
 .Pp
-Except for memory exhaustion and similar system-level failures,
-failures while trying to open, read, parse, or format individual
-manual pages, to save individual formatted files to the file system,
-or even to create directories do not cause
+Some fatal errors cause the iteration over input files to be aborted
+prematurely:
+.Bl -tag -width Ds -offset indent
+.It FATAL: Sy fts_read : Ar reason
+A call to
+.Xr fts_read 3
+returned
+.Dv NULL ,
+meaning that the iteration failed before being complete.
+.It FATAL: mandocd child died: got Ar SIGNAME
+This message appears if
 .Nm
-to return an error exit status.
-In such cases,
+gets the
+.Dv SIGCHLD
+or
+.Dv SIGPIPE
+signal, most likely due to a fatal bug in
+.Xr mandocd 8 .
+.It FATAL: Sy sendmsg : Ar reason
+The file descriptors needed to process one of the manual pages
+could not be sent to
+.Xr mandocd 8 ,
+for example because
+.Xr mandocd 8
+could not be started or died unexpectedly.
+.It FATAL: Sy recv : Ar reason
+Trying to read a reply message from
+.Xr mandocd 8
+failed, most likely because
+.Xr mandocd 8
+unexpectedly died or closed the socket.
+.It FATAL: signal Ar SIGNAME
+This message appears if
+.Nm
+gets a
+.Dv SIGHUP ,
+.Dv SIGINT ,
+or
+.Dv SIGTERM
+signal, for example because the user deliberately killed it.
+.El
+.Pp
+Some non-fatal errors cause a single subdirectory to be skipped.
+The iteration is not aborted but continues with the next subdirectory,
+and the exit status is unaffected:
+.Bl -tag -width Ds -offset indent
+.It directory Ar subdirectory No unreadable : Ar reason
+A directory below
+.Ar srcdir
+could not be read and is skipped.
+.It directory Ar subdirectory No causes cycle
+A directory below
+.Ar srcdir
+is skipped because it would cause cyclic processing.
+.It Sy mkdirat Ar subdirectory : reason
+A required directory below
+.Ar dstdir
+does not exist and could not be created.
+The corresponding subdirectory below
+.Ar srcdir
+is skipped.
+.El
+.Pp
+Some non-fatal errors cause a single source file to be skipped.
+The iteration is not aborted but continues with the next file,
+and the exit status is unaffected:
+.Bl -tag -width Ds -offset indent
+.It file Ar filename : reason
+The function
+.Xr fts_read 3
+reported a non-fatal error with respect to
+.Ar filename .
+.It file Ar filename : No not a regular file
+For example, it might be a symbolic link or a device file.
+.It Sy open Ar filename No for reading : Ar reason
+A file below
+.Ar srcdir
+could not be read, for example due to permission problems.
+.It Sy openat Ar filename No for writing : Ar reason
+A file below
+.Ar dstdir
+could not be created or truncated, for example due to permission problems.
+.El
+.Pp
+If errors occur, the applicable summary messages appear
+after the end of the iteration:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It skipped Ar number No directories due to errors
+.It skipped Ar number No files due to errors
+.It processing aborted due to fatal error
+.El
+.Pp
+If the
+.Fl v
+flag is specified, the following summary message also appears:
+.Bl -tag -width Ds -offset indent
+.It processed Ar nfiles No files in Ar ndirs No directories
+A file is counted if it could be opened for reading and the
+corresponding output file could be opened for writing;
+this does not necessarily mean that it is a useful manual page.
+A directory is counted if it could be opened for reading and the
+corresponding output directory existed or could be created;
+this does not necessarily mean that any files could be
+processed inside.
+.El
+.Pp
+If the
+.Fl v
+flag is specified twice, the following messages also appear:
+.Bl -tag -width Ds -offset indent
+.It allowing up to Ar number No files in flight
+This is printed at the beginning of the iteration,
+showing the maximum number of files that
+.Nm
+allows to be in flight at any given time.
+.It files in flight: Ar old No \- Ar decrement No = Ar new
+This message is printed when
+.Nm
+learns about
+.Xr mandocd 8
+accepting more than one file at the same time.
+The three numbers printed are the old number of files in flight,
+the amount this number is being reduced, and the resulting
+new number of files in flight.
+.It waiting for Ar number No files in flight
+This message is printed at the end of the iteration, after
+.Nm
+has submitted all files to
+.Xr mandocd 8
+that it intends to.
+THe message informs about the number of files still in flight
+at this point.
+The
 .Nm
-will simply continue with the next file or subdirectory.
+program then waits until
+.Xr mandocd 8
+has accepted them all or until an error occurs.
+.El
 .Sh SEE ALSO
 .Xr mandoc 1 ,
 .Xr mandocd 8
diff --git a/contrib/mandoc/catman.c b/contrib/mandoc/catman.c
index e46613eb0e8c..c9eda18bf71c 100644
--- a/contrib/mandoc/catman.c
+++ b/contrib/mandoc/catman.c
@@ -1,7 +1,7 @@
-/*	$Id: catman.c,v 1.23 2021/10/15 15:04:02 schwarze Exp $ */
+/* $Id: catman.c,v 1.30 2025/07/13 14:15:26 schwarze Exp $ */
 /*
+ * Copyright (c) 2017, 2025 Ingo Schwarze <schwarze@openbsd.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
  * purpose with or without fee is hereby granted, provided that the above
@@ -25,6 +25,7 @@
 #include <sys/socket.h>
 #include <sys/stat.h>
 
+#include <assert.h>
 #if HAVE_ERR
 #include <err.h>
 #endif
@@ -35,26 +36,44 @@
 #else
 #include "compat_fts.h"
 #endif
+#include <signal.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
 
+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];
+	int	 len;
 
-	if (snprintf(sockfdstr, sizeof(sockfdstr), "%d", sockfd) == -1)
+	len = snprintf(sockfdstr, sizeof(sockfdstr), "%d", sockfd);
+	if (len >= (int)sizeof(sockfdstr)) {
+		errno = EOVERFLOW;
+		len = -1;
+	}
+	if (len < 0)
 		err(1, "snprintf");
 	if (defos == NULL)
 		execlp("mandocd", "mandocd", "-T", outtype,
@@ -109,10 +128,11 @@ sock_fd_write(int fd, int fd0, int fd1, int fd2)
 	 * 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)
+	while ((sz = sendmsg(fd, &msg, 0)) == -1) {
+		if (errno != EAGAIN) {
+			warn("FATAL: sendmsg");
 			break;
+		}
 		nanosleep(&timeout, NULL);
 	}
 	return sz;
@@ -125,14 +145,16 @@ process_manpage(int srv_fd, int dstdir_fd, const char *path)
 	int	 irc;
 
 	if ((in_fd = open(path, O_RDONLY)) == -1) {
-		warn("open(%s)", path);
+		warn("open %s for reading", path);
+		fflush(stderr);
 		return 0;
 	}
 
 	if ((out_fd = openat(dstdir_fd, path,
 	    O_WRONLY | O_NOFOLLOW | O_CREAT | O_TRUNC,
 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) {
-		warn("openat(%s)", path);
+		warn("openat %s for writing", path);
+		fflush(stderr);
 		close(in_fd);
 		return 0;
 	}
@@ -142,20 +164,22 @@ process_manpage(int srv_fd, int dstdir_fd, const char *path)
 	close(in_fd);
 	close(out_fd);
 
-	if (irc < 0) {
-		warn("sendmsg");
-		return -1;
-	}
-	return 0;
+	return irc;
 }
 
 int
 process_tree(int srv_fd, int dstdir_fd)
 {
+	const struct timespec timeout = { 0, 10000000 };  /* 0.01 s */
+	const int	 max_inflight = 16;
+
 	FTS		*ftsp;
 	FTSENT		*entry;
 	const char	*argv[2];
 	const char	*path;
+	int		 inflight, irc, decr, fatal;
+	int		 gooddirs, baddirs, goodfiles, badfiles;
+	char		 dummy[1];
 
 	argv[0] = ".";
 	argv[1] = (char *)NULL;
@@ -166,13 +190,59 @@ process_tree(int srv_fd, int dstdir_fd)
 		return -1;
 	}
 
-	while ((entry = fts_read(ftsp)) != NULL) {
+	if (verbose_flag >= 2) {
+		warnx("allowing up to %d files in flight", max_inflight);
+		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;
 		switch (entry->fts_info) {
 		case FTS_F:
-			if (process_manpage(srv_fd, dstdir_fd, path) == -1) {
-				fts_close(ftsp);
-				return -1;
+			switch (process_manpage(srv_fd, dstdir_fd, path)) {
+			case -1:
+				fatal = errno;
+				break;
+			case 0:
+				badfiles++;
+				break;
+			default:
+				goodfiles++;
+				inflight++;
+				break;
 			}
 			break;
 		case FTS_D:
@@ -180,25 +250,96 @@ process_tree(int srv_fd, int dstdir_fd)
 			    mkdirat(dstdir_fd, path, S_IRWXU | S_IRGRP |
 			      S_IXGRP | S_IROTH | S_IXOTH) == -1 &&
 			    errno != EEXIST) {
-				warn("mkdirat(%s)", path);
+				warn("mkdirat %s", path);
+				fflush(stderr);
 				(void)fts_set(ftsp, entry, FTS_SKIP);
-			}
+				baddirs++;
+			} else
+				gooddirs++;
 			break;
 		case FTS_DP:
 			break;
+		case FTS_DNR:
+			warnx("directory %s unreadable: %s",
+			    path, strerror(entry->fts_errno));
+			fflush(stderr);
+			baddirs++;
+			break;
+		case FTS_DC:
+			warnx("directory %s causes cycle", path);
+			fflush(stderr);
+			baddirs++;
+			break;
+		case FTS_ERR:
+		case FTS_NS:
+			warnx("file %s: %s",
+			    path, strerror(entry->fts_errno));
+			fflush(stderr);
+			badfiles++;
+			break;
 		default:
-			warnx("%s: not a regular file", path);
+			warnx("file %s: not a regular file", path);
+			fflush(stderr);
+			badfiles++;
 			break;
 		}
 	}
+	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");
 
 	fts_close(ftsp);
-	return 0;
+	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)
+		warnx("skipped %d %s due to errors", baddirs,
+		    baddirs == 1 ? "directory" : "directories");
+	if (badfiles > 0)
+		warnx("skipped %d %s due to errors", badfiles,
+		    badfiles == 1 ? "file" : "files");
+	if (fatal != 0) {
+		warnx("processing aborted due to fatal error, "
+		    "results are probably incomplete");
+		inflight = -1;
+	}
+	return inflight;
 }
 
 int
 main(int argc, char **argv)
 {
+	struct sigaction sa;
 	const char	*defos, *outtype;
 	int		 srv_fds[2];
 	int		 dstdir_fd;
@@ -207,7 +348,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;
@@ -215,6 +356,9 @@ main(int argc, char **argv)
 		case 'T':
 			outtype = optarg;
 			break;
+		case 'v':
+			verbose_flag += 1;
+			break;
 		default:
 			usage();
 		}
@@ -224,8 +368,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");
@@ -242,11 +414,18 @@ main(int argc, char **argv)
 	}
 	close(srv_fds[1]);
 
-	if ((dstdir_fd = open(argv[1], O_RDONLY | O_DIRECTORY)) == -1)
-		err(1, "open(%s)", argv[1]);
+	if ((dstdir_fd = open(argv[1], O_RDONLY | O_DIRECTORY)) == -1) {
+		if (errno != ENOENT)
+			err(1, "open destination %s", argv[1]);
+		if (mkdir(argv[1], S_IRWXU |
+		    S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) 
+			err(1, "mkdir destination %s", argv[1]);
+		if ((dstdir_fd = open(argv[1], O_RDONLY | O_DIRECTORY)) == -1)
+			err(1, "open destination %s", argv[1]);
+	}
 
 	if (chdir(argv[0]) == -1)
-		err(1, "chdir(%s)", argv[0]);
+		err(1, "chdir to source %s", argv[0]);
 
 	return process_tree(srv_fds[0], dstdir_fd) == -1 ? 1 : 0;
 }
diff --git a/contrib/mandoc/gmdiff b/contrib/mandoc/gmdiff
index 69431f703aaf..54025e4cd450 100644
--- a/contrib/mandoc/gmdiff
+++ b/contrib/mandoc/gmdiff
@@ -45,8 +45,8 @@ while [ -n "$1" ]; do
   file=$1
   shift
   echo " ========== $file ========== "
-  $ROFF -mandoc $file | $COLPIPE 2> /tmp/roff.err > /tmp/roff.out
-  ${MANDOC:=mandoc} $MOPT $file | $COLPIPE \
+  ($ROFF -mandoc $file | $COLPIPE) 2> /tmp/roff.err > /tmp/roff.out
+  (${MANDOC:=mandoc} $MOPT $file | $COLPIPE) \
     2> /tmp/mandoc.err > /tmp/mandoc.out
   for i in roff mandoc; do
     [ -s /tmp/$i.err ] && echo "$i errors:" && cat /tmp/$i.err
diff --git a/contrib/mandoc/man.7 b/contrib/mandoc/man.7
index 4d27c76ba110..91eafbb35f70 100644
--- a/contrib/mandoc/man.7
+++ b/contrib/mandoc/man.7
@@ -1,7 +1,8 @@
-.\" $Id: man.7,v 1.150 2023/10/23 22:57:54 schwarze Exp $
+.\" $Id: man.7,v 1.154 2025/08/05 21:16:20 schwarze Exp $
 .\"
+.\" Copyright (c) 2011-2015, 2017-2020, 2023, 2025
+.\"               Ingo Schwarze <schwarze@openbsd.org>
 .\" Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2011-2015,2017-2020,2023 Ingo Schwarze <schwarze@openbsd.org>
 .\" Copyright (c) 2017 Anthony Bentley <bentley@openbsd.org>
 .\" Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
 .\"
@@ -17,7 +18,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: October 23 2023 $
+.Dd $Mdocdate: August 5 2025 $
 .Dt MAN 7
 .Os
 .Sh NAME
@@ -89,7 +90,7 @@ but can be found in the alphabetical reference below.
 .Ss Page header and footer meta-data
 .Bl -column "RS, RE" description
 .It Ic TH Ta set the title: Ar name section date Op Ar source Op Ar volume
-.It Ic AT Ta display AT&T UNIX version in the page footer (<= 1 argument)
+.It Ic AT Ta display AT&T UNIX version in the page footer (<= 2 arguments)
 .It Ic UC Ta display BSD version in the page footer (<= 1 argument)
 .El
 .Ss Sections and paragraphs
@@ -99,6 +100,7 @@ but can be found in the alphabetical reference below.
 .It Ic PP Ta start an undecorated paragraph (no arguments)
 .It Ic IP Ta indented paragraph: Op Ar head Op Ar width
 .It Ic TP Ta tagged paragraph: Op Ar width
+.It Ic HP Ta hanged paragraph: Op Ar width
 .It Ic PD Ta set vertical paragraph distance: Op Ar height
 .It Ic EX , EE Ta display an example (no arguments)
 .It Ic RS , RE Ta reset the left margin: Op Ar width
@@ -198,11 +200,6 @@ argument is a
 scaling width.
 If specified, it's saved for later paragraph left margins;
 if unspecified, the saved or default width is used.
-.Pp
-This macro is portable, but deprecated
-because it has no good representation in HTML output,
-usually ending up indistinguishable from
-.Ic PP .
 .It Ic I
 Text is rendered in italics.
 .It Ic IB
@@ -239,6 +236,17 @@ A synonym for
 End a mailto block started with
 .Ic MT .
 This is a GNU extension.
+.It Ic MR
+Reference another manual page.
+This is a Plan 9 extension also supported by GNU.
+It has the following syntax:
+.Pp
+.D1 Pf . Ic MR Ar name section Op Ar suffix
+.Pp
+The optional, single
+.Ar suffix
+argument is appended without preceding whitespace
+and typically used for trailing punctuation.
 .It Ic MT
 Begin a mailto block.
 This is a GNU extension.
@@ -250,8 +258,12 @@ link description to be shown
 .Ed
 .It Ic OP
 Optional command-line argument.
-This is a rarely used DWB extension.
-It has the following syntax:
+This is a deprecated GNU extension.
+The name and purpose of the macro match an earlier DWB extension,
+but both the syntax and semantics are incompatible.
+In GNU and
+.Xr mandoc 1 ,
+it has the following syntax:
 .Pp
 .D1 Pf . Ic OP Ar key Op Ar value
 .Pp
@@ -503,43 +515,56 @@ raised.
 .Pp
 The syntax is as follows:
 .Bd -literal -offset indent
-\&.YO \(lBbody...\(rB
-\(lBbody...\(rB
+\&.\e" current-line syntax
+\&.YO \(lBbody ...\(rB
+
+\&.\e" next-line syntax
+\&.YO
+body ...
 .Ed
-.Bl -column "MacroX" "ArgumentsX" "ScopeXXXXX" "CompatX" -offset indent
-.It Em Macro Ta Em Arguments Ta Em Scope     Ta Em Notes
-.It Ic AT  Ta    <=1       Ta    current   Ta    \&
-.It Ic B   Ta    n         Ta    next-line Ta    \&
-.It Ic BI  Ta    n         Ta    current   Ta    \&
-.It Ic BR  Ta    n         Ta    current   Ta    \&
-.It Ic DT  Ta    0         Ta    current   Ta    \&
-.It Ic EE  Ta    0         Ta    current   Ta    Version 9 At
-.It Ic EX  Ta    0         Ta    current   Ta    Version 9 At
-.It Ic I   Ta    n         Ta    next-line Ta    \&
-.It Ic IB  Ta    n         Ta    current   Ta    \&
-.It Ic IR  Ta    n         Ta    current   Ta    \&
-.It Ic OP  Ta    >=1       Ta    current   Ta    DWB
-.It Ic PD  Ta    1         Ta    current   Ta    \&
-.It Ic RB  Ta    n         Ta    current   Ta    \&
-.It Ic RI  Ta    n         Ta    current   Ta    \&
-.It Ic SB  Ta    n         Ta    next-line Ta    \&
-.It Ic SM  Ta    n         Ta    next-line Ta    \&
-.It Ic TH  Ta    >1, <6    Ta    current   Ta    \&
-.It Ic UC  Ta    <=1       Ta    current   Ta    \&
-.It Ic in  Ta    1         Ta    current   Ta    Xr roff 7
+.Bl -column -offset indent\
+      "Macro"     "Arguments"     "curr and next"     "Version 9 AT&T UNIX"
+.It Em Macro Ta Em Arguments Ta Em Line Scope    Ta Em Notes
+.It Ic AT    Ta    0 to 2    Ta    current       Ta    \&
+.It Ic B     Ta    1 or more Ta    curr or next  Ta    \&
+.It Ic BI    Ta    2 or more Ta    current       Ta    \&
+.It Ic BR    Ta    2 or more Ta    current       Ta    \&
+.It Ic DT    Ta    0         Ta    none          Ta    \&
+.It Ic EE    Ta    0         Ta    none          Ta    Version 9 At
+.It Ic EX    Ta    0         Ta    none          Ta    Version 9 At
+.It Ic I     Ta    1 or more Ta    curr or next  Ta    \&
+.It Ic IB    Ta    2 or more Ta    current       Ta    \&
+.It Ic IR    Ta    2 or more Ta    current       Ta    \&
+.It Ic MR    Ta    2 or 3    Ta    current       Ta    Plan 9
+.It Ic OP    Ta    1 or 2    Ta    current       Ta    GNU
+.It Ic PD    Ta    0 or 1    Ta    current       Ta    \&
+.It Ic RB    Ta    2 or more Ta    current       Ta    \&
+.It Ic RI    Ta    2 or more Ta    current       Ta    \&
+.It Ic SB    Ta    1 or more Ta    curr or next  Ta    \&
+.It Ic SM    Ta    1 or more Ta    curr or next  Ta    \&
+.It Ic TH    Ta    3 to 5    Ta    current       Ta    \&
+.It Ic UC    Ta    0 or 1    Ta    current       Ta    \&
+.It Ic in    Ta    0 or 1    Ta    current       Ta    Xr roff 7
 .El
 .Ss Block Macros
 Block macros comprise a head and body.
-As with in-line macros, the head is scoped to the current line and, in
-one circumstance, the next line (the next-line stipulations as in
+As with in-line macros, the head is scoped to the current line or,
+for some macros, to the next line (the next-line stipulations as in
 .Sx Line Macros
 apply here as well).
 .Pp
 The syntax is as follows:
 .Bd -literal -offset indent
-\&.YO \(lBhead...\(rB
-\(lBhead...\(rB
-\(lBbody...\(rB
+\&.\e" current-line syntax
+\&.YO \(lBhead ...\(rB
+body ...
+\&...
+
+\&.\e" next-line syntax
+\&.YO \(lBhead\(rB
+head ...
+body ...
+\&...
 .Ed
 .Pp
 The closure of body scope may be to the section, where a macro is closed
@@ -547,40 +572,42 @@ by
 .Ic SH ;
 sub-section, closed by a section or
 .Ic SS ;
-or paragraph, closed by a section, sub-section,
+paragraph, closed by a section, sub-section,
 .Ic HP ,
 .Ic IP ,
 .Ic LP ,
 .Ic P ,
 .Ic PP ,
-.Ic RE ,
+.Ic RS ,
 .Ic SY ,
+.Ic TP ,
 or
-.Ic TP .
-No closure refers to an explicit block closing macro.
+.Ic TQ ;
+or to an explicit block closing macro.
 .Pp
 As a rule, block macros may not be nested; thus, calling a block macro
 while another block macro scope is open, and the open scope is not
 implicitly closed, is syntactically incorrect.
-.Bl -column "MacroX" "ArgumentsX" "Head ScopeX" "sub-sectionX" "compatX" -offset indent
-.It Em Macro Ta Em Arguments Ta Em Head Scope Ta Em Body Scope  Ta Em Notes
-.It Ic HP  Ta    <2        Ta    current    Ta    paragraph   Ta    \&
-.It Ic IP  Ta    <3        Ta    current    Ta    paragraph   Ta    \&
-.It Ic LP  Ta    0         Ta    current    Ta    paragraph   Ta    \&
-.It Ic ME  Ta    0         Ta    none       Ta    none        Ta    GNU
-.It Ic MT  Ta    1         Ta    current    Ta    to \&ME     Ta    GNU
-.It Ic P   Ta    0         Ta    current    Ta    paragraph   Ta    \&
-.It Ic PP  Ta    0         Ta    current    Ta    paragraph   Ta    \&
-.It Ic RE  Ta    <=1       Ta    current    Ta    none        Ta    \&
-.It Ic RS  Ta    1         Ta    current    Ta    to \&RE     Ta    \&
-.It Ic SH  Ta    >0        Ta    next-line  Ta    section     Ta    \&
-.It Ic SS  Ta    >0        Ta    next-line  Ta    sub-section Ta    \&
-.It Ic SY  Ta    1         Ta    current    Ta    to \&YS     Ta    GNU
-.It Ic TP  Ta    n         Ta    next-line  Ta    paragraph   Ta    \&
-.It Ic TQ  Ta    n         Ta    next-line  Ta    paragraph   Ta    GNU
-.It Ic UE  Ta    0         Ta    current    Ta    none        Ta    GNU
-.It Ic UR  Ta    1         Ta    current    Ta    part        Ta    GNU
-.It Ic YS  Ta    0         Ta    none       Ta    none        Ta    GNU
*** 3592 LINES SKIPPED ***


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69853677.3136f.67cd70e>