X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/e1d04f48a45c9f8e8ff75610003048f8ead73219..4ed67f68df666fe38076e3bfd2183db71e742c7a:/src/src/debug.c diff --git a/src/src/debug.c b/src/src/debug.c index 3cd6d0c92..de9796232 100644 --- a/src/src/debug.c +++ b/src/src/debug.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2015 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -14,6 +14,26 @@ static int debug_prefix_length = 0; +const uschar * rc_names[] = { /* Mostly for debug output */ + [OK] = US"OK", + [DEFER] = US"DEFER", + [FAIL] = US"FAIL", + [ERROR] = US"ERROR", + [FAIL_FORCED] = US"FAIL_FORCED", + [DECLINE] = US"DECLINE", + [PASS] = US"PASS", + [DISCARD] = US"DISCARD", + [SKIP] = US"SKIP", + [REROUTED] = US"REROUTED", + [PANIC] = US"PANIC", + [BAD64] = US"BAD64", + [UNEXPECTED] = US"UNEXPECTED", + [CANCELLED] = US"CANCELLED", + [FAIL_SEND] = US"FAIL_SEND", + [FAIL_DROP] = US"FAIL_DROP" +}; + + /************************************************* * Print tree * *************************************************/ @@ -39,12 +59,11 @@ Returns: nothing static void tree_printsub(tree_node *p, int pos, int barswitch) { -int i; -if (p->right != NULL) tree_printsub(p->right, pos+2, 1); -for (i = 0; i <= pos-1; i++) debug_printf("%c", tree_printline[i]); +if (p->right) tree_printsub(p->right, pos+2, 1); +for (int i = 0; i <= pos-1; i++) debug_printf("%c", tree_printline[i]); debug_printf("-->%s [%d]\n", p->name, p->balance); tree_printline[pos] = barswitch? '|' : ' '; -if (p->left != NULL) +if (p->left) { tree_printline[pos+2] = '|'; tree_printsub(p->left, pos+2, 0); @@ -56,9 +75,8 @@ if (p->left != NULL) void debug_print_tree(tree_node *p) { -int i; -for (i = 0; i < tree_printlinesize; i++) tree_printline[i] = ' '; -if (p == NULL) debug_printf("Empty Tree\n"); else tree_printsub(p, 0, 0); +for (int i = 0; i < tree_printlinesize; i++) tree_printline[i] = ' '; +if (!p) debug_printf("Empty Tree\n"); else tree_printsub(p, 0, 0); debug_printf("---- End of tree ----\n"); } @@ -78,7 +96,7 @@ void debug_print_argv(const uschar ** argv) { debug_printf("exec"); -while (*argv != NULL) debug_printf(" %.256s", *argv++); +while (*argv) debug_printf(" %.256s", *argv++); debug_printf("\n"); } @@ -98,11 +116,11 @@ Returns: nothing void debug_print_string(uschar *debug_string) { -if (debug_string == NULL) return; +if (!debug_string) return; HDEBUG(D_any|D_v) { uschar *s = expand_string(debug_string); - if (s == NULL) + if (!s) debug_printf("failed to expand debug_output \"%s\": %s\n", debug_string, expand_string_message); else if (s[0] != 0) @@ -129,6 +147,17 @@ debug_printf("%s uid=%ld gid=%ld euid=%ld egid=%ld\n", s, (long int)getegid()); } +/************************************************/ + +/* Give a string for a return-code */ + +const uschar * +rc_to_string(int rc) +{ +return rc < 0 || rc >= nelem(rc_names) ? US"?" : rc_names[rc]; +} + + @@ -152,33 +181,22 @@ void debug_printf_indent(const char * format, ...) { va_list ap; -unsigned depth = acl_level + expand_level, i; - -if (!debug_file) return; -if (depth > 0) - { - for (i = depth >> 2; i > 0; i--) - fprintf(debug_file, " ."); - fprintf(debug_file, "%*s", depth & 3, ""); - } - va_start(ap, format); -debug_vprintf(format, ap); +debug_vprintf(acl_level + expand_level, format, ap); va_end(ap); } - void debug_printf(const char *format, ...) { va_list ap; va_start(ap, format); -debug_vprintf(format, ap); +debug_vprintf(0, format, ap); va_end(ap); } void -debug_vprintf(const char *format, va_list ap) +debug_vprintf(int indent, const char *format, va_list ap) { int save_errno = errno; @@ -193,45 +211,79 @@ if (debug_ptr == debug_buffer) { DEBUG(D_timestamp) { - time_t now = time(NULL); - struct tm *t = timestamps_utc? gmtime(&now) : localtime(&now); - (void) sprintf(CS debug_ptr, "%02d:%02d:%02d ", t->tm_hour, t->tm_min, - t->tm_sec); - while(*debug_ptr != 0) debug_ptr++; + struct timeval now; + time_t tmp; + struct tm * t; + + gettimeofday(&now, NULL); + tmp = now.tv_sec; + t = f.timestamps_utc ? gmtime(&tmp) : localtime(&tmp); + debug_ptr += sprintf(CS debug_ptr, + LOGGING(millisec) ? "%02d:%02d:%02d.%03d " : "%02d:%02d:%02d ", + t->tm_hour, t->tm_min, t->tm_sec, (int)(now.tv_usec/1000)); } DEBUG(D_pid) - { - sprintf(CS debug_ptr, "%5d ", (int)getpid()); - while(*debug_ptr != 0) debug_ptr++; - } + debug_ptr += sprintf(CS debug_ptr, "%5d ", (int)getpid()); /* Set up prefix if outputting for host checking and not debugging */ if (host_checking && debug_selector == 0) { - Ustrcpy(debug_ptr, ">>> "); + Ustrcpy(debug_ptr, US">>> "); debug_ptr += 4; } debug_prefix_length = debug_ptr - debug_buffer; } -/* Use the checked formatting routine to ensure that the buffer -does not overflow. Ensure there's space for a newline at the end. */ - -if (!string_vformat(debug_ptr, - sizeof(debug_buffer) - (debug_ptr - debug_buffer) - 1, format, ap)) +if (indent > 0) { - uschar *s = US"**** debug string too long - truncated ****\n"; - uschar *p = debug_buffer + Ustrlen(debug_buffer); - int maxlen = sizeof(debug_buffer) - Ustrlen(s) - 3; - if (p > debug_buffer + maxlen) p = debug_buffer + maxlen; - if (p > debug_buffer && p[-1] != '\n') *p++ = '\n'; - Ustrcpy(p, s); + for (int i = indent >> 2; i > 0; i--) + DEBUG(D_noutf8) + { + Ustrcpy(debug_ptr, US" !"); + debug_ptr += 4; /* 3 spaces + shriek */ + debug_prefix_length += 4; + } + else + { + Ustrcpy(debug_ptr, US" " UTF8_VERT_2DASH); + debug_ptr += 6; /* 3 spaces + 3 UTF-8 octets */ + debug_prefix_length += 6; + } + + Ustrncpy(debug_ptr, US" ", indent &= 3); + debug_ptr += indent; + debug_prefix_length += indent; } -while(*debug_ptr != 0) debug_ptr++; +/* Use the lengthchecked formatting routine to ensure that the buffer +does not overflow. Ensure there's space for a newline at the end. +However, use taint-unchecked routines for writing into the buffer +so that we can write tainted info into the static debug_buffer - +we trust that we will never expand the results. */ + + { + gstring gs = { .size = (int)sizeof(debug_buffer) - 1, + .ptr = debug_ptr - debug_buffer, + .s = debug_buffer }; + if (!string_vformat(&gs, SVFMT_TAINT_NOCHK, format, ap)) + { + uschar * s = US"**** debug string too long - truncated ****\n"; + uschar * p = gs.s + gs.ptr; + int maxlen = gs.size - Ustrlen(s) - 2; + if (p > gs.s + maxlen) p = gs.s + maxlen; + if (p > gs.s && p[-1] != '\n') *p++ = '\n'; + Ustrcpy(p, s); + while(*debug_ptr) debug_ptr++; + } + else + { + string_from_gstring(&gs); + debug_ptr = gs.s + gs.ptr; + } + } /* Output the line if it is complete. If we added any prefix data and there are internal newlines, make sure the prefix is on the continuation lines,