📄 log.c
字号:
logflush (void){ FILE *fp = get_log_fp (); if (fp) fflush (fp); needs_flushing = false;}/* Enable or disable log flushing. */voidlog_set_flush (bool flush){ if (flush == flush_log_p) return; if (flush == false) { /* Disable flushing by setting flush_log_p to 0. */ flush_log_p = false; } else { /* Reenable flushing. If anything was printed in no-flush mode, flush the log now. */ if (needs_flushing) logflush (); flush_log_p = true; }}/* (Temporarily) disable storing log to memory. Returns the old status of storing, with which this function can be called again to reestablish storing. */boollog_set_save_context (bool savep){ bool old = save_context_p; save_context_p = savep; return old;}/* 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; bool done; check_redirect_output (); if (inhibit_logging) return; CHECK_VERBOSE (o); xzero (lpstate); do { va_start (args, fmt); done = log_vprintf_internal (&lpstate, fmt, args); va_end (args); } while (!done);}#ifdef ENABLE_DEBUG/* The same as logprintf(), but does anything only if opt.debug is true. */voiddebug_logprintf (const char *fmt, ...){ if (opt.debug) { va_list args; struct logvprintf_state lpstate; bool done; check_redirect_output (); if (inhibit_logging) return; xzero (lpstate); do { va_start (args, fmt); done = log_vprintf_internal (&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, bool appendp){ if (file) { logfp = fopen (file, appendp ? "a" : "w"); if (!logfp) { fprintf (stderr, "%s: %s: %s\n", exec_name, file, strerror (errno)); 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 (1#ifdef HAVE_ISATTY && isatty (fileno (logfp))#endif ) { /* If the output is a TTY, enable save context, i.e. store the most recent several messages ("context") and dump them to a log file in case SIGHUP or SIGUSR1 is received (or Ctrl+Break is pressed under Windows). */ save_context_p = true; } }}/* 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 = true; save_context_p = false; for (i = 0; i < SAVED_LOG_LINES; i++) free_log_line (i); log_line_current = -1; trailing_line = false;}/* 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);}/* String escape functions. *//* Return the number of non-printable characters in SOURCE. Non-printable characters are determined as per safe-ctype.c. */static intcount_nonprint (const char *source){ const char *p; int cnt; for (p = source, cnt = 0; *p; p++) if (!ISPRINT (*p)) ++cnt; return cnt;}/* Copy SOURCE to DEST, escaping non-printable characters. Non-printable refers to anything outside the non-control ASCII range (32-126) which means that, for example, CR, LF, and TAB are considered non-printable along with ESC, BS, and other control chars. This is by design: it makes sure that messages from remote servers cannot be easily used to deceive the users by mimicking Wget's output. Disallowing non-ASCII characters is another necessary security measure, which makes sure that remote servers cannot garble the screen or guess the local charset and perform homographic attacks. Of course, the above mandates that escnonprint only be used in contexts expected to be ASCII, such as when printing host names, URL components, HTTP headers, FTP server messages, and the like. ESCAPE is the leading character of the escape sequence. BASE should be the base of the escape sequence, and must be either 8 for octal or 16 for hex. DEST must point to a location with sufficient room to store an encoded version of SOURCE. */static voidcopy_and_escape (const char *source, char *dest, char escape, int base){ const char *from = source; char *to = dest; unsigned char c; /* Copy chars from SOURCE to DEST, escaping non-printable ones. */ switch (base) { case 8: while ((c = *from++) != '\0') if (ISPRINT (c)) *to++ = c; else { *to++ = escape; *to++ = '0' + (c >> 6); *to++ = '0' + ((c >> 3) & 7); *to++ = '0' + (c & 7); } break; case 16: while ((c = *from++) != '\0') if (ISPRINT (c)) *to++ = c; else { *to++ = escape; *to++ = XNUM_TO_DIGIT (c >> 4); *to++ = XNUM_TO_DIGIT (c & 0xf); } break; default: abort (); } *to = '\0';}#define RING_SIZE 3struct ringel { char *buffer; int size;};static struct ringel ring[RING_SIZE]; /* ring data */static const char *escnonprint_internal (const char *str, char escape, int base){ static int ringpos; /* current ring position */ int nprcnt; assert (base == 8 || base == 16); nprcnt = count_nonprint (str); if (nprcnt == 0) /* If there are no non-printable chars in STR, don't bother copying anything, just return STR. */ return str; { /* Set up a pointer to the current ring position, so we can write simply r->X instead of ring[ringpos].X. */ struct ringel *r = ring + ringpos; /* Every non-printable character is replaced with the escape char and three (or two, depending on BASE) *additional* chars. Size must also include the length of the original string and one additional char for the terminating \0. */ int needed_size = strlen (str) + 1 + (base == 8 ? 3 * nprcnt : 2 * nprcnt); /* If the current buffer is uninitialized or too small, (re)allocate it. */ if (r->buffer == NULL || r->size < needed_size) { r->buffer = xrealloc (r->buffer, needed_size); r->size = needed_size; } copy_and_escape (str, r->buffer, escape, base); ringpos = (ringpos + 1) % RING_SIZE; return r->buffer; }}/* Return a pointer to a static copy of STR with the non-printable characters escaped as \ooo. If there are no non-printable characters in STR, STR is returned. See copy_and_escape for more information on which characters are considered non-printable. DON'T call this function on translated strings because escaping will break them. Don't call it on literal strings from the source, which are by definition trusted. If newlines are allowed in the string, escape and print it line by line because escaping the whole string will convert newlines to \012. (This is so that expectedly single-line messages cannot use embedded newlines to mimic Wget's output and deceive the user.) escnonprint doesn't quote its escape character because it is notf meant as a general and reversible quoting mechanism, but as a quick way to defang binary junk sent by malicious or buggy servers. NOTE: since this function can return a pointer to static data, be careful to copy its result before calling it again. However, to be more useful with printf, it maintains an internal ring of static buffers to return. Currently the ring size is 3, which means you can print up to three values in the same printf; if more is needed, bump RING_SIZE. */const char *escnonprint (const char *str){ return escnonprint_internal (str, '\\', 8);}/* Return a pointer to a static copy of STR with the non-printable characters escaped as %XX. If there are no non-printable characters in STR, STR is returned. See escnonprint for usage details. */const char *escnonprint_uri (const char *str){ return escnonprint_internal (str, '%', 16);}voidlog_cleanup (void){ int i; for (i = 0; i < countof (ring); i++) xfree_null (ring[i].buffer);}/* When SIGHUP or SIGUSR1 are received, the output is redirected elsewhere. Such redirection is only allowed once. */static 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; logfp = unique_create (DEFAULT_LOGFILE, false, &logfile); if (logfp) { fprintf (stderr, _("\n%s received, redirecting output to `%s'.\n"), redirect_request_signal_name, logfile); xfree (logfile); /* Dump the context output to the newly opened log. */ log_dump_context (); } else { /* Eek! Opening the alternate log file has failed. Nothing we can do but disable printing completely. */ fprintf (stderr, _("\n%s received.\n"), redirect_request_signal_name); fprintf (stderr, _("%s: %s; disabling logging.\n"), logfile, strerror (errno)); inhibit_logging = true; } save_context_p = false;}/* 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 + -