16 #ifndef HAVE_CLOCK_GETTIME
17 #ifdef HAVE_SYS_TIME_H
18 # include <sys/time.h> /* gettimeofday() */
22 int log_clock_gettime_realtime (struct timespec
*ts
) {
23 #ifdef HAVE_CLOCK_GETTIME
24 return clock_gettime(CLOCK_REALTIME
, ts
);
26 /* Mac OSX does not provide clock_gettime()
27 * e.g. defined(__APPLE__) && defined(__MACH__) */
29 gettimeofday(&tv
, NULL
);
30 ts
->tv_sec
= tv
.tv_sec
;
31 ts
->tv_nsec
= tv
.tv_usec
* 1000;
36 /* retry write on EINTR or when not all data was written */
37 ssize_t
write_all(int fd
, const void* buf
, size_t count
) {
41 ssize_t r
= write(fd
, buf
, count
);
48 /* fail - repeating probably won't help */
52 /* really shouldn't happen... */
56 force_assert(r
<= (ssize_t
) count
);
58 buf
= r
+ (char const*) buf
;
66 /* lowercase: append space, uppercase: don't */
67 static void log_buffer_append_printf(buffer
*out
, const char *fmt
, va_list ap
) {
75 case 's': /* string */
76 s
= va_arg(ap
, char *);
77 buffer_append_string_c_escaped(out
, s
, (NULL
!= s
) ? strlen(s
) : 0);
78 buffer_append_string_len(out
, CONST_STR_LEN(" "));
80 case 'b': /* buffer */
81 b
= va_arg(ap
, buffer
*);
82 buffer_append_string_c_escaped(out
, CONST_BUF_LEN(b
));
83 buffer_append_string_len(out
, CONST_STR_LEN(" "));
87 buffer_append_int(out
, d
);
88 buffer_append_string_len(out
, CONST_STR_LEN(" "));
91 o
= va_arg(ap
, off_t
);
92 buffer_append_int(out
, o
);
93 buffer_append_string_len(out
, CONST_STR_LEN(" "));
95 case 'x': /* int (hex) */
97 buffer_append_string_len(out
, CONST_STR_LEN("0x"));
98 buffer_append_uint_hex(out
, d
);
99 buffer_append_string_len(out
, CONST_STR_LEN(" "));
101 case 'S': /* string */
102 s
= va_arg(ap
, char *);
103 buffer_append_string_c_escaped(out
, s
, (NULL
!= s
) ? strlen(s
) : 0);
105 case 'B': /* buffer */
106 b
= va_arg(ap
, buffer
*);
107 buffer_append_string_c_escaped(out
, CONST_BUF_LEN(b
));
111 buffer_append_int(out
, d
);
113 case 'O': /* off_t */
114 o
= va_arg(ap
, off_t
);
115 buffer_append_int(out
, o
);
117 case 'X': /* int (hex) */
119 buffer_append_string_len(out
, CONST_STR_LEN("0x"));
120 buffer_append_uint_hex(out
, d
);
128 buffer_append_string_len(out
, fmt
, 1);
134 static int log_buffer_prepare(buffer
*b
, server
*srv
, const char *filename
, unsigned int line
) {
135 switch(srv
->errorlog_mode
) {
139 if (-1 == srv
->errorlog_fd
) return -1;
140 /* cache the generated timestamp */
141 if (srv
->cur_ts
!= srv
->last_generated_debug_ts
) {
142 buffer_string_prepare_copy(srv
->ts_debug_str
, 255);
143 buffer_append_strftime(srv
->ts_debug_str
, "%Y-%m-%d %H:%M:%S", localtime(&(srv
->cur_ts
)));
145 srv
->last_generated_debug_ts
= srv
->cur_ts
;
148 buffer_copy_buffer(b
, srv
->ts_debug_str
);
149 buffer_append_string_len(b
, CONST_STR_LEN(": ("));
151 case ERRORLOG_SYSLOG
:
152 /* syslog is generating its own timestamps */
153 buffer_copy_string_len(b
, CONST_STR_LEN("("));
157 buffer_append_string(b
, filename
);
158 buffer_append_string_len(b
, CONST_STR_LEN("."));
159 buffer_append_int(b
, line
);
160 buffer_append_string_len(b
, CONST_STR_LEN(") "));
165 static void log_write(server
*srv
, buffer
*b
) {
166 switch(srv
->errorlog_mode
) {
170 buffer_append_string_len(b
, CONST_STR_LEN("\n"));
171 write_all(srv
->errorlog_fd
, CONST_BUF_LEN(b
));
173 case ERRORLOG_SYSLOG
:
174 syslog(LOG_ERR
, "%s", b
->ptr
);
179 int log_error_write(server
*srv
, const char *filename
, unsigned int line
, const char *fmt
, ...) {
182 if (-1 == log_buffer_prepare(srv
->errorlog_buf
, srv
, filename
, line
)) return 0;
185 log_buffer_append_printf(srv
->errorlog_buf
, fmt
, ap
);
188 log_write(srv
, srv
->errorlog_buf
);
193 int log_error_write_multiline_buffer(server
*srv
, const char *filename
, unsigned int line
, buffer
*multiline
, const char *fmt
, ...) {
196 buffer
*b
= srv
->errorlog_buf
;
197 char *pos
, *end
, *current_line
;
199 if (buffer_string_is_empty(multiline
)) return 0;
201 if (-1 == log_buffer_prepare(b
, srv
, filename
, line
)) return 0;
204 log_buffer_append_printf(b
, fmt
, ap
);
207 prefix_len
= buffer_string_length(b
);
209 current_line
= pos
= multiline
->ptr
;
210 end
= multiline
->ptr
+ buffer_string_length(multiline
);
212 for ( ; pos
<= end
; ++pos
) {
216 case '\0': /* handles end of string */
217 if (current_line
< pos
) {
218 /* truncate to prefix */
219 buffer_string_set_length(b
, prefix_len
);
221 buffer_append_string_len(b
, current_line
, pos
- current_line
);
224 current_line
= pos
+ 1;