Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 May 2018 16:43:06 +0300
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        Dimitry Andric <dim@FreeBSD.org>
Cc:        Thomas Munro <munro@ip9.org>, freebsd-hackers@freebsd.org
Subject:   Re: printf("%m") doesn't generate a warning -- shouldn't it?
Message-ID:  <20180521134306.GT6887@kib.kiev.ua>
In-Reply-To: <BAD690AA-C51A-4125-8F23-B637758C8EB6@FreeBSD.org>
References:  <CADLWmXU__ZRaS=gg_Y18WYbJJgk2Rs065RhkYmAZCFY8mp1Wjg@mail.gmail.com> <BAD690AA-C51A-4125-8F23-B637758C8EB6@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, May 21, 2018 at 01:19:01PM +0200, Dimitry Andric wrote:
> On 21 May 2018, at 04:38, Thomas Munro <munro@ip9.org> wrote:
> > 
> > As discussed on the PostgreSQL[1] and NetBSD mailing lists[2][3],
> > syslog-like printf("%m") is a GNU extension that doesn't generate a
> > warning from Clang or GCC on other operating systems even though when
> > it doesn't actually work.  That's because the __printf__ attribute
> > that our __printflike macro in /usr/include/stdio.h expands to
> > effectively means "like printf in glibc, allowing %m", not like POSIX
> > or our actual libc which just prints out "m" when it sees it.
> > 
> > It'd sure be nice to get a compiler warning on FreeBSD when porting
> > software that uses that if it doesn't actually work (or ... to support
> > it).
> 
> Please submit upstream bug(s) for clang and gcc.  It turns out clang has
> a -Wformat-non-iso warning flag which should warn about this, but I
> can't get it to emit it:
> 
> $ cat printf-m.c
> #include <stdio.h>
> 
> int main(void)
> {
>         printf("error: %m\n");
>         return 0;
> }
> 
> $ clang -std=c99 -Wformat-non-iso -c printf-m.c
> <nothing>

Why not add %m instead ?  It is very easy and several people did it in
round-about ways.

diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
index 29fbd95b399..70f5074e2f7 100644
--- a/lib/libc/stdio/vfprintf.c
+++ b/lib/libc/stdio/vfprintf.c
@@ -317,6 +317,7 @@ __vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap)
 	int ret;		/* return value accumulator */
 	int width;		/* width from format (%8d), or 0 */
 	int prec;		/* precision from format; <0 for N/A */
+	int saved_errno;
 	char sign;		/* sign prefix (' ', '+', '-', or \0) */
 	struct grouping_state gs; /* thousands' grouping info */
 
@@ -466,6 +467,7 @@ __vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap)
 	savserr = fp->_flags & __SERR;
 	fp->_flags &= ~__SERR;
 
+	saved_errno = errno;
 	convbuf = NULL;
 	fmt = (char *)fmt0;
 	argtable = NULL;
@@ -776,6 +778,11 @@ reswitch:	switch (ch) {
 			}
 			break;
 #endif /* !NO_FLOATING_POINT */
+		case 'm':
+			cp = strerror(saved_errno);
+			size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
+			sign = '\0';
+			break;
 		case 'n':
 			/*
 			 * Assignment-like behavior is specified if the



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20180521134306.GT6887>