Print unsent messages of failed sendmmsg syscall

* mmsghdr.c (decode_mmsgvec): Clear syserror for the time of printing
struct mmsghdr array in !use_msg_len case.
(SYS_FUNC(sendmmsg)): As failed sendmmsg syscall does not
set msg_len fields, tell this to decode_mmsgvec.
* tests/mmsg_name.c (test_mmsg_name): Check it.
diff --git a/mmsghdr.c b/mmsghdr.c
index d310a76..93e3889 100644
--- a/mmsghdr.c
+++ b/mmsghdr.c
@@ -172,6 +172,7 @@
 		printfd(tcp, tcp->u_arg[0]);
 		tprints(", ");
 		if (!verbose(tcp)) {
+			/* msgvec */
 			printaddr(tcp->u_arg[1]);
 			/* vlen */
 			tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
@@ -180,8 +181,13 @@
 			return RVAL_DECODED;
 		}
 	} else {
+		const unsigned int msg_len_vlen =
+			syserror(tcp) ? 0 : tcp->u_rval;
+		/* msgvec */
+		temporarily_clear_syserror(tcp);
 		decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_arg[2],
-			       tcp->u_rval, false);
+			       msg_len_vlen, false);
+		restore_cleared_syserror(tcp);
 		/* vlen */
 		tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
 		/* flags */
@@ -199,6 +205,7 @@
 			save_mmsgvec_namelen(tcp, tcp->u_arg[1], tcp->u_arg[2],
 					     sprint_timespec(tcp, tcp->u_arg[4]));
 		} else {
+			/* msgvec */
 			printaddr(tcp->u_arg[1]);
 			/* vlen */
 			tprintf(", %u, ", (unsigned int) tcp->u_arg[2]);
@@ -210,6 +217,7 @@
 		return 0;
 	} else {
 		if (verbose(tcp)) {
+			/* msgvec */
 			decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval,
 				       tcp->u_rval, true);
 			/* vlen */
diff --git a/tests/mmsg_name.c b/tests/mmsg_name.c
index 466b602..f2b624a 100644
--- a/tests/mmsg_name.c
+++ b/tests/mmsg_name.c
@@ -30,6 +30,7 @@
 
 #include "tests.h"
 
+#include <errno.h>
 #include <limits.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -54,15 +55,19 @@
 	const int offsetof_sun_path = offsetof(struct sockaddr_un, sun_path);
 
 	printf("{msg_name=");
-	if (user_msg_namelen < offsetof_sun_path) {
+	if (!un)
+		printf("NULL");
+	else if (user_msg_namelen < offsetof_sun_path) {
 		printf("%p", un);
 	} else {
 		printf("{sa_family=AF_UNIX");
 		if (user_msg_namelen > offsetof_sun_path) {
 			int len = user_msg_namelen < (int) msg->msg_namelen ?
 				  user_msg_namelen : (int) msg->msg_namelen;
-			printf(", sun_path=\"%.*s\"",
-			       len - offsetof_sun_path, un->sun_path);
+			len -= offsetof_sun_path;
+			if (len > (int) sizeof(un->sun_path))
+				len = sizeof(un->sun_path);
+			printf(", sun_path=\"%.*s\"", len, un->sun_path);
 		}
 		printf("}");
 	}
@@ -78,6 +83,8 @@
 static void
 test_mmsg_name(const int send_fd, const int recv_fd)
 {
+	struct sockaddr_un *const send_addr =
+		tail_alloc(sizeof(*send_addr) * IOV_MAX1);
 	char *const send_buf = tail_alloc(sizeof(*send_buf) * IOV_MAX1);
 	struct iovec *const send_iov = tail_alloc(sizeof(*send_iov) * IOV_MAX1);
 	struct mmsghdr *const send_mh = tail_alloc(sizeof(*send_mh) * IOV_MAX1);
@@ -85,6 +92,13 @@
 	int i, rc;
 
 	for (i = 0; i < IOV_MAX1; ++i) {
+		int sun_len = i + 1 > (int) sizeof(send_addr[i].sun_path)
+				    ? (int) sizeof(send_addr[i].sun_path)
+				    : i + 1;
+
+		send_addr[i].sun_family = AF_UNIX;
+		memset(send_addr[i].sun_path, 'a' + i % 26, sun_len);
+
 		send_buf[i] = '0' + i % 10;
 
 		send_iov[i].iov_base = &send_buf[i];
@@ -92,14 +106,57 @@
 
 		send_mh[i].msg_hdr.msg_iov = &send_iov[i];
 		send_mh[i].msg_hdr.msg_iovlen = 1;
-		send_mh[i].msg_hdr.msg_name = 0;
-		send_mh[i].msg_hdr.msg_namelen = 0;
+		send_mh[i].msg_hdr.msg_name = &send_addr[i];
+		send_mh[i].msg_hdr.msg_namelen = i + 1;
 		send_mh[i].msg_hdr.msg_control = 0;
 		send_mh[i].msg_hdr.msg_controllen = 0;
 		send_mh[i].msg_hdr.msg_flags = 0;
 	}
 
 	rc = send_mmsg(send_fd, send_mh, IOV_MAX1, MSG_DONTWAIT);
+	int saved_errno = errno;
+
+	printf("sendmmsg(%d, [", send_fd);
+	for (i = 0; i < IOV_MAX1; ++i) {
+		if (i)
+			printf(", ");
+		if (i >= IOV_MAX
+# ifndef VERBOSE_MMSGHDR
+			|| i >= DEFAULT_STRLEN
+# endif
+		   ) {
+			printf("...");
+			break;
+		}
+		printf("{msg_hdr=");
+		print_msghdr(&send_mh[i].msg_hdr, i + 1);
+		printf("}");
+	}
+	errno = saved_errno;
+	printf("], %u, MSG_DONTWAIT) = %d %s (%m)\n",
+	       IOV_MAX1, rc, errno2name());
+
+	for (i = 0; i < IOV_MAX1; ++i) {
+		send_mh[i].msg_hdr.msg_name = 0;
+		send_mh[i].msg_hdr.msg_namelen = 0;
+	}
+
+	/*
+	 * When recvmmsg is called with a valid descriptor
+	 * but inaccessible memory, it causes segfaults on some architectures.
+	 * As in these cases we test decoding of failed recvmmsg calls,
+	 * it's ok to fail recvmmsg with any reason as long as
+	 * it doesn't read that inaccessible memory.
+	 */
+	rc = send_mmsg(-1, &send_mh[IOV_MAX], 2, MSG_DONTWAIT);
+	saved_errno = errno;
+	printf("sendmmsg(-1, [{msg_hdr=");
+	print_msghdr(&send_mh[IOV_MAX].msg_hdr, 0);
+	errno = saved_errno;
+	printf("}, %p], %u, MSG_DONTWAIT) = %d %s (%m)\n",
+	       &send_mh[IOV_MAX1], 2, rc, errno2name());
+
+	rc = send_mmsg(send_fd, send_mh, IOV_MAX1, MSG_DONTWAIT);
 	if (rc < 0)
 		perror_msg_and_skip("sendmmsg");
 
@@ -115,11 +172,9 @@
 			printf("...");
 			break;
 		}
-		printf("{msg_hdr={msg_name=NULL, msg_namelen=0"
-		       ", msg_iov=[{iov_base=\"%c\", iov_len=1}]"
-		       ", msg_iovlen=1, msg_controllen=0, msg_flags=0}%s}",
-		       '0' + i % 10,
-		       i < rc ? ", msg_len=1" : "");
+		printf("{msg_hdr=");
+		print_msghdr(&send_mh[i].msg_hdr, 0);
+		printf("%s}", i < rc ? ", msg_len=1" : "");
 	}
 	printf("], %u, MSG_DONTWAIT) = %d\n", IOV_MAX1, rc);