/* Messages logging.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998-2006 Free Software Foundation, Inc.
This file is part of GNU Wget.
GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GNU Wget is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with Wget; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+along with Wget. If not, see <http://www.gnu.org/licenses/>.
In addition, as a special exception, the Free Software Foundation
gives permission to link the code of its release of Wget with the
#include <config.h>
#include <stdio.h>
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# include <strings.h>
-#endif
+#include <string.h>
#include <stdlib.h>
-#ifdef WGET_USE_STDARG
-# include <stdarg.h>
-#else
-# include <varargs.h>
-#endif
+#include <stdarg.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "utils.h"
#include "log.h"
-#ifndef errno
-extern int errno;
-#endif
-
/* This file impplement support for "logging". Logging means printing
output, plus several additional features:
logging is inhibited, logfp is set back to NULL. */
static FILE *logfp;
-/* If non-zero, it means logging is inhibited, i.e. nothing is printed
- or stored. */
-static int inhibit_logging;
+/* If true, it means logging is inhibited, i.e. nothing is printed or
+ stored. */
+static bool inhibit_logging;
/* Whether the last output lines are stored for use as context. */
-static int save_context_p;
+static bool save_context_p;
/* Whether the log is flushed after each command. */
-static int flush_log_p = 1;
+static bool flush_log_p = true;
/* Whether any output has been received while flush_log_p was 0. */
-static int needs_flushing;
+static bool needs_flushing;
/* In the event of a hang-up, and if its output was on a TTY, Wget
redirects its output to `wget-log'.
finish with \n. This is an important piece of information because
the code is always careful to append data to trailing lines, rather
than create new ones. */
-static int trailing_line;
+static bool trailing_line;
-static void check_redirect_output PARAMS ((void));
+static void check_redirect_output (void);
\f
#define ROT_ADVANCE(num) do { \
if (++num >= SAVED_LOG_LINES) \
{
/* Allocate memory and concatenate the old and the new
contents. */
- ln->malloced_line = (char *)xmalloc (old_len + len + 1);
+ ln->malloced_line = xmalloc (old_len + len + 1);
memcpy (ln->malloced_line, ln->static_line,
old_len);
memcpy (ln->malloced_line + old_len, start, len);
if (flush_log_p)
logflush ();
else
- needs_flushing = 1;
+ needs_flushing = true;
}
struct logvprintf_state {
(An alternative approach would be to use va_copy, but that's not
portable.) */
-static int
+static bool
log_vprintf_internal (struct logvprintf_state *state, const char *fmt,
va_list args)
{
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 (C99). 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 it fails, it returns either -1 (older implementations) or the
+ number of characters (not counting the terminating \0) that
+ *would have* been written if there had been enough room (C99).
+ In the former case, we double 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)
{
int newsize = available_size << 1;
state->bigmsg = xrealloc (state->bigmsg, newsize);
state->allocated = newsize;
- return 0;
+ return false;
}
else if (numwritten >= available_size)
{
int newsize = numwritten + 1;
state->bigmsg = xrealloc (state->bigmsg, newsize);
state->allocated = newsize;
- return 0;
+ return false;
}
/* Writing succeeded. */
if (flush_log_p)
logflush ();
else
- needs_flushing = 1;
+ needs_flushing = true;
- return 1;
+ return true;
}
/* Flush LOGFP. Useful while flushing is disabled. */
FILE *fp = get_log_fp ();
if (fp)
fflush (fp);
- needs_flushing = 0;
+ needs_flushing = false;
}
/* Enable or disable log flushing. */
void
-log_set_flush (int flush)
+log_set_flush (bool flush)
{
if (flush == flush_log_p)
return;
- if (flush == 0)
+ if (flush == false)
{
/* Disable flushing by setting flush_log_p to 0. */
- flush_log_p = 0;
+ flush_log_p = false;
}
else
{
flush the log now. */
if (needs_flushing)
logflush ();
- flush_log_p = 1;
+ flush_log_p = true;
}
}
status of storing, with which this function can be called again to
reestablish storing. */
-int
-log_set_save_context (int savep)
+bool
+log_set_save_context (bool savep)
{
- int old = save_context_p;
+ bool old = save_context_p;
save_context_p = savep;
return old;
}
-/* Handle difference in va_start between pre-ANSI and ANSI C. Note
- that we always use `...' in function definitions and let ansi2knr
- convert it for us. */
-
-#ifdef WGET_USE_STDARG
-# define VA_START(args, arg1) va_start (args, arg1)
-#else
-# define VA_START(args, ignored) va_start (args)
-#endif
-
/* Print a message to the screen or to the log. The first argument
defines the verbosity of the message, and the rest are as in
printf(3). */
{
va_list args;
struct logvprintf_state lpstate;
- int done;
+ bool done;
check_redirect_output ();
if (inhibit_logging)
xzero (lpstate);
do
{
- VA_START (args, fmt);
+ va_start (args, fmt);
done = log_vprintf_internal (&lpstate, fmt, args);
va_end (args);
}
#ifdef ENABLE_DEBUG
/* The same as logprintf(), but does anything only if opt.debug is
- non-zero. */
+ true. */
void
debug_logprintf (const char *fmt, ...)
{
{
va_list args;
struct logvprintf_state lpstate;
- int done;
+ bool done;
check_redirect_output ();
if (inhibit_logging)
xzero (lpstate);
do
{
- VA_START (args, fmt);
+ va_start (args, fmt);
done = log_vprintf_internal (&lpstate, fmt, args);
va_end (args);
}
/* Open FILE and set up a logging stream. If FILE cannot be opened,
exit with status of 1. */
void
-log_init (const char *file, int appendp)
+log_init (const char *file, bool appendp)
{
if (file)
{
the most recent several messages ("context") and dump
them to a log file in case SIGHUP or SIGUSR1 is received
(or Ctrl+Break is pressed under Windows). */
- save_context_p = 1;
+ save_context_p = true;
}
}
}
if (logfp)
fclose (logfp);
logfp = NULL;
- inhibit_logging = 1;
- save_context_p = 0;
+ inhibit_logging = true;
+ save_context_p = false;
for (i = 0; i < SAVED_LOG_LINES; i++)
free_log_line (i);
log_line_current = -1;
- trailing_line = 0;
+ trailing_line = false;
}
/* Dump saved lines to logfp. */
escnonprint_internal (const char *str, char escape, int base)
{
static int ringpos; /* current ring position */
+ int nprcnt;
assert (base == 8 || base == 16);
- int nprcnt = count_nonprint (str);
+ nprcnt = count_nonprint (str);
if (nprcnt == 0)
/* If there are no non-printable chars in STR, don't bother
copying anything, just return STR. */
characters in STR, STR is returned. See copy_and_escape for more
information on which characters are considered non-printable.
+ DON'T call this function on translated strings because escaping
+ will break them. Don't call it on literal strings from the source,
+ which are by definition trusted. If newlines are allowed in the
+ string, escape and print it line by line because escaping the whole
+ string will convert newlines to \012. (This is so that expectedly
+ single-line messages cannot use embedded newlines to mimic Wget's
+ output and deceive the user.)
+
+ escnonprint doesn't quote its escape character because it is notf
+ meant as a general and reversible quoting mechanism, but as a quick
+ way to defang binary junk sent by malicious or buggy servers.
+
NOTE: since this function can return a pointer to static data, be
careful to copy its result before calling it again. However, to be
more useful with printf, it maintains an internal ring of static
/* Return a pointer to a static copy of STR with the non-printable
characters escaped as %XX. If there are no non-printable
- characters in STR, STR is returned. See copy_and_escape for more
- information on which characters are considered non-printable.
+ characters in STR, STR is returned.
- This function returns a pointer to static data which will be
- overwritten by subsequent calls -- see escnonprint for details. */
+ See escnonprint for usage details. */
const char *
escnonprint_uri (const char *str)
\f
/* When SIGHUP or SIGUSR1 are received, the output is redirected
elsewhere. Such redirection is only allowed once. */
-enum { RR_NONE, RR_REQUESTED, RR_DONE } redirect_request = RR_NONE;
+static enum { RR_NONE, RR_REQUESTED, RR_DONE } redirect_request = RR_NONE;
static const char *redirect_request_signal_name;
/* Redirect output to `wget-log'. */
redirect_output (void)
{
char *logfile;
- logfp = unique_create (DEFAULT_LOGFILE, 0, &logfile);
+ logfp = unique_create (DEFAULT_LOGFILE, false, &logfile);
if (logfp)
{
fprintf (stderr, _("\n%s received, redirecting output to `%s'.\n"),
fprintf (stderr, _("\n%s received.\n"), redirect_request_signal_name);
fprintf (stderr, _("%s: %s; disabling logging.\n"),
logfile, strerror (errno));
- inhibit_logging = 1;
+ inhibit_logging = true;
}
- save_context_p = 0;
+ save_context_p = false;
}
/* Check whether a signal handler requested the output to be