Subject: Re: syslog_r (Re: CVS commit: src/lib/libc)
To: Christos Zoulas <christos@astron.com>
From: Jason Thorpe <thorpej@shagadelic.org>
List: tech-userlevel
Date: 10/27/2006 08:45:47
On Oct 26, 2006, at 12:18 PM, Christos Zoulas wrote:

> So it is really trivial to make syslog_r async-signal-safe in our  
> case.

Please, no, because it makes syslog_r(3) lack functionality that syslog 
(3) has.

If we REALLY want this logging nonsense in libssp, then write a NEW  
LIBRARY CALL that takes only constant strings or something.

(Personally, I think the best thing for such programs is to simply  
abort(3) rather than spew messages into the system log.)

>
> First we add a flag in stdio.h:
> Index: stdio.h
> ===================================================================
> RCS file: /cvsroot/src/include/stdio.h,v
> retrieving revision 1.64
> diff -u -u -r1.64 stdio.h
> --- stdio.h	10 May 2006 21:09:45 -0000	1.64
> +++ stdio.h	26 Oct 2006 19:13:57 -0000
> @@ -157,6 +157,7 @@
>  #define	__SOFF	0x1000		/* set iff _offset is in fact correct */
>  #define	__SMOD	0x2000		/* true => fgetln modified _p text */
>  #define	__SALC	0x4000		/* allocate string space dynamically */
> +#define	__SAFE	0x8000		/* don't call signal-unsafe functions */
>
>  /*
>   * The following three definitions are for ANSI C, which took them
>
> Then we use it to avoid calling non-signal-safe functions in vfprintf 
> ():
> Index: vfprintf.c
> ===================================================================
> RCS file: /cvsroot/src/lib/libc/stdio/vfprintf.c,v
> retrieving revision 1.50
> diff -u -b -w -u -r1.50 vfprintf.c
> --- vfprintf.c	16 Feb 2006 23:26:19 -0000	1.50
> +++ vfprintf.c	26 Oct 2006 19:10:23 -0000
> @@ -335,6 +335,10 @@
>  	 */
>  	for (;;) {
>  		cp = fmt;
> +		if (fp->_flags & __SAFE) {
> +			for (; *fmt &&*fmt != '%'; fmt++)
> +				continue;
> +		} else {
>  		while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
>  			fmt += n;
>  			if (wc == '%') {
> @@ -342,6 +346,7 @@
>  				break;
>  			}
>  		}
> +		}
>  		if ((m = fmt - cp) != 0) {
>  			PRINT(cp, m);
>  			ret += m;
> @@ -493,7 +498,7 @@
>  				size = 3;
>  				break;
>  			}
> -			if (isnan(_double)) {
> +			if ((fp->_flags & __SAFE) || isnan(_double)) {
>  				if (ch == 'E' || ch == 'F' || ch == 'G')
>  					cp = "NAN";
>  				else
>
> Finally we provide a snprintf_r() and a vsnprintf_r() [call them  
> what you
> wish] wrappers that look like the nor _r functions, but they only do:
>
> 	fp->_flags |= __SAFE;
>
> Then we can use them in syslog_r(), and everything works as expected.
> Well, floating point numbers print NaN, but...
>
> Opinions?
>
> christos

-- thorpej