]> sjero.net Git - wget/blobdiff - src/log.c
[svn] Fix a possible race condition when opening files.
[wget] / src / log.c
index 5e02bac8bebe679a342d5fa41b51b4c5ad669090..2511513fc0ef95bb9ab0763d9a22499188508554 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -29,19 +29,6 @@ so, delete this exception statement from your version.  */
 
 #include <config.h>
 
-/* This allows the architecture-specific .h files to specify the use
-   of stdargs regardless of __STDC__.  */
-#ifndef WGET_USE_STDARG
-/* Use stdarg only if the compiler supports ANSI C and stdarg.h is
-   present.  We check for both because there are configurations where
-   stdarg.h exists, but doesn't work. */
-# ifdef __STDC__
-#  ifdef HAVE_STDARG_H
-#   define WGET_USE_STDARG
-#  endif
-# endif
-#endif /* not WGET_USE_STDARG */
-
 #include <stdio.h>
 #ifdef HAVE_STRING_H
 # include <string.h>
@@ -233,7 +220,7 @@ saved_append_1 (const char *start, const char *end)
            {
              /* Allocate memory and concatenate the old and the new
                  contents. */
-             ln->malloced_line = xmalloc (old_len + len + 1);
+             ln->malloced_line = (char *)xmalloc (old_len + len + 1);
              memcpy (ln->malloced_line, ln->static_line,
                      old_len);
              memcpy (ln->malloced_line + old_len, start, len);
@@ -350,15 +337,20 @@ struct logvprintf_state {
 /* Print a message to the log.  A copy of message will be saved to
    saved_log, for later reusal by log_dump_context().
 
-   It is not possible to code this function in a "natural" way, using
-   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.  */
+   Normally we'd want this function to loop around vsnprintf until
+   sufficient room is allocated, as the Linux man page recommends.
+   However each call to vsnprintf() must be preceded by va_start and
+   followed by va_end.  Since calling va_start/va_end is possible only
+   in the function that contains the `...' declaration, we cannot call
+   vsnprintf more than once.  Therefore this function saves its state
+   to logvprintf_state and signals the parent to call it again.
+
+   (An alternative approach would be to use va_copy, but that's not
+   portable.)  */
 
 static int
-logvprintf (struct logvprintf_state *state, const char *fmt, va_list args)
+log_vprintf_internal (struct logvprintf_state *state, const char *fmt,
+                     va_list args)
 {
   char smallmsg[128];
   char *write_ptr = smallmsg;
@@ -500,11 +492,11 @@ logprintf (enum log_options o, const char *fmt, ...)
     return;
   CHECK_VERBOSE (o);
 
-  memset (&lpstate, '\0', sizeof (lpstate));
+  xzero (lpstate);
   do
     {
       VA_START (args, fmt);
-      done = logvprintf (&lpstate, fmt, args);
+      done = log_vprintf_internal (&lpstate, fmt, args);
       va_end (args);
     }
   while (!done);
@@ -526,11 +518,11 @@ debug_logprintf (const char *fmt, ...)
       if (inhibit_logging)
        return;
 
-      memset (&lpstate, '\0', sizeof (lpstate));
+      xzero (lpstate);
       do
        {
          VA_START (args, fmt);
-         done = logvprintf (&lpstate, fmt, args);
+         done = log_vprintf_internal (&lpstate, fmt, args);
          va_end (args);
        }
       while (!done);
@@ -548,7 +540,7 @@ log_init (const char *file, int appendp)
       logfp = fopen (file, appendp ? "a" : "w");
       if (!logfp)
        {
-         perror (opt.lfilename);
+         fprintf (stderr, "%s: %s: %s\n", exec_name, file, strerror (errno));
          exit (1);
        }
     }
@@ -562,16 +554,16 @@ log_init (const char *file, int appendp)
          easier on the user.  */
       logfp = stderr;
 
-      /* If the output is a TTY, enable storing, which will make Wget
-         remember the last several printed messages, to be able to
-         dump them to a log file in case SIGHUP or SIGUSR1 is received
-         (or Ctrl+Break is pressed under Windows).  */
       if (1
 #ifdef HAVE_ISATTY
          && isatty (fileno (logfp))
 #endif
          )
        {
+         /* If the output is a TTY, enable save context, i.e. store
+            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;
        }
     }
@@ -633,24 +625,25 @@ static const char *redirect_request_signal_name;
 static void
 redirect_output (void)
 {
-  char *logfile = unique_name (DEFAULT_LOGFILE, 0);
-  fprintf (stderr, _("\n%s received, redirecting output to `%s'.\n"),
-          redirect_request_signal_name, logfile);
-  logfp = fopen (logfile, "w");
-  if (!logfp)
+  char *logfile;
+  logfp = unique_create (DEFAULT_LOGFILE, 0, &logfile);
+  if (logfp)
+    {
+      fprintf (stderr, _("\n%s received, redirecting output to `%s'.\n"),
+              redirect_request_signal_name, logfile);
+      xfree (logfile);
+      /* Dump the context output to the newly opened log.  */
+      log_dump_context ();
+    }
+  else
     {
       /* Eek!  Opening the alternate log file has failed.  Nothing we
          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));
       inhibit_logging = 1;
     }
-  else
-    {
-      /* Dump the context output to the newly opened log.  */
-      log_dump_context ();
-    }
-  xfree (logfile);
   save_context_p = 0;
 }