X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Fevents.c;h=f707e0bec24ab1096ec3b03493f791d7061f05df;hb=1e35941f62bddafd6b88270b22b3afe4a5d37baa;hp=3894349133b811bb583ed8b2e99ab90517bd53ed;hpb=a53833fdd21cd573fe8fd02d7a11a3a5e9764ce0;p=libguestfs.git diff --git a/src/events.c b/src/events.c index 3894349..f707e0b 100644 --- a/src/events.c +++ b/src/events.c @@ -28,6 +28,7 @@ #include #include +#include "c-ctype.h" #include "ignore-value.h" #include "guestfs.h" @@ -110,15 +111,17 @@ guestfs___call_callbacks_message (guestfs_h *g, uint64_t event, count++; } - /* If nothing was registered and we're verbose or tracing, then we - * print the message on stderr. This essentially emulates the - * behaviour of the old-style handlers, while allowing callers to - * override print-on-stderr simply by registering a callback. + /* Emulate the old-style handlers. Callers can override + * print-on-stderr simply by registering a callback. */ - if (count == 0 && (g->verbose || event == GUESTFS_EVENT_TRACE)) { - const char *prefix = "libguestfs: "; - const char *trace = "trace: "; - const char *nl = "\n"; + if (count == 0 && + (event == GUESTFS_EVENT_APPLIANCE || + event == GUESTFS_EVENT_LIBRARY || + event == GUESTFS_EVENT_TRACE) && + (g->verbose || event == GUESTFS_EVENT_TRACE)) { + int from_appliance = event == GUESTFS_EVENT_APPLIANCE; + size_t i; + char c; /* APPLIANCE => * LIBRARY => libguestfs: \n @@ -126,18 +129,47 @@ guestfs___call_callbacks_message (guestfs_h *g, uint64_t event, */ if (event != GUESTFS_EVENT_APPLIANCE) - ignore_value (write (STDERR_FILENO, prefix, strlen (prefix))); + fputs ("libguestfs: ", stderr); if (event == GUESTFS_EVENT_TRACE) - ignore_value (write (STDERR_FILENO, trace, strlen (trace))); - - ignore_value (write (STDERR_FILENO, buf, buf_len)); - - /* Messages from the appliance already contain \n characters, others - * need this to be appended. + fputs ("trace: ", stderr); + + /* Special or non-printing characters in the buffer must be + * escaped (RHBZ#731744). The buffer can contain any 8 bit + * character, even \0. + * + * Handling of \n and \r characters is complex: + * + * Case 1: Messages from the appliance: These messages already + * contain \n and \r characters at logical positions, so we just + * echo those out directly. + * + * Case 2: Messages from other sources: These messages should NOT + * contain \n or \r. If they do, it is escaped. However we also + * need to print a real end of line after these messages. */ - if (event != GUESTFS_EVENT_APPLIANCE) - ignore_value (write (STDERR_FILENO, nl, strlen (nl))); + for (i = 0; i < buf_len; ++i) { + c = buf[i]; + if (c_isprint (c) || (from_appliance && (c == '\n' || c == '\r'))) + putc (c, stderr); + else { + switch (c) { + case '\0': fputs ("\\0", stderr); break; + case '\a': fputs ("\\a", stderr); break; + case '\b': fputs ("\\b", stderr); break; + case '\f': fputs ("\\f", stderr); break; + case '\n': fputs ("\\n", stderr); break; + case '\r': fputs ("\\r", stderr); break; + case '\t': fputs ("\\t", stderr); break; + case '\v': fputs ("\\v", stderr); break; + default: + fprintf (stderr, "\\x%x", (unsigned) c); + } + } + } + + if (!from_appliance) + putc ('\n', stderr); } }