4 Copyright (C) Andrew Tridgell 2008
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "../include/ctdb_client.h"
22 #include "../include/ctdb_private.h"
23 #include "system/syslog.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "lib/util/debug.h"
28 struct syslog_message
{
35 struct ctdb_syslog_state
{
40 static int syslogd_is_started
= 0;
42 /* called when child is finished
43 * this is for the syslog daemon, we can not use DEBUG here
45 static void ctdb_syslog_handler(struct event_context
*ev
, struct fd_event
*fde
,
46 uint16_t flags
, void *p
)
48 struct ctdb_syslog_state
*state
= talloc_get_type(p
, struct ctdb_syslog_state
);
52 struct syslog_message
*msg
;
58 count
= recv(state
->syslog_fd
, str
, sizeof(str
), 0);
59 if (count
< sizeof(struct syslog_message
)) {
62 msg
= (struct syslog_message
*)str
;
63 if (msg
->len
>= (sizeof(str
) - offsetof(struct syslog_message
, message
))) {
64 msg
->len
= (sizeof(str
)-1) - offsetof(struct syslog_message
, message
);
66 msg
->message
[msg
->len
] = '\0';
68 syslog(msg
->level
, "%s", msg
->message
);
72 /* called when the pipe from the main daemon has closed
73 * this is for the syslog daemon, we can not use DEBUG here
75 static void ctdb_syslog_terminate_handler(struct event_context
*ev
, struct fd_event
*fde
,
76 uint16_t flags
, void *p
)
78 syslog(LOG_ERR
, "Shutting down SYSLOG daemon with pid:%d", (int)getpid());
85 * this is for the syslog daemon, we can not use DEBUG here
87 int start_syslog_daemon(struct ctdb_context
*ctdb
)
89 struct sockaddr_in syslog_sin
;
90 struct ctdb_syslog_state
*state
;
91 struct tevent_fd
*fde
;
95 state
= talloc(ctdb
, struct ctdb_syslog_state
);
96 CTDB_NO_MEMORY(ctdb
, state
);
98 if (pipe(state
->fd
) != 0) {
99 printf("Failed to create syslog pipe\n");
104 if (pipe(startup_fd
) != 0) {
105 printf("Failed to create syslog startup pipe\n");
112 ctdb
->syslogd_pid
= ctdb_fork(ctdb
);
113 if (ctdb
->syslogd_pid
== (pid_t
)-1) {
114 printf("Failed to create syslog child process\n");
117 close(startup_fd
[0]);
118 close(startup_fd
[1]);
123 if (ctdb
->syslogd_pid
!= 0) {
127 DEBUG(DEBUG_ERR
,("Starting SYSLOG child process with pid:%d\n", (int)ctdb
->syslogd_pid
));
130 set_close_on_exec(state
->fd
[0]);
132 close(startup_fd
[1]);
133 n
= sys_read(startup_fd
[0], &dummy
, sizeof(dummy
));
134 close(startup_fd
[0]);
135 if (n
< sizeof(dummy
)) {
139 syslogd_is_started
= 1;
143 debug_extra
= talloc_asprintf(NULL
, "syslogd:");
144 talloc_free(ctdb
->ev
);
145 ctdb
->ev
= event_context_init(NULL
);
147 syslog(LOG_ERR
, "Starting SYSLOG daemon with pid:%d", (int)getpid());
148 ctdb_set_process_name("ctdb_syslogd");
151 close(startup_fd
[0]);
152 set_close_on_exec(state
->fd
[1]);
153 set_close_on_exec(startup_fd
[1]);
154 fde
= event_add_fd(ctdb
->ev
, state
, state
->fd
[1], EVENT_FD_READ
,
155 ctdb_syslog_terminate_handler
, state
);
156 tevent_fd_set_auto_close(fde
);
158 state
->syslog_fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
159 if (state
->syslog_fd
== -1) {
160 printf("Failed to create syslog socket\n");
161 close(startup_fd
[1]);
165 set_close_on_exec(state
->syslog_fd
);
167 syslog_sin
.sin_family
= AF_INET
;
168 syslog_sin
.sin_port
= htons(CTDB_PORT
);
169 syslog_sin
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
171 if (bind(state
->syslog_fd
, (struct sockaddr
*)&syslog_sin
,
172 sizeof(syslog_sin
)) == -1)
174 printf("syslog daemon failed to bind to socket. errno:%d(%s)\n", errno
, strerror(errno
));
175 close(startup_fd
[1]);
180 fde
= event_add_fd(ctdb
->ev
, state
, state
->syslog_fd
, EVENT_FD_READ
,
181 ctdb_syslog_handler
, state
);
182 tevent_fd_set_auto_close(fde
);
184 /* Tell parent that we're up */
186 sys_write(startup_fd
[1], &ret
, sizeof(ret
));
187 close(startup_fd
[1]);
189 event_loop_wait(ctdb
->ev
);
191 /* this should not happen */
195 struct ctdb_log_state
{
201 void (*logfn
)(const char *, uint16_t, void *);
205 /* we need this global to keep the DEBUG() syntax */
206 static struct ctdb_log_state
*log_state
;
209 syslog logging function
211 static void ctdb_syslog_log(void *private_ptr
, int dbglevel
, const char *s
)
213 struct syslog_message
*msg
;
214 int level
= LOG_DEBUG
;
217 struct sockaddr_in syslog_sin
;
237 len
= offsetof(struct syslog_message
, message
) + strlen(debug_extra
) + strlen(s
) + 1;
243 msg
->len
= strlen(debug_extra
) + strlen(s
);
244 strcpy(msg
->message
, debug_extra
);
245 strcat(msg
->message
, s
);
247 if (syslogd_is_started
== 0) {
248 syslog(msg
->level
, "%s", msg
->message
);
250 syslog_fd
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
251 if (syslog_fd
== -1) {
252 printf("Failed to create syslog socket\n");
257 syslog_sin
.sin_family
= AF_INET
;
258 syslog_sin
.sin_port
= htons(CTDB_PORT
);
259 syslog_sin
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
261 (void) sendto(syslog_fd
, msg
, len
, 0,
262 (struct sockaddr
*)&syslog_sin
,
264 /* no point in checking here since we cant log an error */
274 log file logging function
276 static void ctdb_logfile_log(void *private_ptr
, int dbglevel
, const char *s
)
284 t
= timeval_current();
285 tm
= localtime(&t
.tv_sec
);
287 strftime(tbuf
,sizeof(tbuf
)-1,"%Y/%m/%d %H:%M:%S", tm
);
289 ret
= asprintf(&s2
, "%s.%06u [%s%5u]: %s\n",
290 tbuf
, (unsigned)t
.tv_usec
,
291 debug_extra
, (unsigned)getpid(), s
);
293 const char *errstr
= "asprintf failed\n";
294 sys_write(log_state
->fd
, errstr
, strlen(errstr
));
298 sys_write(log_state
->fd
, s2
, strlen(s2
));
304 choose the logfile location
306 int ctdb_set_logfile(TALLOC_CTX
*mem_ctx
, const char *logfile
, bool use_syslog
)
308 debug_callback_fn callback
;
311 log_state
= talloc_zero(mem_ctx
, struct ctdb_log_state
);
312 if (log_state
== NULL
) {
313 printf("talloc_zero failed\n");
318 callback
= ctdb_syslog_log
;
319 log_state
->use_syslog
= true;
320 } else if (logfile
== NULL
|| strcmp(logfile
, "-") == 0) {
321 callback
= ctdb_logfile_log
;
323 /* also catch stderr of subcommands to stdout */
326 printf("dup2 failed: %s\n", strerror(errno
));
330 callback
= ctdb_logfile_log
;
332 log_state
->fd
= open(logfile
, O_WRONLY
|O_APPEND
|O_CREAT
, 0666);
333 if (log_state
->fd
== -1) {
334 printf("Failed to open logfile %s\n", logfile
);
339 debug_set_callback(NULL
, callback
);
344 /* Note that do_debug always uses the global log state. */
345 static void write_to_log(struct ctdb_log_state
*log
,
346 const char *buf
, unsigned int len
)
348 if (script_log_level
<= DEBUGLEVEL
) {
349 if (log
!= NULL
&& log
->prefix
!= NULL
) {
350 dbgtext("%s: %*.*s\n", log
->prefix
, len
, len
, buf
);
352 dbgtext("%*.*s\n", len
, len
, buf
);
354 /* log it in the eventsystem as well */
355 if (log
&& log
->logfn
) {
356 log
->logfn(log
->buf
, len
, log
->logfn_private
);
362 called when log data comes in from a child process
364 static void ctdb_child_log_handler(struct event_context
*ev
,
365 struct fd_event
*fde
,
366 uint16_t flags
, void *private)
368 struct ctdb_log_state
*log
= talloc_get_type(private, struct ctdb_log_state
);
372 if (!(flags
& EVENT_FD_READ
)) {
376 n
= sys_read(log
->pfd
, &log
->buf
[log
->buf_used
],
377 sizeof(log
->buf
) - log
->buf_used
);
381 if (log
!= log_state
) {
387 while (log
->buf_used
> 0 &&
388 (p
= memchr(log
->buf
, '\n', log
->buf_used
)) != NULL
) {
389 int n1
= (p
- log
->buf
)+1;
391 /* swallow \r from child processes */
392 if (n2
> 0 && log
->buf
[n2
-1] == '\r') {
395 write_to_log(log
, log
->buf
, n2
);
396 memmove(log
->buf
, p
+1, sizeof(log
->buf
) - n1
);
400 /* the buffer could have completely filled - unfortunately we have
401 no choice but to dump it out straight away */
402 if (log
->buf_used
== sizeof(log
->buf
)) {
403 write_to_log(log
, log
->buf
, log
->buf_used
);
408 static int log_context_destructor(struct ctdb_log_state
*log
)
410 /* Flush buffer in case it wasn't \n-terminated. */
411 if (log
->buf_used
> 0) {
412 write_to_log(log
, log
->buf
, log
->buf_used
);
418 * vfork + exec, redirecting child output to logging and specified callback.
420 struct ctdb_log_state
*ctdb_vfork_with_logging(TALLOC_CTX
*mem_ctx
,
421 struct ctdb_context
*ctdb
,
422 const char *log_prefix
,
425 const char **helper_argv
,
426 void (*logfn
)(const char *, uint16_t, void *),
427 void *logfn_private
, pid_t
*pid
)
430 struct ctdb_log_state
*log
;
431 struct tevent_fd
*fde
;
435 log
= talloc_zero(mem_ctx
, struct ctdb_log_state
);
436 CTDB_NO_MEMORY_NULL(ctdb
, log
);
438 log
->prefix
= log_prefix
;
440 log
->logfn_private
= logfn_private
;
443 DEBUG(DEBUG_ERR
, (__location__
" Failed to setup pipe for child logging\n"));
447 argv
= talloc_array(mem_ctx
, char *, helper_argc
+ 2);
449 DEBUG(DEBUG_ERR
, (__location__
"Failed to allocate memory for helper\n"));
452 argv
[0] = discard_const(helper
);
453 argv
[1] = talloc_asprintf(argv
, "%d", p
[1]);
454 if (argv
[1] == NULL
) {
455 DEBUG(DEBUG_ERR
, (__location__
"Failed to allocate memory for helper\n"));
460 for (i
=0; i
<helper_argc
; i
++) {
461 argv
[i
+2] = discard_const(helper_argv
[i
]);
472 DEBUG(DEBUG_ERR
, (__location__
"vfork failed for helper process\n"));
477 ctdb_track_child(ctdb
, *pid
);
480 set_close_on_exec(log
->pfd
);
481 talloc_set_destructor(log
, log_context_destructor
);
482 fde
= tevent_add_fd(ctdb
->ev
, log
, log
->pfd
, EVENT_FD_READ
,
483 ctdb_child_log_handler
, log
);
484 tevent_fd_set_auto_close(fde
);
495 setup for logging of child process stdout
497 int ctdb_set_child_logging(struct ctdb_context
*ctdb
)
500 int old_stdout
, old_stderr
;
501 struct tevent_fd
*fde
;
503 if (log_state
->fd
== STDOUT_FILENO
) {
504 /* not needed for stdout logging */
508 /* setup a pipe to catch IO from subprocesses */
510 DEBUG(DEBUG_ERR
,(__location__
" Failed to setup for child logging pipe\n"));
514 /* We'll fail if stderr/stdout not already open; it's simpler. */
515 old_stdout
= dup(STDOUT_FILENO
);
516 old_stderr
= dup(STDERR_FILENO
);
517 if (old_stdout
< 0 || old_stderr
< 0) {
518 DEBUG(DEBUG_ERR
, ("Failed to dup stdout/stderr for child logging\n"));
521 if (dup2(p
[1], STDOUT_FILENO
) < 0 || dup2(p
[1], STDERR_FILENO
) < 0) {
522 int saved_errno
= errno
;
523 dup2(old_stdout
, STDOUT_FILENO
);
524 dup2(old_stderr
, STDERR_FILENO
);
531 printf(__location__
" dup2 failed: %s\n",
539 fde
= event_add_fd(ctdb
->ev
, log_state
, p
[0],
540 EVENT_FD_READ
, ctdb_child_log_handler
, log_state
);
541 tevent_fd_set_auto_close(fde
);
543 log_state
->pfd
= p
[0];
545 DEBUG(DEBUG_DEBUG
, (__location__
" Created PIPE FD:%d for logging\n", p
[0]));
552 * set up a log handler to catch logging from TEVENT
554 static void ctdb_tevent_logging(void *private_data
,
555 enum tevent_debug_level level
,
559 enum debug_level lvl
= DEBUG_CRIT
;
562 case TEVENT_DEBUG_FATAL
:
565 case TEVENT_DEBUG_ERROR
:
568 case TEVENT_DEBUG_WARNING
:
571 case TEVENT_DEBUG_TRACE
:
576 if (lvl
<= DEBUGLEVEL
) {
581 int ctdb_init_tevent_logging(struct ctdb_context
*ctdb
)
585 ret
= tevent_set_debug(ctdb
->ev
,