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