/* Messages logging.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007 Free Software Foundation, Inc.
+ 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.
shall include the source code for the parts of OpenSSL used as well
as that of the covered work. */
-#include <config.h>
+#include "wget.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
+#include <unistd.h>
#include <assert.h>
#include <errno.h>
-#include "wget.h"
#include "utils.h"
#include "log.h"
-/* This file impplement support for "logging". Logging means printing
+/* 2005-10-25 SMS.
+ VMS log files are often VFC record format, not stream, so fputs() can
+ produce multiple records, even when there's no newline terminator in
+ the buffer. The result is unsightly output with spurious newlines.
+ Using fprintf() instead of fputs(), along with inhibiting some
+ fflush() activity below, seems to solve the problem.
+*/
+#ifdef __VMS
+# define FPUTS( s, f) fprintf( (f), "%s", (s))
+#else /* def __VMS */
+# define FPUTS( s, f) fputs( (s), (f))
+#endif /* def __VMS [else] */
+
+/* This file implements support for "logging". Logging means printing
output, plus several additional features:
- Cataloguing output by importance. You can specify that a log
logging is inhibited, logfp is set back to NULL. */
static FILE *logfp;
+/* A second file descriptor pointing to the temporary log file for the
+ WARC writer. If WARC writing is disabled, this is NULL. */
+static FILE *warclogfp;
+
/* If true, it means logging is inhibited, i.e. nothing is printed or
stored. */
static bool inhibit_logging;
return logfp;
return stderr;
}
+
+/* Returns the file descriptor for the secondary log file. This is
+ WARCLOGFP, except if called before log_init, in which case it
+ returns stderr. This is useful in case someone calls a logging
+ function before log_init.
+
+ If logging is inhibited, return NULL. */
+
+static FILE *
+get_warc_log_fp (void)
+{
+ if (inhibit_logging)
+ return NULL;
+ if (warclogfp)
+ return warclogfp;
+ return NULL;
+}
+
+/* Sets the file descriptor for the secondary log file. */
+
+void
+log_set_warc_log_fp (FILE * fp)
+{
+ warclogfp = fp;
+}
\f
/* Log a literal string S. The string is logged as-is, without a
newline appended. */
logputs (enum log_options o, const char *s)
{
FILE *fp;
+ FILE *warcfp;
check_redirect_output ();
if ((fp = get_log_fp ()) == NULL)
return;
+ warcfp = get_warc_log_fp ();
CHECK_VERBOSE (o);
- fputs (s, fp);
+ FPUTS (s, fp);
+ if (warcfp != NULL)
+ FPUTS (s, warcfp);
if (save_context_p)
saved_append (s);
if (flush_log_p)
int available_size = sizeof (smallmsg);
int numwritten;
FILE *fp = get_log_fp ();
+ FILE *warcfp = get_warc_log_fp ();
- if (!save_context_p)
+ if (!save_context_p && warcfp == NULL)
{
/* In the simple case just call vfprintf(), to avoid needless
allocation and games with vsnprintf(). */
}
/* Writing succeeded. */
- saved_append (write_ptr);
- fputs (write_ptr, fp);
+ if (save_context_p)
+ saved_append (write_ptr);
+ FPUTS (write_ptr, fp);
+ if (warcfp != NULL)
+ FPUTS (write_ptr, warcfp);
if (state->bigmsg)
xfree (state->bigmsg);
logflush (void)
{
FILE *fp = get_log_fp ();
+ FILE *warcfp = get_warc_log_fp ();
if (fp)
- fflush (fp);
+ {
+/* 2005-10-25 SMS.
+ On VMS, flush only for a terminal. See note at FPUTS macro, above.
+*/
+#ifdef __VMS
+ if (isatty( fileno( fp)))
+ {
+ fflush (fp);
+ }
+#else /* def __VMS */
+ fflush (fp);
+#endif /* def __VMS [else] */
+ }
+
+ if (warcfp != NULL)
+ fflush (warcfp);
+
needs_flushing = false;
}
va_start (args, fmt);
done = log_vprintf_internal (&lpstate, fmt, args);
va_end (args);
+
+ if (done && errno == EPIPE)
+ exit (1);
}
while (!done);
}
}
}
-/* Close LOGFP, inhibit further logging and free the memory associated
- with it. */
+/* Close LOGFP (only if we opened it, not if it's stderr), inhibit
+ further logging and free the memory associated with it. */
void
log_close (void)
{
int i;
- if (logfp)
+ if (logfp && (logfp != stderr))
fclose (logfp);
logfp = NULL;
inhibit_logging = true;
{
int num = log_line_current;
FILE *fp = get_log_fp ();
+ FILE *warcfp = get_warc_log_fp ();
if (!fp)
return;
{
struct log_ln *ln = log_lines + num;
if (ln->content)
- fputs (ln->content, fp);
+ {
+ FPUTS (ln->content, fp);
+ if (warcfp != NULL)
+ FPUTS (ln->content, warcfp);
+ }
ROT_ADVANCE (num);
}
while (num != log_line_current);
if (trailing_line)
if (log_lines[log_line_current].content)
- fputs (log_lines[log_line_current].content, fp);
+ {
+ FPUTS (log_lines[log_line_current].content, fp);
+ if (warcfp != NULL)
+ FPUTS (log_lines[log_line_current].content, warcfp);
+ }
fflush (fp);
+ fflush (warcfp);
}
\f
/* String escape functions. */
/* Return the number of non-printable characters in SOURCE.
- Non-printable characters are determined as per safe-ctype.c. */
+ Non-printable characters are determined as per c-ctype.c. */
static int
count_nonprint (const char *source)
const char *p;
int cnt;
for (p = source, cnt = 0; *p; p++)
- if (!ISPRINT (*p))
+ if (!c_isprint (*p))
++cnt;
return cnt;
}
{
case 8:
while ((c = *from++) != '\0')
- if (ISPRINT (c))
+ if (c_isprint (c))
*to++ = c;
else
{
break;
case 16:
while ((c = *from++) != '\0')
- if (ISPRINT (c))
+ if (c_isprint (c))
*to++ = c;
else
{
void
log_cleanup (void)
{
- int i;
+ size_t i;
for (i = 0; i < countof (ring); i++)
xfree_null (ring[i].buffer);
}
logfp = unique_create (DEFAULT_LOGFILE, false, &logfile);
if (logfp)
{
- fprintf (stderr, _("\n%s received, redirecting output to `%s'.\n"),
- redirect_request_signal_name, logfile);
+ fprintf (stderr, _("\n%s received, redirecting output to %s.\n"),
+ redirect_request_signal_name, quote (logfile));
xfree (logfile);
/* Dump the context output to the newly opened log. */
log_dump_context ();
can do but disable printing completely. */
fprintf (stderr, _("\n%s received.\n"), redirect_request_signal_name);
fprintf (stderr, _("%s: %s; disabling logging.\n"),
- logfile, strerror (errno));
+ (logfile) ? logfile : DEFAULT_LOGFILE, strerror (errno));
inhibit_logging = true;
}
save_context_p = false;