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