Unobfuscate how the unconditional prefix and the conditional timestamp
will prefix the caller's message. Separate the result check for emission
of the prefix/timestamp from the check for successful construction of
the caller's message text. Release the dynamic buffer in the error path.
Use pointers and character variables in the copy loop for readability.
Strip LF as well as CR from the resulting log output text. The previous
implementation exclusively stripped LF. Escaping non-printables is not
attempted in this version.
static int sr_logv(void *cb_data, int loglevel, const char *format, va_list args)
{
static int sr_logv(void *cb_data, int loglevel, const char *format, va_list args)
{
uint64_t elapsed_us, minutes;
unsigned int rest_us, seconds, microseconds;
uint64_t elapsed_us, minutes;
unsigned int rest_us, seconds, microseconds;
- char *raw_output, *output;
- int raw_len, raw_idx, idx, ret;
+ char *raw_output, *output, c;
+ ssize_t print_len;
+ size_t raw_len;
+ const char *raw_ptr;
+ char *out_ptr;
/* This specific log callback doesn't need the void pointer data. */
(void)cb_data;
(void)loglevel;
/* This specific log callback doesn't need the void pointer data. */
(void)cb_data;
(void)loglevel;
+ /* Prefix with 'sr:'. Optionally prefix with timestamp. */
+ ret = fputs("sr: ", stderr);
+ if (ret < 0)
+ return SR_ERR;
if (cur_loglevel >= LOGLEVEL_TIMESTAMP) {
elapsed_us = g_get_monotonic_time() - sr_log_start_time;
if (cur_loglevel >= LOGLEVEL_TIMESTAMP) {
elapsed_us = g_get_monotonic_time() - sr_log_start_time;
seconds = rest_us / G_TIME_SPAN_SECOND;
microseconds = rest_us % G_TIME_SPAN_SECOND;
seconds = rest_us / G_TIME_SPAN_SECOND;
microseconds = rest_us % G_TIME_SPAN_SECOND;
- ret = g_fprintf(stderr, "sr: [%.2" PRIu64 ":%.2u.%.6u] ",
+ ret = g_fprintf(stderr, "[%.2" PRIu64 ":%.2u.%.6u] ",
minutes, seconds, microseconds);
minutes, seconds, microseconds);
- } else {
- ret = fputs("sr: ", stderr);
+ if (ret < 0)
+ return SR_ERR;
- if (ret < 0 || (raw_len = g_vasprintf(&raw_output, format, args)) < 0)
+ /* Print the caller's message into a local buffer. */
+ raw_output = NULL;
+ print_len = g_vasprintf(&raw_output, format, args);
+ if (print_len < 0) {
+ g_free(raw_output);
+ }
+ raw_len = (size_t)print_len;
- output = g_malloc0(raw_len + 1);
-
- /* Copy the string without any unwanted newlines. */
- raw_idx = idx = 0;
- while (raw_idx < raw_len) {
- if (raw_output[raw_idx] != '\n') {
- output[idx] = raw_output[raw_idx];
- idx++;
- }
- raw_idx++;
+ /* Copy the string. Strip unwanted line breaks. */
+ output = g_malloc(raw_len + 1);
+ if (!output) {
+ g_free(raw_output);
+ return SR_ERR;
+ }
+ out_ptr = output;
+ raw_ptr = raw_output;
+ while (*raw_ptr) {
+ c = *raw_ptr++;
+ if (c == '\r' || c == '\n')
+ continue;
+ *out_ptr++ = c;
+ *out_ptr = '\0';
+ g_free(raw_output);
+ /* Print the trimmed output text. */
g_fprintf(stderr, "%s\n", output);
fflush(stderr);
g_fprintf(stderr, "%s\n", output);
fflush(stderr);
g_free(output);
return SR_OK;
g_free(output);
return SR_OK;