/** * prelude_string_vprintf: * @string: Pointer to a #prelude_string_t object. * @fmt: Format string to use. * @ap: Variable argument list. * * Produce output according to @fmt, storing argument provided in @ap * variable argument list, and write the output to the given @string. * See sprintf(3) for more information on @fmt format. * * Returns: The number of characters written, or a negative value if an error occured. */ int prelude_string_vprintf(prelude_string_t *string, const char *fmt, va_list ap) { int ret; va_list bkp; prelude_return_val_if_fail(string, prelude_error(PRELUDE_ERROR_ASSERTION)); prelude_return_val_if_fail(fmt, prelude_error(PRELUDE_ERROR_ASSERTION)); if ( ! (string->flags & PRELUDE_STRING_OWN_DATA) ) { ret = allocate_more_chunk_if_needed(string, 0); if ( ret < 0 ) return ret; } PRELUDE_VA_COPY(bkp, ap); ret = vsnprintf(string->data.rwbuf + string->index, string->size - string->index, fmt, ap); /* * From sprintf(3) on GNU/Linux: * * snprintf and vsnprintf do not write more than * size bytes (including the trailing '\0'), and return -1 if * the output was truncated due to this limit. (Thus until * glibc 2.0.6. Since glibc 2.1 these functions follow the * C99 standard and return the number of characters (exclud- * ing the trailing '\0') which would have been written to * the final string if enough space had been available.) */ if ( ret >= 0 && (size_t) ret < string->size - string->index ) { string->index += ret; goto end; } ret = allocate_more_chunk_if_needed(string, (ret < 0) ? 0 : ret + 1); if ( ret < 0 ) goto end; ret = prelude_string_vprintf(string, fmt, bkp); end: va_end(bkp); return ret; }
static void do_log_v(prelude_log_t level, const char *file, const char *function, int line, const char *fmt, va_list ap) { int ret; va_list bkp; char buf[1024]; ssize_t len = 0; if ( global_log_cb == do_log_print || global_log_cb == do_log_syslog ) { len = get_header(level, buf, sizeof(buf)); if ( len < 0 ) return; } PRELUDE_VA_COPY(bkp, ap); ret = vsnprintf(buf + len, sizeof(buf) - len, fmt, ap); if ( ret < 0 || (size_t) ret >= (sizeof(buf) - len) ) goto out; if ( level <= PRELUDE_LOG_ERR || level >= PRELUDE_LOG_DEBUG ) { for ( len += ret; buf[len - 1] == '\n' ; len-- ); snprintf(buf + len, sizeof(buf) - len, " (%s:%d %s)\n", file, line, function); } if ( need_to_log(level, log_level) || need_to_log(level, debug_level) ) { ret = global_log_cb(level, buf); if ( ret < 0 && global_log_cb == do_log_print ) { prelude_log_set_flags(PRELUDE_LOG_FLAGS_SYSLOG); do_log_v(level, file, function, line, fmt, bkp); goto out; } if ( debug_logfile ) fprintf(debug_logfile, "%s", buf); } out: va_end(bkp); }