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