static void verror_msg_helper(const char *s, va_list p, const char* strerr, int flags) { char *msg; int prefix_len, strerr_len, msgeol_len, used; if (!logmode) return; used = vasprintf(&msg, s, p); if (used < 0) return; /* This is ugly and costs +60 bytes compared to multiple * fprintf's, but is guaranteed to do a single write. * This is needed for e.g. when multiple children * can produce log messages simultaneously. */ prefix_len = msg_prefix[0] ? strlen(msg_prefix) + 2 : 0; strerr_len = strerr ? strlen(strerr) : 0; msgeol_len = strlen(msg_eol); /* +3 is for ": " before strerr and for terminating NUL */ msg = (char*) xrealloc(msg, prefix_len + used + strerr_len + msgeol_len + 3); /* TODO: maybe use writev instead of memmoving? Need full_writev? */ if (prefix_len) { char *p; memmove(msg + prefix_len, msg, used); used += prefix_len; p = stpcpy(msg, msg_prefix); p[0] = ':'; p[1] = ' '; } if (strerr) { if (s[0]) { msg[used++] = ':'; msg[used++] = ' '; } strcpy(&msg[used], strerr); used += strerr_len; } strcpy(&msg[used], msg_eol); if (flags & LOGMODE_STDIO) { fflush(stdout); full_write(STDERR_FILENO, msg, used + msgeol_len); } msg[used] = '\0'; /* remove msg_eol (usually "\n") */ if (flags & LOGMODE_SYSLOG) { syslog(LOG_ERR, "%s", msg + prefix_len); } if ((flags & LOGMODE_CUSTOM) && g_custom_logger) { g_custom_logger(msg + prefix_len); } free(msg); }
static void verror_msg_helper(const char *s, va_list p, const char *strerr, int flags) { if (!logmode) return; /* This is ugly and costs +60 bytes compared to multiple * fprintf's, but is guaranteed to do a single write. * This is needed for e.g. when multiple children * can produce log messages simultaneously. */ int prefix_len = msg_prefix[0] ? strlen(msg_prefix) + 2 : 0; int strerr_len = strerr ? strlen(strerr) : 0; int msgeol_len = strlen(msg_eol); int used; /* Try to format the message in a fixed buffer. * This eliminates malloc. * Main reason isn't the speed optimization, but to make * short logging safe after fork in multithreaded libraries. */ char buf[1024]; va_list p2; va_copy(p2, p); if (prefix_len < sizeof(buf)) used = vsnprintf(buf + prefix_len, sizeof(buf) - prefix_len, s, p2); else used = vsnprintf(buf, 0, s, p2); va_end(p2); char *msg = buf; /* +3 is for ": " before strerr and for terminating NUL */ unsigned total_len = prefix_len + used + strerr_len + msgeol_len + 3; #if USE_ALLOCA if (total_len >= sizeof(buf)) { msg = alloca(total_len); used = vsnprintf(msg + prefix_len, total_len - prefix_len, s, p); } #else #define LOGMODE_DIE ((unsigned)INT_MAX + 1) char *malloced = NULL; if (total_len >= sizeof(buf)) { /* Nope, need to malloc the buffer. * Can't use xmalloc: it calls error_msg_and_die on failure, * that will result in a recursion. */ msg = malloced = malloc(total_len); if (!msg) { /* Same as xmalloc error */ msg = strcpy(buf, "Out of memory, exiting\n"); used = strlen(msg) - 1; msgeol_len = 1; /* '\n' */ prefix_len = 0; flags |= LOGMODE_DIE; goto send_it; } used = vsnprintf(msg + prefix_len, total_len - prefix_len, s, p); } #endif if (prefix_len) { char *p; used += prefix_len; p = stpcpy(msg, msg_prefix); p[0] = ':'; p[1] = ' '; } if (strerr) { if (s[0]) { msg[used++] = ':'; msg[used++] = ' '; } strcpy(&msg[used], strerr); used += strerr_len; } strcpy(&msg[used], msg_eol); #if !USE_ALLOCA send_it: #endif if (flags & LOGMODE_STDIO) { /*fflush(stdout); - unsafe after fork! */ full_write(STDERR_FILENO, msg, used + msgeol_len); } msg[used] = '\0'; /* remove msg_eol (usually "\n") */ if (flags & LOGMODE_SYSLOG) { syslog(LOG_ERR, "%s", msg + prefix_len); } if ((flags & LOGMODE_CUSTOM) && g_custom_logger) { g_custom_logger(msg + prefix_len); } #if !USE_ALLOCA free(malloced); if (flags & LOGMODE_DIE) xfunc_die(); #endif }