[OpenAFS] sprintf -> snprintf...

Russ Allbery rra@stanford.edu
Thu, 26 Jun 2003 11:06:52 -0700


Joshua Johnson <joshua.johnson@ftlsys.com> writes:

> 	A quick look into the systems I have access to shows that snprintf
> 	is stock on:

> 	Solaris >2.6
> 	HPUX 11
> 	SGI Irix
> 	AIX 4.3.3 (with a define)

None of these platforms provide an snprintf with C99 semantics.

> 	Digital UNIX

Has no snprintf at all.

> 	Linux >libc4.5

Only provides C99 semantics with glibc 2.1 and later.

> 	AIX >5.1
> 	BSD >4.4 (*BSD, OS-X, and Darwin are included by default I believe)
> 	Win 95 & NT (_snprintf)

I don't have these platforms to check.

Given the widespread lack of compliance of snprintf, you may want to just
always use your own.  If this is for user-space code, you can use the
attached Autoconf probe to see if the platform has a working snprintf.

I'm not entirely sure where you got your snprintf from; I have another
version with slightly different floating point support (it doesn't use the
native sprintf and is therefore safe, but it doesn't work for floating
point numbers whose integer component won't fit into the largest available
integer type) that's used for INN and wget, among other packages.  Let me
know if you want a copy.

Here's the Autoconf probe:

dnl Source used by INN_FUNC_SNPRINTF.
define([_INN_FUNC_SNPRINTF_SOURCE],
[[#include <stdio.h>
#include <stdarg.h>

char buf[2];

int
test (char *format, ...)
{
  va_list args;
  int count;

  va_start (args, format);
  count = vsnprintf (buf, sizeof buf, format, args);
  va_end (args);
  return count;
}

int
main ()
{
  return ((test ("%s", "abcd") == 4 && buf[0] == 'a' && buf[1] == '\0'
           && snprintf(NULL, 0, "%s", "abcd") == 4) ? 0 : 1);
}]])

dnl Check for a working snprintf.  Some systems have snprintf, but it doesn't
dnl null-terminate if the buffer isn't large enough or it returns -1 if the
dnl string doesn't fit instead of returning the number of characters that
dnl would have been formatted.
AC_DEFUN([INN_FUNC_SNPRINTF],
[AC_CACHE_CHECK(for working snprintf, inn_cv_func_snprintf_works,
[AC_TRY_RUN(_INN_FUNC_SNPRINTF_SOURCE(),
            [inn_cv_func_snprintf_works=yes],
            [inn_cv_func_snprintf_works=no],
            [inn_cv_func_snprintf_works=no])])
if test "$inn_cv_func_snprintf_works" = yes ; then
    AC_DEFINE([HAVE_SNPRINTF], 1,
        [Define if your system has a working snprintf function.])
else
    LIBOBJS="$LIBOBJS snprintf.${ac_objext}"
fi])
INN_FUNC_SNPRINTF

-- 
Russ Allbery (rra@stanford.edu)             <http://www.eyrie.org/~eagle/>