1/* Messages logging.
2   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3   2007, 2008, 2009 Free Software Foundation, Inc.
4
5This file is part of GNU Wget.
6
7GNU Wget is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
11
12GNU Wget is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with Wget.  If not, see <http://www.gnu.org/licenses/>.
19
20Additional permission under GNU GPL version 3 section 7
21
22If you modify this program, or any covered work, by linking or
23combining it with the OpenSSL project's OpenSSL library (or a
24modified version of that library), containing parts covered by the
25terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
26grants you additional permission to convey the resulting work.
27Corresponding Source for a non-source form of such a combination
28shall include the source code for the parts of OpenSSL used as well
29as 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 implements 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
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. */
82static FILE *logfp;
83
84/* If true, it means logging is inhibited, i.e. nothing is printed or
85   stored.  */
86static bool inhibit_logging;
87
88/* Whether the last output lines are stored for use as context.  */
89static bool save_context_p;
90
91/* Whether the log is flushed after each command. */
92static bool flush_log_p = true;
93
94/* Whether any output has been received while flush_log_p was 0. */
95static 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
121static 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. */
133static 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.  */
139static bool trailing_line;
140
141static void check_redirect_output (void);
142
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
152static void
153free_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
168static void
169saved_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
251static void
252saved_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
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
300static FILE *
301get_log_fp (void)
302{
303  if (inhibit_logging)
304    return NULL;
305  if (logfp)
306    return logfp;
307  return stderr;
308}
309
310/* Log a literal string S.  The string is logged as-is, without a
311   newline appended.  */
312
313void
314logputs (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
332struct 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
352static bool
353log_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.  */
427void
428logflush (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. */
449void
450log_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
474bool
475log_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
486void
487logprintf (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.  */
511void
512debug_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
536/* Open FILE and set up a logging stream.  If FILE cannot be opened,
537   exit with status of 1.  */
538void
539log_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.  */
577void
578log_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. */
595static void
596log_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
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
626static int
627count_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
660static void
661copy_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
700struct ringel {
701  char *buffer;
702  int size;
703};
704static struct ringel ring[RING_SIZE];   /* ring data */
705
706static const char *
707escnonprint_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
769const char *
770escnonprint (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
781const char *
782escnonprint_uri (const char *str)
783{
784  return escnonprint_internal (str, '%', 16);
785}
786
787void
788log_cleanup (void)
789{
790  size_t i;
791  for (i = 0; i < countof (ring); i++)
792    xfree_null (ring[i].buffer);
793}
794
795/* When SIGHUP or SIGUSR1 are received, the output is redirected
796   elsewhere.  Such redirection is only allowed once. */
797static enum { RR_NONE, RR_REQUESTED, RR_DONE } redirect_request = RR_NONE;
798static const char *redirect_request_signal_name;
799
800/* Redirect output to `wget-log'.  */
801
802static void
803redirect_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, quote (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
830static void
831check_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
843void
844log_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}
853