]> sjero.net Git - wget/blob - src/log.c
[svn] Use new macros xnew, xnew0, xnew_array, and xnew0_array in various places.
[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    It is not possible to code this function in a "natural" way, using
354    a loop, because of the braindeadness of the varargs API.
355    Specifically, each call to vsnprintf() must be preceded by va_start
356    and followed by va_end.  And this is possible only in the function
357    that contains the `...' declaration.  The alternative would be to
358    use va_copy, but that's not portable.  */
359
360 static int
361 logvprintf (struct logvprintf_state *state, const char *fmt, va_list args)
362 {
363   char smallmsg[128];
364   char *write_ptr = smallmsg;
365   int available_size = sizeof (smallmsg);
366   int numwritten;
367   FILE *fp = get_log_fp ();
368
369   if (!save_context_p)
370     {
371       /* In the simple case just call vfprintf(), to avoid needless
372          allocation and games with vsnprintf(). */
373       vfprintf (fp, fmt, args);
374       goto flush;
375     }
376
377   if (state->allocated != 0)
378     {
379       write_ptr = state->bigmsg;
380       available_size = state->allocated;
381     }
382
383   /* The GNU coding standards advise not to rely on the return value
384      of sprintf().  However, vsnprintf() is a relatively new function
385      missing from legacy systems.  Therefore I consider it safe to
386      assume that its return value is meaningful.  On the systems where
387      vsnprintf() is not available, we use the implementation from
388      snprintf.c which does return the correct value.  */
389   numwritten = vsnprintf (write_ptr, available_size, fmt, args);
390
391   /* vsnprintf() will not step over the limit given by available_size.
392      If it fails, it will return either -1 (POSIX?) or the number of
393      characters that *would have* been written, if there had been
394      enough room (C99).  In the former case, we double the
395      available_size and malloc to get a larger buffer, and try again.
396      In the latter case, we use the returned information to build a
397      buffer of the correct size.  */
398
399   if (numwritten == -1)
400     {
401       /* Writing failed, and we don't know the needed size.  Try
402          again with doubled size. */
403       int newsize = available_size << 1;
404       state->bigmsg = xrealloc (state->bigmsg, newsize);
405       state->allocated = newsize;
406       return 0;
407     }
408   else if (numwritten >= available_size)
409     {
410       /* Writing failed, but we know exactly how much space we
411          need. */
412       int newsize = numwritten + 1;
413       state->bigmsg = xrealloc (state->bigmsg, newsize);
414       state->allocated = newsize;
415       return 0;
416     }
417
418   /* Writing succeeded. */
419   saved_append (write_ptr);
420   fputs (write_ptr, fp);
421   if (state->bigmsg)
422     xfree (state->bigmsg);
423
424  flush:
425   if (flush_log_p)
426     logflush ();
427   else
428     needs_flushing = 1;
429
430   return 1;
431 }
432
433 /* Flush LOGFP.  Useful while flushing is disabled.  */
434 void
435 logflush (void)
436 {
437   FILE *fp = get_log_fp ();
438   if (fp)
439     fflush (fp);
440   needs_flushing = 0;
441 }
442
443 /* Enable or disable log flushing. */
444 void
445 log_set_flush (int flush)
446 {
447   if (flush == flush_log_p)
448     return;
449
450   if (flush == 0)
451     {
452       /* Disable flushing by setting flush_log_p to 0. */
453       flush_log_p = 0;
454     }
455   else
456     {
457       /* Reenable flushing.  If anything was printed in no-flush mode,
458          flush the log now.  */
459       if (needs_flushing)
460         logflush ();
461       flush_log_p = 1;
462     }
463 }
464
465 /* (Temporarily) disable storing log to memory.  Returns the old
466    status of storing, with which this function can be called again to
467    reestablish storing. */
468
469 int
470 log_set_save_context (int savep)
471 {
472   int old = save_context_p;
473   save_context_p = savep;
474   return old;
475 }
476
477 /* Handle difference in va_start between pre-ANSI and ANSI C.  Note
478    that we always use `...' in function definitions and let ansi2knr
479    convert it for us.  */
480
481 #ifdef WGET_USE_STDARG
482 # define VA_START(args, arg1) va_start (args, arg1)
483 #else
484 # define VA_START(args, ignored) va_start (args)
485 #endif
486
487 /* Print a message to the screen or to the log.  The first argument
488    defines the verbosity of the message, and the rest are as in
489    printf(3).  */
490
491 void
492 logprintf (enum log_options o, const char *fmt, ...)
493 {
494   va_list args;
495   struct logvprintf_state lpstate;
496   int done;
497
498   check_redirect_output ();
499   if (inhibit_logging)
500     return;
501   CHECK_VERBOSE (o);
502
503   xzero (lpstate);
504   do
505     {
506       VA_START (args, fmt);
507       done = logvprintf (&lpstate, fmt, args);
508       va_end (args);
509     }
510   while (!done);
511 }
512
513 #ifdef ENABLE_DEBUG
514 /* The same as logprintf(), but does anything only if opt.debug is
515    non-zero.  */
516 void
517 debug_logprintf (const char *fmt, ...)
518 {
519   if (opt.debug)
520     {
521       va_list args;
522       struct logvprintf_state lpstate;
523       int done;
524
525       check_redirect_output ();
526       if (inhibit_logging)
527         return;
528
529       xzero (lpstate);
530       do
531         {
532           VA_START (args, fmt);
533           done = logvprintf (&lpstate, fmt, args);
534           va_end (args);
535         }
536       while (!done);
537     }
538 }
539 #endif /* ENABLE_DEBUG */
540 \f
541 /* Open FILE and set up a logging stream.  If FILE cannot be opened,
542    exit with status of 1.  */
543 void
544 log_init (const char *file, int appendp)
545 {
546   if (file)
547     {
548       logfp = fopen (file, appendp ? "a" : "w");
549       if (!logfp)
550         {
551           perror (opt.lfilename);
552           exit (1);
553         }
554     }
555   else
556     {
557       /* The log goes to stderr to avoid collisions with the output if
558          the user specifies `-O -'.  #### Francois Pinard suggests
559          that it's a better idea to print to stdout by default, and to
560          stderr only if the user actually specifies `-O -'.  He says
561          this inconsistency is harder to document, but is overall
562          easier on the user.  */
563       logfp = stderr;
564
565       /* If the output is a TTY, enable storing, which will make Wget
566          remember the last several printed messages, to be able to
567          dump them to a log file in case SIGHUP or SIGUSR1 is received
568          (or Ctrl+Break is pressed under Windows).  */
569       if (1
570 #ifdef HAVE_ISATTY
571           && isatty (fileno (logfp))
572 #endif
573           )
574         {
575           save_context_p = 1;
576         }
577     }
578 }
579
580 /* Close LOGFP, inhibit further logging and free the memory associated
581    with it.  */
582 void
583 log_close (void)
584 {
585   int i;
586
587   if (logfp)
588     fclose (logfp);
589   logfp = NULL;
590   inhibit_logging = 1;
591   save_context_p = 0;
592
593   for (i = 0; i < SAVED_LOG_LINES; i++)
594     free_log_line (i);
595   log_line_current = -1;
596   trailing_line = 0;
597 }
598
599 /* Dump saved lines to logfp. */
600 static void
601 log_dump_context (void)
602 {
603   int num = log_line_current;
604   FILE *fp = get_log_fp ();
605   if (!fp)
606     return;
607
608   if (num == -1)
609     return;
610   if (trailing_line)
611     ROT_ADVANCE (num);
612   do
613     {
614       struct log_ln *ln = log_lines + num;
615       if (ln->content)
616         fputs (ln->content, fp);
617       ROT_ADVANCE (num);
618     }
619   while (num != log_line_current);
620   if (trailing_line)
621     if (log_lines[log_line_current].content)
622       fputs (log_lines[log_line_current].content, fp);
623   fflush (fp);
624 }
625 \f
626 /* When SIGHUP or SIGUSR1 are received, the output is redirected
627    elsewhere.  Such redirection is only allowed once. */
628 enum { RR_NONE, RR_REQUESTED, RR_DONE } redirect_request = RR_NONE;
629 static const char *redirect_request_signal_name;
630
631 /* Redirect output to `wget-log'.  */
632
633 static void
634 redirect_output (void)
635 {
636   char *logfile = unique_name (DEFAULT_LOGFILE, 0);
637   fprintf (stderr, _("\n%s received, redirecting output to `%s'.\n"),
638            redirect_request_signal_name, logfile);
639   logfp = fopen (logfile, "w");
640   if (!logfp)
641     {
642       /* Eek!  Opening the alternate log file has failed.  Nothing we
643          can do but disable printing completely. */
644       fprintf (stderr, _("%s: %s; disabling logging.\n"),
645                logfile, strerror (errno));
646       inhibit_logging = 1;
647     }
648   else
649     {
650       /* Dump the context output to the newly opened log.  */
651       log_dump_context ();
652     }
653   xfree (logfile);
654   save_context_p = 0;
655 }
656
657 /* Check whether a signal handler requested the output to be
658    redirected. */
659
660 static void
661 check_redirect_output (void)
662 {
663   if (redirect_request == RR_REQUESTED)
664     {
665       redirect_request = RR_DONE;
666       redirect_output ();
667     }
668 }
669
670 /* Request redirection at a convenient time.  This may be called from
671    a signal handler. */
672
673 void
674 log_request_redirect_output (const char *signal_name)
675 {
676   if (redirect_request == RR_NONE && save_context_p)
677     /* Request output redirection.  The request will be processed by
678        check_redirect_output(), which is called from entry point log
679        functions. */
680     redirect_request = RR_REQUESTED;
681   redirect_request_signal_name = signal_name;
682 }