]> sjero.net Git - wget/blob - src/log.c
Fix ISDIGIT to c_isdigit.
[wget] / src / log.c
1 /* Messages logging.
2    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3    2007, 2008 Free Software Foundation, Inc.
4
5 This file is part of GNU Wget.
6
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Wget.  If not, see <http://www.gnu.org/licenses/>.
19
20 Additional permission under GNU GPL version 3 section 7
21
22 If you modify this program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a
24 modified version of that library), containing parts covered by the
25 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
26 grants you additional permission to convey the resulting work.
27 Corresponding Source for a non-source form of such a combination
28 shall include the source code for the parts of OpenSSL used as well
29 as that of the covered work.  */
30
31 #include "wget.h"
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40 #include <assert.h>
41 #include <errno.h>
42
43 #include "utils.h"
44 #include "log.h"
45
46 /* 2005-10-25 SMS.
47    VMS log files are often VFC record format, not stream, so fputs() can
48    produce multiple records, even when there's no newline terminator in
49    the buffer.  The result is unsightly output with spurious newlines.
50    Using fprintf() instead of fputs(), along with inhibiting some
51    fflush() activity below, seems to solve the problem.
52 */
53 #ifdef __VMS
54 # define FPUTS( s, f) fprintf( (f), "%s", (s))
55 #else /* def __VMS */
56 # define FPUTS( s, f) fputs( (s), (f))
57 #endif /* def __VMS [else] */
58
59 /* This file impplement support for "logging".  Logging means printing
60    output, plus several additional features:
61
62    - Cataloguing output by importance.  You can specify that a log
63    message is "verbose" or "debug", and it will not be printed unless
64    in verbose or debug mode, respectively.
65
66    - Redirecting the log to the file.  When Wget's output goes to the
67    terminal, and Wget receives SIGHUP, all further output is
68    redirected to a log file.  When this is the case, Wget can also
69    print the last several lines of "context" to the log file so that
70    it does not begin in the middle of a line.  For this to work, the
71    logging code stores the last several lines of context.  Callers may
72    request for certain output not to be stored.
73
74    - Inhibiting output.  When Wget receives SIGHUP, but redirecting
75    the output fails, logging is inhibited.  */
76
77 \f
78 /* The file descriptor used for logging.  This is NULL before log_init
79    is called; logging functions log to stderr then.  log_init sets it
80    either to stderr or to a file pointer obtained from fopen().  If
81    logging is inhibited, logfp is set back to NULL. */
82 static FILE *logfp;
83
84 /* If true, it means logging is inhibited, i.e. nothing is printed or
85    stored.  */
86 static bool inhibit_logging;
87
88 /* Whether the last output lines are stored for use as context.  */
89 static bool save_context_p;
90
91 /* Whether the log is flushed after each command. */
92 static bool flush_log_p = true;
93
94 /* Whether any output has been received while flush_log_p was 0. */
95 static bool needs_flushing;
96
97 /* In the event of a hang-up, and if its output was on a TTY, Wget
98    redirects its output to `wget-log'.
99
100    For the convenience of reading this newly-created log, we store the
101    last several lines ("screenful", hence the choice of 24) of Wget
102    output, and dump them as context when the time comes.  */
103 #define SAVED_LOG_LINES 24
104
105 /* log_lines is a circular buffer that stores SAVED_LOG_LINES lines of
106    output.  log_line_current always points to the position in the
107    buffer that will be written to next.  When log_line_current reaches
108    SAVED_LOG_LINES, it is reset to zero.
109
110    The problem here is that we'd have to either (re)allocate and free
111    strings all the time, or limit the lines to an arbitrary number of
112    characters.  Instead of settling for either of these, we do both:
113    if the line is smaller than a certain "usual" line length (128
114    chars by default), a preallocated memory is used.  The rare lines
115    that are longer than 128 characters are malloc'ed and freed
116    separately.  This gives good performance with minimum memory
117    consumption and fragmentation.  */
118
119 #define STATIC_LENGTH 128
120
121 static struct log_ln {
122   char static_line[STATIC_LENGTH + 1]; /* statically allocated
123                                           line. */
124   char *malloced_line;          /* malloc'ed line, for lines of output
125                                    larger than 80 characters. */
126   char *content;                /* this points either to malloced_line
127                                    or to the appropriate static_line.
128                                    If this is NULL, it means the line
129                                    has not yet been used. */
130 } log_lines[SAVED_LOG_LINES];
131
132 /* The current position in the ring. */
133 static int log_line_current = -1;
134
135 /* Whether the most recently written line was "trailing", i.e. did not
136    finish with \n.  This is an important piece of information because
137    the code is always careful to append data to trailing lines, rather
138    than create new ones.  */
139 static bool trailing_line;
140
141 static void check_redirect_output (void);
142 \f
143 #define ROT_ADVANCE(num) do {                   \
144   if (++num >= SAVED_LOG_LINES)                 \
145     num = 0;                                    \
146 } while (0)
147
148 /* Free the log line index with NUM.  This calls free on
149    ln->malloced_line if it's non-NULL, and it also resets
150    ln->malloced_line and ln->content to NULL.  */
151
152 static void
153 free_log_line (int num)
154 {
155   struct log_ln *ln = log_lines + num;
156   if (ln->malloced_line)
157     {
158       xfree (ln->malloced_line);
159       ln->malloced_line = NULL;
160     }
161   ln->content = NULL;
162 }
163
164 /* Append bytes in the range [start, end) to one line in the log.  The
165    region is not supposed to contain newlines, except for the last
166    character (at end[-1]).  */
167
168 static void
169 saved_append_1 (const char *start, const char *end)
170 {
171   int len = end - start;
172   if (!len)
173     return;
174
175   /* First, check whether we need to append to an existing line or to
176      create a new one.  */
177   if (!trailing_line)
178     {
179       /* Create a new line. */
180       struct log_ln *ln;
181
182       if (log_line_current == -1)
183         log_line_current = 0;
184       else
185         free_log_line (log_line_current);
186       ln = log_lines + log_line_current;
187       if (len > STATIC_LENGTH)
188         {
189           ln->malloced_line = strdupdelim (start, end);
190           ln->content = ln->malloced_line;
191         }
192       else
193         {
194           memcpy (ln->static_line, start, len);
195           ln->static_line[len] = '\0';
196           ln->content = ln->static_line;
197         }
198     }
199   else
200     {
201       /* Append to the last line.  If the line is malloc'ed, we just
202          call realloc and append the new string.  If the line is
203          static, we have to check whether appending the new string
204          would make it exceed STATIC_LENGTH characters, and if so,
205          convert it to malloc(). */
206       struct log_ln *ln = log_lines + log_line_current;
207       if (ln->malloced_line)
208         {
209           /* Resize malloc'ed line and append. */
210           int old_len = strlen (ln->malloced_line);
211           ln->malloced_line = xrealloc (ln->malloced_line, old_len + len + 1);
212           memcpy (ln->malloced_line + old_len, start, len);
213           ln->malloced_line[old_len + len] = '\0';
214           /* might have changed due to realloc */
215           ln->content = ln->malloced_line;
216         }
217       else
218         {
219           int old_len = strlen (ln->static_line);
220           if (old_len + len > STATIC_LENGTH)
221             {
222               /* Allocate memory and concatenate the old and the new
223                  contents. */
224               ln->malloced_line = xmalloc (old_len + len + 1);
225               memcpy (ln->malloced_line, ln->static_line,
226                       old_len);
227               memcpy (ln->malloced_line + old_len, start, len);
228               ln->malloced_line[old_len + len] = '\0';
229               ln->content = ln->malloced_line;
230             }
231           else
232             {
233               /* Just append to the old, statically allocated
234                  contents.  */
235               memcpy (ln->static_line + old_len, start, len);
236               ln->static_line[old_len + len] = '\0';
237               ln->content = ln->static_line;
238             }
239         }
240     }
241   trailing_line = !(end[-1] == '\n');
242   if (!trailing_line)
243     ROT_ADVANCE (log_line_current);
244 }
245
246 /* Log the contents of S, as explained above.  If S consists of
247    multiple lines, they are logged separately.  If S does not end with
248    a newline, it will form a "trailing" line, to which things will get
249    appended the next time this function is called.  */
250
251 static void
252 saved_append (const char *s)
253 {
254   while (*s)
255     {
256       const char *end = strchr (s, '\n');
257       if (!end)
258         end = s + strlen (s);
259       else
260         ++end;
261       saved_append_1 (s, end);
262       s = end;
263     }
264 }
265 \f
266 /* Check X against opt.verbose and opt.quiet.  The semantics is as
267    follows:
268
269    * LOG_ALWAYS - print the message unconditionally;
270
271    * LOG_NOTQUIET - print the message if opt.quiet is non-zero;
272
273    * LOG_NONVERBOSE - print the message if opt.verbose is zero;
274
275    * LOG_VERBOSE - print the message if opt.verbose is non-zero.  */
276 #define CHECK_VERBOSE(x)                        \
277   switch (x)                                    \
278     {                                           \
279     case LOG_ALWAYS:                            \
280       break;                                    \
281     case LOG_NOTQUIET:                          \
282       if (opt.quiet)                            \
283         return;                                 \
284       break;                                    \
285     case LOG_NONVERBOSE:                        \
286       if (opt.verbose || opt.quiet)             \
287         return;                                 \
288       break;                                    \
289     case LOG_VERBOSE:                           \
290       if (!opt.verbose)                         \
291         return;                                 \
292     }
293
294 /* Returns the file descriptor for logging.  This is LOGFP, except if
295    called before log_init, in which case it returns stderr.  This is
296    useful in case someone calls a logging function before log_init.
297
298    If logging is inhibited, return NULL.  */
299
300 static FILE *
301 get_log_fp (void)
302 {
303   if (inhibit_logging)
304     return NULL;
305   if (logfp)
306     return logfp;
307   return stderr;
308 }
309 \f
310 /* Log a literal string S.  The string is logged as-is, without a
311    newline appended.  */
312
313 void
314 logputs (enum log_options o, const char *s)
315 {
316   FILE *fp;
317
318   check_redirect_output ();
319   if ((fp = get_log_fp ()) == NULL)
320     return;
321   CHECK_VERBOSE (o);
322
323   FPUTS (s, fp);
324   if (save_context_p)
325     saved_append (s);
326   if (flush_log_p)
327     logflush ();
328   else
329     needs_flushing = true;
330 }
331
332 struct logvprintf_state {
333   char *bigmsg;
334   int expected_size;
335   int allocated;
336 };
337
338 /* Print a message to the log.  A copy of message will be saved to
339    saved_log, for later reusal by log_dump_context().
340
341    Normally we'd want this function to loop around vsnprintf until
342    sufficient room is allocated, as the Linux man page recommends.
343    However each call to vsnprintf() must be preceded by va_start and
344    followed by va_end.  Since calling va_start/va_end is possible only
345    in the function that contains the `...' declaration, we cannot call
346    vsnprintf more than once.  Therefore this function saves its state
347    to logvprintf_state and signals the parent to call it again.
348
349    (An alternative approach would be to use va_copy, but that's not
350    portable.)  */
351
352 static bool
353 log_vprintf_internal (struct logvprintf_state *state, const char *fmt,
354                       va_list args)
355 {
356   char smallmsg[128];
357   char *write_ptr = smallmsg;
358   int available_size = sizeof (smallmsg);
359   int numwritten;
360   FILE *fp = get_log_fp ();
361
362   if (!save_context_p)
363     {
364       /* In the simple case just call vfprintf(), to avoid needless
365          allocation and games with vsnprintf(). */
366       vfprintf (fp, fmt, args);
367       goto flush;
368     }
369
370   if (state->allocated != 0)
371     {
372       write_ptr = state->bigmsg;
373       available_size = state->allocated;
374     }
375
376   /* The GNU coding standards advise not to rely on the return value
377      of sprintf().  However, vsnprintf() is a relatively new function
378      missing from legacy systems.  Therefore I consider it safe to
379      assume that its return value is meaningful.  On the systems where
380      vsnprintf() is not available, we use the implementation from
381      snprintf.c which does return the correct value.  */
382   numwritten = vsnprintf (write_ptr, available_size, fmt, args);
383
384   /* vsnprintf() will not step over the limit given by available_size.
385      If it fails, it returns either -1 (older implementations) or the
386      number of characters (not counting the terminating \0) that
387      *would have* been written if there had been enough room (C99).
388      In the former case, we double available_size and malloc to get a
389      larger buffer, and try again.  In the latter case, we use the
390      returned information to build a buffer of the correct size.  */
391
392   if (numwritten == -1)
393     {
394       /* Writing failed, and we don't know the needed size.  Try
395          again with doubled size. */
396       int newsize = available_size << 1;
397       state->bigmsg = xrealloc (state->bigmsg, newsize);
398       state->allocated = newsize;
399       return false;
400     }
401   else if (numwritten >= available_size)
402     {
403       /* Writing failed, but we know exactly how much space we
404          need. */
405       int newsize = numwritten + 1;
406       state->bigmsg = xrealloc (state->bigmsg, newsize);
407       state->allocated = newsize;
408       return false;
409     }
410
411   /* Writing succeeded. */
412   saved_append (write_ptr);
413   FPUTS (write_ptr, fp);
414   if (state->bigmsg)
415     xfree (state->bigmsg);
416
417  flush:
418   if (flush_log_p)
419     logflush ();
420   else
421     needs_flushing = true;
422
423   return true;
424 }
425
426 /* Flush LOGFP.  Useful while flushing is disabled.  */
427 void
428 logflush (void)
429 {
430   FILE *fp = get_log_fp ();
431   if (fp)
432     {
433 /* 2005-10-25 SMS.
434    On VMS, flush only for a terminal.  See note at FPUTS macro, above.
435 */
436 #ifdef __VMS
437       if (isatty( fileno( fp)))
438         {
439           fflush (fp);
440         }
441 #else /* def __VMS */
442       fflush (fp);
443 #endif /* def __VMS [else] */
444     }
445   needs_flushing = false;
446 }
447
448 /* Enable or disable log flushing. */
449 void
450 log_set_flush (bool flush)
451 {
452   if (flush == flush_log_p)
453     return;
454
455   if (flush == false)
456     {
457       /* Disable flushing by setting flush_log_p to 0. */
458       flush_log_p = false;
459     }
460   else
461     {
462       /* Reenable flushing.  If anything was printed in no-flush mode,
463          flush the log now.  */
464       if (needs_flushing)
465         logflush ();
466       flush_log_p = true;
467     }
468 }
469
470 /* (Temporarily) disable storing log to memory.  Returns the old
471    status of storing, with which this function can be called again to
472    reestablish storing. */
473
474 bool
475 log_set_save_context (bool savep)
476 {
477   bool old = save_context_p;
478   save_context_p = savep;
479   return old;
480 }
481
482 /* Print a message to the screen or to the log.  The first argument
483    defines the verbosity of the message, and the rest are as in
484    printf(3).  */
485
486 void
487 logprintf (enum log_options o, const char *fmt, ...)
488 {
489   va_list args;
490   struct logvprintf_state lpstate;
491   bool done;
492
493   check_redirect_output ();
494   if (inhibit_logging)
495     return;
496   CHECK_VERBOSE (o);
497
498   xzero (lpstate);
499   do
500     {
501       va_start (args, fmt);
502       done = log_vprintf_internal (&lpstate, fmt, args);
503       va_end (args);
504     }
505   while (!done);
506 }
507
508 #ifdef ENABLE_DEBUG
509 /* The same as logprintf(), but does anything only if opt.debug is
510    true.  */
511 void
512 debug_logprintf (const char *fmt, ...)
513 {
514   if (opt.debug)
515     {
516       va_list args;
517       struct logvprintf_state lpstate;
518       bool done;
519
520       check_redirect_output ();
521       if (inhibit_logging)
522         return;
523
524       xzero (lpstate);
525       do
526         {
527           va_start (args, fmt);
528           done = log_vprintf_internal (&lpstate, fmt, args);
529           va_end (args);
530         }
531       while (!done);
532     }
533 }
534 #endif /* ENABLE_DEBUG */
535 \f
536 /* Open FILE and set up a logging stream.  If FILE cannot be opened,
537    exit with status of 1.  */
538 void
539 log_init (const char *file, bool appendp)
540 {
541   if (file)
542     {
543       logfp = fopen (file, appendp ? "a" : "w");
544       if (!logfp)
545         {
546           fprintf (stderr, "%s: %s: %s\n", exec_name, file, strerror (errno));
547           exit (1);
548         }
549     }
550   else
551     {
552       /* The log goes to stderr to avoid collisions with the output if
553          the user specifies `-O -'.  #### Francois Pinard suggests
554          that it's a better idea to print to stdout by default, and to
555          stderr only if the user actually specifies `-O -'.  He says
556          this inconsistency is harder to document, but is overall
557          easier on the user.  */
558       logfp = stderr;
559
560       if (1
561 #ifdef HAVE_ISATTY
562           && isatty (fileno (logfp))
563 #endif
564           )
565         {
566           /* If the output is a TTY, enable save context, i.e. store
567              the most recent several messages ("context") and dump
568              them to a log file in case SIGHUP or SIGUSR1 is received
569              (or Ctrl+Break is pressed under Windows).  */
570           save_context_p = true;
571         }
572     }
573 }
574
575 /* Close LOGFP, inhibit further logging and free the memory associated
576    with it.  */
577 void
578 log_close (void)
579 {
580   int i;
581
582   if (logfp)
583     fclose (logfp);
584   logfp = NULL;
585   inhibit_logging = true;
586   save_context_p = false;
587
588   for (i = 0; i < SAVED_LOG_LINES; i++)
589     free_log_line (i);
590   log_line_current = -1;
591   trailing_line = false;
592 }
593
594 /* Dump saved lines to logfp. */
595 static void
596 log_dump_context (void)
597 {
598   int num = log_line_current;
599   FILE *fp = get_log_fp ();
600   if (!fp)
601     return;
602
603   if (num == -1)
604     return;
605   if (trailing_line)
606     ROT_ADVANCE (num);
607   do
608     {
609       struct log_ln *ln = log_lines + num;
610       if (ln->content)
611         FPUTS (ln->content, fp);
612       ROT_ADVANCE (num);
613     }
614   while (num != log_line_current);
615   if (trailing_line)
616     if (log_lines[log_line_current].content)
617       FPUTS (log_lines[log_line_current].content, fp);
618   fflush (fp);
619 }
620 \f
621 /* String escape functions. */
622
623 /* Return the number of non-printable characters in SOURCE.
624    Non-printable characters are determined as per c-ctype.c.  */
625
626 static int
627 count_nonprint (const char *source)
628 {
629   const char *p;
630   int cnt;
631   for (p = source, cnt = 0; *p; p++)
632     if (!c_isprint (*p))
633       ++cnt;
634   return cnt;
635 }
636
637 /* Copy SOURCE to DEST, escaping non-printable characters.
638
639    Non-printable refers to anything outside the non-control ASCII
640    range (32-126) which means that, for example, CR, LF, and TAB are
641    considered non-printable along with ESC, BS, and other control
642    chars.  This is by design: it makes sure that messages from remote
643    servers cannot be easily used to deceive the users by mimicking
644    Wget's output.  Disallowing non-ASCII characters is another
645    necessary security measure, which makes sure that remote servers
646    cannot garble the screen or guess the local charset and perform
647    homographic attacks.
648
649    Of course, the above mandates that escnonprint only be used in
650    contexts expected to be ASCII, such as when printing host names,
651    URL components, HTTP headers, FTP server messages, and the like.
652
653    ESCAPE is the leading character of the escape sequence.  BASE
654    should be the base of the escape sequence, and must be either 8 for
655    octal or 16 for hex.
656
657    DEST must point to a location with sufficient room to store an
658    encoded version of SOURCE.  */
659
660 static void
661 copy_and_escape (const char *source, char *dest, char escape, int base)
662 {
663   const char *from = source;
664   char *to = dest;
665   unsigned char c;
666
667   /* Copy chars from SOURCE to DEST, escaping non-printable ones. */
668   switch (base)
669     {
670     case 8:
671       while ((c = *from++) != '\0')
672         if (c_isprint (c))
673           *to++ = c;
674         else
675           {
676             *to++ = escape;
677             *to++ = '0' + (c >> 6);
678             *to++ = '0' + ((c >> 3) & 7);
679             *to++ = '0' + (c & 7);
680           }
681       break;
682     case 16:
683       while ((c = *from++) != '\0')
684         if (c_isprint (c))
685           *to++ = c;
686         else
687           {
688             *to++ = escape;
689             *to++ = XNUM_TO_DIGIT (c >> 4);
690             *to++ = XNUM_TO_DIGIT (c & 0xf);
691           }
692       break;
693     default:
694       abort ();
695     }
696   *to = '\0';
697 }
698
699 #define RING_SIZE 3
700 struct ringel {
701   char *buffer;
702   int size;
703 };
704 static struct ringel ring[RING_SIZE];   /* ring data */
705
706 static const char *
707 escnonprint_internal (const char *str, char escape, int base)
708 {
709   static int ringpos;                   /* current ring position */
710   int nprcnt;
711
712   assert (base == 8 || base == 16);
713
714   nprcnt = count_nonprint (str);
715   if (nprcnt == 0)
716     /* If there are no non-printable chars in STR, don't bother
717        copying anything, just return STR.  */
718     return str;
719
720   {
721     /* Set up a pointer to the current ring position, so we can write
722        simply r->X instead of ring[ringpos].X. */
723     struct ringel *r = ring + ringpos;
724
725     /* Every non-printable character is replaced with the escape char
726        and three (or two, depending on BASE) *additional* chars.  Size
727        must also include the length of the original string and one
728        additional char for the terminating \0. */
729     int needed_size = strlen (str) + 1 + (base == 8 ? 3 * nprcnt : 2 * nprcnt);
730
731     /* If the current buffer is uninitialized or too small,
732        (re)allocate it.  */
733     if (r->buffer == NULL || r->size < needed_size)
734       {
735         r->buffer = xrealloc (r->buffer, needed_size);
736         r->size = needed_size;
737       }
738
739     copy_and_escape (str, r->buffer, escape, base);
740     ringpos = (ringpos + 1) % RING_SIZE;
741     return r->buffer;
742   }
743 }
744
745 /* Return a pointer to a static copy of STR with the non-printable
746    characters escaped as \ooo.  If there are no non-printable
747    characters in STR, STR is returned.  See copy_and_escape for more
748    information on which characters are considered non-printable.
749
750    DON'T call this function on translated strings because escaping
751    will break them.  Don't call it on literal strings from the source,
752    which are by definition trusted.  If newlines are allowed in the
753    string, escape and print it line by line because escaping the whole
754    string will convert newlines to \012.  (This is so that expectedly
755    single-line messages cannot use embedded newlines to mimic Wget's
756    output and deceive the user.)
757
758    escnonprint doesn't quote its escape character because it is notf
759    meant as a general and reversible quoting mechanism, but as a quick
760    way to defang binary junk sent by malicious or buggy servers.
761
762    NOTE: since this function can return a pointer to static data, be
763    careful to copy its result before calling it again.  However, to be
764    more useful with printf, it maintains an internal ring of static
765    buffers to return.  Currently the ring size is 3, which means you
766    can print up to three values in the same printf; if more is needed,
767    bump RING_SIZE.  */
768
769 const char *
770 escnonprint (const char *str)
771 {
772   return escnonprint_internal (str, '\\', 8);
773 }
774
775 /* Return a pointer to a static copy of STR with the non-printable
776    characters escaped as %XX.  If there are no non-printable
777    characters in STR, STR is returned.
778
779    See escnonprint for usage details.  */
780
781 const char *
782 escnonprint_uri (const char *str)
783 {
784   return escnonprint_internal (str, '%', 16);
785 }
786
787 void
788 log_cleanup (void)
789 {
790   int i;
791   for (i = 0; i < countof (ring); i++)
792     xfree_null (ring[i].buffer);
793 }
794 \f
795 /* When SIGHUP or SIGUSR1 are received, the output is redirected
796    elsewhere.  Such redirection is only allowed once. */
797 static enum { RR_NONE, RR_REQUESTED, RR_DONE } redirect_request = RR_NONE;
798 static const char *redirect_request_signal_name;
799
800 /* Redirect output to `wget-log'.  */
801
802 static void
803 redirect_output (void)
804 {
805   char *logfile;
806   logfp = unique_create (DEFAULT_LOGFILE, false, &logfile);
807   if (logfp)
808     {
809       fprintf (stderr, _("\n%s received, redirecting output to `%s'.\n"),
810                redirect_request_signal_name, logfile);
811       xfree (logfile);
812       /* Dump the context output to the newly opened log.  */
813       log_dump_context ();
814     }
815   else
816     {
817       /* Eek!  Opening the alternate log file has failed.  Nothing we
818          can do but disable printing completely. */
819       fprintf (stderr, _("\n%s received.\n"), redirect_request_signal_name);
820       fprintf (stderr, _("%s: %s; disabling logging.\n"),
821                logfile, strerror (errno));
822       inhibit_logging = true;
823     }
824   save_context_p = false;
825 }
826
827 /* Check whether a signal handler requested the output to be
828    redirected. */
829
830 static void
831 check_redirect_output (void)
832 {
833   if (redirect_request == RR_REQUESTED)
834     {
835       redirect_request = RR_DONE;
836       redirect_output ();
837     }
838 }
839
840 /* Request redirection at a convenient time.  This may be called from
841    a signal handler. */
842
843 void
844 log_request_redirect_output (const char *signal_name)
845 {
846   if (redirect_request == RR_NONE && save_context_p)
847     /* Request output redirection.  The request will be processed by
848        check_redirect_output(), which is called from entry point log
849        functions. */
850     redirect_request = RR_REQUESTED;
851   redirect_request_signal_name = signal_name;
852 }