0
|
1 /* Distributed Checksum Clearinghouse |
|
2 * |
|
3 * Copyright (c) 2008 by Rhyolite Software, LLC |
|
4 * |
|
5 * This agreement is not applicable to any entity which sells anti-spam |
|
6 * solutions to others or provides an anti-spam solution as part of a |
|
7 * security solution sold to other entities, or to a private network |
|
8 * which employs the DCC or uses data provided by operation of the DCC |
|
9 * but does not provide corresponding data to other users. |
|
10 * |
|
11 * Permission to use, copy, modify, and distribute this software without |
|
12 * changes for any purpose with or without fee is hereby granted, provided |
|
13 * that the above copyright notice and this permission notice appear in all |
|
14 * copies and any distributed versions or copies are either unchanged |
|
15 * or not called anything similar to "DCC" or "Distributed Checksum |
|
16 * Clearinghouse". |
|
17 * |
|
18 * Parties not eligible to receive a license under this agreement can |
|
19 * obtain a commercial license to use DCC by contacting Rhyolite Software |
|
20 * at sales@rhyolite.com. |
|
21 * |
|
22 * A commercial license would be for Distributed Checksum and Reputation |
|
23 * Clearinghouse software. That software includes additional features. This |
|
24 * free license for Distributed ChecksumClearinghouse Software does not in any |
|
25 * way grant permision to use Distributed Checksum and Reputation Clearinghouse |
|
26 * software |
|
27 * |
|
28 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL |
|
29 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES |
|
30 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC |
|
31 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES |
|
32 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
|
33 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, |
|
34 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
|
35 * SOFTWARE. |
|
36 * |
|
37 * Rhyolite Software DCC 1.3.103-1.53 $Revision$ |
|
38 */ |
|
39 |
|
40 #include "dcc_defs.h" |
|
41 #include "dcc_paths.h" |
|
42 #ifndef DCC_WIN32 |
|
43 #include <syslog.h> |
|
44 #endif |
|
45 |
|
46 extern void dcc_syslog_lock(void); |
|
47 extern void dcc_syslog_unlock(void); |
|
48 |
|
49 u_char trace_quiet; |
|
50 |
|
51 u_char dcc_no_syslog; |
|
52 |
|
53 int dcc_error_priority = LOG_ERR | LOG_MAIL; |
|
54 int dcc_trace_priority = LOG_NOTICE | LOG_MAIL; |
|
55 |
|
56 |
|
57 /* commonly used, but not thread safe */ |
|
58 int dcc_ex_code = EX_UNAVAILABLE; |
|
59 |
|
60 |
|
61 DCC_PATH dcc_progname; |
|
62 int dcc_progname_len; |
|
63 |
|
64 #ifdef HAVE___PROGNAME |
|
65 extern const char *__progname; |
|
66 #endif |
|
67 |
|
68 |
|
69 static void |
|
70 clean_stdfd(int stdfd) |
|
71 { |
|
72 struct stat sb; |
|
73 int fd; |
|
74 |
|
75 if (0 > fstat(stdfd, &sb) && errno == EBADF) { |
|
76 fd = open(_PATH_DEVNULL, 0, O_RDWR); |
|
77 if (fd < 0) /* ignore errors we can't help */ |
|
78 return; |
|
79 if (fd != stdfd) { |
|
80 dup2(fd, stdfd); |
|
81 close(fd); |
|
82 } |
|
83 } |
|
84 } |
|
85 |
|
86 |
|
87 |
|
88 /* prevent surprises from uses of stdio FDs by ensuring that the FDs are open */ |
|
89 void |
|
90 clean_stdio(void) |
|
91 { |
|
92 clean_stdfd(STDIN_FILENO); |
|
93 clean_stdfd(STDOUT_FILENO); |
|
94 clean_stdfd(STDERR_FILENO); |
|
95 } |
|
96 |
|
97 |
|
98 |
|
99 void |
|
100 dcc_syslog_init(u_char use_syslog, |
|
101 const char *argv0 UATTRIB, const char *suffix) |
|
102 { |
|
103 const char *p; |
|
104 |
|
105 /* Solaris defaults to "syslog" with a null identification string, |
|
106 * but does not seem to have __progname set by crt0. */ |
|
107 #undef GOT_PROGNAME |
|
108 #ifdef HAVE_GETPROGNAME |
|
109 p = getprogname(); |
|
110 # define GOT_PROGNAME |
|
111 #endif |
|
112 #if defined(HAVE___PROGNAME) && !defined(GOT_PROGNAME) |
|
113 p = __progname; |
|
114 # define GOT_PROGNAME |
|
115 #endif |
|
116 #ifndef GOT_PROGNAME |
|
117 p = strrchr(argv0, '/'); |
|
118 #ifdef DCC_WIN32 |
|
119 if (!p) |
|
120 p = strrchr(argv0, '\\'); |
|
121 #endif |
|
122 if (!p) |
|
123 p = argv0; |
|
124 else |
|
125 ++p; |
|
126 #ifdef DCC_WIN32 |
|
127 /* strip ".exe" from Windows progam name */ |
|
128 dcc_progname_len = strlen(p); |
|
129 if (dcc_progname_len > LITZ(".exe") |
|
130 && !CLITCMP(&p[dcc_progname_len-LITZ(".exe")], ".exe")) { |
|
131 char *p1 = strdup(p); |
|
132 p1[dcc_progname_len-LITZ(".exe")] = '\0'; |
|
133 p = p1; |
|
134 } |
|
135 #endif /* DCC_WIN32 */ |
|
136 #endif /* !GOT_PROGNAME */ |
|
137 snprintf(dcc_progname, sizeof(dcc_progname), "%s%s", |
|
138 p, suffix ? suffix : ""); |
|
139 dcc_progname_len = strlen(dcc_progname); |
|
140 |
|
141 /* ensure that stdout and stderr exist so that when we open |
|
142 * database or other files, we don't get file descriptor 1 or 2 |
|
143 * and then later write error messages to them. */ |
|
144 clean_stdio(); |
|
145 |
|
146 #ifdef DCC_WIN32 |
|
147 dcc_no_syslog = 1; |
|
148 #else |
|
149 /* Don't wait for the console if somehow we must use it, |
|
150 * because that messes up dccm. */ |
|
151 #ifndef LOG_NOWAIT |
|
152 #define LOG_NOWAIT 0 |
|
153 #endif |
|
154 openlog(dcc_progname, LOG_PID | LOG_NOWAIT, LOG_MAIL); |
|
155 if (!use_syslog) |
|
156 dcc_no_syslog = 1; |
|
157 #endif /* DCC_WIN32 */ |
|
158 } |
|
159 |
|
160 |
|
161 |
|
162 void |
|
163 dcc_vfatal_msg(const char *p, va_list args) |
|
164 { |
|
165 char logbuf[LOGBUF_SIZE]; |
|
166 int i; |
|
167 |
|
168 /* write the message with the "fatal error" addition as |
|
169 * a single message to syslog */ |
|
170 i = vsnprintf(logbuf, sizeof(logbuf), p, args); |
|
171 if (i >= ISZ(logbuf)) |
|
172 strcpy(&logbuf[ISZ(logbuf)-sizeof("...")], "..."); |
|
173 |
|
174 fflush(stdout); /* keep stderr and stdout straight */ |
|
175 fprintf(stderr, "%s; fatal error\n", logbuf); |
|
176 fflush(stderr); |
|
177 |
|
178 if (dcc_no_syslog) |
|
179 return; |
|
180 |
|
181 dcc_syslog_lock(); |
|
182 syslog(dcc_error_priority, "%s; fatal error", logbuf); |
|
183 closelog(); |
|
184 dcc_syslog_unlock(); |
|
185 } |
|
186 |
|
187 |
|
188 |
|
189 int |
|
190 dcc_verror_msg(const char *p, va_list args) |
|
191 { |
|
192 char logbuf[LOGBUF_SIZE]; |
|
193 int i; |
|
194 |
|
195 i = vsnprintf(logbuf, sizeof(logbuf), p, args); |
|
196 if (i >= ISZ(logbuf)) { |
|
197 strcpy(&logbuf[ISZ(logbuf)-sizeof("...")], "..."); |
|
198 i = ISZ(logbuf)-1; |
|
199 } else if (i == 0) { |
|
200 i = snprintf(logbuf, sizeof(logbuf), "(empty error message)"); |
|
201 } |
|
202 |
|
203 fflush(stdout); /* keep stderr and stdout straight */ |
|
204 fwrite(logbuf, i, 1, stderr); |
|
205 if (logbuf[i-1] != '\n') { |
|
206 fwrite("\n", 1, 1, stderr); |
|
207 ++i; |
|
208 } |
|
209 |
|
210 if (!dcc_no_syslog) { |
|
211 dcc_syslog_lock(); |
|
212 syslog(dcc_error_priority, "%s", logbuf); |
|
213 dcc_syslog_unlock(); |
|
214 } |
|
215 |
|
216 return i; |
|
217 } |
|
218 |
|
219 |
|
220 |
|
221 void PATTRIB(1,2) |
|
222 dcc_error_msg(const char *p, ...) |
|
223 { |
|
224 va_list args; |
|
225 |
|
226 va_start(args, p); |
|
227 dcc_verror_msg(p, args); |
|
228 va_end(args); |
|
229 } |
|
230 |
|
231 |
|
232 |
|
233 void |
|
234 dcc_vtrace_msg(const char *p, va_list args) |
|
235 { |
|
236 char logbuf[LOGBUF_SIZE]; |
|
237 int i; |
|
238 |
|
239 /* Some systems including Linux with gcc 3.4.2 on AMD 64 processors |
|
240 * do not allow two uses of a va_list but requires va_copy() |
|
241 * Other systems do not have any notion of va_copy(). */ |
|
242 i = vsnprintf(logbuf, sizeof(logbuf), p, args); |
|
243 if (i >= ISZ(logbuf)) |
|
244 strcpy(&logbuf[ISZ(logbuf)-sizeof("...")], "..."); |
|
245 |
|
246 fflush(stdout); /* keep stderr and stdout straight */ |
|
247 fprintf(stderr, "%s\n", logbuf); |
|
248 |
|
249 if (!dcc_no_syslog) { |
|
250 dcc_syslog_lock(); |
|
251 syslog(dcc_trace_priority, "%s", logbuf); |
|
252 dcc_syslog_unlock(); |
|
253 } |
|
254 } |
|
255 |
|
256 |
|
257 |
|
258 void PATTRIB(1,2) |
|
259 dcc_trace_msg(const char *p, ...) |
|
260 { |
|
261 va_list args; |
|
262 |
|
263 va_start(args, p); |
|
264 dcc_vtrace_msg(p, args); |
|
265 va_end(args); |
|
266 } |
|
267 |
|
268 |
|
269 |
|
270 /* send only to system log if being quiet */ |
|
271 void PATTRIB(1,2) |
|
272 quiet_trace_msg(const char *p, ...) |
|
273 { |
|
274 va_list args; |
|
275 |
|
276 va_start(args, p); |
|
277 if (trace_quiet) { |
|
278 vsyslog(dcc_trace_priority, p, args); |
|
279 } else { |
|
280 dcc_vtrace_msg(p, args); |
|
281 } |
|
282 va_end(args); |
|
283 } |
|
284 |
|
285 |
|
286 |
|
287 void |
|
288 dcc_vpemsg(int ex_code, DCC_EMSG emsg, const char *msg, va_list args) |
|
289 { |
|
290 if (!emsg) { |
|
291 dcc_verror_msg(msg, args); |
|
292 } else { |
|
293 dcc_ex_code = ex_code; |
|
294 vsnprintf(emsg, sizeof(DCC_EMSG), msg, args); |
|
295 } |
|
296 } |
|
297 |
|
298 |
|
299 |
|
300 void PATTRIB(3,4) |
|
301 dcc_pemsg(int ex_code, DCC_EMSG emsg, const char *msg, ...) |
|
302 { |
|
303 va_list args; |
|
304 |
|
305 va_start(args, msg); |
|
306 dcc_vpemsg(ex_code, emsg, msg, args); |
|
307 va_end(args); |
|
308 } |
|
309 |
|
310 |
|
311 |
|
312 const char * |
|
313 fnm_lno(DCC_FNM_LNO_BUF *buf, const char *fnm, int lno) |
|
314 { |
|
315 DCC_PATH tmp; |
|
316 |
|
317 if (!fnm || *fnm == '\0') { |
|
318 buf->b[0] = '\0'; |
|
319 } else { |
|
320 fnm2abs(tmp, fnm, ""); |
|
321 snprintf(buf->b, sizeof(buf->b), DCC_FNM_LNO_PAT, lno, tmp); |
|
322 } |
|
323 return buf->b; |
|
324 } |
|
325 |
|
326 |
|
327 |
|
328 int |
|
329 dcc_vearly_log(EARLY_LOG *el, const char *p, va_list args) |
|
330 { |
|
331 # define ELIPS_STR "...\n" |
|
332 int max_len, len; |
|
333 |
|
334 max_len = sizeof(el->buf) - el->len; |
|
335 if (max_len <= 0) |
|
336 return 0; |
|
337 |
|
338 len = vsnprintf(&el->buf[el->len], max_len, p, args); |
|
339 if (len < max_len) { |
|
340 el->len += len; |
|
341 return len; |
|
342 } else { |
|
343 memcpy(&el->buf[sizeof(el->buf)-LITZ(ELIPS_STR)], |
|
344 ELIPS_STR, LITZ(ELIPS_STR)); |
|
345 el->len = sizeof(el->buf); |
|
346 return max_len; |
|
347 } |
|
348 |
|
349 #undef ELIPS_STR |
|
350 } |
|
351 |
|
352 |
|
353 |
|
354 const char * |
|
355 optopt2str(int i) |
|
356 { |
|
357 static char b[] = "-x"; |
|
358 |
|
359 b[1] = i; |
|
360 return b; |
|
361 } |