From: Howard Chu Date: Fri, 19 Jul 2002 17:33:14 +0000 (+0000) Subject: Added vsnprintf, snprintf implementations. X-Git-Tag: NO_SLAP_OP_BLOCKS~1357 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=1a8d570c08cd33f74858565f26c4aed8367012f9;p=openldap Added vsnprintf, snprintf implementations. --- diff --git a/libraries/liblutil/utils.c b/libraries/liblutil/utils.c index bd502ba0c0..5024e907ff 100644 --- a/libraries/liblutil/utils.c +++ b/libraries/liblutil/utils.c @@ -44,3 +44,74 @@ int mkstemp( char * template ) #endif } #endif + +#ifndef HAVE_VSNPRINTF +#include +#include +#include + +/* Write at most n characters to the buffer in str, return the + * number of chars written or -1 if the buffer would have been + * overflowed. + * + * This is portable to any POSIX-compliant system. We use pipe() + * to create a valid file descriptor, and then fdopen() it to get + * a valid FILE pointer. The user's buffer and size are assigned + * to the FILE pointer using setvbuf. Then we close the read side + * of the pipe to invalidate the descriptor. + * + * If the write arguments all fit into size n, the write will + * return successfully. If the write is too large, the stdio + * buffer will need to be flushed to the underlying file descriptor. + * The flush will fail because it is attempting to write to a + * broken pipe, and the write will be terminated. + * + * Note: glibc's setvbuf is broken, so this code fails on glibc. + * But that's no loss since glibc provides these functions itself. + * + * In practice, the main app will probably have ignored SIGPIPE + * already, so catching it here is redundant, but harmless. + * + * -- hyc, 2002-07-19 + */ +int vsnprintf( char *str, size_t n, const char *fmt, va_list ap ) +{ + int fds[2], res; + FILE *f; +#ifdef SIGPIPE + RETSIGTYPE (*sig)(); +#endif + + if (pipe( fds )) return -1; + + f = fdopen( fds[1], "w" ); + if ( !f ) { + close( fds[1] ); + close( fds[0] ); + return -1; + } +#ifdef SIGPIPE + sig = SIGNAL( SIGPIPE, SIG_IGN ); +#endif + setvbuf( f, str, _IOFBF, n ); + close( fds[0] ); + + res = vfprintf( f, fmt, ap ); + fclose( f ); +#ifdef SIGPIPE + SIGNAL( SIGPIPE, sig ); +#endif + return res; +} + +int snprintf( char *str, size_t n, const char *fmt, ... ) +{ + va_list ap; + int res; + + va_start( ap, fmt ); + res = vsnprintf( str, n, fmt, ap ); + va_end( ap ); + return res; +} +#endif /* !HAVE_VSNPRINTF */