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