cleanup va_start/va_end and introduce vasprintf (#826)

* refactor: cleanup va_start/va_end

- Missing va_end statements;
- Incorrect va_copy ordering in BFR_VSNPRINTF;
- Sanitize snprintf results or ensure buffer is initially \0'd.

* refactor: introduce vasprintf

Replace dynamic format string allocation (i.e., incrementing a buffer by
a fixed amount until vsnprintf returns success) with vasprintf.
Polyfill'ing for builds that do not include the GNU extension.
This commit is contained in:
gottfriedleibniz
2026-04-30 16:44:49 -03:00
committed by GitHub
parent 9617672195
commit 3d239d3db5
20 changed files with 247 additions and 250 deletions
+4 -2
View File
@@ -7208,6 +7208,7 @@ DLL_EXPORT void cckd_print_itrace()
/*-------------------------------------------------------------------*/
void cckd_trace( const char* func, int line, DEVBLK* dev, char* fmt, ... )
{
int rc;
va_list vl;
char trcmsg[ CCKD_TRACE_SIZE ];
@@ -7217,9 +7218,10 @@ void cckd_trace( const char* func, int line, DEVBLK* dev, char* fmt, ... )
/* Build the cckd trace message */
va_start( vl, fmt );
if (vsnprintf( trcmsg, sizeof( trcmsg ), fmt, vl ) < 0)
return;
rc = vsnprintf( trcmsg, sizeof( trcmsg ), fmt, vl );
va_end( vl );
if (rc < 0)
return;
/* Add the message to our internal trace table (if we have one) */
OBTAIN_TRACE_LOCK();
Vendored
+13
View File
@@ -17526,6 +17526,19 @@ fi
done
for ac_func in vasprintf
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
for ac_func in vsscanf
do :
ac_fn_c_check_func "$LINENO" "vsscanf" "ac_cv_func_vsscanf"
+1
View File
@@ -1172,6 +1172,7 @@ AC_CHECK_FUNCS( pvalloc )
AC_CHECK_FUNCS( valloc )
AC_CHECK_FUNCS( posix_memalign )
AC_CHECK_FUNCS( vasprintf )
AC_CHECK_FUNCS( vsscanf,
[hc_cv_have_vsscanf=yes],
[hc_cv_have_vsscanf=no] )
+14 -18
View File
@@ -95,28 +95,24 @@ static int syntax( const char* pgm, const char* msgfmt, ... )
if (msgfmt)
{
const int chunksize = 128;
int rc = -1;
int buffsize = 0;
char* msgbuf = NULL;
va_list vargs;
int rc;
char* msgbuf = NULL;
do
va_start( vargs, msgfmt );
rc = vasprintf( &msgbuf, msgfmt, vargs );
va_end( vargs );
if (rc >= 0)
{
if (msgbuf) free( msgbuf );
if (!(msgbuf = calloc( 1, buffsize += chunksize )))
BREAK_INTO_DEBUGGER();
va_end( vargs );
va_start( vargs, msgfmt );
rc = vsnprintf( msgbuf, buffsize, msgfmt, vargs );
// "Syntax error: %s"
FWRMSG( stderr, HHC02959, "E", msgbuf );
free( msgbuf );
}
else
{
BREAK_INTO_DEBUGGER();
}
while (rc < 0 || rc >= buffsize);
// "Syntax error: %s"
FWRMSG( stderr, HHC02959, "E", msgbuf );
free( msgbuf );
}
// "Usage: %s [-r] [-c] [-q] [-v] infile outfile"
+14 -18
View File
@@ -623,28 +623,24 @@ int syntax( const char* pgm, const char* msgfmt, ... )
/* Show them their syntax error... */
if (msgfmt)
{
const int chunksize = 128;
int rc = -1;
int buffsize = 0;
char* msgbuf = NULL;
va_list vargs;
int rc;
char* msgbuf = NULL;
do
va_start( vargs, msgfmt );
rc = vasprintf( &msgbuf, msgfmt, vargs );
va_end( vargs );
if (rc >= 0)
{
if (msgbuf) free( msgbuf );
if (!(msgbuf = malloc( buffsize += chunksize )))
BREAK_INTO_DEBUGGER();
va_end( vargs );
va_start( vargs, msgfmt );
rc = vsnprintf( msgbuf, buffsize, msgfmt, vargs );
// "Syntax error: %s"
FWRMSG( stderr, HHC02594, "E", msgbuf );
free( msgbuf );
}
else
{
BREAK_INTO_DEBUGGER();
}
while (rc < 0 || rc >= buffsize);
// "Syntax error: %s"
FWRMSG( stderr, HHC02594, "E", msgbuf );
free( msgbuf );
}
#ifdef CCKD_COMPRESS_ZLIB
+14 -18
View File
@@ -662,28 +662,24 @@ int syntax( const char* pgm, const char* msgfmt, ... )
/* Show them their syntax error... */
if (msgfmt)
{
const int chunksize = 128;
int rc = -1;
int buffsize = 0;
char* msgbuf = NULL;
va_list vargs;
int rc;
char* msgbuf = NULL;
do
va_start( vargs, msgfmt );
rc = vasprintf( &msgbuf, msgfmt, vargs );
va_end( vargs );
if (rc >= 0)
{
if (msgbuf) free( msgbuf );
if (!(msgbuf = malloc( buffsize += chunksize )))
BREAK_INTO_DEBUGGER();
va_end( vargs );
va_start( vargs, msgfmt );
rc = vsnprintf( msgbuf, buffsize, msgfmt, vargs );
// "Syntax error: %s"
FWRMSG( stderr, HHC02594, "E", msgbuf );
free( msgbuf );
}
else
{
BREAK_INTO_DEBUGGER();
}
while (rc < 0 || rc >= buffsize);
// "Syntax error: %s"
FWRMSG( stderr, HHC02594, "E", msgbuf );
free( msgbuf );
}
#ifdef CCKD_COMPRESS_ZLIB
+1
View File
@@ -168,6 +168,7 @@ va_list vl;
{
va_start(vl, msg);
vprintf (msg, vl);
va_end(vl);
}
} /* end function info_msg */
+21 -15
View File
@@ -80,34 +80,40 @@ static int cchh_colhdr_width;
static void prtcchhseg( const char* fmt, ... )
{
va_list vl;
va_start( vl, fmt );
vsnprintf( segbuf, sizeof( segbuf ), fmt, vl );
lcchhtab = realloc( lcchhtab, (numcchh + 1) * sizeof( char* ));
lcchhtab[ numcchh++ ] = strdup( segbuf );
if (vsnprintf( segbuf, sizeof( segbuf ), fmt, vl ) >= 0)
{
lcchhtab = realloc( lcchhtab, (numcchh + 1) * sizeof( char* ));
lcchhtab[ numcchh++ ] = strdup( segbuf );
}
va_end( vl );
}
static void prtseg( const char* fmt, ... )
{
va_list vl;
va_start( vl, fmt );
vsnprintf( segbuf, sizeof( segbuf ), fmt, vl );
lsegstab = realloc( lsegstab, (numsegs + 1) * sizeof( char* ));
lsegstab[ numsegs++ ] = strdup( segbuf );
if (vsnprintf( segbuf, sizeof( segbuf ), fmt, vl ) >= 0)
{
lsegstab = realloc( lsegstab, (numsegs + 1) * sizeof( char* ));
lsegstab[ numsegs++ ] = strdup( segbuf );
}
va_end( vl );
}
static void prtline( const char* fmt, ... )
{
va_list vl;
va_start( vl, fmt );
vsnprintf( linebuf, sizeof( linebuf ), fmt, vl );
linestab = realloc( linestab, (numlines + 1) * sizeof( char* ));
linestab[ numlines++ ] = strdup( linebuf );
if (vsnprintf( linebuf, sizeof( linebuf ), fmt, vl ) >= 0)
{
linestab = realloc( linestab, (numlines + 1) * sizeof( char* ));
linestab[ numlines++ ] = strdup( linebuf );
}
va_end( vl );
}
static void print_line_from_segs()
+25 -25
View File
@@ -191,36 +191,36 @@
static inline void DebuggerTrace( char* fmt, ...)
{
const int chunksize = 512;
int buffsize = 0;
char* buffer = NULL;
int rc = -1;
va_list args;
va_list vl;
int expectedLen, actualLen;
size_t bufCount;
char *buf = NULL;
va_start( args, fmt );
do
va_start( vl, fmt );
expectedLen = _vscprintf( fmt , vl );
va_end( vl );
if (expectedLen < 0)
{
if (buffer)
free( buffer );
buffsize += chunksize;
buffer = malloc( buffsize + 1 );
if (!buffer)
BREAK_INTO_DEBUGGER();
rc = _vsnprintf_s( buffer, buffsize+1, buffsize, fmt, args);
DebuggerTrace_Fail:
BREAK_INTO_DEBUGGER();
if (buf != NULL)
free(buf);
return;
}
while (rc < 0 || rc >= buffsize);
bufCount = ((size_t)expectedLen) + 1;
if ((buf = (char *)malloc( bufCount )) == NULL)
goto DebuggerTrace_Fail;
va_start( vl, fmt );
actualLen = _vsnprintf_s( buf, bufCount, _TRUNCATE, fmt, vl );
va_end( vl );
if (actualLen < 0)
goto DebuggerTrace_Fail;
/* Write to debugger pane */
OutputDebugStringA( buffer );
if (buffer)
free( buffer );
va_end( args );
OutputDebugStringA( buf );
free( buf );
}
#endif // _ENABLE_TRACING_STMTS_DEBUGGERTRACE_DEFINED
+6 -2
View File
@@ -145,10 +145,13 @@ static int rx_sprintf( PRXSTRING prx, const char* fmt, ... )
static const HR_MEMSIZE_T maxlen = (64 * 1024); // (64K)
len = 0;
va_start( vargs, fmt );
if (RXVALIDSTRING( *prx ))
{
va_start( vargs, fmt );
len = vsnprintf( prx->strptr, prx->strlength, fmt, vargs );
va_end( vargs );
}
/* PROGRAMMING NOTE: we use '>=' comparison to ensure there
will always be room for a terminating NULL, even though
@@ -171,7 +174,9 @@ static int rx_sprintf( PRXSTRING prx, const char* fmt, ... )
break;
}
va_start( vargs, fmt );
len = vsnprintf( prx->strptr, prx->strlength, fmt, vargs );
va_end( vargs );
}
while (len >= prx->strlength && prx->strlength < maxlen);
@@ -179,7 +184,6 @@ static int rx_sprintf( PRXSTRING prx, const char* fmt, ... )
len = maxlen; // (then set final len to the maximum)
}
va_end( vargs );
prx->strlength = len;
return len;
}
+1 -1
View File
@@ -1999,7 +1999,7 @@ static void dumpdata( char *label, BYTE *data, int len )
static void debug_pf( const char* __fmt, ... )
{
#if _ENABLE_TRACING_STMTS_IMPL
char write_buf[2000]; /* big enough for an IP packet */
char write_buf[2000] = ""; /* big enough for an IP packet */
int writebuf_len;
va_list arglist;
+71 -54
View File
@@ -251,6 +251,57 @@ strlcat(char *dst, const char *src, size_t siz)
}
#endif // !defined(HAVE_STRLCAT)
#if !defined( HAVE_VASPRINTF )
DLL_EXPORT int
vasprintf(char **strp, const char *fmt, va_list ap)
{
va_list vcopy;
int expectedLen, actualLen;
size_t bufCount;
char *buf;
va_copy( vcopy, ap );
#if defined(_MSVC_) /* See w32_vsnprintf documentation */
expectedLen = _vscprintf( fmt, vcopy );
#else
expectedLen = vsnprintf( NULL, 0, fmt, vcopy );
#endif
va_end(vcopy);
if (expectedLen < 0)
{
*strp = NULL;
return -1;
}
bufCount = ((size_t)expectedLen) + 1;
if ((buf = (char *)malloc( bufCount )) == NULL)
{
*strp = NULL;
errno = ENOMEM;
return -1;
}
#if defined(_MSVC_)
actualLen = _vsnprintf_s( buf, bufCount, bufCount - 1, fmt, ap );
#else
actualLen = vsprintf( buf, fmt, ap );
#endif
if (actualLen != expectedLen)
{
free(buf);
*strp = NULL;
errno = EINVAL;
return -1;
}
*strp = buf;
return expectedLen;
}
#endif // !defined(HAVE_VASPRINTF)
/* The following structures are defined herein because they are private structures */
/* that MUST be opaque to the outside world */
typedef struct _SYMBOL_TOKEN
@@ -1031,6 +1082,7 @@ DLL_EXPORT int hopen( const char* path, int oflag, ... )
va_list vargs;
va_start( vargs, oflag );
pmode = va_arg( vargs, int );
va_end( vargs );
}
return open( path, oflag, pmode );
}
@@ -1088,29 +1140,19 @@ DLL_EXPORT int hwrite(int s,const char *bfr,size_t sz)
DLL_EXPORT int hprintf(int s,char *fmt,...)
{
char *bfr;
size_t bsize=1024;
int rc;
va_list vl;
int rc;
char *bfr = NULL;
bfr=malloc(bsize);
while(1)
va_start( vl, fmt );
rc = vasprintf( &bfr, fmt, vl );
va_end( vl );
if (rc < 0)
{
if(!bfr)
{
return -1;
}
va_start(vl,fmt);
rc=vsnprintf(bfr,bsize,fmt,vl);
va_end(vl);
if(rc<(int)bsize)
{
break;
}
bsize+=1024;
bfr=realloc(bfr,bsize);
return -1;
}
rc=hwrite(s,bfr,strlen(bfr));
rc = hwrite(s, bfr, rc + 1);
free(bfr);
return rc;
}
@@ -2019,6 +2061,7 @@ DLL_EXPORT int idx_snprintf( int idx, char* buffer, size_t bufsiz, const char*
va_start( vargs, fmt );
rc = vsnprintf( buffer+idx, bufsiz-idx, fmt, vargs );
va_end( vargs );
return rc;
}
@@ -2734,48 +2777,22 @@ DLL_EXPORT void send2gui( const char* pszFormat, ... )
{
if (extgui)
{
va_list vl, original_vl;
int size = 1024;
int rc = -1;
va_list vl;
int rc;
char* msg = NULL;
// CRASH if invalid function arguments or Out of Memory
if (0
|| !pszFormat
|| !(msg = malloc( size ))
)
CRASH();
// Format the message...
va_start( vl, pszFormat );
va_copy( original_vl, vl );
while( rc < 0 )
{
va_start( vl, pszFormat );
rc = vsnprintf( msg, size, pszFormat, vl );
if (0
|| (rc > 0 && rc < size) // success
|| (size >= 4096) // too big
)
break;
if (!(msg = realloc( msg, size += 1024 )))
CRASH(); // (Out of Memory)
va_copy( vl, original_vl );
}
rc = vasprintf( &msg, pszFormat, vl );
va_end( vl );
// CRASH if invalid function arguments or Out of Memory
// CRASH if unable to successfully format a message
if (0
|| rc <= 0
|| rc >= size
)
if (rc < 0)
{
CRASH(); // (WTF?!)
return;
}
// Send the message to HercGUI...
+18
View File
@@ -146,6 +146,24 @@ HUT_DLL_IMPORT size_t
strlcat(char *dst, const char *src, size_t siz);
#endif
#if !defined( HAVE_VASPRINTF )
/*
* The functions asprintf() and vasprintf() are analogs of sprintf(3) and
* vsprintf(3), except that they allocate a string large enough to hold the
* output including the terminating null byte, and return a pointer to it via
* the first argument. This pointer should be passed to free(3) to release the
* allocated storage when it is no longer needed.
*
* When successful, these functions return the number of bytes printed, just
* like sprintf(3). On error, -1 is returned, errno is set to indicate the
* error, and the contents of strp are undefined.
*/
HUT_DLL_IMPORT int
vasprintf(char **strp, const char *fmt, va_list ap) ATTR_PRINTF(2,0);
#endif // !defined(HAVE_VASPRINTF)
/* The following helper macros can be used in place of direct calls
* to either the strlcpy or strlcat functions ONLY when the destination
* buffer is an array. They must NEVER be used whenever the destination
+7 -76
View File
@@ -13,74 +13,6 @@
#include "hercules.h"
/*-------------------------------------------------------------------*/
/* Helper macro "BFR_VSNPRINTF" */
/*-------------------------------------------------------------------*/
/* Original design by Fish */
/* Modified by Jay Maynard */
/* Further modification by Ivan Warren */
/* */
/* Purpose: */
/* */
/* set 'bfr' to contain a C string based on a message format */
/* and va_list of args. NOTE: 'bfr' must be free()d when done. */
/* */
/* Local variables referenced: */
/* */
/* char* bfr; must be originally defined */
/* int siz; must be defined and contain a start size */
/* va_list vl; must be defined and initialised with va_start */
/* char* fmt; is the message format */
/* int rc; will contain final size */
/* */
/*-------------------------------------------------------------------*/
#define BFR_CHUNKSIZE (256)
#define BFR_VSNPRINTF() \
\
do \
{ \
va_list original_vl; \
va_copy( original_vl, vl ); \
\
bfr = (char*) calloc( 1, siz ); \
rc = -1; \
\
while (bfr && rc < 0) \
{ \
rc = vsnprintf( bfr, siz, fmt, vl ); \
\
if (rc >= 0 && rc < siz) \
break; \
\
rc = -1; \
siz += BFR_CHUNKSIZE; \
\
if (siz > 65536) \
break; \
\
bfr = realloc( bfr, siz ); \
va_copy( vl, original_vl ); \
} \
\
if (bfr && strlen( bfr ) == 0 && strlen( fmt) != 0) \
{ \
free( bfr ); \
bfr = strdup( fmt ); \
} \
else \
{ \
if (bfr) \
{ \
char* p = strdup( bfr ); \
free( bfr ); \
bfr = p; \
} \
} \
} \
while (0)
/*-------------------------------------------------------------------*/
/* panel_command message capturing structs and vars */
/*-------------------------------------------------------------------*/
@@ -382,7 +314,6 @@ static void vfwritemsg( BYTE panel, FILE* f,
char prefix[ 32 ] = {0};
char* bfr = NULL;
int rc = 1;
int siz = 1024;
char* msgbuf;
size_t msglen, bufsiz;
@@ -391,12 +322,11 @@ static void vfwritemsg( BYTE panel, FILE* f,
#endif
// Format just the message part, without the filename and line number
BFR_VSNPRINTF(); // Note: uses 'vl', 'bfr', 'siz', 'fmt' and 'rc'.
if (!bfr) // If BFR_VSNPRINTF runs out of memory,
rc = vasprintf( &bfr, fmt, vl );
if (rc < 0) // If vasprintf runs out of memory,
return; // then there's nothing more we can do.
bufsiz = msglen = strlen( bfr ) + 2;
bufsiz = msglen = ((size_t)rc) + 2;
// Prefix message with filename and line number, if requested
@@ -482,14 +412,13 @@ static void vflogmsg( BYTE panel, FILE* f, const char* fmt, va_list vl )
{
char *bfr = NULL;
int rc;
int siz = 1024;
#ifdef NEED_LOGMSG_FFLUSH
fflush(f);
#endif
BFR_VSNPRINTF(); // Note: uses 'vl', 'bfr', 'siz', 'fmt' and 'rc'.
if (!bfr) // If BFR_VSNPRINTF runs out of memory,
rc = vasprintf( &bfr, fmt, vl );
if (rc < 0) // If vasprintf runs out of memory,
return; // then there's nothing more we can do.
flog_write( panel, f, bfr );
@@ -517,6 +446,7 @@ DLL_EXPORT void fwritemsg( const char* filename, int line, const char* func,
va_list vl;
va_start( vl, fmt );
vfwritemsg( panel, f, filename, line, func, fmt, vl );
va_end( vl );
}
DLL_EXPORT void logmsg( const char* fmt, ... )
@@ -524,4 +454,5 @@ DLL_EXPORT void logmsg( const char* fmt, ... )
va_list vl;
va_start( vl, fmt );
vflogmsg( WRMSG_NORMAL, stdout, fmt, vl );
va_end( vl );
}
+6 -4
View File
@@ -174,14 +174,15 @@ static void dbgtrc( const char* file, int line, const char* func,
OSA_GRP* grp = devgrp->grp_data;
if (grp && grp->debugmask)
{
char buf[256];
char buf[256] = "";
va_list vargs;
va_start( vargs, fmt );
vsnprintf( buf, sizeof(buf), fmt, vargs );
va_end( vargs );
// HHC03991D "%1d:%04X %s: %s"
fwritemsg( file, line, func, WRMSG_NORMAL, stdout,
"HHC03991D " HHC03991 "\n", LCSS_DEVNUM, dev->typname, buf );
va_end( vargs );
}
}
}
@@ -205,14 +206,15 @@ static void dbgupd( const char* file, int line, const char* func,
OSA_GRP* grp = devgrp->grp_data;
if (grp && (grp->debugmask & DBGQETHUPDOWN))
{
char buf[256];
char buf[256] = "";
va_list vargs;
va_start( vargs, fmt );
vsnprintf( buf, sizeof(buf), fmt, vargs );
va_end( vargs );
// HHC03991D "%1d:%04X %s: %s"
fwritemsg( file, line, func, WRMSG_NORMAL, stdout,
"HHC03991D " HHC03991 "\n", LCSS_DEVNUM, dev->typname, buf );
va_end( vargs );
if (what == 3) {
mpc_display_osa_iear( dev, adr, dir, len );
} else if (what == 2) {
+2
View File
@@ -2786,6 +2786,7 @@ static void shrdtrc( DEVBLK* dev, const char* fmt, ... )
va_start( vl, fmt );
vsnprintf( (char*) tracemsg + strlen( tracemsg ),
sizeof( tracemsg ) - strlen( tracemsg ), fmt, vl );
va_end( vl );
/* Log the trace message directly to the panel (WITHOUT the
timestamp prefix) if the device is being traced/stepped. */
@@ -2828,6 +2829,7 @@ static void shrdgentrc( const char* fmt, ... )
va_start( vl, fmt );
vsnprintf( (char*) tracemsg + strlen( tracemsg ),
sizeof( tracemsg ) - strlen( tracemsg ), fmt, vl );
va_end( vl );
/* Copy the trace message into the trace table (if it exists) */
shrdtrclog_locked( tracemsg );
+1 -1
View File
@@ -3266,7 +3266,7 @@ static void print_args( int argc, char* argv[] )
// into a buffer and then do one printf of that buffer since we do
// not know how big that buffer should be. Some arguments could be
// quite long! (Yeah, yeah, we COULD use malloc/realloc much like
// BFR_VSNPRINTF does, but that would be overkill IMHO).
// vasprintf does, but that would be overkill IMHO).
// HHC03217 "Args: %s"
printf( "HHC03217I Args:" );
+1 -1
View File
@@ -50,7 +50,7 @@ static void print_args( int argc, char* argv[] )
// into a buffer and then do one printf of that buffer since we do
// not know how big that buffer should be. Some arguments could be
// quite long! (Yeah, yeah, we COULD use malloc/realloc much like
// BFR_VSNPRINTF does, but that would be overkill IMHO).
// vasprintf does, but that would be overkill IMHO).
// HHC03217 "Args: %s"
printf( "HHC03217I Args:" );
+1
View File
@@ -753,6 +753,7 @@ int w32_ioctl_tape ( ufd_t ufd, int request, ... )
va_start ( vl, request );
ptr = va_arg( vl, void* );
va_end( vl );
if ( !ptr )
{
+26 -15
View File
@@ -3929,10 +3929,19 @@ DLL_EXPORT size_t w32_fwrite ( const void* buff, size_t size, size_t count, FILE
// the number of bytes (excluding the terminating null byte) that would
// be written had count been sufficiently large, 2) ALWAYS appending a
// terminating null byte REGARDLESS of whether count is large enough.
//
// With older MSVC versions, passing a NULL buffer with a zero count to
// vsnprintf were considered invalid and invoked the error handler or returned
// -1. C99 and POSIX explicitly define this behavior so the function is updated
// to match.
//
// Since this is MSVC-only we are also ignoring va_copy.
DLL_EXPORT int w32_vsnprintf( char* bfr, size_t cnt, const char* fmt, va_list vargs )
{
int rc = _vsnprintf_s( bfr, cnt, _TRUNCATE, fmt, vargs );
int rc = -1;
if (bfr != NULL) // ASSERT( cnt > 0 );
rc = _vsnprintf_s( bfr, cnt, _TRUNCATE, fmt, vargs );
if (rc < 0)
rc = _vscprintf( fmt, vargs );
return rc;
@@ -3964,34 +3973,35 @@ DLL_EXPORT int w32_snprintf( char* bfr, size_t cnt, const char* fmt, ... )
DLL_EXPORT int w32_fprintf( FILE* stream, const char* format, ... )
{
char* buff = NULL;
int bytes = 0, rc;
int bytes, rc;
va_list vl;
SOCKET sock;
ASSERT( stream && format );
va_start( vl, format );
{
int sd = fileno( stream );
if ( !socket_is_socket( sd ) )
return vfprintf( stream, format, vl );
{
va_start( vl, format );
rc = vfprintf( stream, format, vl );
va_end( vl );
return rc;
}
sock = (SOCKET) _get_osfhandle( sd );
}
do
va_start( vl, format );
bytes = vasprintf( &buff, format, vl );
va_end( vl );
if (bytes < 0)
{
free( buff );
if ( !( buff = malloc( bytes += 1000 ) ) )
{
errno = ENOMEM;
return -1;
}
errno = ENOMEM;
return -1;
}
while ( ( rc = vsnprintf( buff, bytes, format, vl ) ) < 0 );
rc = send( sock, buff, bytes = rc, 0 );
rc = send( sock, buff, bytes + 1, 0 );
free( buff );
@@ -4904,6 +4914,7 @@ DLL_EXPORT int w32_hopen( const char* path, int oflag, ... )
va_list vargs;
va_start( vargs, oflag );
pmode = va_arg( vargs, int );
va_end( vargs );
}
err = _sopen_s( &fh, path, oflag, sh_flg, pmode );