📄 log.c
字号:
struct logvprintf_state { char *bigmsg; int expected_size; int allocated;};/* Print a message to the log. A copy of message will be saved to saved_log, for later reusal by log_dump_context(). It is not possible to code this function in a "natural" way, using a loop, because of the braindeadness of the varargs API. Specifically, each call to vsnprintf() must be preceded by va_start and followed by va_end. And this is possible only in the function that contains the `...' declaration. The alternative would be to use va_copy, but that's not portable. */static intlogvprintf (struct logvprintf_state *state, const char *fmt, va_list args){ char smallmsg[128]; char *write_ptr = smallmsg; int available_size = sizeof (smallmsg); int numwritten; FILE *fp = get_log_fp (); if (!save_context_p) { /* In the simple case just call vfprintf(), to avoid needless allocation and games with vsnprintf(). */ vfprintf (fp, fmt, args); goto flush; } if (state->allocated != 0) { write_ptr = state->bigmsg; available_size = state->allocated; } /* The GNU coding standards advise not to rely on the return value of sprintf(). However, vsnprintf() is a relatively new function missing from legacy systems. Therefore I consider it safe to assume that its return value is meaningful. On the systems where vsnprintf() is not available, we use the implementation from snprintf.c which does return the correct value. */ numwritten = vsnprintf (write_ptr, available_size, fmt, args); /* vsnprintf() will not step over the limit given by available_size. If it fails, it will return either -1 (POSIX?) or the number of characters that *would have* been written, if there had been enough room (C99). In the former case, we double the available_size and malloc to get a larger buffer, and try again. In the latter case, we use the returned information to build a buffer of the correct size. */ if (numwritten == -1) { /* Writing failed, and we don't know the needed size. Try again with doubled size. */ int newsize = available_size << 1; state->bigmsg = xrealloc (state->bigmsg, newsize); state->allocated = newsize; return 0; } else if (numwritten >= available_size) { /* Writing failed, but we know exactly how much space we need. */ int newsize = numwritten + 1; state->bigmsg = xrealloc (state->bigmsg, newsize); state->allocated = newsize; return 0; } /* Writing succeeded. */ saved_append (write_ptr); fputs (write_ptr, fp); if (state->bigmsg) xfree (state->bigmsg); flush: if (flush_log_p) logflush (); else needs_flushing = 1; return 1;}/* Flush LOGFP. Useful while flushing is disabled. */voidlogflush (void){ FILE *fp = get_log_fp (); if (fp) fflush (fp); needs_flushing = 0;}/* Enable or disable log flushing. */voidlog_set_flush (int flush){ if (flush == flush_log_p) return; if (flush == 0) { /* Disable flushing by setting flush_log_p to 0. */ flush_log_p = 0; } else { /* Reenable flushing. If anything was printed in no-flush mode, flush the log now. */ if (needs_flushing) logflush (); flush_log_p = 1; }}/* (Temporarily) disable storing log to memory. Returns the old status of storing, with which this function can be called again to reestablish storing. */intlog_set_save_context (int savep){ int old = save_context_p; save_context_p = savep; return old;}/* Handle difference in va_start between pre-ANSI and ANSI C. Note that we always use `...' in function definitions and let ansi2knr convert it for us. */#ifdef WGET_USE_STDARG# define VA_START(args, arg1) va_start (args, arg1)#else# define VA_START(args, ignored) va_start (args)#endif/* Print a message to the screen or to the log. The first argument defines the verbosity of the message, and the rest are as in printf(3). */voidlogprintf (enum log_options o, const char *fmt, ...){ va_list args; struct logvprintf_state lpstate; int done; check_redirect_output (); if (inhibit_logging) return; CHECK_VERBOSE (o); memset (&lpstate, '\0', sizeof (lpstate)); do { VA_START (args, fmt); done = logvprintf (&lpstate, fmt, args); va_end (args); } while (!done);}#ifdef ENABLE_DEBUG/* The same as logprintf(), but does anything only if opt.debug is non-zero. */voiddebug_logprintf (const char *fmt, ...){ if (opt.debug) { va_list args; struct logvprintf_state lpstate; int done; check_redirect_output (); if (inhibit_logging) return; memset (&lpstate, '\0', sizeof (lpstate)); do { VA_START (args, fmt); done = logvprintf (&lpstate, fmt, args); va_end (args); } while (!done); }}#endif /* ENABLE_DEBUG *//* Open FILE and set up a logging stream. If FILE cannot be opened, exit with status of 1. */voidlog_init (const char *file, int appendp){ if (file) { logfp = fopen (file, appendp ? "a" : "w"); if (!logfp) { perror (opt.lfilename); exit (1); } } else { /* The log goes to stderr to avoid collisions with the output if the user specifies `-O -'. #### Francois Pinard suggests that it's a better idea to print to stdout by default, and to stderr only if the user actually specifies `-O -'. He says this inconsistency is harder to document, but is overall easier on the user. */ logfp = stderr; /* If the output is a TTY, enable storing, which will make Wget remember the last several printed messages, to be able to dump them to a log file in case SIGHUP or SIGUSR1 is received (or Ctrl+Break is pressed under Windows). */ if (1#ifdef HAVE_ISATTY && isatty (fileno (logfp))#endif ) { save_context_p = 1; } }}/* Close LOGFP, inhibit further logging and free the memory associated with it. */voidlog_close (void){ int i; if (logfp) fclose (logfp); logfp = NULL; inhibit_logging = 1; save_context_p = 0; for (i = 0; i < SAVED_LOG_LINES; i++) free_log_line (i); log_line_current = -1; trailing_line = 0;}/* Dump saved lines to logfp. */static voidlog_dump_context (void){ int num = log_line_current; FILE *fp = get_log_fp (); if (!fp) return; if (num == -1) return; if (trailing_line) ROT_ADVANCE (num); do { struct log_ln *ln = log_lines + num; if (ln->content) fputs (ln->content, fp); ROT_ADVANCE (num); } while (num != log_line_current); if (trailing_line) if (log_lines[log_line_current].content) fputs (log_lines[log_line_current].content, fp); fflush (fp);}/* When SIGHUP or SIGUSR1 are received, the output is redirected elsewhere. Such redirection is only allowed once. */enum { RR_NONE, RR_REQUESTED, RR_DONE } redirect_request = RR_NONE;static const char *redirect_request_signal_name;/* Redirect output to `wget-log'. */static voidredirect_output (void){ char *logfile = unique_name (DEFAULT_LOGFILE, 0); fprintf (stderr, _("\n%s received, redirecting output to `%s'.\n"), redirect_request_signal_name, logfile); logfp = fopen (logfile, "w"); if (!logfp) { /* Eek! Opening the alternate log file has failed. Nothing we can do but disable printing completely. */ fprintf (stderr, _("%s: %s; disabling logging.\n"), logfile, strerror (errno)); inhibit_logging = 1; } else { /* Dump the context output to the newly opened log. */ log_dump_context (); } xfree (logfile); save_context_p = 0;}/* Check whether a signal handler requested the output to be redirected. */static voidcheck_redirect_output (void){ if (redirect_request == RR_REQUESTED) { redirect_request = RR_DONE; redirect_output (); }}/* Request redirection at a convenient time. This may be called from a signal handler. */voidlog_request_redirect_output (const char *signal_name){ if (redirect_request == RR_NONE && save_context_p) /* Request output redirection. The request will be processed by check_redirect_output(), which is called from entry point log functions. */ redirect_request = RR_REQUESTED; redirect_request_signal_name = signal_name;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -