source: MondoRescue/branches/3.3/mindi-busybox/libbb/verror_msg.c@ 3906

Last change on this file since 3906 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 4.5 KB
Line 
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 source tree.
8 */
9#include "libbb.h"
10#if ENABLE_FEATURE_SYSLOG
11# include <syslog.h>
12#endif
13
14#if ENABLE_FEATURE_SYSLOG
15smallint syslog_level = LOG_ERR;
16#endif
17smallint logmode = LOGMODE_STDIO;
18const char *msg_eol = "\n";
19
20void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
21{
22 char *msg, *msg1;
23 char stack_msg[80];
24 int applet_len, strerr_len, msgeol_len, used;
25
26 if (!logmode)
27 return;
28
29 if (!s) /* nomsg[_and_die] uses NULL fmt */
30 s = ""; /* some libc don't like printf(NULL) */
31
32 applet_len = strlen(applet_name) + 2; /* "applet: " */
33 strerr_len = strerr ? strlen(strerr) : 0;
34 msgeol_len = strlen(msg_eol);
35
36 /* This costs ~90 bytes of code, but avoids costly
37 * malloc()[in vasprintf]+realloc()+memmove()+free() in 99% of cases.
38 * ~40% speedup.
39 */
40 if ((int)sizeof(stack_msg) - applet_len > 0) {
41 va_list p2;
42
43 /* It is not portable to use va_list twice, need to va_copy it */
44 va_copy(p2, p);
45 used = vsnprintf(stack_msg + applet_len, (int)sizeof(stack_msg) - applet_len, s, p2);
46 va_end(p2);
47 msg = stack_msg;
48 used += applet_len;
49 if (used < (int)sizeof(stack_msg) - 3 - msgeol_len - strerr_len)
50 goto add_pfx_and_sfx;
51 }
52
53 used = vasprintf(&msg, s, p);
54 if (used < 0)
55 return;
56
57 /* This is ugly and costs +60 bytes compared to multiple
58 * fprintf's, but is guaranteed to do a single write.
59 * This is needed for e.g. httpd logging, when multiple
60 * children can produce log messages simultaneously. */
61
62 /* can't use xrealloc: it calls error_msg on failure,
63 * that may result in a recursion */
64 /* +3 is for ": " before strerr and for terminating NUL */
65 msg1 = realloc(msg, applet_len + used + strerr_len + msgeol_len + 3);
66 if (!msg1) {
67 msg[used++] = '\n'; /* overwrites NUL */
68 applet_len = 0;
69 } else {
70 msg = msg1;
71 /* TODO: maybe use writev instead of memmoving? Need full_writev? */
72 memmove(msg + applet_len, msg, used);
73 used += applet_len;
74 add_pfx_and_sfx:
75 strcpy(msg, applet_name);
76 msg[applet_len - 2] = ':';
77 msg[applet_len - 1] = ' ';
78 if (strerr) {
79 if (s[0]) { /* not perror_nomsg? */
80 msg[used++] = ':';
81 msg[used++] = ' ';
82 }
83 strcpy(&msg[used], strerr);
84 used += strerr_len;
85 }
86 strcpy(&msg[used], msg_eol);
87 used += msgeol_len;
88 }
89
90 if (logmode & LOGMODE_STDIO) {
91 fflush_all();
92 full_write(STDERR_FILENO, msg, used);
93 }
94#if ENABLE_FEATURE_SYSLOG
95 if (logmode & LOGMODE_SYSLOG) {
96 syslog(syslog_level, "%s", msg + applet_len);
97 }
98#endif
99 if (msg != stack_msg)
100 free(msg);
101}
102
103#ifdef VERSION_WITH_WRITEV
104/* Code size is approximately the same, but currently it's the only user
105 * of writev in entire bbox. __libc_writev in uclibc is ~50 bytes. */
106void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
107{
108 int strerr_len, msgeol_len;
109 struct iovec iov[3];
110
111#define used (iov[2].iov_len)
112#define msgv (iov[2].iov_base)
113#define msgc ((char*)(iov[2].iov_base))
114#define msgptr (&(iov[2].iov_base))
115
116 if (!logmode)
117 return;
118
119 if (!s) /* nomsg[_and_die] uses NULL fmt */
120 s = ""; /* some libc don't like printf(NULL) */
121
122 /* Prevent "derefing type-punned ptr will break aliasing rules" */
123 used = vasprintf((char**)(void*)msgptr, s, p);
124 if (used < 0)
125 return;
126
127 /* This is ugly and costs +60 bytes compared to multiple
128 * fprintf's, but is guaranteed to do a single write.
129 * This is needed for e.g. httpd logging, when multiple
130 * children can produce log messages simultaneously. */
131
132 strerr_len = strerr ? strlen(strerr) : 0;
133 msgeol_len = strlen(msg_eol);
134 /* +3 is for ": " before strerr and for terminating NUL */
135 msgv = xrealloc(msgv, used + strerr_len + msgeol_len + 3);
136 if (strerr) {
137 msgc[used++] = ':';
138 msgc[used++] = ' ';
139 strcpy(msgc + used, strerr);
140 used += strerr_len;
141 }
142 strcpy(msgc + used, msg_eol);
143 used += msgeol_len;
144
145 if (logmode & LOGMODE_STDIO) {
146 iov[0].iov_base = (char*)applet_name;
147 iov[0].iov_len = strlen(applet_name);
148 iov[1].iov_base = (char*)": ";
149 iov[1].iov_len = 2;
150 /*iov[2].iov_base = msgc;*/
151 /*iov[2].iov_len = used;*/
152 fflush_all();
153 writev(STDERR_FILENO, iov, 3);
154 }
155# if ENABLE_FEATURE_SYSLOG
156 if (logmode & LOGMODE_SYSLOG) {
157 syslog(LOG_ERR, "%s", msgc);
158 }
159# endif
160 free(msgc);
161}
162#endif
163
164
165void FAST_FUNC bb_error_msg_and_die(const char *s, ...)
166{
167 va_list p;
168
169 va_start(p, s);
170 bb_verror_msg(s, p, NULL);
171 va_end(p);
172 xfunc_die();
173}
174
175void FAST_FUNC bb_error_msg(const char *s, ...)
176{
177 va_list p;
178
179 va_start(p, s);
180 bb_verror_msg(s, p, NULL);
181 va_end(p);
182}
Note: See TracBrowser for help on using the repository browser.