From 1b97efd66aecdd79fa6501bc90aefe9998464347 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Fri, 17 Aug 2007 19:18:06 +0000 Subject: httpd shring and logging update, part 1 or 7 text data bss dec hex filename 9836 0 0 9836 266c busybox.t1/networking/httpd.o.orig 9724 0 0 9724 25fc busybox.t2/networking/httpd.o 9657 0 0 9657 25b9 busybox.t3/networking/httpd.o 9342 0 0 9342 247e busybox.t4/networking/httpd.o 9342 0 0 9342 247e busybox.t5/networking/httpd.o 9262 0 0 9262 242e busybox.t6/networking/httpd.o 9283 0 0 9283 2443 busybox.t7/networking/httpd.o 9334 0 0 9334 2476 busybox.t8/networking/httpd.o --- libbb/verror_msg.c | 126 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 100 insertions(+), 26 deletions(-) (limited to 'libbb/verror_msg.c') diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index 082e7bf3c..e51003134 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c @@ -7,45 +7,119 @@ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include "libbb.h" #include +#include "libbb.h" smallint logmode = LOGMODE_STDIO; const char *msg_eol = "\n"; void bb_verror_msg(const char *s, va_list p, const char* strerr) { - /* va_copy is used because it is not portable - * to use va_list p twice */ - va_list p2; - va_copy(p2, p); + char *msg; + int applet_len, strerr_len, msgeol_len, used; + + if (!logmode) + return; + + if (!s) /* nomsg[_and_die] uses NULL fmt */ + s = ""; /* some libc don't like printf(NULL) */ + + 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. httpd logging, when multiple + * children can produce log messages simultaneously. */ + + applet_len = strlen(applet_name) + 2; /* "applet: " */ + strerr_len = strerr ? strlen(strerr) : 0; + msgeol_len = strlen(msg_eol); + /* +3 is for ": " before strerr and for terminating NUL */ + msg = xrealloc(msg, applet_len + used + strerr_len + msgeol_len + 3); + /* TODO: maybe use writev instead of memmoving? Need full_writev? */ + memmove(msg + applet_len, msg, used); + used += applet_len; + strcpy(msg, applet_name); + msg[applet_len - 2] = ':'; + msg[applet_len - 1] = ' '; + if (strerr) { + msg[used++] = ':'; + msg[used++] = ' '; + strcpy(&msg[used], strerr); + used += strerr_len; + } + strcpy(&msg[used], msg_eol); + + if (logmode & LOGMODE_STDIO) { + fflush(stdout); + full_write(2, msg, used + msgeol_len); + } + if (logmode & LOGMODE_SYSLOG) { + syslog(LOG_ERR, "%s", msg + applet_len); + } + free(msg); +} + + +#ifdef VERSION_WITH_WRITEV + +/* Code size is approximately the same, but currently it's the only user + * of writev in entire bbox. __libc_writev in uclibc is ~50 bytes. */ + +void bb_verror_msg(const char *s, va_list p, const char* strerr) +{ + int strerr_len, msgeol_len; + struct iovec iov[3]; + +#define used (iov[2].iov_len) +#define msgv (iov[2].iov_base) +#define msgc ((char*)(iov[2].iov_base)) +#define msgptr (&(iov[2].iov_base)) + + if (!logmode) + return; if (!s) /* nomsg[_and_die] uses NULL fmt */ s = ""; /* some libc don't like printf(NULL) */ + /* Prevent "derefing type-punned ptr will break aliasing rules" */ + used = vasprintf((char**)(void*)msgptr, 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. httpd logging, when multiple + * children can produce log messages simultaneously. */ + + strerr_len = strerr ? strlen(strerr) : 0; + msgeol_len = strlen(msg_eol); + /* +3 is for ": " before strerr and for terminating NUL */ + msgv = xrealloc(msgv, used + strerr_len + msgeol_len + 3); + if (strerr) { + msgc[used++] = ':'; + msgc[used++] = ' '; + strcpy(msgc + used, strerr); + used += strerr_len; + } + strcpy(msgc + used, msg_eol); + used += msgeol_len; + if (logmode & LOGMODE_STDIO) { + iov[0].iov_base = (char*)applet_name; + iov[0].iov_len = strlen(applet_name); + iov[1].iov_base = (char*)": "; + iov[1].iov_len = 2; + /*iov[2].iov_base = msgc;*/ + /*iov[2].iov_len = used;*/ fflush(stdout); - fprintf(stderr, "%s: ", applet_name); - vfprintf(stderr, s, p); - if (!strerr) - fputs(msg_eol, stderr); - else - fprintf(stderr, "%s%s%s", - s[0] ? ": " : "", - strerr, msg_eol); + writev(2, iov, 3); } - if (ENABLE_FEATURE_SYSLOG && (logmode & LOGMODE_SYSLOG)) { - if (!strerr) - vsyslog(LOG_ERR, s, p2); - else { - char *msg; - if (vasprintf(&msg, s, p2) < 0) { - fprintf(stderr, "%s: %s\n", applet_name, bb_msg_memory_exhausted); - xfunc_die(); - } - syslog(LOG_ERR, "%s: %s", msg, strerr); - free(msg); - } + if (logmode & LOGMODE_SYSLOG) { + syslog(LOG_ERR, "%s", msgc); } - va_end(p2); + free(msgc); } +#endif -- cgit v1.2.3