]> sjero.net Git - wget/blob - src/log.c
[svn] Update the license to include the OpenSSL exception.
[wget] / src / log.c
1 /* Messages logging.
2    Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables.  You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL".  If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so.  If you do not wish to do
28 so, delete this exception statement from your version.  */
29
30 #include <config.h>
31
32 /* Use stdarg only if the compiler supports ANSI C and stdarg.h is
33    present.  We check for both because there are configurations where
34    stdarg.h exists, but doesn't work. */
35 #undef WGET_USE_STDARG
36 #ifdef __STDC__
37 # ifdef HAVE_STDARG_H
38 #  define WGET_USE_STDARG
39 # endif
40 #endif
41
42 #include <stdio.h>
43 #ifdef HAVE_STRING_H
44 # include <string.h>
45 #else
46 # include <strings.h>
47 #endif
48 #include <stdlib.h>
49 #ifdef WGET_USE_STDARG
50 # include <stdarg.h>
51 #else
52 # include <varargs.h>
53 #endif
54 #ifdef HAVE_UNISTD_H
55 # include <unistd.h>
56 #endif
57 #include <assert.h>
58 #include <errno.h>
59
60 #include "wget.h"
61 #include "utils.h"
62
63 #ifndef errno
64 extern int errno;
65 #endif
66
67 /* This file impplement support for "logging".  Logging means printing
68    output, plus several additional features:
69
70    - Cataloguing output by importance.  You can specify that a log
71    message is "verbose" or "debug", and it will not be printed unless
72    in verbose or debug mode, respectively.
73
74    - Redirecting the log to the file.  When Wget's output goes to the
75    terminal, and Wget receives SIGHUP, all further output is
76    redirected to a log file.  When this is the case, Wget can also
77    print the last several lines of "context" to the log file so that
78    it does not begin in the middle of a line.  For this to work, the
79    logging code stores the last several lines of context.  Callers may
80    request for certain output not to be stored.
81
82    - Inhibiting output.  When Wget receives SIGHUP, but redirecting
83    the output fails, logging is inhibited.  */
84
85 \f
86 /* The file descriptor used for logging.  This is NULL before log_init
87    is called; logging functions log to stderr then.  log_init sets it
88    either to stderr or to a file pointer obtained from fopen().  If
89    logging is inhibited, logfp is set back to NULL. */
90 static FILE *logfp;
91
92 /* If non-zero, it means logging is inhibited, i.e. nothing is printed
93    or stored.  */
94 static int inhibit_logging;
95
96 /* Whether the last output lines are stored for use as context.  */
97 static int save_context_p;
98
99 /* Whether the log is flushed after each command. */
100 static int flush_log_p = 1;
101
102 /* Whether any output has been received while flush_log_p was 0. */
103 static int needs_flushing;
104
105 /* In the event of a hang-up, and if its output was on a TTY, Wget
106    redirects its output to `wget-log'.
107
108    For the convenience of reading this newly-created log, we store the
109    last several lines ("screenful", hence the choice of 24) of Wget
110    output, and dump them as context when the time comes.  */
111 #define SAVED_LOG_LINES 24
112
113 /* log_lines is a circular buffer that stores SAVED_LOG_LINES lines of
114    output.  log_line_current always points to the position in the
115    buffer that will be written to next.  When log_line_current reaches
116    SAVED_LOG_LINES, it is reset to zero.
117
118    The problem here is that we'd have to either (re)allocate and free
119    strings all the time, or limit the lines to an arbitrary number of
120    characters.  Instead of settling for either of these, we do both:
121    if the line is smaller than a certain "usual" line length (128
122    chars by default), a preallocated memory is used.  The rare lines
123    that are longer than 128 characters are malloc'ed and freed
124    separately.  This gives good performance with minimum memory
125    consumption and fragmentation.  */
126
127 #define STATIC_LENGTH 128
128
129 static struct log_ln {
130   char static_line[STATIC_LENGTH + 1]; /* statically allocated
131                                           line. */
132   char *malloced_line;          /* malloc'ed line, for lines of output
133                                    larger than 80 characters. */
134   char *content;                /* this points either to malloced_line
135                                    or to the appropriate static_line.
136                                    If this is NULL, it means the line
137                                    has not yet been used. */
138 } log_lines[SAVED_LOG_LINES];
139
140 /* The current position in the ring. */
141 static int log_line_current = -1;
142
143 /* Whether the most recently written line was "trailing", i.e. did not
144    finish with \n.  This is an important piece of information because
145    the code is always careful to append data to trailing lines, rather
146    than create new ones.  */
147 static int trailing_line;
148
149 static void check_redirect_output PARAMS ((void));
150 \f
151 #define ROT_ADVANCE(num) do {                   \
152   if (++num >= SAVED_LOG_LINES)                 \
153     num = 0;                                    \
154 } while (0)
155
156 /* Free the log line index with NUM.  This calls free on
157    ln->malloced_line if it's non-NULL, and it also resets
158    ln->malloced_line and ln->content to NULL.  */
159
160 static void
161 free_log_line (int num)
162 {
163   struct log_ln *ln = log_lines + num;
164   if (ln->malloced_line)
165     {
166       xfree (ln->malloced_line);
167       ln->malloced_line = NULL;
168     }
169   ln->content = NULL;
170 }
171
172 /* Append bytes in the range [start, end) to one line in the log.  The
173    region is not supposed to contain newlines, except for the last
174    character (at end[-1]).  */
175
176 static void
177 saved_append_1 (const char *start, const char *end)
178 {
179   int len = end - start;
180   if (!len)
181     return;
182
183   /* First, check whether we need to append to an existing line or to
184      create a new one.  */
185   if (!trailing_line)
186     {
187       /* Create a new line. */
188       struct log_ln *ln;
189
190       if (log_line_current == -1)
191         log_line_current = 0;
192       else
193         free_log_line (log_line_current);
194       ln = log_lines + log_line_current;
195       if (len > STATIC_LENGTH)
196         {
197           ln->malloced_line = strdupdelim (start, end);
198           ln->content = ln->malloced_line;
199         }
200       else
201         {
202           memcpy (ln->static_line, start, len);
203           ln->static_line[len] = '\0';
204           ln->content = ln->static_line;
205         }
206     }
207   else
208     {
209       /* Append to the last line.  If the line is malloc'ed, we just
210          call realloc and append the new string.  If the line is
211          static, we have to check whether appending the new string
212          would make it exceed STATIC_LENGTH characters, and if so,
213          convert it to malloc(). */
214       struct log_ln *ln = log_lines + log_line_current;
215       if (ln->malloced_line)
216         {
217           /* Resize malloc'ed line and append. */
218           int old_len = strlen (ln->malloced_line);
219           ln->malloced_line = xrealloc (ln->malloced_line, old_len + len + 1);
220           memcpy (ln->malloced_line + old_len, start, len);
221           ln->malloced_line[old_len + len] = '\0';
222           /* might have changed due to realloc */
223           ln->content = ln->malloced_line;
224         }
225       else
226         {
227           int old_len = strlen (ln->static_line);
228           if (old_len + len > STATIC_LENGTH)
229             {
230               /* Allocate memory and concatenate the old and the new
231                  contents. */
232               ln->malloced_line = xmalloc (old_len + len + 1);
233               memcpy (ln->malloced_line, ln->static_line,
234                       old_len);
235               memcpy (ln->malloced_line + old_len, start, len);
236               ln->malloced_line[old_len + len] = '\0';
237               ln->content = ln->malloced_line;
238             }
239           else
240             {
241               /* Just append to the old, statically allocated
242                  contents.  */
243               memcpy (ln->static_line + old_len, start, len);
244               ln->static_line[old_len + len] = '\0';
245               ln->content = ln->static_line;
246             }
247         }
248     }
249   trailing_line = !(end[-1] == '\n');
250   if (!trailing_line)
251     ROT_ADVANCE (log_line_current);
252 }
253
254 /* Log the contents of S, as explained above.  If S consists of
255    multiple lines, they are logged separately.  If S does not end with
256    a newline, it will form a "trailing" line, to which things will get
257    appended the next time this function is called.  */
258
259 static void
260 saved_append (const char *s)
261 {
262   while (*s)
263     {
264       const char *end = strchr (s, '\n');
265       if (!end)
266         end = s + strlen (s);
267       else
268         ++end;
269       saved_append_1 (s, end);
270       s = end;
271     }
272 }
273 \f
274 /* Check X against opt.verbose and opt.quiet.  The semantics is as
275    follows:
276
277    * LOG_ALWAYS - print the message unconditionally;
278
279    * LOG_NOTQUIET - print the message if opt.quiet is non-zero;
280
281    * LOG_NONVERBOSE - print the message if opt.verbose is zero;
282
283    * LOG_VERBOSE - print the message if opt.verbose is non-zero.  */
284 #define CHECK_VERBOSE(x)                        \
285   switch (x)                                    \
286     {                                           \
287     case LOG_ALWAYS:                            \
288       break;                                    \
289     case LOG_NOTQUIET:                          \
290       if (opt.quiet)                            \
291         return;                                 \
292       break;                                    \
293     case LOG_NONVERBOSE:                        \
294       if (opt.verbose || opt.quiet)             \
295         return;                                 \
296       break;                                    \
297     case LOG_VERBOSE:                           \
298       if (!opt.verbose)                         \
299         return;                                 \
300     }
301
302 /* Returns the file descriptor for logging.  This is LOGFP, except if
303    called before log_init, in which case it returns stderr.  This is
304    useful in case someone calls a logging function before log_init.
305
306    If logging is inhibited, return NULL.  */
307
308 static FILE *
309 get_log_fp (void)
310 {
311   if (inhibit_logging)
312     return NULL;
313   if (logfp)
314     return logfp;
315   return stderr;
316 }
317 \f
318 /* Log a literal string S.  The string is logged as-is, without a
319    newline appended.  */
320
321 void
322 logputs (enum log_options o, const char *s)
323 {
324   FILE *fp;
325
326   check_redirect_output ();
327   if (!(fp = get_log_fp ()))
328     return;
329   CHECK_VERBOSE (o);
330
331   fputs (s, fp);
332   if (save_context_p)
333     saved_append (s);
334   if (flush_log_p)
335     logflush ();
336   else
337     needs_flushing = 1;
338 }
339
340 struct logvprintf_state {
341   char *bigmsg;
342   int expected_size;
343   int allocated;
344 };
345
346 /* Print a message to the log.  A copy of message will be saved to
347    saved_log, for later reusal by log_dump_context().
348
349    It is not possible to code this function in a "natural" way, using
350    a loop, because of the braindeadness of the varargs API.
351    Specifically, each call to vsnprintf() must be preceded by va_start
352    and followed by va_end.  And this is possible only in the function
353    that contains the `...' declaration.  The alternative would be to
354    use va_copy, but that's not portable.  */
355
356 static int
357 logvprintf (struct logvprintf_state *state, const char *fmt, va_list args)
358 {
359   char smallmsg[128];
360   char *write_ptr = smallmsg;
361   int available_size = sizeof (smallmsg);
362   int numwritten;
363   FILE *fp = get_log_fp ();
364
365   if (!save_context_p)
366     {
367       /* In the simple case just call vfprintf(), to avoid needless
368          allocation and games with vsnprintf(). */
369       vfprintf (fp, fmt, args);
370       goto flush;
371     }
372
373   if (state->allocated != 0)
374     {
375       write_ptr = state->bigmsg;
376       available_size = state->allocated;
377     }
378
379   /* The GNU coding standards advise not to rely on the return value
380      of sprintf().  However, vsnprintf() is a relatively new function
381      missing from legacy systems.  Therefore I consider it safe to
382      assume that its return value is meaningful.  On the systems where
383      vsnprintf() is not available, we use the implementation from
384      snprintf.c which does return the correct value.  */
385   numwritten = vsnprintf (write_ptr, available_size, fmt, args);
386
387   /* vsnprintf() will not step over the limit given by available_size.
388      If it fails, it will return either -1 (POSIX?) or the number of
389      characters that *would have* been written, if there had been
390      enough room.  In the former case, we double the available_size
391      and malloc() to get a larger buffer, and try again.  In the
392      latter case, we use the returned information to build a buffer of
393      the correct size.  */
394
395   if (numwritten == -1)
396     {
397       /* Writing failed, and we don't know the needed size.  Try
398          again with doubled size. */
399       int newsize = available_size << 1;
400       state->bigmsg = xrealloc (state->bigmsg, newsize);
401       state->allocated = newsize;
402       return 0;
403     }
404   else if (numwritten >= available_size)
405     {
406       /* Writing failed, but we know exactly how much space we
407          need. */
408       int newsize = numwritten + 1;
409       state->bigmsg = xrealloc (state->bigmsg, newsize);
410       state->allocated = newsize;
411       return 0;
412     }
413
414   /* Writing succeeded. */
415   saved_append (write_ptr);
416   fputs (write_ptr, fp);
417   if (state->bigmsg)
418     xfree (state->bigmsg);
419
420  flush:
421   if (flush_log_p)
422     logflush ();
423   else
424     needs_flushing = 1;
425
426   return 1;
427 }
428
429 /* Flush LOGFP.  Useful while flushing is disabled.  */
430 void
431 logflush (void)
432 {
433   FILE *fp = get_log_fp ();
434   if (fp)
435     fflush (fp);
436   needs_flushing = 0;
437 }
438
439 /* Enable or disable log flushing. */
440 void
441 log_set_flush (int flush)
442 {
443   if (flush == flush_log_p)
444     return;
445
446   if (flush == 0)
447     {
448       /* Disable flushing by setting flush_log_p to 0. */
449       flush_log_p = 0;
450     }
451   else
452     {
453       /* Reenable flushing.  If anything was printed in no-flush mode,
454          flush the log now.  */
455       if (needs_flushing)
456         logflush ();
457       flush_log_p = 1;
458     }
459 }
460
461 /* (Temporarily) disable storing log to memory.  Returns the old
462    status of storing, with which this function can be called again to
463    reestablish storing. */
464
465 int
466 log_set_save_context (int savep)
467 {
468   int old = save_context_p;
469   save_context_p = savep;
470   return old;
471 }
472
473 #ifdef WGET_USE_STDARG
474 # define VA_START_1(arg1_type, arg1, args) va_start(args, arg1)
475 # define VA_START_2(arg1_type, arg1, arg2_type, arg2, args) va_start(args, arg2)
476 #else  /* not WGET_USE_STDARG */
477 # define VA_START_1(arg1_type, arg1, args) do { \
478   va_start (args);                                                      \
479   arg1 = va_arg (args, arg1_type);                                      \
480 } while (0)
481 # define VA_START_2(arg1_type, arg1, arg2_type, arg2, args) do {        \
482   va_start (args);                                                      \
483   arg1 = va_arg (args, arg1_type);                                      \
484   arg2 = va_arg (args, arg2_type);                                      \
485 } while (0)
486 #endif /* not WGET_USE_STDARG */
487
488 /* Portability with pre-ANSI compilers makes these two functions look
489    like @#%#@$@#$.  */
490
491 #ifdef WGET_USE_STDARG
492 void
493 logprintf (enum log_options o, const char *fmt, ...)
494 #else  /* not WGET_USE_STDARG */
495 void
496 logprintf (va_alist)
497      va_dcl
498 #endif /* not WGET_USE_STDARG */
499 {
500   va_list args;
501   struct logvprintf_state lpstate;
502   int done;
503
504 #ifndef WGET_USE_STDARG
505   enum log_options o;
506   const char *fmt;
507
508   /* Perform a "dry run" of VA_START_2 to get the value of O. */
509   VA_START_2 (enum log_options, o, char *, fmt, args);
510   va_end (args);
511 #endif
512
513   check_redirect_output ();
514   if (inhibit_logging)
515     return;
516   CHECK_VERBOSE (o);
517
518   memset (&lpstate, '\0', sizeof (lpstate));
519   do
520     {
521       VA_START_2 (enum log_options, o, char *, fmt, args);
522       done = logvprintf (&lpstate, fmt, args);
523       va_end (args);
524     }
525   while (!done);
526 }
527
528 #ifdef DEBUG
529 /* The same as logprintf(), but does anything only if opt.debug is
530    non-zero.  */
531 #ifdef WGET_USE_STDARG
532 void
533 debug_logprintf (const char *fmt, ...)
534 #else  /* not WGET_USE_STDARG */
535 void
536 debug_logprintf (va_alist)
537      va_dcl
538 #endif /* not WGET_USE_STDARG */
539 {
540   if (opt.debug)
541     {
542       va_list args;
543 #ifndef WGET_USE_STDARG
544       const char *fmt;
545 #endif
546       struct logvprintf_state lpstate;
547       int done;
548
549       check_redirect_output ();
550       if (inhibit_logging)
551         return;
552
553       memset (&lpstate, '\0', sizeof (lpstate));
554       do
555         {
556           VA_START_1 (char *, fmt, args);
557           done = logvprintf (&lpstate, fmt, args);
558           va_end (args);
559         }
560       while (!done);
561     }
562 }
563 #endif /* DEBUG */
564 \f
565 /* Open FILE and set up a logging stream.  If FILE cannot be opened,
566    exit with status of 1.  */
567 void
568 log_init (const char *file, int appendp)
569 {
570   if (file)
571     {
572       logfp = fopen (file, appendp ? "a" : "w");
573       if (!logfp)
574         {
575           perror (opt.lfilename);
576           exit (1);
577         }
578     }
579   else
580     {
581       /* The log goes to stderr to avoid collisions with the output if
582          the user specifies `-O -'.  #### Francois Pinard suggests
583          that it's a better idea to print to stdout by default, and to
584          stderr only if the user actually specifies `-O -'.  He says
585          this inconsistency is harder to document, but is overall
586          easier on the user.  */
587       logfp = stderr;
588
589       /* If the output is a TTY, enable storing, which will make Wget
590          remember all the printed messages, to be able to dump them to
591          a log file in case SIGHUP or SIGUSR1 is received (or
592          Ctrl+Break is pressed under Windows).  */
593       if (1
594 #ifdef HAVE_ISATTY
595           && isatty (fileno (logfp))
596 #endif
597           )
598         {
599           save_context_p = 1;
600         }
601     }
602 }
603
604 /* Close LOGFP, inhibit further logging and free the memory associated
605    with it.  */
606 void
607 log_close (void)
608 {
609   int i;
610
611   if (logfp)
612     fclose (logfp);
613   logfp = NULL;
614   inhibit_logging = 1;
615   save_context_p = 0;
616
617   for (i = 0; i < SAVED_LOG_LINES; i++)
618     free_log_line (i);
619   log_line_current = -1;
620   trailing_line = 0;
621 }
622
623 /* Dump saved lines to logfp. */
624 static void
625 log_dump_context (void)
626 {
627   int num = log_line_current;
628   FILE *fp = get_log_fp ();
629   if (!fp)
630     return;
631
632   if (num == -1)
633     return;
634   if (trailing_line)
635     ROT_ADVANCE (num);
636   do
637     {
638       struct log_ln *ln = log_lines + num;
639       if (ln->content)
640         fputs (ln->content, fp);
641       ROT_ADVANCE (num);
642     }
643   while (num != log_line_current);
644   if (trailing_line)
645     if (log_lines[log_line_current].content)
646       fputs (log_lines[log_line_current].content, fp);
647   fflush (fp);
648 }
649 \f
650 /* When SIGHUP or SIGUSR1 are received, the output is redirected
651    elsewhere.  Such redirection is only allowed once. */
652 enum { RR_NONE, RR_REQUESTED, RR_DONE } redirect_request = RR_NONE;
653 static const char *redirect_request_signal_name;
654
655 /* Redirect output to `wget-log'.  */
656
657 static void
658 redirect_output (void)
659 {
660   char *logfile = unique_name (DEFAULT_LOGFILE);
661   fprintf (stderr, _("\n%s received, redirecting output to `%s'.\n"),
662            redirect_request_signal_name, logfile);
663   logfp = fopen (logfile, "w");
664   if (!logfp)
665     {
666       /* Eek!  Opening the alternate log file has failed.  Nothing we
667          can do but disable printing completely. */
668       fprintf (stderr, _("%s: %s; disabling logging.\n"),
669                logfile, strerror (errno));
670       inhibit_logging = 1;
671     }
672   else
673     {
674       /* Dump the context output to the newly opened log.  */
675       log_dump_context ();
676     }
677   xfree (logfile);
678   save_context_p = 0;
679 }
680
681 /* Check whether a signal handler requested the output to be
682    redirected. */
683
684 static void
685 check_redirect_output (void)
686 {
687   if (redirect_request == RR_REQUESTED)
688     {
689       redirect_request = RR_DONE;
690       redirect_output ();
691     }
692 }
693
694 /* Request redirection at a convenient time.  This may be called from
695    a signal handler. */
696
697 void
698 log_request_redirect_output (const char *signal_name)
699 {
700   if (redirect_request == RR_NONE && save_context_p)
701     /* Request output redirection.  The request will be processed by
702        check_redirect_output(), which is called from entry point log
703        functions. */
704     redirect_request = RR_REQUESTED;
705   redirect_request_signal_name = signal_name;
706 }