1/* vi: set sw=4 ts=4: */ 2/* 3 * Utility routines. 4 * 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 */ 9 10#include <syslog.h> 11#include "libbb.h" 12 13smallint logmode = LOGMODE_STDIO; 14const char *msg_eol = "\n"; 15 16void bb_verror_msg(const char *s, va_list p, const char* strerr) 17{ 18 char *msg; 19 int applet_len, strerr_len, msgeol_len, used; 20 21 if (!logmode) 22 return; 23 24 if (!s) /* nomsg[_and_die] uses NULL fmt */ 25 s = ""; /* some libc don't like printf(NULL) */ 26 27 used = vasprintf(&msg, s, p); 28 if (used < 0) 29 return; 30 31 /* This is ugly and costs +60 bytes compared to multiple 32 * fprintf's, but is guaranteed to do a single write. 33 * This is needed for e.g. httpd logging, when multiple 34 * children can produce log messages simultaneously. */ 35 36 applet_len = strlen(applet_name) + 2; /* "applet: " */ 37 strerr_len = strerr ? strlen(strerr) : 0; 38 msgeol_len = strlen(msg_eol); 39 /* +3 is for ": " before strerr and for terminating NUL */ 40 msg = xrealloc(msg, applet_len + used + strerr_len + msgeol_len + 3); 41 /* TODO: maybe use writev instead of memmoving? Need full_writev? */ 42 memmove(msg + applet_len, msg, used); 43 used += applet_len; 44 strcpy(msg, applet_name); 45 msg[applet_len - 2] = ':'; 46 msg[applet_len - 1] = ' '; 47 if (strerr) { 48 msg[used++] = ':'; 49 msg[used++] = ' '; 50 strcpy(&msg[used], strerr); 51 used += strerr_len; 52 } 53 strcpy(&msg[used], msg_eol); 54 55 if (logmode & LOGMODE_STDIO) { 56 fflush(stdout); 57 full_write(2, msg, used + msgeol_len); 58 } 59 if (logmode & LOGMODE_SYSLOG) { 60 syslog(LOG_ERR, "%s", msg + applet_len); 61 } 62 free(msg); 63} 64 65 66#ifdef VERSION_WITH_WRITEV 67 68/* Code size is approximately the same, but currently it's the only user 69 * of writev in entire bbox. __libc_writev in uclibc is ~50 bytes. */ 70 71void bb_verror_msg(const char *s, va_list p, const char* strerr) 72{ 73 int strerr_len, msgeol_len; 74 struct iovec iov[3]; 75 76#define used (iov[2].iov_len) 77#define msgv (iov[2].iov_base) 78#define msgc ((char*)(iov[2].iov_base)) 79#define msgptr (&(iov[2].iov_base)) 80 81 if (!logmode) 82 return; 83 84 if (!s) /* nomsg[_and_die] uses NULL fmt */ 85 s = ""; /* some libc don't like printf(NULL) */ 86 87 /* Prevent "derefing type-punned ptr will break aliasing rules" */ 88 used = vasprintf((char**)(void*)msgptr, s, p); 89 if (used < 0) 90 return; 91 92 /* This is ugly and costs +60 bytes compared to multiple 93 * fprintf's, but is guaranteed to do a single write. 94 * This is needed for e.g. httpd logging, when multiple 95 * children can produce log messages simultaneously. */ 96 97 strerr_len = strerr ? strlen(strerr) : 0; 98 msgeol_len = strlen(msg_eol); 99 /* +3 is for ": " before strerr and for terminating NUL */ 100 msgv = xrealloc(msgv, used + strerr_len + msgeol_len + 3); 101 if (strerr) { 102 msgc[used++] = ':'; 103 msgc[used++] = ' '; 104 strcpy(msgc + used, strerr); 105 used += strerr_len; 106 } 107 strcpy(msgc + used, msg_eol); 108 used += msgeol_len; 109 110 if (logmode & LOGMODE_STDIO) { 111 iov[0].iov_base = (char*)applet_name; 112 iov[0].iov_len = strlen(applet_name); 113 iov[1].iov_base = (char*)": "; 114 iov[1].iov_len = 2; 115 /*iov[2].iov_base = msgc;*/ 116 /*iov[2].iov_len = used;*/ 117 fflush(stdout); 118 writev(2, iov, 3); 119 } 120 if (logmode & LOGMODE_SYSLOG) { 121 syslog(LOG_ERR, "%s", msgc); 122 } 123 free(msgc); 124} 125#endif 126