mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Fix varargs usage in logvprintf.
Published in <sxs667knbe1.fsf@florida.arsdigita.de>.
This commit is contained in:
parent
fcf68c0e9a
commit
f8e6feb6bc
@ -1,3 +1,10 @@
|
|||||||
|
2001-12-06 Hrvoje Niksic <hniksic@arsdigita.com>
|
||||||
|
|
||||||
|
* log.c (logvprintf): Restructure to allow being called multiple
|
||||||
|
times.
|
||||||
|
(logprintf): Call logvprintf in a loop.
|
||||||
|
(debug_logprintf): Ditto.
|
||||||
|
|
||||||
2001-12-06 Hrvoje Niksic <hniksic@arsdigita.com>
|
2001-12-06 Hrvoje Niksic <hniksic@arsdigita.com>
|
||||||
|
|
||||||
* gen_sslfunc.c (ssl_init_prng): Allow the user to disable EGD by
|
* gen_sslfunc.c (ssl_init_prng): Allow the user to disable EGD by
|
||||||
|
194
src/log.c
194
src/log.c
@ -281,84 +281,92 @@ logputs (enum log_options o, const char *s)
|
|||||||
needs_flushing = 1;
|
needs_flushing = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct logvprintf_state {
|
||||||
|
char *bigmsg;
|
||||||
|
int expected_size;
|
||||||
|
int allocated;
|
||||||
|
};
|
||||||
|
|
||||||
/* Print a message to the log. A copy of message will be saved to
|
/* Print a message to the log. A copy of message will be saved to
|
||||||
saved_log, for later reusal by log_dump(). */
|
saved_log, for later reusal by log_dump().
|
||||||
|
|
||||||
static void
|
It is not possible to code this function in a "natural" way, using
|
||||||
logvprintf (enum log_options o, const char *fmt, va_list args)
|
a loop, because of the braindeadness of the varargs API.
|
||||||
|
Specifically, each call to vsnprintf() must be preceded by va_start
|
||||||
|
and followed by va_end. And this is possible only in the function
|
||||||
|
that contains the `...' declaration. The alternative would be to
|
||||||
|
use va_copy, but that's not portable. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
logvprintf (struct logvprintf_state *state, const char *fmt, va_list args)
|
||||||
{
|
{
|
||||||
CHECK_VERBOSE (o);
|
char smallmsg[128];
|
||||||
CANONICALIZE_LOGFP_OR_RETURN;
|
char *write_ptr = smallmsg;
|
||||||
|
int available_size = sizeof (smallmsg);
|
||||||
/* Originally, we first used vfprintf(), and then checked whether
|
int numwritten;
|
||||||
the message needs to be stored with vsprintf(). However, Watcom
|
|
||||||
C didn't like ARGS being used twice, so now we first vsprintf()
|
|
||||||
the message, and then fwrite() it to LOGFP. */
|
|
||||||
|
|
||||||
if (!save_log_p)
|
if (!save_log_p)
|
||||||
{
|
{
|
||||||
/* In the simple case just call vfprintf(), to avoid needless
|
/* In the simple case just call vfprintf(), to avoid needless
|
||||||
allocation and games with vsnprintf(). */
|
allocation and games with vsnprintf(). */
|
||||||
vfprintf (logfp, fmt, args);
|
vfprintf (logfp, fmt, args);
|
||||||
|
goto flush;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (state->allocated != 0)
|
||||||
{
|
{
|
||||||
char smallmsg[128];
|
write_ptr = state->bigmsg;
|
||||||
char *bigmsg = NULL;
|
available_size = state->allocated;
|
||||||
int available_size = sizeof (smallmsg);
|
|
||||||
char *write_ptr = smallmsg;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
/* The GNU coding standards advise not to rely on the return
|
|
||||||
value of sprintf(). However, vsnprintf() is a relatively
|
|
||||||
new function missing from legacy systems. Therefore it's
|
|
||||||
safe to assume that its return value is meaningful. On
|
|
||||||
the systems where vsnprintf() is not available, we use
|
|
||||||
the implementation from snprintf.c which does return the
|
|
||||||
correct value. */
|
|
||||||
int numwritten = vsnprintf (write_ptr, available_size, fmt, args);
|
|
||||||
|
|
||||||
/* vsnprintf() will not step over the limit given by
|
|
||||||
available_size. If it fails, it will return either -1
|
|
||||||
(POSIX?) or the number of characters that *would have*
|
|
||||||
been written, if there had been enough room. In the
|
|
||||||
former case, we double the available_size and malloc() to
|
|
||||||
get a larger buffer, and try again. In the latter case,
|
|
||||||
we use the returned information to build a buffer of the
|
|
||||||
correct size. */
|
|
||||||
|
|
||||||
if (numwritten == -1)
|
|
||||||
{
|
|
||||||
/* Writing failed, and we don't know the needed size.
|
|
||||||
Try again with doubled size. */
|
|
||||||
available_size <<= 1;
|
|
||||||
bigmsg = xrealloc (bigmsg, available_size);
|
|
||||||
write_ptr = bigmsg;
|
|
||||||
}
|
|
||||||
else if (numwritten >= available_size)
|
|
||||||
{
|
|
||||||
/* Writing failed, but we know exactly how much space we
|
|
||||||
need. */
|
|
||||||
available_size = numwritten + 1;
|
|
||||||
bigmsg = xrealloc (bigmsg, available_size);
|
|
||||||
write_ptr = bigmsg;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Writing succeeded. */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
saved_append (write_ptr);
|
|
||||||
fputs (write_ptr, logfp);
|
|
||||||
if (bigmsg)
|
|
||||||
xfree (bigmsg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The GNU coding standards advise not to rely on the return value
|
||||||
|
of sprintf(). However, vsnprintf() is a relatively new function
|
||||||
|
missing from legacy systems. Therefore I consider it safe to
|
||||||
|
assume that its return value is meaningful. On the systems where
|
||||||
|
vsnprintf() is not available, we use the implementation from
|
||||||
|
snprintf.c which does return the correct value. */
|
||||||
|
numwritten = vsnprintf (write_ptr, available_size, fmt, args);
|
||||||
|
|
||||||
|
/* vsnprintf() will not step over the limit given by available_size.
|
||||||
|
If it fails, it will return either -1 (POSIX?) or the number of
|
||||||
|
characters that *would have* been written, if there had been
|
||||||
|
enough room. In the former case, we double the available_size
|
||||||
|
and malloc() to get a larger buffer, and try again. In the
|
||||||
|
latter case, we use the returned information to build a buffer of
|
||||||
|
the correct size. */
|
||||||
|
|
||||||
|
if (numwritten == -1)
|
||||||
|
{
|
||||||
|
/* Writing failed, and we don't know the needed size. Try
|
||||||
|
again with doubled size. */
|
||||||
|
int newsize = available_size << 1;
|
||||||
|
state->bigmsg = xrealloc (state->bigmsg, newsize);
|
||||||
|
state->allocated = newsize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (numwritten >= available_size)
|
||||||
|
{
|
||||||
|
/* Writing failed, but we know exactly how much space we
|
||||||
|
need. */
|
||||||
|
int newsize = numwritten + 1;
|
||||||
|
state->bigmsg = xrealloc (state->bigmsg, newsize);
|
||||||
|
state->allocated = newsize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Writing succeeded. */
|
||||||
|
saved_append (write_ptr);
|
||||||
|
fputs (write_ptr, logfp);
|
||||||
|
if (state->bigmsg)
|
||||||
|
xfree (state->bigmsg);
|
||||||
|
|
||||||
|
flush:
|
||||||
if (flush_log_p)
|
if (flush_log_p)
|
||||||
logflush ();
|
logflush ();
|
||||||
else
|
else
|
||||||
needs_flushing = 1;
|
needs_flushing = 1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush LOGFP. Useful while flushing is disabled. */
|
/* Flush LOGFP. Useful while flushing is disabled. */
|
||||||
@ -392,6 +400,21 @@ log_set_flush (int flush)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WGET_USE_STDARG
|
||||||
|
# define VA_START_1(arg1_type, arg1, args) va_start(args, arg1)
|
||||||
|
# define VA_START_2(arg1_type, arg1, arg2_type, arg2, args) va_start(args, arg2)
|
||||||
|
#else /* not WGET_USE_STDARG */
|
||||||
|
# define VA_START_1(arg1_type, arg1, args) do { \
|
||||||
|
va_start (args); \
|
||||||
|
arg1 = va_arg (args, arg1_type); \
|
||||||
|
} while (0)
|
||||||
|
# define VA_START_2(arg1_type, arg1, arg2_type, arg2, args) do { \
|
||||||
|
va_start (args); \
|
||||||
|
arg1 = va_arg (args, arg1_type); \
|
||||||
|
arg2 = va_arg (args, arg2_type); \
|
||||||
|
} while (0)
|
||||||
|
#endif /* not WGET_USE_STDARG */
|
||||||
|
|
||||||
/* Portability with pre-ANSI compilers makes these two functions look
|
/* Portability with pre-ANSI compilers makes these two functions look
|
||||||
like @#%#@$@#$. */
|
like @#%#@$@#$. */
|
||||||
|
|
||||||
@ -405,20 +428,29 @@ logprintf (va_alist)
|
|||||||
#endif /* not WGET_USE_STDARG */
|
#endif /* not WGET_USE_STDARG */
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
struct logvprintf_state lpstate;
|
||||||
|
int done;
|
||||||
|
|
||||||
#ifndef WGET_USE_STDARG
|
#ifndef WGET_USE_STDARG
|
||||||
enum log_options o;
|
enum log_options o;
|
||||||
const char *fmt;
|
const char *fmt;
|
||||||
|
|
||||||
|
/* Perform a "dry run" of VA_START_2 to get the value of O. */
|
||||||
|
VA_START_2 (enum log_options, o, char *, fmt, args);
|
||||||
|
va_end (args);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WGET_USE_STDARG
|
CHECK_VERBOSE (o);
|
||||||
va_start (args, fmt);
|
CANONICALIZE_LOGFP_OR_RETURN;
|
||||||
#else
|
|
||||||
va_start (args);
|
memset (&lpstate, '\0', sizeof (lpstate));
|
||||||
o = va_arg (args, enum log_options);
|
do
|
||||||
fmt = va_arg (args, char *);
|
{
|
||||||
#endif
|
VA_START_2 (enum log_options, o, char *, fmt, args);
|
||||||
logvprintf (o, fmt, args);
|
done = logvprintf (&lpstate, fmt, args);
|
||||||
va_end (args);
|
va_end (args);
|
||||||
|
}
|
||||||
|
while (!done);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -439,15 +471,19 @@ debug_logprintf (va_alist)
|
|||||||
#ifndef WGET_USE_STDARG
|
#ifndef WGET_USE_STDARG
|
||||||
const char *fmt;
|
const char *fmt;
|
||||||
#endif
|
#endif
|
||||||
|
struct logvprintf_state lpstate;
|
||||||
|
int done;
|
||||||
|
|
||||||
#ifdef WGET_USE_STDARG
|
CANONICALIZE_LOGFP_OR_RETURN;
|
||||||
va_start (args, fmt);
|
|
||||||
#else
|
memset (&lpstate, '\0', sizeof (lpstate));
|
||||||
va_start (args);
|
do
|
||||||
fmt = va_arg (args, char *);
|
{
|
||||||
#endif
|
VA_START_1 (char *, fmt, args);
|
||||||
logvprintf (LOG_ALWAYS, fmt, args);
|
done = logvprintf (&lpstate, fmt, args);
|
||||||
va_end (args);
|
va_end (args);
|
||||||
|
}
|
||||||
|
while (!done);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
Loading…
Reference in New Issue
Block a user